@ni/nimble-components 18.13.4 → 18.13.5

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 (36) hide show
  1. package/dist/all-components-bundle.js +296 -77
  2. package/dist/all-components-bundle.js.map +1 -1
  3. package/dist/all-components-bundle.min.js +794 -776
  4. package/dist/all-components-bundle.min.js.map +1 -1
  5. package/dist/esm/table/components/group-row/index.js +6 -2
  6. package/dist/esm/table/components/group-row/index.js.map +1 -1
  7. package/dist/esm/table/components/row/index.js +4 -2
  8. package/dist/esm/table/components/row/index.js.map +1 -1
  9. package/dist/esm/table/components/row/template.js +0 -1
  10. package/dist/esm/table/components/row/template.js.map +1 -1
  11. package/dist/esm/table/index.d.ts +4 -16
  12. package/dist/esm/table/index.js +26 -70
  13. package/dist/esm/table/index.js.map +1 -1
  14. package/dist/esm/table/models/interactive-selection-manager.d.ts +17 -0
  15. package/dist/esm/table/models/interactive-selection-manager.js +51 -0
  16. package/dist/esm/table/models/interactive-selection-manager.js.map +1 -0
  17. package/dist/esm/table/models/selection-managers/disabled-selection-manager.d.ts +11 -0
  18. package/dist/esm/table/models/selection-managers/disabled-selection-manager.js +17 -0
  19. package/dist/esm/table/models/selection-managers/disabled-selection-manager.js.map +1 -0
  20. package/dist/esm/table/models/selection-managers/multi-selection-manager.d.ts +20 -0
  21. package/dist/esm/table/models/selection-managers/multi-selection-manager.js +104 -0
  22. package/dist/esm/table/models/selection-managers/multi-selection-manager.js.map +1 -0
  23. package/dist/esm/table/models/selection-managers/selection-manager-base.d.ts +19 -0
  24. package/dist/esm/table/models/selection-managers/selection-manager-base.js +78 -0
  25. package/dist/esm/table/models/selection-managers/selection-manager-base.js.map +1 -0
  26. package/dist/esm/table/models/selection-managers/single-selection-manager.d.ts +11 -0
  27. package/dist/esm/table/models/selection-managers/single-selection-manager.js +18 -0
  28. package/dist/esm/table/models/selection-managers/single-selection-manager.js.map +1 -0
  29. package/dist/esm/table/template.js +1 -1
  30. package/dist/esm/table/template.js.map +1 -1
  31. package/dist/esm/table/testing/table.pageobject.d.ts +6 -3
  32. package/dist/esm/table/testing/table.pageobject.js +30 -4
  33. package/dist/esm/table/testing/table.pageobject.js.map +1 -1
  34. package/dist/esm/table/types.d.ts +17 -0
  35. package/dist/esm/table/types.js.map +1 -1
  36. package/package.json +1 -1
@@ -16366,7 +16366,7 @@
16366
16366
 
16367
16367
  /**
16368
16368
  * Do not edit directly
16369
- * Generated on Mon, 08 May 2023 13:48:08 GMT
16369
+ * Generated on Mon, 08 May 2023 16:01:14 GMT
16370
16370
  */
16371
16371
  const Information100DarkUi = "#a46eff";
16372
16372
  const Information100LightUi = "#804ad9";
@@ -28639,7 +28639,6 @@
28639
28639
  <span role="gridcell" class="checkbox-container">
28640
28640
  <${checkboxTag}
28641
28641
  ${ref('selectionCheckbox')}
28642
- role="cell"
28643
28642
  class="selection-checkbox"
28644
28643
  @change="${(x, c) => x.onSelectionChange(c.event)}"
28645
28644
  @click="${(_, c) => c.event.stopPropagation()}"
@@ -28735,9 +28734,11 @@
28735
28734
  return;
28736
28735
  }
28737
28736
  const checkbox = event.target;
28737
+ const checked = checkbox.checked;
28738
+ this.selected = checked;
28738
28739
  const detail = {
28739
- oldState: !checkbox.checked,
28740
- newState: checkbox.checked
28740
+ oldState: !checked,
28741
+ newState: checked
28741
28742
  };
28742
28743
  this.$emit('row-selection-toggle', detail);
