-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
BaseInputTemplate.tsx
102 lines (97 loc) · 2.99 KB
/
BaseInputTemplate.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import { ChangeEvent, FocusEvent, useCallback } from 'react';
import {
ariaDescribedByIds,
BaseInputTemplateProps,
examplesId,
getInputProps,
FormContextType,
RJSFSchema,
StrictRJSFSchema,
} from '@rjsf/utils';
/** The `BaseInputTemplate` is the template to use to render the basic `<input>` component for the `core` theme.
* It is used as the template for rendering many of the <input> based widgets that differ by `type` and callbacks only.
* It can be customized/overridden for other themes or individual implementations as needed.
*
* @param props - The `WidgetProps` for this template
*/
export default function BaseInputTemplate<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any
>(props: BaseInputTemplateProps<T, S, F>) {
const {
id,
name, // remove this from ...rest
value,
readonly,
disabled,
autofocus,
onBlur,
onFocus,
onChange,
onChangeOverride,
options,
schema,
uiSchema,
formContext,
registry,
rawErrors,
type,
hideLabel, // remove this from ...rest
hideError, // remove this from ...rest
...rest
} = props;
// Note: since React 15.2.0 we can't forward unknown element attributes, so we
// exclude the "options" and "schema" ones here.
if (!id) {
console.log('No id for', props);
throw new Error(`no id for props ${JSON.stringify(props)}`);
}
const inputProps = {
...rest,
...getInputProps<T, S, F>(schema, type, options),
};
let inputValue;
if (inputProps.type === 'number' || inputProps.type === 'integer') {
inputValue = value || value === 0 ? value : '';
} else {
inputValue = value == null ? '' : value;
}
const _onChange = useCallback(
({ target: { value } }: ChangeEvent<HTMLInputElement>) => onChange(value === '' ? options.emptyValue : value),
[onChange, options]
);
const _onBlur = useCallback(({ target: { value } }: FocusEvent<HTMLInputElement>) => onBlur(id, value), [onBlur, id]);
const _onFocus = useCallback(
({ target: { value } }: FocusEvent<HTMLInputElement>) => onFocus(id, value),
[onFocus, id]
);
return (
<>
<input
id={id}
name={id}
className='form-control'
readOnly={readonly}
disabled={disabled}
autoFocus={autofocus}
value={inputValue}
{...inputProps}
list={schema.examples ? examplesId<T>(id) : undefined}
onChange={onChangeOverride || _onChange}
onBlur={_onBlur}
onFocus={_onFocus}
aria-describedby={ariaDescribedByIds<T>(id, !!schema.examples)}
/>
{Array.isArray(schema.examples) && (
<datalist key={`datalist_${id}`} id={examplesId<T>(id)}>
{(schema.examples as string[])
.concat(schema.default && !schema.examples.includes(schema.default) ? ([schema.default] as string[]) : [])
.map((example: any) => {
return <option key={example} value={example} />;
})}
</datalist>
)}
</>
);
}