@etsoo/materialui 1.0.3 → 1.0.6

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.
@@ -0,0 +1,58 @@
1
+ import { DataTypes, IdDefaultType, LabelDefaultType } from '@etsoo/shared';
2
+ import { SelectChangeEvent } from '@mui/material';
3
+ import React from 'react';
4
+ /**
5
+ * Hierarchy selector props
6
+ */
7
+ export declare type HiSelectorProps<T extends object, D extends DataTypes.Keys<T> = IdDefaultType<T>, L extends DataTypes.Keys<T, string> = LabelDefaultType<T>> = {
8
+ /**
9
+ * Id field
10
+ */
11
+ idField?: D;
12
+ /**
13
+ * Error
14
+ */
15
+ error?: boolean;
16
+ /**
17
+ * The helper text content.
18
+ */
19
+ helperText?: React.ReactNode;
20
+ /**
21
+ * Name, also hidden input field name
22
+ */
23
+ name: string;
24
+ /**
25
+ * Label
26
+ */
27
+ label?: string;
28
+ /**
29
+ * Label field
30
+ */
31
+ labelField?: L;
32
+ /**
33
+ * Load data callback
34
+ */
35
+ loadData: (parent?: T[D]) => PromiseLike<T[] | null | undefined>;
36
+ /**
37
+ * On value change event
38
+ */
39
+ onChange?: (value: unknown) => void;
40
+ /**
41
+ * On item change event
42
+ */
43
+ onItemChange?: (e: SelectChangeEvent<unknown>) => void;
44
+ /**
45
+ * Required
46
+ */
47
+ required?: boolean;
48
+ /**
49
+ * Values
50
+ */
51
+ values?: T[D][];
52
+ };
53
+ /**
54
+ * Hierarchy selector
55
+ * @param props Prop
56
+ * @returns Component
57
+ */
58
+ export declare function HiSelector<T extends object, D extends DataTypes.Keys<T> = IdDefaultType<T>, L extends DataTypes.Keys<T, string> = LabelDefaultType<T>>(props: HiSelectorProps<T, D, L>): JSX.Element;
@@ -0,0 +1,47 @@
1
+ import { FormLabel, Grid } from '@mui/material';
2
+ import React from 'react';
3
+ import { SelectEx } from './SelectEx';
4
+ /**
5
+ * Hierarchy selector
6
+ * @param props Prop
7
+ * @returns Component
8
+ */
9
+ export function HiSelector(props) {
10
+ // Destruct
11
+ const { idField = 'id', error, helperText, name, label = name, labelField = 'name', loadData, onChange, onItemChange, required, values = [] } = props;
12
+ const [localValues, setValues] = React.useState(values);
13
+ const updateValue = (value) => {
14
+ if (onChange)
15
+ onChange(value);
16
+ };
17
+ const doChange = (event, index) => {
18
+ const value = event.target.value;
19
+ const itemValue = value === '' ? undefined : value;
20
+ updateValue(itemValue);
21
+ const newValues = [...localValues.slice(0, index)];
22
+ if (itemValue != null)
23
+ newValues.push(itemValue);
24
+ setValues(newValues);
25
+ if (onItemChange)
26
+ onItemChange(event);
27
+ };
28
+ React.useEffect(() => {
29
+ if (values.length > 0) {
30
+ setValues(values);
31
+ updateValue(values.at(-1));
32
+ }
33
+ }, [values]);
34
+ const currentValue = localValues.at(-1);
35
+ return (React.createElement(React.Fragment, null,
36
+ React.createElement(Grid, { item: true, xs: 12 },
37
+ React.createElement(FormLabel, { required: required, sx: { fontSize: (theme) => theme.typography.caption } }, label),
38
+ React.createElement("input", { type: "hidden", name: name, value: `${currentValue !== null && currentValue !== void 0 ? currentValue : ''}` })),
39
+ React.createElement(Grid, { item: true, xs: 6, md: 4, lg: 3 },
40
+ React.createElement(SelectEx, { idField: idField, labelField: labelField, name: "tab1", search: true, fullWidth: true, loadData: () => loadData(), value: values[0], onChange: (event) => doChange(event, 0), inputRequired: required, error: error, helperText: helperText })),
41
+ localValues[0] != null && (React.createElement(Grid, { item: true, xs: 6, md: 4, lg: 3 },
42
+ React.createElement(SelectEx, { key: `${localValues[0]}`, idField: idField, labelField: labelField, name: "tab2", search: true, fullWidth: true, loadData: () => loadData(localValues[0]), value: values[1], onChange: (event) => doChange(event, 1) }))),
43
+ localValues[1] != null && (React.createElement(Grid, { item: true, xs: 6, md: 4, lg: 3 },
44
+ React.createElement(SelectEx, { key: `${localValues[1]}`, idField: idField, labelField: labelField, name: "tab3", search: true, fullWidth: true, loadData: () => loadData(localValues[1]), value: values[2], onChange: (event) => doChange(event, 2) }))),
45
+ localValues[2] != null && (React.createElement(Grid, { item: true, xs: 6, md: 4, lg: 3 },
46
+ React.createElement(SelectEx, { key: `${localValues[2]}`, idField: idField, labelField: labelField, name: "tab4", search: true, fullWidth: true, loadData: () => loadData(localValues[2]), value: values[3], onChange: (event) => doChange(event, 3) })))));
47
+ }
package/lib/SelectEx.d.ts CHANGED
@@ -9,6 +9,14 @@ export declare type SelectExProps<T extends object, D extends DataTypes.Keys<T>
9
9
  * Auto add blank item
