@wavemaker-ai/react-runtime 1.0.0-rc.326 → 1.0.0-rc.328

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 (80) hide show
  1. package/components/basic/icon/index.js +36 -5
  2. package/components/basic/iframe/index.js +18 -8
  3. package/components/basic/label/index.js +4 -3
  4. package/components/basic/search/index.d.ts +72 -3
  5. package/components/basic/search/index.js +75 -21
  6. package/components/basic/search/props.d.ts +4 -0
  7. package/components/common/WmAppIcon/index.js +11 -8
  8. package/components/common/WmAppIcon/props.d.ts +2 -0
  9. package/components/container/accordion/accordion-pane/index.d.ts +1 -0
  10. package/components/container/accordion/accordion-pane/index.js +7 -3
  11. package/components/container/accordion/accordion-pane/props.d.ts +1 -0
  12. package/components/container/index.js +13 -5
  13. package/components/container/panel/components/panel-header/index.js +1 -3
  14. package/components/container/tabs/tab-pane/index.d.ts +1 -0
  15. package/components/container/tabs/tab-pane/index.js +2 -2
  16. package/components/container/tabs/tab-pane/props.d.ts +1 -0
  17. package/components/container/wizard/index.js +11 -10
  18. package/components/container/wizard/utils.js +1 -0
  19. package/components/data/form/dynamic-fields/WmxDynamicFormField.d.ts +11 -0
  20. package/components/data/form/dynamic-fields/WmxDynamicFormField.js +77 -0
  21. package/components/data/form/dynamic-fields/index.js +12 -1
  22. package/components/data/form/form-controller/withFormController.js +0 -14
  23. package/components/data/form/form-field/index.js +10 -7
  24. package/components/data/list/index.js +3 -2
  25. package/components/data/table/components/RowCells.js +3 -1
  26. package/components/data/table/components/TableHeader.js +5 -1
  27. package/components/data/table/hooks/useRowHandlers.d.ts +4 -2
  28. package/components/data/table/hooks/useRowHandlers.js +23 -11
  29. package/components/data/table/hooks/useRowSelection.d.ts +1 -1
  30. package/components/data/table/hooks/useRowSelection.js +80 -66
  31. package/components/data/table/hooks/useTableState.js +14 -2
  32. package/components/data/table/index.js +52 -48
  33. package/components/data/table/props.d.ts +4 -0
  34. package/components/data/table/utils/buildSelectionColumns.js +2 -2
  35. package/components/data/table/utils/columnBuilder.js +1 -1
  36. package/components/data/table/utils/index.d.ts +9 -1
  37. package/components/data/table/utils/index.js +15 -1
  38. package/components/data/table/utils/selectionUtils.d.ts +5 -0
  39. package/components/data/table/utils/selectionUtils.js +5 -0
  40. package/components/dialogs/dialog-header/index.js +1 -1
  41. package/components/dialogs/index.js +14 -2
  42. package/components/input/chips/index.js +29 -5
  43. package/components/input/color-picker/index.js +4 -6
  44. package/components/input/epoch/date/index.js +1 -1
  45. package/components/input/select/index.js +3 -4
  46. package/components/input/text/index.js +2 -2
  47. package/components/input/textarea/index.js +41 -16
  48. package/components/navbar/nav/index.js +10 -5
  49. package/components/navigation/breadcrumb/index.js +2 -1
  50. package/components/navigation/popover/index.js +9 -1
  51. package/components/page/page-content/index.js +24 -4
  52. package/components/page/page-content/props.d.ts +1 -0
  53. package/components/page/partial-container/index.js +1 -1
  54. package/components/wmx/WmxRenderer.d.ts +8 -0
  55. package/components/wmx/WmxRenderer.js +57 -0
  56. package/core/appstore.js +1 -1
  57. package/core/util/index.d.ts +0 -2
  58. package/core/util/index.js +0 -29
  59. package/higherOrder/BasePage.js +24 -63
  60. package/higherOrder/DataNav.js +4 -1
  61. package/hooks/useHttp.js +4 -2
  62. package/hooks/useLayoutSize.js +1 -1
  63. package/package-lock.json +196 -552
  64. package/package.json +3 -3
  65. package/runtime-dynamic/app-initializer.js +2 -1
  66. package/runtime-dynamic/components/partial-content.js +2 -1
  67. package/runtime-dynamic/components/wmx-placeholder.d.ts +18 -0
  68. package/runtime-dynamic/components/wmx-placeholder.js +48 -0
  69. package/runtime-dynamic/main.js +6 -0
  70. package/runtime-dynamic/services/compile-render.js +75 -12
  71. package/store/slices/i18nSlice.d.ts +0 -1
  72. package/store/slices/i18nSlice.js +0 -2
  73. package/utils/layoutsize-util.js +12 -7
  74. package/utils/style-utils.d.ts +6 -0
  75. package/utils/style-utils.js +10 -0
  76. package/utils/wmx.utils.d.ts +6 -0
  77. package/utils/wmx.utils.js +41 -0
  78. package/variables/crud-variable.js +1 -1
  79. package/variables/live-variable.js +1 -1
  80. package/variables/service-variable.js +6 -3
