@ni/nimble-components 18.6.3 → 18.6.4

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.
@@ -28593,6 +28593,111 @@
28593
28593
  return 1;
28594
28594
  }
28595
28595
 
28596
+ const isColumnProperty = (changedProperty, ...args) => {
28597
+ for (const arg of args) {
28598
+ if (changedProperty === arg) {
28599
+ return true;
28600
+ }
28601
+ }
28602
+ return false;
28603
+ };
28604
+ /**
28605
+ * Helper class to track what updates are needed to the table based on configuration
28606
+ * changes.
28607
+ */
28608
+ class UpdateTracker {
28609
+ constructor(table) {
28610
+ this.requiredUpdates = {
28611
+ rowIds: false,
28612
+ columnIds: false,
28613
+ columnSort: false,
28614
+ columnWidths: false,
28615
+ columnDefinition: false,
28616
+ actionMenuSlots: false
28617
+ };
28618
+ this.updateQueued = false;
28619
+ this.table = table;
28620
+ }
28621
+ get updateRowIds() {
28622
+ return this.requiredUpdates.rowIds;
28623
+ }
28624
+ get updateColumnIds() {
28625
+ return this.requiredUpdates.columnIds;
28626
+ }
28627
+ get updateColumnSort() {
28628
+ return this.requiredUpdates.columnSort;
28629
+ }
28630
+ get updateColumnWidths() {
28631
+ return this.requiredUpdates.columnWidths;
28632
+ }
28633
+ get updateColumnDefinition() {
28634
+ return this.requiredUpdates.columnDefinition;
28635
+ }
28636
+ get updateActionMenuSlots() {
28637
+ return this.requiredUpdates.actionMenuSlots;
28638
+ }
28639
+ get requiresTanStackUpdate() {
28640
+ return (this.requiredUpdates.rowIds
28641
+ || this.requiredUpdates.columnSort
28642
+ || this.requiredUpdates.columnDefinition);
28643
+ }
28644
+ get requiresTanStackDataReset() {
28645
+ return (this.requiredUpdates.rowIds || this.requiredUpdates.columnDefinition);
28646
+ }
28647
+ trackAllStateChanged() {
28648
+ this.setAllKeys(true);
28649
+ this.queueUpdate();
28650
+ }
28651
+ trackColumnPropertyChanged(changedColumnProperty) {
28652
+ if (isColumnProperty(changedColumnProperty, 'columnId')) {
28653
+ this.requiredUpdates.columnIds = true;
28654
+ }
28655
+ else if (isColumnProperty(changedColumnProperty, 'operandDataRecordFieldName', 'sortOperation')) {
28656
+ this.requiredUpdates.columnDefinition = true;
28657
+ }
28658
+ else if (isColumnProperty(changedColumnProperty, 'sortIndex', 'sortDirection')) {
28659
+ this.requiredUpdates.columnSort = true;
28660
+ }
28661
+ else if (isColumnProperty(changedColumnProperty, 'currentFractionalWidth', 'currentPixelWidth', 'internalMinPixelWidth', 'columnHidden')) {
28662
+ this.requiredUpdates.columnWidths = true;
28663
+ }
28664
+ else if (isColumnProperty(changedColumnProperty, 'actionMenuSlot')) {
28665
+ this.requiredUpdates.actionMenuSlots = true;
28666
+ }
28667
+ this.queueUpdate();
28668
+ }
28669
+ trackColumnInstancesChanged() {
28670
+ this.requiredUpdates.columnIds = true;
28671
+ this.requiredUpdates.columnDefinition = true;
28672
+ this.requiredUpdates.columnSort = true;
28673
+ this.requiredUpdates.columnWidths = true;
28674
+ this.requiredUpdates.actionMenuSlots = true;
28675
+ this.queueUpdate();
28676
+ }
28677
+ trackIdFieldNameChanged() {
28678
+ this.requiredUpdates.rowIds = true;
28679
+ this.queueUpdate();
28680
+ }
28681
+ setAllKeys(value) {
28682
+ Object.keys(this.requiredUpdates).forEach(key => {
28683
+ this.requiredUpdates[key] = value;
28684
+ });
28685
+ }
28686
+ queueUpdate() {
28687
+ if (!this.table.$fastController.isConnected) {
28688
+ return;
28689
+ }
28690
+ if (!this.updateQueued) {
28691
+ this.updateQueued = true;
28692
+ DOM.queueUpdate(() => {
28693
+ this.table.update();
28694
+ this.setAllKeys(false);
28695
+ this.updateQueued = false;
28696
+ });
28697
+ }
28698
+ }
28699
+ }
28700
+
28596
28701
  /**
28597
28702
  * This class provides helper methods for managing the layout of cells within
28598
28703
  * a Table.
@@ -28648,6 +28753,7 @@
28648
28753
  */