28743
28744
  }
@@ -28997,9 +28998,13 @@
28997
28998
  return;
28998
28999
  }
28999
29000
  const checkbox = event.target;
29001
+ const checked = checkbox.checked;
29002
+ this.selectionState = checked
29003
+ ? TableRowSelectionState.selected
29004
+ : TableRowSelectionState.notSelected;
29000
29005
  const detail = {
29001
- oldState: !checkbox.checked,
29002
- newState: checkbox.checked
29006
+ oldState: !checked,
29007
+ newState: checked
29003
29008
  };
29004
29009
  this.$emit('group-selection-toggle', detail);
29005
29010
  }
@@ -29140,7 +29145,7 @@
29140
29145
  :dataRecord="${(x, c) => c.parent.tableData[x.index]?.record}"
29141
29146
  :columns="${(_, c) => c.parent.columns}"
29142
29147
  :nestingLevel="${(x, c) => c.parent.tableData[x.index]?.nestingLevel}"
29143
- @click="${(x, c) => c.parent.onRowClick(x.index)}"
29148
+ @click="${(x, c) => c.parent.onRowClick(x.index, c.event)}"
29144
29149
  @row-selection-toggle="${(x, c) => c.parent.onRowSelectionToggle(x.index, c.event)}"
29145
29150
  @row-action-menu-beforetoggle="${(x, c) => c.parent.onRowActionMenuBeforeToggle(x.index, c.event)}"
29146
29151
  @row-action-menu-toggle="${(_, c) => c.parent.onRowActionMenuToggle(c.event)}"
@@ -30091,6 +30096,265 @@
30091
30096
  }
30092
30097
  }
30093
30098
 