10
10
  */
11
11
  autoAddBlankItem?: boolean;
12
+ /**
13
+ * The helper text content.
14
+ */
15
+ helperText?: React.ReactNode;
16
+ /**
17
+ * Input required
18
+ */
19
+ inputRequired?: boolean;
12
20
  /**
13
21
  * Id field
14
22
  */
@@ -17,6 +25,10 @@ export declare type SelectExProps<T extends object, D extends DataTypes.Keys<T>
17
25
  * Item icon renderer
18
26
  */
19
27
  itemIconRenderer?: (id: T[D]) => React.ReactNode;
28
+ /**
29
+ * Item style
30
+ */
31
+ itemStyle?: (option: T) => React.CSSProperties;
20
32
  /**
21
33
  * Label field
22
34
  */
package/lib/SelectEx.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Checkbox, FormControl, InputLabel, ListItemText, MenuItem, OutlinedInput, Select } from '@mui/material';
1
+ import { Checkbox, FormControl, FormHelperText, InputLabel, ListItemText, MenuItem, OutlinedInput, Select } from '@mui/material';
2
2
  import React from 'react';
3
3
  import { MUGlobal } from './MUGlobal';
4
4
  import { ListItemRightIcon } from './ListItemRightIcon';
@@ -12,7 +12,7 @@ import { ReactUtils } from '@etsoo/react';
12
12
  export function SelectEx(props) {
13
13
  var _a;
14
14
  // Destruct
15
- const { defaultValue, idField = 'id', itemIconRenderer, label, labelField = 'label', loadData, onItemClick, onLoadData, multiple = false, name, options = [], search = false, autoAddBlankItem = search, value, onChange, fullWidth, ...rest } = props;
15
+ const { defaultValue, idField = 'id', error, helperText, inputRequired, itemIconRenderer, itemStyle, label, labelField = 'label', loadData, onItemClick, onLoadData, multiple = false, name, options = [], search = false, autoAddBlankItem = search, value, onChange, fullWidth, ...rest } = props;
16
16
  // Options state
17
17
  const [localOptions, setOptions] = React.useState(options);
18
18
  const isMounted = React.useRef(true);
@@ -112,13 +112,13 @@ export function SelectEx(props) {
112
112
  };
113
113
  }, []);
114
114
  // Layout
