@ni/nimble-components 18.11.1 → 18.12.1

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 (39) hide show
  1. package/dist/all-components-bundle.js +455 -86
  2. package/dist/all-components-bundle.js.map +1 -1
  3. package/dist/all-components-bundle.min.js +1067 -931
  4. package/dist/all-components-bundle.min.js.map +1 -1
  5. package/dist/esm/icon-base/icon-metadata.js +3 -0
  6. package/dist/esm/icon-base/icon-metadata.js.map +1 -1
  7. package/dist/esm/icons/all-icons.d.ts +1 -0
  8. package/dist/esm/icons/all-icons.js +1 -0
  9. package/dist/esm/icons/all-icons.js.map +1 -1
  10. package/dist/esm/icons/file-export.d.ts +13 -0
  11. package/dist/esm/icons/file-export.js +16 -0
  12. package/dist/esm/icons/file-export.js.map +1 -0
  13. package/dist/esm/table/components/cell/template.js +1 -0
  14. package/dist/esm/table/components/cell/template.js.map +1 -1
  15. package/dist/esm/table/components/group-row/index.d.ts +14 -1
  16. package/dist/esm/table/components/group-row/index.js +44 -0
  17. package/dist/esm/table/components/group-row/index.js.map +1 -1
  18. package/dist/esm/table/components/group-row/styles.js +16 -4
  19. package/dist/esm/table/components/group-row/styles.js.map +1 -1
  20. package/dist/esm/table/components/group-row/template.js +30 -10
  21. package/dist/esm/table/components/group-row/template.js.map +1 -1
  22. package/dist/esm/table/components/row/index.d.ts +12 -2
  23. package/dist/esm/table/components/row/index.js +40 -4
  24. package/dist/esm/table/components/row/index.js.map +1 -1
  25. package/dist/esm/table/components/row/styles.js +21 -4
  26. package/dist/esm/table/components/row/styles.js.map +1 -1
  27. package/dist/esm/table/components/row/template.js +36 -20
  28. package/dist/esm/table/components/row/template.js.map +1 -1
  29. package/dist/esm/table/index.d.ts +27 -4
  30. package/dist/esm/table/index.js +185 -22
  31. package/dist/esm/table/index.js.map +1 -1
  32. package/dist/esm/table/styles.js +32 -9
  33. package/dist/esm/table/styles.js.map +1 -1
  34. package/dist/esm/table/template.js +37 -14
  35. package/dist/esm/table/template.js.map +1 -1
  36. package/dist/esm/table/types.d.ts +11 -0
  37. package/dist/esm/table/types.js +4 -2
  38. package/dist/esm/table/types.js.map +1 -1
  39. package/package.json +15 -14
@@ -19086,6 +19086,10 @@
19086
19086
  name: 'file_drawer_16_x_16',