30099
+ /**
30100
+ * Abstract base class for handling behavior associated with interactive row selection of the table.
30101
+ */
30102
+ class SelectionManagerBase {
30103
+ constructor(tanStackTable) {
30104
+ this.tanStackTable = tanStackTable;
30105
+ }
30106
+ reset() { }
30107
+ toggleIsRowSelected(rowState, isSelecting) {
30108
+ if (rowState.isGrouped
30109
+ && rowState.selectionState === TableRowSelectionState.selected) {
30110
+ // Work around for https://github.com/TanStack/table/issues/4759
30111
+ // Manually deselect all leaf rows when a fully selected group is being deselected.
30112
+ this.deselectAllLeafRows(rowState.id);
30113
+ }
30114
+ else {
30115
+ this.tanStackTable.getRow(rowState.id).toggleSelected(isSelecting);
30116
+ }
30117
+ }
30118
+ selectSingleRow(rowState) {
30119
+ if (rowState.isGrouped) {
30120
+ throw new Error('function not intended to select grouped rows');
30121
+ }
30122
+ const currentSelection = this.tanStackTable.getState().rowSelection;
30123
+ const selectedRecordIds = [];
30124
+ Object.entries(currentSelection).forEach(([recordId, isSelected]) => {
30125
+ if (isSelected) {
30126
+ selectedRecordIds.push(recordId);
30127
+ }
30128
+ });
30129
+ if (selectedRecordIds.length === 1
30130
+ && selectedRecordIds[0] === rowState.id) {
30131
+ // The clicked row is already the only selected row. Do nothing.
30132
+ return false;
30133
+ }
30134
+ const newSelectionState = {};
30135
+ newSelectionState[rowState.id] = true;
30136
+ this.tanStackTable.setRowSelection(newSelectionState);
30137
+ return true;
30138
+ }
30139
+ deselectAllLeafRows(rowId) {
30140
+ const groupRow = this.tanStackTable.getRow(rowId);
30141
+ const leafRowIds = this.getAllLeafRowIds(groupRow.id);
30142
+ const selectionState = this.tanStackTable.getState().rowSelection;
30143
+ for (const id of leafRowIds) {
30144
+ delete selectionState[id];
30145
+ }
30146
+ this.tanStackTable.setRowSelection(selectionState);
30147
+ }
30148
+ getAllLeafRowIds(id) {
30149
+ const row = this.tanStackTable
30150
+ .getRowModel()
30151
+ .flatRows.find(x => x.id === id);
30152
+ if (!row?.getIsGrouped()) {
30153
+ return [];
30154
+ }
30155
+ return row
30156
+ .getLeafRows()
30157
+ .filter(leafRow => leafRow.getLeafRows().length === 0)
30158
+ .map(leafRow => leafRow.id);
30159
+ }
30160
+ getAllOrderedRows() {
30161
+ const topLevelRows = this.tanStackTable.getPreExpandedRowModel().rows;
30162
+ return this.getOrderedRows(topLevelRows);
30163
+ }
30164
+ getOrderedRows(topLevelRows) {
30165
+ const allRows = [];
30166
+ for (const row of topLevelRows) {
30167
+ allRows.push(row);
30168
+ if (row.subRows?.length) {
30169
+ allRows.push(...this.getOrderedRows(row.subRows));
30170
+ }
30171
+ }
30172
+ return allRows;
30173
+ }
30174
+ }
30175
+
30176
+ /**
30177
+ * Selection manager for interactive selection when the selection mode of the table is
30178
+ * `TableRowSelectionMode.none`.
30179
+ */
30180
+ class DisabledSelectionManager extends SelectionManagerBase {
30181
+ handleRowSelectionToggle(_rowState, _isSelecting, _shiftKey) {
30182
+ return false;
30183
+ }
30184
+ handleRowClick(_rowState, _shiftKey, _ctrlKey) {
30185
+ return false;
30186
+ }
30187
+ handleActionMenuOpening(_rowState) {
30188
+ return false;
30189
+ }
30190
+ }
30191
+
30192
+ /**
30193
+ * Selection manager for interactive selection when the selection mode of the table is
30194
+ * `TableRowSelectionMode.multiple`.
30195
+ */
30196
+ class MultiSelectionManager extends SelectionManagerBase {
30197
+ handleRowSelectionToggle(rowState, isSelecting, shiftKey) {
30198
+ if (shiftKey) {
30199
+ if (this.tryUpdateRangeSelection(rowState.id)) {
30200
+ // Made a range selection
30201
+ return true;
30202
+ }
30203
+ }
30204
+ this.shiftSelectStartRowId = rowState.id;
30205
+ this.previousShiftSelectRowEndId = undefined;
30206
+ this.toggleIsRowSelected(rowState, isSelecting);
30207
+ return true;
30208
+ }
30209
+ handleRowClick(rowState, shiftKey, ctrlKey) {
30210
+ if (ctrlKey) {
30211
+ this.shiftSelectStartRowId = rowState.id;
30212
+ this.previousShiftSelectRowEndId = undefined;
30213
+ this.toggleIsRowSelected(rowState);
30214
+ return true;
30215
+ }
30216
+ if (shiftKey) {
30217
+ if (this.tryUpdateRangeSelection(rowState.id)) {
30218
+ // Made a range selection
30219
+ return true;
30220
+ }
30221
+ }
30222
+ this.shiftSelectStartRowId = rowState.id;
30223
+ this.previousShiftSelectRowEndId = undefined;
30224
+ return this.selectSingleRow(rowState);
30225
+ }
30226
+ handleActionMenuOpening(rowState) {
30227
+ if (rowState.selectionState === TableRowSelectionState.selected) {
30228
+ return false;
30229
+ }
30230
+ return this.selectSingleRow(rowState);
30231
+ }
30232
+ reset() {
30233
+ this.shiftSelectStartRowId = undefined;
30234
+ this.previousShiftSelectRowEndId = undefined;
30235
+ }
30236
+ tryUpdateRangeSelection(rowId) {
30237
+ if (this.shiftSelectStartRowId === undefined) {
30238
+ return false;
30239
+ }
30240
+ const allRows = this.getAllOrderedRows();
30241
+ const selectionStartIndex = this.getRowIndexForId(this.shiftSelectStartRowId, allRows);
30242
+ if (selectionStartIndex === -1) {
30243
+ return false;
30244
+ }
30245
+ const selectionState = this.tanStackTable.getState().rowSelection;
30246
+ this.removePreviousRangeSelection(selectionState, selectionStartIndex, allRows);
30247
+ this.addNewRangeSelection(selectionState, rowId, selectionStartIndex, allRows);
30248
+ this.previousShiftSelectRowEndId = rowId;
30249
+ this.tanStackTable.setRowSelection(selectionState);
30250
+ return true;
30251
+ }
30252
+ removePreviousRangeSelection(selection, shiftSelectStartRowIndex, allRows) {
30253
+ const previousRangeEndIndex = this.getRowIndexForId(this.previousShiftSelectRowEndId, allRows);
30254
+ this.updateSelectionStateForRange(selection, shiftSelectStartRowIndex, previousRangeEndIndex, allRows, false);
30255
+ }
30256
+ addNewRangeSelection(selection, endRangeRowId, shiftSelectStartRowIndex, allRows) {
30257
+ const newRangeEndIndex = this.getRowIndexForId(endRangeRowId, allRows);
30258
+ this.updateSelectionStateForRange(selection, shiftSelectStartRowIndex, newRangeEndIndex, allRows, true);
30259
+ }
30260
+ updateSelectionStateForRange(selection, rangeStartIndex, rangeEndIndex, allRows, isSelecting) {
30261
+ if (rangeStartIndex === -1 || rangeEndIndex === -1) {
30262
+ return;
30263
+ }
30264
+ const firstRowIndex = Math.min(rangeStartIndex, rangeEndIndex);
30265
+ const lastRowIndex = Math.max(rangeStartIndex, rangeEndIndex);
30266
+ for (let i = firstRowIndex; i <= lastRowIndex; i++) {
30267
+ const row = allRows[i];
30268
+ if (row.getIsGrouped()) {
30269
+ continue;
30270
+ }
30271
+ this.updateSelectionStateForRow(selection, row.id, isSelecting);
30272
+ }
30273
+ const endRangeRow = allRows[rangeEndIndex];
30274
+ if (endRangeRow.getIsGrouped()) {
30275
+ this.getAllLeafRowIds(endRangeRow.id).forEach(id => this.updateSelectionStateForRow(selection, id, isSelecting));
30276
+ }
30277
+ }
30278
+ updateSelectionStateForRow(selection, rowId, isSelecting) {
30279
+ if (isSelecting) {
30280
+ selection[rowId] = true;
30281
+ }
30282
+ else {
30283
+ delete selection[rowId];
30284
+ }
30285
+ }
30286
+ getRowIndexForId(id, rows) {
30287
+ if (!id) {
30288
+ return -1;
30289
+ }
30290
+ return rows.findIndex(x => x.id === id);
30291
+ }
30292
+ }
30293
+
30294
+ /**
30295
+ * Selection manager for interactive selection when the selection mode of the table is
30296
+ * `TableRowSelectionMode.single`.
30297
+ */
30298
+ class SingleSelectionManager extends SelectionManagerBase {
30299
+ handleRowSelectionToggle(rowState, isSelecting, _shiftKey) {
30300
+ this.toggleIsRowSelected(rowState, isSelecting);
30301
+ return true;
30302
+ }
30303
+ handleRowClick(rowState, _shiftKey, _ctrlKey) {
30304
+ return this.selectSingleRow(rowState);
30305
+ }
30306
+ handleActionMenuOpening(rowState) {
30307
+ return this.handleRowClick(rowState, false, false);
30308
+ }
30309
+ }
30310
+
30311
+ /**
30312
+ * Manages the behavior associated with interactive row selection for the table, including
30313
+ * handling when the selection mode of the table is changed.
30314
+ */
30315
+ class InteractiveSelectionManager {
30316
+ constructor(tanStackTable, selectionMode) {
30317
+ this.tanStackTable = tanStackTable;
30318
+ this.selectionManager = this.createSelectionManager(selectionMode);
30319
+ }
30320
+ handleRowSelectionToggle(rowState, isSelecting, shiftKey) {
30321
+ if (!rowState) {
30322
+ return false;
30323
+ }
30324
+ return this.selectionManager.handleRowSelectionToggle(rowState, isSelecting, shiftKey);
30325
+ }
30326
+ handleRowClick(rowState, shiftKey, ctrlKey) {
30327
+ if (!rowState) {
30328
+ return false;
30329
+ }
30330
+ return this.selectionManager.handleRowClick(rowState, shiftKey, ctrlKey);
30331
+ }
30332
+ handleActionMenuOpening(rowState) {
30333
+ if (!rowState) {
30334
+ return false;
30335
+ }
30336
+ return this.selectionManager.handleActionMenuOpening(rowState);
30337
+ }
30338
+ handleSelectionModeChanged(selectionMode) {
30339
+ this.selectionManager = this.createSelectionManager(selectionMode);
30340
+ }
30341
+ handleSelectionReset() {
30342
+ this.selectionManager.reset();
30343
+ }
30344
+ createSelectionManager(selectionMode) {
30345
+ switch (selectionMode) {
30346
+ case TableRowSelectionMode.multiple:
30347
+ return new MultiSelectionManager(this.tanStackTable);
30348
+ case TableRowSelectionMode.single:
30349
+ return new SingleSelectionManager(this.tanStackTable);
30350
+ case TableRowSelectionMode.none:
30351
+ return new DisabledSelectionManager(this.tanStackTable);
30352
+ default:
30353
+ throw new Error('unknown selection mode found');
30354
+ }
30355
+ }
30356
+ }
30357
+
30094
30358
  /**
30095
30359
  * A nimble-styled table.
30096
30360
  */
