import '../../components/button/button.js';
import '../../components/checkbox/checkbox.js';
import '../../components/divider/divider.js';
import '../../components/dropdown-item/dropdown-item.js';
import '../../components/dropdown/dropdown.js';
import '../../components/icon/icon.js';
import '../../components/input/input.js';
import '../../components/option/option.js';
import '../../components/pagination/pagination.js';
import '../../components/popover/popover.js';
import '../../components/select/select.js';
import '../../components/spinner/spinner.js';
import WebAwesomeElement from '../../internal/webawesome-element.js';
import { type SortingState } from '@tanstack/table-core';
import { type PropertyValues, type TemplateResult } from 'lit';
import '../date-input/date-input.js';
type Row = Record<string, unknown>;
/** A single column definition for `<wa-data-grid>`. */
export interface DataGridColumn {
    /** Dot-path accessor into the row object, e.g. `'user.name'`. Doubles as the column id when `id` is omitted. */
    field?: string;
    /** Explicit column id. Required for columns without a `field` (e.g. an actions or computed column). */
    id?: string;
    /**
     * Computes the cell value from the row (e.g. a derived total). Unlike a `formatter`, which only changes how a
     * cell renders, the computed value drives sorting, filtering, searching, clipboard copy, and CSV export. Takes
     * precedence over `field`; give the column an `id`.
     */
    value?: (row: Row) => unknown;
    /** Header text. */
    label?: string;
    /** Horizontal alignment of the cell content. */
    align?: 'start' | 'center' | 'end';
    /** Horizontal alignment of the header content. Defaults to `align`. */
    headerAlign?: 'start' | 'center' | 'end';
    /** Whether the column can be sorted. Defaults to `true` for columns with a `field` or `value` accessor. */
    sortable?: boolean;
    /**
     * A built-in sort algorithm: `'alphanumeric'` (the default; mixed strings and numbers), `'alphanumericCaseSensitive'`,
     * `'text'` (faster, strings only), `'textCaseSensitive'`, `'datetime'` (for `Date` objects or date
     * strings), or `'basic'` (fastest, `>`/`<` comparison). Ignored when a `comparator` is provided.
     */
    sortFn?: 'alphanumeric' | 'alphanumericCaseSensitive' | 'text' | 'textCaseSensitive' | 'datetime' | 'basic';
    /** Where `undefined`/`null` values sort. `'first'`/`'last'` or `1`/`-1`; `false` (default) leaves them in place. */
    sortUndefined?: false | -1 | 1 | 'first' | 'last';
    /** When `true`, this column's first sort click is descending (defaults to the grid-level `sort-desc-first`). */
    sortDescFirst?: boolean;
    /** Whether the global search box matches this column. Defaults to `true` for columns with a `field` or `value`. */
    searchable?: boolean;
    /** Whether the column shows a per-column filter input. */
    filterable?: boolean;
    /**
     * How the column's filter matches, mapping to a table-core filter function. `'text'` (the default) is a
     * case-insensitive substring match (`includesString`). `'equals'` is an exact string match (`equalsString`).
     * `'number-range'` matches a `[min, max]` numeric window (`inNumberRange`) and renders min/max inputs.
     * `'date-range'` matches a `[from, to]` date window and renders two date inputs. `'set'` keeps rows whose cell
     * value is one of the chosen values and renders a multi-select of distinct values. For array-valued cells,
     * `'includes-any'` keeps rows whose array contains any chosen value (`arrIncludesSome`) and `'includes-all'`
     * requires every chosen value (`arrIncludesAll`).
     */
    filterType?: 'text' | 'equals' | 'number-range' | 'date-range' | 'set' | 'includes-any' | 'includes-all';
    /**
     * A custom filter predicate. Receives the cell value, the active filter value, and the row; return `true` to keep
     * the row. Takes precedence over `filterType`. Runs client-side only.
     */
    filterFn?: (value: unknown, filterValue: unknown, row: Row) => boolean;
    /**
     * The options shown in a `set`/`includes-*` filter picker, replacing the facets the grid computes from its rows.
     * Each option filters by `value`, displays `label` (defaults to the value), and shows `count` next to it when
     * provided. Options render in the order given. Required for a value picker in server mode, where the grid only
     * holds one page and can't derive the distinct values itself; also useful client-side to control ordering or
     * include values no loaded row has.
     */
    filterOptions?: {
        value: string;
        label?: string;
        count?: number;
    }[];
    /** Whether the column starts hidden. */
    hidden?: boolean;
    /** Whether the user can toggle the column's visibility in the columns menu. Defaults to `true`. */
    hideable?: boolean;
    /** Whether the column can be resized. Overrides the grid-level `resizable` setting. */
    resizable?: boolean;
    /** Whether the column can be drag-reordered. Defaults to the grid-level `reorderable` setting. */
    movable?: boolean;
    /** Whether the column can be pinned to an edge. Defaults to the grid-level `pinnable` setting. */
    pinnable?: boolean;
    /**
     * Pins the column to an edge initially. The user can still unpin it (when `pinnable`); use `pinColumn()` for
     * programmatic control. Pinned columns without an explicit `width` freeze their rendered width on first paint.
     */
    pinned?: 'left' | 'right';
    /** Initial column width in pixels. Ignored when `flex` is set. */
    width?: number;
    /** Minimum column width in pixels (resize + flex clamp). */
    minWidth?: number;
    /** Maximum column width in pixels (resize + flex clamp). */
    maxWidth?: number;
    /**
     * Flex-grow ratio. When set, the column shares leftover horizontal space proportionally with other flex columns
     * (respecting `minWidth`/`maxWidth`) instead of using a fixed `width`.
     */
    flex?: number;
    /**
     * Custom comparator for client-side sorting. Receives the two accessor values (and their rows); return a negative,
     * zero, or positive number for ascending order (the grid applies the descending direction itself).
     */
    comparator?: (a: unknown, b: unknown, rowA: Row, rowB: Row) => number;
    /**
     * Renders cell content. A string renders as escaped text; a Lit `TemplateResult` or `Node` renders rich content.
     * Runs on every render, so a fresh `Node` replaces the previous one each time. Return a template for diffed
     * updates, or reuse the same `Node` instance when the cell must keep its DOM state.
     */
    formatter?: (value: unknown, row: Row) => string | TemplateResult | Node;
    /**
     * Footer content: a string, or a function given the filtered rows across every page (top-level rows for tree data,
     * data rows when grouped, the loaded page in server mode). Any visible column with a footer adds a pinned footer row.
     */
    footer?: string | ((rows: Row[]) => string | TemplateResult | Node);
    /**
     * How the column aggregates on grouped rows (with the grid's `group-by`). A table-core built-in or a function that
     * takes the group's values and rows. Aggregates render through `formatter` (its `row` arg is the group's first row);
     * columns without an `aggregation` show empty group cells.
     */
    aggregation?: 'sum' | 'min' | 'max' | 'extent' | 'mean' | 'median' | 'unique' | 'uniqueCount' | 'count' | ((values: unknown[], rows: Row[]) => unknown);
    /**
     * Renders aggregated cells on group rows, receiving the aggregate value and the group's data rows. Falls back to
     * `formatter` (which only sees the group's first row) when omitted.
     */
    aggregatedFormatter?: (value: unknown, rows: Row[]) => string | TemplateResult | Node;
    /** A CSS class (or classes) applied to every cell in the column. Use for alignment/emphasis hooks. */
    cellClass?: string | ((value: unknown, row: Row) => string);
}
/** The request passed to a `dataSource` callback (and the `wa-data-request` event) in server mode. */
export interface DataGridRequest {
    sort: {
        id: string;
        desc: boolean;
    }[];
    filters: {
        id: string;
        value: unknown;
    }[];
    search: string;
    page: number;
    pageSize: number;
    signal: AbortSignal;
}
/** The response a `dataSource` callback returns. */
export interface DataGridResponse {
    rows: Row[];
    total: number;
}
/** A serializable snapshot of the grid's user-adjustable state. Safe to `JSON.stringify` and persist. */
export interface DataGridState {
    version: 1;
    columnOrder?: string[];
    columnWidths?: Record<string, number>;
    columnVisibility?: Record<string, boolean>;
    columnPinning?: {
        left: string[];
        right: string[];
    };
    sort?: {
        id: string;
        desc: boolean;
    }[];
    filters?: {
        id: string;
        value: unknown;
    }[];
    search?: string;
    selectedKeys?: (string | number)[];
    expandedKeys?: (string | number)[];
    page?: number;
    pageSize?: number;
}
/**
 * @summary Data grids display tabular data with sorting, selection, filtering, pinning, tree data, grouping with
 *  aggregation, column footers, expandable rows, pagination, CSV export, full keyboard navigation, and virtualization
 *  for large datasets.
 * @documentation https://webawesome.com/docs/components/data-grid
 * @status experimental
 * @since 3.11
 *
 * @dependency wa-checkbox
 * @dependency wa-icon
 * @dependency wa-button
 * @dependency wa-input
 * @dependency wa-select
 * @dependency wa-option
 * @dependency wa-dropdown
 * @dependency wa-dropdown-item
 * @dependency wa-divider
 * @dependency wa-pagination
 * @dependency wa-spinner
 *
 * @slot empty - Content shown when there are no rows to display.
 * @slot no-results - Content shown when an active search or filter matches no rows (falls back to a localized message).
 * @slot loading - Content shown in the loading overlay (server mode).
 *
 * @event wa-sort-change - Emitted when the sort order changes.
 * @event wa-row-select - Emitted when the row selection changes.
 * @event wa-page-change - Emitted when the current page or page size changes.
 * @event wa-filter-change - Emitted when the global search or a column filter changes.
 * @event wa-row-expand - Emitted when a row expands (a detail panel or a tree row's children).
 * @event wa-row-collapse - Emitted when a row collapses (a detail panel or a tree row's children).
 * @event wa-data-request - Emitted in server mode when the grid needs data for the current sort, filters, and page.
 * @event wa-data-error - Emitted in server mode when a `dataSource` request rejects.
 * @event wa-column-move - Emitted when a column is reordered (live during drag; check `detail.finished`).
 * @event wa-column-resize - Emitted when a column is resized (live during drag; check `detail.finished`).
 * @event wa-column-visibility-change - Emitted when the user shows or hides a column through the built-in menus.
 *  Programmatic `toggleColumn()` calls don't emit.
 * @event wa-column-pin - Emitted when the user pins or unpins a column through the built-in controls. Programmatic
 *  `pinColumn()` calls don't emit.
 * @event wa-cell-click - Emitted when a data cell is clicked, or [[Enter]] is pressed on the active data cell.
 * @event wa-cell-contextmenu - Emitted when a data cell is right-clicked (or Shift+F10 / the menu key is pressed on
 *  the active cell). Cancel it to suppress the native context menu.
 *
 * @csspart data-grid - The component's outer wrapper.
 * @csspart toolbar - The toolbar that contains the search box and columns menu.
 * @csspart search - The global search input.
 * @csspart select-all-checkbox - The header checkbox that selects the current page.
 * @csspart columns-menu - The column visibility menu.
 * @csspart table - The grid table element.
 * @csspart header - The header row container.
 * @csspart header-cell - A column header cell.
 * @csspart sort-indicator - The sort direction arrow icon in a header cell.
 * @csspart sort-number - The numbered priority badge shown next to each column in a multi-column sort.
 * @csspart resize-handle - The drag handle for resizing a column.
 * @csspart column-menu - The per-column header options dropdown.
 * @csspart column-menu-button - The kebab button that opens a column's options menu.
 * @csspart filter-button - The funnel button in a filterable column's header that opens its filter panel.
 * @csspart filter-panel - The popover panel that contains a column's filter controls.
 * @csspart pin-indicator - The pin button shown in a pinned column's header (click to unpin).
 * @csspart drag-ghost - The floating label that follows the pointer while reordering a column (rendered in the top layer).
 * @csspart body - The scrollable body container.
 * @csspart empty - The empty-state container shown when there are no rows (wraps the `empty` slot).
 * @csspart no-results - The container shown when a search or filter matches no rows (wraps the `no-results` slot).
 * @csspart row - A data row.
 * @csspart cell - A data cell.
 * @csspart expand-button - The expand/collapse toggle button on a row.
 * @csspart row-detail - The expandable detail panel for a row.
 * @csspart loading-overlay - The overlay shown while a server request is in flight.
 * @csspart live-region - The visually-hidden polite live region for screen-reader announcements.
 * @csspart group-row - A group row (also carries `row`), when `group-by` is set.
 * @csspart group-value - The group's value in a group row's grouping cell.
 * @csspart group-count - The member count shown next to a group's value.
 * @csspart footer-row - The column footer row pinned to the bottom of the scroll area.
 * @csspart footer-cell - A column footer cell.
 * @csspart footer - The footer that contains the pager.
 * @csspart pager - The pagination control (a `<wa-pagination>` element).
 * @csspart pager-button - Every button in the pager, including page numbers (exported from `wa-pagination`'s `button` part).
 * @csspart page - A page-number button in the pager.
 * @csspart page-current - The current page-number button in the pager.
 * @csspart ellipsis - The collapsed-pages ellipsis in the pager.
 * @csspart first-button - The "first page" pager button.
 * @csspart previous-button - The "previous page" pager button.
 * @csspart next-button - The "next page" pager button.
 * @csspart last-button - The "last page" pager button.
 * @csspart page-size - The page-size `<wa-select>` in the footer.
 *
 * @cssproperty [--accent-color=var(--wa-color-brand-fill-loud)] - The checkbox accent and pinned-column highlight.
 * @cssproperty [--background-color=var(--wa-color-surface-default)] - The grid body background.
 * @cssproperty [--text-color=var(--wa-color-text-normal)] - The cell text color.
 * @cssproperty [--border-color=var(--wa-color-surface-border)] - The gridline and outer border color.
 * @cssproperty [--border-width=var(--wa-border-width-s)] - The gridline thickness.
 * @cssproperty [--border-radius=var(--wa-border-radius-m)] - The outer corner radius (outlined appearance).
 * @cssproperty [--max-height=30rem] - The maximum height of the scrollable body. Set `none` for natural height.
 * @cssproperty [--row-height=3.5rem] - The height of each row (also set by `size`).
 * @cssproperty [--header-row-height=var(--row-height)] - The height of the header row.
 * @cssproperty [--cell-padding=var(--wa-space-m)] - The cell inline padding (also set by `size`).
 * @cssproperty [--header-background=var(--wa-color-surface-lowered)] - The header row background.
 * @cssproperty [--header-text-color=var(--wa-color-text-normal)] - The header text color.
 * @cssproperty [--row-hover-background=var(--wa-color-neutral-fill-normal)] - The hovered row background.
 * @cssproperty [--stripe-background=var(--wa-color-neutral-fill-quiet)] - The zebra (odd row) background.
 * @cssproperty [--selected-background=var(--wa-color-brand-fill-quiet)] - The selected row background.
 * @cssproperty [--focus-ring=var(--wa-focus-ring)] - The active-cell focus ring.
 * @cssproperty [--transition-duration=var(--wa-transition-normal)] - The reorder/resize transition duration.
 * @cssproperty [--indent-size=1.25em] - The indentation applied per depth level to child rows in tree data.
 */
