@adaptabletools/adaptable 23.1.0-canary.0 → 23.1.0-canary.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptabletools/adaptable",
3
- "version": "23.1.0-canary.0",
3
+ "version": "23.1.0-canary.2",
4
4
  "description": "Powerful AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements",
5
5
  "keywords": [
6
6
  "web-components",
@@ -68,8 +68,8 @@
68
68
  "uuid": "9.0.1"
69
69
  },
70
70
  "peerDependencies": {
71
- "ag-grid-enterprise": ">=36.1.0",
72
- "ag-stack": ">=36.1.0"
71
+ "ag-grid-enterprise": ">=36.2.0",
72
+ "ag-stack": ">=36.2.0"
73
73
  },
74
74
  "publishTimestamp": 0,
75
75
  "type": "module",
@@ -48,6 +48,36 @@ export interface AgGridConfig {
48
48
  modules: Module[];
49
49
  }
50
50
  export type AdaptableVariant = 'vanilla' | 'react' | 'angular' | 'vue';
51
+ /**
52
+ * #narrow_column_model_refresh
53
+ *
54
+ * What has to be refreshed in AG Grid after a column-model pass (`updateColumnModelAndRefreshGrid()`),
55
+ * ie. after `setupColumns()` re-installed the Adaptable colDef callbacks.
56
+ *
57
+ * Whatever changed in a colDef VALUE (eg. a new `cellRenderer`, `comparator` or `valueFormatter`) is
58
+ * already taken care of by AG Grid: `AgColumn.setColDef()` (see #col_def_commit) force-refreshes the
59
+ * rendered cells and header of the changed column. The scope only has to cover state read by the
60
+ * #stable_col_def_callbacks at render time, which AG Grid cannot know about.
61
+ */
62
+ export interface GridRefreshScope {
63
+ /**
64
+ * Destroy & recreate the rendered rows (`redrawRows()`).
65
+ * Only needed when a ROW-level definition may have changed: `getRowStyle` / `getRowClass` (Alert row
66
+ * highlights), row height, full-width rows. Cancels cell editing; implies `cells`.
67
+ */
68
+ rows?: boolean;
69
+ /**
70
+ * Re-run the cell-level callbacks (`cellStyle`, `cellClass`, `valueFormatter`, `cellRenderer` params)
71
+ * on the rendered cells (`refreshCells({ force: true })`). Keeps focus, selection and in-progress edits.
72
+ */
73
+ cells?: boolean;
74
+ /**
75
+ * Recreate the header cells (`refreshHeader()`).
76
+ * Only needed when a header-level callback (`headerStyle` / `headerClass` / `headerValueGetter`) reads
77
+ * state that changed, ie. Format Columns targeting the column header.
78
+ */
79
+ header?: boolean;
80
+ }
51
81
  /**
52
82
  * The only interface for Adaptable
53
83
  *
@@ -280,7 +310,12 @@ export interface IAdaptable {
280
310
  expandRowGroupsForValues(columnValues: any[]): void;
281
311
  getAdaptableContainerElement(): HTMLElement | null;
282
312
  getAgGridContainerElement(): HTMLElement | null;
283
- updateColumnModelAndRefreshGrid(): void;
313
+ /**
314
+ * Re-derives the Adaptable column state, sets up all columns again and refreshes AG Grid.
315
+ * @param refreshScope what to refresh after the columns were set up (see #narrow_column_model_refresh);
316
+ * defaults to a full refresh (rows + header)
317
+ */
318
+ updateColumnModelAndRefreshGrid(refreshScope?: GridRefreshScope): void;
284
319
  refreshSortIfColumnsSorted(): void;
285
320
  getAgGridColumnForColumnId(columnId: string): Column;
286
321
  getMinMaxCachedValueForColumn(column: AdaptableColumn, aggregation: 'min' | 'max' | 'avg' | 'median'): number | undefined;
