From e327f42848279662d063e4626b0cc4723b3081dd Mon Sep 17 00:00:00 2001 From: Stephen Cooper Date: Tue, 13 Jan 2026 10:27:58 +0000 Subject: [PATCH 1/5] AG-16432 release bundle size comparison (#12871) * Improve report details * Enable comparison based on src swap --- .github/actions/module-size-test/action.yml | 52 ++++++++++++++++++++ .github/workflows/module-size-vs-release.yml | 7 +-- scripts/ci/compare-module-sizes.mjs | 20 +++++++- 3 files changed, 75 insertions(+), 4 deletions(-) diff --git a/.github/actions/module-size-test/action.yml b/.github/actions/module-size-test/action.yml index 84d112b6a71..5ae27dd6546 100644 --- a/.github/actions/module-size-test/action.yml +++ b/.github/actions/module-size-test/action.yml @@ -25,6 +25,10 @@ inputs: description: 'Git ref to get .github/actions from (for testing older refs that lack these actions)' required: false default: '' + source-ref: + description: 'Git ref to get source code from (swaps src folders for ag-grid-community, ag-grid-enterprise, ag-grid-react). When set, uses ref for tooling but source-ref for actual source code.' + required: false + default: '' runs: using: composite @@ -51,6 +55,54 @@ runs: cp -r .actions-temp/.github/actions .github/actions rm -rf .actions-temp + - name: Checkout source from source-ref + if: inputs.source-ref != '' && inputs.source-ref != inputs.ref + uses: actions/checkout@v4 + with: + ref: ${{ inputs.source-ref }} + sparse-checkout: | + packages/ag-grid-community/src + packages/ag-grid-enterprise/src + packages/ag-grid-react/src + path: .source-temp + + - name: Swap src folders from source-ref + if: inputs.source-ref != '' && inputs.source-ref != inputs.ref + shell: bash + run: | + echo "Swapping src folders from ${{ inputs.source-ref }} into ${{ inputs.ref }} tooling..." + + # Swap ag-grid-community/src + if [ -d ".source-temp/packages/ag-grid-community/src" ]; then + rm -rf packages/ag-grid-community/src + cp -r .source-temp/packages/ag-grid-community/src packages/ag-grid-community/src + echo "✓ Swapped ag-grid-community/src" + else + echo "⚠ Warning: ag-grid-community/src not found in source-ref" + fi + + # Swap ag-grid-enterprise/src + if [ -d ".source-temp/packages/ag-grid-enterprise/src" ]; then + rm -rf packages/ag-grid-enterprise/src + cp -r .source-temp/packages/ag-grid-enterprise/src packages/ag-grid-enterprise/src + echo "✓ Swapped ag-grid-enterprise/src" + else + echo "⚠ Warning: ag-grid-enterprise/src not found in source-ref" + fi + + # Swap ag-grid-react/src + if [ -d ".source-temp/packages/ag-grid-react/src" ]; then + rm -rf packages/ag-grid-react/src + cp -r .source-temp/packages/ag-grid-react/src packages/ag-grid-react/src + echo "✓ Swapped ag-grid-react/src" + else + echo "⚠ Warning: ag-grid-react/src not found in source-ref" + fi + + # Clean up + rm -rf .source-temp + echo "Source swap complete." + - name: Setup uses: ./.github/actions/setup-nx with: diff --git a/.github/workflows/module-size-vs-release.yml b/.github/workflows/module-size-vs-release.yml index 800959e1ca7..73ef9a3852b 100644 --- a/.github/workflows/module-size-vs-release.yml +++ b/.github/workflows/module-size-vs-release.yml @@ -111,6 +111,7 @@ jobs: base-ref: latest # Build and run module size tests on release tag (sharded) - only if cache miss + # Uses latest branch tooling with source code from the release tag module-size-release: name: Module Size Release (${{ matrix.shard }}/${{ strategy.job-total }}) runs-on: ubuntu-latest @@ -130,12 +131,12 @@ jobs: - name: Run module size tests uses: ./.github/actions/module-size-test with: - ref: ${{ needs.prepare.outputs.release-tag }} + ref: latest shard: ${{ matrix.shard }} total-shards: ${{ strategy.job-total }} artifact-prefix: module-size-release - base-ref: ${{ needs.prepare.outputs.release-tag }} - actions-ref: latest + base-ref: latest + source-ref: ${{ needs.prepare.outputs.release-tag }} # Cache release results (only when we had to build) cache-release-results: diff --git a/scripts/ci/compare-module-sizes.mjs b/scripts/ci/compare-module-sizes.mjs index 8085aeacae5..dcfcdc6b545 100644 --- a/scripts/ci/compare-module-sizes.mjs +++ b/scripts/ci/compare-module-sizes.mjs @@ -205,7 +205,25 @@ report += '
\n📊 Full Statistics\n\n'; report += `- **Modules compared:** ${diffs.length}\n`; report += `- **Modules with increases:** ${diffs.filter((d) => d.selfSizeDiff > 0).length}\n`; report += `- **Modules with decreases:** ${diffs.filter((d) => d.selfSizeDiff < 0).length}\n`; -report += `- **Modules unchanged:** ${diffs.filter((d) => d.selfSizeDiff === 0).length}\n`; +report += `- **Modules unchanged:** ${diffs.filter((d) => d.selfSizeDiff === 0).length}\n\n`; + +// All changes table +const allChanges = diffs.filter((d) => d.selfSizeDiff !== 0); +if (allChanges.length > 0) { + report += '#### All Module Changes\n\n'; + report += '| Module(s) | Base (KB) | PR (KB) | Diff (KB) | Gzip Diff (KB) |\n'; + report += '|-----------|-----------|---------|-----------|----------------|\n'; + + for (const diff of allChanges) { + const moduleName = diff.modules.length === 0 ? 'Base (no modules)' : diff.modules.join(', '); + const emoji = getChangeEmoji(diff.selfSizeDiff); + const status = diff.isNew ? ' 🆕' : diff.isRemoved ? ' 🗑️' : ''; + + report += `| ${emoji} ${moduleName}${status} | ${formatSize(diff.baseSelfSize)} | ${formatSize(diff.prSelfSize)} | **${formatDiff(diff.selfSizeDiff)}** | ${formatDiff(diff.gzipSizeDiff)} |\n`; + } + report += '\n'; +} + report += '
\n'; // Write report From ab67057e32d492b6640da9758bdaa35a66bfd465 Mon Sep 17 00:00:00 2001 From: seanlandsman Date: Tue, 13 Jan 2026 11:56:40 +0000 Subject: [PATCH 2/5] Increase timeout on grid state tests to remove flakiness from tests (#12872) --- .../src/grid-state/grid-state.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/testing/behavioural/src/grid-state/grid-state.test.ts b/testing/behavioural/src/grid-state/grid-state.test.ts index 13e2d7f9058..6d4f175c123 100644 --- a/testing/behavioural/src/grid-state/grid-state.test.ts +++ b/testing/behavioural/src/grid-state/grid-state.test.ts @@ -362,7 +362,7 @@ describe('StateService - Grid State Management', () => { name: { filterType: 'text', type: 'startsWith', filter: 'A' }, }); - await asyncSetTimeout(20); + await asyncSetTimeout(50); expect(api.getState().filter).toEqual({ advancedFilterModel: undefined, @@ -390,7 +390,7 @@ describe('StateService - Grid State Management', () => { // Focus a cell api.setFocusedCell(0, 'name'); - await asyncSetTimeout(10); + await asyncSetTimeout(50); expect(api.getState().focusedCell).toEqual({ colId: 'name', @@ -408,7 +408,7 @@ describe('StateService - Grid State Management', () => { api.addCellRange({ rowStartIndex: 0, rowEndIndex: 1, columns: ['name'] }); - await asyncSetTimeout(10); + await asyncSetTimeout(50); expect(api.getState().cellSelection).toEqual({ cellRanges: [ @@ -451,7 +451,7 @@ describe('StateService - Grid State Management', () => { api.ensureIndexVisible(20); - await asyncSetTimeout(10); + await asyncSetTimeout(50); expect(api.getState().scroll).toEqual({ left: 0, @@ -536,7 +536,7 @@ describe('StateService - Grid State Management', () => { }; api.setState(stateToApply); - await asyncSetTimeout(5); + await asyncSetTimeout(50); const state = api.getState(); expect(state.sort?.sortModel).toHaveLength(1); @@ -563,7 +563,7 @@ describe('StateService - Grid State Management', () => { // Apply state but ignore rowSelection api.setState(stateToApply, ['rowSelection']); - await asyncSetTimeout(5); + await asyncSetTimeout(50); const state = api.getState(); expect(state.sort?.sortModel).toHaveLength(1); @@ -609,7 +609,7 @@ describe('StateService - Grid State Management', () => { }); api2.setState(savedState); - await asyncSetTimeout(5); + await asyncSetTimeout(50); const restoredState = api2.getState(); expect(restoredState).toEqual(savedState); @@ -676,7 +676,7 @@ describe('StateService - Grid State Management', () => { }); api.applyColumnState({ state: [{ colId: 'name', sort: 'asc' }] }); - await asyncSetTimeout(10); + await asyncSetTimeout(50); expect(eventFired).toBe(true); expect(eventState?.sort).toBeDefined(); From 9efc626cb7895e335d8a6c3bdbd7cdfde36d91d9 Mon Sep 17 00:00:00 2001 From: Alan Treadway Date: Tue, 13 Jan 2026 12:05:50 +0000 Subject: [PATCH 3/5] Cleanup .yarnrc after Node 22 bump. --- .yarnrc | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .yarnrc diff --git a/.yarnrc b/.yarnrc deleted file mode 100644 index 59c218016eb..00000000000 --- a/.yarnrc +++ /dev/null @@ -1,3 +0,0 @@ -# Ignore engine requirements for packages like rulesync that require Node 22+ -# The repo uses Node 20 and patch-package fixes compatibility issues -ignore-engines true From 5fa04914c105da498cb39ce5a9af57c85cea1daf Mon Sep 17 00:00:00 2001 From: Alan Treadway Date: Tue, 13 Jan 2026 12:30:15 +0000 Subject: [PATCH 4/5] Remove Node 20 compatibility from rulesync patch. The globSync import change is no longer needed now that the repo uses Node 22. --- patches/rulesync+5.2.0.patch | 9 --------- 1 file changed, 9 deletions(-) diff --git a/patches/rulesync+5.2.0.patch b/patches/rulesync+5.2.0.patch index 38e67401e79..4ffa47a86a3 100644 --- a/patches/rulesync+5.2.0.patch +++ b/patches/rulesync+5.2.0.patch @@ -2,15 +2,6 @@ diff --git a/node_modules/rulesync/dist/index.js b/node_modules/rulesync/dist/in index 23dce30..e2b3dc0 100755 --- a/node_modules/rulesync/dist/index.js +++ b/node_modules/rulesync/dist/index.js -@@ -86,7 +86,7 @@ import { resolve as resolve2 } from "path"; - import { parse as parseJsonc } from "jsonc-parser"; - - // src/utils/file.ts --import { globSync } from "fs"; -+import { globSync } from "glob"; - import { mkdir, readdir, readFile, rm, stat, writeFile } from "fs/promises"; - import os from "os"; - import { dirname, join, relative, resolve } from "path"; @@ -10595,12 +10595,7 @@ var toolRuleFactories = /* @__PURE__ */ new Map([ meta: { extension: "md", From 5a377053d3396c32f74d8fe4d0877e109a8fc761 Mon Sep 17 00:00:00 2001 From: Guilherme Lopes Date: Tue, 13 Jan 2026 09:53:12 -0300 Subject: [PATCH 5/5] Decouple RangeService from RowNumbers and Formulas (#12866) * decouple rangeService from rowNumbers and Formulas * fixed lint --- .../src/formula/formulaService.ts | 20 +++- .../rangeSelectionExtensions.ts | 13 +++ .../src/rangeSelection/rangeService.ts | 103 ++++++++++-------- .../src/rowNumbers/rowNumbersService.ts | 34 +++++- 4 files changed, 121 insertions(+), 49 deletions(-) create mode 100644 packages/ag-grid-enterprise/src/rangeSelection/rangeSelectionExtensions.ts diff --git a/packages/ag-grid-enterprise/src/formula/formulaService.ts b/packages/ag-grid-enterprise/src/formula/formulaService.ts index ae94bb930b7..cca7ecbe24c 100644 --- a/packages/ag-grid-enterprise/src/formula/formulaService.ts +++ b/packages/ag-grid-enterprise/src/formula/formulaService.ts @@ -9,6 +9,10 @@ import type { } from 'ag-grid-community'; import { BeanStub, _convertColumnEventSourceType, _isExpressionString, _warn } from 'ag-grid-community'; +import type { + RangeSelectionExtension, + RangeSelectionExtensionRegistry, +} from '../rangeSelection/rangeSelectionExtensions'; import { parseFormula } from './ast/parsers'; import { serializeFormula } from './ast/serializer'; import type { FormulaNode } from './ast/utils'; @@ -91,7 +95,7 @@ interface FormulaFrame { ast: FormulaNode; unresolvedDepIterator: Generator; } -export class FormulaService extends BeanStub implements IFormulaService, NamedBean { +export class FormulaService extends BeanStub implements IFormulaService, NamedBean, RangeSelectionExtension { public readonly beanName = 'formula' as const; /** Cache: row -> (column -> CellFormula) */ @@ -150,6 +154,7 @@ export class FormulaService extends BeanStub implements IFormulaService, NamedBe public postConstruct(): void { this.setupFunctions(); + this.registerRangeSelectionExtension(); const refreshFormulas = () => { if (this.active) { @@ -181,6 +186,19 @@ export class FormulaService extends BeanStub implements IFormulaService, NamedBe }); } + public shouldSuppressRangeSelection(eventTarget: EventTarget | null): boolean { + return !!(eventTarget as HTMLElement | null)?.closest?.('.ag-formula-input-field'); + } + + private registerRangeSelectionExtension(): void { + const rangeSvc = this.beans.rangeSvc as RangeSelectionExtensionRegistry | undefined; + if (!rangeSvc) { + return; + } + rangeSvc.registerRangeSelectionExtension(this); + this.addDestroyFunc(() => rangeSvc.unregisterRangeSelectionExtension?.(this)); + } + public updateFormulaByOffset(params: { value: string; rowDelta?: number; diff --git a/packages/ag-grid-enterprise/src/rangeSelection/rangeSelectionExtensions.ts b/packages/ag-grid-enterprise/src/rangeSelection/rangeSelectionExtensions.ts new file mode 100644 index 00000000000..61837c5c598 --- /dev/null +++ b/packages/ag-grid-enterprise/src/rangeSelection/rangeSelectionExtensions.ts @@ -0,0 +1,13 @@ +import type { AgColumn, CellPosition, CellRange } from 'ag-grid-community'; + +export interface RangeSelectionExtension { + shouldSuppressRangeSelection?(eventTarget: EventTarget | null): boolean; + shouldSkipColumn?(column: AgColumn): boolean; + isAllColumnsSelectionCell?(cellPosition: CellPosition): boolean; + isAllColumnsRange?(range: CellRange, allColumns: AgColumn[]): boolean; +} + +export interface RangeSelectionExtensionRegistry { + registerRangeSelectionExtension(extension: RangeSelectionExtension): void; + unregisterRangeSelectionExtension?(extension: RangeSelectionExtension): void; +} diff --git a/packages/ag-grid-enterprise/src/rangeSelection/rangeService.ts b/packages/ag-grid-enterprise/src/rangeSelection/rangeService.ts index f3ed6de4aee..90c824db42e 100644 --- a/packages/ag-grid-enterprise/src/rangeSelection/rangeService.ts +++ b/packages/ag-grid-enterprise/src/rangeSelection/rangeService.ts @@ -44,7 +44,6 @@ import { _isCellSelectionEnabled, _isDomLayout, _isRowBefore, - _isRowNumbers, _isSameRow, _isUsingNewCellSelectionAPI, _last, @@ -53,13 +52,13 @@ import { _removeAllFromArray, _removeFromArray, _warn, - isRowNumberCol, } from 'ag-grid-community'; import { CellRangeFeature } from './cellRangeFeature'; import { DragListenerFeature } from './dragListenerFeature'; import { HeaderGroupCellMouseListenerFeature } from './headerGroupCellMouseListenerFeature'; import { RangeHeaderHighlightFeature } from './rangeHeaderHighlightFeature'; +import type { RangeSelectionExtension, RangeSelectionExtensionRegistry } from './rangeSelectionExtensions'; enum SelectionMode { NORMAL, @@ -71,7 +70,7 @@ interface ColumnRangeSelectionContext { root?: AgColumn; } -export class RangeService extends BeanStub implements NamedBean, IRangeService { +export class RangeService extends BeanStub implements NamedBean, IRangeService, RangeSelectionExtensionRegistry { beanName = 'rangeSvc' as const; private rowModel: IRowModel; @@ -82,6 +81,7 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { private ctrlsSvc: CtrlsService; private valueSvc: ValueService; private selectionMode: SelectionMode; + private readonly rangeSelectionExtensions: RangeSelectionExtension[] = []; public wireBeans(beans: BeanCollection) { this.rowModel = beans.rowModel; @@ -147,6 +147,37 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { }); } + public registerRangeSelectionExtension(extension: RangeSelectionExtension): void { + if (this.rangeSelectionExtensions.includes(extension)) { + return; + } + this.rangeSelectionExtensions.push(extension); + } + + public unregisterRangeSelectionExtension(extension: RangeSelectionExtension): void { + _removeFromArray(this.rangeSelectionExtensions, extension); + } + + private shouldSuppressRangeSelection(eventTarget: EventTarget | null): boolean { + return this.rangeSelectionExtensions.some((extension) => extension.shouldSuppressRangeSelection?.(eventTarget)); + } + + private shouldSkipColumn(column: AgColumn): boolean { + return this.rangeSelectionExtensions.some((extension) => extension.shouldSkipColumn?.(column)); + } + + private isAllColumnsSelectionCell(cellPosition: CellPosition): boolean { + return this.rangeSelectionExtensions.some((extension) => extension.isAllColumnsSelectionCell?.(cellPosition)); + } + + private isAllColumnsRange(range: CellRange, allColumns: AgColumn[]): boolean { + return this.rangeSelectionExtensions.some((extension) => extension.isAllColumnsRange?.(range, allColumns)); + } + + private updateSelectionModeForCell(cellPosition: CellPosition): void { + this.setSelectionMode(this.isAllColumnsSelectionCell(cellPosition)); + } + // Drag And Drop Target Methods public onDragStart(mouseEvent: MouseEvent): void { const gos = this.gos; @@ -154,8 +185,7 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { if (!_isCellSelectionEnabled(gos) || _getRowCtrlForEventTarget(gos, target)?.isSuppressMouseEvent(mouseEvent)) { return; } - // Dragging to select text inside the formula editor should not start range selection. - if (isEventWithinFormulaEditor(target)) { + if (this.shouldSuppressRangeSelection(target)) { return; } @@ -388,13 +418,12 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { const { beans } = this; const target = event.target as HTMLElement | null; - // Clicking inside the formula editor should not create a new range for the edited cell. - if (isEventWithinFormulaEditor(target)) { + if (this.shouldSuppressRangeSelection(target)) { return; } - const isRowNumber = isRowNumberCol(cell.column); - if (isRowNumber) { + const isAllColumnsCell = this.isAllColumnsSelectionCell(cell); + if (isAllColumnsCell) { event.preventDefault(); } @@ -402,19 +431,19 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { return this.extendLatestRangeToCell(cell); } - if (isRowNumber && _interpretAsRightClick(beans, event)) { + if (isAllColumnsCell && _interpretAsRightClick(beans, event)) { return; } const isMultiRange = this.isMultiRange(event); - this.setSelectionMode(isRowNumber); + this.updateSelectionModeForCell(cell); const columns = this.calculateColumnsBetween(cell.column as AgColumn, cell.column as AgColumn); if (!columns) { return; } - const containingRange = isRowNumber + const containingRange = isAllColumnsCell ? this.findContainingRange({ columns, startRow: cell, @@ -422,10 +451,10 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { }) : undefined; const isMultiRangeRemoval = - isRowNumber && !!containingRange && isMultiRange && (event.ctrlKey || event.metaKey); + isAllColumnsCell && !!containingRange && isMultiRange && (event.ctrlKey || event.metaKey); if (isMultiRangeRemoval && containingRange) { - this.removeRowFromRowNumberRange(cell, containingRange); + this.removeRowFromAllColumnsRange(cell, containingRange); } else { this.setRangeToCell(cell, isMultiRange); } @@ -442,7 +471,7 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { return editingWithRanges || (allowMulti ? isMultiKey : false); } - private removeRowFromRowNumberRange(cell: CellPosition, containingRange: CellRange): void { + private removeRowFromAllColumnsRange(cell: CellPosition, containingRange: CellRange): void { const { beans, cellRanges } = this; const firstRow = _getFirstRow(beans); const lastRow = _getLastRow(beans); @@ -483,16 +512,12 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { } public setRangeToCell(cell: CellPosition, appendRange = false): void { - const { gos, beans } = this; + const { gos } = this; if (!_isCellSelectionEnabled(gos)) { return; } - const isRowNumbersEnabled = _isRowNumbers(beans); - if (isRowNumbersEnabled) { - const allColumnsRange = isRowNumberCol(cell.column); - this.setSelectionMode(allColumnsRange); - } + this.updateSelectionModeForCell(cell); const columns = this.calculateColumnsBetween(cell.column as AgColumn, cell.column as AgColumn); @@ -643,7 +668,7 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { const cellRange = _last(this.cellRanges); - this.setSelectionMode(isRowNumberCol(cellPosition.column)); + this.updateSelectionModeForCell(cellPosition); this.updateRangeRowBoundary({ cellRange, boundary: 'end', cellPosition }); } @@ -652,7 +677,7 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { return; } - this.setSelectionMode(isRowNumberCol(cellPosition.column)); + this.updateSelectionModeForCell(cellPosition); this.updateRangeRowBoundary({ cellRange, boundary: 'end', cellPosition }); } @@ -752,8 +777,7 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { this.setSelectionMode(false); this.removeAllCellRanges(true); - const rowNumbersEnabled = _isRowNumbers(this.beans); - const allDataColumns = rowNumbersEnabled ? this.getColumnsFromModel(this.visibleCols.allCols) ?? [] : []; + const allDataColumns = this.getColumnsFromModel(this.visibleCols.allCols) ?? []; let hasAllColumnsRange = false; for (const cellRange of cellRanges) { @@ -774,21 +798,15 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { }); } - if ( - rowNumbersEnabled && - !hasAllColumnsRange && - allDataColumns.length > 0 && - cellRange.columns && - cellRange.columns.length === allDataColumns.length - ) { - hasAllColumnsRange = allDataColumns.every((column) => cellRange.columns!.includes(column)); + if (!hasAllColumnsRange && allDataColumns.length > 0 && this.isAllColumnsRange(cellRange, allDataColumns)) { + hasAllColumnsRange = true; } this.cellRanges.push(cellRange); } - // Restore row-number selection mode if any range spans all data columns. - this.setSelectionMode(rowNumbersEnabled && hasAllColumnsRange); + // Restore all-columns selection mode if any range spans all data columns. + this.setSelectionMode(hasAllColumnsRange); this.dispatchChangedEvent(false, true); } @@ -1078,7 +1096,7 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { public intersectLastRange(fromMouseClick?: boolean) { // when ranges are created due to a mouse click without drag (happens in cellMouseListener) // this method will be called with `fromMouseClick=true`. - // Formula editing relies on overlapping ranges to keep token colors accurate. + // Range selection while editing relies on overlapping ranges to preserve editor overlays. if (this.beans.editSvc?.isRangeSelectionEnabledWhileEditing?.()) { return; } @@ -1311,8 +1329,7 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { } private getColumnsFromModel(cols?: (string | AgColumn)[]): AgColumn[] | undefined { - const { visibleCols, beans, selectionMode } = this; - const isRowHeaderActive = _isRowNumbers(beans); + const { visibleCols, selectionMode } = this; if (!cols || selectionMode === SelectionMode.ALL_COLUMNS) { cols = visibleCols.allCols; @@ -1322,7 +1339,7 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService { for (const col of cols) { const column = this.getColumnFromModel(col); - if (!column || (isRowHeaderActive && shouldSkipCurrentColumn(column))) { + if (!column || this.shouldSkipColumn(column)) { continue; } columns.push(column); @@ -1543,10 +1560,6 @@ function rowMin(rows: RowPosition[]): RowPosition | undefined { return min; } -function shouldSkipCurrentColumn(currentColumn: AgColumn): boolean { - return isRowNumberCol(currentColumn); -} - function isLastCellOfRange(cellRange: CellRange, cell: CellPosition): boolean { const { startRow, endRow } = cellRange; const lastRow = _isRowBefore(startRow!, endRow!) ? endRow : startRow; @@ -1569,7 +1582,3 @@ function replaceEdgeRow(range: CellRange, row: RowPosition | null, topOrBottom: } range[key] = row ?? undefined; } - -function isEventWithinFormulaEditor(target: HTMLElement | null): boolean { - return !!target?.closest?.('.ag-formula-input-field'); -} diff --git a/packages/ag-grid-enterprise/src/rowNumbers/rowNumbersService.ts b/packages/ag-grid-enterprise/src/rowNumbers/rowNumbersService.ts index 838f79ab05a..335f0fa53a8 100644 --- a/packages/ag-grid-enterprise/src/rowNumbers/rowNumbersService.ts +++ b/packages/ag-grid-enterprise/src/rowNumbers/rowNumbersService.ts @@ -24,6 +24,7 @@ import type { CellClassParams, CellCtrl, CellPosition, + CellRange, ColDef, IRowNumbersRowResizeFeature, IRowNumbersService, @@ -38,9 +39,13 @@ import type { _HeaderComp, } from 'ag-grid-community'; +import type { + RangeSelectionExtension, + RangeSelectionExtensionRegistry, +} from '../rangeSelection/rangeSelectionExtensions'; import { RowNumbersRowResizeFeature, _isRowNumbersResizerEnabled } from './rowNumbersRowResizeFeature'; -export class RowNumbersService extends BeanStub implements NamedBean, IRowNumbersService { +export class RowNumbersService extends BeanStub implements NamedBean, IRowNumbersService, RangeSelectionExtension { beanName = 'rowNumbersSvc' as const; public columns: _ColumnCollections | null; @@ -69,6 +74,33 @@ export class RowNumbersService extends BeanStub implements NamedBean, IRowNumber }); this.refreshSelectionIntegration(); + this.registerRangeSelectionExtension(); + } + + public shouldSkipColumn(column: AgColumn): boolean { + return _isRowNumbers(this.beans) && isRowNumberCol(column); + } + + public isAllColumnsSelectionCell(cellPosition: CellPosition): boolean { + return _isRowNumbers(this.beans) && isRowNumberCol(cellPosition.column); + } + + public isAllColumnsRange(range: CellRange, allColumns: AgColumn[]): boolean { + if (!_isRowNumbers(this.beans) || allColumns.length === 0) { + return false; + } + return ( + range.columns.length === allColumns.length && allColumns.every((column) => range.columns.includes(column)) + ); + } + + private registerRangeSelectionExtension(): void { + const rangeSvc = this.beans.rangeSvc as RangeSelectionExtensionRegistry | undefined; + if (!rangeSvc) { + return; + } + rangeSvc.registerRangeSelectionExtension(this); + this.addDestroyFunc(() => rangeSvc.unregisterRangeSelectionExtension?.(this)); } public addColumns(cols: _ColumnCollections): void {