@etsoo/materialui 1.5.56 → 1.5.58

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.
@@ -40,7 +40,7 @@ export type ButtonPopupCheckboxProps<D extends DnDItemType> = Omit<ButtonProps,
40
40
  /**
41
41
  * Load data
42
42
  */
43
- loadData: () => Promise<D[]>;
43
+ loadData: D[] | (() => Promise<D[]>);
44
44
  /**
45
45
  * On add handler
46
46
  * @param ids Ids
@@ -36,13 +36,17 @@ function ButtonPopupList(props) {
36
36
  // Set selected ids
37
37
  setSelectedIds([...value]);
38
38
  }, [value]);
39
- return ((0, jsx_runtime_1.jsxs)(FlexBox_1.VBox, { gap: 2, children: [(0, jsx_runtime_1.jsx)(FormGroup_1.default, { children: (0, jsx_runtime_1.jsx)(Grid_1.default, { container: true, spacing: 0, children: (0, jsx_runtime_1.jsx)(DnDList_1.DnDList, { items: items, labelField: labelField, itemRenderer: (item, index, nodeRef, actionNodeRef) => ((0, jsx_runtime_1.jsxs)(Grid_1.default, { size: { xs: 12, md: 6, lg: 4 }, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, ...nodeRef, children: [(0, jsx_runtime_1.jsx)(IconButton_1.default, { style: { cursor: "move" }, size: "small", title: labels?.dragIndicator, ...actionNodeRef, children: (0, jsx_runtime_1.jsx)(DragIndicator_1.default, {}) }), (0, jsx_runtime_1.jsx)(FormControlLabel_1.default, { control: (0, jsx_runtime_1.jsx)(Checkbox_1.default, { name: "item", value: item.id, checked: selectedIds.includes(item.id), onChange: (e) => {
39
+ return ((0, jsx_runtime_1.jsxs)(FlexBox_1.VBox, { gap: 2, children: [(0, jsx_runtime_1.jsx)(FormGroup_1.default, { children: (0, jsx_runtime_1.jsx)(Grid_1.default, { container: true, spacing: 0, children: (0, jsx_runtime_1.jsx)(DnDList_1.DnDList, { items: items, labelField: labelField, onFormChange: (items) => {
40
+ const ids = items
41
+ .filter((item) => selectedIds.includes(item.id))
42
+ .map((item) => item.id);
43
+ onValueChange(ids);
44
+ }, itemRenderer: (item, index, nodeRef, actionNodeRef) => ((0, jsx_runtime_1.jsxs)(Grid_1.default, { size: { xs: 12, md: 6, lg: 4 }, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, ...nodeRef, children: [(0, jsx_runtime_1.jsx)(IconButton_1.default, { style: { cursor: "move" }, size: "small", title: labels?.dragIndicator, ...actionNodeRef, children: (0, jsx_runtime_1.jsx)(DragIndicator_1.default, {}) }), (0, jsx_runtime_1.jsx)(FormControlLabel_1.default, { control: (0, jsx_runtime_1.jsx)(Checkbox_1.default, { name: "item", value: item.id, checked: selectedIds.includes(item.id), onChange: (e) => {
40
45
  const checked = e.target.checked;
41
46
  const newIds = [
42
47
  ...selectedIds.toggleItem(item.id, checked)
43
48
  ];
44
49
  setSelectedIds(newIds);
45
- onValueChange(newIds);
46
50
  } }), label: `${index + 1}. ${labelFormatter(item)}` })] })), height: 200, mRef: dndRef }) }) }), onAdd && ((0, jsx_runtime_1.jsxs)(FlexBox_1.HBox, { gap: 1, children: [(0, jsx_runtime_1.jsx)(TextField_1.default, { variant: "outlined", label: labels?.more, fullWidth: true, inputRef: inputRef }), (0, jsx_runtime_1.jsx)(Button_1.default, { sx: { width: "120px" }, variant: "contained", startIcon: (0, jsx_runtime_1.jsx)(Add_1.default, {}), size: "small", onClick: async () => {
47
51
  if (inputRef.current == null)
48
52
  return;
@@ -90,12 +94,17 @@ function ButtonPopupCheckbox(props) {
90
94
  const [items, setItems] = react_1.default.useState([]);
91
95
  const [selectedIds, setSelectedIds] = react_1.default.useState();
92
96
  react_1.default.useEffect(() => {
93
- // Load data
94
- loadData().then((data) => {
95
- if (data != null) {
96
- setItems(data);
97
- }
98
- });
97
+ if (typeof loadData === "function") {
98
+ // Load data
99
+ loadData().then((data) => {
100
+ if (data != null) {
101
+ setItems(data);
102
+ }
103
+ });
104
+ }
105
+ else {
106
+ setItems(loadData);
107
+ }
99
108
  }, [loadData]);
100
109
  react_1.default.useEffect(() => {
101
110
  // Set selected ids
@@ -40,7 +40,7 @@ export type ButtonPopupRadioProps<D extends DnDItemType> = Omit<ButtonProps, "ch
40
40
  /**
41
41
  * Load data
42
42
  */
