@jsonforms/material-renderers 3.1.0-alpha.1 → 3.1.0-alpha.3
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/README.md +16 -17
- package/lib/additional/ListWithDetailMasterItem.d.ts +2 -0
- package/lib/additional/MaterialListWithDetailRenderer.d.ts +1 -1
- package/lib/additional/index.d.ts +2 -2
- package/lib/additional/unwrapped.d.ts +5 -0
- package/lib/cells/index.d.ts +1 -1
- package/lib/complex/CombinatorProperties.d.ts +1 -2
- package/lib/complex/DeleteDialog.d.ts +5 -1
- package/lib/complex/MaterialAllOfRenderer.d.ts +1 -1
- package/lib/complex/MaterialAnyOfRenderer.d.ts +1 -1
- package/lib/complex/MaterialArrayControlRenderer.d.ts +2 -1
- package/lib/complex/MaterialEnumArrayRenderer.d.ts +1 -1
- package/lib/complex/MaterialObjectRenderer.d.ts +1 -1
- package/lib/complex/MaterialOneOfRenderer.d.ts +1 -1
- package/lib/complex/MaterialTableControl.d.ts +4 -2
- package/lib/complex/NoBorderTableCell.d.ts +2 -2
- package/lib/complex/TableToolbar.d.ts +3 -2
- package/lib/complex/index.d.ts +11 -16
- package/lib/complex/unwrapped.d.ts +9 -0
- package/lib/controls/MaterialBooleanControl.d.ts +1 -1
- package/lib/controls/MaterialBooleanToggleControl.d.ts +1 -1
- package/lib/controls/index.d.ts +8 -26
- package/lib/controls/unwrapped.d.ts +19 -0
- package/lib/index.d.ts +34 -1
- package/lib/jsonforms-react-material.cjs.js +690 -599
- package/lib/jsonforms-react-material.cjs.js.map +1 -1
- package/lib/jsonforms-react-material.esm.js +620 -557
- package/lib/jsonforms-react-material.esm.js.map +1 -1
- package/lib/layouts/ArrayToolbar.d.ts +3 -1
- package/lib/layouts/ExpandPanelRenderer.d.ts +3 -1
- package/lib/layouts/MaterialGroupLayout.d.ts +1 -1
- package/lib/layouts/MaterialHorizontalLayout.d.ts +1 -1
- package/lib/layouts/MaterialVerticalLayout.d.ts +1 -1
- package/lib/layouts/index.d.ts +3 -1
- package/lib/layouts/unwrapped.d.ts +10 -0
- package/lib/mui-controls/MuiCheckbox.d.ts +1 -1
- package/lib/mui-controls/MuiInputInteger.d.ts +1 -1
- package/lib/mui-controls/MuiInputNumber.d.ts +1 -1
- package/lib/mui-controls/MuiInputNumberFormat.d.ts +1 -1
- package/lib/mui-controls/MuiInputText.d.ts +1 -1
- package/lib/mui-controls/MuiInputTime.d.ts +1 -1
- package/lib/mui-controls/MuiSelect.d.ts +1 -1
- package/lib/mui-controls/MuiToggle.d.ts +1 -1
- package/lib/mui-controls/index.d.ts +3 -1
- package/lib/util/layout.d.ts +2 -3
- package/package.json +16 -9
- package/src/additional/ListWithDetailMasterItem.tsx +31 -23
- package/src/additional/MaterialLabelRenderer.tsx +8 -15
- package/src/additional/MaterialListWithDetailRenderer.tsx +8 -5
- package/src/additional/index.ts +12 -4
- package/src/additional/unwrapped.ts +32 -0
- package/src/cells/MaterialBooleanCell.tsx +1 -1
- package/src/cells/MaterialBooleanToggleCell.tsx +2 -2
- package/src/cells/MaterialDateCell.tsx +4 -12
- package/src/cells/MaterialEnumCell.tsx +13 -6
- package/src/cells/MaterialIntegerCell.tsx +1 -1
- package/src/cells/MaterialNumberCell.tsx +1 -1
- package/src/cells/MaterialNumberFormatCell.tsx +1 -1
- package/src/cells/MaterialOneOfEnumCell.tsx +17 -7
- package/src/cells/MaterialTextCell.tsx +1 -1
- package/src/cells/MaterialTimeCell.tsx +1 -1
- package/src/cells/index.ts +7 -7
- package/src/complex/CombinatorProperties.tsx +20 -9
- package/src/complex/DeleteDialog.tsx +48 -37
- package/src/complex/MaterialAllOfRenderer.tsx +2 -2
- package/src/complex/MaterialAnyOfRenderer.tsx +3 -3
- package/src/complex/MaterialArrayControlRenderer.tsx +27 -11
- package/src/complex/MaterialEnumArrayRenderer.tsx +6 -8
- package/src/complex/MaterialObjectRenderer.tsx +6 -3
- package/src/complex/MaterialOneOfRenderer.tsx +105 -88
- package/src/complex/MaterialTableControl.tsx +145 -97
- package/src/complex/NoBorderTableCell.tsx +3 -5
- package/src/complex/TableToolbar.tsx +24 -25
- package/src/complex/ValidationIcon.tsx +10 -18
- package/src/complex/index.ts +35 -32
- package/src/complex/unwrapped.ts +39 -0
- package/src/controls/MaterialAnyOfStringOrEnumControl.tsx +19 -11
- package/src/controls/MaterialBooleanControl.tsx +22 -16
- package/src/controls/MaterialBooleanToggleControl.tsx +22 -16
- package/src/controls/MaterialDateControl.tsx +16 -19
- package/src/controls/MaterialDateTimeControl.tsx +24 -23
- package/src/controls/MaterialEnumControl.tsx +21 -15
- package/src/controls/MaterialInputControl.tsx +7 -8
- package/src/controls/MaterialIntegerControl.tsx +1 -1
- package/src/controls/MaterialNativeControl.tsx +12 -9
- package/src/controls/MaterialNumberControl.tsx +1 -1
- package/src/controls/MaterialOneOfEnumControl.tsx +21 -15
- package/src/controls/MaterialOneOfRadioGroupControl.tsx +5 -3
- package/src/controls/MaterialRadioGroup.tsx +11 -17
- package/src/controls/MaterialRadioGroupControl.tsx +8 -3
- package/src/controls/MaterialSliderControl.tsx +17 -16
- package/src/controls/MaterialTextControl.tsx +1 -1
- package/src/controls/MaterialTimeControl.tsx +19 -22
- package/src/controls/index.ts +36 -72
- package/src/controls/unwrapped.ts +57 -0
- package/src/index.ts +41 -22
- package/src/layouts/ArrayToolbar.tsx +38 -42
- package/src/layouts/ExpandPanelRenderer.tsx +96 -67
- package/src/layouts/MaterialArrayLayout.tsx +21 -16
- package/src/layouts/MaterialArrayLayoutRenderer.tsx +6 -9
- package/src/layouts/MaterialCategorizationLayout.tsx +52 -21
- package/src/layouts/MaterialCategorizationStepperLayout.tsx +60 -44
- package/src/layouts/MaterialGroupLayout.tsx +25 -6
- package/src/layouts/MaterialHorizontalLayout.tsx +18 -4
- package/src/layouts/MaterialVerticalLayout.tsx +18 -4
- package/src/layouts/index.ts +18 -7
- package/src/layouts/unwrapped.ts +41 -0
- package/src/mui-controls/MuiAutocomplete.tsx +51 -35
- package/src/mui-controls/MuiCheckbox.tsx +5 -3
- package/src/mui-controls/MuiInputInteger.tsx +31 -32
- package/src/mui-controls/MuiInputNumber.tsx +16 -16
- package/src/mui-controls/MuiInputNumberFormat.tsx +51 -42
- package/src/mui-controls/MuiInputText.tsx +30 -19
- package/src/mui-controls/MuiInputTime.tsx +11 -12
- package/src/mui-controls/MuiSelect.tsx +15 -6
- package/src/mui-controls/MuiToggle.tsx +5 -3
- package/src/mui-controls/index.ts +3 -1
- package/src/util/datejs.tsx +41 -20
- package/src/util/debounce.ts +26 -11
- package/src/util/focus.ts +7 -7
- package/src/util/i18nDefaults.ts +2 -2
- package/src/util/layout.tsx +47 -42
- package/src/util/theme.ts +2 -2
|
@@ -22,52 +22,61 @@
|
|
|
22
22
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
23
|
THE SOFTWARE.
|
|
24
24
|
*/
|
|
25
|
-
import React, {useCallback} from 'react';
|
|
25
|
+
import React, { useCallback } from 'react';
|
|
26
26
|
import { CellProps, Formatted, WithClassname } from '@jsonforms/core';
|
|
27
27
|
import { Input } from '@mui/material';
|
|
28
28
|
import merge from 'lodash/merge';
|
|
29
29
|
import { useDebouncedChange } from '../util';
|
|
30
30
|
|
|
31
|
-
export const MuiInputNumberFormat = React.memo(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
31
|
+
export const MuiInputNumberFormat = React.memo(function MuiInputNumberFormat(
|
|
32
|
+
props: CellProps & WithClassname & Formatted<number>
|
|
33
|
+
) {
|
|
34
|
+
const {
|
|
35
|
+
className,
|
|
36
|
+
id,
|
|
37
|
+
enabled,
|
|
38
|
+
uischema,
|
|
39
|
+
isValid,
|
|
40
|
+
path,
|
|
41
|
+
handleChange,
|
|
42
|
+
schema,
|
|
43
|
+
config,
|
|
44
|
+
} = props;
|
|
45
|
+
const maxLength = schema.maxLength;
|
|
46
|
+
const appliedUiSchemaOptions = merge({}, config, uischema.options);
|
|
47
|
+
let inputProps;
|
|
48
|
+
if (appliedUiSchemaOptions.restrict) {
|
|
49
|
+
inputProps = { maxLength: maxLength };
|
|
50
|
+
} else {
|
|
51
|
+
inputProps = {};
|
|
52
|
+
}
|
|
53
|
+
const formattedNumber = props.toFormatted(props.data);
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
const validStringNumber = useCallback(
|
|
56
|
+
(ev: any) => props.fromFormatted(ev.currentTarget.value),
|
|
57
|
+
[props.fromFormatted]
|
|
58
|
+
);
|
|
59
|
+
const [inputValue, onChange] = useDebouncedChange(
|
|
60
|
+
handleChange,
|
|
61
|
+
'',
|
|
62
|
+
formattedNumber,
|
|
63
|
+
path,
|
|
64
|
+
validStringNumber
|
|
65
|
+
);
|
|
56
66
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
});
|
|
67
|
+
return (
|
|
68
|
+
<Input
|
|
69
|
+
type='text'
|
|
70
|
+
value={inputValue}
|
|
71
|
+
onChange={onChange}
|
|
72
|
+
className={className}
|
|
73
|
+
id={id}
|
|
74
|
+
disabled={!enabled}
|
|
75
|
+
autoFocus={appliedUiSchemaOptions.focus}
|
|
76
|
+
multiline={appliedUiSchemaOptions.multi}
|
|
77
|
+
fullWidth={!appliedUiSchemaOptions.trim || maxLength === undefined}
|
|
78
|
+
inputProps={inputProps}
|
|
79
|
+
error={!isValid}
|
|
80
|
+
/>
|
|
81
|
+
);
|
|
82
|
+
});
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
InputAdornment,
|
|
31
31
|
InputBaseComponentProps,
|
|
32
32
|
InputProps,
|
|
33
|
-
useTheme
|
|
33
|
+
useTheme,
|
|
34
34
|
} from '@mui/material';
|
|
35
35
|
import merge from 'lodash/merge';
|
|
36
36
|
import Close from '@mui/icons-material/Close';
|
|
@@ -41,9 +41,12 @@ interface MuiTextInputProps {
|
|
|
41
41
|
inputComponent?: InputProps['inputComponent'];
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const eventToValue = (ev:any) =>
|
|
44
|
+
const eventToValue = (ev: any) =>
|
|
45
|
+
ev.target.value === '' ? undefined : ev.target.value;
|
|
45
46
|
|
|
46
|
-
export const MuiInputText = React.memo((
|
|
47
|
+
export const MuiInputText = React.memo(function MuiInputText(
|
|
48
|
+
props: CellProps & WithClassname & MuiTextInputProps
|
|
49
|
+
) {
|
|
47
50
|
const [showAdornment, setShowAdornment] = useState(false);
|
|
48
51
|
const {
|
|
49
52
|
data,
|
|
@@ -57,7 +60,7 @@ export const MuiInputText = React.memo((props: CellProps & WithClassname & MuiTe
|
|
|
57
60
|
handleChange,
|
|
58
61
|
schema,
|
|
59
62
|
muiInputProps,
|
|
60
|
-
inputComponent
|
|
63
|
+
inputComponent,
|
|
61
64
|
} = props;
|
|
62
65
|
const maxLength = schema.maxLength;
|
|
63
66
|
const appliedUiSchemaOptions = merge({}, config, uischema.options);
|
|
@@ -67,29 +70,35 @@ export const MuiInputText = React.memo((props: CellProps & WithClassname & MuiTe
|
|
|
67
70
|
} else {
|
|
68
71
|
inputProps = {};
|
|
69
72
|
}
|
|
70
|
-
|
|
73
|
+
|
|
71
74
|
inputProps = merge(inputProps, muiInputProps);
|
|
72
|
-
|
|
75
|
+
|
|
73
76
|
if (appliedUiSchemaOptions.trim && maxLength !== undefined) {
|
|
74
77
|
inputProps.size = maxLength;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const [inputText, onChange, onClear] = useDebouncedChange(
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const [inputText, onChange, onClear] = useDebouncedChange(
|
|
81
|
+
handleChange,
|
|
82
|
+
'',
|
|
83
|
+
data,
|
|
84
|
+
path,
|
|
85
|
+
eventToValue
|
|
86
|
+
);
|
|
78
87
|
const onPointerEnter = () => setShowAdornment(true);
|
|
79
88
|
const onPointerLeave = () => setShowAdornment(false);
|
|
80
89
|
|
|
81
90
|
const theme: JsonFormsTheme = useTheme();
|
|
82
|
-
|
|
91
|
+
|
|
83
92
|
const closeStyle = {
|
|
84
|
-
background:
|
|
85
|
-
|
|
93
|
+
background:
|
|
94
|
+
theme.jsonforms?.input?.delete?.background ||
|
|
95
|
+
theme.palette.background.default,
|
|
96
|
+
borderRadius: '50%',
|
|
86
97
|
};
|
|
87
98
|
|
|
88
99
|
return (
|
|
89
100
|
<Input
|
|
90
|
-
type={
|
|
91
|
-
appliedUiSchemaOptions.format === 'password' ? 'password' : 'text'
|
|
92
|
-
}
|
|
101
|
+
type={appliedUiSchemaOptions.format === 'password' ? 'password' : 'text'}
|
|
93
102
|
value={inputText}
|
|
94
103
|
onChange={onChange}
|
|
95
104
|
className={className}
|
|
@@ -107,17 +116,19 @@ export const MuiInputText = React.memo((props: CellProps & WithClassname & MuiTe
|
|
|
107
116
|
position='end'
|
|
108
117
|
style={{
|
|
109
118
|
display:
|
|
110
|
-
!showAdornment || !enabled || data === undefined
|
|
119
|
+
!showAdornment || !enabled || data === undefined
|
|
120
|
+
? 'none'
|
|
121
|
+
: 'flex',
|
|
111
122
|
position: 'absolute',
|
|
112
|
-
right: 0
|
|
123
|
+
right: 0,
|
|
113
124
|
}}
|
|
114
125
|
>
|
|
115
126
|
<IconButton
|
|
116
127
|
aria-label='Clear input field'
|
|
117
|
-
onClick={onClear}
|
|
128
|
+
onClick={onClear}
|
|
118
129
|
size='large'
|
|
119
130
|
>
|
|
120
|
-
<Close style={closeStyle}/>
|
|
131
|
+
<Close style={closeStyle} />
|
|
121
132
|
</IconButton>
|
|
122
133
|
</InputAdornment>
|
|
123
134
|
}
|
|
@@ -28,19 +28,18 @@ import { Input } from '@mui/material';
|
|
|
28
28
|
import merge from 'lodash/merge';
|
|
29
29
|
import { useDebouncedChange } from '../util';
|
|
30
30
|
|
|
31
|
-
export const MuiInputTime = React.memo((
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
enabled,
|
|
37
|
-
uischema,
|
|
38
|
-
path,
|
|
39
|
-
handleChange,
|
|
40
|
-
config
|
|
41
|
-
} = props;
|
|
31
|
+
export const MuiInputTime = React.memo(function MuiInputTime(
|
|
32
|
+
props: CellProps & WithClassname
|
|
33
|
+
) {
|
|
34
|
+
const { data, className, id, enabled, uischema, path, handleChange, config } =
|
|
35
|
+
props;
|
|
42
36
|
const appliedUiSchemaOptions = merge({}, config, uischema.options);
|
|
43
|
-
const [inputValue, onChange] = useDebouncedChange(
|
|
37
|
+
const [inputValue, onChange] = useDebouncedChange(
|
|
38
|
+
handleChange,
|
|
39
|
+
'',
|
|
40
|
+
data,
|
|
41
|
+
path
|
|
42
|
+
);
|
|
44
43
|
|
|
45
44
|
return (
|
|
46
45
|
<Input
|
|
@@ -30,7 +30,9 @@ import merge from 'lodash/merge';
|
|
|
30
30
|
import { TranslateProps } from '@jsonforms/react';
|
|
31
31
|
import { i18nDefaults } from '../util';
|
|
32
32
|
|
|
33
|
-
export const MuiSelect = React.memo((
|
|
33
|
+
export const MuiSelect = React.memo(function MuiSelect(
|
|
34
|
+
props: EnumCellProps & WithClassname & TranslateProps
|
|
35
|
+
) {
|
|
34
36
|
const {
|
|
35
37
|
data,
|
|
36
38
|
className,
|
|
@@ -42,10 +44,13 @@ export const MuiSelect = React.memo((props: EnumCellProps & WithClassname & Tran
|
|
|
42
44
|
handleChange,
|
|
43
45
|
options,
|
|
44
46
|
config,
|
|
45
|
-
t
|
|
47
|
+
t,
|
|
46
48
|
} = props;
|
|
47
49
|
const appliedUiSchemaOptions = merge({}, config, uischema.options);
|
|
48
|
-
const noneOptionLabel = useMemo(
|
|
50
|
+
const noneOptionLabel = useMemo(
|
|
51
|
+
() => t('enum.none', i18nDefaults['enum.none'], { schema, uischema, path }),
|
|
52
|
+
[t, schema, uischema, path]
|
|
53
|
+
);
|
|
49
54
|
|
|
50
55
|
return (
|
|
51
56
|
<Select
|
|
@@ -54,12 +59,16 @@ export const MuiSelect = React.memo((props: EnumCellProps & WithClassname & Tran
|
|
|
54
59
|
disabled={!enabled}
|
|
55
60
|
autoFocus={appliedUiSchemaOptions.focus}
|
|
56
61
|
value={data !== undefined ? data : ''}
|
|
57
|
-
onChange={ev =>handleChange(path, ev.target.value || undefined)}
|
|
62
|
+
onChange={(ev) => handleChange(path, ev.target.value || undefined)}
|
|
58
63
|
fullWidth={true}
|
|
59
64
|
variant={'standard'}
|
|
60
65
|
>
|
|
61
|
-
{[
|
|
62
|
-
|
|
66
|
+
{[
|
|
67
|
+
<MenuItem value={''} key='jsonforms.enum.none'>
|
|
68
|
+
<em>{noneOptionLabel}</em>
|
|
69
|
+
</MenuItem>,
|
|
70
|
+
].concat(
|
|
71
|
+
options.map((optionValue) => (
|
|
63
72
|
<MenuItem value={optionValue.value} key={optionValue.value}>
|
|
64
73
|
{optionValue.label}
|
|
65
74
|
</MenuItem>
|
|
@@ -31,7 +31,9 @@ interface MuiToggleInputProps {
|
|
|
31
31
|
inputProps?: InputProps['inputProps'];
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export const MuiToggle = React.memo((
|
|
34
|
+
export const MuiToggle = React.memo(function MuiToggle(
|
|
35
|
+
props: CellProps & WithClassname & MuiToggleInputProps
|
|
36
|
+
) {
|
|
35
37
|
const {
|
|
36
38
|
data,
|
|
37
39
|
className,
|
|
@@ -41,11 +43,11 @@ export const MuiToggle = React.memo((props: CellProps & WithClassname & MuiToggl
|
|
|
41
43
|
path,
|
|
42
44
|
handleChange,
|
|
43
45
|
config,
|
|
44
|
-
inputProps
|
|
46
|
+
inputProps,
|
|
45
47
|
} = props;
|
|
46
48
|
const appliedUiSchemaOptions = merge({}, config, uischema.options);
|
|
47
49
|
const inputPropsMerged = merge({}, inputProps, {
|
|
48
|
-
autoFocus: !!appliedUiSchemaOptions.focus
|
|
50
|
+
autoFocus: !!appliedUiSchemaOptions.focus,
|
|
49
51
|
});
|
|
50
52
|
const checked = !!data;
|
|
51
53
|
|
|
@@ -22,10 +22,12 @@
|
|
|
22
22
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
23
|
THE SOFTWARE.
|
|
24
24
|
*/
|
|
25
|
+
export * from './MuiAutocomplete';
|
|
25
26
|
export * from './MuiCheckbox';
|
|
26
|
-
export * from './MuiSelect';
|
|
27
27
|
export * from './MuiInputInteger';
|
|
28
28
|
export * from './MuiInputNumber';
|
|
29
29
|
export * from './MuiInputNumberFormat';
|
|
30
30
|
export * from './MuiInputText';
|
|
31
31
|
export * from './MuiInputTime';
|
|
32
|
+
export * from './MuiSelect';
|
|
33
|
+
export * from './MuiToggle';
|
package/src/util/datejs.tsx
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
import { TextField, TextFieldProps } from '@mui/material';
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
3
|
import customParsing from 'dayjs/plugin/customParseFormat';
|
|
4
|
-
import React, { useRef} from 'react';
|
|
4
|
+
import React, { useRef } from 'react';
|
|
5
5
|
|
|
6
6
|
// required for the custom save formats in the date, time and date-time pickers
|
|
7
7
|
dayjs.extend(customParsing);
|
|
8
8
|
|
|
9
|
-
export const createOnChangeHandler =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
export const createOnChangeHandler =
|
|
10
|
+
(
|
|
11
|
+
path: string,
|
|
12
|
+
handleChange: (path: string, value: any) => void,
|
|
13
|
+
saveFormat: string | undefined
|
|
14
|
+
) =>
|
|
15
|
+
(time: dayjs.Dayjs, textInputValue: string) => {
|
|
16
|
+
if (!time) {
|
|
17
|
+
handleChange(path, undefined);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const result = dayjs(time).format(saveFormat);
|
|
21
|
+
handleChange(path, result === 'Invalid Date' ? textInputValue : result);
|
|
22
|
+
};
|
|
21
23
|
|
|
22
24
|
export const getData = (
|
|
23
25
|
data: any,
|
|
@@ -33,7 +35,6 @@ export const getData = (
|
|
|
33
35
|
return dayjsData;
|
|
34
36
|
};
|
|
35
37
|
|
|
36
|
-
|
|
37
38
|
interface InputRef {
|
|
38
39
|
lastInput: string;
|
|
39
40
|
toShow: string;
|
|
@@ -44,7 +45,7 @@ type ResettableTextFieldProps = TextFieldProps & {
|
|
|
44
45
|
dayjsValueIsValid: boolean;
|
|
45
46
|
valueInInputFormat: string;
|
|
46
47
|
focused: boolean;
|
|
47
|
-
}
|
|
48
|
+
};
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
51
|
* The dayjs formatter/parser is very lenient and for example ignores additional digits and/or characters.
|
|
@@ -52,13 +53,28 @@ type ResettableTextFieldProps = TextFieldProps & {
|
|
|
52
53
|
* The 'ResettableTextField' component adjusts the text field to reflect the actual value stored in the data
|
|
53
54
|
* once it's no longer 'focused', i.e. when the user stops editing.
|
|
54
55
|
*/
|
|
55
|
-
export const ResettableTextField: React.FC<ResettableTextFieldProps> = ({
|
|
56
|
-
|
|
56
|
+
export const ResettableTextField: React.FC<ResettableTextFieldProps> = ({
|
|
57
|
+
rawValue,
|
|
58
|
+
dayjsValueIsValid,
|
|
59
|
+
valueInInputFormat,
|
|
60
|
+
focused,
|
|
61
|
+
inputProps,
|
|
62
|
+
...props
|
|
63
|
+
}) => {
|
|
64
|
+
const value = useRef<InputRef>({
|
|
65
|
+
lastInput: inputProps?.value,
|
|
66
|
+
toShow: inputProps?.value,
|
|
67
|
+
});
|
|
57
68
|
if (!focused) {
|
|
58
69
|
// The input text is not focused, therefore let's show the value actually stored in the data
|
|
59
70
|
if (!dayjsValueIsValid) {
|
|
60
71
|
// pass through the "raw" value in case it can't be formatted by dayjs
|
|
61
|
-
value.current.toShow =
|
|
72
|
+
value.current.toShow =
|
|
73
|
+
typeof rawValue === 'string' ||
|
|
74
|
+
rawValue === null ||
|
|
75
|
+
rawValue === undefined
|
|
76
|
+
? rawValue
|
|
77
|
+
: JSON.stringify(rawValue);
|
|
62
78
|
} else {
|
|
63
79
|
// otherwise use the specified format
|
|
64
80
|
value.current.toShow = valueInInputFormat;
|
|
@@ -69,5 +85,10 @@ export const ResettableTextField: React.FC<ResettableTextFieldProps> = ({ rawVal
|
|
|
69
85
|
value.current.lastInput = inputProps?.value;
|
|
70
86
|
value.current.toShow = inputProps?.value;
|
|
71
87
|
}
|
|
72
|
-
return
|
|
73
|
-
|
|
88
|
+
return (
|
|
89
|
+
<TextField
|
|
90
|
+
{...props}
|
|
91
|
+
inputProps={{ ...inputProps, value: value.current.toShow || '' }}
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
94
|
+
};
|
package/src/util/debounce.ts
CHANGED
|
@@ -23,21 +23,36 @@
|
|
|
23
23
|
THE SOFTWARE.
|
|
24
24
|
*/
|
|
25
25
|
import debounce from 'lodash/debounce';
|
|
26
|
-
import { useState, useCallback, useEffect } from 'react'
|
|
27
|
-
|
|
26
|
+
import { useState, useCallback, useEffect } from 'react';
|
|
28
27
|
|
|
29
28
|
const eventToValue = (ev: any) => ev.target.value;
|
|
30
|
-
export const useDebouncedChange = (
|
|
29
|
+
export const useDebouncedChange = (
|
|
30
|
+
handleChange: (path: string, value: any) => void,
|
|
31
|
+
defaultValue: any,
|
|
32
|
+
data: any,
|
|
33
|
+
path: string,
|
|
34
|
+
eventToValueFunction: (ev: any) => any = eventToValue,
|
|
35
|
+
timeout = 300
|
|
36
|
+
): [any, React.ChangeEventHandler, () => void] => {
|
|
31
37
|
const [input, setInput] = useState(data ?? defaultValue);
|
|
32
38
|
useEffect(() => {
|
|
33
39
|
setInput(data ?? defaultValue);
|
|
34
40
|
}, [data]);
|
|
35
|
-
const debouncedUpdate = useCallback(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
const debouncedUpdate = useCallback(
|
|
42
|
+
debounce((newValue: string) => handleChange(path, newValue), timeout),
|
|
43
|
+
[handleChange, path, timeout]
|
|
44
|
+
);
|
|
45
|
+
const onChange = useCallback(
|
|
46
|
+
(ev: any) => {
|
|
47
|
+
const newValue = eventToValueFunction(ev);
|
|
48
|
+
setInput(newValue ?? defaultValue);
|
|
49
|
+
debouncedUpdate(newValue);
|
|
50
|
+
},
|
|
51
|
+
[debouncedUpdate, eventToValueFunction]
|
|
52
|
+
);
|
|
53
|
+
const onClear = useCallback(() => {
|
|
54
|
+
setInput(defaultValue);
|
|
55
|
+
handleChange(path, undefined);
|
|
56
|
+
}, [defaultValue, handleChange, path]);
|
|
42
57
|
return [input, onChange, onClear];
|
|
43
|
-
};
|
|
58
|
+
};
|
package/src/util/focus.ts
CHANGED
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
23
|
THE SOFTWARE.
|
|
24
24
|
*/
|
|
25
|
-
import {useState, useCallback} from 'react';
|
|
25
|
+
import { useState, useCallback } from 'react';
|
|
26
26
|
|
|
27
|
-
export const useFocus = ():[boolean, () => void, () => void] => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
};
|
|
27
|
+
export const useFocus = (): [boolean, () => void, () => void] => {
|
|
28
|
+
const [focused, setFocused] = useState(false);
|
|
29
|
+
const onFocus = useCallback(() => setFocused(true), []);
|
|
30
|
+
const onBlur = useCallback(() => setFocused(false), []);
|
|
31
|
+
return [focused, onFocus, onBlur];
|
|
32
|
+
};
|
package/src/util/i18nDefaults.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export const i18nDefaults = {
|
|
2
|
-
|
|
3
|
-
}
|
|
2
|
+
'enum.none': 'None',
|
|
3
|
+
};
|
package/src/util/layout.tsx
CHANGED
|
@@ -23,8 +23,7 @@
|
|
|
23
23
|
THE SOFTWARE.
|
|
24
24
|
*/
|
|
25
25
|
import isEmpty from 'lodash/isEmpty';
|
|
26
|
-
import React from 'react';
|
|
27
|
-
import { ComponentType } from 'react';
|
|
26
|
+
import React, { ComponentType } from 'react';
|
|
28
27
|
import Ajv from 'ajv';
|
|
29
28
|
import type { UISchemaElement } from '@jsonforms/core';
|
|
30
29
|
import {
|
|
@@ -63,54 +62,60 @@ export interface MaterialLayoutRendererProps extends OwnPropsOfRenderer {
|
|
|
63
62
|
elements: UISchemaElement[];
|
|
64
63
|
direction: 'row' | 'column';
|
|
65
64
|
}
|
|
66
|
-
const MaterialLayoutRendererComponent =
|
|
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
|
-
|
|
65
|
+
const MaterialLayoutRendererComponent = ({
|
|
66
|
+
visible,
|
|
67
|
+
elements,
|
|
68
|
+
schema,
|
|
69
|
+
path,
|
|
70
|
+
enabled,
|
|
71
|
+
direction,
|
|
72
|
+
renderers,
|
|
73
|
+
cells,
|
|
74
|
+
}: MaterialLayoutRendererProps) => {
|
|
75
|
+
if (isEmpty(elements)) {
|
|
76
|
+
return null;
|
|
77
|
+
} else {
|
|
78
|
+
return (
|
|
79
|
+
<Hidden xsUp={!visible}>
|
|
80
|
+
<Grid
|
|
81
|
+
container
|
|
82
|
+
direction={direction}
|
|
83
|
+
spacing={direction === 'row' ? 2 : 0}
|
|
84
|
+
>
|
|
85
|
+
{renderLayoutElements(
|
|
86
|
+
elements,
|
|
87
|
+
schema,
|
|
88
|
+
path,
|
|
89
|
+
enabled,
|
|
90
|
+
renderers,
|
|
91
|
+
cells
|
|
92
|
+
)}
|
|
93
|
+
</Grid>
|
|
94
|
+
</Hidden>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
export const MaterialLayoutRenderer = React.memo(
|
|
99
|
+
MaterialLayoutRendererComponent
|
|
100
|
+
);
|
|
101
101
|
|
|
102
102
|
export interface AjvProps {
|
|
103
103
|
ajv: Ajv;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
// TODO fix @typescript-eslint/ban-types
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
108
|
+
export const withAjvProps = <P extends {}>(
|
|
109
|
+
Component: ComponentType<AjvProps & P>
|
|
110
|
+
) =>
|
|
111
|
+
function WithAjvProps(props: P) {
|
|
108
112
|
const ctx = useJsonForms();
|
|
109
|
-
const ajv = getAjv({jsonforms: {...ctx}});
|
|
113
|
+
const ajv = getAjv({ jsonforms: { ...ctx } });
|
|
110
114
|
|
|
111
|
-
return
|
|
115
|
+
return <Component {...props} ajv={ajv} />;
|
|
112
116
|
};
|
|
113
117
|
|
|
114
|
-
export interface MaterialLabelableLayoutRendererProps
|
|
118
|
+
export interface MaterialLabelableLayoutRendererProps
|
|
119
|
+
extends MaterialLayoutRendererProps {
|
|
115
120
|
label?: string;
|
|
116
121
|
}
|