@etsoo/materialui 1.3.62 → 1.3.64

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.
Files changed (47) hide show
  1. package/__tests__/CustomFields.tsx +93 -0
  2. package/lib/custom/CustomFieldUtils.d.ts +50 -0
  3. package/lib/custom/CustomFieldUtils.js +138 -0
  4. package/lib/custom/FieldAmountLabel.d.ts +7 -0
  5. package/lib/custom/FieldAmountLabel.js +40 -0
  6. package/lib/custom/FieldCheckbox.d.ts +8 -0
  7. package/lib/custom/FieldCheckbox.js +49 -0
  8. package/lib/custom/FieldCombobox.d.ts +8 -0
  9. package/lib/custom/FieldCombobox.js +40 -0
  10. package/lib/custom/FieldDateInput.d.ts +7 -0
  11. package/lib/custom/FieldDateInput.js +43 -0
  12. package/lib/custom/FieldDivider.d.ts +7 -0
  13. package/lib/custom/FieldDivider.js +12 -0
  14. package/lib/custom/FieldInput.d.ts +7 -0
  15. package/lib/custom/FieldInput.js +27 -0
  16. package/lib/custom/FieldJson.d.ts +7 -0
  17. package/lib/custom/FieldJson.js +50 -0
  18. package/lib/custom/FieldLabel.d.ts +7 -0
  19. package/lib/custom/FieldLabel.js +28 -0
  20. package/lib/custom/FieldNumberInput.d.ts +7 -0
  21. package/lib/custom/FieldNumberInput.js +37 -0
  22. package/lib/custom/FieldRadio.d.ts +8 -0
  23. package/lib/custom/FieldRadio.js +49 -0
  24. package/lib/custom/FieldSelect.d.ts +8 -0
  25. package/lib/custom/FieldSelect.js +48 -0
  26. package/lib/custom/FieldSwitch.d.ts +7 -0
  27. package/lib/custom/FieldSwitch.js +42 -0
  28. package/lib/custom/FieldTexarea.d.ts +7 -0
  29. package/lib/custom/FieldTexarea.js +28 -0
  30. package/lib/pages/DataGridPageProps.d.ts +1 -1
  31. package/package.json +14 -14
  32. package/src/ShowDataComparison.tsx +0 -1
  33. package/src/custom/CustomFieldUtils.tsx +195 -0
  34. package/src/custom/FieldAmountLabel.tsx +62 -0
  35. package/src/custom/FieldCheckbox.tsx +74 -0
  36. package/src/custom/FieldCombobox.tsx +63 -0
  37. package/src/custom/FieldDateInput.tsx +75 -0
  38. package/src/custom/FieldDivider.tsx +18 -0
  39. package/src/custom/FieldInput.tsx +49 -0
  40. package/src/custom/FieldJson.tsx +77 -0
  41. package/src/custom/FieldLabel.tsx +40 -0
  42. package/src/custom/FieldNumberInput.tsx +60 -0
  43. package/src/custom/FieldRadio.tsx +73 -0
  44. package/src/custom/FieldSelect.tsx +70 -0
  45. package/src/custom/FieldSwitch.tsx +58 -0
  46. package/src/custom/FieldTexarea.tsx +54 -0
  47. package/src/pages/DataGridPageProps.ts +1 -1
@@ -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,8 @@
1
+ import { ICustomFieldReact } from "@etsoo/react";
2
+ import { IdType } from "@etsoo/shared";
3
+ /**
4
+ * Radio (single value) field creator
5
+ * type: radio
6
+ * @returns Component
7
+ */
8
+ export declare const FieldRadio: ICustomFieldReact<IdType>;
@@ -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,8 @@
1
+ import { IdType } from "@etsoo/shared";
2
+ import { ICustomFieldReact } from "@etsoo/react";
3
+ /**
4
+ * Select (single value) field creator
5
+ * type select
6
+ * @returns Component
7
+ */
8
+ export declare const FieldSelect: ICustomFieldReact<IdType>;
@@ -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,7 @@
1
+ import { ICustomFieldReact } from "@etsoo/react";
2
+ /**
3
+ * Input field creator
4
+ * type: switch
5
+ * @returns Component
6
+ */
7
+ export declare const FieldSwitch: ICustomFieldReact<boolean>;
@@ -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,7 @@
1
+ import { ICustomFieldReact } from "@etsoo/react";
2
+ /**
3
+ * Textarea field creator
4
+ * type: textarea
5
+ * @returns Component
6
+ */
7
+ export declare const FieldTexarea: ICustomFieldReact<string>;
@@ -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
+ };
@@ -4,7 +4,7 @@ import type { SearchPageProps } from "./SearchPageProps";
4
4
  /**
5
5
  * DataGrid page props
6
6
  */
7
- export type DataGridPageProps<T extends object, F extends DataTypes.BasicTemplate> = SearchPageProps<T, F> & Omit<DataGridExProps<T>, "loadData" | "height"> & {
7
+ export type DataGridPageProps<T extends object, F extends DataTypes.BasicTemplate> = SearchPageProps<T, F> & DataGridExProps<T> & {
8
8
  /**
9
9
  * Height will be deducted
10
10
  * @param height Current calcuated height
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.3.62",
3
+ "version": "1.3.64",
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.90",
53
+ "@etsoo/appscript": "^1.4.95",
54
54
  "@etsoo/notificationbase": "^1.1.42",
55
- "@etsoo/react": "^1.7.46",
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.0"
70
+ "react-imask": "7.6.1"
71
71
  },
72
72
  "devDependencies": {
73
- "@babel/cli": "^7.24.5",
74
- "@babel/core": "^7.24.5",
75
- "@babel/plugin-transform-runtime": "^7.24.3",
76
- "@babel/preset-env": "^7.24.5",
77
- "@babel/preset-react": "^7.24.1",
78
- "@babel/preset-typescript": "^7.24.1",
79
- "@babel/runtime-corejs3": "^7.24.5",
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.2",
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.9.0",
91
- "@typescript-eslint/parser": "^7.9.0",
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"
@@ -8,7 +8,6 @@ import {
8
8
  TableHead,
9
9
  TableRow
10
10
  } from "@mui/material";
11
- import React from "react";
12
11
  import { globalApp } from "./app/ReactApp";
13
12
 
14
13
  /**
@@ -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
+ };