43
- loadData: () => Promise<D[]>;
43
+ loadData: D[] | (() => Promise<D[]>);
44
44
  /**
45
45
  * On add handler
46
46
  * @param ids Ids
@@ -86,12 +86,17 @@ function ButtonPopupRadio(props) {
86
86
  ? items.find((item) => item.id === currentValue)
87
87
  : undefined;
88
88
  react_1.default.useEffect(() => {
89
- // Load data
90
- loadData().then((data) => {
91
- if (data != null) {
92
- setItems(data);
93
- }
94
- });
89
+ if (typeof loadData === "function") {
90
+ // Load data
91
+ loadData().then((data) => {
92
+ if (data != null) {
93
+ setItems(data);
94
+ }
95
+ });
96
+ }
97
+ else {
98
+ setItems(loadData);
99
+ }
95
100
  }, [loadData]);
96
101
  react_1.default.useEffect(() => {
97
102
  setCurrentValue(value);
@@ -152,6 +152,17 @@ function DnDList(props) {
152
152
  ]);
153
153
  });
154
154
  }, []);
155
+ const divRef = react_1.default.useRef(null);
156
+ react_1.default.useEffect(() => {
157
+ if (divRef.current) {
158
+ setupDiv(divRef.current);
159
+ }
160
+ return () => {
161
+ if (divRef.current) {
162
+ setupDiv(divRef.current, true);
163
+ }
164
+ };
165
+ }, []);
155
166
  if (dnd == null) {
156
167
  return (0, jsx_runtime_1.jsx)(Skeleton_1.default, { variant: "rectangular", width: "100%", height: height });
157
168
  }
@@ -195,29 +206,33 @@ function DnDList(props) {
195
206
  }
196
207
  setActiveId(undefined);
197
208
  }
198
- const setupDiv = (div) => {
209
+ const doChange = react_1.default.useCallback(() => doFormChange(), []);
210
+ const setupDiv = (div, clearup = false) => {
199
211
  // Inputs
200
212
  div
201
213
  .querySelectorAll("input")
202
- .forEach((input) => input.addEventListener("change", () => doFormChange()));
214
+ .forEach((input) => clearup
215
+ ? input.removeEventListener("change", doChange)
216
+ : input.addEventListener("change", doChange));
203
217
  // Textareas
204
218
  div
205
219
  .querySelectorAll("textarea")
206
- .forEach((input) => input.addEventListener("change", () => doFormChange()));
220
+ .forEach((input) => clearup
221
+ ? input.removeEventListener("change", doChange)
222
+ : input.addEventListener("change", doChange));
207
223
  // Select
208
224
  div
209
225
  .querySelectorAll("select")
210
- .forEach((input) => input.addEventListener("change", () => doFormChange()));
226
+ .forEach((input) => clearup
227
+ ? input.removeEventListener("change", doChange)
228
+ : input.addEventListener("change", doChange));
211
229
  };
212
230
  const children = ((0, jsx_runtime_1.jsx)(DndContextType, { onDragStart: handleDragStart, onDragEnd: handleDragEnd, children: (0, jsx_runtime_1.jsx)(SortableContextType, { items: items, strategy: strategy, children: items.map((item, index) => {
213
231
  const id = item.id;
214
232
  return ((0, jsx_runtime_1.jsx)(SortableItem, { id: id, useSortableType: useSortableType, CSSType: CSSType, style: getItemStyle(index, id === activeId), itemRenderer: (nodeRef, actionNodeRef) => itemRenderer(item, index, nodeRef, actionNodeRef) }, id));
215
233
  }) }) }));
216
234
  if (onFormChange) {
217
- return ((0, jsx_runtime_1.jsx)("div", { style: { width: "100%" }, ref: (div) => {
218
- if (div)
219
- setupDiv(div);
220
- }, children: children }));
235
+ return ((0, jsx_runtime_1.jsx)("div", { style: { width: "100%" }, ref: divRef, children: children }));
221
236
  }
222
237
  return children;
223
238
  }
@@ -40,7 +40,7 @@ export type ButtonPopupCheckboxProps<D extends DnDItemType> = Omit<ButtonProps,
40
40
  /**
41
41
  * Load data
42
42
  */
