@ni/nimble-components 18.12.0 → 18.12.2

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 (31) hide show
  1. package/dist/all-components-bundle.js +440 -87
  2. package/dist/all-components-bundle.js.map +1 -1
  3. package/dist/all-components-bundle.min.js +1013 -878
  4. package/dist/all-components-bundle.min.js.map +1 -1
  5. package/dist/esm/table/components/cell/template.js +1 -0
  6. package/dist/esm/table/components/cell/template.js.map +1 -1
  7. package/dist/esm/table/components/group-row/index.d.ts +14 -1
  8. package/dist/esm/table/components/group-row/index.js +44 -0
  9. package/dist/esm/table/components/group-row/index.js.map +1 -1
  10. package/dist/esm/table/components/group-row/styles.js +16 -4
  11. package/dist/esm/table/components/group-row/styles.js.map +1 -1
  12. package/dist/esm/table/components/group-row/template.js +30 -10
  13. package/dist/esm/table/components/group-row/template.js.map +1 -1
  14. package/dist/esm/table/components/row/index.d.ts +12 -2
  15. package/dist/esm/table/components/row/index.js +40 -4
  16. package/dist/esm/table/components/row/index.js.map +1 -1
  17. package/dist/esm/table/components/row/styles.js +21 -4
  18. package/dist/esm/table/components/row/styles.js.map +1 -1
  19. package/dist/esm/table/components/row/template.js +36 -20
  20. package/dist/esm/table/components/row/template.js.map +1 -1
  21. package/dist/esm/table/index.d.ts +27 -4
  22. package/dist/esm/table/index.js +185 -22
  23. package/dist/esm/table/index.js.map +1 -1
  24. package/dist/esm/table/styles.js +32 -9
  25. package/dist/esm/table/styles.js.map +1 -1
  26. package/dist/esm/table/template.js +37 -14
  27. package/dist/esm/table/template.js.map +1 -1
  28. package/dist/esm/table/types.d.ts +11 -0
  29. package/dist/esm/table/types.js +4 -2
  30. package/dist/esm/table/types.js.map +1 -1
  31. package/package.json +14 -14
@@ -16374,7 +16374,7 @@
16374
16374
 
16375
16375
  /**
16376
16376
  * Do not edit directly
16377
- * Generated on Thu, 20 Oct 2022 19:57:29 GMT
16377
+ * Generated on Wed, 19 Apr 2023 17:42:08 GMT
16378
16378
  */
16379
16379
  const Information100DarkUi = "#a46eff";
16380
16380
  const Information100LightUi = "#804ad9";
@@ -20098,7 +20098,7 @@
20098
20098
  indeterminateIndicator: minus16X16.data
20099
20099
  });
20100
20100
  DesignSystem.getOrCreate().withPrefix('nimble').register(nimbleCheckbox());
20101
- DesignSystem.tagFor(Checkbox);
20101
+ const checkboxTag = DesignSystem.tagFor(Checkbox);
20102
20102
 