19087
19087
  data: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path class="cls-1" d="M2 4v10h12V4Zm8 4H6V6h4Zm4-5H2V2h12Z"/></svg>`
19088
19088
  };
19089
+ const fileExport = {
19090
+ name: 'file_export',
19091
+ data: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M6.8 13.6H2V3h4.2v4.2h4.2V10c-2 0-3.6 1.6-3.6 3.6Zm3.7-7.4H7.3V3l3.2 3.2Z"/><path d="M11.6 9.2v1.6c-1.9-.2-3.6 1.1-3.9 3 .6-.7 2.2-2.2 3.9-1.8v1.5l2.4-2.1-2.4-2.2Z"/></svg>`
19092
+ };
19089
19093
  const fileSearch16X16 = {
19090
19094
  name: 'file_search_16_x_16',
19091
19095
  data: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path class="cls-1" d="M14 6v6h-3.333a3.662 3.662 0 0 0 .249-1.302A3.701 3.701 0 0 0 7.22 7 3.654 3.654 0 0 0 6 7.223V2h4v4Zm-3-4v3h3Zm-1.126 8.698a2.697 2.697 0 0 1-4.73 1.772L2.521 14l-.48-.823 2.613-1.523a2.698 2.698 0 1 1 5.22-.956Zm-.952 0a1.745 1.745 0 1 0-1.745 1.745 1.747 1.747 0 0 0 1.745-1.745Z"/></svg>`
@@ -20094,7 +20098,7 @@
20094
20098
  indeterminateIndicator: minus16X16.data
20095
20099
  });
20096
20100
  DesignSystem.getOrCreate().withPrefix('nimble').register(nimbleCheckbox());
20097
- DesignSystem.tagFor(Checkbox);
20101
+ const checkboxTag = DesignSystem.tagFor(Checkbox);
20098
20102
 
20099
20103
  const styles$x = css `
20100
20104
  ${styles$M}
@@ -22146,6 +22150,18 @@
22146
22150
  registerIcon('icon-file-drawer', IconFileDrawer);
22147
22151
  DesignSystem.tagFor(IconFileDrawer);
22148
22152
 
22153
+ // AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY
22154
+ /**
22155
+ * The icon component for the 'fileExport' icon
22156
+ */
22157
+ class IconFileExport extends Icon {
22158
+ constructor() {
22159
+ super(fileExport);
22160
+ }
22161
+ }
22162
+ registerIcon('icon-file-export', IconFileExport);
22163
+ DesignSystem.tagFor(IconFileExport);
22164
+
22149
22165
  // AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY
22150
22166
  /**
22151
22167
  * The icon component for the 'fileSearch' icon
@@ -27808,7 +27824,8 @@
27808
27824
  */
27809
27825
  const TableRowSelectionMode = {
27810
27826
  none: undefined,
27811
- single: 'single'
27827
+ single: 'single',
27828
+ multiple: 'multiple'
27812
27829
  };
27813
27830
  /**
27814
27831
  * @internal
@@ -27817,7 +27834,8 @@
27817
27834
  */
27818
27835
  const TableRowSelectionState = {
27819
27836
  notSelected: 'notSelected',
27820
- selected: 'selected'
27837
+ selected: 'selected',
27838
+ partiallySelected: 'partiallySelected'
27821
27839
  };
27822
27840
 
27823
27841
  /**
@@ -28187,15 +28205,20 @@
28187
28205
  }
28188
28206
 
28189
28207
  .header-row {
28190
- display: grid;
28208
+ display: flex;
28191
28209
  background: ${applicationBackgroundColor};
28192
28210
  position: relative;
28193
28211
  width: fit-content;
28194
28212
  min-width: 100%;
28195
- grid-template-columns: var(--ni-private-table-row-grid-columns) auto;
28196
28213
  left: var(--ni-private-table-scroll-x);
28197
28214
  }
28198
28215
 
28216
+ .column-header-container {
28217
+ display: grid;
28218
+ width: 100%;
28219
+ grid-template-columns: var(--ni-private-table-row-grid-columns) auto;
28220
+ }
28221
+
28199
28222
  .header-scrollbar-spacer {
28200
28223
  width: var(--ni-private-table-header-scrollbar-spacer-width);
28201
28224
  }
@@ -28204,6 +28227,18 @@
28204
28227
  flex: 1;
28205
28228
  }
28206
28229
 
28230
+ .checkbox-container {
28231
+ display: flex;
28232
+ }
28233
+
28234
+ .selection-checkbox {
28235
+ margin-left: ${standardPadding};
28236
+ }
28237
+
28238
+ .selection-checkbox::part(label) {
28239
+ padding-left: 0px;
28240
+ }
28241
+
28207
28242
  .row {
28208
28243
  background: ${applicationBackgroundColor};
28209
28244
  position: relative;
@@ -28218,15 +28253,18 @@
28218
28253
  pointer-events: none;
28219
28254
  }
28220
28255
 
28221
- :host([selection-mode='single']) .row:hover::before {
28256
+ :host([selection-mode='single']) .row:hover::before,
28257
+ :host([selection-mode='multiple']) .row:hover::before {
28222
28258
  background: ${fillHoverColor};
28223
28259
  }
28224
28260
 
28225
- :host([selection-mode='single']) .row[selected]::before {
28261
+ :host([selection-mode='single']) .row[selected]::before,
28262
+ :host([selection-mode='multiple']) .row[selected]::before {
28226
28263
  background: ${fillSelectedColor};
28227
28264
  }
28228
28265
 
28229
- :host([selection-mode='single']) .row[selected]:hover::before {
28266
+ :host([selection-mode='single']) .row[selected]:hover::before,
28267
+ :host([selection-mode='multiple']) .row[selected]:hover::before {
28230
28268
  background: ${fillHoverSelectedColor};
28231
28269
  }
28232
28270
  `.withBehaviors(themeBehavior(Theme.color, css `
@@ -28243,15 +28281,18 @@
28243
28281
  background: ${fillHoverColor};
28244
28282
  }
28245
28283
 
28246
- :host([selection-mode='single']) .row:hover::before {
28284
+ :host([selection-mode='single']) .row:hover::before,
28285
+ :host([selection-mode='multiple']) .row:hover::before {
28247
28286
  background: ${hexToRgbaCssColor(White, 0.15)};
28248
28287
  }
28249
28288
 
28250
- :host([selection-mode='single']) .row[selected]::before {
28289
+ :host([selection-mode='single']) .row[selected]::before,
28290
+ :host([selection-mode='multiple']) .row[selected]::before {
28251
28291
  background: ${hexToRgbaCssColor(White, 0.25)};
28252
28292
  }
28253
28293
 
28254
- :host([selection-mode='single']) .row[selected]:hover::before {
28294
+ :host([selection-mode='single']) .row[selected]:hover::before,
28295
+ :host([selection-mode='multiple']) .row[selected]:hover::before {
28255
28296
  background: ${hexToRgbaCssColor(White, 0.2)};
28256
28297
  }
28257
28298
  `));
@@ -28332,16 +28373,33 @@
28332
28373
  const tableHeaderTag = DesignSystem.tagFor(TableHeader);
28333
28374
 
28334
28375
  const styles$e = css `
28335
- ${display('grid')}
28376
+ ${display('flex')}
28336
28377
 
28337
28378
  :host {
28338
28379
  height: calc(${controlHeight} + 2 * ${borderWidth});
28339
28380
  border-top: calc(2 * ${borderWidth}) solid ${tableRowBorderColor};
28381
+ width: fit-content;
28382
+ min-width: 100%;
28383
+ }
28384
+
28385
+ .checkbox-container {
28386
+ display: flex;
28387
+ }
28388
+
28389
+ .selection-checkbox {
28390
+ margin-left: ${standardPadding};
28391
+ }
28392
+
28393
+ .selection-checkbox::part(label) {
28394
+ padding-left: 0px;
28395
+ }
28396
+
28397
+ .cell-container {
28398
+ display: grid;
28399
+ width: 100%;
28340
28400
  grid-auto-flow: column;
28341
28401
  grid-auto-columns: 1fr;
28342
28402
  grid-template-columns: var(--ni-private-table-row-grid-columns) auto;
28343
- width: fit-content;
28344
- min-width: 100%;
28345
28403
  }
28346
28404
 
28347
28405
  nimble-table-cell {
@@ -28402,6 +28460,7 @@
28402
28460
  appearance="${ButtonAppearance.ghost}"
28403
28461
  @beforetoggle="${(x, c) => x.onActionMenuBeforeToggle(c.event)}"
28404
28462
  @toggle="${(x, c) => x.onActionMenuToggle(c.event)}"
28463
+ @click="${(_, c) => c.event.stopPropagation()}"
28405
28464
  class="action-menu"
28406
28465
  >
28407
28466
  <${iconThreeDotsLineTag} slot="start"></${iconThreeDotsLineTag}>
@@ -28460,28 +28519,43 @@
28460
28519
  // prettier-ignore
28461
28520
  const template$9 = html `
28462
28521
  <template role="row" aria-selected=${x => x.ariaSelected}>
28463
- ${repeat(x => x.columnStates, html `
28464
- ${when(x => !x.column.columnHidden, html `
28465
- <${tableCellTag}
28466
- class="cell"
28467
- :cellState="${x => x.cellState}"
28468
- :cellViewTemplate="${x => x.column.columnInternals.cellViewTemplate}"
28469
- ?has-action-menu="${x => !!x.column.actionMenuSlot}"
28470
- action-menu-label="${x => x.column.actionMenuLabel}"
28471
- @cell-action-menu-beforetoggle="${(x, c) => c.parent.onCellActionMenuBeforeToggle(c.event, x.column)}"
28472
- @cell-action-menu-toggle="${(x, c) => c.parent.onCellActionMenuToggle(c.event, x.column)}"
28473
- :nestingLevel="${x => x.cellIndentLevel};"
28522
+ ${when(x => x.selectable && !x.hideSelection, html `
28523
+ <span role="gridcell" class="checkbox-container">
28524
+ <${checkboxTag}
28525
+ ${ref('selectionCheckbox')}
28526
+ role="cell"
28527
+ class="selection-checkbox"
28528
+ @change="${(x, c) => x.onSelectionChange(c.event)}"
28529
+ @click="${(_, c) => c.event.stopPropagation()}"
28474
28530
  >
28531
+ </${checkboxTag}>
28532
+ </span>
28533
+ `)}
28475
28534
 
28476
- ${when((x, c) => (c.parent.currentActionMenuColumn === x.column) && x.column.actionMenuSlot, html `
28477
- <slot
28478
- name="${x => `row-action-menu-${x.column.actionMenuSlot}`}"
28479
- slot="cellActionMenu"
28480
- ></slot>
28481
- `)}
28482
- </${tableCellTag}>
28535
+ <span ${ref('cellContainer')} class="cell-container">
28536
+ ${repeat(x => x.columnStates, html `
28537
+ ${when(x => !x.column.columnHidden, html `
28538
+ <${tableCellTag}
28539
+ class="cell"
28540
+ :cellState="${x => x.cellState}"
28541
+ :cellViewTemplate="${x => x.column.columnInternals.cellViewTemplate}"
28542
+ ?has-action-menu="${x => !!x.column.actionMenuSlot}"
28543
+ action-menu-label="${x => x.column.actionMenuLabel}"
28544
+ @cell-action-menu-beforetoggle="${(x, c) => c.parent.onCellActionMenuBeforeToggle(c.event, x.column)}"
28545
+ @cell-action-menu-toggle="${(x, c) => c.parent.onCellActionMenuToggle(c.event, x.column)}"
28546
+ :nestingLevel="${x => x.cellIndentLevel};"
28547
+ >
28548
+
28549
+ ${when((x, c) => (c.parent.currentActionMenuColumn === x.column) && x.column.actionMenuSlot, html `
28550
+ <slot
28551
+ name="${x => `row-action-menu-${x.column.actionMenuSlot}`}"
28552
+ slot="cellActionMenu"
28553
+ ></slot>
28554
+ `)}
28555
+ </${tableCellTag}>
28556
+ `)}
28483
28557
  `)}
28484
- `)}
28558
+ </span>
28485
28559
  </template>
28486
28560
  `;
28487
28561
 
@@ -28494,9 +28568,15 @@
28494
28568
  super(...arguments);
28495
28569
  this.selectable = false;
28496
28570
  this.selected = false;
28571
+ this.hideSelection = false;
28497
28572
  this.columns = [];
28498
28573
  this.nestingLevel = 0;
28499
28574
  this.menuOpen = false;
28575
+ // Programmatically updating the selection state of a checkbox fires the 'change' event.
28576
+ // Therefore, selection change events that occur due to programmatically updating
28577
+ // the selection checkbox 'checked' value should be ingored.
28578
+ // https://github.com/microsoft/fast/issues/5750
28579
+ this.ignoreSelectionChangeEvents = false;
28500
28580
  }
28501
28581
  get columnStates() {
28502
28582
  return this.columns.map((column, i) => {
@@ -28530,23 +28610,34 @@
28530
28610
  }
28531
28611
  return null;
28532
28612
  }
28613
+ onSelectionChange(event) {
28614
+ if (this.ignoreSelectionChangeEvents) {
28615
+ return;
28616
+ }
28617
+ const checkbox = event.target;
28618
+ const detail = {
28619
+ oldState: !checkbox.checked,
28620
+ newState: checkbox.checked
28621
+ };
28622
+ this.$emit('row-selection-toggle', detail);
28623
+ }
28533
28624
  onCellActionMenuBeforeToggle(event, column) {
28534
28625
  this.currentActionMenuColumn = column;
28535
- this.emitToggleEvent('row-action-menu-beforetoggle', event.detail, column);
28626
+ this.emitActionMenuToggleEvent('row-action-menu-beforetoggle', event.detail, column);
28536
28627
  }
28537
28628
  onCellActionMenuToggle(event, column) {
28538
28629
  this.menuOpen = event.detail.newState;
28539
- this.emitToggleEvent('row-action-menu-toggle', event.detail, column);
28630
+ this.emitActionMenuToggleEvent('row-action-menu-toggle', event.detail, column);
28540
28631
  }
28541
28632
  closeOpenActionMenus() {
28542
28633
  if (this.menuOpen) {
28543
- const cellWithMenuOpen = Array.from(this.shadowRoot.children).find(c => c instanceof TableCell && c.menuOpen);
28634
+ const cellWithMenuOpen = Array.from(this.cellContainer.children).find(c => c instanceof TableCell && c.menuOpen);
28544
28635
  if (cellWithMenuOpen?.actionMenuButton?.open) {
28545
28636
  cellWithMenuOpen.actionMenuButton.toggleButton.control.click();
28546
28637
  }
28547
28638
  }
28548
28639
  }
28549
- emitToggleEvent(eventType, menuButtonEventDetail, column) {
28640
+ emitActionMenuToggleEvent(eventType, menuButtonEventDetail, column) {
28550
28641
  const detail = {
28551
28642
  newState: menuButtonEventDetail.newState,
28552
28643
  oldState: menuButtonEventDetail.oldState,
@@ -28558,6 +28649,19 @@
28558
28649
  hasValidFieldNames(keys) {
28559
28650
  return keys.every(key => key !== undefined);
28560
28651
  }
28652
+ selectedChanged() {
28653
+ this.setSelectionCheckboxState();
28654
+ }
28655
+ selectionCheckboxChanged() {
28656
+ this.setSelectionCheckboxState();
28657
+ }
28658
+ setSelectionCheckboxState() {
28659
+ if (this.selectionCheckbox) {
28660
+ this.ignoreSelectionChangeEvents = true;
28661
+ this.selectionCheckbox.checked = this.selected;
28662
+ this.ignoreSelectionChangeEvents = false;
28663
+ }
28664
+ }
28561
28665
  }
28562
28666
  __decorate$1([
28563
28667
  attr({ attribute: 'record-id' })
@@ -28568,6 +28672,9 @@
28568
28672
  __decorate$1([
28569
28673
  attr({ mode: 'boolean' })
28570
28674
  ], TableRow.prototype, "selected", void 0);
28675
+ __decorate$1([
28676
+ attr({ attribute: 'hide-selection', mode: 'boolean' })
28677
+ ], TableRow.prototype, "hideSelection", void 0);
28571
28678
  __decorate$1([
28572
28679
  observable
28573
28680
  ], TableRow.prototype, "dataRecord", void 0);
@@ -28583,6 +28690,9 @@
28583
28690
  __decorate$1([
28584
28691
  attr({ attribute: 'menu-open', mode: 'boolean' })
28585
28692
  ], TableRow.prototype, "menuOpen", void 0);
28693
+ __decorate$1([
28694
+ observable
28695
+ ], TableRow.prototype, "selectionCheckbox", void 0);
28586
28696
  __decorate$1([
28587
28697
  volatile
28588
28698
  ], TableRow.prototype, "columnStates", null);
@@ -28604,10 +28714,6 @@
28604
28714
  align-items: center;
28605
28715
  height: calc(${controlHeight} + 2 * ${borderWidth});
28606
28716
  border-top: calc(2 * ${borderWidth}) solid ${tableRowBorderColor};
28607
- padding-left: calc(
28608
- ${smallPadding} * 2 + ${standardPadding} * 2 *
28609
- var(--ni-private-table-group-row-indent-level)
28610
- );
28611
28717
  }
28612
28718
 
28613
28719
  :host(:hover) {
@@ -28620,6 +28726,10 @@
28620
28726
  }
28621
28727
 
28622
28728
  .expand-collapse-button {
28729
+ margin-left: calc(
28730
+ ${smallPadding} * 2 + ${standardPadding} * 2 *
28731
+ var(--ni-private-table-group-row-indent-level)
28732
+ );
28623
28733
  width: ${controlSlimHeight};
28624
28734
  height: ${controlSlimHeight};
28625
28735
  }
@@ -28656,20 +28766,51 @@
28656
28766
  transition-duration: 0s;
28657
28767
  }
28658
28768
  }
28769
+
28770
+ .checkbox-container {
28771
+ display: flex;
28772
+ }
28773
+
28774
+ .selection-checkbox {
28775
+ margin-left: ${standardPadding};
28776
+ }
28777
+
28778
+ .selection-checkbox::part(label) {
28779
+ padding-left: 0px;
28780
+ }
28659
28781
  `;
28660
28782
 
28661
28783
  /* eslint-disable @typescript-eslint/indent */
28662
28784
  // prettier-ignore
28663
28785
  const template$8 = html `
28664
- <template @click=${x => x.onGroupExpandToggle()} style="--ni-private-table-group-row-indent-level: ${x => x.nestingLevel};">
28665
- <${buttonTag}
28666
- appearance="${ButtonAppearance.ghost}"
28667
- content-hidden
28668
- class="expand-collapse-button"
28669
- tabindex="-1"
28670
- >
28671
- <${iconArrowExpanderRightTag} ${ref('expandIcon')} slot="start" class="expander-icon ${x => x.animationClass}"></${iconArrowExpanderRightTag}>
28672
- </${buttonTag}>
28786
+ <template
28787
+ role="row"
28788
+ @click=${x => x.onGroupExpandToggle()}
28789
+ style="--ni-private-table-group-row-indent-level: ${x => x.nestingLevel};"
28790
+ >
28791
+ ${when(x => x.selectable, html `
28792
+ <span role="gridcell" class="checkbox-container">
28793
+ <${checkboxTag}
28794
+ ${ref('selectionCheckbox')}
28795
+ class="selection-checkbox"
28796
+ @change="${(x, c) => x.onSelectionChange(c.event)}"
28797
+ @click="${(_, c) => c.event.stopPropagation()}"
28798
+ >
28799
+ </${checkboxTag}>
28800
+ </span>
28801
+ `)}
28802
+
28803
+ <span role="gridcell">
28804
+ <${buttonTag}
28805
+ appearance="${ButtonAppearance.ghost}"
28806
+ content-hidden
28807
+ class="expand-collapse-button"
28808
+ tabindex="-1"
28809
+ >
28810
+ <${iconArrowExpanderRightTag} ${ref('expandIcon')} slot="start" class="expander-icon ${x => x.animationClass}"></${iconArrowExpanderRightTag}>
28811
+ </${buttonTag}>
28812
+ </span>
28813
+
28673
28814
  <div class="group-row-header-content">
28674
28815
  ${x => x.groupColumn?.columnInternals.groupHeaderViewTemplate}
28675
28816
  <div class="group-row-child-count">(${x => x.leafItemCount})</span>
@@ -28686,10 +28827,17 @@
28686
28827
  super(...arguments);
28687
28828
  this.nestingLevel = 0;
28688
28829
  this.expanded = false;
28830
+ this.selectable = false;
28831
+ this.selectionState = TableRowSelectionState.notSelected;
28689
28832
  /**
28690
28833
  * @internal
28691
28834
  */
28692
28835
  this.animationClass = '';
28836
+ // Programmatically updating the selection state of a checkbox fires the 'change' event.
28837
+ // Therefore, selection change events that occur due to programmatically updating
28838
+ // the selection checkbox 'checked' value should be ingored.
28839
+ // https://github.com/microsoft/fast/issues/5750
28840
+ this.ignoreSelectionChangeEvents = false;
28693
28841
  this.removeAnimatingClass = () => {
28694
28842
  this.animationClass = '';
28695
28843
  this.expandIcon.removeEventListener('transitionend', this.removeAnimatingClass);
@@ -28706,6 +28854,33 @@
28706
28854
  this.animationClass = 'animating';
28707
28855
  this.expandIcon.addEventListener('transitionend', this.removeAnimatingClass);
28708
28856
  }
28857
+ /** @internal */
28858
+ onSelectionChange(event) {
28859
+ if (this.ignoreSelectionChangeEvents) {
28860
+ return;
28861
+ }
28862
+ const checkbox = event.target;
28863
+ const detail = {
28864
+ oldState: !checkbox.checked,
28865
+ newState: checkbox.checked
28866
+ };
28867
+ this.$emit('group-selection-toggle', detail);
28868
+ }
28869
+ selectionStateChanged() {
28870
+ this.setSelectionCheckboxState();
28871
+ }
28872
+ selectionCheckboxChanged() {
28873
+ this.setSelectionCheckboxState();
28874
+ }
28875
+ setSelectionCheckboxState() {
28876
+ if (this.selectionCheckbox) {
28877
+ this.ignoreSelectionChangeEvents = true;
28878
+ this.selectionCheckbox.checked = this.selectionState === TableRowSelectionState.selected;
28879
+ this.selectionCheckbox.indeterminate = this.selectionState
28880
+ === TableRowSelectionState.partiallySelected;
28881
+ this.ignoreSelectionChangeEvents = false;
28882
+ }
28883
+ }
28709
28884
  }
28710
28885
  __decorate$1([
28711
28886
  observable
@@ -28722,6 +28897,15 @@
28722
28897
  __decorate$1([
28723
28898
  attr({ mode: 'boolean' })
28724
28899
  ], TableGroupRow.prototype, "expanded", void 0);
28900
+ __decorate$1([
28901
+ attr({ mode: 'boolean' })
28902
+ ], TableGroupRow.prototype, "selectable", void 0);
28903
+ __decorate$1([
28904
+ attr({ attribute: 'selection-state' })
28905
+ ], TableGroupRow.prototype, "selectionState", void 0);
28906
+ __decorate$1([
28907
+ observable
28908
+ ], TableGroupRow.prototype, "selectionCheckbox", void 0);
28725
28909
  __decorate$1([
28726
28910
  observable
28727
28911
  ], TableGroupRow.prototype, "animationClass", void 0);
@@ -28735,7 +28919,11 @@
28735
28919
 
28736
28920
  // prettier-ignore
28737
28921
  const template$7 = html `
28738
- <template role="grid" ${children$1({ property: 'childItems', filter: elements() })}>
28922
+ <template
28923
+ role="grid"
28924
+ aria-multiselectable="${x => x.ariaMultiSelectable}"
28925
+ ${children$1({ property: 'childItems', filter: elements() })}
28926
+ >
28739
28927
  <div class="table-container" style="
28740
28928
  --ni-private-table-scroll-x: -${x => x.scrollX}px;
28741
28929
  --ni-private-table-header-scrollbar-spacer-width: ${x => x.virtualizer.headerContainerMarginRight}px;
@@ -28745,18 +28933,31 @@
28745
28933
  ">
28746
28934
  <div role="rowgroup" class="header-container">
28747
28935
  <div class="header-row" role="row">
28748
- ${repeat(x => x.columns, html `
28749
- ${when(x => !x.columnHidden, html `
28750
- <${tableHeaderTag}
28751
- class="header"
28752
- sort-direction="${x => (typeof x.sortIndex === 'number' ? x.sortDirection : TableColumnSortDirection.none)}"
28753
- ?first-sorted-column="${(x, c) => x === c.parent.firstSortedColumn}"
28936
+ ${when(x => x.selectionMode === TableRowSelectionMode.multiple, html `
28937
+ <span role="columnheader" class="checkbox-container">
28938
+ <${checkboxTag}
28939
+ ${ref('selectionCheckbox')}
28940
+ class="${x => `selection-checkbox ${x.selectionMode ?? ''}`}"
28941
+ @change="${async (x, c) => x.onAllRowsSelectionChange(c.event)}"
28754
28942
  >
28755
- <slot name="${x => x.slot}"></slot>
28756
- </${tableHeaderTag}>
28757
- `)}
28943
+ </${checkboxTag}>
28944
+ </span>
28758
28945
  `)}
28759
- <div class="header-scrollbar-spacer"></div>
28946
+
28947
+ <span class="column-header-container">
28948
+ ${repeat(x => x.columns, html `
28949
+ ${when(x => !x.columnHidden, html `
28950
+ <${tableHeaderTag}
28951
+ class="header"
28952
+ sort-direction="${x => (typeof x.sortIndex === 'number' ? x.sortDirection : TableColumnSortDirection.none)}"
28953
+ ?first-sorted-column="${(x, c) => x === c.parent.firstSortedColumn}"
28954
+ >
28955
+ <slot name="${x => x.slot}"></slot>
28956
+ </${tableHeaderTag}>
28957
+ `)}
28958
+ `)}
28959
+ <div class="header-scrollbar-spacer"></div>
28960
+ </span>
28760
28961
  </div>
28761
28962
  </div>
28762
28963
  <div class="table-viewport" ${ref('viewport')}>
@@ -28773,8 +28974,11 @@
28773
28974
  :nestingLevel="${(x, c) => c.parent.tableData[x.index]?.nestingLevel}"
28774
28975
  :leafItemCount="${(x, c) => c.parent.tableData[x.index]?.leafItemCount}"
28775
28976
  :groupColumn="${(x, c) => c.parent.tableData[x.index]?.groupColumn}"
28977
+ ?selectable="${(_, c) => c.parent.selectionMode === TableRowSelectionMode.multiple}"
28978
+ selection-state="${(x, c) => c.parent.tableData[x.index]?.selectionState}"
28979
+ @group-selection-toggle="${async (x, c) => c.parent.onRowSelectionToggle(x.index, c.event)}"
28776
28980
  @group-expand-toggle="${(x, c) => c.parent.handleGroupRowExpanded(x.index, c.event)}"
28777
- >
28981
+ >
28778
28982
  </${tableGroupRowTag}>
28779
28983
  `)}
28780
28984
  ${when((x, c) => !c.parent.tableData[x.index]?.isGrouped, html `
@@ -28783,12 +28987,14 @@
28783
28987
  record-id="${(x, c) => c.parent.tableData[x.index]?.id}"
28784
28988
  ?selectable="${(_, c) => c.parent.selectionMode !== TableRowSelectionMode.none}"
28785
28989
  ?selected="${(x, c) => c.parent.tableData[x.index]?.selectionState === TableRowSelectionState.selected}"
28990
+ ?hide-selection="${(_, c) => c.parent.selectionMode !== TableRowSelectionMode.multiple}"
28786
28991
  :dataRecord="${(x, c) => c.parent.tableData[x.index]?.record}"
28787
28992
  :columns="${(_, c) => c.parent.columns}"
28788
28993
  :nestingLevel="${(x, c) => c.parent.tableData[x.index]?.nestingLevel}"
28789
28994
  @click="${async (x, c) => c.parent.onRowClick(x.index)}"
28790
- @row-action-menu-beforetoggle="${(_, c) => c.parent.onRowActionMenuBeforeToggle(c.event)}"
28791
- @row-action-menu-toggle="${(_, c) => c.parent.onRowActionMenuToggle(c.event)}"
28995
+ @row-selection-toggle="${async (x, c) => c.parent.onRowSelectionToggle(x.index, c.event)}"
28996
+ @row-action-menu-beforetoggle="${async (x, c) => c.parent.onRowActionMenuBeforeToggle(x.index, c.event)}"
28997
+ @row-action-menu-toggle="${async (_, c) => c.parent.onRowActionMenuToggle(c.event)}"
28792
28998
  >
28793
28999
  ${when((x, c) => c.parent.openActionMenuRecordId === c.parent.tableData[x.index]?.id, html `
28794
29000
  ${repeat((_, c) => c.parent.actionMenuSlots, html `
@@ -29770,11 +29976,20 @@
29770
29976
  * @internal
29771
29977
  */
29772
29978
  this.scrollX = 0;
29979
+ /**
29980
+ * @internal
29981
+ */
29982
+ this.selectionState = TableRowSelectionState.notSelected;
29773
29983
  this.tableValidator = new TableValidator();
29774
29984
  this.updateTracker = new UpdateTracker(this);
29775
29985
  this.columnNotifiers = [];
29776
29986
  this.isInitialized = false;
29777
29987
  this.collapsedRows = new Set();
29988
+ // Programmatically updating the selection state of a checkbox fires the 'change' event.
29989
+ // Therefore, selection change events that occur due to programmatically updating
29990
+ // the selection checkbox 'checked' value should be ingored.
29991
+ // https://github.com/microsoft/fast/issues/5750
29992
+ this.ignoreSelectionChangeEvents = false;
29778
29993
  this.onViewPortScroll = (event) => {
29779
29994
  this.scrollX = event.target.scrollLeft;
29780
29995
  };
@@ -29827,7 +30042,9 @@
29827
30042
  grouping: [],
29828
30043
  expanded: true // Workaround until we can apply a fix to TanStack regarding leveraging our getIsRowExpanded implementation
29829
30044
  },
29830
- enableRowSelection: false,
30045
+ enableRowSelection: row => !row.getIsGrouped(),
30046
+ enableMultiRowSelection: false,
30047
+ enableSubRowSelection: false,
29831
30048
  enableSorting: true,
29832
30049
  enableGrouping: true,
29833
30050
  renderFallbackValue: null,
@@ -29914,37 +30131,74 @@
29914
30131
  }
29915
30132
  }
29916
30133
  /** @internal */
29917
- async onRowClick(rowIndex) {
30134
+ async onRowSelectionToggle(rowIndex, event) {
30135
+ event.stopImmediatePropagation();
29918
30136
  if (this.selectionMode === TableRowSelectionMode.none) {
29919
30137
  return;
29920
30138
  }
29921
- const row = this.table.getRowModel().rows[rowIndex];
29922
- if (!row) {
29923
- return;
30139
+ const rowState = this.tableData[rowIndex];
30140
+ if (rowState?.isGrouped
30141
+ && rowState?.selectionState === TableRowSelectionState.selected) {
30142
+ // Work around for https://github.com/TanStack/table/issues/4759
30143
+ // Manually deselect all leaf rows when a fully selected group is being deselected.
30144
+ this.deselectAllLeafRows(rowIndex);
29924
30145
  }
29925
- const currentSelection = await this.getSelectedRecordIds();
29926
- if (currentSelection.length === 1 && currentSelection[0] === row.id) {
29927
- // The clicked row is already the only selected row. Do nothing.
30146
+ else {
30147
+ this.table
30148
+ .getRowModel()
30149
+ .rows[rowIndex]?.toggleSelected(event.detail.newState);
30150
+ }
30151
+ await this.emitSelectionChangeEvent();
30152
+ }
30153
+ /** @internal */
30154
+ async onRowClick(rowIndex) {
30155
+ return this.selectSingleRow(rowIndex);
30156
+ }
30157
+ /** @internal */
30158
+ async onAllRowsSelectionChange(event) {
30159
+ event.stopPropagation();
30160
+ if (this.ignoreSelectionChangeEvents) {
29928
30161
  return;
29929
30162
  }
29930
- this.table.toggleAllRowsSelected(false);
29931
- row.toggleSelected(true);
30163
+ this.table.toggleAllRowsSelected(this.selectionCheckbox.checked);
29932
30164
  await this.emitSelectionChangeEvent();
29933
30165
  }
29934
30166
  /** @internal */
29935
- onRowActionMenuBeforeToggle(event) {
30167
+ async onRowActionMenuBeforeToggle(rowIndex, event) {
29936
30168
  event.stopImmediatePropagation();
30169
+ let recordIds = event.detail.recordIds;
30170
+ if (this.selectionMode !== TableRowSelectionMode.none) {
30171
+ const row = this.table.getRowModel().rows[rowIndex];
30172
+ if (row && !row.getIsSelected()) {
30173
+ await this.selectSingleRow(rowIndex);
30174
+ }
30175
+ else {
30176
+ recordIds = await this.getSelectedRecordIds();
30177
+ }
30178
+ }
29937
30179
  this.openActionMenuRecordId = event.detail.recordIds[0];
29938
- this.$emit('action-menu-beforetoggle', event.detail);
30180
+ const detail = {
30181
+ ...event.detail,
30182
+ recordIds
30183
+ };
30184
+ this.$emit('action-menu-beforetoggle', detail);
29939
30185
  }
29940
30186
  /** @internal */
29941
- onRowActionMenuToggle(event) {
30187
+ async onRowActionMenuToggle(event) {
29942
30188
  event.stopImmediatePropagation();
29943
- this.$emit('action-menu-toggle', event.detail);
30189
+ const recordIds = this.selectionMode === TableRowSelectionMode.multiple
30190
+ ? await this.getSelectedRecordIds()
30191
+ : event.detail.recordIds;
30192
+ const detail = {
30193
+ ...event.detail,
30194
+ recordIds
30195
+ };
30196
+ this.$emit('action-menu-toggle', detail);
29944
30197
  if (!event.detail.newState) {
29945
30198
  this.openActionMenuRecordId = undefined;
29946
30199
  }
29947
30200
  }
30201
+ /** @internal */
29948
30202
  handleGroupRowExpanded(rowIndex, event) {
29949
30203
  this.toggleGroupExpanded(rowIndex);
29950
30204
  event.stopPropagation();
@@ -29964,6 +30218,16 @@
29964
30218
  this.updateRowGridColumns();
29965
30219
  }
29966
30220
  }
30221
+ get ariaMultiSelectable() {
30222
+ switch (this.selectionMode) {
30223
+ case TableRowSelectionMode.multiple:
30224
+ return 'true';
30225
+ case TableRowSelectionMode.single:
30226
+ return 'false';
30227
+ default:
30228
+ return null;
30229
+ }
30230
+ }
29967
30231
  selectionModeChanged(_prev, _next) {
29968
30232
  if (!this.$fastController.isConnected) {
29969
30233
  return;
@@ -30050,7 +30314,8 @@
30050
30314
  updatedOptions.state.rowSelection = {};
30051
30315
  }
30052
30316
  if (this.updateTracker.updateSelectionMode) {
30053
- updatedOptions.enableRowSelection = this.selectionMode !== TableRowSelectionMode.none;
30317
+ updatedOptions.enableMultiRowSelection = this.selectionMode === TableRowSelectionMode.multiple;
30318
+ updatedOptions.enableSubRowSelection = this.selectionMode === TableRowSelectionMode.multiple;
30054
30319
  updatedOptions.state.rowSelection = {};
30055
30320
  }
30056
30321
  if (this.updateTracker.requiresTanStackDataReset) {
@@ -30093,15 +30358,29 @@
30093
30358
  };
30094
30359
  this.$emit('selection-change', detail);
30095
30360
  }
30361
+ selectionStateChanged() {
30362
+ this.setSelectionCheckboxState();
30363
+ }
30364
+ selectionCheckboxChanged() {
30365
+ this.setSelectionCheckboxState();
30366
+ }
30367
+ setSelectionCheckboxState() {
30368
+ if (this.selectionCheckbox) {
30369
+ this.ignoreSelectionChangeEvents = true;
30370
+ this.selectionCheckbox.checked = this.selectionState === TableRowSelectionState.selected;
30371
+ this.selectionCheckbox.indeterminate = this.selectionState
30372
+ === TableRowSelectionState.partiallySelected;
30373
+ this.ignoreSelectionChangeEvents = false;
30374
+ }
30375
+ }
30096
30376
  refreshRows() {
30377
+ this.selectionState = this.getTableSelectionState();
30097
30378
  const rows = this.table.getRowModel().rows;
30098
30379
  this.tableData = rows.map(row => {
30099
30380
  const rowState = {
30100
30381
  record: row.original,
30101
30382
  id: row.id,
30102
- selectionState: row.getIsSelected()
30103
- ? TableRowSelectionState.selected
30104
- : TableRowSelectionState.notSelected,
30383
+ selectionState: this.getRowSelectionState(row),
30105
30384
  isGrouped: row.getIsGrouped(),
30106
30385
  isExpanded: row.getIsExpanded(),
30107
30386
  groupRowValue: row.getIsGrouped()
@@ -30118,6 +30397,55 @@
30118
30397
  });
30119
30398
  this.virtualizer.dataChanged();
30120
30399
  }
30400
+ getTableSelectionState() {
30401
+ if (this.table.getIsAllRowsSelected()) {
30402
+ return TableRowSelectionState.selected;
30403
+ }
30404
+ if (this.table.getIsSomeRowsSelected()) {
30405
+ return TableRowSelectionState.partiallySelected;
30406
+ }
30407
+ return TableRowSelectionState.notSelected;
30408
+ }
30409
+ getRowSelectionState(row) {
30410
+ if (row.getIsGrouped()) {
30411
+ return this.getGroupedRowSelectionState(row);
30412
+ }
30413
+ return row.getIsSelected()
30414
+ ? TableRowSelectionState.selected
30415
+ : TableRowSelectionState.notSelected;
30416
+ }
30417
+ getGroupedRowSelectionState(groupedRow) {
30418
+ const subRows = groupedRow.subRows ?? [];
30419
+ let foundSelectedRow = false;
30420
+ let foundNotSelectedRow = false;
30421
+ for (const row of subRows) {
30422
+ if (row.getIsGrouped()) {
30423
+ const subGroupRowSelectionState = this.getGroupedRowSelectionState(row);
30424
+ switch (subGroupRowSelectionState) {
30425
+ case TableRowSelectionState.notSelected:
30426
+ foundNotSelectedRow = true;
30427
+ break;
30428
+ case TableRowSelectionState.selected:
30429
+ foundSelectedRow = true;
30430
+ break;
30431
+ default:
30432
+ return TableRowSelectionState.partiallySelected;
30433
+ }
30434
+ }
30435
+ else if (row.getIsSelected()) {
30436
+ foundSelectedRow = true;
30437
+ }
30438
+ else {
30439
+ foundNotSelectedRow = true;
30440
+ }
30441
+ if (foundSelectedRow && foundNotSelectedRow) {
30442
+ return TableRowSelectionState.partiallySelected;
30443
+ }
30444
+ }
30445
+ return foundSelectedRow
30446
+ ? TableRowSelectionState.selected
30447
+ : TableRowSelectionState.notSelected;
30448
+ }
30121
30449
  getGroupRowColumn(row) {
30122
30450
  const groupedId = row.groupingColumnId;
30123
30451
  if (groupedId !== undefined) {
@@ -30134,6 +30462,39 @@
30134
30462
  this.table.setOptions(this.options);
30135
30463
  this.refreshRows();
30136
30464
  }
30465
+ async selectSingleRow(rowIndex) {
30466
+ if (this.selectionMode === TableRowSelectionMode.none) {
30467
+ return;
30468
+ }
30469
+ const row = this.table.getRowModel().rows[rowIndex];
30470
+ if (!row) {
30471
+ return;
30472
+ }
30473
+ const currentSelection = await this.getSelectedRecordIds();
30474
+ if (currentSelection.length === 1 && currentSelection[0] === row.id) {
30475
+ // The clicked row is already the only selected row. Do nothing.
30476
+ return;
30477
+ }
30478
+ this.table.toggleAllRowsSelected(false);
30479
+ row.toggleSelected(true);
30480
+ await this.emitSelectionChangeEvent();
30481
+ }
30482
+ deselectAllLeafRows(rowIndex) {
30483
+ const groupRow = this.table.getRowModel().rows[rowIndex];
30484
+ const leafRowIds = groupRow
30485
+ .getLeafRows()
30486
+ .filter(leafRow => leafRow.getLeafRows().length === 0)
30487
+ .map(leafRow => leafRow.id);
30488
+ const selectionState = this.table.getState().rowSelection;
30489
+ for (const id of leafRowIds) {
30490
+ delete selectionState[id];
30491
+ }
30492
+ this.updateTableOptions({
30493
+ state: {
30494
+ rowSelection: selectionState
30495
+ }
30496
+ });
30497
+ }
30137
30498
  toggleGroupExpanded(rowIndex) {
30138
30499
  const row = this.table.getRowModel().rows[rowIndex];
30139
30500
  const wasExpanded = row.getIsExpanded();
@@ -30188,10 +30549,12 @@
30188
30549
  }
30189
30550
  const tanstackSelectionState = {};
30190
30551
  const selectableRecordIds = this.tableValidator.getPresentRecordIds(recordIdsToSelect);
30191
- if (selectableRecordIds.length) {
30192
- // In single selection mode, only select the first record ID that is requested
30193
- const firstSelectableRecordId = selectableRecordIds[0];
30194
- tanstackSelectionState[firstSelectableRecordId] = true;
30552
+ for (const recordId of selectableRecordIds) {
30553
+ tanstackSelectionState[recordId] = true;
30554
+ if (this.selectionMode === TableRowSelectionMode.single) {
30555
+ // In single selection mode, only select the first record ID that is requested
30556
+ break;
30557
+ }
30195
30558
  }
30196
30559
  return tanstackSelectionState;
30197
30560
  }
@@ -30229,6 +30592,12 @@
30229
30592
  __decorate$1([
30230
30593
  observable
30231
30594
  ], Table.prototype, "rowGridColumns", void 0);
30595
+ __decorate$1([
30596
+ observable
30597
+ ], Table.prototype, "selectionState", void 0);
30598
+ __decorate$1([
30599
+ observable
30600
+ ], Table.prototype, "selectionCheckbox", void 0);
30232
30601
  __decorate$1([
30233
30602
  observable
30234
30603
  ], Table.prototype, "firstSortedColumn", void 0);