@@ -7,6 +7,13 @@ export declare class FormatColumnInternalApi extends ApiBase {
7
7
  * Column-model update alone can leave visible cells stale until scroll.
8
8
  */
9
9
  refreshFormatColumnPresentation(formatColumns: FormatColumn | FormatColumn[] | undefined): void;
10
+ /**
11
+ * see #narrow_column_model_refresh
12
+ * Whether ANY Format Column in state (suspended or not, in any layout) targets the column header -
13
+ * ie. whether the `headerStyle` / `headerClass` / header name callbacks read Format Column state at all.
14
+ * When none does, a Format Column change cannot alter the rendered header, so it does not have to be refreshed.
15
+ */
16
+ hasFormatColumnsTargetingHeader(): boolean;
10
17
  /**
11
18
  * Retrieves all Format Columns in Adaptable State with the `Style` property set
12
19
  * @returns format columns
@@ -83,8 +90,11 @@ export declare class FormatColumnInternalApi extends ApiBase {
83
90
  * Checks if format column is relevant for a given cell (intersection of given AdaptableColumn and RowNode)
84
91
  *
85
92
  * @param formatColumn
86
- * @param column
87
- * @param params
93
+ * @param column - the column the Format Column is scoped to
94
+ * @param rowNode
95
+ * @param cellValue
96
+ * @param pivotResultColumn - set when the cell belongs to a pivot result column, so that a Rule Expression
97
+ * written against the base column reads the pivot result cell value (see #derived_pivot_cell_style)
88
98
  */
89
99
  formatColumnShouldRenderInCell(formatColumn: FormatColumn, column: AdaptableColumn, rowNode: IRowNode, cellValue: any, pivotResultColumn?: Column): boolean;
90
100
  /**
@@ -49,6 +49,10 @@ export class FormatColumnInternalApi extends ApiBase {
49
49
  this.getGridApi().refreshColumns([...columnIds]);
50
50
  }
51
51
  }
52
+ hasFormatColumnsTargetingHeader() {
53
+ const headerTarget = 'columnHeader';
54
+ return (this.getFormatColumnApi().getFormatColumnState()?.FormatColumns ?? []).some((formatColumn) => formatColumn?.Target === headerTarget);
55
+ }
52
56
  getAllFormatColumnWithStyle(config) {
53
57
  return this.getFormatColumnApi()
54
58
  .getFormatColumns(config)
@@ -205,7 +205,9 @@ export class GridInternalApi extends ApiBase {
205
205
  Aggregatable: defaultColumnDefinition.enableValue,
206
206
  SuppressMenu: defaultColumnDefinition.suppressHeaderMenuButton,
207
207
  SuppressMovable: defaultColumnDefinition.suppressMovable,
208
- HeaderToolTip: defaultColumnDefinition.headerTooltip,
208
+ HeaderToolTip: typeof defaultColumnDefinition.headerTooltip === 'string'
209
+ ? defaultColumnDefinition.headerTooltip
210
+ : undefined,
209
211
  Width: defaultColumnDefinition.width,
210
212
  };
211
213
  }
@@ -464,7 +464,7 @@ const adaptableMiddleware = (adaptable) => (function(middlewareAPI) {
464
464
  }
465
465
  });
466
466
  }
467
- adaptable.updateColumnModelAndRefreshGrid();
467
+ adaptable.updateColumnModelAndRefreshGrid({ rows: true });
468
468
  let module = (adaptable.adaptableModules.get(ModuleConstants.AlertModuleId));
469
469
  if (module) {
470
470
  module.checkListenToCellDataChanged();
@@ -480,7 +480,7 @@ const adaptableMiddleware = (adaptable) => (function(middlewareAPI) {
480
480
  case FlashingCellRedux.FLASHING_CELL_DEFINITION_UNSUSPEND_ALL:
481
481
  case FlashingCellRedux.FLASHING_CELL_DEFINITION_SUSPEND_ALL: {
482
482
  const returnAction = next(action);
483
- adaptable.updateColumnModelAndRefreshGrid();
483
+ adaptable.updateColumnModelAndRefreshGrid({ cells: true });
484
484
  let module = (adaptable.adaptableModules.get(ModuleConstants.FlashingCellModuleId));
485
485
  if (module) {
486
486
  module.checkListenToCellDataChanged();
@@ -542,7 +542,7 @@ const adaptableMiddleware = (adaptable) => (function(middlewareAPI) {
542
542
  if (StringExtensions.IsNotNullOrEmpty(adaptable.api.quickSearchApi.getQuickSearchValue())) {
543
543
  adaptable.refreshAgGridFind();
544
544
  }
545
- adaptable.updateColumnModelAndRefreshGrid();
545
+ adaptable.updateColumnModelAndRefreshGrid({ cells: true });
546
546
  return returnAction;
547
547
  }
548
548
  case FormatColumnRedux.FORMAT_COLUMN_ADD_BATCH:
@@ -555,7 +555,16 @@ const adaptableMiddleware = (adaptable) => (function(middlewareAPI) {
555
555
  case FormatColumnRedux.FORMAT_COLUMN_SUSPEND:
556
556
  case FormatColumnRedux.FORMAT_COLUMN_UNSUSPEND:
557
557
  case FormatColumnRedux.FORMAT_COLUMN_SUSPEND_ALL:
558
- case FormatColumnRedux.FORMAT_COLUMN_UNSUSPEND_ALL:
558
+ case FormatColumnRedux.FORMAT_COLUMN_UNSUSPEND_ALL: {
559
+ const hadHeaderFormatColumns = adaptable.api.formatColumnApi.internalApi.hasFormatColumnsTargetingHeader();
560
+ const returnAction = next(action);
561
+ const hasHeaderFormatColumns = adaptable.api.formatColumnApi.internalApi.hasFormatColumnsTargetingHeader();
562
+ adaptable.updateColumnModelAndRefreshGrid({
563
+ cells: true,
564
+ header: hadHeaderFormatColumns || hasHeaderFormatColumns,
565
+ });
566
+ return returnAction;
567
+ }
559
568
  case StyledColumnRedux.STYLED_COLUMN_ADD:
560
569
  case StyledColumnRedux.STYLED_COLUMN_EDIT:
561
570
  case StyledColumnRedux.STYLED_COLUMN_DELETE:
@@ -564,7 +573,7 @@ const adaptableMiddleware = (adaptable) => (function(middlewareAPI) {
564
573
  case StyledColumnRedux.STYLED_COLUMN_SUSPEND_ALL:
565
574
  case StyledColumnRedux.STYLED_COLUMN_UNSUSPEND_ALL: {
566
575
  const returnAction = next(action);
567
- adaptable.updateColumnModelAndRefreshGrid();
576
+ adaptable.updateColumnModelAndRefreshGrid({ cells: true });
568
577
  return returnAction;
569
578
  }
570
579
  case CustomSortRedux.CUSTOM_SORT_ADD:
@@ -575,7 +584,7 @@ const adaptableMiddleware = (adaptable) => (function(middlewareAPI) {
575
584
  case CustomSortRedux.CUSTOM_SORT_SUSPEND_ALL:
576
585
  case CustomSortRedux.CUSTOM_SORT_UNSUSPEND_ALL: {
577
586
  const returnAction = next(action);
578
- adaptable.updateColumnModelAndRefreshGrid();
587
+ adaptable.updateColumnModelAndRefreshGrid({});
579
588
  adaptable.refreshSortIfColumnsSorted();
580
589
  return returnAction;
581
590
  }
@@ -361,7 +361,10 @@ export class LayoutModule extends AdaptableModuleBase {
361
361
  .getModuleService()
362
362
  .getModuleById('Shortcut')
363
363
  .checkListenToKeyDown();
364
- this.api.internalApi.getAdaptableInstance().updateColumnModelAndRefreshGrid();
364
+ this.api.internalApi.getAdaptableInstance().updateColumnModelAndRefreshGrid({
365
+ cells: true,
366
+ header: this.api.formatColumnApi.internalApi.hasFormatColumnsTargetingHeader(),
367
+ });
365
368
  }
366
369
  getReferencedNamedQueryNames(layout) {
367
370
  if (!layout.GridFilter?.Expression) {
@@ -2,7 +2,7 @@ import { AdaptableOptions } from '../AdaptableOptions/AdaptableOptions';
2
2
  import { ChartRef, Column, GridApi, GridOptions, IRowNode, Module, RowModelType, StatusPanelDef } from 'ag-grid-enterprise';
3
3
  import { AdaptableLogger } from './AdaptableLogger';
4
4
  import { AdaptableApi, DestroyConfig } from '../Api/AdaptableApi';
5
- import { AdaptableVariant, IAdaptable, NormalizeAdaptableStateOptions } from '../AdaptableInterfaces/IAdaptable';
5
+ import { AdaptableVariant, GridRefreshScope, IAdaptable, NormalizeAdaptableStateOptions } from '../AdaptableInterfaces/IAdaptable';
6
6
  import { EmitterCallback } from '../Utilities/Emitter';
7
7
  import { AdaptablePlugin } from '../AdaptableOptions/AdaptablePlugin';
8
8
  import { AgGridAdapter, RowNodeEvent } from './AgGridAdapter';
@@ -247,10 +247,47 @@ export declare class AdaptableAgGrid implements IAdaptable {
247
247
  getDisplayValueFromRawValue(rowNode: IRowNode, columnId: string, rawValue: any): string | undefined;
248
248
  private getCleanValue;
249
249
  getNormalisedValueFromRawValue(rawValue: any, column: AdaptableColumn): string | number | boolean | Date | unknown;
250
- private __updateColumnModelAndRefreshGrid_already_called;
250
+ /**
251
+ * The refresh scope already applied by a column-model pass in the current microtask window
252
+ * (`null` when no pass ran yet), see `updateColumnModelAndRefreshGrid`.
253
+ */
254
+ private __columnModelRefreshDoneInThisTick;
251
255
  private __forceUpdateColumnModel;
252
- updateColumnModelAndRefreshGrid(): void;
253
- _updateColumnModelAndRefreshGridNow(): void;
256
+ /**
257
+ * #narrow_column_model_refresh
258
+ *
259
+ * Runs the column-model pass at most once per microtask window: the first call runs it synchronously
260
+ * with the requested refresh scope; a later call in the same window does NOT set up the columns again
261
+ * (the #stable_col_def_callbacks read live state anyway) but still gets any refresh it asks for that
262
+ * the first call did not perform - eg a cells-only pass followed by a request for a row redraw.
263
+ */
264
+ updateColumnModelAndRefreshGrid(refreshScope?: GridRefreshScope): void;
265
+ /**
266
+ * #column_model_refresh_perf
267
+ *
268
+ * The whole pass and each of its phases are published as DevTools performance tracks
269
+ * (`Runtime` track, see `DevToolsTracks`) when profiling is enabled (`localStorage.adaptableProfileTracks = 'true'`).
270
+ * The `Update column model & refresh grid` entry carries the number of columns set up, the number of
271
+ * colDefs AG Grid actually saw as changed (see `AgGridAdapter.DANGER_getColDefsVersion`) and the refresh
272
+ * scope applied, so a `performance.getEntriesByName()` consumer (eg the `perf/column-model-refresh`
273
+ * Playwright spec) can tell a callback-only pass from one that committed real colDef changes.
274
+ *
275
+ * @param refreshScope see #narrow_column_model_refresh; defaults to a full refresh (rows + header)
276
+ */
277
+ _updateColumnModelAndRefreshGridNow(refreshScope?: GridRefreshScope): void;
278
+ /**
279
+ * see #narrow_column_model_refresh
280
+ * Applies the given refresh scope; each operation is a DevTools `Runtime` track entry (see #column_model_refresh_perf).
281
+ */
282
+ private refreshGridAfterColumnModelUpdate;
283
+ /**
284
+ * see #narrow_column_model_refresh
285
+ * The cell-level counterpart of `redrawBody()`: re-runs the colDef callbacks on every rendered cell
286
+ * without destroying the rows, so cell focus, selection and an in-progress edit survive.
287
+ * `cellStyle` results are normalised (see `normalizeStyleForAgGrid`), so a style that no longer applies
288
+ * is cleared even though AG Grid only ever ADDS inline styles on refresh.
289
+ */
290
+ refreshRenderedCells(): void;
254
291
  /**
255
292
  * Re-applies the current sort, eg. after a Custom Sort was added/edited/removed at runtime.
256
293
  * The column comparators are already up to date (see #stable_col_def_callbacks), AG Grid just has to sort again.
@@ -2,6 +2,7 @@ import { debounce } from '../Utilities/Helpers/TimingHelper';
2
2
  import { createGrid, } from 'ag-grid-enterprise';
3
3
  import { AdaptableLogger } from './AdaptableLogger';
4
4
  import { PrimaryKeyDocsLink } from '../Utilities/Constants/DocumentationLinkConstants';
5
+ import { describeGridRefreshScope, FULL_GRID_REFRESH_SCOPE, getMissingGridRefreshScope, mergeGridRefreshScopes, } from './gridRefreshScope';
5
6
  import StringExtensions from '../Utilities/Extensions/StringExtensions';
6
7
  import { applyQuickSearchFindCssVars } from '../Utilities/Helpers/QuickSearchHelper';
7
8
  import Emitter from '../Utilities/Emitter';
@@ -617,7 +618,6 @@ export class AdaptableAgGrid {
617
618
  agGridApi.onFilterChanged();
618
619
  filteringApplied = true;
619
620
  }
620
- agGridApi.refreshCells();
621
621
  this._emit('AdapTableFiltersApplied');
622
622
  return filteringApplied;
623
623
  }
@@ -1429,7 +1429,10 @@ export class AdaptableAgGrid {
1429
1429
  if (this.api.formatColumnApi.getActiveFormatColumns().some((fc) => {
1430
1430
  return fc.ColumnGroupScope != null;
1431
1431
  })) {
1432
- this.updateColumnModelAndRefreshGrid();
1432
+ this.updateColumnModelAndRefreshGrid({
1433
+ cells: true,
1434
+ header: this.api.formatColumnApi.internalApi.hasFormatColumnsTargetingHeader(),
1435
+ });
1433
1436
  }
1434
1437
  }));
1435
1438
  this.agGridAdapter.getAgGridApi().addEventListener('columnPivotChanged', (this.listenerPivotChanged = (params) => {
@@ -1883,30 +1886,81 @@ export class AdaptableAgGrid {
1883
1886
  }
1884
1887
  return rawValue;
1885
1888
  }
1886
- __updateColumnModelAndRefreshGrid_already_called = false;
1889
+ __columnModelRefreshDoneInThisTick = null;
1887
1890
  __forceUpdateColumnModel = false;
1888
- updateColumnModelAndRefreshGrid() {
1889
- if (this.__updateColumnModelAndRefreshGrid_already_called && !this.__forceUpdateColumnModel) {
1891
+ updateColumnModelAndRefreshGrid(refreshScope = FULL_GRID_REFRESH_SCOPE) {
1892
+ const alreadyDone = this.__columnModelRefreshDoneInThisTick;
1893
+ if (alreadyDone && !this.__forceUpdateColumnModel) {
1894
+ const missingScope = getMissingGridRefreshScope(alreadyDone, refreshScope);
1895
+ if (missingScope) {
1896
+ this.refreshGridAfterColumnModelUpdate(missingScope);
1897
+ this.__columnModelRefreshDoneInThisTick = mergeGridRefreshScopes(alreadyDone, missingScope);
1898
+ }
1890
1899
  return;
1891
1900
  }
1892
1901
  this.__forceUpdateColumnModel = false;
1893
1902
  try {
1894
- this._updateColumnModelAndRefreshGridNow();
1895
- this.__updateColumnModelAndRefreshGrid_already_called = true;
1903
+ this._updateColumnModelAndRefreshGridNow(refreshScope);
1904
+ this.__columnModelRefreshDoneInThisTick = alreadyDone
1905
+ ? mergeGridRefreshScopes(alreadyDone, refreshScope)
1906
+ : { ...refreshScope };
1896
1907
  }
1897
1908
  finally {
1898
1909
  queueMicrotask(() => {
1899
- this.__updateColumnModelAndRefreshGrid_already_called = false;
1910
+ this.__columnModelRefreshDoneInThisTick = null;
1900
1911
  });
1901
1912
  }
1902
1913
  }
1903
- _updateColumnModelAndRefreshGridNow() {
1914
+ _updateColumnModelAndRefreshGridNow(refreshScope = FULL_GRID_REFRESH_SCOPE) {
1904
1915
  const startTime = performance.now();
1916
+ const adaptableId = this.adaptableOptions.adaptableId;
1917
+ const runtimeTrack = () => getMarker(adaptableId).track.Runtime.label;
1918
+ const colDefsVersionBefore = this.agGridAdapter.DANGER_getColDefsVersion();
1919
+ const passMarker = runtimeTrack().UpdateColumnModel.start();
1920
+ const deriveMarker = runtimeTrack().DeriveColumnState.start();
1905
1921
  this.deriveAdaptableColumnStateFromAgGrid();
1922
+ deriveMarker.end();
1923
+ const setupColumnsMarker = runtimeTrack().SetupColumns.start();
1906
1924
  this.agGridColumnAdapter.setupColumns();
1907
- this.redrawBody();
1908
- this.refreshHeader();
1909
- this.logger.info(`Updated column model and refreshed grid in ${Math.round(performance.now() - startTime)}ms.`);
1925
+ setupColumnsMarker.end();
1926
+ this.refreshGridAfterColumnModelUpdate(refreshScope);
1927
+ const colDefsVersionAfter = this.agGridAdapter.DANGER_getColDefsVersion();
1928
+ const colDefsChanged = colDefsVersionBefore != null && colDefsVersionAfter != null
1929
+ ? colDefsVersionAfter - colDefsVersionBefore
1930
+ : -1;
1931
+ const columnCount = this.api.columnApi.getColumns().length;
1932
+ const refreshScopeLabel = describeGridRefreshScope(refreshScope);
1933
+ passMarker.end({
1934
+ details: [
1935
+ { name: 'columns', value: columnCount },
1936
+ { name: 'colDefsChanged', value: colDefsChanged },
1937
+ { name: 'refresh', value: refreshScopeLabel },
1938
+ ],
1939
+ });
1940
+ this.logger.info(`Updated column model and refreshed grid in ${Math.round(performance.now() - startTime)}ms (${columnCount} columns, ${colDefsChanged} colDefs changed, refresh: ${refreshScopeLabel}).`);
1941
+ }
1942
+ refreshGridAfterColumnModelUpdate(refreshScope) {
1943
+ const runtimeTrack = getMarker(this.adaptableOptions.adaptableId).track.Runtime.label;
1944
+ if (refreshScope.rows) {
1945
+ const redrawBodyMarker = runtimeTrack.RedrawBody.start();
1946
+ this.redrawBody();
1947
+ redrawBodyMarker.end();
1948
+ }
1949
+ else if (refreshScope.cells) {
1950
+ const refreshCellsMarker = runtimeTrack.RefreshCells.start();
1951
+ this.refreshRenderedCells();
1952
+ refreshCellsMarker.end();
1953
+ }
1954
+ if (refreshScope.header) {
1955
+ const refreshHeaderMarker = runtimeTrack.RefreshHeader.start();
1956
+ this.refreshHeader();
1957
+ refreshHeaderMarker.end();
1958
+ }
1959
+ }
1960
+ refreshRenderedCells() {
1961
+ this.agGridAdapter.getAgGridApi().refreshCells({ force: true, suppressFlash: true });
1962
+ this.refreshAgGridFindIfNeeded();
1963
+ this._emit('GridRefreshed');
1910
1964
  }
1911
1965
  refreshSortIfColumnsSorted() {
1912
1966
  const columnSorts = this.api.layoutApi.getCurrentLayout()?.ColumnSorts;
@@ -64,6 +64,7 @@ export declare class AgGridAdapter {
64
64
  private DANGER_getPrivateAgGridBeans;
65
65
  DANGER_getCreateSparkline(): ((options: AgSparklineOptions) => AgChartInstance<AgSparklineOptions>) | undefined;
66
66
  DANGER_getLiveGridOptions(): GridOptions<any>;
67
+ DANGER_getColDefsVersion(): number | undefined;
67
68
  DANGER_invalidateSortCache(): void;
68
69
  getAgGridRootElement(): HTMLElement;
69
70
  /**
@@ -48,47 +48,6 @@ const patchLocalEventServiceDispatchEvent = (beans) => {
48
48
  DANGER_AG_GRID_ADAPTERS_MAP[gridId]?.handleRowNodeEvent(rowNodeEvent);
49
49
  };
50
50
  };
51
- const patchVisibleColsPartition = (beans) => {
52
- const visibleCols = beans?.visibleCols;
53
- if (!visibleCols || typeof visibleCols.partitionVisibleCols !== 'function') {
54
- console.error(`CRITICAL: could not get hold of AG Grid VisibleColsService.partitionVisibleCols, the selection column may NOT be displayed when it is the last column!`);
55
- return;
56
- }
57
- const original_partitionVisibleCols = visibleCols.partitionVisibleCols;
58
- visibleCols.partitionVisibleCols = function () {
59
- const result = original_partitionVisibleCols.apply(this, arguments);
60
- const leftCols = result?.leftCols ?? [];
61
- const rightCols = result?.rightCols ?? [];
62
- const centerCols = result?.centerCols ?? [];
63
- if (leftCols.length + rightCols.length + centerCols.length === 0) {
64
- return result;
65
- }
66
- const colModel = beans.colModel;
67
- const selectionCol = colModel?.colsList?.find((col) => col?.colKind === 'selection');
68
- if (!selectionCol || !selectionCol.visible) {
69
- return result;
70
- }
71
- if (leftCols.includes(selectionCol) ||
72
- rightCols.includes(selectionCol) ||
73
- centerCols.includes(selectionCol)) {
74
- return result;
75
- }
76
- const showAutoGroupAndValuesOnly = colModel.pivotMode && !colModel.showingPivotResult;
77
- if (showAutoGroupAndValuesOnly && !(beans.selectionColSvc?.isEnabled?.() ?? false)) {
78
- return result;
79
- }
80
- if (selectionCol.pinned === 'right') {
81
- rightCols.push(selectionCol);
82
- }
83
- else if (selectionCol.pinned) {
84
- leftCols.push(selectionCol);
85
- }
86
- else {
87
- centerCols.push(selectionCol);
88
- }
89
- return result;
90
- };
91
- };
92
51
  export class AgGridAdapter {
93
52
  _adaptableInstance;
94
53
  DANGER_USE_GETTER_gridApi;
@@ -117,7 +76,6 @@ export class AgGridAdapter {
117
76
  }
118
77
  DANGER_AG_GRID_BEANS_MAP[gridId] = beans;
119
78
  patchLocalEventServiceDispatchEvent(beans);
120
- patchVisibleColsPartition(beans);
121
79
  };
122
80
  }
123
81
  }
@@ -308,6 +266,9 @@ export class AgGridAdapter {
308
266
  DANGER_getLiveGridOptions() {
309
267
  return this.DANGER_getPrivateAgGridBeans()?.gridOptions;
310
268
  }
269
+ DANGER_getColDefsVersion() {
270
+ return this.DANGER_getPrivateAgGridBeans()?.colModel?.colDefsVersion;
271
+ }
311
272
  DANGER_invalidateSortCache() {
312
273
  this.DANGER_getPrivateAgGridBeans()?.sortSvc?.invalidate();
313
274
  }
@@ -116,6 +116,22 @@ export declare class AgGridColumnAdapter {
116
116
  * The combination of styled column and format cells
117
117
  * This function decides when the two can be merged.
118
118
  */
119
+ /**
120
+ * #derived_pivot_cell_style
121
+ *
122
+ * A pivot result column is generated by AG Grid for a value (base) column, so the cells of
123
+ * `pivot_make_Ford_rating` show (aggregated) `rating` values. Adaptable objects are defined
124
+ * against the base column, and its pivot result cells inherit them:
125
+ * - Format Columns whose Scope contains the base column style the pivot result cells, and their
126
+ * Rule is evaluated against the pivot result cell: in a Rule Expression `[rating]` / `$SCOPE()`
127
+ * resolve to the pivot result cell value (`COL` / `$SCOPE` in `scalarExpressionFunctions.ts`
128
+ * read `pivotResultColumn` from the evaluation context), a Rule Predicate gets it as `value`;
129
+ * - the Styled Column of the base column contributes its cell style (e.g. Gradient background).
130
+ *
131
+ * Returns the context when `params` describe a pivot result cell, `undefined` otherwise.
132
+ * This is the single place deriving it; everything below `setupColumnCellStyle` receives it explicitly.
133
+ */
134
+ private getPivotResultCellContext;
119
135
  private getFormatColumnAndStyledColumnCellStyle;
120
136
  /**
121
137
  * Returns true when the active Styled Column declares a `Font` slot
@@ -136,7 +152,14 @@ export declare class AgGridColumnAdapter {
136
152
  private styledColumnClaimsCellBoxStyle;
137
153
  private getFormatColumnHeaderStyle;
138
154
  private getStyledColumnStyle;
139
- private getFormatColumnCellStyle;
155
+ /**
156
+ * The given (in scope) Format Columns whose Rule matches the cell.
157
+ *
158
+ * @param abColumn - the column the Format Columns are scoped to: the cell's column, or its base column
159
+ * for a pivot result cell inheriting base column Format Columns (see #derived_pivot_cell_style)
160
+ * @param pivotResultColumn - set when the cell is a pivot result cell, see #derived_pivot_cell_style
161
+ */
162
+ private getRelevantFormatColumnsForCell;
140
163
  private getFormatColumnAdaptableStyle;
141
164
  private getAlertCellStyle;
142
165
  private getFlashingCellStyle;
@@ -462,31 +462,14 @@ export class AgGridColumnAdapter {
462
462
  const textStyleToApply = isCurrentMatch
463
463
  ? { ...textMatchStyle, ...currentTextMatchStyle }
464
464
  : textMatchStyle;
465
- let baseStyles = {};
466
- if (this.adaptableApi.columnApi.isPivotResultColumn(columnId)) {
467
- const baseColumn = params.column.getColDef()?.pivotValueColumn;
468
- if (baseColumn) {
469
- const baseColDefCellStyle = baseColumn?.getColDef()?.cellStyle;
470
- const baseColParams = {
471
- ...params,
472
- column: baseColumn,
473
- __pivotResultColumn: params.column,
474
- };
475
- baseStyles =
476
- typeof baseColDefCellStyle === 'function'
477
- ? baseColDefCellStyle(baseColParams)
478
- : baseColDefCellStyle;
479
- }
480
- }
481
- else {
482
- baseStyles = typeof userCellStyle === 'function' ? userCellStyle(params) : userCellStyle;
483
- }
465
+ const baseStyles = typeof userCellStyle === 'function' ? userCellStyle(params) : userCellStyle;
466
+ const pivotResultCell = this.getPivotResultCellContext(params);
484
467
  const result = {
485
468
  ...baseStyles,
486
469
  ...this.getReadOnlyCellStyle(gridCell, params),
487
470
  ...this.getEditableCellStyle(gridCell, params),
488
471
  ...this.getEditedCellStyle(gridCell, params),
489
- ...this.getFormatColumnAndStyledColumnCellStyle(gridCell.column, params),
472
+ ...this.getFormatColumnAndStyledColumnCellStyle(gridCell.column, params, pivotResultCell),
490
473
  ...(isQuickSearchActive ? quickSearchStyle : {}),
491
474
  ...(isQuickSearchActive && textStyleToApply ? textStyleToApply : {}),
492
475
  ...this.getAlertCellStyle(gridCell, params),
@@ -1317,21 +1300,44 @@ export class AgGridColumnAdapter {
1317
1300
  }
1318
1301
  return undefined;
1319
1302
  }
1320
- getFormatColumnAndStyledColumnCellStyle(column, params) {
1321
- const styledColumn = this.adaptableApi.styledColumnApi.getStyledColumnForColumnId(column.columnId);
1303
+ getPivotResultCellContext(params) {
1304
+ if (!this.adaptableApi.columnApi.isPivotResultColumn(params.column.getColId())) {
1305
+ return undefined;
1306
+ }
1307
+ const baseAgColumn = params.column.getColDef()?.pivotValueColumn;
1308
+ const baseColumn = baseAgColumn
1309
+ ? this.adaptableApi.columnApi.getColumnWithColumnId(baseAgColumn.getColId())
1310
+ : undefined;
1311
+ if (!baseColumn) {
1312
+ return undefined;
1313
+ }
1314
+ return { pivotResultColumn: params.column, baseColumn };
1315
+ }
1316
+ getFormatColumnAndStyledColumnCellStyle(column, params, pivotResultCell) {
1317
+ let styledColumn = this.adaptableApi.styledColumnApi.getStyledColumnForColumnId(column.columnId);
1318
+ let styledColumnColumn = column;
1319
+ if (!styledColumn && pivotResultCell) {
1320
+ styledColumn = this.adaptableApi.styledColumnApi.getStyledColumnForColumnId(pivotResultCell.baseColumn.columnId);
1321
+ styledColumnColumn = pivotResultCell.baseColumn;
1322
+ }
1322
1323
  const styledColumnIsActive = !!styledColumn && !styledColumn?.IsSuspended;
1323
1324
  const styledColumnStyle = styledColumnIsActive
1324
- ? this.getStyledColumnStyle(styledColumn, column, params)
1325
+ ? this.getStyledColumnStyle(styledColumn, styledColumnColumn, params)
1325
1326
  : {};
1326
- const activeFormatColumnsWithStyle = this.adaptableApi.formatColumnApi.internalApi.getFormatColumnsWithStyleForColumn(column, {
1327
- target: 'cell',
1328
- });
1329
- let formatColumnStyle = this.getFormatColumnCellStyle(column, activeFormatColumnsWithStyle, params);
1327
+ const formatColumnInternalApi = this.adaptableApi.formatColumnApi.internalApi;
1328
+ const relevantFormatColumnsWithStyle = this.getRelevantFormatColumnsForCell(column, formatColumnInternalApi.getFormatColumnsWithStyleForColumn(column, { target: 'cell' }), params, pivotResultCell?.pivotResultColumn);
1329
+ if (pivotResultCell) {
1330
+ const baseFormatColumnsWithStyle = formatColumnInternalApi
1331
+ .getFormatColumnsWithStyleForColumn(pivotResultCell.baseColumn, { target: 'cell' })
1332
+ .filter((formatColumn) => !relevantFormatColumnsWithStyle.includes(formatColumn));
1333
+ relevantFormatColumnsWithStyle.push(...this.getRelevantFormatColumnsForCell(pivotResultCell.baseColumn, baseFormatColumnsWithStyle, params, pivotResultCell.pivotResultColumn));
1334
+ }
1335
+ let formatColumnStyle = this.getFormatColumnAdaptableStyle(relevantFormatColumnsWithStyle);
1330
1336
  if (styledColumnIsActive) {
1331
- if (this.styledColumnClaimsFontStyle(styledColumn, column)) {
1337
+ if (this.styledColumnClaimsFontStyle(styledColumn, styledColumnColumn)) {
1332
1338
  formatColumnStyle = stripFontCssKeys(formatColumnStyle);
1333
1339
  }
1334
- if (this.styledColumnClaimsCellBoxStyle(styledColumn, column)) {
1340
+ if (this.styledColumnClaimsCellBoxStyle(styledColumn, styledColumnColumn)) {
1335
1341
  formatColumnStyle = stripCellBoxCssKeys(formatColumnStyle);
1336
1342
  }
1337
1343
  }
@@ -1444,14 +1450,10 @@ export class AgGridColumnAdapter {
1444
1450
  }
1445
1451
  return style;
1446
1452
  }
1447
- getFormatColumnCellStyle(abColumn, activeFormatColumnsWithStyle, params) {
1448
- if (!activeFormatColumnsWithStyle.length) {
1449
- return {};
1450
- }
1451
- const relevantFormatColumnsWithStyle = activeFormatColumnsWithStyle.filter((formatColumn) => {
1452
- return this.adaptableApi.formatColumnApi.internalApi.formatColumnShouldRenderInCell(formatColumn, abColumn, params.node, params.value, params.__pivotResultColumn);
1453
+ getRelevantFormatColumnsForCell(abColumn, activeFormatColumnsWithStyle, params, pivotResultColumn) {
1454
+ return activeFormatColumnsWithStyle.filter((formatColumn) => {
1455
+ return this.adaptableApi.formatColumnApi.internalApi.formatColumnShouldRenderInCell(formatColumn, abColumn, params.node, params.value, pivotResultColumn);
1453
1456
  });
1454
- return this.getFormatColumnAdaptableStyle(relevantFormatColumnsWithStyle);
1455
1457
  }
1456
1458
  getFormatColumnAdaptableStyle(formatColumns) {
1457
1459
  return formatColumns.reduceRight((style, formatColumn) => {
@@ -0,0 +1,20 @@
1
+ import type { GridRefreshScope } from '../AdaptableInterfaces/IAdaptable';
2
+ /**
3
+ * see #narrow_column_model_refresh
4
+ *
5
+ * Helpers for the refresh scope of a column-model pass (`AdaptableAgGrid.updateColumnModelAndRefreshGrid`).
6
+ */
7
+ /** The legacy behaviour: destroy & recreate every rendered row and every header cell. */
8
+ export declare const FULL_GRID_REFRESH_SCOPE: Readonly<GridRefreshScope>;
9
+ /** Re-run the cell-level callbacks on the rendered cells; rows and header are kept. */
10
+ export declare const CELLS_GRID_REFRESH_SCOPE: Readonly<GridRefreshScope>;
11
+ /** Only set up the columns; whatever colDef value changed is refreshed by AG Grid itself (see #col_def_commit). */
12
+ export declare const NO_GRID_REFRESH_SCOPE: Readonly<GridRefreshScope>;
13
+ export declare const mergeGridRefreshScopes: (a: GridRefreshScope, b: GridRefreshScope) => GridRefreshScope;
14
+ /**
15
+ * The part of `requested` that `done` did not cover, or `null` when `done` already covers everything.
16
+ * A row redraw covers a cell refresh (the cells are recreated with the rows).
17
+ */
18
+ export declare const getMissingGridRefreshScope: (done: GridRefreshScope, requested: GridRefreshScope) => GridRefreshScope | null;
19
+ /** eg `rows+header`, `cells`, `none` - used in the perf track details and the log line */
20
+ export declare const describeGridRefreshScope: (scope: GridRefreshScope) => string;