20103
20103
  const styles$x = css `
20104
20104
  ${styles$M}
@@ -27824,7 +27824,8 @@
27824
27824
  */
27825
27825
  const TableRowSelectionMode = {
27826
27826
  none: undefined,
27827
- single: 'single'
27827
+ single: 'single',
27828
+ multiple: 'multiple'
27828
27829
  };
27829
27830
  /**
27830
27831
  * @internal
@@ -27833,7 +27834,8 @@
27833
27834
  */
27834
27835
  const TableRowSelectionState = {
27835
27836
  notSelected: 'notSelected',
27836
- selected: 'selected'
27837
+ selected: 'selected',
27838
+ partiallySelected: 'partiallySelected'
27837
27839
  };
27838
27840
 
27839
27841
  /**
@@ -28203,15 +28205,20 @@
28203
28205
  }
28204
28206
 
28205
28207
  .header-row {
28206
- display: grid;
28208
+ display: flex;
28207
28209
  background: ${applicationBackgroundColor};
28208
28210
  position: relative;
28209
28211
  width: fit-content;
28210
28212
  min-width: 100%;
28211
- grid-template-columns: var(--ni-private-table-row-grid-columns) auto;
28212
28213
  left: var(--ni-private-table-scroll-x);
28213
28214
  }
28214
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
+
28215
28222
  .header-scrollbar-spacer {
28216
28223
  width: var(--ni-private-table-header-scrollbar-spacer-width);
28217
28224
  }
@@ -28220,6 +28227,18 @@
28220
28227
  flex: 1;
28221
28228
  }
28222
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
+
28223
28242
  .row {
28224
28243
  background: ${applicationBackgroundColor};
28225
28244
  position: relative;
@@ -28234,15 +28253,18 @@
28234
28253
  pointer-events: none;
28235
28254
  }
28236
28255
 
28237
- :host([selection-mode='single']) .row:hover::before {
28256
+ :host([selection-mode='single']) .row:hover::before,
28257
+ :host([selection-mode='multiple']) .row:hover::before {
28238
28258
  background: ${fillHoverColor};
28239
28259
  }
28240
28260
 
28241
- :host([selection-mode='single']) .row[selected]::before {
28261
+ :host([selection-mode='single']) .row[selected]::before,
28262
+ :host([selection-mode='multiple']) .row[selected]::before {
28242
28263
  background: ${fillSelectedColor};
28243
28264
  }
28244
28265
 
28245
- :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 {
28246
28268
  background: ${fillHoverSelectedColor};
28247
28269
  }
28248
28270
  `.withBehaviors(themeBehavior(Theme.color, css `
@@ -28259,15 +28281,18 @@
28259
28281
  background: ${fillHoverColor};
28260
28282
  }
28261
28283
 
28262
- :host([selection-mode='single']) .row:hover::before {
28284
+ :host([selection-mode='single']) .row:hover::before,
28285
+ :host([selection-mode='multiple']) .row:hover::before {
28263
28286
  background: ${hexToRgbaCssColor(White, 0.15)};
28264
28287
  }
28265
28288
 
28266
- :host([selection-mode='single']) .row[selected]::before {
28289
+ :host([selection-mode='single']) .row[selected]::before,
28290
+ :host([selection-mode='multiple']) .row[selected]::before {
28267
28291
  background: ${hexToRgbaCssColor(White, 0.25)};
28268
28292
  }
28269
28293
 
28270
- :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 {
28271
28296
  background: ${hexToRgbaCssColor(White, 0.2)};
28272
28297
  }
28273
28298
  `));
@@ -28348,16 +28373,33 @@
28348
28373
  const tableHeaderTag = DesignSystem.tagFor(TableHeader);
28349
28374
 
28350
28375
  const styles$e = css `
28351
- ${display('grid')}
28376
+ ${display('flex')}
28352
28377
 
28353
28378
  :host {
28354
28379
  height: calc(${controlHeight} + 2 * ${borderWidth});
28355
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%;
28356
28400
  grid-auto-flow: column;
28357
28401
  grid-auto-columns: 1fr;
28358
28402
  grid-template-columns: var(--ni-private-table-row-grid-columns) auto;
28359
- width: fit-content;
28360
- min-width: 100%;
28361
28403
  }
28362
28404
 
28363
28405
  nimble-table-cell {
@@ -28418,6 +28460,7 @@
28418
28460
  appearance="${ButtonAppearance.ghost}"
28419
28461
  @beforetoggle="${(x, c) => x.onActionMenuBeforeToggle(c.event)}"
28420
28462
  @toggle="${(x, c) => x.onActionMenuToggle(c.event)}"
28463
+ @click="${(_, c) => c.event.stopPropagation()}"
28421
28464
  class="action-menu"
28422
28465
  >
28423
28466
  <${iconThreeDotsLineTag} slot="start"></${iconThreeDotsLineTag}>
@@ -28476,28 +28519,43 @@
28476
28519
  // prettier-ignore
28477
28520
  const template$9 = html `
28478
28521
  <template role="row" aria-selected=${x => x.ariaSelected}>