115
- return (React.createElement(FormControl, { size: search ? MUGlobal.searchFieldSize : MUGlobal.inputFieldSize, fullWidth: fullWidth },
115
+ return (React.createElement(FormControl, { size: search ? MUGlobal.searchFieldSize : MUGlobal.inputFieldSize, fullWidth: fullWidth, error: error },
116
116
  React.createElement(InputLabel, { id: labelId, shrink: search
117
117
  ? MUGlobal.searchFieldShrink
118
118
  : MUGlobal.inputFieldShrink }, label),
119
119
  React.createElement(Select, { ref: divRef, value: localOptions.some((option) => itemChecked(getId(option)))
120
120
  ? valueState !== null && valueState !== void 0 ? valueState : ''
121
- : '', input: React.createElement(OutlinedInput, { notched: true, label: label }), labelId: labelId, name: name, multiple: multiple, onChange: (event, child) => {
121
+ : '', input: React.createElement(OutlinedInput, { notched: true, label: label, required: inputRequired }), labelId: labelId, name: name, multiple: multiple, onChange: (event, child) => {
122
122
  if (onChange)
123
123
  onChange(event, child);
124
124
  if (multiple)
@@ -148,9 +148,12 @@ export function SelectEx(props) {
148
148
  }
149
149
  if (!multiple)
150
150
  setItemValue(id);
151
- } },
151
+ }, style: itemStyle == null
152
+ ? undefined
153
+ : itemStyle(option) },
152
154
  multiple && React.createElement(Checkbox, { checked: itemChecked(id) }),
153
155
  React.createElement(ListItemText, { primary: label }),
154
156
  itemIconRenderer && (React.createElement(ListItemRightIcon, null, itemIconRenderer(option[idField])))));
155
- }))));
157
+ })),
158
+ helperText != null && (React.createElement(FormHelperText, null, helperText))));
156
159
  }
package/lib/index.d.ts CHANGED
@@ -38,6 +38,7 @@ export * from './EmailInput';
38
38
  export * from './FabBox';
39
39
  export * from './FlexBox';
40
40
  export * from './GridDataFormat';
41
+ export * from './HiSelector';
41
42
  export * from './IconButtonLink';
42
43
  export * from './InputField';
43
44
  export * from './ItemList';
package/lib/index.js CHANGED
@@ -38,6 +38,7 @@ export * from './EmailInput';
38
38
  export * from './FabBox';
39
39
  export * from './FlexBox';
40
40
  export * from './GridDataFormat';
41
+ export * from './HiSelector';
41
42
  export * from './IconButtonLink';
42
43
  export * from './InputField';
43
44
  export * from './ItemList';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.0.3",
