argus-table 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +1 -1
  2. package/dist/argus-column.js +24 -1
  3. package/dist/argus-column.js.map +1 -1
  4. package/dist/argus-table.js +1024 -165
  5. package/dist/argus-table.js.map +1 -1
  6. package/dist/cdn/argus-table.js +74 -50
  7. package/dist/cdn/argus-table.js.map +1 -1
  8. package/dist/controllers/auto-width.js +11 -0
  9. package/dist/controllers/auto-width.js.map +1 -1
  10. package/dist/controllers/column-window.js +139 -0
  11. package/dist/controllers/column-window.js.map +1 -0
  12. package/dist/controllers/data-controller.js +9 -4
  13. package/dist/controllers/data-controller.js.map +1 -1
  14. package/dist/controllers/plugins.js +102 -0
  15. package/dist/controllers/plugins.js.map +1 -0
  16. package/dist/controllers/reorder-drag.js +9 -10
  17. package/dist/controllers/reorder-drag.js.map +1 -1
  18. package/dist/controllers/row-measure.js +121 -0
  19. package/dist/controllers/row-measure.js.map +1 -0
  20. package/dist/controllers/virtual-controller.js +311 -10
  21. package/dist/controllers/virtual-controller.js.map +1 -1
  22. package/dist/core/src/columns/column-order.js +14 -10
  23. package/dist/core/src/columns/column-order.js.map +1 -1
  24. package/dist/core/src/columns/resolve-columns.js +18 -4
  25. package/dist/core/src/columns/resolve-columns.js.map +1 -1
  26. package/dist/core/src/data/page-cache.js +4 -0
  27. package/dist/core/src/data/page-cache.js.map +1 -1
  28. package/dist/core/src/filters/filter.js +185 -0
  29. package/dist/core/src/filters/filter.js.map +1 -0
  30. package/dist/core/src/state/selection.js +70 -0
  31. package/dist/core/src/state/selection.js.map +1 -0
  32. package/dist/core/src/table/create-table.js +239 -64
  33. package/dist/core/src/table/create-table.js.map +1 -1
  34. package/dist/core/src/table/filtered-row-model.js +48 -0
  35. package/dist/core/src/table/filtered-row-model.js.map +1 -0
  36. package/dist/core/src/table/sorted-row-model.js +13 -2
  37. package/dist/core/src/table/sorted-row-model.js.map +1 -1
  38. package/dist/core/src/virtual/column-window.js +72 -0
  39. package/dist/core/src/virtual/column-window.js.map +1 -0
  40. package/dist/core/src/virtual/row-pool.js +2 -1
  41. package/dist/core/src/virtual/row-pool.js.map +1 -1
  42. package/dist/core/src/virtual/row-sizes.js +156 -0
  43. package/dist/core/src/virtual/row-sizes.js.map +1 -0
  44. package/dist/core/src/virtual/scroll-scale.js +41 -3
  45. package/dist/core/src/virtual/scroll-scale.js.map +1 -1
  46. package/dist/custom-elements.json +1273 -45
  47. package/dist/events.js +9 -1
  48. package/dist/events.js.map +1 -1
  49. package/dist/index.d.ts +609 -74
  50. package/dist/index.js +3 -2
  51. package/dist/interactive.js +22 -0
  52. package/dist/interactive.js.map +1 -0
  53. package/dist/max-height.js +22 -8
  54. package/dist/max-height.js.map +1 -1
  55. package/dist/render/body.js +47 -7
  56. package/dist/render/body.js.map +1 -1
  57. package/dist/render/cells.js +14 -11
  58. package/dist/render/cells.js.map +1 -1
  59. package/dist/render/content-directive.js +115 -0
  60. package/dist/render/content-directive.js.map +1 -0
  61. package/dist/render/content.js +20 -9
  62. package/dist/render/content.js.map +1 -1
  63. package/dist/render/header.js +24 -5
  64. package/dist/render/header.js.map +1 -1
  65. package/dist/render/pinned-rows.js +1 -1
  66. package/dist/render/pinned-rows.js.map +1 -1
  67. package/dist/styles/base.js +1 -1
  68. package/dist/styles/base.js.map +1 -1
  69. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"argus-table.js","names":["_decorate"],"sources":["../src/argus-table.ts"],"sourcesContent":["import {\n LitElement,\n html,\n nothing,\n type CSSResultGroup,\n type PropertyValues,\n type TemplateResult,\n} from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport {\n controllable,\n RowLayout,\n type ColumnReorderDetail,\n type ColumnResizeDetail,\n type ColumnView,\n type GridRow,\n type TableModel,\n} from '@argus-table/core';\nimport { announce } from './announce.js';\nimport { AutoWidths, measureColumns } from './controllers/auto-width.js';\nimport { ColumnChildrenController } from './controllers/column-children.js';\nimport { DataController } from './controllers/data-controller.js';\nimport { PinScrollController } from './controllers/pin-scroll-controller.js';\nimport {\n canStartReorder,\n dropTarget,\n startReorderDrag,\n type DropSlot,\n} from './controllers/reorder-drag.js';\nimport { startResizeDrag } from './controllers/resize-drag.js';\nimport { TableController } from './controllers/table-controller.js';\nimport { VirtualController, type VirtualWindow } from './controllers/virtual-controller.js';\nimport {\n CELL_CLICK,\n COLUMN_REORDER,\n COLUMN_RESIZE,\n fire,\n LOAD_ERROR,\n RANGE_CHANGE,\n ROW_CLICK,\n SORT_CHANGE,\n} from './events.js';\nimport { bodyCap, watchMaxElementHeight } from './max-height.js';\nimport { renderBody, type ActiveCell, type Loading } from './render/body.js';\nimport { renderLightDom } from './render/cells.js';\nimport { renderHeader, type HeaderDrag } from './render/header.js';\nimport { renderPinnedRows } from './render/pinned-rows.js';\nimport { baseStyles } from './styles/base.js';\nimport type {\n CellContent,\n ColumnDef,\n ColumnOrderState,\n ColumnSizingState,\n DataSource,\n Density,\n PinnedRows,\n SortState,\n} from './types.js';\n\n/**\n * The host carries the grid role, so rows rendered in the shadow root become\n * its children in the accessibility tree. ElementInternals sets the default;\n * `connectedCallback` also adds a `role` attribute, because tools such as\n * axe-core can't see the ElementInternals role. A `role` the page sets wins.\n */\nfunction attachGridInternals(host: HTMLElement): ElementInternals {\n const internals = host.attachInternals();\n internals.role = 'grid';\n return internals;\n}\n\n/**\n * The sortable column a header click came from, if any. Works for slotted content\n * too. Clicks on a resize handle never sort, so a click that ends a drag doesn't.\n */\nfunction sortColumnOf(event: Event): string | undefined {\n for (const target of event.composedPath()) {\n if (!(target instanceof HTMLElement)) continue;\n if (target.dataset.resizeCol !== undefined) return undefined;\n if (target.dataset.sortCol !== undefined) return target.dataset.sortCol;\n if (target.getAttribute('part') === 'header-row') return undefined;\n }\n return undefined;\n}\n\nconst RESIZE_STEP = 10;\n\n/**\n * The cell holding the grid's single tab stop: a row (its section, and its index\n * there: in the row model for the body, in its list for a pinned row) and a\n * column. `rowId` keeps it on the same body row when the order changes.\n */\ninterface Active extends GridRow {\n rowId: string | undefined;\n col: string;\n}\n\nconst HEADER: GridRow = { section: 'header', index: 0 };\n\n/** Where the rows sit in the grid: header, pinned top, body, pinned bottom. */\nfunction layoutOf<T>(model: TableModel<T, CellContent>): RowLayout {\n return new RowLayout(model.pinnedCount('top'), model.rowCount, model.pinnedCount('bottom'));\n}\n\n/** The grid cell or column header an element is, if any. */\nfunction gridCell(target: EventTarget): HTMLElement | undefined {\n if (!(target instanceof HTMLElement) || target.dataset.col === undefined) return undefined;\n const role = target.getAttribute('role');\n return role === 'gridcell' || role === 'columnheader' ? target : undefined;\n}\n\n/** The grid row a rendered row element is, from its `aria-rowindex`. */\nfunction gridRowOf(row: Element | null, layout: RowLayout): GridRow | undefined {\n const index = row?.getAttribute('aria-rowindex');\n return index ? layout.fromAriaRowIndex(Number(index)) : undefined;\n}\n\n/**\n * The pinned edge's shadow, drawn once per side over the scroller rather than\n * per row: a shadow on every pinned cell repaints on every scroll frame. It\n * covers the pinned columns and casts `--argus-pinned-shadow` onto the rest;\n * PinScrollController sizes it to the visible area.\n */\nfunction pinShadow(side: 'start' | 'end', width: number, rows: number, rowPx: number) {\n if (width === 0) return nothing;\n return html`<div\n class=\"pin-shadow\"\n data-side=${side}\n aria-hidden=\"true\"\n style=${styleMap({\n inlineSize: `${String(width)}px`,\n '--_content-h': `${String((rows + 1) * rowPx)}px`,\n })}\n ></div>`;\n}\n\n/** CSS grid track for a column: fixed px, or a flex share with the min width as floor. */\nfunction track<T>(column: ColumnView<T, CellContent>): string {\n return column.flex === undefined\n ? `${String(column.width)}px`\n : `minmax(${String(column.minWidth)}px, ${String(column.flex)}fr)`;\n}\n\n/**\n * A virtualized data table.\n *\n * Set `columns`, and `data` or `dataSource`, as properties. Columns can also be\n * written as `<argus-column>` children; a non-empty `columns` wins over them.\n * Header and cell content is rendered into the element's light DOM and slotted\n * into the cells, so page CSS and the page's own components work inside cells.\n *\n * Any number of rows scrolls to the end. Browsers limit an element's height\n * (about 800k rows of 40 px in Chromium and Safari, 400k in Firefox), so a taller\n * body renders shorter and its scroll position is scaled onto the rows: the\n * scrollbar still spans every row, and a wheel step covers a few more of them.\n * Use `scrollToRow()` rather than setting the scroll container's `scrollTop`.\n *\n * @summary Data table with pinned rows and columns and infinite loading.\n *\n * @fires {CustomEvent<SortChangeDetail>} argus-sort-change - A sortable header was clicked, or activated with Enter or Space. `detail: { sorting }`: the new order, or the proposed one when `sorting` is controlled.\n * @fires {CustomEvent<ColumnResizeDetail>} argus-column-resize - A column was resized: by dragging its handle, with Alt+Arrow on its header, by a double-click on its handle (fit to content) or by `autosizeColumns()`. `detail: { columnId, width, sizing }`: the new widths, or the proposed ones when `columnSizing` is controlled. Fires on every frame of a drag, and once per column that `autosizeColumns()` changes.\n * @fires {CustomEvent<ColumnReorderDetail>} argus-column-reorder - A column was moved: by dragging its header, or with Alt+Shift+Arrow on its focused header. Columns move within their own group (start-pinned, scrolling, end-pinned). `detail: { columnId, order }`: the new order, or the proposed one when `columnOrder` is controlled. Fires once per move, on drop.\n * @fires {CustomEvent<CellClickDetail<T>>} argus-cell-click - A body or pinned-row cell was clicked, or Enter was pressed on it. `detail: { row, columnId, value, pinned? }`; `pinned` is `'top'` or `'bottom'` for a pinned row. Fires before `argus-row-click`.\n * @fires {CustomEvent<RowClickDetail<T>>} argus-row-click - A body or pinned row was clicked, or Enter was pressed on one of its cells. `detail: { row, rowId, index, pinned? }`; for a pinned row, `index` is its index in its list.\n * @fires {CustomEvent<RangeChangeDetail>} argus-range-change - The visible rows changed. `detail: { start, end }` (row indices, inclusive).\n * @fires {CustomEvent<LoadErrorDetail>} argus-load-error - A `dataSource` page failed to load: `getRows()` rejected or threw. `detail: { error, start, end }` (`end` exclusive). The rows show a Retry button.\n *\n * @slot empty - Shown instead of the body when there are no rows. Default: \"No rows\".\n *\n * @csspart table - The scroll container that holds header and body.\n * @csspart header - The sticky header row group.\n * @csspart header-row - The header row.\n * @csspart header-cell - Every header cell.\n * @csspart header-cell-sorted - The header of the sorted column. The direction is in `aria-sort`.\n * @csspart header-cell-dragging - Added to `header-cell` on the header being dragged to a new position.\n * @csspart drop-indicator - The line on the edge of the header where a dragged column would land.\n * @csspart resize-handle - The drag handle on the inline-end edge of a resizable column's header. A double-click fits the column to its content.\n * @csspart body - The row group holding the rendered body rows.\n * @csspart row - Every body row.\n * @csspart row-even - Body rows with an even index (0-based).\n * @csspart row-odd - Body rows with an odd index.\n * @csspart row-loading - Body rows whose `dataSource` page hasn't loaded yet, or failed.\n * @csspart row-pinned - Every row from `pinnedRows`, on either side. Also has `row`, but no `row-even`/`row-odd`.\n * @csspart row-pinned-top - The rows pinned below the header.\n * @csspart row-pinned-bottom - The rows pinned to the bottom.\n * @csspart cell-pinned-row - Every cell of a pinned row (next to `cell`).\n * @csspart cell - Every body cell.\n * @csspart cell-sorted - Body cells in the sorted column.\n * @csspart cell-pinned - Body cells in a pinned column, on either side.\n * @csspart cell-pinned-edge - The pinned body cell next to the scrolling columns (one per pinned side).\n * @csspart skeleton - The placeholder bar in each cell of a row that is still loading.\n * @csspart skeleton-error - Added to `skeleton` in a row whose page failed to load.\n * @csspart retry - The Retry button in the first cell of a failed page's first visible row.\n * @csspart empty - The empty-state container.\n *\n * @cssprop [--argus-bg=Canvas] - Background of the table and rows.\n * @cssprop [--argus-fg=CanvasText] - Text colour.\n * @cssprop [--argus-font=inherit] - Font shorthand for the table.\n * @cssprop [--argus-header-bg] - Header background.\n * @cssprop [--argus-header-fg=inherit] - Header text colour.\n * @cssprop [--argus-border-color] - Colour of the row borders.\n * @cssprop [--argus-border-width=1px] - Width of the row borders.\n * @cssprop [--argus-outline=none] - Border around the whole table, as a `border` shorthand (`1px solid …`). Inside the element's size.\n * @cssprop [--argus-radius=0] - Corner radius of the table. Header, rows and pinned columns are clipped to it.\n * @cssprop [--argus-row-height] - Height of a row. Default per density: 32px, 40px, 52px.\n * @cssprop [--argus-cell-padding-inline] - Inline padding of cells. Default per density: 8px, 12px, 16px.\n * @cssprop [--argus-row-stripe-bg] - Background of odd rows. Default: no stripes.\n * @cssprop [--argus-pinned-shadow] - Shadow on the pinned edge, as a `box-shadow` falling toward the end side (`4px 0 6px -4px …`). Mirrored for the end edge and in RTL; `none` removes it.\n * @cssprop [--argus-resize-handle-color] - Colour of the resize handle's line, shown on hover, focus and drag.\n * @cssprop [--argus-focus-ring=2px solid Highlight] - Outline of the focused header or cell.\n * @cssprop [--argus-drop-indicator-color=Highlight] - Colour of the line that marks where a dragged column would land.\n * @cssprop [--argus-row-hover-bg] - Background of the hovered row. Default: no change.\n * @cssprop [--argus-pinned-row-bg=var(--argus-bg)] - Background of the pinned rows, pinned columns included.\n * @cssprop [--argus-skeleton-bg] - Colour of the skeleton bars in rows still loading. Default: the text colour at low opacity.\n * @cssprop [--argus-row-selected-bg] - Reserved for row selection, which comes after v0.1. The table doesn't read it yet.\n */\n@customElement('argus-table')\nexport class ArgusTable<T = unknown> extends LitElement {\n static override styles: CSSResultGroup = baseStyles;\n\n /**\n * Column definitions. Property only: functions can't be attributes. While empty,\n * the table reads its `<argus-column>` children instead. `null` or `undefined`\n * means `[]`.\n */\n @property({ attribute: false })\n get columns(): readonly ColumnDef<T>[] {\n return this.#columnsProp;\n }\n set columns(value: readonly ColumnDef<T>[] | null | undefined) {\n // Framework bindings set `undefined` when a prop goes away.\n this.#columnsProp = value ?? [];\n }\n\n /**\n * The rows to show. Replace the array to update; changes inside it aren't\n * detected. `null` or `undefined` means `[]`.\n */\n @property({ attribute: false })\n get data(): readonly T[] {\n return this.#dataProp;\n }\n set data(value: readonly T[] | null | undefined) {\n this.#dataProp = value ?? [];\n }\n\n /**\n * Loads rows page by page as they scroll into view, instead of `data`:\n * `{ getRows({ start, end, sorting, signal }), pageSize? }`, where `end` is\n * exclusive and `getRows` resolves to `{ rows, total? }`. Without a `total`,\n * the table grows as pages arrive and a short page marks the end. Sorting\n * happens on the server: a new order reloads from the top. While set, it wins\n * over `data`. Replace the object to change `getRows` or `pageSize`.\n */\n @property({ attribute: false })\n dataSource?: DataSource<T>;\n\n /**\n * Rows fixed below the header (`top`) and at the bottom of the view (`bottom`),\n * such as a totals row: `{ top?: T[], bottom?: T[] }`. They are separate\n * objects, not rows of `data`: columns read them the same way, but they are\n * never sorted and work the same with a `dataSource`. A `cell` function gets\n * `pinned: 'top' | 'bottom'` in its context. Replace the object to update.\n */\n @property({ attribute: false })\n pinnedRows?: PinnedRows<T>;\n\n /** Returns a stable id for a row. Default: the row's index (in `data`, or among all `dataSource` rows). */\n @property({ attribute: false })\n getRowId?: (row: T, index: number) => string;\n\n /** Row height in px. Unset: the density (or the `--argus-row-height` token) decides. */\n @property({ attribute: 'row-height', type: Number })\n rowHeight?: number;\n\n /** Row density: `compact`, `comfortable` or `spacious`. */\n @property({ reflect: true })\n density: Density = 'comfortable';\n\n /** Rows rendered above and below the visible ones. `null` or `undefined` means the default, 6. */\n @property({ type: Number })\n get overscan(): number {\n return this.#overscan;\n }\n set overscan(value: number | null | undefined) {\n this.#overscan = value ?? 6;\n }\n\n /**\n * The sort order, e.g. `[{ id: 'total', desc: true }]`; `[]` when unsorted. Unset,\n * the table keeps it itself and header clicks change it. Once set, it is\n * controlled: a click only fires `argus-sort-change` with the proposed order,\n * and nothing changes until you set the property. Set `undefined` to hand it back.\n */\n @property({ attribute: false })\n get sorting(): SortState {\n return this.#sorting.value;\n }\n set sorting(value: SortState | undefined) {\n // Lit wraps this accessor and requests the update with the old value.\n this.#sorting.set(value);\n }\n\n /**\n * Resized widths in px by column id, e.g. `{ name: 240 }`. A resized flex column\n * becomes fixed. Uncontrolled until set, like `sorting`: once set, a resize only\n * fires `argus-column-resize` with the proposed widths. `undefined` hands it back.\n */\n @property({ attribute: false })\n get columnSizing(): ColumnSizingState {\n return this.#sizing.value;\n }\n set columnSizing(value: ColumnSizingState | undefined) {\n this.#sizing.set(value);\n }\n\n /**\n * The column order: column ids as the table shows them, e.g.\n * `['id', 'total', 'customer']`. `[]` (the default) keeps the order of `columns`.\n * Each pin group (start-pinned, scrolling, end-pinned) takes its columns in this\n * order; unknown ids are ignored and columns it doesn't list follow the listed\n * ones of their group. After a move it holds every column id. Uncontrolled\n * until set, like `sorting`: once set, a move only fires `argus-column-reorder`\n * with the proposed order. `undefined` hands it back.\n */\n @property({ attribute: false })\n get columnOrder(): ColumnOrderState {\n return this.#order.value;\n }\n set columnOrder(value: ColumnOrderState | undefined) {\n this.#order.set(value);\n }\n\n #columnsProp: readonly ColumnDef<T>[] = [];\n #dataProp: readonly T[] = [];\n #overscan = 6;\n readonly #sorting = controllable<SortState>([]);\n readonly #sizing = controllable<ColumnSizingState>({});\n readonly #order = controllable<ColumnOrderState>([]);\n /** Moves the table applied itself, by column; their events fire once the update is done. */\n readonly #appliedReorders = new Map<string, ColumnReorderDetail>();\n /** The header being dragged to a new position, if any. */\n #drag: HeaderDrag | undefined;\n /** A move from the keyboard, announced once it has rendered: the column and its old position. */\n #announceMove: { id: string; from: number } | undefined;\n /** Resizes the table applied itself, by column; their events fire once the update is done. */\n readonly #appliedResizes = new Map<string, ColumnResizeDetail>();\n /** Measured widths of `width: 'auto'` columns. */\n readonly #autoWidths = new AutoWidths(() => {\n this.requestUpdate();\n });\n /** The auto widths last passed to the model; a change re-measures the pinned columns' offsets. */\n #pushedAutoWidths: ColumnSizingState | undefined;\n #autoWidthsChanged = false;\n /** A sort the table applied itself; its event fires once the update is done. */\n #appliedSort: SortState | undefined;\n readonly #internals = attachGridInternals(this);\n readonly #table = new TableController<T>();\n readonly #children = new ColumnChildrenController<T>(this);\n /** The columns last passed to the model: `columns`, or the `<argus-column>` children. */\n #columns: readonly ColumnDef<T>[] = [];\n #columnsChanged = false;\n #warnedColumns = false;\n /** End of the light-DOM part holding cell content, so later children stay outside it. */\n #contentEnd: Comment | undefined;\n readonly #data = new DataController<T>(this);\n /** Scroll back to the top after the update (a new sort order for a data source). */\n #scrollToTop = false;\n // Looked up lazily: the virtualizer's hostUpdated runs before firstUpdated.\n readonly #virtual = new VirtualController(this, () =>\n this.renderRoot.querySelector<HTMLElement>('[part~=\"table\"]'),\n );\n readonly #pinScroll = new PinScrollController(this, () =>\n this.renderRoot.querySelector<HTMLElement>('[part~=\"table\"]'),\n );\n #rowPx = 40;\n #probeObserver?: ResizeObserver;\n #window: VirtualWindow = { rows: [], totalSize: 0, range: null };\n #active: Active | undefined;\n /** Move focus to the active cell after the next update (keyboard navigation). */\n #focusPending = false;\n #lastRange = '';\n #unwatchMaxHeight: (() => void) | undefined;\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (!this.hasAttribute('role')) this.setAttribute('role', 'grid');\n if (this.hasUpdated) this.#observeProbe();\n // A zoom change changes the tallest body the engine renders.\n this.#unwatchMaxHeight = watchMaxElementHeight(() => {\n this.requestUpdate();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#probeObserver?.disconnect();\n this.#unwatchMaxHeight?.();\n this.#unwatchMaxHeight = undefined;\n }\n\n /**\n * `columns` when it has any, otherwise the `<argus-column>` children. Keeps its\n * identity while neither changes, so the model is only rebuilt on a change.\n */\n #effectiveColumns(): readonly ColumnDef<T>[] {\n if (this.columns.length === 0) return this.#children.defs;\n if (!this.#warnedColumns && this.#children.present) {\n this.#warnedColumns = true;\n console.warn(\n 'argus-table: the columns property is set, so <argus-column> children are ignored.',\n );\n }\n return this.columns;\n }\n\n /**\n * The node the light-DOM content is rendered before. Lit's part then ends there,\n * so children appended later (an `<argus-column>`) never land inside it. If the\n * marker was removed (say by `innerHTML`), a new one starts a fresh part.\n */\n #lightDomEnd(): Comment {\n if (this.#contentEnd?.parentNode !== this) {\n this.#contentEnd = document.createComment('');\n this.append(this.#contentEnd);\n }\n return this.#contentEnd;\n }\n\n /**\n * With a `dataSource`, drops every loaded page and loads the rows in view\n * again, keeping the scroll position. With `data`, re-renders the cells (after\n * changing row objects in place). Resolves once the table has re-rendered;\n * reloaded rows arrive as their pages load.\n */\n async refresh(): Promise<void> {\n this.#data.refresh();\n this.requestUpdate();\n await this.updateComplete;\n }\n\n /**\n * Fits columns to their content: the header, the pinned rows and the body rows\n * rendered now (rows out of view aren't measured). It resizes them like a drag\n * would, so `argus-column-resize` fires for each column that changes, and with a\n * controlled `columnSizing` nothing changes until you set it. Without `ids`, fits\n * every resizable column; columns with `resizable: false` keep their width.\n * Resolves once the table has re-rendered.\n */\n async autosizeColumns(ids?: readonly string[]): Promise<void> {\n await this.updateComplete;\n const targets = this.#table.model.columns\n .filter((c) => c.resizable && (ids === undefined || ids.includes(c.id)))\n .map((c) => c.id);\n this.#requestResizes(measureColumns(this.renderRoot, targets));\n await this.updateComplete;\n }\n\n /** Scrolls so that the row at `index` (in the current row order) is at the top. */\n async scrollToRow(index: number): Promise<void> {\n await this.updateComplete;\n this.#virtual.scrollToIndex(index);\n await this.updateComplete;\n }\n\n protected override willUpdate(changed: PropertyValues<this>): void {\n const columns = this.#effectiveColumns();\n this.#columnsChanged = columns !== this.#columns;\n this.#columns = columns;\n if (changed.has('dataSource') || changed.has('sorting') || changed.has('getRowId')) {\n this.#data.configure({\n source: this.dataSource,\n sorting: this.#sorting.value,\n getRowId: this.getRowId,\n });\n // A new order starts over from the first row, so show it.\n if (this.dataSource && this.hasUpdated && changed.has('sorting')) {\n this.#scrollToTop = !changed.has('dataSource');\n }\n }\n if (\n this.#columnsChanged ||\n changed.has('data') ||\n changed.has('getRowId') ||\n changed.has('sorting') ||\n changed.has('columnSizing') ||\n changed.has('columnOrder') ||\n changed.has('pinnedRows')\n ) {\n if (this.#columnsChanged) {\n this.#autoWidths.sync(columns.filter((c) => c.width === 'auto').map((c) => c.id));\n }\n this.#table.update({\n columns,\n data: this.data,\n getRowId: this.getRowId,\n sorting: this.#sorting.value,\n columnSizing: this.#sizing.value,\n columnOrder: this.#order.value,\n pinnedRows: this.pinnedRows,\n });\n }\n // A new page cache (new source, sort order or refresh) or none, and new measured widths.\n const autoWidths = this.#autoWidths.widths;\n this.#autoWidthsChanged = autoWidths !== this.#pushedAutoWidths;\n this.#pushedAutoWidths = autoWidths;\n this.#table.update({ remote: this.#data.rows, autoWidths });\n const model = this.#table.model;\n this.#reconcileActive(model);\n const active = this.#active;\n // -1 tells assistive tech the total is unknown (a data source still growing).\n const unknownTotal = this.#data.rows?.totalKnown === false;\n const layout = layoutOf(model);\n this.#internals.ariaRowCount = unknownTotal ? '-1' : String(layout.total);\n this.#internals.ariaColCount = String(model.columns.length);\n // The header and pinned rows scroll with the body, one row each.\n const extra = (1 + layout.top + layout.bottom) * this.#rowPx;\n this.#virtual.configure({\n count: model.rowCount,\n rowHeight: this.#rowPx,\n cap: bodyCap(model.rowCount * this.#rowPx, extra),\n overscan: Math.max(0, this.overscan),\n rowIdAt: (index) => this.#rowId(model, index),\n // The active body row stays rendered, so the tab stop and focus survive scrolling.\n keep:\n active?.section !== 'body' || active.rowId === undefined\n ? undefined\n : { id: active.rowId, index: active.index },\n });\n }\n\n protected override render(): TemplateResult {\n const model = this.#table.model;\n const columns = model.columns;\n this.#window = this.#virtual.computeWindow();\n const pinnedWidth = (side: 'start' | 'end') =>\n columns.reduce((sum, c) => (c.pin === side ? sum + c.width : sum), 0);\n const pinned = (side: 'start' | 'end') => `${String(pinnedWidth(side))}px`;\n const layout = layoutOf(model);\n const style: Record<string, string> = {\n '--_cols': columns.map(track).join(' '),\n '--_width': `${String(model.totalWidth)}px`,\n '--_pin-start': pinned('start'),\n '--_pin-end': pinned('end'),\n '--_pin-top-rows': String(layout.top),\n '--_pin-bottom-rows': String(layout.bottom),\n };\n const active = this.#active;\n const activeIn = (section: GridRow['section']): ActiveCell | undefined =>\n active?.section === section ? { index: active.index, col: active.col } : undefined;\n const firstIndex = (section: GridRow['section']) => layout.ariaRowIndex({ section, index: 0 });\n if (this.rowHeight !== undefined && this.rowHeight > 0) {\n style['--_row-height'] = `${String(this.rowHeight)}px`;\n }\n return html`<div\n part=\"table\"\n role=\"presentation\"\n style=${styleMap(style)}\n ?data-dragging=${this.#drag !== undefined}\n @keydown=${this.#onKeydown}\n @focusin=${this.#onFocusin}\n @click=${this.#onClick}\n >\n ${renderHeader(columns, this.#headerHandlers, activeIn('header')?.col, this.#drag)}\n ${renderPinnedRows('top', layout.top, columns, firstIndex('top'), activeIn('top'))}\n ${\n model.rowCount === 0\n ? html`<div part=\"empty\"><slot name=\"empty\">No rows</slot></div>`\n : renderBody(\n this.#window.rows,\n columns,\n this.#window.totalSize,\n activeIn('body'),\n firstIndex('body'),\n this.#loading(),\n )\n }\n ${renderPinnedRows('bottom', layout.bottom, columns, firstIndex('bottom'), activeIn('bottom'))}\n <div class=\"probe\" aria-hidden=\"true\"></div>\n </div>\n ${pinShadow('start', pinnedWidth('start'), layout.total - 1, this.#rowPx)}\n ${pinShadow('end', pinnedWidth('end'), layout.total - 1, this.#rowPx)}`;\n }\n\n protected override firstUpdated(): void {\n this.#observeProbe();\n this.#measureRowHeight();\n }\n\n protected override updated(changed: PropertyValues<this>): void {\n const model = this.#table.model;\n renderLightDom(this, model, this.#window.rows, this.#lightDomEnd());\n this.#measureAutoWidths(model);\n if (this.#scrollToTop) {\n this.#scrollToTop = false;\n const scroller = this.renderRoot.querySelector<HTMLElement>('[part~=\"table\"]');\n if (scroller) scroller.scrollTop = 0;\n }\n if (\n this.#columnsChanged ||\n changed.has('columnSizing') ||\n changed.has('columnOrder') ||\n this.#autoWidthsChanged\n ) {\n this.#pinScroll.measure();\n }\n if (this.#focusPending) {\n this.#focusPending = false;\n this.#focusActive();\n }\n if (changed.has('density') || changed.has('rowHeight')) this.#measureRowHeight();\n if (this.#appliedResizes.size > 0) {\n const details = [...this.#appliedResizes.values()];\n this.#appliedResizes.clear();\n for (const detail of details) fire(this, COLUMN_RESIZE, detail);\n }\n if (this.#announceMove) {\n this.#announceMoved(model, this.#announceMove);\n this.#announceMove = undefined;\n }\n if (this.#appliedReorders.size > 0) {\n const details = [...this.#appliedReorders.values()];\n this.#appliedReorders.clear();\n for (const detail of details) fire(this, COLUMN_REORDER, detail);\n }\n if (this.#appliedSort) {\n const sorting = this.#appliedSort;\n this.#appliedSort = undefined;\n fire(this, SORT_CHANGE, { sorting });\n }\n const { range } = this.#window;\n const key = range ? `${String(range.start)}:${String(range.end)}` : '';\n if (range && key !== this.#lastRange) {\n this.#lastRange = key;\n fire(this, RANGE_CHANGE, { start: range.start, end: range.end });\n }\n if (range) {\n // The rendered rows: visible plus overscan, end exclusive.\n const over = Math.max(0, this.overscan);\n this.#data.request(Math.max(0, range.start - over), range.end + 1 + over);\n }\n for (const detail of this.#data.takeErrors()) fire(this, LOAD_ERROR, detail);\n }\n\n /**\n * Measures the `width: 'auto'` columns once loaded body rows render, or right\n * away when there are no rows (the header and pinned rows only). While a data\n * source's first rows load, they keep the default width. A changed width\n * renders once more.\n */\n #measureAutoWidths(model: TableModel<T, CellContent>): void {\n const loaded = this.#window.rows.some((r) => model.rowAt(r.index) !== undefined);\n if (!loaded && model.rowCount > 0) return;\n if (this.#autoWidths.measure(this.renderRoot, model.columns, loaded)) this.requestUpdate();\n }\n\n /**\n * Loading state for the body while a data source is set: the state of each\n * row, and a Retry button on the first visible row of each failed page.\n */\n #loading(): Loading | undefined {\n const cache = this.#data.rows;\n if (!cache) return undefined;\n const top = this.#window.range?.start ?? 0;\n const firstByPage = new Map<number, number>();\n for (const { index } of this.#window.rows) {\n if (index < top || cache.stateAt(index) !== 'error') continue;\n const page = cache.pageOf(index);\n const first = firstByPage.get(page);\n if (first === undefined || index < first) firstByPage.set(page, index);\n }\n const retry = new Map<number, string>();\n for (const [page, index] of firstByPage) {\n const start = page * cache.pageSize;\n const end = Math.min(start + cache.pageSize, cache.rowCount);\n retry.set(index, `Retry loading rows ${String(start + 1)} to ${String(end)}`);\n }\n return { stateAt: (index) => cache.stateAt(index), retry, onRetry: this.#onRetry };\n }\n\n readonly #onRetry = (event: Event) => {\n const button = event.currentTarget as HTMLElement;\n // The button goes away with the retry; keep focus in the grid, on its cell.\n if (button.matches(':focus')) button.parentElement?.focus({ preventScroll: true });\n this.#data.retry(Number(button.dataset.row));\n };\n\n /**\n * A row's id. A data source row that hasn't loaded gets a stand-in: the\n * active cell's row id if it sits there (so its DOM and focus stay put), else\n * the index, which is also its real id when there is no `getRowId`.\n */\n #rowId(model: TableModel<T, CellContent>, index: number): string {\n const id = model.rowAt(index)?.id;\n if (id !== undefined) return id;\n const active = this.#active;\n if (active?.index === index && active.rowId !== undefined) return active.rowId;\n return this.#placeholderId(index);\n }\n\n /** The id of an unloaded row: its index, or a reserved string if `getRowId` makes the ids. */\n #placeholderId(index: number): string {\n return this.getRowId ? `\\u0000${String(index)}` : String(index);\n }\n\n readonly #headerHandlers = {\n click: (event: MouseEvent) => {\n const id = sortColumnOf(event);\n if (id !== undefined) this.#requestSort(id);\n },\n pointerdown: (event: PointerEvent) => {\n if (event.button !== 0) return;\n const handle = event.composedPath()[0];\n if (!(handle instanceof HTMLElement)) return;\n const id = handle.dataset.resizeCol;\n const cell = handle.parentElement;\n if (id !== undefined && cell) {\n startResizeDrag(\n handle,\n event,\n cell.getBoundingClientRect().width,\n this.#direction(),\n (w) => {\n this.#requestResize(id, w);\n },\n );\n return;\n }\n this.#startReorder(event);\n },\n /** A double-click on a resize handle fits the column to its rendered content. */\n dblclick: (event: MouseEvent) => {\n const handle = event.composedPath()[0];\n const id = handle instanceof HTMLElement ? handle.dataset.resizeCol : undefined;\n if (id === undefined) return;\n this.#requestResizes(measureColumns(this.renderRoot, [id]));\n },\n };\n\n /**\n * Keys on a focused cell or header: arrows by cell, Home/End along the row,\n * PageUp/PageDown by a page of rows (the view scrolls with it), Ctrl+Home/End\n * (or Cmd) to the first header and the last cell. Keys from content inside a\n * cell (an input, a button) are left to that content.\n */\n readonly #onKeydown = (event: KeyboardEvent) => {\n const cell = gridCell(event.composedPath()[0] ?? event.target ?? this);\n const id = cell?.dataset.col;\n if (!cell || id === undefined) return;\n const scroller = event.currentTarget as HTMLElement;\n if (event.key === 'Tab' && event.shiftKey) {\n // Firefox makes the scroll container a tab stop, so Shift+Tab would stop\n // on it before leaving the grid. Take it out of the tab order for this\n // one move only: a tabindex there for good would expose it as a node of\n // its own between the grid and its rows.\n scroller.tabIndex = -1;\n // Put it back once focus has actually moved (a timer can run first).\n cell.addEventListener(\n 'focusout',\n () => {\n scroller.removeAttribute('tabindex');\n },\n { once: true },\n );\n return;\n }\n const inHeader = cell.getAttribute('role') === 'columnheader';\n const { key } = event;\n const arrow = key === 'ArrowLeft' || key === 'ArrowRight';\n if (inHeader && arrow && event.altKey && event.shiftKey) {\n event.preventDefault();\n // Logical: the arrow pointing toward the inline end moves the column that way.\n const towardEnd = (key === 'ArrowRight') === (this.#direction() === 1);\n this.#moveByKey(id, towardEnd ? 1 : -1);\n return;\n }\n if (inHeader && event.altKey && arrow) {\n event.preventDefault();\n // Logical: the arrow pointing toward the inline end grows the column.\n const towardEnd = (key === 'ArrowRight') === (this.#direction() === 1);\n this.#requestResize(\n id,\n this.#currentWidth(id, cell) + (towardEnd ? RESIZE_STEP : -RESIZE_STEP),\n );\n return;\n }\n if (inHeader && (key === 'Enter' || key === ' ') && cell.dataset.sortCol !== undefined) {\n event.preventDefault();\n this.#requestSort(id);\n return;\n }\n // Ctrl (Cmd on macOS) only goes with Home and End: to the corners.\n const corner = event.ctrlKey || event.metaKey;\n if (event.altKey || event.shiftKey || (corner && key !== 'Home' && key !== 'End')) return;\n const model = this.#table.model;\n const layout = layoutOf(model);\n const from = inHeader ? HEADER : gridRowOf(cell.parentElement, layout);\n if (!from) return;\n if (!inHeader && key === 'Enter') {\n // Enter on a body cell does what a click does; on a failed row, it retries.\n event.preventDefault();\n if (from.section === 'body' && this.#data.stateAt(from.index) === 'error') {\n this.#data.retry(from.index);\n } else {\n this.#activate(event.composedPath());\n }\n return;\n }\n const columns = model.columns;\n // Rows step by grid position: header, pinned top, body, pinned bottom.\n let pos = layout.position(from);\n const last = layout.total - 1;\n const bodyFirst = layout.position({ section: 'body', index: 0 });\n const bodyLast = bodyFirst + layout.body - 1;\n // Whole rows between the sticky header and pinned rows (each one row tall).\n const fit = Math.floor(scroller.clientHeight / this.#rowPx + 0.01);\n const page = Math.max(1, fit - 1 - layout.top - layout.bottom);\n let col = columns.findIndex((c) => c.id === id);\n switch (key) {\n case 'PageDown':\n // Pages through the body: from above it, a page into it; it stops at its last row.\n if (layout.body > 0 && pos <= bodyLast) {\n pos = Math.min(Math.max(pos, bodyFirst - 1) + page, bodyLast);\n }\n break;\n case 'PageUp':\n // Stays in the body; ArrowUp or Ctrl+Home goes on to the rows above it.\n if (layout.body > 0 && pos > bodyFirst) {\n pos = Math.max(Math.min(pos, bodyLast + 1) - page, bodyFirst);\n }\n break;\n case 'ArrowDown':\n pos = Math.min(pos + 1, last);\n break;\n case 'ArrowUp':\n pos = Math.max(pos - 1, 0);\n break;\n case 'ArrowRight':\n col += this.#direction();\n break;\n case 'ArrowLeft':\n col -= this.#direction();\n break;\n case 'Home':\n col = 0;\n if (corner) {\n pos = 0;\n this.#virtual.scrollToEdge('start');\n }\n break;\n case 'End':\n col = columns.length - 1;\n if (corner) pos = last;\n break;\n default:\n return;\n }\n event.preventDefault();\n const row = layout.at(pos) ?? HEADER;\n // PageUp/PageDown scroll by as many rows as focus moved, so the focused cell\n // keeps its place on screen. The ends clamp; focusing scrolls the rest of\n // the way. Through the virtualizer: a scaled body's px aren't rows.\n if (key.startsWith('Page') && from.section === 'body' && row.section === 'body') {\n this.#virtual.scrollBy((row.index - from.index) * this.#rowPx);\n }\n // Ctrl+End onto a bottom pinned row: show the end of the body too, as\n // Ctrl+Home shows its start.\n if (corner && key === 'End' && row.section === 'bottom') {\n this.#virtual.scrollToEdge('end');\n }\n const target = columns[Math.min(Math.max(col, 0), columns.length - 1)];\n if (target) this.#moveTo(row, target.id, model);\n };\n\n /** Focus that lands in a cell (a click, or content inside it) makes that cell active. */\n readonly #onFocusin = (event: FocusEvent) => {\n // Tab into the grid landed on the scroll container (Firefox makes it a tab\n // stop): move on to the grid's one tab stop, the active cell. Only when focus\n // came from outside the grid: coming from inside means the user is leaving,\n // and sending them back would trap the keyboard.\n const scroller = event.currentTarget as HTMLElement;\n if (event.composedPath()[0] === scroller) {\n const from = event.relatedTarget;\n if (!(from instanceof Node && scroller.contains(from))) {\n this.#focusPending = true;\n this.requestUpdate();\n }\n return;\n }\n for (const target of event.composedPath()) {\n const cell = gridCell(target);\n if (cell?.dataset.col !== undefined) {\n const model = this.#table.model;\n const row =\n cell.getAttribute('role') === 'columnheader'\n ? HEADER\n : gridRowOf(cell.parentElement, layoutOf(model));\n const { col } = cell.dataset;\n const prev = this.#active;\n if (\n row &&\n (row.section !== prev?.section || row.index !== prev.index || col !== prev.col)\n ) {\n this.#active = { ...row, rowId: this.#gridRowId(model, row), col };\n this.requestUpdate();\n }\n return;\n }\n if (target === event.currentTarget) return;\n }\n };\n\n /** `argus-cell-click`, then `argus-row-click`, for clicks in the body. */\n readonly #onClick = (event: MouseEvent) => {\n this.#activate(event.composedPath());\n };\n\n /**\n * Fires `argus-cell-click` (when a cell is on the path), then `argus-row-click`,\n * for the body or pinned row on an event path. Clicks and Enter on a cell use\n * it. Rows that haven't loaded and the header fire nothing.\n */\n #activate(path: EventTarget[]): void {\n let columnId: string | undefined;\n for (const target of path) {\n if (!(target instanceof HTMLElement)) continue;\n const role = target.getAttribute('role');\n if (role === 'gridcell') columnId = target.dataset.col;\n if (role !== 'row') continue;\n const model = this.#table.model;\n const at = gridRowOf(target, layoutOf(model));\n if (!at || at.section === 'header') return;\n const { index } = at;\n if (at.section === 'body') {\n const row = model.rowAt(index);\n if (!row) return;\n if (columnId !== undefined) {\n fire(this, CELL_CLICK, {\n row: row.original,\n columnId,\n value: model.valueAt(index, columnId),\n });\n }\n fire(this, ROW_CLICK, { row: row.original, rowId: row.id, index });\n return;\n }\n const pinned = at.section;\n const row = model.pinnedRowAt(pinned, index);\n if (!row) return;\n if (columnId !== undefined) {\n fire(this, CELL_CLICK, {\n row: row.original,\n columnId,\n value: model.pinnedValueAt(pinned, index, columnId),\n pinned,\n });\n }\n fire(this, ROW_CLICK, { row: row.original, rowId: row.id, index, pinned });\n return;\n }\n }\n\n /** The id of a grid row: a body or pinned row's id; none for the header. */\n #gridRowId(model: TableModel<T, CellContent>, row: GridRow): string | undefined {\n switch (row.section) {\n case 'header':\n return undefined;\n case 'body':\n return this.#rowId(model, row.index);\n default:\n return model.pinnedRowAt(row.section, row.index)?.id;\n }\n }\n\n /** Makes a cell active and focuses it after the update. The keep-rendered rule renders its row. */\n #moveTo(row: GridRow, col: string, model: TableModel<T, CellContent>): void {\n this.#active = { ...row, rowId: this.#gridRowId(model, row), col };\n this.#focusPending = true;\n this.requestUpdate();\n }\n\n #focusActive(): void {\n const active = this.#active;\n if (!active) return;\n const col = CSS.escape(active.col);\n // aria-rowindex is unique across the grid: header, pinned and body rows.\n const index = layoutOf(this.#table.model).ariaRowIndex(active);\n const cell = this.renderRoot.querySelector<HTMLElement>(\n `[role='row'][aria-rowindex=\"${String(index)}\"] > [data-col=\"${col}\"]`,\n );\n if (!cell) return;\n cell.focus({ preventScroll: true });\n // A scaled body moves `ratio` px of rows per px scrolled, so the browser can't\n // scroll a body row into view: the virtualizer does, and the next update\n // (from its scroll) shows the row and scrolls sideways.\n if (active.section === 'body' && this.#virtual.scaled) {\n const layout = layoutOf(this.#table.model);\n const before = (1 + layout.top) * this.#rowPx;\n if (this.#virtual.reveal(active.index, before, layout.bottom * this.#rowPx)) {\n this.#focusPending = true;\n return;\n }\n }\n cell.scrollIntoView({ block: 'nearest', inline: 'nearest' });\n }\n\n /**\n * Keeps the active cell valid after columns or rows change. In the body: on the\n * same row id when it still exists (it may have moved), else at the same\n * index, clamped. A data source row that isn't loaded (yet, or any more) keeps\n * its id. A pinned row stays at its index, clamped to its list. A row whose\n * section has no rows left gives way to the header, the default. If its row\n * went away while the grid had focus, focus follows to the replacement.\n */\n #reconcileActive(model: TableModel<T, CellContent>): void {\n const columns = model.columns;\n const first = columns[0];\n if (!first) {\n this.#active = undefined;\n return;\n }\n const prev = this.#active ?? { ...HEADER, rowId: undefined, col: first.id };\n const col = columns.some((c) => c.id === prev.col) ? prev.col : first.id;\n let { section, index, rowId } = prev;\n let moved = false;\n if (section === 'body' && rowId !== undefined) {\n const found = model.indexOf(rowId);\n const unloaded = index < model.rowCount && model.rowAt(index) === undefined;\n if (found !== undefined) {\n index = found;\n } else if (!unloaded) {\n index = Math.min(index, model.rowCount - 1);\n rowId = index >= 0 ? (model.rowAt(index)?.id ?? this.#placeholderId(index)) : undefined;\n moved = true;\n }\n } else if (section === 'top' || section === 'bottom') {\n const count = model.pinnedCount(section);\n if (index >= count) {\n index = count - 1;\n moved = true;\n }\n rowId = index >= 0 ? model.pinnedRowAt(section, index)?.id : undefined;\n }\n if (index < 0) {\n ({ section, index } = HEADER);\n rowId = undefined;\n }\n if (moved && this.matches(':focus-within')) this.#focusPending = true;\n if (\n section !== prev.section ||\n index !== prev.index ||\n rowId !== prev.rowId ||\n col !== prev.col ||\n !this.#active\n ) {\n this.#active = { section, index, rowId, col };\n }\n }\n\n /**\n * The width a resize starts from: the latest requested width (key presses can\n * come faster than renders), else the model's fixed width, else the rendered\n * width of a flex column.\n */\n #currentWidth(columnId: string, cell: HTMLElement): number {\n const sized = this.#sizing.value[columnId];\n if (sized !== undefined) return sized;\n const view = this.#table.model.columns.find((c) => c.id === columnId);\n return view && view.flex === undefined ? view.width : cell.getBoundingClientRect().width;\n }\n\n #direction(): 1 | -1 {\n return getComputedStyle(this).direction === 'rtl' ? -1 : 1;\n }\n\n /** Sets one column's width (clamped by core), through the controlled/uncontrolled rules. */\n #requestResize(columnId: string, width: number): void {\n this.#requestResizes(new Map([[columnId, width]]));\n }\n\n /**\n * Sets column widths (clamped by core) in one change, through the\n * controlled/uncontrolled rules. One `argus-column-resize` per column that\n * changes, each with the whole new sizing.\n */\n #requestResizes(widths: ReadonlyMap<string, number>): void {\n const model = this.#table.model;\n const old = this.#sizing.value;\n const targets: [string, number][] = [];\n for (const [columnId, width] of widths) {\n const target = model.nextSizing(columnId, width)?.[columnId];\n if (target !== undefined && target !== old[columnId]) targets.push([columnId, target]);\n }\n if (targets.length === 0) return;\n const { value, applied } = this.#sizing.request({ ...old, ...Object.fromEntries(targets) });\n const details = targets.map(([columnId, width]) => ({ columnId, width, sizing: value }));\n if (applied) {\n // Only the latest width per column fires, all with the latest sizing.\n for (const detail of this.#appliedResizes.values()) detail.sizing = value;\n for (const detail of details) this.#appliedResizes.set(detail.columnId, detail);\n this.requestUpdate('columnSizing', old);\n } else {\n for (const detail of details) fire(this, COLUMN_RESIZE, detail);\n }\n }\n\n /**\n * Moves a column to position `to` in the whole order (within its pin group),\n * through the controlled/uncontrolled rules. Starts from the latest requested\n * order, so moves can come faster than renders. `false` if it can't move there.\n */\n #requestReorder(columnId: string, to: number): boolean {\n const old = this.#order.value;\n const next = this.#table.model.nextOrder(columnId, to, old);\n if (!next) return false;\n const { value, applied } = this.#order.request(next);\n if (applied) {\n for (const detail of this.#appliedReorders.values()) detail.order = value;\n this.#appliedReorders.set(columnId, { columnId, order: value });\n this.requestUpdate('columnOrder', old);\n } else {\n fire(this, COLUMN_REORDER, { columnId, order: value });\n }\n return true;\n }\n\n /** Alt+Shift+Arrow on a header: one step toward the start (-1) or the end (1). */\n #moveByKey(columnId: string, step: 1 | -1): void {\n const model = this.#table.model;\n const from = model.orderOf(this.#order.value).indexOf(columnId);\n const view = model.columns.find((c) => c.id === columnId);\n if (from < 0 || !view) return;\n if (!this.#requestReorder(columnId, from + step)) return;\n // The header node moves, which drops its focus: focus it again once rendered.\n this.#focusPending = true;\n this.#announceMove ??= { id: columnId, from: view.colIndex };\n this.requestUpdate();\n }\n\n /** Tells screen readers where a column moved from the keyboard went. */\n #announceMoved(model: TableModel<T, CellContent>, move: { id: string; from: number }): void {\n const view = model.columns.find((c) => c.id === move.id);\n if (!view || view.colIndex === move.from) return;\n const header = this.renderRoot.querySelector(\n `[role='columnheader'][data-col=\"${CSS.escape(move.id)}\"] > slot`,\n );\n const name =\n header instanceof HTMLSlotElement\n ? header\n .assignedNodes({ flatten: true })\n .map((n) => n.textContent)\n .join('')\n .trim()\n : '';\n announce(\n this.ownerDocument,\n `${name || move.id} moved to column ${String(view.colIndex)} of ${String(model.columns.length)}`,\n );\n }\n\n /** A press on a reorderable header: becomes a drag once the pointer moves. */\n #startReorder(down: PointerEvent): void {\n const cell = down\n .composedPath()\n .find(\n (t): t is HTMLElement =>\n t instanceof HTMLElement && t.getAttribute('role') === 'columnheader',\n );\n const columnId = cell?.dataset.moveCol;\n if (!cell || columnId === undefined || !canStartReorder(down, cell)) return;\n const scroller = this.renderRoot.querySelector<HTMLElement>('[part~=\"table\"]');\n if (!scroller) return;\n const pin = this.#table.model.columns.find((c) => c.id === columnId)?.pin;\n startReorderDrag(cell, down, {\n scroller,\n targetAt: (x) => dropTarget(this.#dropSlots(pin), columnId, x, this.#direction()),\n scrollArea: () => (pin === undefined ? this.#scrollArea(scroller) : undefined),\n onStart: () => {\n this.#drag = { columnId, target: undefined };\n this.requestUpdate();\n },\n onTarget: (target) => {\n this.#drag = { columnId, target };\n this.requestUpdate();\n },\n onDrop: (target) => {\n this.#drag = undefined;\n if (target && this.#requestReorder(columnId, target.to)) {\n // The header node moves, which drops its focus: focus it again once rendered.\n if (this.matches(':focus-within')) this.#focusPending = true;\n }\n this.requestUpdate();\n },\n onCancel: () => {\n this.#drag = undefined;\n this.requestUpdate();\n },\n });\n }\n\n /** The rendered headers of one pin group, with their positions in the whole order. */\n #dropSlots(pin: ColumnView<T, CellContent>['pin']): DropSlot[] {\n const slots: DropSlot[] = [];\n this.#table.model.columns.forEach((c, index) => {\n if (c.pin !== pin) return;\n const cell = this.renderRoot.querySelector(\n `[role='columnheader'][data-col=\"${CSS.escape(c.id)}\"]`,\n );\n if (cell) slots.push({ id: c.id, index, rect: cell.getBoundingClientRect() });\n });\n return slots;\n }\n\n /** Where the scrolling columns show: the scroller's inside, less the pinned columns. */\n #scrollArea(scroller: HTMLElement): { left: number; right: number } {\n const columns = this.#table.model.columns;\n const width = (side: 'start' | 'end') =>\n columns.reduce((sum, c) => (c.pin === side ? sum + c.width : sum), 0);\n const ltr = this.#direction() === 1;\n const left = scroller.getBoundingClientRect().left + scroller.clientLeft;\n return {\n left: left + width(ltr ? 'start' : 'end'),\n right: left + scroller.clientWidth - width(ltr ? 'end' : 'start'),\n };\n }\n\n /** asc → desc → unsorted, through the controlled/uncontrolled rules. */\n #requestSort(columnId: string): void {\n const next = this.#table.model.nextSorting(columnId);\n if (!next) return;\n const old = this.#sorting.value;\n const { value, applied } = this.#sorting.request(next);\n if (applied) {\n this.#appliedSort = value;\n this.requestUpdate('sorting', old);\n } else {\n fire(this, SORT_CHANGE, { sorting: value });\n }\n }\n\n #observeProbe(): void {\n const probe = this.renderRoot.querySelector('.probe');\n if (!probe) return;\n this.#probeObserver ??= new ResizeObserver(() => {\n this.#measureRowHeight();\n });\n this.#probeObserver.observe(probe);\n }\n\n /** Reads the resolved row height, so themes and density change the virtualizer too. */\n #measureRowHeight(): void {\n const probe = this.renderRoot.querySelector('.probe');\n const px = probe?.getBoundingClientRect().height ?? 0;\n if (px > 0 && Math.abs(px - this.#rowPx) > 0.01) {\n this.#rowPx = px;\n this.requestUpdate();\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'argus-table': ArgusTable;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"argus-table.js","names":["_decorate"],"sources":["../src/argus-table.ts"],"sourcesContent":["import {\n LitElement,\n html,\n nothing,\n type CSSResultGroup,\n type PropertyValues,\n type RootPart,\n type TemplateResult,\n} from 'lit';\nimport type { ComplexAttributeConverter } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport {\n clickSelection,\n controllable,\n RowLayout,\n sameSelection,\n selectAll,\n selectRange,\n SELECTION_COLUMN_ID,\n toggleRow,\n type ColumnFilterDetail,\n type ColumnHideDetail,\n type ColumnPinDetail,\n type ColumnReorderDetail,\n type ColumnResizeDetail,\n type ColumnView,\n type Controllable,\n type GridRow,\n type SelectionStep,\n type SelectionTarget,\n type TableModel,\n} from '@argus-table/core';\nimport { announce } from './announce.js';\nimport { AutoWidths, measureColumns } from './controllers/auto-width.js';\nimport { ColumnChildrenController } from './controllers/column-children.js';\nimport { ColumnWindowController, type RenderedColumn } from './controllers/column-window.js';\nimport { DataController } from './controllers/data-controller.js';\nimport { PinScrollController } from './controllers/pin-scroll-controller.js';\nimport { PluginController, sameItems } from './controllers/plugins.js';\nimport { RowMeasure } from './controllers/row-measure.js';\nimport {\n canStartReorder,\n dropTarget,\n startReorderDrag,\n type DropSlot,\n} from './controllers/reorder-drag.js';\nimport { startResizeDrag } from './controllers/resize-drag.js';\nimport { TableController } from './controllers/table-controller.js';\nimport { VirtualController, type VirtualWindow } from './controllers/virtual-controller.js';\nimport {\n CELL_CLICK,\n COLUMN_FILTER,\n COLUMN_HIDE,\n COLUMN_PIN,\n COLUMN_REORDER,\n COLUMN_RESIZE,\n fire,\n LOAD_ERROR,\n RANGE_CHANGE,\n ROW_CLICK,\n ROW_SELECT,\n SORT_CHANGE,\n} from './events.js';\nimport { fromInteractive, INTERACTIVE } from './interactive.js';\nimport { bodyCap, watchMaxElementHeight } from './max-height.js';\nimport { renderBody, type ActiveCell, type Loading, type SelectedAt } from './render/body.js';\nimport { renderLightDom } from './render/cells.js';\nimport { content, flushContent, type ContentRenderer } from './render/content-directive.js';\nimport { renderHeader, type CheckAll, type HeaderDrag } from './render/header.js';\nimport type { CheckboxHandlers } from './render/content.js';\nimport { renderPinnedRows } from './render/pinned-rows.js';\nimport type { ArgusPlugin, CellTarget, ColumnInfo, PluginHost } from './plugins.js';\nimport { baseStyles } from './styles/base.js';\nimport type {\n CellContent,\n ColumnDef,\n ColumnFilter,\n ColumnFilterState,\n ColumnOrderState,\n ColumnPin,\n ColumnPinningState,\n ColumnSizingState,\n ColumnVisibilityState,\n DataSource,\n Density,\n PinnedRows,\n SelectionMode,\n SelectionState,\n SortState,\n TableState,\n} from './types.js';\n\n/**\n * The host carries the grid role, so rows rendered in the shadow root become\n * its children in the accessibility tree. ElementInternals sets the default;\n * `connectedCallback` also adds a `role` attribute, because tools such as\n * axe-core can't see the ElementInternals role. A `role` the page sets wins.\n */\nfunction attachGridInternals(host: HTMLElement): ElementInternals {\n const internals = host.attachInternals();\n internals.role = 'grid';\n return internals;\n}\n\n/**\n * The sortable column a header click came from, if any. Works for slotted content\n * too. Clicks on a resize handle never sort, so a click that ends a drag doesn't,\n * and neither do clicks on interactive content in the header (a button, an input).\n */\nfunction sortColumnOf(event: Event): string | undefined {\n for (const target of event.composedPath()) {\n if (!(target instanceof HTMLElement)) continue;\n if (target.dataset.resizeCol !== undefined) return undefined;\n if (target.matches(INTERACTIVE)) return undefined;\n if (target.dataset.sortCol !== undefined) return target.dataset.sortCol;\n if (target.getAttribute('part') === 'header-row') return undefined;\n }\n return undefined;\n}\n\nconst RESIZE_STEP = 10;\n\n/** `row-height`: px (`48` or `48px`) or `auto`; anything else is unset. */\nconst rowHeightConverter: ComplexAttributeConverter<number | 'auto' | undefined> = {\n fromAttribute(value) {\n if (value === null) return undefined;\n const text = value.trim().toLowerCase();\n if (text === 'auto') return 'auto';\n const px = Number(text.replace(/px$/, ''));\n return text !== '' && px > 0 ? px : undefined;\n },\n};\n\n/**\n * The cell holding the grid's single tab stop: a row (its section, and its index\n * there: in the row model for the body, in its list for a pinned row) and a\n * column. `rowId` keeps it on the same body row when the order changes.\n */\ninterface Active extends GridRow {\n rowId: string | undefined;\n col: string;\n}\n\nconst HEADER: GridRow = { section: 'header', index: 0 };\n\n/** Where the rows sit in the grid: header, pinned top, body, pinned bottom. */\nfunction layoutOf<T>(model: TableModel<T, CellContent>): RowLayout {\n return new RowLayout(model.pinnedCount('top'), model.rowCount, model.pinnedCount('bottom'));\n}\n\n/** The grid cell or column header an element is, if any. */\nfunction gridCell(target: EventTarget): HTMLElement | undefined {\n if (!(target instanceof HTMLElement) || target.dataset.col === undefined) return undefined;\n const role = target.getAttribute('role');\n return role === 'gridcell' || role === 'columnheader' ? target : undefined;\n}\n\n/** The grid row a rendered row element is, from its `aria-rowindex`. */\nfunction gridRowOf(row: Element | null, layout: RowLayout): GridRow | undefined {\n const index = row?.getAttribute('aria-rowindex');\n return index ? layout.fromAriaRowIndex(Number(index)) : undefined;\n}\n\n/**\n * The pinned edge's shadow, drawn once per side over the scroller rather than\n * per row: a shadow on every pinned cell repaints on every scroll frame. It\n * covers the pinned columns and casts `--argus-pinned-shadow` onto the rest;\n * PinScrollController sizes it to the visible area.\n */\nfunction pinShadow(side: 'start' | 'end', width: number, contentPx: number) {\n if (width === 0) return nothing;\n return html`<div\n class=\"pin-shadow\"\n data-side=${side}\n aria-hidden=\"true\"\n style=${styleMap({\n inlineSize: `${String(width)}px`,\n '--_content-h': `${String(contentPx)}px`,\n })}\n ></div>`;\n}\n\n/** CSS grid track for a column: fixed px, or a flex share with the min width as floor. */\nfunction track<T>(column: ColumnView<T, CellContent>): string {\n return column.flex === undefined\n ? `${String(column.width)}px`\n : `minmax(${String(column.minWidth)}px, ${String(column.flex)}fr)`;\n}\n\n/**\n * A virtualized data table.\n *\n * Set `columns`, and `data` or `dataSource`, as properties. Columns can also be\n * written as `<argus-column>` children; a non-empty `columns` wins over them.\n * Header and cell content is rendered into the element's light DOM and slotted\n * into the cells, so page CSS and the page's own components work inside cells.\n *\n * Any number of rows scrolls to the end. Browsers limit an element's height\n * (about 800k rows of 40 px in Chromium and Safari, 400k in Firefox), so a taller\n * body renders shorter and its scroll position is scaled onto the rows: the\n * scrollbar still spans every row, and a wheel step covers a few more of them.\n * Use `scrollToRow()` rather than setting the scroll container's `scrollTop`.\n *\n * @summary Data table with pinned rows and columns and infinite loading.\n *\n * @fires {CustomEvent<SortChangeDetail>} argus-sort-change - A sortable header was clicked, or activated with Enter or Space. `detail: { sorting }`: the new order, or the proposed one when `sorting` is controlled.\n * @fires {CustomEvent<ColumnResizeDetail>} argus-column-resize - A column was resized: by dragging its handle, with Alt+Arrow on its header, by a double-click on its handle (fit to content) or by `autosizeColumns()`. `detail: { columnId, width, sizing }`: the new widths, or the proposed ones when `columnSizing` is controlled. Fires on every frame of a drag, and once per column that `autosizeColumns()` changes.\n * @fires {CustomEvent<ColumnReorderDetail>} argus-column-reorder - A column was moved: by dragging its header, or with Alt+Shift+Arrow on its focused header. Columns move within their own group (start-pinned, scrolling, end-pinned). `detail: { columnId, order }`: the new order, or the proposed one when `columnOrder` is controlled. Fires once per move, on drop.\n * @fires {CustomEvent<ColumnPinDetail>} argus-column-pin - A column was pinned to a side or unpinned, through a plugin such as the column menu. `detail: { columnId, pin, pinning }`: `pin` is `'start'`, `'end'` or `false`; `pinning` is the new state, or the proposed one when `columnPinning` is controlled.\n * @fires {CustomEvent<ColumnHideDetail>} argus-column-hide - A column was hidden or shown, through a plugin such as the column menu. `detail: { columnId, hidden, visibility }`: `hidden` is `true` when it was hidden; `visibility` is the new state, or the proposed one when `columnVisibility` is controlled.\n * @fires {CustomEvent<ColumnFilterDetail>} argus-column-filter - A column's filter was set, changed or cleared, through a plugin such as the column menu. `detail: { columnId, filter, filters }`: `filter` is the column's new filter, or `undefined` when it was cleared; `filters` is the new state, or the proposed one when `columnFilters` is controlled.\n * @fires {CustomEvent<CellClickDetail<T>>} argus-cell-click - A body or pinned-row cell was clicked, or Enter was pressed on it. `detail: { row, columnId, value, pinned? }`; `pinned` is `'top'` or `'bottom'` for a pinned row. Fires before `argus-row-click`.\n * @fires {CustomEvent<RowClickDetail<T>>} argus-row-click - A body or pinned row was clicked, or Enter was pressed on one of its cells. `detail: { row, rowId, index, pinned? }`; for a pinned row, `index` is its index in its list.\n * @fires {CustomEvent<RangeChangeDetail>} argus-range-change - The visible rows changed. `detail: { start, end }` (row indices, inclusive).\n * @fires {CustomEvent<RowSelectDetail>} argus-row-select - The selected rows changed: by a click on a row (Ctrl/Cmd toggles, Shift selects a range), with Space, Shift+Arrow or Shift+PageUp/PageDown on a body cell, or with Ctrl/Cmd+A. Only with a `selectionMode`. `detail: { selection }`: the new row ids, or the proposed ones when `selection` is controlled.\n * @fires {CustomEvent<LoadErrorDetail>} argus-load-error - A `dataSource` page failed to load: `getRows()` rejected or threw. `detail: { error, start, end }` (`end` exclusive). The rows show a Retry button.\n *\n * @slot empty - Shown instead of the body when there are no rows. Default: \"No rows\".\n *\n * @csspart table - The scroll container that holds header and body.\n * @csspart header - The sticky header row group.\n * @csspart header-row - The header row.\n * @csspart header-cell - Every header cell.\n * @csspart header-cell-sorted - The header of the sorted column. The direction is in `aria-sort`.\n * @csspart header-cell-filtered - Added to `header-cell` on the headers of filtered columns.\n * @csspart filter-indicator - The mark in the header of a filtered column, after the sort indicator.\n * @csspart header-cell-dragging - Added to `header-cell` on the header being dragged to a new position.\n * @csspart drop-indicator - The line on the edge of the header where a dragged column would land.\n * @csspart resize-handle - The drag handle on the inline-end edge of a resizable column's header. A double-click fits the column to its content.\n * @csspart body - The row group holding the rendered body rows.\n * @csspart row - Every body row.\n * @csspart row-even - Body rows with an even index (0-based).\n * @csspart row-odd - Body rows with an odd index.\n * @csspart row-loading - Body rows whose `dataSource` page hasn't loaded yet, or failed.\n * @csspart row-selected - Body rows whose id is in `selection`.\n * @csspart cell-selection - Added to `cell` in the checkbox column (`selectionCheckboxes`), pinned rows included.\n * @csspart header-cell-selection - Added to `header-cell` on the checkbox column's header.\n * @csspart selection-checkbox - The checkboxes of the checkbox column: one per selectable row, and the select-all one in the header (`multi` mode).\n * @csspart row-pinned - Every row from `pinnedRows`, on either side. Also has `row`, but no `row-even`/`row-odd`.\n * @csspart row-pinned-top - The rows pinned below the header.\n * @csspart row-pinned-bottom - The rows pinned to the bottom.\n * @csspart cell-pinned-row - Every cell of a pinned row (next to `cell`).\n * @csspart cell - Every body cell.\n * @csspart cell-sorted - Body cells in the sorted column.\n * @csspart cell-pinned - Body cells in a pinned column, on either side.\n * @csspart cell-pinned-edge - The pinned body cell next to the scrolling columns (one per pinned side).\n * @csspart skeleton - The placeholder bar in each cell of a row that is still loading.\n * @csspart skeleton-error - Added to `skeleton` in a row whose page failed to load.\n * @csspart retry - The Retry button in the first cell of a failed page's first visible row.\n * @csspart empty - The empty-state container.\n *\n * @cssprop [--argus-bg=Canvas] - Background of the table and rows.\n * @cssprop [--argus-fg=CanvasText] - Text colour.\n * @cssprop [--argus-font=inherit] - Font shorthand for the table.\n * @cssprop [--argus-header-bg] - Header background.\n * @cssprop [--argus-header-fg=inherit] - Header text colour.\n * @cssprop [--argus-border-color] - Colour of the row borders.\n * @cssprop [--argus-border-width=1px] - Width of the row borders.\n * @cssprop [--argus-outline=none] - Border around the whole table, as a `border` shorthand (`1px solid …`). Inside the element's size.\n * @cssprop [--argus-radius=0] - Corner radius of the table. Header, rows and pinned columns are clipped to it.\n * @cssprop [--argus-row-height] - Height of a row. Default per density: 32px, 40px, 52px. With `rowHeight: 'auto'`: the header's height and the least a body or pinned row is.\n * @cssprop [--argus-cell-padding-inline] - Inline padding of cells. Default per density: 8px, 12px, 16px.\n * @cssprop [--argus-cell-padding-block] - Block padding of body and pinned-row cells with `rowHeight: 'auto'`, where content sits at the top of the cell. Default: what centres one line of text in `--argus-row-height`.\n * @cssprop [--argus-row-stripe-bg] - Background of odd rows. Default: no stripes.\n * @cssprop [--argus-pinned-shadow] - Shadow on the pinned edge, as a `box-shadow` falling toward the end side (`4px 0 6px -4px …`). Mirrored for the end edge and in RTL; `none` removes it.\n * @cssprop [--argus-resize-handle-color] - Colour of the resize handle's line, shown on hover, focus and drag.\n * @cssprop [--argus-focus-ring=2px solid Highlight] - Outline of the focused header or cell.\n * @cssprop [--argus-filter-indicator-color=currentColor] - Colour of the mark in the header of a filtered column.\n * @cssprop [--argus-drop-indicator-color=Highlight] - Colour of the line that marks where a dragged column would land.\n * @cssprop [--argus-row-hover-bg] - Background of the hovered row. Default: no change.\n * @cssprop [--argus-pinned-row-bg=var(--argus-bg)] - Background of the pinned rows, pinned columns included.\n * @cssprop [--argus-skeleton-bg] - Colour of the skeleton bars in rows still loading. Default: the text colour at low opacity.\n * @cssprop [--argus-row-selected-bg] - Background of selected rows, pinned columns included. Default: the system highlight colour, mixed into `--argus-bg`. It wins over `--argus-row-hover-bg`.\n */\n@customElement('argus-table')\nexport class ArgusTable<T = unknown> extends LitElement {\n static override styles: CSSResultGroup = baseStyles;\n\n /**\n * Column definitions. Property only: functions can't be attributes. While empty,\n * the table reads its `<argus-column>` children instead. `null` or `undefined`\n * means `[]`.\n */\n @property({ attribute: false })\n get columns(): readonly ColumnDef<T>[] {\n return this.#columnsProp;\n }\n set columns(value: readonly ColumnDef<T>[] | null | undefined) {\n // Framework bindings set `undefined` when a prop goes away.\n this.#columnsProp = value ?? [];\n }\n\n /**\n * The rows to show. Replace the array to update; changes inside it aren't\n * detected. `null` or `undefined` means `[]`.\n */\n @property({ attribute: false })\n get data(): readonly T[] {\n return this.#dataProp;\n }\n set data(value: readonly T[] | null | undefined) {\n this.#dataProp = value ?? [];\n }\n\n /**\n * Loads rows page by page as they scroll into view, instead of `data`:\n * `{ getRows({ start, end, sorting, signal }), pageSize? }`, where `end` is\n * exclusive and `getRows` resolves to `{ rows, total? }`. Without a `total`,\n * the table grows as pages arrive and a short page marks the end. Sorting\n * happens on the server: a new order reloads from the top. While set, it wins\n * over `data`. Replace the object to change `getRows` or `pageSize`.\n */\n @property({ attribute: false })\n dataSource?: DataSource<T>;\n\n /**\n * Rows fixed below the header (`top`) and at the bottom of the view (`bottom`),\n * such as a totals row: `{ top?: T[], bottom?: T[] }`. They are separate\n * objects, not rows of `data`: columns read them the same way, but they are\n * never sorted and work the same with a `dataSource`. A `cell` function gets\n * `pinned: 'top' | 'bottom'` in its context. Replace the object to update.\n */\n @property({ attribute: false })\n pinnedRows?: PinnedRows<T>;\n\n /** Returns a stable id for a row. Default: the row's index (in `data`, or among all `dataSource` rows). */\n @property({ attribute: false })\n getRowId?: (row: T, index: number) => string;\n\n /**\n * Row height in px, or `'auto'` to fit each row to its content (`row-height=\"auto\"`).\n * Unset: the density (or the `--argus-row-height` token) decides. With\n * `'auto'`, that height is the header's and the least a body or pinned row is;\n * rows grow to fit wrapped text (`wrap` columns) and taller content, and cell\n * content sits at the top. Rows are measured as they render: a row's height\n * counts the columns rendered (see `virtualizeColumns`), and rows not seen yet\n * count as one line. Give images a size, so rows don't move when they load.\n */\n @property({ attribute: 'row-height', converter: rowHeightConverter })\n rowHeight?: number | 'auto';\n\n /** Row density: `compact`, `comfortable` or `spacious`. */\n @property({ reflect: true })\n density: Density = 'comfortable';\n\n /** Rows rendered above and below the visible ones. `null` or `undefined` means the default, 6. */\n @property({ type: Number })\n get overscan(): number {\n return this.#overscan;\n }\n set overscan(value: number | null | undefined) {\n this.#overscan = value ?? 6;\n }\n\n /**\n * Renders only the scrolling columns in view (plus two on each side), for\n * wide tables: a few dozen columns and more. Pinned columns, the checkbox\n * column and the focused cell's column always render. Off by default: then\n * every column renders, as before. Cells are placed in their grid column\n * explicitly, so page CSS that relies on their order in the DOM (`:nth-child`\n * on cells) doesn't apply. `autosizeColumns()` and `width: 'auto'` columns\n * still measure columns out of view: they render for the measurement.\n */\n @property({ attribute: 'virtualize-columns', type: Boolean })\n virtualizeColumns = false;\n\n /**\n * The sort order, e.g. `[{ id: 'total', desc: true }]`; `[]` when unsorted. Unset,\n * the table keeps it itself and header clicks change it. Once set, it is\n * controlled: a click only fires `argus-sort-change` with the proposed order,\n * and nothing changes until you set the property. Set `undefined` to hand it back.\n */\n @property({ attribute: false })\n get sorting(): SortState {\n return this.#sorting.value;\n }\n set sorting(value: SortState | undefined) {\n // Lit wraps this accessor and requests the update with the old value.\n this.#sorting.set(value);\n }\n\n /**\n * Resized widths in px by column id, e.g. `{ name: 240 }`. A resized flex column\n * becomes fixed. Uncontrolled until set, like `sorting`: once set, a resize only\n * fires `argus-column-resize` with the proposed widths. `undefined` hands it back.\n */\n @property({ attribute: false })\n get columnSizing(): ColumnSizingState {\n return this.#sizing.value;\n }\n set columnSizing(value: ColumnSizingState | undefined) {\n this.#sizing.set(value);\n }\n\n /**\n * The column order: column ids as the table shows them, e.g.\n * `['id', 'total', 'customer']`. `[]` (the default) keeps the order of `columns`.\n * Each pin group (start-pinned, scrolling, end-pinned) takes its columns in this\n * order; unknown ids are ignored and columns it doesn't list follow the listed\n * ones of their group. After a move it holds every column id. Uncontrolled\n * until set, like `sorting`: once set, a move only fires `argus-column-reorder`\n * with the proposed order. `undefined` hands it back.\n */\n @property({ attribute: false })\n get columnOrder(): ColumnOrderState {\n return this.#order.value;\n }\n set columnOrder(value: ColumnOrderState | undefined) {\n this.#order.set(value);\n }\n\n /**\n * Pins by column id, over the columns' own `pin`: `'start'` or `'end'` pins a\n * column, `false` unpins one whose definition pins it, e.g.\n * `{ total: 'end', id: false }`. Columns it doesn't list keep their `pin`. A pinned\n * column joins the edge of its group nearest its place in `columnOrder`, and stops\n * flexing. Uncontrolled until set, like `sorting`: once set, pinning from a plugin\n * only fires `argus-column-pin` with the proposed pins. `undefined` hands it back.\n */\n @property({ attribute: false })\n get columnPinning(): ColumnPinningState {\n return this.#pinning.value;\n }\n set columnPinning(value: ColumnPinningState | undefined) {\n this.#pinning.set(value);\n }\n\n /**\n * Visibility by column id, over the columns' own `hidden`: `false` hides a column,\n * `true` shows one defined as `hidden`, e.g. `{ email: false }`. Columns it\n * doesn't list keep their `hidden`. A hidden column isn't rendered, but sorting by\n * it still works and it keeps its place in `columnOrder`. Uncontrolled until set,\n * like `sorting`: once set, hiding or showing from a plugin only fires\n * `argus-column-hide` with the proposed visibility. `undefined` hands it back.\n */\n @property({ attribute: false })\n get columnVisibility(): ColumnVisibilityState {\n return this.#visibility.value;\n }\n set columnVisibility(value: ColumnVisibilityState | undefined) {\n this.#visibility.set(value);\n }\n\n /**\n * Filters by column id, e.g. `{ city: { kind: 'set', values: ['Berlin'] } }` or\n * `{ total: { kind: 'number', op: 'gt', value: 100 } }`. A row shows when it passes\n * every filter and `quickFilter`. Filters on hidden columns still apply; unknown ids\n * are ignored. A column's `filterFn` replaces the built-in matching. With a\n * `dataSource`, the filters go to `getRows()` and the server filters. Users set\n * filters through plugins (the column menu) on columns with a `filter` kind.\n * Uncontrolled until set, like `sorting`: once set, a change from a plugin only\n * fires `argus-column-filter` with the proposed filters. `undefined` hands it back.\n */\n @property({ attribute: false })\n get columnFilters(): ColumnFilterState {\n return this.#filters.value;\n }\n set columnFilters(value: ColumnFilterState | undefined) {\n this.#filters.set(value);\n }\n\n /**\n * Shows only rows that contain each word of this text in one of their shown\n * columns, ignoring case, e.g. from a search box. Values are matched as text\n * (dates as `2026-11-10`); objects aren't searched. With a `dataSource`, it goes\n * to `getRows()` and the server filters. `''` (the default) shows every row.\n */\n @property({ attribute: 'quick-filter' })\n get quickFilter(): string {\n return this.#quickFilter;\n }\n set quickFilter(value: string | null | undefined) {\n this.#quickFilter = value ?? '';\n }\n\n /**\n * How rows can be selected: `none` (the default), `single` or `multi`. A click\n * on a body row selects it; in `multi` mode Ctrl/Cmd+click toggles a row,\n * Shift+click selects the range from the last clicked row, and Ctrl/Cmd+A\n * selects every row. Space toggles the focused row. Clicks on buttons, links\n * and inputs inside cells don't select. Pinned rows, and `dataSource` rows not\n * loaded yet, can't be selected.\n */\n @property({ attribute: 'selection-mode' })\n selectionMode: SelectionMode = 'none';\n\n /**\n * Adds a checkbox column, pinned first at the start, while `selectionMode` is\n * `single` or `multi`. A row's checkbox toggles it (Shift+click adds the range\n * from the last row clicked); in `multi` mode the header's checkbox selects\n * every row, or clears the selection when all are selected. Space on a\n * focused checkbox cell does the same. The column isn't part of `columns`,\n * `columnOrder` or `columnSizing`, and it fires no `argus-cell-click`.\n */\n @property({ attribute: 'selection-checkboxes', type: Boolean })\n selectionCheckboxes = false;\n\n /**\n * The selected rows, as row ids (from `getRowId`, or the row's index as a\n * string), e.g. `['p4', 'p7']`. Uncontrolled until set, like `sorting`: once\n * set, a click only fires `argus-row-select` with the proposed ids.\n * `undefined` hands it back. The table never drops ids on its own: they stay\n * through sorting, a new `data` or reloaded pages. With a `dataSource`,\n * Ctrl/Cmd+A selects the loaded rows only.\n */\n @property({ attribute: false })\n get selection(): SelectionState {\n return this.#selection.value;\n }\n set selection(value: SelectionState | undefined) {\n this.#selection.set(value);\n }\n\n /**\n * Renders header and cell content the table can't render itself, such as React\n * elements, Vue VNodes or Angular templates: `{ render(target, content),\n * release(target), flush?() }`. A `header` or `cell` that returns anything other\n * than a string, a number, a DOM node or a Lit template hands it to the renderer,\n * with a target element the table keeps while the cell is reused for other rows.\n * The framework wrappers set it; set it yourself only for another framework.\n */\n @property({ attribute: false })\n contentRenderer?: ContentRenderer;\n\n /**\n * Add-ons, such as `headerMenu()` from `@argus-table/header-menu`. Each one can\n * change the column definitions, handle keys on a focused header or cell, and\n * use the table through a small API. They run in array order. Replace the\n * array to change them; an array with the same plugins in the same order\n * changes nothing. `null` or `undefined` means `[]`.\n */\n @property({ attribute: false })\n get plugins(): readonly ArgusPlugin<T>[] {\n return this.#pluginsProp;\n }\n set plugins(value: readonly ArgusPlugin<T>[] | null | undefined) {\n const next = value ?? [];\n // The same plugins in a new array (a framework re-render) keep their connection.\n if (!sameItems(next, this.#pluginsProp)) this.#pluginsProp = next;\n }\n\n #columnsProp: readonly ColumnDef<T>[] = [];\n #pluginsProp: readonly ArgusPlugin<T>[] = [];\n #dataProp: readonly T[] = [];\n #overscan = 6;\n readonly #sorting = controllable<SortState>([]);\n readonly #sizing = controllable<ColumnSizingState>({});\n readonly #order = controllable<ColumnOrderState>([]);\n readonly #pinning = controllable<ColumnPinningState>({});\n readonly #visibility = controllable<ColumnVisibilityState>({});\n readonly #filters = controllable<ColumnFilterState>({});\n #quickFilter = '';\n /** Filters the table applied itself, by column; their events fire once the update is done. */\n readonly #appliedFilters = new Map<string, ColumnFilterDetail>();\n /** Announce the row count after the update: the filters changed. */\n #announceRows = false;\n /** Pins the table applied itself, by column; their events fire once the update is done. */\n readonly #appliedPins = new Map<string, ColumnPinDetail>();\n /** Hidden or shown columns the table applied itself; their events fire once the update is done. */\n readonly #appliedHides = new Map<string, ColumnHideDetail>();\n readonly #selection = controllable<SelectionState>([]);\n /** `selection` as a set, for the rows rendered; rebuilt when `selection` changes. */\n #selectedIds: { of: SelectionState; ids: ReadonlySet<string> } | undefined;\n /** The row a Shift range starts from: the last row clicked or toggled without Shift. */\n #anchor: string | undefined;\n /** A selection the table applied itself; its event fires once the update is done. */\n #appliedSelection: SelectionState | undefined;\n /** Whether the checkbox column was last shown; a change re-measures the pinned columns. */\n #selectionColumn = false;\n #selectionColumnChanged = false;\n /** The select-all checkbox's state, kept until `selection`, `data` or `getRowId` change. */\n #checkAll: { key: readonly unknown[]; state: CheckAll['state'] } | undefined;\n /** Moves the table applied itself, by column; their events fire once the update is done. */\n readonly #appliedReorders = new Map<string, ColumnReorderDetail>();\n /** The header being dragged to a new position, if any. */\n #drag: HeaderDrag | undefined;\n /** A move from the keyboard, announced once it has rendered: the column and its old position. */\n #announceMove: { id: string; from: number } | undefined;\n /** Resizes the table applied itself, by column; their events fire once the update is done. */\n readonly #appliedResizes = new Map<string, ColumnResizeDetail>();\n /** Columns `autosizeColumns()` renders out of view for its measurement. */\n #measureKeep: readonly string[] = [];\n /** Measured widths of `width: 'auto'` columns. */\n readonly #autoWidths = new AutoWidths(() => {\n this.requestUpdate();\n });\n /** The auto widths last passed to the model; a change re-measures the pinned columns' offsets. */\n #pushedAutoWidths: ColumnSizingState | undefined;\n #autoWidthsChanged = false;\n /** A sort the table applied itself; its event fires once the update is done. */\n #appliedSort: SortState | undefined;\n readonly #internals = attachGridInternals(this);\n readonly #table = new TableController<T>();\n readonly #children = new ColumnChildrenController<T>(this);\n /** What plugins get: closures over the table's private state. */\n readonly #pluginHost: PluginHost<T> = {\n element: this,\n column: (id) => this.#columnInfo(id),\n columns: () =>\n this.#table.model.allColumns.flatMap((c) => {\n const info = this.#columnInfo(c.id);\n return info ? [info] : [];\n }),\n setPin: (columnId, pin) => {\n this.#requestPin(columnId, pin);\n },\n setHidden: (columnId, hidden) => {\n this.#requestHide(columnId, hidden);\n },\n setFilter: (columnId, filter) => {\n this.#requestFilter(columnId, filter);\n },\n filterValues: (columnId, limit) => this.#table.model.filterValues(columnId, limit),\n cellOf: (event) => this.#cellTarget(event),\n setSort: (columnId, direction) => {\n this.#setSort(columnId, direction);\n },\n focusHeader: (columnId) => {\n this.#moveTo(HEADER, columnId, this.#table.model);\n },\n announce: (message) => {\n announce(this.ownerDocument, message);\n },\n invalidateColumns: () => {\n this.#plugins.invalidate();\n this.requestUpdate();\n },\n requestUpdate: () => {\n this.requestUpdate();\n },\n row: (index) => this.#table.model.rowAt(index)?.original,\n content: (value) => content(value),\n };\n readonly #plugins = new PluginController<T>(this, this.#pluginHost);\n #columnsById:\n | {\n of: readonly ColumnView<T, CellContent>[];\n byId: ReadonlyMap<string, ColumnView<T, CellContent>>;\n }\n | undefined;\n /** The columns last passed to the model: `columns`, or the `<argus-column>` children. */\n #columns: readonly ColumnDef<T>[] = [];\n #columnsChanged = false;\n #warnedColumns = false;\n /** End of the light-DOM part holding cell content, so later children stay outside it. */\n #contentEnd: Comment | undefined;\n /** The light-DOM part: disconnected with the table, so foreign content is released. */\n #lightPart: RootPart | undefined;\n #lightConnected = true;\n readonly #data = new DataController<T>(this);\n /** Scroll back to the top after the update (a new sort order for a data source). */\n #scrollToTop = false;\n // Looked up lazily: the virtualizer's hostUpdated runs before firstUpdated.\n readonly #virtual = new VirtualController(this, () =>\n this.renderRoot.querySelector<HTMLElement>('[part~=\"table\"]'),\n );\n readonly #pinScroll = new PinScrollController(this, () =>\n this.renderRoot.querySelector<HTMLElement>('[part~=\"table\"]'),\n );\n readonly #columnWindow = new ColumnWindowController<T>(this, () =>\n this.renderRoot.querySelector<HTMLElement>('[part~=\"table\"]'),\n );\n /** The columns the last render rendered (all of them, unless `virtualizeColumns`). */\n #rendered: RenderedColumn<T>[] = [];\n #rowPx = 40;\n #probeObserver?: ResizeObserver;\n /** The column template and row height the rows were last read for. */\n #rowsKey = '';\n /** Rows of different heights: reads the rendered rows (`rowHeight: 'auto'` only). */\n readonly #rowMeasure = new RowMeasure(this, {\n bodyIndex: (row) => {\n const at = gridRowOf(row, layoutOf(this.#table.model));\n return at?.section === 'body' && this.#data.stateAt(at.index) === 'loaded'\n ? at.index\n : undefined;\n },\n sizeOf: (index) => this.#virtual.sizeOf(index),\n minimum: () => this.#rowPx,\n });\n #window: VirtualWindow = { rows: [], totalSize: 0, range: null };\n #active: Active | undefined;\n /** Move focus to the active cell after the next update (keyboard navigation). */\n #focusPending = false;\n #lastRange = '';\n #unwatchMaxHeight: (() => void) | undefined;\n\n /**\n * The row `setState()` still has to scroll to: a data source's rows that far\n * aren't counted yet. Scrolled to again whenever the row count changes.\n */\n #scrollTarget: { row: number; count: number } | undefined;\n\n constructor() {\n super();\n // The user's own scrolling (or a click, or a key) wins over a restored position.\n for (const type of ['wheel', 'touchstart', 'pointerdown', 'keydown'] as const) {\n this.addEventListener(type, this.#dropScrollTarget, { passive: true });\n }\n }\n\n readonly #dropScrollTarget = () => {\n this.#scrollTarget = undefined;\n };\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (!this.hasAttribute('role')) this.setAttribute('role', 'grid');\n if (this.hasUpdated) this.#observeProbe();\n if (this.#lightPart && !this.#lightConnected) {\n this.#lightConnected = true;\n this.#lightPart.setConnected(true);\n flushContent(this);\n }\n // A zoom change changes the tallest body the engine renders.\n this.#unwatchMaxHeight = watchMaxElementHeight(() => {\n this.requestUpdate();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#probeObserver?.disconnect();\n this.#rowMeasure.stop();\n // Framework content in the cells is unmounted until the table comes back.\n if (this.#lightPart && this.#lightConnected) {\n this.#lightConnected = false;\n this.#lightPart.setConnected(false);\n flushContent(this);\n }\n this.#unwatchMaxHeight?.();\n this.#unwatchMaxHeight = undefined;\n }\n\n /**\n * `columns` when it has any, otherwise the `<argus-column>` children. Keeps its\n * identity while neither changes, so the model is only rebuilt on a change.\n */\n #effectiveColumns(): readonly ColumnDef<T>[] {\n if (this.columns.length === 0) return this.#children.defs;\n if (!this.#warnedColumns && this.#children.present) {\n this.#warnedColumns = true;\n console.warn(\n 'argus-table: the columns property is set, so <argus-column> children are ignored.',\n );\n }\n return this.columns;\n }\n\n /**\n * The node the light-DOM content is rendered before. Lit's part then ends there,\n * so children appended later (an `<argus-column>`) never land inside it. If the\n * marker was removed (say by `innerHTML`), a new one starts a fresh part.\n */\n #lightDomEnd(): Comment {\n if (this.#contentEnd?.parentNode !== this) {\n this.#contentEnd = document.createComment('');\n this.append(this.#contentEnd);\n }\n return this.#contentEnd;\n }\n\n /**\n * With a `dataSource`, drops every loaded page and loads the rows in view\n * again, keeping the scroll position. With `data`, re-renders the cells (after\n * changing row objects in place). Resolves once the table has re-rendered;\n * reloaded rows arrive as their pages load.\n */\n async refresh(): Promise<void> {\n this.#data.refresh();\n this.requestUpdate();\n await this.updateComplete;\n }\n\n /**\n * Fits columns to their content: the header, the pinned rows and the body rows\n * rendered now (rows out of view aren't measured). It resizes them like a drag\n * would, so `argus-column-resize` fires for each column that changes, and with a\n * controlled `columnSizing` nothing changes until you set it. Without `ids`, fits\n * every resizable column; columns with `resizable: false` keep their width.\n * With `virtualizeColumns`, columns out of view render for the measurement.\n * Resolves once the table has re-rendered.\n */\n async autosizeColumns(ids?: readonly string[]): Promise<void> {\n await this.updateComplete;\n const targets = this.#table.model.columns\n .filter((c) => c.resizable && (ids === undefined || ids.includes(c.id)))\n .map((c) => c.id);\n if (this.virtualizeColumns) {\n this.#measureKeep = targets;\n this.requestUpdate();\n await this.updateComplete;\n }\n const widths = measureColumns(this.renderRoot, targets);\n if (this.#measureKeep.length > 0) {\n this.#measureKeep = [];\n this.requestUpdate();\n }\n this.#requestResizes(widths);\n await this.updateComplete;\n }\n\n /** Scrolls so that the row at `index` (in the current row order) is at the top. */\n async scrollToRow(index: number): Promise<void> {\n await this.updateComplete;\n this.#virtual.scrollToIndex(index);\n await this.#settled();\n }\n\n /**\n * Waits for the update, and with `rowHeight: 'auto'` for the ones measured\n * rows request (a few at most: heights don't depend on positions).\n */\n async #settled(): Promise<void> {\n let done = await this.updateComplete;\n for (let i = 0; i < 8 && !done && this.rowHeight === 'auto'; i++) {\n done = await this.updateComplete;\n }\n }\n\n /**\n * The state users change, as one object of plain JSON for saving a user's\n * layout: `sorting`, `columnSizing`, `columnOrder`, `columnPinning`,\n * `columnVisibility`, `columnFilters`, `selection`, `quickFilter`, and `scroll`\n * (the row at the top and the horizontal offset). Controlled properties are\n * included with the values you set. The object is a copy: changing it changes\n * nothing in the table.\n */\n getState(): Required<TableState> {\n const scroller = this.renderRoot.querySelector<HTMLElement>('[part~=\"table\"]');\n return structuredClone({\n sorting: this.#sorting.value,\n columnSizing: this.#sizing.value,\n columnOrder: this.#order.value,\n columnPinning: this.#pinning.value,\n columnVisibility: this.#visibility.value,\n columnFilters: this.#filters.value,\n selection: this.#selection.value,\n quickFilter: this.#quickFilter,\n // Negative in RTL.\n scroll: { row: this.#virtual.topRow, left: Math.abs(scroller?.scrollLeft ?? 0) },\n });\n }\n\n /**\n * Restores state from `getState()`, for example a layout saved in\n * `localStorage`. Only the keys given change; ids of columns that no longer\n * exist are ignored. Properties you control are left alone (set them\n * yourself), and the others stay uncontrolled. No change events fire.\n * `quickFilter` is set like the property: a search box of yours shows it only\n * if you read it back. `scroll` is applied after the rest, so with a\n * `dataSource` the restored rows load where it points. Resolves once the table\n * has re-rendered there.\n */\n async setState(state: TableState): Promise<void> {\n this.#restore('sorting', this.#sorting, state.sorting);\n this.#restore('columnSizing', this.#sizing, state.columnSizing);\n this.#restore('columnOrder', this.#order, state.columnOrder);\n this.#restore('columnPinning', this.#pinning, state.columnPinning);\n this.#restore('columnVisibility', this.#visibility, state.columnVisibility);\n this.#restore('columnFilters', this.#filters, state.columnFilters);\n // A Shift range starts over from the restored selection.\n if (this.#restore('selection', this.#selection, state.selection)) this.#anchor = undefined;\n if (state.quickFilter !== undefined) this.quickFilter = state.quickFilter;\n this.#scrollTarget = undefined;\n await this.updateComplete;\n const { scroll } = state;\n if (!scroll) return;\n this.#virtual.scrollToIndex(scroll.row);\n // A data source counts one page past its loaded rows until it knows the\n // total: scroll on as the count grows.\n const count = this.#table.model.rowCount;\n if (this.#data.rows?.totalKnown === false && scroll.row >= count) {\n this.#scrollTarget = { row: scroll.row, count };\n }\n const scroller = this.renderRoot.querySelector<HTMLElement>('[part~=\"table\"]');\n if (scroller) scroller.scrollLeft = scroll.left * this.#direction();\n // The scroll event comes before the next frame, and the rows move with its update.\n await new Promise(requestAnimationFrame);\n await this.#settled();\n }\n\n /** Scrolls on toward the row `setState()` restored once more rows are counted. */\n #chaseScrollTarget(count: number): void {\n const target = this.#scrollTarget;\n if (!target || target.count === count) return;\n target.count = count;\n this.#virtual.scrollToIndex(target.row);\n if (target.row < count || this.#data.rows?.totalKnown !== false) this.#scrollTarget = undefined;\n }\n\n /**\n * Applies a restored value to uncontrolled state without an event, as a user\n * change would without the event. Returns whether it changed.\n */\n #restore<V>(name: keyof TableState, state: Controllable<V>, value: V | undefined): boolean {\n if (value === undefined || state.controlled) return false;\n // The same value restored again doesn't reload a data source.\n if (JSON.stringify(value) === JSON.stringify(state.value)) return false;\n const old = state.value;\n state.request(structuredClone(value));\n this.requestUpdate(name, old);\n return true;\n }\n\n protected override willUpdate(changed: PropertyValues<this>): void {\n if (changed.has('plugins')) this.#plugins.set(this.plugins);\n const columns = this.#plugins.transform(this.#effectiveColumns());\n this.#columnsChanged = columns !== this.#columns;\n this.#columns = columns;\n const filtersChanged = changed.has('columnFilters') || changed.has('quickFilter');\n if (\n changed.has('dataSource') ||\n changed.has('sorting') ||\n changed.has('getRowId') ||\n filtersChanged\n ) {\n this.#data.configure({\n source: this.dataSource,\n sorting: this.#sorting.value,\n filters: this.#filters.value,\n quickFilter: this.#quickFilter,\n getRowId: this.getRowId,\n });\n // A new order or filter starts over from the first row, so show it.\n if (this.dataSource && this.hasUpdated && (changed.has('sorting') || filtersChanged)) {\n this.#scrollToTop = !changed.has('dataSource');\n }\n // Other rows: a position restored for the old ones no longer applies.\n this.#scrollTarget = undefined;\n }\n if (filtersChanged && this.hasUpdated) this.#announceRows = true;\n if (\n this.#columnsChanged ||\n changed.has('data') ||\n changed.has('getRowId') ||\n changed.has('sorting') ||\n changed.has('columnSizing') ||\n changed.has('columnOrder') ||\n changed.has('columnPinning') ||\n changed.has('columnVisibility') ||\n changed.has('columnFilters') ||\n changed.has('quickFilter') ||\n changed.has('pinnedRows')\n ) {\n if (this.#columnsChanged) {\n this.#autoWidths.sync(columns.filter((c) => c.width === 'auto').map((c) => c.id));\n }\n this.#table.update({\n columns,\n data: this.data,\n getRowId: this.getRowId,\n sorting: this.#sorting.value,\n columnSizing: this.#sizing.value,\n columnOrder: this.#order.value,\n columnPinning: this.#pinning.value,\n columnVisibility: this.#visibility.value,\n columnFilters: this.#filters.value,\n quickFilter: this.#quickFilter,\n pinnedRows: this.pinnedRows,\n });\n }\n // A new page cache (new source, sort order or refresh) or none, and new measured widths.\n const autoWidths = this.#autoWidths.widths;\n this.#autoWidthsChanged = autoWidths !== this.#pushedAutoWidths;\n this.#pushedAutoWidths = autoWidths;\n const selectionColumn = this.selectionCheckboxes && this.#mode() !== 'none';\n this.#selectionColumnChanged = selectionColumn !== this.#selectionColumn;\n this.#selectionColumn = selectionColumn;\n this.#table.update({ remote: this.#data.rows, autoWidths, selectionColumn });\n const model = this.#table.model;\n this.#reconcileActive(model);\n const active = this.#active;\n // -1 tells assistive tech the total is unknown (a data source still growing).\n const unknownTotal = this.#data.rows?.totalKnown === false;\n const layout = layoutOf(model);\n this.#internals.ariaRowCount = unknownTotal ? '-1' : String(layout.total);\n this.#internals.ariaColCount = String(model.columns.length);\n this.#internals.ariaMultiSelectable = this.#mode() === 'multi' ? 'true' : null;\n // The header and pinned rows scroll with the body.\n const extra = this.#rowPx + this.#pinnedPx('top', layout) + this.#pinnedPx('bottom', layout);\n const auto = this.rowHeight === 'auto';\n if (!auto) this.#rowMeasure.stop();\n // Anything but a scroll may change what rows hold (data, columns, widths).\n else if (changed.size > 0 || this.#columnsChanged) this.#rowMeasure.invalidate();\n this.#virtual.configure({\n count: model.rowCount,\n rowHeight: this.#rowPx,\n cap: (logical) => bodyCap(logical, extra),\n auto: auto ? { order: model.rowOrder, indexOf: (id) => model.indexOf(id) } : undefined,\n overscan: Math.max(0, this.overscan),\n rowIdAt: (index) => this.#rowId(model, index),\n // The active body row stays rendered, so the tab stop and focus survive scrolling.\n keep:\n active?.section !== 'body' || active.rowId === undefined\n ? undefined\n : { id: active.rowId, index: active.index },\n });\n }\n\n protected override render(): TemplateResult {\n const model = this.#table.model;\n const columns = model.columns;\n this.#window = this.#virtual.computeWindow();\n const rendered = this.#columnWindow.compute(\n columns,\n this.virtualizeColumns,\n this.virtualizeColumns ? this.#keptColumns(model) : [],\n );\n this.#rendered = rendered;\n const pinnedWidth = (side: 'start' | 'end') =>\n columns.reduce((sum, c) => (c.pin === side ? sum + c.width : sum), 0);\n const pinned = (side: 'start' | 'end') => `${String(pinnedWidth(side))}px`;\n const layout = layoutOf(model);\n const style: Record<string, string> = {\n '--_cols': columns.map(track).join(' '),\n '--_width': `${String(model.totalWidth)}px`,\n '--_pin-start': pinned('start'),\n '--_pin-end': pinned('end'),\n '--_pin-top-rows': String(layout.top),\n '--_pin-bottom-rows': String(layout.bottom),\n };\n const auto = this.rowHeight === 'auto';\n if (auto) {\n // New column widths or a new row height rewrap rows: read them all again.\n const key = `${style['--_cols'] ?? ''}|${String(this.#rowPx)}`;\n if (key !== this.#rowsKey) {\n this.#rowsKey = key;\n this.#rowMeasure.invalidate();\n }\n style['--_pin-top-h'] = `${String(this.#pinnedPx('top', layout))}px`;\n style['--_pin-bottom-h'] = `${String(this.#pinnedPx('bottom', layout))}px`;\n }\n const active = this.#active;\n const activeIn = (section: GridRow['section']): ActiveCell | undefined =>\n active?.section === section ? { index: active.index, col: active.col } : undefined;\n const firstIndex = (section: GridRow['section']) => layout.ariaRowIndex({ section, index: 0 });\n if (typeof this.rowHeight === 'number' && this.rowHeight > 0) {\n style['--_row-height'] = `${String(this.rowHeight)}px`;\n }\n // The header, the pinned rows and the body: what the pinned-column shadows cover.\n const contentPx =\n this.#rowPx +\n this.#pinnedPx('top', layout) +\n this.#pinnedPx('bottom', layout) +\n (model.rowCount === 0 ? 0 : this.#window.totalSize);\n return html`<div\n part=\"table\"\n role=\"presentation\"\n style=${styleMap(style)}\n ?data-dragging=${this.#drag !== undefined}\n ?data-auto-rows=${auto}\n @keydown=${this.#onKeydown}\n @focusin=${this.#onFocusin}\n @mousedown=${this.#onMousedown}\n @click=${this.#onClick}\n >\n ${renderHeader(\n rendered,\n this.#headerHandlers,\n activeIn('header')?.col,\n this.#drag,\n this.#checkAllOf(model),\n )}\n ${renderPinnedRows('top', layout.top, rendered, firstIndex('top'), activeIn('top'))}\n ${\n model.rowCount === 0\n ? html`<div part=\"empty\"><slot name=\"empty\">No rows</slot></div>`\n : renderBody(\n this.#window.rows,\n rendered,\n this.#window.totalSize,\n activeIn('body'),\n firstIndex('body'),\n this.#loading(),\n this.#selectedAt(model),\n this.#selectionColumn ? this.#checkboxHandlers : undefined,\n auto,\n )\n }\n ${renderPinnedRows('bottom', layout.bottom, rendered, firstIndex('bottom'), activeIn('bottom'))}\n <div class=\"probe\" aria-hidden=\"true\"></div>\n </div>\n ${pinShadow('start', pinnedWidth('start'), contentPx)}\n ${pinShadow('end', pinnedWidth('end'), contentPx)}`;\n }\n\n protected override firstUpdated(): void {\n this.#observeProbe();\n this.#measureRowHeight();\n }\n\n protected override updated(changed: PropertyValues<this>): void {\n const model = this.#table.model;\n const part = renderLightDom(\n this,\n model,\n this.#window.rows,\n this.#rendered,\n this.#lightDomEnd(),\n );\n // A new marker starts a new part (the old one was removed): its content is gone.\n if (this.#lightPart && this.#lightPart !== part) this.#lightPart.setConnected(false);\n this.#lightPart = part;\n // Foreign content is committed before anything measures it.\n flushContent(this);\n this.#measureAutoWidths(model);\n // Rows of different heights: placed by the update this requests.\n const resized = this.rowHeight === 'auto' && this.#measureRows();\n if (this.#scrollToTop) {\n this.#scrollToTop = false;\n const scroller = this.renderRoot.querySelector<HTMLElement>('[part~=\"table\"]');\n if (scroller) scroller.scrollTop = 0;\n }\n this.#chaseScrollTarget(model.rowCount);\n if (\n this.#columnsChanged ||\n changed.has('columnSizing') ||\n changed.has('columnOrder') ||\n changed.has('columnPinning') ||\n changed.has('columnVisibility') ||\n this.#autoWidthsChanged ||\n this.#selectionColumnChanged\n ) {\n this.#pinScroll.measure();\n }\n // Rows that just changed height move with the next update: focus them there.\n if (this.#focusPending && !resized) {\n this.#focusPending = false;\n this.#focusActive();\n }\n if (changed.has('density') || changed.has('rowHeight')) this.#measureRowHeight();\n if (this.#appliedResizes.size > 0) {\n const details = [...this.#appliedResizes.values()];\n this.#appliedResizes.clear();\n for (const detail of details) fire(this, COLUMN_RESIZE, detail);\n }\n if (this.#announceMove) {\n this.#announceMoved(model, this.#announceMove);\n this.#announceMove = undefined;\n }\n if (this.#appliedReorders.size > 0) {\n const details = [...this.#appliedReorders.values()];\n this.#appliedReorders.clear();\n for (const detail of details) fire(this, COLUMN_REORDER, detail);\n }\n if (this.#appliedPins.size > 0) {\n const details = [...this.#appliedPins.values()];\n this.#appliedPins.clear();\n for (const detail of details) fire(this, COLUMN_PIN, detail);\n }\n if (this.#appliedHides.size > 0) {\n const details = [...this.#appliedHides.values()];\n this.#appliedHides.clear();\n for (const detail of details) fire(this, COLUMN_HIDE, detail);\n }\n if (this.#appliedFilters.size > 0) {\n const details = [...this.#appliedFilters.values()];\n this.#appliedFilters.clear();\n for (const detail of details) fire(this, COLUMN_FILTER, detail);\n }\n if (this.#announceRows) {\n this.#announceRows = false;\n this.#announceRowCount(model);\n }\n if (this.#appliedSort) {\n const sorting = this.#appliedSort;\n this.#appliedSort = undefined;\n fire(this, SORT_CHANGE, { sorting });\n }\n if (this.#appliedSelection) {\n const selection = this.#appliedSelection;\n this.#appliedSelection = undefined;\n fire(this, ROW_SELECT, { selection });\n }\n const { range } = this.#window;\n const key = range ? `${String(range.start)}:${String(range.end)}` : '';\n if (range && key !== this.#lastRange) {\n this.#lastRange = key;\n fire(this, RANGE_CHANGE, { start: range.start, end: range.end });\n }\n if (range) {\n // The rendered rows: visible plus overscan, end exclusive.\n const over = Math.max(0, this.overscan);\n this.#data.request(Math.max(0, range.start - over), range.end + 1 + over);\n }\n for (const detail of this.#data.takeErrors()) fire(this, LOAD_ERROR, detail);\n }\n\n /**\n * Columns to render wherever they are, with `virtualizeColumns`: the active\n * cell's (its tab stop and focus survive scrolling sideways, and keyboard\n * moves land on a rendered cell), one being dragged, auto widths still to\n * measure, the targets of `autosizeColumns()`, and with a `dataSource` the\n * first data column, which holds the Retry buttons.\n */\n #keptColumns(model: TableModel<T, CellContent>): (string | undefined)[] {\n return [\n this.#active?.col,\n this.#drag?.columnId,\n this.dataSource ? model.columns.find((c) => c.kind === 'data')?.id : undefined,\n ...this.#autoWidths.pending(model.columns),\n ...this.#measureKeep,\n ];\n }\n\n /**\n * Measures the `width: 'auto'` columns once loaded body rows render, or right\n * away when there are no rows (the header and pinned rows only). While a data\n * source's first rows load, they keep the default width. A changed width\n * renders once more.\n */\n #measureAutoWidths(model: TableModel<T, CellContent>): void {\n const loaded = this.#window.rows.some((r) => model.rowAt(r.index) !== undefined);\n if (!loaded && model.rowCount > 0) return;\n if (this.#autoWidths.measure(this.renderRoot, model.columns, loaded)) this.requestUpdate();\n }\n\n /**\n * Loading state for the body while a data source is set: the state of each\n * row, and a Retry button on the first visible row of each failed page.\n */\n #loading(): Loading | undefined {\n const cache = this.#data.rows;\n if (!cache) return undefined;\n const top = this.#window.range?.start ?? 0;\n const firstByPage = new Map<number, number>();\n for (const { index } of this.#window.rows) {\n if (index < top || cache.stateAt(index) !== 'error') continue;\n const page = cache.pageOf(index);\n const first = firstByPage.get(page);\n if (first === undefined || index < first) firstByPage.set(page, index);\n }\n const retry = new Map<number, string>();\n for (const [page, index] of firstByPage) {\n const start = page * cache.pageSize;\n const end = Math.min(start + cache.pageSize, cache.rowCount);\n retry.set(index, `Retry loading rows ${String(start + 1)} to ${String(end)}`);\n }\n return { stateAt: (index) => cache.stateAt(index), retry, onRetry: this.#onRetry };\n }\n\n readonly #onRetry = (event: Event) => {\n const button = event.currentTarget as HTMLElement;\n // The button goes away with the retry; keep focus in the grid, on its cell.\n if (button.matches(':focus')) button.parentElement?.focus({ preventScroll: true });\n this.#data.retry(Number(button.dataset.row));\n };\n\n /**\n * A row's id. A data source row that hasn't loaded gets a stand-in: the\n * active cell's row id if it sits there (so its DOM and focus stay put), else\n * the index, which is also its real id when there is no `getRowId`.\n */\n #rowId(model: TableModel<T, CellContent>, index: number): string {\n const id = model.rowAt(index)?.id;\n if (id !== undefined) return id;\n const active = this.#active;\n if (active?.index === index && active.rowId !== undefined) return active.rowId;\n return this.#placeholderId(index);\n }\n\n /** The id of an unloaded row: its index, or a reserved string if `getRowId` makes the ids. */\n #placeholderId(index: number): string {\n return this.getRowId ? `\\u0000${String(index)}` : String(index);\n }\n\n readonly #headerHandlers = {\n click: (event: MouseEvent) => {\n const id = sortColumnOf(event);\n if (id !== undefined) this.#requestSort(id);\n },\n pointerdown: (event: PointerEvent) => {\n if (event.button !== 0) return;\n const handle = event.composedPath()[0];\n if (!(handle instanceof HTMLElement)) return;\n const id = handle.dataset.resizeCol;\n const cell = handle.parentElement;\n if (id !== undefined && cell) {\n startResizeDrag(\n handle,\n event,\n cell.getBoundingClientRect().width,\n this.#direction(),\n (w) => {\n this.#requestResize(id, w);\n },\n );\n return;\n }\n this.#startReorder(event);\n },\n /** A double-click on a resize handle fits the column to its rendered content. */\n dblclick: (event: MouseEvent) => {\n const handle = event.composedPath()[0];\n const id = handle instanceof HTMLElement ? handle.dataset.resizeCol : undefined;\n if (id === undefined) return;\n this.#requestResizes(measureColumns(this.renderRoot, [id]));\n },\n };\n\n /**\n * Keys on a focused cell or header: arrows by cell, Home/End along the row,\n * PageUp/PageDown by a page of rows (the view scrolls with it), Ctrl+Home/End\n * (or Cmd) to the first header and the last cell. Keys from content inside a\n * cell (an input, a button) are left to that content.\n */\n readonly #onKeydown = (event: KeyboardEvent) => {\n const cell = gridCell(event.composedPath()[0] ?? event.target ?? this);\n const id = cell?.dataset.col;\n if (!cell || id === undefined) return;\n const scroller = event.currentTarget as HTMLElement;\n if (event.key === 'Tab' && event.shiftKey) {\n // Firefox makes the scroll container a tab stop, so Shift+Tab would stop\n // on it before leaving the grid. Take it out of the tab order for this\n // one move only: a tabindex there for good would expose it as a node of\n // its own between the grid and its rows.\n scroller.tabIndex = -1;\n // Put it back once focus has actually moved (a timer can run first).\n cell.addEventListener(\n 'focusout',\n () => {\n scroller.removeAttribute('tabindex');\n },\n { once: true },\n );\n return;\n }\n const pluginTarget = id === SELECTION_COLUMN_ID ? undefined : this.#cellTarget(event);\n if (pluginTarget && this.#plugins.keydown(event, pluginTarget)) return;\n const inHeader = cell.getAttribute('role') === 'columnheader';\n const { key } = event;\n const arrow = key === 'ArrowLeft' || key === 'ArrowRight';\n if (inHeader && arrow && event.altKey && event.shiftKey) {\n event.preventDefault();\n // Logical: the arrow pointing toward the inline end moves the column that way.\n const towardEnd = (key === 'ArrowRight') === (this.#direction() === 1);\n this.#moveByKey(id, towardEnd ? 1 : -1);\n return;\n }\n if (inHeader && event.altKey && arrow) {\n event.preventDefault();\n // Logical: the arrow pointing toward the inline end grows the column.\n const towardEnd = (key === 'ArrowRight') === (this.#direction() === 1);\n this.#requestResize(\n id,\n this.#currentWidth(id, cell) + (towardEnd ? RESIZE_STEP : -RESIZE_STEP),\n );\n return;\n }\n if (inHeader && (key === 'Enter' || key === ' ') && cell.dataset.sortCol !== undefined) {\n event.preventDefault();\n this.#requestSort(id);\n return;\n }\n if (this.#selectionKey(event, cell, id, inHeader, scroller)) return;\n // Ctrl (Cmd on macOS) only goes with Home and End: to the corners.\n const corner = event.ctrlKey || event.metaKey;\n if (event.altKey || event.shiftKey || (corner && key !== 'Home' && key !== 'End')) return;\n const model = this.#table.model;\n const layout = layoutOf(model);\n const from = inHeader ? HEADER : gridRowOf(cell.parentElement, layout);\n if (!from) return;\n if (!inHeader && key === 'Enter') {\n // Enter on a body cell does what a click does; on a failed row, it retries.\n event.preventDefault();\n if (from.section === 'body' && this.#data.stateAt(from.index) === 'error') {\n this.#data.retry(from.index);\n } else {\n this.#activate(event.composedPath());\n }\n return;\n }\n const columns = model.columns;\n // Rows step by grid position: header, pinned top, body, pinned bottom.\n let pos = layout.position(from);\n const last = layout.total - 1;\n let col = columns.findIndex((c) => c.id === id);\n switch (key) {\n case 'PageDown':\n case 'PageUp':\n case 'ArrowDown':\n case 'ArrowUp':\n pos = this.#verticalStep(key, pos, layout, scroller);\n break;\n case 'ArrowRight':\n col += this.#direction();\n break;\n case 'ArrowLeft':\n col -= this.#direction();\n break;\n case 'Home':\n col = 0;\n if (corner) {\n pos = 0;\n this.#virtual.scrollToEdge('start');\n }\n break;\n case 'End':\n col = columns.length - 1;\n if (corner) pos = last;\n break;\n default:\n return;\n }\n event.preventDefault();\n const row = layout.at(pos) ?? HEADER;\n // PageUp/PageDown scroll by as many rows as focus moved, so the focused cell\n // keeps its place on screen. The ends clamp; focusing scrolls the rest of\n // the way. Through the virtualizer: a scaled body's px aren't rows.\n if (key.startsWith('Page') && from.section === 'body' && row.section === 'body') {\n this.#virtual.scrollBy(this.#virtual.startOf(row.index) - this.#virtual.startOf(from.index));\n }\n // Ctrl+End onto a bottom pinned row: show the end of the body too, as\n // Ctrl+Home shows its start.\n if (corner && key === 'End' && row.section === 'bottom') {\n this.#virtual.scrollToEdge('end');\n }\n const target = columns[Math.min(Math.max(col, 0), columns.length - 1)];\n if (target) this.#moveTo(row, target.id, model);\n };\n\n /**\n * The grid position ArrowUp/ArrowDown (one row) or PageUp/PageDown (a page of\n * the body) moves to from `pos`. PageDown from above the body lands a page\n * into it and stops at its last row; PageUp stays in the body.\n */\n #verticalStep(\n key: 'PageDown' | 'PageUp' | 'ArrowDown' | 'ArrowUp',\n pos: number,\n layout: RowLayout,\n scroller: HTMLElement,\n ): number {\n const bodyFirst = layout.position({ section: 'body', index: 0 });\n const bodyLast = bodyFirst + layout.body - 1;\n const page = this.#pageRows(key, pos, layout, scroller);\n switch (key) {\n case 'PageDown':\n return layout.body > 0 && pos <= bodyLast\n ? Math.min(Math.max(pos, bodyFirst - 1) + page, bodyLast)\n : pos;\n case 'PageUp':\n return layout.body > 0 && pos > bodyFirst\n ? Math.max(Math.min(pos, bodyLast + 1) - page, bodyFirst)\n : pos;\n case 'ArrowDown':\n return Math.min(pos + 1, layout.total - 1);\n case 'ArrowUp':\n return Math.max(pos - 1, 0);\n }\n }\n\n /** How many rows PageUp/PageDown move from grid position `pos`. */\n #pageRows(key: string, pos: number, layout: RowLayout, scroller: HTMLElement): number {\n if (this.rowHeight !== 'auto') {\n // Whole rows between the sticky header and pinned rows (each one row tall).\n const fit = Math.floor(scroller.clientHeight / this.#rowPx + 0.01);\n return Math.max(1, fit - 1 - layout.top - layout.bottom);\n }\n // The body rows that fit between the header and the pinned rows, from the\n // focused body row (or the body's first or last row).\n const view =\n scroller.clientHeight -\n this.#rowPx -\n this.#pinnedPx('top', layout) -\n this.#pinnedPx('bottom', layout);\n const bodyFirst = layout.position({ section: 'body', index: 0 });\n const from = Math.min(Math.max(pos - bodyFirst, 0), Math.max(layout.body - 1, 0));\n return this.#virtual.pageRows(from, key === 'PageDown', view);\n }\n\n /**\n * Selection keys, with a `selectionMode`: Space (or Shift+Space) toggles the\n * focused body row; in `multi` mode, Shift+ArrowUp/ArrowDown and\n * Shift+PageUp/PageDown move focus through the body and select from the\n * anchor to it, and Ctrl/Cmd+A selects every row. `true` if it took the key.\n */\n #selectionKey(\n event: KeyboardEvent,\n cell: HTMLElement,\n col: string,\n inHeader: boolean,\n scroller: HTMLElement,\n ): boolean {\n const mode = this.#mode();\n if (mode === 'none' || event.altKey) return false;\n const { key } = event;\n const command = event.ctrlKey || event.metaKey;\n const model = this.#table.model;\n if (command && !event.shiftKey && key.toLowerCase() === 'a') {\n if (mode !== 'multi') return false;\n // Not the page's text: the rows.\n event.preventDefault();\n this.#selectAll();\n return true;\n }\n if (command) return false;\n if (inHeader) {\n // Space on the select-all header does what its checkbox does.\n if (key !== ' ' || col !== SELECTION_COLUMN_ID || mode !== 'multi') return false;\n event.preventDefault();\n this.#toggleAll();\n return true;\n }\n const layout = layoutOf(model);\n const from = gridRowOf(cell.parentElement, layout);\n if (from?.section !== 'body') return false;\n if (key === ' ') {\n // Space would scroll the table.\n event.preventDefault();\n const id = model.rowAt(from.index)?.id;\n if (id !== undefined) this.#requestSelection(toggleRow(this.#selection.value, mode, id));\n return true;\n }\n if (\n !event.shiftKey ||\n mode !== 'multi' ||\n (key !== 'ArrowDown' && key !== 'ArrowUp' && key !== 'PageDown' && key !== 'PageUp')\n ) {\n return false;\n }\n event.preventDefault();\n // A range stays in the body: the header and pinned rows can't be selected.\n const bodyFirst = layout.position({ section: 'body', index: 0 });\n const pos = this.#verticalStep(key, layout.position(from), layout, scroller);\n const to = layout.at(Math.min(Math.max(pos, bodyFirst), bodyFirst + layout.body - 1));\n if (to?.section !== 'body' || to.index === from.index) return true;\n if (key.startsWith('Page')) {\n this.#virtual.scrollBy(this.#virtual.startOf(to.index) - this.#virtual.startOf(from.index));\n }\n const fromId = model.rowAt(from.index)?.id;\n const anchor =\n this.#anchorAt(model) ??\n (fromId === undefined ? undefined : { id: fromId, index: from.index });\n if (anchor) {\n const idAt = (index: number) => model.rowAt(index)?.id;\n const selection = selectRange([], anchor.index, to.index, idAt, false);\n this.#requestSelection({ selection, anchor: anchor.id });\n }\n this.#moveTo(to, col, model);\n return true;\n }\n\n /** Focus that lands in a cell (a click, or content inside it) makes that cell active. */\n readonly #onFocusin = (event: FocusEvent) => {\n // Tab into the grid landed on the scroll container (Firefox makes it a tab\n // stop): move on to the grid's one tab stop, the active cell. Only when focus\n // came from outside the grid: coming from inside means the user is leaving,\n // and sending them back would trap the keyboard.\n const scroller = event.currentTarget as HTMLElement;\n if (event.composedPath()[0] === scroller) {\n const from = event.relatedTarget;\n if (!(from instanceof Node && scroller.contains(from))) {\n this.#focusPending = true;\n this.requestUpdate();\n }\n return;\n }\n for (const target of event.composedPath()) {\n const cell = gridCell(target);\n if (cell?.dataset.col !== undefined) {\n const model = this.#table.model;\n const row =\n cell.getAttribute('role') === 'columnheader'\n ? HEADER\n : gridRowOf(cell.parentElement, layoutOf(model));\n const { col } = cell.dataset;\n const prev = this.#active;\n if (\n row &&\n (row.section !== prev?.section || row.index !== prev.index || col !== prev.col)\n ) {\n this.#active = { ...row, rowId: this.#gridRowId(model, row), col };\n this.requestUpdate();\n }\n return;\n }\n if (target === event.currentTarget) return;\n }\n };\n\n /**\n * `argus-cell-click`, then `argus-row-click`, for clicks in the body; then,\n * with a `selectionMode`, the click selects its row.\n */\n readonly #onClick = (event: MouseEvent) => {\n const path = event.composedPath();\n this.#activate(path);\n const mode = this.#mode();\n const target = mode === 'none' ? undefined : this.#selectableRowOf(path);\n if (!target) return;\n // A click in the checkbox column, beside the checkbox, toggles like it.\n const inSelectionCell = path.some(\n (t) => t instanceof HTMLElement && t.dataset.col === SELECTION_COLUMN_ID,\n );\n this.#clickRow(target, event, inSelectionCell || event.ctrlKey || event.metaKey);\n };\n\n /** Selects for a click on a row, through `clickSelection`. */\n #clickRow(target: SelectionTarget, event: MouseEvent, toggle: boolean): void {\n const model = this.#table.model;\n this.#requestSelection(\n clickSelection(\n this.#selection.value,\n this.#mode(),\n target,\n this.#anchorAt(model),\n { toggle, range: event.shiftKey },\n (index) => model.rowAt(index)?.id,\n ),\n );\n }\n\n /**\n * The checkboxes' handlers. The table owns their state: a click asks for a new\n * selection, and the render that always follows sets every box back to the\n * selection (`live()`), so a change a controlled host turns down unticks it\n * again. Not `preventDefault()`: for a real click the browser runs that render\n * inside the dispatch, then undoes the toggle after it, over the render. A\n * press leaves focus on the cell, so the grid's keys keep working.\n */\n readonly #checkboxHandlers: CheckboxHandlers = {\n row: (event) => {\n const index = Number((event.currentTarget as HTMLElement).dataset.row);\n const id = this.#table.model.rowAt(index)?.id;\n if (id !== undefined) this.#clickRow({ id, index }, event, true);\n this.requestUpdate();\n },\n all: () => {\n this.#toggleAll();\n this.requestUpdate();\n },\n press: (event) => {\n event.preventDefault();\n (event.currentTarget as HTMLElement).parentElement?.focus({ preventScroll: true });\n },\n };\n\n /** Selects every selectable row, keeping the others (with a `dataSource`: the loaded ones). */\n #selectAll(): void {\n const ids = this.#table.model.selectableIds();\n this.#requestSelection({\n selection: selectAll(this.#selection.value, ids),\n anchor: this.#anchor,\n });\n }\n\n /** The select-all checkbox: clears the selection when every row is selected, else selects all. */\n #toggleAll(): void {\n if (this.#checkAllState(this.#table.model) === 'all') {\n this.#requestSelection({ selection: [], anchor: this.#anchor });\n } else {\n this.#selectAll();\n }\n }\n\n /** The select-all checkbox, in the checkbox column of a `multi` table. */\n #checkAllOf(model: TableModel<T, CellContent>): CheckAll | undefined {\n if (!this.#selectionColumn || this.#mode() !== 'multi') return undefined;\n return { state: this.#checkAllState(model), handlers: this.#checkboxHandlers };\n }\n\n /**\n * Whether all, some or none of the selectable rows are selected. With `data`\n * it's worked out once per `selection`, `data` and `getRowId`, not on scroll;\n * with a `dataSource` every time, over the loaded rows, which eviction keeps few.\n */\n #checkAllState(model: TableModel<T, CellContent>): CheckAll['state'] {\n const count = (): CheckAll['state'] => {\n const ids = model.selectableIds();\n const selected = this.#selectedSet();\n const n = ids.reduce((sum, id) => (selected.has(id) ? sum + 1 : sum), 0);\n if (n === 0) return 'none';\n return n === ids.length ? 'all' : 'some';\n };\n if (this.#data.rows) return count();\n // Everything the rows of the model depend on: the data and what filters it.\n const key = [\n this.#selection.value,\n this.data,\n this.getRowId,\n this.#columns,\n this.#filters.value,\n this.#quickFilter,\n this.#visibility.value,\n ];\n const cached = this.#checkAll;\n if (cached?.key.length !== key.length || key.some((k, i) => k !== cached.key[i])) {\n this.#checkAll = { key, state: count() };\n }\n return this.#checkAll?.state ?? 'none';\n }\n\n /**\n * A Shift+press on a row in `multi` mode selects a range of rows, not the\n * page's text from the last click: no text selection, and the cell still\n * takes focus.\n */\n readonly #onMousedown = (event: MouseEvent) => {\n if (!event.shiftKey || event.button !== 0 || this.#mode() !== 'multi') return;\n const path = event.composedPath();\n if (!this.#selectableRowOf(path)) return;\n event.preventDefault();\n for (const target of path) {\n const cell = gridCell(target);\n if (cell) {\n cell.focus({ preventScroll: true });\n return;\n }\n }\n };\n\n /** `selectionMode`, with anything unknown read as `none`. */\n #mode(): SelectionMode {\n const mode = this.selectionMode;\n return mode === 'single' || mode === 'multi' ? mode : 'none';\n }\n\n /** Whether each rendered body row is selected; `undefined` without a `selectionMode`. */\n #selectedAt(model: TableModel<T, CellContent>): SelectedAt | undefined {\n if (this.#mode() === 'none') return undefined;\n const ids = this.#selectedSet();\n return (index) => {\n const id = model.rowAt(index)?.id;\n return id === undefined ? undefined : ids.has(id);\n };\n }\n\n /** `selection` as a set, rebuilt only when `selection` changes. */\n #selectedSet(): ReadonlySet<string> {\n const selection = this.#selection.value;\n if (this.#selectedIds?.of !== selection) {\n this.#selectedIds = { of: selection, ids: new Set(selection) };\n }\n return this.#selectedIds.ids;\n }\n\n /**\n * The loaded body row a pointer event is on, as a selection target. None for\n * the header, pinned rows, rows still loading, and presses on interactive\n * content in a cell (a button, a link, an input).\n */\n #selectableRowOf(path: readonly EventTarget[]): SelectionTarget | undefined {\n const row = path.find(\n (t): t is HTMLElement => t instanceof HTMLElement && t.getAttribute('role') === 'row',\n );\n if (!row || fromInteractive(path, row)) return undefined;\n const model = this.#table.model;\n const at = gridRowOf(row, layoutOf(model));\n if (at?.section !== 'body') return undefined;\n const id = model.rowAt(at.index)?.id;\n return id === undefined ? undefined : { id, index: at.index };\n }\n\n /** The anchor row and where it is now; `undefined` if it isn't in the rows (or not loaded). */\n #anchorAt(model: TableModel<T, CellContent>): SelectionTarget | undefined {\n const id = this.#anchor;\n const index = id === undefined ? undefined : model.indexOf(id);\n return id === undefined || index === undefined ? undefined : { id, index };\n }\n\n /**\n * Changes the selection through the controlled/uncontrolled rules, and moves\n * the anchor. A step that leaves the same rows selected fires nothing.\n */\n #requestSelection(step: SelectionStep | undefined): void {\n if (!step) return;\n this.#anchor = step.anchor;\n const old = this.#selection.value;\n if (sameSelection(step.selection, old)) return;\n const { value, applied } = this.#selection.request(step.selection);\n if (applied) {\n this.#appliedSelection = value;\n this.requestUpdate('selection', old);\n } else {\n fire(this, ROW_SELECT, { selection: value });\n }\n }\n\n /**\n * Fires `argus-cell-click` (when a cell is on the path), then `argus-row-click`,\n * for the body or pinned row on an event path. Clicks and Enter on a cell use\n * it. Rows that haven't loaded, the header and the checkbox column fire nothing.\n */\n #activate(path: EventTarget[]): void {\n let columnId: string | undefined;\n for (const target of path) {\n if (!(target instanceof HTMLElement)) continue;\n const role = target.getAttribute('role');\n if (role === 'gridcell') columnId = target.dataset.col;\n if (columnId === SELECTION_COLUMN_ID) return;\n if (role !== 'row') continue;\n const model = this.#table.model;\n const at = gridRowOf(target, layoutOf(model));\n if (!at || at.section === 'header') return;\n const { index } = at;\n if (at.section === 'body') {\n const row = model.rowAt(index);\n if (!row) return;\n if (columnId !== undefined) {\n fire(this, CELL_CLICK, {\n row: row.original,\n columnId,\n value: model.valueAt(index, columnId),\n });\n }\n fire(this, ROW_CLICK, { row: row.original, rowId: row.id, index });\n return;\n }\n const pinned = at.section;\n const row = model.pinnedRowAt(pinned, index);\n if (!row) return;\n if (columnId !== undefined) {\n fire(this, CELL_CLICK, {\n row: row.original,\n columnId,\n value: model.pinnedValueAt(pinned, index, columnId),\n pinned,\n });\n }\n fire(this, ROW_CLICK, { row: row.original, rowId: row.id, index, pinned });\n return;\n }\n }\n\n /** The id of a grid row: a body or pinned row's id; none for the header. */\n #gridRowId(model: TableModel<T, CellContent>, row: GridRow): string | undefined {\n switch (row.section) {\n case 'header':\n return undefined;\n case 'body':\n return this.#rowId(model, row.index);\n default:\n return model.pinnedRowAt(row.section, row.index)?.id;\n }\n }\n\n /** Makes a cell active and focuses it after the update. The keep-rendered rule renders its row. */\n #moveTo(row: GridRow, col: string, model: TableModel<T, CellContent>): void {\n this.#active = { ...row, rowId: this.#gridRowId(model, row), col };\n this.#focusPending = true;\n this.requestUpdate();\n }\n\n #focusActive(): void {\n const active = this.#active;\n if (!active) return;\n const col = CSS.escape(active.col);\n // aria-rowindex is unique across the grid: header, pinned and body rows.\n const index = layoutOf(this.#table.model).ariaRowIndex(active);\n const cell = this.renderRoot.querySelector<HTMLElement>(\n `[role='row'][aria-rowindex=\"${String(index)}\"] > [data-col=\"${col}\"]`,\n );\n if (!cell) return;\n cell.focus({ preventScroll: true });\n // A scaled body moves `ratio` px of rows per px scrolled, so the browser can't\n // scroll a body row into view: the virtualizer does, and the next update\n // (from its scroll) shows the row and scrolls sideways. Rows of different\n // heights too: rows measured on the way can move the row again, so it\n // scrolls until they're done.\n if (active.section === 'body' && (this.#virtual.scaled || this.rowHeight === 'auto')) {\n const layout = layoutOf(this.#table.model);\n const before = this.#rowPx + this.#pinnedPx('top', layout);\n if (this.#virtual.reveal(active.index, before, this.#pinnedPx('bottom', layout))) {\n this.#focusPending = true;\n return;\n }\n }\n cell.scrollIntoView({ block: 'nearest', inline: 'nearest' });\n }\n\n /**\n * Keeps the active cell valid after columns or rows change. In the body: on the\n * same row id when it still exists (it may have moved), else at the same\n * index, clamped. A data source row that isn't loaded (yet, or any more) keeps\n * its id. A pinned row stays at its index, clamped to its list. A row whose\n * section has no rows left gives way to the header, the default. If its row\n * went away while the grid had focus, focus follows to the replacement.\n */\n #reconcileActive(model: TableModel<T, CellContent>): void {\n const columns = model.columns;\n const first = columns[0];\n if (!first) {\n this.#active = undefined;\n return;\n }\n const prev = this.#active ?? { ...HEADER, rowId: undefined, col: first.id };\n const col = columns.some((c) => c.id === prev.col)\n ? prev.col\n : this.#columnInPlaceOf(model, prev.col, first.id);\n let { section, index, rowId } = prev;\n // The cell went away with its column while focused: focus its replacement.\n let moved = col !== prev.col && this.#active !== undefined;\n if (section === 'body' && rowId !== undefined) {\n const found = model.indexOf(rowId);\n const unloaded = index < model.rowCount && model.rowAt(index) === undefined;\n if (found !== undefined) {\n index = found;\n } else if (!unloaded) {\n index = Math.min(index, model.rowCount - 1);\n rowId = index >= 0 ? (model.rowAt(index)?.id ?? this.#placeholderId(index)) : undefined;\n moved = true;\n }\n } else if (section === 'top' || section === 'bottom') {\n const count = model.pinnedCount(section);\n if (index >= count) {\n index = count - 1;\n moved = true;\n }\n rowId = index >= 0 ? model.pinnedRowAt(section, index)?.id : undefined;\n }\n if (index < 0) {\n ({ section, index } = HEADER);\n rowId = undefined;\n }\n if (moved && this.matches(':focus-within')) this.#focusPending = true;\n if (\n section !== prev.section ||\n index !== prev.index ||\n rowId !== prev.rowId ||\n col !== prev.col ||\n !this.#active\n ) {\n this.#active = { section, index, rowId, col };\n }\n }\n\n /**\n * The shown column that takes a hidden column's place: the next one in the\n * column order, else the one before it. `fallback` for a column that is gone\n * altogether.\n */\n #columnInPlaceOf(model: TableModel<T, CellContent>, id: string, fallback: string): string {\n const all = model.allColumns;\n const at = all.findIndex((c) => c.id === id);\n if (at < 0) return fallback;\n const shown = (c: ColumnView<T, CellContent>) => !c.hidden;\n return (all.slice(at + 1).find(shown) ?? all.slice(0, at).findLast(shown))?.id ?? fallback;\n }\n\n /**\n * The width a resize starts from: the latest requested width (key presses can\n * come faster than renders), else the model's fixed width, else the rendered\n * width of a flex column.\n */\n #currentWidth(columnId: string, cell: HTMLElement): number {\n const sized = this.#sizing.value[columnId];\n if (sized !== undefined) return sized;\n const view = this.#table.model.columns.find((c) => c.id === columnId);\n return view && view.flex === undefined ? view.width : cell.getBoundingClientRect().width;\n }\n\n #direction(): 1 | -1 {\n return getComputedStyle(this).direction === 'rtl' ? -1 : 1;\n }\n\n /** Sets one column's width (clamped by core), through the controlled/uncontrolled rules. */\n #requestResize(columnId: string, width: number): void {\n this.#requestResizes(new Map([[columnId, width]]));\n }\n\n /**\n * Sets column widths (clamped by core) in one change, through the\n * controlled/uncontrolled rules. One `argus-column-resize` per column that\n * changes, each with the whole new sizing.\n */\n #requestResizes(widths: ReadonlyMap<string, number>): void {\n const model = this.#table.model;\n const old = this.#sizing.value;\n const targets: [string, number][] = [];\n for (const [columnId, width] of widths) {\n const target = model.nextSizing(columnId, width)?.[columnId];\n if (target !== undefined && target !== old[columnId]) targets.push([columnId, target]);\n }\n if (targets.length === 0) return;\n const { value, applied } = this.#sizing.request({ ...old, ...Object.fromEntries(targets) });\n const details = targets.map(([columnId, width]) => ({ columnId, width, sizing: value }));\n if (applied) {\n // Only the latest width per column fires, all with the latest sizing.\n for (const detail of this.#appliedResizes.values()) detail.sizing = value;\n for (const detail of details) this.#appliedResizes.set(detail.columnId, detail);\n this.requestUpdate('columnSizing', old);\n } else {\n for (const detail of details) fire(this, COLUMN_RESIZE, detail);\n }\n }\n\n /**\n * Pins or unpins a column through the controlled/uncontrolled rules. Starts\n * from the latest requested pins, so requests can come faster than renders.\n */\n #requestPin(columnId: string, pin: ColumnPin | false): void {\n const old = this.#pinning.value;\n const next = this.#table.model.nextPinning(columnId, pin, old);\n if (!next) return;\n const { value, applied } = this.#pinning.request(next);\n if (applied) {\n for (const detail of this.#appliedPins.values()) detail.pinning = value;\n this.#appliedPins.set(columnId, { columnId, pin, pinning: value });\n this.requestUpdate('columnPinning', old);\n } else {\n fire(this, COLUMN_PIN, { columnId, pin, pinning: value });\n }\n }\n\n /** Hides or shows a column through the controlled/uncontrolled rules. */\n #requestHide(columnId: string, hidden: boolean): void {\n const old = this.#visibility.value;\n const next = this.#table.model.nextVisibility(columnId, hidden, old);\n if (!next) return;\n const { value, applied } = this.#visibility.request(next);\n if (applied) {\n for (const detail of this.#appliedHides.values()) detail.visibility = value;\n this.#appliedHides.set(columnId, { columnId, hidden, visibility: value });\n this.requestUpdate('columnVisibility', old);\n } else {\n fire(this, COLUMN_HIDE, { columnId, hidden, visibility: value });\n }\n }\n\n /** Sets or clears a column's filter through the controlled/uncontrolled rules. */\n #requestFilter(columnId: string, filter: ColumnFilter | undefined): void {\n const old = this.#filters.value;\n const next = this.#table.model.nextFilters(columnId, filter, old);\n if (!next) return;\n const { value, applied } = this.#filters.request(next);\n if (applied) {\n for (const detail of this.#appliedFilters.values()) detail.filters = value;\n this.#appliedFilters.set(columnId, { columnId, filter, filters: value });\n this.requestUpdate('columnFilters', old);\n } else {\n fire(this, COLUMN_FILTER, { columnId, filter, filters: value });\n }\n }\n\n /**\n * Says how many rows the filters leave (\"42 rows\"). With a `dataSource` the count\n * isn't known until the first page answers, so nothing is said.\n */\n #announceRowCount(model: TableModel<T, CellContent>): void {\n if (this.#data.rows) return;\n const n = model.rowCount;\n announce(this.ownerDocument, n === 1 ? '1 row' : `${String(n)} rows`);\n }\n\n /**\n * Moves a column to position `to` among the shown data columns (within its pin group),\n * through the controlled/uncontrolled rules. Starts from the latest requested\n * order, so moves can come faster than renders. `false` if it can't move there.\n */\n #requestReorder(columnId: string, to: number): boolean {\n const old = this.#order.value;\n const next = this.#table.model.nextOrder(columnId, to, old);\n if (!next) return false;\n const { value, applied } = this.#order.request(next);\n if (applied) {\n for (const detail of this.#appliedReorders.values()) detail.order = value;\n this.#appliedReorders.set(columnId, { columnId, order: value });\n this.requestUpdate('columnOrder', old);\n } else {\n fire(this, COLUMN_REORDER, { columnId, order: value });\n }\n return true;\n }\n\n /** Alt+Shift+Arrow on a header: one step toward the start (-1) or the end (1). */\n #moveByKey(columnId: string, step: 1 | -1): void {\n const model = this.#table.model;\n // From the latest requested order, so presses can come faster than renders.\n // Positions count the shown columns: hidden ones keep their place.\n const shown = new Set(model.columns.map((c) => c.id));\n const from = model\n .orderOf(this.#order.value)\n .filter((id) => shown.has(id))\n .indexOf(columnId);\n const view = model.columns.find((c) => c.id === columnId);\n if (from < 0 || !view) return;\n if (!this.#requestReorder(columnId, from + step)) return;\n // The header node moves, which drops its focus: focus it again once rendered.\n this.#focusPending = true;\n this.#announceMove ??= { id: columnId, from: view.colIndex };\n this.requestUpdate();\n }\n\n /** Tells screen readers where a column moved from the keyboard went. */\n #announceMoved(model: TableModel<T, CellContent>, move: { id: string; from: number }): void {\n const view = model.columns.find((c) => c.id === move.id);\n if (!view || view.colIndex === move.from) return;\n const header = this.renderRoot.querySelector(\n `[role='columnheader'][data-col=\"${CSS.escape(move.id)}\"] > slot`,\n );\n const name =\n header instanceof HTMLSlotElement\n ? header\n .assignedNodes({ flatten: true })\n .map((n) => n.textContent)\n .join('')\n .trim()\n : '';\n announce(\n this.ownerDocument,\n `${name || move.id} moved to column ${String(view.colIndex)} of ${String(model.columns.length)}`,\n );\n }\n\n /** A press on a reorderable header: becomes a drag once the pointer moves. */\n #startReorder(down: PointerEvent): void {\n const cell = down\n .composedPath()\n .find(\n (t): t is HTMLElement =>\n t instanceof HTMLElement && t.getAttribute('role') === 'columnheader',\n );\n const columnId = cell?.dataset.moveCol;\n if (!cell || columnId === undefined || !canStartReorder(down, cell)) return;\n const scroller = this.renderRoot.querySelector<HTMLElement>('[part~=\"table\"]');\n if (!scroller) return;\n const pin = this.#table.model.columns.find((c) => c.id === columnId)?.pin;\n startReorderDrag(cell, down, {\n scroller,\n targetAt: (x) => dropTarget(this.#dropSlots(pin), columnId, x, this.#direction()),\n scrollArea: () => (pin === undefined ? this.#scrollArea(scroller) : undefined),\n onStart: () => {\n this.#drag = { columnId, target: undefined };\n this.requestUpdate();\n },\n onTarget: (target) => {\n this.#drag = { columnId, target };\n this.requestUpdate();\n },\n onDrop: (target) => {\n this.#drag = undefined;\n if (target && this.#requestReorder(columnId, target.to)) {\n // The header node moves, which drops its focus: focus it again once rendered.\n if (this.matches(':focus-within')) this.#focusPending = true;\n }\n this.requestUpdate();\n },\n onCancel: () => {\n this.#drag = undefined;\n this.requestUpdate();\n },\n });\n }\n\n /**\n * The rendered headers of one pin group, with their positions in the whole\n * order (which leaves out the checkbox column).\n */\n #dropSlots(pin: ColumnView<T, CellContent>['pin']): DropSlot[] {\n const slots: DropSlot[] = [];\n const columns = this.#table.model.columns.filter((c) => c.kind === 'data');\n columns.forEach((c, index) => {\n if (c.pin !== pin) return;\n const cell = this.renderRoot.querySelector(\n `[role='columnheader'][data-col=\"${CSS.escape(c.id)}\"]`,\n );\n if (cell) slots.push({ id: c.id, index, rect: cell.getBoundingClientRect() });\n });\n return slots;\n }\n\n /** Where the scrolling columns show: the scroller's inside, less the pinned columns. */\n #scrollArea(scroller: HTMLElement): { left: number; right: number } {\n const columns = this.#table.model.columns;\n const width = (side: 'start' | 'end') =>\n columns.reduce((sum, c) => (c.pin === side ? sum + c.width : sum), 0);\n const ltr = this.#direction() === 1;\n const left = scroller.getBoundingClientRect().left + scroller.clientLeft;\n return {\n left: left + width(ltr ? 'start' : 'end'),\n right: left + scroller.clientWidth - width(ltr ? 'end' : 'start'),\n };\n }\n\n /** asc → desc → unsorted, through the controlled/uncontrolled rules. */\n #requestSort(columnId: string): void {\n const next = this.#table.model.nextSorting(columnId);\n if (next) this.#applySorting(next);\n }\n\n /**\n * A plugin's sort: by a column in a direction, or (`null`) cleared if it is by\n * that column. Only sortable columns, and only a change.\n */\n #setSort(columnId: string, direction: 'asc' | 'desc' | null): void {\n const view = this.#table.model.columns.find((c) => c.id === columnId);\n if (view?.kind !== 'data' || !view.sortable) return;\n const sorted = view.sorted === false ? null : view.sorted;\n if (direction === sorted) return;\n if (direction === null) this.#applySorting([]);\n else this.#applySorting([{ id: columnId, desc: direction === 'desc' }]);\n }\n\n /** A new sort order, through the controlled/uncontrolled rules. */\n #applySorting(next: SortState): void {\n const old = this.#sorting.value;\n const { value, applied } = this.#sorting.request(next);\n if (applied) {\n this.#appliedSort = value;\n this.requestUpdate('sorting', old);\n } else {\n fire(this, SORT_CHANGE, { sorting: value });\n }\n }\n\n /**\n * A data column as plugins see it. Header functions call this on every\n * render, so the views are indexed by id once per new column list.\n */\n #columnInfo(id: string): ColumnInfo | undefined {\n const columns = this.#table.model.allColumns;\n if (this.#columnsById?.of !== columns) {\n this.#columnsById = { of: columns, byId: new Map(columns.map((c) => [c.id, c])) };\n }\n const view = this.#columnsById.byId.get(id);\n if (view?.kind !== 'data') return undefined;\n return {\n id,\n sortable: view.sortable,\n resizable: view.resizable,\n pinnable: view.pinnable,\n hideable: view.hideable,\n pin: view.pin,\n hidden: view.hidden,\n width: view.width,\n sorted: view.sorted === false ? undefined : view.sorted,\n filter: view.filter,\n filterValue: this.#filters.value[id],\n };\n }\n\n /** The header or cell an event happened in, for plugins. */\n #cellTarget(event: Event): CellTarget | undefined {\n for (const target of event.composedPath()) {\n const cell = gridCell(target);\n const columnId = cell?.dataset.col;\n if (!cell || columnId === undefined) continue;\n const model = this.#table.model;\n const row =\n cell.getAttribute('role') === 'columnheader'\n ? HEADER\n : gridRowOf(cell.parentElement, layoutOf(model));\n if (!row) return undefined;\n return {\n section: row.section,\n columnId,\n rowIndex: row.index,\n rowId: this.#gridRowId(model, row),\n };\n }\n return undefined;\n }\n\n #observeProbe(): void {\n const probe = this.renderRoot.querySelector('.probe');\n if (!probe) return;\n this.#probeObserver ??= new ResizeObserver(() => {\n this.#measureRowHeight();\n });\n this.#probeObserver.observe(probe);\n }\n\n /** The height of the rows pinned to one side: one row each, or measured with `rowHeight: 'auto'`. */\n #pinnedPx(side: 'top' | 'bottom', layout: RowLayout): number {\n const count = side === 'top' ? layout.top : layout.bottom;\n if (this.rowHeight !== 'auto' || count === 0) return count * this.#rowPx;\n return Math.max(this.#rowMeasure.pinned[side], count * this.#rowPx);\n }\n\n /**\n * `rowHeight: 'auto'`: reads the heights of the rendered rows, after their\n * content has rendered. Returns whether any changed (an update is requested).\n */\n #measureRows(): boolean {\n const { rows, pinnedChanged } = this.#rowMeasure.read(this.renderRoot);\n const resized = this.#virtual.measureRows(rows);\n if (pinnedChanged) this.requestUpdate();\n return resized || pinnedChanged;\n }\n\n /** Reads the resolved row height, so themes and density change the virtualizer too. */\n #measureRowHeight(): void {\n const probe = this.renderRoot.querySelector('.probe');\n const px = probe?.getBoundingClientRect().height ?? 0;\n if (px > 0 && Math.abs(px - this.#rowPx) > 0.01) {\n this.#rowPx = px;\n this.requestUpdate();\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'argus-table': ArgusTable;\n }\n}\n"],"mappings":"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"}