@@ -3,10 +3,19 @@ import {
3
3
  isInteractiveElement,
4
4
  getRowIdsFromDataset,
5
5
  rowExistsInDataset,
6
- selectionStateHelpers
6
+ selectionStateHelpers,
7
+ getWidgetForCallback
7
8
  } from "../utils/selectionUtils";
8
9
  import { saveTableState, getTableState } from "../utils/table-helpers";
9
10
  import { cleanRowData, UNSUPPORTED_STATE_PERSISTENCE_TYPES } from "../utils";
11
+ const getRowFallbackId = (row) => row._wmTableRowId || String(row.id) || String(0);
12
+ const getSelectedIndices = (selectedIds, dataset) => selectedIds.reduce((indices, rowId) => {
13
+ const index = dataset.findIndex((row) => row._wmTableRowId === rowId || row.id === rowId);
14
+ if (index >= 0) {
15
+ indices.push(index);
16
+ }
17
+ return indices;
18
+ }, []);
10
19
  const useRowSelection = ({
11
20
  radioselect = false,
12
21
  multiselect = false,
@@ -21,6 +30,8 @@ const useRowSelection = ({
21
30
  onRowdeselect,
22
31
  listener,
23
32
  navigation = "Basic",
33
+ viewParent,
34
+ widgetRegistrationKey,
24
35
  onSyncSelectedItems
25
36
  }) => {
26
37
  const datasetRef = useRef(internalDataset);
@@ -31,22 +42,36 @@ const useRowSelection = ({
31
42
  const [updateTrigger, forceUpdate] = useState({});
32
43
  const useMultiSelect = multiselect;
33
44
  const useRadioSelect = radioselect && !multiselect;
34
- const hasSelectionMode = useRadioSelect || useMultiSelect;
45
+ const prevMultiselectRef = useRef(multiselect);
46
+ useEffect(() => {
47
+ const prev = prevMultiselectRef.current;
48
+ prevMultiselectRef.current = multiselect;
49
+ if (prev === multiselect) return;
50
+ selectionStateHelpers.clearSelection(cellState);
51
+ forceUpdate({});
52
+ onSyncSelectedItems == null ? void 0 : onSyncSelectedItems([]);
53
+ if (statehandler && getTableCurrentState) {
54
+ saveTableState(name, statehandler, {});
55
+ }
56
+ }, [multiselect, cellState, onSyncSelectedItems, statehandler, name, getTableCurrentState]);
57
+ const applySelectionForMode = useCallback(
58
+ (rowIds) => {
59
+ if (rowIds.length === 0) return;
60
+ if (useMultiSelect) {
61
+ rowIds.forEach((rowId) => selectionStateHelpers.addToSelection(cellState, rowId));
62
+ } else {
63
+ selectionStateHelpers.setSelection(cellState, rowIds[0]);
64
+ }
65
+ },
66
+ [useMultiSelect, cellState]
67
+ );
35
68
  const saveStateImmediate = useCallback(() => {
36
69
  if (!statehandler || !getTableCurrentState) {
37
70
  return;
38
71
  }
39
72
  const { currentPage, currentPageSize } = getTableCurrentState();
40
73
  const selectedIds = selectionStateHelpers.getSelection(cellState);
41
- const selectedIndices = [];
42
- selectedIds.forEach((rowId) => {
43
- const index = internalDataset.findIndex(
44
- (row) => row._wmTableRowId === rowId || row.id === rowId
45
- );
46
- if (index >= 0) {
47
- selectedIndices.push(index);
48
- }
49
- });
74
+ const selectedIndices = getSelectedIndices(selectedIds, internalDataset);
50
75
  const selectedItemsWithPage = selectedIndices.map((idx) => ({
51
76
  page: currentPage,
52
77
  index: idx
@@ -91,19 +116,35 @@ const useRowSelection = ({
91
116
  internalDataset,
92
117
  initialActualPageSize
93
118
  ]);
94
- const getWidgetRef = useCallback(() => {
95
- var _a;
96
- return (_a = listener == null ? void 0 : listener.Widgets) == null ? void 0 : _a[name];
97
- }, [name]);
119
+ const widgetKey = widgetRegistrationKey != null ? widgetRegistrationKey : name;
120
+ const getWidgetRef = useCallback(
121
+ () => getWidgetForCallback(listener, viewParent, widgetKey),
122
+ [viewParent, widgetKey]
123
+ );
124
+ const syncSelectionToWidget = useCallback(
125
+ (selectedIds) => {
126
+ const ids = selectedIds != null ? selectedIds : selectionStateHelpers.getSelection(cellState);
127
+ onSyncSelectedItems == null ? void 0 : onSyncSelectedItems(ids);
128
+ },
129
+ [onSyncSelectedItems, cellState]
130
+ );
131
+ const commitSelectionChange = useCallback(
132
+ (syncIds) => {
133
+ forceUpdate({});
134
+ saveStateImmediate();
135
+ syncSelectionToWidget(syncIds);
136
+ },
137
+ [saveStateImmediate, syncSelectionToWidget]
138
+ );
98
139
  const triggerSelectionCallback = useCallback(
99
140
  (event, rowData, callback) => {
100
141
  if (callback && rowData) {
101
- onSyncSelectedItems == null ? void 0 : onSyncSelectedItems(selectionStateHelpers.getSelection(cellState));
142
+ const widget = getWidgetRef();
102
143
  const cleanedRow = cleanRowData([rowData])[0];
103
- callback(event, getWidgetRef(), cleanedRow);
144
+ callback(event, widget, cleanedRow);
104
145
  }
105
146
  },
106
- [getWidgetRef, onSyncSelectedItems, cellState]
147
+ [getWidgetRef]
107
148
  );
108
149
  const handleRadioSelection = useCallback(
109
150
  (rowId, rowData) => {
@@ -116,8 +157,7 @@ const useRowSelection = ({
116
157
  );
117
158
  }
118
159
  selectionStateHelpers.setSelection(cellState, rowId);
119
- forceUpdate({});
120
- saveStateImmediate();
160
+ commitSelectionChange();
121
161
  if (previousRowData) {
122
162
  triggerSelectionCallback(null, previousRowData, onRowdeselect);
123
163
  }
@@ -125,7 +165,7 @@ const useRowSelection = ({
125
165
  },
126
166
  [
127
167
  cellState,
128
- saveStateImmediate,
168
+ commitSelectionChange,
129
169
  onRowselect,
130
170
  onRowdeselect,
131
171
  internalDataset,
@@ -139,11 +179,10 @@ const useRowSelection = ({
139
179
  } else {
140
180
  selectionStateHelpers.removeFromSelection(cellState, rowId);
141
181
  }
142
- forceUpdate({});
143
- saveStateImmediate();
182
+ commitSelectionChange();
144
183
  triggerSelectionCallback(null, rowData, isSelected ? onRowselect : onRowdeselect);
145
184
  },
146
- [cellState, saveStateImmediate, onRowselect, onRowdeselect, triggerSelectionCallback]
185
+ [cellState, commitSelectionChange, onRowselect, onRowdeselect, triggerSelectionCallback]
147
186
  );
148
187
  const handleSelectAll = useCallback(
149
188
  (isSelected) => {
@@ -154,9 +193,7 @@ const useRowSelection = ({
154
193
  } else {
155
194
  selectionStateHelpers.clearSelection(cellState);
156
195
  }
157
- forceUpdate({});
158
- saveStateImmediate();
159
- onSyncSelectedItems == null ? void 0 : onSyncSelectedItems(newIds);
196
+ commitSelectionChange(newIds);
160
197
  const rows = datasetRef.current;
161
198
  const callback = isSelected ? onRowselect : onRowdeselect;
162
199
  if (callback && rows.length > 0) {
@@ -166,7 +203,7 @@ const useRowSelection = ({
166
203
  });
167
204
  }
168
205
  },
169
- [cellState, saveStateImmediate, onSyncSelectedItems, onRowselect, onRowdeselect, getWidgetRef]
206
+ [cellState, commitSelectionChange, onRowselect, onRowdeselect, getWidgetRef]
170
207
  );
171
208
  const handleRowSelectionClick = useCallback(
172
209
  (event, rowId, rowData) => {
@@ -177,20 +214,18 @@ const useRowSelection = ({
177
214
  const isCurrentlySelected = selectionStateHelpers.isRowSelected(cellState, rowId);
178
215
  const willBeSelected = !isCurrentlySelected;
179
216
  selectionStateHelpers.toggleSelection(cellState, rowId);
180
- forceUpdate({});
181
- saveStateImmediate();
217
+ commitSelectionChange();
182
218
  triggerSelectionCallback(event, rowData, willBeSelected ? onRowselect : onRowdeselect);
183
219
  return true;
184
- } else {
185
- handleRadioSelection(rowId, rowData);
186
- return true;
187
220
  }
221
+ handleRadioSelection(rowId, rowData);
222
+ return true;
188
223
  },
189
224
  [
190
225
  useMultiSelect,
191
226
  handleRadioSelection,
192
227
  cellState,
193
- saveStateImmediate,
228
+ commitSelectionChange,
194
229
  triggerSelectionCallback,
195
230
  onRowselect,
196
231
  onRowdeselect
@@ -202,26 +237,22 @@ const useRowSelection = ({
202
237
  }
203
238
  if (gridfirstrowselect && internalDataset.length > 0) {
204
239
  const firstRowData = internalDataset[0];
205
- const firstRowId = firstRowData._wmTableRowId || String(firstRowData.id) || String(0);
240
+ const firstRowId = getRowFallbackId(firstRowData);
206
241
  const currentSelection = selectionStateHelpers.getSelection(cellState);
207
242
  if (currentSelection.length === 0) {
208
- if (useMultiSelect) {
209
- selectionStateHelpers.addToSelection(cellState, firstRowId);
210
- } else {
211
- selectionStateHelpers.setSelection(cellState, firstRowId);
212
- }
243
+ applySelectionForMode([firstRowId]);
213
244
  forceUpdate({});
214
245
  initialSelectionDoneRef.current = true;
215
246
  } else if (!useMultiSelect) {
216
247
  const selectedId = currentSelection[0];
217
248
  if (!rowExistsInDataset(selectedId, internalDataset)) {
218
- selectionStateHelpers.setSelection(cellState, firstRowId);
249
+ applySelectionForMode([firstRowId]);
219
250
  forceUpdate({});
220
251
  initialSelectionDoneRef.current = true;
221
252
  }
222
253
  }
223
254
  }
224
- }, [gridfirstrowselect, internalDataset, useMultiSelect, cellState]);
255
+ }, [gridfirstrowselect, internalDataset, useMultiSelect, cellState, applySelectionForMode]);
225
256
  useEffect(() => {
226
257
  var _a;
227
258
  if (!gridfirstrowselect || internalDataset.length === 0 || !initialSelectionDoneRef.current) {
@@ -239,12 +270,8 @@ const useRowSelection = ({
239
270
  );
240
271
  if (!hasSelectionInCurrentPage) {
241
272
  const firstRowData = internalDataset[0];
242
- const firstRowId = firstRowData._wmTableRowId || String(firstRowData.id) || String(0);
243
- if (useMultiSelect) {
244
- selectionStateHelpers.addToSelection(cellState, firstRowId);
245
- } else {
246
- selectionStateHelpers.setSelection(cellState, firstRowId);
247
- }
273
+ const firstRowId = getRowFallbackId(firstRowData);
274
+ applySelectionForMode([firstRowId]);
248
275
  forceUpdate({});
249
276
  if (onRowselect) {
250
277
  triggerSelectionCallback(null, firstRowData, onRowselect);
@@ -259,7 +286,8 @@ const useRowSelection = ({
259
286
  name,
260
287
  statehandler,
261
288
  onRowselect,
262
- triggerSelectionCallback
289
+ triggerSelectionCallback,
290
+ applySelectionForMode
263
291
  ]);
264
292
  const isRowSelected = useCallback(
265
293
  (rowId) => {
@@ -302,23 +330,8 @@ const useRowSelection = ({
302
330
  if (!isAlreadyRestored && expectedRowIds.length > 0) {
303
331
  if (useMultiSelect) {
304
332
  selectionStateHelpers.clearSelection(cellState);
305
- currentPageSelections.forEach((index) => {
306
- if (index >= 0 && index < internalDataset.length) {
307
- const row = internalDataset[index];
308
- if (row && row._wmTableRowId) {
309
- selectionStateHelpers.addToSelection(cellState, row._wmTableRowId);
310
- }
311
- }
312
- });
313
- } else {
314
- const firstIndex = currentPageSelections[0];
315
- if (firstIndex >= 0 && firstIndex < internalDataset.length) {
316
- const row = internalDataset[firstIndex];
317
- if (row && row._wmTableRowId) {
318
- selectionStateHelpers.setSelection(cellState, row._wmTableRowId);
319
- }
320
- }
321
333
  }
334
+ applySelectionForMode(expectedRowIds);
322
335
  forceUpdate({});
323
336
  }
324
337
  }
@@ -329,7 +342,8 @@ const useRowSelection = ({
329
342
  navigation,
330
343
  internalDataset,
331
344
  cellState,
332
- useMultiSelect
345
+ useMultiSelect,
346
+ applySelectionForMode
333
347
  ]);
334
348
  return {
335
349
  selectedRowIds,
@@ -1,10 +1,23 @@
1
- import { useState, useCallback } from "react";
1
+ import { useState, useCallback, useEffect, useRef } from "react";
2
2
  const useTableState = ({
3
3
  editMode = "none",
4
4
  radioselect = false,
5
5
  multiselect = false
6
6
  }) => {
7
7
  const [activeRowIds, setActiveRowIds] = useState([]);
8
+ const prevMultiselectRef = useRef(multiselect);
9
+ const prevRadioselectRef = useRef(radioselect);
10
+ useEffect(() => {
11
+ const prevMultiselect = prevMultiselectRef.current;
12
+ const prevRadioselect = prevRadioselectRef.current;
13
+ prevMultiselectRef.current = multiselect;
14
+ prevRadioselectRef.current = radioselect;
15
+ if (prevMultiselect && !multiselect) {
16
+ setActiveRowIds([]);
17
+ } else if (prevRadioselect && !radioselect && !multiselect) {
18
+ setActiveRowIds([]);
19
+ }
20
+ }, [multiselect, radioselect]);
8
21
  const handleRowActiveClick = useCallback(
9
22
  (rowId, isSelectionHandled, isEditingOrAdding) => {
10
23
  if (isEditingOrAdding) {
@@ -39,7 +52,6 @@ const useTableState = ({
39
52
  setActiveRowIds([]);
40
53
  }
41
54
  }, []);
42
- const activeRowId = activeRowIds && activeRowIds.length > 0 ? activeRowIds[0] : null;
43
55
  return {
44
56
  activeRowIds,
45
57
  setActiveRow,
@@ -82,6 +82,7 @@ import {
82
82
  parseTableRowActions,
83
83
  parseTableActions,
84
84
  parseTableRowExpansion,
85
+ isRowExpansionVisible,
85
86
  getSpacingClasses,
86
87
  TABLE_CSS_CLASSES,
87
88
  TABLE_MESSAGES,
@@ -201,7 +202,8 @@ const WmTableComponent = memo(
201
202
  exportdatasize,
202
203
  onBeforeexport,
203
204
  onAfterexport,
204
- styles
205
+ styles,
206
+ viewParent
205
207
  } = _c, rest = __objRest(_c, [
206
208
  "name",
207
209
  "dataset",
@@ -282,7 +284,8 @@ const WmTableComponent = memo(
282
284
  "exportdatasize",
283
285
  "onBeforeexport",
284
286
  "onAfterexport",
285
- "styles"
287
+ "styles",
288
+ "viewParent"
286
289
  ]);
287
290
  const effectiveStorageKey = useMemo(
288
291
  () => name + ((listener == null ? void 0 : listener.partialName) ? `__${listener == null ? void 0 : listener.partialName}` : ""),
@@ -461,6 +464,8 @@ const WmTableComponent = memo(
461
464
  onRowdeselect,
462
465
  listener,
463
466
  navigation,
467
+ viewParent,
468
+ widgetRegistrationKey,
464
469
  onSyncSelectedItems
465
470
  });
466
471
  const { activeRowIds, setActiveRow, handleRowActiveClick, isRowActive } = useTableState({
@@ -493,15 +498,20 @@ const WmTableComponent = memo(
493
498
  const staticColumns = parseTableColumns(children, internalDataset);
494
499
  const hasGroups = structure.some((item) => "isGroup" in item && item.isGroup);
495
500
  const finalColumns = hasGroups && flatColumns.length > 0 ? flatColumns : staticColumns.length > 0 ? staticColumns : isDynamicTable && dynamicColumns.length > 0 ? dynamicColumns : flatColumns;
501
+ const parsedExpansion = parseTableRowExpansion(children);
496
502
  return {
497
503
  wmTableColumns: finalColumns,
498
504
  tableStructure: structure,
499
505
  tableActions: allTableActions,
500
506
  headerActions: headerActions2,
501
507
  footerActions: footerActions2,
502
- rowExpansionConfig: parseTableRowExpansion(children)
508
+ rowExpansionConfig: parsedExpansion
503
509
  };
504
510
  }, [children, internalDataset, isDynamicTable, dynamicColumns]);
511
+ const visibleRowExpansionConfig = useMemo(
512
+ () => isRowExpansionVisible(rowExpansionConfig, internalDataset) ? rowExpansionConfig : null,
513
+ [rowExpansionConfig, internalDataset]
514
+ );
505
515
  const rowActions = useMemo(() => parseTableRowActions(children), [children]);
506
516
  const [columnsVersion, setColumnsVersion] = useState(0);
507
517
  const [columnOverrides, setColumnOverrides] = useState(
@@ -556,8 +566,8 @@ const WmTableComponent = memo(
556
566
  updatemessage,
557
567
  errormessage,
558
568
  showToast,
559
- hasRowExpansion: rowExpansionConfig ? true : false,
560
- expansionPosition: rowExpansionConfig ? parseInt(String(rowExpansionConfig.position || "0"), 10) : 0,
569
+ hasRowExpansion: visibleRowExpansionConfig ? true : false,
570
+ expansionPosition: visibleRowExpansionConfig ? parseInt(String(visibleRowExpansionConfig.position || "0"), 10) : 0,
561
571
  datasource,
562
572
  binddataset,
563
573
  onSuccess,
@@ -580,7 +590,9 @@ const WmTableComponent = memo(
580
590
  useMultiSelect,
581
591
  isrowselectable,
582
592
  listener,
583
- name
593
+ viewParent,
594
+ name,
595
+ widgetRegistrationKey
584
596
  });
585
597
  useEffect(() => {
586
598
  const currentPage = paginationState.pageIndex;
@@ -1344,23 +1356,33 @@ const WmTableComponent = memo(
1344
1356
  selectPageSize,
1345
1357
  rowDefInstances
1346
1358
  };
1347
- syncSelectedItemsImplRef.current = (newSelectedIds) => {
1359
+ const getRowId = (row) => row._wmTableRowId || String(row.id);
1360
+ const pushSelectedItemsToWidget = (selectedIds) => {
1348
1361
  if (!(listener == null ? void 0 : listener.onChange)) return;
1349
- const getRowId = (row) => row._wmTableRowId || String(row.id);
1350
1362
  const selectedRows = internalDataset.filter(
1351
- (row) => newSelectedIds.includes(getRowId(row))
1363
+ (row) => selectedIds.includes(getRowId(row))
1352
1364
  );
1353
1365
  const selectedItems = cleanRowData(selectedRows);
1354
- if (!isEqual(prevSelectedRow.current, selectedItems)) {
1355
- prevSelectedRow.current = selectedItems;
1356
- if (tableApisRegistered.current) {
1357
- listener.onChange(widgetRegistrationKey, { selectedItems });
1358
- } else {
1359
- tableApisRegistered.current = true;
1360
- listener.onChange(widgetRegistrationKey, __spreadProps(__spreadValues({}, tableApis), { selectedItems }));
1361
- }
1366
+ if (selectedIds.length === 0) {
1367
+ prevSelectedRow.current = null;
1362
1368
  }
1369
+ if (isEqual(prevSelectedRow.current, selectedItems)) {
1370
+ return;
1371
+ }
1372
+ prevSelectedRow.current = selectedItems;
1373
+ const selectionPayload = {
1374
+ selectedItems,
1375
+ selecteditem: selectedItems,
1376
+ selectedItem: selectedItems.length === 1 ? selectedItems[0] : selectedItems
1377
+ };
1378
+ if (tableApisRegistered.current) {
1379
+ listener.onChange(widgetRegistrationKey, selectionPayload);
1380
+ return;
1381
+ }
1382
+ tableApisRegistered.current = true;
1383
+ listener.onChange(widgetRegistrationKey, __spreadValues(__spreadValues({}, tableApis), selectionPayload));
1363
1384
  };
1385
+ syncSelectedItemsImplRef.current = pushSelectedItemsToWidget;
1364
1386
  useEffect(() => {
1365
1387
  var _a2, _b2, _c2;
1366
1388
  if (parentForm && name && ((_a2 = listener == null ? void 0 : listener.Widgets) == null ? void 0 : _a2[parentForm])) {
@@ -1384,32 +1406,14 @@ const WmTableComponent = memo(
1384
1406
  }
1385
1407
  }
1386
1408
  }, [parentForm, parentFormColumns]);
1387
- const updateSelectedItem = () => {
1388
- if (!(listener == null ? void 0 : listener.onChange)) return;
1389
- const getRowId = (row) => row._wmTableRowId || String(row.id);
1390
- let selectedRows = [];
1391
- if ((useRadioSelect || useMultiSelect) && selectedRowIds.length > 0) {
1392
- selectedRows = internalDataset.filter((row) => selectedRowIds.includes(getRowId(row)));
1393
- } else if (activeRowIds.length > 0) {
1394
- selectedRows = internalDataset.filter(
1395
- (row) => activeRowIds.includes(getRowId(row))
1396
- );
1397
- }
1398
- const cleanedRows = cleanRowData(selectedRows);
1399
- const selectedItems = cleanedRows.length > 0 ? cleanedRows : [];
1400
- if (!isEqual(prevSelectedRow.current, selectedItems)) {
1401
- prevSelectedRow.current = selectedItems;
1402
- if (tableApisRegistered.current) {
1403
- listener.onChange(widgetRegistrationKey, { selectedItems });
1404
- return;
1405
- }
1406
- tableApisRegistered.current = true;
1407
- listener.onChange(widgetRegistrationKey, __spreadProps(__spreadValues({}, tableApis), { selectedItems }));
1408
- }
1409
- };
1410
1409
  useEffect(() => {
1411
- updateSelectedItem();
1412
- }, [activeRowIds, selectedRowIds, useRadioSelect, useMultiSelect, internalDataset, name]);
1410
+ if (!useRadioSelect && !useMultiSelect) return;
1411
+ pushSelectedItemsToWidget(selectedRowIds);
1412
+ }, [internalDataset, selectedRowIds, useRadioSelect, useMultiSelect]);
1413
+ useEffect(() => {
1414
+ if (useRadioSelect || useMultiSelect) return;
1415
+ pushSelectedItemsToWidget(activeRowIds != null ? activeRowIds : []);
1416
+ }, [activeRowIds, useRadioSelect, useMultiSelect]);
1413
1417
  const isTableLoading = useMemo(() => {
1414
1418
  return loading && navigation !== "On-Demand" && internalDataset.length === 0;
1415
1419
  }, [loading, navigation, internalDataset.length]);
@@ -1428,16 +1432,16 @@ const WmTableComponent = memo(
1428
1432
  domHidden: !!hiddenColStyle
1429
1433
  };
1430
1434
  });
1431
- if (rowExpansionConfig) {
1435
+ if (visibleRowExpansionConfig) {
1432
1436
  const expansionInsertIndex = getExpansionColumnInsertIndex(
1433
1437
  leafHeaders,
1434
- rowExpansionConfig,
1438
+ visibleRowExpansionConfig,
1435
1439
  {
1436
1440
  appendForGroupedTable: !!(tableStructure && hasTableGroups(tableStructure))
1437
1441
  }
1438
1442
  );
1439
1443
  if (expansionInsertIndex >= 0) {
1440
- base.splice(expansionInsertIndex, 0, __spreadProps(__spreadValues({}, buildExpansionColSpec(rowExpansionConfig.columnwidth)), {
1444
+ base.splice(expansionInsertIndex, 0, __spreadProps(__spreadValues({}, buildExpansionColSpec(visibleRowExpansionConfig.columnwidth)), {
1441
1445
  domHidden: false
1442
1446
  }));
1443
1447
  }
@@ -1449,7 +1453,7 @@ const WmTableComponent = memo(
1449
1453
  columnsVersion,
1450
1454
  showheader,
1451
1455
  ColClassSignature,
1452
- rowExpansionConfig,
1456
+ visibleRowExpansionConfig,
1453
1457
  tableStructure
1454
1458
  ]);
1455
1459
  return /* @__PURE__ */ jsxs(
@@ -1532,7 +1536,7 @@ const WmTableComponent = memo(
1532
1536
  sorting,
1533
1537
  columnSizing,
1534
1538
  rowSelection,
1535
- rowExpansionConfig,
1539
+ rowExpansionConfig: visibleRowExpansionConfig,
1536
1540
  columnsVersion,
1537
1541
  filterMode: filtermode,
1538
1542
  columnFilters,
@@ -1562,7 +1566,7 @@ const WmTableComponent = memo(
1562
1566
  nodatamessage,
1563
1567
  loadingdatamsg,
1564
1568
  isLoading: datasource == null ? void 0 : datasource.loading,
1565
- rowExpansionConfig,
1569
+ rowExpansionConfig: visibleRowExpansionConfig,
1566
1570
  expandedRows,
1567
1571
  toggleRowExpansion: handleToggleRowExpansion,
1568
1572
  isRowExpanded,
@@ -1113,6 +1113,8 @@ export interface UseRowSelectionProps {
1113
1113
  onRowdeselect?: (event: any, widget: any, row: any) => void;
1114
1114
  listener?: any;
1115
1115
  navigation?: string;
1116
+ viewParent?: any;
1117
+ widgetRegistrationKey?: string;
1116
1118
  onSyncSelectedItems?: (selectedIds: string[]) => void;
1117
1119
  }
1118
1120
  export interface UseRowSelectionReturn {
@@ -1261,7 +1263,9 @@ export interface UseRowHandlersProps {
1261
1263
  useMultiSelect?: boolean;
1262
1264
  isrowselectable?: boolean;
1263
1265
  listener?: any;
1266
+ viewParent?: any;
1264
1267
  name: string;
1268
+ widgetRegistrationKey?: string;
1265
1269
  }
1266
1270
  export interface UseRowHandlersReturn {
1267
1271
  handleRowClick: (event: MouseEvent, rowData: any, rowId: string) => void;
@@ -38,7 +38,7 @@ function MultiSelectCell(ctx) {
38
38
  const rowId = row.id;
39
39
  const isSelected = row.getIsSelected();
40
40
  const { handleMultiSelection, multiselecttitle, multiselectarialabel } = getSelectionMeta(ctx);
41
- return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", justifyContent: "center" }, children: [
41
+ return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex" }, children: [
42
42
  /* @__PURE__ */ jsx(Tooltip, { title: multiselecttitle != null ? multiselecttitle : "", placement: "top", children: /* @__PURE__ */ jsx(Box, { className: "app-checkbox checkbox", children: /* @__PURE__ */ jsx(
43
43
  Checkbox,
44
44
  {
@@ -65,7 +65,7 @@ function MultiSelectHeader({ table, column }) {
65
65
  var _a, _b;
66
66
  const isAllSelected = table.getIsAllRowsSelected();
67
67
  const { handleSelectAll } = (_b = (_a = column.columnDef.meta) == null ? void 0 : _a.selection) != null ? _b : {};
68
- return /* @__PURE__ */ jsx(Box, { sx: { display: "flex", justifyContent: "center", width: "100%" }, children: /* @__PURE__ */ jsx(Box, { className: "app-checkbox checkbox", children: /* @__PURE__ */ jsx(
68
+ return /* @__PURE__ */ jsx(Box, { sx: { display: "flex", width: "100%" }, children: /* @__PURE__ */ jsx(Box, { className: "app-checkbox checkbox", children: /* @__PURE__ */ jsx(
69
69
  Checkbox,
70
70
  {
71
71
  checked: isAllSelected,
@@ -62,7 +62,7 @@ const createDataColumn = (wmColumn, renderCell, index = 0) => {
62
62
  const colClassProp = (_a = wmColumn.colClass) != null ? _a : wmColumn["col-class"];
63
63
  let columnSize;
64
64
  if (wmColumn.width) {
65
- columnSize = parseInt(wmColumn.width);
65
+ columnSize = parseWidth(wmColumn.width);
66
66
  } else if ((_b = wmColumn.styles) == null ? void 0 : _b.width) {
67
67
  columnSize = parseWidth(wmColumn.styles.width);
68
68
  }
@@ -7,7 +7,8 @@ export type EditWidgetType = FormWidgetType;
7
7
  * Angular behavior: when a dataset is a non-array object (e.g. a REST API response
8
8
  * like { users: [...], total: 100 }), return the first array-valued property as the
9
9
  * actual row data. If the value is already an array it is returned as-is; if no
10
- * array property is found (e.g. a params snapshot) an empty array is returned.
10
+ * array property is found, the object itself is a single record (e.g. a get-by-id
11
+ * service response) and is wrapped as a one-row array.
11
12
  */
12
13
  export declare const extractDataArray: (dataset: any) => any[];
13
14
  /**
@@ -48,6 +49,13 @@ export declare const parseTableRowActions: (children: React.ReactNode) => WmTabl
48
49
  export declare const parseTableActions: (children: React.ReactNode) => WmTableActionProps[];
49
50
  /** Resolve row-bound expansion props. Uses precomputed map first, then tableRowProps(rowData) fallback. */
50
51
  export declare const getRowExpansionConfig: (config: WmTableRowProps | null, rowId: string, rowData?: any) => WmTableRowProps | null;
52
+ /**
53
+ * Whether the expansion column should be reserved in the table layout.
54
+ * When tableRowProps gates show per row (e.g. hierarchy children.length), hide the
55
+ * column entirely if no current row would show an expand control — avoids empty
56
+ * row-expansion-cell spacers for leaf-only datasets.
57
+ */
58
+ export declare const isRowExpansionVisible: (config: WmTableRowProps | null | undefined, dataset: any[] | undefined) => boolean;
51
59
  export declare const parseTableRowExpansion: (children: React.ReactNode) => WmTableRowProps | null;
52
60
  export declare const isEditAction: (actionKey: string) => boolean;
53
61
  export declare const isDeleteAction: (actionKey: string) => boolean;
@@ -86,7 +86,7 @@ const extractDataArray = (dataset) => {
86
86
  if (isArray(dataset)) return dataset;
87
87
  if (dataset !== null && dataset !== void 0 && typeof dataset === "object") {
88
88
  const firstArray = Object.values(dataset).find((v) => isArray(v));
89
- return firstArray != null ? firstArray : [];
89
+ return firstArray != null ? firstArray : [dataset];
90
90
  }
91
91
  return [];
92
92
  };
@@ -351,6 +351,19 @@ const getRowExpansionConfig = (config, rowId, rowData) => {
351
351
  const overrides = typeof config.tableRowProps === "function" && rowData !== void 0 ? config.tableRowProps(rowData) : {};
352
352
  return __spreadValues(__spreadValues({}, config), overrides);
353
353
  };
354
+ const isRowExpansionVisible = (config, dataset) => {
355
+ if (!config) return false;
356
+ if (typeof config.tableRowProps === "function") {
357
+ if (!Array.isArray(dataset) || dataset.length === 0) return false;
358
+ return dataset.some((row) => {
359
+ var _a;
360
+ const overrides = ((_a = config.tableRowProps) == null ? void 0 : _a.call(config, row)) || {};
361
+ const show = overrides.show !== void 0 ? overrides.show : config.show;
362
+ return show !== false;
363
+ });
364
+ }
365
+ return config.show !== false;
366
+ };
354
367
  const parseTableRowExpansion = (children) => {
355
368
  let rowExpansionConfig = null;
356
369
  React.Children.forEach(children, (child) => {
@@ -714,6 +727,7 @@ export {
714
727
  isDeleteAction,
715
728
  isEditAction,
716
729
  isInteractiveElement,
730
+ isRowExpansionVisible,
717
731
  parseTableActions,
718
732
  parseTableColumns,
719
733
  parseTableRowActions,
@@ -11,6 +11,11 @@ export declare const hasInteractiveAttributes: (element: HTMLElement) => boolean
11
11
  * Check if element or its ancestors are interactive
12
12
  */
13
13
  export declare const isInteractiveElement: (event: React.MouseEvent) => boolean;
14
+ /**
15
+ * Widget passed to user callbacks must come from the page proxy (viewParent), which
16
+ * listener.onChange updates synchronously. listener.Widgets lags one React commit behind.
17
+ */
18
+ export declare const getWidgetForCallback: (listener: any | undefined, viewParent: any | undefined, widgetKey: string) => any;
14
19
  /**
15
20
  * Get row IDs from dataset
16
21
  */
@@ -47,6 +47,10 @@ const isInteractiveElement = (event) => {
47
47
  }
48
48
  return false;
49
49
  };
50
+ const getWidgetForCallback = (listener, viewParent, widgetKey) => {
51
+ var _a, _b, _c;
52
+ return (_c = (_a = viewParent == null ? void 0 : viewParent.Widgets) == null ? void 0 : _a[widgetKey]) != null ? _c : (_b = listener == null ? void 0 : listener.Widgets) == null ? void 0 : _b[widgetKey];
53
+ };
50
54
  const getRowIdsFromDataset = (dataset) => {
51
55
  return dataset.map((row) => row._wmTableRowId || String(row.id));
52
56
  };
@@ -103,6 +107,7 @@ const selectionStateHelpers = {
103
107
  };
104
108
  export {
105
109
  getRowIdsFromDataset,
110
+ getWidgetForCallback,
106
111
  hasInteractiveAttributes,
107
112
  hasInteractiveClass,
108
113
  isInteractiveElement,