28479
- ${repeat(x => x.columnStates, html `
28480
- ${when(x => !x.column.columnHidden, html `
28481
- <${tableCellTag}
28482
- class="cell"
28483
- :cellState="${x => x.cellState}"
28484
- :cellViewTemplate="${x => x.column.columnInternals.cellViewTemplate}"
28485
- ?has-action-menu="${x => !!x.column.actionMenuSlot}"
28486
- action-menu-label="${x => x.column.actionMenuLabel}"
28487
- @cell-action-menu-beforetoggle="${(x, c) => c.parent.onCellActionMenuBeforeToggle(c.event, x.column)}"
28488
- @cell-action-menu-toggle="${(x, c) => c.parent.onCellActionMenuToggle(c.event, x.column)}"
28489
- :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()}"
28490
28530
  >
28531
+ </${checkboxTag}>
28532
+ </span>
28533
+ `)}
28491
28534
 
28492
- ${when((x, c) => (c.parent.currentActionMenuColumn === x.column) && x.column.actionMenuSlot, html `
28493
- <slot
28494
- name="${x => `row-action-menu-${x.column.actionMenuSlot}`}"
28495
- slot="cellActionMenu"
28496
- ></slot>
28497
- `)}
28498
- </${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
+ `)}
28499
28557
  `)}
28500
- `)}
28558
+ </span>
28501
28559
  </template>
28502
28560
  `;
28503
28561
 
@@ -28510,9 +28568,15 @@
28510
28568
  super(...arguments);
28511
28569
  this.selectable = false;
28512
28570
  this.selected = false;
28571
+ this.hideSelection = false;
28513
28572
  this.columns = [];
28514
28573
  this.nestingLevel = 0;
28515
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;
28516
28580
  }
28517
28581
  get columnStates() {
28518
28582
  return this.columns.map((column, i) => {
@@ -28546,23 +28610,34 @@
28546
28610
  }
28547
28611
  return null;
28548
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
+ }
28549
28624
  onCellActionMenuBeforeToggle(event, column) {
28550
28625
  this.currentActionMenuColumn = column;
28551
- this.emitToggleEvent('row-action-menu-beforetoggle', event.detail, column);
28626
+ this.emitActionMenuToggleEvent('row-action-menu-beforetoggle', event.detail, column);
28552
28627
  }
28553
28628
  onCellActionMenuToggle(event, column) {
28554
28629
  this.menuOpen = event.detail.newState;
28555
- this.emitToggleEvent('row-action-menu-toggle', event.detail, column);
28630
+ this.emitActionMenuToggleEvent('row-action-menu-toggle', event.detail, column);
28556
28631
  }
28557
28632
  closeOpenActionMenus() {
28558
28633
  if (this.menuOpen) {
28559
- 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);
28560
28635
  if (cellWithMenuOpen?.actionMenuButton?.open) {
28561
28636
  cellWithMenuOpen.actionMenuButton.toggleButton.control.click();
28562
28637
  }
28563
28638
  }
28564
28639
  }
28565
- emitToggleEvent(eventType, menuButtonEventDetail, column) {
28640
+ emitActionMenuToggleEvent(eventType, menuButtonEventDetail, column) {
28566
28641
  const detail = {
28567
28642
  newState: menuButtonEventDetail.newState,
28568
28643
  oldState: menuButtonEventDetail.oldState,
@@ -28574,6 +28649,19 @@
28574
28649
  hasValidFieldNames(keys) {
28575
28650
  return keys.every(key => key !== undefined);
28576
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
+ }
28577
28665
  }
28578
28666
  __decorate$1([
28579
28667
  attr({ attribute: 'record-id' })
@@ -28584,6 +28672,9 @@
28584
28672
  __decorate$1([
28585
28673
  attr({ mode: 'boolean' })
28586
28674
  ], TableRow.prototype, "selected", void 0);
28675
+ __decorate$1([
28676
+ attr({ attribute: 'hide-selection', mode: 'boolean' })
28677
+ ], TableRow.prototype, "hideSelection", void 0);
28587
28678
  __decorate$1([
28588
28679
  observable
28589
28680
  ], TableRow.prototype, "dataRecord", void 0);
@@ -28599,6 +28690,9 @@
28599
28690
  __decorate$1([
28600
28691
  attr({ attribute: 'menu-open', mode: 'boolean' })
28601
28692
  ], TableRow.prototype, "menuOpen", void 0);
28693
+ __decorate$1([
28694
+ observable
28695
+ ], TableRow.prototype, "selectionCheckbox", void 0);
28602
28696
  __decorate$1([
28603
28697
  volatile
28604
28698
  ], TableRow.prototype, "columnStates", null);
@@ -28620,10 +28714,6 @@
28620
28714
  align-items: center;
28621
28715
  height: calc(${controlHeight} + 2 * ${borderWidth});
28622
28716
  border-top: calc(2 * ${borderWidth}) solid ${tableRowBorderColor};
28623
- padding-left: calc(
28624
- ${smallPadding} * 2 + ${standardPadding} * 2 *
28625
- var(--ni-private-table-group-row-indent-level)
28626
- );
28627
28717
  }
28628
28718
 
28629
28719
  :host(:hover) {
@@ -28636,6 +28726,10 @@
28636
28726
  }
28637
28727
 
28638
28728
  .expand-collapse-button {
28729
+ margin-left: calc(
28730
+ ${smallPadding} * 2 + ${standardPadding} * 2 *
28731
+ var(--ni-private-table-group-row-indent-level)
28732
+ );
28639
28733
  width: ${controlSlimHeight};
28640
28734
  height: ${controlSlimHeight};
28641
28735
  }
@@ -28672,20 +28766,51 @@
28672
28766
  transition-duration: 0s;
28673
28767
  }
28674
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
+ }
28675
28781
  `;
