apex-grid 3.5.0 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +338 -0
- package/LICENSE.md +125 -0
- package/README.md +64 -10
- package/components/cell.d.ts +30 -4
- package/components/cell.js +199 -53
- package/components/cell.js.map +1 -1
- package/components/filter-row.d.ts +2 -0
- package/components/filter-row.js +82 -28
- package/components/filter-row.js.map +1 -1
- package/components/grid.d.ts +146 -36
- package/components/grid.js +442 -103
- package/components/grid.js.map +1 -1
- package/components/group-header-row.js +28 -25
- package/components/group-header-row.js.map +1 -1
- package/components/header-row.d.ts +7 -5
- package/components/header-row.js +11 -9
- package/components/header-row.js.map +1 -1
- package/components/header.js +32 -20
- package/components/header.js.map +1 -1
- package/components/row.d.ts +19 -3
- package/components/row.js +69 -23
- package/components/row.js.map +1 -1
- package/components/toolbar.js +2 -1
- package/components/toolbar.js.map +1 -1
- package/components/virtualizer.d.ts +40 -0
- package/components/virtualizer.js +116 -5
- package/components/virtualizer.js.map +1 -1
- package/controllers/dom.d.ts +4 -4
- package/controllers/dom.js +40 -22
- package/controllers/dom.js.map +1 -1
- package/controllers/editing.d.ts +104 -37
- package/controllers/editing.js +230 -78
- package/controllers/editing.js.map +1 -1
- package/controllers/expansion.d.ts +14 -5
- package/controllers/expansion.js +24 -1
- package/controllers/expansion.js.map +1 -1
- package/controllers/filter.d.ts +10 -2
- package/controllers/filter.js +62 -17
- package/controllers/filter.js.map +1 -1
- package/controllers/history.d.ts +45 -8
- package/controllers/history.js +58 -20
- package/controllers/history.js.map +1 -1
- package/controllers/navigation.d.ts +67 -13
- package/controllers/navigation.js +191 -51
- package/controllers/navigation.js.map +1 -1
- package/controllers/pagination.d.ts +6 -0
- package/controllers/pagination.js +10 -2
- package/controllers/pagination.js.map +1 -1
- package/controllers/reorder.js +38 -22
- package/controllers/reorder.js.map +1 -1
- package/controllers/resize.d.ts +17 -2
- package/controllers/resize.js +16 -6
- package/controllers/resize.js.map +1 -1
- package/controllers/row-pin.d.ts +20 -2
- package/controllers/row-pin.js +16 -9
- package/controllers/row-pin.js.map +1 -1
- package/controllers/row-reorder.d.ts +31 -11
- package/controllers/row-reorder.js +117 -37
- package/controllers/row-reorder.js.map +1 -1
- package/controllers/selection.d.ts +11 -4
- package/controllers/selection.js +26 -11
- package/controllers/selection.js.map +1 -1
- package/controllers/sort.d.ts +22 -2
- package/controllers/sort.js +29 -23
- package/controllers/sort.js.map +1 -1
- package/controllers/state.d.ts +56 -7
- package/controllers/state.js +76 -6
- package/controllers/state.js.map +1 -1
- package/controllers/tree.d.ts +15 -10
- package/controllers/tree.js +0 -0
- package/controllers/tree.js.map +1 -1
- package/custom-elements.json +3156 -277
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/highlight.css +15 -8
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/ApexGrid.html +155 -81
- package/docs/classes/ApexGridPaginator.html +1 -1
- package/docs/classes/ApexGridToolbar.html +3 -3
- package/docs/functions/localize.html +2 -2
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +74 -11
- package/docs/interfaces/ApexCellValidationFailedEvent.html +3 -2
- package/docs/interfaces/ApexCellValueChangedEvent.html +4 -2
- package/docs/interfaces/ApexCellValueChangingEvent.html +3 -2
- package/docs/interfaces/ApexGridEventMap.html +5 -2
- package/docs/interfaces/ApexRowEditEndedEvent.html +2 -1
- package/docs/interfaces/ApexRowEditStartedEvent.html +2 -1
- package/docs/interfaces/ApexRowMovingEvent.html +9 -3
- package/docs/interfaces/ApexRowPinningEvent.html +1 -1
- package/docs/interfaces/ApexTreeRowExpandedEvent.html +4 -1
- package/docs/interfaces/ApexTreeRowExpandingEvent.html +4 -1
- package/docs/interfaces/BaseApexCellContext.html +1 -1
- package/docs/interfaces/BaseApexEditorContext.html +1 -1
- package/docs/interfaces/BaseFilterExpression.html +2 -2
- package/docs/interfaces/CSVExportOptions.html +12 -4
- package/docs/interfaces/DataPipelineConfiguration.html +1 -1
- package/docs/interfaces/ExportOptions.html +5 -3
- package/docs/interfaces/GridExpansionConfiguration.html +6 -2
- package/docs/interfaces/GridRowReorderingConfiguration.html +1 -1
- package/docs/interfaces/PaginationState.html +1 -1
- package/docs/interfaces/SetStateResult.html +3 -2
- package/docs/interfaces/ValidatorContext.html +7 -2
- package/docs/media/_token-values.scss +118 -0
- package/docs/media/package.json +3 -2
- package/docs/modules.html +1 -1
- package/docs/types/ExportSource.html +6 -4
- package/docs/types/OperandKeys.html +9 -0
- package/docs/variables/EN_LOCALE.html +2 -2
- package/i18n/en.d.ts +5 -0
- package/i18n/en.js +5 -0
- package/i18n/en.js.map +1 -1
- package/i18n/es.js +5 -0
- package/i18n/es.js.map +1 -1
- package/internal/column-types.d.ts +27 -1
- package/internal/column-types.js +75 -49
- package/internal/column-types.js.map +1 -1
- package/internal/constants.d.ts +1 -2
- package/internal/constants.js +0 -4
- package/internal/constants.js.map +1 -1
- package/internal/document-styles.d.ts +30 -0
- package/internal/document-styles.js +48 -0
- package/internal/document-styles.js.map +1 -0
- package/internal/export.d.ts +39 -7
- package/internal/export.js +35 -34
- package/internal/export.js.map +1 -1
- package/internal/feature-module.d.ts +60 -3
- package/internal/feature-module.js +6 -0
- package/internal/feature-module.js.map +1 -1
- package/internal/index.d.ts +6 -4
- package/internal/index.js +5 -3
- package/internal/index.js.map +1 -1
- package/internal/normalize-case.d.ts +8 -1
- package/internal/normalize-case.js +3 -2
- package/internal/normalize-case.js.map +1 -1
- package/internal/state-snapshot.d.ts +60 -8
- package/internal/state-snapshot.js +87 -19
- package/internal/state-snapshot.js.map +1 -1
- package/internal/types.d.ts +17 -2
- package/internal/types.js.map +1 -1
- package/internal/utils.d.ts +34 -6
- package/internal/utils.js +30 -21
- package/internal/utils.js.map +1 -1
- package/internal/validators.js +1 -0
- package/internal/validators.js.map +1 -1
- package/operations/filter/operands/number.js +9 -6
- package/operations/filter/operands/number.js.map +1 -1
- package/operations/filter/operands/string.js +2 -3
- package/operations/filter/operands/string.js.map +1 -1
- package/operations/filter/types.d.ts +13 -1
- package/operations/filter/types.js.map +1 -1
- package/operations/filter.d.ts +6 -0
- package/operations/filter.js +23 -7
- package/operations/filter.js.map +1 -1
- package/operations/quick-filter.js +2 -5
- package/operations/quick-filter.js.map +1 -1
- package/operations/sort.d.ts +21 -2
- package/operations/sort.js +41 -14
- package/operations/sort.js.map +1 -1
- package/package.json +8 -3
- package/setup.d.ts +11 -0
- package/setup.js +9 -19
- package/setup.js.map +1 -1
- package/styles/_token-values.css.d.ts +1 -0
- package/styles/_token-values.css.js +3 -0
- package/styles/_token-values.css.js.map +1 -0
- package/styles/_tokens.css.js +1 -1
- package/styles/_tokens.css.js.map +1 -1
- package/styles/body-cell/body-cell.css.js +1 -1
- package/styles/body-cell/body-cell.css.js.map +1 -1
- package/styles/body-cell/cell-renderers.css.js +1 -1
- package/styles/body-cell/cell-renderers.css.js.map +1 -1
- package/styles/body-row/body-row.css.js +1 -1
- package/styles/body-row/body-row.css.js.map +1 -1
- package/styles/document-tokens.css.d.ts +1 -0
- package/styles/document-tokens.css.js +3 -0
- package/styles/document-tokens.css.js.map +1 -0
- package/styles/filter-row/filter-row.css.js +1 -1
- package/styles/filter-row/filter-row.css.js.map +1 -1
- package/styles/grid/_grid.base.css.js +1 -1
- package/styles/grid/_grid.base.css.js.map +1 -1
- package/styles/grid/grid.css.js +1 -1
- package/styles/grid/grid.css.js.map +1 -1
- package/styles/group-header-row/group-header-row.css.js +1 -1
- package/styles/group-header-row/group-header-row.css.js.map +1 -1
- package/styles/header-cell/header-cell.css.js +1 -1
- package/styles/header-cell/header-cell.css.js.map +1 -1
- package/styles/header-row/header-row.base.css.js +1 -1
- package/styles/header-row/header-row.base.css.js.map +1 -1
- package/styles/paginator/paginator.css.js +1 -1
- package/styles/paginator/paginator.css.js.map +1 -1
- package/styles/toolbar/toolbar.css.js +1 -1
- package/styles/toolbar/toolbar.css.js.map +1 -1
- package/tokens.css +78 -0
- package/LICENSE +0 -80
- package/docs/media/LICENSE +0 -80
- package/docs/media/_tokens.scss +0 -214
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../../src/components/toolbar.ts"],"names":[],"mappings":"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","sourcesContent":["import { consume } from '@lit/context';\nimport { html, LitElement, nothing } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { gridStateContext, type StateController } from '../controllers/state.js';\nimport { renderIcon } from '../internal/icons.js';\nimport { registerComponent } from '../internal/register.js';\nimport { GRID_TOOLBAR_TAG } from '../internal/tags.js';\nimport { styles } from '../styles/toolbar/toolbar.css.js';\n\n/**\n * Toolbar shown above the grid's header row. Hosts opt-in toolbar features\n * such as the quick-filter (global search) input and the export menu.\n *\n * @element apex-grid-toolbar\n *\n * @csspart toolbar - The toolbar's container element.\n * @csspart toolbar-search - The quick-filter input wrapper.\n * @csspart search-field - The bordered field containing the icon + input.\n * @csspart search-icon - The leading search icon.\n * @csspart search-input - The text input itself.\n * @csspart toolbar-actions - The trailing actions area (right side).\n * @csspart toolbar-action - A custom host-contributed action button (e.g. \"Create chart\").\n * @csspart export-trigger - The export menu trigger button.\n * @csspart export-menu - The dropdown menu containing export options.\n * @csspart export-menu-item - A single menu item inside the export dropdown.\n */\nexport default class ApexGridToolbar<T extends object> extends LitElement {\n public static get tagName() {\n return GRID_TOOLBAR_TAG;\n }\n\n public static override styles = styles;\n\n /**\n * Registers the `<apex-grid-toolbar>` element. Idempotent.\n */\n public static register() {\n registerComponent(ApexGridToolbar);\n }\n\n @consume({ context: gridStateContext, subscribe: true })\n @property({ attribute: false })\n public state!: StateController<T>;\n\n /**\n * The current quick-filter value, mirrored from {@link ApexGrid.quickFilter}.\n */\n @property({ type: String })\n public value = '';\n\n /**\n * The placeholder rendered in the search input.\n *\n * @remarks\n * When unset, falls back to the grid's localized `toolbar.searchPlaceholder`\n * text (see {@link ApexGrid.localeText}).\n */\n @property({ type: String })\n public placeholder = '';\n\n protected get searchPlaceholder() {\n return this.placeholder || this.state?.localize('toolbar.searchPlaceholder') || 'Search…';\n }\n\n /**\n * Debounce window (ms) before {@link ApexGrid.quickFilter} updates.\n */\n @property({ type: Number, attribute: 'debounce' })\n public debounce = 200;\n\n /** Whether to render the quick-filter input. Driven by the parent grid. */\n @property({ attribute: false, type: Boolean })\n public showQuickFilter = true;\n\n /** Whether to render the export menu trigger. Driven by the parent grid. */\n @property({ attribute: false, type: Boolean })\n public showExport = false;\n\n /** Optional override filename (without extension) for exports. */\n @property({ attribute: false, type: String })\n public exportFilename = 'data';\n\n @query('input')\n protected input!: HTMLInputElement;\n\n @query('[part=\"export-trigger\"]')\n protected exportTrigger!: HTMLButtonElement;\n\n @query('[part=\"export-menu\"]')\n protected exportMenuEl!: HTMLElement;\n\n @state()\n protected exportMenuOpen = false;\n\n #debounceHandle: ReturnType<typeof setTimeout> | null = null;\n\n public override connectedCallback(): void {\n super.connectedCallback();\n document.addEventListener('pointerdown', this.#handleOutsidePointer, true);\n document.addEventListener('keydown', this.#handleDocumentKey, true);\n }\n\n public override disconnectedCallback(): void {\n document.removeEventListener('pointerdown', this.#handleOutsidePointer, true);\n document.removeEventListener('keydown', this.#handleDocumentKey, true);\n if (this.#debounceHandle) {\n clearTimeout(this.#debounceHandle);\n this.#debounceHandle = null;\n }\n super.disconnectedCallback();\n }\n\n #emit(value: string) {\n this.dispatchEvent(\n new CustomEvent<string>('apex-quick-filter', {\n detail: value,\n bubbles: true,\n composed: true,\n })\n );\n }\n\n #handleInput = (event: Event) => {\n event.stopPropagation();\n const next = (event.target as HTMLInputElement).value ?? '';\n if (this.#debounceHandle) clearTimeout(this.#debounceHandle);\n\n if (this.debounce <= 0) {\n this.#emit(next);\n return;\n }\n\n this.#debounceHandle = setTimeout(() => {\n this.#debounceHandle = null;\n this.#emit(next);\n }, this.debounce);\n };\n\n #handleKeydown = (event: KeyboardEvent) => {\n // Don't let arrow keys bubble into the grid navigation controller.\n event.stopPropagation();\n if (event.key === 'Escape' && this.input.value) {\n event.preventDefault();\n this.input.value = '';\n if (this.#debounceHandle) {\n clearTimeout(this.#debounceHandle);\n this.#debounceHandle = null;\n }\n this.#emit('');\n }\n };\n\n #toggleExportMenu = (event?: Event) => {\n event?.stopPropagation();\n this.exportMenuOpen = !this.exportMenuOpen;\n };\n\n #closeExportMenu(returnFocus = false) {\n if (!this.exportMenuOpen) return;\n this.exportMenuOpen = false;\n if (returnFocus) {\n // Return focus to the trigger so keyboard users don't lose their place.\n requestAnimationFrame(() => this.exportTrigger?.focus());\n }\n }\n\n #handleOutsidePointer = (event: PointerEvent) => {\n if (!this.exportMenuOpen) return;\n const path = event.composedPath();\n if (path.includes(this.exportTrigger) || path.includes(this.exportMenuEl)) return;\n this.#closeExportMenu();\n };\n\n #handleDocumentKey = (event: KeyboardEvent) => {\n if (!this.exportMenuOpen) return;\n if (event.key === 'Escape') {\n event.stopPropagation();\n this.#closeExportMenu(true);\n }\n };\n\n #handleExport = (formatId: string) => {\n this.#closeExportMenu();\n const grid = this.state?.host;\n if (!grid) return;\n grid.exportAs(formatId, { filename: this.exportFilename });\n };\n\n /** Lets keyboard users land in the menu when it opens via arrow-down. */\n #handleTriggerKeydown = (event: KeyboardEvent) => {\n if (event.key === 'ArrowDown' || event.key === 'Down') {\n event.preventDefault();\n if (!this.exportMenuOpen) this.exportMenuOpen = true;\n requestAnimationFrame(() => {\n const first = this.exportMenuEl?.querySelector<HTMLElement>('[role=\"menuitem\"]');\n first?.focus();\n });\n }\n };\n\n #handleMenuKeydown = (event: KeyboardEvent) => {\n const items = Array.from(\n this.exportMenuEl?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]') ?? []\n );\n const current = items.indexOf(document.activeElement as HTMLElement);\n if (event.key === 'ArrowDown' || event.key === 'Down') {\n event.preventDefault();\n items[(current + 1) % items.length]?.focus();\n } else if (event.key === 'ArrowUp' || event.key === 'Up') {\n event.preventDefault();\n items[(current - 1 + items.length) % items.length]?.focus();\n } else if (event.key === 'Home') {\n event.preventDefault();\n items[0]?.focus();\n } else if (event.key === 'End') {\n event.preventDefault();\n items[items.length - 1]?.focus();\n } else if (event.key === 'Tab') {\n // Tab closes the menu so focus moves naturally to the next focusable.\n this.#closeExportMenu();\n }\n };\n\n protected renderQuickFilter() {\n if (!this.showQuickFilter) return nothing;\n return html`<div part=\"toolbar-search\">\n <label part=\"search-field\">\n ${renderIcon('search', { part: 'search-icon' })}\n <input\n part=\"search-input\"\n type=\"search\"\n role=\"searchbox\"\n aria-label=${this.searchPlaceholder}\n placeholder=${this.searchPlaceholder}\n .value=${this.value}\n @input=${this.#handleInput}\n @keydown=${this.#handleKeydown}\n />\n </label>\n </div>`;\n }\n\n protected renderExportMenu() {\n if (!this.showExport) return nothing;\n const open = this.exportMenuOpen;\n return html`<div part=\"export\">\n <button\n type=\"button\"\n part=\"export-trigger\"\n aria-label=${this.state.localize('toolbar.export')}\n aria-haspopup=\"menu\"\n aria-expanded=${open ? 'true' : 'false'}\n @click=${this.#toggleExportMenu}\n @keydown=${this.#handleTriggerKeydown}\n >\n ${renderIcon('download', { part: 'export-icon' })}\n ${renderIcon('chevron-down', { part: 'export-caret' })}\n </button>\n <ul\n part=\"export-menu\"\n role=\"menu\"\n aria-label=${this.state.localize('toolbar.exportOptions')}\n ?hidden=${!open}\n @keydown=${this.#handleMenuKeydown}\n >\n ${(this.state?.host?.exportFormats ?? []).map(\n (format) => html`<li role=\"none\">\n <button\n type=\"button\"\n role=\"menuitem\"\n part=\"export-menu-item\"\n tabindex=\"-1\"\n @click=${() => this.#handleExport(format.id)}\n >\n ${format.label}\n </button>\n </li>`\n )}\n </ul>\n </div>`;\n }\n\n protected renderToolbarActions() {\n const actions = this.state?.host?.toolbarActions ?? [];\n if (!actions.length) return nothing;\n return html`${actions.map(\n (action) => html`<button\n type=\"button\"\n part=\"toolbar-action\"\n data-action-id=${action.id ?? ''}\n @click=${() => action.run()}\n >\n ${action.label}\n </button>`\n )}`;\n }\n\n protected override render() {\n if (!this.state) return nothing;\n return html`\n <div part=\"toolbar\" role=\"toolbar\" aria-label=${this.state.localize('toolbar.label')}>\n ${this.renderQuickFilter()}\n <div part=\"toolbar-actions\">${this.renderToolbarActions()}${this.renderExportMenu()}</div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ApexGridToolbar.tagName]: ApexGridToolbar<object>;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../../src/components/toolbar.ts"],"names":[],"mappings":"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","sourcesContent":["import { consume } from '@lit/context';\nimport { html, LitElement, nothing } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { gridStateContext, type StateController } from '../controllers/state.js';\nimport { renderIcon } from '../internal/icons.js';\nimport { registerComponent } from '../internal/register.js';\nimport { GRID_TOOLBAR_TAG } from '../internal/tags.js';\nimport { styles } from '../styles/toolbar/toolbar.css.js';\n\n/**\n * Toolbar shown above the grid's header row. Hosts opt-in toolbar features\n * such as the quick-filter (global search) input and the export menu.\n *\n * @element apex-grid-toolbar\n *\n * @csspart toolbar - The toolbar's container element.\n * @csspart toolbar-search - The quick-filter input wrapper.\n * @csspart search-field - The bordered field containing the icon + input.\n * @csspart search-icon - The leading search icon.\n * @csspart search-input - The text input itself.\n * @csspart toolbar-actions - The trailing actions area (right side).\n * @csspart toolbar-action - A custom host-contributed action button (e.g. \"Create chart\").\n * @csspart export-trigger - The export menu trigger button.\n * @csspart export-menu - The dropdown menu containing export options.\n * @csspart export-menu-item - A single menu item inside the export dropdown.\n */\nexport default class ApexGridToolbar<T extends object> extends LitElement {\n public static get tagName() {\n return GRID_TOOLBAR_TAG;\n }\n\n public static override styles = styles;\n\n /**\n * Registers the `<apex-grid-toolbar>` element. Idempotent.\n */\n public static register() {\n registerComponent(ApexGridToolbar);\n }\n\n @consume({ context: gridStateContext, subscribe: true })\n @property({ attribute: false })\n public state!: StateController<T>;\n\n /**\n * The current quick-filter value, mirrored from {@link ApexGrid.quickFilter}.\n */\n @property({ type: String })\n public value = '';\n\n /**\n * The placeholder rendered in the search input.\n *\n * @remarks\n * When unset, falls back to the grid's localized `toolbar.searchPlaceholder`\n * text (see {@link ApexGrid.localeText}).\n */\n @property({ type: String })\n public placeholder = '';\n\n protected get searchPlaceholder() {\n return this.placeholder || this.state?.localize('toolbar.searchPlaceholder') || 'Search…';\n }\n\n /**\n * Debounce window (ms) before {@link ApexGrid.quickFilter} updates.\n */\n @property({ type: Number, attribute: 'debounce' })\n public debounce = 200;\n\n /** Whether to render the quick-filter input. Driven by the parent grid. */\n @property({ attribute: false, type: Boolean })\n public showQuickFilter = true;\n\n /** Whether to render the export menu trigger. Driven by the parent grid. */\n @property({ attribute: false, type: Boolean })\n public showExport = false;\n\n /** Optional override filename (without extension) for exports. */\n @property({ attribute: false, type: String })\n public exportFilename = 'data';\n\n @query('input')\n protected input!: HTMLInputElement;\n\n @query('[part=\"export-trigger\"]')\n protected exportTrigger!: HTMLButtonElement;\n\n @query('[part=\"export-menu\"]')\n protected exportMenuEl!: HTMLElement;\n\n @state()\n protected exportMenuOpen = false;\n\n #debounceHandle: ReturnType<typeof setTimeout> | null = null;\n\n public override connectedCallback(): void {\n super.connectedCallback();\n document.addEventListener('pointerdown', this.#handleOutsidePointer, true);\n document.addEventListener('keydown', this.#handleDocumentKey, true);\n }\n\n public override disconnectedCallback(): void {\n document.removeEventListener('pointerdown', this.#handleOutsidePointer, true);\n document.removeEventListener('keydown', this.#handleDocumentKey, true);\n if (this.#debounceHandle) {\n clearTimeout(this.#debounceHandle);\n this.#debounceHandle = null;\n }\n super.disconnectedCallback();\n }\n\n #emit(value: string) {\n this.dispatchEvent(\n new CustomEvent<string>('apex-quick-filter', {\n detail: value,\n bubbles: true,\n composed: true,\n })\n );\n }\n\n #handleInput = (event: Event) => {\n event.stopPropagation();\n const next = (event.target as HTMLInputElement).value ?? '';\n if (this.#debounceHandle) clearTimeout(this.#debounceHandle);\n\n if (this.debounce <= 0) {\n this.#emit(next);\n return;\n }\n\n this.#debounceHandle = setTimeout(() => {\n this.#debounceHandle = null;\n this.#emit(next);\n }, this.debounce);\n };\n\n #handleKeydown = (event: KeyboardEvent) => {\n // Don't let arrow keys bubble into the grid navigation controller.\n event.stopPropagation();\n if (event.key === 'Escape' && this.input.value) {\n event.preventDefault();\n this.input.value = '';\n if (this.#debounceHandle) {\n clearTimeout(this.#debounceHandle);\n this.#debounceHandle = null;\n }\n this.#emit('');\n }\n };\n\n #toggleExportMenu = (event?: Event) => {\n event?.stopPropagation();\n this.exportMenuOpen = !this.exportMenuOpen;\n };\n\n #closeExportMenu(returnFocus = false) {\n if (!this.exportMenuOpen) return;\n this.exportMenuOpen = false;\n if (returnFocus) {\n // Return focus to the trigger so keyboard users don't lose their place.\n requestAnimationFrame(() => this.exportTrigger?.focus());\n }\n }\n\n #handleOutsidePointer = (event: PointerEvent) => {\n if (!this.exportMenuOpen) return;\n const path = event.composedPath();\n if (path.includes(this.exportTrigger) || path.includes(this.exportMenuEl)) return;\n this.#closeExportMenu();\n };\n\n #handleDocumentKey = (event: KeyboardEvent) => {\n if (!this.exportMenuOpen) return;\n if (event.key === 'Escape') {\n event.stopPropagation();\n this.#closeExportMenu(true);\n }\n };\n\n #handleExport = (formatId: string) => {\n this.#closeExportMenu();\n const grid = this.state?.host;\n if (!grid) return;\n grid.exportAs(formatId, { filename: this.exportFilename });\n };\n\n /** Lets keyboard users land in the menu when it opens via arrow-down. */\n #handleTriggerKeydown = (event: KeyboardEvent) => {\n if (event.key === 'ArrowDown' || event.key === 'Down') {\n event.preventDefault();\n if (!this.exportMenuOpen) this.exportMenuOpen = true;\n requestAnimationFrame(() => {\n const first = this.exportMenuEl?.querySelector<HTMLElement>('[role=\"menuitem\"]');\n first?.focus();\n });\n }\n };\n\n #handleMenuKeydown = (event: KeyboardEvent) => {\n const items = Array.from(\n this.exportMenuEl?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]') ?? []\n );\n // The menu lives in this shadow root, so `document.activeElement` is only\n // the outermost host; ask the menu's own root for the focused item.\n const root = this.exportMenuEl?.getRootNode() as Document | ShadowRoot | undefined;\n const current = items.indexOf(root?.activeElement as HTMLElement);\n if (event.key === 'ArrowDown' || event.key === 'Down') {\n event.preventDefault();\n items[(current + 1) % items.length]?.focus();\n } else if (event.key === 'ArrowUp' || event.key === 'Up') {\n event.preventDefault();\n items[(current - 1 + items.length) % items.length]?.focus();\n } else if (event.key === 'Home') {\n event.preventDefault();\n items[0]?.focus();\n } else if (event.key === 'End') {\n event.preventDefault();\n items[items.length - 1]?.focus();\n } else if (event.key === 'Tab') {\n // Tab closes the menu so focus moves naturally to the next focusable.\n this.#closeExportMenu();\n }\n };\n\n protected renderQuickFilter() {\n if (!this.showQuickFilter) return nothing;\n return html`<div part=\"toolbar-search\">\n <label part=\"search-field\">\n ${renderIcon('search', { part: 'search-icon' })}\n <input\n part=\"search-input\"\n type=\"search\"\n role=\"searchbox\"\n aria-label=${this.searchPlaceholder}\n placeholder=${this.searchPlaceholder}\n .value=${this.value}\n @input=${this.#handleInput}\n @keydown=${this.#handleKeydown}\n />\n </label>\n </div>`;\n }\n\n protected renderExportMenu() {\n if (!this.showExport) return nothing;\n const open = this.exportMenuOpen;\n return html`<div part=\"export\">\n <button\n type=\"button\"\n part=\"export-trigger\"\n aria-label=${this.state.localize('toolbar.export')}\n aria-haspopup=\"menu\"\n aria-expanded=${open ? 'true' : 'false'}\n @click=${this.#toggleExportMenu}\n @keydown=${this.#handleTriggerKeydown}\n >\n ${renderIcon('download', { part: 'export-icon' })}\n ${renderIcon('chevron-down', { part: 'export-caret' })}\n </button>\n <ul\n part=\"export-menu\"\n role=\"menu\"\n aria-label=${this.state.localize('toolbar.exportOptions')}\n ?hidden=${!open}\n @keydown=${this.#handleMenuKeydown}\n >\n ${(this.state?.host?.exportFormats ?? []).map(\n (format) => html`<li role=\"none\">\n <button\n type=\"button\"\n role=\"menuitem\"\n part=\"export-menu-item\"\n tabindex=\"-1\"\n @click=${() => this.#handleExport(format.id)}\n >\n ${format.label}\n </button>\n </li>`\n )}\n </ul>\n </div>`;\n }\n\n protected renderToolbarActions() {\n const actions = this.state?.host?.toolbarActions ?? [];\n if (!actions.length) return nothing;\n return html`${actions.map(\n (action) => html`<button\n type=\"button\"\n part=\"toolbar-action\"\n data-action-id=${action.id ?? ''}\n @click=${() => action.run()}\n >\n ${action.label}\n </button>`\n )}`;\n }\n\n protected override render() {\n if (!this.state) return nothing;\n return html`\n <div part=\"toolbar\" role=\"toolbar\" aria-label=${this.state.localize('toolbar.label')}>\n ${this.renderQuickFilter()}\n <div part=\"toolbar-actions\">${this.renderToolbarActions()}${this.renderExportMenu()}</div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ApexGridToolbar.tagName]: ApexGridToolbar<object>;\n }\n}\n"]}
|
|
@@ -1,7 +1,47 @@
|
|
|
1
1
|
import { LitVirtualizer } from '@lit-labs/virtualizer/LitVirtualizer.js';
|
|
2
2
|
import type { PropertyValues } from 'lit';
|
|
3
|
+
/** Space, in px, that sticky chrome covers on each side of the scrollport. */
|
|
4
|
+
export interface ScrollInsets {
|
|
5
|
+
top: number;
|
|
6
|
+
right: number;
|
|
7
|
+
bottom: number;
|
|
8
|
+
left: number;
|
|
9
|
+
}
|
|
10
|
+
/** `scrollIntoView` options plus the sticky chrome to keep the target clear of. */
|
|
11
|
+
export type RevealOptions = ScrollIntoViewOptions & {
|
|
12
|
+
insets?: ScrollInsets;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Scrolls `el` into view as if `scroller` had `insets` as its scroll-padding.
|
|
16
|
+
* The padding is set only for the duration of the call. Left in place, the
|
|
17
|
+
* browser would apply it to every later scroll into view, including focus
|
|
18
|
+
* moving onto the sticky chrome itself (a header button, the paginator),
|
|
19
|
+
* which sits inside the padding and would drag the body along.
|
|
20
|
+
*/
|
|
21
|
+
export declare function revealWithin(scroller: HTMLElement | null, el: Element, { insets, ...options }: RevealOptions): void;
|
|
3
22
|
export default class ApexVirtualizer extends LitVirtualizer {
|
|
4
23
|
#private;
|
|
24
|
+
constructor();
|
|
25
|
+
/**
|
|
26
|
+
* Resolves once the layout has settled, or after a bounded wait when no
|
|
27
|
+
* layout is pending (upstream `layoutComplete` only settles on a layout).
|
|
28
|
+
*/
|
|
29
|
+
settled(): Promise<void>;
|
|
30
|
+
/** Whether the item at `index` is in the rendered range. */
|
|
31
|
+
isRendered(index: number): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Scroll handle for item `index`, rendered or not.
|
|
34
|
+
*
|
|
35
|
+
* Upstream scrolls an unrendered item into view by pinning the layout to it,
|
|
36
|
+
* and that pin path assumes the window is the scroller: with the grid host
|
|
37
|
+
* scrolling (`scroller = false`) it overshoots every item once the host has
|
|
38
|
+
* scrolled, leaving the body empty at the maximum scroll offset. An
|
|
39
|
+
* unrendered item is instead reached with a real scroll of the host, to its
|
|
40
|
+
* estimated offset, which the layout then follows like any user scroll.
|
|
41
|
+
*/
|
|
42
|
+
element(index: number): {
|
|
43
|
+
scrollIntoView: (options?: RevealOptions) => void;
|
|
44
|
+
} | undefined;
|
|
5
45
|
static get tagName(): "apex-virtualizer";
|
|
6
46
|
static register(): void;
|
|
7
47
|
scroller: boolean;
|
|
@@ -3,19 +3,130 @@ import { registerComponent } from '../internal/register.js';
|
|
|
3
3
|
import { GRID_BODY } from '../internal/tags.js';
|
|
4
4
|
const SIZER_ATTRIBUTE = 'virtualizer-sizer';
|
|
5
5
|
const MAX_RECOVERY_ATTEMPTS = 3;
|
|
6
|
+
const SETTLE_TIMEOUT_MS = 250;
|
|
7
|
+
export function revealWithin(scroller, el, { insets, ...options }) {
|
|
8
|
+
const style = insets && scroller?.style;
|
|
9
|
+
const previous = style ? style.scrollPadding : '';
|
|
10
|
+
if (style) {
|
|
11
|
+
const { top, right, bottom, left } = insets;
|
|
12
|
+
style.scrollPadding = `${top}px ${right}px ${bottom}px ${left}px`;
|
|
13
|
+
}
|
|
14
|
+
el.scrollIntoView(options);
|
|
15
|
+
if (style)
|
|
16
|
+
style.scrollPadding = previous;
|
|
17
|
+
}
|
|
6
18
|
export default class ApexVirtualizer extends LitVirtualizer {
|
|
19
|
+
#viewportObserver;
|
|
20
|
+
#visibleHeight;
|
|
21
|
+
#pendingCheck;
|
|
22
|
+
#recoveryAttempts;
|
|
23
|
+
#first;
|
|
24
|
+
#last;
|
|
7
25
|
constructor() {
|
|
8
|
-
super(
|
|
26
|
+
super();
|
|
9
27
|
this.#viewportObserver = null;
|
|
10
28
|
this.#visibleHeight = 0;
|
|
11
29
|
this.#pendingCheck = 0;
|
|
12
30
|
this.#recoveryAttempts = 0;
|
|
31
|
+
this.#first = -1;
|
|
32
|
+
this.#last = -1;
|
|
13
33
|
this.scroller = false;
|
|
34
|
+
this.addEventListener('rangeChanged', (event) => {
|
|
35
|
+
const { first, last } = event;
|
|
36
|
+
this.#first = first;
|
|
37
|
+
this.#last = last;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
settled() {
|
|
41
|
+
const layout = this.layoutComplete;
|
|
42
|
+
const timeout = new Promise((resolve) => setTimeout(resolve, SETTLE_TIMEOUT_MS));
|
|
43
|
+
return layout ? Promise.race([layout.catch(() => undefined), timeout]) : timeout;
|
|
44
|
+
}
|
|
45
|
+
isRendered(index) {
|
|
46
|
+
return index >= 0 && index >= this.#first && index <= this.#last;
|
|
47
|
+
}
|
|
48
|
+
element(index) {
|
|
49
|
+
const target = index === Number.POSITIVE_INFINITY ? this.items.length - 1 : index;
|
|
50
|
+
if (!super.element(target))
|
|
51
|
+
return undefined;
|
|
52
|
+
return {
|
|
53
|
+
scrollIntoView: (options = {}) => {
|
|
54
|
+
const row = this.#renderedChild(target);
|
|
55
|
+
if (row)
|
|
56
|
+
revealWithin(this.#scroller(), row, options);
|
|
57
|
+
else
|
|
58
|
+
this.#scrollToUnrendered(target, options);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
#renderedChild(index) {
|
|
63
|
+
if (!this.isRendered(index))
|
|
64
|
+
return null;
|
|
65
|
+
for (let child = this.firstElementChild; child; child = child.nextElementSibling) {
|
|
66
|
+
if (child.index === index)
|
|
67
|
+
return child;
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
#scroller() {
|
|
72
|
+
let node = this.parentNode;
|
|
73
|
+
while (node) {
|
|
74
|
+
if (node instanceof ShadowRoot) {
|
|
75
|
+
node = node.host;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
if (node instanceof HTMLElement && getComputedStyle(node).overflowY !== 'visible') {
|
|
79
|
+
return node;
|
|
80
|
+
}
|
|
81
|
+
node = node.parentNode;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
#scrollToUnrendered(index, options) {
|
|
87
|
+
const scroller = this.#scroller();
|
|
88
|
+
const count = this.items.length;
|
|
89
|
+
if (!scroller || !count)
|
|
90
|
+
return;
|
|
91
|
+
const size = this.offsetHeight / count;
|
|
92
|
+
if (!size)
|
|
93
|
+
return;
|
|
94
|
+
const padStart = options.insets?.top ?? 0;
|
|
95
|
+
const padEnd = options.insets?.bottom ?? 0;
|
|
96
|
+
const viewport = scroller.clientHeight - padStart - padEnd;
|
|
97
|
+
const origin = this.getBoundingClientRect().top -
|
|
98
|
+
scroller.getBoundingClientRect().top -
|
|
99
|
+
scroller.clientTop +
|
|
100
|
+
scroller.scrollTop;
|
|
101
|
+
const start = origin + index * size;
|
|
102
|
+
const end = start + size;
|
|
103
|
+
const current = scroller.scrollTop;
|
|
104
|
+
let top;
|
|
105
|
+
switch (options.block ?? 'start') {
|
|
106
|
+
case 'start':
|
|
107
|
+
top = start - padStart;
|
|
108
|
+
break;
|
|
109
|
+
case 'end':
|
|
110
|
+
top = end - padStart - viewport;
|
|
111
|
+
break;
|
|
112
|
+
case 'center':
|
|
113
|
+
top = (start + end) / 2 - padStart - viewport / 2;
|
|
114
|
+
break;
|
|
115
|
+
default:
|
|
116
|
+
if (start < current + padStart)
|
|
117
|
+
top = start - padStart;
|
|
118
|
+
else if (end > current + padStart + viewport)
|
|
119
|
+
top = end - padStart - viewport;
|
|
120
|
+
else
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
scroller.scrollTo({ top, behavior: options.behavior });
|
|
124
|
+
void this.settled().then(() => {
|
|
125
|
+
const row = this.#renderedChild(index);
|
|
126
|
+
if (row)
|
|
127
|
+
revealWithin(scroller, row, options);
|
|
128
|
+
});
|
|
14
129
|
}
|
|
15
|
-
#viewportObserver;
|
|
16
|
-
#visibleHeight;
|
|
17
|
-
#pendingCheck;
|
|
18
|
-
#recoveryAttempts;
|
|
19
130
|
static get tagName() {
|
|
20
131
|
return GRID_BODY;
|
|
21
132
|
}
|
|
@@ -1 +1 @@
|
|
|
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
|
+
{"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\n/** Space, in px, that sticky chrome covers on each side of the scrollport. */\nexport interface ScrollInsets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/** `scrollIntoView` options plus the sticky chrome to keep the target clear of. */\nexport type RevealOptions = ScrollIntoViewOptions & { insets?: ScrollInsets };\n\n/** Longest wait for the layout to settle after a scroll to an unrendered row. */\nconst SETTLE_TIMEOUT_MS = 250;\n\n/**\n * Scrolls `el` into view as if `scroller` had `insets` as its scroll-padding.\n * The padding is set only for the duration of the call. Left in place, the\n * browser would apply it to every later scroll into view, including focus\n * moving onto the sticky chrome itself (a header button, the paginator),\n * which sits inside the padding and would drag the body along.\n */\nexport function revealWithin(\n scroller: HTMLElement | null,\n el: Element,\n { insets, ...options }: RevealOptions\n): void {\n const style = insets && scroller?.style;\n const previous = style ? style.scrollPadding : '';\n if (style) {\n const { top, right, bottom, left } = insets;\n style.scrollPadding = `${top}px ${right}px ${bottom}px ${left}px`;\n }\n el.scrollIntoView(options);\n if (style) style.scrollPadding = previous;\n}\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 /** Item indexes currently rendered, as last reported by `rangeChanged`. */\n #first = -1;\n #last = -1;\n\n constructor() {\n super();\n // Registered before the upstream directive's own listener (added on first\n // render), so the range is current before the rows are re-rendered.\n this.addEventListener('rangeChanged', (event) => {\n const { first, last } = event as Event & { first: number; last: number };\n this.#first = first;\n this.#last = last;\n });\n }\n\n /**\n * Resolves once the layout has settled, or after a bounded wait when no\n * layout is pending (upstream `layoutComplete` only settles on a layout).\n */\n public settled(): Promise<void> {\n const layout = this.layoutComplete;\n const timeout = new Promise<void>((resolve) => setTimeout(resolve, SETTLE_TIMEOUT_MS));\n return layout ? Promise.race([layout.catch(() => undefined), timeout]) : timeout;\n }\n\n /** Whether the item at `index` is in the rendered range. */\n public isRendered(index: number): boolean {\n return index >= 0 && index >= this.#first && index <= this.#last;\n }\n\n /**\n * Scroll handle for item `index`, rendered or not.\n *\n * Upstream scrolls an unrendered item into view by pinning the layout to it,\n * and that pin path assumes the window is the scroller: with the grid host\n * scrolling (`scroller = false`) it overshoots every item once the host has\n * scrolled, leaving the body empty at the maximum scroll offset. An\n * unrendered item is instead reached with a real scroll of the host, to its\n * estimated offset, which the layout then follows like any user scroll.\n */\n public override element(\n index: number\n ): { scrollIntoView: (options?: RevealOptions) => void } | undefined {\n const target = index === Number.POSITIVE_INFINITY ? this.items.length - 1 : index;\n if (!super.element(target)) return undefined;\n return {\n scrollIntoView: (options: RevealOptions = {}) => {\n const row = this.#renderedChild(target);\n if (row) revealWithin(this.#scroller(), row, options);\n else this.#scrollToUnrendered(target, options);\n },\n };\n }\n\n #renderedChild(index: number): HTMLElement | null {\n if (!this.isRendered(index)) return null;\n for (let child = this.firstElementChild; child; child = child.nextElementSibling) {\n if ((child as Element & { index?: number }).index === index) return child as HTMLElement;\n }\n return null;\n }\n\n /** The nearest ancestor that scrolls this element (the grid host). */\n #scroller(): HTMLElement | null {\n let node: Node | null = this.parentNode;\n while (node) {\n if (node instanceof ShadowRoot) {\n node = node.host;\n } else {\n if (node instanceof HTMLElement && getComputedStyle(node).overflowY !== 'visible') {\n return node;\n }\n node = node.parentNode;\n }\n }\n return null;\n }\n\n #scrollToUnrendered(index: number, options: RevealOptions): void {\n const scroller = this.#scroller();\n const count = this.items.length;\n if (!scroller || !count) return;\n // The upstream layout sizes this element to its estimate of the total\n // extent, so the average item size here matches its own estimates for\n // items it has not measured.\n const size = this.offsetHeight / count;\n if (!size) return;\n\n const padStart = options.insets?.top ?? 0;\n const padEnd = options.insets?.bottom ?? 0;\n const viewport = scroller.clientHeight - padStart - padEnd;\n const origin =\n this.getBoundingClientRect().top -\n scroller.getBoundingClientRect().top -\n scroller.clientTop +\n scroller.scrollTop;\n const start = origin + index * size;\n const end = start + size;\n const current = scroller.scrollTop;\n\n let top: number;\n switch (options.block ?? 'start') {\n case 'start':\n top = start - padStart;\n break;\n case 'end':\n top = end - padStart - viewport;\n break;\n case 'center':\n top = (start + end) / 2 - padStart - viewport / 2;\n break;\n default:\n if (start < current + padStart) top = start - padStart;\n else if (end > current + padStart + viewport) top = end - padStart - viewport;\n else return;\n }\n scroller.scrollTo({ top, behavior: options.behavior });\n // The offset was an estimate; once the target is rendered, align the real row.\n void this.settled().then(() => {\n const row = this.#renderedChild(index);\n if (row) revealWithin(scroller, row, options);\n });\n }\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"]}
|
package/controllers/dom.d.ts
CHANGED
|
@@ -30,9 +30,10 @@ export declare class GridDOMController<T extends object> implements ReactiveCont
|
|
|
30
30
|
rowRenderer: RenderItemFunction<T>;
|
|
31
31
|
/**
|
|
32
32
|
* Renders a single pinned row for a sticky band. Reuses {@link ApexGridRow}
|
|
33
|
-
* so selection / expansion / decoration all work by data
|
|
34
|
-
* sentinel {@link ActiveNode} (pinned rows are
|
|
35
|
-
* surfaces in v1, never the
|
|
33
|
+
* so selection / expansion / decoration / editing all work by data
|
|
34
|
+
* reference, but pins a sentinel {@link ActiveNode} (pinned rows are
|
|
35
|
+
* presentation, selection and pointer-edit surfaces in v1, never the
|
|
36
|
+
* keyboard-active cell).
|
|
36
37
|
*
|
|
37
38
|
* @param localIndex - position within the band (drives the active sentinel id).
|
|
38
39
|
* @param ariaRowOffset - so `aria-rowindex` continues the unified sequence.
|
|
@@ -48,7 +49,6 @@ export declare class GridDOMController<T extends object> implements ReactiveCont
|
|
|
48
49
|
* horizontal scrolling doesn't drag them off-screen.
|
|
49
50
|
*/
|
|
50
51
|
recomputeHostWidth(): void;
|
|
51
|
-
setScrollOffset(): void;
|
|
52
52
|
protected setGridColumnSizes(): void;
|
|
53
53
|
getActiveRowStyles(index: number): StyleInfo;
|
|
54
54
|
/**
|
package/controllers/dom.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { html } from 'lit';
|
|
2
2
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
3
3
|
import { SENTINEL_NODE } from '../internal/constants.js';
|
|
4
|
-
import { applyColumnWidths, getDisplayColumns } from '../internal/utils.js';
|
|
4
|
+
import { applyColumnWidths, getDisplayColumns, leadingChromeTracks, } from '../internal/utils.js';
|
|
5
5
|
export class GridDOMController {
|
|
6
6
|
constructor(host, state) {
|
|
7
7
|
this.host = host;
|
|
8
8
|
this.state = state;
|
|
9
9
|
this.#initialSize = () => {
|
|
10
10
|
setTimeout(() => {
|
|
11
|
-
this.setScrollOffset();
|
|
12
11
|
this.recomputePinOffsets();
|
|
13
12
|
this.recomputeStickyRowOffsets();
|
|
14
13
|
});
|
|
@@ -20,8 +19,7 @@ export class GridDOMController {
|
|
|
20
19
|
this.columnSizes = {};
|
|
21
20
|
this.pinOffsets = new Map();
|
|
22
21
|
this.rowRenderer = (data, index) => {
|
|
23
|
-
const
|
|
24
|
-
const editingKey = editingCell?.rowIndex === index ? editingCell.columnKey : null;
|
|
22
|
+
const editingKey = this.#editingKey(data);
|
|
25
23
|
const ariaRowOffset = this.headerRowCount + this.state.rowPin.pinnedRows.top.length;
|
|
26
24
|
return html `
|
|
27
25
|
<apex-grid-row
|
|
@@ -35,6 +33,7 @@ export class GridDOMController {
|
|
|
35
33
|
.editingKey=${editingKey}
|
|
36
34
|
.ariaRowOffset=${ariaRowOffset}
|
|
37
35
|
.decorationVersion=${this.state.decorationVersion}
|
|
36
|
+
.dataVersion=${this.state.dataVersion}
|
|
38
37
|
.validationVersion=${this.state.editing.validationVersion}
|
|
39
38
|
.dragging=${this.state.rowReorder.dragging === data}
|
|
40
39
|
.grabbed=${this.state.rowReorder.grabbed === data}
|
|
@@ -43,6 +42,7 @@ export class GridDOMController {
|
|
|
43
42
|
</apex-grid-row>
|
|
44
43
|
`;
|
|
45
44
|
};
|
|
45
|
+
this.#chromeWidth = 0;
|
|
46
46
|
this.#lastGroupTop = -1;
|
|
47
47
|
this.#lastHeaderTop = -1;
|
|
48
48
|
this.#lastFilterTop = -1;
|
|
@@ -66,6 +66,10 @@ export class GridDOMController {
|
|
|
66
66
|
get headerRowCount() {
|
|
67
67
|
return this.host.columnGroupDepth + 1;
|
|
68
68
|
}
|
|
69
|
+
#editingKey(data) {
|
|
70
|
+
const editingCell = this.state.editing.activeCell;
|
|
71
|
+
return editingCell && editingCell.data === data ? editingCell.columnKey : null;
|
|
72
|
+
}
|
|
69
73
|
pinnedRowRenderer(data, localIndex, ariaRowOffset) {
|
|
70
74
|
return html `
|
|
71
75
|
<apex-grid-row
|
|
@@ -76,9 +80,10 @@ export class GridDOMController {
|
|
|
76
80
|
.data=${data}
|
|
77
81
|
.columns=${this.displayColumns}
|
|
78
82
|
.pinOffsets=${this.pinOffsets}
|
|
79
|
-
.editingKey=${
|
|
83
|
+
.editingKey=${this.#editingKey(data)}
|
|
80
84
|
.ariaRowOffset=${ariaRowOffset}
|
|
81
85
|
.decorationVersion=${this.state.decorationVersion}
|
|
86
|
+
.dataVersion=${this.state.dataVersion}
|
|
82
87
|
.validationVersion=${this.state.editing.validationVersion}
|
|
83
88
|
.coordinateHints=${Boolean(this.host.coordinateHints)}
|
|
84
89
|
>
|
|
@@ -98,7 +103,6 @@ export class GridDOMController {
|
|
|
98
103
|
this.recomputeHostWidth();
|
|
99
104
|
}
|
|
100
105
|
hostUpdate() {
|
|
101
|
-
this.setScrollOffset();
|
|
102
106
|
this.setGridColumnSizes();
|
|
103
107
|
}
|
|
104
108
|
hostUpdated() {
|
|
@@ -125,16 +129,28 @@ export class GridDOMController {
|
|
|
125
129
|
host.style.setProperty('--apex-host-width', `${width}px`);
|
|
126
130
|
this.#lastHostWidth = width;
|
|
127
131
|
}
|
|
128
|
-
setScrollOffset() {
|
|
129
|
-
this.host.style.setProperty('--scrollbar-offset', '0px');
|
|
130
|
-
}
|
|
131
132
|
setGridColumnSizes() {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
const chrome = leadingChromeTracks(this.state);
|
|
134
|
+
this.columnSizes = applyColumnWidths(this.displayColumns, chrome);
|
|
135
|
+
this.#publishChromeOffsets(chrome);
|
|
136
|
+
}
|
|
137
|
+
#chromeWidth;
|
|
138
|
+
#publishChromeOffsets(chrome) {
|
|
139
|
+
const offsets = {
|
|
140
|
+
'row-number': 0,
|
|
141
|
+
reorder: 0,
|
|
142
|
+
selection: 0,
|
|
143
|
+
expansion: 0,
|
|
144
|
+
};
|
|
145
|
+
let accum = 0;
|
|
146
|
+
for (const [track, width] of chrome) {
|
|
147
|
+
offsets[track] = accum;
|
|
148
|
+
accum += width;
|
|
149
|
+
}
|
|
150
|
+
this.#chromeWidth = accum;
|
|
151
|
+
for (const [track, offset] of Object.entries(offsets)) {
|
|
152
|
+
this.host.style.setProperty(`--apex-chrome-offset-${track}`, `${offset}px`);
|
|
153
|
+
}
|
|
138
154
|
}
|
|
139
155
|
getActiveRowStyles(index) {
|
|
140
156
|
const { row } = this.state.active;
|
|
@@ -145,19 +161,22 @@ export class GridDOMController {
|
|
|
145
161
|
if (!headerRow?.headers)
|
|
146
162
|
return;
|
|
147
163
|
const next = new Map();
|
|
148
|
-
const
|
|
164
|
+
const widths = new Map();
|
|
165
|
+
const host = this.host;
|
|
166
|
+
const visual = host.getBoundingClientRect().width;
|
|
167
|
+
const layout = host.offsetWidth;
|
|
168
|
+
const scale = visual && layout && Math.abs(visual - layout) >= 1 ? visual / layout : 1;
|
|
149
169
|
for (const header of headerRow.headers) {
|
|
150
|
-
|
|
170
|
+
widths.set(header.column.key, header.getBoundingClientRect().width / scale);
|
|
151
171
|
}
|
|
152
|
-
let leftAccum =
|
|
172
|
+
let leftAccum = this.#chromeWidth;
|
|
153
173
|
for (const column of this.displayColumns) {
|
|
154
174
|
if (column.hidden)
|
|
155
175
|
continue;
|
|
156
176
|
if (column.pinned !== 'start')
|
|
157
177
|
break;
|
|
158
178
|
next.set(column.key, leftAccum);
|
|
159
|
-
|
|
160
|
-
leftAccum += rect?.width ?? 0;
|
|
179
|
+
leftAccum += widths.get(column.key) ?? 0;
|
|
161
180
|
}
|
|
162
181
|
let rightAccum = 0;
|
|
163
182
|
for (let i = this.displayColumns.length - 1; i >= 0; i--) {
|
|
@@ -167,8 +186,7 @@ export class GridDOMController {
|
|
|
167
186
|
if (column.pinned !== 'end')
|
|
168
187
|
break;
|
|
169
188
|
next.set(column.key, rightAccum);
|
|
170
|
-
|
|
171
|
-
rightAccum += rect?.width ?? 0;
|
|
189
|
+
rightAccum += widths.get(column.key) ?? 0;
|
|
172
190
|
}
|
|
173
191
|
if (!offsetsEqual(this.pinOffsets, next)) {
|
|
174
192
|
this.pinOffsets = next;
|
package/controllers/dom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/controllers/dom.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RenderItemFunction } from '@lit-labs/virtualizer/virtualize.js';\nimport { html, type ReactiveController } from 'lit';\nimport { type StyleInfo, styleMap } from 'lit/directives/style-map.js';\nimport { SENTINEL_NODE } from '../internal/constants.js';\nimport type { ActiveNode, ColumnConfiguration, GridHost, Keys } from '../internal/types.js';\nimport { applyColumnWidths, getDisplayColumns } from '../internal/utils.js';\nimport type { StateController } from './state.js';\n\nexport class GridDOMController<T extends object> implements ReactiveController {\n constructor(\n protected host: GridHost<T>,\n protected state: StateController<T>\n ) {\n this.host.addController(this);\n }\n\n #initialSize = () => {\n setTimeout(() => {\n this.setScrollOffset();\n this.recomputePinOffsets();\n this.recomputeStickyRowOffsets();\n });\n };\n\n #resizeObserver: ResizeObserver | null = null;\n #observedHeaders = new Set<Element>();\n #stickyRowObserver: ResizeObserver | null = null;\n #observedStickyRows = new Set<Element>();\n\n public get container() {\n // @ts-expect-error: protected member access\n return this.host.scrollContainer;\n }\n\n /**\n * Visual render order: `'start'`-pinned columns first, then unpinned, then\n * `'end'`-pinned. The user-supplied `columns` array is never mutated.\n */\n public get displayColumns(): Array<ColumnConfiguration<T>> {\n return getDisplayColumns(this.host.columns);\n }\n\n public columnSizes: StyleInfo = {};\n\n /**\n * The resolved inline-start (for `'start'` pin) or inline-end (for `'end'` pin)\n * pixel offset per pinned column key. Populated after layout by\n * {@link recomputePinOffsets}.\n */\n public pinOffsets = new Map<Keys<T>, number>();\n\n /**\n * Number of chrome rows above the body for `aria-rowindex`: an optional group\n * header row and the column header (always present). The filter panel is a\n * floating overlay rather than a table row, so it is not counted here.\n */\n protected get headerRowCount(): number {\n return this.host.columnGroupDepth + 1;\n }\n\n public rowRenderer: RenderItemFunction<T> = (data: T, index: number) => {\n const editingCell = this.state.editing.activeCell;\n const editingKey = editingCell?.rowIndex === index ? editingCell.columnKey : null;\n // Body rows follow the chrome rows and any pinned-top rows in the\n // aria-rowindex sequence.\n const ariaRowOffset = this.headerRowCount + this.state.rowPin.pinnedRows.top.length;\n return html`\n <apex-grid-row\n part=\"row\"\n style=${styleMap({ ...this.columnSizes, ...this.getActiveRowStyles(index) })}\n .index=${index}\n .activeNode=${this.state.active}\n .data=${data}\n .columns=${this.displayColumns}\n .pinOffsets=${this.pinOffsets}\n .editingKey=${editingKey}\n .ariaRowOffset=${ariaRowOffset}\n .decorationVersion=${this.state.decorationVersion}\n .validationVersion=${this.state.editing.validationVersion}\n .dragging=${this.state.rowReorder.dragging === data}\n .grabbed=${this.state.rowReorder.grabbed === data}\n .coordinateHints=${Boolean(this.host.coordinateHints)}\n >\n </apex-grid-row>\n `;\n };\n\n /**\n * Renders a single pinned row for a sticky band. Reuses {@link ApexGridRow}\n * so selection / expansion / decoration all work by data reference, but pins a\n * sentinel {@link ActiveNode} (pinned rows are presentation + selection\n * surfaces in v1, never the active/edited cell) and renders no editor.\n *\n * @param localIndex - position within the band (drives the active sentinel id).\n * @param ariaRowOffset - so `aria-rowindex` continues the unified sequence.\n */\n public pinnedRowRenderer(data: T, localIndex: number, ariaRowOffset: number) {\n return html`\n <apex-grid-row\n part=\"row pinned-row\"\n style=${styleMap(this.columnSizes)}\n .index=${localIndex}\n .activeNode=${SENTINEL_NODE as ActiveNode<T>}\n .data=${data}\n .columns=${this.displayColumns}\n .pinOffsets=${this.pinOffsets}\n .editingKey=${null}\n .ariaRowOffset=${ariaRowOffset}\n .decorationVersion=${this.state.decorationVersion}\n .validationVersion=${this.state.editing.validationVersion}\n .coordinateHints=${Boolean(this.host.coordinateHints)}\n >\n </apex-grid-row>\n `;\n }\n\n public async hostConnected() {\n this.setGridColumnSizes();\n // Wait for the initial paint of the virtualizer and recalculate the scrollbar offset\n // for the next one\n await this.host.updateComplete;\n this.#initialSize();\n if (typeof ResizeObserver !== 'undefined' && !this.#hostWidthObserver) {\n this.#hostWidthObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => this.recomputeHostWidth());\n });\n this.#hostWidthObserver.observe(this.host as HTMLElement);\n }\n this.recomputeHostWidth();\n }\n\n public hostUpdate(): void {\n this.setScrollOffset();\n this.setGridColumnSizes();\n }\n\n public hostUpdated(): void {\n this.recomputePinOffsets();\n this.observeHeaderCells();\n this.recomputeStickyRowOffsets();\n this.observeStickyRows();\n }\n\n public hostDisconnected(): void {\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = null;\n this.#observedHeaders.clear();\n this.#stickyRowObserver?.disconnect();\n this.#stickyRowObserver = null;\n this.#observedStickyRows.clear();\n this.#hostWidthObserver?.disconnect();\n this.#hostWidthObserver = null;\n }\n\n /**\n * Writes the grid host's `clientWidth` into `--apex-host-width`. Used by the\n * toolbar and paginator to clamp their width to the visible viewport so\n * horizontal scrolling doesn't drag them off-screen.\n */\n public recomputeHostWidth(): void {\n const host = this.host as HTMLElement;\n const width = host.clientWidth;\n if (width === this.#lastHostWidth) return;\n host.style.setProperty('--apex-host-width', `${width}px`);\n this.#lastHostWidth = width;\n }\n\n public setScrollOffset() {\n // The grid host now owns vertical scrolling, so the historic per-row\n // padding-inline-end compensation is no longer needed. Keep the CSS var\n // set to `0` for forward compatibility with consumer themes that read it.\n this.host.style.setProperty('--scrollbar-offset', '0px');\n }\n\n protected setGridColumnSizes() {\n this.columnSizes = applyColumnWidths(this.displayColumns, {\n showSelectionColumn: this.state.selection.showCheckboxColumn,\n showExpansionColumn: this.state.expansion.showToggleColumn,\n showReorderHandle: this.state.rowReorder.showHandleColumn,\n showRowNumbers: Boolean(this.host.coordinateHints),\n });\n }\n\n public getActiveRowStyles(index: number): StyleInfo {\n const { row } = this.state.active;\n return row === index ? { 'z-index': '3' } : {};\n }\n\n /**\n * Measures the rendered widths of pinned header cells and writes cumulative\n * inline-start / inline-end pixel offsets into {@link pinOffsets}. Called after\n * each grid update and whenever a header cell is resized.\n */\n public recomputePinOffsets(): void {\n // @ts-expect-error - protected member access\n const headerRow = this.host.headerRow as\n | {\n headers?: Array<{\n column: ColumnConfiguration<T>;\n getBoundingClientRect: () => DOMRect;\n }>;\n }\n | undefined;\n if (!headerRow?.headers) return;\n\n const next = new Map<Keys<T>, number>();\n const headersByKey = new Map<Keys<T>, DOMRect>();\n for (const header of headerRow.headers) {\n headersByKey.set(header.column.key as Keys<T>, header.getBoundingClientRect());\n }\n\n let leftAccum = 0;\n for (const column of this.displayColumns) {\n if (column.hidden) continue;\n if (column.pinned !== 'start') break;\n next.set(column.key as Keys<T>, leftAccum);\n const rect = headersByKey.get(column.key as Keys<T>);\n leftAccum += rect?.width ?? 0;\n }\n\n let rightAccum = 0;\n for (let i = this.displayColumns.length - 1; i >= 0; i--) {\n const column = this.displayColumns[i];\n if (column.hidden) continue;\n if (column.pinned !== 'end') break;\n next.set(column.key as Keys<T>, rightAccum);\n const rect = headersByKey.get(column.key as Keys<T>);\n rightAccum += rect?.width ?? 0;\n }\n\n if (!offsetsEqual(this.pinOffsets, next)) {\n this.pinOffsets = next;\n this.host.requestUpdate();\n }\n }\n\n protected observeHeaderCells(): void {\n // @ts-expect-error - protected member access\n const headerRow = this.host.headerRow as { headers?: Array<Element> } | undefined;\n if (!headerRow?.headers) return;\n\n if (!this.#resizeObserver) {\n this.#resizeObserver = new ResizeObserver(() => {\n // Defer to a new frame so any layout writes can't synchronously feed back\n // into this observer (which makes the browser raise the benign\n // \"ResizeObserver loop completed\" warning).\n requestAnimationFrame(() => this.recomputePinOffsets());\n });\n }\n\n const next = new Set<Element>(headerRow.headers);\n for (const element of this.#observedHeaders) {\n if (!next.has(element)) this.#resizeObserver.unobserve(element);\n }\n for (const element of next) {\n if (!this.#observedHeaders.has(element)) this.#resizeObserver.observe(element);\n }\n this.#observedHeaders = next;\n }\n\n #lastGroupTop = -1;\n #lastHeaderTop = -1;\n #lastFilterTop = -1;\n #lastPinnedTop = -1;\n #lastPinnedBottom = -1;\n #lastHostWidth = -1;\n #hostWidthObserver: ResizeObserver | null = null;\n\n /**\n * Writes the cumulative heights of the sticky chrome rows into CSS custom\n * properties used for their `inset-block-start` / `inset-block-end` offsets.\n * The toolbar is at `top: 0`; the header sits below it\n * (`--apex-row-top-header`), the filter below the header\n * (`--apex-row-top-filter`), and the pinned-top band below the filter\n * (`--apex-row-top-pinned`). The pinned-bottom band sticks above the\n * paginator (`--apex-row-bottom-pinned`). Writes are skipped when values are\n * unchanged so the ResizeObserver feedback loop terminates.\n */\n public recomputeStickyRowOffsets(): void {\n const root = (this.host as HTMLElement).shadowRoot;\n if (!root) return;\n const toolbar = root.querySelector('apex-grid-toolbar') as HTMLElement | null;\n const groupHeader = root.querySelector('apex-grid-group-header-row') as HTMLElement | null;\n const header = root.querySelector('apex-grid-header-row') as HTMLElement | null;\n const filter = root.querySelector('apex-filter-row') as HTMLElement | null;\n const paginator = root.querySelector('apex-grid-paginator') as HTMLElement | null;\n\n const toolbarH = toolbar?.offsetHeight ?? 0;\n const groupH = groupHeader?.offsetHeight ?? 0;\n const headerH = header?.offsetHeight ?? 0;\n const filterH = filter?.offsetHeight ?? 0;\n const paginatorH = paginator?.offsetHeight ?? 0;\n // The group header (when present) sits below the toolbar; the column header\n // sits below the group header; filter below header; pinned-top below filter.\n const groupTop = toolbarH;\n const headerTop = toolbarH + groupH;\n const filterTop = toolbarH + groupH + headerH;\n const pinnedTop = toolbarH + groupH + headerH + filterH;\n\n if (groupTop !== this.#lastGroupTop) {\n this.host.style.setProperty('--apex-row-top-group', `${groupTop}px`);\n this.#lastGroupTop = groupTop;\n }\n if (headerTop !== this.#lastHeaderTop) {\n this.host.style.setProperty('--apex-row-top-header', `${headerTop}px`);\n this.#lastHeaderTop = headerTop;\n }\n if (filterTop !== this.#lastFilterTop) {\n this.host.style.setProperty('--apex-row-top-filter', `${filterTop}px`);\n this.#lastFilterTop = filterTop;\n }\n if (pinnedTop !== this.#lastPinnedTop) {\n this.host.style.setProperty('--apex-row-top-pinned', `${pinnedTop}px`);\n this.#lastPinnedTop = pinnedTop;\n }\n if (paginatorH !== this.#lastPinnedBottom) {\n this.host.style.setProperty('--apex-row-bottom-pinned', `${paginatorH}px`);\n this.#lastPinnedBottom = paginatorH;\n }\n }\n\n protected observeStickyRows(): void {\n const root = (this.host as HTMLElement).shadowRoot;\n if (!root) return;\n const toolbar = root.querySelector('apex-grid-toolbar') as HTMLElement | null;\n const groupHeader = root.querySelector('apex-grid-group-header-row') as HTMLElement | null;\n const header = root.querySelector('apex-grid-header-row') as HTMLElement | null;\n const filter = root.querySelector('apex-filter-row') as HTMLElement | null;\n const paginator = root.querySelector('apex-grid-paginator') as HTMLElement | null;\n\n if (!this.#stickyRowObserver) {\n this.#stickyRowObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => this.recomputeStickyRowOffsets());\n });\n }\n\n const next = new Set<Element>(\n [toolbar, groupHeader, header, filter, paginator].filter((el): el is HTMLElement => !!el)\n );\n for (const element of this.#observedStickyRows) {\n if (!next.has(element)) this.#stickyRowObserver.unobserve(element);\n }\n for (const element of next) {\n if (!this.#observedStickyRows.has(element)) this.#stickyRowObserver.observe(element);\n }\n this.#observedStickyRows = next;\n }\n}\n\nfunction offsetsEqual<K>(a: Map<K, number>, b: Map<K, number>): boolean {\n if (a.size !== b.size) return false;\n for (const [key, value] of a) {\n if (b.get(key) !== value) return false;\n }\n return true;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/controllers/dom.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAA2B,MAAM,KAAK,CAAC;AACpD,OAAO,EAAkB,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,EACL,iBAAiB,EAEjB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,OAAO,iBAAiB;IAC5B,YACY,IAAiB,EACjB,KAAyB;QADzB,SAAI,GAAJ,IAAI,CAAa;QACjB,UAAK,GAAL,KAAK,CAAoB;QAKrC,iBAAY,GAAG,GAAG,EAAE;YAClB,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAC3B,IAAI,CAAC,yBAAyB,EAAE,CAAC;YACnC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,oBAAe,GAA0B,IAAI,CAAC;QAC9C,qBAAgB,GAAG,IAAI,GAAG,EAAW,CAAC;QACtC,uBAAkB,GAA0B,IAAI,CAAC;QACjD,wBAAmB,GAAG,IAAI,GAAG,EAAW,CAAC;QAelC,gBAAW,GAAc,EAAE,CAAC;QAO5B,eAAU,GAAG,IAAI,GAAG,EAAmB,CAAC;QAWxC,gBAAW,GAA0B,CAAC,IAAO,EAAE,KAAa,EAAE,EAAE;YACrE,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAG1C,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;YACpF,OAAO,IAAI,CAAA;;;gBAGC,QAAQ,CAAC,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;iBACnE,KAAK;sBACA,IAAI,CAAC,KAAK,CAAC,MAAM;gBACvB,IAAI;mBACD,IAAI,CAAC,cAAc;sBAChB,IAAI,CAAC,UAAU;sBACf,UAAU;yBACP,aAAa;6BACT,IAAI,CAAC,KAAK,CAAC,iBAAiB;uBAClC,IAAI,CAAC,KAAK,CAAC,WAAW;6BAChB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB;oBAC7C,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,KAAK,IAAI;mBACxC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,KAAK,IAAI;2BAC9B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;;;KAGxD,CAAC;QACJ,CAAC,CAAC;QAqGF,iBAAY,GAAG,CAAC,CAAC;QAkHjB,kBAAa,GAAG,CAAC,CAAC,CAAC;QACnB,mBAAc,GAAG,CAAC,CAAC,CAAC;QACpB,mBAAc,GAAG,CAAC,CAAC,CAAC;QACpB,mBAAc,GAAG,CAAC,CAAC,CAAC;QACpB,sBAAiB,GAAG,CAAC,CAAC,CAAC;QACvB,mBAAc,GAAG,CAAC,CAAC,CAAC;QACpB,uBAAkB,GAA0B,IAAI,CAAC;QApS/C,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,YAAY,CAKV;IAEF,eAAe,CAA+B;IAC9C,gBAAgB,CAAsB;IACtC,kBAAkB,CAA+B;IACjD,mBAAmB,CAAsB;IAEzC,IAAW,SAAS;QAElB,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;IACnC,CAAC;IAMD,IAAW,cAAc;QACvB,OAAO,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAgBD,IAAc,cAAc;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;IACxC,CAAC;IAmCD,WAAW,CAAC,IAAO;QACjB,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;QAClD,OAAO,WAAW,IAAI,WAAW,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;IACjF,CAAC;IAYM,iBAAiB,CAAC,IAAO,EAAE,UAAkB,EAAE,aAAqB;QACzE,OAAO,IAAI,CAAA;;;gBAGC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC;iBACzB,UAAU;sBACL,aAA8B;gBACpC,IAAI;mBACD,IAAI,CAAC,cAAc;sBAChB,IAAI,CAAC,UAAU;sBACf,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;yBACnB,aAAa;6BACT,IAAI,CAAC,KAAK,CAAC,iBAAiB;uBAClC,IAAI,CAAC,KAAK,CAAC,WAAW;6BAChB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB;2BACtC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;;;KAGxD,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,aAAa;QACxB,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAG1B,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;QAC/B,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,OAAO,cAAc,KAAK,WAAW,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACtE,IAAI,CAAC,kBAAkB,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE;gBAChD,qBAAqB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC;YACzD,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,IAAmB,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B,CAAC;IAEM,UAAU;QACf,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B,CAAC;IAEM,WAAW;QAChB,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,yBAAyB,EAAE,CAAC;QACjC,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAEM,gBAAgB;QACrB,IAAI,CAAC,eAAe,EAAE,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,kBAAkB,EAAE,UAAU,EAAE,CAAC;QACtC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC;QACjC,IAAI,CAAC,kBAAkB,EAAE,UAAU,EAAE,CAAC;QACtC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;IACjC,CAAC;IAOM,kBAAkB;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAmB,CAAC;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC;QAC/B,IAAI,KAAK,KAAK,IAAI,CAAC,cAAc;YAAE,OAAO;QAC1C,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,mBAAmB,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;IAC9B,CAAC;IAES,kBAAkB;QAC1B,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,CAAC,WAAW,GAAG,iBAAiB,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QAClE,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAGD,YAAY,CAAK;IAYjB,qBAAqB,CAAC,MAAoC;QACxD,MAAM,OAAO,GAAgC;YAC3C,YAAY,EAAE,CAAC;YACf,OAAO,EAAE,CAAC;YACV,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,CAAC;SACb,CAAC;QACF,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YACpC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;YACvB,KAAK,IAAI,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACtD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,wBAAwB,KAAK,EAAE,EAAE,GAAG,MAAM,IAAI,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;IAEM,kBAAkB,CAAC,KAAa;QACrC,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAClC,OAAO,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACjD,CAAC;IAOM,mBAAmB;QAExB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAOf,CAAC;QACd,IAAI,CAAC,SAAS,EAAE,OAAO;YAAE,OAAO;QAEhC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAmB,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAmB,CAAC;QAK1C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAmB,CAAC;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC;QAChC,MAAM,KAAK,GAAG,MAAM,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACvF,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAc,EAAE,MAAM,CAAC,qBAAqB,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;QACzF,CAAC;QAGD,IAAI,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC;QAClC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACzC,IAAI,MAAM,CAAC,MAAM;gBAAE,SAAS;YAC5B,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO;gBAAE,MAAM;YACrC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAc,EAAE,SAAS,CAAC,CAAC;YAC3C,SAAS,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAc,CAAC,IAAI,CAAC,CAAC;QACtD,CAAC;QAED,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACzD,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;YACtC,IAAI,MAAM,CAAC,MAAM;gBAAE,SAAS;YAC5B,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK;gBAAE,MAAM;YACnC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAc,EAAE,UAAU,CAAC,CAAC;YAC5C,UAAU,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAc,CAAC,IAAI,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAES,kBAAkB;QAE1B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAqD,CAAC;QAClF,IAAI,CAAC,SAAS,EAAE,OAAO;YAAE,OAAO;QAEhC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,IAAI,CAAC,eAAe,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE;gBAI7C,qBAAqB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC;YAC1D,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,GAAG,CAAU,SAAS,CAAC,OAAO,CAAC,CAAC;QACjD,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC5C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAClE,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACjF,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAC/B,CAAC;IAED,aAAa,CAAM;IACnB,cAAc,CAAM;IACpB,cAAc,CAAM;IACpB,cAAc,CAAM;IACpB,iBAAiB,CAAM;IACvB,cAAc,CAAM;IACpB,kBAAkB,CAA+B;IAY1C,yBAAyB;QAC9B,MAAM,IAAI,GAAI,IAAI,CAAC,IAAoB,CAAC,UAAU,CAAC;QACnD,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,mBAAmB,CAAuB,CAAC;QAC9E,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,4BAA4B,CAAuB,CAAC;QAC3F,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,sBAAsB,CAAuB,CAAC;QAChF,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAuB,CAAC;QAC3E,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,qBAAqB,CAAuB,CAAC;QAElF,MAAM,QAAQ,GAAG,OAAO,EAAE,YAAY,IAAI,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,WAAW,EAAE,YAAY,IAAI,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,MAAM,EAAE,YAAY,IAAI,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,EAAE,YAAY,IAAI,CAAC,CAAC;QAC1C,MAAM,UAAU,GAAG,SAAS,EAAE,YAAY,IAAI,CAAC,CAAC;QAGhD,MAAM,QAAQ,GAAG,QAAQ,CAAC;QAC1B,MAAM,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;QACpC,MAAM,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;QAC9C,MAAM,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;QAExD,IAAI,QAAQ,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,sBAAsB,EAAE,GAAG,QAAQ,IAAI,CAAC,CAAC;YACrE,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAChC,CAAC;QACD,IAAI,SAAS,KAAK,IAAI,CAAC,cAAc,EAAE,CAAC;YACtC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,uBAAuB,EAAE,GAAG,SAAS,IAAI,CAAC,CAAC;YACvE,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAClC,CAAC;QACD,IAAI,SAAS,KAAK,IAAI,CAAC,cAAc,EAAE,CAAC;YACtC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,uBAAuB,EAAE,GAAG,SAAS,IAAI,CAAC,CAAC;YACvE,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAClC,CAAC;QACD,IAAI,SAAS,KAAK,IAAI,CAAC,cAAc,EAAE,CAAC;YACtC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,uBAAuB,EAAE,GAAG,SAAS,IAAI,CAAC,CAAC;YACvE,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAClC,CAAC;QACD,IAAI,UAAU,KAAK,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC1C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,0BAA0B,EAAE,GAAG,UAAU,IAAI,CAAC,CAAC;YAC3E,IAAI,CAAC,iBAAiB,GAAG,UAAU,CAAC;QACtC,CAAC;IACH,CAAC;IAES,iBAAiB;QACzB,MAAM,IAAI,GAAI,IAAI,CAAC,IAAoB,CAAC,UAAU,CAAC;QACnD,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,mBAAmB,CAAuB,CAAC;QAC9E,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,4BAA4B,CAAuB,CAAC;QAC3F,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,sBAAsB,CAAuB,CAAC;QAChF,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAuB,CAAC;QAC3E,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,qBAAqB,CAAuB,CAAC;QAElF,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC7B,IAAI,CAAC,kBAAkB,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE;gBAChD,qBAAqB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC,CAAC;YAChE,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,GAAG,CAClB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAqB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC1F,CAAC;QACF,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC/C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACrE,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAClC,CAAC;CACF;AAED,SAAS,YAAY,CAAI,CAAiB,EAAE,CAAiB;IAC3D,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACpC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type { RenderItemFunction } from '@lit-labs/virtualizer/virtualize.js';\nimport { html, type ReactiveController } from 'lit';\nimport { type StyleInfo, styleMap } from 'lit/directives/style-map.js';\nimport { SENTINEL_NODE } from '../internal/constants.js';\nimport type { ActiveNode, ColumnConfiguration, GridHost, Keys } from '../internal/types.js';\nimport {\n applyColumnWidths,\n type ChromeTrack,\n getDisplayColumns,\n leadingChromeTracks,\n} from '../internal/utils.js';\nimport type { StateController } from './state.js';\n\nexport class GridDOMController<T extends object> implements ReactiveController {\n constructor(\n protected host: GridHost<T>,\n protected state: StateController<T>\n ) {\n this.host.addController(this);\n }\n\n #initialSize = () => {\n setTimeout(() => {\n this.recomputePinOffsets();\n this.recomputeStickyRowOffsets();\n });\n };\n\n #resizeObserver: ResizeObserver | null = null;\n #observedHeaders = new Set<Element>();\n #stickyRowObserver: ResizeObserver | null = null;\n #observedStickyRows = new Set<Element>();\n\n public get container() {\n // @ts-expect-error: protected member access\n return this.host.scrollContainer;\n }\n\n /**\n * Visual render order: `'start'`-pinned columns first, then unpinned, then\n * `'end'`-pinned. The user-supplied `columns` array is never mutated.\n */\n public get displayColumns(): Array<ColumnConfiguration<T>> {\n return getDisplayColumns(this.host.columns);\n }\n\n public columnSizes: StyleInfo = {};\n\n /**\n * The resolved inline-start (for `'start'` pin) or inline-end (for `'end'` pin)\n * pixel offset per pinned column key. Populated after layout by\n * {@link recomputePinOffsets}.\n */\n public pinOffsets = new Map<Keys<T>, number>();\n\n /**\n * Number of chrome rows above the body for `aria-rowindex`: an optional group\n * header row and the column header (always present). The filter panel is a\n * floating overlay rather than a table row, so it is not counted here.\n */\n protected get headerRowCount(): number {\n return this.host.columnGroupDepth + 1;\n }\n\n public rowRenderer: RenderItemFunction<T> = (data: T, index: number) => {\n const editingKey = this.#editingKey(data);\n // Body rows follow the chrome rows and any pinned-top rows in the\n // aria-rowindex sequence.\n const ariaRowOffset = this.headerRowCount + this.state.rowPin.pinnedRows.top.length;\n return html`\n <apex-grid-row\n part=\"row\"\n style=${styleMap({ ...this.columnSizes, ...this.getActiveRowStyles(index) })}\n .index=${index}\n .activeNode=${this.state.active}\n .data=${data}\n .columns=${this.displayColumns}\n .pinOffsets=${this.pinOffsets}\n .editingKey=${editingKey}\n .ariaRowOffset=${ariaRowOffset}\n .decorationVersion=${this.state.decorationVersion}\n .dataVersion=${this.state.dataVersion}\n .validationVersion=${this.state.editing.validationVersion}\n .dragging=${this.state.rowReorder.dragging === data}\n .grabbed=${this.state.rowReorder.grabbed === data}\n .coordinateHints=${Boolean(this.host.coordinateHints)}\n >\n </apex-grid-row>\n `;\n };\n\n /**\n * The column whose editor the row showing `data` renders, or `null`. Bound\n * to the edited record, never to a view index, so a view change (sort,\n * filter, paging, live data, pinning) cannot move the editor onto another\n * record.\n */\n #editingKey(data: T): Keys<T> | null {\n const editingCell = this.state.editing.activeCell;\n return editingCell && editingCell.data === data ? editingCell.columnKey : null;\n }\n\n /**\n * Renders a single pinned row for a sticky band. Reuses {@link ApexGridRow}\n * so selection / expansion / decoration / editing all work by data\n * reference, but pins a sentinel {@link ActiveNode} (pinned rows are\n * presentation, selection and pointer-edit surfaces in v1, never the\n * keyboard-active cell).\n *\n * @param localIndex - position within the band (drives the active sentinel id).\n * @param ariaRowOffset - so `aria-rowindex` continues the unified sequence.\n */\n public pinnedRowRenderer(data: T, localIndex: number, ariaRowOffset: number) {\n return html`\n <apex-grid-row\n part=\"row pinned-row\"\n style=${styleMap(this.columnSizes)}\n .index=${localIndex}\n .activeNode=${SENTINEL_NODE as ActiveNode<T>}\n .data=${data}\n .columns=${this.displayColumns}\n .pinOffsets=${this.pinOffsets}\n .editingKey=${this.#editingKey(data)}\n .ariaRowOffset=${ariaRowOffset}\n .decorationVersion=${this.state.decorationVersion}\n .dataVersion=${this.state.dataVersion}\n .validationVersion=${this.state.editing.validationVersion}\n .coordinateHints=${Boolean(this.host.coordinateHints)}\n >\n </apex-grid-row>\n `;\n }\n\n public async hostConnected() {\n this.setGridColumnSizes();\n // Wait for the initial paint of the virtualizer, then measure the pinned\n // columns and sticky rows it laid out.\n await this.host.updateComplete;\n this.#initialSize();\n if (typeof ResizeObserver !== 'undefined' && !this.#hostWidthObserver) {\n this.#hostWidthObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => this.recomputeHostWidth());\n });\n this.#hostWidthObserver.observe(this.host as HTMLElement);\n }\n this.recomputeHostWidth();\n }\n\n public hostUpdate(): void {\n this.setGridColumnSizes();\n }\n\n public hostUpdated(): void {\n this.recomputePinOffsets();\n this.observeHeaderCells();\n this.recomputeStickyRowOffsets();\n this.observeStickyRows();\n }\n\n public hostDisconnected(): void {\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = null;\n this.#observedHeaders.clear();\n this.#stickyRowObserver?.disconnect();\n this.#stickyRowObserver = null;\n this.#observedStickyRows.clear();\n this.#hostWidthObserver?.disconnect();\n this.#hostWidthObserver = null;\n }\n\n /**\n * Writes the grid host's `clientWidth` into `--apex-host-width`. Used by the\n * toolbar and paginator to clamp their width to the visible viewport so\n * horizontal scrolling doesn't drag them off-screen.\n */\n public recomputeHostWidth(): void {\n const host = this.host as HTMLElement;\n const width = host.clientWidth;\n if (width === this.#lastHostWidth) return;\n host.style.setProperty('--apex-host-width', `${width}px`);\n this.#lastHostWidth = width;\n }\n\n protected setGridColumnSizes() {\n const chrome = leadingChromeTracks(this.state);\n this.columnSizes = applyColumnWidths(this.displayColumns, chrome);\n this.#publishChromeOffsets(chrome);\n }\n\n /** Total width (CSS px) of the leading chrome tracks; start pins stack after it. */\n #chromeWidth = 0;\n\n /**\n * Writes each leading chrome cell's sticky inline-start offset into\n * `--apex-chrome-offset-<track>` on the host (the stylesheets of the header,\n * group header and body rows read it), so the gutter, grip, checkbox and\n * chevron stay side by side during a horizontal scroll instead of all\n * sticking at 0. Every track is written, absent ones as 0, so a grid nested\n * in another grid's row never inherits its parent's offsets. Written on\n * every update, not deduped, so they come back after something replaces\n * the host's style attribute (a string style binding, setAttribute).\n */\n #publishChromeOffsets(chrome: Array<[ChromeTrack, number]>): void {\n const offsets: Record<ChromeTrack, number> = {\n 'row-number': 0,\n reorder: 0,\n selection: 0,\n expansion: 0,\n };\n let accum = 0;\n for (const [track, width] of chrome) {\n offsets[track] = accum;\n accum += width;\n }\n this.#chromeWidth = accum;\n for (const [track, offset] of Object.entries(offsets)) {\n this.host.style.setProperty(`--apex-chrome-offset-${track}`, `${offset}px`);\n }\n }\n\n public getActiveRowStyles(index: number): StyleInfo {\n const { row } = this.state.active;\n return row === index ? { 'z-index': '3' } : {};\n }\n\n /**\n * Measures the rendered widths of pinned header cells and writes cumulative\n * inline-start / inline-end pixel offsets into {@link pinOffsets}. Called after\n * each grid update and whenever a header cell is resized.\n */\n public recomputePinOffsets(): void {\n // @ts-expect-error - protected member access\n const headerRow = this.host.headerRow as\n | {\n headers?: Array<{\n column: ColumnConfiguration<T>;\n getBoundingClientRect: () => DOMRect;\n }>;\n }\n | undefined;\n if (!headerRow?.headers) return;\n\n const next = new Map<Keys<T>, number>();\n const widths = new Map<Keys<T>, number>();\n // Rects are visual px (after any ancestor transform) but the offsets are\n // applied as CSS px, so divide out the scale. Rects rather than\n // offsetWidth keep subpixel widths; offsetWidth is rounded to whole px, so\n // a difference under 1px is that rounding, not a transform.\n const host = this.host as HTMLElement;\n const visual = host.getBoundingClientRect().width;\n const layout = host.offsetWidth;\n const scale = visual && layout && Math.abs(visual - layout) >= 1 ? visual / layout : 1;\n for (const header of headerRow.headers) {\n widths.set(header.column.key as Keys<T>, header.getBoundingClientRect().width / scale);\n }\n\n // Start pins stack after the leading chrome cells, which stick first.\n let leftAccum = this.#chromeWidth;\n for (const column of this.displayColumns) {\n if (column.hidden) continue;\n if (column.pinned !== 'start') break;\n next.set(column.key as Keys<T>, leftAccum);\n leftAccum += widths.get(column.key as Keys<T>) ?? 0;\n }\n\n let rightAccum = 0;\n for (let i = this.displayColumns.length - 1; i >= 0; i--) {\n const column = this.displayColumns[i];\n if (column.hidden) continue;\n if (column.pinned !== 'end') break;\n next.set(column.key as Keys<T>, rightAccum);\n rightAccum += widths.get(column.key as Keys<T>) ?? 0;\n }\n\n if (!offsetsEqual(this.pinOffsets, next)) {\n this.pinOffsets = next;\n this.host.requestUpdate();\n }\n }\n\n protected observeHeaderCells(): void {\n // @ts-expect-error - protected member access\n const headerRow = this.host.headerRow as { headers?: Array<Element> } | undefined;\n if (!headerRow?.headers) return;\n\n if (!this.#resizeObserver) {\n this.#resizeObserver = new ResizeObserver(() => {\n // Defer to a new frame so any layout writes can't synchronously feed back\n // into this observer (which makes the browser raise the benign\n // \"ResizeObserver loop completed\" warning).\n requestAnimationFrame(() => this.recomputePinOffsets());\n });\n }\n\n const next = new Set<Element>(headerRow.headers);\n for (const element of this.#observedHeaders) {\n if (!next.has(element)) this.#resizeObserver.unobserve(element);\n }\n for (const element of next) {\n if (!this.#observedHeaders.has(element)) this.#resizeObserver.observe(element);\n }\n this.#observedHeaders = next;\n }\n\n #lastGroupTop = -1;\n #lastHeaderTop = -1;\n #lastFilterTop = -1;\n #lastPinnedTop = -1;\n #lastPinnedBottom = -1;\n #lastHostWidth = -1;\n #hostWidthObserver: ResizeObserver | null = null;\n\n /**\n * Writes the cumulative heights of the sticky chrome rows into CSS custom\n * properties used for their `inset-block-start` / `inset-block-end` offsets.\n * The toolbar is at `top: 0`; the header sits below it\n * (`--apex-row-top-header`), the filter below the header\n * (`--apex-row-top-filter`), and the pinned-top band below the filter\n * (`--apex-row-top-pinned`). The pinned-bottom band sticks above the\n * paginator (`--apex-row-bottom-pinned`). Writes are skipped when values are\n * unchanged so the ResizeObserver feedback loop terminates.\n */\n public recomputeStickyRowOffsets(): void {\n const root = (this.host as HTMLElement).shadowRoot;\n if (!root) return;\n const toolbar = root.querySelector('apex-grid-toolbar') as HTMLElement | null;\n const groupHeader = root.querySelector('apex-grid-group-header-row') as HTMLElement | null;\n const header = root.querySelector('apex-grid-header-row') as HTMLElement | null;\n const filter = root.querySelector('apex-filter-row') as HTMLElement | null;\n const paginator = root.querySelector('apex-grid-paginator') as HTMLElement | null;\n\n const toolbarH = toolbar?.offsetHeight ?? 0;\n const groupH = groupHeader?.offsetHeight ?? 0;\n const headerH = header?.offsetHeight ?? 0;\n const filterH = filter?.offsetHeight ?? 0;\n const paginatorH = paginator?.offsetHeight ?? 0;\n // The group header (when present) sits below the toolbar; the column header\n // sits below the group header; filter below header; pinned-top below filter.\n const groupTop = toolbarH;\n const headerTop = toolbarH + groupH;\n const filterTop = toolbarH + groupH + headerH;\n const pinnedTop = toolbarH + groupH + headerH + filterH;\n\n if (groupTop !== this.#lastGroupTop) {\n this.host.style.setProperty('--apex-row-top-group', `${groupTop}px`);\n this.#lastGroupTop = groupTop;\n }\n if (headerTop !== this.#lastHeaderTop) {\n this.host.style.setProperty('--apex-row-top-header', `${headerTop}px`);\n this.#lastHeaderTop = headerTop;\n }\n if (filterTop !== this.#lastFilterTop) {\n this.host.style.setProperty('--apex-row-top-filter', `${filterTop}px`);\n this.#lastFilterTop = filterTop;\n }\n if (pinnedTop !== this.#lastPinnedTop) {\n this.host.style.setProperty('--apex-row-top-pinned', `${pinnedTop}px`);\n this.#lastPinnedTop = pinnedTop;\n }\n if (paginatorH !== this.#lastPinnedBottom) {\n this.host.style.setProperty('--apex-row-bottom-pinned', `${paginatorH}px`);\n this.#lastPinnedBottom = paginatorH;\n }\n }\n\n protected observeStickyRows(): void {\n const root = (this.host as HTMLElement).shadowRoot;\n if (!root) return;\n const toolbar = root.querySelector('apex-grid-toolbar') as HTMLElement | null;\n const groupHeader = root.querySelector('apex-grid-group-header-row') as HTMLElement | null;\n const header = root.querySelector('apex-grid-header-row') as HTMLElement | null;\n const filter = root.querySelector('apex-filter-row') as HTMLElement | null;\n const paginator = root.querySelector('apex-grid-paginator') as HTMLElement | null;\n\n if (!this.#stickyRowObserver) {\n this.#stickyRowObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => this.recomputeStickyRowOffsets());\n });\n }\n\n const next = new Set<Element>(\n [toolbar, groupHeader, header, filter, paginator].filter((el): el is HTMLElement => !!el)\n );\n for (const element of this.#observedStickyRows) {\n if (!next.has(element)) this.#stickyRowObserver.unobserve(element);\n }\n for (const element of next) {\n if (!this.#observedStickyRows.has(element)) this.#stickyRowObserver.observe(element);\n }\n this.#observedStickyRows = next;\n }\n}\n\nfunction offsetsEqual<K>(a: Map<K, number>, b: Map<K, number>): boolean {\n if (a.size !== b.size) return false;\n for (const [key, value] of a) {\n if (b.get(key) !== value) return false;\n }\n return true;\n}\n"]}
|