apex-grid 3.4.0 → 3.5.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.
Files changed (109) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/README.md +45 -6
  3. package/components/grid.d.ts +127 -0
  4. package/components/grid.js +25 -0
  5. package/components/grid.js.map +1 -1
  6. package/components/header-row.js +8 -0
  7. package/components/header-row.js.map +1 -1
  8. package/components/header.js +5 -3
  9. package/components/header.js.map +1 -1
  10. package/components/row.js +32 -4
  11. package/components/row.js.map +1 -1
  12. package/components/virtualizer.d.ts +5 -1
  13. package/components/virtualizer.js +72 -2
  14. package/components/virtualizer.js.map +1 -1
  15. package/controllers/navigation.d.ts +1 -0
  16. package/controllers/navigation.js +10 -5
  17. package/controllers/navigation.js.map +1 -1
  18. package/controllers/reorder.js +4 -2
  19. package/controllers/reorder.js.map +1 -1
  20. package/controllers/state.d.ts +9 -3
  21. package/controllers/state.js +11 -1
  22. package/controllers/state.js.map +1 -1
  23. package/custom-elements.json +439 -181
  24. package/docs/assets/hierarchy.js +1 -1
  25. package/docs/assets/navigation.js +1 -1
  26. package/docs/assets/search.js +1 -1
  27. package/docs/classes/ApexGrid.html +586 -0
  28. package/docs/classes/ApexGridPaginator.html +36 -0
  29. package/docs/classes/ApexGridToolbar.html +67 -0
  30. package/docs/functions/localize.html +2 -2
  31. package/docs/functions/setup.html +1 -2
  32. package/docs/hierarchy.html +1 -1
  33. package/docs/index.html +33 -6
  34. package/docs/interfaces/ApexCellValidationFailedEvent.html +1 -1
  35. package/docs/interfaces/ApexCellValueChangedEvent.html +1 -1
  36. package/docs/interfaces/ApexCellValueChangingEvent.html +2 -2
  37. package/docs/interfaces/ApexColumnMovedEvent.html +2 -2
  38. package/docs/interfaces/ApexColumnMovingEvent.html +1 -1
  39. package/docs/interfaces/ApexDetailContext.html +2 -2
  40. package/docs/interfaces/ApexGridEventMap.html +5 -5
  41. package/docs/interfaces/ApexRowMovingEvent.html +1 -1
  42. package/docs/interfaces/ApexRowPinningEvent.html +1 -1
  43. package/docs/interfaces/BaseApexCellContext.html +1 -1
  44. package/docs/interfaces/BaseApexEditorContext.html +1 -1
  45. package/docs/interfaces/BaseColumnConfiguration.html +3 -3
  46. package/docs/interfaces/CSVExportOptions.html +2 -2
  47. package/docs/interfaces/DataPipelineConfiguration.html +2 -2
  48. package/docs/interfaces/EditingHistoryConfiguration.html +1 -1
  49. package/docs/interfaces/ExportFormat.html +2 -2
  50. package/docs/interfaces/ExportOptions.html +1 -1
  51. package/docs/interfaces/GridRowPinningConfiguration.html +1 -1
  52. package/docs/interfaces/GridRowReorderingConfiguration.html +2 -2
  53. package/docs/interfaces/PaginationConfiguration.html +1 -1
  54. package/docs/interfaces/PaginationState.html +1 -1
  55. package/docs/media/_tokens.scss +29 -8
  56. package/docs/media/package.json +3 -4
  57. package/docs/media/state-persistence.html +0 -10
  58. package/docs/modules.html +1 -1
  59. package/docs/types/DataPipelineParams.html +2 -2
  60. package/docs/types/EditMode.html +2 -2
  61. package/docs/types/GridLocaleText.html +1 -1
  62. package/docs/types/PaginationMode.html +1 -1
  63. package/docs/variables/EN_LOCALE.html +3 -3
  64. package/docs/variables/esLocale.html +1 -1
  65. package/i18n/en.d.ts +14 -0
  66. package/i18n/en.js +14 -0
  67. package/i18n/en.js.map +1 -1
  68. package/i18n/es.js +14 -0
  69. package/i18n/es.js.map +1 -1
  70. package/index.d.ts +2 -0
  71. package/index.js +2 -0
  72. package/index.js.map +1 -1
  73. package/internal/feature-module.d.ts +22 -0
  74. package/internal/feature-module.js +5 -0
  75. package/internal/feature-module.js.map +1 -1
  76. package/internal/index.d.ts +2 -2
  77. package/internal/index.js +1 -1
  78. package/internal/index.js.map +1 -1
  79. package/internal/utils.d.ts +14 -0
  80. package/internal/utils.js +5 -0
  81. package/internal/utils.js.map +1 -1
  82. package/package.json +1 -2
  83. package/setup.d.ts +12 -11
  84. package/setup.js +12 -4
  85. package/setup.js.map +1 -1
  86. package/styles/_common.css.js +1 -1
  87. package/styles/_common.css.js.map +1 -1
  88. package/styles/_tokens.css.js +1 -1
  89. package/styles/_tokens.css.js.map +1 -1
  90. package/styles/body-cell/body-cell.css.js +1 -1
  91. package/styles/body-cell/body-cell.css.js.map +1 -1
  92. package/styles/body-row/body-row.css.js +1 -1
  93. package/styles/body-row/body-row.css.js.map +1 -1
  94. package/styles/filter-row/filter-row.css.js +1 -1
  95. package/styles/filter-row/filter-row.css.js.map +1 -1
  96. package/styles/grid/_grid.base.css.js +1 -1
  97. package/styles/grid/_grid.base.css.js.map +1 -1
  98. package/styles/grid/grid.css.js +1 -1
  99. package/styles/grid/grid.css.js.map +1 -1
  100. package/styles/group-header-row/group-header-row.css.js +1 -1
  101. package/styles/group-header-row/group-header-row.css.js.map +1 -1
  102. package/styles/header-cell/header-cell.css.js +1 -1
  103. package/styles/header-cell/header-cell.css.js.map +1 -1
  104. package/styles/header-row/header-row.base.css.js +1 -1
  105. package/styles/header-row/header-row.base.css.js.map +1 -1
  106. package/styles/paginator/paginator.css.js +1 -1
  107. package/styles/paginator/paginator.css.js.map +1 -1
  108. package/styles/toolbar/toolbar.css.js +1 -1
  109. package/styles/toolbar/toolbar.css.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"virtualizer.js","sourceRoot":"","sources":["../../src/components/virtualizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,cAAc;IAA3D;;QAckB,aAAQ,GAAG,KAAK,CAAC;IAQnC,CAAC;IArBQ,MAAM,KAAK,OAAO;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAEM,MAAM,CAAC,QAAQ;QACpB,iBAAiB,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;IASe,KAAK,CAAC,iBAAiB;QACrC,MAAM,KAAK,CAAC,cAAc,CAAC;QAE3B,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACrC,CAAC;CACF","sourcesContent":["import { LitVirtualizer } from '@lit-labs/virtualizer/LitVirtualizer.js';\nimport { registerComponent } from '../internal/register.js';\nimport { GRID_BODY } from '../internal/tags.js';\n\nexport default class ApexVirtualizer extends LitVirtualizer {\n public static get tagName() {\n return GRID_BODY;\n }\n\n public static register(): void {\n registerComponent(ApexVirtualizer);\n }\n\n // The virtualizer used to own vertical scrolling, which made it a scroll container\n // and broke `position: sticky` for body cells in pinned columns (cells would anchor\n // to the virtualizer instead of the horizontally-scrolling grid host). With\n // `scroller = false` the grid host owns both axes, so headers and pinned body cells\n // share a single sticky containing block.\n public override scroller = false;\n\n public override async connectedCallback() {\n await super.layoutComplete;\n\n super.connectedCallback();\n this.setAttribute('tabindex', '0');\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ApexVirtualizer.tagName]: ApexVirtualizer;\n }\n}\n"]}
