0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-03 21:48:55 -05:00

refactor(console): change number input appearance to text input (#3620)

This commit is contained in:
Xiao Yijun 2023-03-29 17:43:26 +08:00 committed by GitHub
parent 7845872196
commit 8ffe82c4e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 6 deletions

View file

@ -71,6 +71,16 @@
height: 18px; height: 18px;
} }
} }
&[type='number'] {
-moz-appearance: textfield;
&::-webkit-outer-spin-button,
&::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
}
} }
&.disabled { &.disabled {

View file

@ -1,6 +1,15 @@
import { type Nullable } from '@silverhand/essentials';
import classNames from 'classnames'; import classNames from 'classnames';
import type { HTMLProps, ForwardedRef, ReactElement } from 'react'; import {
import { cloneElement, forwardRef } from 'react'; type HTMLProps,
type ReactElement,
useImperativeHandle,
useRef,
cloneElement,
forwardRef,
type Ref,
useEffect,
} from 'react';
import * as styles from './index.module.scss'; import * as styles from './index.module.scss';
@ -20,10 +29,36 @@ function TextInput(
disabled, disabled,
className, className,
readOnly, readOnly,
type = 'text',
...rest ...rest
}: Props, }: Props,
reference: ForwardedRef<HTMLInputElement> reference: Ref<Nullable<HTMLInputElement>>
) { ) {
const innerRef = useRef<HTMLInputElement>(null);
useImperativeHandle(reference, () => innerRef.current);
useEffect(() => {
if (type !== 'number') {
return;
}
const input = innerRef.current;
if (!input) {
return;
}
const handleWheel = (event: WheelEvent) => {
event.preventDefault();
};
input.addEventListener('wheel', handleWheel, { passive: false });
return () => {
input.removeEventListener('wheel', handleWheel);
};
}, [type]);
return ( return (
<div className={className}> <div className={className}>
<div <div
@ -36,7 +71,7 @@ function TextInput(
)} )}
> >
{icon && <span className={styles.icon}>{icon}</span>} {icon && <span className={styles.icon}>{icon}</span>}
<input type="text" {...rest} ref={reference} disabled={disabled} readOnly={readOnly} /> <input type={type} {...rest} ref={innerRef} disabled={disabled} readOnly={readOnly} />
{suffix && {suffix &&
cloneElement(suffix, { cloneElement(suffix, {
className: classNames([suffix.props.className, styles.suffix]), className: classNames([suffix.props.className, styles.suffix]),

View file

@ -68,7 +68,11 @@ function ApiResourceSettings() {
</FormField> </FormField>
<FormField isRequired title="api_resource_details.token_expiration_time_in_seconds"> <FormField isRequired title="api_resource_details.token_expiration_time_in_seconds">
<TextInput <TextInput
{...register('accessTokenTtl', { required: true, valueAsNumber: true })} {...register('accessTokenTtl', {
required: true,
valueAsNumber: true,
})}
type="number"
hasError={Boolean(errors.accessTokenTtl)} hasError={Boolean(errors.accessTokenTtl)}
placeholder={t('api_resource_details.token_expiration_time_in_seconds_placeholder')} placeholder={t('api_resource_details.token_expiration_time_in_seconds_placeholder')}
/> />

View file

@ -51,7 +51,10 @@ function ConfigForm({ formItems }: Props) {
const errorMessage = errors[item.key]?.message; const errorMessage = errors[item.key]?.message;
const buildCommonProperties = () => ({ const buildCommonProperties = () => ({
...register(item.key, { required: item.required }), ...register(item.key, {
required: item.required,
valueAsNumber: item.type === ConnectorConfigFormItemType.Number,
}),
placeholder: item.placeholder, placeholder: item.placeholder,
hasError, hasError,
}); });