43
- loadData: () => Promise<D[]>;
43
+ loadData: D[] | (() => Promise<D[]>);
44
44
  /**
45
45
  * On add handler
46
46
  * @param ids Ids
@@ -30,13 +30,17 @@ function ButtonPopupList(props) {
30
30
  // Set selected ids
31
31
  setSelectedIds([...value]);
32
32
  }, [value]);
33
- return (_jsxs(VBox, { gap: 2, children: [_jsx(FormGroup, { children: _jsx(Grid, { container: true, spacing: 0, children: _jsx(DnDList, { items: items, labelField: labelField, itemRenderer: (item, index, nodeRef, actionNodeRef) => (_jsxs(Grid, { size: { xs: 12, md: 6, lg: 4 }, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, ...nodeRef, children: [_jsx(IconButton, { style: { cursor: "move" }, size: "small", title: labels?.dragIndicator, ...actionNodeRef, children: _jsx(DragIndicatorIcon, {}) }), _jsx(FormControlLabel, { control: _jsx(Checkbox, { name: "item", value: item.id, checked: selectedIds.includes(item.id), onChange: (e) => {
33
+ return (_jsxs(VBox, { gap: 2, children: [_jsx(FormGroup, { children: _jsx(Grid, { container: true, spacing: 0, children: _jsx(DnDList, { items: items, labelField: labelField, onFormChange: (items) => {
34
+ const ids = items
35
+ .filter((item) => selectedIds.includes(item.id))
36
+ .map((item) => item.id);
37
+ onValueChange(ids);
38
+ }, itemRenderer: (item, index, nodeRef, actionNodeRef) => (_jsxs(Grid, { size: { xs: 12, md: 6, lg: 4 }, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, ...nodeRef, children: [_jsx(IconButton, { style: { cursor: "move" }, size: "small", title: labels?.dragIndicator, ...actionNodeRef, children: _jsx(DragIndicatorIcon, {}) }), _jsx(FormControlLabel, { control: _jsx(Checkbox, { name: "item", value: item.id, checked: selectedIds.includes(item.id), onChange: (e) => {
34
39
  const checked = e.target.checked;
35
40
  const newIds = [
36
41
  ...selectedIds.toggleItem(item.id, checked)
37
42
  ];
38
43
  setSelectedIds(newIds);
39
- onValueChange(newIds);
40
44
  } }), label: `${index + 1}. ${labelFormatter(item)}` })] })), height: 200, mRef: dndRef }) }) }), onAdd && (_jsxs(HBox, { gap: 1, children: [_jsx(TextField, { variant: "outlined", label: labels?.more, fullWidth: true, inputRef: inputRef }), _jsx(Button, { sx: { width: "120px" }, variant: "contained", startIcon: _jsx(AddIcon, {}), size: "small", onClick: async () => {
41
45
  if (inputRef.current == null)
42
46
  return;
@@ -84,12 +88,17 @@ export function ButtonPopupCheckbox(props) {
84
88
  const [items, setItems] = React.useState([]);
85
89
  const [selectedIds, setSelectedIds] = React.useState();
86
90
  React.useEffect(() => {
87
- // Load data
88
- loadData().then((data) => {
89
- if (data != null) {
90
- setItems(data);
91
- }
92
- });
91
+ if (typeof loadData === "function") {
92
+ // Load data
93
+ loadData().then((data) => {
94
+ if (data != null) {
95
+ setItems(data);
96
+ }
97
+ });
98
+ }
99
+ else {
100
+ setItems(loadData);
101
+ }
93
102
  }, [loadData]);
94
103
  React.useEffect(() => {
95
104
  // Set selected ids
@@ -40,7 +40,7 @@ export type ButtonPopupRadioProps<D extends DnDItemType> = Omit<ButtonProps, "ch
40
40
  /**
41
41
  * Load data
42
42
  */
