import type { ColumnDefInput } from '../types/column.types'; import type { ColumnModel } from '../core/column-model'; import type { IconRenderer } from '../icons/icon-renderer'; /** * Modal "Choose Columns" dialog — the target of the column menu's * `Visibility ▸ Column Chooser…` item. * * Renders the grid's columns as a tree that mirrors the header's column-group * structure: any `ColumnDef` with a `children` array becomes an * expand/collapse group node with a tri-state checkbox that toggles all of its * descendant columns; every other column is a flat row with a checkbox and its * header label. A search box filters by header text. * * The component owns only DOM + view state (expanded groups, search term). * Visibility itself is delegated to {@link ColumnModel.setColumnVisible}, so the * grid stays the single source of truth. Every visual is class-driven — all * colors, spacing, radii and typography come from theme CSS variables (see * `column-chooser.css.ts`); the component sets no inline styles. */ export declare class ColumnChooser { private readonly columnModel; private readonly iconRenderer; /** * The owning grid's container. Used only to resolve the portal host the * dialog is appended to, so it wears its own grid's theme rather than * whichever grid last wrote to the document root. * * Optional for standalone use; the dialog then mounts to `
` and * resolves whatever palette is mirrored there. */ private readonly ownerEl?; private overlayEl; private dialogEl; private treeEl; /** * The "Select all" checkbox, kept so {@link syncSelectAll} can re-state it * without rebuilding the row it lives in. * * It sits *outside* the tree, so the wholesale `renderTree` rebuild never * touches it — which is why it needs its own sync step rather than being * regenerated like every other checkbox here. */ private selectAllBoxEl; private selectAllRowEl; /** Original, still-nested column definitions used as the tree's structure. */ private columns; /** Group ids currently expanded in the tree. */ private readonly expanded; /** Lower-cased search term; empty shows everything. */ private searchTerm; private readonly boundKeydown; private readonly boundOutsideDown; constructor(columnModel: ColumnModel, iconRenderer: IconRenderer, /** * The owning grid's container. Used only to resolve the portal host the * dialog is appended to, so it wears its own grid's theme rather than * whichever grid last wrote to the document root. * * Optional for standalone use; the dialog then mounts to `` and * resolves whatever palette is mirrored there. */ ownerEl?: HTMLElement | undefined); /** * Opens the dialog for the given (nested) column definitions. Re-opening * while already open rebuilds it. Groups are expanded by default so the user * sees the full structure immediately. * * @param columns - The grid's top-level `ColumnDef[]`, groups included. */ open(columns: ColumnDefInput[]): void; /** Closes the dialog and detaches listeners. Safe when already closed. */ close(): void; /** Permanently disposes the component. */ destroy(): void; private build; /** Rebuilds the tree body from the current search term and expanded state. */ private renderTree; /** * Builds the "Select all" row that sits between the search box and the tree. * * A single affordance for the most common two actions in this dialog — * "show me everything again" and "clear the lot so I can pick a few" — which * otherwise cost one click per column. */ private buildSelectAllRow; /** * Re-derives the select-all checkbox from the columns the tree is currently * showing. * * Tri-state, and deliberately scoped to the *listed* columns rather than to * every column in the grid: with a search term active the row the user is * looking at describes what they can see, and toggling it acts on exactly * that. A checkbox reading "all selected" while a filtered list showed three * unticked rows would be describing something off screen. * * Always-visible columns are excluded from the count as well as from the * write — they can never be unticked, so including them would leave the box * stuck at "some" no matter what the user did. A list of nothing but * always-visible columns therefore disables the row entirely. */ private syncSelectAll; /** * Shows or hides every listed column in one act. * * "All visible" hides them; anything else — none or some — shows them all, * so a half-ticked box always resolves upward. That matches the group * checkbox's rule, and means the destructive direction is only ever reached * from a state the user can see is complete. */ private toggleSelectAll; /** * The live columns the tree is currently rendering, in display order. * * Mirrors the filtering in {@link buildGroupNode} and {@link buildLeafNode} * exactly — a group filtered out by the search contributes nothing, and a * group kept by a header match still filters its own leaves — so the * select-all box can never describe a different set from the rows beneath it. */ private listedLeaves; /** * Binds pointer *and* keyboard activation to an element acting as a control. * * These checkboxes are `` with a tabindex, which makes * them focusable but not operable: a real `` fires `click` for Space, * a span does not. Without this a keyboard user can reach every checkbox in * the dialog and toggle none of them. * * Space is the checkbox's own binding and Enter is accepted too, matching the * latitude every native control allows. The default is suppressed for both — * Space would otherwise scroll the dialog out from under the row just toggled. * * Propagation is stopped in both directions so a checkbox inside a group row * cannot also trigger the row-level label handler sitting beside it. */ private onActivate; /** * Builds a group or leaf node (recursively), or `null` when it is filtered * out by the current search term. */ private buildNode; private buildGroupNode; private buildLeafNode; /** A tree row. Hierarchical indent is handled by the nested `__children` container in CSS — no inline geometry. */ private makeRow; private makeLabel; /** * A themed tri-state checkbox. `checked`/`indeterminate` drive modifier * classes; the tick glyph comes from the icon registry so it themes with the * rest of the grid. `disabled` covers always-visible columns. */ private makeCheckbox; /** Builds a group checkbox reflecting the aggregate visibility of its leaves. */ private makeGroupCheckbox; private setGroupVisible; /** Live {@link ColumnModel} leaves that belong to a (possibly nested) group. */ private groupLeaves; /** * Resolves a nested (possibly un-normalized) leaf definition to the live * column held by {@link ColumnModel}. Matches by `colId` first, then falls * back to `field` since the original defs may predate colId normalization. */ private resolveLeaf; /** `true` when a group has at least one leaf whose header matches the search. */ private groupMatches; private groupId; private collectGroupIds; } //# sourceMappingURL=column-chooser.d.ts.map