/** * DOM renderer for one summary band. * * A *band* is one horizontal strip of summary rows anchored to an edge of the * grid body — there are up to four (top/bottom × sticky/in-content), each an * independent instance of this class. * * ### Layout * The band mirrors the grid's three-panel structure exactly, so a summary cell * lines up with its column with no measurement and no per-frame bookkeeping: * * ```text * .pg-summary * .pg-summary__region--left width: var(--pg-left-panel-width) * .pg-summary__region--center flex; overflow hidden * .pg-summary__region-inner translateX(var(--pg-scroll-x)) * .pg-summary__region--right width: var(--pg-right-panel-width) * .pg-summary__vscroll-spacer width: var(--pg-scrollbar-v-live-width) * ``` * * Four grid features therefore need no code here at all: * - **Column pinning** — the same `--pg-left/right-panel-width` variables the * header and body panels use. * - **Horizontal scrolling** — the same `translateX(var(--pg-scroll-x))` the * center header inner uses. * - **Column resizing** — cells carry `data-col-id`, so `ColumnStyleManager`'s * generated width rules apply to them the instant a drag updates them. * - **Column visibility** — hidden columns are simply absent from the column * lists the band is rendered with. * * ### Reconciliation * A full rebuild happens only when the band's *structure* changes — the row set, * the columns in a region, the virtual column window, the gutters. A plain value * change (the common case, once per data refresh) patches text content in place, * so scrolling a grid with summary rows allocates nothing and lays out nothing. * * @packageDocumentation */ import type { ColumnDef } from '../types/column.types'; import type { ResolvedSummaryRow } from './summary-model'; import { SummaryPosition, type SummaryRowSnapshot } from './summary.types'; /** A row definition paired with its freshly computed values. */ export interface SummaryBandRow { /** The resolved definition — supplies per-cell renderers, classes and spans. */ readonly def: ResolvedSummaryRow; /** The computed values for this refresh. */ readonly snapshot: SummaryRowSnapshot; } /** * Everything about the current column layout the band needs in order to line up * with the header and body. * * Supplied by `GridRenderer` from values it has already computed for the header, * so the band never derives geometry of its own and can never disagree. */ export interface SummaryBandLayout { /** Left-pinned columns, in order. */ readonly leftCols: readonly ColumnDef[]; /** The center columns to render — the virtual window slice, or all of them when a `colSpan` is present. */ readonly centerCols: readonly ColumnDef[]; /** Right-pinned columns, in order. */ readonly rightCols: readonly ColumnDef[]; /** Width of the leading spacer standing in for center columns before the window. */ readonly centerLeftSpacerW: number; /** Width of the trailing spacer standing in for center columns after the window. */ readonly centerRightSpacerW: number; /** Whether the grid shows a leading checkbox gutter. */ readonly showCheckboxes: boolean; /** Whether the grid shows a leading serial-number gutter. */ readonly showSerialNumber: boolean; /** Whether interior vertical grid lines are on. */ readonly showVerticalBorders: boolean; /** Whether an auto-group column occupies the start of the center region. */ readonly hasGroupColumn: boolean; /** Width of that auto-group column, in px. */ readonly groupColWidth: number; /** Whether the left pinned panel is displayed at all. */ readonly hasLeftPanel: boolean; /** Whether the right pinned panel is displayed at all. */ readonly hasRightPanel: boolean; /** Resolved width of a column, for sizing `colSpan` cells. */ readonly getColumnWidth: (colId: string) => number; } /** * Renders and maintains one summary band. * * Owns no listeners and no timers — it is pure presentation driven by * `GridRenderer`'s frame, which is what makes {@link destroy} a plain DOM * detach with no leak surface. */ export declare class SummaryRowRenderer { private readonly position; private readonly sticky; private bandEl; private readonly regionEls; private bindings; /** * Fingerprint of the structure currently painted. A mismatch forces a rebuild; * a match means only values can have changed. @see {@link buildStructureKey} */ private structureKey; /** Total painted height in px, cached so `GridRenderer` need not measure the DOM. */ private height; /** * @param position - Which edge this band is anchored to. * @param sticky - `true` for the docked band, `false` for the in-content one. */ constructor(position: SummaryPosition.Top | SummaryPosition.Bottom, sticky: boolean); /** * Creates the band's scaffolding and inserts it into `hostEl`. * * @param hostEl - Container the band lives in — `.pg-grid-main` for a sticky * band, the in-content overlay for a non-sticky one. * @param beforeEl - Insert before this child instead of appending. A sticky * band is a flex item whose *position among its siblings* is * its position on screen, so a top band must land ahead of * the body rather than after it. */ mount(hostEl: HTMLElement, beforeEl?: HTMLElement | null): void; /** * Paints the band. * * @param rows - Rows belonging to this band, in paint order. * @param layout - The current column layout. */ render(rows: readonly SummaryBandRow[], layout: SummaryBandLayout): void; /** * Total painted height in px. * * `GridRenderer` uses this for two things: reserving the flex band's own * height, and — for a non-sticky band — extending the scrollable content * height so the band occupies real scroll space rather than overlaying rows. */ getHeight(): number; /** The band's root element, or `null` before {@link mount}. */ getElement(): HTMLElement | null; /** * Vertically offsets a non-sticky band so it tracks the scrolling content. * * Computed by `GridRenderer` in JS doubles and always within a viewport of * zero, so it never hits the float32 rasterisation limit that forces the data * rows through origin rebasing (see `panels.css.ts`). Written only on change: * `setProperty` invalidates style for the whole subtree, and this runs every * scroll frame. * * @param offsetY - Screen-space Y of the band's top edge, relative to the body viewport. * @param visible - `false` when the band has scrolled fully out of view. */ setInlineOffset(offsetY: number, visible: boolean): void; /** Detaches the band and releases every retained element. */ destroy(): void; /** Drops every rendered row and its retained bindings. */ private clear; /** * Rebuilds every row in every region. * * Each region is assembled into a `DocumentFragment` and attached once, so a * band with three rows across three regions costs three DOM insertions rather * than one per cell. */ private rebuild; /** Builds one row's slice for one region, registering each cell's binding. */ private buildRowElement; /** Builds one cell and returns its binding. */ private buildCell; /** * Updates values in place, touching only the cells whose display string or * tooltip actually changed. * * This is the path every ordinary data refresh takes, so it does no * allocation, no element creation, and — because `textContent` on an existing * text node does not change the box tree — no layout beyond the text itself. */ private patch; } //# sourceMappingURL=summary-row-renderer.d.ts.map