43
- loadData: () => Promise<D[]>;
43
+ loadData: D[] | (() => Promise<D[]>);
44
44
  /**
45
45
  * On add handler
46
46
  * @param ids Ids
@@ -80,12 +80,17 @@ export function ButtonPopupRadio(props) {
80
80
  ? items.find((item) => item.id === currentValue)
81
81
  : undefined;
82
82
  React.useEffect(() => {
83
- // Load data
84
- loadData().then((data) => {
85
- if (data != null) {
86
- setItems(data);
87
- }
88
- });
83
+ if (typeof loadData === "function") {
84
+ // Load data
85
+ loadData().then((data) => {
86
+ if (data != null) {
87
+ setItems(data);
88
+ }
89
+ });
90
+ }
91
+ else {
92
+ setItems(loadData);
93
+ }
89
94
  }, [loadData]);
90
95
  React.useEffect(() => {
91
96
  setCurrentValue(value);
@@ -144,6 +144,17 @@ export function DnDList(props) {
144
144
  ]);
145
145
  });
146
146
  }, []);
147
+ const divRef = React.useRef(null);
148
+ React.useEffect(() => {
149
+ if (divRef.current) {
150
+ setupDiv(divRef.current);
151
+ }
152
+ return () => {
153
+ if (divRef.current) {
154
+ setupDiv(divRef.current, true);
155
+ }
156
+ };
157
+ }, []);
147
158
  if (dnd == null) {
148
159
  return _jsx(Skeleton, { variant: "rectangular", width: "100%", height: height });
149
160
  }
@@ -187,29 +198,33 @@ export function DnDList(props) {
187
198
  }
188
199
  setActiveId(undefined);
189
200
  }
190
- const setupDiv = (div) => {
201
+ const doChange = React.useCallback(() => doFormChange(), []);
202
+ const setupDiv = (div, clearup = false) => {
191
203
  // Inputs
192
204
  div
193
205
  .querySelectorAll("input")
194
- .forEach((input) => input.addEventListener("change", () => doFormChange()));
206
+ .forEach((input) => clearup
207
+ ? input.removeEventListener("change", doChange)
208
+ : input.addEventListener("change", doChange));
195
209
  // Textareas
196
210
  div
197
211
  .querySelectorAll("textarea")
198
- .forEach((input) => input.addEventListener("change", () => doFormChange()));
212
+ .forEach((input) => clearup
213
+ ? input.removeEventListener("change", doChange)
214
+ : input.addEventListener("change", doChange));
199
215
  // Select
200
216
  div
201
217
  .querySelectorAll("select")
202
- .forEach((input) => input.addEventListener("change", () => doFormChange()));
218
+ .forEach((input) => clearup
219
+ ? input.removeEventListener("change", doChange)
220
+ : input.addEventListener("change", doChange));
203
221
  };
204
222
  const children = (_jsx(DndContextType, { onDragStart: handleDragStart, onDragEnd: handleDragEnd, children: _jsx(SortableContextType, { items: items, strategy: strategy, children: items.map((item, index) => {
205
223
  const id = item.id;
206
224
  return (_jsx(SortableItem, { id: id, useSortableType: useSortableType, CSSType: CSSType, style: getItemStyle(index, id === activeId), itemRenderer: (nodeRef, actionNodeRef) => itemRenderer(item, index, nodeRef, actionNodeRef) }, id));
207
225
  }) }) }));
208
226
  if (onFormChange) {
209
- return (_jsx("div", { style: { width: "100%" }, ref: (div) => {
210
- if (div)
211
- setupDiv(div);
212
- }, children: children }));
227
+ return (_jsx("div", { style: { width: "100%" }, ref: divRef, children: children }));
213
228
  }
214
229
  return children;
215
230
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.5.56",
3
+ "version": "1.5.58",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -40,7 +40,7 @@
40
40
  "@dnd-kit/sortable": "^10.0.0",
41
41
  "@emotion/react": "^11.14.0",
42
42
  "@emotion/styled": "^11.14.0",
43
- "@etsoo/appscript": "^1.6.36",
43
+ "@etsoo/appscript": "^1.6.38",
44
44
  "@etsoo/notificationbase": "^1.1.62",
45
45
  "@etsoo/react": "^1.8.45",
46
46
  "@etsoo/shared": "^1.2.74",
@@ -67,7 +67,7 @@ export type ButtonPopupCheckboxProps<D extends DnDItemType> = Omit<
67
67
  /**
68
68
  * Load data
69
69
  */
70
- loadData: () => Promise<D[]>;
70
+ loadData: D[] | (() => Promise<D[]>);
71
71
 
