@etsoo/materialui 1.0.28 → 1.0.29

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/SelectEx.d.ts CHANGED
@@ -53,6 +53,10 @@ export declare type SelectExProps<T extends object, D extends DataTypes.Keys<T>
53
53
  * Array of options.
54
54
  */
55
55
  options?: ReadonlyArray<T>;
56
+ /**
57
+ * Supports refresh label or component
58
+ */
59
+ refresh?: string | React.ReactNode;
56
60
  /**
57
61
  * Is search case?
58
62
  */
package/lib/SelectEx.js CHANGED
@@ -1,7 +1,8 @@
1
- import { Checkbox, FormControl, FormHelperText, InputLabel, ListItemText, MenuItem, OutlinedInput, Select } from '@mui/material';
1
+ import { Checkbox, FormControl, FormHelperText, IconButton, InputLabel, ListItemText, MenuItem, OutlinedInput, Select, Stack } from '@mui/material';
2
2
  import React from 'react';
3
3
  import { MUGlobal } from './MUGlobal';
4
4
  import { ListItemRightIcon } from './ListItemRightIcon';
5
+ import RefreshIcon from '@mui/icons-material/Refresh';
5
6
  import { Utils } from '@etsoo/shared';
6
7
  /**
7
8
  * Extended select component
@@ -11,7 +12,7 @@ import { Utils } from '@etsoo/shared';
11
12
  export function SelectEx(props) {
12
13
  var _a;
13
14
  // Destruct
14
- const { defaultValue, idField = 'id', error, helperText, inputRequired, itemIconRenderer, itemStyle, label, labelField = 'label', loadData, onItemChange, 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, onItemChange, onItemClick, onLoadData, multiple = false, name, options, refresh, search = false, autoAddBlankItem = search, value, onChange, fullWidth, ...rest } = props;
15
16
  // Options state
16
17
  const [localOptions, setOptions] = React.useState([]);
17
18
  const isMounted = React.useRef(true);
@@ -97,20 +98,24 @@ export function SelectEx(props) {
97
98
  };
98
99
  // Refs
99
100
  const divRef = React.useRef();
101
+ // Refresh list data
102
+ const refreshData = () => {
103
+ if (loadData == null)
104
+ return;
105
+ loadData().then((result) => {
106
+ if (result == null || !isMounted.current)
107
+ return;
108
+ if (onLoadData)
109
+ onLoadData(result);
110
+ if (autoAddBlankItem) {
111
+ Utils.addBlankItem(result, idField, labelField);
112
+ }
113
+ setOptionsAdd(result);
114
+ });
115
+ };
100
116
  // When value change
101
117
  React.useEffect(() => {
102
- if (loadData) {
103
- loadData().then((result) => {
104
- if (result == null || !isMounted.current)
105
- return;
106
- if (onLoadData)
107
- onLoadData(result);
108
- if (autoAddBlankItem) {
109
- Utils.addBlankItem(result, idField, labelField);
110
- }
111
- setOptionsAdd(result);
112
- });
113
- }
118
+ refreshData();
114
119
  }, [localValue]);
115
120
  // When layout ready
116
121
  React.useEffect(() => {
@@ -128,48 +133,53 @@ export function SelectEx(props) {
128
133
  };
129
134
  }, []);
130
135
  // Layout
131
- return (React.createElement(FormControl, { size: search ? MUGlobal.searchFieldSize : MUGlobal.inputFieldSize, fullWidth: fullWidth, error: error },
132
- React.createElement(InputLabel, { id: labelId, shrink: search
133
- ? MUGlobal.searchFieldShrink
134
- : MUGlobal.inputFieldShrink }, label),
135
- React.createElement(Select, { ref: divRef, value: localOptions.some((option) => itemChecked(getId(option)))
136
- ? valueState !== null && valueState !== void 0 ? valueState : ''
137
- : '', input: React.createElement(OutlinedInput, { notched: true, label: label, required: inputRequired }), labelId: labelId, name: name, multiple: multiple, onChange: (event, child) => {
138
- if (onChange) {
139
- onChange(event, child);
140
- // event.preventDefault() will block executing
141
- if (event.defaultPrevented)
142
- return;
143
- }
144
- doItemChange(localOptions, event.target.value, true);
145
- handleChange(event);
146
- }, renderValue: (selected) => {
147
- // The text shows up
148
- return localOptions
149
- .filter((option) => {
150
- const id = getId(option);
151
- return Array.isArray(selected)
152
- ? selected.indexOf(id) !== -1
153
- : selected === id;
154
- })
155
- .map((option) => getLabel(option))
156
- .join(', ');
157
- }, sx: { minWidth: '150px' }, fullWidth: fullWidth, ...rest }, localOptions.map((option) => {
158
- // Option id
159
- const id = getId(option);
160
- // Option label
161
- const label = getLabel(option);
162
- // Option
163
- return (React.createElement(MenuItem, { key: id, value: id, onClick: (event) => {
164
- if (onItemClick) {
165
- onItemClick(event, option);
136
+ return (React.createElement(Stack, { direction: "row" },
137
+ React.createElement(FormControl, { size: search ? MUGlobal.searchFieldSize : MUGlobal.inputFieldSize, fullWidth: fullWidth, error: error },
138
+ React.createElement(InputLabel, { id: labelId, shrink: search
139
+ ? MUGlobal.searchFieldShrink
140
+ : MUGlobal.inputFieldShrink }, label),
141
+ React.createElement(Select, { ref: divRef, value: localOptions.some((option) => itemChecked(getId(option)))
142
+ ? valueState !== null && valueState !== void 0 ? valueState : ''
143
+ : '', input: React.createElement(OutlinedInput, { notched: true, label: label, required: inputRequired }), labelId: labelId, name: name, multiple: multiple, onChange: (event, child) => {
144
+ if (onChange) {
145
+ onChange(event, child);
146
+ // event.preventDefault() will block executing
147
+ if (event.defaultPrevented)
148
+ return;
166
149
  }
167
- }, style: itemStyle == null
168
- ? undefined
169
- : itemStyle(option) },
170
- multiple && React.createElement(Checkbox, { checked: itemChecked(id) }),
171
- React.createElement(ListItemText, { primary: label }),
172
- itemIconRenderer && (React.createElement(ListItemRightIcon, null, itemIconRenderer(option[idField])))));
173
- })),
174
- helperText != null && (React.createElement(FormHelperText, null, helperText))));
150
+ doItemChange(localOptions, event.target.value, true);
151
+ handleChange(event);
152
+ }, renderValue: (selected) => {
153
+ // The text shows up
154
+ return localOptions
155
+ .filter((option) => {
156
+ const id = getId(option);
157
+ return Array.isArray(selected)
158
+ ? selected.indexOf(id) !== -1
159
+ : selected === id;
160
+ })
161
+ .map((option) => getLabel(option))
162
+ .join(', ');
163
+ }, sx: { minWidth: '150px' }, fullWidth: fullWidth, ...rest }, localOptions.map((option) => {
164
+ // Option id
165
+ const id = getId(option);
166
+ // Option label
167
+ const label = getLabel(option);
168
+ // Option
169
+ return (React.createElement(MenuItem, { key: id, value: id, onClick: (event) => {
170
+ if (onItemClick) {
171
+ onItemClick(event, option);
172
+ }
173
+ }, style: itemStyle == null
174
+ ? undefined
175
+ : itemStyle(option) },
176
+ multiple && (React.createElement(Checkbox, { checked: itemChecked(id) })),
177
+ React.createElement(ListItemText, { primary: label }),
178
+ itemIconRenderer && (React.createElement(ListItemRightIcon, null, itemIconRenderer(option[idField])))));
179
+ })),
180
+ helperText != null && (React.createElement(FormHelperText, null, helperText))),
181
+ refresh != null &&
182
+ loadData != null &&
183
+ (typeof refresh === 'string' ? (React.createElement(IconButton, { size: "small", title: refresh, onClick: refreshData },
184
+ React.createElement(RefreshIcon, null))) : (refresh))));
175
185
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.0.28",
3
+ "version": "1.0.29",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -51,15 +51,15 @@
51
51
  "@emotion/css": "^11.10.0",
52
52
  "@emotion/react": "^11.10.4",
53
53
  "@emotion/styled": "^11.10.4",
54
- "@etsoo/appscript": "^1.2.96",
54
+ "@etsoo/appscript": "^1.2.97",
55
55
  "@etsoo/notificationbase": "^1.1.7",
56
- "@etsoo/react": "^1.6.2",
57
- "@etsoo/shared": "^1.1.57",
56
+ "@etsoo/react": "^1.6.3",
57
+ "@etsoo/shared": "^1.1.58",
58
58
  "@mui/icons-material": "^5.10.6",
59
59
  "@mui/material": "^5.10.6",
60
60
  "@types/pica": "^9.0.1",
61
61
  "@types/pulltorefreshjs": "^0.1.5",
62
- "@types/react": "^18.0.20",
62
+ "@types/react": "^18.0.21",
63
63
  "@types/react-avatar-editor": "^13.0.0",
64
64
  "@types/react-dom": "^18.0.6",
65
65
  "@types/react-input-mask": "^3.0.1",
@@ -71,7 +71,7 @@
71
71
  "react-dom": "^18.2.0",
72
72
  "react-draggable": "^4.4.5",
73
73
  "react-imask": "^6.4.3",
74
- "react-router-dom": "^6.4.0",
74
+ "react-router-dom": "^6.4.1",
75
75
  "react-window": "^1.8.7"
76
76
  },
77
77
  "devDependencies": {
@@ -85,13 +85,13 @@
85
85
  "@types/jest": "^29.0.3",
86
86
  "@typescript-eslint/eslint-plugin": "^5.38.0",
87
87
  "@typescript-eslint/parser": "^5.38.0",
88
- "eslint": "^8.23.1",
88
+ "eslint": "^8.24.0",
89
89
  "eslint-config-airbnb-base": "^15.0.0",
90
90
  "eslint-plugin-import": "^2.26.0",
91
91
  "eslint-plugin-react": "^7.31.8",
92
92
  "jest": "^29.0.3",
93
93
  "jest-environment-jsdom": "^29.0.3",
94
- "ts-jest": "^29.0.1",
94
+ "ts-jest": "^29.0.2",
95
95
  "typescript": "^4.8.3"
96
96
  }
97
97
  }
package/src/SelectEx.tsx CHANGED
@@ -2,17 +2,20 @@ import {
2
2
  Checkbox,
3
3
  FormControl,
4
4
  FormHelperText,
5
+ IconButton,
5
6
  InputLabel,
6
7
  ListItemText,
7
8
  MenuItem,
8
9
  OutlinedInput,
9
10
  Select,
10
11
  SelectChangeEvent,
11
- SelectProps
12
+ SelectProps,
13
+ Stack
12
14
  } from '@mui/material';
13
15
  import React from 'react';
14
16
  import { MUGlobal } from './MUGlobal';
15
17
  import { ListItemRightIcon } from './ListItemRightIcon';
18
+ import RefreshIcon from '@mui/icons-material/Refresh';
16
19
  import {
17
20
  DataTypes,
18
21
  IdDefaultType,
@@ -89,6 +92,11 @@ export type SelectExProps<
89
92
  */
