@etsoo/materialui 1.1.71 → 1.1.73
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/ComboBoxPro.d.ts +34 -0
- package/lib/ComboBoxPro.js +53 -0
- package/lib/SelectEx.d.ts +4 -4
- package/lib/SelectEx.js +24 -28
- package/lib/TagList.js +19 -4
- package/lib/TagListPro.d.ts +30 -0
- package/lib/TagListPro.js +63 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/package.json +4 -4
- package/src/ComboBoxPro.tsx +139 -0
- package/src/SelectEx.tsx +359 -382
- package/src/TagList.tsx +23 -2
- package/src/TagListPro.tsx +175 -0
- package/src/Tiplist.tsx +1 -1
- package/src/index.ts +2 -0
package/src/SelectEx.tsx
CHANGED
|
@@ -1,106 +1,107 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from
|
|
14
|
-
import React from
|
|
15
|
-
import { MUGlobal } from
|
|
16
|
-
import { ListItemRightIcon } from
|
|
17
|
-
import RefreshIcon from
|
|
2
|
+
Checkbox,
|
|
3
|
+
FormControl,
|
|
4
|
+
FormHelperText,
|
|
5
|
+
IconButton,
|
|
6
|
+
InputLabel,
|
|
7
|
+
ListItemText,
|
|
8
|
+
MenuItem,
|
|
9
|
+
OutlinedInput,
|
|
10
|
+
Select,
|
|
11
|
+
SelectProps,
|
|
12
|
+
Stack
|
|
13
|
+
} from "@mui/material";
|
|
14
|
+
import React from "react";
|
|
15
|
+
import { MUGlobal } from "./MUGlobal";
|
|
16
|
+
import { ListItemRightIcon } from "./ListItemRightIcon";
|
|
17
|
+
import RefreshIcon from "@mui/icons-material/Refresh";
|
|
18
18
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
ArrayUtils,
|
|
20
|
+
DataTypes,
|
|
21
|
+
IdDefaultType,
|
|
22
|
+
LabelDefaultType,
|
|
23
|
+
ListType,
|
|
24
|
+
Utils
|
|
25
|
+
} from "@etsoo/shared";
|
|
26
|
+
import { ReactUtils } from "@etsoo/react";
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Extended select component props
|
|
29
30
|
*/
|
|
30
31
|
export type SelectExProps<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
> = Omit<SelectProps,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
32
|
+
T extends object,
|
|
33
|
+
D extends DataTypes.Keys<T> = IdDefaultType<T>,
|
|
34
|
+
L extends DataTypes.Keys<T, string> = LabelDefaultType<T>
|
|
35
|
+
> = Omit<SelectProps, "labelId" | "input" | "native"> & {
|
|
36
|
+
/**
|
|
37
|
+
* Auto add blank item
|
|
38
|
+
*/
|
|
39
|
+
autoAddBlankItem?: boolean;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The helper text content.
|
|
43
|
+
*/
|
|
44
|
+
helperText?: React.ReactNode;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Input required
|
|
48
|
+
*/
|
|
49
|
+
inputRequired?: boolean;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Id field
|
|
53
|
+
*/
|
|
54
|
+
idField?: D;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Item icon renderer
|
|
58
|
+
*/
|
|
59
|
+
itemIconRenderer?: (id: T[D]) => React.ReactNode;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Item style
|
|
63
|
+
*/
|
|
64
|
+
itemStyle?: (option: T) => React.CSSProperties;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Label field
|
|
68
|
+
*/
|
|
69
|
+
labelField?: L | ((option: T) => string);
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Load data callback
|
|
73
|
+
*/
|
|
74
|
+
loadData?: () => PromiseLike<T[] | null | undefined>;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Item change callback
|
|
78
|
+
*/
|
|
79
|
+
onItemChange?: (option: T | undefined, userAction: boolean) => void;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Item click handler
|
|
83
|
+
*/
|
|
84
|
+
onItemClick?: (event: React.MouseEvent, option: T) => void;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* On load data handler
|
|
88
|
+
*/
|
|
89
|
+
onLoadData?: (options: T[]) => void;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Array of options.
|
|
93
|
+
*/
|
|
94
|
+
options?: ReadonlyArray<T>;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Supports refresh label or component
|
|
98
|
+
*/
|
|
99
|
+
refresh?: string | React.ReactNode;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Is search case?
|
|
103
|
+
*/
|
|
104
|
+
search?: boolean;
|
|
104
105
|
};
|
|
105
106
|
|
|
106
107
|
/**
|
|
@@ -109,301 +110,277 @@ export type SelectExProps<
|
|
|
109
110
|
* @returns Component
|
|
110
111
|
*/
|
|
111
112
|
export function SelectEx<
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
T extends object = ListType,
|
|
114
|
+
D extends DataTypes.Keys<T> = IdDefaultType<T>,
|
|
115
|
+
L extends DataTypes.Keys<T, string> = LabelDefaultType<T>
|
|
115
116
|
>(props: SelectExProps<T, D, L>) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
117
|
+
// Destruct
|
|
118
|
+
const {
|
|
119
|
+
defaultValue,
|
|
120
|
+
idField = "id" as D,
|
|
121
|
+
error,
|
|
122
|
+
helperText,
|
|
123
|
+
inputRequired,
|
|
124
|
+
itemIconRenderer,
|
|
125
|
+
itemStyle,
|
|
126
|
+
label,
|
|
127
|
+
labelField = "label" as L,
|
|
128
|
+
loadData,
|
|
129
|
+
onItemChange,
|
|
130
|
+
onItemClick,
|
|
131
|
+
onLoadData,
|
|
132
|
+
multiple = false,
|
|
133
|
+
name,
|
|
134
|
+
options,
|
|
135
|
+
refresh,
|
|
136
|
+
search = false,
|
|
137
|
+
autoAddBlankItem = search,
|
|
138
|
+
value,
|
|
139
|
+
onChange,
|
|
140
|
+
fullWidth,
|
|
141
|
+
...rest
|
|
142
|
+
} = props;
|
|
143
|
+
|
|
144
|
+
// Options state
|
|
145
|
+
const [localOptions, setOptions] = React.useState<readonly T[]>([]);
|
|
146
|
+
const isMounted = React.useRef(false);
|
|
147
|
+
|
|
148
|
+
const doItemChange = (
|
|
149
|
+
options: readonly T[],
|
|
150
|
+
value: unknown,
|
|
151
|
+
userAction: boolean
|
|
152
|
+
) => {
|
|
153
|
+
if (onItemChange == null) return;
|
|
154
|
+
|
|
155
|
+
let option: T | undefined;
|
|
156
|
+
if (multiple && Array.isArray(value)) {
|
|
157
|
+
option = options.find((option) => value.includes(option[idField]));
|
|
158
|
+
} else if (value == null || value === "") {
|
|
159
|
+
option = undefined;
|
|
160
|
+
} else {
|
|
161
|
+
option = options.find((option) => option[idField] === value);
|
|
162
|
+
}
|
|
163
|
+
onItemChange(option, userAction);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const setOptionsAdd = (options: readonly T[]) => {
|
|
167
|
+
setOptions(options);
|
|
168
|
+
if (valueSource != null) doItemChange(options, valueSource, false);
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// When options change
|
|
172
|
+
// [options] will cause infinite loop
|
|
173
|
+
const propertyWay = loadData == null;
|
|
174
|
+
React.useEffect(() => {
|
|
175
|
+
if (options == null || !propertyWay) return;
|
|
176
|
+
setOptionsAdd(options);
|
|
177
|
+
}, [options, propertyWay]);
|
|
178
|
+
|
|
179
|
+
// Local value
|
|
180
|
+
const v = defaultValue ?? value;
|
|
181
|
+
const valueSource = React.useMemo(
|
|
182
|
+
() => (multiple ? (v ? (Array.isArray(v) ? v : [v]) : []) : v ?? ""),
|
|
183
|
+
[multiple, v]
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
// Value state
|
|
187
|
+
const [valueState, setValueStateBase] = React.useState<unknown>(valueSource);
|
|
188
|
+
const valueRef = React.useRef<unknown>();
|
|
189
|
+
const setValueState = (newValue: unknown) => {
|
|
190
|
+
valueRef.current = newValue;
|
|
191
|
+
setValueStateBase(newValue);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
React.useEffect(() => {
|
|
195
|
+
if (valueSource != null) setValueState(valueSource);
|
|
196
|
+
}, [valueSource]);
|
|
197
|
+
|
|
198
|
+
// Label id
|
|
199
|
+
const labelId = `selectex-label-${name}`;
|
|
200
|
+
|
|
201
|
+
// Set item
|
|
202
|
+
const setItemValue = (id: unknown) => {
|
|
203
|
+
if (id !== valueRef.current) {
|
|
204
|
+
// Difference
|
|
205
|
+
const diff = multiple
|
|
206
|
+
? ArrayUtils.differences(id as T[D][], valueRef.current as T[D][])
|
|
207
|
+
: id;
|
|
208
|
+
|
|
209
|
+
setValueState(id);
|
|
210
|
+
|
|
211
|
+
const input = divRef.current?.querySelector("input");
|
|
212
|
+
if (input) {
|
|
213
|
+
// Different value, trigger change event
|
|
214
|
+
ReactUtils.triggerChange(input, id as string, false);
|
|
215
|
+
}
|
|
216
|
+
return diff;
|
|
217
|
+
}
|
|
218
|
+
return undefined;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// Get option id
|
|
222
|
+
const getId = (option: T) => {
|
|
223
|
+
return option[idField] as unknown as React.Key;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
// Get option label
|
|
227
|
+
const getLabel = (option: T) => {
|
|
228
|
+
return typeof labelField === "function"
|
|
229
|
+
? labelField(option)
|
|
230
|
+
: (option[labelField] as string);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Refs
|
|
234
|
+
const divRef = React.useRef<HTMLDivElement>();
|
|
235
|
+
|
|
236
|
+
// Refresh list data
|
|
237
|
+
const refreshData = () => {
|
|
238
|
+
if (loadData == null) return;
|
|
239
|
+
loadData().then((result) => {
|
|
240
|
+
if (result == null || !isMounted.current) return;
|
|
241
|
+
if (onLoadData) onLoadData(result);
|
|
242
|
+
if (autoAddBlankItem) {
|
|
243
|
+
Utils.addBlankItem(result, idField, labelField);
|
|
244
|
+
}
|
|
245
|
+
setOptionsAdd(result);
|
|
246
|
+
});
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// When value change
|
|
250
|
+
React.useEffect(() => {
|
|
251
|
+
refreshData();
|
|
252
|
+
}, [valueSource]);
|
|
253
|
+
|
|
254
|
+
// When layout ready
|
|
255
|
+
React.useEffect(() => {
|
|
256
|
+
const input = divRef.current?.querySelector("input");
|
|
257
|
+
const inputChange = (event: Event) => {
|
|
258
|
+
// Reset case
|
|
259
|
+
if (event.cancelable) setValueState(multiple ? [] : "");
|
|
163
260
|
};
|
|
261
|
+
input?.addEventListener("change", inputChange);
|
|
164
262
|
|
|
165
|
-
|
|
166
|
-
setOptions(options);
|
|
167
|
-
if (valueSource != null) doItemChange(options, valueSource, false);
|
|
168
|
-
};
|
|
263
|
+
isMounted.current = true;
|
|
169
264
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
React.useEffect(() => {
|
|
174
|
-
if (options == null || !propertyWay) return;
|
|
175
|
-
setOptionsAdd(options);
|
|
176
|
-
}, [options, propertyWay]);
|
|
177
|
-
|
|
178
|
-
// Local value
|
|
179
|
-
const v = defaultValue ?? value;
|
|
180
|
-
const valueSource = React.useMemo(
|
|
181
|
-
() => (multiple ? (v ? (Array.isArray(v) ? v : [v]) : []) : v ?? ''),
|
|
182
|
-
[multiple, v]
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
// Value state
|
|
186
|
-
const [valueState, setValueStateBase] =
|
|
187
|
-
React.useState<unknown>(valueSource);
|
|
188
|
-
const valueRef = React.useRef<unknown>();
|
|
189
|
-
const setValueState = (newValue: unknown) => {
|
|
190
|
-
valueRef.current = newValue;
|
|
191
|
-
setValueStateBase(newValue);
|
|
265
|
+
return () => {
|
|
266
|
+
isMounted.current = false;
|
|
267
|
+
input?.removeEventListener("change", inputChange);
|
|
192
268
|
};
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
269
|
+
}, [multiple]);
|
|
270
|
+
|
|
271
|
+
// Layout
|
|
272
|
+
return (
|
|
273
|
+
<Stack direction="row">
|
|
274
|
+
<FormControl
|
|
275
|
+
size={search ? MUGlobal.searchFieldSize : MUGlobal.inputFieldSize}
|
|
276
|
+
fullWidth={fullWidth}
|
|
277
|
+
error={error}
|
|
278
|
+
>
|
|
279
|
+
<InputLabel
|
|
280
|
+
id={labelId}
|
|
281
|
+
shrink={
|
|
282
|
+
search ? MUGlobal.searchFieldShrink : MUGlobal.inputFieldShrink
|
|
283
|
+
}
|
|
284
|
+
>
|
|
285
|
+
{label}
|
|
286
|
+
</InputLabel>
|
|
287
|
+
<Select
|
|
288
|
+
ref={divRef}
|
|
289
|
+
value={
|
|
290
|
+
multiple
|
|
291
|
+
? valueState
|
|
292
|
+
: localOptions.some((o) => o[idField] === valueState)
|
|
293
|
+
? valueState
|
|
294
|
+
: ""
|
|
295
|
+
}
|
|
296
|
+
input={
|
|
297
|
+
<OutlinedInput notched label={label} required={inputRequired} />
|
|
298
|
+
}
|
|
299
|
+
labelId={labelId}
|
|
300
|
+
name={name}
|
|
301
|
+
multiple={multiple}
|
|
302
|
+
onChange={(event, child) => {
|
|
303
|
+
if (onChange) {
|
|
304
|
+
onChange(event, child);
|
|
305
|
+
|
|
306
|
+
// event.preventDefault() will block executing
|
|
307
|
+
if (event.defaultPrevented) return;
|
|
218
308
|
}
|
|
219
|
-
return diff;
|
|
220
|
-
}
|
|
221
|
-
return undefined;
|
|
222
|
-
};
|
|
223
309
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
// Get option label
|
|
230
|
-
const getLabel = (option: T) => {
|
|
231
|
-
return typeof labelField === 'function'
|
|
232
|
-
? labelField(option)
|
|
233
|
-
: (option[labelField] as string);
|
|
234
|
-
};
|
|
310
|
+
// Set item value
|
|
311
|
+
const value = event.target.value;
|
|
312
|
+
if (multiple && !Array.isArray(value)) return;
|
|
235
313
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
// Refresh list data
|
|
240
|
-
const refreshData = () => {
|
|
241
|
-
if (loadData == null) return;
|
|
242
|
-
loadData().then((result) => {
|
|
243
|
-
if (result == null || !isMounted.current) return;
|
|
244
|
-
if (onLoadData) onLoadData(result);
|
|
245
|
-
if (autoAddBlankItem) {
|
|
246
|
-
Utils.addBlankItem(result, idField, labelField);
|
|
314
|
+
const diff = setItemValue(value);
|
|
315
|
+
if (diff != null) {
|
|
316
|
+
doItemChange(localOptions, diff, true);
|
|
247
317
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
>
|
|
292
|
-
{label}
|
|
293
|
-
</InputLabel>
|
|
294
|
-
<Select
|
|
295
|
-
ref={divRef}
|
|
296
|
-
value={
|
|
297
|
-
multiple
|
|
298
|
-
? valueState
|
|
299
|
-
: localOptions.some(
|
|
300
|
-
(o) => o[idField] === valueState
|
|
301
|
-
)
|
|
302
|
-
? valueState
|
|
303
|
-
: ''
|
|
318
|
+
}}
|
|
319
|
+
renderValue={(selected) => {
|
|
320
|
+
// The text shows up
|
|
321
|
+
return localOptions
|
|
322
|
+
.filter((option) => {
|
|
323
|
+
const id = getId(option);
|
|
324
|
+
return Array.isArray(selected)
|
|
325
|
+
? selected.indexOf(id) !== -1
|
|
326
|
+
: selected === id;
|
|
327
|
+
})
|
|
328
|
+
.map((option) => getLabel(option))
|
|
329
|
+
.join(", ");
|
|
330
|
+
}}
|
|
331
|
+
sx={{ minWidth: "150px" }}
|
|
332
|
+
fullWidth={fullWidth}
|
|
333
|
+
{...rest}
|
|
334
|
+
>
|
|
335
|
+
{localOptions.map((option) => {
|
|
336
|
+
// Option id
|
|
337
|
+
const id = getId(option);
|
|
338
|
+
|
|
339
|
+
// Option label
|
|
340
|
+
const label = getLabel(option);
|
|
341
|
+
|
|
342
|
+
// Option
|
|
343
|
+
return (
|
|
344
|
+
<MenuItem
|
|
345
|
+
key={id}
|
|
346
|
+
value={id}
|
|
347
|
+
onClick={(event) => {
|
|
348
|
+
if (onItemClick) {
|
|
349
|
+
onItemClick(event, option);
|
|
350
|
+
}
|
|
351
|
+
}}
|
|
352
|
+
style={itemStyle == null ? undefined : itemStyle(option)}
|
|
353
|
+
>
|
|
354
|
+
{multiple && (
|
|
355
|
+
<Checkbox
|
|
356
|
+
checked={
|
|
357
|
+
Array.isArray(valueState)
|
|
358
|
+
? valueState.includes(id)
|
|
359
|
+
: valueState === id
|
|
304
360
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
labelId={labelId}
|
|
313
|
-
name={name}
|
|
314
|
-
multiple={multiple}
|
|
315
|
-
onChange={(event, child) => {
|
|
316
|
-
if (onChange) {
|
|
317
|
-
onChange(event, child);
|
|
318
|
-
|
|
319
|
-
// event.preventDefault() will block executing
|
|
320
|
-
if (event.defaultPrevented) return;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Set item value
|
|
324
|
-
const value = event.target.value;
|
|
325
|
-
if (multiple && !Array.isArray(value)) return;
|
|
326
|
-
|
|
327
|
-
const diff = setItemValue(value);
|
|
328
|
-
if (diff != null) {
|
|
329
|
-
doItemChange(localOptions, diff, true);
|
|
330
|
-
}
|
|
331
|
-
}}
|
|
332
|
-
renderValue={(selected) => {
|
|
333
|
-
// The text shows up
|
|
334
|
-
return localOptions
|
|
335
|
-
.filter((option) => {
|
|
336
|
-
const id = getId(option);
|
|
337
|
-
return Array.isArray(selected)
|
|
338
|
-
? selected.indexOf(id) !== -1
|
|
339
|
-
: selected === id;
|
|
340
|
-
})
|
|
341
|
-
.map((option) => getLabel(option))
|
|
342
|
-
.join(', ');
|
|
343
|
-
}}
|
|
344
|
-
sx={{ minWidth: '150px' }}
|
|
345
|
-
fullWidth={fullWidth}
|
|
346
|
-
{...rest}
|
|
347
|
-
>
|
|
348
|
-
{localOptions.map((option) => {
|
|
349
|
-
// Option id
|
|
350
|
-
const id = getId(option);
|
|
351
|
-
|
|
352
|
-
// Option label
|
|
353
|
-
const label = getLabel(option);
|
|
354
|
-
|
|
355
|
-
// Option
|
|
356
|
-
return (
|
|
357
|
-
<MenuItem
|
|
358
|
-
key={id}
|
|
359
|
-
value={id}
|
|
360
|
-
onClick={(event) => {
|
|
361
|
-
if (onItemClick) {
|
|
362
|
-
onItemClick(event, option);
|
|
363
|
-
}
|
|
364
|
-
}}
|
|
365
|
-
style={
|
|
366
|
-
itemStyle == null
|
|
367
|
-
? undefined
|
|
368
|
-
: itemStyle(option)
|
|
369
|
-
}
|
|
370
|
-
>
|
|
371
|
-
{multiple && (
|
|
372
|
-
<Checkbox
|
|
373
|
-
checked={
|
|
374
|
-
Array.isArray(valueState)
|
|
375
|
-
? valueState.includes(id)
|
|
376
|
-
: valueState === id
|
|
377
|
-
}
|
|
378
|
-
/>
|
|
379
|
-
)}
|
|
380
|
-
<ListItemText primary={label} />
|
|
381
|
-
{itemIconRenderer && (
|
|
382
|
-
<ListItemRightIcon>
|
|
383
|
-
{itemIconRenderer(option[idField])}
|
|
384
|
-
</ListItemRightIcon>
|
|
385
|
-
)}
|
|
386
|
-
</MenuItem>
|
|
387
|
-
);
|
|
388
|
-
})}
|
|
389
|
-
</Select>
|
|
390
|
-
{helperText != null && (
|
|
391
|
-
<FormHelperText>{helperText}</FormHelperText>
|
|
361
|
+
/>
|
|
362
|
+
)}
|
|
363
|
+
<ListItemText primary={label} />
|
|
364
|
+
{itemIconRenderer && (
|
|
365
|
+
<ListItemRightIcon>
|
|
366
|
+
{itemIconRenderer(option[idField])}
|
|
367
|
+
</ListItemRightIcon>
|
|
392
368
|
)}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
369
|
+
</MenuItem>
|
|
370
|
+
);
|
|
371
|
+
})}
|
|
372
|
+
</Select>
|
|
373
|
+
{helperText != null && <FormHelperText>{helperText}</FormHelperText>}
|
|
374
|
+
</FormControl>
|
|
375
|
+
{refresh != null &&
|
|
376
|
+
loadData != null &&
|
|
377
|
+
(typeof refresh === "string" ? (
|
|
378
|
+
<IconButton size="small" title={refresh} onClick={refreshData}>
|
|
379
|
+
<RefreshIcon />
|
|
380
|
+
</IconButton>
|
|
381
|
+
) : (
|
|
382
|
+
refresh
|
|
383
|
+
))}
|
|
384
|
+
</Stack>
|
|
385
|
+
);
|
|
409
386
|
}
|