argus-table 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -230,7 +230,7 @@ var ArgusTable = class ArgusTable extends LitElement {
230
230
  col = 0;
231
231
  if (corner) {
232
232
  pos = 0;
233
- scroller.scrollTop = 0;
233
+ this.#virtual.scrollToEdge("start");
234
234
  }
235
235
  break;
236
236
  case "End":
@@ -242,7 +242,7 @@ var ArgusTable = class ArgusTable extends LitElement {
242
242
  event.preventDefault();
243
243
  const row = layout.at(pos) ?? HEADER;
244
244
  if (key.startsWith("Page") && from.section === "body" && row.section === "body") this.#virtual.scrollBy((row.index - from.index) * this.#rowPx);
245
- if (corner && key === "End" && row.section === "bottom") scroller.scrollTop = scroller.scrollHeight;
245
+ if (corner && key === "End" && row.section === "bottom") this.#virtual.scrollToEdge("end");
246
246
  const target = columns[Math.min(Math.max(col, 0), columns.length - 1)];
247
247
  if (target) this.#moveTo(row, target.id, model);
248
248
  };
@@ -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 scroller.scrollTop = 0;\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 scroller.scrollTop = scroller.scrollHeight;\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 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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"}