90
93
  options?: ReadonlyArray<T>;
91
94
 
95
+ /**
96
+ * Supports refresh label or component
97
+ */
98
+ refresh?: string | React.ReactNode;
99
+
92
100
  /**
93
101
  * Is search case?
94
102
  */
@@ -123,6 +131,7 @@ export function SelectEx<
123
131
  multiple = false,
124
132
  name,
125
133
  options,
134
+ refresh,
126
135
  search = false,
127
136
  autoAddBlankItem = search,
128
137
  value,
@@ -226,18 +235,22 @@ export function SelectEx<
226
235
  // Refs
227
236
  const divRef = React.useRef<HTMLDivElement>();
228
237
 
238
+ // Refresh list data
239
+ const refreshData = () => {
240
+ if (loadData == null) return;
241
+ loadData().then((result) => {
242
+ if (result == null || !isMounted.current) return;
243
+ if (onLoadData) onLoadData(result);
244
+ if (autoAddBlankItem) {
245
+ Utils.addBlankItem(result, idField, labelField);
246
+ }
247
+ setOptionsAdd(result);
248
+ });
249
+ };
250
+
229
251
  // When value change
230
252
  React.useEffect(() => {
231
- if (loadData) {
232
- loadData().then((result) => {
233
- if (result == null || !isMounted.current) return;
234
- if (onLoadData) onLoadData(result);
235
- if (autoAddBlankItem) {
236
- Utils.addBlankItem(result, idField, labelField);
237
- }
238
- setOptionsAdd(result);
239
- });
240
- }
253
+ refreshData();
241
254
  }, [localValue]);