28649
28754
  this.scrollX = 0;
28650
28755
  this.tableValidator = new TableValidator();
28756
+ this.updateTracker = new UpdateTracker(this);
28651
28757
  this.columnNotifiers = [];
28652
28758
  this.onViewPortScroll = (event) => {
28653
28759
  this.scrollX = event.target.scrollLeft;
@@ -28675,7 +28781,8 @@
28675
28781
  connectedCallback() {
28676
28782
  super.connectedCallback();
28677
28783
  this.virtualizer.connectedCallback();
28678
- this.validateAndObserveColumns();
28784
+ this.updateTracker.trackAllStateChanged();
28785
+ this.observeColumns();
28679
28786
  this.viewport.addEventListener('scroll', this.onViewPortScroll, {
28680
28787
  passive: true
28681
28788
  });
@@ -28697,24 +28804,8 @@
28697
28804
  * is the string name of the property that changed on that column.
28698
28805
  */
28699
28806
  handleChange(source, args) {
28700
- if (source instanceof TableColumn) {
28701
- if (args === 'columnId') {
28702
- this.validateColumnIds();
28703
- }
28704
- else if (args === 'operandDataRecordFieldName'
28705
- || args === 'sortOperation') {
28706
- this.generateTanStackColumns();
28707
- }
28708
- else if (args === 'sortIndex' || args === 'sortDirection') {
28709
- this.validateColumnSortIndices();
28710
- this.setSortState();
28711
- }
28712
- else if (args === 'currentFractionalWidth'
28713
- || args === 'currentPixelWidth'
28714
- || args === 'internalMinPixelWidth'
28715
- || args === 'columnHidden') {
28716
- this.updateRowGridColumns();
28717
- }
28807
+ if (source instanceof TableColumn && typeof args === 'string') {
28808
+ this.updateTracker.trackColumnPropertyChanged(args);
28718
28809
  }
28719
28810
  }
28720
28811
  onRowActionMenuBeforeToggle(event) {
@@ -28724,29 +28815,33 @@
28724
28815
  onRowActionMenuToggle(event) {
28725
28816
  this.$emit('action-menu-toggle', event.detail);
28726
28817
  }
28727
- childItemsChanged() {
28728
- void this.updateColumnsFromChildItems();
28818
+ /**
28819
+ * @internal
28820
+ */
28821
+ update() {
28822
+ this.validate();
28823
+ if (this.updateTracker.requiresTanStackUpdate) {
28824
+ this.updateTanStack();
28825
+ }
28826
+ if (this.updateTracker.updateActionMenuSlots) {
28827
+ this.updateActionMenuSlots();
28828
+ }
28829
+ if (this.updateTracker.updateColumnWidths) {
28830
+ this.updateRowGridColumns();
28831
+ }
28729
28832
  }
28730
28833
  idFieldNameChanged(_prev, _next) {
28731
- // Force TanStack to detect a data update because a row's ID is only
28732
- // generated when creating a new row model.
28733
- this.setTableData(this.table.options.data);
28834
+ if (!this.$fastController.isConnected) {
28835
+ return;
28836
+ }
28837
+ this.updateTracker.trackIdFieldNameChanged();
28734
28838
  }
28735
28839
  columnsChanged(_prev, _next) {
28736
28840
  if (!this.$fastController.isConnected) {
28737
28841
  return;
28738
28842
  }
28739
- this.validateAndObserveColumns();
28740
- this.generateTanStackColumns();
28741
- this.setSortState();
28742
- const slots = new Set();
28743
- for (const column of this.columns) {
28744
- if (column.actionMenuSlot) {
28745
- slots.add(column.actionMenuSlot);
28746
- }
28747
- }
28748
- this.actionMenuSlots = Array.from(slots);
28749
- this.updateRowGridColumns();
28843
+ this.observeColumns();
28844
+ this.updateTracker.trackColumnInstancesChanged();
28750
28845
  }
28751
28846
  removeColumnObservers() {
28752
28847
  this.columnNotifiers.forEach(notifier => {
@@ -28754,30 +28849,20 @@
28754
28849
  });
28755
28850
  this.columnNotifiers = [];
28756
28851
  }
28757
- validateAndObserveColumns() {
28852
+ observeColumns() {
28758
28853
  this.removeColumnObservers();
28759
28854
  for (const column of this.columns) {
28760
28855
  const notifier = Observable.getNotifier(column);
28761
28856
  notifier.subscribe(this);
28762
28857
  this.columnNotifiers.push(notifier);
28763
28858
  }
28764
- this.validateColumnIds();
28765
- this.validateColumnSortIndices();
28766
- }
28767
- validateColumnIds() {
28768
- this.tableValidator.validateColumnIds(this.columns.map(x => x.columnId));
28769
- this.canRenderRows = this.checkValidity();
28770
- }
28771
- validateColumnSortIndices() {
28772
- this.tableValidator.validateColumnSortIndices(this.getColumnsParticipatingInSorting().map(x => x.sortIndex));
28773
- this.canRenderRows = this.checkValidity();
28774
28859
  }
28775
28860
  getColumnsParticipatingInSorting() {
28776
28861
  return this.columns.filter(x => x.sortDirection !== TableColumnSortDirection.none
28777
28862
  && typeof x.sortIndex === 'number');
28778
28863
  }
28779
- updateRowGridColumns() {
28780
- this.rowGridColumns = TableLayoutHelper.getGridTemplateColumns(this.columns);
28864
+ childItemsChanged() {
28865
+ void this.updateColumnsFromChildItems();
28781
28866
  }
28782
28867
  async updateColumnsFromChildItems() {
28783
28868
  const definedElements = this.childItems.map(async (item) => (item.matches(':not(:defined)')
@@ -28786,18 +28871,53 @@
28786
28871
  await Promise.all(definedElements);
28787
28872
  this.columns = this.childItems.filter((x) => x instanceof TableColumn);
28788
28873
  }
28874
+ updateTanStack() {
28875
+ const updatedOptions = {
28876
+ state: {}
28877
+ };
28878
+ if (this.updateTracker.updateColumnSort) {
28879
+ updatedOptions.state.sorting = this.calculateTanStackSortState();
28880
+ }
28881
+ if (this.updateTracker.updateColumnDefinition) {
28882
+ updatedOptions.columns = this.calculateTanStackColumns();
28883
+ }
28884
+ if (this.updateTracker.updateRowIds) {
28885
+ updatedOptions.getRowId = this.calculateTanStackRowIdFunction();
28886
+ }
28887
+ if (this.updateTracker.requiresTanStackDataReset) {
28888
+ // Perform a shallow copy of the data to trigger tanstack to regenerate the row models and columns.
28889
+ updatedOptions.data = [...this.table.options.data];
28890
+ }
28891
+ this.updateTableOptions(updatedOptions);
28892
+ }
28893
+ updateActionMenuSlots() {
28894
+ const slots = new Set();
28895
+ for (const column of this.columns) {
28896
+ if (column.actionMenuSlot) {
28897
+ slots.add(column.actionMenuSlot);
28898
+ }
28899
+ }
28900
+ this.actionMenuSlots = Array.from(slots);
28901
+ }
28902
+ updateRowGridColumns() {
28903
+ this.rowGridColumns = TableLayoutHelper.getGridTemplateColumns(this.columns);
28904
+ }
28905
+ validate() {
28906
+ this.tableValidator.validateColumnIds(this.columns.map(x => x.columnId));
28907
+ this.tableValidator.validateColumnSortIndices(this.getColumnsParticipatingInSorting().map(x => x.sortIndex));
28908
+ this.validateWithData(this.table.options.data);
28909
+ }
28910
+ validateWithData(data) {
28911
+ this.tableValidator.validateRecordIds(data, this.idFieldName);
28912
+ this.canRenderRows = this.checkValidity();
28913
+ }
28789
28914
  setTableData(newData) {
28790
28915
  const data = newData.map(record => {
28791
28916
  return { ...record };
28792
28917
  });
28793
- this.tableValidator.validateRecordIds(data, this.idFieldName);
28794
- this.canRenderRows = this.checkValidity();
28795
- const getRowIdFunction = this.idFieldName === null || this.idFieldName === undefined
28796
- ? undefined
28797
- : (record) => record[this.idFieldName];
28918
+ this.validateWithData(data);
28798
28919
  this.updateTableOptions({
28799
- data,
28800
- getRowId: getRowIdFunction
28920
+ data
28801
28921
  });
28802
28922
  }
28803
28923
  refreshRows() {
@@ -28820,27 +28940,26 @@
28820
28940
  this.table.setOptions(this.options);
28821
28941
  this.refreshRows();
28822
28942
  }
28823
- setSortState() {
28943
+ calculateTanStackSortState() {
28824
28944
  const sortedColumns = this.getColumnsParticipatingInSorting().sort((x, y) => x.sortIndex - y.sortIndex);
28825
28945
  this.firstSortedColumn = sortedColumns.length
28826
28946
  ? sortedColumns[0]
28827
28947
  : undefined;
28828
- const tanStackSortingState = sortedColumns.map(column => {
28948
+ return sortedColumns.map(column => {
28829
28949
  return {
28830
28950
  id: column.internalUniqueId,
28831
- desc: column.sortDirection
28832
- === TableColumnSortDirection.descending
28951
+ desc: column.sortDirection === TableColumnSortDirection.descending
28833
28952
  };
28834
28953
  });
28835
- this.updateTableOptions({
28836
- state: {
28837
- sorting: tanStackSortingState
28838
- }
28839
- });
28840
28954
  }
28841
- generateTanStackColumns() {
28842
- const generatedColumns = this.columns.map(column => {
28843
- const columnDef = {
28955
+ calculateTanStackRowIdFunction() {
28956
+ return this.idFieldName === null || this.idFieldName === undefined
28957
+ ? undefined
28958
+ : (record) => record[this.idFieldName];
28959
+ }
28960
+ calculateTanStackColumns() {
28961
+ return this.columns.map(column => {
28962
+ return {
28844
28963
  id: column.internalUniqueId,
28845
28964
  accessorFn: (data) => {
28846
28965
  const fieldName = column.operandDataRecordFieldName;
@@ -28851,13 +28970,6 @@
28851
28970
  },
28852
28971
  sortingFn: getTanStackSortingFunction(column.sortOperation)
28853
28972
  };
28854
- return columnDef;
28855
- });
28856
- this.updateTableOptions({
28857
- // Force TanStack to detect a data update because a columns's accessor is
28858
- // referenced when creating a new row model.
28859
- data: [...this.table.options.data],
28860
- columns: generatedColumns
28861
28973
  });
28862
28974
  }
28863
28975
  }