@etsoo/materialui 1.3.63 → 1.3.65
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/__tests__/CustomFields.tsx +93 -0
- package/lib/custom/CustomFieldUtils.d.ts +50 -0
- package/lib/custom/CustomFieldUtils.js +138 -0
- package/lib/custom/FieldAmountLabel.d.ts +7 -0
- package/lib/custom/FieldAmountLabel.js +40 -0
- package/lib/custom/FieldCheckbox.d.ts +8 -0
- package/lib/custom/FieldCheckbox.js +49 -0
- package/lib/custom/FieldCombobox.d.ts +8 -0
- package/lib/custom/FieldCombobox.js +40 -0
- package/lib/custom/FieldDateInput.d.ts +7 -0
- package/lib/custom/FieldDateInput.js +43 -0
- package/lib/custom/FieldDivider.d.ts +7 -0
- package/lib/custom/FieldDivider.js +12 -0
- package/lib/custom/FieldInput.d.ts +7 -0
- package/lib/custom/FieldInput.js +27 -0
- package/lib/custom/FieldJson.d.ts +7 -0
- package/lib/custom/FieldJson.js +50 -0
- package/lib/custom/FieldLabel.d.ts +7 -0
- package/lib/custom/FieldLabel.js +28 -0
- package/lib/custom/FieldNumberInput.d.ts +7 -0
- package/lib/custom/FieldNumberInput.js +37 -0
- package/lib/custom/FieldRadio.d.ts +8 -0
- package/lib/custom/FieldRadio.js +49 -0
- package/lib/custom/FieldSelect.d.ts +8 -0
- package/lib/custom/FieldSelect.js +48 -0
- package/lib/custom/FieldSwitch.d.ts +7 -0
- package/lib/custom/FieldSwitch.js +42 -0
- package/lib/custom/FieldTexarea.d.ts +7 -0
- package/lib/custom/FieldTexarea.js +28 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/package.json +14 -14
- package/src/ShowDataComparison.tsx +0 -1
- package/src/custom/CustomFieldUtils.tsx +195 -0
- package/src/custom/FieldAmountLabel.tsx +62 -0
- package/src/custom/FieldCheckbox.tsx +74 -0
- package/src/custom/FieldCombobox.tsx +63 -0
- package/src/custom/FieldDateInput.tsx +75 -0
- package/src/custom/FieldDivider.tsx +18 -0
- package/src/custom/FieldInput.tsx +49 -0
- package/src/custom/FieldJson.tsx +77 -0
- package/src/custom/FieldLabel.tsx +40 -0
- package/src/custom/FieldNumberInput.tsx +60 -0
- package/src/custom/FieldRadio.tsx +73 -0
- package/src/custom/FieldSelect.tsx +70 -0
- package/src/custom/FieldSwitch.tsx +58 -0
- package/src/custom/FieldTexarea.tsx +54 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Typography } from "@mui/material";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { NumberInputField } from "../NumberInputField";
|
|
5
|
+
import { NumberUtils } from "@etsoo/shared";
|
|
6
|
+
/**
|
|
7
|
+
* Number input field creator
|
|
8
|
+
* type: number
|
|
9
|
+
* @returns Component
|
|
10
|
+
*/
|
|
11
|
+
export const FieldNumberInput = ({ field, mref, onChange, defaultValue }) => {
|
|
12
|
+
// Ref
|
|
13
|
+
const inputRef = React.useRef();
|
|
14
|
+
const getValue = () => {
|
|
15
|
+
const value = inputRef.current?.valueAsNumber;
|
|
16
|
+
return NumberUtils.parse(value);
|
|
17
|
+
};
|
|
18
|
+
const setValue = (value) => {
|
|
19
|
+
if (inputRef.current)
|
|
20
|
+
inputRef.current.value = `${value ?? ""}`;
|
|
21
|
+
};
|
|
22
|
+
React.useImperativeHandle(mref, () => ({
|
|
23
|
+
getValue,
|
|
24
|
+
setValue
|
|
25
|
+
}));
|
|
26
|
+
React.useEffect(() => {
|
|
27
|
+
if (defaultValue == null)
|
|
28
|
+
return;
|
|
29
|
+
setValue(defaultValue);
|
|
30
|
+
}, [defaultValue]);
|
|
31
|
+
// Name
|
|
32
|
+
const name = field.name;
|
|
33
|
+
if (!name) {
|
|
34
|
+
return (_jsxs(Typography, { children: ["No name for FieldNumberInput ", JSON.stringify(field)] }));
|
|
35
|
+
}
|
|
36
|
+
return (_jsx(NumberInputField, { label: field.label ?? "", helperText: field.helperText, inputRef: inputRef, name: name, fullWidth: true, onChange: () => onChange(name, getValue()), ...field.mainSlotProps }));
|
|
37
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Typography } from "@mui/material";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { OptionGroup } from "../OptionGroup";
|
|
5
|
+
/**
|
|
6
|
+
* Radio (single value) field creator
|
|
7
|
+
* type: radio
|
|
8
|
+
* @returns Component
|
|
9
|
+
*/
|
|
10
|
+
export const FieldRadio = ({ field, mref, onChange, defaultValue }) => {
|
|
11
|
+
// State
|
|
12
|
+
const [value, setLocalValue] = React.useState();
|
|
13
|
+
// Ref
|
|
14
|
+
const getValue = () => value;
|
|
15
|
+
const setValue = (value) => {
|
|
16
|
+
if (Array.isArray(value)) {
|
|
17
|
+
setLocalValue(value[0]);
|
|
18
|
+
}
|
|
19
|
+
else if (typeof value === "string" || typeof value === "number") {
|
|
20
|
+
setLocalValue(value);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
setLocalValue(undefined);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
React.useImperativeHandle(mref, () => ({
|
|
27
|
+
getValue,
|
|
28
|
+
setValue
|
|
29
|
+
}));
|
|
30
|
+
React.useEffect(() => {
|
|
31
|
+
if (defaultValue == null)
|
|
32
|
+
return;
|
|
33
|
+
setValue(defaultValue);
|
|
34
|
+
}, [defaultValue]);
|
|
35
|
+
// Name
|
|
36
|
+
const name = field.name;
|
|
37
|
+
if (!name) {
|
|
38
|
+
return (_jsxs(Typography, { children: ["No name for FieldRadio ", JSON.stringify(field)] }));
|
|
39
|
+
}
|
|
40
|
+
return (_jsx(OptionGroup, { name: name, options: field.options ?? [], multiple: false, row: true, helperText: field.helperText, label: field.label, variant: "outlined", fullWidth: true, defaultValue: value, onValueChange: (value) => {
|
|
41
|
+
const newValue = Array.isArray(value)
|
|
42
|
+
? value[0]
|
|
43
|
+
: value == null
|
|
44
|
+
? undefined
|
|
45
|
+
: value;
|
|
46
|
+
setLocalValue(newValue);
|
|
47
|
+
onChange(name, newValue);
|
|
48
|
+
}, ...field.mainSlotProps }));
|
|
49
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Typography } from "@mui/material";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { SelectEx } from "../SelectEx";
|
|
5
|
+
/**
|
|
6
|
+
* Select (single value) field creator
|
|
7
|
+
* type select
|
|
8
|
+
* @returns Component
|
|
9
|
+
*/
|
|
10
|
+
export const FieldSelect = ({ field, mref, onChange, defaultValue }) => {
|
|
11
|
+
// State
|
|
12
|
+
const [value, setLocalValue] = React.useState();
|
|
13
|
+
const getValue = () => value;
|
|
14
|
+
const setValue = (value) => {
|
|
15
|
+
if (Array.isArray(value)) {
|
|
16
|
+
setLocalValue(value[0]);
|
|
17
|
+
}
|
|
18
|
+
else if (typeof value === "string" || typeof value === "number") {
|
|
19
|
+
setLocalValue(value);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
setLocalValue(undefined);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
// Ref
|
|
26
|
+
React.useImperativeHandle(mref, () => ({
|
|
27
|
+
getValue,
|
|
28
|
+
setValue
|
|
29
|
+
}));
|
|
30
|
+
React.useEffect(() => {
|
|
31
|
+
if (defaultValue == null)
|
|
32
|
+
return;
|
|
33
|
+
setValue(defaultValue);
|
|
34
|
+
}, [defaultValue]);
|
|
35
|
+
// Name
|
|
36
|
+
const name = field.name;
|
|
37
|
+
if (!name) {
|
|
38
|
+
return (_jsxs(Typography, { children: ["No name for FieldSelect ", JSON.stringify(field)] }));
|
|
39
|
+
}
|
|
40
|
+
return (_jsx(SelectEx, { label: field.label ?? "", helperText: field.helperText, name: name, options: field.options, fullWidth: true, onChange: (event) => {
|
|
41
|
+
const value = event.target.value;
|
|
42
|
+
const newValue = typeof value === "string" || typeof value === "number"
|
|
43
|
+
? value
|
|
44
|
+
: undefined;
|
|
45
|
+
setLocalValue(newValue);
|
|
46
|
+
onChange(name, newValue);
|
|
47
|
+
}, ...field.mainSlotProps }));
|
|
48
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { SwitchAnt } from "../SwitchAnt";
|
|
4
|
+
import { Typography } from "@mui/material";
|
|
5
|
+
/**
|
|
6
|
+
* Input field creator
|
|
7
|
+
* type: switch
|
|
8
|
+
* @returns Component
|
|
9
|
+
*/
|
|
10
|
+
export const FieldSwitch = ({ field, mref, onChange, defaultValue }) => {
|
|
11
|
+
// State
|
|
12
|
+
const [value, setLocalValue] = React.useState();
|
|
13
|
+
const getValue = () => value;
|
|
14
|
+
const setValue = (value) => {
|
|
15
|
+
if (typeof value === "boolean")
|
|
16
|
+
setLocalValue(value);
|
|
17
|
+
else if (value === "true" || value === "1" || value === 1)
|
|
18
|
+
setLocalValue(true);
|
|
19
|
+
else if (value === "false" || value === "0" || value === 0)
|
|
20
|
+
setLocalValue(false);
|
|
21
|
+
else
|
|
22
|
+
setLocalValue(undefined);
|
|
23
|
+
};
|
|
24
|
+
React.useImperativeHandle(mref, () => ({
|
|
25
|
+
getValue,
|
|
26
|
+
setValue
|
|
27
|
+
}));
|
|
28
|
+
// Name
|
|
29
|
+
const name = field.name;
|
|
30
|
+
if (!name) {
|
|
31
|
+
return (_jsxs(Typography, { children: ["No name for FieldSwitch ", JSON.stringify(field)] }));
|
|
32
|
+
}
|
|
33
|
+
React.useEffect(() => {
|
|
34
|
+
if (defaultValue == null)
|
|
35
|
+
return;
|
|
36
|
+
setValue(defaultValue);
|
|
37
|
+
}, [defaultValue]);
|
|
38
|
+
return (_jsx(SwitchAnt, { name: name, onChange: (_event, value) => {
|
|
39
|
+
setLocalValue(value);
|
|
40
|
+
onChange(name, value);
|
|
41
|
+
}, ...field.mainSlotProps }));
|
|
42
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Typography } from "@mui/material";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { InputField } from "../InputField";
|
|
5
|
+
/**
|
|
6
|
+
* Textarea field creator
|
|
7
|
+
* type: textarea
|
|
8
|
+
* @returns Component
|
|
9
|
+
*/
|
|
10
|
+
export const FieldTexarea = ({ field, mref, onChange, defaultValue }) => {
|
|
11
|
+
// Ref
|
|
12
|
+
const inputRef = React.useRef();
|
|
13
|
+
const getValue = () => inputRef.current?.value;
|
|
14
|
+
const setValue = (value) => {
|
|
15
|
+
if (inputRef.current)
|
|
16
|
+
inputRef.current.value = `${value ?? ""}`;
|
|
17
|
+
};
|
|
18
|
+
React.useImperativeHandle(mref, () => ({
|
|
19
|
+
getValue,
|
|
20
|
+
setValue
|
|
21
|
+
}));
|
|
22
|
+
// Name
|
|
23
|
+
const name = field.name;
|
|
24
|
+
if (!name) {
|
|
25
|
+
return (_jsxs(Typography, { children: ["No name for FieldTextarea ", JSON.stringify(field)] }));
|
|
26
|
+
}
|
|
27
|
+
return (_jsx(InputField, { label: field.label ?? "", helperText: field.helperText, name: name, fullWidth: true, multiline: true, rows: 4, inputProps: { maxLength: 1280 }, inputRef: inputRef, defaultValue: defaultValue, onChange: () => onChange(name, getValue()), ...field.mainSlotProps }));
|
|
28
|
+
};
|
package/lib/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./app/ISmartERPUser";
|
|
|
8
8
|
export * from "./app/Labels";
|
|
9
9
|
export * from "./app/ReactApp";
|
|
10
10
|
export * from "./app/ServiceApp";
|
|
11
|
+
export * from "./custom/CustomFieldUtils";
|
|
11
12
|
export * from "./messages/MessageUtils";
|
|
12
13
|
export * from "./messages/OperationMessageContainer";
|
|
13
14
|
export * from "./messages/OperationMessageDto";
|
package/lib/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./app/ISmartERPUser";
|
|
|
8
8
|
export * from "./app/Labels";
|
|
9
9
|
export * from "./app/ReactApp";
|
|
10
10
|
export * from "./app/ServiceApp";
|
|
11
|
+
export * from "./custom/CustomFieldUtils";
|
|
11
12
|
export * from "./messages/MessageUtils";
|
|
12
13
|
export * from "./messages/OperationMessageContainer";
|
|
13
14
|
export * from "./messages/OperationMessageDto";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/materialui",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.65",
|
|
4
4
|
"description": "TypeScript Material-UI Implementation",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"@emotion/css": "^11.11.2",
|
|
51
51
|
"@emotion/react": "^11.11.4",
|
|
52
52
|
"@emotion/styled": "^11.11.5",
|
|
53
|
-
"@etsoo/appscript": "^1.4.
|
|
53
|
+
"@etsoo/appscript": "^1.4.95",
|
|
54
54
|
"@etsoo/notificationbase": "^1.1.42",
|
|
55
|
-
"@etsoo/react": "^1.7.
|
|
55
|
+
"@etsoo/react": "^1.7.52",
|
|
56
56
|
"@etsoo/shared": "^1.2.40",
|
|
57
57
|
"@mui/icons-material": "^5.15.18",
|
|
58
58
|
"@mui/material": "^5.15.18",
|
|
@@ -67,28 +67,28 @@
|
|
|
67
67
|
"react-chartjs-2": "^5.2.0",
|
|
68
68
|
"react-dom": "^18.3.1",
|
|
69
69
|
"react-draggable": "^4.4.6",
|
|
70
|
-
"react-imask": "7.6.
|
|
70
|
+
"react-imask": "7.6.1"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"@babel/cli": "^7.24.
|
|
74
|
-
"@babel/core": "^7.24.
|
|
75
|
-
"@babel/plugin-transform-runtime": "^7.24.
|
|
76
|
-
"@babel/preset-env": "^7.24.
|
|
77
|
-
"@babel/preset-react": "^7.24.
|
|
78
|
-
"@babel/preset-typescript": "^7.24.
|
|
79
|
-
"@babel/runtime-corejs3": "^7.24.
|
|
73
|
+
"@babel/cli": "^7.24.6",
|
|
74
|
+
"@babel/core": "^7.24.6",
|
|
75
|
+
"@babel/plugin-transform-runtime": "^7.24.6",
|
|
76
|
+
"@babel/preset-env": "^7.24.6",
|
|
77
|
+
"@babel/preset-react": "^7.24.6",
|
|
78
|
+
"@babel/preset-typescript": "^7.24.6",
|
|
79
|
+
"@babel/runtime-corejs3": "^7.24.6",
|
|
80
80
|
"@testing-library/jest-dom": "^6.4.5",
|
|
81
81
|
"@testing-library/react": "^15.0.7",
|
|
82
82
|
"@types/jest": "^29.5.12",
|
|
83
83
|
"@types/pica": "^9.0.4",
|
|
84
84
|
"@types/pulltorefreshjs": "^0.1.7",
|
|
85
|
-
"@types/react": "^18.3.
|
|
85
|
+
"@types/react": "^18.3.3",
|
|
86
86
|
"@types/react-avatar-editor": "^13.0.2",
|
|
87
87
|
"@types/react-dom": "^18.3.0",
|
|
88
88
|
"@types/react-input-mask": "^3.0.5",
|
|
89
89
|
"@types/react-window": "^1.8.8",
|
|
90
|
-
"@typescript-eslint/eslint-plugin": "^7.
|
|
91
|
-
"@typescript-eslint/parser": "^7.
|
|
90
|
+
"@typescript-eslint/eslint-plugin": "^7.10.0",
|
|
91
|
+
"@typescript-eslint/parser": "^7.10.0",
|
|
92
92
|
"jest": "^29.7.0",
|
|
93
93
|
"jest-environment-jsdom": "^29.7.0",
|
|
94
94
|
"typescript": "^5.4.5"
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CustomFieldData,
|
|
3
|
+
CustomFieldRef,
|
|
4
|
+
CustomFieldSpace
|
|
5
|
+
} from "@etsoo/appscript";
|
|
6
|
+
import { CustomFieldReactCollection, ICustomFieldReact } from "@etsoo/react";
|
|
7
|
+
import { IdType, ListType2 } from "@etsoo/shared";
|
|
8
|
+
import { Grid, GridProps, Typography } from "@mui/material";
|
|
9
|
+
import { TypographyProps } from "@mui/material/Typography";
|
|
10
|
+
import React from "react";
|
|
11
|
+
import { FieldCheckbox } from "./FieldCheckbox";
|
|
12
|
+
import { FieldAmountLabel } from "./FieldAmountLabel";
|
|
13
|
+
import { FieldDateInput } from "./FieldDateInput";
|
|
14
|
+
import { FieldDivider } from "./FieldDivider";
|
|
15
|
+
import { FieldCombobox } from "./FieldCombobox";
|
|
16
|
+
import { FieldInput } from "./FieldInput";
|
|
17
|
+
import { FieldLabel } from "./FieldLabel";
|
|
18
|
+
import { FieldNumberInput } from "./FieldNumberInput";
|
|
19
|
+
import { FieldTexarea } from "./FieldTexarea";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Custom field utilities
|
|
23
|
+
*/
|
|
24
|
+
export namespace CustomFieldUtils {
|
|
25
|
+
/**
|
|
26
|
+
* Custom field creators
|
|
27
|
+
*/
|
|
28
|
+
export const customFieldCreators: Record<
|
|
29
|
+
string,
|
|
30
|
+
ICustomFieldReact<any> | undefined
|
|
31
|
+
> = {
|
|
32
|
+
amountlabel: FieldAmountLabel,
|
|
33
|
+
checkbox: FieldCheckbox,
|
|
34
|
+
combobox: FieldCombobox,
|
|
35
|
+
date: FieldDateInput,
|
|
36
|
+
divider: FieldDivider,
|
|
37
|
+
input: FieldInput,
|
|
38
|
+
label: FieldLabel,
|
|
39
|
+
number: FieldNumberInput,
|
|
40
|
+
textarea: FieldTexarea
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Create layout
|
|
45
|
+
* @param fields Fields
|
|
46
|
+
* @param collections Ref collections
|
|
47
|
+
* @param getValue Get default value callback
|
|
48
|
+
* @param onChange Callback for value change
|
|
49
|
+
* @param globalCallback Global label callback, can be repeated
|
|
50
|
+
* @param fieldCalback Field callback
|
|
51
|
+
* @returns
|
|
52
|
+
*/
|
|
53
|
+
export function create<D extends CustomFieldData = CustomFieldData>(
|
|
54
|
+
fields: D[],
|
|
55
|
+
collections: CustomFieldReactCollection<D>,
|
|
56
|
+
getValue: (field: D) => unknown,
|
|
57
|
+
onChange: (name: string, value: unknown) => void,
|
|
58
|
+
globalCallback?: (input: string) => string,
|
|
59
|
+
fieldCalback?: (field: D) => void
|
|
60
|
+
) {
|
|
61
|
+
return fields.map((field, index) => {
|
|
62
|
+
// Global callback for labels
|
|
63
|
+
if (globalCallback) {
|
|
64
|
+
if (field.label) field.label = globalCallback(field.label);
|
|
65
|
+
if (field.helperText)
|
|
66
|
+
field.helperText = globalCallback(field.helperText);
|
|
67
|
+
if (field.mainSlotProps)
|
|
68
|
+
updateProperties(field.mainSlotProps, globalCallback);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Field callback for each field
|
|
72
|
+
if (fieldCalback) fieldCalback(field);
|
|
73
|
+
|
|
74
|
+
const creator = customFieldCreators[field.type];
|
|
75
|
+
if (creator == null) {
|
|
76
|
+
return (
|
|
77
|
+
<Grid
|
|
78
|
+
item
|
|
79
|
+
key={index}
|
|
80
|
+
{...field.gridItemProps}
|
|
81
|
+
{...transformSpace(field.space)}
|
|
82
|
+
>
|
|
83
|
+
{`Type ${field.type} is not supported currently`}
|
|
84
|
+
</Grid>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const Creator = creator;
|
|
89
|
+
const mref = React.createRef<CustomFieldRef<unknown>>();
|
|
90
|
+
|
|
91
|
+
let ui: JSX.Element | string = (
|
|
92
|
+
<Creator
|
|
93
|
+
field={field}
|
|
94
|
+
mref={mref}
|
|
95
|
+
onChange={onChange}
|
|
96
|
+
defaultValue={getValue(field)}
|
|
97
|
+
/>
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const name = field.name;
|
|
101
|
+
if (name) {
|
|
102
|
+
if (collections[name] == null) {
|
|
103
|
+
collections[name] = [mref, field];
|
|
104
|
+
} else {
|
|
105
|
+
ui = `Duplicate custom field ${name}`;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<Grid
|
|
111
|
+
item
|
|
112
|
+
key={name ?? index}
|
|
113
|
+
{...field.gridItemProps}
|
|
114
|
+
{...transformSpace(field.space)}
|
|
115
|
+
>
|
|
116
|
+
{ui}
|
|
117
|
+
</Grid>
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Create multiline label
|
|
124
|
+
* @param label Original label
|
|
125
|
+
* @param props Properties
|
|
126
|
+
* @returns Result
|
|
127
|
+
*/
|
|
128
|
+
export function createMultilineLabel(
|
|
129
|
+
label?: string,
|
|
130
|
+
props?: TypographyProps
|
|
131
|
+
) {
|
|
132
|
+
return label?.split("\n").map((line, index) => (
|
|
133
|
+
<Typography component="div" key={index} {...props}>
|
|
134
|
+
{line}
|
|
135
|
+
</Typography>
|
|
136
|
+
));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Transform custom field space
|
|
141
|
+
* @param space Space
|
|
142
|
+
* @returns Result
|
|
143
|
+
*/
|
|
144
|
+
export function transformSpace(space?: CustomFieldSpace) {
|
|
145
|
+
const props: GridProps =
|
|
146
|
+
space === "full"
|
|
147
|
+
? { xs: 12 }
|
|
148
|
+
: space === "quater"
|
|
149
|
+
? { sm: 12, md: 6, lg: 3 }
|
|
150
|
+
: space === "five"
|
|
151
|
+
? { sm: 12, md: 5 }
|
|
152
|
+
: space === "seven"
|
|
153
|
+
? { sm: 12, md: 7 }
|
|
154
|
+
: space === "half1"
|
|
155
|
+
? { xs: 12, sm: 6 }
|
|
156
|
+
: { sm: 12, md: 6 };
|
|
157
|
+
return props;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Update ref options
|
|
162
|
+
* @param fields Fields
|
|
163
|
+
* @param callback Callback
|
|
164
|
+
*/
|
|
165
|
+
export function updateOptions(
|
|
166
|
+
fields: CustomFieldData[],
|
|
167
|
+
callback: (key: string, ids: IdType[]) => ListType2[]
|
|
168
|
+
) {
|
|
169
|
+
fields.forEach((field) => {
|
|
170
|
+
if (field.refs == null || field.refs.length < 2) return;
|
|
171
|
+
const key = field.refs[0];
|
|
172
|
+
const ids = field.refs.slice(1);
|
|
173
|
+
field.options = callback(key, ids);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Update properties
|
|
179
|
+
* @param input Input object
|
|
180
|
+
* @param globalCallback Global callback
|
|
181
|
+
*/
|
|
182
|
+
export function updateProperties(
|
|
183
|
+
input: object,
|
|
184
|
+
globalCallback: (input: string) => string
|
|
185
|
+
) {
|
|
186
|
+
for (const key in input) {
|
|
187
|
+
const value = Reflect.get(input, key);
|
|
188
|
+
if (typeof value === "string") {
|
|
189
|
+
Reflect.set(input, key, globalCallback(value));
|
|
190
|
+
} else if (typeof value === "object" && value != null) {
|
|
191
|
+
updateProperties(value, globalCallback);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ICustomFieldReact } from "@etsoo/react";
|
|
2
|
+
import { NumberUtils } from "@etsoo/shared";
|
|
3
|
+
import { FormHelperText, Typography } from "@mui/material";
|
|
4
|
+
import React from "react";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Amount label field creator
|
|
8
|
+
* type: amountlabel
|
|
9
|
+
* @returns Component
|
|
10
|
+
*/
|
|
11
|
+
export const FieldAmountLabel: ICustomFieldReact<string> = ({
|
|
12
|
+
field,
|
|
13
|
+
mref,
|
|
14
|
+
defaultValue
|
|
15
|
+
}) => {
|
|
16
|
+
// Destruct
|
|
17
|
+
const { label, mainSlotProps = {}, helperText } = field;
|
|
18
|
+
const { currency, ...rest } = mainSlotProps;
|
|
19
|
+
|
|
20
|
+
const currencySymbol = React.useMemo(
|
|
21
|
+
() => (currency ? NumberUtils.getCurrencySymbol(currency) : ""),
|
|
22
|
+
[currency]
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
// State
|
|
26
|
+
const [amountLabel, setAmountLabel] = React.useState<string | undefined>(
|
|
27
|
+
label
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
React.useEffect(() => {
|
|
31
|
+
setAmountLabel(label);
|
|
32
|
+
}, [label]);
|
|
33
|
+
|
|
34
|
+
// Ref
|
|
35
|
+
const getValue = () => amountLabel;
|
|
36
|
+
const setValue = (value: unknown) => {
|
|
37
|
+
if (typeof value === "number") {
|
|
38
|
+
setAmountLabel(NumberUtils.formatMoney(value));
|
|
39
|
+
} else {
|
|
40
|
+
setAmountLabel(`${value} ?? ''`);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
React.useImperativeHandle(mref, () => ({
|
|
45
|
+
getValue,
|
|
46
|
+
setValue
|
|
47
|
+
}));
|
|
48
|
+
|
|
49
|
+
React.useEffect(() => {
|
|
50
|
+
if (defaultValue == null) return;
|
|
51
|
+
setValue(defaultValue);
|
|
52
|
+
}, [defaultValue]);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<React.Fragment>
|
|
56
|
+
<Typography {...rest}>
|
|
57
|
+
{currencySymbol} {amountLabel}
|
|
58
|
+
</Typography>
|
|
59
|
+
{helperText && <FormHelperText>{helperText}</FormHelperText>}
|
|
60
|
+
</React.Fragment>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ICustomFieldReact } from "@etsoo/react";
|
|
2
|
+
import { IdType } from "@etsoo/shared";
|
|
3
|
+
import { Typography } from "@mui/material";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { OptionGroup } from "../OptionGroup";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Checkbox (multiple values) field creator
|
|
9
|
+
* type: checkbox
|
|
10
|
+
* @returns Component
|
|
11
|
+
*/
|
|
12
|
+
export const FieldCheckbox: ICustomFieldReact<IdType[]> = ({
|
|
13
|
+
field,
|
|
14
|
+
mref,
|
|
15
|
+
onChange,
|
|
16
|
+
defaultValue
|
|
17
|
+
}) => {
|
|
18
|
+
// State
|
|
19
|
+
const [value, setLocalValue] = React.useState<IdType[]>();
|
|
20
|
+
|
|
21
|
+
// Ref
|
|
22
|
+
const getValue = () => value;
|
|
23
|
+
const setValue = (value: unknown) => {
|
|
24
|
+
if (Array.isArray(value)) {
|
|
25
|
+
setLocalValue(value);
|
|
26
|
+
} else if (typeof value === "string" || typeof value === "number") {
|
|
27
|
+
setLocalValue([value]);
|
|
28
|
+
} else {
|
|
29
|
+
setLocalValue(undefined);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
React.useImperativeHandle(mref, () => ({
|
|
34
|
+
getValue,
|
|
35
|
+
setValue
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
React.useEffect(() => {
|
|
39
|
+
if (defaultValue == null) return;
|
|
40
|
+
setValue(defaultValue);
|
|
41
|
+
}, [defaultValue]);
|
|
42
|
+
|
|
43
|
+
// Name
|
|
44
|
+
const name = field.name;
|
|
45
|
+
if (!name) {
|
|
46
|
+
return (
|
|
47
|
+
<Typography>No name for FieldCheckbox {JSON.stringify(field)}</Typography>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<OptionGroup
|
|
53
|
+
name={name}
|
|
54
|
+
options={field.options ?? []}
|
|
55
|
+
multiple
|
|
56
|
+
row
|
|
57
|
+
helperText={field.helperText}
|
|
58
|
+
label={field.label}
|
|
59
|
+
variant="outlined"
|
|
60
|
+
fullWidth
|
|
61
|
+
defaultValue={value}
|
|
62
|
+
onValueChange={(value) => {
|
|
63
|
+
const newValue = Array.isArray(value)
|
|
64
|
+
? value
|
|
65
|
+
: value == null
|
|
66
|
+
? undefined
|
|
67
|
+
: [value];
|
|
68
|
+
setLocalValue(newValue);
|
|
69
|
+
onChange(name, newValue);
|
|
70
|
+
}}
|
|
71
|
+
{...field.mainSlotProps}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
};
|