1
+ {"version":3,"file":"virtualizer.js","sourceRoot":"","sources":["../../src/components/virtualizer.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitVirtualizer } from '@lit-labs/virtualizer/LitVirtualizer.js';\nimport type { PropertyValues } from 'lit';\nimport { registerComponent } from '../internal/register.js';\nimport { GRID_BODY } from '../internal/tags.js';\n\n/**\n * Attribute the upstream virtualizer stamps on the spacer element it appends in\n * scroller mode. It is not a rendered row, so it is skipped when asking whether\n * the body rendered anything.\n */\nconst SIZER_ATTRIBUTE = 'virtualizer-sizer';\n\n/**\n * Re-measure attempts allowed per geometry change. A grid that still renders\n * nothing after this many tries has a cause we cannot fix by re-measuring, so\n * we stop rather than spin.\n */\nconst MAX_RECOVERY_ATTEMPTS = 3;\n\nexport default class ApexVirtualizer extends LitVirtualizer {\n /**\n * Watches the host's intersection with the window, which is the one input to\n * the upstream viewport measurement that has no invalidation signal of its\n * own. See the note on `#observeViewport`.\n */\n #viewportObserver: IntersectionObserver | null = null;\n\n /**\n * Height of the host's last observed intersection with the window: the\n * viewport height the layout should be working from. Zero means an empty\n * range is the *correct* render and there is nothing to recover.\n */\n #visibleHeight = 0;\n\n #pendingCheck = 0;\n\n #recoveryAttempts = 0;\n\n public static get tagName() {\n return GRID_BODY;\n }\n\n public static register(): void {\n registerComponent(ApexVirtualizer);\n }\n\n // The virtualizer used to own vertical scrolling, which made it a scroll container\n // and broke `position: sticky` for body cells in pinned columns (cells would anchor\n // to the virtualizer instead of the horizontally-scrolling grid host). With\n // `scroller = false` the grid host owns both axes, so headers and pinned body cells\n // share a single sticky containing block.\n public override scroller = false;\n\n public override connectedCallback() {\n // Nothing may be awaited before this call. The upstream virtualizer is only\n // created (and reconnected) from the element's own Lit update cycle, which\n // `super.connectedCallback()` is what starts. Deferring it past an await on\n // any virtualizer state deadlocks on a reconnect: the promise waits for a\n // layout that waits for the update that this call would have scheduled.\n super.connectedCallback();\n this.setAttribute('tabindex', '0');\n this.#observeViewport();\n }\n\n public override disconnectedCallback() {\n this.#viewportObserver?.disconnect();\n this.#viewportObserver = null;\n // Geometry is meaningless while detached; the observer re-reports on connect.\n this.#visibleHeight = 0;\n if (this.#pendingCheck) {\n cancelAnimationFrame(this.#pendingCheck);\n this.#pendingCheck = 0;\n }\n super.disconnectedCallback();\n }\n\n protected override updated(changed: PropertyValues) {\n super.updated(changed);\n this.#scheduleViewportCheck();\n }\n\n /**\n * The upstream virtualizer derives its viewport from the intersection of the\n * host, its clipping ancestors and the window, and clears the rendered range\n * outright when that intersection is zero-height, while still sizing the\n * scroll extent from the full item count. A grid that is laid out while it\n * sits outside the window (an iframe not yet sized by its host page, a panel\n * still settling, content above it that has not finished loading) therefore\n * ends up reporting a correct row count and scroll extent with no rows in it.\n *\n * That state is not self-correcting, because the only invalidation signals\n * upstream listens for are `ResizeObserver` size changes and scroll events:\n * an element that *moves* into view, or a window that resizes around a\n * fixed-size host, fires neither. The grid then stays empty until something\n * unrelated forces a re-render, which is why the failure reads as a race and\n * heals on the first interaction.\n *\n * `IntersectionObserver` fires on exactly the missing signal, so it is what\n * arms the recovery check.\n *\n * @see https://github.com/apexcharts/apex-grid/issues/31\n */\n #observeViewport(): void {\n if (this.#viewportObserver || typeof IntersectionObserver === 'undefined') return;\n this.#viewportObserver = new IntersectionObserver((entries) => {\n this.#visibleHeight = entries.at(-1)?.intersectionRect.height ?? 0;\n // Fresh geometry, so the attempt budget starts over.\n this.#recoveryAttempts = 0;\n this.#scheduleViewportCheck();\n });\n this.#viewportObserver.observe(this);\n }\n\n #scheduleViewportCheck(): void {\n // Healthy path: one element lookup and out, no frame scheduled.\n if (this.#pendingCheck || !this.isConnected) return;\n if (!this.items?.length || this.#hasRenderedRows()) return;\n // Two frames, matching what the virtualizer itself waits before calling a\n // layout settled. Checking sooner would flag a first paint still in flight.\n this.#pendingCheck = requestAnimationFrame(() => {\n this.#pendingCheck = requestAnimationFrame(() => {\n this.#pendingCheck = 0;\n this.#recoverIfStale();\n });\n });\n }\n\n #recoverIfStale(): void {\n if (!this.isConnected) return;\n\n const items = this.items;\n if (!Array.isArray(items) || items.length === 0) return;\n\n if (this.#hasRenderedRows()) {\n this.#recoveryAttempts = 0;\n return;\n }\n\n // No visible slice means rendering nothing is correct: the grid is scrolled\n // out of view, inside a collapsed panel, or hidden. Leave it alone.\n if (this.#visibleHeight <= 0) return;\n if (this.#recoveryAttempts >= MAX_RECOVERY_ATTEMPTS) return;\n\n this.#recoveryAttempts++;\n // Re-assigning `items` with a new array identity is the public lever that\n // makes the virtualizer re-run its layout, and so re-measure the viewport.\n // Unlike a synthetic scroll event it cannot disturb a pending\n // `scrollIntoView`, which the layout holds as a pin until a real scroll.\n this.items = items.slice();\n }\n\n #hasRenderedRows(): boolean {\n for (let child = this.firstElementChild; child; child = child.nextElementSibling) {\n if (!child.hasAttribute(SIZER_ATTRIBUTE)) return true;\n }\n return false;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ApexVirtualizer.tagName]: ApexVirtualizer;\n }\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import type { ReactiveController } from 'lit';
2
2
  import type { ActiveNode, ColumnConfiguration, GridHost, Keys } from '../internal/types.js';
3
3
  export declare class NavigationController<T extends object> implements ReactiveController {
4
+ #private;
4
5
  protected host: GridHost<T>;
5
6
  protected handlers: Map<string, (() => void) | (() => void) | (() => void) | (() => void) | (() => void) | (() => void) | (() => void) | (() => void) | (() => void)>;
6
7
  protected get virtualizer(): import("../components/virtualizer.js").default;
@@ -1,6 +1,6 @@
1
1
  import { NAVIGATION_STATE, SENTINEL_NODE } from '../internal/constants.js';
2
2
  import { GRID_ROW_TAG } from '../internal/tags.js';
3
- import { getDisplayColumns } from '../internal/utils.js';
3
+ import { getDisplayColumns, isRTL } from '../internal/utils.js';
4
4
  export class NavigationController {
5
5
  get virtualizer() {
6
6
  return this.host.scrollContainer;
@@ -138,13 +138,18 @@ export class NavigationController {
138
138
  this.virtualizer.element(next.row)?.scrollIntoView({ block: 'nearest' });
139
139
  }
140
140
  arrowLeft() {
141
- const next = this.nextNode;
142
- this.active = Object.assign(next, { column: this.getPreviousColumn(next.column) });
143
- this.scrollToCell(this.active);
141
+ this.#moveInline('left');
144
142
  }
145
143
  arrowRight() {
144
+ this.#moveInline('right');
145
+ }
146
+ #moveInline(direction) {
147
+ const towardsEnd = isRTL(this.host) === (direction === 'left');
146
148
  const next = this.nextNode;
147
- this.active = Object.assign(next, { column: this.getNextColumn(next.column) });
149
+ const column = towardsEnd
150
+ ? this.getNextColumn(next.column)
151
+ : this.getPreviousColumn(next.column);
152
+ this.active = Object.assign(next, { column });
148
153
  this.scrollToCell(this.active);
149
154
  }
150
155
  toggleSelection() {
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/controllers/navigation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport type ApexGridRow from '../components/row.js';\nimport { NAVIGATION_STATE, SENTINEL_NODE } from '../internal/constants.js';\nimport { GRID_ROW_TAG } from '../internal/tags.js';\nimport type { ActiveNode, ColumnConfiguration, GridHost, Keys } from '../internal/types.js';\nimport { getDisplayColumns } from '../internal/utils.js';\n\nexport class NavigationController<T extends object> implements ReactiveController {\n protected handlers = new Map(\n Object.entries({\n ArrowDown: this.arrowDown,\n ArrowUp: this.arrowUp,\n ArrowLeft: this.arrowLeft,\n ArrowRight: this.arrowRight,\n Home: this.home,\n End: this.end,\n PageUp: this.pageUp,\n PageDown: this.pageDown,\n ' ': this.toggleSelection,\n })\n );\n\n protected get virtualizer() {\n // @ts-expect-error - Protected member access\n return this.host.scrollContainer;\n }\n\n protected state = NAVIGATION_STATE;\n protected _active = SENTINEL_NODE;\n\n protected get nextNode() {\n const node = this.state.get('current')!;\n return node === SENTINEL_NODE\n ? { column: this.firstColumn, row: 0 }\n : ({ ...node } as ActiveNode<T>);\n }\n\n protected get columns(): Array<{ key: Keys<T>; hidden?: boolean }> {\n return getDisplayColumns(this.host.columns) as unknown as Array<{\n key: Keys<T>;\n hidden?: boolean;\n }>;\n }\n\n protected get visibleColumns() {\n return this.columns.filter((column) => !column.hidden);\n }\n\n protected get firstColumn(): Keys<T> {\n const first = this.visibleColumns.at(0);\n return (first?.key ?? (this.host.columns[0]?.key as Keys<T>)) as Keys<T>;\n }\n\n protected getPreviousColumn(key: Keys<T>): Keys<T> {\n const columns = this.visibleColumns;\n const idx = columns.findIndex((column) => column.key === key);\n return columns[Math.max(idx - 1, 0)].key;\n }\n\n protected getNextColumn(key: Keys<T>): Keys<T> {\n const columns = this.visibleColumns;\n const idx = columns.findIndex((column) => column.key === key);\n return columns[Math.min(idx + 1, columns.length - 1)].key;\n }\n\n protected scrollToCell(node: ActiveNode<T>) {\n const row = Array.from(this.virtualizer.querySelectorAll(GRID_ROW_TAG)).find(\n (row) => (row as unknown as ApexGridRow<T>).index === node.row\n ) as unknown as ApexGridRow<T>;\n\n if (row) {\n row.cells\n .find((cell) => cell.column.key === node.column)\n ?.scrollIntoView({ block: 'nearest' });\n }\n }\n\n protected findActiveCell() {\n const row = Array.from(this.virtualizer.querySelectorAll(GRID_ROW_TAG)).find(\n (el) => (el as unknown as ApexGridRow<T>).index === this.active.row\n ) as unknown as ApexGridRow<T> | undefined;\n return row?.cells.find((cell) => cell.column.key === this.active.column);\n }\n\n /**\n * Moves real DOM focus to the active cell (the grid body's roving tab stop),\n * so screen readers track keyboard navigation. Waits for the host render to\n * commit the cell's `active` state, then retries once on the next frame to\n * cover virtualizer re-materialization after a long jump. No-op while no\n * cell is active (the scroll container keeps focus as the entry point).\n */\n public focusActiveCell(): void {\n const node = this.state.get('current');\n if (!node || node === SENTINEL_NODE) return;\n void (async () => {\n await this.host.updateComplete;\n let cell = this.findActiveCell();\n if (!cell) {\n await new Promise(requestAnimationFrame);\n cell = this.findActiveCell();\n }\n cell?.focus({ preventScroll: true });\n })();\n }\n\n public get active() {\n return this._active as ActiveNode<T>;\n }\n\n public set active(node: ActiveNode<T>) {\n this._active = node;\n this.state.set('previous', this._active);\n this.state.set('current', node);\n this.host.requestUpdate();\n }\n\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n /** Home moves to the first cell in the row (ARIA grid pattern). */\n protected home() {\n this.active = Object.assign(this.nextNode, { column: this.firstColumn });\n this.scrollToCell(this.active);\n }\n\n /** End moves to the last cell in the row (ARIA grid pattern). */\n protected end() {\n const last = this.visibleColumns.at(-1)?.key ?? this.firstColumn;\n this.active = Object.assign(this.nextNode, { column: last });\n this.scrollToCell(this.active);\n }\n\n /** Ctrl/Cmd+Home moves to the first cell of the grid. */\n protected ctrlHome() {\n this.active = { column: this.firstColumn, row: 0 } as ActiveNode<T>;\n this.virtualizer.element(0)?.scrollIntoView({ block: 'nearest' });\n this.scrollToCell(this.active);\n }\n\n /** Ctrl/Cmd+End moves to the last cell of the grid. */\n protected ctrlEnd() {\n const row = Math.max(0, this.host.pageItems.length - 1);\n const last = this.visibleColumns.at(-1)?.key ?? this.firstColumn;\n this.active = { column: last, row } as ActiveNode<T>;\n this.virtualizer.element(row)?.scrollIntoView({ block: 'nearest' });\n this.scrollToCell(this.active);\n }\n\n /**\n * Rows per Page Up/Down step, derived from the host viewport and the height\n * of a rendered row (fallback: 10 rows when nothing is measurable yet).\n */\n protected pageStep(): number {\n const rowEl = this.virtualizer.element(this.nextNode.row) as HTMLElement | undefined;\n const rowHeight = rowEl?.offsetHeight || 0;\n const viewport = (this.host as unknown as HTMLElement).clientHeight || 0;\n if (!rowHeight || !viewport) return 10;\n const rows = Math.floor(viewport / rowHeight) - 1;\n return rows > 0 ? rows : 10;\n }\n\n protected pageUp() {\n const next = this.nextNode;\n this.active = Object.assign(next, { row: Math.max(0, next.row - this.pageStep()) });\n this.virtualizer.element(this.active.row)?.scrollIntoView({ block: 'nearest' });\n }\n\n protected pageDown() {\n const next = this.nextNode;\n this.active = Object.assign(next, {\n row: Math.min(this.host.pageItems.length - 1, next.row + this.pageStep()),\n });\n this.virtualizer.element(this.active.row)?.scrollIntoView({ block: 'nearest' });\n }\n\n protected arrowDown() {\n const next = this.nextNode;\n\n this.active = Object.assign(next, {\n row: Math.min(next.row + 1, this.host.pageItems.length - 1),\n });\n this.virtualizer.element(next.row)?.scrollIntoView({ block: 'nearest' });\n }\n\n protected arrowUp() {\n const next = this.nextNode;\n this.active = Object.assign(next, { row: Math.max(0, next.row - 1) });\n this.virtualizer.element(next.row)?.scrollIntoView({ block: 'nearest' });\n }\n\n protected arrowLeft() {\n const next = this.nextNode;\n this.active = Object.assign(next, { column: this.getPreviousColumn(next.column) });\n this.scrollToCell(this.active);\n }\n\n protected arrowRight() {\n const next = this.nextNode;\n this.active = Object.assign(next, { column: this.getNextColumn(next.column) });\n this.scrollToCell(this.active);\n }\n\n protected toggleSelection() {\n // Space on the focused grid toggles selection of the active row.\n // No-op when selection is disabled or there's no active row.\n const data = this.host.pageItems[this.active.row] as T | undefined;\n if (!data) return;\n void this.host.toggleRowSelection(data);\n }\n\n public hostConnected() {}\n\n public hostDisconnected() {\n this.active = SENTINEL_NODE as ActiveNode<T>;\n this.state = NAVIGATION_STATE;\n }\n\n protected get editing() {\n // @ts-expect-error - protected member access\n return this.host.stateController.editing as\n | {\n enabled: boolean;\n isEditable(column: ColumnConfiguration<T>): boolean;\n editCell(rowIndex: number, columnKey: Keys<T>): Promise<boolean>;\n }\n | undefined;\n }\n\n /**\n * Enter / F2 on the active cell opens its editor (the keyboard path into\n * edit mode). Returns `true` when the event was consumed.\n */\n protected handleEditKey(event: KeyboardEvent): boolean {\n if (event.key !== 'Enter' && event.key !== 'F2') return false;\n if (event.ctrlKey || event.metaKey || event.altKey) return false;\n const node = this.state.get('current');\n if (!node || node === SENTINEL_NODE) return false;\n const editing = this.editing;\n if (!editing?.enabled) return false;\n const column = this.host.getColumn(this.active.column);\n if (!column || !editing.isEditable(column)) return false;\n event.preventDefault();\n void editing.editCell(this.active.row, this.active.column);\n return true;\n }\n\n protected get rowReorder() {\n // @ts-expect-error - protected member access\n return this.host.stateController.rowReorder as\n | {\n enabled: boolean;\n isGrabbing: boolean;\n grab(rowIndex: number): boolean;\n moveGrabbed(direction: -1 | 1): number;\n drop(): void;\n cancelGrab(): void;\n }\n | undefined;\n }\n\n /**\n * Keyboard row reorder: Space grabs the active row, arrows move it, Space /\n * Enter drops, Escape cancels. Returns `true` when the event was consumed.\n * Only active when `rowReordering.enabled` (so it never shadows Space-to-select\n * on grids without reordering).\n */\n protected handleReorderKey(event: KeyboardEvent): boolean {\n const reorder = this.rowReorder;\n if (!reorder?.enabled) return false;\n\n if (reorder.isGrabbing) {\n switch (event.key) {\n case 'ArrowUp':\n case 'ArrowDown': {\n event.preventDefault();\n const next = reorder.moveGrabbed(event.key === 'ArrowDown' ? 1 : -1);\n if (next >= 0) {\n this.active = Object.assign(this.nextNode, { row: next });\n this.virtualizer.element(next)?.scrollIntoView({ block: 'nearest' });\n }\n return true;\n }\n case ' ':\n case 'Enter':\n event.preventDefault();\n reorder.drop();\n return true;\n case 'Escape':\n event.preventDefault();\n reorder.cancelGrab();\n return true;\n default:\n return false;\n }\n }\n\n if (event.key === ' ' && this.active.row >= 0) {\n event.preventDefault();\n return reorder.grab(this.active.row);\n }\n return false;\n }\n\n public navigate(event: KeyboardEvent) {\n if (this.handleReorderKey(event)) return;\n // Undo / redo: Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z, Ctrl/Cmd+Y. Only fires when the\n // grid body (not an open editor) has focus, so a text editor's native undo\n // is never hijacked.\n if ((event.ctrlKey || event.metaKey) && !event.altKey) {\n const key = event.key.toLowerCase();\n if (key === 'z' && !event.shiftKey) {\n event.preventDefault();\n this.host.undo();\n return;\n }\n if ((key === 'z' && event.shiftKey) || key === 'y') {\n event.preventDefault();\n this.host.redo();\n return;\n }\n // Ctrl/Cmd+Home / Ctrl/Cmd+End jump to the grid corners (ARIA grid pattern).\n if (event.key === 'Home' || event.key === 'End') {\n event.preventDefault();\n if (event.key === 'Home') {\n this.ctrlHome();\n } else {\n this.ctrlEnd();\n }\n this.focusActiveCell();\n return;\n }\n }\n if (this.handleEditKey(event)) return;\n if (this.handlers.has(event.key)) {\n event.preventDefault();\n this.handlers.get(event.key)!.call(this);\n // Real focus follows the active cell so AT tracks the movement.\n this.focusActiveCell();\n }\n }\n}\n"]}
1
+ {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/controllers/navigation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport type ApexGridRow from '../components/row.js';\nimport { NAVIGATION_STATE, SENTINEL_NODE } from '../internal/constants.js';\nimport { GRID_ROW_TAG } from '../internal/tags.js';\nimport type { ActiveNode, ColumnConfiguration, GridHost, Keys } from '../internal/types.js';\nimport { getDisplayColumns, isRTL } from '../internal/utils.js';\n\nexport class NavigationController<T extends object> implements ReactiveController {\n protected handlers = new Map(\n Object.entries({\n ArrowDown: this.arrowDown,\n ArrowUp: this.arrowUp,\n ArrowLeft: this.arrowLeft,\n ArrowRight: this.arrowRight,\n Home: this.home,\n End: this.end,\n PageUp: this.pageUp,\n PageDown: this.pageDown,\n ' ': this.toggleSelection,\n })\n );\n\n protected get virtualizer() {\n // @ts-expect-error - Protected member access\n return this.host.scrollContainer;\n }\n\n protected state = NAVIGATION_STATE;\n protected _active = SENTINEL_NODE;\n\n protected get nextNode() {\n const node = this.state.get('current')!;\n return node === SENTINEL_NODE\n ? { column: this.firstColumn, row: 0 }\n : ({ ...node } as ActiveNode<T>);\n }\n\n protected get columns(): Array<{ key: Keys<T>; hidden?: boolean }> {\n return getDisplayColumns(this.host.columns) as unknown as Array<{\n key: Keys<T>;\n hidden?: boolean;\n }>;\n }\n\n protected get visibleColumns() {\n return this.columns.filter((column) => !column.hidden);\n }\n\n protected get firstColumn(): Keys<T> {\n const first = this.visibleColumns.at(0);\n return (first?.key ?? (this.host.columns[0]?.key as Keys<T>)) as Keys<T>;\n }\n\n protected getPreviousColumn(key: Keys<T>): Keys<T> {\n const columns = this.visibleColumns;\n const idx = columns.findIndex((column) => column.key === key);\n return columns[Math.max(idx - 1, 0)].key;\n }\n\n protected getNextColumn(key: Keys<T>): Keys<T> {\n const columns = this.visibleColumns;\n const idx = columns.findIndex((column) => column.key === key);\n return columns[Math.min(idx + 1, columns.length - 1)].key;\n }\n\n protected scrollToCell(node: ActiveNode<T>) {\n const row = Array.from(this.virtualizer.querySelectorAll(GRID_ROW_TAG)).find(\n (row) => (row as unknown as ApexGridRow<T>).index === node.row\n ) as unknown as ApexGridRow<T>;\n\n if (row) {\n row.cells\n .find((cell) => cell.column.key === node.column)\n ?.scrollIntoView({ block: 'nearest' });\n }\n }\n\n protected findActiveCell() {\n const row = Array.from(this.virtualizer.querySelectorAll(GRID_ROW_TAG)).find(\n (el) => (el as unknown as ApexGridRow<T>).index === this.active.row\n ) as unknown as ApexGridRow<T> | undefined;\n return row?.cells.find((cell) => cell.column.key === this.active.column);\n }\n\n /**\n * Moves real DOM focus to the active cell (the grid body's roving tab stop),\n * so screen readers track keyboard navigation. Waits for the host render to\n * commit the cell's `active` state, then retries once on the next frame to\n * cover virtualizer re-materialization after a long jump. No-op while no\n * cell is active (the scroll container keeps focus as the entry point).\n */\n public focusActiveCell(): void {\n const node = this.state.get('current');\n if (!node || node === SENTINEL_NODE) return;\n void (async () => {\n await this.host.updateComplete;\n let cell = this.findActiveCell();\n if (!cell) {\n await new Promise(requestAnimationFrame);\n cell = this.findActiveCell();\n }\n cell?.focus({ preventScroll: true });\n })();\n }\n\n public get active() {\n return this._active as ActiveNode<T>;\n }\n\n public set active(node: ActiveNode<T>) {\n this._active = node;\n this.state.set('previous', this._active);\n this.state.set('current', node);\n this.host.requestUpdate();\n }\n\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n /** Home moves to the first cell in the row (ARIA grid pattern). */\n protected home() {\n this.active = Object.assign(this.nextNode, { column: this.firstColumn });\n this.scrollToCell(this.active);\n }\n\n /** End moves to the last cell in the row (ARIA grid pattern). */\n protected end() {\n const last = this.visibleColumns.at(-1)?.key ?? this.firstColumn;\n this.active = Object.assign(this.nextNode, { column: last });\n this.scrollToCell(this.active);\n }\n\n /** Ctrl/Cmd+Home moves to the first cell of the grid. */\n protected ctrlHome() {\n this.active = { column: this.firstColumn, row: 0 } as ActiveNode<T>;\n this.virtualizer.element(0)?.scrollIntoView({ block: 'nearest' });\n this.scrollToCell(this.active);\n }\n\n /** Ctrl/Cmd+End moves to the last cell of the grid. */\n protected ctrlEnd() {\n const row = Math.max(0, this.host.pageItems.length - 1);\n const last = this.visibleColumns.at(-1)?.key ?? this.firstColumn;\n this.active = { column: last, row } as ActiveNode<T>;\n this.virtualizer.element(row)?.scrollIntoView({ block: 'nearest' });\n this.scrollToCell(this.active);\n }\n\n /**\n * Rows per Page Up/Down step, derived from the host viewport and the height\n * of a rendered row (fallback: 10 rows when nothing is measurable yet).\n */\n protected pageStep(): number {\n const rowEl = this.virtualizer.element(this.nextNode.row) as HTMLElement | undefined;\n const rowHeight = rowEl?.offsetHeight || 0;\n const viewport = (this.host as unknown as HTMLElement).clientHeight || 0;\n if (!rowHeight || !viewport) return 10;\n const rows = Math.floor(viewport / rowHeight) - 1;\n return rows > 0 ? rows : 10;\n }\n\n protected pageUp() {\n const next = this.nextNode;\n this.active = Object.assign(next, { row: Math.max(0, next.row - this.pageStep()) });\n this.virtualizer.element(this.active.row)?.scrollIntoView({ block: 'nearest' });\n }\n\n protected pageDown() {\n const next = this.nextNode;\n this.active = Object.assign(next, {\n row: Math.min(this.host.pageItems.length - 1, next.row + this.pageStep()),\n });\n this.virtualizer.element(this.active.row)?.scrollIntoView({ block: 'nearest' });\n }\n\n protected arrowDown() {\n const next = this.nextNode;\n\n this.active = Object.assign(next, {\n row: Math.min(next.row + 1, this.host.pageItems.length - 1),\n });\n this.virtualizer.element(next.row)?.scrollIntoView({ block: 'nearest' });\n }\n\n protected arrowUp() {\n const next = this.nextNode;\n this.active = Object.assign(next, { row: Math.max(0, next.row - 1) });\n this.virtualizer.element(next.row)?.scrollIntoView({ block: 'nearest' });\n }\n\n protected arrowLeft() {\n this.#moveInline('left');\n }\n\n protected arrowRight() {\n this.#moveInline('right');\n }\n\n /**\n * Moves the active cell one column in a *physical* direction.\n *\n * ArrowLeft and ArrowRight name screen directions, not column order, so under\n * `dir=\"rtl\"` the column to the left is the *next* one and the mapping onto\n * previous/next inverts. Everything else about navigation is order-based and\n * needs no direction awareness.\n */\n #moveInline(direction: 'left' | 'right') {\n const towardsEnd = isRTL(this.host as unknown as Element) === (direction === 'left');\n const next = this.nextNode;\n const column = towardsEnd\n ? this.getNextColumn(next.column)\n : this.getPreviousColumn(next.column);\n this.active = Object.assign(next, { column });\n this.scrollToCell(this.active);\n }\n\n protected toggleSelection() {\n // Space on the focused grid toggles selection of the active row.\n // No-op when selection is disabled or there's no active row.\n const data = this.host.pageItems[this.active.row] as T | undefined;\n if (!data) return;\n void this.host.toggleRowSelection(data);\n }\n\n public hostConnected() {}\n\n public hostDisconnected() {\n this.active = SENTINEL_NODE as ActiveNode<T>;\n this.state = NAVIGATION_STATE;\n }\n\n protected get editing() {\n // @ts-expect-error - protected member access\n return this.host.stateController.editing as\n | {\n enabled: boolean;\n isEditable(column: ColumnConfiguration<T>): boolean;\n editCell(rowIndex: number, columnKey: Keys<T>): Promise<boolean>;\n }\n | undefined;\n }\n\n /**\n * Enter / F2 on the active cell opens its editor (the keyboard path into\n * edit mode). Returns `true` when the event was consumed.\n */\n protected handleEditKey(event: KeyboardEvent): boolean {\n if (event.key !== 'Enter' && event.key !== 'F2') return false;\n if (event.ctrlKey || event.metaKey || event.altKey) return false;\n const node = this.state.get('current');\n if (!node || node === SENTINEL_NODE) return false;\n const editing = this.editing;\n if (!editing?.enabled) return false;\n const column = this.host.getColumn(this.active.column);\n if (!column || !editing.isEditable(column)) return false;\n event.preventDefault();\n void editing.editCell(this.active.row, this.active.column);\n return true;\n }\n\n protected get rowReorder() {\n // @ts-expect-error - protected member access\n return this.host.stateController.rowReorder as\n | {\n enabled: boolean;\n isGrabbing: boolean;\n grab(rowIndex: number): boolean;\n moveGrabbed(direction: -1 | 1): number;\n drop(): void;\n cancelGrab(): void;\n }\n | undefined;\n }\n\n /**\n * Keyboard row reorder: Space grabs the active row, arrows move it, Space /\n * Enter drops, Escape cancels. Returns `true` when the event was consumed.\n * Only active when `rowReordering.enabled` (so it never shadows Space-to-select\n * on grids without reordering).\n */\n protected handleReorderKey(event: KeyboardEvent): boolean {\n const reorder = this.rowReorder;\n if (!reorder?.enabled) return false;\n\n if (reorder.isGrabbing) {\n switch (event.key) {\n case 'ArrowUp':\n case 'ArrowDown': {\n event.preventDefault();\n const next = reorder.moveGrabbed(event.key === 'ArrowDown' ? 1 : -1);\n if (next >= 0) {\n this.active = Object.assign(this.nextNode, { row: next });\n this.virtualizer.element(next)?.scrollIntoView({ block: 'nearest' });\n }\n return true;\n }\n case ' ':\n case 'Enter':\n event.preventDefault();\n reorder.drop();\n return true;\n case 'Escape':\n event.preventDefault();\n reorder.cancelGrab();\n return true;\n default:\n return false;\n }\n }\n\n if (event.key === ' ' && this.active.row >= 0) {\n event.preventDefault();\n return reorder.grab(this.active.row);\n }\n return false;\n }\n\n public navigate(event: KeyboardEvent) {\n if (this.handleReorderKey(event)) return;\n // Undo / redo: Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z, Ctrl/Cmd+Y. Only fires when the\n // grid body (not an open editor) has focus, so a text editor's native undo\n // is never hijacked.\n if ((event.ctrlKey || event.metaKey) && !event.altKey) {\n const key = event.key.toLowerCase();\n if (key === 'z' && !event.shiftKey) {\n event.preventDefault();\n this.host.undo();\n return;\n }\n if ((key === 'z' && event.shiftKey) || key === 'y') {\n event.preventDefault();\n this.host.redo();\n return;\n }\n // Ctrl/Cmd+Home / Ctrl/Cmd+End jump to the grid corners (ARIA grid pattern).\n if (event.key === 'Home' || event.key === 'End') {\n event.preventDefault();\n if (event.key === 'Home') {\n this.ctrlHome();\n } else {\n this.ctrlEnd();\n }\n this.focusActiveCell();\n return;\n }\n }\n if (this.handleEditKey(event)) return;\n if (this.handlers.has(event.key)) {\n event.preventDefault();\n this.handlers.get(event.key)!.call(this);\n // Real focus follows the active cell so AT tracks the movement.\n this.focusActiveCell();\n }\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { awaitChildUpdates, captureRect, playFlip } from '../internal/flip.js';
2
+ import { isRTL } from '../internal/utils.js';
2
3
  export class ReorderController {
3
4
  #swapping;
4
5
  constructor(host) {
@@ -81,14 +82,15 @@ export class ReorderController {
81
82
  const targetIdx = visibleColumns.findIndex((c) => c.key === target.column.key);
82
83
  if (sourceIdx === -1 || targetIdx === -1)
83
84
  return;
85
+ const rtl = isRTL(this.host);
84
86
  let position;
85
87
  if (sourceIdx < targetIdx) {
86
- if (clientX < midpoint)
88
+ if (rtl ? clientX > midpoint : clientX < midpoint)
87
89
  return;
88
90
  position = 'after';
89
91
  }
90
92
  else {
91
- if (clientX > midpoint)
93
+ if (rtl ? clientX < midpoint : clientX > midpoint)
92
94
  return;
93
95
  position = 'before';
94
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"reorder.js","sourceRoot":"","sources":["../../src/controllers/reorder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport { awaitChildUpdates, captureRect, type FlipEntry, playFlip } from '../internal/flip.js';\nimport type { ColumnConfiguration, GridHost, Keys } from '../internal/types.js';\n\n/**\n * Live drag state surfaced to the header row so it can render the floating\n * \"ghost\" element that follows the cursor.\n *\n * @remarks\n * The dragged column itself stays in the columns array — we live-swap it\n * with neighbours as the cursor crosses their midpoints, so the rendered\n * order updates while the user is still dragging. The ghost is purely a\n * visual indicator of what the user is grabbing.\n */\ninterface ReorderState<T> {\n /** The column currently being dragged. */\n sourceKey: Keys<T>;\n /** Ghost position (viewport-relative top-left, in CSS pixels). */\n ghostX: number;\n ghostY: number;\n /** Ghost size — fixed at the source header's initial bounding rect. */\n ghostWidth: number;\n ghostHeight: number;\n /** Cursor offset within the ghost so the grab point stays under the cursor. */\n pointerOffsetX: number;\n pointerOffsetY: number;\n /** Display label for the ghost (header text or column key). */\n label: string;\n}\n\n/**\n * Reactive controller backing pointer-driven column reordering with a\n * floating ghost and live mid-drag swaps.\n *\n * @remarks\n * Headers feed `pointerdown` / `pointermove` / `pointerup` events into the\n * controller. While dragging, the controller updates the ghost position and\n * decides whether the cursor has crossed an adjacent column's midpoint —\n * if so it calls {@link ApexGrid.moveColumn} immediately, so the swap\n * happens during the drag instead of waiting for drop. The same cancellable\n * `columnMoving` / follow-up `columnMoved` event pipeline applies for\n * every swap.\n */\nexport class ReorderController<T extends object> implements ReactiveController {\n public state: ReorderState<T> | null = null;\n\n /** Re-entrancy guard so a slow `moveColumn` can't trigger a second swap. */\n #swapping = false;\n\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n public hostConnected() {}\n\n protected get headerRow() {\n // @ts-expect-error - protected member access\n return this.host.headerRow as\n | (HTMLElement & { headers?: Array<HTMLElement & { column: ColumnConfiguration<T> }> })\n | undefined;\n }\n\n /**\n * Whether reordering is enabled for the given column.\n */\n public isDraggable(column: ColumnConfiguration<T>): boolean {\n if (!this.host.columnReordering) return false;\n if (column.hidden) return false;\n return column.reorderable !== false;\n }\n\n /**\n * Whether `source` may be dropped onto `target`. Cross-pinning-group moves\n * are blocked so the drag can't escape its pin region.\n */\n public canDrop(source: ColumnConfiguration<T>, target: ColumnConfiguration<T>): boolean {\n if (source.key === target.key) return false;\n if (!this.isDraggable(source) || !this.isDraggable(target)) return false;\n if ((source.pinned ?? null) !== (target.pinned ?? null)) return false;\n // Grouped columns reorder only within their own group; ungrouped only among\n // ungrouped. Keeps a group's members contiguous (v1 has no group-level move).\n return (source.group ?? null) === (target.group ?? null);\n }\n\n /**\n * Begins a drag from `sourceKey`. Captures the source's bounding rect and\n * the cursor offset within it so the ghost stays anchored to the grab\n * point as the cursor moves.\n */\n public start(\n sourceKey: Keys<T>,\n sourceRect: DOMRect,\n initialClientX: number,\n initialClientY: number,\n label: string\n ): void {\n this.state = {\n sourceKey,\n ghostX: sourceRect.left,\n ghostY: sourceRect.top,\n ghostWidth: sourceRect.width,\n ghostHeight: sourceRect.height,\n pointerOffsetX: initialClientX - sourceRect.left,\n pointerOffsetY: initialClientY - sourceRect.top,\n label,\n };\n this.host.requestUpdate();\n }\n\n /**\n * Updates the ghost position and decides whether to swap with an adjacent\n * column.\n */\n public move(clientX: number, clientY: number): void {\n if (!this.state) return;\n this.state = {\n ...this.state,\n ghostX: clientX - this.state.pointerOffsetX,\n ghostY: clientY - this.state.pointerOffsetY,\n };\n this.host.requestUpdate();\n void this.#checkSwap(clientX);\n }\n\n /**\n * Ends the drag session. The columns are already in their final order\n * because we live-swapped during the drag, so there's nothing to commit.\n */\n public end(): void {\n if (!this.state) return;\n this.state = null;\n this.host.requestUpdate();\n }\n\n async #checkSwap(clientX: number): Promise<void> {\n if (!this.state || this.#swapping) return;\n const source = this.host.getColumn(this.state.sourceKey);\n if (!source) return;\n const headerRow = this.headerRow;\n if (!headerRow?.headers) return;\n\n // Find the visible header whose box currently contains the cursor X.\n const target = headerRow.headers.find((h) => {\n const rect = h.getBoundingClientRect();\n return clientX >= rect.left && clientX < rect.right;\n });\n if (!target || target.column.key === source.key) return;\n if (!this.canDrop(source, target.column)) return;\n\n // Only swap once the cursor crosses the target's midpoint, so we don't\n // bounce back and forth as soon as the ghost touches the edge.\n const rect = target.getBoundingClientRect();\n const midpoint = rect.left + rect.width / 2;\n const visibleColumns = this.host.columns.filter((c) => !c.hidden);\n const sourceIdx = visibleColumns.findIndex((c) => c.key === source.key);\n const targetIdx = visibleColumns.findIndex((c) => c.key === target.column.key);\n if (sourceIdx === -1 || targetIdx === -1) return;\n\n let position: 'before' | 'after';\n if (sourceIdx < targetIdx) {\n // Dragging right — swap when the cursor crosses past the target's centre.\n if (clientX < midpoint) return;\n position = 'after';\n } else {\n // Dragging left — swap when the cursor crosses before the target's centre.\n if (clientX > midpoint) return;\n position = 'before';\n }\n\n this.#swapping = true;\n try {\n const before = this.#captureCellRects();\n await this.host.moveColumn(source.key, target.column.key, position);\n await this.host.updateComplete;\n // Child rows + header row schedule their own updates one microtask\n // after the grid — wait for them so the cells have actually moved\n // before measuring the \"Last\" rect.\n await awaitChildUpdates([\n this.headerRow as unknown as { updateComplete: Promise<unknown> } | undefined,\n ...this.host.rows,\n ]);\n playFlip(before, 'x');\n } finally {\n this.#swapping = false;\n }\n }\n\n /**\n * Snapshots the bounding rect of every header + body cell before a\n * swap. Used as the \"First\" step of a FLIP — after `moveColumn` resolves,\n * `playFlip` computes the delta against the new rect and animates each\n * element from its old position back to identity.\n */\n #captureCellRects(): FlipEntry[] {\n const entries: FlipEntry[] = [];\n const headerRow = this.headerRow;\n if (headerRow?.headers) {\n for (const header of headerRow.headers) {\n entries.push(captureRect(header));\n }\n }\n for (const row of this.host.rows) {\n for (const cell of row.cells) {\n entries.push(captureRect(cell as unknown as HTMLElement));\n }\n }\n return entries;\n }\n}\n"]}
1
+ {"version":3,"file":"reorder.js","sourceRoot":"","sources":["../../src/controllers/reorder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport { awaitChildUpdates, captureRect, type FlipEntry, playFlip } from '../internal/flip.js';\nimport type { ColumnConfiguration, GridHost, Keys } from '../internal/types.js';\nimport { isRTL } from '../internal/utils.js';\n\n/**\n * Live drag state surfaced to the header row so it can render the floating\n * \"ghost\" element that follows the cursor.\n *\n * @remarks\n * The dragged column itself stays in the columns array — we live-swap it\n * with neighbours as the cursor crosses their midpoints, so the rendered\n * order updates while the user is still dragging. The ghost is purely a\n * visual indicator of what the user is grabbing.\n */\ninterface ReorderState<T> {\n /** The column currently being dragged. */\n sourceKey: Keys<T>;\n /** Ghost position (viewport-relative top-left, in CSS pixels). */\n ghostX: number;\n ghostY: number;\n /** Ghost size — fixed at the source header's initial bounding rect. */\n ghostWidth: number;\n ghostHeight: number;\n /** Cursor offset within the ghost so the grab point stays under the cursor. */\n pointerOffsetX: number;\n pointerOffsetY: number;\n /** Display label for the ghost (header text or column key). */\n label: string;\n}\n\n/**\n * Reactive controller backing pointer-driven column reordering with a\n * floating ghost and live mid-drag swaps.\n *\n * @remarks\n * Headers feed `pointerdown` / `pointermove` / `pointerup` events into the\n * controller. While dragging, the controller updates the ghost position and\n * decides whether the cursor has crossed an adjacent column's midpoint —\n * if so it calls {@link ApexGrid.moveColumn} immediately, so the swap\n * happens during the drag instead of waiting for drop. The same cancellable\n * `columnMoving` / follow-up `columnMoved` event pipeline applies for\n * every swap.\n */\nexport class ReorderController<T extends object> implements ReactiveController {\n public state: ReorderState<T> | null = null;\n\n /** Re-entrancy guard so a slow `moveColumn` can't trigger a second swap. */\n #swapping = false;\n\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n public hostConnected() {}\n\n protected get headerRow() {\n // @ts-expect-error - protected member access\n return this.host.headerRow as\n | (HTMLElement & { headers?: Array<HTMLElement & { column: ColumnConfiguration<T> }> })\n | undefined;\n }\n\n /**\n * Whether reordering is enabled for the given column.\n */\n public isDraggable(column: ColumnConfiguration<T>): boolean {\n if (!this.host.columnReordering) return false;\n if (column.hidden) return false;\n return column.reorderable !== false;\n }\n\n /**\n * Whether `source` may be dropped onto `target`. Cross-pinning-group moves\n * are blocked so the drag can't escape its pin region.\n */\n public canDrop(source: ColumnConfiguration<T>, target: ColumnConfiguration<T>): boolean {\n if (source.key === target.key) return false;\n if (!this.isDraggable(source) || !this.isDraggable(target)) return false;\n if ((source.pinned ?? null) !== (target.pinned ?? null)) return false;\n // Grouped columns reorder only within their own group; ungrouped only among\n // ungrouped. Keeps a group's members contiguous (v1 has no group-level move).\n return (source.group ?? null) === (target.group ?? null);\n }\n\n /**\n * Begins a drag from `sourceKey`. Captures the source's bounding rect and\n * the cursor offset within it so the ghost stays anchored to the grab\n * point as the cursor moves.\n */\n public start(\n sourceKey: Keys<T>,\n sourceRect: DOMRect,\n initialClientX: number,\n initialClientY: number,\n label: string\n ): void {\n this.state = {\n sourceKey,\n ghostX: sourceRect.left,\n ghostY: sourceRect.top,\n ghostWidth: sourceRect.width,\n ghostHeight: sourceRect.height,\n pointerOffsetX: initialClientX - sourceRect.left,\n pointerOffsetY: initialClientY - sourceRect.top,\n label,\n };\n this.host.requestUpdate();\n }\n\n /**\n * Updates the ghost position and decides whether to swap with an adjacent\n * column.\n */\n public move(clientX: number, clientY: number): void {\n if (!this.state) return;\n this.state = {\n ...this.state,\n ghostX: clientX - this.state.pointerOffsetX,\n ghostY: clientY - this.state.pointerOffsetY,\n };\n this.host.requestUpdate();\n void this.#checkSwap(clientX);\n }\n\n /**\n * Ends the drag session. The columns are already in their final order\n * because we live-swapped during the drag, so there's nothing to commit.\n */\n public end(): void {\n if (!this.state) return;\n this.state = null;\n this.host.requestUpdate();\n }\n\n async #checkSwap(clientX: number): Promise<void> {\n if (!this.state || this.#swapping) return;\n const source = this.host.getColumn(this.state.sourceKey);\n if (!source) return;\n const headerRow = this.headerRow;\n if (!headerRow?.headers) return;\n\n // Find the visible header whose box currently contains the cursor X.\n const target = headerRow.headers.find((h) => {\n const rect = h.getBoundingClientRect();\n return clientX >= rect.left && clientX < rect.right;\n });\n if (!target || target.column.key === source.key) return;\n if (!this.canDrop(source, target.column)) return;\n\n // Only swap once the cursor crosses the target's midpoint, so we don't\n // bounce back and forth as soon as the ghost touches the edge.\n const rect = target.getBoundingClientRect();\n const midpoint = rect.left + rect.width / 2;\n const visibleColumns = this.host.columns.filter((c) => !c.hidden);\n const sourceIdx = visibleColumns.findIndex((c) => c.key === source.key);\n const targetIdx = visibleColumns.findIndex((c) => c.key === target.column.key);\n if (sourceIdx === -1 || targetIdx === -1) return;\n\n // `position` is order-based, so it needs no direction awareness. The\n // midpoint test does: moving toward a *later* column means moving right in\n // LTR and left under `dir=\"rtl\"`, so the comparison flips.\n const rtl = isRTL(this.host as unknown as Element);\n let position: 'before' | 'after';\n if (sourceIdx < targetIdx) {\n // Toward a later column — swap once the cursor crosses the target's centre.\n if (rtl ? clientX > midpoint : clientX < midpoint) return;\n position = 'after';\n } else {\n // Toward an earlier column — swap once the cursor crosses back over it.\n if (rtl ? clientX < midpoint : clientX > midpoint) return;\n position = 'before';\n }\n\n this.#swapping = true;\n try {\n const before = this.#captureCellRects();\n await this.host.moveColumn(source.key, target.column.key, position);\n await this.host.updateComplete;\n // Child rows + header row schedule their own updates one microtask\n // after the grid — wait for them so the cells have actually moved\n // before measuring the \"Last\" rect.\n await awaitChildUpdates([\n this.headerRow as unknown as { updateComplete: Promise<unknown> } | undefined,\n ...this.host.rows,\n ]);\n playFlip(before, 'x');\n } finally {\n this.#swapping = false;\n }\n }\n\n /**\n * Snapshots the bounding rect of every header + body cell before a\n * swap. Used as the \"First\" step of a FLIP — after `moveColumn` resolves,\n * `playFlip` computes the delta against the new rect and animates each\n * element from its old position back to identity.\n */\n #captureCellRects(): FlipEntry[] {\n const entries: FlipEntry[] = [];\n const headerRow = this.headerRow;\n if (headerRow?.headers) {\n for (const header of headerRow.headers) {\n entries.push(captureRect(header));\n }\n }\n for (const row of this.host.rows) {\n for (const cell of row.cells) {\n entries.push(captureRect(cell as unknown as HTMLElement));\n }\n }\n return entries;\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import type { ReactiveController } from 'lit';
2
2
  import type { GridLocaleKey, LocaleParams } from '../i18n/index.js';
3
- import { type CellDecoration, type CellDecoratorContext, type CellInteraction, type GridFeatureModule, type PresentedRow, type RowPresenterContext } from '../internal/feature-module.js';
3
+ import { type CellDecoration, type CellDecoratorContext, type CellInteraction, type GridFeatureModule, type PresentedRow, type RowAria, type RowPresenterContext } from '../internal/feature-module.js';
4
4
  import type { ActiveNode, GridHost } from '../internal/types.js';
5
5
  import { EditingController } from './editing.js';
6
6
  import { ExpansionController } from './expansion.js';
@@ -61,8 +61,8 @@ export declare class StateController<T extends object> implements ReactiveContro
61
61
  set active(node: ActiveNode<T>);
62
62
  get headerRow(): import("../components/header-row.js").default<T>;
63
63
  get scrollContainer(): import("../components/virtualizer.js").default;
64
- get paginator(): import("../components/paginator.js").default<T>;
65
- get toolbar(): import("../components/toolbar.js").default<T>;
64
+ get paginator(): import("../index.js").ApexGridPaginator<T>;
65
+ get toolbar(): import("../index.js").ApexGridToolbar<T>;
66
66
  /**
67
67
  * Cumulative pin offsets (in px) keyed by column key. Populated by the
68
68
  * {@link GridDOMController} after each layout.
@@ -88,6 +88,12 @@ export declare class StateController<T extends object> implements ReactiveContro
88
88
  * the first non-null result, or `null` when no module owns the row.
89
89
  */
90
90
  presentRow(row: T, ctx: RowPresenterContext<T>): PresentedRow | null;
91
+ /**
92
+ * Asks feature modules implementing {@link RowAriaProvider} for ARIA
93
+ * tree/expansion semantics on a normal (cell-rendered) row — e.g. pivoting's
94
+ * expandable parent rows. Returns the first non-null result, or `null`.
95
+ */
96
+ describeRow(row: T, ctx: RowPresenterContext<T>): RowAria | null;
91
97
  get decorationVersion(): number;
92
98
  /**
93
99
  * Signals that {@link CellDecorator} output may have changed. Bumps the
@@ -1,5 +1,5 @@
1
1
  import { createContext } from '@lit/context';
2
- import { isCellDecorator, isCellInteractionHandler, isColumnMenuProvider, isRowPresenter, isRowTransformer, isSerializableModule, } from '../internal/feature-module.js';
2
+ import { isCellDecorator, isCellInteractionHandler, isColumnMenuProvider, isRowAriaProvider, isRowPresenter, isRowTransformer, isSerializableModule, } from '../internal/feature-module.js';
3
3
  import { EditingController } from './editing.js';
4
4
  import { ExpansionController } from './expansion.js';
5
5
  import { FilterController } from './filter.js';
@@ -102,6 +102,16 @@ export class StateController {
102
102
  }
103
103
  return null;
104
104
  }
105
+ describeRow(row, ctx) {
106
+ for (const controller of this.modules.values()) {
107
+ if (isRowAriaProvider(controller)) {
108
+ const aria = controller.describeRow(row, ctx);
109
+ if (aria)
110
+ return aria;
111
+ }
112
+ }
113
+ return null;
114
+ }
105
115
  #decorationVersion;
106
116
  get decorationVersion() {
107
117
  return this.#decorationVersion;
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/controllers/state.ts"],"names":[],"mappings":"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","sourcesContent":["import { createContext } from '@lit/context';\nimport type { ReactiveController } from 'lit';\nimport type { GridLocaleKey, LocaleParams } from '../i18n/index.js';\nimport {\n type CellDecoration,\n type CellDecoratorContext,\n type CellInteraction,\n type GridFeatureModule,\n isCellDecorator,\n isCellInteractionHandler,\n isColumnMenuProvider,\n isRowPresenter,\n isRowTransformer,\n isSerializableModule,\n type PresentedRow,\n type RowPresenterContext,\n} from '../internal/feature-module.js';\nimport type { ActiveNode, GridHost } from '../internal/types.js';\nimport { EditingController } from './editing.js';\nimport { ExpansionController } from './expansion.js';\nimport { FilterController } from './filter.js';\nimport { HistoryController } from './history.js';\nimport { NavigationController } from './navigation.js';\nimport { PaginationController } from './pagination.js';\nimport { ReorderController } from './reorder.js';\nimport { ResizeController } from './resize.js';\nimport { RowPinController } from './row-pin.js';\nimport { RowReorderController } from './row-reorder.js';\nimport { SelectionController } from './selection.js';\nimport { SortController } from './sort.js';\nimport { TreeController } from './tree.js';\n\nexport class StateController<T extends object> implements ReactiveController {\n public sorting!: SortController<T>;\n public filtering!: FilterController<T>;\n public navigation!: NavigationController<T>;\n public resizing!: ResizeController<T>;\n public pagination!: PaginationController<T>;\n public reordering!: ReorderController<T>;\n public editing!: EditingController<T>;\n public history!: HistoryController<T>;\n public selection!: SelectionController<T>;\n public expansion!: ExpansionController<T>;\n public tree!: TreeController<T>;\n public rowPin!: RowPinController<T>;\n public rowReorder!: RowReorderController<T>;\n\n /**\n * Optional feature controllers contributed by {@link GridFeatureModule}s,\n * keyed by module id. Empty for the community `<apex-grid>` element; populated\n * by derived grids (e.g. `@apexcharts/grid-enterprise`) that pass modules to\n * the constructor.\n */\n public readonly modules = new Map<string, ReactiveController>();\n\n /**\n * Current message in the grid's polite live region. Bound by the host's\n * `renderLiveRegion()` template; mutated through {@link setAnnouncement}\n * so screen readers re-announce on every change.\n */\n public announcement = '';\n #announceToken = 0;\n\n /**\n * Updates the polite live region's text. Repeats are forced to fire by\n * appending a zero-width space — screen readers ignore unchanged content,\n * so two identical sort announcements wouldn't otherwise be read aloud.\n */\n public setAnnouncement(message: string): void {\n if (!message) {\n this.announcement = '';\n this.host.requestUpdate();\n return;\n }\n this.#announceToken = (this.#announceToken + 1) % 2;\n this.announcement = this.#announceToken ? message : `${message} `;\n this.host.requestUpdate();\n }\n\n /**\n * Resolves a built-in locale key to its display string, honoring the host\n * grid's {@link ApexGrid.localeText} overrides. Thin proxy to\n * {@link ApexGrid.localize} so components can localize via `this.state`.\n */\n public localize(key: GridLocaleKey, params?: LocaleParams, fallback?: string): string {\n return this.host.localize(key, params, fallback);\n }\n\n public get active() {\n return this.navigation.active;\n }\n\n public set active(node: ActiveNode<T>) {\n this.navigation.active = node;\n }\n\n public get headerRow() {\n // @ts-expect-error - Protected member access\n return this.host.headerRow;\n }\n\n public get scrollContainer() {\n // @ts-expect-error - Protected member access\n return this.host.scrollContainer;\n }\n\n public get paginator() {\n // @ts-expect-error - Protected member access\n return this.host.paginator;\n }\n\n public get toolbar() {\n // @ts-expect-error - Protected member access\n return this.host.toolbar;\n }\n\n /**\n * Cumulative pin offsets (in px) keyed by column key. Populated by the\n * {@link GridDOMController} after each layout.\n */\n public get pinOffsets(): Map<unknown, number> {\n // @ts-expect-error - Protected member access\n const dom = this.host.DOM as { pinOffsets?: Map<unknown, number> } | undefined;\n return dom?.pinOffsets ?? new Map();\n }\n\n constructor(\n public host: GridHost<T>,\n private extraModules: ReadonlyArray<GridFeatureModule<T>> = []\n ) {\n this.host.addController(this);\n this.init();\n }\n\n protected init() {\n this.sorting = new SortController(this.host);\n this.filtering = new FilterController(this.host);\n this.navigation = new NavigationController(this.host);\n this.resizing = new ResizeController(this.host);\n this.pagination = new PaginationController(this.host);\n this.reordering = new ReorderController(this.host);\n this.history = new HistoryController(this.host);\n this.editing = new EditingController(this.host, this.history);\n this.selection = new SelectionController(this.host);\n this.expansion = new ExpansionController(this.host);\n this.tree = new TreeController(this.host);\n this.rowPin = new RowPinController(this.host);\n this.rowReorder = new RowReorderController(this.host);\n\n for (const module of this.extraModules) {\n if (this.modules.has(module.id)) continue;\n this.modules.set(module.id, module.create(this.host, this));\n }\n }\n\n /**\n * Look up a feature controller contributed by a {@link GridFeatureModule},\n * by its module id. Returns `undefined` when no such module is registered.\n */\n public module<C extends ReactiveController>(id: string): C | undefined {\n return this.modules.get(id) as C | undefined;\n }\n\n /**\n * Runs the post-pipeline row transforms contributed by feature modules\n * implementing {@link RowTransformer}, in registration order. Returns the\n * input unchanged when no such module is registered — the community grid path\n * is a no-op pass-through.\n */\n public applyModuleTransforms(rows: T[]): T[] {\n let result = rows;\n for (const controller of this.modules.values()) {\n if (isRowTransformer<T>(controller)) {\n result = controller.processRows(result);\n }\n }\n return result;\n }\n\n /**\n * Asks feature modules implementing {@link RowPresenter} whether they render\n * the given row as full-width custom content (e.g. a group header). Returns\n * the first non-null result, or `null` when no module owns the row.\n */\n public presentRow(row: T, ctx: RowPresenterContext<T>): PresentedRow | null {\n for (const controller of this.modules.values()) {\n if (isRowPresenter<T>(controller)) {\n const presented = controller.presentRow(row, ctx);\n if (presented) return presented;\n }\n }\n return null;\n }\n\n /**\n * Monotonic token bumped by {@link bumpDecoration} whenever module-driven cell\n * decoration changes. Forwarded down to each cell as a reactive property so a\n * decoration-only change (e.g. dragging a selection range) re-renders cells\n * without re-running the data pipeline. Always `0` for the community grid.\n */\n #decorationVersion = 0;\n\n public get decorationVersion(): number {\n return this.#decorationVersion;\n }\n\n /**\n * Signals that {@link CellDecorator} output may have changed. Bumps the\n * {@link decorationVersion} and requests a host update so cells re-run their\n * decoration. Called by feature modules after mutating decoration state.\n */\n public bumpDecoration(): void {\n this.#decorationVersion += 1;\n this.host.requestUpdate();\n }\n\n /**\n * Whether any feature module implementing {@link ColumnMenuProvider} offers a\n * column header menu. The header uses this to show its kebab button even on\n * columns that are neither sortable nor resizable, so a module (the enterprise\n * context menu) can surface pin / hide / group / chart actions. Always `false`\n * for the community grid (no modules).\n */\n public get hasColumnMenu(): boolean {\n for (const controller of this.modules.values()) {\n if (isColumnMenuProvider(controller) && controller.providesColumnMenu()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Collects per-cell decoration contributed by feature modules implementing\n * {@link CellDecorator}, merging their attribute maps (later modules win on a\n * key clash). Returns `null` when no module decorates the cell — the community\n * grid path, where each cell applies nothing.\n */\n public decorateCell(ctx: CellDecoratorContext<T>): CellDecoration | null {\n let attributes: Record<string, string | null | undefined> | null = null;\n for (const controller of this.modules.values()) {\n if (isCellDecorator<T>(controller)) {\n const decoration = controller.decorateCell(ctx);\n if (decoration) {\n attributes ??= {};\n Object.assign(attributes, decoration.attributes);\n }\n }\n }\n return attributes ? { attributes } : null;\n }\n\n /**\n * Forwards a body-cell pointer interaction to every feature module that\n * implements {@link CellInteractionHandler}. No-op for the community grid\n * (no modules); the grid only calls this when modules are registered.\n */\n public handleCellInteraction(interaction: CellInteraction<T>): void {\n for (const controller of this.modules.values()) {\n if (isCellInteractionHandler<T>(controller)) {\n controller.handleCellInteraction(interaction);\n }\n }\n }\n\n /**\n * Collects per-module snapshot state from feature controllers implementing\n * {@link SerializableModule}, keyed by module id. Returns an empty object for\n * the community grid (no modules). Used by `ApexGrid.getState`.\n */\n public serializeModuleState(): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [id, controller] of this.modules) {\n if (isSerializableModule(controller)) {\n out[id] = controller.serializeState();\n }\n }\n return out;\n }\n\n /**\n * Dispatches previously-serialized state back to the matching feature modules\n * (by id) that implement {@link SerializableModule}. Missing ids and unknown\n * modules are ignored. Used by `ApexGrid.setState`.\n */\n public restoreModuleState(data: Record<string, unknown> | undefined): void {\n if (!data) return;\n for (const [id, controller] of this.modules) {\n if (isSerializableModule(controller) && Object.hasOwn(data, id)) {\n controller.restoreState(data[id]);\n }\n }\n }\n\n public hostConnected() {}\n\n public hostUpdate(): void {\n this.headerRow?.requestUpdate();\n this.scrollContainer?.requestUpdate();\n this.paginator?.requestUpdate();\n this.toolbar?.requestUpdate();\n }\n}\n\nexport const gridStateContext = createContext<StateController<any>>('gridStateController');\n"]}
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/controllers/state.ts"],"names":[],"mappings":"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","sourcesContent":["import { createContext } from '@lit/context';\nimport type { ReactiveController } from 'lit';\nimport type { GridLocaleKey, LocaleParams } from '../i18n/index.js';\nimport {\n type CellDecoration,\n type CellDecoratorContext,\n type CellInteraction,\n type GridFeatureModule,\n isCellDecorator,\n isCellInteractionHandler,\n isColumnMenuProvider,\n isRowAriaProvider,\n isRowPresenter,\n isRowTransformer,\n isSerializableModule,\n type PresentedRow,\n type RowAria,\n type RowPresenterContext,\n} from '../internal/feature-module.js';\nimport type { ActiveNode, GridHost } from '../internal/types.js';\nimport { EditingController } from './editing.js';\nimport { ExpansionController } from './expansion.js';\nimport { FilterController } from './filter.js';\nimport { HistoryController } from './history.js';\nimport { NavigationController } from './navigation.js';\nimport { PaginationController } from './pagination.js';\nimport { ReorderController } from './reorder.js';\nimport { ResizeController } from './resize.js';\nimport { RowPinController } from './row-pin.js';\nimport { RowReorderController } from './row-reorder.js';\nimport { SelectionController } from './selection.js';\nimport { SortController } from './sort.js';\nimport { TreeController } from './tree.js';\n\nexport class StateController<T extends object> implements ReactiveController {\n public sorting!: SortController<T>;\n public filtering!: FilterController<T>;\n public navigation!: NavigationController<T>;\n public resizing!: ResizeController<T>;\n public pagination!: PaginationController<T>;\n public reordering!: ReorderController<T>;\n public editing!: EditingController<T>;\n public history!: HistoryController<T>;\n public selection!: SelectionController<T>;\n public expansion!: ExpansionController<T>;\n public tree!: TreeController<T>;\n public rowPin!: RowPinController<T>;\n public rowReorder!: RowReorderController<T>;\n\n /**\n * Optional feature controllers contributed by {@link GridFeatureModule}s,\n * keyed by module id. Empty for the community `<apex-grid>` element; populated\n * by derived grids (e.g. `@apexcharts/grid-enterprise`) that pass modules to\n * the constructor.\n */\n public readonly modules = new Map<string, ReactiveController>();\n\n /**\n * Current message in the grid's polite live region. Bound by the host's\n * `renderLiveRegion()` template; mutated through {@link setAnnouncement}\n * so screen readers re-announce on every change.\n */\n public announcement = '';\n #announceToken = 0;\n\n /**\n * Updates the polite live region's text. Repeats are forced to fire by\n * appending a zero-width space — screen readers ignore unchanged content,\n * so two identical sort announcements wouldn't otherwise be read aloud.\n */\n public setAnnouncement(message: string): void {\n if (!message) {\n this.announcement = '';\n this.host.requestUpdate();\n return;\n }\n this.#announceToken = (this.#announceToken + 1) % 2;\n this.announcement = this.#announceToken ? message : `${message} `;\n this.host.requestUpdate();\n }\n\n /**\n * Resolves a built-in locale key to its display string, honoring the host\n * grid's {@link ApexGrid.localeText} overrides. Thin proxy to\n * {@link ApexGrid.localize} so components can localize via `this.state`.\n */\n public localize(key: GridLocaleKey, params?: LocaleParams, fallback?: string): string {\n return this.host.localize(key, params, fallback);\n }\n\n public get active() {\n return this.navigation.active;\n }\n\n public set active(node: ActiveNode<T>) {\n this.navigation.active = node;\n }\n\n public get headerRow() {\n // @ts-expect-error - Protected member access\n return this.host.headerRow;\n }\n\n public get scrollContainer() {\n // @ts-expect-error - Protected member access\n return this.host.scrollContainer;\n }\n\n public get paginator() {\n // @ts-expect-error - Protected member access\n return this.host.paginator;\n }\n\n public get toolbar() {\n // @ts-expect-error - Protected member access\n return this.host.toolbar;\n }\n\n /**\n * Cumulative pin offsets (in px) keyed by column key. Populated by the\n * {@link GridDOMController} after each layout.\n */\n public get pinOffsets(): Map<unknown, number> {\n // @ts-expect-error - Protected member access\n const dom = this.host.DOM as { pinOffsets?: Map<unknown, number> } | undefined;\n return dom?.pinOffsets ?? new Map();\n }\n\n constructor(\n public host: GridHost<T>,\n private extraModules: ReadonlyArray<GridFeatureModule<T>> = []\n ) {\n this.host.addController(this);\n this.init();\n }\n\n protected init() {\n this.sorting = new SortController(this.host);\n this.filtering = new FilterController(this.host);\n this.navigation = new NavigationController(this.host);\n this.resizing = new ResizeController(this.host);\n this.pagination = new PaginationController(this.host);\n this.reordering = new ReorderController(this.host);\n this.history = new HistoryController(this.host);\n this.editing = new EditingController(this.host, this.history);\n this.selection = new SelectionController(this.host);\n this.expansion = new ExpansionController(this.host);\n this.tree = new TreeController(this.host);\n this.rowPin = new RowPinController(this.host);\n this.rowReorder = new RowReorderController(this.host);\n\n for (const module of this.extraModules) {\n if (this.modules.has(module.id)) continue;\n this.modules.set(module.id, module.create(this.host, this));\n }\n }\n\n /**\n * Look up a feature controller contributed by a {@link GridFeatureModule},\n * by its module id. Returns `undefined` when no such module is registered.\n */\n public module<C extends ReactiveController>(id: string): C | undefined {\n return this.modules.get(id) as C | undefined;\n }\n\n /**\n * Runs the post-pipeline row transforms contributed by feature modules\n * implementing {@link RowTransformer}, in registration order. Returns the\n * input unchanged when no such module is registered — the community grid path\n * is a no-op pass-through.\n */\n public applyModuleTransforms(rows: T[]): T[] {\n let result = rows;\n for (const controller of this.modules.values()) {\n if (isRowTransformer<T>(controller)) {\n result = controller.processRows(result);\n }\n }\n return result;\n }\n\n /**\n * Asks feature modules implementing {@link RowPresenter} whether they render\n * the given row as full-width custom content (e.g. a group header). Returns\n * the first non-null result, or `null` when no module owns the row.\n */\n public presentRow(row: T, ctx: RowPresenterContext<T>): PresentedRow | null {\n for (const controller of this.modules.values()) {\n if (isRowPresenter<T>(controller)) {\n const presented = controller.presentRow(row, ctx);\n if (presented) return presented;\n }\n }\n return null;\n }\n\n /**\n * Asks feature modules implementing {@link RowAriaProvider} for ARIA\n * tree/expansion semantics on a normal (cell-rendered) row — e.g. pivoting's\n * expandable parent rows. Returns the first non-null result, or `null`.\n */\n public describeRow(row: T, ctx: RowPresenterContext<T>): RowAria | null {\n for (const controller of this.modules.values()) {\n if (isRowAriaProvider<T>(controller)) {\n const aria = controller.describeRow(row, ctx);\n if (aria) return aria;\n }\n }\n return null;\n }\n\n /**\n * Monotonic token bumped by {@link bumpDecoration} whenever module-driven cell\n * decoration changes. Forwarded down to each cell as a reactive property so a\n * decoration-only change (e.g. dragging a selection range) re-renders cells\n * without re-running the data pipeline. Always `0` for the community grid.\n */\n #decorationVersion = 0;\n\n public get decorationVersion(): number {\n return this.#decorationVersion;\n }\n\n /**\n * Signals that {@link CellDecorator} output may have changed. Bumps the\n * {@link decorationVersion} and requests a host update so cells re-run their\n * decoration. Called by feature modules after mutating decoration state.\n */\n public bumpDecoration(): void {\n this.#decorationVersion += 1;\n this.host.requestUpdate();\n }\n\n /**\n * Whether any feature module implementing {@link ColumnMenuProvider} offers a\n * column header menu. The header uses this to show its kebab button even on\n * columns that are neither sortable nor resizable, so a module (the enterprise\n * context menu) can surface pin / hide / group / chart actions. Always `false`\n * for the community grid (no modules).\n */\n public get hasColumnMenu(): boolean {\n for (const controller of this.modules.values()) {\n if (isColumnMenuProvider(controller) && controller.providesColumnMenu()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Collects per-cell decoration contributed by feature modules implementing\n * {@link CellDecorator}, merging their attribute maps (later modules win on a\n * key clash). Returns `null` when no module decorates the cell — the community\n * grid path, where each cell applies nothing.\n */\n public decorateCell(ctx: CellDecoratorContext<T>): CellDecoration | null {\n let attributes: Record<string, string | null | undefined> | null = null;\n for (const controller of this.modules.values()) {\n if (isCellDecorator<T>(controller)) {\n const decoration = controller.decorateCell(ctx);\n if (decoration) {\n attributes ??= {};\n Object.assign(attributes, decoration.attributes);\n }\n }\n }\n return attributes ? { attributes } : null;\n }\n\n /**\n * Forwards a body-cell pointer interaction to every feature module that\n * implements {@link CellInteractionHandler}. No-op for the community grid\n * (no modules); the grid only calls this when modules are registered.\n */\n public handleCellInteraction(interaction: CellInteraction<T>): void {\n for (const controller of this.modules.values()) {\n if (isCellInteractionHandler<T>(controller)) {\n controller.handleCellInteraction(interaction);\n }\n }\n }\n\n /**\n * Collects per-module snapshot state from feature controllers implementing\n * {@link SerializableModule}, keyed by module id. Returns an empty object for\n * the community grid (no modules). Used by `ApexGrid.getState`.\n */\n public serializeModuleState(): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [id, controller] of this.modules) {\n if (isSerializableModule(controller)) {\n out[id] = controller.serializeState();\n }\n }\n return out;\n }\n\n /**\n * Dispatches previously-serialized state back to the matching feature modules\n * (by id) that implement {@link SerializableModule}. Missing ids and unknown\n * modules are ignored. Used by `ApexGrid.setState`.\n */\n public restoreModuleState(data: Record<string, unknown> | undefined): void {\n if (!data) return;\n for (const [id, controller] of this.modules) {\n if (isSerializableModule(controller) && Object.hasOwn(data, id)) {\n controller.restoreState(data[id]);\n }\n }\n }\n\n public hostConnected() {}\n\n public hostUpdate(): void {\n this.headerRow?.requestUpdate();\n this.scrollContainer?.requestUpdate();\n this.paginator?.requestUpdate();\n this.toolbar?.requestUpdate();\n }\n}\n\nexport const gridStateContext = createContext<StateController<any>>('gridStateController');\n"]}