export default class WaDataGrid extends WebAwesomeElement {
    static css: import("lit").CSSResult[];
    private readonly localize;
    private tableController;
    private virtualizer;
    private nav;
    private reorder;
    private measuredRowHeight;
    /**
     * Memoized TanStack column defs, rebuilt only when `columns` (or a grid flag that feeds the defs) changes.
     * table-core memoizes its row models by the `columns` reference, so a fresh array every render would thrash.
     */
    private columnDefsCache;
    private columnDefsKey;
    /** The table synced for the CURRENT render pass, so the many `syncTable()` callers reuse one synced instance. */
    private renderTable;
    /** Set true by the reorder controller when a drag started, so the next header click doesn't also sort. */
    private suppressNextHeaderClick;
    private scroller;
    /** The row objects to display. In client mode this is the full set. */
    data: Row[];
    /** The column definitions. */
    columns: DataGridColumn[];
    /** The field used as a stable row id for selection. Required in practice when `selectable` is set. */
    rowKey: string | null;
    /**
     * A predicate deciding whether a row can be selected. Return `false` to lock a row: its checkbox is disabled and it's
     * skipped by select-all and range selection. When unset, every row is selectable (subject to `selectable`).
     */
    selectableRows: ((row: Row) => boolean) | null;
    /** Enables row selection. A bare attribute means `multiple`. */
    selectable: '' | 'single' | 'multiple' | 'none';
    /** Enables client-side pagination and the pager footer. */
    paginate: boolean;
    /** The number of rows per page. */
    pageSize: number;
    /** The page sizes offered by the pager's page-size selector. */
    pageSizeOptions: number[];
    /** The current page index (0-based). */
    page: number;
    /**
     * Keeps a sorted column always sorted, alternating between ascending and descending. By default, a sorted column's
     * third click clears its sort (the asc → desc → unsorted cycle).
     */
    withoutSortRemoval: boolean;
    /** When `true`, a column's first sort click sorts descending instead of ascending (table-core `sortDescFirst`). */
    sortDescFirst: boolean;
    /** The maximum number of columns that can participate in a multi-column sort. `0` (default) means no limit. */
    maxMultiSort: number;
    /** Shows a global search box that filters across all columns. */
    withSearch: boolean;
    /** The current global search term. */
    searchTerm: string;
    /** Enables drag-to-resize for columns (can be overridden per column). */
    resizable: boolean;
    /** Enables drag-to-reorder for columns (can be overridden per column with `movable`). */
    reorderable: boolean;
    /** Enables column pinning (and the pin actions in the column menu). Can be overridden per column with `pinnable`. */
    pinnable: boolean;
    /** Shows a per-column header menu (kebab button) with pin, sort, hide, and autosize actions. */
    withColumnMenu: boolean;
    /** Shows a toolbar menu for toggling column visibility. */
    withColumnsMenu: boolean;
    /** Renders alternating row background colors. */
    striped: boolean;
    /**
     * Renders an expandable detail panel for a row. When set, each row shows an expand toggle. Return a string (escaped
     * text), a Lit `TemplateResult`, or a `Node`.
     */
    rowDetail: ((row: Row) => string | TemplateResult | Node) | null;
    /**
     * Returns extra CSS class names for a row (space-separated; falsy for none) — e.g. to flag overdue or archived
     * rows. Classes land on the row element inside the grid's shadow root, so style them with an adopted stylesheet
     * (see the docs' "Styling Rendered Components"). Group rows are skipped.
     */
    rowClass: ((row: Row) => string | null | undefined) | null;
    /**
     * Provides each row's child rows for tree data — a field name (dot paths allowed) or a function returning children.
     * Rows with children get an expand toggle; expanded children render indented and join sorting/filtering/selection.
     */
    childRows: string | ((row: Row) => Row[] | undefined) | null;
    /**
     * When filtering tree data, keeps a parent visible when any descendant matches (the filter runs leaf-up). By default
     * a non-matching parent is removed with its entire subtree.
     */
    filterFromLeafRows: boolean;
    /**
     * Groups rows by column id — a single id, a space/comma-separated list (or array) for multi-level grouping. Each
     * group is an expandable row showing its value, member count, and any column aggregates. Ignored for tree data and
     * in server mode.
     */
    groupBy: string | string[] | null;
    /**
     * An async function that loads data from a server. When set, the grid switches to manual mode: client-side
     * sorting/filtering/pagination are disabled and this runs on any sort/filter/search/page change. Return `rows` and
     * `total`.
     */
    dataSource: ((request: DataGridRequest) => Promise<DataGridResponse>) | null;
    /**
     * Switches the grid to server mode without a `dataSource` callback: client-side sorting, filtering, and pagination
     * are disabled and the grid emits `wa-data-request` whenever it needs data. Listen for it, fetch, then set `data`,
     * `total`, and `loading` yourself. Implied when `dataSource` is set.
     */
    server: boolean;
    /**
     * How long (in milliseconds) to wait after a search or filter keystroke before requesting data in server mode.
     * Client-side filtering is always immediate. Sort and page changes are never debounced.
     */
    filterDebounce: number;
    /**
     * A custom predicate for the global search box. Receives the cell value, the search term, and the row; return
     * `true` to keep the row (a row matches when any searchable column matches). Client mode only.
     */
    searchFn: ((value: unknown, searchTerm: string, row: Row) => boolean) | null;
    /** The total row count in server mode. Drives the pager. Set automatically when `dataSource` resolves. */
    total: number;
    /** Whether a `dataSource` request is in flight. */
    loading: boolean;
    /** An accessible label for the grid. */
    label: string | null;
    /** The grid's visual appearance. */
    appearance: 'outlined' | 'plain';
    /** The grid's size. Controls the font scale of grid text and form controls, plus row height and cell padding. */
    size: 'xs' | 's' | 'm' | 'l' | 'xl' | 'small' | 'medium' | 'large';
    private selectionState;
    /**
     * Row index of the last checkbox toggled without Shift; the anchor for Shift-click range selection. Not state — it
     * only seeds the next range and never affects rendering.
     */
    private selectionAnchorIndex;
    private sortingState;
    private columnFiltersState;
    /**
     * The column whose header filter panel is open, if any. Panel contents (facet lists in particular) only render
     * while their panel is open, so a large distinct-value set costs nothing until the user asks for it.
     */
    private openFilterColumn;
    /** The set-filter panel's option search text. Reset every time a panel opens. */
    private filterOptionQuery;
    private columnVisibilityState;
    private columnSizingState;
    /**
     * Per-column minimum widths that keep a header label from truncating below its own text. Measured from the rendered
     * headers after layout and applied only to fixed-width (non-flex) columns via `columnStyle`. Kept separate from
     * `columnSizingState` because this is auto-computed presentation, not user intent — it must never be persisted by
     * `getState()` or emit resize events. Recomputed on column/size changes.
     */
    private headerMinWidths;
    private columnPinningState;
    /**
     * table-core's expanded slice: `true` = everything expanded, else a `{ [rowId]: true }` record. Drives both detail
     * panels and tree (sub-row) expansion.
     */
    private expandedState;
    /** User-applied column order (array of column ids). Empty = natural `columns` order. Round-trips via state. */
    private columnOrderState;
    /** The currently focused/active cell for roving-tabindex keyboard nav. `row: -1` = header. */
    private activeCell;
    private pendingActiveCell;
    private mousePressActive;
    /** Transient announcement string fed to the aria-live polite region. */
    private liveAnnouncement;
    /** Tracks in-flight server requests so stale responses can be ignored (race-safe). */
    private requestToken;
    private abortController;
    /** Set by resetPage() so the resulting page-watcher fetch keeps the search/filter caller's debounce intent. */
    private pageResetPending;
    /** Set by setState() so the searchTerm watcher's resetPage() can't clobber a page restored in the same batch. */
    private suppressPageReset;
    connectedCallback(): void;
    private get isSelectable();
    private get selectionMode();
    /** The canonical size passed to child form controls (never a deprecated alias). */
    private get controlSize();
    /**
     * Resolves a stable id for a row using `rowKey`. Without one, sub-rows fall back to table-core's `parent.index`
     * convention so ids stay unique across tree depths.
     */
    private getRowId;
    /** Whether the grid renders hierarchical (tree) rows. */
    private get hasTreeRows();
    /**
     * The normalized grouping state. Tree data and grouping don't compose (tree rows win), and server mode owns its own
     * shaping — grouping a single loaded page client-side would produce misleading per-page groups. Memoized by value:
     * table-core's grouped row model is keyed on this array's REFERENCE, so a fresh array per render would re-group
     * (and re-sort, re-expand, re-paginate) the whole dataset on every render — including every scroll frame.
     */
    private groupingCache;
    private get grouping();
    /** Whether row grouping is active. */
    private get isGrouped();
    /**
     * Whether rows form a hierarchy (tree data or grouping) — drives treegrid semantics, indentation, and the
     * parent→descendant selection cascade.
     */
    private get hasHierarchy();
    /** Whether an expand-toggle control column is rendered (detail panels, tree rows, or grouped rows). */
    private get hasExpandColumn();
    /**
     * A stable `getSubRows` accessor for table-core, cached by the `childRows` value so its identity doesn't churn
     * between syncs (a new function each sync would look like an option change on every render).
     */
    private subRowsAccessorCache;
    private subRowsAccessor;
    /** Returns the column id used by table-core for a given column definition. */
    private columnId;
    /**
     * id → column lookup, rebuilt once per render pass. `columnById` runs for every cell of every rendered row, so a
     * linear scan over `columns` would be O(columns²·rows) per frame on wide grids.
     */
    private columnMap;
    private rebuildColumnMap;
    /** Looks up a column definition by the id table-core uses for it. */
    private columnById;
    /** Whether a column can be resized, considering the grid-level and per-column settings. */
    private columnResizable;
    /** Whether a column can be reordered, considering the grid-level and per-column settings. */
    private columnMovableFor;
    /** Whether a column can be pinned, considering the grid-level and per-column settings. */
    private columnPinnableFor;
    /** Pins a column to the `'left'` or `'right'` edge, or unpins it with `false`. */
    pinColumn(columnId: string, side: 'left' | 'right' | false): void;
    /** Returns which edge a column is pinned to, or `false` if it isn't pinned. */
    getColumnPin(columnId: string): 'left' | 'right' | false;
    /**
     * Translates `DataGridColumn[]` into TanStack column defs, memoized so table-core's row-model memos don't thrash on
     * a fresh array each render. The memo key is a STRUCTURAL signature of every field the builder reads, not the
     * `columns` reference — `columns` is `hasChanged: () => true` (in-place mutation is supported), so a reference-
     * identity memo would serve stale defs after such an edit.
     */
    private buildColumnDefs;
    /**
     * Stable identity counter for per-column functions (comparator, custom filterFn) so swapping one (a new function
     * reference) invalidates the columnDefs memo.
     */
    private functionIds;
    private nextFunctionId;
    private functionId;
    /** A structural signature of every component/column field that feeds `buildColumnDefsUncached`. */
    private columnDefsSignature;
    private buildColumnDefsUncached;
    /**
     * Wraps the consumer's friendly `searchFn(value, term, row)` as a table-core global filter fn, cached by the
     * function's identity so table-core doesn't see a new option every render.
     */
    private searchFnCache;
    private resolveSearchFn;
    /** Maps a column's `filterType`/custom `filterFn` to a table-core filter function (name or predicate). */
    private resolveFilterFn;
    /**
     * The initial column visibility computed from `hidden` column flags, merged with user toggles. Memoized by value —
     * table-core invalidates every row's visible-cells memo when this object's reference changes, so a fresh object per
     * render would recompute the whole visible window per frame.
     */
    private visibilityCache;
    private get effectiveVisibility();
    /**
     * The pagination slice, memoized by value — table-core's pagination row model re-slices whenever this object's
     * reference changes. When `paginate` is off it's a neutralizing slice (see `syncTable`).
     */
    private paginationSliceCache;
    private get paginationSlice();
    /**
     * The grid's `'left'`/`'right'` pinning state translated to table-core v9's logical `start`/`end` slice, memoized by
     * the state object's reference — table-core's pinning memos key on this object's identity, so a fresh object per
     * render would recompute pinned offsets and header groups every frame.
     */
    private pinningSliceCache;
    private get pinningSlice();
    /** Whether the grid is in manual (server) mode. */
    private get isManual();
    /** True only while `render()` is executing, so `syncTable()` can safely reuse one synced instance per pass. */
    private inRenderPass;
    private syncTable;
    firstUpdated(): void;
    /** Freezes the rendered width of any pinned column that has neither an explicit `width` nor a sizing entry. */
    private freezePinnedColumnWidths;
    /**
     * Measures each fixed-width (non-flex) column's header-label floor from the rendered headers and stores any that
     * differ, so `columnStyle` can widen a column whose explicit `width` is narrower than its own label. Flex columns
     * are skipped — they already grow to fit and clip only when space is genuinely tight. Runs after layout (headers
     * must exist) and re-runs when columns or size change. Only triggers a re-render when a value actually changed.
     */
    private refreshHeaderMinWidths;
    /** Focuses the grid by focusing the active (roving-tabindex) cell. */
    focus(options?: FocusOptions): void;
    protected willUpdate(changedProperties: PropertyValues<this>): void;
    /**
     * The server renders from markup alone, so JS-only properties are at their class defaults in the server DOM.
     * Assigning `columns`/`data` before the first client update (typical right after `whenDefined`) would make the
     * hydration render diverge from that DOM and throw. Park those properties for the hydration render;
     * `restoreHydrationStash()` re-applies them right after, through the same watchers as any post-render assignment.
     */
    private hydrationStash;
    private stashForHydration;
    private restoreHydrationStash;
    protected update(changedProperties: PropertyValues<this>): void;
    updated(): void;
    disconnectedCallback(): void;
    handleDataSourceChange(): void;
    /**
     * Reacts to `page` changes from ANY source — pager clicks and programmatic sets alike — so `grid.page = 3` clamps,
     * keeps the roving tab stop in range, and refetches in server mode. UI paths that already requested data are
     * deduped by the fetch scheduler.
     */
    handlePageChange(): void;
    /**
     * Clamps `page` into the valid range when the row count is known: client mode always is; server mode only once
     * `total` reports. Returns true when a correction was applied (assigning re-fires the page watcher).
     */
    private clampPage;
    handlePageSizeWatch(): void;
    handleGroupByWatch(): void;
    handleTotalChange(): void;
    /**
     * Reacts to `searchTerm` changes from any source: returns to the first page, keeps the tab stop in range, and
     * refetches (debounced) in server mode. The UI input handler only sets the property and emits — the behavior
     * lives here so programmatic sets act exactly like typing.
     */
    handleSearchTermChange(): void;
    /** Returns to the first page (search/filter changes invalidate the current page), emitting `wa-page-change`. */
    private resetPage;
    handleDataChange(): void;
    /**
     * Colliding row ids silently break selection (selecting one row selects its twins) and keyed rendering, so warn
     * once per data assignment when `rowKey` values aren't unique among top-level rows.
     */
    private warnOnDuplicateRowKeys;
    /** Set by the columns/size watchers so `updated()` re-measures header floors once the new headers are laid out. */
    private headerMinWidthsDirty;
    handleSizeChange(): void;
    /**
     * When the columns change, prune any persisted order/sizing/visibility for column ids that no longer exist, and
     * append newly-added column ids to the end of the order so they remain visible.
     */
    handleColumnsChange(): void;
    /**
     * Applies each column's declarative `pinned` side once per column id. Seeding is once-only so a user unpinning a
     * `pinned: 'left'` column isn't fought by the next render; `resetState()` clears the ledger to re-apply defaults.
     */
    private seededPinIds;
    private seedDeclarativePins;
    /** The sticky header rowgroup's height, cached until a size change or viewport resize invalidates it. */
    private measuredHeaderHeight;
    private measureHeaderHeight;
    private measureRowHeight;
    /**
     * Per-row detail panel heights, measured from the DOM after each render (see `updated()`). Panels can have
     * different heights per row, and a panel doesn't exist in the DOM until the render AFTER its row expands — so
     * `estimateSize` reads this cache and the post-render measurement corrects any first-expansion guess.
     */
    private detailHeights;
    /** The best-known height of a row's expanded detail panel: its last measured height, else a rough default. */
    private estimateDetailHeight;
    /**
     * Measures every rendered detail panel and, when any height changed since the last pass, re-runs the virtualizer's
     * size estimates so row positions match reality. Runs from `updated()` — the panels are committed to the DOM there.
     */
    /** Watches rendered detail panels: content that grows after commit (async images, lazy content) has no render
     *  to re-measure it, so size changes re-run the measurement. Subscriptions refresh per render (recycled DOM). */
    private detailResizeObserver;
    private measureDetailHeights;
    private measureRenderedDetailPanels;
    private handleHeaderClick;
    /** The first sort direction for a column: per-column `sortDescFirst` overrides the grid-level default. */
    private firstSortDesc;
    private handleSort;
    /** Sets a single column's sort to an explicit direction (used by the column menu, which isn't a cycle). */
    private setColumnSort;
    /** Clears the sort on a single column (column-menu "Clear sort"). */
    private clearColumnSort;
    /** Applies a new sort state, announces, emits, and refetches in server mode. */
    private commitSort;
    /** Get/set the sort state declaratively, e.g. `[{ id: 'name', desc: false }]`. */
    get sort(): SortingState;
    set sort(value: SortingState);
    /** Get/set the column display order as an array of column ids. Empty array = natural order. */
    get columnOrder(): string[];
    set columnOrder(ids: string[]);
    /**
     * The visible data column ids in VISUAL display order: left-pinned, then center, then right-pinned (honoring column
     * order + visibility). table-core's `getVisibleLeafColumns()` orders by `columnOrder` only and does NOT apply
     * pinning, but `getHeaderGroups()`/`getVisibleCells()` render in pinned order — so we must mirror the pinned order
     * here too, or `aria-colindex` and keyboard nav would disagree with the rendered column positions.
     */
    private orderedColumnIds;
    /**
     * The visible leaf columns in RENDER order (left-pinned → center → right-pinned). Everything that lays out against
     * the header/body (footer row, CSV columns, colindex) must use this, not `getVisibleLeafColumns()`.
     */
    private visibleColumnsInRenderOrder;
    /**
     * Commits a new column order. With `finished: true` it sets the order state (one re-render) and emits the settled
     * event; with `finished: false` it emits only the interim event (no state change, so a live drag isn't re-rendered).
     */
    private commitColumnOrder;
    /**
     * Drag/keyboard reordering only sees the VISIBLE columns, but the committed order must cover every column —
     * otherwise table-core appends the missing (hidden) ids at the end and a hidden column reappears in the wrong
     * place. Each unlisted column stays anchored to the visible column that preceded it before the move.
     */
    private mergeHiddenColumnsIntoOrder;
    /** Moves a column by `delta` positions (keyboard Shift+Arrow path), announces, keeps focus on the moved column. */
    private moveColumnByStep;
    private handleRowToggle;
    /**
     * Looks up a row (any depth, pre-filter) by its id. Group rows only exist post-grouping, so fall back to the current
     * row model for them.
     */
    private rowByIdAnyDepth;
    /**
     * Toggles every selectable leaf row under a group row. The group's own (synthetic) id never enters the selection
     * state — its checkbox state is derived from its leaves.
     */
    private handleGroupRowToggle;
    /**
     * Handles a click on a row's selection checkbox, adding Shift-click range selection. Routed from `click` (not
     * `input`, which can't carry `shiftKey`). With Shift + a prior anchor, the anchor→clicked range takes the clicked
     * checkbox's state; otherwise a normal toggle that (re)sets the anchor. Shift is ignored in `single` mode.
     */
    private handleRowCheckboxClick;
    /**
     * Invalidate the Shift-click anchor. The anchor is a row *position*, so it's meaningless once sorting, filtering,
     * searching, or paging reorders or replaces the visible rows.
     */
    private resetSelectionAnchor;
    /** The selection as it was when the current Shift+Arrow range began; the range replaces, not unions, on top of it. */
    private rangeBaseSelection;
    /**
     * Toggles selection for the rows on the CURRENT PAGE only, preserving selections on other pages. This matches
     * table-core's `getToggleAllPageRowsSelectedHandler` and the prevailing paginated-grid convention (MUI/AG/GitHub):
     * the header checkbox never silently selects thousands of off-page rows. Rows that can't be selected
     * (`enableRowSelection` predicate) are skipped. With pagination off, the "page" is the full filtered set.
     */
    private handleSelectAll;
    private setSelection;
    /** The `rowKey` values of the currently selected rows. The source of truth for selection. */
    get selectedKeys(): (string | number)[];
    set selectedKeys(keys: (string | number)[]);
    /**
     * Removes any key that resolves to a currently-loaded row the `selectableRows` predicate rejects. Keys that don't
     * resolve to a loaded row are kept (e.g. server-mode selections on pages we can't see here).
     */
    private dropLockedKeys;
    /**
     * The selected row objects resolvable from the currently loaded `data` (best-effort, any tree depth). Settable,
     * resolved by key.
     */
    get selectedRows(): Row[];
    set selectedRows(rows: Row[]);
    /** Whether a row (detail panel or tree subtree) is currently expanded. */
    private isRowExpanded;
    /**
     * Materializes the expanded slice as a per-row record (the `true` = "all expanded" form becomes explicit keys), so a
     * single row can be collapsed out of an expand-all state.
     */
    private expandedRecord;
    /** Sets one row's expansion, emitting `wa-row-expand`/`wa-row-collapse` and re-measuring panel heights. */
    private setRowExpansion;
    private toggleRowExpansion;
    /**
     * The row keys of the currently expanded rows. Settable. Without a `row-key`, ids follow table-core's convention:
     * a top-level row's index (`'0'`), then dotted index paths for children (`'0.1'`).
     */
    get expandedKeys(): (string | number)[];
    set expandedKeys(keys: (string | number)[]);
    /** Expands the row with the given key (its `rowKey` value). */
    expandRow(key: string | number): void;
    /** Collapses the row with the given key (its `rowKey` value). */
    collapseRow(key: string | number): void;
    /** Expands every row (all detail panels, or every branch of a tree). */
    expandAllRows(): void;
    /** Collapses every row. */
    collapseAllRows(): void;
    private goToPage;
    private handlePageSizeChange;
    /** The number of pages in the current result set (always `1` when `paginate` is off). Read-only. */
    get pageCount(): number;
    /**
     * The number of rows in the current result set after filtering and search, across every page (top-level rows for
     * tree and grouped data; the server-reported `total` in server mode). Read-only.
     */
    get filteredCount(): number;
    /**
     * The data rows currently displayed, in display order — after sorting, filtering, expansion, and pagination.
     * Group header rows are excluded.
     */
    getVisibleRows(): Row[];
    /**
     * Every data row in the current result set, in display order — after sorting, filtering, and search, across all
     * pages and tree depths (parents before their children). Group header rows are excluded. In server mode this is
     * the currently loaded page.
     */
    getProcessedRows(): Row[];
    /** The sorted + filtered data rows across every page and depth (the walk CSV export and clipboard copy share). */
    private processedDataRows;
    /**
     * The number of top-level rows after filtering (and grouping — each group counts as one row for paging), before
     * pagination. In server mode this is the server-reported total.
     */
    private get filteredRowCount();
    private handleSearchInput;
    private handleColumnFilter;
    /** Get/set the column filters declaratively, e.g. `[{ id: 'category', value: 'Lighting' }]`. */
    get filters(): {
        id: string;
        value: unknown;
    }[];
    set filters(value: {
        id: string;
        value: unknown;
    }[]);
    /**
     * Faceted data for a column — distinct cell values (with counts) and the numeric min/max, computed before this
     * column's own filter applies. Use it to build filter UIs. Client mode only; returns empty facets in server mode.
     */
    getColumnFacets(columnId: string): {
        uniqueValues: Map<unknown, number>;
        minMax: [number, number] | undefined;
    };
    private emitFilterChange;
    private get currentRequest();
    /** Debounce timer + microtask flag for the fetch scheduler, plus the last-issued request key for deduping. */
    private fetchDebounceTimer;
    private fetchQueued;
    private fetchForce;
    private lastRequestKey;
    /**
     * Schedules a server-mode data request. Multiple synchronous callers (a UI handler plus the property watchers it
     * triggers) coalesce into one request per microtask, `debounce: true` waits `filterDebounce` ms for typing to
     * settle, and a request identical to the last one issued is skipped unless `force` is set.
     */
    private requestServerData;
    /** Re-runs the current server request (server mode only), even if its parameters haven't changed. */
    reload(): void;
    /**
     * Fetches the current page from `dataSource` (or emits `wa-data-request` for event-style consumers). Aborts any
     * in-flight request and ignores stale responses so out-of-order arrivals can't clobber newer data.
     */
    private flushServerRequest;
    /** Shows or hides a column by its id (the column's `id`, or `field` when no id is set). */
    toggleColumn(columnId: string, visible?: boolean): void;
    /**
     * If the active (roving-tabindex) cell sits on a column that no longer exists or is now hidden, move it to a
     * surviving column. Without this, hiding/removing the active column leaves NO cell with `tabindex="0"`, so the grid
     * becomes un-tabbable until the user clicks back in. (Mirrors the nav controller's row clamp, for columns.)
     */
    private reseatActiveColumn;
    private resizeColumnTo;
    /** Tears down an in-flight resize drag's window listeners (drag interrupted or the grid disconnected). */
    private cancelResizeDrag;
    private handleResizeStart;
    /**
     * Measures the minimum inline size a header cell needs to show its label without truncating, including the space
     * its trailing controls (sort indicator, priority badge, pin/menu actions) and cell padding claim. Returns 0 when
     * the header cell isn't rendered yet or measurement is unavailable. Body content is deliberately excluded — this is
     * the "never clip the label" floor, not a fit-to-content size.
     */
    private measureHeaderMinWidth;
    /** Resizes one column to fit its widest rendered cell content (the double-click-handle behavior). */
    autoSizeColumn(columnId: string): void;
    /** Resizes every resizable column to fit its content. */
    autoSizeColumns(): void;
    /** Distributes column widths to fill the available horizontal space, honoring each column's min/max. */
    sizeColumnsToFit(): void;
    /** Scrolls the row at the given display index into view (pairs with virtualization). */
    scrollToIndex(index: number, options?: {
        align?: 'start' | 'center' | 'end';
    }): void;
    /**
     * Lazily mirrors a truncated text cell's content into `title` on hover, so the ellipsis-hidden text is
     * recoverable without paying a per-render measurement sweep (titles only ever show on pointer hover anyway).
     */
    private handleCellPointerOver;
    /**
     * Horizontally scrolls the given cell into the visible band between the sticky pinned sections. Keyboard
     * navigation focuses with `preventScroll` (the virtualizer owns vertical position), so without this the focus
     * ring can land on a cell scrolled out of horizontal view. Pinned cells are sticky and always visible.
     */
    private revealColumn;
    /**
     * Returns the current rows as a CSV string, honoring the active sort, filters, search, and column visibility/order.
     * Each column's `formatter` runs for string output only (`TemplateResult`/`Node` cells fall back to the raw value).
     * Every page and tree depth is included; server mode exports only the loaded page. Set `escapeFormulas: true` when
     * the file may open in a spreadsheet and the data isn't trusted — cells starting with `=`, `+`, `-`, or `@` are
     * prefixed with an apostrophe so they can't execute as formulas (plain numbers are left alone).
     */
    getDataAsCsv(options?: {
        columnIds?: string[];
        includeHeaders?: boolean;
        delimiter?: string;
        escapeFormulas?: boolean;
    }): string;
    /** A cell's plain-text value: the `formatter`'s string output, else the raw value stringified. */
    private cellText;
    /**
     * Exports the current rows as a CSV file (browser download). Respects the active sort, filters, search, and column
     * visibility/order, and runs each column's `formatter`. In server mode, only the currently loaded page is exported.
     */
    exportDataAsCsv(options?: {
        fileName?: string;
        columnIds?: string[];
        includeHeaders?: boolean;
        delimiter?: string;
        escapeFormulas?: boolean;
    }): void;
    /**
     * Copies the selected rows (or every processed row when nothing is selected) to the clipboard, honoring the active
     * sort, filters, and column visibility/order. The default tab-separated format pastes into spreadsheet cells;
     * `format: 'csv'` copies comma-separated text instead. Also wired to [[Ctrl]]+[[C]] when the grid has focus.
     * Returns the number of rows copied.
     */
    copySelectedRows(options?: {
        columnIds?: string[];
        includeHeaders?: boolean;
        format?: 'tsv' | 'csv';
        escapeFormulas?: boolean;
    }): Promise<number>;
    /** Returns a serializable snapshot of column order, widths, visibility, sort, filters, search, selection, paging. */
    getState(): DataGridState;
    /** Restores a previously captured state. Unknown column ids are ignored; omitted keys are left unchanged. */
    setState(state: DataGridState): void;
    /**
     * Resets all user-adjusted view state (order, widths, visibility, pinning, sort, filters, search, expansion) to the
     * column defaults. Selection and paging are left alone — clearing a user's selection is destructive.
     */
    resetState(): void;
    /**
     * Resets column order, widths, visibility, and pinning to the column definitions' defaults, leaving sort,
     * filters, search, selection, and paging untouched (the columns menu's "Reset columns" action).
     */
    resetColumns(): void;
    /** Alternates an invisible suffix so repeating the same message still mutates the DOM — AT only re-announces on change. */
    private announceTick;
    private announce;
    /** The number of header-area rows — they occupy the leading `aria-rowindex` slots, so data rows start after them. */
    private headerRowCount;
    /** The number of control (non-data) columns rendered before the data columns. */
    private controlColumnCount;
    /** The 1-based ARIA colindex for a column id (control cells included). */
    private colIndexOf;
    /** All focusable column ids in render order: control ids first, then visible data columns. */
    private focusableColumnIds;
    private headerCellEl;
    private bodyCellEls;
    /**
     * Whether a column can be reordered (used by the template + the reorder adapter). A pinned column is positioned by
     * its pin section, not free drag, so it isn't draggable while pinned.
     */
    private columnMovable;
    /** Builds the adapter the navigation controller talks to (avoids exposing private members on the element). */
    private navAdapter;
    /** Builds the adapter the reorder controller talks to. */
    private reorderAdapter;
    /** The rows array from the previous pass. Its identity changes exactly when the index → row mapping does. */
    private previousRows;
    render(): TemplateResult<1>;
    /** Whether a given coordinate is the active (roving tabindex=0) cell. */
    private isActive;
    /**
     * Keeps the roving-tabindex coordinate in sync with pointer interactions: clicking (and therefore focusing) any
     * cell makes it the active cell, per the APG grid pattern, so the next arrow key navigates from where the user
     * actually is. Focus moves from our own keyboard nav land on the already-active coordinate and no-op. While a
     * mouse button is down, the update is parked until the press has fully dispatched (see `handleTableMouseDown`).
     */
    private handleTableFocusIn;
    private handleTableMouseDown;
    private handleWindowMouseUp;
    private renderHeaderControlCell;
    private columnStyle;
    /**
     * Sticky-position CSS for a pinned column. The inline-start/-end offset is the cumulative width of the pinned
     * columns before it (`getStart('start')` / `getAfter('end')`). `pinColumn` freezes the width into `columnSizing` so
     * rendered width, flex basis, and offsets agree — else an unsized flex column reports the default 150 and mis-offsets
     * the next pinned column. Pinned columns stay in their natural DOM slot and are merely sticky-shifted, so pinning
     * reads cleanest when the column already sits near that edge in column order.
     */
    private pinnedStyle;
    private renderCell;
    /** Whether any currently-visible column defines a footer. */
    private get hasFooterRow();
    /**
     * The rows a footer function receives: the filtered + sorted set across every page (top-level rows for tree data).
     * Grouping inserts synthetic parents post-filter, so grouped grids hand over the underlying data rows instead. In
     * server mode that's whatever is currently loaded.
     */
    private footerRows;
    /**
     * The column footer row, pinned to the bottom of the scroll area. Cells mirror the header's layout (control columns,
     * sizing, alignment, pinning) so footers line up with their columns.
     */
    private renderFooterRow;
    private renderToolbar;
    private renderColumnsMenu;
    /** The per-column header menu (kebab → dropdown). Items are gated by the column's capabilities. */
    private renderColumnMenu;
    /** Renders a filterable column's funnel button plus the anchored popover panel holding its filter controls. */
    private renderFilterButton;
    /** Moves focus to the first control in a just-opened filter panel (panel contents render on open, after Lit updates). */
    private focusFilterPanel;
    /** Renders the contents of a column's filter panel appropriate to its `filterType`. */
    private renderFilterPanel;
    /**
     * Renders the value picker for `set`/`includes-*` filters: a search box (when the list is long), then one checkbox
     * per distinct value with its row count. Checking values keeps the matching rows; unchecking all clears the filter.
     */
    private renderFilterOptions;
    private renderPager;
}
declare global {
    interface HTMLElementTagNameMap {
        'wa-data-grid': WaDataGrid;
    }
}
export {};