28676
28782
 
28677
28783
  /* eslint-disable @typescript-eslint/indent */
28678
28784
  // prettier-ignore
28679
28785
  const template$8 = html `
28680
- <template @click=${x => x.onGroupExpandToggle()} style="--ni-private-table-group-row-indent-level: ${x => x.nestingLevel};">
28681
- <${buttonTag}
28682
- appearance="${ButtonAppearance.ghost}"
28683
- content-hidden
28684
- class="expand-collapse-button"
28685
- tabindex="-1"
28686
- >
28687
- <${iconArrowExpanderRightTag} ${ref('expandIcon')} slot="start" class="expander-icon ${x => x.animationClass}"></${iconArrowExpanderRightTag}>
28688
- </${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
+
28689
28814
  <div class="group-row-header-content">
28690
28815
  ${x => x.groupColumn?.columnInternals.groupHeaderViewTemplate}
28691
28816
  <div class="group-row-child-count">(${x => x.leafItemCount})</span>
@@ -28702,10 +28827,17 @@
28702
28827
  super(...arguments);
28703
28828
  this.nestingLevel = 0;
28704
28829
  this.expanded = false;
28830
+ this.selectable = false;
28831
+ this.selectionState = TableRowSelectionState.notSelected;
28705
28832
  /**
28706
28833
  * @internal
28707
28834
  */
28708
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;
28709
28841
  this.removeAnimatingClass = () => {
28710
28842
  this.animationClass = '';
28711
28843
  this.expandIcon.removeEventListener('transitionend', this.removeAnimatingClass);
@@ -28722,6 +28854,33 @@
28722
28854
  this.animationClass = 'animating';
28723
28855
  this.expandIcon.addEventListener('transitionend', this.removeAnimatingClass);
28724
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
+ }
28725
28884
  }
28726
28885
  __decorate$1([
28727
28886
  observable
@@ -28738,6 +28897,15 @@
28738
28897
  __decorate$1([
28739
28898
  attr({ mode: 'boolean' })
28740
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);
28741
28909
  __decorate$1([
28742
28910
  observable
28743
28911
  ], TableGroupRow.prototype, "animationClass", void 0);
@@ -28751,7 +28919,11 @@
28751
28919
 
28752
28920
  // prettier-ignore
28753
28921
  const template$7 = html `
28754
- <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
+ >
28755
28927
  <div class="table-container" style="
28756
28928
  --ni-private-table-scroll-x: -${x => x.scrollX}px;
28757
28929
  --ni-private-table-header-scrollbar-spacer-width: ${x => x.virtualizer.headerContainerMarginRight}px;
@@ -28761,18 +28933,31 @@
28761
28933
  ">
28762
28934
  <div role="rowgroup" class="header-container">
28763
28935
  <div class="header-row" role="row">
28764
- ${repeat(x => x.columns, html `
28765
- ${when(x => !x.columnHidden, html `
28766
- <${tableHeaderTag}
28767
- class="header"
28768
- sort-direction="${x => (typeof x.sortIndex === 'number' ? x.sortDirection : TableColumnSortDirection.none)}"
28769
- ?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)}"
28770
28942
  >
28771
- <slot name="${x => x.slot}"></slot>
28772
- </${tableHeaderTag}>
28773
- `)}
28943
+ </${checkboxTag}>
28944
+ </span>
28774
28945
  `)}
28775
- <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>
28776
28961
  </div>
28777
28962
  </div>
28778
28963
  <div class="table-viewport" ${ref('viewport')}>