3
+ "version": "1.0.6",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -0,0 +1,201 @@
1
+ import { DataTypes, IdDefaultType, LabelDefaultType } from '@etsoo/shared';
2
+ import { FormLabel, Grid, SelectChangeEvent } from '@mui/material';
3
+ import React from 'react';
4
+ import { SelectEx } from './SelectEx';
5
+
6
+ /**
7
+ * Hierarchy selector props
8
+ */
9
+ export type HiSelectorProps<
10
+ T extends object,
11
+ D extends DataTypes.Keys<T> = IdDefaultType<T>,
12
+ L extends DataTypes.Keys<T, string> = LabelDefaultType<T>
13
+ > = {
14
+ /**
15
+ * Id field
16
+ */
17
+ idField?: D;
18
+
19
+ /**
20
+ * Error
21
+ */
22
+ error?: boolean;
23
+
24
+ /**
25
+ * The helper text content.
26
+ */
27
+ helperText?: React.ReactNode;
28
+
29
+ /**
30
+ * Name, also hidden input field name
31
+ */
32
+ name: string;
33
+
34
+ /**
35
+ * Label
36
+ */
37
+ label?: string;
38
+
39
+ /**
40
+ * Label field
41
+ */
42
+ labelField?: L;
43
+
44
+ /**
45
+ * Load data callback
46
+ */
47
+ loadData: (parent?: T[D]) => PromiseLike<T[] | null | undefined>;
48
+
49
+ /**
50
+ * On value change event
51
+ */
52
+ onChange?: (value: unknown) => void;
53
+
54
+ /**
55
+ * On item change event
56
+ */
57
+ onItemChange?: (e: SelectChangeEvent<unknown>) => void;
58
+
59
+ /**
60
+ * Required
61
+ */
62
+ required?: boolean;
63
+
64
+ /**
65
+ * Values
66
+ */
67
+ values?: T[D][];
68
+ };
69
+
70
+ /**
71
+ * Hierarchy selector
72
+ * @param props Prop
73
+ * @returns Component
74
+ */
75
+ export function HiSelector<
76
+ T extends object,
77
+ D extends DataTypes.Keys<T> = IdDefaultType<T>,
78
+ L extends DataTypes.Keys<T, string> = LabelDefaultType<T>
79
+ >(props: HiSelectorProps<T, D, L>) {
80
+ // Destruct
81
+ const {
82
+ idField = 'id' as D,
83
+ error,
84
+ helperText,
85
+ name,
86
+ label = name,
87
+ labelField = 'name' as L,
88
+ loadData,
89
+ onChange,
90
+ onItemChange,
91
+ required,
92
+ values = []
93
+ } = props;
94
+
95
+ // Value type
96
+ type ValueType = T[D];
97
+ const [localValues, setValues] = React.useState<ValueType[]>(values);
98
+
99
+ const updateValue = (value?: T[D]) => {
100
+ if (onChange) onChange(value);
101
+ };
102
+
103
+ const doChange = (event: SelectChangeEvent<unknown>, index: number) => {
104
+ const value = event.target.value;
105
+ const itemValue = value === '' ? undefined : (value as T[D]);
106
+ updateValue(itemValue);
107
+
108
+ const newValues = [...localValues.slice(0, index)];
109
+ if (itemValue != null) newValues.push(itemValue);
110
+ setValues(newValues);
111
+
112
+ if (onItemChange) onItemChange(event);
113
+ };
114
+
115
+ React.useEffect(() => {
116
+ if (values.length > 0) {
117
+ setValues(values);
118
+ updateValue(values.at(-1));
119
+ }
120
+ }, [values]);
121
+
122
+ const currentValue = localValues.at(-1);
123
+
124
+ return (
125
+ <React.Fragment>
126
+ <Grid item xs={12}>
127
+ <FormLabel
128
+ required={required}
129
+ sx={{ fontSize: (theme) => theme.typography.caption }}
130
+ >
131
+ {label}
132
+ </FormLabel>
133
+ <input
134
+ type="hidden"
135
+ name={name}
136
+ value={`${currentValue ?? ''}`}
137
+ />
138
+ </Grid>
139
+ <Grid item xs={6} md={4} lg={3}>
140
+ <SelectEx<T, D, L>
141
+ idField={idField}
142
+ labelField={labelField}
143
+ name="tab1"
144
+ search
145
+ fullWidth
146
+ loadData={() => loadData()}
147
+ value={values[0]}
148
+ onChange={(event) => doChange(event, 0)}
149
+ inputRequired={required}
150
+ error={error}
151
+ helperText={helperText}
152
+ />
153
+ </Grid>
154
+ {localValues[0] != null && (
155
+ <Grid item xs={6} md={4} lg={3}>
156
+ <SelectEx<T, D, L>
157
+ key={`${localValues[0]}`}
158
+ idField={idField}
159
+ labelField={labelField}
160
+ name="tab2"
161
+ search
162
+ fullWidth
163
+ loadData={() => loadData(localValues[0])}
164
+ value={values[1]}
165
+ onChange={(event) => doChange(event, 1)}
166
+ />
167
+ </Grid>
168
+ )}
169
+ {localValues[1] != null && (
170
+ <Grid item xs={6} md={4} lg={3}>
171
+ <SelectEx<T, D, L>
172
+ key={`${localValues[1]}`}
173
+ idField={idField}
174
+ labelField={labelField}
175
+ name="tab3"
176
+ search
177
+ fullWidth
178
+ loadData={() => loadData(localValues[1])}
179
+ value={values[2]}
180
+ onChange={(event) => doChange(event, 2)}
181
+ />
182
+ </Grid>
183
+ )}
184
+ {localValues[2] != null && (
185
+ <Grid item xs={6} md={4} lg={3}>
186
+ <SelectEx<T, D, L>
187
+ key={`${localValues[2]}`}
188
+ idField={idField}
189
+ labelField={labelField}
190
+ name="tab4"
191
+ search
192
+ fullWidth
193
+ loadData={() => loadData(localValues[2])}
194
+ value={values[3]}
195
+ onChange={(event) => doChange(event, 3)}
196
+ />
197
+ </Grid>
198
+ )}
199
+ </React.Fragment>
200
+ );
201
+ }
package/src/SelectEx.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  Checkbox,
3
3
  FormControl,
