@adaptabletools/adaptable 21.2.1 → 21.2.2-canary.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptabletools/adaptable",
3
- "version": "21.2.1",
3
+ "version": "21.2.2-canary.0",
4
4
  "description": "Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements",
5
5
  "keywords": [
6
6
  "web-components",
@@ -4,6 +4,7 @@ import { AdaptableColumnPredicate, AdaptablePredicate, AdaptablePredicateDef, Pr
4
4
  import { IAdaptable } from '../../AdaptableInterfaces/IAdaptable';
5
5
  import { PredicateInternalApi } from '../Internal/PredicateInternalApi';
6
6
  import { TreeSelectionState } from '@infinite-table/infinite-react';
7
+ export declare const clearPredicateDefMapMemo: () => void;
7
8
  export declare const getTreeSelectionStateForPredicateInputs: (inputs: any[], cache?: WeakMap<any[], TreeSelectionState>) => TreeSelectionState<any>;
8
9
  export declare class PredicateApiImpl extends ApiBase implements PredicateApi {
9
10
  internalApi: PredicateInternalApi;
@@ -5,6 +5,10 @@ import { PredicateInternalApi } from '../Internal/PredicateInternalApi';
5
5
  import { SystemPredicateDefs } from '../../AdaptableState/Common/AdaptablePredicate';
6
6
  import { AG_GRID_GROUPED_COLUMN } from '../../Utilities/Constants/GeneralConstants';
7
7
  import { TreeSelectionState } from '@infinite-table/infinite-react';
8
+ const predicateDefMap_MEMO = new Map();
9
+ export const clearPredicateDefMapMemo = () => {
10
+ predicateDefMap_MEMO.clear();
11
+ };
8
12
  const treeSelectionStatesForPredicates = new WeakMap();
9
13
  export const getTreeSelectionStateForPredicateInputs = (inputs, cache = treeSelectionStatesForPredicates) => {
10
14
  const treeSelectionState = cache.get(inputs);
@@ -136,7 +140,14 @@ export class PredicateApiImpl extends ApiBase {
136
140
  if (!predicate) {
137
141
  return defaultReturn;
138
142
  }
139
- const predicateDef = this.getPredicateDefById(predicate.PredicateId);
143
+ // memoization to avoid repeated lookups
144
+ // during filtering of large datasets
145
+ // see #column_filter_predicates_evaluation
146
+ let predicateDef = predicateDefMap_MEMO.get(predicate.PredicateId);
147
+ if (predicateDef === undefined) {
148
+ predicateDef = this.getPredicateDefById(predicate.PredicateId);
149
+ predicateDefMap_MEMO.set(predicate.PredicateId, predicateDef);
150
+ }
140
151
  if (predicateDef === undefined) {
141
152
  return defaultReturn;
142
153
  }
@@ -164,6 +175,9 @@ export class PredicateApiImpl extends ApiBase {
164
175
  if (predicates === undefined || predicates === null || predicates?.length === 0) {
165
176
  return this.handlePredicate(undefined, params, defaultReturn);
166
177
  }
178
+ if (predicates.length === 1) {
179
+ return this.handlePredicate(predicates[0], params, defaultReturn);
180
+ }
167
181
  if (params.predicatesOperator && params.predicatesOperator === 'OR') {
168
182
  return predicates?.some((p) => this.handlePredicate(p, params, defaultReturn));
169
183
  }
@@ -97,6 +97,7 @@ export class ColumnFilterInternalApi extends ApiBase {
97
97
  predicatesOperator: columnFilter.PredicatesOperator,
98
98
  ...this.getAdaptableInternalApi().buildBaseContext(),
99
99
  };
100
+ // #column_filter_predicates_evaluation
100
101
  return this.getPredicateApi().handlePredicates(columnFilter.Predicates, predicateDefHandlerContext, true);
101
102
  }
102
103
  /**
@@ -34,4 +34,5 @@ export declare class LayoutInternalApi extends ApiBase {
34
34
  }, type?: 'table' | 'pivot'): Layout;
35
35
  private getLayoutCreationDefaultProperties;
36
36
  cloneLayout(layoutToClone: Layout): Omit<Layout, 'Name'>;
37
+ getCurrentLayout_perfOptimized(): Layout | null;
37
38
  }
@@ -186,4 +186,13 @@ export class LayoutInternalApi extends ApiBase {
186
186
  delete result.Name;
187
187
  return result;
188
188
  }
189
+ getCurrentLayout_perfOptimized() {
190
+ // perf-optimized version of getCurrentLayout()
191
+ const layoutState = this.getAdaptableState().Layout;
192
+ const currentLayoutName = layoutState.CurrentLayout;
193
+ if (!currentLayoutName) {
194
+ return null;
195
+ }
196
+ return layoutState.Layouts.find((layout) => layout.Name === currentLayoutName);
197
+ }
189
198
  }
@@ -149,9 +149,19 @@ export declare class AdaptableAgGrid implements IAdaptable {
149
149
  private normaliseToolPanelState;
150
150
  private getCurrentLayoutModel;
151
151
  silentUpdateCurrentLayoutModel(layoutModel?: TableLayoutModel | PivotLayoutModel): void;
152
+ /**
153
+ * Returns TRUE if filtering was applied, FALSE otherwise
154
+ * This is important in the INIT phase because applying filtering will automatically refresh AG Grids columnState,
155
+ * implicitly refreshing the sorting state too (hence we don't need to apply sorting separately)
156
+ */
152
157
  applyFiltering(config?: {
153
158
  updateColumnFilterModel?: boolean;
154
- }): void;
159
+ }): boolean;
160
+ /**
161
+ * Checks if the current layout has ColumnSorts for columns that have CustomSort defined
162
+ * (either via initialState CustomSorts or via customSortComparers option) and refreshes the sort if needed.
163
+ */
164
+ private refreshInitialSortIfNeeded;
155
165
  showQuickFilter(): void;
156
166
  hideQuickFilter(): void;
157
167
  private normalizeAdaptableOptions;
@@ -102,6 +102,7 @@ import { AgGridModulesAdapter } from './AgGridModulesAdapter';
102
102
  import { getMarker } from '../devTools';
103
103
  import { DeepMap } from '@infinite-table/infinite-react';
104
104
  import { DateFormatter } from '../Utilities/Helpers/FormatHelper';
105
+ import { clearPredicateDefMapMemo } from '../Api/Implementation/PredicateApiImpl';
105
106
  const LocalEventService_Prototype = LocalEventService.prototype;
106
107
  const LocalEventService_dispatchEvent = LocalEventService_Prototype.dispatchEvent;
107
108
  LocalEventService_Prototype.dispatchEvent = function (event) {
@@ -446,10 +447,14 @@ export class AdaptableAgGrid {
446
447
  this.api.themeApi.applyCurrentTheme();
447
448
  this.validatePrimaryKey();
448
449
  this.checkShouldClearExistingFiltersOrSearches();
449
- // FIXME AFL FILTER: talk with Radu: should ColumnFilters still be ignored?!
450
- // see layoutModel.Ignore_ColumnFilters
451
450
  // initial filter model
452
- this.applyFiltering();
451
+ const filteringApplied = this.applyFiltering();
452
+ // We may need to re-apply sort if there are ColumnSorts for columns with CustomSort defined
453
+ // This is required because AG Grid wasn't aware of the CustomSort when applying sorting initially
454
+ // this is not required when filtering was applied because filtering also triggers a sort refresh internally
455
+ if (!filteringApplied) {
456
+ this.refreshInitialSortIfNeeded();
457
+ }
453
458
  // apply quick search if there is one
454
459
  // yes, we could have put this on the gridOptions.findSearchValue
455
460
  // but we need to wait for setupColumns to run first so as to correctly
@@ -621,26 +626,67 @@ You need to define at least one Layout!`);
621
626
  normalize: true,
622
627
  });
623
628
  }
629
+ /**
630
+ * Returns TRUE if filtering was applied, FALSE otherwise
631
+ * This is important in the INIT phase because applying filtering will automatically refresh AG Grids columnState,
632
+ * implicitly refreshing the sorting state too (hence we don't need to apply sorting separately)
633
+ */
624
634
  applyFiltering(config) {
635
+ let filteringApplied = false;
625
636
  // default updateColumnFilterModel to TRUE, if not provided
626
637
  const updateColumnFilterModel = config?.updateColumnFilterModel ?? true;
627
638
  const agGridApi = this.agGridAdapter.getAgGridApi();
628
639
  if (updateColumnFilterModel) {
629
640
  const columnFilters = this.api.filterApi.columnFilterApi
630
641
  .getActiveColumnFilters()
631
- // FIXME AFL: we need this additional filter because 'getActiveColumnFilters' checks only for suspended while 'isColumnFilterActive' also checkss for COMPLETE filters
642
+ // we need this additional filter because 'getActiveColumnFilters' checks only for suspended while 'isColumnFilterActive' also checkss for COMPLETE filters
632
643
  .filter((columnFilter) => this.api.filterApi.columnFilterApi.isColumnFilterActive(columnFilter));
633
644
  const filterModel = {};
634
645
  columnFilters.forEach((columnFilter) => {
635
646
  filterModel[columnFilter.ColumnId] = columnFilter;
636
647
  });
637
648
  agGridApi.setFilterModel(filterModel);
649
+ filteringApplied = Object.keys(filterModel).length > 0;
638
650
  }
639
651
  // FIXME AFL FILTER why is this needed???
640
652
  this.refreshSelectedCellsState();
641
653
  this.refreshSelectedRowsState();
642
- agGridApi.onFilterChanged();
654
+ // FIXME AFL: this is temporary, will be replaced with v22's new autoCol filtering
655
+ const currentPivotLayoutHasAutoCols = this.api.layoutApi.isCurrentLayoutPivot() &&
656
+ !!this.api.layoutApi.getCurrentRowGroupsColumnIds()?.length;
657
+ // agGridApi.setFilterModel() already triggered onFilterChanged(), so we skip it if updateColumnFilterModel is TRUE
658
+ if (!filteringApplied || currentPivotLayoutHasAutoCols) {
659
+ agGridApi.onFilterChanged();
660
+ filteringApplied = true;
661
+ }
643
662
  this._emit('AdapTableFiltersApplied');
663
+ return filteringApplied;
664
+ }
665
+ /**
666
+ * Checks if the current layout has ColumnSorts for columns that have CustomSort defined
667
+ * (either via initialState CustomSorts or via customSortComparers option) and refreshes the sort if needed.
668
+ */
669
+ refreshInitialSortIfNeeded() {
670
+ const currentLayout = this.api.layoutApi.getCurrentLayout();
671
+ const columnSorts = currentLayout?.ColumnSorts;
672
+ if (!columnSorts || columnSorts.length === 0) {
673
+ return;
674
+ }
675
+ const hasCustomSortForSortedColumn = columnSorts.some((columnSort) => {
676
+ // Check if there's a CustomSort defined in state for this column
677
+ const customSort = this.api.customSortApi.getCustomSortForColumn(columnSort.ColumnId);
678
+ if (customSort && !customSort.IsSuspended) {
679
+ return true;
680
+ }
681
+ // Check if there's a customSortComparer defined in options for this column
682
+ if (this.api.customSortApi.internalApi.columnHasCustomSortComparer(columnSort.ColumnId)) {
683
+ return true;
684
+ }
685
+ return false;
686
+ });
687
+ if (hasCustomSortForSortedColumn) {
688
+ this.layoutManager.refreshSort();
689
+ }
644
690
  }
645
691
  showQuickFilter() {
646
692
  const height = this.api.optionsApi.getFilterOptions().columnFilterOptions.quickFilterHeight;
@@ -1764,14 +1810,21 @@ You need to define at least one Layout!`);
1764
1810
  let _displayValue = defaults ? defaults.displayValue : undefined;
1765
1811
  let _normalisedValue = defaults ? defaults.normalisedValue : undefined;
1766
1812
  let _isRowGroupCell;
1767
- const _isPivotCell = this.api.columnApi.isPivotResultColumn(columnId) ||
1768
- this.api.columnApi.isPivotAggColumnWithNoPivotColumns(columnId);
1813
+ let _isPivotCell;
1769
1814
  const self = this;
1770
1815
  const api = this.api;
1816
+ const getIsPivotCell = () => {
1817
+ if (_isPivotCell === undefined) {
1818
+ _isPivotCell =
1819
+ api.columnApi.isPivotResultColumn(columnId) ||
1820
+ api.columnApi.isPivotAggColumnWithNoPivotColumns(columnId);
1821
+ }
1822
+ return _isPivotCell;
1823
+ };
1771
1824
  const getRawValue = () => {
1772
1825
  if (_rawValue === undefined) {
1773
1826
  _rawValue = self.getRawValueFromRowNode(rowNode, columnId);
1774
- if (_isPivotCell && _rawValue?.value != undefined) {
1827
+ if (_rawValue?.value != undefined && getIsPivotCell()) {
1775
1828
  // for pivot result columns, the raw value is an object with a value property
1776
1829
  // we want to return the value property as the raw value
1777
1830
  _rawValue = _rawValue.value;
@@ -1814,7 +1867,7 @@ You need to define at least one Layout!`);
1814
1867
  return _primaryKeyValue;
1815
1868
  },
1816
1869
  get isPivotCell() {
1817
- return _isPivotCell;
1870
+ return getIsPivotCell();
1818
1871
  },
1819
1872
  get isRowGroupCell() {
1820
1873
  if (_isRowGroupCell === undefined) {
@@ -3386,6 +3439,7 @@ You need to define at least one Layout!`);
3386
3439
  this.__prevLayoutForRefresh = undefined;
3387
3440
  this.layoutManager?.destroy();
3388
3441
  this.layoutManager = null;
3442
+ clearPredicateDefMapMemo();
3389
3443
  const agGridApi = this.agGridAdapter?.getAgGridApi();
3390
3444
  if (agGridApi && !agGridApi.isDestroyed()) {
3391
3445
  agGridApi.removeEventListener('firstDataRendered', this.listenerFirstDataRendered);
@@ -8,6 +8,7 @@ export declare class AdaptableFilterHandler implements FilterHandler {
8
8
  readonly colId: string;
9
9
  private filterDisplayValuesResult;
10
10
  private previousFilterDisplayValuesResult;
11
+ private currentColumnFilters_MEMO;
11
12
  constructor(adaptableApi: AdaptableApi, columnSetup: ColumnSetupInfo);
12
13
  getCurrentColumnFilters(): ColumnFilter[];
13
14
  doesFilterPass(params: DoesFilterPassParams): boolean;
@@ -1,9 +1,17 @@
1
1
  export class AdaptableFilterHandler {
2
2
  constructor(adaptableApi, columnSetup) {
3
3
  this.adaptableApi = adaptableApi;
4
+ this.currentColumnFilters_MEMO = new WeakMap();
4
5
  this.colId = columnSetup.colId;
5
6
  }
6
7
  getCurrentColumnFilters() {
8
+ // we memoize based on layout column filters object reference
9
+ // this method is called for each row during filtering so we need to optimize it
10
+ const layoutColumnFilters = this.adaptableApi.layoutApi.internalApi.getCurrentLayout_perfOptimized()?.ColumnFilters;
11
+ const memoizedColumnFilters = this.currentColumnFilters_MEMO.get(layoutColumnFilters);
12
+ if (memoizedColumnFilters) {
13
+ return memoizedColumnFilters;
14
+ }
7
15
  const columnFilters = this.adaptableApi.filterApi.columnFilterApi
8
16
  .getActiveColumnFilters()
9
17
  .filter((columnFilter) => this.adaptableApi.filterApi.columnFilterApi.isColumnFilterActive(columnFilter))
@@ -12,6 +20,7 @@ export class AdaptableFilterHandler {
12
20
  const shouldEvaluateFilterOnClient = this.adaptableApi.expressionApi.internalApi.shouldEvaluatePredicatesInAdaptableQL('ColumnFilter', columnFilter, columnFilter.Predicates);
13
21
  return shouldEvaluateFilterOnClient;
14
22
  });
23
+ this.currentColumnFilters_MEMO.set(layoutColumnFilters, columnFilters);
15
24
  return columnFilters;
16
25
  }
17
26
  doesFilterPass(params) {
@@ -23,11 +32,11 @@ export class AdaptableFilterHandler {
23
32
  return true;
24
33
  }
25
34
  const columnFilters = this.getCurrentColumnFilters();
26
- const anyFilterFailed = columnFilters.some((columnFilter) => {
27
- const result = !this.adaptableApi.filterApi.columnFilterApi.internalApi.evaluateColumnFilter(columnFilter, rowNode);
28
- return result;
35
+ // #column_filter_predicates_evaluation
36
+ const allFiltersMatched = columnFilters.every((columnFilter) => {
37
+ return this.adaptableApi.filterApi.columnFilterApi.internalApi.evaluateColumnFilter(columnFilter, rowNode);
29
38
  });
30
- return anyFilterFailed ? false : true;
39
+ return allFiltersMatched;
31
40
  }
32
41
  catch (ex) {
33
42
  this.adaptableApi.consoleError(ex);
@@ -46,7 +55,7 @@ export class AdaptableFilterHandler {
46
55
  }
47
56
  return this.fetchFilterDisplayValues(options);
48
57
  }
49
- fetchFilterDisplayValues(options) {
58
+ async fetchFilterDisplayValues(options) {
50
59
  return this.adaptableApi.gridApi.internalApi
51
60
  .getDistinctFilterDisplayValuesForColumn({
52
61
  columnId: this.colId,
@@ -88,5 +97,6 @@ export class AdaptableFilterHandler {
88
97
  destroy() {
89
98
  this.filterDisplayValuesResult = undefined;
90
99
  this.previousFilterDisplayValuesResult = undefined;
100
+ this.currentColumnFilters_MEMO = undefined;
91
101
  }
92
102
  }
@@ -11,6 +11,7 @@ export declare class AgGridAdapter {
11
11
  private DANGER_updateGridOptionsMonkeyPatcher;
12
12
  private DANGER_doFiltersPassMonkeyPatcher;
13
13
  private DANGER_isAggFilterPresentMonkeyPatcher;
14
+ private activePivotColumnFilters_MEMO;
14
15
  initialGridOptions: GridOptions;
15
16
  private _agGridId;
16
17
  constructor(_adaptableInstance: AdaptableAgGrid, config?: {
@@ -20,6 +21,7 @@ export declare class AgGridAdapter {
20
21
  private get adaptableOptions();
21
22
  private get adaptableApi();
22
23
  private get logger();
24
+ private getActivePivotColumnFilters;
23
25
  private get agGridOptionsService();
24
26
  setAgGridId(agGridId: string): void;
25
27
  setAgGridApi(gridApi: GridApi): void;
@@ -15,6 +15,7 @@ const getColumnApiModule = () => ColumnApiModule;
15
15
  export class AgGridAdapter {
16
16
  constructor(_adaptableInstance, config) {
17
17
  this._adaptableInstance = _adaptableInstance;
18
+ this.activePivotColumnFilters_MEMO = new WeakMap();
18
19
  const columnApiModuleReference = config?.getAgGridColumnApiModuleReference?.() ?? getColumnApiModule();
19
20
  const ColumnDefFactory_Prototype = columnApiModuleReference?.beans?.[0]?.prototype;
20
21
  if (!ColumnDefFactory_Prototype) {
@@ -40,6 +41,7 @@ export class AgGridAdapter {
40
41
  this.DANGER_updateGridOptionsMonkeyPatcher = null;
41
42
  this.DANGER_doFiltersPassMonkeyPatcher = null;
42
43
  this.DANGER_isAggFilterPresentMonkeyPatcher = null;
44
+ this.activePivotColumnFilters_MEMO = null;
43
45
  this._adaptableInstance = null;
44
46
  }
45
47
  get adaptableOptions() {
@@ -51,6 +53,27 @@ export class AgGridAdapter {
51
53
  get logger() {
52
54
  return this._adaptableInstance.logger;
53
55
  }
56
+ getActivePivotColumnFilters() {
57
+ // we memoize based on layout column filters object reference
58
+ // this method is called for each row during filtering so we need to optimize it
59
+ const layoutColumnFilters = this.adaptableApi.layoutApi.internalApi.getCurrentLayout_perfOptimized()?.ColumnFilters;
60
+ if (!layoutColumnFilters) {
61
+ return [];
62
+ }
63
+ const memoizedColumnFilters = this.activePivotColumnFilters_MEMO.get(layoutColumnFilters);
64
+ if (memoizedColumnFilters) {
65
+ return memoizedColumnFilters;
66
+ }
67
+ const pivotColumnFilters = this.adaptableApi.filterApi.columnFilterApi
68
+ .getActiveColumnFilters()
69
+ .filter((columnFilter) => this.adaptableApi.columnApi.isPivotResultColumn(columnFilter.ColumnId) ||
70
+ this.adaptableApi.columnApi.isAutoRowGroupColumnForSingle(columnFilter.ColumnId) ||
71
+ this.adaptableApi.columnApi.isPivotAggColumnWithNoPivotColumns(columnFilter.ColumnId))
72
+ .filter((columnFilter) => this.adaptableApi.filterApi.columnFilterApi.isColumnFilterActive(columnFilter))
73
+ .filter((columnFilter) => this.adaptableApi.expressionApi.internalApi.shouldEvaluatePredicatesInAdaptableQL('ColumnFilter', columnFilter, columnFilter.Predicates));
74
+ this.activePivotColumnFilters_MEMO.set(layoutColumnFilters, pivotColumnFilters);
75
+ return pivotColumnFilters;
76
+ }
54
77
  get agGridOptionsService() {
55
78
  return this._adaptableInstance.agGridOptionsService;
56
79
  }
@@ -151,21 +174,15 @@ export class AgGridAdapter {
151
174
  // should NEVER happen
152
175
  return true;
153
176
  }
154
- const pivotColumnFilters = self.adaptableApi.filterApi.columnFilterApi
155
- .getActiveColumnFilters()
156
- .filter((columnFilter) => self.adaptableApi.columnApi.isPivotResultColumn(columnFilter.ColumnId) ||
157
- self.adaptableApi.columnApi.isAutoRowGroupColumnForSingle(columnFilter.ColumnId) ||
158
- self.adaptableApi.columnApi.isPivotAggColumnWithNoPivotColumns(columnFilter.ColumnId));
177
+ const pivotColumnFilters = self.getActivePivotColumnFilters();
159
178
  try {
160
179
  if (pivotColumnFilters.length > 0) {
161
180
  for (const columnFilter of pivotColumnFilters) {
162
- const evaluateColumnFilterOnClient = self.adaptableApi.expressionApi.internalApi.shouldEvaluatePredicatesInAdaptableQL('ColumnFilter', columnFilter, columnFilter.Predicates);
163
- if (evaluateColumnFilterOnClient) {
164
- const columnFilterEvaluationResult = self.adaptableApi.filterApi.columnFilterApi.internalApi.evaluateColumnFilter(columnFilter, rowNode);
165
- if (!columnFilterEvaluationResult) {
166
- return false;
167
- }
181
+ const columnFilterEvaluationResult = self.adaptableApi.filterApi.columnFilterApi.internalApi.evaluateColumnFilter(columnFilter, rowNode);
182
+ if (!columnFilterEvaluationResult) {
183
+ return false;
168
184
  }
185
+ // else continue to next filter
169
186
  }
170
187
  }
171
188
  }
@@ -177,10 +194,7 @@ export class AgGridAdapter {
177
194
  };
178
195
  agGridColumnFilterService.doFiltersPass = this.DANGER_doFiltersPassMonkeyPatcher;
179
196
  this.DANGER_isAggFilterPresentMonkeyPatcher = function () {
180
- const columnFilters = self.adaptableApi.filterApi.columnFilterApi.getActiveColumnFilters();
181
- return columnFilters.some((colFilter) => self.adaptableApi.columnApi.isPivotResultColumn(colFilter.ColumnId) ||
182
- self.adaptableApi.columnApi.isAutoRowGroupColumnForSingle(colFilter.ColumnId) ||
183
- self.adaptableApi.columnApi.isPivotAggColumnWithNoPivotColumns(colFilter.ColumnId));
197
+ return self.getActivePivotColumnFilters().length > 0;
184
198
  };
185
199
  agGridColumnFilterService.isAggFilterPresent = this.DANGER_isAggFilterPresentMonkeyPatcher;
186
200
  }
package/src/env.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export default {
2
2
  NEXT_PUBLIC_INFINITE_TABLE_LICENSE_KEY: "StartDate=2021-06-29|EndDate=2030-01-01|Owner=Adaptable|Type=distribution|TS=1624971462479|C=137829811,1004007071,2756196225,1839832928,3994409405,636616862" || '',
3
- PUBLISH_TIMESTAMP: 1768226502639 || Date.now(),
4
- VERSION: "21.2.1" || '--current-version--',
3
+ PUBLISH_TIMESTAMP: 1768333302626 || Date.now(),
4
+ VERSION: "21.2.2-canary.0" || '--current-version--',
5
5
  };
@@ -87,6 +87,12 @@ export declare class LayoutManager<DATA_TYPE = any> extends LMEmitter {
87
87
  applyPivotTotals(layout: PivotLayoutModel): void;
88
88
  applyColumnGroupCollapseExpandState(layout: PivotLayoutModel | TableLayoutModel): void;
89
89
  private withSuppressColumnAnimation;
90
+ private withSuppressRowAnimation;
91
+ /**
92
+ * Refreshes the sort order by refreshing the client side row model.
93
+ * This is useful when custom sort comparers are defined and the sort needs to be re-applied after filtering.
94
+ */
95
+ refreshSort(): void;
90
96
  private patchColDefType;
91
97
  private setupPivotTotals;
92
98
  private patchPivotAggregationTotal;
@@ -1630,6 +1630,26 @@ export class LayoutManager extends LMEmitter {
1630
1630
  }
1631
1631
  return res;
1632
1632
  }
1633
+ withSuppressRowAnimation(fn) {
1634
+ const animateRows = this.gridApi.getGridOption('animateRows');
1635
+ if (animateRows) {
1636
+ this.gridApi.setGridOption('animateRows', false);
1637
+ }
1638
+ const res = fn();
1639
+ if (animateRows) {
1640
+ this.gridApi.setGridOption('animateRows', true);
1641
+ }
1642
+ return res;
1643
+ }
1644
+ /**
1645
+ * Refreshes the sort order by refreshing the client side row model.
1646
+ * This is useful when custom sort comparers are defined and the sort needs to be re-applied after filtering.
1647
+ */
1648
+ refreshSort() {
1649
+ this.withSuppressRowAnimation(() => {
1650
+ this.gridApi.refreshClientSideRowModel('sort');
1651
+ });
1652
+ }
1633
1653
  patchColDefType(colDef, colTypes) {
1634
1654
  const originalTypes = colDef.type == undefined ? [] : Array.isArray(colDef.type) ? colDef.type : [colDef.type];
1635
1655
  const columnTypes = new Set(originalTypes);