@etsoo/materialui 1.6.16 → 1.6.18
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 +12 -24
- package/lib/cjs/custom/CustomFieldUI.d.ts +27 -0
- package/lib/cjs/custom/CustomFieldUI.js +29 -0
- package/lib/cjs/custom/CustomFieldUtils.js +1 -1
- package/lib/cjs/custom/FieldCombobox.js +3 -2
- package/lib/cjs/index.d.ts +1 -0
- package/lib/cjs/index.js +1 -0
- package/lib/mjs/ComboBoxMultiple.js +12 -24
- package/lib/mjs/custom/CustomFieldUI.d.ts +27 -0
- package/lib/mjs/custom/CustomFieldUI.js +23 -0
- package/lib/mjs/custom/CustomFieldUtils.js +1 -1
- package/lib/mjs/custom/FieldCombobox.js +3 -2
- package/lib/mjs/index.d.ts +1 -0
- package/lib/mjs/index.js +1 -0
- package/package.json +1 -1
- package/src/ComboBoxMultiple.tsx +18 -34
- package/src/custom/CustomFieldUI.tsx +60 -0
- package/src/custom/CustomFieldUtils.tsx +9 -9
- package/src/custom/FieldCombobox.tsx +4 -1
- package/src/index.ts +1 -0
|
@@ -29,41 +29,29 @@ 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) {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { CustomFieldData } from "@etsoo/appscript";
|
|
2
|
+
/**
|
|
3
|
+
* CustomFieldUI component props
|
|
4
|
+
*/
|
|
5
|
+
export type CustomFieldUIProps<D extends CustomFieldData = CustomFieldData> = {
|
|
6
|
+
/**
|
|
7
|
+
* Custom fields
|
|
8
|
+
*/
|
|
9
|
+
fields: D[];
|
|
10
|
+
/**
|
|
11
|
+
* Change event
|
|
12
|
+
* @param data Current data collection
|
|
13
|
+
* @param name Changed field name
|
|
14
|
+
* @param value Changed field value
|
|
15
|
+
*/
|
|
16
|
+
onChange?: (data: Record<string, unknown>, name: string, value: unknown) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Initial value
|
|
19
|
+
*/
|
|
20
|
+
value?: Record<string, unknown>;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* CustomFieldUI component
|
|
24
|
+
* @param props Props
|
|
25
|
+
* @returns component
|
|
26
|
+
*/
|
|
27
|
+
export declare function CustomFieldUI<D extends CustomFieldData = CustomFieldData>(props: CustomFieldUIProps<D>): import("react/jsx-runtime").JSX.Element[];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CustomFieldUI = CustomFieldUI;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const CustomFieldUtils_1 = require("./CustomFieldUtils");
|
|
9
|
+
/**
|
|
10
|
+
* CustomFieldUI component
|
|
11
|
+
* @param props Props
|
|
12
|
+
* @returns component
|
|
13
|
+
*/
|
|
14
|
+
function CustomFieldUI(props) {
|
|
15
|
+
// Destruct
|
|
16
|
+
const { fields, onChange, value } = props;
|
|
17
|
+
const data = react_1.default.useRef({});
|
|
18
|
+
const getValue = react_1.default.useCallback((field) => {
|
|
19
|
+
if (!field.name)
|
|
20
|
+
return undefined;
|
|
21
|
+
return value?.[field.name];
|
|
22
|
+
}, [value]);
|
|
23
|
+
const doChange = react_1.default.useCallback((name, value) => {
|
|
24
|
+
data.current[name] = value;
|
|
25
|
+
onChange?.(data.current, name, value);
|
|
26
|
+
}, []);
|
|
27
|
+
// Layout
|
|
28
|
+
return CustomFieldUtils_1.CustomFieldUtils.create(fields, {}, getValue, doChange);
|
|
29
|
+
}
|
|
@@ -70,7 +70,7 @@ var CustomFieldUtils;
|
|
|
70
70
|
fieldCalback(field);
|
|
71
71
|
const creator = CustomFieldUtils.customFieldCreators[field.type];
|
|
72
72
|
if (creator == null) {
|
|
73
|
-
return ((0, jsx_runtime_1.jsx)(Grid_1.default, { size: transformSpace(field.space), ...field.gridItemProps, children: `Type ${field.type} is not supported currently` }, index));
|
|
73
|
+
return ((0, jsx_runtime_1.jsx)(Grid_1.default, { size: transformSpace(field.space), ...field.gridItemProps, children: `Type ${field.type} is not supported currently` }, field.name ?? index));
|
|
74
74
|
}
|
|
75
75
|
const Creator = creator;
|
|
76
76
|
const mref = react_1.default.createRef();
|
|
@@ -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, name: name, options: field.options, fullWidth: true, idValues: ids, inputRequired: required || inputRequired, 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;
|
package/lib/cjs/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./app/Labels";
|
|
|
7
7
|
export * from "./app/ReactApp";
|
|
8
8
|
export * from "./app/ServiceApp";
|
|
9
9
|
export * from "./custom/CustomAttributeArea";
|
|
10
|
+
export * from "./custom/CustomFieldUI";
|
|
10
11
|
export * from "./custom/CustomFieldUtils";
|
|
11
12
|
export * from "./custom/CustomFieldViewer";
|
|
12
13
|
export * from "./custom/CustomFieldWindow";
|
package/lib/cjs/index.js
CHANGED
|
@@ -23,6 +23,7 @@ __exportStar(require("./app/Labels"), exports);
|
|
|
23
23
|
__exportStar(require("./app/ReactApp"), exports);
|
|
24
24
|
__exportStar(require("./app/ServiceApp"), exports);
|
|
25
25
|
__exportStar(require("./custom/CustomAttributeArea"), exports);
|
|
26
|
+
__exportStar(require("./custom/CustomFieldUI"), exports);
|
|
26
27
|
__exportStar(require("./custom/CustomFieldUtils"), exports);
|
|
27
28
|
__exportStar(require("./custom/CustomFieldViewer"), exports);
|
|
28
29
|
__exportStar(require("./custom/CustomFieldWindow"), exports);
|
|
@@ -23,41 +23,29 @@ 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) {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { CustomFieldData } from "@etsoo/appscript";
|
|
2
|
+
/**
|
|
3
|
+
* CustomFieldUI component props
|
|
4
|
+
*/
|
|
5
|
+
export type CustomFieldUIProps<D extends CustomFieldData = CustomFieldData> = {
|
|
6
|
+
/**
|
|
7
|
+
* Custom fields
|
|
8
|
+
*/
|
|
9
|
+
fields: D[];
|
|
10
|
+
/**
|
|
11
|
+
* Change event
|
|
12
|
+
* @param data Current data collection
|
|
13
|
+
* @param name Changed field name
|
|
14
|
+
* @param value Changed field value
|
|
15
|
+
*/
|
|
16
|
+
onChange?: (data: Record<string, unknown>, name: string, value: unknown) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Initial value
|
|
19
|
+
*/
|
|
20
|
+
value?: Record<string, unknown>;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* CustomFieldUI component
|
|
24
|
+
* @param props Props
|
|
25
|
+
* @returns component
|
|
26
|
+
*/
|
|
27
|
+
export declare function CustomFieldUI<D extends CustomFieldData = CustomFieldData>(props: CustomFieldUIProps<D>): import("react/jsx-runtime").JSX.Element[];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { CustomFieldUtils } from "./CustomFieldUtils";
|
|
3
|
+
/**
|
|
4
|
+
* CustomFieldUI component
|
|
5
|
+
* @param props Props
|
|
6
|
+
* @returns component
|
|
7
|
+
*/
|
|
8
|
+
export function CustomFieldUI(props) {
|
|
9
|
+
// Destruct
|
|
10
|
+
const { fields, onChange, value } = props;
|
|
11
|
+
const data = React.useRef({});
|
|
12
|
+
const getValue = React.useCallback((field) => {
|
|
13
|
+
if (!field.name)
|
|
14
|
+
return undefined;
|
|
15
|
+
return value?.[field.name];
|
|
16
|
+
}, [value]);
|
|
17
|
+
const doChange = React.useCallback((name, value) => {
|
|
18
|
+
data.current[name] = value;
|
|
19
|
+
onChange?.(data.current, name, value);
|
|
20
|
+
}, []);
|
|
21
|
+
// Layout
|
|
22
|
+
return CustomFieldUtils.create(fields, {}, getValue, doChange);
|
|
23
|
+
}
|
|
@@ -64,7 +64,7 @@ export var CustomFieldUtils;
|
|
|
64
64
|
fieldCalback(field);
|
|
65
65
|
const creator = CustomFieldUtils.customFieldCreators[field.type];
|
|
66
66
|
if (creator == null) {
|
|
67
|
-
return (_jsx(Grid, { size: transformSpace(field.space), ...field.gridItemProps, children: `Type ${field.type} is not supported currently` }, index));
|
|
67
|
+
return (_jsx(Grid, { size: transformSpace(field.space), ...field.gridItemProps, children: `Type ${field.type} is not supported currently` }, field.name ?? index));
|
|
68
68
|
}
|
|
69
69
|
const Creator = creator;
|
|
70
70
|
const mref = React.createRef();
|
|
@@ -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, name: name, options: field.options, fullWidth: true, idValues: ids, inputRequired: required || inputRequired, 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/lib/mjs/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./app/Labels";
|
|
|
7
7
|
export * from "./app/ReactApp";
|
|
8
8
|
export * from "./app/ServiceApp";
|
|
9
9
|
export * from "./custom/CustomAttributeArea";
|
|
10
|
+
export * from "./custom/CustomFieldUI";
|
|
10
11
|
export * from "./custom/CustomFieldUtils";
|
|
11
12
|
export * from "./custom/CustomFieldViewer";
|
|
12
13
|
export * from "./custom/CustomFieldWindow";
|
package/lib/mjs/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./app/Labels";
|
|
|
7
7
|
export * from "./app/ReactApp";
|
|
8
8
|
export * from "./app/ServiceApp";
|
|
9
9
|
export * from "./custom/CustomAttributeArea";
|
|
10
|
+
export * from "./custom/CustomFieldUI";
|
|
10
11
|
export * from "./custom/CustomFieldUtils";
|
|
11
12
|
export * from "./custom/CustomFieldViewer";
|
|
12
13
|
export * from "./custom/CustomFieldWindow";
|
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
|
-
|
|
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());
|
|
155
158
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const propertyWay = loadData == null;
|
|
159
|
-
React.useEffect(() => {
|
|
160
|
-
if (propertyWay && options != null) {
|
|
161
|
-
setOptions(options);
|
|
162
|
-
|
|
163
|
-
if (stateValue != null) {
|
|
164
|
-
if (Array.isArray(stateValue)) {
|
|
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) => {
|
|
@@ -258,8 +242,8 @@ export function ComboBoxMultiple<
|
|
|
258
242
|
stateValue == null
|
|
259
243
|
? []
|
|
260
244
|
: Array.isArray(stateValue)
|
|
261
|
-
|
|
262
|
-
|
|
245
|
+
? stateValue
|
|
246
|
+
: [stateValue]
|
|
263
247
|
}
|
|
264
248
|
disabled={disabled}
|
|
265
249
|
disableCloseOnSelect={disableCloseOnSelect}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { CustomFieldData } from "@etsoo/appscript";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { CustomFieldUtils } from "./CustomFieldUtils";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* CustomFieldUI component props
|
|
7
|
+
*/
|
|
8
|
+
export type CustomFieldUIProps<D extends CustomFieldData = CustomFieldData> = {
|
|
9
|
+
/**
|
|
10
|
+
* Custom fields
|
|
11
|
+
*/
|
|
12
|
+
fields: D[];
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Change event
|
|
16
|
+
* @param data Current data collection
|
|
17
|
+
* @param name Changed field name
|
|
18
|
+
* @param value Changed field value
|
|
19
|
+
*/
|
|
20
|
+
onChange?: (
|
|
21
|
+
data: Record<string, unknown>,
|
|
22
|
+
name: string,
|
|
23
|
+
value: unknown
|
|
24
|
+
) => void;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Initial value
|
|
28
|
+
*/
|
|
29
|
+
value?: Record<string, unknown>;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* CustomFieldUI component
|
|
34
|
+
* @param props Props
|
|
35
|
+
* @returns component
|
|
36
|
+
*/
|
|
37
|
+
export function CustomFieldUI<D extends CustomFieldData = CustomFieldData>(
|
|
38
|
+
props: CustomFieldUIProps<D>
|
|
39
|
+
) {
|
|
40
|
+
// Destruct
|
|
41
|
+
const { fields, onChange, value } = props;
|
|
42
|
+
|
|
43
|
+
const data = React.useRef<Record<string, unknown>>({});
|
|
44
|
+
|
|
45
|
+
const getValue = React.useCallback(
|
|
46
|
+
(field: CustomFieldData) => {
|
|
47
|
+
if (!field.name) return undefined;
|
|
48
|
+
return value?.[field.name];
|
|
49
|
+
},
|
|
50
|
+
[value]
|
|
51
|
+
);
|
|
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
|
+
}
|
|
@@ -84,7 +84,7 @@ export namespace CustomFieldUtils {
|
|
|
84
84
|
if (creator == null) {
|
|
85
85
|
return (
|
|
86
86
|
<Grid
|
|
87
|
-
key={index}
|
|
87
|
+
key={field.name ?? index}
|
|
88
88
|
size={transformSpace(field.space)}
|
|
89
89
|
{...field.gridItemProps}
|
|
90
90
|
>
|
|
@@ -153,14 +153,14 @@ export namespace CustomFieldUtils {
|
|
|
153
153
|
space === "full"
|
|
154
154
|
? { xs: 12 }
|
|
155
155
|
: space === "quater"
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
156
|
+
? { sm: 12, md: 6, lg: 3 }
|
|
157
|
+
: space === "five"
|
|
158
|
+
? { sm: 12, md: 5 }
|
|
159
|
+
: space === "seven"
|
|
160
|
+
? { sm: 12, md: 7 }
|
|
161
|
+
: space === "half1"
|
|
162
|
+
? { xs: 12, sm: 6 }
|
|
163
|
+
: { sm: 12, md: 6 };
|
|
164
164
|
return size;
|
|
165
165
|
}
|
|
166
166
|
|
|
@@ -44,6 +44,8 @@ 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 ?? ""}
|
|
@@ -52,12 +54,13 @@ export const FieldCombobox: ICustomFieldReact<IdType[]> = ({
|
|
|
52
54
|
options={field.options}
|
|
53
55
|
fullWidth
|
|
54
56
|
idValues={ids}
|
|
57
|
+
inputRequired={required || inputRequired}
|
|
55
58
|
onChange={(_event, value) => {
|
|
56
59
|
const ids = value.map((v) => v.id);
|
|
57
60
|
setIds(ids);
|
|
58
61
|
onChange(name, ids);
|
|
59
62
|
}}
|
|
60
|
-
{...
|
|
63
|
+
{...mainRests}
|
|
61
64
|
/>
|
|
62
65
|
);
|
|
63
66
|
};
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./app/ReactApp";
|
|
|
8
8
|
export * from "./app/ServiceApp";
|
|
9
9
|
|
|
10
10
|
export * from "./custom/CustomAttributeArea";
|
|
11
|
+
export * from "./custom/CustomFieldUI";
|
|
11
12
|
export * from "./custom/CustomFieldUtils";
|
|
12
13
|
export * from "./custom/CustomFieldViewer";
|
|
13
14
|
export * from "./custom/CustomFieldWindow";
|