@dartech/arsenal-ui 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +12 -0
- package/.eslintrc.json +22 -0
- package/README.md +7 -0
- package/index.ts +3 -0
- package/jest.config.js +9 -0
- package/package.json +21 -0
- package/project.json +69 -0
- package/rollup.config.js +135 -0
- package/src/interfaces/common.ts +12 -0
- package/src/interfaces/definition.ts +143 -0
- package/src/interfaces/index.ts +3 -0
- package/src/interfaces/ui.ts +35 -0
- package/src/lib/Alert/Alert.tsx +108 -0
- package/src/lib/Alert/index.ts +1 -0
- package/src/lib/Definition/CreateDefinition/CreateDefinition.tsx +74 -0
- package/src/lib/Definition/CreateDefinition/index.ts +1 -0
- package/src/lib/Definition/DefinitionFiller/DefinitionFiller.tsx +85 -0
- package/src/lib/Definition/DefinitionFiller/WidgetDefinitionFiller.tsx +96 -0
- package/src/lib/Definition/DefinitionFiller/index.ts +2 -0
- package/src/lib/Definition/index.ts +2 -0
- package/src/lib/DemPropertyField/DemPropertyField.tsx +93 -0
- package/src/lib/DemPropertyField/DemPropertyView/DemPropertyView.tsx +44 -0
- package/src/lib/DemPropertyField/DemPropertyView/index.ts +1 -0
- package/src/lib/DemPropertyField/MultipleDemField/MultipleDemField.tsx +293 -0
- package/src/lib/DemPropertyField/MultipleDemField/index.tsx +1 -0
- package/src/lib/DemPropertyField/RestrictedValuesEditor.tsx +63 -0
- package/src/lib/DemPropertyField/SingleDemField/SingleDemField.tsx +156 -0
- package/src/lib/DemPropertyField/SingleDemField/index.ts +1 -0
- package/src/lib/DemPropertyField/index.ts +2 -0
- package/src/lib/DemPropertyField/styles.ts +50 -0
- package/src/lib/DemPropertyField/widgets/DemBooleanWidget.tsx +26 -0
- package/src/lib/DemPropertyField/widgets/DemDateTimeWidget.tsx +34 -0
- package/src/lib/DemPropertyField/widgets/DemDateWidget.tsx +33 -0
- package/src/lib/DemPropertyField/widgets/DemFieldWidget.tsx +67 -0
- package/src/lib/DemPropertyField/widgets/DemFloatWidget.tsx +49 -0
- package/src/lib/DemPropertyField/widgets/DemIntegerWidget.tsx +63 -0
- package/src/lib/DemPropertyField/widgets/DemJsonWidget.tsx +33 -0
- package/src/lib/DemPropertyField/widgets/DemStringWidget.tsx +35 -0
- package/src/lib/DemPropertyField/widgets/DemTimeWidget.tsx +46 -0
- package/src/lib/DemPropertyField/widgets/index.ts +1 -0
- package/src/lib/Forms/BackButton.tsx +45 -0
- package/src/lib/Forms/ControlAceEditor.tsx +103 -0
- package/src/lib/Forms/ControlAutocomplete.tsx +134 -0
- package/src/lib/Forms/ControlCheckbox.tsx +57 -0
- package/src/lib/Forms/ControlDebouncedInput.tsx +69 -0
- package/src/lib/Forms/ControlInput.tsx +102 -0
- package/src/lib/Forms/ControlNumberInput.tsx +144 -0
- package/src/lib/Forms/ControlRadioBtn.tsx +46 -0
- package/src/lib/Forms/ControlSelect.tsx +135 -0
- package/src/lib/Forms/CopyButton.tsx +49 -0
- package/src/lib/Forms/index.ts +10 -0
- package/src/lib/InfoItem/InfoItem.tsx +39 -0
- package/src/lib/InfoItem/index.ts +1 -0
- package/src/lib/InfoItem/styles.ts +17 -0
- package/src/lib/JsonPathPicker/JsonPathPicker.tsx +71 -0
- package/src/lib/JsonPathPicker/PropertyStep.tsx +74 -0
- package/src/lib/JsonPathPicker/index.ts +1 -0
- package/src/lib/JsonView/JsonView.tsx +43 -0
- package/src/lib/JsonView/index.ts +1 -0
- package/src/lib/Loader/Loader.tsx +41 -0
- package/src/lib/Loader/index.ts +1 -0
- package/src/lib/Modals/JsonModalView.tsx +52 -0
- package/src/lib/Modals/index.ts +1 -0
- package/src/lib/Property/PropertyValueField/BooleanValueField.tsx +41 -0
- package/src/lib/Property/PropertyValueField/DateTimeValueField.tsx +59 -0
- package/src/lib/Property/PropertyValueField/DateValueField.tsx +59 -0
- package/src/lib/Property/PropertyValueField/EntityValueField.tsx +33 -0
- package/src/lib/Property/PropertyValueField/JsonValueField.tsx +64 -0
- package/src/lib/Property/PropertyValueField/PropertyValue.tsx +97 -0
- package/src/lib/Property/PropertyValueField/PropertyValueField.tsx +86 -0
- package/src/lib/Property/PropertyValueField/StringValueField.tsx +21 -0
- package/src/lib/Property/PropertyValueField/TimeValueField.tsx +68 -0
- package/src/lib/Property/PropertyValueField/ValueComponent.tsx +63 -0
- package/src/lib/Property/PropertyValueField/index.ts +1 -0
- package/src/lib/Property/PropertyWidget/PropertyWidget.tsx +167 -0
- package/src/lib/Property/PropertyWidget/index.ts +1 -0
- package/src/lib/Property/UpsertProperty/CreatePropertiesList.tsx +131 -0
- package/src/lib/Property/UpsertProperty/CreatePropertyFormFields.tsx +147 -0
- package/src/lib/Property/UpsertProperty/CustomPropertyField.tsx +40 -0
- package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/BigDecimalPropertyFields.tsx +41 -0
- package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/DateAdditionalFields.tsx +27 -0
- package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/EntityAdditionalFields.tsx +133 -0
- package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/EntityReferencePropertyFields.tsx +46 -0
- package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/PropertyAdditionalFields.tsx +52 -0
- package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/StringPropertyFields.tsx +98 -0
- package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/index.ts +1 -0
- package/src/lib/Property/UpsertProperty/index.ts +2 -0
- package/src/lib/Property/UpsertProperty/useCustomFields.ts +22 -0
- package/src/lib/Property/ViewPropertiesList/ViewPropertiesList.tsx +50 -0
- package/src/lib/Property/ViewPropertiesList/index.ts +1 -0
- package/src/lib/Property/ViewProperty/EntityPropertiesShortView.tsx +41 -0
- package/src/lib/Property/ViewProperty/EntityPropertiesView.tsx +48 -0
- package/src/lib/Property/ViewProperty/PropertyDataTable.tsx +139 -0
- package/src/lib/Property/ViewProperty/PropertyItem.tsx +46 -0
- package/src/lib/Property/ViewProperty/ViewProperty.tsx +52 -0
- package/src/lib/Property/ViewProperty/index.ts +1 -0
- package/src/lib/Property/index.ts +4 -0
- package/src/lib/Status/Status.tsx +15 -0
- package/src/lib/Status/index.ts +1 -0
- package/src/lib/Status/styles.ts +14 -0
- package/src/lib/Table/Table.tsx +116 -0
- package/src/lib/Table/TableColumnMenu.tsx +12 -0
- package/src/lib/Table/TablePagination.tsx +42 -0
- package/src/lib/Table/index.ts +1 -0
- package/src/lib/Table/styles.ts +59 -0
- package/src/lib/Table/usePagination.ts +15 -0
- package/src/lib/Table/useTableQueryPagination.ts +49 -0
- package/src/lib/Table/useTableQuerySorting.ts +52 -0
- package/src/lib/Tabs/RouteTabs.tsx +54 -0
- package/src/lib/Tabs/TabPanel.tsx +42 -0
- package/src/lib/Tabs/index.ts +2 -0
- package/src/lib/TemplateContent/ExpressionDecorator.tsx +7 -0
- package/src/lib/TemplateContent/TemplateContentEditor.tsx +144 -0
- package/src/lib/TemplateContent/index.ts +1 -0
- package/src/lib/index.ts +14 -0
- package/src/utils/common.ts +68 -0
- package/src/utils/dem.ts +78 -0
- package/src/utils/hooks.ts +41 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/ui-utils.tsx +71 -0
- package/src/utils/validators.ts +130 -0
- package/tsconfig.json +24 -0
- package/tsconfig.lib.json +22 -0
- package/tsconfig.spec.json +19 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
import { Controller, Control, useFormContext } from 'react-hook-form';
|
2
|
+
import AceEditor from 'react-ace';
|
3
|
+
import 'ace-builds/src-noconflict/mode-python';
|
4
|
+
import 'ace-builds/src-noconflict/theme-monokai';
|
5
|
+
import 'ace-builds/src-noconflict/ext-language_tools';
|
6
|
+
import Typography from '@material-ui/core/Typography';
|
7
|
+
import FormHelperText from '@material-ui/core/FormHelperText';
|
8
|
+
|
9
|
+
export interface ControlAceEditorProps {
|
10
|
+
name: string;
|
11
|
+
control: Control<any>;
|
12
|
+
mode?: string;
|
13
|
+
label?: string;
|
14
|
+
width?: string;
|
15
|
+
height?: string;
|
16
|
+
theme?: string;
|
17
|
+
readOnly?: boolean;
|
18
|
+
required?: boolean;
|
19
|
+
validateJson?: boolean;
|
20
|
+
fontSize?: number;
|
21
|
+
}
|
22
|
+
|
23
|
+
export const ControlAceEditor = ({
|
24
|
+
control,
|
25
|
+
name,
|
26
|
+
mode = 'json',
|
27
|
+
label,
|
28
|
+
width = '100%',
|
29
|
+
height = '200px',
|
30
|
+
theme = 'monokai',
|
31
|
+
readOnly,
|
32
|
+
required = false,
|
33
|
+
validateJson = false,
|
34
|
+
fontSize = 16,
|
35
|
+
}: ControlAceEditorProps) => {
|
36
|
+
const { setError, clearErrors } = useFormContext();
|
37
|
+
|
38
|
+
return (
|
39
|
+
<>
|
40
|
+
{label && (
|
41
|
+
<Typography variant="subtitle1" display="inline" style={{ marginRight: 10 }}>
|
42
|
+
{label}
|
43
|
+
</Typography>
|
44
|
+
)}
|
45
|
+
|
46
|
+
<Controller
|
47
|
+
control={control}
|
48
|
+
name={name}
|
49
|
+
render={({ field, fieldState }) => (
|
50
|
+
<>
|
51
|
+
<AceEditor
|
52
|
+
{...field}
|
53
|
+
value={mode === 'json' && typeof field.value !== 'string' ? JSON.stringify(field.value) : field.value}
|
54
|
+
onChange={(value) => {
|
55
|
+
if (!value) {
|
56
|
+
if (required) {
|
57
|
+
setError(name, { message: 'Required field' });
|
58
|
+
} else {
|
59
|
+
clearErrors(name);
|
60
|
+
field.onChange('');
|
61
|
+
}
|
62
|
+
return;
|
63
|
+
}
|
64
|
+
|
65
|
+
field.onChange(value);
|
66
|
+
|
67
|
+
if (validateJson) {
|
68
|
+
try {
|
69
|
+
JSON.parse(value);
|
70
|
+
} catch (error) {
|
71
|
+
setError(name, { message: 'Invalid JSON' });
|
72
|
+
return;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
clearErrors(name);
|
76
|
+
return;
|
77
|
+
}}
|
78
|
+
width={width}
|
79
|
+
height={height}
|
80
|
+
readOnly={readOnly}
|
81
|
+
mode={mode}
|
82
|
+
focus
|
83
|
+
showPrintMargin={false}
|
84
|
+
theme={theme}
|
85
|
+
wrapEnabled
|
86
|
+
fontSize={fontSize}
|
87
|
+
setOptions={{
|
88
|
+
enableLiveAutocompletion: true,
|
89
|
+
enableBasicAutocompletion: true,
|
90
|
+
showLineNumbers: true,
|
91
|
+
tabSize: 2,
|
92
|
+
}}
|
93
|
+
style={{ lineHeight: 1.4, zIndex: 0, isolation: 'isolate' }}
|
94
|
+
/>
|
95
|
+
{fieldState.error && <FormHelperText error>{fieldState.error.message}</FormHelperText>}
|
96
|
+
</>
|
97
|
+
)}
|
98
|
+
/>
|
99
|
+
</>
|
100
|
+
);
|
101
|
+
};
|
102
|
+
|
103
|
+
export default ControlAceEditor;
|
@@ -0,0 +1,134 @@
|
|
1
|
+
import { Controller, Control } from 'react-hook-form';
|
2
|
+
import TextField from '@material-ui/core/TextField';
|
3
|
+
import Autocomplete from '@material-ui/lab/Autocomplete';
|
4
|
+
import { useCallback } from 'react';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* This interface is referencing the [[ControlAutocomplete]] component props.
|
8
|
+
* @category Forms
|
9
|
+
*/
|
10
|
+
export interface ControlAutocompleteProps {
|
11
|
+
/**
|
12
|
+
* React Hook Form control `name` propery
|
13
|
+
*/
|
14
|
+
name: string;
|
15
|
+
/**
|
16
|
+
* React Hook Form `control`
|
17
|
+
*/
|
18
|
+
control: Control<any>;
|
19
|
+
/**
|
20
|
+
* Autocomplete `options` prop
|
21
|
+
*/
|
22
|
+
options?: any[];
|
23
|
+
/**
|
24
|
+
* Material-UI TextField `label` prop
|
25
|
+
*/
|
26
|
+
label: string;
|
27
|
+
/**
|
28
|
+
* Material-UI TextField `placeholder` prop
|
29
|
+
*/
|
30
|
+
placeholder?: string;
|
31
|
+
/**
|
32
|
+
* Autocomplete `multiple` prop
|
33
|
+
*/
|
34
|
+
/**
|
35
|
+
* onChange handle function
|
36
|
+
*/
|
37
|
+
onChange?: (name: string, value: unknown) => void;
|
38
|
+
multiple?: boolean;
|
39
|
+
required?: boolean;
|
40
|
+
disableCloseOnSelect?: boolean;
|
41
|
+
filterSelectedOptions?: boolean;
|
42
|
+
labelKey?: string;
|
43
|
+
valueKey?: string;
|
44
|
+
loading?: boolean;
|
45
|
+
getOptionDisabled?: (option) => boolean;
|
46
|
+
}
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Material UI `Autocomplete` controlled component. Used with react-hook-form
|
50
|
+
* @category Forms
|
51
|
+
*/
|
52
|
+
export const ControlAutocomplete = ({
|
53
|
+
control,
|
54
|
+
name,
|
55
|
+
options,
|
56
|
+
label,
|
57
|
+
placeholder,
|
58
|
+
multiple,
|
59
|
+
required,
|
60
|
+
disableCloseOnSelect = false,
|
61
|
+
labelKey,
|
62
|
+
valueKey,
|
63
|
+
loading,
|
64
|
+
onChange,
|
65
|
+
getOptionDisabled,
|
66
|
+
}: ControlAutocompleteProps) => {
|
67
|
+
const getOptionSelected = useCallback((option, value) => {
|
68
|
+
if (option && value) {
|
69
|
+
if (typeof option === 'string') {
|
70
|
+
return option === value;
|
71
|
+
} else if (valueKey) {
|
72
|
+
return option[valueKey] === value[valueKey] || option[valueKey] === value;
|
73
|
+
} else if (option.value) {
|
74
|
+
return option.value === value.value || option.value === value;
|
75
|
+
}
|
76
|
+
}
|
77
|
+
return false;
|
78
|
+
}, []);
|
79
|
+
|
80
|
+
const getOptionLabel = useCallback(
|
81
|
+
(option) => {
|
82
|
+
if (option) {
|
83
|
+
if (typeof option === 'string') {
|
84
|
+
return option;
|
85
|
+
} else if (labelKey && option[labelKey]) {
|
86
|
+
return option[labelKey];
|
87
|
+
} else {
|
88
|
+
return option.label || option.name || option.value || option.code || '';
|
89
|
+
}
|
90
|
+
}
|
91
|
+
return '';
|
92
|
+
},
|
93
|
+
[options]
|
94
|
+
);
|
95
|
+
|
96
|
+
return (
|
97
|
+
<Controller
|
98
|
+
name={name}
|
99
|
+
control={control}
|
100
|
+
rules={{
|
101
|
+
required: required && 'Required field',
|
102
|
+
}}
|
103
|
+
render={({ field, fieldState }) => (
|
104
|
+
<Autocomplete
|
105
|
+
{...field}
|
106
|
+
multiple={multiple}
|
107
|
+
size="small"
|
108
|
+
disableCloseOnSelect={disableCloseOnSelect || multiple}
|
109
|
+
filterSelectedOptions={multiple}
|
110
|
+
disablePortal
|
111
|
+
loading={loading}
|
112
|
+
options={options}
|
113
|
+
getOptionSelected={getOptionSelected}
|
114
|
+
getOptionLabel={getOptionLabel}
|
115
|
+
getOptionDisabled={getOptionDisabled ? getOptionDisabled : null}
|
116
|
+
value={field.value || null}
|
117
|
+
onChange={(e, val) => (onChange ? onChange(field.name, val) : field.onChange(val))}
|
118
|
+
renderInput={(params) => (
|
119
|
+
<TextField
|
120
|
+
{...params}
|
121
|
+
label={label}
|
122
|
+
variant="outlined"
|
123
|
+
helperText={fieldState.error?.message}
|
124
|
+
placeholder={placeholder}
|
125
|
+
error={!!fieldState.error}
|
126
|
+
/>
|
127
|
+
)}
|
128
|
+
/>
|
129
|
+
)}
|
130
|
+
/>
|
131
|
+
);
|
132
|
+
};
|
133
|
+
|
134
|
+
export default ControlAutocomplete;
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import Checkbox from '@material-ui/core/Checkbox';
|
2
|
+
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
3
|
+
import { Controller } from 'react-hook-form';
|
4
|
+
|
5
|
+
/**
|
6
|
+
* This interface is referencing the [[ControlCheckbox]] component props.
|
7
|
+
* @category Forms
|
8
|
+
*/
|
9
|
+
export interface ControlCheckboxProps {
|
10
|
+
/**
|
11
|
+
* React Hook Form `control`
|
12
|
+
*/
|
13
|
+
control: any;
|
14
|
+
/**
|
15
|
+
* React Hook Form control `name` propery
|
16
|
+
*/
|
17
|
+
name: string;
|
18
|
+
/**
|
19
|
+
* Material-UI FormControlLabel `label` prop
|
20
|
+
*/
|
21
|
+
label?: string;
|
22
|
+
/**
|
23
|
+
* Is disabled input flag
|
24
|
+
*/
|
25
|
+
disabled?: boolean;
|
26
|
+
onChange?: (name: string, value: unknown) => void;
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Material UI `Checkbox` controlled component. Used with react-hook-form
|
31
|
+
* @category Forms
|
32
|
+
*/
|
33
|
+
export const ControlCheckbox = ({ name, control, label, disabled, onChange }: ControlCheckboxProps) => {
|
34
|
+
return (
|
35
|
+
<FormControlLabel
|
36
|
+
label={label || name}
|
37
|
+
control={
|
38
|
+
<Controller
|
39
|
+
control={control}
|
40
|
+
name={name}
|
41
|
+
render={({ field }) => (
|
42
|
+
<Checkbox
|
43
|
+
color="primary"
|
44
|
+
size="small"
|
45
|
+
{...field}
|
46
|
+
onChange={(e, checked) => (onChange ? onChange(field.name, checked) : field.onChange(e))}
|
47
|
+
checked={field.value}
|
48
|
+
disabled={disabled}
|
49
|
+
/>
|
50
|
+
)}
|
51
|
+
/>
|
52
|
+
}
|
53
|
+
/>
|
54
|
+
);
|
55
|
+
};
|
56
|
+
|
57
|
+
export default ControlCheckbox;
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import TextField from '@material-ui/core/TextField';
|
2
|
+
import { useCallback, useMemo, useState } from 'react';
|
3
|
+
import { Controller, useFormContext } from 'react-hook-form';
|
4
|
+
import { ControlInputProps } from './ControlInput';
|
5
|
+
import { useDebounce } from '../../utils';
|
6
|
+
|
7
|
+
export const ControlDebouncedInput = ({
|
8
|
+
inputProps,
|
9
|
+
name,
|
10
|
+
required,
|
11
|
+
validate,
|
12
|
+
label = '',
|
13
|
+
variant = 'outlined',
|
14
|
+
type = 'text',
|
15
|
+
defaultValue = '',
|
16
|
+
disabled,
|
17
|
+
InputLabelProps,
|
18
|
+
textarea,
|
19
|
+
}: ControlInputProps) => {
|
20
|
+
const { setValue, control, getValues } = useFormContext();
|
21
|
+
const [fieldValue, setFieldValue] = useState('');
|
22
|
+
|
23
|
+
const debouncedChange = useDebounce((e) => {
|
24
|
+
setValue(name, e.target.value);
|
25
|
+
}, 350);
|
26
|
+
|
27
|
+
useMemo(() => {
|
28
|
+
const value = getValues(name);
|
29
|
+
setFieldValue(value);
|
30
|
+
}, [getValues, name]);
|
31
|
+
|
32
|
+
const handleChange = useCallback((e) => {
|
33
|
+
setFieldValue(e.target.value);
|
34
|
+
debouncedChange(e);
|
35
|
+
}, [debouncedChange]);
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
return (
|
40
|
+
<Controller
|
41
|
+
name={name}
|
42
|
+
control={control}
|
43
|
+
defaultValue={defaultValue}
|
44
|
+
rules={{ required: required && 'Required field', validate }}
|
45
|
+
render={({ field: { ref, value, ...restProps }, fieldState: { error } }) => (
|
46
|
+
<TextField
|
47
|
+
fullWidth
|
48
|
+
size="small"
|
49
|
+
inputRef={ref}
|
50
|
+
type={type}
|
51
|
+
label={label}
|
52
|
+
error={!!error}
|
53
|
+
helperText={error?.message}
|
54
|
+
disabled={disabled}
|
55
|
+
variant={variant}
|
56
|
+
InputLabelProps={InputLabelProps}
|
57
|
+
inputProps={inputProps}
|
58
|
+
multiline={textarea}
|
59
|
+
minRows={textarea ? 3 : 1}
|
60
|
+
{...restProps}
|
61
|
+
onChange={handleChange}
|
62
|
+
value={fieldValue}
|
63
|
+
/>
|
64
|
+
)}
|
65
|
+
/>
|
66
|
+
);
|
67
|
+
};
|
68
|
+
|
69
|
+
export default ControlDebouncedInput;
|
@@ -0,0 +1,102 @@
|
|
1
|
+
import { useController, Control } from 'react-hook-form';
|
2
|
+
import TextField from '@material-ui/core/TextField';
|
3
|
+
|
4
|
+
type ValidateFunc = (value: string) => boolean | string;
|
5
|
+
type onChangeCallback = (e: any) => void;
|
6
|
+
|
7
|
+
/**
|
8
|
+
* This interface is referencing the [[ControlInput]] component props.
|
9
|
+
* @category Forms
|
10
|
+
*/
|
11
|
+
export interface ControlInputProps {
|
12
|
+
/**
|
13
|
+
* Props for MUI TextField component
|
14
|
+
*/
|
15
|
+
inputProps?: Record<string, string | number | boolean | onChangeCallback | { [key: string]: any }>;
|
16
|
+
/**
|
17
|
+
* React Hook Form control `name` propery
|
18
|
+
*/
|
19
|
+
name: string;
|
20
|
+
label?: string;
|
21
|
+
type?: 'text' | 'date' | 'password' | 'search' | 'number' | 'email' | 'datetime-local';
|
22
|
+
/**
|
23
|
+
* React Hook Form `control`
|
24
|
+
*/
|
25
|
+
control: Control<any>;
|
26
|
+
/**
|
27
|
+
* Is input required flag
|
28
|
+
*/
|
29
|
+
required?: boolean;
|
30
|
+
defaultValue?: any;
|
31
|
+
/**
|
32
|
+
* Is disabled input flag
|
33
|
+
*/
|
34
|
+
disabled?: boolean;
|
35
|
+
/**
|
36
|
+
* Material-UI TextField `variant` prop
|
37
|
+
*/
|
38
|
+
variant?: 'filled' | 'outlined' | 'standard';
|
39
|
+
/**
|
40
|
+
* React Hook Form validate function
|
41
|
+
* ```typescript
|
42
|
+
* type ValidateFunc = (value: string) => boolean | string;
|
43
|
+
* ```
|
44
|
+
*/
|
45
|
+
validate?: ValidateFunc | Record<string, ValidateFunc>;
|
46
|
+
InputLabelProps?: any;
|
47
|
+
textarea?: boolean;
|
48
|
+
}
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Material UI `TextField` controlled component. Used with react-hook-form
|
52
|
+
* @category Forms
|
53
|
+
*/
|
54
|
+
export const ControlInput = ({
|
55
|
+
inputProps,
|
56
|
+
name,
|
57
|
+
control,
|
58
|
+
required,
|
59
|
+
validate,
|
60
|
+
label = '',
|
61
|
+
variant = 'outlined',
|
62
|
+
type = 'text',
|
63
|
+
defaultValue = '',
|
64
|
+
disabled,
|
65
|
+
InputLabelProps,
|
66
|
+
textarea,
|
67
|
+
}: ControlInputProps) => {
|
68
|
+
const {
|
69
|
+
field: { ref, value, ...restProps },
|
70
|
+
fieldState: { error },
|
71
|
+
} = useController({
|
72
|
+
name,
|
73
|
+
control,
|
74
|
+
defaultValue,
|
75
|
+
rules: {
|
76
|
+
required: required && 'Required field',
|
77
|
+
validate,
|
78
|
+
},
|
79
|
+
});
|
80
|
+
|
81
|
+
return (
|
82
|
+
<TextField
|
83
|
+
fullWidth
|
84
|
+
size="small"
|
85
|
+
inputRef={ref}
|
86
|
+
type={type}
|
87
|
+
label={label}
|
88
|
+
error={!!error}
|
89
|
+
helperText={error?.message}
|
90
|
+
disabled={disabled}
|
91
|
+
variant={variant}
|
92
|
+
InputLabelProps={InputLabelProps}
|
93
|
+
inputProps={inputProps}
|
94
|
+
multiline={textarea}
|
95
|
+
minRows={textarea ? 3 : 1}
|
96
|
+
value={value || ''}
|
97
|
+
{...restProps}
|
98
|
+
/>
|
99
|
+
);
|
100
|
+
};
|
101
|
+
|
102
|
+
export default ControlInput;
|
@@ -0,0 +1,144 @@
|
|
1
|
+
import { PropertyType } from '../../interfaces';
|
2
|
+
import TextField from '@material-ui/core/TextField';
|
3
|
+
import { useCallback } from 'react';
|
4
|
+
import { useController, Control, useFormContext } from 'react-hook-form';
|
5
|
+
import { validateFloat, validateInteger } from '../../utils';
|
6
|
+
|
7
|
+
type onChangeCallback = (e: any) => void;
|
8
|
+
|
9
|
+
type Props = {
|
10
|
+
/**
|
11
|
+
* Props for MUI TextField component
|
12
|
+
*/
|
13
|
+
inputProps?: Record<string, string | number | boolean | onChangeCallback | { [key: string]: any }>;
|
14
|
+
/**
|
15
|
+
* React Hook Form control `name` propery
|
16
|
+
*/
|
17
|
+
name: string;
|
18
|
+
label?: string;
|
19
|
+
/**
|
20
|
+
* React Hook Form `control`
|
21
|
+
*/
|
22
|
+
control: Control<any>;
|
23
|
+
/**
|
24
|
+
* Is input required flag
|
25
|
+
*/
|
26
|
+
required?: boolean;
|
27
|
+
defaultValue?: number;
|
28
|
+
/**
|
29
|
+
* Is disabled input flag
|
30
|
+
*/
|
31
|
+
disabled?: boolean;
|
32
|
+
/**
|
33
|
+
* Material-UI TextField `variant` prop
|
34
|
+
*/
|
35
|
+
variant?: 'filled' | 'outlined' | 'standard';
|
36
|
+
/**
|
37
|
+
* React Hook Form validate function
|
38
|
+
* ```typescript
|
39
|
+
* type ValidateFunc = (value: string) => boolean | string;
|
40
|
+
* ```
|
41
|
+
*/
|
42
|
+
InputLabelProps?: any;
|
43
|
+
decimal?: boolean;
|
44
|
+
};
|
45
|
+
|
46
|
+
export const ControlNumberInput = ({
|
47
|
+
inputProps,
|
48
|
+
name,
|
49
|
+
label = '',
|
50
|
+
control,
|
51
|
+
required,
|
52
|
+
defaultValue,
|
53
|
+
disabled,
|
54
|
+
variant = 'outlined',
|
55
|
+
InputLabelProps,
|
56
|
+
decimal = false,
|
57
|
+
}: Props) => {
|
58
|
+
const { setError, clearErrors } = useFormContext();
|
59
|
+
const {
|
60
|
+
field: { ref, onChange, value, ...restProps },
|
61
|
+
fieldState: { error },
|
62
|
+
} = useController({
|
63
|
+
name,
|
64
|
+
control,
|
65
|
+
defaultValue,
|
66
|
+
rules: {
|
67
|
+
required: required && 'Required field',
|
68
|
+
},
|
69
|
+
});
|
70
|
+
|
71
|
+
const handleChange = useCallback(
|
72
|
+
(e) => {
|
73
|
+
let { value: inputValue } = e.target;
|
74
|
+
|
75
|
+
if (inputValue.length >= 2 && inputValue.startsWith('0')) {
|
76
|
+
inputValue = inputValue.slice(1);
|
77
|
+
}
|
78
|
+
|
79
|
+
if (inputValue.length >= 2 && inputValue.startsWith('-') && inputValue[1] === '0') {
|
80
|
+
inputValue = '-' + inputValue.slice(2);
|
81
|
+
}
|
82
|
+
|
83
|
+
if (!inputValue || (inputValue.length < 2 && inputValue[0] === '-')) {
|
84
|
+
onChange(inputValue);
|
85
|
+
return;
|
86
|
+
}
|
87
|
+
|
88
|
+
if (decimal) {
|
89
|
+
const { valid, continuable, message, displayOnChange } = validateFloat(inputValue);
|
90
|
+
|
91
|
+
if (continuable) {
|
92
|
+
onChange(inputValue);
|
93
|
+
}
|
94
|
+
|
95
|
+
if (!valid && displayOnChange && message) {
|
96
|
+
setError(name, { type: 'custom', message });
|
97
|
+
} else {
|
98
|
+
clearErrors(name);
|
99
|
+
}
|
100
|
+
|
101
|
+
if (valid) {
|
102
|
+
onChange(Number(inputValue));
|
103
|
+
}
|
104
|
+
} else {
|
105
|
+
const { valid, continuable, message } = validateInteger(inputValue, PropertyType.INTEGER);
|
106
|
+
|
107
|
+
if (continuable) {
|
108
|
+
onChange(inputValue);
|
109
|
+
}
|
110
|
+
|
111
|
+
if (!valid && message) {
|
112
|
+
setError(name, { type: 'custom', message });
|
113
|
+
} else {
|
114
|
+
clearErrors(name);
|
115
|
+
}
|
116
|
+
|
117
|
+
if (valid) {
|
118
|
+
onChange(Number(inputValue));
|
119
|
+
}
|
120
|
+
}
|
121
|
+
},
|
122
|
+
[decimal]
|
123
|
+
);
|
124
|
+
|
125
|
+
return (
|
126
|
+
<TextField
|
127
|
+
fullWidth
|
128
|
+
size="small"
|
129
|
+
inputRef={ref}
|
130
|
+
label={label}
|
131
|
+
error={!!error}
|
132
|
+
helperText={error?.message}
|
133
|
+
disabled={disabled}
|
134
|
+
variant={variant}
|
135
|
+
InputLabelProps={InputLabelProps}
|
136
|
+
inputProps={inputProps}
|
137
|
+
onChange={handleChange}
|
138
|
+
value={value || ''}
|
139
|
+
{...restProps}
|
140
|
+
/>
|
141
|
+
);
|
142
|
+
};
|
143
|
+
|
144
|
+
export default ControlNumberInput;
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
2
|
+
import Radio from '@material-ui/core/Radio';
|
3
|
+
import RadioGroup from '@material-ui/core/RadioGroup';
|
4
|
+
import { Controller, Control } from 'react-hook-form';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* This interface is referencing the [[ControlRadioBtn]] component props.
|
8
|
+
* @category Forms
|
9
|
+
*/
|
10
|
+
export interface ControlRadioBtnProps {
|
11
|
+
/**
|
12
|
+
* React Hook Form `control`
|
13
|
+
*/
|
14
|
+
control: Control<any>;
|
15
|
+
/**
|
16
|
+
* React Hook Form control `name` propery
|
17
|
+
*/
|
18
|
+
name: string;
|
19
|
+
/**
|
20
|
+
* Radio group values
|
21
|
+
*/
|
22
|
+
values: any[];
|
23
|
+
}
|
24
|
+
|
25
|
+
/**
|
26
|
+
* Material UI `Radio` controlled component. Used with react-hook-form
|
27
|
+
* @category Forms
|
28
|
+
*/
|
29
|
+
export const ControlRadioBtn = ({ name, values, control }: ControlRadioBtnProps) => {
|
30
|
+
|
31
|
+
return (
|
32
|
+
<Controller
|
33
|
+
control={control}
|
34
|
+
name={name}
|
35
|
+
render={({ field }) => (
|
36
|
+
<RadioGroup row {...field}>
|
37
|
+
{values.map((item) => (
|
38
|
+
<FormControlLabel value={item} control={<Radio />} label={item} />
|
39
|
+
))}
|
40
|
+
</RadioGroup>
|
41
|
+
)}
|
42
|
+
/>
|
43
|
+
)
|
44
|
+
}
|
45
|
+
|
46
|
+
export default ControlRadioBtn;
|