4
+ FormHelperText,
4
5
  InputLabel,
5
6
  ListItemText,
6
7
  MenuItem,
@@ -34,6 +35,16 @@ export type SelectExProps<
34
35
  */
35
36
  autoAddBlankItem?: boolean;
36
37
 
38
+ /**
39
+ * The helper text content.
40
+ */
41
+ helperText?: React.ReactNode;
42
+
43
+ /**
44
+ * Input required
45
+ */
46
+ inputRequired?: boolean;
47
+
37
48
  /**
38
49
  * Id field
39
50
  */
@@ -44,6 +55,11 @@ export type SelectExProps<
44
55
  */
45
56
  itemIconRenderer?: (id: T[D]) => React.ReactNode;
46
57
 
58
+ /**
59
+ * Item style
60
+ */
61
+ itemStyle?: (option: T) => React.CSSProperties;
62
+
47
63
  /**
48
64
  * Label field
49
65
  */
@@ -89,7 +105,11 @@ export function SelectEx<
89
105
  const {
90
106
  defaultValue,
91
107
  idField = 'id' as D,
108
+ error,
109
+ helperText,
110
+ inputRequired,
92
111
  itemIconRenderer,
112
+ itemStyle,
93
113
  label,
94
114
  labelField = 'label' as L,
95
115
  loadData,
@@ -212,6 +232,7 @@ export function SelectEx<
212
232
  <FormControl
213
233
  size={search ? MUGlobal.searchFieldSize : MUGlobal.inputFieldSize}
214
234
  fullWidth={fullWidth}
235
+ error={error}
215
236
  >
216
237
  <InputLabel
217
238
  id={labelId}
@@ -230,7 +251,13 @@ export function SelectEx<
230
251
  ? valueState ?? ''
231
252
  : ''
232
253
  }
233
- input={<OutlinedInput notched label={label} />}
254
+ input={
255
+ <OutlinedInput
256
+ notched
257
+ label={label}
258
+ required={inputRequired}
259
+ />
260
+ }
234
261
  labelId={labelId}
235
262
  name={name}
236
263
  multiple={multiple}
@@ -273,6 +300,11 @@ export function SelectEx<
273
300
  }
274
301
  if (!multiple) setItemValue(id);
275
302
  }}
303
+ style={
304
+ itemStyle == null
305
+ ? undefined
306
+ : itemStyle(option)
307
+ }
276
308
  >
277
309
  {multiple && <Checkbox checked={itemChecked(id)} />}
278
310
  <ListItemText primary={label} />
@@ -285,6 +317,9 @@ export function SelectEx<
285
317
  );
286
318
  })}
287
319
  </Select>
320
+ {helperText != null && (
321
+ <FormHelperText>{helperText}</FormHelperText>
322
+ )}
288
323
  </FormControl>
289
324
  );
290
325
  }
package/src/index.ts CHANGED
@@ -41,6 +41,7 @@ export * from './EmailInput';
41
41
  export * from './FabBox';
42
42
  export * from './FlexBox';
43
43
  export * from './GridDataFormat';
44
+ export * from './HiSelector';
44
45
  export * from './IconButtonLink';
45
46
  export * from './InputField';
46
47
  export * from './ItemList';