@@ -28789,8 +28974,11 @@
28789
28974
  :nestingLevel="${(x, c) => c.parent.tableData[x.index]?.nestingLevel}"
28790
28975
  :leafItemCount="${(x, c) => c.parent.tableData[x.index]?.leafItemCount}"
28791
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)}"
28792
28980
  @group-expand-toggle="${(x, c) => c.parent.handleGroupRowExpanded(x.index, c.event)}"
28793
- >
28981
+ >
28794
28982
  </${tableGroupRowTag}>
28795
28983
  `)}
28796
28984
  ${when((x, c) => !c.parent.tableData[x.index]?.isGrouped, html `
@@ -28799,12 +28987,14 @@
28799
28987
  record-id="${(x, c) => c.parent.tableData[x.index]?.id}"
28800
28988
  ?selectable="${(_, c) => c.parent.selectionMode !== TableRowSelectionMode.none}"
28801
28989
  ?selected="${(x, c) => c.parent.tableData[x.index]?.selectionState === TableRowSelectionState.selected}"
28990
+ ?hide-selection="${(_, c) => c.parent.selectionMode !== TableRowSelectionMode.multiple}"
28802
28991
  :dataRecord="${(x, c) => c.parent.tableData[x.index]?.record}"
28803
28992
  :columns="${(_, c) => c.parent.columns}"
28804
28993
  :nestingLevel="${(x, c) => c.parent.tableData[x.index]?.nestingLevel}"
28805
28994
  @click="${async (x, c) => c.parent.onRowClick(x.index)}"
28806
- @row-action-menu-beforetoggle="${(_, c) => c.parent.onRowActionMenuBeforeToggle(c.event)}"
28807
- @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)}"
28808
28998
  >
28809
28999
  ${when((x, c) => c.parent.openActionMenuRecordId === c.parent.tableData[x.index]?.id, html `
28810
29000
  ${repeat((_, c) => c.parent.actionMenuSlots, html `
@@ -29786,11 +29976,20 @@
29786
29976
  * @internal
29787
29977
  */
29788
29978
  this.scrollX = 0;
29979
+ /**
29980
+ * @internal
29981
+ */
29982
+ this.selectionState = TableRowSelectionState.notSelected;
29789
29983
  this.tableValidator = new TableValidator();
29790
29984
  this.updateTracker = new UpdateTracker(this);
29791
29985
  this.columnNotifiers = [];
29792
29986
  this.isInitialized = false;
29793
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;
29794
29993
  this.onViewPortScroll = (event) => {
29795
29994
  this.scrollX = event.target.scrollLeft;
29796
29995
  };
@@ -29843,7 +30042,9 @@
29843
30042
  grouping: [],
29844
30043
  expanded: true // Workaround until we can apply a fix to TanStack regarding leveraging our getIsRowExpanded implementation
29845
30044
  },
29846
- enableRowSelection: false,
30045
+ enableRowSelection: row => !row.getIsGrouped(),
30046
+ enableMultiRowSelection: false,
30047
+ enableSubRowSelection: false,
29847
30048
  enableSorting: true,
29848
30049
  enableGrouping: true,
29849
30050
  renderFallbackValue: null,
@@ -29930,37 +30131,74 @@
29930
30131
  }
29931
30132
  }
29932
30133
  /** @internal */
29933
- async onRowClick(rowIndex) {
30134
+ async onRowSelectionToggle(rowIndex, event) {
30135
+ event.stopImmediatePropagation();
29934
30136
  if (this.selectionMode === TableRowSelectionMode.none) {
29935
30137
  return;
29936
30138
  }
29937
- const row = this.table.getRowModel().rows[rowIndex];
29938
- if (!row) {
29939
- 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);
29940
30145
  }
29941
- const currentSelection = await this.getSelectedRecordIds();
29942
- if (currentSelection.length === 1 && currentSelection[0] === row.id) {
29943
- // 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) {
29944
30161
  return;
29945
30162
  }
29946
- this.table.toggleAllRowsSelected(false);
29947
- row.toggleSelected(true);
30163
+ this.table.toggleAllRowsSelected(this.selectionCheckbox.checked);
29948
30164
  await this.emitSelectionChangeEvent();
29949
30165
  }
29950
30166
  /** @internal */