@@ -30220,6 +30484,7 @@
30220
30484
  };
30221
30485
  this.table = createTable(this.options);
30222
30486
  this.virtualizer = new Virtualizer(this, this.table);
30487
+ this.selectionManager = new InteractiveSelectionManager(this.table, this.selectionMode);
30223
30488
  }
30224
30489
  get validity() {
30225
30490
  return this.tableValidator.getValidity();
@@ -30305,26 +30570,17 @@
30305
30570
  /** @internal */
30306
30571
  onRowSelectionToggle(rowIndex, event) {
30307
30572
  event.stopImmediatePropagation();
30308
- if (this.selectionMode === TableRowSelectionMode.none) {
30309
- return;
30310
- }
30311
- const rowState = this.tableData[rowIndex];
30312
- if (rowState?.isGrouped
30313
- && rowState?.selectionState === TableRowSelectionState.selected) {
30314
- // Work around for https://github.com/TanStack/table/issues/4759
30315
- // Manually deselect all leaf rows when a fully selected group is being deselected.
30316
- this.deselectAllLeafRows(rowIndex);
30573
+ const selectionChanged = this.selectionManager.handleRowSelectionToggle(this.tableData[rowIndex], event.detail.newState, this.documentShiftKeyDown);
30574
+ if (selectionChanged) {
30575
+ void this.emitSelectionChangeEvent();
30317
30576
  }
30318
- else {
30319
- this.table
30320
- .getRowModel()
30321
- .rows[rowIndex]?.toggleSelected(event.detail.newState);
30322
- }
30323
- void this.emitSelectionChangeEvent();
30324
30577
  }
30325
30578
  /** @internal */
30326
- onRowClick(rowIndex) {
30327
- void this.selectSingleRow(rowIndex);
30579
+ onRowClick(rowIndex, event) {
30580
+ const selectionChanged = this.selectionManager.handleRowClick(this.tableData[rowIndex], event.shiftKey, event.ctrlKey || event.metaKey);
30581
+ if (selectionChanged) {
30582
+ void this.emitSelectionChangeEvent();
30583
+ }
30328
30584
  return true;
30329
30585
  }
30330
30586
  /** @internal */
@@ -30449,36 +30705,30 @@
30449
30705
  this.updateTracker.trackColumnInstancesChanged();
30450
30706
  }
30451
30707
  async handleActionMenuBeforeToggleEvent(rowIndex, event) {
30452
- let recordIds = event.detail.recordIds;
30453
- if (this.selectionMode !== TableRowSelectionMode.none) {
30454
- const row = this.table.getRowModel().rows[rowIndex];
30455
- if (row && !row.getIsSelected()) {
30456
- await this.selectSingleRow(rowIndex);
30457
- }
30458
- else {
30459
- recordIds = await this.getSelectedRecordIds();
30460
- }
30708
+ const selectionChanged = this.selectionManager.handleActionMenuOpening(this.tableData[rowIndex]);
30709
+ if (selectionChanged) {
30710
+ await this.emitSelectionChangeEvent();
30461
30711
  }
30462
30712
  this.openActionMenuRecordId = event.detail.recordIds[0];
30463
- const detail = {
30464
- ...event.detail,
30465
- recordIds
30466
- };
30713
+ const detail = await this.getActionMenuToggleEventDetail(event);
30467
30714
  this.$emit('action-menu-beforetoggle', detail);
30468
30715
  }
30469
30716
  async handleRowActionMenuToggleEvent(event) {
30470
- const recordIds = this.selectionMode === TableRowSelectionMode.multiple
30471
- ? await this.getSelectedRecordIds()
30472
- : event.detail.recordIds;
30473
- const detail = {
30474
- ...event.detail,
30475
- recordIds
30476
- };
30717
+ const detail = await this.getActionMenuToggleEventDetail(event);
30477
30718
  this.$emit('action-menu-toggle', detail);
30478
30719
  if (!event.detail.newState) {
30479
30720
  this.openActionMenuRecordId = undefined;
30480
30721
  }
30481
30722
  }
30723
+ async getActionMenuToggleEventDetail(originalEvent) {
30724
+ const recordIds = this.selectionMode === TableRowSelectionMode.multiple
30725
+ ? await this.getSelectedRecordIds()
30726
+ : [this.openActionMenuRecordId];
30727
+ return {
30728
+ ...originalEvent.detail,
30729
+ recordIds
30730
+ };
30731
+ }
30482
30732
  removeColumnObservers() {
30483
30733
  this.columnNotifiers.forEach(notifier => {
30484
30734
  notifier.unsubscribe(this);
@@ -30546,11 +30796,13 @@
30546
30796
  if (this.updateTracker.updateRowIds) {
30547
30797
  updatedOptions.getRowId = this.calculateTanStackRowIdFunction();
30548
30798
  updatedOptions.state.rowSelection = {};
30799
+ this.selectionManager.handleSelectionReset();
30549
30800
  }
30550
30801
  if (this.updateTracker.updateSelectionMode) {
30551
30802
  updatedOptions.enableMultiRowSelection = this.selectionMode === TableRowSelectionMode.multiple;
30552
30803
  updatedOptions.enableSubRowSelection = this.selectionMode === TableRowSelectionMode.multiple;
30553
30804
  updatedOptions.state.rowSelection = {};
30805
+ this.selectionManager.handleSelectionModeChanged(this.selectionMode);
30554
30806
  }
30555
30807
  if (this.updateTracker.requiresTanStackDataReset) {
30556
30808
  // Perform a shallow copy of the data to trigger tanstack to regenerate the row models and columns.
@@ -30696,39 +30948,6 @@
30696
30948
  this.table.setOptions(this.options);
30697
30949
  this.refreshRows();
30698
30950
  }
30699
- async selectSingleRow(rowIndex) {
30700
- if (this.selectionMode === TableRowSelectionMode.none) {
30701
- return;
30702
- }
30703
- const row = this.table.getRowModel().rows[rowIndex];
30704
- if (!row) {
30705
- return;
30706
- }
30707
- const currentSelection = await this.getSelectedRecordIds();
30708
- if (currentSelection.length === 1 && currentSelection[0] === row.id) {
30709
- // The clicked row is already the only selected row. Do nothing.
30710
- return;
30711
- }
30712
- this.table.toggleAllRowsSelected(false);
30713
- row.toggleSelected(true);
30714
- await this.emitSelectionChangeEvent();
30715
- }
30716
- deselectAllLeafRows(rowIndex) {
30717
- const groupRow = this.table.getRowModel().rows[rowIndex];
30718
- const leafRowIds = groupRow
30719
- .getLeafRows()
30720
- .filter(leafRow => leafRow.getLeafRows().length === 0)
30721
- .map(leafRow => leafRow.id);
30722
- const selectionState = this.table.getState().rowSelection;
30723
- for (const id of leafRowIds) {
30724
- delete selectionState[id];
30725
- }
30726
- this.updateTableOptions({
30727
- state: {
30728
- rowSelection: selectionState
30729
- }
30730
- });
30731
- }
30732
30951
  toggleGroupExpanded(rowIndex) {
30733
30952
  const row = this.table.getRowModel().rows[rowIndex];
30734
30953
  const wasExpanded = row.getIsExpanded();