@etsoo/materialui 1.6.17 → 1.6.19
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/lib/cjs/ComboBoxMultiple.js +17 -24
- package/lib/cjs/custom/CustomFieldUI.js +8 -15
- package/lib/cjs/custom/FieldCombobox.js +3 -2
- package/lib/mjs/ComboBoxMultiple.js +17 -24
- package/lib/mjs/custom/CustomFieldUI.js +8 -12
- package/lib/mjs/custom/FieldCombobox.js +3 -2
- package/package.json +1 -1
- package/src/ComboBoxMultiple.tsx +24 -34
- package/src/custom/CustomFieldUI.tsx +11 -16
- package/src/custom/FieldCombobox.tsx +4 -1
|
@@ -29,47 +29,40 @@ function ComboBoxMultiple(props) {
|
|
|
29
29
|
// Labels
|
|
30
30
|
const labels = app?.getLabels("noOptions", "loading");
|
|
31
31
|
// Destruct
|
|
32
|
-
const { search = false, autoAddBlankItem = search, idField = "id", idValue, idValues, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputReset, inputVariant, defaultValue, label, labelField = "label", loadData, onLoadData, name, inputAutoComplete = "off", options, dataReadonly = true, readOnly, onChange, openOnFocus = true, value, disableCloseOnSelect = true, renderOption = (
|
|
32
|
+
const { search = false, autoAddBlankItem = search, idField = "id", idValue, idValues, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputReset, inputVariant, defaultValue, label, labelField = "label", loadData, onLoadData, name, inputAutoComplete = "off", options, dataReadonly = true, readOnly, onChange, openOnFocus = true, value, disableCloseOnSelect = true, renderOption = ({ key, ...restProps }, option, { selected }) => ((0, jsx_runtime_1.jsxs)("li", { ...restProps, children: [(0, jsx_runtime_1.jsx)(Checkbox_1.default, { icon: icon, checkedIcon: checkedIcon, style: { marginRight: 8 }, checked: selected }), `${option[labelField]}`] }, key)), getOptionLabel = (option) => `${option[labelField]}`, getOptionKey = (option) => `${option[idField]}`, sx = { minWidth: "150px" }, noOptionsText = labels?.noOptions, loadingText = labels?.loading, disabled, ...rest } = props;
|
|
33
33
|
// Value input ref
|
|
34
34
|
const inputRef = react_1.default.createRef();
|
|
35
35
|
// Options state
|
|
36
36
|
const [localOptions, setOptions] = react_1.default.useState(options ?? []);
|
|
37
37
|
const isMounted = react_1.default.useRef(true);
|
|
38
|
-
// Local default value
|
|
39
|
-
const localValue = idValue != null
|
|
40
|
-
? localOptions.filter((o) => o[idField] === idValue)
|
|
41
|
-
: idValues != null
|
|
42
|
-
? localOptions.filter((o) => idValues?.includes(o[idField]))
|
|
43
|
-
: defaultValue?.concat() ?? value?.concat();
|
|
44
|
-
// State
|
|
45
|
-
// null for controlled
|
|
46
|
-
const [stateValue, setStateValue] = react_1.default.useState(null);
|
|
47
|
-
react_1.default.useEffect(() => {
|
|
48
|
-
setStateValue(localValue ?? []);
|
|
49
|
-
}, [localValue]);
|
|
50
|
-
// When options change
|
|
51
|
-
// [options] will cause infinite loop
|
|
52
38
|
const propertyWay = loadData == null;
|
|
53
39
|
react_1.default.useEffect(() => {
|
|
54
40
|
if (propertyWay && options != null) {
|
|
55
41
|
setOptions(options);
|
|
56
|
-
if (stateValue != null) {
|
|
57
|
-
if (Array.isArray(stateValue)) {
|
|
58
|
-
const newState = stateValue.filter((item) => options.some((option) => option[idField] === item[idField]));
|
|
59
|
-
setStateValue(newState);
|
|
60
|
-
}
|
|
61
|
-
else if (!options.some((option) => option[idField] === stateValue[idField])) {
|
|
62
|
-
setStateValue(null);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
42
|
}
|
|
66
43
|
}, [options, propertyWay]);
|
|
44
|
+
// State
|
|
45
|
+
// null for controlled
|
|
46
|
+
const [stateValue, setStateValue] = react_1.default.useState(null);
|
|
47
|
+
react_1.default.useEffect(() => {
|
|
48
|
+
const localValue = idValue != null
|
|
49
|
+
? localOptions.filter((o) => o[idField] === idValue)
|
|
50
|
+
: idValues != null
|
|
51
|
+
? localOptions.filter((o) => idValues?.includes(o[idField]))
|
|
52
|
+
: (defaultValue?.concat() ?? value?.concat());
|
|
53
|
+
setStateValue(localValue ?? []);
|
|
54
|
+
}, [localOptions, idField, idValue, idValues, defaultValue, value]);
|
|
67
55
|
// Add readOnly
|
|
68
56
|
const addReadOnly = (params) => {
|
|
69
57
|
if (readOnly != null) {
|
|
70
58
|
Object.assign(params, { readOnly });
|
|
71
59
|
}
|
|
72
60
|
Object.assign(params.inputProps, { "data-reset": inputReset });
|
|
61
|
+
params.inputProps.onInvalid = (event) => {
|
|
62
|
+
if (inputRequired && stateValue != null && stateValue.length > 0) {
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
73
66
|
if (dataReadonly) {
|
|
74
67
|
params.inputProps.onKeyDown = (event) => {
|
|
75
68
|
if (shared_1.Keyboard.isTypingContent(event.key)) {
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.CustomFieldUI = CustomFieldUI;
|
|
7
|
-
const react_1 = __importDefault(require("react"));
|
|
8
4
|
const CustomFieldUtils_1 = require("./CustomFieldUtils");
|
|
9
5
|
/**
|
|
10
6
|
* CustomFieldUI component
|
|
@@ -13,17 +9,14 @@ const CustomFieldUtils_1 = require("./CustomFieldUtils");
|
|
|
13
9
|
*/
|
|
14
10
|
function CustomFieldUI(props) {
|
|
15
11
|
// Destruct
|
|
16
|
-
const { fields, onChange, value } = props;
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
const { fields, onChange, value = {} } = props;
|
|
13
|
+
// Layout
|
|
14
|
+
return CustomFieldUtils_1.CustomFieldUtils.create(fields, {}, (field) => {
|
|
19
15
|
if (!field.name)
|
|
20
16
|
return undefined;
|
|
21
|
-
return value
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}, []);
|
|
27
|
-
// Layout
|
|
28
|
-
return CustomFieldUtils_1.CustomFieldUtils.create(fields, {}, getValue, doChange);
|
|
17
|
+
return value[field.name];
|
|
18
|
+
}, (name, fieldValue) => {
|
|
19
|
+
value[name] = fieldValue;
|
|
20
|
+
onChange?.(value, name, fieldValue);
|
|
21
|
+
});
|
|
29
22
|
}
|
|
@@ -38,10 +38,11 @@ const FieldCombobox = ({ field, mref, onChange, defaultValue }) => {
|
|
|
38
38
|
if (!name) {
|
|
39
39
|
return ((0, jsx_runtime_1.jsxs)(Typography_1.default, { children: ["No name for FieldCombobox ", JSON.stringify(field)] }));
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
const { required, inputRequired, ...mainRests } = field.mainSlotProps || {};
|
|
42
|
+
return ((0, jsx_runtime_1.jsx)(ComboBoxMultiple_1.ComboBoxMultiple, { label: field.label ?? "", inputHelperText: field.helperText, inputRequired: required || inputRequired, name: name, options: field.options, fullWidth: true, idValues: ids, onChange: (_event, value) => {
|
|
42
43
|
const ids = value.map((v) => v.id);
|
|
43
44
|
setIds(ids);
|
|
44
45
|
onChange(name, ids);
|
|
45
|
-
}, ...
|
|
46
|
+
}, ...mainRests }));
|
|
46
47
|
};
|
|
47
48
|
exports.FieldCombobox = FieldCombobox;
|
|
@@ -23,47 +23,40 @@ export function ComboBoxMultiple(props) {
|
|
|
23
23
|
// Labels
|
|
24
24
|
const labels = app?.getLabels("noOptions", "loading");
|
|
25
25
|
// Destruct
|
|
26
|
-
const { search = false, autoAddBlankItem = search, idField = "id", idValue, idValues, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputReset, inputVariant, defaultValue, label, labelField = "label", loadData, onLoadData, name, inputAutoComplete = "off", options, dataReadonly = true, readOnly, onChange, openOnFocus = true, value, disableCloseOnSelect = true, renderOption = (
|
|
26
|
+
const { search = false, autoAddBlankItem = search, idField = "id", idValue, idValues, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputReset, inputVariant, defaultValue, label, labelField = "label", loadData, onLoadData, name, inputAutoComplete = "off", options, dataReadonly = true, readOnly, onChange, openOnFocus = true, value, disableCloseOnSelect = true, renderOption = ({ key, ...restProps }, option, { selected }) => (_jsxs("li", { ...restProps, children: [_jsx(Checkbox, { icon: icon, checkedIcon: checkedIcon, style: { marginRight: 8 }, checked: selected }), `${option[labelField]}`] }, key)), getOptionLabel = (option) => `${option[labelField]}`, getOptionKey = (option) => `${option[idField]}`, sx = { minWidth: "150px" }, noOptionsText = labels?.noOptions, loadingText = labels?.loading, disabled, ...rest } = props;
|
|
27
27
|
// Value input ref
|
|
28
28
|
const inputRef = React.createRef();
|
|
29
29
|
// Options state
|
|
30
30
|
const [localOptions, setOptions] = React.useState(options ?? []);
|
|
31
31
|
const isMounted = React.useRef(true);
|
|
32
|
-
// Local default value
|
|
33
|
-
const localValue = idValue != null
|
|
34
|
-
? localOptions.filter((o) => o[idField] === idValue)
|
|
35
|
-
: idValues != null
|
|
36
|
-
? localOptions.filter((o) => idValues?.includes(o[idField]))
|
|
37
|
-
: defaultValue?.concat() ?? value?.concat();
|
|
38
|
-
// State
|
|
39
|
-
// null for controlled
|
|
40
|
-
const [stateValue, setStateValue] = React.useState(null);
|
|
41
|
-
React.useEffect(() => {
|
|
42
|
-
setStateValue(localValue ?? []);
|
|
43
|
-
}, [localValue]);
|
|
44
|
-
// When options change
|
|
45
|
-
// [options] will cause infinite loop
|
|
46
32
|
const propertyWay = loadData == null;
|
|
47
33
|
React.useEffect(() => {
|
|
48
34
|
if (propertyWay && options != null) {
|
|
49
35
|
setOptions(options);
|
|
50
|
-
if (stateValue != null) {
|
|
51
|
-
if (Array.isArray(stateValue)) {
|
|
52
|
-
const newState = stateValue.filter((item) => options.some((option) => option[idField] === item[idField]));
|
|
53
|
-
setStateValue(newState);
|
|
54
|
-
}
|
|
55
|
-
else if (!options.some((option) => option[idField] === stateValue[idField])) {
|
|
56
|
-
setStateValue(null);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
36
|
}
|
|
60
37
|
}, [options, propertyWay]);
|
|
38
|
+
// State
|
|
39
|
+
// null for controlled
|
|
40
|
+
const [stateValue, setStateValue] = React.useState(null);
|
|
41
|
+
React.useEffect(() => {
|
|
42
|
+
const localValue = idValue != null
|
|
43
|
+
? localOptions.filter((o) => o[idField] === idValue)
|
|
44
|
+
: idValues != null
|
|
45
|
+
? localOptions.filter((o) => idValues?.includes(o[idField]))
|
|
46
|
+
: (defaultValue?.concat() ?? value?.concat());
|
|
47
|
+
setStateValue(localValue ?? []);
|
|
48
|
+
}, [localOptions, idField, idValue, idValues, defaultValue, value]);
|
|
61
49
|
// Add readOnly
|
|
62
50
|
const addReadOnly = (params) => {
|
|
63
51
|
if (readOnly != null) {
|
|
64
52
|
Object.assign(params, { readOnly });
|
|
65
53
|
}
|
|
66
54
|
Object.assign(params.inputProps, { "data-reset": inputReset });
|
|
55
|
+
params.inputProps.onInvalid = (event) => {
|
|
56
|
+
if (inputRequired && stateValue != null && stateValue.length > 0) {
|
|
57
|
+
event.preventDefault();
|
|
58
|
+
}
|
|
59
|
+
};
|
|
67
60
|
if (dataReadonly) {
|
|
68
61
|
params.inputProps.onKeyDown = (event) => {
|
|
69
62
|
if (Keyboard.isTypingContent(event.key)) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React from "react";
|
|
2
1
|
import { CustomFieldUtils } from "./CustomFieldUtils";
|
|
3
2
|
/**
|
|
4
3
|
* CustomFieldUI component
|
|
@@ -7,17 +6,14 @@ import { CustomFieldUtils } from "./CustomFieldUtils";
|
|
|
7
6
|
*/
|
|
8
7
|
export function CustomFieldUI(props) {
|
|
9
8
|
// Destruct
|
|
10
|
-
const { fields, onChange, value } = props;
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const { fields, onChange, value = {} } = props;
|
|
10
|
+
// Layout
|
|
11
|
+
return CustomFieldUtils.create(fields, {}, (field) => {
|
|
13
12
|
if (!field.name)
|
|
14
13
|
return undefined;
|
|
15
|
-
return value
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}, []);
|
|
21
|
-
// Layout
|
|
22
|
-
return CustomFieldUtils.create(fields, {}, getValue, doChange);
|
|
14
|
+
return value[field.name];
|
|
15
|
+
}, (name, fieldValue) => {
|
|
16
|
+
value[name] = fieldValue;
|
|
17
|
+
onChange?.(value, name, fieldValue);
|
|
18
|
+
});
|
|
23
19
|
}
|
|
@@ -32,9 +32,10 @@ export const FieldCombobox = ({ field, mref, onChange, defaultValue }) => {
|
|
|
32
32
|
if (!name) {
|
|
33
33
|
return (_jsxs(Typography, { children: ["No name for FieldCombobox ", JSON.stringify(field)] }));
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
const { required, inputRequired, ...mainRests } = field.mainSlotProps || {};
|
|
36
|
+
return (_jsx(ComboBoxMultiple, { label: field.label ?? "", inputHelperText: field.helperText, inputRequired: required || inputRequired, name: name, options: field.options, fullWidth: true, idValues: ids, onChange: (_event, value) => {
|
|
36
37
|
const ids = value.map((v) => v.id);
|
|
37
38
|
setIds(ids);
|
|
38
39
|
onChange(name, ids);
|
|
39
|
-
}, ...
|
|
40
|
+
}, ...mainRests }));
|
|
40
41
|
};
|
package/package.json
CHANGED
package/src/ComboBoxMultiple.tsx
CHANGED
|
@@ -110,8 +110,8 @@ export function ComboBoxMultiple<
|
|
|
110
110
|
openOnFocus = true,
|
|
111
111
|
value,
|
|
112
112
|
disableCloseOnSelect = true,
|
|
113
|
-
renderOption = (
|
|
114
|
-
<li {...
|
|
113
|
+
renderOption = ({ key, ...restProps }, option, { selected }) => (
|
|
114
|
+
<li key={key} {...restProps}>
|
|
115
115
|
<Checkbox
|
|
116
116
|
icon={icon}
|
|
117
117
|
checkedIcon={checkedIcon}
|
|
@@ -137,43 +137,27 @@ export function ComboBoxMultiple<
|
|
|
137
137
|
const [localOptions, setOptions] = React.useState(options ?? []);
|
|
138
138
|
const isMounted = React.useRef(true);
|
|
139
139
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
: defaultValue?.concat() ?? value?.concat();
|
|
140
|
+
const propertyWay = loadData == null;
|
|
141
|
+
React.useEffect(() => {
|
|
142
|
+
if (propertyWay && options != null) {
|
|
143
|
+
setOptions(options);
|
|
144
|
+
}
|
|
145
|
+
}, [options, propertyWay]);
|
|
147
146
|
|
|
148
147
|
// State
|
|
149
148
|
// null for controlled
|
|
150
149
|
const [stateValue, setStateValue] = React.useState<T[] | null>(null);
|
|
151
150
|
|
|
152
151
|
React.useEffect(() => {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
React.useEffect(() => {
|
|
160
|
-
if (propertyWay && options != null) {
|
|
161
|
-
setOptions(options);
|
|
152
|
+
const localValue: T[] | null | undefined =
|
|
153
|
+
idValue != null
|
|
154
|
+
? localOptions.filter((o) => o[idField] === idValue)
|
|
155
|
+
: idValues != null
|
|
156
|
+
? localOptions.filter((o) => idValues?.includes(o[idField]))
|
|
157
|
+
: (defaultValue?.concat() ?? value?.concat());
|
|
162
158
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const newState = stateValue.filter((item) =>
|
|
166
|
-
options.some((option) => option[idField] === item[idField])
|
|
167
|
-
);
|
|
168
|
-
setStateValue(newState);
|
|
169
|
-
} else if (
|
|
170
|
-
!options.some((option) => option[idField] === stateValue[idField])
|
|
171
|
-
) {
|
|
172
|
-
setStateValue(null);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}, [options, propertyWay]);
|
|
159
|
+
setStateValue(localValue ?? []);
|
|
160
|
+
}, [localOptions, idField, idValue, idValues, defaultValue, value]);
|
|
177
161
|
|
|
178
162
|
// Add readOnly
|
|
179
163
|
const addReadOnly = (params: AutocompleteRenderInputParams) => {
|
|
@@ -183,6 +167,12 @@ export function ComboBoxMultiple<
|
|
|
183
167
|
|
|
184
168
|
Object.assign(params.inputProps, { "data-reset": inputReset });
|
|
185
169
|
|
|
170
|
+
params.inputProps.onInvalid = (event) => {
|
|
171
|
+
if (inputRequired && stateValue != null && stateValue.length > 0) {
|
|
172
|
+
event.preventDefault();
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
186
176
|
if (dataReadonly) {
|
|
187
177
|
params.inputProps.onKeyDown = (event) => {
|
|
188
178
|
if (Keyboard.isTypingContent(event.key)) {
|
|
@@ -258,8 +248,8 @@ export function ComboBoxMultiple<
|
|
|
258
248
|
stateValue == null
|
|
259
249
|
? []
|
|
260
250
|
: Array.isArray(stateValue)
|
|
261
|
-
|
|
262
|
-
|
|
251
|
+
? stateValue
|
|
252
|
+
: [stateValue]
|
|
263
253
|
}
|
|
264
254
|
disabled={disabled}
|
|
265
255
|
disableCloseOnSelect={disableCloseOnSelect}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { CustomFieldData } from "@etsoo/appscript";
|
|
2
|
-
import React from "react";
|
|
3
2
|
import { CustomFieldUtils } from "./CustomFieldUtils";
|
|
4
3
|
|
|
5
4
|
/**
|
|
@@ -38,23 +37,19 @@ export function CustomFieldUI<D extends CustomFieldData = CustomFieldData>(
|
|
|
38
37
|
props: CustomFieldUIProps<D>
|
|
39
38
|
) {
|
|
40
39
|
// Destruct
|
|
41
|
-
const { fields, onChange, value } = props;
|
|
40
|
+
const { fields, onChange, value = {} } = props;
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
// Layout
|
|
43
|
+
return CustomFieldUtils.create(
|
|
44
|
+
fields,
|
|
45
|
+
{},
|
|
46
|
+
(field) => {
|
|
47
47
|
if (!field.name) return undefined;
|
|
48
|
-
return value
|
|
48
|
+
return value[field.name];
|
|
49
49
|
},
|
|
50
|
-
|
|
50
|
+
(name, fieldValue) => {
|
|
51
|
+
value[name] = fieldValue;
|
|
52
|
+
onChange?.(value, name, fieldValue);
|
|
53
|
+
}
|
|
51
54
|
);
|
|
52
|
-
|
|
53
|
-
const doChange = React.useCallback((name: string, value: unknown) => {
|
|
54
|
-
data.current[name] = value;
|
|
55
|
-
onChange?.(data.current, name, value);
|
|
56
|
-
}, []);
|
|
57
|
-
|
|
58
|
-
// Layout
|
|
59
|
-
return CustomFieldUtils.create(fields, {}, getValue, doChange);
|
|
60
55
|
}
|
|
@@ -44,10 +44,13 @@ export const FieldCombobox: ICustomFieldReact<IdType[]> = ({
|
|
|
44
44
|
);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
const { required, inputRequired, ...mainRests } = field.mainSlotProps || {};
|
|
48
|
+
|
|
47
49
|
return (
|
|
48
50
|
<ComboBoxMultiple
|
|
49
51
|
label={field.label ?? ""}
|
|
50
52
|
inputHelperText={field.helperText}
|
|
53
|
+
inputRequired={required || inputRequired}
|
|
51
54
|
name={name}
|
|
52
55
|
options={field.options}
|
|
53
56
|
fullWidth
|
|
@@ -57,7 +60,7 @@ export const FieldCombobox: ICustomFieldReact<IdType[]> = ({
|
|
|
57
60
|
setIds(ids);
|
|
58
61
|
onChange(name, ids);
|
|
59
62
|
}}
|
|
60
|
-
{...
|
|
63
|
+
{...mainRests}
|
|
61
64
|
/>
|
|
62
65
|
);
|
|
63
66
|
};
|