* A basic HTML input control for entering text, numbers, or passwords. * * Note that checkbox and radio types are supported through * the Checklist and RadioItems component. Dates, times, and file uploads * are also supported through separate components.
({
type = HTMLInputTypes.text,
inputMode = 'verbatim',
n_blur = 0,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
n_blur_timestamp = -1,
n_submit = 0,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
n_submit_timestamp = -1,
debounce = false,
step = 'any',
autoComplete = 'off',
// eslint-disable-next-line @typescript-eslint/no-unused-vars
persisted_props = [PersistedProps.value],
// eslint-disable-next-line @typescript-eslint/no-unused-vars
persistence_type = PersistenceTypes.local,
disabled,
...props
}: InputProps)
| 59 | * are also supported through separate components. |
| 60 | */ |
| 61 | function Input({ |
| 62 | type = HTMLInputTypes.text, |
| 63 | inputMode = 'verbatim', |
| 64 | n_blur = 0, |
| 65 | // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 66 | n_blur_timestamp = -1, |
| 67 | n_submit = 0, |
| 68 | // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 69 | n_submit_timestamp = -1, |
| 70 | debounce = false, |
| 71 | step = 'any', |
| 72 | autoComplete = 'off', |
| 73 | // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 74 | persisted_props = [PersistedProps.value], |
| 75 | // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 76 | persistence_type = PersistenceTypes.local, |
| 77 | disabled, |
| 78 | ...props |
| 79 | }: InputProps) { |
| 80 | const input = useRef(document.createElement('input')); |
| 81 | const [value, setValue] = useState<InputProps['value']>(props.value); |
| 82 | const [pendingEvent, setPendingEvent] = useState<number>(); |
| 83 | const inputId = useState(() => uniqid('input-'))[0]; |
| 84 | |
| 85 | const valprops = type === HTMLInputTypes.number ? {} : {value: value ?? ''}; |
| 86 | let {className} = props; |
| 87 | className = 'dash-input' + (className ? ` ${className}` : ''); |
| 88 | |
| 89 | const setPropValue = useCallback( |
| 90 | (base: InputProps['value'], value: InputProps['value']) => { |
| 91 | const {setProps} = props; |
| 92 | base = convert(base); |
| 93 | value = input.current.checkValidity() ? convert(value) : NaN; |
| 94 | |
| 95 | if (!isEquivalent(base, value)) { |
| 96 | setProps({value}); |
| 97 | } |
| 98 | }, |
| 99 | [props.setProps] |
| 100 | ); |
| 101 | |
| 102 | const onEvent = () => { |
| 103 | const {value: inputValue} = input.current; |
| 104 | const valueAsNumber = convert(inputValue); |
| 105 | if (type === HTMLInputTypes.number) { |
| 106 | setPropValue(props.value, valueAsNumber ?? value); |
| 107 | } else { |
| 108 | const propValue = |
| 109 | inputValue === '' && props.value === undefined |
| 110 | ? undefined |
| 111 | : inputValue; |
| 112 | props.setProps({value: propValue}); |
| 113 | } |
| 114 | setPendingEvent(undefined); |
| 115 | }; |
| 116 | |
| 117 | const onBlur = useCallback(() => { |
| 118 | props.setProps({ |
searching dependent graphs…