72
72
  /**
73
73
  * On add handler
@@ -158,6 +158,12 @@ function ButtonPopupList<D extends DnDItemType>(
158
158
  <DnDList<D>
159
159
  items={items}
160
160
  labelField={labelField}
161
+ onFormChange={(items) => {
162
+ const ids = items
163
+ .filter((item) => selectedIds.includes(item.id))
164
+ .map((item) => item.id);
165
+ onValueChange(ids);
166
+ }}
161
167
  itemRenderer={(item, index, nodeRef, actionNodeRef) => (
162
168
  <Grid
163
169
  size={{ xs: 12, md: 6, lg: 4 }}
@@ -187,7 +193,6 @@ function ButtonPopupList<D extends DnDItemType>(
187
193
  ...selectedIds.toggleItem(item.id, checked)
188
194
  ];
189
195
  setSelectedIds(newIds);
190
- onValueChange(newIds);
191
196
  }}
192
197
  />
193
198
  }
@@ -296,12 +301,16 @@ export function ButtonPopupCheckbox<D extends DnDItemType>(
296
301
  const [selectedIds, setSelectedIds] = React.useState<D["id"][]>();
297
302
 
298
303
  React.useEffect(() => {
299
- // Load data
300
- loadData().then((data) => {
301
- if (data != null) {
302
- setItems(data);
303
- }
304
- });
304
+ if (typeof loadData === "function") {
305
+ // Load data
306
+ loadData().then((data) => {
307
+ if (data != null) {
308
+ setItems(data);
309
+ }
310
+ });
311
+ } else {
312
+ setItems(loadData);
313
+ }
305
314
  }, [loadData]);
306
315
 
307
316
  React.useEffect(() => {
@@ -64,7 +64,7 @@ export type ButtonPopupRadioProps<D extends DnDItemType> = Omit<
64
64
  /**
65
65
  * Load data
66
66
  */
67
- loadData: () => Promise<D[]>;
67
+ loadData: D[] | (() => Promise<D[]>);
68
68
 
69
69
  /**
70
70
  * On add handler
@@ -270,12 +270,16 @@ export function ButtonPopupRadio<D extends DnDItemType>(
270
270
  : undefined;
271
271
 
272
272
  React.useEffect(() => {
273
- // Load data
274
- loadData().then((data) => {
275
- if (data != null) {
276
- setItems(data);
277
- }
278
- });
273
+ if (typeof loadData === "function") {
274
+ // Load data
275
+ loadData().then((data) => {
276
+ if (data != null) {
277
+ setItems(data);
278
+ }
279
+ });
280
+ } else {
281
+ setItems(loadData);
282
+ }
279
283
  }, [loadData]);
280
284
 
281
285
  React.useEffect(() => {
package/src/DnDList.tsx CHANGED
@@ -362,6 +362,20 @@ export function DnDList<D extends { id: UniqueIdentifier }>(
362
362
  );
363
363
  }, []);
364
364
 
365
+ const divRef = React.useRef<HTMLDivElement>(null);
366
+
367
+ React.useEffect(() => {
368
+ if (divRef.current) {
369
+ setupDiv(divRef.current);
370
+ }
371
+
372
+ return () => {
373
+ if (divRef.current) {
374
+ setupDiv(divRef.current, true);
375
+ }
376
+ };
377
+ }, []);
378
+
365
379
  if (dnd == null) {
366
380
  return <Skeleton variant="rectangular" width="100%" height={height} />;
367
381
  }
@@ -428,26 +442,34 @@ export function DnDList<D extends { id: UniqueIdentifier }>(
428
442
  setActiveId(undefined);
429
443
  }
430
444
 
431
- const setupDiv = (div: HTMLDivElement) => {
445
+ const doChange = React.useCallback(() => doFormChange(), []);
446
+
447
+ const setupDiv = (div: HTMLDivElement, clearup: boolean = false) => {
432
448
  // Inputs
433
449
  div
434
450
  .querySelectorAll("input")
435
451
  .forEach((input) =>
436
- input.addEventListener("change", () => doFormChange())
452
+ clearup
453
+ ? input.removeEventListener("change", doChange)
454
+ : input.addEventListener("change", doChange)
437
455
  );
438
456
 
439
457
  // Textareas
440
458
  div
441
459
  .querySelectorAll("textarea")
442
460
  .forEach((input) =>
443
- input.addEventListener("change", () => doFormChange())
461
+ clearup
462
+ ? input.removeEventListener("change", doChange)
463
+ : input.addEventListener("change", doChange)
444
464
  );
445
465
 
446
466
  // Select
447
467
  div
448
468
  .querySelectorAll("select")
449
469
  .forEach((input) =>
450
- input.addEventListener("change", () => doFormChange())
470
+ clearup
471
+ ? input.removeEventListener("change", doChange)
472
+ : input.addEventListener("change", doChange)
451
473
  );
452
474
  };
453
475
 
@@ -475,12 +497,7 @@ export function DnDList<D extends { id: UniqueIdentifier }>(
475
497
 
476
498
  if (onFormChange) {
477
499
  return (
478
- <div
479
- style={{ width: "100%" }}
480
- ref={(div) => {
481
- if (div) setupDiv(div);
482
- }}
483
- >
500
+ <div style={{ width: "100%" }} ref={divRef}>
484
501
  {children}
485
502
  </div>
486
503
  );