242
255
 
243
256
  // When layout ready
@@ -257,101 +270,122 @@ export function SelectEx<
257
270
 
258
271
  // Layout
259
272
  return (
260
- <FormControl
261
- size={search ? MUGlobal.searchFieldSize : MUGlobal.inputFieldSize}
262
- fullWidth={fullWidth}
263
- error={error}
264
- >
265
- <InputLabel
266
- id={labelId}
267
- shrink={
268
- search
269
- ? MUGlobal.searchFieldShrink
270
- : MUGlobal.inputFieldShrink
273
+ <Stack direction="row">
274
+ <FormControl
275
+ size={
276
+ search ? MUGlobal.searchFieldSize : MUGlobal.inputFieldSize
271
277
  }
272
- >
273
- {label}
274
- </InputLabel>
275
- <Select
276
- ref={divRef}
277
- value={
278
- localOptions.some((option) => itemChecked(getId(option)))
279
- ? valueState ?? ''
280
- : ''
281
- }
282
- input={
283
- <OutlinedInput
284
- notched
285
- label={label}
286
- required={inputRequired}
287
- />
288
- }
289
- labelId={labelId}
290
- name={name}
291
- multiple={multiple}
292
- onChange={(event, child) => {
293
- if (onChange) {
294
- onChange(event, child);
295
-
296
- // event.preventDefault() will block executing
297
- if (event.defaultPrevented) return;
298
- }
299
- doItemChange(localOptions, event.target.value, true);
300
- handleChange(event);
301
- }}
302
- renderValue={(selected) => {
303
- // The text shows up
304
- return localOptions
305
- .filter((option) => {
306
- const id = getId(option);
307
- return Array.isArray(selected)
308
- ? selected.indexOf(id) !== -1
309
- : selected === id;
310
- })
311
- .map((option) => getLabel(option))
312
- .join(', ');
313
- }}
314
- sx={{ minWidth: '150px' }}
315
278
  fullWidth={fullWidth}
316
- {...rest}
279
+ error={error}
317
280
  >
318
- {localOptions.map((option) => {
319
- // Option id
320
- const id = getId(option);
321
-
322
- // Option label
323
- const label = getLabel(option);
324
-
325
- // Option
326
- return (
327
- <MenuItem
328
- key={id}
329
- value={id}
330
- onClick={(event) => {
331
- if (onItemClick) {
332
- onItemClick(event, option);
281
+ <InputLabel
282
+ id={labelId}
283
+ shrink={
284
+ search
285
+ ? MUGlobal.searchFieldShrink
286
+ : MUGlobal.inputFieldShrink
287
+ }
288
+ >
289
+ {label}
290
+ </InputLabel>
291
+ <Select
292
+ ref={divRef}
293
+ value={
294
+ localOptions.some((option) =>
295
+ itemChecked(getId(option))
296
+ )
297
+ ? valueState ?? ''
298
+ : ''
299
+ }
300
+ input={
301
+ <OutlinedInput
302
+ notched
303
+ label={label}
304
+ required={inputRequired}
305
+ />
306
+ }
307
+ labelId={labelId}
308
+ name={name}
309
+ multiple={multiple}
310
+ onChange={(event, child) => {
311
+ if (onChange) {
312
+ onChange(event, child);
313
+
314
+ // event.preventDefault() will block executing
315
+ if (event.defaultPrevented) return;
316
+ }
317
+ doItemChange(localOptions, event.target.value, true);
318
+ handleChange(event);
319
+ }}
320
+ renderValue={(selected) => {
321
+ // The text shows up
322
+ return localOptions
323
+ .filter((option) => {
324
+ const id = getId(option);
325
+ return Array.isArray(selected)
326
+ ? selected.indexOf(id) !== -1
327
+ : selected === id;
328
+ })
329
+ .map((option) => getLabel(option))
330
+ .join(', ');
331
+ }}
332
+ sx={{ minWidth: '150px' }}
333
+ fullWidth={fullWidth}
334
+ {...rest}
335
+ >
336
+ {localOptions.map((option) => {
337
+ // Option id
338
+ const id = getId(option);
339
+
340
+ // Option label
341
+ const label = getLabel(option);
342
+
343
+ // Option
344
+ return (
345
+ <MenuItem
346
+ key={id}
347
+ value={id}
348
+ onClick={(event) => {
349
+ if (onItemClick) {
350
+ onItemClick(event, option);
351
+ }
352
+ }}
353
+ style={
354
+ itemStyle == null
355
+ ? undefined
356
+ : itemStyle(option)
333
357
  }
334
- }}
335
- style={
336
- itemStyle == null
337
- ? undefined
338
- : itemStyle(option)
339
- }
340
- >
341
- {multiple && <Checkbox checked={itemChecked(id)} />}
342
- <ListItemText primary={label} />
343
- {itemIconRenderer && (
344
- <ListItemRightIcon>
345
- {itemIconRenderer(option[idField])}
346
- </ListItemRightIcon>
347
- )}
348
- </MenuItem>
349
- );
350
- })}
351
- </Select>
352
- {helperText != null && (
353
- <FormHelperText>{helperText}</FormHelperText>
354
- )}
355
- </FormControl>
358
+ >
359
+ {multiple && (
360
+ <Checkbox checked={itemChecked(id)} />
361
+ )}
362
+ <ListItemText primary={label} />
363
+ {itemIconRenderer && (
364
+ <ListItemRightIcon>
365
+ {itemIconRenderer(option[idField])}
366
+ </ListItemRightIcon>
367
+ )}
368
+ </MenuItem>
369
+ );
370
+ })}
371
+ </Select>
372
+ {helperText != null && (
373
+ <FormHelperText>{helperText}</FormHelperText>
374
+ )}
375
+ </FormControl>
376
+ {refresh != null &&
377
+ loadData != null &&
378
+ (typeof refresh === 'string' ? (
379
+ <IconButton
380
+ size="small"
381
+ title={refresh}
382
+ onClick={refreshData}
383
+ >
384
+ <RefreshIcon />
385
+ </IconButton>
386
+ ) : (
387
+ refresh
388
+ ))}
389
+ </Stack>
356
390
  );
357
391
  }