29951
- onRowActionMenuBeforeToggle(event) {
30167
+ async onRowActionMenuBeforeToggle(rowIndex, event) {
29952
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
+ }
29953
30179
  this.openActionMenuRecordId = event.detail.recordIds[0];
29954
- this.$emit('action-menu-beforetoggle', event.detail);
30180
+ const detail = {
30181
+ ...event.detail,
30182
+ recordIds
30183
+ };
30184
+ this.$emit('action-menu-beforetoggle', detail);
29955
30185
  }
29956
30186
  /** @internal */
29957
- onRowActionMenuToggle(event) {
30187
+ async onRowActionMenuToggle(event) {
29958
30188
  event.stopImmediatePropagation();
29959
- 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);
29960
30197
  if (!event.detail.newState) {
29961
30198
  this.openActionMenuRecordId = undefined;
29962
30199
  }
29963
30200
  }
30201
+ /** @internal */
29964
30202
  handleGroupRowExpanded(rowIndex, event) {
29965
30203
  this.toggleGroupExpanded(rowIndex);
29966
30204
  event.stopPropagation();
@@ -29980,6 +30218,16 @@
29980
30218
  this.updateRowGridColumns();
29981
30219
  }
29982
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
+ }
29983
30231
  selectionModeChanged(_prev, _next) {
29984
30232
  if (!this.$fastController.isConnected) {
29985
30233
  return;
@@ -30066,7 +30314,8 @@
30066
30314
  updatedOptions.state.rowSelection = {};
30067
30315
  }
30068
30316
  if (this.updateTracker.updateSelectionMode) {
30069
- updatedOptions.enableRowSelection = this.selectionMode !== TableRowSelectionMode.none;
30317
+ updatedOptions.enableMultiRowSelection = this.selectionMode === TableRowSelectionMode.multiple;
30318
+ updatedOptions.enableSubRowSelection = this.selectionMode === TableRowSelectionMode.multiple;
30070
30319
  updatedOptions.state.rowSelection = {};
30071
30320
  }
30072
30321
  if (this.updateTracker.requiresTanStackDataReset) {
@@ -30109,15 +30358,29 @@
30109
30358
  };
30110
30359
  this.$emit('selection-change', detail);
30111
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
+ }
30112
30376
  refreshRows() {
30377
+ this.selectionState = this.getTableSelectionState();
30113
30378
  const rows = this.table.getRowModel().rows;
30114
30379
  this.tableData = rows.map(row => {
30115
30380
  const rowState = {
30116
30381
  record: row.original,
30117
30382
  id: row.id,
30118
- selectionState: row.getIsSelected()
30119
- ? TableRowSelectionState.selected
30120
- : TableRowSelectionState.notSelected,
30383
+ selectionState: this.getRowSelectionState(row),
30121
30384
  isGrouped: row.getIsGrouped(),
30122
30385
  isExpanded: row.getIsExpanded(),
30123
30386
  groupRowValue: row.getIsGrouped()
@@ -30134,6 +30397,55 @@
30134
30397
  });
30135
30398
  this.virtualizer.dataChanged();
30136
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
+ }
30137
30449
  getGroupRowColumn(row) {
30138
30450
  const groupedId = row.groupingColumnId;
30139
30451
  if (groupedId !== undefined) {
@@ -30150,6 +30462,39 @@
30150
30462
  this.table.setOptions(this.options);
30151
30463
  this.refreshRows();
30152
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
+ }
30153
30498
  toggleGroupExpanded(rowIndex) {
30154
30499
  const row = this.table.getRowModel().rows[rowIndex];
30155
30500
  const wasExpanded = row.getIsExpanded();
@@ -30204,10 +30549,12 @@
30204
30549
  }
30205
30550
  const tanstackSelectionState = {};
30206
30551
  const selectableRecordIds = this.tableValidator.getPresentRecordIds(recordIdsToSelect);
30207
- if (selectableRecordIds.length) {
30208
- // In single selection mode, only select the first record ID that is requested
30209
- const firstSelectableRecordId = selectableRecordIds[0];
30210
- 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
+ }
30211
30558
  }
30212
30559
  return tanstackSelectionState;
30213
30560
  }
@@ -30245,6 +30592,12 @@
30245
30592
  __decorate$1([
30246
30593
  observable
30247
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);
30248
30601
  __decorate$1([
30249
30602
  observable
30250
30603
  ], Table.prototype, "firstSortedColumn", void 0);