@gridkitjs/react 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +154 -63
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/DataGrid/DataGrid.tsx","../src/DataGrid/components/GridColgroup.tsx","../src/DataGrid/components/GridHeader.tsx","../src/DataGrid/ariaAttr.ts","../src/DataGrid/classNames.ts","../src/DataGrid/icons.tsx","../src/DataGrid/isOwnEvent.ts","../src/DataGrid/useGridNavigation.ts","../src/DataGrid/useGridSelection.ts","../src/DataGrid/components/GridBody.tsx","../src/DataGrid/rowProps.ts","../src/DataGrid/components/GridGroupRow.tsx","../src/DataGrid/components/renderAggregate.ts","../src/DataGrid/components/GridGroupSummaryRow.tsx","../src/DataGrid/components/GridRow.tsx","../src/DataGrid/components/GridFooter.tsx","../src/DataGrid/components/GridPager.tsx","../src/DataGrid/components/GroupByBar.tsx","../src/DataGrid/useGroupByDrag.ts","../src/DataGrid/useDragReorder.ts","../src/DataGrid/announcedCallbacks.ts","../src/DataGrid/clipboard/useGridCopy.ts","../src/DataGrid/commands/useGridCommands.ts","../src/DataGrid/clipboard/copyToClipboard.ts","../src/DataGrid/export/useSaveFile.ts","../src/DataGrid/export/exportApi.ts","../src/DataGrid/print/printApi.ts","../src/DataGrid/menu/GridMenu.tsx","../src/DataGrid/overlay/Overlay.tsx","../src/DataGrid/menu/menuIcons.tsx","../src/DataGrid/contextMenu/GridContextMenu.tsx","../src/DataGrid/contextMenu/useContextMenu.ts","../src/DataGrid/contextMenu/contextMenuPlaces.ts","../src/DataGrid/panels/GridPanels.tsx","../src/DataGrid/columnChooser/ColumnChooser.tsx","../src/DataGrid/filterMenu/FilterMenu.tsx","../src/DataGrid/filterMenu/ExcelFilterEditor.tsx","../src/DataGrid/filterMenu/OperatorMenuButton.tsx","../src/DataGrid/filterMenu/SimpleFilterEditor.tsx","../src/DataGrid/filterMenu/ConditionRow.tsx","../src/DataGrid/filterMenu/ValueChecklist.tsx","../src/DataGrid/filterMenu/useApplyFilter.ts","../src/DataGrid/filterMenu/useFilterValueCache.ts","../src/DataGrid/panels/panelApi.ts","../src/DataGrid/panels/useGridPanels.ts","../src/DataGrid/toolbar/GridToolbar.tsx","../src/DataGrid/toolbar/ToolbarMenuButton.tsx","../src/DataGrid/toolbar/ToolbarSearch.tsx","../src/DataGrid/toolbar/useToolbarOverflow.ts","../src/DataGrid/useColumnDrag.ts","../src/DataGrid/useColumnResize.ts","../src/DataGrid/useElementWidth.ts","../src/DataGrid/useGridController.ts","../src/DataGrid/useInfiniteScroll.ts","../src/DataGrid/useLiveAnnouncer.ts","../src/DataGrid/useRowVirtualizer.ts","../src/index.ts","../src/DataGrid/hooks/usePaginationState.ts","../src/DataGrid/hooks/useGridSnapshot.ts","../src/DataGrid/hooks/useGroupByState.ts","../src/DataGrid/hooks/useColumnSortState.ts","../src/DataGrid/hooks/useSelectionState.ts","../src/DataGrid/hooks/useAggregateState.ts","../src/DataGrid/hooks/useColumnSizingState.ts","../src/DataGrid/hooks/useColumnOrderState.ts","../src/DataGrid/hooks/useColumnVisibilityState.ts","../src/DataGrid/hooks/useFilterState.ts"],"sourcesContent":["import {\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport {\n moveColumnBefore,\n resolveColumnHeaderText,\n resolveMessages,\n resolveRows,\n totalColumnWidth,\n type ColumnDefinition as CoreColumnDefinition,\n type DataColumn as CoreDataColumn,\n type ResolvedColumn as CoreResolvedColumn,\n type AggregateResults,\n type AggregateState,\n type Borders,\n type ColumnOrderState,\n type ColumnSizingState,\n type ColumnSortState,\n type ColumnVisibilityState,\n type DisplayRow,\n type FilterState,\n type GridCommandTarget,\n type GridContextMenuTarget,\n type GridOptions,\n type GridState,\n type GroupByBarVisibility,\n type GroupByState,\n type GroupExpansionState,\n type HoverableConfig,\n type PaginationState,\n type ResizeMode,\n type ResolvedRow,\n type CellSelectionState,\n type SelectedCell as CoreSelectedCell,\n type SelectedColumn as CoreSelectedColumn,\n type SelectionState,\n type CellSelectEvent as CoreCellSelectEvent,\n type CellSelectionChangeEvent as CoreCellSelectionChangeEvent,\n type ColumnSelectEvent as CoreColumnSelectEvent,\n type ColumnSelectionChangeEvent as CoreColumnSelectionChangeEvent,\n type ColumnsSelectEvent as CoreColumnsSelectEvent,\n type SelectionCallbacks as CoreSelectionCallbacks,\n type SerializedGridState,\n} from \"@gridkitjs/core\";\nimport type { ColumnDropTarget } from \"@gridkitjs/dom\";\nimport GridColgroup from \"./components/GridColgroup\";\nimport GridHeader from \"./components/GridHeader\";\nimport GridBody from \"./components/GridBody\";\nimport GridFooter from \"./components/GridFooter\";\nimport GridPager from \"./components/GridPager\";\nimport GroupByBar from \"./components/GroupByBar\";\nimport { announcedCallbacks } from \"./announcedCallbacks\";\nimport { ariaAttr } from \"./ariaAttr\";\nimport { classNames } from \"./classNames\";\nimport useGridCopy from \"./clipboard/useGridCopy\";\nimport useGridCommands from \"./commands/useGridCommands\";\nimport GridContextMenu from \"./contextMenu/GridContextMenu\";\nimport useContextMenu from \"./contextMenu/useContextMenu\";\nimport { exportApi, type GridExportApi } from \"./export/exportApi\";\nimport { isOwnEvent } from \"./isOwnEvent\";\nimport GridPanels from \"./panels/GridPanels\";\nimport { panelApi, type GridPanelApi } from \"./panels/panelApi\";\nimport { printApi, type GridPrintApi } from \"./print/printApi\";\nimport useGridPanels from \"./panels/useGridPanels\";\nimport GridToolbar from \"./toolbar/GridToolbar\";\nimport useColumnDrag from \"./useColumnDrag\";\nimport useColumnResize from \"./useColumnResize\";\nimport useElementWidth from \"./useElementWidth\";\nimport useGridController, {\n type DataGridController,\n} from \"./useGridController\";\nimport useGridNavigation, { HEADER_ROW } from \"./useGridNavigation\";\nimport useGridSelection from \"./useGridSelection\";\nimport useInfiniteScroll from \"./useInfiniteScroll\";\nimport useLiveAnnouncer from \"./useLiveAnnouncer\";\nimport useRowVirtualizer from \"./useRowVirtualizer\";\n\n/**\n * A column whose header and cells may render arbitrary React content.\n * @gridkitjs/core stays framework-agnostic and so leaves that output type open;\n * this is the binding React consumers want, and the one they should import.\n */\nexport type ColumnDefinition<Row> = CoreColumnDefinition<Row, ReactNode>;\n\n/** A column paired with the width it renders at. */\nexport type ResolvedColumn<Row> = CoreResolvedColumn<Row, ReactNode>;\n\n/** A column paired with its id, hidden or not — what `getDataColumns()` lists. */\nexport type DataColumn<Row> = CoreDataColumn<Row, ReactNode>;\n\n/**\n * The selection payloads, bound to React's node type for the same reason\n * `ColumnDefinition` is: they carry a resolved column, whose label is whatever\n * a `headerTemplate` returned.\n *\n * The row payloads name no node type at all and so are re-exported from\n * `@gridkitjs/core` as they are.\n */\nexport type SelectedColumn<Row> = CoreSelectedColumn<Row, ReactNode>;\nexport type SelectedCell<Row> = CoreSelectedCell<Row, ReactNode>;\nexport type ColumnSelectEvent<Row> = CoreColumnSelectEvent<Row, ReactNode>;\nexport type ColumnsSelectEvent<Row> = CoreColumnsSelectEvent<Row, ReactNode>;\nexport type ColumnSelectionChangeEvent<Row> = CoreColumnSelectionChangeEvent<\n Row,\n ReactNode\n>;\nexport type CellSelectEvent<Row> = CoreCellSelectEvent<Row, ReactNode>;\nexport type CellSelectionChangeEvent<Row> = CoreCellSelectionChangeEvent<\n Row,\n ReactNode\n>;\nexport type SelectionCallbacks<Row> = CoreSelectionCallbacks<Row, ReactNode>;\n\n/**\n * Imperative handle for a mounted `DataGrid`, reached via its `ref` prop:\n * the grid's DOM nodes, getters for its live state, the actions every grid\n * ref carries (focus, select all, scroll-to), and a setter for every slice of\n * state, for a toolbar, a saved layout or a test to drive it from outside.\n *\n * Every getter reads the grid's state at call time, so a read straight after\n * an action sees its result. Every setter changes the grid as the user's own\n * interaction would: it fires the slice's `on*Change` callback, and, for a\n * slice held through a controlled prop, only asks. `subscribe` is the\n * notify channel for state that changes; see\n * `packages/react/src/DataGrid/hooks/` for the public hooks built on it.\n */\nexport interface DataGridApi<Row>\n extends GridExportApi, GridPrintApi, GridPanelApi {\n /** The grid's scrollable viewport element. */\n readonly element: HTMLDivElement | null;\n /**\n * The grid's row-area `<table>` element — the one holding `<tbody>`. The\n * header and, when aggregates are active, footer render as their own\n * sibling `<table>`s outside this one; use `element` to reach the whole\n * scrollable viewport instead.\n */\n readonly table: HTMLTableElement | null;\n\n /** Rows as currently filtered and sorted — what's rendered, ungrouped. */\n getRows(): readonly ResolvedRow<Row>[];\n /**\n * `getRows()` regrouped into the active `groupBy` — group headers\n * interleaved with data rows, in render order. Identical to `getRows()`\n * when `groupBy` is empty.\n */\n getDisplayRows(): readonly DisplayRow<Row>[];\n /**\n * The current page of `getDisplayRows()` — exactly the rows the body\n * renders. All of `getDisplayRows()` when `paginated` is off.\n */\n getPageRows(): readonly DisplayRow<Row>[];\n /** Columns as currently sized and ordered — what's rendered, so hidden columns are left out. */\n getColumns(): readonly ResolvedColumn<Row>[];\n /** Every column in its current order, hidden ones included — what sorting, filtering and grouping read. */\n getDataColumns(): readonly DataColumn<Row>[];\n\n getColumnSizing(): ColumnSizingState;\n getColumnOrder(): ColumnOrderState;\n /** Columns shown or hidden since the grid mounted. A column absent from it follows its definition's `hidden`. */\n getColumnVisibility(): ColumnVisibilityState;\n getColumnSort(): ColumnSortState;\n /** The filter the rows are shown through — every entry, ANDed together. */\n getFilter(): FilterState<Row>;\n getGroupBy(): GroupByState;\n getGroupExpansion(): GroupExpansionState;\n /** The active page and page size. Meaningful even when `paginated` is off — it stays at page 0 over the grid's whole (single) page. */\n getPagination(): PaginationState;\n /** How many pages the current `pagination.pageSize` splits the grid's rows into — `1` whenever `paginated` is off. */\n getPageCount(): number;\n /**\n * The grand-total aggregate results — every active aggregate computed over\n * the whole filtered/sorted dataset, ungrouped and unpaginated. A specific\n * group's own results are read off `getDisplayRows()` instead, on that\n * group header's `aggregates` field.\n */\n getAggregates(): AggregateResults;\n getRowSelection(): SelectionState;\n /**\n * The selected rows themselves, in the order they were selected — among\n * every row the filter lets through, on any page or in any group, so a row\n * filtered out while selected is left out until it is back.\n */\n getSelectedRows(): readonly ResolvedRow<Row>[];\n getColumnSelection(): SelectionState;\n getCellSelection(): CellSelectionState;\n /** The cell currently holding the grid's single tab stop. */\n getFocusedCell(): { rowIndex: number; columnIndex: number };\n /**\n * Every slice of state as the grid applies it, in one object — what\n * `restoreState` takes back. Pass it through `serializeGridState` before\n * saving it as JSON.\n */\n getState(): GridState<Row>;\n /**\n * Puts back state saved earlier, whole or in part — from `getState()`, or\n * from `serializeGridState` and back through JSON. Each slice given is set\n * as its setter would set it, firing its callback when it changes; the\n * grid re-renders once.\n */\n restoreState(\n saved: Partial<GridState<Row>> | Partial<SerializedGridState<Row>>,\n ): void;\n\n focusCell(rowIndex: number, columnIndex: number): void;\n clearSelection(): void;\n selectAllRows(): void;\n /**\n * Selects rows by id, as far as `selectable.rows` allows: `\"replace\"` (the\n * default) selects exactly these — only the last of them under\n * `\"single\"` — and `\"toggle\"` flips each one. Fires the row selection\n * callbacks once for the whole call, and none when nothing changed.\n */\n selectRows(rowIds: readonly string[], intent?: \"replace\" | \"toggle\"): void;\n /** Expands every group at once, as the `group.expandAll` command does. */\n expandAllGroups(): void;\n /** Collapses every group currently shown at once — see `collapseAllGroups` in `@gridkitjs/core` for what \"currently shown\" means for a group already nested under a collapsed one. */\n collapseAllGroups(): void;\n /** Moves to the given page, clamped into range. */\n goToPage(pageIndex: number): void;\n /** Moves to the next page. A no-op on the last page. */\n nextPage(): void;\n /** Moves to the previous page. A no-op on the first page. */\n previousPage(): void;\n /** Changes the page size, resetting to the first page. */\n setPageSize(pageSize: number): void;\n /**\n * Shows the columns with the given ids, each in the place it held when\n * hidden. Reports one `onColumnVisibilityChange` for the whole call, and\n * none if every column was already showing.\n */\n showColumns(columnIds: readonly string[]): void;\n /**\n * Hides the columns with the given ids. A hidden column still sorts,\n * filters and groups, and keeps its place in the column order.\n */\n hideColumns(columnIds: readonly string[]): void;\n /**\n * Replaces the filter, the way a filter UI would, and sends an uncontrolled\n * grid back to its first page. Reports one `onFilterChange`, and none when\n * `filter` is equal to the current one. With a controlled `filter` prop it\n * only asks, as any change does.\n */\n setFilter(filter: FilterState<Row>): void;\n /**\n * Replaces the sort. Reports one `onColumnSortChange`, naming the first\n * column whose place or direction changed, and none for an equal sort —\n * the rule every setter below follows for its own slice and callback.\n */\n setColumnSort(sort: ColumnSortState): void;\n /** Replaces the group-by stack. Reports through `onGroupByChange`. */\n setGroupBy(groupBy: GroupByState): void;\n /** Replaces the collapsed groups. Reports through `onGroupExpansionChange` with `groupId: null`. */\n setGroupExpansion(expansion: GroupExpansionState): void;\n /** Replaces the page and page size as given. Reports through `onPaginationChange`. */\n setPagination(pagination: PaginationState): void;\n /** Replaces the column widths. Reports through `onColumnResize`, as the `\"end\"` of a resize. */\n setColumnSizing(sizing: ColumnSizingState): void;\n /** Replaces the column order. Reports through `onColumnOrderChange`. */\n setColumnOrder(order: ColumnOrderState): void;\n /** Replaces the column visibility state. Reports through `onColumnVisibilityChange`. */\n setColumnVisibility(visibility: ColumnVisibilityState): void;\n /** Replaces the selected row ids as given, whatever `selectable` allows. Fires the row selection callbacks. */\n setRowSelection(selection: SelectionState): void;\n /** Replaces the selected column ids as given. Fires the column selection callbacks. */\n setColumnSelection(selection: SelectionState): void;\n /** Replaces the selected cell as given, `null` for none. Fires the cell selection callbacks. */\n setCellSelection(selection: CellSelectionState): void;\n /**\n * Sizes a shown column to fit its content, as double-clicking its resize\n * handle does, reporting through `onColumnResize`. A hidden column, or one\n * with no rows to measure, is left as it is.\n */\n autoFitColumn(columnId: string): void;\n /**\n * `autoFitColumn` for each of the given columns, or for every column shown\n * when given none.\n */\n autoFitColumns(columnIds?: readonly string[]): void;\n /**\n * Opens the context menu `target` has, as a right-click there would —\n * selecting it and focusing its cell first — beside `anchor`, a point in\n * viewport coordinates or an element, or else below its cell. Says whether\n * it opened: not for a target not on screen, nor where `contextMenu`\n * gives no menu.\n */\n openContextMenu(\n target: GridContextMenuTarget,\n anchor?: { readonly x: number; readonly y: number } | Element,\n ): boolean;\n /** Closes the context menu, if one is open. */\n closeContextMenu(): void;\n /**\n * Runs a command by id — a built-in or one of `commands` — on `target`,\n * `{ area: \"grid\" }` when left out, when it is visible and enabled there.\n * Reports it through `onCommand` with `source: \"api\"`, and says whether it\n * ran.\n */\n runCommand(commandId: string, target?: GridCommandTarget): boolean;\n /** Scrolls the row with the given id into view, if it is currently shown. */\n scrollToRow(rowId: string, options?: ScrollIntoViewOptions): void;\n /** Scrolls the column with the given id into view. */\n scrollToColumn(columnId: string, options?: ScrollIntoViewOptions): void;\n\n /**\n * Registers `listener` to be called after any render in which the grid's\n * internal state may have changed — every getter above may return a\n * different value once `listener` fires, not just one. Returns an\n * unsubscribe function. The primitive the `use*State` hooks under\n * `packages/react/src/DataGrid/hooks/` build on; most consumers should\n * reach for one of those instead of calling `subscribe` directly.\n */\n subscribe(listener: () => void): () => void;\n}\n\n/**\n * Defined in `@gridkitjs/core` with the rest of `GridOptions`, and exported\n * from here too so a React consumer needs one import.\n */\nexport type { Borders, GroupByBarVisibility, HoverableConfig, ResizeMode };\n\n/**\n * A stable empty fallback for an omitted `aggregates` prop, for the parts of\n * the grid that draw aggregate cells — a fresh `[]` every render would hand\n * them a new array each time.\n */\nconst NO_AGGREGATES: AggregateState<never> = [];\n\n/**\n * `DataGridApi.getPagination`, read off `controller` at call time: the page\n * shown — clamped, unlike the stored index — and the page size. The same\n * object while both stay the same, since a `useSyncExternalStore` snapshot\n * built fresh on every read makes React warn and re-render forever.\n */\nfunction paginationReader<Row>(\n controller: DataGridController<Row>,\n): () => PaginationState {\n let last: PaginationState | undefined;\n return () => {\n const { pageIndex } = controller.getView();\n const { pageSize } = controller.getState().pagination;\n if (last?.pageIndex !== pageIndex || last.pageSize !== pageSize) {\n last = { pageIndex, pageSize };\n }\n return last;\n };\n}\n\n/**\n * Everything a `pager.template` render prop needs to rebuild the built-in\n * pager's UI itself. Passed fresh on every render where pagination-relevant\n * state changed, so it's current by construction — unlike `DataGridApi`'s\n * imperative methods and snapshot getters, which carry no \"something\n * changed, re-render\" signal of their own.\n */\nexport interface PagerTemplateContext {\n /** Same shape as `DataGridApi.getPagination()` — 0-based `pageIndex`. */\n pagination: PaginationState;\n /** `pagination.pageIndex + 1`, clamped — the display-ready page number. */\n currentPage: number;\n pageCount: number;\n /** Passthrough of `pager.sizeOptions`, undefined when not given. */\n pageSizeOptions: readonly number[] | undefined;\n /** 0-based, same as `DataGridApi.goToPage` — not `currentPage`'s numbering. */\n goToPage: (pageIndex: number) => void;\n nextPage: () => void;\n previousPage: () => void;\n setPageSize: (pageSize: number) => void;\n}\n\n/** Presentation options for the grid's built-in pager. */\nexport interface PagerConfig {\n /** Page sizes offered by the built-in pager's page-size control. */\n sizeOptions?: readonly number[] | undefined;\n /** Defaults to `\"compact\"` — today's Prev/status/Next. */\n variant?: \"compact\" | \"numbered\" | undefined;\n /** Numbered variant only. How many pages to always show at each end. Defaults to 1. */\n boundaryCount?: number | undefined;\n /** Numbered variant only. How many pages to show on each side of the current page. Defaults to 1. */\n siblingCount?: number | undefined;\n /** Replaces the built-in pager entirely when given. `variant` is ignored. */\n template?: ((context: PagerTemplateContext) => ReactNode) | undefined;\n}\n\n/**\n * Loads more rows as the user scrolls near the bottom, in place of paging.\n * Appends only — there is no equivalent of `paginated`'s reset-to-page-0 for\n * a result set that shrinks out from under the current position.\n */\nexport interface InfiniteScrollConfig {\n /** Whether a further `onLoadMore` could still return more rows. `false` removes the sentinel entirely, so no further scrolling can trigger a load. */\n readonly hasMore: boolean;\n /**\n * Called at most once per genuine threshold-crossing: fires when the\n * sentinel comes within `rootMargin` of the body's viewport, and not again\n * until `isLoadingMore` has gone back to `false`.\n */\n readonly onLoadMore: () => void;\n /** Whether a load triggered by `onLoadMore` is still in flight. Suppresses further calls to it until this goes back to `false`. */\n readonly isLoadingMore?: boolean | undefined;\n /**\n * How far from the bottom of the scrollable body `onLoadMore` fires, ahead\n * of the sentinel actually scrolling into view, as CSS margins — an\n * intersection observer's `rootMargin`. Defaults to `\"200px\"`.\n */\n readonly rootMargin?: string | undefined;\n /** Replaces the built-in \"Loading more…\" row (`messages.loadingMore`). */\n readonly loadingTemplate?: (() => ReactNode) | undefined;\n}\n\n/**\n * The props that name a React type, and so have no place in the\n * framework-free `GridOptions`: columns whose templates return `ReactNode`,\n * the pager and infinite-scroll configs whose templates do too, and the\n * toolbar's custom entries.\n */\nexport interface ReactRenderSlots<Row> {\n columns?: readonly ColumnDefinition<Row>[] | undefined;\n /** Presentation options for the built-in pager. */\n pager?: PagerConfig | undefined;\n /**\n * Loads more rows as the user scrolls near the bottom, instead of paging.\n * Mutually exclusive with `paginated` — setting both logs a dev-time\n * `console.error` and only `paginated` takes effect. Recommended (not\n * required) alongside `virtualized` for a dataset that grows without\n * bound, so the mounted row count never grows with it either.\n */\n infiniteScroll?: InfiniteScrollConfig | undefined;\n /** Draws the toolbar's custom entries — `{ type: \"custom\", id }` — by id. */\n renderToolbarItem?: ((id: string) => ReactNode) | undefined;\n}\n\n/**\n * Every grid setting in `@gridkitjs/core`'s `GridOptions`, plus what only\n * React can express: render slots, selection callbacks carrying React-bound\n * columns, and the `ref`.\n */\nexport interface DataGridProps<Row>\n extends GridOptions<Row>, ReactRenderSlots<Row>, SelectionCallbacks<Row> {\n /** Imperative handle for reading live grid state and triggering actions. */\n ref?: Ref<DataGridApi<Row>> | undefined;\n}\n\n/**\n * `DataGridApi.getSelectedRows`, read off `controller` at call time: the\n * selected ids resolved against every filtered row. Recomputed only when the\n * rows or the selection change, so repeated reads are cheap and return the\n * same array.\n */\nfunction selectedRowsReader<Row>(\n controller: DataGridController<Row>,\n): () => readonly ResolvedRow<Row>[] {\n let last:\n | {\n readonly rows: readonly ResolvedRow<Row>[];\n readonly selection: SelectionState;\n readonly selected: readonly ResolvedRow<Row>[];\n }\n | undefined;\n return () => {\n const { rows } = controller.getView();\n const selection = controller.getState().rowSelection;\n if (last?.rows !== rows || last.selection !== selection) {\n const rowsById = new Map(rows.map((entry) => [entry.rowId, entry]));\n last = { rows, selection, selected: resolveRows(rowsById, selection) };\n }\n return last.selected;\n };\n}\n\nexport function DataGrid<Row>(props: DataGridProps<Row>) {\n const {\n borders,\n hoverable,\n selectable,\n resizeMode = \"fit\",\n columnSizeDefaults,\n sortableColumns = false,\n groupableColumns = false,\n groupToggleIconColumns = true,\n groupByBarVisibility = \"auto\",\n paginated = false,\n pager,\n infiniteScroll,\n aggregates = NO_AGGREGATES as AggregateState<Row>,\n groupAggregateDisplay = \"inline\",\n height,\n virtualized = false,\n overscan = 4,\n estimatedRowHeight = 40,\n label,\n labelledBy,\n locale,\n getRowProps,\n onRowClick,\n onRowDoubleClick,\n messages: messageOverrides,\n ref,\n } = props;\n const hoverRows = hoverable?.rows ?? true;\n const hoverColumns = hoverable?.columns ?? true;\n const hoverCells = hoverable?.cells ?? true;\n\n const viewportRef = useRef<HTMLDivElement>(null);\n const headerTableRef = useRef<HTMLTableElement>(null);\n const bodyTableRef = useRef<HTMLTableElement>(null);\n const bodyScrollRef = useRef<HTMLDivElement>(null);\n const sentinelRef = useRef<HTMLTableRowElement>(null);\n const viewportWidth = useElementWidth(viewportRef, resizeMode === \"fit\");\n const subscribersRef = useRef(new Set<() => void>());\n /** The grid element's id, for the toolbar's `aria-controls`. */\n const gridId = useId();\n /** Reports a change no visual cue can carry to a screen reader. */\n const announce = useLiveAnnouncer(viewportRef);\n /** Every string the grid shows or announces, `messages` over the English defaults. */\n const messages = useMemo(\n () => resolveMessages(messageOverrides),\n [messageOverrides],\n );\n\n /**\n * Every slice of grid state, and everything the grid draws, comes from\n * here. The change callbacks go in wrapped, so each change is announced\n * where the controller reports it — see `announcedCallbacks`.\n */\n const { controller, state, view } = useGridController<Row>({\n ...props,\n viewportWidth,\n ...announcedCallbacks({\n callbacks: props,\n announce,\n messages,\n columnName,\n columnOf,\n }),\n });\n\n /**\n * `getPagination()`'s value: the page shown — clamped, unlike the stored\n * index — and the page size, kept as one object while both stay the same.\n * Read live off the controller rather than this render, so a read straight\n * after an action sees it.\n */\n const [readPagination] = useState(() => paginationReader(controller));\n const [readSelectedRows] = useState(() => selectedRowsReader(controller));\n\n /**\n * `enabled` is `virtualized` alone, independent of `height`: an `auto`\n * height body has no `overflow`, so its measured `clientHeight` covers\n * the whole content and the computed range naturally comes out as\n * everything anyway — the dev-time warning below is what tells a consumer\n * that combination does nothing useful, not a behavioral gate here.\n */\n const virtualizer = useRowVirtualizer({\n enabled: virtualized,\n rows: view.pageRows,\n bodyScrollRef,\n estimatedRowHeight,\n overscan,\n });\n\n useEffect(() => {\n if (virtualized && height === undefined) {\n console.error(\n \"DataGrid: `virtualized` has no effect without `height` — a body with no bounded height has no viewport to window rows against.\",\n );\n }\n }, [virtualized, height]);\n\n const hasInfiniteScroll = infiniteScroll !== undefined;\n useEffect(() => {\n if (paginated && hasInfiniteScroll) {\n console.error(\n \"DataGrid: `paginated` and `infiniteScroll` are mutually exclusive — only `paginated` takes effect while both are set.\",\n );\n }\n }, [paginated, hasInfiniteScroll]);\n\n useInfiniteScroll({\n rootRef: bodyScrollRef,\n sentinelRef,\n config: infiniteScroll,\n });\n\n /** A column's definition by id, hidden ones included. */\n function columnOf(columnId: string): ColumnDefinition<Row> | undefined {\n return view.dataColumns.find((candidate) => candidate.id === columnId)\n ?.column;\n }\n\n /** What a column is called in an announcement — see `resolveColumnHeaderText`. */\n function columnName(columnId: string): string {\n const column = columnOf(columnId);\n return column === undefined ? columnId : resolveColumnHeaderText(column);\n }\n\n const resize = useColumnResize<Row>({\n // `@gridkitjs/dom`'s `measureColumnContent` only ever matches\n // `td[data-gridkit-column]` (never `th`), so the header table has nothing\n // for it to find — the body table alone was already the effective scope\n // before this split.\n tableRef: bodyTableRef,\n controller,\n columnSizeDefaults,\n });\n const nav = useGridNavigation({\n headerTableRef,\n bodyTableRef,\n // `null` when virtualization is off, in which case behavior is\n // byte-for-byte unchanged from before this feature existed.\n virtualRange: virtualized ? virtualizer : null,\n // Group headers are addressable rows too — the whole point of the flat\n // `DisplayRow[]` shape is that they share one position space with data\n // rows, so navigation counts them the same way. Page-relative\n // (`view.pageRows`, not `view.displayRows`): arrow keys operate on what's\n // actually in the DOM, which is the current page — a different \"page\"\n // concept than `useGridNavigation`'s own Page Up/Down viewport scrolling.\n rowCount: view.pageRows.length,\n columnCount: view.columns.length,\n // A group's own summary row (`groupAggregateDisplay: \"row\"`) occupies a\n // real slot in `rowCount` above — its DOM position has to line up with\n // everything else — but is presentational, never a tab stop: arrow-key\n // vertical movement steps over it rather than landing there.\n isSkippableRow: (rowIndex) => {\n const entry = view.pageRows[rowIndex];\n return (\n entry !== undefined && \"kind\" in entry && entry.kind === \"group-summary\"\n );\n },\n });\n\n const panels = useGridPanels({ rootRef: viewportRef, headerTableRef, nav });\n const commands = useGridCommands({\n controller,\n commands: props.commands,\n onCommand: props.onCommand,\n messages,\n announce,\n resize,\n openPanel: panels.open,\n });\n const handleCopyKey = useGridCopy({ controller, commands, nav });\n\n /**\n * Every id in display order, hidden ones included — the list a column\n * move is made among, so a hidden column keeps its slot through a move\n * made around it.\n */\n const orderedIds = useMemo(\n () => view.dataColumns.map((entry) => entry.id),\n [view.dataColumns],\n );\n\n /**\n * The ids of the columns on screen, which a drag or a keyboard move is\n * resolved against: a move one place left has to pass the next visible\n * column, not stop in front of a hidden one and appear to do nothing.\n */\n const displayedIds = useMemo(\n () => view.columns.map((entry) => entry.id),\n [view.columns],\n );\n\n /** Every column's definition by id, hidden ones included, for a group header naming a hidden column. */\n const definitions = useMemo(\n () => new Map(view.dataColumns.map((entry) => [entry.id, entry.column])),\n [view.dataColumns],\n );\n\n /** Column ids whose header may be dragged into the group-by bar at all. */\n const groupByDraggableIds = useMemo(\n () =>\n new Set(\n view.columns\n .filter((entry) => entry.groupByDraggable)\n .map((entry) => entry.id),\n ),\n [view.columns],\n );\n\n /**\n * The one place a drop is applied — the two-armed switch on `target.kind`\n * the group-by bar's own second drop zone was always going to need.\n */\n function handleDrop(target: ColumnDropTarget, movedId: string): void {\n if (target.kind === \"group-by\") {\n // Already announced: `moveGroupBy` reports through the same\n // `onGroupByChange` pipeline the header toggle and the bar's own chip\n // drag do, so this needs no announcement or focus-follow of its own —\n // unlike a column-order drop, the moved thing leaves the grid's single\n // tab-stop system entirely for the bar's own independently-focusable\n // chips, which have no shared index to update.\n controller.moveGroupBy(movedId, target.beforeColumnId);\n return;\n }\n\n // The order the controller will arrive at, worked out here as well for\n // where the column lands on screen. `moveColumnBefore` hands back the\n // same reference for a move that changes nothing, so a drop in place\n // neither renders nor reports.\n const next = moveColumnBefore(orderedIds, movedId, target.beforeId);\n if (next === orderedIds) {\n return;\n }\n controller.moveColumn(movedId, target.beforeId);\n // Counted among the columns on screen, which is what the user can see\n // and what the tab stop indexes.\n const shown = next.filter((id) => displayedIds.includes(id));\n const position = shown.indexOf(movedId);\n announce(\n messages.columnMoved(columnName(movedId), position + 1, shown.length),\n );\n /**\n * The tab stop travels with the column. React reorders the headers by key,\n * so the browser's focus stays on the moved one by itself — without this\n * the stop would be left on whichever column took its index, and the next\n * arrow key would appear to do nothing.\n */\n nav.focusCell(HEADER_ROW, position);\n }\n\n const drag = useColumnDrag<Row>({\n order: displayedIds,\n groupBy: state.groupBy,\n groupByDraggableIds,\n onDrop: handleDrop,\n });\n\n /** Whether the header drag currently open (if any) is for a column already in the group-by stack — reordering it is the chip's job, so dragging it back in is never a valid target. */\n const draggedColumnAlreadyGrouped =\n drag.draggedColumnId !== null &&\n state.groupBy.some((entry) => entry.columnId === drag.draggedColumnId);\n\n /**\n * Whether the drag currently open (if any) could land on the group-by bar\n * — the signal `groupByBarVisibility=\"auto\"` needs to show the bar as a\n * drop target even while `groupBy` is still empty. Depends only on\n * `draggedColumnId` (set once the drag opens), the static\n * `groupByDraggableIds`, and whether that column is already grouped, never\n * the pointer's current position, so the bar mounts for the drag's whole\n * duration rather than flickering in only while directly hovering it.\n */\n const dragEligibleForGroupBy =\n drag.draggedColumnId !== null &&\n groupByDraggableIds.has(drag.draggedColumnId) &&\n !draggedColumnAlreadyGrouped;\n\n const showGroupByBar =\n groupByBarVisibility === \"always\" ||\n (groupByBarVisibility === \"auto\" &&\n (state.groupBy.length > 0 || dragEligibleForGroupBy));\n\n const headerGroupByDropTarget =\n drag.dropTarget?.kind === \"group-by\" ? drag.dropTarget : null;\n\n /** What the built-in pager draws, and what a `pager.template` is handed. */\n const pagerContext: PagerTemplateContext = {\n pagination: state.pagination,\n currentPage: Math.min(state.pagination.pageIndex + 1, view.pageCount),\n pageCount: view.pageCount,\n pageSizeOptions: pager?.sizeOptions,\n goToPage: controller.goToPage,\n nextPage: controller.nextPage,\n previousPage: controller.previousPage,\n setPageSize: controller.setPageSize,\n };\n\n const selection = useGridSelection<Row>({ controller, state, selectable });\n\n const multiselectable =\n selection.rowMode === \"multiple\" || selection.columnMode === \"multiple\";\n\n const contextMenu = useContextMenu({\n rootRef: viewportRef,\n headerTableRef,\n bodyTableRef,\n bodyScrollRef,\n contextMenu: props.contextMenu,\n onContextMenuOpenChange: props.onContextMenuOpenChange,\n controller,\n commands,\n nav,\n selection,\n messages,\n columnName,\n });\n\n /**\n * Tells `subscribe`'s listeners once a render has drawn a change: to the\n * controller's state or view — whether an action or a prop made it — or to\n * the focused cell, which `@gridkitjs/dom`'s grid focus keeps apart from\n * the controller.\n *\n * Gated on those values, not run after every render: `useSyncExternalStore`\n * re-renders a subscriber that is notified, and a subscriber that renders\n * this grid as a plain (non-memoized) child would re-render it in turn and\n * be notified again, forever, though nothing ever changed. The state and\n * view objects keep their identity until something in them changes, which\n * is what breaks that cycle.\n */\n useEffect(() => {\n for (const listener of subscribersRef.current) {\n listener();\n }\n }, [view, state, nav.focus]);\n\n /**\n * No deps array: `nav`, `resize` and `virtualizer` are freshly\n * constructed every render (none of those hooks memoize their returned\n * API), so the handle has to be rebuilt every render too or its closures\n * would go stale. Grid state is read off the controller at call time.\n */\n useImperativeHandle(ref, () => ({\n get element() {\n return viewportRef.current;\n },\n get table() {\n return bodyTableRef.current;\n },\n getRows: () => controller.getView().rows,\n // Every group header's own `aggregates` field is populated here — the\n // whole reason `getDisplayRows()` is where a consumer reads a specific\n // group's computed results from.\n getDisplayRows: () => controller.getView().displayRows,\n getPageRows: () => controller.getView().pageRows,\n getColumns: () => controller.getView().columns,\n getDataColumns: () => controller.getView().dataColumns,\n getColumnSizing: () => controller.getState().columnSizing,\n getColumnOrder: () => controller.getState().columnOrder,\n getColumnVisibility: () => controller.getState().columnVisibility,\n getColumnSort: () => controller.getState().columnSort,\n getFilter: () => controller.getState().filter,\n getGroupBy: () => controller.getState().groupBy,\n getGroupExpansion: () => controller.getState().groupExpansion,\n getPagination: readPagination,\n getPageCount: () => controller.getView().pageCount,\n getAggregates: () => controller.getView().grandTotal,\n getRowSelection: () => controller.getState().rowSelection,\n getSelectedRows: readSelectedRows,\n getColumnSelection: () => controller.getState().columnSelection,\n getCellSelection: () => controller.getState().cellSelection,\n getFocusedCell: () => nav.focus,\n getState: controller.getState,\n restoreState: controller.restoreState,\n focusCell: nav.focusCell,\n clearSelection: controller.clearSelection,\n selectAllRows: controller.selectAllRows,\n selectRows: controller.selectRows,\n expandAllGroups: controller.expandAllGroups,\n collapseAllGroups: controller.collapseAllGroups,\n goToPage: controller.goToPage,\n nextPage: controller.nextPage,\n previousPage: controller.previousPage,\n setPageSize: controller.setPageSize,\n showColumns: controller.showColumns,\n hideColumns: controller.hideColumns,\n setFilter: controller.setFilter,\n setColumnSort: controller.setColumnSort,\n setGroupBy: controller.setGroupBy,\n setGroupExpansion: controller.setGroupExpansion,\n setPagination: controller.setPagination,\n setColumnSizing: controller.setColumnSizing,\n setColumnOrder: controller.setColumnOrder,\n setColumnVisibility: controller.setColumnVisibility,\n setRowSelection: controller.setRowSelection,\n setColumnSelection: controller.setColumnSelection,\n setCellSelection: controller.setCellSelection,\n autoFitColumn: (columnId) => {\n commands.host.autoFitColumns([columnId]);\n },\n autoFitColumns: (columnIds) => {\n commands.host.autoFitColumns(\n columnIds ?? controller.getView().columns.map((entry) => entry.id),\n );\n },\n openContextMenu: contextMenu.open,\n closeContextMenu: contextMenu.close,\n ...exportApi(commands),\n ...printApi(commands),\n ...panelApi(panels, controller),\n runCommand: (commandId, target = { area: \"grid\" }) =>\n commands.run(commandId, target, \"api\"),\n scrollToRow: (rowId, options) => {\n // `pageRows`, not `displayRows`: a data row's DOM position is its place\n // in the currently rendered page — with grouping active, that's its\n // place in the grouped, flattened output; with pagination also active,\n // that's the page's own slice of it. A row on a different page isn't\n // in the DOM at all, so there is nothing to scroll to.\n const index = controller\n .getView()\n .pageRows.findIndex(\n (entry) => !(\"kind\" in entry) && entry.rowId === rowId,\n );\n if (index === -1) return;\n // Under virtualization the target row may not be mounted at all —\n // `virtualizer.scrollToIndex` estimates, scrolls, and self-corrects\n // once it mounts and is measured, rather than reaching for a DOM row\n // that may not exist.\n if (virtualized) {\n virtualizer.scrollToIndex(index, options);\n return;\n }\n bodyTableRef.current?.tBodies[0]?.rows[index]?.scrollIntoView(options);\n },\n scrollToColumn: (columnId, options) => {\n // The whole viewport, not just one table: a column's cells with\n // `data-gridkit-column` now live across three sibling tables\n // (header/body/footer) rather than one, and the header's `<th>` is\n // the one guaranteed to exist even when the body has no rows.\n const cells = viewportRef.current?.querySelectorAll(\n \"[data-gridkit-column]\",\n );\n const cell = cells\n ? Array.from(cells).find(\n (entry) => entry.getAttribute(\"data-gridkit-column\") === columnId,\n )\n : undefined;\n cell?.scrollIntoView(options);\n },\n subscribe: (listener) => {\n subscribersRef.current.add(listener);\n return () => {\n subscribersRef.current.delete(listener);\n };\n },\n }));\n\n // Shared by all three tables below, so borders/hover/selectable styling —\n // every `.gridkit-data-grid.<modifier>` rule in `theme-tailwind` — applies\n // identically to each rather than only to whichever one happened to carry\n // it. Each rule's own descendant selector (e.g. `.borders-horizontal\n // .grid-cell`) still needs the modifier class on that cell's own table\n // ancestor, which is exactly what splitting into one table per section\n // would otherwise lose.\n const gridTableClassName = classNames(\n \"gridkit-data-grid\",\n borders ? `borders-${borders}` : \"\",\n // Hover is on by default and selection off, so one set of classes\n // turns styling off and the other turns it on. The polarity differs\n // because the defaults do.\n hoverRows ? \"\" : \"no-hover-rows\",\n hoverColumns ? \"\" : \"no-hover-columns\",\n hoverCells ? \"\" : \"no-hover-cells\",\n selection.rowMode === false ? \"\" : \"selectable-rows\",\n selection.columnMode === false ? \"\" : \"selectable-columns\",\n selection.cellMode === false ? \"\" : \"selectable-cells\",\n );\n\n return (\n <div className=\"gridkit-data-grid-viewport\" ref={viewportRef}>\n <GridToolbar<Row>\n toolbar={props.toolbar}\n renderItem={props.renderToolbarItem}\n gridId={gridId}\n controller={controller}\n commands={commands}\n messages={messages}\n announce={announce}\n />\n {showGroupByBar && (\n <GroupByBar<Row>\n columns={view.columns}\n definitions={definitions}\n groupBy={state.groupBy}\n controller={controller}\n columnName={columnName}\n headerDragEligible={dragEligibleForGroupBy}\n headerDragBlocked={draggedColumnAlreadyGrouped}\n headerDropTarget={headerGroupByDropTarget}\n messages={messages}\n />\n )}\n <div\n id={gridId}\n className=\"gridkit-data-grid-tables\"\n /*\n * `role=\"grid\"` sits on this wrapper rather than any one of the\n * three `<table>`s below: the WAI-ARIA grid pattern needs a single\n * ancestor holding every row — header, body, and (when aggregates\n * are active) footer alike — and no one table is an ancestor of the\n * other two's rows now that they're split. It obliges the single\n * tab stop `useGridNavigation` keeps.\n *\n * Switches to `\"treegrid\"` — the WAI-ARIA pattern for expandable,\n * collapsible rows — whenever `groupBy` is non-empty, rather than\n * committing to it unconditionally. The alternative (always\n * `treegrid`) would change what every existing, ungrouped consumer\n * announces to assistive technology the moment this feature shipped;\n * that regression is certain, while the edge case this trades away —\n * the role flipping mid-session if a consumer removes its last\n * group-by level — is rare and, per the WAI-ARIA grid pattern, still\n * a valid `role` change to make when the row structure itself\n * changes shape. See the \"Scope note\" this mirrors: grouping stays\n * an internal detail for an ungrouped grid, ARIA role included.\n */\n role={state.groupBy.length > 0 ? \"treegrid\" : \"grid\"}\n // The header is a row too, and counted from one; group headers (and,\n // under `groupAggregateDisplay: \"row\"`, each group's own summary\n // row) count as rows here too, the same way they do in `nav`'s\n // `rowCount`. `view.displayRows`, not `view.pageRows`: the total\n // dataset count, not the current page's, so this stays the true row\n // count per the WAI-ARIA grid pattern even while paged.\n aria-rowcount={view.displayRows.length + 1}\n aria-colcount={view.columns.length}\n {...ariaAttr(multiselectable, \"aria-multiselectable\", true)}\n {...ariaAttr(labelledBy !== undefined, \"aria-labelledby\", labelledBy)}\n {...ariaAttr(\n labelledBy === undefined && label !== undefined,\n \"aria-label\",\n label,\n )}\n onKeyDown={(event) => {\n // The keys that address the grid rather than a cell, caught here\n // where everything bubbles to rather than in each of them.\n if (!isOwnEvent(event)) return;\n handleCopyKey(event);\n if (event.key === \"Escape\") {\n // A gesture in flight has its own use for Escape — cancelling —\n // and gets it first.\n if (drag.draggedColumnId !== null || resize.activeColumnId !== null)\n return;\n selection.clear();\n return;\n }\n if (\n (event.ctrlKey || event.metaKey) &&\n (event.key === \"a\" || event.key === \"A\")\n ) {\n // Left to the browser unless the grid has something to do with it,\n // so a grid without multiple rows does not swallow select-all.\n if (selection.rowMode !== \"multiple\") return;\n event.preventDefault();\n selection.selectAllRows();\n }\n }}\n >\n <table\n ref={headerTableRef}\n // Widths are only honoured exactly when the table is as wide as its\n // columns; at `100%` the fixed layout redistributes the difference.\n style={{ width: totalColumnWidth(view.columns) }}\n className={classNames(gridTableClassName, \"gridkit-data-grid-header\")}\n >\n <GridColgroup columns={view.columns} />\n <GridHeader<Row>\n columns={view.columns}\n resize={resize}\n drag={drag}\n controller={controller}\n state={state}\n sortableColumns={sortableColumns}\n groupableColumns={groupableColumns}\n groupToggleIconColumns={groupToggleIconColumns}\n headerMenu={contextMenu.opens(\"header\")}\n panels={panels}\n messages={messages}\n nav={nav}\n selection={selection}\n />\n </table>\n\n <div\n className=\"gridkit-data-grid-body\"\n ref={bodyScrollRef}\n style={\n height === undefined\n ? undefined\n : ({\n \"--gridkit-body-height\":\n typeof height === \"number\" ? `${String(height)}px` : height,\n } as CSSProperties)\n }\n >\n <table\n ref={bodyTableRef}\n style={{ width: totalColumnWidth(view.columns) }}\n className={gridTableClassName}\n >\n <GridColgroup columns={view.columns} />\n <GridBody<Row>\n columns={view.columns}\n definitions={definitions}\n rows={view.pageRows}\n activeColumnId={resize.activeColumnId}\n nav={nav}\n selection={selection}\n controller={controller}\n aggregates={aggregates}\n groupAggregateDisplay={groupAggregateDisplay}\n virtualRange={virtualized ? virtualizer : null}\n infiniteScroll={infiniteScroll}\n sentinelRef={sentinelRef}\n locale={locale}\n getRowProps={getRowProps}\n onRowClick={onRowClick}\n onRowDoubleClick={onRowDoubleClick}\n messages={messages}\n cellMenu={contextMenu.opens(\"cell\")}\n groupMenu={contextMenu.opens(\"group\")}\n />\n </table>\n </div>\n\n {aggregates.length > 0 && (\n <table\n style={{ width: totalColumnWidth(view.columns) }}\n className={classNames(\n gridTableClassName,\n \"gridkit-data-grid-footer\",\n )}\n >\n <GridColgroup columns={view.columns} />\n <GridFooter<Row>\n columns={view.columns}\n aggregates={aggregates}\n results={view.grandTotal}\n rows={view.rows.map((entry) => entry.row)}\n locale={locale}\n />\n </table>\n )}\n </div>\n <GridContextMenu contextMenu={contextMenu} />\n <GridPanels\n panels={panels}\n controller={controller}\n commands={commands}\n messages={messages}\n />\n {paginated &&\n (pager?.template ? (\n pager.template(pagerContext)\n ) : (\n <GridPager pager={pagerContext} config={pager} messages={messages} />\n ))}\n </div>\n );\n}\n","import type { ResolvedColumn } from \"../DataGrid\";\n\ninterface GridColgroupProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n}\n\n/**\n * One `<colgroup>`, shared verbatim by the header, body, and footer\n * `<table>`s so all three render identical column widths from one source\n * rather than three independent copies of the same `.map()`.\n */\nexport default function GridColgroup<Row>({ columns }: GridColgroupProps<Row>) {\n return (\n <colgroup>\n {columns.map((entry) => (\n <col key={entry.id} style={{ width: entry.width }} />\n ))}\n </colgroup>\n );\n}\n","import { createPortal } from \"react-dom\";\nimport {\n buildKeyShortcuts,\n intentOf,\n isColumnFiltered,\n KEYBOARD_STEP,\n resolveColumnFilterMenu,\n sortDirectionFor,\n sortPriorityFor,\n type GridMessages,\n type GridState,\n} from \"@gridkitjs/core\";\nimport type { ResolvedColumn } from \"../DataGrid\";\nimport { ariaAttr } from \"../ariaAttr\";\nimport { classNames } from \"../classNames\";\nimport {\n ChevronsUpDownIcon,\n ChevronUpIcon,\n FilterIcon,\n GroupIcon,\n} from \"../icons\";\nimport { isOwnEvent } from \"../isOwnEvent\";\nimport type { GridPanelsApi } from \"../panels/useGridPanels\";\nimport type { ColumnDragApi } from \"../useColumnDrag\";\nimport type { ColumnResizeApi } from \"../useColumnResize\";\nimport { HEADER_ROW, type GridNavigationApi } from \"../useGridNavigation\";\nimport {\n keyboardSelectIntent,\n type GridSelectionApi,\n} from \"../useGridSelection\";\nimport type { DataGridController } from \"../useGridController\";\n\ninterface GridHeaderProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n resize: ColumnResizeApi<Row>;\n drag: ColumnDragApi<Row>;\n /** What a header toggle changes — the sort and the group-by stack. */\n controller: DataGridController<Row>;\n /** The state this render draws: the sort, grouping and filter the headers show. */\n state: GridState<Row>;\n sortableColumns: boolean;\n groupableColumns: boolean;\n groupToggleIconColumns: boolean;\n /** Whether a header opens the grid's context menu, which its `aria-keyshortcuts` says. */\n headerMenu: boolean;\n /** Where a header opens its column's filter menu. */\n panels: GridPanelsApi;\n messages: GridMessages;\n nav: GridNavigationApi;\n selection: GridSelectionApi;\n}\n\nexport default function GridHeader<Row>({\n columns,\n resize,\n drag,\n controller,\n state,\n sortableColumns,\n groupableColumns,\n groupToggleIconColumns,\n headerMenu,\n panels,\n messages,\n nav,\n selection,\n}: GridHeaderProps<Row>) {\n const { columnSort, groupBy, filter } = state;\n // Only meaningful for the \"column-order\" branch — a drop headed for the\n // group-by bar instead (`kind: \"group-by\"`) draws no indicator here at\n // all; `GroupByBar` draws its own from the same `drag.dropTarget`.\n const beforeId =\n drag.dropTarget?.kind === \"column-order\"\n ? drag.dropTarget.beforeId\n : undefined;\n const draggedEntry =\n columns.find((entry) => entry.id === drag.draggedColumnId) ?? null;\n\n /**\n * Opens the column's filter menu, or closes it when it is the one open: a\n * press on the header it opened from leaves it open, so pressing its\n * button again is the way back out.\n */\n function toggleFilterMenu(columnId: string): void {\n const { panel } = panels;\n if (\n panel?.kind === \"filter\" &&\n panel.target.area === \"header\" &&\n panel.target.columnId === columnId\n ) {\n panels.close();\n } else {\n panels.open(\"filter\", { area: \"header\", columnId });\n }\n }\n\n return (\n <thead>\n <tr className=\"grid-header\" role=\"row\" aria-rowindex={1}>\n {columns.map((entry, index) => {\n const { column } = entry;\n const resizing = resize.activeColumnId === entry.id;\n const dragging = drag.draggedColumnId === entry.id;\n\n /**\n * Drawn on the gap's own edge, so the one gap between two columns is\n * marked once. No guard against the dragged column: the hook reports\n * only gaps that would move it.\n */\n const dropBefore = beforeId !== undefined && beforeId === entry.id;\n const dropAfter = beforeId === null && index === columns.length - 1;\n const selected = selection.selectedColumnIds.has(entry.id);\n const sortable = column.sortable ?? sortableColumns;\n const sortDirection = sortDirectionFor(columnSort, entry.id);\n // Only meaningful once two or more columns are stacked.\n const sortPriority = sortPriorityFor(columnSort, entry.id);\n const groupable = column.groupable ?? groupableColumns;\n // Purely a rendering choice — see the prop's own doc comment. Never\n // gates `groupable` itself, `aria-keyshortcuts`, or `Alt+ArrowDown`.\n const showGroupToggleIcon =\n column.groupToggleIcon ?? groupToggleIconColumns;\n const isGrouped = groupBy.some(\n (level) => level.columnId === entry.id,\n );\n const filterable =\n resolveColumnFilterMenu(controller.getOptions(), column) !== null;\n // Shown, and described, only where the header opens the menu that\n // changes it: a grid filtering a column in code alone keeps its\n // headers as they were.\n const filtered = filterable && isColumnFiltered(filter, entry.id);\n\n const shortcuts = buildKeyShortcuts({\n reorderable: entry.reorderable,\n resizable: entry.resizable,\n sortable,\n groupable,\n filterable,\n contextMenu: headerMenu,\n });\n\n return (\n <th\n key={entry.id}\n scope=\"col\"\n // Explicit, matching `GridRow.tsx`'s `role=\"gridcell\"` on the\n // body `<td>`: both sit inside a `<table role=\"grid\">`, and\n // mixing that non-native ancestor role with descendants that\n // rely on implicit native role mapping is inconsistently\n // resolved across browser/AT combinations.\n role=\"columnheader\"\n data-gridkit-column={entry.id}\n aria-colindex={index + 1}\n tabIndex={nav.tabIndexFor(HEADER_ROW, index)}\n {...ariaAttr(\n selection.columnMode !== false,\n \"aria-selected\",\n selected,\n )}\n onFocus={() => {\n nav.focusCell(HEADER_ROW, index);\n }}\n onClick={(event) => {\n /*\n * A drag ends in a click on the header it started from, and a\n * resize in one on the handle inside it. Neither is the press\n * that selects a column, so both are shown the door here —\n * the drag by the distance it travelled, the resize by where\n * it began.\n */\n if (drag.justDragged()) {\n return;\n }\n if (\n event.target instanceof Element &&\n (event.target.closest(\".header-resize-handle\") !== null ||\n event.target.closest(\".header-sort-toggle\") !== null ||\n event.target.closest(\".header-group-toggle\") !== null ||\n event.target.closest(\".header-filter-toggle\") !== null)\n ) {\n return;\n }\n selection.selectColumn(entry.id, intentOf(event));\n }}\n onKeyDown={(event) => {\n if (!isOwnEvent(event)) return;\n const horizontal =\n event.key === \"ArrowLeft\" || event.key === \"ArrowRight\";\n const direction = event.key === \"ArrowLeft\" ? -1 : 1;\n\n if (horizontal && event.ctrlKey && entry.reorderable) {\n event.preventDefault();\n drag.moveByKeyboard(entry, direction);\n return;\n }\n if (horizontal && event.altKey && entry.resizable) {\n event.preventDefault();\n resize.nudge(entry, direction * KEYBOARD_STEP);\n return;\n }\n // The keyboard equivalent of double-clicking the resize\n // handle, which auto-fits the column to its content.\n if (event.key === \"Enter\" && event.altKey && entry.resizable) {\n event.preventDefault();\n resize.sizeToContent(entry);\n return;\n }\n if (event.key === \"ArrowUp\" && event.altKey && sortable) {\n event.preventDefault();\n controller.toggleColumnSort(entry.id, {\n stack: event.shiftKey,\n });\n return;\n }\n // Shift sets the filter menu apart from grouping, which\n // holds Alt+ArrowDown — the key Excel opens its filter with.\n if (\n event.key === \"ArrowDown\" &&\n event.altKey &&\n event.shiftKey &&\n filterable\n ) {\n event.preventDefault();\n toggleFilterMenu(entry.id);\n return;\n }\n if (\n event.key === \"ArrowDown\" &&\n event.altKey &&\n !event.shiftKey &&\n groupable\n ) {\n event.preventDefault();\n controller.toggleGroupBy(entry.id);\n return;\n }\n // Space builds a selection up and Enter replaces it, as in the\n // body. Taken either way, or Space scrolls the grid away.\n if (event.key === \" \" || event.key === \"Enter\") {\n event.preventDefault();\n selection.selectColumn(\n entry.id,\n intentOf(keyboardSelectIntent(event)),\n );\n return;\n }\n nav.onKeyDown(event);\n }}\n className={classNames(\n \"header-cell\",\n // The grab affordance a header showing either drag\n // destination shares — a column dragged only for grouping\n // (`groupByDraggable` without `reorderable`) grabs the same\n // way one dragged only for reordering does.\n entry.reorderable || entry.groupByDraggable\n ? \"is-reorderable\"\n : \"\",\n selected ? \"is-selected\" : \"\",\n resizing ? \"is-resizing\" : \"\",\n dragging ? \"is-dragging\" : \"\",\n dropBefore ? \"is-drop-before\" : \"\",\n dropAfter ? \"is-drop-after\" : \"\",\n column.wrap?.header ? \"is-wrapped\" : \"\",\n column.headerClassName ?? \"\",\n )}\n {...ariaAttr(shortcuts !== \"\", \"aria-keyshortcuts\", shortcuts)}\n {...ariaAttr(\n filtered,\n \"aria-description\",\n messages.columnFiltered,\n )}\n {...ariaAttr<\"aria-sort\", \"ascending\" | \"descending\">(\n sortable && sortDirection !== null,\n \"aria-sort\",\n sortDirection === \"asc\" ? \"ascending\" : \"descending\",\n )}\n {...((entry.reorderable || entry.groupByDraggable) && {\n onPointerDown: (event) => {\n drag.startDrag(entry, event);\n },\n })}\n >\n {groupable && showGroupToggleIcon && (\n /*\n * Inline, before the label, rather than absolutely\n * positioned like the sort toggle and resize handle: those\n * two already share the header's right edge, and a third\n * overlay there would need its own carve-out. Sitting in\n * normal flow costs nothing but a few pixels of label width.\n * A pointer affordance only, same as the other two — the\n * keyboard equivalent is Alt+ArrowDown on the header itself.\n */\n <span\n className={classNames(\n \"header-group-toggle\",\n isGrouped ? \"is-grouped\" : \"\",\n )}\n aria-hidden=\"true\"\n tabIndex={-1}\n onPointerDown={(event) => {\n // See the sort toggle's own note: otherwise a\n // reorderable header's drag would swallow this click.\n event.stopPropagation();\n }}\n onClick={(event) => {\n event.stopPropagation();\n controller.toggleGroupBy(entry.id);\n }}\n >\n <GroupIcon />\n </span>\n )}\n {entry.label}\n {sortable && (\n /*\n * A pointer affordance only, and hidden from assistive\n * technology like the resize handle: the keyboard equivalent\n * lives on the header itself, under Alt+ArrowUp (plain) /\n * Alt+Shift+ArrowUp (stacking).\n */\n <span\n className={classNames(\n \"header-sort-toggle\",\n sortDirection !== null ? `is-sorted-${sortDirection}` : \"\",\n )}\n aria-hidden=\"true\"\n tabIndex={-1}\n onPointerDown={(event) => {\n /*\n * Otherwise a reorderable header's own `onPointerDown`\n * sees this bubble up and starts a column drag, whose\n * pointer capture then redirects the click that\n * follows to the `th` — the same reason `startResize`\n * stops it for the resize handle.\n */\n event.stopPropagation();\n }}\n onClick={(event) => {\n controller.toggleColumnSort(entry.id, {\n stack: event.shiftKey,\n });\n }}\n >\n {sortDirection === null ? (\n <ChevronsUpDownIcon />\n ) : (\n <ChevronUpIcon />\n )}\n {sortPriority !== null && sortPriority > 1 && (\n <span className=\"header-sort-priority\">{sortPriority}</span>\n )}\n </span>\n )}\n {filterable && (\n /*\n * A pointer affordance only, like the sort toggle: the\n * keyboard opens the menu from the header itself, under\n * Alt+Shift+ArrowDown, and a screen reader hears the\n * filtered state as the header's description.\n */\n <span\n className={classNames(\n \"header-filter-toggle\",\n filtered ? \"is-filtered\" : \"\",\n )}\n aria-hidden=\"true\"\n tabIndex={-1}\n onPointerDown={(event) => {\n // See the sort toggle's own note.\n event.stopPropagation();\n }}\n onClick={() => {\n toggleFilterMenu(entry.id);\n }}\n >\n <FilterIcon />\n </span>\n )}\n {entry.resizable && (\n /*\n * A pointer affordance only, and hidden from assistive\n * technology accordingly: a focusable handle per column would\n * put N tab stops inside a widget that is meant to have one.\n * The keyboard resizes from the header itself, under Alt.\n */\n <span\n className=\"header-resize-handle\"\n aria-hidden=\"true\"\n tabIndex={-1}\n onPointerDown={(event) => {\n resize.startResize(entry, event);\n }}\n onDoubleClick={() => {\n resize.sizeToContent(entry);\n }}\n />\n )}\n </th>\n );\n })}\n </tr>\n {/*\n * Portalled to the body, and not only because a `div` cannot sit in a\n * `tr`: inside the viewport the overflow that makes the grid scroll\n * would clip it.\n */}\n {draggedEntry !== null &&\n drag.ghostTransform !== null &&\n createPortal(\n <div\n className=\"gridkit-data-grid header-cell drag-ghost\"\n style={{\n width: draggedEntry.width,\n transform: drag.ghostTransform,\n }}\n aria-hidden=\"true\"\n >\n {draggedEntry.label}\n </div>,\n document.body,\n )}\n </thead>\n );\n}\n","/**\n * Collapses the `{...(condition && { \"aria-foo\": value })}` idiom for\n * conditionally including a single ARIA attribute in a JSX spread.\n */\nexport function ariaAttr<K extends string, V>(\n condition: boolean,\n key: K,\n value: V,\n): Record<K, V> | Record<string, never> {\n return condition ? ({ [key]: value } as Record<K, V>) : {};\n}\n","export function classNames(\n ...values: (string | false | null | undefined)[]\n): string {\n return values.filter(Boolean).join(\" \");\n}\n","import type { ReactNode } from \"react\";\n\n/** The common attributes behind every icon the grid draws — just the `<path>`s differ. */\nexport function Icon({ children }: { children: ReactNode }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n {children}\n </svg>\n );\n}\n\n/**\n * The two glyphs a sort toggle shows: a neutral hint before a column has a\n * direction, and a single chevron reused for both directions once it does —\n * `theme-tailwind` rotates it 180° for `desc` rather than swapping icons.\n */\nexport function ChevronsUpDownIcon() {\n return (\n <Icon>\n <path d=\"m7 15 5 5 5-5\" />\n <path d=\"m7 9 5-5 5 5\" />\n </Icon>\n );\n}\n\nexport function ChevronUpIcon() {\n return (\n <Icon>\n <path d=\"m18 15-6-6-6 6\" />\n </Icon>\n );\n}\n\n/** Three stacked panes, standing in for \"group by this column\". */\nexport function GroupIcon() {\n return (\n <Icon>\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\" />\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\" />\n <rect x=\"8.5\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\" />\n </Icon>\n );\n}\n\n/** A funnel, standing in for \"filter this column\". */\nexport function FilterIcon() {\n return (\n <Icon>\n <path d=\"M22 3H2l8 9.46V19l4 2v-8.54z\" />\n </Icon>\n );\n}\n","/**\n * Whether `event` happened inside the element whose handler is running.\n * React bubbles a portal's events up the component tree rather than the DOM,\n * so a panel rendered into `document.body` from inside the grid still reaches\n * the grid's key handlers — and Escape or Ctrl+A pressed in it is the\n * panel's, not the grid's.\n */\nexport function isOwnEvent(event: {\n readonly currentTarget: Element;\n readonly target: EventTarget;\n}): boolean {\n return (\n event.target instanceof Node && event.currentTarget.contains(event.target)\n );\n}\n","import {\n useEffect,\n useLayoutEffect,\n useState,\n useSyncExternalStore,\n type KeyboardEvent as ReactKeyboardEvent,\n type RefObject,\n} from \"react\";\nimport { HEADER_ROW, type GridFocus } from \"@gridkitjs/core\";\nimport {\n createGridFocus,\n findBodyRow,\n measurePageSize,\n type FocusVirtualRange,\n type GridFocusOptions,\n type GridFocusRows,\n} from \"@gridkitjs/dom\";\n\nexport { HEADER_ROW, type GridFocus };\n\ninterface UseGridNavigationOptions {\n headerTableRef: RefObject<HTMLTableElement | null>;\n bodyTableRef: RefObject<HTMLTableElement | null>;\n rowCount: number;\n columnCount: number;\n /**\n * Rows the vertical navigation keys step over rather than land a tab stop\n * on — a group's own summary row (`groupAggregateDisplay: \"row\"`), which\n * still occupies a real row slot for `rowCount` purposes but is\n * presentational, not a stop of its own. Left unset (skips nothing) for a\n * grid with no such rows.\n */\n isSkippableRow?: ((rowIndex: number) => boolean) | undefined;\n /**\n * The window `useRowVirtualizer` drew, present only when `virtualized` is\n * on, in which case behavior is otherwise unchanged. A focus move can\n * target a row index that isn't currently mounted — `ArrowDown` repeated\n * past the mounted window's end, or `End`/`Ctrl+End` jumping straight to\n * the last row.\n */\n virtualRange?: FocusVirtualRange | null | undefined;\n}\n\nexport interface GridNavigationApi {\n focus: GridFocus;\n /**\n * `0` for the focused cell and `-1` for every other. A grid is one tab stop:\n * tabbing reaches it, and the arrow keys move within it.\n */\n tabIndexFor: (rowIndex: number, columnIndex: number) => 0 | -1;\n /** Moves the tab stop, and the browser's focus with it. */\n focusCell: (rowIndex: number, columnIndex: number) => void;\n /**\n * `focusCell` for a cell on screen, whose browser focus moves now rather\n * than once the move is drawn — for something about to take focus from\n * it, such as a menu opened on it, which the drawing would pull focus back\n * out of. It renders nothing synchronously, so it is safe in an effect.\n */\n focusCellNow: (rowIndex: number, columnIndex: number) => void;\n /**\n * Moves the browser's focus to the cell holding the tab stop, as drawn now\n * — for when the element focus was to go back to has gone, as a header\n * does when a menu opened on it hides its column.\n */\n focusTabStop: () => void;\n /** Handles the navigation keys, leaving every other key to bubble. */\n onKeyDown: (event: ReactKeyboardEvent<HTMLElement>) => void;\n}\n\n/**\n * `0` for the column holding the tab stop and `-1` for every other.\n * Standalone rather than reached only through the hook's own `tabIndexFor`,\n * because `GridRow` is `memo()`-wrapped and cannot take the whole `nav`\n * object as a prop without defeating that boundary. Takes the row's own\n * already-narrowed `focusedColumnIndex` (`null` when focus sits on a\n * different row) rather than a `rowIndex`/`GridFocus` pair, since that\n * narrowing — done once per row in `GridBody` — is what keeps a focus move\n * from re-rendering every row instead of the two it actually touches.\n */\nexport function tabIndexFor(\n columnIndex: number,\n focusedColumnIndex: number | null,\n): 0 | -1 {\n return columnIndex === focusedColumnIndex ? 0 : -1;\n}\n\n/**\n * The grid's single tab stop, kept by `@gridkitjs/dom`'s `createGridFocus`\n * and drawn from it: created once, handed the current counts and window on\n * every render, and subscribed to, so a move re-renders the grid. The\n * header row comes from the header table's own `.tHead`; a body row through\n * `findBodyRow`, by its `data-gridkit-row-index`.\n */\nexport default function useGridNavigation({\n headerTableRef,\n bodyTableRef,\n rowCount,\n columnCount,\n isSkippableRow,\n virtualRange,\n}: UseGridNavigationOptions): GridNavigationApi {\n const options: GridFocusOptions = {\n rowCount,\n columnCount,\n isSkippableRow,\n virtualRange,\n };\n const [gridFocus] = useState(() => createGridFocus(options));\n gridFocus.setOptions(options);\n const focus = useSyncExternalStore(gridFocus.subscribe, gridFocus.getFocus);\n\n const [rows] = useState<GridFocusRows>(() => ({\n getHeaderRow: () => headerTableRef.current?.tHead?.rows[0] ?? null,\n getBodyRow: (rowIndex) => findBodyRow(bodyTableRef.current, rowIndex),\n }));\n useLayoutEffect(() => gridFocus.attach(rows), [gridFocus, rows]);\n\n // After every commit rather than only when `focus` changes: under\n // virtualization the target row may mount only in a later drawing, once\n // the window has scrolled to it, and this is what retries.\n useEffect(() => {\n gridFocus.focusDrawnCell(focus);\n });\n\n // A new object each render, as the other hooks here return: `tabIndexFor`\n // closes over the focus it draws.\n return {\n focus,\n tabIndexFor: (rowIndex, columnIndex) =>\n tabIndexFor(\n columnIndex,\n rowIndex === focus.rowIndex ? focus.columnIndex : null,\n ),\n focusCell: gridFocus.focusCell,\n focusCellNow: (rowIndex, columnIndex) => {\n gridFocus.focusCell(rowIndex, columnIndex);\n // The cell is drawn already, all but its tab stop, so the move is\n // followed now, and the drawing that redraws the stop has none left.\n gridFocus.focusDrawnCell(gridFocus.getFocus());\n },\n focusTabStop: () => {\n const cells = (\n focus.rowIndex === HEADER_ROW\n ? rows.getHeaderRow()\n : rows.getBodyRow(focus.rowIndex)\n )?.cells;\n // A group header's row has one cell, whatever column the stop is in.\n cells?.[Math.min(focus.columnIndex, cells.length - 1)]?.focus();\n },\n onKeyDown: (event) => {\n if (\n gridFocus.handleKey(\n event.key,\n event,\n measurePageSize(bodyTableRef.current),\n )\n ) {\n event.preventDefault();\n }\n },\n };\n}\n","import { useMemo, type KeyboardEvent as ReactKeyboardEvent } from \"react\";\nimport type {\n CellSelectionMode,\n CellSelectionState,\n GridState,\n SelectableConfig,\n SelectedCellRef,\n SelectIntent,\n SelectionMode,\n} from \"@gridkitjs/core\";\nimport type { DataGridController } from \"./useGridController\";\n\n/**\n * The modifiers a Space or Enter keydown carries, for a caller that means to\n * hand them to `intentOf` as a click's modifiers would be. Space builds a\n * selection up and Enter replaces it, as in the body — so Space is mapped to\n * act like Ctrl, matching Ctrl-click and the plain click they stand in for.\n */\nexport function keyboardSelectIntent(event: ReactKeyboardEvent): {\n ctrlKey: boolean;\n metaKey: boolean;\n shiftKey: boolean;\n} {\n return {\n ctrlKey: event.key === \" \" || event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n };\n}\n\ninterface UseGridSelectionOptions<Row> {\n controller: DataGridController<Row>;\n state: GridState<Row>;\n selectable: SelectableConfig | undefined;\n}\n\nexport interface GridSelectionApi {\n rowMode: SelectionMode;\n columnMode: SelectionMode;\n cellMode: CellSelectionMode;\n /** Whether a plain click on a row toggles it — `selectable.toggleOnClick`. */\n toggleOnClick: boolean;\n /**\n * Lookups for the render pass. The state itself stays an ordered list, which\n * is what makes the most recent selection its last entry.\n */\n selectedRowIds: ReadonlySet<string>;\n selectedColumnIds: ReadonlySet<string>;\n selectedCell: CellSelectionState;\n selectRow: (rowId: string, intent: SelectIntent) => void;\n selectColumn: (columnId: string, intent: SelectIntent) => void;\n selectCell: (cell: SelectedCellRef, intent: SelectIntent) => void;\n selectAllRows: () => void;\n /** Lets go of every selection at once, as Escape does. */\n clear: () => void;\n}\n\n/**\n * The selection as the header and body draw and change it. The selections\n * themselves, the intent each click carries and the callbacks it fires all\n * live in the grid's controller; this hook only adds the lookups a render\n * pass wants and names the actions the components call.\n */\nexport default function useGridSelection<Row>({\n controller,\n state,\n selectable,\n}: UseGridSelectionOptions<Row>): GridSelectionApi {\n const selectedRowIds = useMemo(\n () => new Set(state.rowSelection),\n [state.rowSelection],\n );\n const selectedColumnIds = useMemo(\n () => new Set(state.columnSelection),\n [state.columnSelection],\n );\n\n // A new object each render, as the other hooks here return.\n return {\n rowMode: selectable?.rows ?? false,\n columnMode: selectable?.columns ?? false,\n cellMode: selectable?.cells ?? false,\n toggleOnClick: selectable?.toggleOnClick ?? false,\n selectedRowIds,\n selectedColumnIds,\n selectedCell: state.cellSelection,\n selectRow: controller.selectRow,\n selectColumn: controller.selectColumn,\n selectCell: controller.selectCell,\n selectAllRows: controller.selectAllRows,\n clear: controller.clearSelection,\n };\n}\n","import {\n useMemo,\n useState,\n type MouseEvent as ReactMouseEvent,\n type RefObject,\n} from \"react\";\nimport {\n groupRowId,\n intentOf,\n type AggregateState,\n type DisplayRow,\n type FormatLocale,\n type GridMessages,\n type GridOptions,\n type GroupAggregateDisplay,\n type ResolvedRow,\n type RowPointerEvent,\n} from \"@gridkitjs/core\";\nimport {\n bodyCellFrom,\n bodyRowFrom,\n groupRowFrom,\n type BodyCellTarget,\n} from \"@gridkitjs/dom\";\nimport type {\n ColumnDefinition,\n InfiniteScrollConfig,\n ResolvedColumn,\n} from \"../DataGrid\";\nimport type { GridNavigationApi } from \"../useGridNavigation\";\nimport type { DataGridController } from \"../useGridController\";\nimport type { RowVirtualizerApi } from \"../useRowVirtualizer\";\nimport { isOwnEvent } from \"../isOwnEvent\";\nimport { createRowPropsResolver } from \"../rowProps\";\nimport {\n keyboardSelectIntent,\n type GridSelectionApi,\n} from \"../useGridSelection\";\nimport GridGroupRow from \"./GridGroupRow\";\nimport GridGroupSummaryRow from \"./GridGroupSummaryRow\";\nimport GridRow from \"./GridRow\";\n\ninterface GridBodyProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n /** Every column's definition by id, hidden ones included — a grid may group or aggregate by a column it does not show. */\n definitions: ReadonlyMap<string, ColumnDefinition<Row>>;\n rows: readonly DisplayRow<Row>[];\n /** The column being resized, so its cells outline with its header. */\n activeColumnId: string | null;\n nav: GridNavigationApi;\n selection: GridSelectionApi;\n /** What a group header's click or key press expands or collapses. */\n controller: DataGridController<Row>;\n /** Active aggregates. Empty when none are active. */\n aggregates: AggregateState<Row>;\n /** Where a group's aggregates render — inline in its header, or as its own summary row. */\n groupAggregateDisplay: GroupAggregateDisplay;\n /** Windows `rows` down to the rows near the current scroll position. `null` when `virtualized` is off, in which case every row of `rows` renders exactly as it always has. */\n virtualRange: RowVirtualizerApi | null;\n /** Renders a sentinel row (and, while loading, a loading row) as the last child of `<tbody>` when set. `undefined` renders neither. */\n infiniteScroll: InfiniteScrollConfig | undefined;\n /** Ref the sentinel row attaches to — owned and observed by `DataGrid.tsx`'s `useInfiniteScroll`, not by this component. */\n sentinelRef: RefObject<HTMLTableRowElement | null>;\n /** The grid's `locale`, which every cell and aggregate without a template is formatted for. */\n locale: FormatLocale;\n getRowProps: GridOptions<Row>[\"getRowProps\"];\n onRowClick: GridOptions<Row>[\"onRowClick\"];\n onRowDoubleClick: GridOptions<Row>[\"onRowDoubleClick\"];\n messages: GridMessages;\n /** Whether a data cell, or a group row, opens the grid's context menu — for their `aria-keyshortcuts`. */\n cellMenu: boolean;\n groupMenu: boolean;\n}\n\ninterface GroupAriaMeta {\n posinset: number;\n setsize: number;\n}\n\n/**\n * `aria-posinset`/`aria-setsize` per group header: its 1-based position\n * among, and count of, the group headers sharing its level and immediate\n * parent. Depth-first order (see `groupRows`) keeps siblings contiguous, so\n * one pass tallies each parent's total and a second assigns each header's\n * position within it.\n */\nfunction groupAriaMeta<Row>(\n rows: readonly DisplayRow<Row>[],\n): ReadonlyMap<string, GroupAriaMeta> {\n const totals = new Map<string, number>();\n for (const entry of rows) {\n if (!(\"kind\" in entry) || entry.kind !== \"group\") continue;\n const parentKey = groupRowId(entry.path.slice(0, -1));\n totals.set(parentKey, (totals.get(parentKey) ?? 0) + 1);\n }\n\n const seen = new Map<string, number>();\n const meta = new Map<string, GroupAriaMeta>();\n for (const entry of rows) {\n if (!(\"kind\" in entry) || entry.kind !== \"group\") continue;\n const parentKey = groupRowId(entry.path.slice(0, -1));\n const posinset = (seen.get(parentKey) ?? 0) + 1;\n seen.set(parentKey, posinset);\n meta.set(entry.groupId, {\n posinset,\n setsize: totals.get(parentKey) ?? posinset,\n });\n }\n return meta;\n}\n\n/**\n * Events are delegated to the body rather than bound per cell, which is what\n * lets `GridRow` be memoised: a handler rebuilt each render is a prop that\n * changes each render, and one reaching every row would defeat the boundary\n * entirely.\n */\nexport default function GridBody<Row>({\n columns,\n definitions,\n rows,\n activeColumnId,\n nav,\n selection,\n controller,\n aggregates,\n groupAggregateDisplay,\n virtualRange,\n infiniteScroll,\n sentinelRef,\n locale,\n getRowProps,\n onRowClick,\n onRowDoubleClick,\n messages,\n cellMenu,\n groupMenu,\n}: GridBodyProps<Row>) {\n const { selectedCell, rowMode, cellMode, toggleOnClick } = selection;\n const ariaMeta = useMemo(() => groupAriaMeta(rows), [rows]);\n // The full `rows` array otherwise — `virtualRange` is `null` whenever\n // `virtualized` is off, so this slice, and the spacer rows below, are a\n // no-op that reproduces today's output exactly.\n const visibleRows =\n virtualRange === null\n ? rows\n : rows.slice(virtualRange.startIndex, virtualRange.endIndex + 1);\n const { booleanTrue, booleanFalse, blankGroupValue } = messages;\n // Keyed on the strings rather than `messages`, so the memoised rows hold\n // still under a `messages` object rebuilt on every render.\n const cellMessages = useMemo(\n () => ({ booleanTrue, booleanFalse, blankGroupValue }),\n [booleanTrue, booleanFalse, blankGroupValue],\n );\n const [resolveRowProps] = useState(() => createRowPropsResolver<Row>());\n const rowPropsOf = resolveRowProps(\n visibleRows.filter(\n (entry): entry is ResolvedRow<Row> => !(\"kind\" in entry),\n ),\n getRowProps,\n );\n\n /** The row and cell an event addresses, resolved once for every handler. */\n function targetOf(\n target: EventTarget,\n ): { position: BodyCellTarget; rowId: string } | null {\n const position = bodyCellFrom(target);\n const entry = position === null ? undefined : rows[position.rowIndex];\n if (position === null || entry === undefined || \"kind\" in entry) {\n return null;\n }\n return { position, rowId: entry.rowId };\n }\n\n function select(\n rowId: string,\n columnId: string,\n modifiers: { ctrlKey: boolean; metaKey: boolean; shiftKey: boolean },\n ): void {\n // Independent of each other: selecting a cell says nothing about its row,\n // so a grid with both on reports both. `toggleOnClick` is the rows' own.\n if (rowMode !== false) {\n selection.selectRow(rowId, intentOf(modifiers, { toggleOnClick }));\n }\n if (cellMode !== false) {\n selection.selectCell({ rowId, columnId }, intentOf(modifiers));\n }\n }\n\n /**\n * What `onRowClick`/`onRowDoubleClick` are told of a pointer event on a\n * data row — `null` off one, a group header included. Unlike `targetOf`\n * it needs no cell: the row alone is enough to report.\n */\n function rowPointerEventOf(\n event: ReactMouseEvent,\n ): RowPointerEvent<Row> | null {\n const target = bodyRowFrom(event.target);\n const entry = target === null ? undefined : rows[target.rowIndex];\n if (target === null || entry === undefined || \"kind\" in entry) {\n return null;\n }\n return {\n row: entry,\n columnId: target.columnId,\n native: {\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n altKey: event.altKey,\n button: event.button,\n },\n };\n }\n\n function reportRowPointer(\n event: ReactMouseEvent,\n callback: ((event: RowPointerEvent<Row>) => void) | undefined,\n ): void {\n if (callback === undefined) return;\n const pointer = rowPointerEventOf(event);\n if (pointer !== null) {\n callback(pointer);\n }\n }\n\n return (\n <tbody\n className=\"grid-body\"\n onFocus={(event) => {\n const group = groupRowFrom(event.target);\n if (group !== null) {\n // One cell for the whole row — see the note on `focused` below.\n nav.focusCell(group.rowIndex, 0);\n return;\n }\n const found = targetOf(event.target);\n if (found === null) return;\n nav.focusCell(found.position.rowIndex, found.position.columnIndex);\n }}\n onClick={(event) => {\n const group = groupRowFrom(event.target);\n if (group !== null) {\n controller.toggleGroupExpansion(group.groupId);\n return;\n }\n const found = targetOf(event.target);\n if (found !== null) {\n select(found.rowId, found.position.columnId, event);\n }\n // After selecting, so a handler reading the selection sees this\n // click's.\n reportRowPointer(event, onRowClick);\n }}\n onDoubleClick={(event) => {\n reportRowPointer(event, onRowDoubleClick);\n }}\n onKeyDown={(event) => {\n if (!isOwnEvent(event)) return;\n const group = groupRowFrom(event.target);\n if (group !== null) {\n // One cell spans every column, so there is nothing to move within —\n // left/right stay a no-op rather than silently moving `nav`'s\n // stored column index off of a cell this row doesn't have.\n if (event.key === \"ArrowLeft\" || event.key === \"ArrowRight\") {\n event.preventDefault();\n return;\n }\n if (event.key === \" \" || event.key === \"Enter\") {\n event.preventDefault();\n controller.toggleGroupExpansion(group.groupId);\n return;\n }\n nav.onKeyDown(event);\n return;\n }\n\n // Space builds a selection up and Enter replaces it, matching the\n // Ctrl-click and the plain click they stand in for.\n if (event.key === \" \" || event.key === \"Enter\") {\n const found = targetOf(event.target);\n if (found === null) return;\n // Taken whether or not anything is selectable: Space would otherwise\n // scroll the grid out from under the focused cell.\n event.preventDefault();\n select(\n found.rowId,\n found.position.columnId,\n keyboardSelectIntent(event),\n );\n return;\n }\n nav.onKeyDown(event);\n }}\n >\n {virtualRange !== null && virtualRange.offsetBefore > 0 && (\n // `aria-hidden` and carrying neither `data-gridkit-column` nor\n // `data-gridkit-group`/`data-gridkit-row-index`, so `bodyCellFrom`/\n // `groupRowFrom` never mistake it for a real row — it exists purely\n // to give the browser's scrollbar the correct total height and thumb\n // position, the same way `GridFooter`'s `<tfoot>` isn't a \"row\" to\n // any of this grid's own row-counting logic.\n <tr aria-hidden=\"true\">\n <td\n style={{\n height: virtualRange.offsetBefore,\n padding: 0,\n border: \"none\",\n }}\n />\n </tr>\n )}\n {visibleRows.map((entry) => {\n if (!(\"kind\" in entry)) {\n const rowProps = rowPropsOf(entry.rowId);\n return (\n <GridRow<Row>\n key={entry.rowId}\n ref={virtualRange?.measureRow(entry.rowIndex)}\n columns={columns}\n rowId={entry.rowId}\n row={entry.row}\n rowIndex={entry.rowIndex}\n datasetIndex={entry.datasetIndex}\n activeColumnId={activeColumnId}\n selectedColumnIds={selection.selectedColumnIds}\n selected={selection.selectedRowIds.has(entry.rowId)}\n /*\n * Narrowed to this row before it crosses the boundary, so\n * that moving the selected cell re-renders the two rows it\n * moved between rather than all of them.\n */\n selectedColumnId={\n selectedCell?.rowId === entry.rowId\n ? selectedCell.columnId\n : null\n }\n focusedColumnIndex={\n nav.focus.rowIndex === entry.rowIndex\n ? nav.focus.columnIndex\n : null\n }\n rowsSelectable={rowMode !== false}\n cellsSelectable={cellMode !== false}\n contextMenu={cellMenu}\n locale={locale}\n cellMessages={cellMessages}\n rowClassName={rowProps.className}\n rowAttributes={rowProps.attributes}\n />\n );\n }\n\n if (entry.kind === \"group-summary\") {\n return (\n <GridGroupSummaryRow<Row>\n key={`${entry.groupId}-summary`}\n ref={virtualRange?.measureRow(entry.rowIndex)}\n groupId={entry.groupId}\n level={entry.level}\n rowIndex={entry.rowIndex}\n datasetIndex={entry.datasetIndex}\n results={entry.aggregates}\n aggregates={aggregates}\n columns={columns}\n locale={locale}\n />\n );\n }\n\n return (\n <GridGroupRow\n key={entry.groupId}\n ref={virtualRange?.measureRow(entry.rowIndex)}\n columnCount={columns.length}\n groupId={entry.groupId}\n level={entry.level}\n // A grouping by a column the grid does not have reads its value\n // by its kind alone.\n groupColumn={\n definitions.get(entry.columnId) ?? { field: entry.columnId }\n }\n value={entry.value}\n expanded={entry.expanded}\n count={entry.count}\n rowIndex={entry.rowIndex}\n datasetIndex={entry.datasetIndex}\n posinset={ariaMeta.get(entry.groupId)?.posinset ?? 1}\n setsize={ariaMeta.get(entry.groupId)?.setsize ?? 1}\n // Inline rendering only under \"inline\" display — under \"row\",\n // the group's own summary row (above) already shows these, and\n // showing them twice would be redundant.\n aggregates={groupAggregateDisplay === \"inline\" ? aggregates : []}\n results={entry.aggregates}\n definitions={definitions}\n locale={locale}\n cellMessages={cellMessages}\n // Ignores `nav.focus.columnIndex`: with only one cell in this\n // row, whether it holds the tab stop depends on `rowIndex`\n // alone.\n focused={nav.focus.rowIndex === entry.rowIndex}\n contextMenu={groupMenu}\n />\n );\n })}\n {virtualRange !== null && virtualRange.offsetAfter > 0 && (\n <tr aria-hidden=\"true\">\n <td\n style={{\n height: virtualRange.offsetAfter,\n padding: 0,\n border: \"none\",\n }}\n />\n </tr>\n )}\n {/*\n * Presentational, like the spacer rows above: neither carries\n * `data-gridkit-row-index`/`data-gridkit-column`, so `bodyCellFrom`/\n * `groupRowFrom` never match them, and neither is part of `rows` (the\n * array `aria-rowcount` and `useGridNavigation`'s `rowCount` are\n * computed from in `DataGrid.tsx`), so both are already excluded from\n * row counting and keyboard navigation without any extra check here.\n */}\n {infiniteScroll?.hasMore && (\n <>\n {infiniteScroll.isLoadingMore === true && (\n <tr aria-hidden=\"true\" className=\"grid-loading-row\">\n <td colSpan={columns.length} className=\"grid-loading-cell\">\n {infiniteScroll.loadingTemplate\n ? infiniteScroll.loadingTemplate()\n : messages.loadingMore}\n </td>\n </tr>\n )}\n <tr\n aria-hidden=\"true\"\n ref={sentinelRef}\n className=\"grid-sentinel-row\"\n >\n <td\n colSpan={columns.length}\n style={{ padding: 0, border: \"none\" }}\n />\n </tr>\n </>\n )}\n </tbody>\n );\n}\n","import type { ResolvedRow, RowProps } from \"@gridkitjs/core\";\n\nexport type RowAttributes = Readonly<Record<`data-${string}`, string>>;\n\n/** What `GridRow` is handed from `getRowProps`, both always present. */\nexport interface ResolvedRowProps {\n readonly className: string;\n readonly attributes: RowAttributes;\n}\n\n/** Shared by every row without attributes, so each compares equal to the last. */\nexport const NO_ATTRIBUTES: RowAttributes = {};\n\nconst NO_ROW_PROPS: ResolvedRowProps = {\n className: \"\",\n attributes: NO_ATTRIBUTES,\n};\n\nfunction sameAttributes(a: RowAttributes, b: RowAttributes): boolean {\n const keys = Object.keys(a) as (keyof RowAttributes)[];\n return (\n keys.length === Object.keys(b).length &&\n keys.every((key) => a[key] === b[key])\n );\n}\n\n/**\n * Runs `getRowProps` over the rows about to render, keeping each row's\n * attributes the same object as last time while they read the same.\n *\n * `GridRow` is memoised, and `getRowProps` returns a fresh attributes object\n * on every call — often from an inline arrow that is itself new on every\n * render — so handing those objects straight through would redraw every row\n * on every render. The class is a string and compares by value already.\n *\n * Remembers only the rows of the latest call, so a virtualized grid scrolled\n * over many rows holds no more than the ones on screen.\n */\nexport function createRowPropsResolver<Row>(): (\n rows: readonly ResolvedRow<Row>[],\n getRowProps: ((row: ResolvedRow<Row>) => RowProps) | undefined,\n) => (rowId: string) => ResolvedRowProps {\n let previous = new Map<string, RowAttributes>();\n return (rows, getRowProps) => {\n if (getRowProps === undefined) {\n previous = new Map();\n return () => NO_ROW_PROPS;\n }\n const resolved = new Map<string, ResolvedRowProps>();\n const attributesById = new Map<string, RowAttributes>();\n for (const entry of rows) {\n const { className = \"\", attributes = NO_ATTRIBUTES } = getRowProps(entry);\n const last = previous.get(entry.rowId);\n const stable =\n last !== undefined && sameAttributes(last, attributes)\n ? last\n : attributes;\n attributesById.set(entry.rowId, stable);\n resolved.set(entry.rowId, { className, attributes: stable });\n }\n previous = attributesById;\n return (rowId) => resolved.get(rowId) ?? NO_ROW_PROPS;\n };\n}\n","import { memo, type Ref } from \"react\";\nimport {\n formatGroupValue,\n resolveColumnLabel,\n type AggregateResults,\n type AggregateState,\n type FormatLocale,\n type GridMessages,\n} from \"@gridkitjs/core\";\nimport type { ColumnDefinition } from \"../DataGrid\";\nimport { classNames } from \"../classNames\";\nimport { renderAggregate } from \"./renderAggregate\";\n\ninterface GridGroupRowProps<Row> {\n /** How many columns this group's header spans, matching the grid's own count. */\n columnCount: number;\n groupId: string;\n /** Nesting depth, 0 for a top-level group — indents the header and feeds `aria-level`. */\n level: number;\n /** The column grouped by, whose label names the group and whose formatting its value reads in. */\n groupColumn: ColumnDefinition<Row>;\n /** This group's own value — the last entry of its `path`. */\n value: unknown;\n expanded: boolean;\n /** Leaf row count under this group, regardless of collapse state. */\n count: number;\n /** This row's position in the full (unsliced) display-rows array — see `ResolvedGroupRow.rowIndex`. */\n rowIndex: number;\n /** This header's absolute position in the whole dataset, unaffected by which page is showing — see `ResolvedGroupRow.datasetIndex`. */\n datasetIndex: number;\n /** This group's 1-based position among its own siblings, for `aria-posinset`. */\n posinset: number;\n /** How many siblings this group has, for `aria-setsize`. */\n setsize: number;\n /** Whether this row currently holds the grid's single tab stop. */\n focused: boolean;\n /** Whether this row opens the grid's context menu, which its `aria-keyshortcuts` says. */\n contextMenu: boolean;\n /** Active aggregates — empty when none are active, in which case no subtotal renders. */\n aggregates: AggregateState<Row>;\n /** This group's own computed results, keyed the same way `aggregates` resolves each spec's key. */\n results: AggregateResults;\n /** Every column's definition by id, hidden ones included — whose label and formatting each aggregate takes. */\n definitions: ReadonlyMap<string, ColumnDefinition<Row>>;\n /** The grid's `locale`, which values are formatted for. */\n locale: FormatLocale;\n /** The words for a boolean or missing group value, from `messages` — memoised by `GridBody`. */\n cellMessages: Pick<\n GridMessages,\n \"booleanTrue\" | \"booleanFalse\" | \"blankGroupValue\"\n >;\n ref?: Ref<HTMLTableRowElement> | undefined;\n}\n\nfunction GridGroupRowComponent<Row>({\n columnCount,\n groupId,\n level,\n groupColumn,\n value,\n expanded,\n count,\n rowIndex,\n datasetIndex,\n posinset,\n setsize,\n focused,\n contextMenu,\n aggregates,\n results,\n definitions,\n locale,\n cellMessages,\n ref,\n}: GridGroupRowProps<Row>) {\n return (\n <tr\n ref={ref}\n role=\"row\"\n // Two past the index: rows are counted from one, and the header is the\n // first of them — the same convention `GridRow` uses. Built from\n // `datasetIndex`, not the page-relative `rowIndex`, matching `GridRow`.\n aria-rowindex={datasetIndex + 2}\n // 1-based, per the WAI-ARIA treegrid pattern.\n aria-level={level + 1}\n aria-expanded={expanded}\n aria-setsize={setsize}\n aria-posinset={posinset}\n data-gridkit-group={groupId}\n // See `GridRow`'s own `data-gridkit-row-index` for why this reads off\n // the array position rather than the DOM's `sectionRowIndex`.\n data-gridkit-row-index={rowIndex}\n className={classNames(\n \"grid-group-row\",\n `is-group-level-${String(level)}`,\n )}\n >\n <td\n role=\"gridcell\"\n colSpan={columnCount}\n tabIndex={focused ? 0 : -1}\n aria-keyshortcuts={\n contextMenu ? \"Space Enter Shift+F10\" : \"Space Enter\"\n }\n className=\"grid-group-cell\"\n >\n {/*\n * The flex layout lives on this inner `div`, not the `<td>` itself:\n * a `display` other than `table-cell` on the cell element changes\n * its box type entirely, and the browser fixes that up by wrapping\n * it in an anonymous table-cell — which throws off the cell's own\n * hit-testing (a click landing where the row's bounding box says\n * the cell is can miss it and hit the table underneath instead).\n */}\n <div\n className=\"grid-group-cell-content\"\n style={{ paddingInlineStart: `${String(level * 1.25 + 0.5)}rem` }}\n >\n <span\n className={classNames(\n \"group-toggle\",\n expanded ? \"is-expanded\" : \"is-collapsed\",\n )}\n aria-hidden=\"true\"\n />\n <span className=\"group-label\">\n {resolveColumnLabel(groupColumn)}:{\" \"}\n {formatGroupValue(value, groupColumn, locale, cellMessages)}\n </span>\n <span className=\"group-count\">({count})</span>\n {aggregates.length > 0 && (\n <span className=\"group-aggregates\">\n {aggregates.map((spec) => {\n const key = spec.id ?? spec.columnId;\n const aggregateValue = results.get(key);\n const column = definitions.get(spec.columnId);\n const rendered = renderAggregate(\n aggregateValue,\n spec,\n column,\n [],\n locale,\n );\n // An explicit `id` disambiguates two specs on the same\n // column (e.g. both `sum` and `avg` of Amount) — when given,\n // it's the caller's own label for this result, so it takes\n // priority over the column's shared label.\n const aggregateLabel =\n spec.id ??\n (column === undefined\n ? spec.columnId\n : resolveColumnLabel(column));\n return (\n <span key={key} className=\"group-aggregate\">\n {aggregateLabel}: {rendered}\n </span>\n );\n })}\n </span>\n )}\n </div>\n </td>\n </tr>\n );\n}\n\n/**\n * `memo()`-wrapped for the same reason `GridRow` is: every prop here is a\n * scalar or an already-narrowed value, and no handler reaches this component\n * directly — `GridBody` delegates group-header clicks and keydowns the same\n * way it does for data rows.\n */\nconst GridGroupRow = memo(\n GridGroupRowComponent,\n) as typeof GridGroupRowComponent;\n\nexport default GridGroupRow;\n","import type { ReactNode } from \"react\";\nimport {\n formatAggregateValue,\n type AggregateSpec,\n type FormatLocale,\n} from \"@gridkitjs/core\";\nimport type { ColumnDefinition } from \"../DataGrid\";\n\n/**\n * One aggregate result as the grid shows it — in the grand-total footer, a\n * group's summary row, or inline in a group's header. The column's own\n * `footerTemplate` when it has one; otherwise the text\n * `formatAggregateValue` makes of it, with a dash standing in for an empty\n * result so a cell that has an aggregate never looks like one that has none.\n */\nexport function renderAggregate<Row>(\n value: unknown,\n spec: AggregateSpec<Row>,\n column: ColumnDefinition<Row> | undefined,\n rows: readonly Row[],\n locale: FormatLocale,\n): ReactNode {\n if (column?.footerTemplate) {\n return column.footerTemplate({ value, rows });\n }\n if (value === null || value === undefined) {\n return \"—\";\n }\n return formatAggregateValue(value, spec, column, locale);\n}\n","import { memo, type Ref } from \"react\";\nimport type {\n AggregateResults,\n AggregateState,\n FormatLocale,\n} from \"@gridkitjs/core\";\nimport type { ResolvedColumn } from \"../DataGrid\";\nimport { classNames } from \"../classNames\";\nimport { renderAggregate } from \"./renderAggregate\";\n\ninterface GridGroupSummaryRowProps<Row> {\n groupId: string;\n /** Nesting depth, matching the group's own level — indents the row the same amount `GridGroupRow` does. */\n level: number;\n /** This row's position in the full (unsliced) display-rows array — see `ResolvedGroupSummaryRow.rowIndex`. */\n rowIndex: number;\n /** This row's absolute position in the whole dataset, unaffected by which page is showing — see `ResolvedGroupSummaryRow.datasetIndex`. */\n datasetIndex: number;\n /** The group's own computed results — identical to its header's `aggregates`. */\n results: AggregateResults;\n aggregates: AggregateState<Row>;\n columns: readonly ResolvedColumn<Row>[];\n /** The grid's `locale`, which values are formatted for. */\n locale: FormatLocale;\n ref?: Ref<HTMLTableRowElement> | undefined;\n}\n\n/**\n * A group's own aggregate results, one real `<td>` per column rather than\n * text inside the header's single spanning cell — the `groupAggregateDisplay:\n * \"row\"` alternative to `GridGroupRow`'s own inline rendering. Structurally\n * mirrors `GridFooter`'s grand-total row, scoped to one group's `results`\n * instead of the dataset-wide total, and indented the same amount its own\n * `GridGroupRow` is.\n *\n * Presentational: it occupies a real row slot (counted in `rowCount`/\n * `aria-rowindex`, since it is a genuine `<tr>` inside `<tbody>`) but is\n * never a keyboard tab stop — `DataGrid.tsx`'s `isSkippableRow` steps over\n * it during arrow-key navigation the same way this component itself takes\n * no `tabIndex`, `role=\"row\"`/`\"gridcell\"` only, no interactive attributes.\n *\n * Each cell's alignment follows the same rule `GridFooter`'s own cells do:\n * the first matching spec's `AggregateSpec.alignment` override, falling\n * back to the column's own `alignment` when neither is set.\n */\nfunction GridGroupSummaryRowComponent<Row>({\n groupId,\n level,\n rowIndex,\n datasetIndex,\n results,\n aggregates,\n columns,\n locale,\n ref,\n}: GridGroupSummaryRowProps<Row>) {\n return (\n <tr\n ref={ref}\n role=\"row\"\n aria-rowindex={datasetIndex + 2}\n data-gridkit-group-summary={groupId}\n // See `GridRow`'s own `data-gridkit-row-index` for why this reads off\n // the array position rather than the DOM's `sectionRowIndex`.\n data-gridkit-row-index={rowIndex}\n className={classNames(\n \"grid-group-summary-row\",\n `is-group-level-${String(level)}`,\n )}\n >\n {columns.map((entry) => {\n const specs = aggregates.filter(\n (candidate) => candidate.columnId === entry.id,\n );\n\n return (\n <td\n key={entry.id}\n role=\"gridcell\"\n data-gridkit-column={entry.id}\n className=\"grid-group-summary-cell\"\n style={{ textAlign: specs[0]?.alignment ?? entry.alignment }}\n >\n {entry.id === columns[0]?.id && (\n <span\n className=\"grid-group-summary-indent\"\n style={{ width: `${String(level * 1.25 + 0.5)}rem` }}\n aria-hidden=\"true\"\n />\n )}\n {specs\n .map((spec) =>\n renderAggregate(\n results.get(spec.id ?? spec.columnId),\n spec,\n entry.column,\n [],\n locale,\n ),\n )\n .flatMap((rendered, index) =>\n index === 0 ? [rendered] : [\", \", rendered],\n )}\n </td>\n );\n })}\n </tr>\n );\n}\n\n/**\n * `memo()`-wrapped for the same reason `GridGroupRow`/`GridRow` are: every\n * prop here is a scalar or an already-narrowed value.\n */\nconst GridGroupSummaryRow = memo(\n GridGroupSummaryRowComponent,\n) as typeof GridGroupSummaryRowComponent;\n\nexport default GridGroupSummaryRow;\n","import {\n accessDotted,\n formatCellValue,\n type FormatLocale,\n type GridMessages,\n} from \"@gridkitjs/core\";\nimport { memo, type Ref } from \"react\";\nimport type { ResolvedColumn } from \"../DataGrid\";\nimport { ariaAttr } from \"../ariaAttr\";\nimport { classNames } from \"../classNames\";\nimport type { RowAttributes } from \"../rowProps\";\nimport { tabIndexFor } from \"../useGridNavigation\";\n\ninterface GridRowProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n rowId: string;\n row: Row;\n rowIndex: number;\n /** This row's absolute position in the whole dataset, unaffected by which page is showing — see `CellTemplateContext.datasetIndex`. */\n datasetIndex: number;\n /** The column being resized, so its cells outline with its header. */\n activeColumnId: string | null;\n selectedColumnIds: ReadonlySet<string>;\n selected: boolean;\n /** Which of this row's cells is the selected one, if any. */\n selectedColumnId: string | null;\n /** Which of this row's cells holds the grid's tab stop, if any. */\n focusedColumnIndex: number | null;\n rowsSelectable: boolean;\n cellsSelectable: boolean;\n /** Whether a cell opens the grid's context menu, which its `aria-keyshortcuts` says. */\n contextMenu: boolean;\n /** The grid's `locale`, which a cell without a template is formatted for. */\n locale: FormatLocale;\n /** A boolean cell's words, from `messages` — memoised on the two strings by `GridBody`. */\n cellMessages: Pick<GridMessages, \"booleanTrue\" | \"booleanFalse\">;\n /** The class `getRowProps` gave this row, `\"\"` for none. */\n rowClassName: string;\n /** The `data-*` attributes `getRowProps` gave this row — the same object while they read the same, so they do not defeat `memo`. */\n rowAttributes: RowAttributes;\n ref?: Ref<HTMLTableRowElement> | undefined;\n}\n\nfunction GridRowComponent<Row>({\n columns,\n rowId,\n row,\n rowIndex,\n datasetIndex,\n activeColumnId,\n selectedColumnIds,\n selected,\n selectedColumnId,\n focusedColumnIndex,\n rowsSelectable,\n cellsSelectable,\n contextMenu,\n locale,\n cellMessages,\n rowClassName,\n rowAttributes,\n ref,\n}: GridRowProps<Row>) {\n // The ContextMenu key needs no mention: it says what it does on its face.\n const shortcuts = [\n cellsSelectable ? \"Space Enter\" : \"\",\n contextMenu ? \"Shift+F10\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n return (\n <tr\n // First, so the grid's own attributes below win over one of the same\n // name: `GridBody` finds rows by them.\n {...rowAttributes}\n ref={ref}\n role=\"row\"\n // Two past the index: rows are counted from one, and the header is the\n // first of them. Built from `datasetIndex` rather than the\n // page-relative `rowIndex`, so a paginated grid still reports each\n // row's true position in the whole dataset — the two only diverge once\n // pagination is on.\n aria-rowindex={datasetIndex + 2}\n // This row's position in the full (unsliced) rows array — read by\n // `GridBody`'s event delegation (`bodyCellFrom`) instead of the DOM's own\n // `sectionRowIndex`, which under virtualization no longer matches a\n // row's array position once a leading spacer `<tr>` shifts it.\n data-gridkit-row-index={rowIndex}\n // The row's identity, for a test or a script to find it by however it\n // has moved — the index above changes with every sort.\n data-gridkit-row-id={rowId}\n // Omitted rather than `false` when rows cannot be selected, which would\n // otherwise have every row announce that it is not.\n {...ariaAttr(rowsSelectable, \"aria-selected\", selected)}\n className={classNames(\n \"grid-row\",\n selected ? \"is-selected\" : \"\",\n rowClassName,\n )}\n >\n {columns.map(({ id, column, alignment }, columnIndex) => {\n // Resolved either way, so a template never has to walk the field path\n // a second time.\n const value = accessDotted(row, column.field);\n const cellSelected = id === selectedColumnId;\n\n return (\n <td\n key={id}\n role=\"gridcell\"\n data-gridkit-column={id}\n aria-colindex={columnIndex + 1}\n tabIndex={tabIndexFor(columnIndex, focusedColumnIndex)}\n {...ariaAttr(cellsSelectable, \"aria-selected\", cellSelected)}\n {...ariaAttr(shortcuts !== \"\", \"aria-keyshortcuts\", shortcuts)}\n className={classNames(\n \"grid-cell\",\n id === activeColumnId ? \"is-resizing\" : \"\",\n cellSelected || selectedColumnIds.has(id) ? \"is-selected\" : \"\",\n column.wrap?.cells ? \"is-wrapped\" : \"\",\n column.cellClassName ?? \"\",\n )}\n style={{ textAlign: alignment }}\n >\n {column.cellTemplate\n ? column.cellTemplate({\n value,\n row,\n rowIndex,\n datasetIndex,\n rowId,\n selected,\n })\n : formatCellValue(value, column, locale, row, cellMessages)}\n </td>\n );\n })}\n </tr>\n );\n}\n\n/**\n * Selection lives at the top of the grid, so any change to it re-renders the\n * whole body — without this boundary a click would rebuild every cell of every\n * row rather than the one or two rows that changed.\n *\n * Every prop above is a scalar or already memoised for that reason, and no\n * handler reaches here at all: the body delegates its events, so a row has\n * nothing to compare that changes each render.\n *\n * `memo` erases the type parameter, and the cast puts it back — the standard\n * price of memoising a generic component.\n */\nconst GridRow = memo(GridRowComponent) as typeof GridRowComponent;\n\nexport default GridRow;\n","import type {\n AggregateResults,\n AggregateState,\n FormatLocale,\n} from \"@gridkitjs/core\";\nimport type { ResolvedColumn } from \"../DataGrid\";\nimport { renderAggregate } from \"./renderAggregate\";\n\ninterface GridFooterProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n aggregates: AggregateState<Row>;\n results: AggregateResults;\n /** Every row the grand total was computed over — what a `footerTemplate` receives as `rows`. */\n rows: readonly Row[];\n /** The grid's `locale`, which values are formatted for. */\n locale: FormatLocale;\n}\n\n/**\n * The grand-total footer — one `<tfoot>` row, one cell per column, using\n * that column's own `footerTemplate` when it defines one, its own computed\n * value formatted like the column's values when it doesn't, and a blank cell for a column\n * with no aggregate at all. Structurally mirrors `GridHeader`, minus\n * everything interactive: a footer cell is not resizable, sortable, or\n * selectable.\n *\n * A column named by more than one spec (e.g. both `sum` and `avg` of the\n * same column, disambiguated by `id`) renders every matching spec's result\n * in its one cell, comma-separated — the cell grid stays one-per-column,\n * but no result is dropped the way picking only the first match would. The\n * cell's own alignment follows the first matching spec's `AggregateSpec.\n * alignment` override, falling back to the column's own `alignment` when\n * neither is set — one `<td>` can only take one `text-align`, so a second\n * spec's own override (if it disagrees) applies only to its value, not the\n * cell.\n *\n * Sits outside `<tbody>`'s row count on purpose — a `<tfoot>` is not part\n * of `aria-rowcount`/`aria-rowindex`/keyboard navigation's `rowCount`, the\n * same way `<thead>`'s header row is counted separately from data rows.\n */\nexport default function GridFooter<Row>({\n columns,\n aggregates,\n results,\n rows,\n locale,\n}: GridFooterProps<Row>) {\n return (\n <tfoot>\n <tr className=\"grid-footer\" role=\"row\">\n {columns.map((entry) => {\n const specs = aggregates.filter(\n (candidate) => candidate.columnId === entry.id,\n );\n\n return (\n <td\n key={entry.id}\n role=\"gridcell\"\n data-gridkit-column={entry.id}\n className=\"grid-footer-cell\"\n style={{ textAlign: specs[0]?.alignment ?? entry.alignment }}\n >\n {specs\n .map((spec) =>\n renderAggregate(\n results.get(spec.id ?? spec.columnId),\n spec,\n entry.column,\n rows,\n locale,\n ),\n )\n // Two values in one cell need a visible separator; a single\n // one (the common case) renders exactly as before.\n .flatMap((rendered, index) =>\n index === 0 ? [rendered] : [\", \", rendered],\n )}\n </td>\n );\n })}\n </tr>\n </tfoot>\n );\n}\n","import { paginationWindow, type GridMessages } from \"@gridkitjs/core\";\nimport type { PagerConfig, PagerTemplateContext } from \"../DataGrid\";\n\ninterface GridPagerProps {\n /** The same context a `pager.template` is handed. */\n pager: PagerTemplateContext;\n /** Presentation options for the pager. `undefined` renders the `\"compact\"` default with no page-size control. */\n config: PagerConfig | undefined;\n messages: GridMessages;\n}\n\n/**\n * A minimal, semantically-classed pager: previous/next, a page-index\n * display (or, under `config.variant === \"numbered\"`, a row of page\n * buttons), and — when `config.sizeOptions` is given — a page-size\n * `<select>`. Rendered as a sibling below the table, not a row inside it,\n * the same reasoning `GroupByBar` gives for its own placement: a control\n * surface, not grid content.\n *\n * Whether this mounts at all is `DataGrid.tsx`'s call (`paginated`), not\n * this component's own.\n */\nexport default function GridPager({ pager, config, messages }: GridPagerProps) {\n const { pagination, pageCount, currentPage } = pager;\n const variant = config?.variant ?? \"compact\";\n const sizeOptions = config?.sizeOptions;\n\n return (\n <div\n className=\"gridkit-grid-pager\"\n role=\"group\"\n aria-label={messages.pagerLabel}\n >\n <button\n type=\"button\"\n className=\"grid-pager-button\"\n disabled={pagination.pageIndex <= 0}\n onClick={() => {\n pager.previousPage();\n }}\n >\n {messages.previousPage}\n </button>\n {variant === \"numbered\" ? (\n paginationWindow(currentPage, pageCount, {\n boundaryCount: config?.boundaryCount,\n siblingCount: config?.siblingCount,\n }).map((entry, index) =>\n entry === \"ellipsis\" ? (\n <span\n key={`ellipsis-${String(index)}`}\n className=\"grid-pager-ellipsis\"\n aria-hidden=\"true\"\n >\n …\n </span>\n ) : (\n <button\n key={entry}\n type=\"button\"\n className=\"grid-pager-button\"\n aria-label={messages.pageButtonLabel(entry)}\n aria-current={entry === currentPage ? \"page\" : undefined}\n onClick={() => {\n pager.goToPage(entry - 1);\n }}\n >\n {entry}\n </button>\n ),\n )\n ) : (\n <span className=\"grid-pager-status\">\n {messages.pageStatus(pageCount === 0 ? 0 : currentPage, pageCount)}\n </span>\n )}\n <button\n type=\"button\"\n className=\"grid-pager-button\"\n disabled={pagination.pageIndex >= pageCount - 1}\n onClick={() => {\n pager.nextPage();\n }}\n >\n {messages.nextPage}\n </button>\n {sizeOptions !== undefined && sizeOptions.length > 0 && (\n <label className=\"grid-pager-page-size\">\n {messages.pageSizeLabel}\n <select\n value={pagination.pageSize}\n onChange={(event) => {\n pager.setPageSize(Number(event.target.value));\n }}\n >\n {sizeOptions.map((size) => (\n <option key={size} value={size}>\n {size}\n </option>\n ))}\n </select>\n </label>\n )}\n </div>\n );\n}\n","import { createPortal } from \"react-dom\";\nimport {\n resolveColumnLabel,\n resolveKeyboardDropTarget,\n type GridMessages,\n type GroupByState,\n} from \"@gridkitjs/core\";\nimport type { GroupByDropTarget } from \"@gridkitjs/dom\";\nimport type { ColumnDefinition, ResolvedColumn } from \"../DataGrid\";\nimport { classNames } from \"../classNames\";\nimport useGroupByDrag from \"../useGroupByDrag\";\nimport type { DataGridController } from \"../useGridController\";\n\ninterface GroupByBarProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n /** Every column's definition by id, hidden ones included, so a chip for a hidden column still carries its label. */\n definitions: ReadonlyMap<string, ColumnDefinition<Row>>;\n groupBy: GroupByState;\n /** What a chip's drag, move or remove button changes. */\n controller: DataGridController<Row>;\n /** A column's accessible name — see `DataGrid.tsx`'s own `columnName`. */\n columnName: (columnId: string) => string;\n /** Whether the header drag currently open (if any) could drop into this bar. */\n headerDragEligible: boolean;\n /**\n * Whether the header drag currently open (if any) is for a column already\n * in the group-by stack — a drag this bar rejects outright, since\n * repositioning a grouped column is the chip's job, not the header's.\n */\n headerDragBlocked: boolean;\n /** That header drag's own target within this bar, or `null`. */\n headerDropTarget: GroupByDropTarget | null;\n messages: GridMessages;\n}\n\n/**\n * The active group-by stack, outer to inner, as removable, reorderable\n * chips — and the drop target for a header dragged in from outside it.\n * Each column's own header already carries a group toggle (a pointer\n * affordance, plus `Alt+ArrowDown`) for adding or removing a level without\n * dragging at all; this bar shows the resulting stack, lets a level be\n * removed from it directly, lets a chip be dragged to reorder the stack (or\n * moved via `Ctrl+ArrowLeft`/`Ctrl+ArrowRight` on a focused one), and — for\n * a column whose header sets `groupByDraggable` and isn't grouped yet —\n * accepts a header dropped onto it, at whatever position among the existing\n * chips it's released. A header for a column already in the stack is\n * rejected outright (`is-drag-blocked`, `cursor: not-allowed`): the header\n * only ever adds, and repositioning an existing level is the chip's job.\n *\n * Whether this component mounts at all is `DataGrid.tsx`'s call\n * (`groupByBarVisibility`), not this component's own — it never bails out\n * on its own initiative once rendered.\n *\n * Chips sit outside the grid's own single-roving-tabstop model: there is no\n * shared index to keep in sync the way a row or a header cell has, so each\n * chip (and its own remove button) is simply, always `tabIndex={0}` — plain\n * DOM tab order, no roving-focus bookkeeping.\n */\nexport default function GroupByBar<Row>({\n columns,\n definitions,\n groupBy,\n controller,\n columnName,\n headerDragEligible,\n headerDragBlocked,\n headerDropTarget,\n messages,\n}: GroupByBarProps<Row>) {\n const groupByIds = groupBy.map((entry) => entry.columnId);\n\n const chipDrag = useGroupByDrag({\n groupBy,\n onDrop: (movedId, beforeColumnId) => {\n controller.moveGroupBy(movedId, beforeColumnId);\n },\n });\n\n // Mutually exclusive by construction — one pointer, so at most one of \"a\n // chip dragged within this bar\" and \"a header dragged in from outside it\"\n // is ever active at once.\n const activeDropTarget = chipDrag.dropTarget ?? headerDropTarget;\n const isDragTarget = chipDrag.draggedColumnId !== null || headerDragEligible;\n const showPlaceholder =\n groupBy.length === 0 && columns.some((entry) => entry.groupByDraggable);\n\n function labelFor(columnId: string) {\n const definition = definitions.get(columnId);\n return definition === undefined ? columnId : resolveColumnLabel(definition);\n }\n\n function moveByKeyboard(columnId: string, direction: -1 | 1): void {\n const beforeColumnId = resolveKeyboardDropTarget(\n groupByIds,\n columnId,\n direction,\n );\n if (beforeColumnId === undefined) {\n return;\n }\n controller.moveGroupBy(columnId, beforeColumnId);\n }\n\n return (\n <div\n className={classNames(\n \"gridkit-group-by-bar\",\n isDragTarget ? \"is-drag-target\" : \"\",\n headerDragBlocked ? \"is-drag-blocked\" : \"\",\n )}\n data-gridkit-group-by-bar=\"\"\n role=\"group\"\n aria-label={messages.groupByBarLabel}\n >\n {showPlaceholder && (\n <span className=\"group-by-bar-placeholder\">\n {messages.groupByBarPlaceholder}\n </span>\n )}\n {groupBy.map((entry, index) => {\n const dropBefore = activeDropTarget?.beforeColumnId === entry.columnId;\n const dropAfter =\n activeDropTarget?.beforeColumnId === null &&\n index === groupBy.length - 1;\n const dragging = chipDrag.draggedColumnId === entry.columnId;\n\n return (\n <span\n key={entry.columnId}\n className={classNames(\n \"group-by-chip\",\n dragging ? \"is-dragging\" : \"\",\n dropBefore ? \"is-drop-before\" : \"\",\n dropAfter ? \"is-drop-after\" : \"\",\n )}\n data-gridkit-group-chip={entry.columnId}\n tabIndex={0}\n aria-label={messages.groupByChipLabel(\n columnName(entry.columnId),\n index + 1,\n groupBy.length,\n )}\n aria-keyshortcuts=\"Control+ArrowLeft Control+ArrowRight\"\n onPointerDown={(event) => {\n chipDrag.startDrag(entry.columnId, event);\n }}\n onKeyDown={(event) => {\n const horizontal =\n event.key === \"ArrowLeft\" || event.key === \"ArrowRight\";\n if (horizontal && event.ctrlKey) {\n event.preventDefault();\n moveByKeyboard(\n entry.columnId,\n event.key === \"ArrowLeft\" ? -1 : 1,\n );\n }\n }}\n >\n <span className=\"group-by-chip-label\">\n {labelFor(entry.columnId)}\n </span>\n <button\n type=\"button\"\n className=\"group-by-chip-remove\"\n aria-label={messages.removeGroupBy(columnName(entry.columnId))}\n onPointerDown={(event) => {\n // Otherwise the chip's own `onPointerDown` sees this bubble\n // up and starts a drag — the same reason the header's own\n // sort toggle stops it.\n event.stopPropagation();\n }}\n onClick={() => {\n controller.toggleGroupBy(entry.columnId);\n }}\n >\n ×\n </button>\n </span>\n );\n })}\n {/*\n * Portalled to the body, the same reason the header's own drag ghost\n * is: inside the viewport the overflow that makes the grid scroll\n * would clip it, and this bar sits right above that viewport.\n */}\n {chipDrag.draggedColumnId !== null &&\n chipDrag.ghostTransform !== null &&\n createPortal(\n <span\n className=\"group-by-chip drag-ghost\"\n style={{ transform: chipDrag.ghostTransform }}\n aria-hidden=\"true\"\n >\n {labelFor(chipDrag.draggedColumnId)}\n </span>,\n document.body,\n )}\n </div>\n );\n}\n","import type { PointerEvent as ReactPointerEvent } from \"react\";\nimport type { GroupByState } from \"@gridkitjs/core\";\nimport {\n resolveGroupByDropTarget,\n type GroupByDropTarget,\n} from \"@gridkitjs/dom\";\nimport useDragReorder from \"./useDragReorder\";\n\ninterface UseGroupByDragOptions {\n groupBy: GroupByState;\n onDrop: (movedColumnId: string, beforeColumnId: string | null) => void;\n}\n\nexport interface GroupByDragApi {\n /** The chip being dragged, for as long as the drag lasts. */\n draggedColumnId: string | null;\n /** Where it would land if released now. */\n dropTarget: GroupByDropTarget | null;\n /** Where the element trailing the pointer sits, as a CSS `transform`. */\n ghostTransform: string | null;\n startDrag: (columnId: string, event: ReactPointerEvent<HTMLElement>) => void;\n /** Whether the gesture that just ended was a drag rather than a click. */\n justDragged: () => boolean;\n}\n\n/**\n * Drag-to-reorder for chips inside the group-by bar, built on the same\n * `useDragReorder` mechanics `useColumnDrag` uses for headers — only the\n * hit-testing (`resolveGroupByDropTarget`, shared with a header dropped in\n * from outside the bar) differs.\n */\nexport default function useGroupByDrag({\n groupBy,\n onDrop,\n}: UseGroupByDragOptions): GroupByDragApi {\n const drag = useDragReorder<GroupByDropTarget>({\n resolveTarget: (clientX, clientY, movedId) =>\n resolveGroupByDropTarget(clientX, clientY, movedId, groupBy),\n onDrop: (target, movedId) => {\n onDrop(movedId, target.beforeColumnId);\n },\n });\n\n return {\n draggedColumnId: drag.draggedId,\n dropTarget: drag.dropTarget,\n ghostTransform: drag.ghostTransform,\n startDrag: (columnId, event) => {\n drag.startDrag(columnId, event.currentTarget, event);\n },\n justDragged: drag.justDragged,\n };\n}\n","import {\n useRef,\n useState,\n type PointerEvent as ReactPointerEvent,\n} from \"react\";\nimport {\n NO_DRAG,\n startDragReorder,\n type DragReorderHandlers,\n type DragReorderState,\n} from \"@gridkitjs/dom\";\n\ntype UseDragReorderOptions<Target> = Pick<\n DragReorderHandlers<Target>,\n \"resolveTarget\" | \"onDrop\"\n>;\n\nexport interface DragReorderApi<Target> extends DragReorderState<Target> {\n startDrag: (\n id: string,\n grabElement: HTMLElement,\n event: ReactPointerEvent<HTMLElement>,\n ) => void;\n /**\n * Whether the gesture that just ended was a drag rather than a click, for\n * a press that has something of its own to do with a click.\n *\n * Reading it clears it, so that a press which never opened a drag at all\n * does not see the last one's answer.\n */\n justDragged: () => boolean;\n}\n\n/**\n * `@gridkitjs/dom`'s `startDragReorder`, the pointer mechanics behind every\n * drag-to-reorder gesture in the grid, with what it reports held as state\n * for the header and the group-by bar to draw. A column header drag and a\n * group-by chip drag (`useColumnDrag`, `useGroupByDrag`) share it, so they\n * can only ever differ in their own hit-testing (`resolveTarget`).\n */\nexport default function useDragReorder<Target>({\n resolveTarget,\n onDrop,\n}: UseDragReorderOptions<Target>): DragReorderApi<Target> {\n const [drag, setDrag] = useState<DragReorderState<Target>>(NO_DRAG);\n const dragged = useRef(false);\n\n function justDragged(): boolean {\n const answer = dragged.current;\n dragged.current = false;\n return answer;\n }\n\n function startDrag(\n id: string,\n grabElement: HTMLElement,\n event: ReactPointerEvent<HTMLElement>,\n ): void {\n startDragReorder(id, grabElement, event, {\n resolveTarget,\n onState(state) {\n // Latched for the `click` that follows the release, which is the\n // only thing that can tell a drag apart from a press in the same\n // spot.\n if (state.draggedId !== null) {\n dragged.current = true;\n }\n setDrag(state);\n },\n onDrop,\n });\n }\n\n // A new object each render, as `useColumnDrag`/`useColumnResize` return:\n // the handlers close over `resolveTarget`/`onDrop`, and a stable identity\n // would buy nothing.\n return {\n draggedId: drag.draggedId,\n dropTarget: drag.dropTarget,\n ghostTransform: drag.ghostTransform,\n startDrag,\n justDragged,\n };\n}\n","import {\n isColumnVisible,\n type ColumnResizeEvent,\n type ColumnSortEvent,\n type ColumnVisibilityEvent,\n type GridMessages,\n type GroupByEvent,\n type GroupExpansionEvent,\n type PaginationChangeEvent,\n type SelectionDiffEvent,\n} from \"@gridkitjs/core\";\nimport type {\n CellSelectionChangeEvent,\n ColumnDefinition,\n DataGridProps,\n} from \"./DataGrid\";\n\n/** The change callbacks of a grid's props that announce what they report. */\ntype AnnouncedProps<Row> = Pick<\n DataGridProps<Row>,\n | \"onColumnResize\"\n | \"onColumnVisibilityChange\"\n | \"onColumnSortChange\"\n | \"onGroupByChange\"\n | \"onGroupExpansionChange\"\n | \"onPaginationChange\"\n | \"onCellSelectionChange\"\n>;\n\ninterface AnnouncedCallbacksOptions<Row> {\n /** The grid's own callbacks, each called before its change is announced. */\n readonly callbacks: AnnouncedProps<Row>;\n readonly announce: (text: string) => void;\n readonly messages: GridMessages;\n /** What a column is called in an announcement. */\n readonly columnName: (columnId: string) => string;\n /** A column's definition by id, hidden or not. */\n readonly columnOf: (columnId: string) => ColumnDefinition<Row> | undefined;\n}\n\n/** What the grid hands its controller to hear each change through. */\nexport interface AnnouncedCallbacks<Row> {\n readonly onColumnResize: (event: ColumnResizeEvent) => void;\n readonly onColumnVisibilityChange: (event: ColumnVisibilityEvent) => void;\n readonly onColumnSortChange: (event: ColumnSortEvent) => void;\n readonly onGroupByChange: (event: GroupByEvent) => void;\n readonly onGroupExpansionChange: (event: GroupExpansionEvent) => void;\n readonly onPaginationChange: (event: PaginationChangeEvent) => void;\n readonly onCellSelectionChange: (\n event: CellSelectionChangeEvent<Row>,\n ) => void;\n readonly onSelectionDiff: (event: SelectionDiffEvent) => void;\n}\n\n/**\n * The grid's change callbacks, each wrapped to announce its change in the\n * live region after calling the grid's own — so a change is announced where\n * the controller reports it, the same whether a click, a key, a menu or the\n * ref made it.\n */\nexport function announcedCallbacks<Row>({\n callbacks,\n announce,\n messages,\n columnName,\n columnOf,\n}: AnnouncedCallbacksOptions<Row>): AnnouncedCallbacks<Row> {\n return {\n /**\n * Announced only once the drag ends: the controller reports the\n * continuous `\"move\"` phase as well, and a live region given every frame\n * of a drag says nothing an assistive technology can keep up with.\n */\n onColumnResize: (event) => {\n callbacks.onColumnResize?.(event);\n if (event.phase === \"end\") {\n announce(\n messages.columnResized(\n columnName(event.columnId),\n Math.round(event.width),\n ),\n );\n }\n },\n\n /**\n * Naming a column shown or hidden alone, and counting several — \"Show\n * all\" in the column chooser, or `hideColumns` given a list. A change\n * that shows some and hides others, as restoring a layout can, has no\n * one thing to say, and says nothing.\n */\n onColumnVisibilityChange: (event) => {\n callbacks.onColumnVisibilityChange?.(event);\n const { columnIds, visibility } = event;\n const [columnId] = columnIds;\n const shownCount = columnIds.filter((id) => {\n const column = columnOf(id);\n return column !== undefined && isColumnVisible(column, visibility);\n }).length;\n if (\n columnId === undefined ||\n (shownCount !== 0 && shownCount !== columnIds.length)\n ) {\n return;\n }\n const shown = shownCount > 0;\n if (columnIds.length > 1) {\n announce(\n shown\n ? messages.columnsShown(columnIds.length)\n : messages.columnsHidden(columnIds.length),\n );\n return;\n }\n announce(\n shown\n ? messages.columnShown(columnName(columnId))\n : messages.columnHidden(columnName(columnId)),\n );\n },\n\n /** A toggle, a stack, or a clear back to \"none\" each get their own. */\n onColumnSortChange: (event) => {\n callbacks.onColumnSortChange?.(event);\n const entry = event.sort.find(\n (candidate) => candidate.columnId === event.columnId,\n );\n if (entry === undefined) {\n announce(messages.sortCleared(columnName(event.columnId)));\n return;\n }\n announce(\n messages.columnSorted(\n columnName(event.columnId),\n entry.direction,\n event.sort.indexOf(entry) + 1,\n event.sort.length,\n ),\n );\n },\n\n onGroupByChange: (event) => {\n callbacks.onGroupByChange?.(event);\n const entry = event.groupBy.find(\n (candidate) => candidate.columnId === event.columnId,\n );\n if (entry === undefined) {\n announce(messages.groupingRemoved(columnName(event.columnId)));\n return;\n }\n announce(\n messages.groupedBy(\n columnName(event.columnId),\n event.groupBy.indexOf(entry) + 1,\n event.groupBy.length,\n ),\n );\n },\n\n /**\n * `groupId: null` marks `expandAll`/`collapseAll`, which touch every\n * group in one call rather than one at a time — announced as a single\n * summary instead of naming a group that doesn't apply.\n */\n onGroupExpansionChange: (event) => {\n callbacks.onGroupExpansionChange?.(event);\n if (event.groupId === null) {\n announce(\n event.expansion.length === 0\n ? messages.allGroupsExpanded\n : messages.allGroupsCollapsed,\n );\n return;\n }\n announce(\n event.expansion.includes(event.groupId)\n ? messages.groupCollapsed\n : messages.groupExpanded,\n );\n },\n\n onPaginationChange: (event) => {\n callbacks.onPaginationChange?.(event);\n announce(\n messages.pageStatus(event.pagination.pageIndex + 1, event.pageCount),\n );\n },\n\n /**\n * Unlike rows and columns, a cell selection is always exactly one cell —\n * there is no multi-cell range — so it never crosses the count's >1\n * threshold and the focused cell's own `aria-selected` is the only\n * feedback a screen-reader user would otherwise get. Announced on every\n * change that lands on a cell instead.\n */\n onCellSelectionChange: (event) => {\n callbacks.onCellSelectionChange?.(event);\n if (event.selected !== null) {\n announce(\n messages.cellSelected(\n columnName(event.selected.columnId),\n event.selected.rowIndex + 1,\n ),\n );\n }\n },\n\n /**\n * Announced only for a change touching more than one row or column. A\n * single selection is already carried by the focused member's own\n * `aria-selected`, and repeating it here would talk over that. Counted\n * by id, so rows the change touched off screen — on another page, in a\n * collapsed group — count too.\n */\n onSelectionDiff: (event) => {\n if (event.added.length + event.removed.length > 1) {\n announce(messages.selectedCount(event.selection.length, event.target));\n }\n },\n };\n}\n","import type { KeyboardEvent } from \"react\";\nimport { runCommand, type GridCommandTarget } from \"@gridkitjs/core\";\nimport { isNativeCopy } from \"@gridkitjs/dom\";\nimport type { GridCommandsApi } from \"../commands/useGridCommands\";\nimport type { DataGridController } from \"../useGridController\";\nimport { HEADER_ROW, type GridNavigationApi } from \"../useGridNavigation\";\n\ninterface UseGridCopyOptions<Row> {\n controller: DataGridController<Row>;\n commands: GridCommandsApi<Row>;\n nav: GridNavigationApi;\n}\n\nfunction isCopyKey(event: KeyboardEvent): boolean {\n return (\n (event.ctrlKey || event.metaKey) &&\n !event.altKey &&\n (event.key === \"c\" || event.key === \"C\")\n );\n}\n\n/**\n * Ctrl+C (Cmd+C on a Mac) on the grid: copies the selection, else the\n * focused cell, through the same `copy.selection` and `copy.cell` commands\n * the context menu runs — so an app that overrides one changes both. The\n * returned handler belongs on the grid root's `onKeyDown`, for keys the\n * grid itself received.\n *\n * A press in a text field inside a cell, or with text highlighted on the\n * page, is the browser's, and so is one with nothing to copy: the default\n * is prevented only once a copy ran. Like the grid's other keys, it is not\n * reported to `onCommand`, which hears of menu and API runs.\n */\nexport default function useGridCopy<Row>({\n controller,\n commands,\n nav,\n}: UseGridCopyOptions<Row>): (event: KeyboardEvent) => void {\n function run(commandId: string, target: GridCommandTarget): boolean {\n const command = commands.commands.get(commandId);\n return (\n command !== undefined && runCommand(command, commands.contextFor(target))\n );\n }\n\n /** The focused data cell as a command target, or `null` on a header or a group row. */\n function focusedCell(): GridCommandTarget | null {\n const { rowIndex, columnIndex } = nav.focus;\n if (rowIndex === HEADER_ROW) {\n return null;\n }\n const { pageRows, columns } = controller.getView();\n const entry = pageRows[rowIndex];\n const column = columns[columnIndex];\n return entry === undefined || \"kind\" in entry || column === undefined\n ? null\n : { area: \"cell\", rowId: entry.rowId, columnId: column.id };\n }\n\n return (event) => {\n if (!isCopyKey(event) || isNativeCopy(event.target)) {\n return;\n }\n const cell = focusedCell();\n if (\n run(\"copy.selection\", { area: \"grid\" }) ||\n (cell !== null && run(\"copy.cell\", cell))\n ) {\n event.preventDefault();\n }\n };\n}\n","import { useMemo } from \"react\";\nimport {\n createCommandContext,\n resolveCommands,\n runCommand,\n type GridCommand,\n type GridCommandContext,\n type GridCommandHost,\n type GridCommandSource,\n type GridCommandTarget,\n type GridMessages,\n type GridOptions,\n} from \"@gridkitjs/core\";\nimport { copyToClipboard } from \"../clipboard/copyToClipboard\";\nimport useSaveFile from \"../export/useSaveFile\";\nimport { printGrid } from \"../print/printApi\";\nimport type { ColumnResizeApi } from \"../useColumnResize\";\nimport type { DataGridController } from \"../useGridController\";\n\ninterface UseGridCommandsOptions<Row> {\n controller: DataGridController<Row>;\n /** The app's commands, over the built-ins. */\n commands: GridOptions<Row>[\"commands\"];\n onCommand: GridOptions<Row>[\"onCommand\"];\n /** The grid's messages, over the defaults — what every built-in label reads. */\n messages: GridMessages;\n announce: (text: string) => void;\n resize: ColumnResizeApi<Row>;\n /** Opens one of the grid's panels — see `useGridPanels`. */\n openPanel: GridCommandHost[\"openPanel\"];\n}\n\nexport interface GridCommandsApi<Row> {\n /** Every command the grid knows, by id. */\n commands: ReadonlyMap<string, GridCommand<Row>>;\n /** What a command needs that only the grid has: its DOM, its live region. */\n host: GridCommandHost;\n /** A command context for `target`, over the grid as it is now. */\n contextFor: (target: GridCommandTarget) => GridCommandContext<Row>;\n /** Tells `onCommand` that a command, or an inline menu item, ran. */\n report: (\n commandId: string,\n target: GridCommandTarget,\n source: GridCommandSource,\n ) => void;\n /**\n * Runs the command `commandId` on `target` when it is visible and enabled\n * there, reports it, and says whether it ran.\n */\n run: (\n commandId: string,\n target: GridCommandTarget,\n source: GridCommandSource,\n ) => boolean;\n}\n\n/**\n * The commands behind the grid's menus — the built-ins and the app's own —\n * and the context they run in. Which command shows, is enabled or does what\n * is `@gridkitjs/core`'s; the grid lends them what needs a DOM — sizing a\n * column to its content, as double-clicking its resize handle does,\n * opening its panels, downloading an export, writing the clipboard and\n * printing — and its live region.\n */\nexport default function useGridCommands<Row>({\n controller,\n commands: appCommands,\n onCommand,\n messages,\n announce,\n resize,\n openPanel,\n}: UseGridCommandsOptions<Row>): GridCommandsApi<Row> {\n const commands = useMemo(() => resolveCommands(appCommands), [appCommands]);\n const saveFile = useSaveFile({ messages, announce });\n\n const host: GridCommandHost = {\n autoFitColumns: (columnIds) => {\n const { columns } = controller.getView();\n let fitted = 0;\n for (const columnId of columnIds) {\n const entry = columns.find((candidate) => candidate.id === columnId);\n if (entry !== undefined && resize.sizeToContent(entry)) {\n fitted += 1;\n }\n }\n // Each resize announced itself, and the live region keeps only the\n // last; one message for them all replaces it before anything is read.\n if (fitted > 1) {\n announce(messages.columnsAutoFitted(fitted));\n }\n },\n openPanel,\n announce,\n saveFile,\n writeClipboard: (content) => {\n copyToClipboard(content, { messages, announce });\n },\n print: (document, options) => {\n printGrid(document, options).catch((error: unknown) => {\n console.error(\"DataGrid: the print failed.\", error);\n });\n },\n };\n\n function contextFor(target: GridCommandTarget): GridCommandContext<Row> {\n return createCommandContext({ controller, target, messages, host });\n }\n\n function report(\n commandId: string,\n target: GridCommandTarget,\n source: GridCommandSource,\n ): void {\n onCommand?.({ commandId, target, source });\n }\n\n // A new object each render, as the other hooks here return.\n return {\n commands,\n host,\n contextFor,\n report,\n run: (commandId, target, source) => {\n const command = commands.get(commandId);\n if (command === undefined) {\n console.error(`DataGrid: there is no command \\`${commandId}\\` to run.`);\n return false;\n }\n if (!runCommand(command, contextFor(target))) {\n return false;\n }\n report(commandId, target, source);\n return true;\n },\n };\n}\n","import type { CopyContent, GridMessages } from \"@gridkitjs/core\";\nimport { writeClipboard } from \"@gridkitjs/dom\";\n\ninterface CopyToClipboardOptions {\n messages: GridMessages;\n announce: (text: string) => void;\n}\n\n/**\n * The host's `writeClipboard`: puts a copy on the clipboard and says so, as\n * nothing on screen does. A copy the browser refuses is logged for the\n * developer and announced for the user, who would otherwise paste whatever\n * the clipboard held before.\n */\nexport function copyToClipboard(\n content: CopyContent,\n { messages, announce }: CopyToClipboardOptions,\n): void {\n writeClipboard(content).then(\n () => {\n announce(messages.copied(content.count, content.unit));\n },\n (error: unknown) => {\n console.error(\"DataGrid: the clipboard could not be written.\", error);\n announce(messages.copyFailed);\n },\n );\n}\n","import { useRef } from \"react\";\nimport type {\n ExportFile,\n GridCommandHost,\n GridMessages,\n} from \"@gridkitjs/core\";\nimport { downloadBlob } from \"@gridkitjs/dom\";\nimport { exportBlob } from \"./exportApi\";\n\ninterface UseSaveFileOptions {\n messages: GridMessages;\n announce: (text: string) => void;\n}\n\nfunction download(file: ExportFile): void {\n downloadBlob(exportBlob(file), file.fileName);\n}\n\n/**\n * The host's `saveFile`: downloads an export, once its writer has finished\n * writing it.\n *\n * One at a time. An export asked for while a writer is still writing the\n * last is dropped and logged, so pressing a slow export twice saves one file\n * rather than two. A writer that fails is logged for the developer and\n * announced for the user, who asked for a file that will not come.\n */\nexport default function useSaveFile({\n messages,\n announce,\n}: UseSaveFileOptions): GridCommandHost[\"saveFile\"] {\n const writingRef = useRef(false);\n\n return (file) => {\n if (writingRef.current) {\n console.error(\n \"DataGrid: an export is still being written, so this one was dropped.\",\n );\n return;\n }\n if (!(file instanceof Promise)) {\n download(file);\n return;\n }\n writingRef.current = true;\n file\n .then(download, (error: unknown) => {\n console.error(\"DataGrid: the export's writer failed.\", error);\n announce(messages.exportFailed);\n })\n .finally(() => {\n writingRef.current = false;\n });\n };\n}\n","import {\n exportFile,\n resolveExportWriters,\n type ExportFile,\n type ExportWriter,\n type GridExportOptions,\n} from \"@gridkitjs/core\";\nimport type { GridCommandsApi } from \"../commands/useGridCommands\";\n\n/** What `DataGridApi` carries for exporting. */\nexport interface GridExportApi {\n /**\n * The grid's view exported as `format` — `\"csv\"`, `\"json\"`, a format\n * registered through `exportWriters`, or a writer passed as it is — and\n * handed back as a `Blob`, under the grid's `export` option with\n * `options` over it, field by field. Nothing is downloaded:\n * `runCommand(\"export.csv\")` downloads.\n *\n * Rejects for a format no writer is registered for, and when the writer\n * fails.\n */\n exportData(\n format: string | ExportWriter,\n options?: GridExportOptions,\n ): Promise<Blob>;\n}\n\n/**\n * An export's contents as a `Blob` of its media type. Text is stored as\n * UTF-8, a byte order mark the writer put first included, so a CSV opens in\n * a spreadsheet with its accents intact. Bytes are copied: a `Blob` takes\n * no view of shared memory, which a `Uint8Array` may be.\n */\nexport function exportBlob({ content, mimeType }: ExportFile): Blob {\n const part = typeof content === \"string\" ? content : content.slice();\n return new Blob([part], { type: mimeType });\n}\n\n/** `DataGridApi.exportData`, over the grid as it is when called. */\nexport function exportApi<Row>({\n contextFor,\n}: GridCommandsApi<Row>): GridExportApi {\n return {\n exportData: async (format, options) => {\n const context = contextFor({ area: \"grid\" });\n const { export: defaults, exportWriters } = context.options;\n const file = exportFile(\n context,\n format,\n { ...defaults, ...options },\n resolveExportWriters(exportWriters),\n );\n // `exportFile` has logged the format by name; the caller is told too.\n if (file === null) {\n throw new Error(\n \"DataGrid: there is no export writer for that format — register one through `exportWriters`.\",\n );\n }\n return exportBlob(await file);\n },\n };\n}\n","import {\n exportPrintDocument,\n type PrintDocument,\n type PrintOptions,\n} from \"@gridkitjs/core\";\nimport { printDocument, printStyles } from \"@gridkitjs/dom\";\nimport type { GridCommandsApi } from \"../commands/useGridCommands\";\n\n/** What `DataGridApi` carries for printing. */\nexport interface GridPrintApi {\n /**\n * Prints the grid's view through the browser's print dialog — every row\n * the filter leaves, across pages and collapsed groups, not only those\n * drawn — under the grid's `print` option with `options` over it, field\n * by field. Resolves once the dialog has closed, or at once while another\n * print is open.\n */\n print(options?: PrintOptions): Promise<void>;\n}\n\n/**\n * Puts a print document on paper through a hidden frame, under the print\n * stylesheet for its page with `options.styles` after it. The frame sees\n * none of the page's CSS, the theme's included.\n */\nexport function printGrid(\n document: PrintDocument,\n { styles = \"\" }: PrintOptions,\n): Promise<void> {\n return printDocument({\n title: document.title,\n bodyHtml: document.bodyHtml,\n styles: printStyles(document.page) + styles,\n });\n}\n\n/** `DataGridApi.print`, over the grid as it is when called. */\nexport function printApi<Row>({\n contextFor,\n}: GridCommandsApi<Row>): GridPrintApi {\n return {\n print: (options) => {\n const context = contextFor({ area: \"grid\" });\n const merged = { ...context.options.print, ...options };\n return printGrid(exportPrintDocument(context, merged), merged);\n },\n };\n}\n","import { useLayoutEffect, useRef, useState, type RefObject } from \"react\";\nimport type {\n ResolvedMenuEntry,\n ResolvedMenuItem,\n ResolvedMenuSubmenu,\n} from \"@gridkitjs/core\";\nimport {\n attachMenu,\n type AttachedMenu,\n type MenuSubmenuFocus,\n} from \"@gridkitjs/dom\";\nimport { ariaAttr } from \"../ariaAttr\";\nimport Overlay from \"../overlay/Overlay\";\nimport { CheckIcon, ChevronRightIcon, MenuIcon } from \"./menuIcons\";\n\ninterface GridMenuProps {\n entries: readonly ResolvedMenuEntry[];\n /** The menu's accessible name. */\n label: string;\n /** The palette its submenus take — the one its own overlay took. */\n themeClassName: string;\n /** An enabled item was chosen: run it, and close every menu. */\n onRun: (item: ResolvedMenuItem) => void;\n /** Tab or Shift+Tab: close every menu. */\n onClose: () => void;\n /**\n * ArrowLeft: close this menu, which is a submenu, so focus goes back to\n * the item that opened it. Given only to a submenu; a menu without it has\n * nowhere to go back to.\n */\n onCloseSubmenu?: (() => void) | undefined;\n /**\n * Holds this menu's behaviour while it is attached, for the menu that\n * opened it to move focus in.\n */\n behaviourRef?: RefObject<AttachedMenu | null> | undefined;\n}\n\n/** The submenu open from a menu. */\ninterface OpenSubmenu {\n readonly id: string;\n /** The item it opened from, which it opens beside. */\n readonly anchor: HTMLElement;\n readonly focus: MenuSubmenuFocus;\n /** Lines its first item up with `anchor`. */\n readonly offset: number;\n}\n\n/** The item of `menu` whose id is `id`, read off the markup this drew. */\nfunction itemElement(menu: HTMLElement, id: string): HTMLElement | null {\n return (\n Array.from(\n menu.querySelectorAll<HTMLElement>(\"[data-gridkit-menu-item]\"),\n ).find((item) => item.getAttribute(\"data-gridkit-menu-item\") === id) ?? null\n );\n}\n\n/**\n * How far below a menu's top edge its first item starts: its top border and\n * padding. A submenu is styled the same, so opening it this far up lines its\n * first item up with the item that opened it, whatever the theme makes them.\n */\nfunction topInset(menu: HTMLElement): number {\n const style = getComputedStyle(menu);\n return parseFloat(style.borderTopWidth) + parseFloat(style.paddingTop);\n}\n\nfunction MenuItem({\n entry,\n expanded,\n}: {\n entry: ResolvedMenuItem | ResolvedMenuSubmenu;\n /** For a submenu item: whether its submenu is open. */\n expanded: boolean;\n}) {\n const isItem = entry.type === \"item\";\n const checked = isItem ? entry.checked : undefined;\n const shortcut = isItem ? entry.shortcut : undefined;\n return (\n <div\n role={checked === undefined ? \"menuitem\" : \"menuitemcheckbox\"}\n data-gridkit-menu-item={entry.id}\n className=\"menu-item\"\n {...ariaAttr(isItem && entry.disabled, \"aria-disabled\", true)}\n {...ariaAttr(checked !== undefined, \"aria-checked\", checked)}\n {...ariaAttr(shortcut !== undefined, \"aria-keyshortcuts\", shortcut)}\n {...ariaAttr<\"aria-haspopup\", \"menu\">(!isItem, \"aria-haspopup\", \"menu\")}\n {...ariaAttr(!isItem, \"aria-expanded\", expanded)}\n >\n <span className=\"menu-item-icon\" aria-hidden=\"true\">\n {checked === true ? <CheckIcon /> : <MenuIcon name={entry.icon} />}\n </span>\n <span className=\"menu-item-label\">{entry.label}</span>\n {/* Read out through `aria-keyshortcuts`, not as part of the name. */}\n {shortcut !== undefined && (\n <span className=\"menu-item-shortcut\" aria-hidden=\"true\">\n {shortcut}\n </span>\n )}\n {!isItem && (\n <span className=\"menu-submenu-indicator\" aria-hidden=\"true\">\n <ChevronRightIcon />\n </span>\n )}\n </div>\n );\n}\n\n/**\n * A menu resolved by `@gridkitjs/core`'s `resolveMenu`, drawn as\n * `role=\"menu\"` and made to behave as one by `@gridkitjs/dom`'s\n * `attachMenu`, which decides what every key and hover does; this draws the\n * items and which submenu is open. Shown inside an `Overlay` — which attaches\n * after this, so its initial focus lands on the item `attachMenu` made the\n * tab stop.\n *\n * A submenu is a `GridMenu` of its own, in an `Overlay` of its own anchored\n * to the item that opened it.\n */\nexport default function GridMenu({\n entries,\n label,\n themeClassName,\n onRun,\n onClose,\n onCloseSubmenu,\n behaviourRef,\n}: GridMenuProps) {\n const menuRef = useRef<HTMLDivElement>(null);\n const submenuBehaviourRef = useRef<AttachedMenu | null>(null);\n const [submenu, setSubmenu] = useState<OpenSubmenu | null>(null);\n const isSubmenu = onCloseSubmenu !== undefined;\n\n /**\n * What the behaviour's callbacks read. They are handed over once, when it\n * attaches, so they read the props and state of the latest render here.\n */\n const latest = useRef({ entries, submenu, onRun, onClose, onCloseSubmenu });\n useLayoutEffect(() => {\n latest.current = { entries, submenu, onRun, onClose, onCloseSubmenu };\n });\n\n useLayoutEffect(() => {\n const menu = menuRef.current;\n if (menu === null) {\n return undefined;\n }\n const behaviour = attachMenu(menu, {\n onActivate: (id) => {\n const item = latest.current.entries.find(\n (entry): entry is ResolvedMenuItem =>\n entry.type === \"item\" && entry.id === id,\n );\n if (item !== undefined) {\n latest.current.onRun(item);\n }\n },\n onOpenSubmenu: (id, { focus }) => {\n // Already open — the pointer opened it — so the keyboard only asks\n // for focus to move into it.\n if (latest.current.submenu?.id === id) {\n if (focus === \"first\") {\n submenuBehaviourRef.current?.focusItem(0);\n }\n return;\n }\n const anchor = itemElement(menu, id);\n if (anchor !== null) {\n setSubmenu({ id, anchor, focus, offset: -topInset(menu) });\n }\n },\n onCollapseSubmenu: () => {\n setSubmenu(null);\n },\n onCloseSubmenu: isSubmenu\n ? () => {\n latest.current.onCloseSubmenu?.();\n }\n : undefined,\n onClose: () => {\n latest.current.onClose();\n },\n });\n if (behaviourRef !== undefined) {\n behaviourRef.current = behaviour;\n }\n return () => {\n if (behaviourRef !== undefined) {\n behaviourRef.current = null;\n }\n behaviour.detach();\n };\n }, [isSubmenu, behaviourRef]);\n\n function closeSubmenu(): void {\n setSubmenu(null);\n }\n\n const openEntry =\n submenu === null\n ? undefined\n : entries.find(\n (entry): entry is ResolvedMenuSubmenu =>\n entry.type === \"submenu\" && entry.id === submenu.id,\n );\n\n return (\n <>\n <div\n ref={menuRef}\n role=\"menu\"\n aria-label={label}\n className=\"gridkit-menu\"\n >\n {entries.map((entry) =>\n entry.type === \"separator\" ? (\n <div key={entry.key} role=\"separator\" className=\"menu-separator\" />\n ) : (\n <MenuItem\n key={entry.id}\n entry={entry}\n expanded={entry.id === submenu?.id}\n />\n ),\n )}\n </div>\n {submenu !== null && openEntry !== undefined && (\n <Overlay\n key={submenu.id}\n anchor={submenu.anchor}\n placement=\"right-start\"\n offset={submenu.offset}\n initialFocus={submenu.focus}\n themeClassName={themeClassName}\n onDismiss={closeSubmenu}\n >\n <GridMenu\n entries={openEntry.items}\n label={openEntry.label}\n themeClassName={themeClassName}\n onRun={onRun}\n onClose={onClose}\n onCloseSubmenu={closeSubmenu}\n behaviourRef={submenuBehaviourRef}\n />\n </Overlay>\n )}\n </>\n );\n}\n","import { useLayoutEffect, useRef, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n attachOverlay,\n type OverlayAnchor,\n type OverlayDismissReason,\n type OverlayInitialFocus,\n type OverlayPlacement,\n} from \"@gridkitjs/dom\";\nimport { classNames } from \"../classNames\";\n\ninterface OverlayProps {\n /**\n * What the overlay opens beside: an element, or a point. It and the\n * options after it are read when the overlay attaches, and a change to any\n * of them attaches it afresh — moving focus back in — so each should stay\n * the same for as long as the overlay is open.\n */\n anchor: OverlayAnchor;\n placement?: OverlayPlacement | undefined;\n gap?: number | undefined;\n offset?: number | undefined;\n /**\n * Where focus goes on attaching — see `attachOverlay`'s option — or a ref\n * to the control it goes to, read as the overlay attaches, once its\n * children have mounted, so that it can be one of theirs. A ref holding\n * nothing sends it to the first control.\n */\n initialFocus?:\n OverlayInitialFocus | RefObject<HTMLElement | null> | undefined;\n returnFocusTo?: HTMLElement | null | undefined;\n /** See `attachOverlay`'s option: a panel whose controls change the grid under it. */\n ignoreScrollAfterInput?: boolean | undefined;\n /** See `attachOverlay`'s option: Tab stays inside, as in a dialog. */\n trapFocus?: boolean | undefined;\n /** The palette the overlay takes — see `overlayThemeClassName`. */\n themeClassName: string;\n /** The overlay asks to close; the caller unmounts it, or not. */\n onDismiss: (reason: OverlayDismissReason) => void;\n children: ReactNode;\n}\n\n/**\n * The space between a menu or panel and the element it opens below — a\n * toolbar button, a header — so its shadow does not run into that element's\n * border. Nothing opened at a point, or beside its own menu, as a submenu is,\n * takes it.\n */\nexport const ANCHOR_GAP = 4;\n\n/** `focus` as `attachOverlay` takes it, reading a ref's control now. */\nfunction attachedFocus(\n focus: OverlayProps[\"initialFocus\"],\n): OverlayInitialFocus | undefined {\n return typeof focus === \"object\" && !(focus instanceof HTMLElement)\n ? (focus.current ?? \"first\")\n : focus;\n}\n\n/**\n * The palette class an overlay opened from `element` copies:\n * `gridkit-light` or `gridkit-dark`, from the nearest ancestor carrying one,\n * or none to follow the page. An overlay renders into `document.body`, out of\n * reach of the tokens that ancestor sets.\n */\nexport function overlayThemeClassName(element: Element | null): string {\n const scope = element?.closest(\".gridkit-light, .gridkit-dark\");\n if (scope === null || scope === undefined) {\n return \"\";\n }\n return scope.classList.contains(\"gridkit-dark\")\n ? \"gridkit-dark\"\n : \"gridkit-light\";\n}\n\n/**\n * `children` in a panel portalled into `document.body` — where no scrolling\n * ancestor of the grid clips it — shown beside `anchor` by\n * `@gridkitjs/dom`'s `attachOverlay` for as long as it is mounted.\n *\n * Attached in a layout effect, which React runs after its children's: a menu\n * inside attaches its own behaviour first, so the overlay's initial focus\n * finds the item that behaviour made the tab stop. A nested overlay — a\n * submenu — mounts on a later user action than the one it opens from, so it\n * attaches after it and sits above it in the overlay stack.\n */\nexport default function Overlay({\n anchor,\n placement,\n gap,\n offset,\n initialFocus,\n returnFocusTo,\n ignoreScrollAfterInput,\n trapFocus,\n themeClassName,\n onDismiss,\n children,\n}: OverlayProps) {\n const panelRef = useRef<HTMLDivElement>(null);\n // Read through a ref, so a new handler every render does not re-attach.\n const onDismissRef = useRef(onDismiss);\n useLayoutEffect(() => {\n onDismissRef.current = onDismiss;\n });\n\n useLayoutEffect(() => {\n const panel = panelRef.current;\n if (panel === null) {\n return undefined;\n }\n return attachOverlay(anchor, panel, {\n placement,\n gap,\n offset,\n initialFocus: attachedFocus(initialFocus),\n returnFocusTo,\n ignoreScrollAfterInput,\n trapFocus,\n onDismiss: (reason) => {\n onDismissRef.current(reason);\n },\n });\n }, [\n anchor,\n placement,\n gap,\n offset,\n initialFocus,\n returnFocusTo,\n ignoreScrollAfterInput,\n trapFocus,\n ]);\n\n return createPortal(\n <div\n ref={panelRef}\n className={classNames(\"gridkit-overlay\", themeClassName)}\n >\n {children}\n </div>,\n document.body,\n );\n}\n","import type { ReactNode } from \"react\";\nimport type { BuiltInCommandIcon } from \"@gridkitjs/core\";\nimport { GroupIcon, Icon } from \"../icons\";\n\n/** A glyph for every icon key the built-in commands carry. */\nconst BUILT_IN_ICONS: Readonly<Record<BuiltInCommandIcon, () => ReactNode>> = {\n sortAscending: () => (\n <Icon>\n <path d=\"m3 8 4-4 4 4\" />\n <path d=\"M7 4v16\" />\n <path d=\"M11 12h4\" />\n <path d=\"M11 16h7\" />\n <path d=\"M11 20h10\" />\n </Icon>\n ),\n sortDescending: () => (\n <Icon>\n <path d=\"m3 16 4 4 4-4\" />\n <path d=\"M7 20V4\" />\n <path d=\"M11 4h10\" />\n <path d=\"M11 8h7\" />\n <path d=\"M11 12h4\" />\n </Icon>\n ),\n group: () => <GroupIcon />,\n hide: () => (\n <Icon>\n <path d=\"M9.88 9.88a3 3 0 1 0 4.24 4.24\" />\n <path d=\"M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68\" />\n <path d=\"M6.61 6.61A13.53 13.53 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61\" />\n <path d=\"m2 2 20 20\" />\n </Icon>\n ),\n autoFit: () => (\n <Icon>\n <path d=\"m18 8 4 4-4 4\" />\n <path d=\"M2 12h20\" />\n <path d=\"m6 8-4 4 4 4\" />\n </Icon>\n ),\n copy: () => (\n <Icon>\n <rect x=\"8\" y=\"8\" width=\"14\" height=\"14\" rx=\"2\" />\n <path d=\"M4 16a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2\" />\n </Icon>\n ),\n print: () => (\n <Icon>\n <path d=\"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2\" />\n <path d=\"M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6\" />\n <rect x=\"6\" y=\"14\" width=\"12\" height=\"8\" rx=\"1\" />\n </Icon>\n ),\n};\n\n/**\n * Looked up through a `Map`, since an item's key may be any string an app\n * chose, and one such as `\"toString\"` must find nothing rather than\n * something on `Object.prototype`.\n */\nconst ICONS = new Map(Object.entries(BUILT_IN_ICONS));\n\n/** The icon a key names, or nothing for a key the grid has no glyph for. */\nexport function MenuIcon({ name }: { name: string | undefined }) {\n const draw = name === undefined ? undefined : ICONS.get(name);\n return draw === undefined ? null : draw();\n}\n\n/** What a checked item shows in place of its icon. */\nexport function CheckIcon() {\n return (\n <Icon>\n <path d=\"M20 6 9 17l-5-5\" />\n </Icon>\n );\n}\n\n/** Marks a button that opens a menu below it. */\nexport function ChevronDownIcon() {\n return (\n <Icon>\n <path d=\"m6 9 6 6 6-6\" />\n </Icon>\n );\n}\n\n/** Marks a button going back to what a panel showed before. */\nexport function ChevronLeftIcon() {\n return (\n <Icon>\n <path d=\"m15 18-6-6 6-6\" />\n </Icon>\n );\n}\n\n/** Marks an item that opens a submenu. */\nexport function ChevronRightIcon() {\n return (\n <Icon>\n <path d=\"m9 18 6-6-6-6\" />\n </Icon>\n );\n}\n","import GridMenu from \"../menu/GridMenu\";\nimport Overlay, { ANCHOR_GAP } from \"../overlay/Overlay\";\nimport type { ContextMenuApi } from \"./useContextMenu\";\n\n/**\n * The open context menu, if any — beside the point it was asked for at, or\n * below its cell when asked for by a key — returning focus to that cell when\n * it closes, or, from the body's empty space, to wherever focus was before.\n * Rendered after the grid's tables, as every grid overlay is, so\n * the keys pressed in it reach no header or body handler on their way up\n * React's tree.\n */\nexport default function GridContextMenu({\n contextMenu,\n}: {\n contextMenu: ContextMenuApi;\n}) {\n const { menu, run, close } = contextMenu;\n if (menu === null) {\n return null;\n }\n return (\n <Overlay\n key={menu.key}\n anchor={menu.anchor}\n gap={menu.anchor instanceof Element ? ANCHOR_GAP : 0}\n returnFocusTo={menu.cell ?? undefined}\n themeClassName={menu.themeClassName}\n onDismiss={close}\n >\n <GridMenu\n entries={menu.entries}\n label={menu.label}\n themeClassName={menu.themeClassName}\n onRun={run}\n onClose={close}\n />\n </Overlay>\n );\n}\n","import {\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type RefObject,\n} from \"react\";\nimport {\n contextMenuEntries,\n hasContextMenu,\n isSameCell,\n resolveMenu,\n type GridContextMenuArea,\n type GridContextMenuTarget,\n type GridMessages,\n type GridOptions,\n type ResolvedMenuEntry,\n type ResolvedMenuItem,\n} from \"@gridkitjs/core\";\nimport {\n attachContextMenuTrigger,\n type ContextMenuRequest,\n type OverlayAnchor,\n} from \"@gridkitjs/dom\";\nimport type { GridCommandsApi } from \"../commands/useGridCommands\";\nimport { overlayThemeClassName } from \"../overlay/Overlay\";\nimport type { DataGridController } from \"../useGridController\";\nimport type { GridNavigationApi } from \"../useGridNavigation\";\nimport type { GridSelectionApi } from \"../useGridSelection\";\nimport {\n placeAt,\n placeOf,\n type ContextMenuPlace,\n type GridParts,\n} from \"./contextMenuPlaces\";\n\ninterface UseContextMenuOptions<Row> {\n /** The grid's root element: a menu is asked for on what is inside it. */\n rootRef: RefObject<HTMLElement | null>;\n headerTableRef: RefObject<HTMLTableElement | null>;\n bodyTableRef: RefObject<HTMLTableElement | null>;\n /** The body's scrolling region, whose empty space is the `body` area. */\n bodyScrollRef: RefObject<HTMLElement | null>;\n contextMenu: GridOptions<Row>[\"contextMenu\"];\n onContextMenuOpenChange: GridOptions<Row>[\"onContextMenuOpenChange\"];\n controller: DataGridController<Row>;\n commands: GridCommandsApi<Row>;\n nav: GridNavigationApi;\n selection: GridSelectionApi;\n messages: GridMessages;\n /** What a column is called in a menu's name. */\n columnName: (columnId: string) => string;\n}\n\n/** The context menu open now. */\nexport interface OpenContextMenu {\n /** Counts the openings, so one opened over another replaces it. */\n readonly key: number;\n readonly target: GridContextMenuTarget;\n readonly entries: readonly ResolvedMenuEntry[];\n /** Its accessible name. */\n readonly label: string;\n /** The point it was asked for at, or its cell when asked for by a key. */\n readonly anchor: OverlayAnchor;\n /**\n * The cell it opened on, which has focus first and gets it back after —\n * `null` in the body's empty space, which leaves focus where it was.\n */\n readonly cell: HTMLElement | null;\n readonly themeClassName: string;\n}\n\nexport interface ContextMenuApi {\n menu: OpenContextMenu | null;\n /** Whether `area` opens a menu — for the `aria-keyshortcuts` of its cells. */\n opens: (area: GridContextMenuArea) => boolean;\n /**\n * Opens the menu `target` has, as a right-click there would, beside\n * `anchor` or below its cell, and says whether it did: not for a target\n * that is not on screen, or whose menu is empty.\n */\n open: (target: GridContextMenuTarget, anchor?: OverlayAnchor) => boolean;\n /** Runs the item the user chose, reporting it if it ran, then closes the menu. */\n run: (item: ResolvedMenuItem) => void;\n close: () => void;\n}\n\n/**\n * The grid's context menu. `@gridkitjs/dom`'s trigger reports a right-click,\n * Shift+F10 or the ContextMenu key inside the grid, and the ref can ask for\n * one too; the `contextMenu` option and `@gridkitjs/core`'s `resolveMenu`\n * say what menu that place has; this holds which one is open, tells\n * `onContextMenuOpenChange`, and does what opening it means in the grid.\n *\n * Opening one on a column, row or cell that is not selected selects it\n * first, where that kind is selectable, as a click on it would — opening one\n * inside the selection keeps it, so a menu can act on everything selected.\n * Focus moves to the cell first, so closing the menu returns it there. A\n * place whose menu resolves to nothing shows the browser's own.\n */\nexport default function useContextMenu<Row>({\n rootRef,\n headerTableRef,\n bodyTableRef,\n bodyScrollRef,\n contextMenu,\n onContextMenuOpenChange,\n controller,\n commands,\n nav,\n selection,\n messages,\n columnName,\n}: UseContextMenuOptions<Row>): ContextMenuApi {\n const [menu, setMenu] = useState<OpenContextMenu | null>(null);\n /** The menu open as of the last change, ahead of the render that draws it. */\n const current = useRef<OpenContextMenu | null>(null);\n const openings = useRef(0);\n const enabled = contextMenu !== undefined && contextMenu !== false;\n\n function parts(): GridParts<Row> {\n const { columns, pageRows } = controller.getView();\n return {\n root: rootRef.current,\n headerTable: headerTableRef.current,\n bodyTable: bodyTableRef.current,\n body: bodyScrollRef.current,\n columns,\n pageRows,\n };\n }\n\n function labelOf(target: GridContextMenuTarget): string {\n switch (target.area) {\n case \"header\":\n return messages.headerMenuLabel(columnName(target.columnId));\n case \"cell\":\n return messages.cellMenuLabel;\n case \"group\":\n return messages.groupMenuLabel;\n case \"body\":\n return messages.bodyMenuLabel;\n }\n }\n\n /**\n * Selects what the menu opens on unless it is selected already, and says\n * whether it did. Each kind follows its own `selectable` mode, as a click\n * does — a cell's row and the cell itself apart — and a kind a user cannot\n * select is left alone.\n */\n function selectTarget(target: GridContextMenuTarget): boolean {\n const state = controller.getState();\n if (target.area === \"header\") {\n if (\n selection.columnMode === false ||\n state.columnSelection.includes(target.columnId)\n ) {\n return false;\n }\n controller.selectColumn(target.columnId, \"replace\");\n return true;\n }\n if (target.area !== \"cell\") {\n return false;\n }\n const cell = { rowId: target.rowId, columnId: target.columnId };\n const selectRow =\n selection.rowMode !== false && !state.rowSelection.includes(target.rowId);\n const selectCell =\n selection.cellMode !== false && !isSameCell(state.cellSelection, cell);\n if (selectRow) {\n controller.selectRow(target.rowId, \"replace\");\n }\n if (selectCell) {\n controller.selectCell(cell, \"replace\");\n }\n return selectRow || selectCell;\n }\n\n /** The menu `target` has, over the grid as it is now. */\n function resolveFor(\n target: GridContextMenuTarget,\n ): readonly ResolvedMenuEntry[] {\n const context = commands.contextFor(target);\n return resolveMenu(contextMenuEntries(contextMenu, context), {\n commands: commands.commands,\n context,\n });\n }\n\n /**\n * Shows `next` in place of the menu open, or closes it with `null`, and\n * tells `onContextMenuOpenChange` — the one closing first.\n */\n function show(next: OpenContextMenu | null): void {\n const previous = current.current;\n if (previous === next) {\n return;\n }\n current.current = next;\n setMenu(next);\n if (previous !== null) {\n onContextMenuOpenChange?.({ open: false, target: previous.target });\n }\n if (next !== null) {\n onContextMenuOpenChange?.({ open: true, target: next.target });\n }\n }\n\n function openAt(\n { target, cell, anchor }: ContextMenuPlace,\n point: OverlayAnchor | null,\n ): boolean {\n let resolved = resolveFor(target);\n if (resolved.length === 0) {\n return false;\n }\n // Resolved again against the selection the menu now acts on.\n if (selectTarget(target)) {\n resolved = resolveFor(target);\n }\n if (cell !== null && document.activeElement !== cell.element) {\n // Focused without scrolling first: a scroll would close the menu about\n // to open beside it. Moving the tab stop after it then finds the cell\n // focused already.\n cell.element.focus({ preventScroll: true });\n nav.focusCellNow(cell.rowIndex, cell.columnIndex);\n }\n openings.current += 1;\n show({\n key: openings.current,\n target,\n entries: resolved,\n label: labelOf(target),\n anchor: point ?? anchor,\n cell: cell?.element ?? null,\n themeClassName: overlayThemeClassName(rootRef.current),\n });\n return true;\n }\n\n function handleRequest({ target, point }: ContextMenuRequest): boolean {\n const place = placeAt(target, parts());\n return place !== null && openAt(place, point);\n }\n\n // The trigger is attached once, and hears every request through this.\n const latestRequest = useRef(handleRequest);\n useLayoutEffect(() => {\n latestRequest.current = handleRequest;\n });\n\n useEffect(() => {\n const root = rootRef.current;\n if (!enabled || root === null) {\n return undefined;\n }\n return attachContextMenuTrigger(root, {\n onRequest: (request) => latestRequest.current(request),\n });\n }, [rootRef, enabled]);\n\n /**\n * The cell a menu returns focus to can go with what the menu did — a\n * hidden column takes its header — and focus then falls to the page.\n * It goes to the cell now holding the grid's tab stop instead.\n */\n const shown = useRef<OpenContextMenu | null>(null);\n useLayoutEffect(() => {\n const closed = shown.current;\n shown.current = menu;\n if (\n menu === null &&\n closed !== null &&\n closed.cell !== null &&\n !closed.cell.isConnected &&\n document.activeElement === document.body\n ) {\n nav.focusTabStop();\n }\n });\n\n function close(): void {\n show(null);\n }\n\n return {\n menu,\n opens: (area) => hasContextMenu(contextMenu, area),\n open: (target, anchor) => {\n const place = placeOf(target, parts());\n return place !== null && openAt(place, anchor ?? null);\n },\n run: (item) => {\n const open = current.current;\n if (item.run() && open !== null) {\n commands.report(item.id, open.target, \"contextMenu\");\n }\n close();\n },\n close,\n };\n}\n","import {\n HEADER_ROW,\n type DisplayRow,\n type GridContextMenuTarget,\n} from \"@gridkitjs/core\";\nimport {\n bodyCellFrom,\n bodyRowFrom,\n findBodyRow,\n groupRowFrom,\n type OverlayAnchor,\n} from \"@gridkitjs/dom\";\n\n/** The cell a menu opens on, with its place in the grid's focus. */\nexport interface TargetCell {\n readonly element: HTMLTableCellElement;\n readonly rowIndex: number;\n readonly columnIndex: number;\n}\n\n/** Where a context menu opens: its target, and what it is drawn on. */\nexport interface ContextMenuPlace {\n readonly target: GridContextMenuTarget;\n /** The cell that has focus while it is open; `null` in the body's empty space. */\n readonly cell: TargetCell | null;\n /**\n * What it goes beside when asked for without a point: the cell — or, for a\n * cell scrolled out of the grid's view, the nearest point on that view's\n * edge — or the body's corner.\n */\n readonly anchor: OverlayAnchor;\n}\n\n/** The parts of the grid, as drawn now, that a place is found among. */\nexport interface GridParts<Row> {\n /** The grid's root, which scrolls sideways. */\n readonly root: HTMLElement | null;\n readonly headerTable: HTMLTableElement | null;\n readonly bodyTable: HTMLTableElement | null;\n /** The body's scrolling region, whose empty space is the `body` area. */\n readonly body: HTMLElement | null;\n /** The columns shown, in order — what a cell's column index counts. */\n readonly columns: readonly { readonly id: string }[];\n /** The rows of the page, as `data-gridkit-row-index` counts them. */\n readonly pageRows: readonly DisplayRow<Row>[];\n}\n\nfunction headerCell(\n parts: GridParts<unknown>,\n columnIndex: number,\n): TargetCell | null {\n const element = parts.headerTable?.tHead?.rows[0]?.cells[columnIndex];\n return element === undefined\n ? null\n : { element, rowIndex: HEADER_ROW, columnIndex };\n}\n\nfunction bodyCell(\n parts: GridParts<unknown>,\n rowIndex: number,\n columnIndex: number,\n): TargetCell | null {\n const element = findBodyRow(parts.bodyTable, rowIndex)?.cells[columnIndex];\n return element === undefined ? null : { element, rowIndex, columnIndex };\n}\n\n/** The part of the viewport where `element` can be seen: its grid's scrolled view. */\nfunction viewOf(element: Element, parts: GridParts<unknown>): DOMRect | null {\n const root = parts.root?.getBoundingClientRect();\n if (root === undefined) {\n return null;\n }\n const body =\n parts.body?.contains(element) === true\n ? parts.body.getBoundingClientRect()\n : root;\n const left = Math.max(root.left, body.left);\n const top = Math.max(root.top, body.top);\n return new DOMRect(\n left,\n top,\n Math.max(0, Math.min(root.right, body.right) - left),\n Math.max(0, Math.min(root.bottom, body.bottom) - top),\n );\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * A cell's place, anchored to the cell itself while any of it is in the\n * grid's view (a group row's cell can be wider than the view). One scrolled\n * wholly out of it — the ref can ask for any cell drawn — is\n * anchored to the point of the view nearest its bottom-left corner instead,\n * so the menu opens at the grid's edge rather than off in the page, over\n * whatever the grid's scrolling hides it under.\n */\nfunction onCell(\n target: GridContextMenuTarget,\n cell: TargetCell | null,\n parts: GridParts<unknown>,\n): ContextMenuPlace | null {\n if (cell === null) {\n return null;\n }\n const box = cell.element.getBoundingClientRect();\n const view = viewOf(cell.element, parts);\n if (\n view === null ||\n (box.right > view.left &&\n box.left < view.right &&\n box.bottom > view.top &&\n box.top < view.bottom)\n ) {\n return { target, cell, anchor: cell.element };\n }\n return {\n target,\n cell,\n anchor: {\n x: clamp(box.left, view.left, view.right),\n y: clamp(box.bottom, view.top, view.bottom),\n },\n };\n}\n\n/** The body's empty space, anchored to its top-left corner. */\nfunction onBody(body: HTMLElement): ContextMenuPlace {\n const { left, top } = body.getBoundingClientRect();\n return { target: { area: \"body\" }, cell: null, anchor: { x: left, y: top } };\n}\n\nfunction headerPlaceAt<Row>(\n element: Element,\n parts: GridParts<Row>,\n): ContextMenuPlace | null {\n const cell = element.closest<HTMLTableCellElement>(\"th[data-gridkit-column]\");\n const columnId = cell?.getAttribute(\"data-gridkit-column\");\n if (\n cell === null ||\n cell.parentElement !== parts.headerTable?.tHead?.rows[0] ||\n columnId === null ||\n columnId === undefined\n ) {\n return null;\n }\n return onCell(\n { area: \"header\", columnId },\n headerCell(parts, cell.cellIndex),\n parts,\n );\n}\n\n/**\n * A data cell or a group row of the body, read off the rows of the page, or\n * the body's empty space. A cell must be the one `element` is in, not one of\n * a table some cell template holds, which has rows of its own. A group's\n * summary row, with nothing of its own to act on, has no place.\n */\nfunction bodyPlaceAt<Row>(\n element: Element,\n parts: GridParts<Row>,\n): ContextMenuPlace | null {\n const { body, pageRows } = parts;\n if (body === null || !body.contains(element)) {\n return null;\n }\n const group = groupRowFrom(element);\n if (group !== null) {\n const entry = pageRows[group.rowIndex];\n const cell = bodyCell(parts, group.rowIndex, 0);\n return entry !== undefined &&\n \"kind\" in entry &&\n entry.kind === \"group\" &&\n cell?.element.contains(element) === true\n ? onCell(\n { area: \"group\", groupId: entry.groupId, columnId: entry.columnId },\n cell,\n parts,\n )\n : null;\n }\n const position = bodyCellFrom(element);\n if (position !== null) {\n const entry = pageRows[position.rowIndex];\n const cell = bodyCell(parts, position.rowIndex, position.columnIndex);\n return entry !== undefined &&\n !(\"kind\" in entry) &&\n cell?.element.contains(element) === true\n ? onCell(\n { area: \"cell\", rowId: entry.rowId, columnId: position.columnId },\n cell,\n parts,\n )\n : null;\n }\n return bodyRowFrom(element) === null ? onBody(body) : null;\n}\n\n/**\n * The place `element` is in — a header, a data cell, a group row or the\n * body's empty space — or `null` for anything else in the grid: the footer,\n * the pager, the group-by bar.\n */\nexport function placeAt<Row>(\n element: Element,\n parts: GridParts<Row>,\n): ContextMenuPlace | null {\n return headerPlaceAt(element, parts) ?? bodyPlaceAt(element, parts);\n}\n\n/**\n * The place `target` names, among what is drawn now — `null` for a column,\n * row or group not on screen: hidden, on another page, in a collapsed group\n * or outside a virtualized window.\n */\nexport function placeOf<Row>(\n target: GridContextMenuTarget,\n parts: GridParts<Row>,\n): ContextMenuPlace | null {\n const columnIndexOf = (columnId: string) =>\n parts.columns.findIndex((column) => column.id === columnId);\n switch (target.area) {\n case \"header\":\n return onCell(\n target,\n headerCell(parts, columnIndexOf(target.columnId)),\n parts,\n );\n case \"cell\": {\n const rowIndex = parts.pageRows.findIndex(\n (entry) => !(\"kind\" in entry) && entry.rowId === target.rowId,\n );\n return onCell(\n target,\n bodyCell(parts, rowIndex, columnIndexOf(target.columnId)),\n parts,\n );\n }\n case \"group\": {\n const rowIndex = parts.pageRows.findIndex(\n (entry) =>\n \"kind\" in entry &&\n entry.kind === \"group\" &&\n entry.groupId === target.groupId,\n );\n return onCell(target, bodyCell(parts, rowIndex, 0), parts);\n }\n case \"body\":\n return parts.body === null ? null : onBody(parts.body);\n }\n}\n","import { useRef, type ReactNode, type RefCallback } from \"react\";\nimport type {\n ColumnValueOptions,\n FilterState,\n GridCommandTarget,\n GridMessages,\n GridPanelKind,\n} from \"@gridkitjs/core\";\nimport ColumnChooser from \"../columnChooser/ColumnChooser\";\nimport type { GridCommandsApi } from \"../commands/useGridCommands\";\nimport FilterMenu from \"../filterMenu/FilterMenu\";\nimport useApplyFilter from \"../filterMenu/useApplyFilter\";\nimport useFilterValueCache from \"../filterMenu/useFilterValueCache\";\nimport Overlay, { ANCHOR_GAP } from \"../overlay/Overlay\";\nimport type { DataGridController } from \"../useGridController\";\nimport type { GridPanelsApi } from \"./useGridPanels\";\n\n/** What every panel is drawn with. */\nexport interface GridPanelProps<Row> {\n /** Where it was asked for — a header's names the column a panel acts on. */\n readonly target: GridCommandTarget;\n /** Read for the grid's state as each render draws it, and acted on. */\n readonly controller: DataGridController<Row>;\n /** The grid's commands, for a panel running one so `onCommand` hears it. */\n readonly commands: GridCommandsApi<Row>;\n readonly messages: GridMessages;\n /** Closes the panel, giving focus back to where it was opened from. */\n readonly close: () => void;\n /**\n * The `ref` of the control focus starts on as the panel opens — a filter\n * editor's value box. A panel giving it to none starts on its first\n * control.\n */\n readonly initialFocusRef: RefCallback<HTMLElement>;\n /**\n * Sets the grid's filter as a filter menu applies one, announcing the rows\n * it keeps once they are drawn — even when the menu has closed by then.\n */\n readonly applyFilter: (filter: FilterState<Row>) => void;\n /**\n * The values a filter checklist lists for a column, counted once and\n * handed back again while nothing they are counted from changes — kept\n * by the panel host, so reopening a column's menu reuses its list.\n */\n readonly columnValues: (columnId: string) => ColumnValueOptions;\n}\n\n/** How one kind of panel is drawn. */\ninterface PanelKind {\n readonly component: <Row>(props: GridPanelProps<Row>) => ReactNode;\n /**\n * Whether Tab stays inside the panel, as in a dialog. A panel holding a\n * draft keeps it, since tabbing out would close it and drop the draft; one\n * applying every change at once lets Tab leave.\n */\n readonly trapFocus: boolean;\n}\n\n/**\n * Each kind of panel. Keyed by `GridPanelKind`, so a kind added there fails\n * to compile until it has its entry here, and needs nothing else.\n */\nconst panelKinds: { readonly [Kind in GridPanelKind]: PanelKind } = {\n columnChooser: { component: ColumnChooser, trapFocus: false },\n filter: { component: FilterMenu, trapFocus: true },\n};\n\ninterface GridPanelsProps<Row> {\n panels: GridPanelsApi;\n controller: DataGridController<Row>;\n commands: GridCommandsApi<Row>;\n messages: GridMessages;\n}\n\n/**\n * The open panel, if any, beside where it was asked for. Rendered after the\n * grid's tables, as every grid overlay is, so the keys pressed in it reach\n * no header or body handler on their way up React's tree.\n */\nexport default function GridPanels<Row>({\n panels,\n controller,\n commands,\n messages,\n}: GridPanelsProps<Row>) {\n const initialFocus = useRef<HTMLElement>(null);\n const applyFilter = useApplyFilter(\n controller,\n messages,\n commands.host.announce,\n );\n const columnValues = useFilterValueCache(controller, messages);\n const { panel, close } = panels;\n if (panel === null) {\n return null;\n }\n const { component: Panel, trapFocus } = panelKinds[panel.kind];\n return (\n <Overlay\n key={panel.key}\n anchor={panel.anchor}\n placement={panel.placement}\n gap={panel.anchor instanceof Element ? ANCHOR_GAP : 0}\n initialFocus={initialFocus}\n returnFocusTo={panel.returnFocusTo}\n // A column the chooser hides can scroll the grid back under it.\n ignoreScrollAfterInput\n trapFocus={trapFocus}\n themeClassName={panel.themeClassName}\n onDismiss={close}\n >\n <Panel<Row>\n target={panel.target}\n controller={controller}\n commands={commands}\n messages={messages}\n close={close}\n initialFocusRef={(element) => {\n initialFocus.current = element;\n }}\n applyFilter={applyFilter}\n columnValues={columnValues}\n />\n </Overlay>\n );\n}\n","import { useLayoutEffect, useRef, useState } from \"react\";\nimport { resolveColumnChooser } from \"@gridkitjs/core\";\nimport type { GridPanelProps } from \"../panels/GridPanels\";\n\n/**\n * The column chooser: a dialog listing every data column, hidden ones\n * included, with a native checkbox each, a search box narrowing the list and\n * a \"Show all\" checkbox over what the search shows. Which columns it lists,\n * which checkbox is disabled and what \"Show all\" does are\n * `@gridkitjs/core`'s `resolveColumnChooser`'s; this draws them.\n *\n * Every change applies at once, through `showColumns` and `hideColumns`, so\n * it reports and announces as any other change to the columns does. There\n * is nothing to confirm, so nothing to cancel: Escape or a click outside\n * just closes it.\n */\nexport default function ColumnChooser<Row>({\n controller,\n messages,\n}: GridPanelProps<Row>) {\n const [search, setSearch] = useState(\"\");\n const showAllRef = useRef<HTMLInputElement>(null);\n const { entries, selectAll, toggleAll } = resolveColumnChooser({\n columns: controller.getView().dataColumns,\n visibility: controller.getState().columnVisibility,\n search,\n });\n\n // A checkbox's mixed state has no attribute, only this property.\n useLayoutEffect(() => {\n if (showAllRef.current !== null) {\n showAllRef.current.indeterminate = selectAll === \"mixed\";\n }\n });\n\n function setVisible(columnIds: readonly string[], visible: boolean): void {\n if (visible) {\n controller.showColumns(columnIds);\n } else {\n controller.hideColumns(columnIds);\n }\n }\n\n return (\n <div\n role=\"dialog\"\n aria-label={messages.columnChooserLabel}\n className=\"gridkit-column-chooser\"\n >\n <input\n type=\"search\"\n className=\"column-chooser-search\"\n aria-label={messages.columnChooserSearchLabel}\n placeholder={messages.searchPlaceholder}\n value={search}\n onChange={(event) => {\n setSearch(event.currentTarget.value);\n }}\n />\n {entries.length === 0 ? (\n <p role=\"status\" className=\"column-chooser-empty\">\n {messages.noMatchingColumns}\n </p>\n ) : (\n <>\n <label className=\"column-chooser-option column-chooser-all\">\n <input\n ref={showAllRef}\n type=\"checkbox\"\n checked={selectAll === \"checked\"}\n disabled={toggleAll === null}\n onChange={() => {\n if (toggleAll !== null) {\n setVisible(toggleAll.columnIds, toggleAll.visible);\n }\n }}\n />\n {messages.showAllColumns}\n </label>\n <ul className=\"column-chooser-list\">\n {entries.map((entry) => (\n <li key={entry.columnId}>\n <label className=\"column-chooser-option\">\n <input\n type=\"checkbox\"\n checked={entry.visible}\n disabled={entry.disabled}\n onChange={() => {\n setVisible([entry.columnId], !entry.visible);\n }}\n />\n {entry.label}\n </label>\n </li>\n ))}\n </ul>\n </>\n )}\n </div>\n );\n}\n","import { useEffect, useRef, type SubmitEvent } from \"react\";\nimport {\n resolveColumnFilterMenu,\n resolveColumnHeaderText,\n resolveMenu,\n type BuiltInCommandId,\n type ResolvedMenuEntry,\n type ResolvedMenuItem,\n} from \"@gridkitjs/core\";\nimport { ariaAttr } from \"../ariaAttr\";\nimport { MenuIcon } from \"../menu/menuIcons\";\nimport type { GridPanelProps } from \"../panels/GridPanels\";\nimport ExcelFilterEditor from \"./ExcelFilterEditor\";\nimport type { FilterEditorHandle, FilterEditorProps } from \"./filterEditor\";\nimport SimpleFilterEditor from \"./SimpleFilterEditor\";\n\n/** The sort commands offered above the editor, each hidden where its column cannot sort. */\nconst SORT_COMMANDS: readonly BuiltInCommandId[] = [\n \"sort.ascending\",\n \"sort.descending\",\n \"sort.clear\",\n];\n\nfunction isItem(entry: ResolvedMenuEntry): entry is ResolvedMenuItem {\n return entry.type === \"item\";\n}\n\n/**\n * A column's filter menu: a dialog below its header holding the column's\n * sort commands, its filter editor — the conditions, or the checklist where\n * its `ui` is `\"excel\"` — and buttons that clear the filter, cancel or\n * apply. Which sort entries show and whether \"Clear filter\" can\n * run are the commands' own, resolved by `@gridkitjs/core`'s `resolveMenu`;\n * each runs through the grid's commands, so `onCommand` hears it with the\n * source `\"filterMenu\"`, and closes the menu, as choosing a menu item does.\n *\n * The editor edits a draft, so nothing filters until it is applied: OK, or\n * Enter in a field, applies it; Cancel, Escape or a click outside drops it.\n * The menu closes once the editor has applied, and stays open while the\n * editor marks what keeps it from applying.\n */\nexport default function FilterMenu<Row>({\n target,\n controller,\n commands,\n messages,\n close,\n initialFocusRef,\n applyFilter,\n columnValues,\n}: GridPanelProps<Row>) {\n const editor = useRef<FilterEditorHandle>(null);\n const column =\n target.area === \"header\"\n ? controller\n .getView()\n .dataColumns.find((entry) => entry.id === target.columnId)\n : undefined;\n const menu =\n column === undefined\n ? null\n : resolveColumnFilterMenu(controller.getOptions(), column.column);\n\n // Opened by an app's own command on a column with no menu, or left open as\n // its column loses it: with nothing to show, nothing stays open.\n useEffect(() => {\n if (menu === null) {\n close();\n }\n });\n\n if (column === undefined || menu === null) {\n return null;\n }\n\n const resolveOptions = {\n commands: commands.commands,\n context: commands.contextFor(target),\n };\n const sortItems = resolveMenu(SORT_COMMANDS, resolveOptions).filter(isItem);\n const [clearItem] = resolveMenu([\"filter.clear\"], resolveOptions).filter(\n isItem,\n );\n\n function run(item: ResolvedMenuItem): void {\n commands.run(item.id, target, \"filterMenu\");\n close();\n }\n\n const editorProps: FilterEditorProps<Row> = {\n ref: editor,\n column,\n menu,\n controller,\n messages,\n initialFocusRef,\n applyFilter,\n };\n\n function apply(event: SubmitEvent<HTMLFormElement>): void {\n event.preventDefault();\n if (editor.current?.apply() ?? true) {\n close();\n }\n }\n\n return (\n <div\n role=\"dialog\"\n aria-label={messages.filterMenuLabel(\n resolveColumnHeaderText(column.column),\n )}\n className=\"gridkit-filter-menu\"\n >\n {/*\n * Not validated by the browser: core reads every operand an editor\n * holds, so a `type=\"number\"` input's whole-number step never blocks\n * an apply with a tooltip of the browser's own.\n */}\n <form\n className=\"filter-menu-form\"\n noValidate\n onSubmit={apply}\n onKeyDown={(event) => {\n // Enter submits a form from its text boxes but not from a picker —\n // a select, or a checklist's list; here it applies from any.\n if (\n event.key === \"Enter\" &&\n event.target instanceof Element &&\n event.target.closest(\"select, [role=listbox]\") !== null\n ) {\n event.preventDefault();\n event.currentTarget.requestSubmit();\n }\n }}\n >\n {sortItems.length > 0 && (\n <div className=\"filter-menu-sort\">\n {sortItems.map((item) => (\n <button\n key={item.id}\n type=\"button\"\n className=\"filter-menu-sort-item\"\n disabled={item.disabled}\n {...ariaAttr(\n item.checked !== undefined,\n \"aria-pressed\",\n item.checked,\n )}\n onClick={() => {\n run(item);\n }}\n >\n <span className=\"filter-menu-sort-icon\" aria-hidden=\"true\">\n <MenuIcon name={item.icon} />\n </span>\n {item.label}\n </button>\n ))}\n </div>\n )}\n {menu.ui === \"excel\" ? (\n <ExcelFilterEditor {...editorProps} columnValues={columnValues} />\n ) : (\n <SimpleFilterEditor {...editorProps} />\n )}\n <div className=\"filter-menu-actions\">\n {clearItem !== undefined && (\n <button\n type=\"button\"\n className=\"filter-menu-clear\"\n disabled={clearItem.disabled}\n onClick={() => {\n run(clearItem);\n }}\n >\n {clearItem.label}\n </button>\n )}\n <button type=\"button\" className=\"filter-menu-cancel\" onClick={close}>\n {messages.cancelFilter}\n </button>\n <button type=\"submit\" className=\"filter-menu-apply\">\n {messages.applyFilter}\n </button>\n </div>\n </form>\n </div>\n );\n}\n","import {\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useReducer,\n useRef,\n useState,\n} from \"react\";\nimport {\n describeColumnFilter,\n draftToFilter,\n filterChecklist,\n filterEditorReducer,\n initialFilterEditorDraft,\n selectAllState,\n type ColumnValueOptions,\n type FilterChecklistItem,\n type FilterEditorAction,\n type FilterOperator,\n} from \"@gridkitjs/core\";\nimport { ChevronLeftIcon } from \"../menu/menuIcons\";\nimport type { FilterEditorHandle, FilterEditorProps } from \"./filterEditor\";\nimport OperatorMenuButton from \"./OperatorMenuButton\";\nimport SimpleFilterEditor from \"./SimpleFilterEditor\";\nimport ValueChecklist from \"./ValueChecklist\";\n\nexport interface ExcelFilterEditorProps<Row> extends FilterEditorProps<Row> {\n /**\n * The values a column's checklist lists, counted over the rows the other\n * columns' filters keep — the same list again while nothing it is counted\n * from has changed.\n */\n readonly columnValues: (columnId: string) => ColumnValueOptions;\n}\n\n/** What a checklist item's toggle does to the draft. */\nfunction toggleOf<Row>(item: FilterChecklistItem): FilterEditorAction<Row> {\n return item.kind === \"blanks\"\n ? { type: \"setIncludeBlanks\", includeBlanks: !item.checked }\n : { type: \"toggleValue\", value: item.value };\n}\n\n/**\n * A filter menu's excel editor: a search box, a \"Select all\" checkbox and a\n * checklist of the values the column holds, each checked while the filter\n * keeps it — the model being `@gridkitjs/core`'s `filterEditorReducer`,\n * over the column's values as `columnValues` counts them when the menu\n * opens. The values cascade: they are those of the rows the other columns'\n * filters keep.\n *\n * The search narrows the list, and \"Select all\" acts on what it shows, as\n * in Excel; past the menu's `valueLimit` values the list waits for a search\n * first, and a search matching more lists the first of them. OK applies the\n * draft through `draftToFilter`: everything checked is no filter, anything\n * less one `in` list, OR-ed with \"is blank\" while the blanks stay checked.\n *\n * Above the search, a \"Number filters\" button opens a menu of the column's\n * conditions. Choosing one shows the simple editor in place of the\n * checklist, its first condition at the operator chosen, until \"Back to\n * values\" brings the checklist back as it was left; OK there applies the\n * conditions, which replace the column's values, as Excel's do.\n *\n * Conditions or a custom filter open with every value checked, under a note\n * saying the column is filtered otherwise. OK leaves that filter be until a\n * value is checked or unchecked, as it leaves any filter whose values are as\n * they opened.\n */\nexport default function ExcelFilterEditor<Row>({\n column,\n menu,\n controller,\n messages,\n initialFocusRef,\n applyFilter,\n columnValues,\n ref,\n}: ExcelFilterEditorProps<Row>) {\n // Read once, as the menu opens: from then on the draft is the user's.\n const [opened] = useState(() => {\n const shape = describeColumnFilter(controller.getState().filter, column.id);\n return {\n shape,\n draft: initialFilterEditorDraft(shape, columnValues(column.id)),\n };\n });\n const [draft, dispatch] = useReducer(filterEditorReducer<Row>, opened.draft);\n /**\n * The operator chosen from the menu, while a condition at it shows in place\n * of the checklist.\n */\n const [operator, setOperator] = useState<FilterOperator | null>(null);\n const conditions = useRef<FilterEditorHandle>(null);\n const conditionsFocus = useRef<HTMLElement | null>(null);\n const operatorButton = useRef<HTMLButtonElement>(null);\n /** Set as the editor switches to a condition or back, for focus to follow. */\n const switched = useRef(false);\n const selectAllRef = useRef<HTMLInputElement>(null);\n // Each a pass over every value — tens of thousands of them on a large\n // column — so worked out as the draft changes, not again as the editor\n // switches to a condition and back.\n const selectAll = useMemo(() => selectAllState(draft), [draft]);\n const checklist = useMemo(\n () =>\n filterChecklist(draft, {\n valueLimit: menu.valueLimit,\n blanksLabel: messages.filterBlanks,\n }),\n [draft, menu.valueLimit, messages.filterBlanks],\n );\n\n // A checkbox's mixed state has no attribute, only this property.\n useLayoutEffect(() => {\n if (selectAllRef.current !== null) {\n selectAllRef.current.indeterminate = selectAll === \"mixed\";\n }\n });\n\n // Once the other side is drawn: to the condition's first box, or back to\n // the button whose menu chose it.\n useLayoutEffect(() => {\n if (switched.current) {\n switched.current = false;\n (operator === null\n ? operatorButton.current\n : conditionsFocus.current\n )?.focus();\n }\n }, [operator]);\n\n /**\n * Shows a condition at `chosen` in place of the checklist, or — given\n * `null` — the checklist again.\n */\n function switchTo(chosen: FilterOperator | null): void {\n switched.current = true;\n setOperator(chosen);\n }\n\n useImperativeHandle(ref, () => ({\n apply: () => {\n if (operator !== null) {\n return conditions.current?.apply() ?? true;\n }\n const picked =\n draft.checked !== opened.draft.checked ||\n draft.includeBlanks !== opened.draft.includeBlanks;\n if (picked) {\n applyFilter(\n draftToFilter(draft, column.id, controller.getState().filter),\n );\n }\n return true;\n },\n }));\n\n if (operator !== null) {\n return (\n <>\n <button\n type=\"button\"\n className=\"filter-menu-back\"\n onClick={() => {\n switchTo(null);\n }}\n >\n <span className=\"filter-menu-back-icon\" aria-hidden=\"true\">\n <ChevronLeftIcon />\n </span>\n {messages.filterBackToValues}\n </button>\n <SimpleFilterEditor\n ref={conditions}\n column={column}\n menu={menu}\n controller={controller}\n messages={messages}\n initialFocusRef={(element) => {\n conditionsFocus.current = element;\n }}\n applyFilter={applyFilter}\n operator={operator}\n />\n </>\n );\n }\n\n const { shape } = opened;\n return (\n <div className=\"filter-menu-values\">\n {menu.operators.length > 0 && (\n <OperatorMenuButton\n ref={operatorButton}\n menu={menu}\n active={\n shape.kind === \"conditions\"\n ? shape.conditions.map((condition) => condition.operator)\n : undefined\n }\n messages={messages}\n onChoose={switchTo}\n />\n )}\n {(shape.kind === \"conditions\" || shape.kind === \"custom\") && (\n <p className=\"filter-menu-custom\">\n {shape.kind === \"conditions\"\n ? messages.filterByCondition\n : messages.customFilter}\n </p>\n )}\n <input\n ref={initialFocusRef}\n type=\"search\"\n className=\"filter-menu-search\"\n aria-label={messages.filterSearchLabel}\n placeholder={messages.searchPlaceholder}\n value={draft.search}\n onChange={(event) => {\n dispatch({ type: \"search\", search: event.currentTarget.value });\n }}\n />\n <label className=\"filter-menu-select-all\">\n <input\n ref={selectAllRef}\n type=\"checkbox\"\n checked={selectAll === \"checked\"}\n // Nothing to act on: the search matches no value.\n disabled={!checklist.needsSearch && checklist.items.length === 0}\n onChange={() => {\n dispatch({ type: \"toggleAll\" });\n }}\n />\n {messages.filterSelectAll}\n </label>\n {checklist.needsSearch ? (\n <p className=\"filter-menu-search-first\">\n {messages.filterSearchFirst(checklist.total)}\n </p>\n ) : (\n <ValueChecklist\n items={checklist.items}\n showCounts={menu.showCounts}\n label={messages.filterValuesLabel}\n onToggle={(item) => {\n dispatch(toggleOf<Row>(item));\n }}\n />\n )}\n {checklist.hiddenCount > 0 && (\n <p role=\"status\" className=\"filter-menu-more\">\n {messages.filterMoreValues(checklist.hiddenCount)}\n </p>\n )}\n </div>\n );\n}\n","import { useLayoutEffect, useRef, useState, type Ref } from \"react\";\nimport type {\n FilterOperator,\n GridMessages,\n ResolvedColumnFilterMenu,\n ResolvedMenuItem,\n} from \"@gridkitjs/core\";\nimport type { AttachedMenu } from \"@gridkitjs/dom\";\nimport GridMenu from \"../menu/GridMenu\";\nimport { CheckIcon, ChevronRightIcon } from \"../menu/menuIcons\";\nimport Overlay, { ANCHOR_GAP, overlayThemeClassName } from \"../overlay/Overlay\";\n\ninterface OperatorMenuButtonProps {\n /** The column's filter menu: the operators listed, in its family's words. */\n readonly menu: ResolvedColumnFilterMenu;\n /**\n * The operators the column's conditions use, each checked in the menu — or\n * `undefined` while the column is not filtered by conditions, when no item\n * is checkable.\n */\n readonly active: readonly FilterOperator[] | undefined;\n readonly messages: GridMessages;\n /** An operator was chosen, and the menu has closed. */\n readonly onChoose: (operator: FilterOperator) => void;\n readonly ref: Ref<HTMLButtonElement>;\n}\n\n/** The menu open beside the button. */\ninterface OpenMenu {\n readonly anchor: HTMLElement;\n readonly themeClassName: string;\n /** How far from the button it opens — see `gapBeside`. */\n readonly gap: number;\n /** The item it opens on: the first, or the last when ArrowUp opened it. */\n readonly focusItem: number;\n}\n\n/**\n * How far from the button's side its menu opens: past the edge of the filter\n * menu the button sits in, by the gap an overlay keeps from what it opens\n * beside — so it opens beside the filter menu rather than over its edge.\n * The filter menu's padding is the same either side, so the gap holds when\n * the menu flips to the left.\n */\nfunction gapBeside(button: HTMLElement): number {\n const dialog = button.closest('[role=\"dialog\"]') ?? button;\n return (\n dialog.getBoundingClientRect().right -\n button.getBoundingClientRect().right +\n ANCHOR_GAP\n );\n}\n\n/**\n * The excel editor's \"Number filters\" button, opening a menu of the\n * conditions the column offers — a `GridMenu` in an overlay of its own,\n * stacked above the filter menu, so Escape closes it alone and a click in\n * it leaves the filter menu open. It follows the WAI-ARIA menu button\n * pattern: a click, Enter, Space or ArrowDown opens the menu on its first\n * item, ArrowUp on its last, and closing it returns focus to the button.\n *\n * While the column is filtered by conditions, its operators are checked in\n * the menu, and the button carries a tick, as Excel's does.\n */\nexport default function OperatorMenuButton({\n menu,\n active,\n messages,\n onChoose,\n ref,\n}: OperatorMenuButtonProps) {\n const [open, setOpen] = useState<OpenMenu | null>(null);\n const menuBehaviourRef = useRef<AttachedMenu | null>(null);\n const label = messages.filterOperatorMenu(menu.family);\n\n // As the menu opens, after the overlay — a child, whose layout effect runs\n // first — has focused the first item.\n useLayoutEffect(() => {\n if (open !== null && open.focusItem > 0) {\n menuBehaviourRef.current?.focusItem(open.focusItem);\n }\n }, [open]);\n\n function show(button: HTMLElement, onLast = false): void {\n setOpen({\n anchor: button,\n themeClassName: overlayThemeClassName(button),\n gap: gapBeside(button),\n focusItem: onLast ? menu.operators.length - 1 : 0,\n });\n }\n\n function close(): void {\n setOpen(null);\n }\n\n const entries = menu.operators.map((operator): ResolvedMenuItem => ({\n type: \"item\",\n id: operator,\n label: messages.filterOperatorLabel(operator, menu.family),\n disabled: false,\n checked: active?.includes(operator),\n run: () => {\n close();\n onChoose(operator);\n return true;\n },\n }));\n\n return (\n <>\n <button\n ref={ref}\n type=\"button\"\n className=\"filter-menu-submenu\"\n aria-haspopup=\"menu\"\n aria-expanded={open !== null}\n onClick={(event) => {\n if (open === null) {\n show(event.currentTarget);\n } else {\n close();\n }\n }}\n onKeyDown={(event) => {\n if (\n (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") &&\n open === null\n ) {\n event.preventDefault();\n show(event.currentTarget, event.key === \"ArrowUp\");\n }\n }}\n >\n <span className=\"filter-menu-submenu-icon\" aria-hidden=\"true\">\n {active !== undefined && <CheckIcon />}\n </span>\n {label}\n <span className=\"filter-menu-submenu-indicator\" aria-hidden=\"true\">\n <ChevronRightIcon />\n </span>\n </button>\n {open !== null && (\n <Overlay\n anchor={open.anchor}\n placement=\"right-start\"\n gap={open.gap}\n returnFocusTo={open.anchor}\n themeClassName={open.themeClassName}\n onDismiss={close}\n >\n <GridMenu\n entries={entries}\n label={label}\n themeClassName={open.themeClassName}\n behaviourRef={menuBehaviourRef}\n onRun={(item) => {\n item.run();\n }}\n onClose={close}\n />\n </Overlay>\n )}\n </>\n );\n}\n","import {\n Fragment,\n useId,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n conditionRowsFrom,\n conditionsFromRows,\n describeColumnFilter,\n draftToFilter,\n filterEditorReducer,\n initialFilterEditorDraft,\n type ColumnValueOptions,\n type ConditionRowDraft,\n type FilterOperator,\n type GridMessages,\n type OperatorFilterEntry,\n} from \"@gridkitjs/core\";\nimport ConditionRow from \"./ConditionRow\";\nimport type { FilterEditorProps } from \"./filterEditor\";\n\ntype Combinator = \"and\" | \"or\";\n\n/** The conditions as typed, and how they join. */\ninterface Draft {\n readonly rows: readonly ConditionRowDraft[];\n readonly combinator: Combinator;\n}\n\nconst COMBINATORS: readonly Combinator[] = [\"and\", \"or\"];\n\n/** No condition marked invalid. */\nconst NO_ROWS: readonly number[] = [];\n\n/**\n * The values half of the draft `draftToFilter` applies: the simple editor\n * has no checklist, so none.\n */\nconst NO_VALUES: ColumnValueOptions = {\n options: [],\n total: 0,\n truncated: false,\n blanks: 0,\n};\n\n/**\n * Whether a box in `row` holds what the browser can't read as a number or a\n * date — \"1e\", a date missing its year — which it reports as empty, so the\n * row would otherwise pass for one left blank.\n */\nfunction holdsUnreadable(row: HTMLElement | null | undefined): boolean {\n return Array.from(row?.querySelectorAll(\"input\") ?? []).some(\n (input) => input.validity.badInput,\n );\n}\n\ninterface CombinatorChoiceProps {\n /** The radio buttons' shared `name`, unique to the editor. */\n readonly name: string;\n readonly combinator: Combinator;\n readonly messages: GridMessages;\n readonly onChange: (combinator: Combinator) => void;\n}\n\n/** And or Or, between the two conditions: native radio buttons, one tab stop. */\nfunction CombinatorChoice({\n name,\n combinator,\n messages,\n onChange,\n}: CombinatorChoiceProps) {\n return (\n <div\n role=\"radiogroup\"\n aria-label={messages.filterCombinatorLabel}\n className=\"filter-menu-combinator\"\n >\n {COMBINATORS.map((choice) => (\n <label key={choice} className=\"filter-menu-combinator-option\">\n <input\n type=\"radio\"\n name={name}\n checked={choice === combinator}\n onChange={() => {\n onChange(choice);\n }}\n />\n {choice === \"and\" ? messages.filterAnd : messages.filterOr}\n </label>\n ))}\n </div>\n );\n}\n\nexport interface SimpleFilterEditorProps<Row> extends FilterEditorProps<Row> {\n /**\n * The operator its first condition starts at, chosen from the excel\n * editor's operator submenu — which shows this editor in place of its\n * checklist. A checklist's values are that editor's to show, so they are\n * not called a custom filter here then.\n */\n readonly operator?: FilterOperator | undefined;\n}\n\n/**\n * A filter menu's simple editor: one condition — an operator and its value —\n * and an optional second, joined to it by and/or. It opens on the column's\n * conditions, read by `@gridkitjs/core`'s `describeColumnFilter` and\n * `conditionRowsFrom`, its first at `operator` when given one. On a filter\n * it cannot show — a checklist's values, or a custom filter — it says so\n * above empty conditions, which replace it once applied.\n *\n * The conditions are text until applied, when `conditionsFromRows` reads\n * them as the column's type filters. A condition missing a value, or holding\n * one that doesn't read, keeps the menu open: its boxes are marked invalid,\n * described by a message, and the first takes focus — unless they are as it\n * opened them, as the empty ones on a column it shows no filter for: OK then\n * closes the menu as Cancel would, rather than asking for a value.\n */\nexport default function SimpleFilterEditor<Row>({\n column,\n menu,\n controller,\n messages,\n initialFocusRef,\n applyFilter,\n operator,\n ref,\n}: SimpleFilterEditorProps<Row>) {\n const type = column.column.type;\n // Read once, as the menu opens: from then on the draft is the user's.\n const [opened] = useState(() => {\n const shape = describeColumnFilter(controller.getState().filter, column.id);\n const rows = conditionRowsFrom(shape, menu.operators, type);\n const draft: Draft = {\n // Its typed values kept, as picking the operator in the row keeps them.\n rows:\n operator === undefined\n ? rows\n : rows.map((row, index) =>\n index === 0 ? { ...row, operator } : row,\n ),\n combinator: shape.kind === \"conditions\" ? shape.combinator : \"and\",\n };\n return {\n custom:\n shape.kind === \"custom\" ||\n (shape.kind === \"values\" && operator === undefined),\n draft,\n };\n });\n const [draft, setDraft] = useState(opened.draft);\n const [invalid, setInvalid] = useState(NO_ROWS);\n const rowElements = useRef<(HTMLDivElement | null)[]>([]);\n const invalidMessageId = useId();\n const combinatorName = useId();\n\n function update(next: Draft): void {\n setDraft(next);\n setInvalid(NO_ROWS);\n }\n\n /** Puts `conditions` in place of every entry about the column. */\n function applyConditions(\n conditions: readonly OperatorFilterEntry<Row>[],\n ): void {\n const applied = filterEditorReducer(\n initialFilterEditorDraft<Row>({ kind: \"none\" }, NO_VALUES),\n { type: \"setConditions\", conditions, combinator: draft.combinator },\n );\n applyFilter(\n draftToFilter(applied, column.id, controller.getState().filter),\n );\n }\n\n useImperativeHandle(ref, () => ({\n apply: () => {\n const parsed = conditionsFromRows<Row>(draft.rows, column.id, type);\n const unreadable = draft.rows.map((_, index) =>\n holdsUnreadable(rowElements.current[index]),\n );\n const marked = draft.rows.flatMap((_, index) =>\n parsed.invalid.includes(index) || unreadable[index] === true\n ? [index]\n : [],\n );\n if (marked.length === 0) {\n applyConditions(parsed.conditions);\n return true;\n }\n // Nothing typed since it opened: OK closes it, as Cancel would, rather\n // than asking for a value.\n if (draft === opened.draft && !unreadable.includes(true)) {\n return true;\n }\n setInvalid(marked);\n return false;\n },\n }));\n\n // After the render marking it, so the box is invalid as it takes focus.\n useLayoutEffect(() => {\n const [first] = invalid;\n if (first !== undefined) {\n rowElements.current[first]\n ?.querySelector<HTMLElement>('[aria-invalid=\"true\"]')\n ?.focus();\n }\n }, [invalid]);\n\n return (\n <div className=\"filter-menu-conditions\">\n {opened.custom && (\n <p className=\"filter-menu-custom\">{messages.customFilter}</p>\n )}\n {draft.rows.map((row, index) => (\n // A row is its place: the first condition, or the second.\n <Fragment key={index}>\n {index > 0 && (\n <CombinatorChoice\n name={combinatorName}\n combinator={draft.combinator}\n messages={messages}\n onChange={(combinator) => {\n update({ ...draft, combinator });\n }}\n />\n )}\n <ConditionRow\n ref={(element) => {\n rowElements.current[index] = element;\n }}\n row={row}\n position={index + 1}\n menu={menu}\n type={type}\n messages={messages}\n invalidMessageId={\n invalid.includes(index) ? invalidMessageId : undefined\n }\n focusRef={index === 0 ? initialFocusRef : undefined}\n onChange={(next) => {\n update({\n ...draft,\n rows: draft.rows.map((current, at) =>\n at === index ? next : current,\n ),\n });\n }}\n />\n </Fragment>\n ))}\n {invalid.length > 0 && (\n <p id={invalidMessageId} className=\"filter-menu-invalid\">\n {messages.filterValueInvalid(menu.family)}\n </p>\n )}\n </div>\n );\n}\n","import type { ChangeEvent, Ref, RefCallback } from \"react\";\nimport {\n filterOperandArity,\n parseFilterOperand,\n type ColumnType,\n type ConditionRowDraft,\n type FilterOperatorFamily,\n type GridMessages,\n type ResolvedColumnFilterMenu,\n} from \"@gridkitjs/core\";\n\n/**\n * The input a column of `type` takes an operand in, each writing what\n * `@gridkitjs/core`'s `parseFilterOperand` reads: a day for a date column, a\n * day and a time for a date-time or time one.\n */\nfunction inputType(\n family: Exclude<FilterOperatorFamily, \"boolean\">,\n type: ColumnType | undefined,\n): \"text\" | \"number\" | \"date\" | \"datetime-local\" {\n switch (family) {\n case \"text\":\n return \"text\";\n case \"number\":\n return \"number\";\n case \"date\":\n return type === \"date\" ? \"date\" : \"datetime-local\";\n }\n}\n\ninterface OperandFieldProps {\n readonly family: FilterOperatorFamily;\n readonly type: ColumnType | undefined;\n readonly text: string;\n /** Its accessible name: \"Value\", or a `between`'s \"From\" or \"To\". */\n readonly label: string;\n /** The id of the message describing it while it is invalid. */\n readonly invalidMessageId: string | undefined;\n readonly fieldRef: RefCallback<HTMLElement> | undefined;\n readonly messages: GridMessages;\n readonly onChange: (text: string) => void;\n}\n\n/** One operand's box — a true/false choice on a boolean column. */\nfunction OperandField({\n family,\n type,\n text,\n label,\n invalidMessageId,\n fieldRef,\n messages,\n onChange,\n}: OperandFieldProps) {\n const field = {\n ref: fieldRef,\n className: \"filter-menu-value\",\n \"aria-label\": label,\n \"aria-invalid\": invalidMessageId === undefined ? undefined : true,\n \"aria-describedby\": invalidMessageId,\n value: text,\n onChange: (event: ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {\n onChange(event.currentTarget.value);\n },\n };\n if (family === \"boolean\") {\n // Empty to start with, as a text box is, so a second condition left\n // alone is dropped rather than applied as \"Equals true\".\n return (\n <select {...field}>\n <option value=\"\" />\n <option value=\"true\">{messages.booleanTrue}</option>\n <option value=\"false\">{messages.booleanFalse}</option>\n </select>\n );\n }\n return <input {...field} type={inputType(family, type)} />;\n}\n\ninterface ConditionRowProps {\n readonly row: ConditionRowDraft;\n /** Its place among the editor's conditions, from one — what names it. */\n readonly position: number;\n readonly menu: ResolvedColumnFilterMenu;\n readonly type: ColumnType | undefined;\n readonly messages: GridMessages;\n /**\n * The id of the message saying its value is missing or doesn't read, while\n * it is marked so: each box whose text doesn't read is then invalid, and\n * described by it.\n */\n readonly invalidMessageId: string | undefined;\n /**\n * The `ref` of the control focus starts on: its first box, or its operator\n * picker when its operator takes no operand.\n */\n readonly focusRef: RefCallback<HTMLElement> | undefined;\n readonly onChange: (row: ConditionRowDraft) => void;\n readonly ref: Ref<HTMLDivElement>;\n}\n\n/**\n * One condition of a filter menu's editor, as typed: an operator picker,\n * then a box for each operand its operator takes — none for the blanks\n * operators, two for `between`'s ends.\n */\nexport default function ConditionRow({\n row,\n position,\n menu,\n type,\n messages,\n invalidMessageId,\n focusRef,\n onChange,\n ref,\n}: ConditionRowProps) {\n const arity = filterOperandArity(row.operator);\n // A condition set in code can use an operator the column doesn't offer; it\n // is listed too, so the row shows the condition as it is.\n const operators = menu.operators.includes(row.operator)\n ? menu.operators\n : [row.operator, ...menu.operators];\n const operand = { family: menu.family, type, messages };\n\n /**\n * The message id for a box holding `text`, while the row is marked: on the\n * box that is empty or doesn't read — a `between`'s missing end, not the\n * one filled in.\n */\n function messageIdFor(text: string): string | undefined {\n return parseFilterOperand(text, type) === undefined\n ? invalidMessageId\n : undefined;\n }\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-label={messages.filterConditionLabel(position)}\n className=\"filter-menu-condition\"\n >\n <select\n ref={arity === 0 ? focusRef : undefined}\n className=\"filter-menu-operator\"\n aria-label={messages.filterOperatorFieldLabel}\n value={row.operator}\n onChange={(event) => {\n const operator = operators[event.currentTarget.selectedIndex];\n if (operator !== undefined) {\n onChange({ ...row, operator });\n }\n }}\n >\n {operators.map((operator) => (\n <option key={operator} value={operator}>\n {messages.filterOperatorLabel(operator, menu.family)}\n </option>\n ))}\n </select>\n {arity > 0 && (\n <OperandField\n {...operand}\n text={row.text}\n label={\n arity === 2 ? messages.filterFromLabel : messages.filterValueLabel\n }\n invalidMessageId={messageIdFor(row.text)}\n fieldRef={focusRef}\n onChange={(text) => {\n onChange({ ...row, text });\n }}\n />\n )}\n {arity === 2 && (\n <OperandField\n {...operand}\n text={row.textTo}\n label={messages.filterToLabel}\n invalidMessageId={messageIdFor(row.textTo)}\n fieldRef={undefined}\n onChange={(textTo) => {\n onChange({ ...row, textTo });\n }}\n />\n )}\n </div>\n );\n}\n","import { useLayoutEffect, useRef, useState } from \"react\";\nimport type { FilterChecklistItem, VisibleRange } from \"@gridkitjs/core\";\nimport {\n attachChecklist,\n createRowVirtualizer,\n type AttachedChecklist,\n type RowVirtualizer,\n} from \"@gridkitjs/dom\";\nimport { CheckIcon } from \"../menu/menuIcons\";\n\n/**\n * The height assumed for an item not yet measured: the theme's, a line of\n * text and its padding. Every mounted item is measured, so it only places\n * those scrolled past.\n */\nconst ESTIMATED_ITEM_HEIGHT = 28;\n\n/** Items mounted beyond each edge of the list's visible part. */\nconst OVERSCAN = 4;\n\nconst NO_RANGE: VisibleRange = {\n startIndex: 0,\n endIndex: -1,\n offsetBefore: 0,\n offsetAfter: 0,\n};\n\ninterface ValueChecklistProps {\n /** Every item of the list, in order — only a window of them is mounted. */\n readonly items: readonly FilterChecklistItem[];\n readonly showCounts: boolean;\n /** The list's accessible name. */\n readonly label: string;\n /** An item asks to be checked or unchecked: Space on it, or a click. */\n readonly onToggle: (item: FilterChecklistItem) => void;\n}\n\n/**\n * A filter checklist's values: a `role=\"listbox\"` with one tab stop, each\n * value an option whose `aria-checked` says whether the filter keeps it.\n * A column can hold thousands of values, so the list is windowed by\n * `@gridkitjs/dom`'s `createRowVirtualizer` — the list is its own scroll\n * element, holding only the items near its scroll position between two\n * spacers — and made to behave by `attachChecklist`, which moves focus by\n * the arrow keys, Home, End, PageUp and PageDown and reports Space or a\n * click on an item by its place in the whole list.\n *\n * An item's key holds characters no DOM attribute may, so it keys React's\n * list only; the DOM knows an item by its place, `aria-posinset` one past it.\n */\nexport default function ValueChecklist({\n items,\n showCounts,\n label,\n onToggle,\n}: ValueChecklistProps) {\n const listRef = useRef<HTMLDivElement>(null);\n const checklistRef = useRef<AttachedChecklist | null>(null);\n const [virtualizer, setVirtualizer] = useState<RowVirtualizer | null>(null);\n const [range, setRange] = useState(NO_RANGE);\n\n /**\n * What the behaviour's callbacks read. They are handed over once, when it\n * attaches, so they read the props of the latest render here.\n */\n const latest = useRef({ items, onToggle });\n useLayoutEffect(() => {\n latest.current = { items, onToggle };\n });\n\n useLayoutEffect(() => {\n const list = listRef.current;\n if (list === null) {\n return undefined;\n }\n const rows = createRowVirtualizer(list, {\n estimatedRowHeight: ESTIMATED_ITEM_HEIGHT,\n overscan: OVERSCAN,\n onRange: setRange,\n });\n const checklist = attachChecklist(list, {\n onToggle: (index) => {\n const item = latest.current.items[index];\n if (item !== undefined) {\n latest.current.onToggle(item);\n }\n },\n scrollToIndex: (index) => {\n rows.scrollToIndex(index, { block: \"nearest\" });\n },\n });\n checklistRef.current = checklist;\n setVirtualizer(rows);\n return () => {\n checklistRef.current = null;\n checklist.detach();\n rows.destroy();\n };\n }, []);\n\n useLayoutEffect(() => {\n virtualizer?.setRowCount(items.length);\n checklistRef.current?.setCount(items.length);\n }, [virtualizer, items.length]);\n\n const shown = items.slice(range.startIndex, range.endIndex + 1);\n\n return (\n <div\n ref={listRef}\n role=\"listbox\"\n aria-multiselectable=\"true\"\n aria-label={label}\n className=\"filter-menu-checklist\"\n >\n <div role=\"presentation\" style={{ height: range.offsetBefore }} />\n {shown.map((item, offset) => {\n const index = range.startIndex + offset;\n return (\n <div\n key={item.key}\n ref={virtualizer?.measureRow(index)}\n role=\"option\"\n data-gridkit-checklist-item=\"\"\n data-gridkit-checklist-index={index}\n aria-checked={item.checked}\n aria-setsize={items.length}\n aria-posinset={index + 1}\n className=\"filter-menu-option\"\n >\n <span className=\"filter-menu-option-check\" aria-hidden=\"true\">\n <CheckIcon />\n </span>\n <span className=\"filter-menu-option-label\">{item.label}</span>\n {/* Spaced, so the option's name reads \"Alice 3\", not \"Alice3\". */}\n {showCounts && (\n <>\n {\" \"}\n <span className=\"filter-menu-option-count\">\n {String(item.count)}\n </span>\n </>\n )}\n </div>\n );\n })}\n <div role=\"presentation\" style={{ height: range.offsetAfter }} />\n </div>\n );\n}\n","import { useEffect, useRef } from \"react\";\nimport type { FilterState, GridMessages } from \"@gridkitjs/core\";\nimport type { DataGridController } from \"../useGridController\";\n\n/**\n * How a filter menu applies a filter: it becomes the grid's filter, and once\n * the grid has drawn the rows it keeps, how many they are of all the rows is\n * announced — `filterResults`, \"3 of 10 rows\". Held by the panel host, which\n * outlives the menu: the menu closes as it applies, before the rows are\n * drawn.\n */\nexport default function useApplyFilter<Row>(\n controller: DataGridController<Row>,\n messages: GridMessages,\n announce: (text: string) => void,\n): (filter: FilterState<Row>) => void {\n /** The filter a menu applied, until it is announced. */\n const unannounced = useRef<FilterState<Row> | null>(null);\n\n // After the render that drew the rows, so the count is theirs — and only\n // once the grid holds the filter, which a controlled one may not.\n useEffect(() => {\n if (unannounced.current === controller.getState().filter) {\n unannounced.current = null;\n announce(\n messages.filterResults(\n controller.getView().rows.length,\n controller.getOptions().dataSource?.length ?? 0,\n ),\n );\n }\n });\n\n return (filter) => {\n unannounced.current = filter;\n controller.setFilter(filter);\n };\n}\n","import { useState } from \"react\";\nimport {\n createColumnValueOptionsCache,\n type ColumnValueOptions,\n type GridMessages,\n} from \"@gridkitjs/core\";\nimport type { DataGridController } from \"../useGridController\";\n\n/** Rows to count before the grid has any: one array, so the cache keeps its lists. */\nconst NO_ROWS: readonly never[] = [];\n\n/**\n * The values a column's filter checklist lists, counted over the rows the\n * other columns' filters keep. Held by the panel host for the grid's whole\n * life, so reopening a column's checklist hands back the list it counted\n * last time rather than counting every row again — until the rows, the\n * columns, the locale, `messages` or another column's filter change.\n *\n * `messages` is the grid's own resolved object, which keeps its identity\n * while the `messages` prop does: the cache compares it by identity.\n */\nexport default function useFilterValueCache<Row>(\n controller: DataGridController<Row>,\n messages: GridMessages,\n): (columnId: string) => ColumnValueOptions {\n const [cache] = useState(createColumnValueOptionsCache<Row>);\n\n return (columnId) => {\n const { dataSource = NO_ROWS, locale } = controller.getOptions();\n return cache.get(\n dataSource,\n controller.getView().dataColumns,\n controller.getState().filter,\n columnId,\n locale === undefined ? { messages } : { locale, messages },\n );\n };\n}\n","import { resolveColumnFilterMenu } from \"@gridkitjs/core\";\nimport type { DataGridController } from \"../useGridController\";\nimport type { GridPanelsApi } from \"./useGridPanels\";\n\n/** What `DataGridApi` carries for the grid's panels. */\nexport interface GridPanelApi {\n /**\n * Opens the column chooser at the grid's top-end corner, in place of any\n * panel open; it gives focus back to what had it when it closes.\n */\n openColumnChooser(): void;\n /**\n * Opens the filter menu of the column `columnId` below its header, in\n * place of any panel open, and says whether it opened: not for a column\n * with no filter menu, nor one not shown. It gives focus back to the\n * header when it closes.\n */\n openFilterMenu(columnId: string): boolean;\n /** Closes the filter menu, if one is open, leaving any other panel open. */\n closeFilterMenu(): void;\n}\n\n/** `DataGridApi`'s panel methods, over the grid as it is when called. */\nexport function panelApi<Row>(\n panels: GridPanelsApi,\n controller: DataGridController<Row>,\n): GridPanelApi {\n return {\n openColumnChooser: () => {\n panels.open(\"columnChooser\", { area: \"grid\" });\n },\n openFilterMenu: (columnId) => {\n const shown = controller\n .getView()\n .columns.find((entry) => entry.id === columnId);\n if (\n shown === undefined ||\n resolveColumnFilterMenu(controller.getOptions(), shown.column) === null\n ) {\n return false;\n }\n panels.open(\"filter\", { area: \"header\", columnId });\n return true;\n },\n closeFilterMenu: () => {\n if (panels.panel?.kind === \"filter\") {\n panels.close();\n }\n },\n };\n}\n","import { useLayoutEffect, useRef, useState, type RefObject } from \"react\";\nimport type { GridCommandTarget, GridPanelKind } from \"@gridkitjs/core\";\nimport type { OverlayAnchor, OverlayPlacement } from \"@gridkitjs/dom\";\nimport { overlayThemeClassName } from \"../overlay/Overlay\";\nimport type { GridNavigationApi } from \"../useGridNavigation\";\n\ninterface UseGridPanelsOptions {\n /** The grid's root element, holding the toolbar; a panel asked for from nowhere opens at its corner. */\n rootRef: RefObject<HTMLElement | null>;\n headerTableRef: RefObject<HTMLTableElement | null>;\n nav: GridNavigationApi;\n}\n\n/** The panel open now. */\nexport interface OpenPanel {\n /** Counts the openings, so one opened over another replaces it. */\n readonly key: number;\n readonly kind: GridPanelKind;\n /** Where it was asked for. */\n readonly target: GridCommandTarget;\n readonly anchor: OverlayAnchor;\n readonly placement: OverlayPlacement;\n /**\n * What gets focus back when it closes: the toolbar button or the header it\n * opened from, or, for `undefined`, whatever had focus as it opened.\n */\n readonly returnFocusTo: HTMLElement | undefined;\n readonly themeClassName: string;\n}\n\nexport interface GridPanelsApi {\n panel: OpenPanel | null;\n /** Opens the panel `kind` beside where `target` names, in place of any panel open. */\n open: (kind: GridPanelKind, target: GridCommandTarget) => void;\n close: () => void;\n}\n\n/** The element of the root's own toolbar whose `data-gridkit-toolbar-item` is `itemId`. */\nfunction toolbarItem(root: HTMLElement, itemId: string): HTMLElement | null {\n const items = root.querySelectorAll<HTMLElement>(\n \":scope > .gridkit-toolbar > [data-gridkit-toolbar-item]\",\n );\n return (\n Array.from(items).find(\n (item) => item.getAttribute(\"data-gridkit-toolbar-item\") === itemId,\n ) ??\n // In \"More\" while the toolbar is narrow: the button it is chosen from.\n Array.from(items).find((item) =>\n item.hasAttribute(\"data-gridkit-toolbar-more\"),\n ) ??\n null\n );\n}\n\nfunction headerCell(\n headerTable: HTMLTableElement | null,\n columnId: string,\n): HTMLTableCellElement | null {\n const cells = headerTable?.tHead?.rows[0]?.cells;\n return cells === undefined\n ? null\n : (Array.from(cells).find(\n (cell) => cell.getAttribute(\"data-gridkit-column\") === columnId,\n ) ?? null);\n}\n\n/**\n * The grid's panels — the column chooser and a column's filter menu —\n * opened through the command host's `openPanel`, one at a time. A panel\n * opens beside where it was asked for: below the toolbar button, below the\n * column header, or at the grid's top-end corner for a call from nowhere in\n * particular, as the ref's is.\n *\n * Opened from a menu, it opens as the menu closes, in the same render: the\n * menu hands focus back to where it was opened from, and the panel takes it\n * from there — and gives it back there when it closes.\n */\nexport default function useGridPanels({\n rootRef,\n headerTableRef,\n nav,\n}: UseGridPanelsOptions): GridPanelsApi {\n const [panel, setPanel] = useState<OpenPanel | null>(null);\n const openings = useRef(0);\n\n function placeFor(\n root: HTMLElement,\n target: GridCommandTarget,\n ): Pick<OpenPanel, \"anchor\" | \"placement\" | \"returnFocusTo\"> {\n const element =\n target.area === \"toolbar\"\n ? toolbarItem(root, target.itemId)\n : target.area === \"header\"\n ? headerCell(headerTableRef.current, target.columnId)\n : null;\n if (element !== null) {\n return {\n anchor: element,\n // The toolbar's own button sits at its far end.\n placement: target.area === \"toolbar\" ? \"bottom-end\" : \"bottom-start\",\n returnFocusTo: element,\n };\n }\n const { right, top } = root.getBoundingClientRect();\n return {\n anchor: { x: right, y: top },\n placement: \"bottom-end\",\n returnFocusTo: undefined,\n };\n }\n\n /**\n * A header the panel returns focus to can go with what it did — the\n * chooser hiding that very column — and focus then falls to the page. It\n * goes to the cell now holding the grid's tab stop instead.\n */\n const shown = useRef<OpenPanel | null>(null);\n useLayoutEffect(() => {\n const closed = shown.current;\n shown.current = panel;\n if (\n panel === null &&\n closed?.returnFocusTo?.isConnected === false &&\n document.activeElement === document.body\n ) {\n nav.focusTabStop();\n }\n });\n\n return {\n panel,\n open: (kind, target) => {\n const root = rootRef.current;\n if (root === null) {\n return;\n }\n openings.current += 1;\n setPanel({\n key: openings.current,\n kind,\n target,\n ...placeFor(root, target),\n themeClassName: overlayThemeClassName(root),\n });\n },\n close: () => {\n setPanel(null);\n },\n };\n}\n","import { useLayoutEffect, useRef, type ReactNode } from \"react\";\nimport {\n resolveToolbar,\n splitToolbarItems,\n toolbarEntries,\n type GridMessages,\n type GridOptions,\n type ResolvedMenuEntry,\n type ResolvedToolbarItem,\n type ToolbarEntry,\n} from \"@gridkitjs/core\";\nimport { attachToolbar } from \"@gridkitjs/dom\";\nimport { ariaAttr } from \"../ariaAttr\";\nimport type { GridCommandsApi } from \"../commands/useGridCommands\";\nimport { MenuIcon } from \"../menu/menuIcons\";\nimport type { DataGridController } from \"../useGridController\";\nimport ToolbarMenuButton from \"./ToolbarMenuButton\";\nimport ToolbarSearch from \"./ToolbarSearch\";\nimport useToolbarOverflow from \"./useToolbarOverflow\";\n\ninterface GridToolbarProps<Row> {\n toolbar: GridOptions<Row>[\"toolbar\"];\n /** Fills a custom entry, by its id. */\n renderItem: ((id: string) => ReactNode) | undefined;\n /** The id of the grid element the toolbar acts on. */\n gridId: string;\n controller: DataGridController<Row>;\n commands: GridCommandsApi<Row>;\n messages: GridMessages;\n announce: (text: string) => void;\n}\n\n/** `run`, also telling `onCommand` through `report` whenever it runs. */\nfunction reporting(run: () => boolean, report: () => void): () => boolean {\n return () => {\n const ran = run();\n if (ran) {\n report();\n }\n return ran;\n };\n}\n\n/** A menu's entries, each item reporting through `report` with its id when it runs. */\nfunction reportingEntries(\n entries: readonly ResolvedMenuEntry[],\n report: (commandId: string) => void,\n): readonly ResolvedMenuEntry[] {\n return entries.map((entry) => {\n switch (entry.type) {\n case \"item\":\n return {\n ...entry,\n run: reporting(entry.run, () => {\n report(entry.id);\n }),\n };\n case \"submenu\":\n return { ...entry, items: reportingEntries(entry.items, report) };\n default:\n return entry;\n }\n });\n}\n\n/**\n * A toolbar item whose `run` — or, for a dropdown, whose items' `run` —\n * also reports to `onCommand` as asked from that item, wherever it ends up\n * drawn: as itself, or in \"More\".\n */\nfunction reportingItem(\n item: ResolvedToolbarItem,\n report: (commandId: string, itemId: string) => void,\n): ResolvedToolbarItem {\n switch (item.type) {\n case \"button\":\n return {\n ...item,\n run: reporting(item.run, () => {\n report(item.id, item.id);\n }),\n };\n case \"menu\":\n return {\n ...item,\n items: reportingEntries(item.items, (commandId) => {\n report(commandId, item.id);\n }),\n };\n default:\n return item;\n }\n}\n\n/**\n * The grid's toolbar, when its `toolbar` option lists anything: the entries\n * resolved by `@gridkitjs/core`'s `resolveToolbar` and drawn as a\n * `role=\"toolbar\"`, which `@gridkitjs/dom`'s `attachToolbar` makes one tab\n * stop the arrow keys move within. Which item shows, is enabled, pressed or\n * does what is core's; this draws them, and resolves them again on every\n * render, so they follow the grid's state.\n *\n * What does not fit moves into a \"More\" menu at the end, as\n * `@gridkitjs/dom`'s `observeToolbarOverflow` measures it and core's\n * `splitToolbarItems` turns it into menu entries: a toggle a checkable item,\n * a dropdown a submenu. The search box and custom entries always stay.\n */\nexport default function GridToolbar<Row>(props: GridToolbarProps<Row>) {\n const entries = toolbarEntries(props.toolbar);\n if (entries.length === 0) {\n return null;\n }\n const label =\n (typeof props.toolbar === \"object\" ? props.toolbar.label : undefined) ??\n props.messages.toolbarLabel;\n return <Toolbar {...props} entries={entries} label={label} />;\n}\n\nfunction Toolbar<Row>({\n entries,\n label,\n renderItem,\n gridId,\n controller,\n commands,\n messages,\n announce,\n}: GridToolbarProps<Row> & {\n entries: readonly ToolbarEntry<Row>[];\n label: string;\n}) {\n const toolbarRef = useRef<HTMLDivElement>(null);\n /** Set when a menu closes, for the layout effect below. */\n const menuClosed = useRef(false);\n\n const items = resolveToolbar(entries, {\n commands: commands.commands,\n contextFor: commands.contextFor,\n }).map((item) =>\n reportingItem(item, (commandId, itemId) => {\n commands.report(commandId, { area: \"toolbar\", itemId }, \"toolbar\");\n }),\n );\n const fit = useToolbarOverflow(toolbarRef, items);\n const { shown, overflow } = splitToolbarItems(items, fit);\n\n useLayoutEffect(() => {\n const toolbar = toolbarRef.current;\n return toolbar === null ? undefined : attachToolbar(toolbar);\n }, []);\n\n /**\n * A menu returns focus to its button as it closes — but what it ran can\n * take that button away, a dropdown whose items all hid, and focus then\n * falls to the page. It comes back to the toolbar instead.\n */\n useLayoutEffect(() => {\n if (!menuClosed.current) {\n return;\n }\n menuClosed.current = false;\n const toolbar = toolbarRef.current;\n if (toolbar !== null && document.activeElement === document.body) {\n (\n toolbar.querySelector<HTMLElement>('[tabindex=\"0\"]') ??\n toolbar.querySelector<HTMLElement>(\"button, input\")\n )?.focus();\n }\n });\n\n function onMenuClose(): void {\n menuClosed.current = true;\n }\n\n function draw(item: ResolvedToolbarItem): ReactNode {\n switch (item.type) {\n case \"button\":\n return (\n <button\n key={item.key}\n type=\"button\"\n className=\"toolbar-button\"\n data-gridkit-toolbar-item={item.key}\n {...ariaAttr(item.disabled, \"aria-disabled\", true)}\n {...ariaAttr(\n item.pressed !== undefined,\n \"aria-pressed\",\n item.pressed,\n )}\n {...ariaAttr(\n item.shortcut !== undefined,\n \"aria-keyshortcuts\",\n item.shortcut,\n )}\n onClick={() => {\n item.run();\n }}\n >\n {item.icon !== undefined && (\n <span className=\"toolbar-button-icon\" aria-hidden=\"true\">\n <MenuIcon name={item.icon} />\n </span>\n )}\n {item.label}\n </button>\n );\n case \"menu\":\n return (\n <ToolbarMenuButton\n key={item.key}\n itemKey={item.key}\n label={item.label}\n icon={item.icon}\n entries={item.items}\n onMenuClose={onMenuClose}\n />\n );\n case \"search\":\n return (\n <ToolbarSearch<Row>\n key={item.key}\n itemKey={item.key}\n controller={controller}\n messages={messages}\n announce={announce}\n />\n );\n case \"separator\":\n return (\n <div\n key={item.key}\n role=\"separator\"\n aria-orientation=\"vertical\"\n className=\"toolbar-separator\"\n data-gridkit-toolbar-item={item.key}\n />\n );\n case \"spacer\":\n return (\n <div\n key={item.key}\n className=\"toolbar-spacer\"\n data-gridkit-toolbar-item={item.key}\n />\n );\n case \"custom\":\n return (\n <div\n key={item.key}\n className=\"toolbar-custom\"\n data-gridkit-toolbar-item={item.key}\n >\n {renderItem?.(item.id)}\n </div>\n );\n }\n }\n\n return (\n <div\n ref={toolbarRef}\n role=\"toolbar\"\n aria-label={label}\n aria-controls={gridId}\n className=\"gridkit-toolbar\"\n >\n {shown.map(draw)}\n {overflow.length > 0 && (\n <ToolbarMenuButton\n itemKey=\"more\"\n label={messages.moreToolbarItems}\n entries={overflow}\n more\n onMenuClose={onMenuClose}\n />\n )}\n </div>\n );\n}\n","import { useLayoutEffect, useRef, useState } from \"react\";\nimport type { ResolvedMenuEntry } from \"@gridkitjs/core\";\nimport type { AttachedMenu } from \"@gridkitjs/dom\";\nimport { ariaAttr } from \"../ariaAttr\";\nimport { classNames } from \"../classNames\";\nimport GridMenu from \"../menu/GridMenu\";\nimport { ChevronDownIcon, MenuIcon } from \"../menu/menuIcons\";\nimport Overlay, { ANCHOR_GAP, overlayThemeClassName } from \"../overlay/Overlay\";\n\ninterface ToolbarMenuButtonProps {\n /** Its `data-gridkit-toolbar-item`. */\n itemKey: string;\n /** The button's label, and its menu's accessible name. */\n label: string;\n icon?: string | undefined;\n entries: readonly ResolvedMenuEntry[];\n /** The \"More\" button, holding the entries that do not fit, rather than a dropdown. */\n more?: boolean | undefined;\n /** Its menu closed, however it did. */\n onMenuClose: () => void;\n}\n\n/** The menu open below the button. */\ninterface OpenMenu {\n readonly anchor: HTMLElement;\n readonly themeClassName: string;\n /** The item it opens on: the first, or the last when ArrowUp opened it. */\n readonly focusItem: number;\n}\n\n/**\n * A toolbar button opening a menu below it, following the WAI-ARIA menu\n * button pattern: a click, Enter, Space or ArrowDown opens the menu with\n * focus on its first item, ArrowUp on its last, and a second click closes\n * it. Closing the menu returns focus to the button. What the items do, and\n * whether each runs, is in their `run`.\n */\nexport default function ToolbarMenuButton({\n itemKey,\n label,\n icon,\n entries,\n more = false,\n onMenuClose,\n}: ToolbarMenuButtonProps) {\n const [menu, setMenu] = useState<OpenMenu | null>(null);\n const menuBehaviourRef = useRef<AttachedMenu | null>(null);\n\n // As the menu opens, after the overlay — a child, whose layout effect runs\n // first — has focused the first item.\n useLayoutEffect(() => {\n if (menu !== null && menu.focusItem > 0) {\n menuBehaviourRef.current?.focusItem(menu.focusItem);\n }\n }, [menu]);\n\n function open(button: HTMLElement, onLast = false): void {\n setMenu({\n anchor: button,\n themeClassName: overlayThemeClassName(button),\n focusItem: onLast\n ? entries.filter((entry) => entry.type !== \"separator\").length - 1\n : 0,\n });\n }\n\n function close(): void {\n setMenu(null);\n onMenuClose();\n }\n\n return (\n <>\n <button\n type=\"button\"\n className={classNames(\"toolbar-button\", more && \"toolbar-more\")}\n data-gridkit-toolbar-item={itemKey}\n {...ariaAttr(more, \"data-gridkit-toolbar-more\", \"\")}\n aria-haspopup=\"menu\"\n aria-expanded={menu !== null}\n onClick={(event) => {\n if (menu === null) {\n open(event.currentTarget);\n } else {\n close();\n }\n }}\n onKeyDown={(event) => {\n if (\n (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") &&\n menu === null\n ) {\n event.preventDefault();\n open(event.currentTarget, event.key === \"ArrowUp\");\n }\n }}\n >\n {icon !== undefined && (\n <span className=\"toolbar-button-icon\" aria-hidden=\"true\">\n <MenuIcon name={icon} />\n </span>\n )}\n {label}\n <span className=\"toolbar-button-indicator\" aria-hidden=\"true\">\n <ChevronDownIcon />\n </span>\n </button>\n {menu !== null && (\n <Overlay\n anchor={menu.anchor}\n placement=\"bottom-start\"\n gap={ANCHOR_GAP}\n returnFocusTo={menu.anchor}\n themeClassName={menu.themeClassName}\n onDismiss={close}\n >\n <GridMenu\n entries={entries}\n label={label}\n themeClassName={menu.themeClassName}\n behaviourRef={menuBehaviourRef}\n onRun={(item) => {\n item.run();\n close();\n }}\n onClose={close}\n />\n </Overlay>\n )}\n </>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport {\n searchTextOf,\n setSearchText,\n type GridMessages,\n} from \"@gridkitjs/core\";\nimport type { DataGridController } from \"../useGridController\";\n\n/** How long typing has to rest before the search applies. */\nconst SEARCH_DELAY_MS = 250;\n\n/** What the user has typed and the grid not yet applied. */\ninterface Draft {\n readonly text: string;\n /**\n * The search applied when it was typed. Once the search changes from\n * elsewhere — \"Clear filters\", a restored layout — the draft is dropped\n * and the box shows that instead.\n */\n readonly over: string;\n}\n\ninterface ToolbarSearchProps<Row> {\n /** Its `data-gridkit-toolbar-item`. */\n itemKey: string;\n controller: DataGridController<Row>;\n messages: GridMessages;\n announce: (text: string) => void;\n}\n\n/**\n * The toolbar's search box, over the filter's global text entry — the one\n * naming no column — through `@gridkitjs/core`'s `searchTextOf` and\n * `setSearchText`. It reads what it shows back from the filter, so anything\n * else that changes the search changes the box.\n *\n * Typing applies once it rests for a moment; Enter applies at once, and\n * Escape empties the box. A search the box applied is announced as the\n * number of rows it found, once the grid has drawn them.\n */\nexport default function ToolbarSearch<Row>({\n itemKey,\n controller,\n messages,\n announce,\n}: ToolbarSearchProps<Row>) {\n const applied = searchTextOf(controller.getState().filter);\n const [draft, setDraft] = useState<Draft | null>(null);\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n /** The search this box applied, until it is announced. */\n const unannounced = useRef<string | null>(null);\n const text = draft !== null && draft.over === applied ? draft.text : applied;\n\n /** Applies `next`, typed over the search `over`, unless that has changed since. */\n function apply(next: string, over: string): void {\n clearTimeout(timer.current);\n setDraft(null);\n const filter = controller.getState().filter;\n if (searchTextOf(filter) !== over) {\n return;\n }\n const searched = setSearchText(filter, next);\n if (searched !== filter) {\n unannounced.current = next;\n controller.setFilter(searched);\n }\n }\n\n // After the render that drew the rows, so the count is theirs — and only\n // once the filter holds the search, which a controlled one may not.\n useEffect(() => {\n if (unannounced.current === applied) {\n unannounced.current = null;\n announce(messages.searchResults(controller.getView().rows.length));\n }\n });\n\n useEffect(\n () => () => {\n clearTimeout(timer.current);\n },\n [],\n );\n\n return (\n <input\n type=\"search\"\n className=\"toolbar-search\"\n data-gridkit-toolbar-item={itemKey}\n aria-label={messages.searchLabel}\n placeholder={messages.searchPlaceholder}\n value={text}\n onChange={(event) => {\n const typed = event.target.value;\n setDraft({ text: typed, over: applied });\n clearTimeout(timer.current);\n timer.current = setTimeout(() => {\n apply(typed, applied);\n }, SEARCH_DELAY_MS);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n apply(text, applied);\n } else if (event.key === \"Escape\" && text !== \"\") {\n // Ahead of the browser's own clearing, which would wait out the delay.\n event.preventDefault();\n apply(\"\", applied);\n }\n }}\n />\n );\n}\n","import { useLayoutEffect, useRef, useState, type RefObject } from \"react\";\nimport type { ResolvedToolbarItem } from \"@gridkitjs/core\";\nimport { observeToolbarOverflow, type ToolbarOverflow } from \"@gridkitjs/dom\";\n\n/**\n * How many of a toolbar's items fit in it, from the start, as\n * `@gridkitjs/dom`'s `observeToolbarOverflow` measures them — every item\n * until it first reports, which it does before paint.\n *\n * Attached once, so the widths it remembers for items moved into \"More\"\n * survive, and told of new items only when the toolbar's layout — each\n * item's kind, key and label — changes, rather than on every render, which\n * resolves the items afresh. A label matters for an item in \"More\", whose\n * remembered width it makes stale.\n */\nexport default function useToolbarOverflow(\n toolbarRef: RefObject<HTMLElement | null>,\n items: readonly ResolvedToolbarItem[],\n): number {\n const [fit, setFit] = useState(items.length);\n const overflow = useRef<ToolbarOverflow | null>(null);\n const measuredLayout = useRef(\"\");\n const layout = JSON.stringify(\n items.map((item) => [\n item.type,\n item.key,\n \"label\" in item ? item.label : null,\n ]),\n );\n\n useLayoutEffect(() => {\n const toolbar = toolbarRef.current;\n if (toolbar === null || layout === measuredLayout.current) {\n return;\n }\n measuredLayout.current = layout;\n const options = { items, onChange: setFit };\n if (overflow.current === null) {\n overflow.current = observeToolbarOverflow(toolbar, options);\n } else {\n overflow.current.update(options);\n }\n }, [toolbarRef, layout, items]);\n\n useLayoutEffect(\n () => () => {\n overflow.current?.detach();\n overflow.current = null;\n measuredLayout.current = \"\";\n },\n [],\n );\n\n return fit;\n}\n","import type { PointerEvent as ReactPointerEvent } from \"react\";\nimport {\n resolveKeyboardDropTarget,\n type ColumnOrderState,\n type GroupByState,\n} from \"@gridkitjs/core\";\nimport { resolveColumnDropTarget, type ColumnDropTarget } from \"@gridkitjs/dom\";\nimport type { ResolvedColumn } from \"./DataGrid\";\nimport useDragReorder from \"./useDragReorder\";\n\ninterface UseColumnDragOptions {\n order: ColumnOrderState;\n /** What a drop onto the group-by bar is resolved against. */\n groupBy: GroupByState;\n /** Column ids whose header may be dragged into the group-by bar at all. */\n groupByDraggableIds: ReadonlySet<string>;\n onDrop: (target: ColumnDropTarget, movedId: string) => void;\n}\n\nexport interface ColumnDragApi<Row> {\n /** The column being dragged, for as long as the drag lasts. */\n draggedColumnId: string | null;\n /** Where it would land if released now. */\n dropTarget: ColumnDropTarget | null;\n /** Where the element trailing the pointer sits, as a CSS `transform`. */\n ghostTransform: string | null;\n startDrag: (\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ) => void;\n /** Moves a column one place left (`-1`) or right (`1`). */\n moveByKeyboard: (entry: ResolvedColumn<Row>, direction: -1 | 1) => void;\n /**\n * Whether the gesture that just ended was a drag rather than a click, for a\n * header that has something of its own to do with a click.\n *\n * Reading it clears it, so that a press which never opened a drag at all —\n * on a column that cannot be reordered — does not see the last one's answer.\n */\n justDragged: () => boolean;\n}\n\n/**\n * Turns a pointer drag over the header into a drop target, leaving `onDrop` to\n * apply it. Built on `useDragReorder`'s shared pointer mechanics, with\n * `@gridkitjs/dom`'s `resolveColumnDropTarget` as the hit-testing: another\n * header (reorder among columns) or the group-by bar (add this column to the\n * grouping), tried in that order.\n */\nexport default function useColumnDrag<Row>({\n order,\n groupBy,\n groupByDraggableIds,\n onDrop,\n}: UseColumnDragOptions): ColumnDragApi<Row> {\n const drag = useDragReorder<ColumnDropTarget>({\n resolveTarget: (clientX, clientY, movedId) =>\n resolveColumnDropTarget(clientX, clientY, movedId, {\n order,\n groupBy,\n groupByDraggableIds,\n }),\n onDrop,\n });\n\n function startDrag(\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ): void {\n drag.startDrag(entry.id, event.currentTarget, event);\n }\n\n function moveByKeyboard(entry: ResolvedColumn<Row>, direction: -1 | 1): void {\n const beforeId = resolveKeyboardDropTarget(order, entry.id, direction);\n if (beforeId === undefined) {\n return;\n }\n onDrop({ kind: \"column-order\", beforeId }, entry.id);\n }\n\n // A new object each render, as `useColumnResize` returns: the handlers close\n // over `order`/`groupBy`, and a stable identity would buy nothing.\n return {\n draggedColumnId: drag.draggedId,\n dropTarget: drag.dropTarget,\n ghostTransform: drag.ghostTransform,\n startDrag,\n moveByKeyboard,\n justDragged: drag.justDragged,\n };\n}\n","import {\n useState,\n type PointerEvent as ReactPointerEvent,\n type RefObject,\n} from \"react\";\nimport {\n beginColumnResize,\n clampColumnWidth,\n resolveColumnConstraints,\n sizeColumnToContent,\n type ColumnSizeDefaults,\n} from \"@gridkitjs/core\";\nimport { measureColumnContent, startColumnResizeGesture } from \"@gridkitjs/dom\";\nimport type { ResolvedColumn } from \"./DataGrid\";\nimport type { DataGridController } from \"./useGridController\";\n\ninterface UseColumnResizeOptions<Row> {\n tableRef: RefObject<HTMLTableElement | null>;\n controller: DataGridController<Row>;\n columnSizeDefaults?: Partial<ColumnSizeDefaults> | undefined;\n}\n\nexport interface ColumnResizeApi<Row> {\n /** The column being dragged, for as long as the drag lasts. */\n activeColumnId: string | null;\n startResize: (\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ) => void;\n /** Sizes a column to its content, and says whether it could: not without cells. */\n sizeToContent: (entry: ResolvedColumn<Row>) => boolean;\n nudge: (entry: ResolvedColumn<Row>, delta: number) => void;\n}\n\n/**\n * Turns pointer and keyboard input into column widths. The drag itself is\n * `@gridkitjs/dom`'s `startColumnResizeGesture`, every width comes from\n * `@gridkitjs/core`, and the grid's controller applies them; this hook holds\n * only which column is being dragged.\n */\nexport default function useColumnResize<Row>({\n tableRef,\n controller,\n columnSizeDefaults,\n}: UseColumnResizeOptions<Row>): ColumnResizeApi<Row> {\n const [activeColumnId, setActiveColumnId] = useState<string | null>(null);\n\n function startResize(\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ): void {\n // A press on the handle is never the header's, whichever button made it:\n // a reorderable header's own drag must not see it.\n event.stopPropagation();\n\n const session = beginColumnResize(\n entry.column,\n entry.width,\n event.clientX,\n columnSizeDefaults,\n );\n /** The sizing as the drag found it, which Escape puts the column back to. */\n const base = controller.getState().columnSizing;\n\n const started = startColumnResizeGesture(\n event.currentTarget,\n event,\n session,\n {\n onMove(width) {\n controller.resizeColumn(session.columnId, width, \"move\");\n },\n onEnd(width) {\n setActiveColumnId(null);\n if (width !== null) {\n controller.resizeColumn(session.columnId, width, \"end\");\n }\n },\n /**\n * Escape puts back only the dragged column's pre-drag width, merged\n * into whatever the sizing state is *now* — not the `base` snapshot\n * taken at drag-start — so a different column resized via keyboard\n * while this drag was still open keeps its change instead of being\n * clobbered by a stale restore.\n */\n onCancel() {\n setActiveColumnId(null);\n controller.cancelColumnResize(\n session.columnId,\n base,\n session.startWidth,\n );\n },\n },\n );\n if (started) {\n setActiveColumnId(session.columnId);\n }\n }\n\n function sizeToContent(entry: ResolvedColumn<Row>): boolean {\n const table = tableRef.current;\n if (table === null) {\n return false;\n }\n\n const measured = measureColumnContent(table, entry.id);\n if (measured === null) {\n return false;\n }\n\n controller.resizeColumn(\n entry.id,\n sizeColumnToContent(\n measured,\n resolveColumnConstraints(entry.column, columnSizeDefaults),\n ),\n \"end\",\n );\n return true;\n }\n\n function nudge(entry: ResolvedColumn<Row>, delta: number): void {\n controller.resizeColumn(\n entry.id,\n clampColumnWidth(\n entry.width + delta,\n resolveColumnConstraints(entry.column, columnSizeDefaults),\n ),\n \"end\",\n );\n }\n\n // A new object each render, as the other hooks here return.\n return { activeColumnId, startResize, sizeToContent, nudge };\n}\n","import { useLayoutEffect, useState, type RefObject } from \"react\";\nimport { observeElementWidth } from \"@gridkitjs/dom\";\n\n/**\n * The inner width of `ref`'s element, tracked as it changes by\n * `@gridkitjs/dom`'s `observeElementWidth`.\n *\n * A layout effect rather than an effect so the first measurement lands before\n * paint — otherwise columns show at their natural width for a frame and then\n * visibly jump once auto-fit runs. Server rendering would want the usual\n * isomorphic-layout-effect shim here.\n *\n * @param enabled Whether to observe at all. A caller that does not read the\n * width passes `false` rather than paying a re-render of the whole grid on\n * every frame of a window resize.\n */\nexport default function useElementWidth(\n ref: RefObject<HTMLElement | null>,\n enabled: boolean,\n): number | null {\n const [width, setWidth] = useState<number | null>(null);\n\n useLayoutEffect(() => {\n const element = ref.current;\n if (element === null || !enabled) {\n return undefined;\n }\n return observeElementWidth(element, setWidth);\n }, [ref, enabled]);\n\n return width;\n}\n","import { useState, useSyncExternalStore, type ReactNode } from \"react\";\nimport {\n createGridController,\n type GridController,\n type GridControllerOptions,\n type GridState,\n type GridView,\n} from \"@gridkitjs/core\";\n\n/** The grid's controller, bound to React's node type for its columns. */\nexport type DataGridController<Row> = GridController<Row, ReactNode>;\n\nexport interface GridControllerBinding<Row> {\n controller: DataGridController<Row>;\n /** The state this render draws — re-read on every change the controller commits. */\n state: GridState<Row>;\n view: GridView<Row, ReactNode>;\n}\n\n/**\n * The grid's controller, created once and handed the current props on every\n * render. The controller holds every slice of state and derives the view, so\n * this hook only keeps React in step with it: `setOptions` runs during render,\n * so the view drawn always matches the props drawn, and the subscription\n * re-renders the grid when an action commits.\n *\n * `getState` is the snapshot: the controller hands back the same object until\n * a slice changes, which is exactly the stability `useSyncExternalStore`\n * needs, and a change the props made (a controlled slice) is already in it by\n * the time it is read here.\n */\nexport default function useGridController<Row>(\n options: GridControllerOptions<Row, ReactNode>,\n): GridControllerBinding<Row> {\n const [controller] = useState(() =>\n createGridController<Row, ReactNode>(options),\n );\n controller.setOptions(options);\n const state = useSyncExternalStore(controller.subscribe, controller.getState);\n return { controller, state, view: controller.getView() };\n}\n","import { useEffect, useRef, type RefObject } from \"react\";\nimport { attachInfiniteScroll, type InfiniteScroll } from \"@gridkitjs/dom\";\nimport type { InfiniteScrollConfig } from \"./DataGrid\";\n\ninterface UseInfiniteScrollOptions {\n /** The `.gridkit-data-grid-body` scroll wrapper. */\n rootRef: RefObject<HTMLDivElement | null>;\n /** The always-last `<tr>` `GridBody` renders while `config?.hasMore` is true. */\n sentinelRef: RefObject<HTMLTableRowElement | null>;\n config: InfiniteScrollConfig | undefined;\n}\n\n/**\n * `@gridkitjs/dom`'s `attachInfiniteScroll` on the body, idle until the\n * effect below hands it the props. That runs after every commit: the\n * sentinel row mounts and unmounts with `hasMore`, so only after a commit is\n * `sentinelRef` current, and an update that changes nothing does nothing.\n */\nexport default function useInfiniteScroll({\n rootRef,\n sentinelRef,\n config,\n}: UseInfiniteScrollOptions): void {\n const scroll = useRef<InfiniteScroll | null>(null);\n\n useEffect(() => {\n const root = rootRef.current;\n if (root === null) {\n return undefined;\n }\n const attached = attachInfiniteScroll(root, {\n sentinel: null,\n hasMore: false,\n });\n scroll.current = attached;\n return () => {\n attached.detach();\n scroll.current = null;\n };\n }, [rootRef]);\n\n useEffect(() => {\n scroll.current?.update({\n sentinel: sentinelRef.current,\n hasMore: config?.hasMore ?? false,\n onLoadMore: config?.onLoadMore,\n isLoadingMore: config?.isLoadingMore,\n rootMargin: config?.rootMargin,\n });\n });\n}\n","import { useCallback, useLayoutEffect, useRef, type RefObject } from \"react\";\nimport { createLiveAnnouncer, type LiveAnnouncer } from \"@gridkitjs/dom\";\n\n/**\n * The grid's live region, added as the last child of `containerRef`'s element\n * once it mounts. `@gridkitjs/dom` owns the element, so React never renders\n * it and an announcement re-renders nothing.\n *\n * A layout effect, so the region is in place from the first paint — where it\n * was when React rendered it. The returned `announce` keeps its identity for\n * the grid's whole life.\n */\nexport default function useLiveAnnouncer(\n containerRef: RefObject<HTMLElement | null>,\n): (text: string) => void {\n const announcer = useRef<LiveAnnouncer | null>(null);\n\n useLayoutEffect(() => {\n const container = containerRef.current;\n if (container === null) {\n return undefined;\n }\n const created = createLiveAnnouncer(container);\n announcer.current = created;\n return () => {\n created.destroy();\n announcer.current = null;\n };\n }, [containerRef]);\n\n return useCallback((text: string) => {\n announcer.current?.announce(text);\n }, []);\n}\n","import { useLayoutEffect, useState, type RefObject } from \"react\";\nimport type { VisibleRange } from \"@gridkitjs/core\";\nimport { createRowVirtualizer, type RowVirtualizer } from \"@gridkitjs/dom\";\n\nexport interface RowVirtualizerApi extends VisibleRange {\n /** Ref callback `GridBody` attaches to each rendered row's `<tr>`, keyed by that row's index in the full array. */\n measureRow: (index: number) => (element: HTMLTableRowElement | null) => void;\n /**\n * Scrolls so `index` is visible. Two-pass for a row not currently mounted:\n * jumps to an estimated offset immediately, then — once that row mounts and\n * its real height is measured — corrects the scroll position via the\n * mounted element's own `scrollIntoView`. A row already mounted is scrolled\n * to directly, in one pass.\n */\n scrollToIndex: (index: number, options?: ScrollIntoViewOptions) => void;\n}\n\ninterface UseRowVirtualizerOptions {\n /** Whether virtualization is active at all. `false` attaches nothing — no behavioral or performance difference from not virtualizing. */\n enabled: boolean;\n /** The full row array — only its `.length` and reference identity matter here; a new reference resets the measured heights (see below). */\n rows: readonly unknown[];\n /** The `.gridkit-data-grid-body` scroll wrapper. */\n bodyScrollRef: RefObject<HTMLDivElement | null>;\n estimatedRowHeight: number;\n overscan: number;\n}\n\nconst EMPTY_RANGE: VisibleRange = {\n startIndex: 0,\n endIndex: -1,\n offsetBefore: 0,\n offsetAfter: 0,\n};\n\n/** What a row is measured with before the virtualizer exists — while nothing is rendered. */\nfunction ignoreRow(): () => void {\n return () => undefined;\n}\n\n/**\n * `@gridkitjs/dom`'s `createRowVirtualizer` on the body, with the window of\n * rows it reports held as state for `GridBody` to render. The virtualizer is\n * state too, not a ref, because `measureRow` is read while rendering: a new\n * one — `estimatedRowHeight` or `overscan` changed — re-renders every row\n * with its own ref callbacks, so the rows already mounted are measured anew.\n *\n * Layout effects, so the window settles before paint rather than showing the\n * previous one for a frame — the same reason `useElementWidth` measures in a\n * layout effect.\n *\n * The measured heights reset whenever `rows` becomes a new reference\n * (filter, sort, groupBy, or `dataSource` itself changing) rather than\n * tracking each of those individually — the simplest rule that stays\n * correct, at the cost of one remeasurement on those already-big operations.\n * Keying heights by row id instead, to survive a pure reorder, is a\n * considered, deliberately deferred enhancement.\n */\nexport default function useRowVirtualizer({\n enabled,\n rows,\n bodyScrollRef,\n estimatedRowHeight,\n overscan,\n}: UseRowVirtualizerOptions): RowVirtualizerApi {\n const [virtualizer, setVirtualizer] = useState<RowVirtualizer | null>(null);\n const [range, setRange] = useState<VisibleRange>(EMPTY_RANGE);\n\n useLayoutEffect(() => {\n const element = bodyScrollRef.current;\n if (!enabled || element === null) {\n return undefined;\n }\n const created = createRowVirtualizer(element, {\n estimatedRowHeight,\n overscan,\n onRange: setRange,\n });\n setVirtualizer(created);\n return () => {\n created.destroy();\n };\n }, [enabled, bodyScrollRef, estimatedRowHeight, overscan]);\n\n useLayoutEffect(() => {\n virtualizer?.setRowCount(rows.length);\n virtualizer?.resetHeights();\n }, [virtualizer, rows]);\n\n return {\n startIndex: range.startIndex,\n endIndex: range.endIndex,\n offsetBefore: range.offsetBefore,\n offsetAfter: range.offsetAfter,\n measureRow: virtualizer?.measureRow ?? ignoreRow,\n scrollToIndex: (index, options) => {\n virtualizer?.scrollToIndex(index, options);\n },\n };\n}\n","// React components will be exported from here. They consume the framework-agnostic logic in @gridkitjs/core.\nexport {\n DataGrid,\n type Borders,\n type CellSelectEvent,\n type CellSelectionChangeEvent,\n type ColumnDefinition,\n type ColumnSelectEvent,\n type ColumnSelectionChangeEvent,\n type ColumnsSelectEvent,\n type DataColumn,\n type DataGridApi,\n type DataGridProps,\n type GroupByBarVisibility,\n type HoverableConfig,\n type InfiniteScrollConfig,\n type PagerConfig,\n type PagerTemplateContext,\n type ReactRenderSlots,\n type ResizeMode,\n type ResolvedColumn,\n type SelectedCell,\n type SelectedColumn,\n} from \"./DataGrid/DataGrid\";\n// Re-exported so a consumer wiring up resize or selection, or typing a\n// standalone cellTemplate, needs one import and not two. The row payloads name\n// no node type of their own, so they come straight from core.\nexport type {\n CellSelectionMode,\n CellSelectionState,\n CellTemplateContext,\n ColumnResizeEvent,\n ColumnSizeDefaults,\n ColumnSizingState,\n ColumnVisibilityEvent,\n ColumnVisibilityState,\n ContextMenuOpenChangeEvent,\n FilterChangeEvent,\n FilterEntry,\n FilterState,\n GridCommand,\n GridCommandEvent,\n GridCommandTarget,\n GridContextMenuOptions,\n GridContextMenuRequest,\n GridContextMenuTarget,\n GridMessages,\n GridOptions,\n GridState,\n GridToolbarOptions,\n MenuEntry,\n SerializedGridState,\n ResolvedRow,\n RowPointerEvent,\n RowProps,\n RowSelectEvent,\n RowSelectionChangeEvent,\n RowsSelectEvent,\n SelectableConfig,\n SelectedCellRef,\n SelectionMode,\n SelectionState,\n ToolbarEntry,\n} from \"@gridkitjs/core\";\n\n// Re-exported for the same reason: saving `getState()` as JSON goes through it.\nexport { serializeGridState } from \"@gridkitjs/core\";\n\n// Reactive hooks for building custom UI outside the grid's own DOM, each\n// subscribing to `DataGridApi.subscribe` via `useSyncExternalStore`.\nexport { default as usePaginationState } from \"./DataGrid/hooks/usePaginationState\";\nexport type { PaginationStateApi } from \"./DataGrid/hooks/usePaginationState\";\nexport { default as useGroupByState } from \"./DataGrid/hooks/useGroupByState\";\nexport type { GroupByStateApi } from \"./DataGrid/hooks/useGroupByState\";\nexport { default as useColumnSortState } from \"./DataGrid/hooks/useColumnSortState\";\nexport { default as useSelectionState } from \"./DataGrid/hooks/useSelectionState\";\nexport type { SelectionStateApi } from \"./DataGrid/hooks/useSelectionState\";\nexport { default as useAggregateState } from \"./DataGrid/hooks/useAggregateState\";\nexport { default as useColumnSizingState } from \"./DataGrid/hooks/useColumnSizingState\";\nexport { default as useColumnOrderState } from \"./DataGrid/hooks/useColumnOrderState\";\nexport { default as useColumnVisibilityState } from \"./DataGrid/hooks/useColumnVisibilityState\";\nexport { default as useFilterState } from \"./DataGrid/hooks/useFilterState\";\nexport type { FilterStateApi } from \"./DataGrid/hooks/useFilterState\";\n\n// Re-exported so typing an export — its options, a writer of the app's own,\n// the file a writer gives — needs no import from core.\nexport type {\n ExportFile,\n ExportOptions,\n ExportWriter,\n GridExportOptions,\n} from \"@gridkitjs/core\";\n\n// Re-exported so typing the `print` option, or a call to `print`, needs no\n// import from core.\nexport type { PrintOptions } from \"@gridkitjs/core\";\n\n// The filter popup in its Excel-style form, spread into `DataGrid`:\n// `<DataGrid {...excelFilter} />`.\nexport { excelFilter } from \"@gridkitjs/core\";\n","import { useCallback, type RefObject } from \"react\";\nimport type { PaginationState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_PAGINATION: PaginationState = { pageIndex: 0, pageSize: 0 };\n\nexport interface PaginationStateApi {\n pagination: PaginationState;\n pageCount: number;\n goToPage: (pageIndex: number) => void;\n nextPage: () => void;\n previousPage: () => void;\n setPageSize: (pageSize: number) => void;\n}\n\n/**\n * Reactive pagination state read off a mounted `DataGrid`'s `ref`,\n * for building a pager entirely outside the grid's own DOM — a toolbar or\n * sidebar `pager.template` can't reach. Updates on every pagination change,\n * including the silent page-0 reset a filter/sort/group change triggers,\n * which carries no `onPaginationChange` of its own.\n *\n * Before the grid mounts, `pagination` reads `{ pageIndex: 0, pageSize: 0 }`\n * and `pageCount` reads `0`; the actions are no-ops until then.\n */\nexport default function usePaginationState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): PaginationStateApi {\n const pagination = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getPagination(), []),\n FALLBACK_PAGINATION,\n );\n const pageCount = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getPageCount(), []),\n 0,\n );\n\n return {\n pagination,\n pageCount,\n goToPage: (pageIndex) => {\n gridRef.current?.goToPage(pageIndex);\n },\n nextPage: () => {\n gridRef.current?.nextPage();\n },\n previousPage: () => {\n gridRef.current?.previousPage();\n },\n setPageSize: (pageSize) => {\n gridRef.current?.setPageSize(pageSize);\n },\n };\n}\n","import { useCallback, useSyncExternalStore, type RefObject } from \"react\";\nimport type { DataGridApi } from \"../DataGrid\";\n\n/**\n * Shared `useSyncExternalStore` wiring behind every public `use*State` hook\n * in this folder. Not exported — `gridRef.current` is `null` until the grid\n * mounts, so subscribing has to tolerate that, and falls back to `fallback`\n * for the same reason `getSnapshot` has to until then.\n */\nexport default function useGridSnapshot<Row, T>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n getSnapshot: (api: DataGridApi<Row>) => T,\n fallback: T,\n): T {\n const subscribe = useCallback(\n (listener: () => void) => {\n const api = gridRef.current;\n if (api === null) {\n return () => {\n // Nothing was subscribed — `subscribe` itself already handles\n // that below by re-running on every render until the ref mounts.\n };\n }\n return api.subscribe(listener);\n },\n [gridRef],\n );\n\n return useSyncExternalStore(subscribe, () => {\n const api = gridRef.current;\n return api === null ? fallback : getSnapshot(api);\n });\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { GroupByState, GroupExpansionState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_GROUP_BY: GroupByState = [];\nconst FALLBACK_EXPANSION: GroupExpansionState = [];\n\nexport interface GroupByStateApi {\n groupBy: GroupByState;\n groupExpansion: GroupExpansionState;\n expandAllGroups: () => void;\n collapseAllGroups: () => void;\n}\n\n/**\n * Reactive group-by and group-expansion state read off a mounted\n * `DataGrid`'s `ref`, for a group-by bar or summary sidebar living\n * outside the grid's own DOM.\n *\n * The ref's `setGroupBy` and `setGroupExpansion` change the grouping and the\n * collapsed groups for a custom group-by UI; this hook carries only the\n * all-at-once expansion actions. A specific\n * group's own computed aggregates are read off `getDisplayRows()`'s\n * per-header `aggregates` field instead of a getter here — see\n * `useAggregateState` for the grand-total equivalent.\n *\n * Before the grid mounts, both fields read as empty and the actions are\n * no-ops.\n */\nexport default function useGroupByState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): GroupByStateApi {\n const groupBy = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getGroupBy(), []),\n FALLBACK_GROUP_BY,\n );\n const groupExpansion = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getGroupExpansion(), []),\n FALLBACK_EXPANSION,\n );\n\n return {\n groupBy,\n groupExpansion,\n expandAllGroups: () => {\n gridRef.current?.expandAllGroups();\n },\n collapseAllGroups: () => {\n gridRef.current?.collapseAllGroups();\n },\n };\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { ColumnSortState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_SORT: ColumnSortState = [];\n\n/**\n * Reactive column-sort state read off a mounted `DataGrid`'s `ref`,\n * for a sort indicator living outside the grid's own DOM.\n *\n * Reads only; change the sort through the ref's `setColumnSort`, or hold it\n * yourself with the controlled `columnSort` prop.\n *\n * Before the grid mounts, reads as an empty array.\n */\nexport default function useColumnSortState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): ColumnSortState {\n return useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getColumnSort(), []),\n FALLBACK_SORT,\n );\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { CellSelectionState, SelectionState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_SELECTION: SelectionState = [];\nconst FALLBACK_CELL_SELECTION: CellSelectionState = null;\n\nexport interface SelectionStateApi {\n rowSelection: SelectionState;\n columnSelection: SelectionState;\n cellSelection: CellSelectionState;\n clearSelection: () => void;\n selectAllRows: () => void;\n}\n\n/**\n * Reactive row/column/cell selection state read off a mounted\n * `DataGrid`'s `ref`, for a \"N rows selected\" toolbar living\n * outside the grid's own DOM. One combined hook rather than three, matching\n * how `useGridSelection` already treats all three as one concern\n * internally.\n *\n * Before the grid mounts, the row/column fields read as empty arrays and\n * the cell field reads `null`; the actions are no-ops.\n */\nexport default function useSelectionState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): SelectionStateApi {\n const rowSelection = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getRowSelection(), []),\n FALLBACK_SELECTION,\n );\n const columnSelection = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getColumnSelection(), []),\n FALLBACK_SELECTION,\n );\n const cellSelection = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getCellSelection(), []),\n FALLBACK_CELL_SELECTION,\n );\n\n return {\n rowSelection,\n columnSelection,\n cellSelection,\n clearSelection: () => {\n gridRef.current?.clearSelection();\n },\n selectAllRows: () => {\n gridRef.current?.selectAllRows();\n },\n };\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { AggregateResults } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_AGGREGATES: AggregateResults = new Map();\n\n/**\n * Reactive grand-total aggregate results read off a mounted\n * `DataGrid`'s `ref`, for a summary footer or bar living outside\n * the grid's own DOM — mirroring the built-in one the grid renders itself.\n *\n * Read-only: `getAggregates` is already read-only on `DataGridApi`, computed\n * over the whole filtered/sorted dataset rather than driven by any action.\n * A specific group's own subtotal is read off `getDisplayRows()`'s\n * per-header `aggregates` field instead — see `useGroupByState`.\n *\n * Before the grid mounts, reads as an empty map.\n */\nexport default function useAggregateState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): AggregateResults {\n return useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getAggregates(), []),\n FALLBACK_AGGREGATES,\n );\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { ColumnSizingState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_SIZING: ColumnSizingState = {};\n\n/**\n * Reactive column-sizing state read off a mounted `DataGrid`'s\n * `ref`. Reads only; change the widths through the ref's `setColumnSizing`,\n * or hold them yourself with the controlled `columnSizing` prop.\n *\n * Before the grid mounts, reads as an empty object.\n */\nexport default function useColumnSizingState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): ColumnSizingState {\n return useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getColumnSizing(), []),\n FALLBACK_SIZING,\n );\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { ColumnOrderState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_ORDER: ColumnOrderState = [];\n\n/**\n * Reactive column-order state read off a mounted `DataGrid`'s\n * `ref`. Reads only; change the order through the ref's `setColumnOrder`,\n * or hold it yourself with the controlled `columnOrder` prop.\n *\n * Before the grid mounts, reads as an empty array.\n */\nexport default function useColumnOrderState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): ColumnOrderState {\n return useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getColumnOrder(), []),\n FALLBACK_ORDER,\n );\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { ColumnVisibilityState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_VISIBILITY: ColumnVisibilityState = {};\n\n/**\n * Reactive column-visibility state read off a mounted `DataGrid`'s `ref` —\n * the columns shown or hidden since it mounted, keyed by id. Read-only:\n * change it through the ref's `showColumns`/`hideColumns`. A column absent\n * from it follows its definition's `hidden`.\n *\n * Before the grid mounts, reads as an empty object.\n */\nexport default function useColumnVisibilityState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): ColumnVisibilityState {\n return useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getColumnVisibility(), []),\n FALLBACK_VISIBILITY,\n );\n}\n","import { useCallback, useState, type RefObject } from \"react\";\nimport type { FilterState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nexport interface FilterStateApi<Row> {\n filter: FilterState<Row>;\n setFilter: (filter: FilterState<Row>) => void;\n}\n\n/**\n * Reactive filter state read off a mounted `DataGrid`'s `ref`, for a filter\n * bar or search box living outside the grid's own DOM, which sees every change\n * however it was made — the toolbar's search box included. `setFilter`\n * replaces the whole filter and sends the grid back to its first page.\n *\n * Before the grid mounts, `filter` reads as an empty array and `setFilter`\n * is a no-op.\n */\nexport default function useFilterState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): FilterStateApi<Row> {\n // Held per hook rather than as one module constant: a filter is typed by\n // its row, through a predicate's parameter, so one empty array cannot\n // stand in for every `Row`. Either way it must keep its identity.\n const [fallback] = useState<FilterState<Row>>(() => []);\n const filter = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getFilter(), []),\n fallback,\n );\n\n return {\n filter,\n setFilter: (next) => {\n gridRef.current?.setFilter(next);\n },\n };\n}\n"],"mappings":"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","names":["useEffect","useId","useImperativeHandle","useMemo","useRef","useState","resolveColumnHeaderText","jsx","jsx","jsxs","useMemo","useState","intentOf","jsx","jsxs","memo","jsx","jsxs","memo","memo","jsx","memo","jsx","jsxs","useMemo","useState","intentOf","jsx","jsx","jsxs","createPortal","resolveColumnLabel","useState","jsx","jsxs","resolveColumnLabel","createPortal","useMemo","runCommand","useRef","useRef","document","useMemo","document","runCommand","useLayoutEffect","useRef","useState","useLayoutEffect","useRef","createPortal","jsx","useRef","useLayoutEffect","createPortal","jsx","jsxs","Fragment","jsx","jsxs","isItem","useRef","useState","useLayoutEffect","jsx","useEffect","useLayoutEffect","useRef","useState","HEADER_ROW","bodyCellFrom","bodyRowFrom","findBodyRow","groupRowFrom","useState","useRef","useLayoutEffect","useEffect","useRef","useLayoutEffect","useRef","useState","Fragment","jsx","jsxs","useEffect","useRef","resolveColumnFilterMenu","resolveMenu","useImperativeHandle","useLayoutEffect","useMemo","useRef","useState","describeColumnFilter","draftToFilter","filterEditorReducer","initialFilterEditorDraft","useLayoutEffect","useRef","useState","Fragment","jsx","jsxs","useState","useRef","useLayoutEffect","Fragment","useLayoutEffect","useRef","useState","jsx","jsxs","jsx","jsxs","useState","draft","useRef","useLayoutEffect","Fragment","useLayoutEffect","useRef","useState","Fragment","jsx","jsxs","useRef","useState","useLayoutEffect","Fragment","jsx","jsxs","useState","shape","describeColumnFilter","initialFilterEditorDraft","filterEditorReducer","useRef","useMemo","useLayoutEffect","useImperativeHandle","draftToFilter","jsx","jsxs","useRef","resolveColumnFilterMenu","useEffect","resolveMenu","useEffect","useRef","useState","NO_ROWS","jsx","useRef","resolveColumnFilterMenu","useLayoutEffect","useRef","useState","headerCell","useState","useRef","useLayoutEffect","useLayoutEffect","useRef","useLayoutEffect","useRef","useState","Fragment","jsx","jsxs","useState","useRef","useLayoutEffect","useEffect","useRef","useState","jsx","useLayoutEffect","useRef","useState","jsx","jsxs","useRef","useLayoutEffect","resolveKeyboardDropTarget","resolveKeyboardDropTarget","useState","useLayoutEffect","useState","useState","useSyncExternalStore","useEffect","useRef","useLayoutEffect","useRef","useLayoutEffect","useState","createRowVirtualizer","jsx","jsxs","useRef","useId","useMemo","useState","useEffect","resolveColumnHeaderText","useImperativeHandle","useCallback","useCallback","useSyncExternalStore","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useState","useState","useCallback"]}
|
|
1
|
+
{"version":3,"sources":["../src/DataGrid/DataGrid.tsx","../src/DataGrid/components/GridColgroup.tsx","../src/DataGrid/components/GridHeader.tsx","../src/DataGrid/ariaAttr.ts","../src/DataGrid/classNames.ts","../src/DataGrid/icons.tsx","../src/DataGrid/isOwnEvent.ts","../src/DataGrid/useGridNavigation.ts","../src/DataGrid/useGridSelection.ts","../src/DataGrid/components/GridBody.tsx","../src/DataGrid/rowProps.ts","../src/DataGrid/components/GridGroupRow.tsx","../src/DataGrid/components/renderAggregate.ts","../src/DataGrid/components/GridGroupSummaryRow.tsx","../src/DataGrid/components/GridRow.tsx","../src/DataGrid/components/GridFooter.tsx","../src/DataGrid/components/GridPager.tsx","../src/DataGrid/components/GroupByBar.tsx","../src/DataGrid/useGroupByDrag.ts","../src/DataGrid/useDragReorder.ts","../src/DataGrid/announcedCallbacks.ts","../src/DataGrid/clipboard/useGridCopy.ts","../src/DataGrid/commands/useGridCommands.ts","../src/DataGrid/clipboard/copyToClipboard.ts","../src/DataGrid/export/useSaveFile.ts","../src/DataGrid/export/exportApi.ts","../src/DataGrid/print/printApi.ts","../src/DataGrid/menu/GridMenu.tsx","../src/DataGrid/overlay/Overlay.tsx","../src/DataGrid/menu/menuIcons.tsx","../src/DataGrid/contextMenu/GridContextMenu.tsx","../src/DataGrid/contextMenu/useContextMenu.ts","../src/DataGrid/contextMenu/contextMenuPlaces.ts","../src/DataGrid/panels/GridPanels.tsx","../src/DataGrid/columnChooser/ColumnChooser.tsx","../src/DataGrid/filterMenu/FilterMenu.tsx","../src/DataGrid/filterMenu/ExcelFilterEditor.tsx","../src/DataGrid/filterMenu/OperatorMenuButton.tsx","../src/DataGrid/filterMenu/SimpleFilterEditor.tsx","../src/DataGrid/filterMenu/ConditionRow.tsx","../src/DataGrid/filterMenu/ValueChecklist.tsx","../src/DataGrid/filterMenu/useApplyFilter.ts","../src/DataGrid/filterMenu/useFilterValueCache.ts","../src/DataGrid/panels/panelApi.ts","../src/DataGrid/panels/useGridPanels.ts","../src/DataGrid/toolbar/GridToolbar.tsx","../src/DataGrid/toolbar/ToolbarMenuButton.tsx","../src/DataGrid/toolbar/ToolbarSearch.tsx","../src/DataGrid/toolbar/useToolbarOverflow.ts","../src/DataGrid/useColumnDrag.ts","../src/DataGrid/useColumnResize.ts","../src/DataGrid/useElementWidth.ts","../src/DataGrid/useGridController.ts","../src/DataGrid/useInfiniteScroll.ts","../src/DataGrid/useLiveAnnouncer.ts","../src/DataGrid/useRowVirtualizer.ts","../src/index.ts","../src/DataGrid/hooks/usePaginationState.ts","../src/DataGrid/hooks/useGridSnapshot.ts","../src/DataGrid/hooks/useGroupByState.ts","../src/DataGrid/hooks/useColumnSortState.ts","../src/DataGrid/hooks/useSelectionState.ts","../src/DataGrid/hooks/useAggregateState.ts","../src/DataGrid/hooks/useColumnSizingState.ts","../src/DataGrid/hooks/useColumnOrderState.ts","../src/DataGrid/hooks/useColumnVisibilityState.ts","../src/DataGrid/hooks/useFilterState.ts"],"sourcesContent":["import {\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport {\n moveColumnBefore,\n resolveColumnHeaderText,\n resolveMessages,\n resolveRows,\n totalColumnWidth,\n type ColumnDefinition as CoreColumnDefinition,\n type DataColumn as CoreDataColumn,\n type ResolvedColumn as CoreResolvedColumn,\n type AggregateResults,\n type AggregateState,\n type Borders,\n type ColumnOrderState,\n type ColumnSizingState,\n type ColumnSortState,\n type ColumnVisibilityState,\n type DisplayRow,\n type FilterState,\n type GridCommandTarget,\n type GridContextMenuTarget,\n type GridOptions,\n type GridState,\n type GroupByBarVisibility,\n type GroupByState,\n type GroupExpansionState,\n type HoverableConfig,\n type PaginationState,\n type ResizeMode,\n type ResolvedRow,\n type CellSelectionState,\n type SelectedCell as CoreSelectedCell,\n type SelectedColumn as CoreSelectedColumn,\n type SelectionState,\n type CellSelectEvent as CoreCellSelectEvent,\n type CellSelectionChangeEvent as CoreCellSelectionChangeEvent,\n type ColumnSelectEvent as CoreColumnSelectEvent,\n type ColumnSelectionChangeEvent as CoreColumnSelectionChangeEvent,\n type ColumnsSelectEvent as CoreColumnsSelectEvent,\n type SelectionCallbacks as CoreSelectionCallbacks,\n type SerializedGridState,\n} from \"@gridkitjs/core\";\nimport type { ColumnDropTarget } from \"@gridkitjs/dom\";\nimport GridColgroup from \"./components/GridColgroup\";\nimport GridHeader from \"./components/GridHeader\";\nimport GridBody from \"./components/GridBody\";\nimport GridFooter from \"./components/GridFooter\";\nimport GridPager from \"./components/GridPager\";\nimport GroupByBar from \"./components/GroupByBar\";\nimport { announcedCallbacks } from \"./announcedCallbacks\";\nimport { ariaAttr } from \"./ariaAttr\";\nimport { classNames } from \"./classNames\";\nimport useGridCopy from \"./clipboard/useGridCopy\";\nimport useGridCommands from \"./commands/useGridCommands\";\nimport GridContextMenu from \"./contextMenu/GridContextMenu\";\nimport useContextMenu from \"./contextMenu/useContextMenu\";\nimport { exportApi, type GridExportApi } from \"./export/exportApi\";\nimport { isOwnEvent } from \"./isOwnEvent\";\nimport GridPanels from \"./panels/GridPanels\";\nimport { panelApi, type GridPanelApi } from \"./panels/panelApi\";\nimport { printApi, type GridPrintApi } from \"./print/printApi\";\nimport useGridPanels from \"./panels/useGridPanels\";\nimport GridToolbar from \"./toolbar/GridToolbar\";\nimport useColumnDrag from \"./useColumnDrag\";\nimport useColumnResize from \"./useColumnResize\";\nimport useElementWidth from \"./useElementWidth\";\nimport useGridController, {\n type DataGridController,\n} from \"./useGridController\";\nimport useGridNavigation, { HEADER_ROW } from \"./useGridNavigation\";\nimport useGridSelection from \"./useGridSelection\";\nimport useInfiniteScroll from \"./useInfiniteScroll\";\nimport useLiveAnnouncer from \"./useLiveAnnouncer\";\nimport useRowVirtualizer from \"./useRowVirtualizer\";\n\n/**\n * A column whose header and cells may render arbitrary React content.\n * @gridkitjs/core stays framework-agnostic and so leaves that output type open;\n * this is the binding React consumers want, and the one they should import.\n */\nexport type ColumnDefinition<Row> = CoreColumnDefinition<Row, ReactNode>;\n\n/** A column paired with the width it renders at. */\nexport type ResolvedColumn<Row> = CoreResolvedColumn<Row, ReactNode>;\n\n/** A column paired with its id, hidden or not — what `getDataColumns()` lists. */\nexport type DataColumn<Row> = CoreDataColumn<Row, ReactNode>;\n\n/**\n * The selection payloads, bound to React's node type for the same reason\n * `ColumnDefinition` is: they carry a resolved column, whose label is whatever\n * a `headerTemplate` returned.\n *\n * The row payloads name no node type at all and so are re-exported from\n * `@gridkitjs/core` as they are.\n */\nexport type SelectedColumn<Row> = CoreSelectedColumn<Row, ReactNode>;\nexport type SelectedCell<Row> = CoreSelectedCell<Row, ReactNode>;\nexport type ColumnSelectEvent<Row> = CoreColumnSelectEvent<Row, ReactNode>;\nexport type ColumnsSelectEvent<Row> = CoreColumnsSelectEvent<Row, ReactNode>;\nexport type ColumnSelectionChangeEvent<Row> = CoreColumnSelectionChangeEvent<\n Row,\n ReactNode\n>;\nexport type CellSelectEvent<Row> = CoreCellSelectEvent<Row, ReactNode>;\nexport type CellSelectionChangeEvent<Row> = CoreCellSelectionChangeEvent<\n Row,\n ReactNode\n>;\nexport type SelectionCallbacks<Row> = CoreSelectionCallbacks<Row, ReactNode>;\n\n/**\n * Imperative handle for a mounted `DataGrid`, reached via its `ref` prop:\n * the grid's DOM nodes, getters for its live state, the actions every grid\n * ref carries (focus, select all, scroll-to), and a setter for every slice of\n * state, for a toolbar, a saved layout or a test to drive it from outside.\n *\n * Every getter reads the grid's state at call time, so a read straight after\n * an action sees its result. Every setter changes the grid as the user's own\n * interaction would: it fires the slice's `on*Change` callback, and, for a\n * slice held through a controlled prop, only asks. `subscribe` is the\n * notify channel for state that changes; see\n * `packages/react/src/DataGrid/hooks/` for the public hooks built on it.\n */\nexport interface DataGridApi<Row>\n extends GridExportApi, GridPrintApi, GridPanelApi {\n /** The grid's scrollable viewport element. */\n readonly element: HTMLDivElement | null;\n /**\n * The grid's row-area `<table>` element — the one holding `<tbody>`. The\n * header and, when aggregates are active, footer render as their own\n * sibling `<table>`s outside this one; use `element` to reach the whole\n * scrollable viewport instead.\n */\n readonly table: HTMLTableElement | null;\n\n /** Rows as currently filtered and sorted — what's rendered, ungrouped. */\n getRows(): readonly ResolvedRow<Row>[];\n /**\n * `getRows()` regrouped into the active `groupBy` — group headers\n * interleaved with data rows, in render order. Identical to `getRows()`\n * when `groupBy` is empty.\n */\n getDisplayRows(): readonly DisplayRow<Row>[];\n /**\n * The current page of `getDisplayRows()` — exactly the rows the body\n * renders. All of `getDisplayRows()` when `paginated` is off.\n */\n getPageRows(): readonly DisplayRow<Row>[];\n /** Columns as currently sized and ordered — what's rendered, so hidden columns are left out. */\n getColumns(): readonly ResolvedColumn<Row>[];\n /** Every column in its current order, hidden ones included — what sorting, filtering and grouping read. */\n getDataColumns(): readonly DataColumn<Row>[];\n\n getColumnSizing(): ColumnSizingState;\n getColumnOrder(): ColumnOrderState;\n /** Columns shown or hidden since the grid mounted. A column absent from it follows its definition's `hidden`. */\n getColumnVisibility(): ColumnVisibilityState;\n getColumnSort(): ColumnSortState;\n /** The filter the rows are shown through — every entry, ANDed together. */\n getFilter(): FilterState<Row>;\n getGroupBy(): GroupByState;\n getGroupExpansion(): GroupExpansionState;\n /** The active page and page size. Meaningful even when `paginated` is off — it stays at page 0 over the grid's whole (single) page. */\n getPagination(): PaginationState;\n /** How many pages the current `pagination.pageSize` splits the grid's rows into — `1` whenever `paginated` is off. */\n getPageCount(): number;\n /**\n * The grand-total aggregate results — every active aggregate computed over\n * the whole filtered/sorted dataset, ungrouped and unpaginated. A specific\n * group's own results are read off `getDisplayRows()` instead, on that\n * group header's `aggregates` field.\n */\n getAggregates(): AggregateResults;\n getRowSelection(): SelectionState;\n /**\n * The selected rows themselves, in the order they were selected — among\n * every row the filter lets through, on any page or in any group, so a row\n * filtered out while selected is left out until it is back.\n */\n getSelectedRows(): readonly ResolvedRow<Row>[];\n getColumnSelection(): SelectionState;\n getCellSelection(): CellSelectionState;\n /** The cell currently holding the grid's single tab stop. */\n getFocusedCell(): { rowIndex: number; columnIndex: number };\n /**\n * Every slice of state as the grid applies it, in one object — what\n * `restoreState` takes back. Pass it through `serializeGridState` before\n * saving it as JSON.\n */\n getState(): GridState<Row>;\n /**\n * Puts back state saved earlier, whole or in part — from `getState()`, or\n * from `serializeGridState` and back through JSON. Each slice given is set\n * as its setter would set it, firing its callback when it changes; the\n * grid re-renders once.\n */\n restoreState(\n saved: Partial<GridState<Row>> | Partial<SerializedGridState<Row>>,\n ): void;\n\n focusCell(rowIndex: number, columnIndex: number): void;\n clearSelection(): void;\n selectAllRows(): void;\n /**\n * Selects rows by id, as far as `selectable.rows` allows: `\"replace\"` (the\n * default) selects exactly these — only the last of them under\n * `\"single\"` — and `\"toggle\"` flips each one. Fires the row selection\n * callbacks once for the whole call, and none when nothing changed.\n */\n selectRows(rowIds: readonly string[], intent?: \"replace\" | \"toggle\"): void;\n /** Expands every group at once, as the `group.expandAll` command does. */\n expandAllGroups(): void;\n /** Collapses every group currently shown at once — see `collapseAllGroups` in `@gridkitjs/core` for what \"currently shown\" means for a group already nested under a collapsed one. */\n collapseAllGroups(): void;\n /** Moves to the given page, clamped into range. */\n goToPage(pageIndex: number): void;\n /** Moves to the next page. A no-op on the last page. */\n nextPage(): void;\n /** Moves to the previous page. A no-op on the first page. */\n previousPage(): void;\n /** Changes the page size, resetting to the first page. */\n setPageSize(pageSize: number): void;\n /**\n * Shows the columns with the given ids, each in the place it held when\n * hidden. Reports one `onColumnVisibilityChange` for the whole call, and\n * none if every column was already showing.\n */\n showColumns(columnIds: readonly string[]): void;\n /**\n * Hides the columns with the given ids. A hidden column still sorts,\n * filters and groups, and keeps its place in the column order.\n */\n hideColumns(columnIds: readonly string[]): void;\n /**\n * Replaces the filter, the way a filter UI would, and sends an uncontrolled\n * grid back to its first page. Reports one `onFilterChange`, and none when\n * `filter` is equal to the current one. With a controlled `filter` prop it\n * only asks, as any change does.\n */\n setFilter(filter: FilterState<Row>): void;\n /**\n * Replaces the sort. Reports one `onColumnSortChange`, naming the first\n * column whose place or direction changed, and none for an equal sort —\n * the rule every setter below follows for its own slice and callback.\n */\n setColumnSort(sort: ColumnSortState): void;\n /** Replaces the group-by stack. Reports through `onGroupByChange`. */\n setGroupBy(groupBy: GroupByState): void;\n /** Replaces the collapsed groups. Reports through `onGroupExpansionChange` with `groupId: null`. */\n setGroupExpansion(expansion: GroupExpansionState): void;\n /** Replaces the page and page size as given. Reports through `onPaginationChange`. */\n setPagination(pagination: PaginationState): void;\n /** Replaces the column widths. Reports through `onColumnResize`, as the `\"end\"` of a resize. */\n setColumnSizing(sizing: ColumnSizingState): void;\n /** Replaces the column order. Reports through `onColumnOrderChange`. */\n setColumnOrder(order: ColumnOrderState): void;\n /** Replaces the column visibility state. Reports through `onColumnVisibilityChange`. */\n setColumnVisibility(visibility: ColumnVisibilityState): void;\n /** Replaces the selected row ids as given, whatever `selectable` allows. Fires the row selection callbacks. */\n setRowSelection(selection: SelectionState): void;\n /** Replaces the selected column ids as given. Fires the column selection callbacks. */\n setColumnSelection(selection: SelectionState): void;\n /** Replaces the selected cell as given, `null` for none. Fires the cell selection callbacks. */\n setCellSelection(selection: CellSelectionState): void;\n /**\n * Sizes a shown column to fit its content, as double-clicking its resize\n * handle does, reporting through `onColumnResize`. A hidden column, or one\n * with no rows to measure, is left as it is.\n */\n autoFitColumn(columnId: string): void;\n /**\n * `autoFitColumn` for each of the given columns, or for every column shown\n * when given none.\n */\n autoFitColumns(columnIds?: readonly string[]): void;\n /**\n * Opens the context menu `target` has, as a right-click there would —\n * selecting it and focusing its cell first — beside `anchor`, a point in\n * viewport coordinates or an element, or else below its cell. Says whether\n * it opened: not for a target not on screen, nor where `contextMenu`\n * gives no menu.\n */\n openContextMenu(\n target: GridContextMenuTarget,\n anchor?: { readonly x: number; readonly y: number } | Element,\n ): boolean;\n /** Closes the context menu, if one is open. */\n closeContextMenu(): void;\n /**\n * Runs a command by id — a built-in or one of `commands` — on `target`,\n * `{ area: \"grid\" }` when left out, when it is visible and enabled there.\n * Reports it through `onCommand` with `source: \"api\"`, and says whether it\n * ran.\n */\n runCommand(commandId: string, target?: GridCommandTarget): boolean;\n /** Scrolls the row with the given id into view, if it is currently shown. */\n scrollToRow(rowId: string, options?: ScrollIntoViewOptions): void;\n /** Scrolls the column with the given id into view. */\n scrollToColumn(columnId: string, options?: ScrollIntoViewOptions): void;\n\n /**\n * Registers `listener` to be called after any render in which the grid's\n * internal state may have changed — every getter above may return a\n * different value once `listener` fires, not just one. Returns an\n * unsubscribe function. The primitive the `use*State` hooks under\n * `packages/react/src/DataGrid/hooks/` build on; most consumers should\n * reach for one of those instead of calling `subscribe` directly.\n */\n subscribe(listener: () => void): () => void;\n}\n\n/**\n * Defined in `@gridkitjs/core` with the rest of `GridOptions`, and exported\n * from here too so a React consumer needs one import.\n */\nexport type { Borders, GroupByBarVisibility, HoverableConfig, ResizeMode };\n\n/**\n * A stable empty fallback for an omitted `aggregates` prop, for the parts of\n * the grid that draw aggregate cells — a fresh `[]` every render would hand\n * them a new array each time.\n */\nconst NO_AGGREGATES: AggregateState<never> = [];\n\n/**\n * `DataGridApi.getPagination`, read off `controller` at call time: the page\n * shown — clamped, unlike the stored index — and the page size. The same\n * object while both stay the same, since a `useSyncExternalStore` snapshot\n * built fresh on every read makes React warn and re-render forever.\n */\nfunction paginationReader<Row>(\n controller: DataGridController<Row>,\n): () => PaginationState {\n let last: PaginationState | undefined;\n return () => {\n const { pageIndex } = controller.getView();\n const { pageSize } = controller.getState().pagination;\n if (last?.pageIndex !== pageIndex || last.pageSize !== pageSize) {\n last = { pageIndex, pageSize };\n }\n return last;\n };\n}\n\n/**\n * Everything a `pager.template` render prop needs to rebuild the built-in\n * pager's UI itself. Passed fresh on every render where pagination-relevant\n * state changed, so it's current by construction — unlike `DataGridApi`'s\n * imperative methods and snapshot getters, which carry no \"something\n * changed, re-render\" signal of their own.\n */\nexport interface PagerTemplateContext {\n /** Same shape as `DataGridApi.getPagination()` — 0-based `pageIndex`. */\n pagination: PaginationState;\n /** `pagination.pageIndex + 1`, clamped — the display-ready page number. */\n currentPage: number;\n pageCount: number;\n /** Passthrough of `pager.sizeOptions`, undefined when not given. */\n pageSizeOptions: readonly number[] | undefined;\n /** 0-based, same as `DataGridApi.goToPage` — not `currentPage`'s numbering. */\n goToPage: (pageIndex: number) => void;\n nextPage: () => void;\n previousPage: () => void;\n setPageSize: (pageSize: number) => void;\n}\n\n/** Presentation options for the grid's built-in pager. */\nexport interface PagerConfig {\n /** Page sizes offered by the built-in pager's page-size control. */\n sizeOptions?: readonly number[] | undefined;\n /** Defaults to `\"compact\"` — today's Prev/status/Next. */\n variant?: \"compact\" | \"numbered\" | undefined;\n /** Numbered variant only. How many pages to always show at each end. Defaults to 1. */\n boundaryCount?: number | undefined;\n /** Numbered variant only. How many pages to show on each side of the current page. Defaults to 1. */\n siblingCount?: number | undefined;\n /** Replaces the built-in pager entirely when given. `variant` is ignored. */\n template?: ((context: PagerTemplateContext) => ReactNode) | undefined;\n}\n\n/**\n * Loads more rows as the user scrolls near the bottom, in place of paging.\n * Appends only — there is no equivalent of `paginated`'s reset-to-page-0 for\n * a result set that shrinks out from under the current position.\n */\nexport interface InfiniteScrollConfig {\n /** Whether a further `onLoadMore` could still return more rows. `false` removes the sentinel entirely, so no further scrolling can trigger a load. */\n readonly hasMore: boolean;\n /**\n * Called at most once per genuine threshold-crossing: fires when the\n * sentinel comes within `rootMargin` of the body's viewport, and not again\n * until `isLoadingMore` has gone back to `false`.\n */\n readonly onLoadMore: () => void;\n /** Whether a load triggered by `onLoadMore` is still in flight. Suppresses further calls to it until this goes back to `false`. */\n readonly isLoadingMore?: boolean | undefined;\n /**\n * How far from the bottom of the scrollable body `onLoadMore` fires, ahead\n * of the sentinel actually scrolling into view, as CSS margins — an\n * intersection observer's `rootMargin`. Defaults to `\"200px\"`.\n */\n readonly rootMargin?: string | undefined;\n /** Replaces the built-in \"Loading more…\" row (`messages.loadingMore`). */\n readonly loadingTemplate?: (() => ReactNode) | undefined;\n}\n\n/**\n * The props that name a React type, and so have no place in the\n * framework-free `GridOptions`: columns whose templates return `ReactNode`,\n * the pager and infinite-scroll configs whose templates do too, and the\n * toolbar's custom entries.\n */\nexport interface ReactRenderSlots<Row> {\n columns?: readonly ColumnDefinition<Row>[] | undefined;\n /** Presentation options for the built-in pager. */\n pager?: PagerConfig | undefined;\n /**\n * Loads more rows as the user scrolls near the bottom, instead of paging.\n * Mutually exclusive with `paginated` — setting both logs a dev-time\n * `console.error` and only `paginated` takes effect. Recommended (not\n * required) alongside `virtualized` for a dataset that grows without\n * bound, so the mounted row count never grows with it either.\n */\n infiniteScroll?: InfiniteScrollConfig | undefined;\n /** Draws the toolbar's custom entries — `{ type: \"custom\", id }` — by id. */\n renderToolbarItem?: ((id: string) => ReactNode) | undefined;\n}\n\n/**\n * Every grid setting in `@gridkitjs/core`'s `GridOptions`, plus what only\n * React can express: render slots, selection callbacks carrying React-bound\n * columns, and the `ref`.\n */\nexport interface DataGridProps<Row>\n extends GridOptions<Row>, ReactRenderSlots<Row>, SelectionCallbacks<Row> {\n /** Imperative handle for reading live grid state and triggering actions. */\n ref?: Ref<DataGridApi<Row>> | undefined;\n}\n\n/**\n * `DataGridApi.getSelectedRows`, read off `controller` at call time: the\n * selected ids resolved against every filtered row. Recomputed only when the\n * rows or the selection change, so repeated reads are cheap and return the\n * same array.\n */\nfunction selectedRowsReader<Row>(\n controller: DataGridController<Row>,\n): () => readonly ResolvedRow<Row>[] {\n let last:\n | {\n readonly rows: readonly ResolvedRow<Row>[];\n readonly selection: SelectionState;\n readonly selected: readonly ResolvedRow<Row>[];\n }\n | undefined;\n return () => {\n const { rows } = controller.getView();\n const selection = controller.getState().rowSelection;\n if (last?.rows !== rows || last.selection !== selection) {\n const rowsById = new Map(rows.map((entry) => [entry.rowId, entry]));\n last = { rows, selection, selected: resolveRows(rowsById, selection) };\n }\n return last.selected;\n };\n}\n\nexport function DataGrid<Row>(props: DataGridProps<Row>) {\n const {\n borders,\n hoverable,\n selectable,\n resizeMode = \"fit\",\n columnSizeDefaults,\n sortableColumns = false,\n groupableColumns = false,\n groupToggleIconColumns = true,\n groupByBarVisibility = \"auto\",\n paginated = false,\n pager,\n infiniteScroll,\n aggregates = NO_AGGREGATES as AggregateState<Row>,\n groupAggregateDisplay = \"inline\",\n height,\n virtualized = false,\n overscan = 4,\n estimatedRowHeight = 40,\n label,\n labelledBy,\n locale,\n getRowProps,\n onRowClick,\n onRowDoubleClick,\n messages: messageOverrides,\n ref,\n } = props;\n const hoverRows = hoverable?.rows ?? true;\n const hoverColumns = hoverable?.columns ?? true;\n const hoverCells = hoverable?.cells ?? true;\n\n const viewportRef = useRef<HTMLDivElement>(null);\n const headerTableRef = useRef<HTMLTableElement>(null);\n const bodyTableRef = useRef<HTMLTableElement>(null);\n const bodyScrollRef = useRef<HTMLDivElement>(null);\n const sentinelRef = useRef<HTMLTableRowElement>(null);\n const viewportWidth = useElementWidth(viewportRef, resizeMode === \"fit\");\n const subscribersRef = useRef(new Set<() => void>());\n /** The grid element's id, for the toolbar's `aria-controls`. */\n const gridId = useId();\n /** Reports a change no visual cue can carry to a screen reader. */\n const announce = useLiveAnnouncer(viewportRef);\n /** Every string the grid shows or announces, `messages` over the English defaults. */\n const messages = useMemo(\n () => resolveMessages(messageOverrides, locale),\n [messageOverrides, locale],\n );\n\n /**\n * Every slice of grid state, and everything the grid draws, comes from\n * here. The change callbacks go in wrapped, so each change is announced\n * where the controller reports it — see `announcedCallbacks`.\n */\n const { controller, state, view } = useGridController<Row>({\n ...props,\n viewportWidth,\n ...announcedCallbacks({\n callbacks: props,\n announce,\n messages,\n columnName,\n columnOf,\n }),\n });\n\n /**\n * `getPagination()`'s value: the page shown — clamped, unlike the stored\n * index — and the page size, kept as one object while both stay the same.\n * Read live off the controller rather than this render, so a read straight\n * after an action sees it.\n */\n const [readPagination] = useState(() => paginationReader(controller));\n const [readSelectedRows] = useState(() => selectedRowsReader(controller));\n\n /**\n * `enabled` is `virtualized` alone, independent of `height`: an `auto`\n * height body has no `overflow`, so its measured `clientHeight` covers\n * the whole content and the computed range naturally comes out as\n * everything anyway — the dev-time warning below is what tells a consumer\n * that combination does nothing useful, not a behavioral gate here.\n */\n const virtualizer = useRowVirtualizer({\n enabled: virtualized,\n rows: view.pageRows,\n bodyScrollRef,\n estimatedRowHeight,\n overscan,\n });\n\n useEffect(() => {\n if (virtualized && height === undefined) {\n console.error(\n \"DataGrid: `virtualized` has no effect without `height` — a body with no bounded height has no viewport to window rows against.\",\n );\n }\n }, [virtualized, height]);\n\n const hasInfiniteScroll = infiniteScroll !== undefined;\n useEffect(() => {\n if (paginated && hasInfiniteScroll) {\n console.error(\n \"DataGrid: `paginated` and `infiniteScroll` are mutually exclusive — only `paginated` takes effect while both are set.\",\n );\n }\n }, [paginated, hasInfiniteScroll]);\n\n useInfiniteScroll({\n rootRef: bodyScrollRef,\n sentinelRef,\n config: infiniteScroll,\n });\n\n /** A column's definition by id, hidden ones included. */\n function columnOf(columnId: string): ColumnDefinition<Row> | undefined {\n return view.dataColumns.find((candidate) => candidate.id === columnId)\n ?.column;\n }\n\n /** What a column is called in an announcement — see `resolveColumnHeaderText`. */\n function columnName(columnId: string): string {\n const column = columnOf(columnId);\n return column === undefined ? columnId : resolveColumnHeaderText(column);\n }\n\n const resize = useColumnResize<Row>({\n // `@gridkitjs/dom`'s `measureColumnContent` only ever matches\n // `td[data-gridkit-column]` (never `th`), so the header table has nothing\n // for it to find — the body table alone was already the effective scope\n // before this split.\n tableRef: bodyTableRef,\n controller,\n columnSizeDefaults,\n });\n const nav = useGridNavigation({\n headerTableRef,\n bodyTableRef,\n // `null` when virtualization is off, in which case behavior is\n // byte-for-byte unchanged from before this feature existed.\n virtualRange: virtualized ? virtualizer : null,\n // Group headers are addressable rows too — the whole point of the flat\n // `DisplayRow[]` shape is that they share one position space with data\n // rows, so navigation counts them the same way. Page-relative\n // (`view.pageRows`, not `view.displayRows`): arrow keys operate on what's\n // actually in the DOM, which is the current page — a different \"page\"\n // concept than `useGridNavigation`'s own Page Up/Down viewport scrolling.\n rowCount: view.pageRows.length,\n columnCount: view.columns.length,\n // A group's own summary row (`groupAggregateDisplay: \"row\"`) occupies a\n // real slot in `rowCount` above — its DOM position has to line up with\n // everything else — but is presentational, never a tab stop: arrow-key\n // vertical movement steps over it rather than landing there.\n isSkippableRow: (rowIndex) => {\n const entry = view.pageRows[rowIndex];\n return (\n entry !== undefined && \"kind\" in entry && entry.kind === \"group-summary\"\n );\n },\n });\n\n const panels = useGridPanels({ rootRef: viewportRef, headerTableRef, nav });\n const commands = useGridCommands({\n controller,\n commands: props.commands,\n onCommand: props.onCommand,\n messages,\n announce,\n resize,\n openPanel: panels.open,\n });\n const handleCopyKey = useGridCopy({ controller, commands, nav });\n\n /**\n * Every id in display order, hidden ones included — the list a column\n * move is made among, so a hidden column keeps its slot through a move\n * made around it.\n */\n const orderedIds = useMemo(\n () => view.dataColumns.map((entry) => entry.id),\n [view.dataColumns],\n );\n\n /**\n * The ids of the columns on screen, which a drag or a keyboard move is\n * resolved against: a move one place left has to pass the next visible\n * column, not stop in front of a hidden one and appear to do nothing.\n */\n const displayedIds = useMemo(\n () => view.columns.map((entry) => entry.id),\n [view.columns],\n );\n\n /** Every column's definition by id, hidden ones included, for a group header naming a hidden column. */\n const definitions = useMemo(\n () => new Map(view.dataColumns.map((entry) => [entry.id, entry.column])),\n [view.dataColumns],\n );\n\n /** Column ids whose header may be dragged into the group-by bar at all. */\n const groupByDraggableIds = useMemo(\n () =>\n new Set(\n view.columns\n .filter((entry) => entry.groupByDraggable)\n .map((entry) => entry.id),\n ),\n [view.columns],\n );\n\n /**\n * The one place a drop is applied — the two-armed switch on `target.kind`\n * the group-by bar's own second drop zone was always going to need.\n */\n function handleDrop(target: ColumnDropTarget, movedId: string): void {\n if (target.kind === \"group-by\") {\n // Already announced: `moveGroupBy` reports through the same\n // `onGroupByChange` pipeline the header toggle and the bar's own chip\n // drag do, so this needs no announcement or focus-follow of its own —\n // unlike a column-order drop, the moved thing leaves the grid's single\n // tab-stop system entirely for the bar's own independently-focusable\n // chips, which have no shared index to update.\n controller.moveGroupBy(movedId, target.beforeColumnId);\n return;\n }\n\n // The order the controller will arrive at, worked out here as well for\n // where the column lands on screen. `moveColumnBefore` hands back the\n // same reference for a move that changes nothing, so a drop in place\n // neither renders nor reports.\n const next = moveColumnBefore(orderedIds, movedId, target.beforeId);\n if (next === orderedIds) {\n return;\n }\n controller.moveColumn(movedId, target.beforeId);\n // Counted among the columns on screen, which is what the user can see\n // and what the tab stop indexes.\n const shown = next.filter((id) => displayedIds.includes(id));\n const position = shown.indexOf(movedId);\n announce(\n messages.columnMoved(columnName(movedId), position + 1, shown.length),\n );\n /**\n * The tab stop travels with the column. React reorders the headers by key,\n * so the browser's focus stays on the moved one by itself — without this\n * the stop would be left on whichever column took its index, and the next\n * arrow key would appear to do nothing.\n */\n nav.focusCell(HEADER_ROW, position);\n }\n\n const drag = useColumnDrag<Row>({\n order: displayedIds,\n groupBy: state.groupBy,\n groupByDraggableIds,\n onDrop: handleDrop,\n });\n\n /** Whether the header drag currently open (if any) is for a column already in the group-by stack — reordering it is the chip's job, so dragging it back in is never a valid target. */\n const draggedColumnAlreadyGrouped =\n drag.draggedColumnId !== null &&\n state.groupBy.some((entry) => entry.columnId === drag.draggedColumnId);\n\n /**\n * Whether the drag currently open (if any) could land on the group-by bar\n * — the signal `groupByBarVisibility=\"auto\"` needs to show the bar as a\n * drop target even while `groupBy` is still empty. Depends only on\n * `draggedColumnId` (set once the drag opens), the static\n * `groupByDraggableIds`, and whether that column is already grouped, never\n * the pointer's current position, so the bar mounts for the drag's whole\n * duration rather than flickering in only while directly hovering it.\n */\n const dragEligibleForGroupBy =\n drag.draggedColumnId !== null &&\n groupByDraggableIds.has(drag.draggedColumnId) &&\n !draggedColumnAlreadyGrouped;\n\n const showGroupByBar =\n groupByBarVisibility === \"always\" ||\n (groupByBarVisibility === \"auto\" &&\n (state.groupBy.length > 0 || dragEligibleForGroupBy));\n\n const headerGroupByDropTarget =\n drag.dropTarget?.kind === \"group-by\" ? drag.dropTarget : null;\n\n /** What the built-in pager draws, and what a `pager.template` is handed. */\n const pagerContext: PagerTemplateContext = {\n pagination: state.pagination,\n currentPage: Math.min(state.pagination.pageIndex + 1, view.pageCount),\n pageCount: view.pageCount,\n pageSizeOptions: pager?.sizeOptions,\n goToPage: controller.goToPage,\n nextPage: controller.nextPage,\n previousPage: controller.previousPage,\n setPageSize: controller.setPageSize,\n };\n\n const selection = useGridSelection<Row>({ controller, state, selectable });\n\n const multiselectable =\n selection.rowMode === \"multiple\" || selection.columnMode === \"multiple\";\n\n const contextMenu = useContextMenu({\n rootRef: viewportRef,\n headerTableRef,\n bodyTableRef,\n bodyScrollRef,\n contextMenu: props.contextMenu,\n onContextMenuOpenChange: props.onContextMenuOpenChange,\n controller,\n commands,\n nav,\n selection,\n messages,\n columnName,\n });\n\n /**\n * Tells `subscribe`'s listeners once a render has drawn a change: to the\n * controller's state or view — whether an action or a prop made it — or to\n * the focused cell, which `@gridkitjs/dom`'s grid focus keeps apart from\n * the controller.\n *\n * Gated on those values, not run after every render: `useSyncExternalStore`\n * re-renders a subscriber that is notified, and a subscriber that renders\n * this grid as a plain (non-memoized) child would re-render it in turn and\n * be notified again, forever, though nothing ever changed. The state and\n * view objects keep their identity until something in them changes, which\n * is what breaks that cycle.\n */\n useEffect(() => {\n for (const listener of subscribersRef.current) {\n listener();\n }\n }, [view, state, nav.focus]);\n\n /**\n * No deps array: `nav`, `resize` and `virtualizer` are freshly\n * constructed every render (none of those hooks memoize their returned\n * API), so the handle has to be rebuilt every render too or its closures\n * would go stale. Grid state is read off the controller at call time.\n */\n useImperativeHandle(ref, () => ({\n get element() {\n return viewportRef.current;\n },\n get table() {\n return bodyTableRef.current;\n },\n getRows: () => controller.getView().rows,\n // Every group header's own `aggregates` field is populated here — the\n // whole reason `getDisplayRows()` is where a consumer reads a specific\n // group's computed results from.\n getDisplayRows: () => controller.getView().displayRows,\n getPageRows: () => controller.getView().pageRows,\n getColumns: () => controller.getView().columns,\n getDataColumns: () => controller.getView().dataColumns,\n getColumnSizing: () => controller.getState().columnSizing,\n getColumnOrder: () => controller.getState().columnOrder,\n getColumnVisibility: () => controller.getState().columnVisibility,\n getColumnSort: () => controller.getState().columnSort,\n getFilter: () => controller.getState().filter,\n getGroupBy: () => controller.getState().groupBy,\n getGroupExpansion: () => controller.getState().groupExpansion,\n getPagination: readPagination,\n getPageCount: () => controller.getView().pageCount,\n getAggregates: () => controller.getView().grandTotal,\n getRowSelection: () => controller.getState().rowSelection,\n getSelectedRows: readSelectedRows,\n getColumnSelection: () => controller.getState().columnSelection,\n getCellSelection: () => controller.getState().cellSelection,\n getFocusedCell: () => nav.focus,\n getState: controller.getState,\n restoreState: controller.restoreState,\n focusCell: nav.focusCell,\n clearSelection: controller.clearSelection,\n selectAllRows: controller.selectAllRows,\n selectRows: controller.selectRows,\n expandAllGroups: controller.expandAllGroups,\n collapseAllGroups: controller.collapseAllGroups,\n goToPage: controller.goToPage,\n nextPage: controller.nextPage,\n previousPage: controller.previousPage,\n setPageSize: controller.setPageSize,\n showColumns: controller.showColumns,\n hideColumns: controller.hideColumns,\n setFilter: controller.setFilter,\n setColumnSort: controller.setColumnSort,\n setGroupBy: controller.setGroupBy,\n setGroupExpansion: controller.setGroupExpansion,\n setPagination: controller.setPagination,\n setColumnSizing: controller.setColumnSizing,\n setColumnOrder: controller.setColumnOrder,\n setColumnVisibility: controller.setColumnVisibility,\n setRowSelection: controller.setRowSelection,\n setColumnSelection: controller.setColumnSelection,\n setCellSelection: controller.setCellSelection,\n autoFitColumn: (columnId) => {\n commands.host.autoFitColumns([columnId]);\n },\n autoFitColumns: (columnIds) => {\n commands.host.autoFitColumns(\n columnIds ?? controller.getView().columns.map((entry) => entry.id),\n );\n },\n openContextMenu: contextMenu.open,\n closeContextMenu: contextMenu.close,\n ...exportApi(commands),\n ...printApi(commands),\n ...panelApi(panels, controller),\n runCommand: (commandId, target = { area: \"grid\" }) =>\n commands.run(commandId, target, \"api\"),\n scrollToRow: (rowId, options) => {\n // `pageRows`, not `displayRows`: a data row's DOM position is its place\n // in the currently rendered page — with grouping active, that's its\n // place in the grouped, flattened output; with pagination also active,\n // that's the page's own slice of it. A row on a different page isn't\n // in the DOM at all, so there is nothing to scroll to.\n const index = controller\n .getView()\n .pageRows.findIndex(\n (entry) => !(\"kind\" in entry) && entry.rowId === rowId,\n );\n if (index === -1) return;\n // Under virtualization the target row may not be mounted at all —\n // `virtualizer.scrollToIndex` estimates, scrolls, and self-corrects\n // once it mounts and is measured, rather than reaching for a DOM row\n // that may not exist.\n if (virtualized) {\n virtualizer.scrollToIndex(index, options);\n return;\n }\n bodyTableRef.current?.tBodies[0]?.rows[index]?.scrollIntoView(options);\n },\n scrollToColumn: (columnId, options) => {\n // The whole viewport, not just one table: a column's cells with\n // `data-gridkit-column` now live across three sibling tables\n // (header/body/footer) rather than one, and the header's `<th>` is\n // the one guaranteed to exist even when the body has no rows.\n const cells = viewportRef.current?.querySelectorAll(\n \"[data-gridkit-column]\",\n );\n const cell = cells\n ? Array.from(cells).find(\n (entry) => entry.getAttribute(\"data-gridkit-column\") === columnId,\n )\n : undefined;\n cell?.scrollIntoView(options);\n },\n subscribe: (listener) => {\n subscribersRef.current.add(listener);\n return () => {\n subscribersRef.current.delete(listener);\n };\n },\n }));\n\n // Shared by all three tables below, so borders/hover/selectable styling —\n // every `.gridkit-data-grid.<modifier>` rule in `theme-tailwind` — applies\n // identically to each rather than only to whichever one happened to carry\n // it. Each rule's own descendant selector (e.g. `.borders-horizontal\n // .grid-cell`) still needs the modifier class on that cell's own table\n // ancestor, which is exactly what splitting into one table per section\n // would otherwise lose.\n const gridTableClassName = classNames(\n \"gridkit-data-grid\",\n borders ? `borders-${borders}` : \"\",\n // Hover is on by default and selection off, so one set of classes\n // turns styling off and the other turns it on. The polarity differs\n // because the defaults do.\n hoverRows ? \"\" : \"no-hover-rows\",\n hoverColumns ? \"\" : \"no-hover-columns\",\n hoverCells ? \"\" : \"no-hover-cells\",\n selection.rowMode === false ? \"\" : \"selectable-rows\",\n selection.columnMode === false ? \"\" : \"selectable-columns\",\n selection.cellMode === false ? \"\" : \"selectable-cells\",\n );\n\n return (\n <div className=\"gridkit-data-grid-viewport\" ref={viewportRef}>\n <GridToolbar<Row>\n toolbar={props.toolbar}\n renderItem={props.renderToolbarItem}\n gridId={gridId}\n controller={controller}\n commands={commands}\n messages={messages}\n announce={announce}\n />\n {showGroupByBar && (\n <GroupByBar<Row>\n columns={view.columns}\n definitions={definitions}\n groupBy={state.groupBy}\n controller={controller}\n columnName={columnName}\n headerDragEligible={dragEligibleForGroupBy}\n headerDragBlocked={draggedColumnAlreadyGrouped}\n headerDropTarget={headerGroupByDropTarget}\n messages={messages}\n />\n )}\n <div\n id={gridId}\n className=\"gridkit-data-grid-tables\"\n /*\n * `role=\"grid\"` sits on this wrapper rather than any one of the\n * three `<table>`s below: the WAI-ARIA grid pattern needs a single\n * ancestor holding every row — header, body, and (when aggregates\n * are active) footer alike — and no one table is an ancestor of the\n * other two's rows now that they're split. It obliges the single\n * tab stop `useGridNavigation` keeps.\n *\n * So each `<table>` is `role=\"presentation\"`, and its sections, rows\n * and cells carry `rowgroup`, `row`, `columnheader` and `gridcell`\n * explicitly: a native table inside a grid would own those rows\n * itself, with its own implicit roles, leaving the grid none, and\n * would make a group row's `aria-level`/`aria-expanded` invalid on\n * what is then a plain table row. The tables stay for layout alone.\n *\n * Switches to `\"treegrid\"` — the WAI-ARIA pattern for expandable,\n * collapsible rows — whenever `groupBy` is non-empty, rather than\n * committing to it unconditionally. The alternative (always\n * `treegrid`) would change what every existing, ungrouped consumer\n * announces to assistive technology the moment this feature shipped;\n * that regression is certain, while the edge case this trades away —\n * the role flipping mid-session if a consumer removes its last\n * group-by level — is rare and, per the WAI-ARIA grid pattern, still\n * a valid `role` change to make when the row structure itself\n * changes shape. See the \"Scope note\" this mirrors: grouping stays\n * an internal detail for an ungrouped grid, ARIA role included.\n */\n role={state.groupBy.length > 0 ? \"treegrid\" : \"grid\"}\n // The header is a row too, and counted from one; group headers (and,\n // under `groupAggregateDisplay: \"row\"`, each group's own summary\n // row) count as rows here too, the same way they do in `nav`'s\n // `rowCount`. `view.displayRows`, not `view.pageRows`: the total\n // dataset count, not the current page's, so this stays the true row\n // count per the WAI-ARIA grid pattern even while paged.\n aria-rowcount={view.displayRows.length + 1}\n aria-colcount={view.columns.length}\n {...ariaAttr(multiselectable, \"aria-multiselectable\", true)}\n {...ariaAttr(labelledBy !== undefined, \"aria-labelledby\", labelledBy)}\n {...ariaAttr(\n labelledBy === undefined && label !== undefined,\n \"aria-label\",\n label,\n )}\n onKeyDown={(event) => {\n // The keys that address the grid rather than a cell, caught here\n // where everything bubbles to rather than in each of them.\n if (!isOwnEvent(event)) return;\n handleCopyKey(event);\n if (event.key === \"Escape\") {\n // A gesture in flight has its own use for Escape — cancelling —\n // and gets it first.\n if (drag.draggedColumnId !== null || resize.activeColumnId !== null)\n return;\n selection.clear();\n return;\n }\n if (\n (event.ctrlKey || event.metaKey) &&\n (event.key === \"a\" || event.key === \"A\")\n ) {\n // Left to the browser unless the grid has something to do with it,\n // so a grid without multiple rows does not swallow select-all.\n if (selection.rowMode !== \"multiple\") return;\n event.preventDefault();\n selection.selectAllRows();\n }\n }}\n >\n <table\n ref={headerTableRef}\n role=\"presentation\"\n // Widths are only honoured exactly when the table is as wide as its\n // columns; at `100%` the fixed layout redistributes the difference.\n style={{ width: totalColumnWidth(view.columns) }}\n className={classNames(gridTableClassName, \"gridkit-data-grid-header\")}\n >\n <GridColgroup columns={view.columns} />\n <GridHeader<Row>\n columns={view.columns}\n resize={resize}\n drag={drag}\n controller={controller}\n state={state}\n sortableColumns={sortableColumns}\n groupableColumns={groupableColumns}\n groupToggleIconColumns={groupToggleIconColumns}\n headerMenu={contextMenu.opens(\"header\")}\n panels={panels}\n messages={messages}\n nav={nav}\n selection={selection}\n />\n </table>\n\n <div\n className=\"gridkit-data-grid-body\"\n ref={bodyScrollRef}\n style={\n height === undefined\n ? undefined\n : ({\n \"--gridkit-body-height\":\n typeof height === \"number\" ? `${String(height)}px` : height,\n } as CSSProperties)\n }\n >\n <table\n ref={bodyTableRef}\n role=\"presentation\"\n style={{ width: totalColumnWidth(view.columns) }}\n className={gridTableClassName}\n >\n <GridColgroup columns={view.columns} />\n <GridBody<Row>\n columns={view.columns}\n definitions={definitions}\n rows={view.pageRows}\n activeColumnId={resize.activeColumnId}\n nav={nav}\n selection={selection}\n controller={controller}\n aggregates={aggregates}\n groupAggregateDisplay={groupAggregateDisplay}\n virtualRange={virtualized ? virtualizer : null}\n infiniteScroll={infiniteScroll}\n sentinelRef={sentinelRef}\n locale={locale}\n getRowProps={getRowProps}\n onRowClick={onRowClick}\n onRowDoubleClick={onRowDoubleClick}\n messages={messages}\n cellMenu={contextMenu.opens(\"cell\")}\n groupMenu={contextMenu.opens(\"group\")}\n />\n </table>\n </div>\n\n {aggregates.length > 0 && (\n <table\n role=\"presentation\"\n style={{ width: totalColumnWidth(view.columns) }}\n className={classNames(\n gridTableClassName,\n \"gridkit-data-grid-footer\",\n )}\n >\n <GridColgroup columns={view.columns} />\n <GridFooter<Row>\n columns={view.columns}\n aggregates={aggregates}\n results={view.grandTotal}\n rows={view.rows.map((entry) => entry.row)}\n locale={locale}\n />\n </table>\n )}\n </div>\n <GridContextMenu contextMenu={contextMenu} />\n <GridPanels\n panels={panels}\n controller={controller}\n commands={commands}\n messages={messages}\n />\n {paginated &&\n (pager?.template ? (\n pager.template(pagerContext)\n ) : (\n <GridPager pager={pagerContext} config={pager} messages={messages} />\n ))}\n </div>\n );\n}\n","import type { ResolvedColumn } from \"../DataGrid\";\n\ninterface GridColgroupProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n}\n\n/**\n * One `<colgroup>`, shared verbatim by the header, body, and footer\n * `<table>`s so all three render identical column widths from one source\n * rather than three independent copies of the same `.map()`.\n */\nexport default function GridColgroup<Row>({ columns }: GridColgroupProps<Row>) {\n return (\n <colgroup>\n {columns.map((entry) => (\n <col key={entry.id} style={{ width: entry.width }} />\n ))}\n </colgroup>\n );\n}\n","import { createPortal } from \"react-dom\";\nimport {\n buildKeyShortcuts,\n intentOf,\n isColumnFiltered,\n KEYBOARD_STEP,\n resolveColumnFilterMenu,\n sortDirectionFor,\n sortPriorityFor,\n type GridMessages,\n type GridState,\n} from \"@gridkitjs/core\";\nimport type { ResolvedColumn } from \"../DataGrid\";\nimport { ariaAttr } from \"../ariaAttr\";\nimport { classNames } from \"../classNames\";\nimport {\n ChevronsUpDownIcon,\n ChevronUpIcon,\n FilterIcon,\n GroupIcon,\n} from \"../icons\";\nimport { isOwnEvent } from \"../isOwnEvent\";\nimport type { GridPanelsApi } from \"../panels/useGridPanels\";\nimport type { ColumnDragApi } from \"../useColumnDrag\";\nimport type { ColumnResizeApi } from \"../useColumnResize\";\nimport { HEADER_ROW, type GridNavigationApi } from \"../useGridNavigation\";\nimport {\n keyboardSelectIntent,\n type GridSelectionApi,\n} from \"../useGridSelection\";\nimport type { DataGridController } from \"../useGridController\";\n\ninterface GridHeaderProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n resize: ColumnResizeApi<Row>;\n drag: ColumnDragApi<Row>;\n /** What a header toggle changes — the sort and the group-by stack. */\n controller: DataGridController<Row>;\n /** The state this render draws: the sort, grouping and filter the headers show. */\n state: GridState<Row>;\n sortableColumns: boolean;\n groupableColumns: boolean;\n groupToggleIconColumns: boolean;\n /** Whether a header opens the grid's context menu, which its `aria-keyshortcuts` says. */\n headerMenu: boolean;\n /** Where a header opens its column's filter menu. */\n panels: GridPanelsApi;\n messages: GridMessages;\n nav: GridNavigationApi;\n selection: GridSelectionApi;\n}\n\nexport default function GridHeader<Row>({\n columns,\n resize,\n drag,\n controller,\n state,\n sortableColumns,\n groupableColumns,\n groupToggleIconColumns,\n headerMenu,\n panels,\n messages,\n nav,\n selection,\n}: GridHeaderProps<Row>) {\n const { columnSort, groupBy, filter } = state;\n // Only meaningful for the \"column-order\" branch — a drop headed for the\n // group-by bar instead (`kind: \"group-by\"`) draws no indicator here at\n // all; `GroupByBar` draws its own from the same `drag.dropTarget`.\n const beforeId =\n drag.dropTarget?.kind === \"column-order\"\n ? drag.dropTarget.beforeId\n : undefined;\n const draggedEntry =\n columns.find((entry) => entry.id === drag.draggedColumnId) ?? null;\n\n /**\n * Opens the column's filter menu, or closes it when it is the one open: a\n * press on the header it opened from leaves it open, so pressing its\n * button again is the way back out.\n */\n function toggleFilterMenu(columnId: string): void {\n const { panel } = panels;\n if (\n panel?.kind === \"filter\" &&\n panel.target.area === \"header\" &&\n panel.target.columnId === columnId\n ) {\n panels.close();\n } else {\n panels.open(\"filter\", { area: \"header\", columnId });\n }\n }\n\n return (\n <thead role=\"rowgroup\">\n <tr className=\"grid-header\" role=\"row\" aria-rowindex={1}>\n {columns.map((entry, index) => {\n const { column } = entry;\n const resizing = resize.activeColumnId === entry.id;\n const dragging = drag.draggedColumnId === entry.id;\n\n /**\n * Drawn on the gap's own edge, so the one gap between two columns is\n * marked once. No guard against the dragged column: the hook reports\n * only gaps that would move it.\n */\n const dropBefore = beforeId !== undefined && beforeId === entry.id;\n const dropAfter = beforeId === null && index === columns.length - 1;\n const selected = selection.selectedColumnIds.has(entry.id);\n const sortable = column.sortable ?? sortableColumns;\n const sortDirection = sortDirectionFor(columnSort, entry.id);\n // Only meaningful once two or more columns are stacked.\n const sortPriority = sortPriorityFor(columnSort, entry.id);\n const groupable = column.groupable ?? groupableColumns;\n // Purely a rendering choice — see the prop's own doc comment. Never\n // gates `groupable` itself, `aria-keyshortcuts`, or `Alt+ArrowDown`.\n const showGroupToggleIcon =\n column.groupToggleIcon ?? groupToggleIconColumns;\n const isGrouped = groupBy.some(\n (level) => level.columnId === entry.id,\n );\n const filterable =\n resolveColumnFilterMenu(controller.getOptions(), column) !== null;\n // Shown, and described, only where the header opens the menu that\n // changes it: a grid filtering a column in code alone keeps its\n // headers as they were.\n const filtered = filterable && isColumnFiltered(filter, entry.id);\n\n const shortcuts = buildKeyShortcuts({\n reorderable: entry.reorderable,\n resizable: entry.resizable,\n sortable,\n groupable,\n filterable,\n contextMenu: headerMenu,\n });\n\n return (\n <th\n key={entry.id}\n scope=\"col\"\n // Explicit, like every structural role in the grid: each\n // `<table>` is `role=\"presentation\"`, so the rows and cells\n // belong to the `grid`/`treegrid` wrapper rather than to a\n // native table, and only an explicit role survives that.\n role=\"columnheader\"\n data-gridkit-column={entry.id}\n aria-colindex={index + 1}\n tabIndex={nav.tabIndexFor(HEADER_ROW, index)}\n {...ariaAttr(\n selection.columnMode !== false,\n \"aria-selected\",\n selected,\n )}\n onFocus={() => {\n nav.focusCell(HEADER_ROW, index);\n }}\n onClick={(event) => {\n /*\n * A drag ends in a click on the header it started from, and a\n * resize in one on the handle inside it. Neither is the press\n * that selects a column, so both are shown the door here —\n * the drag by the distance it travelled, the resize by where\n * it began.\n */\n if (drag.justDragged()) {\n return;\n }\n if (\n event.target instanceof Element &&\n (event.target.closest(\".header-resize-handle\") !== null ||\n event.target.closest(\".header-sort-toggle\") !== null ||\n event.target.closest(\".header-group-toggle\") !== null ||\n event.target.closest(\".header-filter-toggle\") !== null)\n ) {\n return;\n }\n selection.selectColumn(entry.id, intentOf(event));\n }}\n onKeyDown={(event) => {\n if (!isOwnEvent(event)) return;\n const horizontal =\n event.key === \"ArrowLeft\" || event.key === \"ArrowRight\";\n const direction = event.key === \"ArrowLeft\" ? -1 : 1;\n\n if (horizontal && event.ctrlKey && entry.reorderable) {\n event.preventDefault();\n drag.moveByKeyboard(entry, direction);\n return;\n }\n if (horizontal && event.altKey && entry.resizable) {\n event.preventDefault();\n resize.nudge(entry, direction * KEYBOARD_STEP);\n return;\n }\n // The keyboard equivalent of double-clicking the resize\n // handle, which auto-fits the column to its content.\n if (event.key === \"Enter\" && event.altKey && entry.resizable) {\n event.preventDefault();\n resize.sizeToContent(entry);\n return;\n }\n if (event.key === \"ArrowUp\" && event.altKey && sortable) {\n event.preventDefault();\n controller.toggleColumnSort(entry.id, {\n stack: event.shiftKey,\n });\n return;\n }\n // Shift sets the filter menu apart from grouping, which\n // holds Alt+ArrowDown — the key Excel opens its filter with.\n if (\n event.key === \"ArrowDown\" &&\n event.altKey &&\n event.shiftKey &&\n filterable\n ) {\n event.preventDefault();\n toggleFilterMenu(entry.id);\n return;\n }\n if (\n event.key === \"ArrowDown\" &&\n event.altKey &&\n !event.shiftKey &&\n groupable\n ) {\n event.preventDefault();\n controller.toggleGroupBy(entry.id);\n return;\n }\n // Space builds a selection up and Enter replaces it, as in the\n // body. Taken either way, or Space scrolls the grid away.\n if (event.key === \" \" || event.key === \"Enter\") {\n event.preventDefault();\n selection.selectColumn(\n entry.id,\n intentOf(keyboardSelectIntent(event)),\n );\n return;\n }\n nav.onKeyDown(event);\n }}\n className={classNames(\n \"header-cell\",\n // The grab affordance a header showing either drag\n // destination shares — a column dragged only for grouping\n // (`groupByDraggable` without `reorderable`) grabs the same\n // way one dragged only for reordering does.\n entry.reorderable || entry.groupByDraggable\n ? \"is-reorderable\"\n : \"\",\n selected ? \"is-selected\" : \"\",\n resizing ? \"is-resizing\" : \"\",\n dragging ? \"is-dragging\" : \"\",\n dropBefore ? \"is-drop-before\" : \"\",\n dropAfter ? \"is-drop-after\" : \"\",\n column.wrap?.header ? \"is-wrapped\" : \"\",\n column.headerClassName ?? \"\",\n )}\n {...ariaAttr(shortcuts !== \"\", \"aria-keyshortcuts\", shortcuts)}\n {...ariaAttr(\n filtered,\n \"aria-description\",\n messages.columnFiltered,\n )}\n {...ariaAttr<\"aria-sort\", \"ascending\" | \"descending\">(\n sortable && sortDirection !== null,\n \"aria-sort\",\n sortDirection === \"asc\" ? \"ascending\" : \"descending\",\n )}\n {...((entry.reorderable || entry.groupByDraggable) && {\n onPointerDown: (event) => {\n drag.startDrag(entry, event);\n },\n })}\n >\n {groupable && showGroupToggleIcon && (\n /*\n * Inline, before the label, rather than absolutely\n * positioned like the sort toggle and resize handle: those\n * two already share the header's right edge, and a third\n * overlay there would need its own carve-out. Sitting in\n * normal flow costs nothing but a few pixels of label width.\n * A pointer affordance only, same as the other two — the\n * keyboard equivalent is Alt+ArrowDown on the header itself.\n */\n <span\n className={classNames(\n \"header-group-toggle\",\n isGrouped ? \"is-grouped\" : \"\",\n )}\n aria-hidden=\"true\"\n tabIndex={-1}\n onPointerDown={(event) => {\n // See the sort toggle's own note: otherwise a\n // reorderable header's drag would swallow this click.\n event.stopPropagation();\n }}\n onClick={(event) => {\n event.stopPropagation();\n controller.toggleGroupBy(entry.id);\n }}\n >\n <GroupIcon />\n </span>\n )}\n {entry.label}\n {sortable && (\n /*\n * A pointer affordance only, and hidden from assistive\n * technology like the resize handle: the keyboard equivalent\n * lives on the header itself, under Alt+ArrowUp (plain) /\n * Alt+Shift+ArrowUp (stacking).\n */\n <span\n className={classNames(\n \"header-sort-toggle\",\n sortDirection !== null ? `is-sorted-${sortDirection}` : \"\",\n )}\n aria-hidden=\"true\"\n tabIndex={-1}\n onPointerDown={(event) => {\n /*\n * Otherwise a reorderable header's own `onPointerDown`\n * sees this bubble up and starts a column drag, whose\n * pointer capture then redirects the click that\n * follows to the `th` — the same reason `startResize`\n * stops it for the resize handle.\n */\n event.stopPropagation();\n }}\n onClick={(event) => {\n controller.toggleColumnSort(entry.id, {\n stack: event.shiftKey,\n });\n }}\n >\n {sortDirection === null ? (\n <ChevronsUpDownIcon />\n ) : (\n <ChevronUpIcon />\n )}\n {sortPriority !== null && sortPriority > 1 && (\n <span className=\"header-sort-priority\">{sortPriority}</span>\n )}\n </span>\n )}\n {filterable && (\n /*\n * A pointer affordance only, like the sort toggle: the\n * keyboard opens the menu from the header itself, under\n * Alt+Shift+ArrowDown, and a screen reader hears the\n * filtered state as the header's description.\n */\n <span\n className={classNames(\n \"header-filter-toggle\",\n filtered ? \"is-filtered\" : \"\",\n )}\n aria-hidden=\"true\"\n tabIndex={-1}\n onPointerDown={(event) => {\n // See the sort toggle's own note.\n event.stopPropagation();\n }}\n onClick={() => {\n toggleFilterMenu(entry.id);\n }}\n >\n <FilterIcon />\n </span>\n )}\n {entry.resizable && (\n /*\n * A pointer affordance only, and hidden from assistive\n * technology accordingly: a focusable handle per column would\n * put N tab stops inside a widget that is meant to have one.\n * The keyboard resizes from the header itself, under Alt.\n */\n <span\n className=\"header-resize-handle\"\n aria-hidden=\"true\"\n tabIndex={-1}\n onPointerDown={(event) => {\n resize.startResize(entry, event);\n }}\n onDoubleClick={() => {\n resize.sizeToContent(entry);\n }}\n />\n )}\n </th>\n );\n })}\n </tr>\n {/*\n * Portalled to the body, and not only because a `div` cannot sit in a\n * `tr`: inside the viewport the overflow that makes the grid scroll\n * would clip it.\n */}\n {draggedEntry !== null &&\n drag.ghostTransform !== null &&\n createPortal(\n <div\n className=\"gridkit-data-grid header-cell drag-ghost\"\n style={{\n width: draggedEntry.width,\n transform: drag.ghostTransform,\n }}\n aria-hidden=\"true\"\n >\n {draggedEntry.label}\n </div>,\n document.body,\n )}\n </thead>\n );\n}\n","/**\n * Collapses the `{...(condition && { \"aria-foo\": value })}` idiom for\n * conditionally including a single ARIA attribute in a JSX spread.\n */\nexport function ariaAttr<K extends string, V>(\n condition: boolean,\n key: K,\n value: V,\n): Record<K, V> | Record<string, never> {\n return condition ? ({ [key]: value } as Record<K, V>) : {};\n}\n","export function classNames(\n ...values: (string | false | null | undefined)[]\n): string {\n return values.filter(Boolean).join(\" \");\n}\n","import type { ReactNode } from \"react\";\n\n/** The common attributes behind every icon the grid draws — just the `<path>`s differ. */\nexport function Icon({ children }: { children: ReactNode }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n {children}\n </svg>\n );\n}\n\n/**\n * The two glyphs a sort toggle shows: a neutral hint before a column has a\n * direction, and a single chevron reused for both directions once it does —\n * `theme-tailwind` rotates it 180° for `desc` rather than swapping icons.\n */\nexport function ChevronsUpDownIcon() {\n return (\n <Icon>\n <path d=\"m7 15 5 5 5-5\" />\n <path d=\"m7 9 5-5 5 5\" />\n </Icon>\n );\n}\n\nexport function ChevronUpIcon() {\n return (\n <Icon>\n <path d=\"m18 15-6-6-6 6\" />\n </Icon>\n );\n}\n\n/** Three stacked panes, standing in for \"group by this column\". */\nexport function GroupIcon() {\n return (\n <Icon>\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\" />\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\" />\n <rect x=\"8.5\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\" />\n </Icon>\n );\n}\n\n/** A funnel, standing in for \"filter this column\". */\nexport function FilterIcon() {\n return (\n <Icon>\n <path d=\"M22 3H2l8 9.46V19l4 2v-8.54z\" />\n </Icon>\n );\n}\n\n/** The pager's previous-page chevron; `theme-tailwind` mirrors the pager's chevrons right-to-left. */\nexport function ChevronLeftIcon() {\n return (\n <Icon>\n <path d=\"m15 18-6-6 6-6\" />\n </Icon>\n );\n}\n\nexport function ChevronRightIcon() {\n return (\n <Icon>\n <path d=\"m9 18 6-6-6-6\" />\n </Icon>\n );\n}\n\n/** The pager's first-page double chevron. */\nexport function ChevronsLeftIcon() {\n return (\n <Icon>\n <path d=\"m11 17-5-5 5-5\" />\n <path d=\"m18 17-5-5 5-5\" />\n </Icon>\n );\n}\n\nexport function ChevronsRightIcon() {\n return (\n <Icon>\n <path d=\"m6 17 5-5-5-5\" />\n <path d=\"m13 17 5-5-5-5\" />\n </Icon>\n );\n}\n","/**\n * Whether `event` happened inside the element whose handler is running.\n * React bubbles a portal's events up the component tree rather than the DOM,\n * so a panel rendered into `document.body` from inside the grid still reaches\n * the grid's key handlers — and Escape or Ctrl+A pressed in it is the\n * panel's, not the grid's.\n */\nexport function isOwnEvent(event: {\n readonly currentTarget: Element;\n readonly target: EventTarget;\n}): boolean {\n return (\n event.target instanceof Node && event.currentTarget.contains(event.target)\n );\n}\n","import {\n useEffect,\n useLayoutEffect,\n useState,\n useSyncExternalStore,\n type KeyboardEvent as ReactKeyboardEvent,\n type RefObject,\n} from \"react\";\nimport { HEADER_ROW, type GridFocus } from \"@gridkitjs/core\";\nimport {\n createGridFocus,\n findBodyRow,\n measurePageSize,\n type FocusVirtualRange,\n type GridFocusOptions,\n type GridFocusRows,\n} from \"@gridkitjs/dom\";\n\nexport { HEADER_ROW, type GridFocus };\n\ninterface UseGridNavigationOptions {\n headerTableRef: RefObject<HTMLTableElement | null>;\n bodyTableRef: RefObject<HTMLTableElement | null>;\n rowCount: number;\n columnCount: number;\n /**\n * Rows the vertical navigation keys step over rather than land a tab stop\n * on — a group's own summary row (`groupAggregateDisplay: \"row\"`), which\n * still occupies a real row slot for `rowCount` purposes but is\n * presentational, not a stop of its own. Left unset (skips nothing) for a\n * grid with no such rows.\n */\n isSkippableRow?: ((rowIndex: number) => boolean) | undefined;\n /**\n * The window `useRowVirtualizer` drew, present only when `virtualized` is\n * on, in which case behavior is otherwise unchanged. A focus move can\n * target a row index that isn't currently mounted — `ArrowDown` repeated\n * past the mounted window's end, or `End`/`Ctrl+End` jumping straight to\n * the last row.\n */\n virtualRange?: FocusVirtualRange | null | undefined;\n}\n\nexport interface GridNavigationApi {\n focus: GridFocus;\n /**\n * `0` for the focused cell and `-1` for every other. A grid is one tab stop:\n * tabbing reaches it, and the arrow keys move within it.\n */\n tabIndexFor: (rowIndex: number, columnIndex: number) => 0 | -1;\n /** Moves the tab stop, and the browser's focus with it. */\n focusCell: (rowIndex: number, columnIndex: number) => void;\n /**\n * `focusCell` for a cell on screen, whose browser focus moves now rather\n * than once the move is drawn — for something about to take focus from\n * it, such as a menu opened on it, which the drawing would pull focus back\n * out of. It renders nothing synchronously, so it is safe in an effect.\n */\n focusCellNow: (rowIndex: number, columnIndex: number) => void;\n /**\n * Moves the browser's focus to the cell holding the tab stop, as drawn now\n * — for when the element focus was to go back to has gone, as a header\n * does when a menu opened on it hides its column.\n */\n focusTabStop: () => void;\n /** Handles the navigation keys, leaving every other key to bubble. */\n onKeyDown: (event: ReactKeyboardEvent<HTMLElement>) => void;\n}\n\n/**\n * `0` for the column holding the tab stop and `-1` for every other.\n * Standalone rather than reached only through the hook's own `tabIndexFor`,\n * because `GridRow` is `memo()`-wrapped and cannot take the whole `nav`\n * object as a prop without defeating that boundary. Takes the row's own\n * already-narrowed `focusedColumnIndex` (`null` when focus sits on a\n * different row) rather than a `rowIndex`/`GridFocus` pair, since that\n * narrowing — done once per row in `GridBody` — is what keeps a focus move\n * from re-rendering every row instead of the two it actually touches.\n */\nexport function tabIndexFor(\n columnIndex: number,\n focusedColumnIndex: number | null,\n): 0 | -1 {\n return columnIndex === focusedColumnIndex ? 0 : -1;\n}\n\n/**\n * The grid's single tab stop, kept by `@gridkitjs/dom`'s `createGridFocus`\n * and drawn from it: created once, handed the current counts and window on\n * every render, and subscribed to, so a move re-renders the grid. The\n * header row comes from the header table's own `.tHead`; a body row through\n * `findBodyRow`, by its `data-gridkit-row-index`.\n */\nexport default function useGridNavigation({\n headerTableRef,\n bodyTableRef,\n rowCount,\n columnCount,\n isSkippableRow,\n virtualRange,\n}: UseGridNavigationOptions): GridNavigationApi {\n const options: GridFocusOptions = {\n rowCount,\n columnCount,\n isSkippableRow,\n virtualRange,\n };\n const [gridFocus] = useState(() => createGridFocus(options));\n gridFocus.setOptions(options);\n // `getFocus` serves the server too: nothing can move focus before the grid\n // hydrates, so both sides draw the same initial tab stop.\n const focus = useSyncExternalStore(\n gridFocus.subscribe,\n gridFocus.getFocus,\n gridFocus.getFocus,\n );\n\n const [rows] = useState<GridFocusRows>(() => ({\n getHeaderRow: () => headerTableRef.current?.tHead?.rows[0] ?? null,\n getBodyRow: (rowIndex) => findBodyRow(bodyTableRef.current, rowIndex),\n }));\n useLayoutEffect(() => gridFocus.attach(rows), [gridFocus, rows]);\n\n // After every commit rather than only when `focus` changes: under\n // virtualization the target row may mount only in a later drawing, once\n // the window has scrolled to it, and this is what retries.\n useEffect(() => {\n gridFocus.focusDrawnCell(focus);\n });\n\n // A new object each render, as the other hooks here return: `tabIndexFor`\n // closes over the focus it draws.\n return {\n focus,\n tabIndexFor: (rowIndex, columnIndex) =>\n tabIndexFor(\n columnIndex,\n rowIndex === focus.rowIndex ? focus.columnIndex : null,\n ),\n focusCell: gridFocus.focusCell,\n focusCellNow: (rowIndex, columnIndex) => {\n gridFocus.focusCell(rowIndex, columnIndex);\n // The cell is drawn already, all but its tab stop, so the move is\n // followed now, and the drawing that redraws the stop has none left.\n gridFocus.focusDrawnCell(gridFocus.getFocus());\n },\n focusTabStop: () => {\n const cells = (\n focus.rowIndex === HEADER_ROW\n ? rows.getHeaderRow()\n : rows.getBodyRow(focus.rowIndex)\n )?.cells;\n // A group header's row has one cell, whatever column the stop is in.\n cells?.[Math.min(focus.columnIndex, cells.length - 1)]?.focus();\n },\n onKeyDown: (event) => {\n if (\n gridFocus.handleKey(\n event.key,\n event,\n measurePageSize(bodyTableRef.current),\n )\n ) {\n event.preventDefault();\n }\n },\n };\n}\n","import { useMemo, type KeyboardEvent as ReactKeyboardEvent } from \"react\";\nimport type {\n CellSelectionMode,\n CellSelectionState,\n GridState,\n SelectableConfig,\n SelectedCellRef,\n SelectIntent,\n SelectionMode,\n} from \"@gridkitjs/core\";\nimport type { DataGridController } from \"./useGridController\";\n\n/**\n * The modifiers a Space or Enter keydown carries, for a caller that means to\n * hand them to `intentOf` as a click's modifiers would be. Space builds a\n * selection up and Enter replaces it, as in the body — so Space is mapped to\n * act like Ctrl, matching Ctrl-click and the plain click they stand in for.\n */\nexport function keyboardSelectIntent(event: ReactKeyboardEvent): {\n ctrlKey: boolean;\n metaKey: boolean;\n shiftKey: boolean;\n} {\n return {\n ctrlKey: event.key === \" \" || event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n };\n}\n\ninterface UseGridSelectionOptions<Row> {\n controller: DataGridController<Row>;\n state: GridState<Row>;\n selectable: SelectableConfig | undefined;\n}\n\nexport interface GridSelectionApi {\n rowMode: SelectionMode;\n columnMode: SelectionMode;\n cellMode: CellSelectionMode;\n /** Whether a plain click on a row toggles it — `selectable.toggleOnClick`. */\n toggleOnClick: boolean;\n /**\n * Lookups for the render pass. The state itself stays an ordered list, which\n * is what makes the most recent selection its last entry.\n */\n selectedRowIds: ReadonlySet<string>;\n selectedColumnIds: ReadonlySet<string>;\n selectedCell: CellSelectionState;\n selectRow: (rowId: string, intent: SelectIntent) => void;\n selectColumn: (columnId: string, intent: SelectIntent) => void;\n selectCell: (cell: SelectedCellRef, intent: SelectIntent) => void;\n selectAllRows: () => void;\n /** Lets go of every selection at once, as Escape does. */\n clear: () => void;\n}\n\n/**\n * The selection as the header and body draw and change it. The selections\n * themselves, the intent each click carries and the callbacks it fires all\n * live in the grid's controller; this hook only adds the lookups a render\n * pass wants and names the actions the components call.\n */\nexport default function useGridSelection<Row>({\n controller,\n state,\n selectable,\n}: UseGridSelectionOptions<Row>): GridSelectionApi {\n const selectedRowIds = useMemo(\n () => new Set(state.rowSelection),\n [state.rowSelection],\n );\n const selectedColumnIds = useMemo(\n () => new Set(state.columnSelection),\n [state.columnSelection],\n );\n\n // A new object each render, as the other hooks here return.\n return {\n rowMode: selectable?.rows ?? false,\n columnMode: selectable?.columns ?? false,\n cellMode: selectable?.cells ?? false,\n toggleOnClick: selectable?.toggleOnClick ?? false,\n selectedRowIds,\n selectedColumnIds,\n selectedCell: state.cellSelection,\n selectRow: controller.selectRow,\n selectColumn: controller.selectColumn,\n selectCell: controller.selectCell,\n selectAllRows: controller.selectAllRows,\n clear: controller.clearSelection,\n };\n}\n","import {\n useMemo,\n useState,\n type MouseEvent as ReactMouseEvent,\n type RefObject,\n} from \"react\";\nimport {\n groupRowId,\n intentOf,\n type AggregateState,\n type DisplayRow,\n type FormatLocale,\n type GridMessages,\n type GridOptions,\n type GroupAggregateDisplay,\n type ResolvedRow,\n type RowPointerEvent,\n} from \"@gridkitjs/core\";\nimport {\n bodyCellFrom,\n bodyRowFrom,\n groupRowFrom,\n type BodyCellTarget,\n} from \"@gridkitjs/dom\";\nimport type {\n ColumnDefinition,\n InfiniteScrollConfig,\n ResolvedColumn,\n} from \"../DataGrid\";\nimport type { GridNavigationApi } from \"../useGridNavigation\";\nimport type { DataGridController } from \"../useGridController\";\nimport type { RowVirtualizerApi } from \"../useRowVirtualizer\";\nimport { isOwnEvent } from \"../isOwnEvent\";\nimport { createRowPropsResolver } from \"../rowProps\";\nimport {\n keyboardSelectIntent,\n type GridSelectionApi,\n} from \"../useGridSelection\";\nimport GridGroupRow from \"./GridGroupRow\";\nimport GridGroupSummaryRow from \"./GridGroupSummaryRow\";\nimport GridRow from \"./GridRow\";\n\ninterface GridBodyProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n /** Every column's definition by id, hidden ones included — a grid may group or aggregate by a column it does not show. */\n definitions: ReadonlyMap<string, ColumnDefinition<Row>>;\n rows: readonly DisplayRow<Row>[];\n /** The column being resized, so its cells outline with its header. */\n activeColumnId: string | null;\n nav: GridNavigationApi;\n selection: GridSelectionApi;\n /** What a group header's click or key press expands or collapses. */\n controller: DataGridController<Row>;\n /** Active aggregates. Empty when none are active. */\n aggregates: AggregateState<Row>;\n /** Where a group's aggregates render — inline in its header, or as its own summary row. */\n groupAggregateDisplay: GroupAggregateDisplay;\n /** Windows `rows` down to the rows near the current scroll position. `null` when `virtualized` is off, in which case every row of `rows` renders exactly as it always has. */\n virtualRange: RowVirtualizerApi | null;\n /** Renders a sentinel row (and, while loading, a loading row) as the last child of `<tbody>` when set. `undefined` renders neither. */\n infiniteScroll: InfiniteScrollConfig | undefined;\n /** Ref the sentinel row attaches to — owned and observed by `DataGrid.tsx`'s `useInfiniteScroll`, not by this component. */\n sentinelRef: RefObject<HTMLTableRowElement | null>;\n /** The grid's `locale`, which every cell and aggregate without a template is formatted for. */\n locale: FormatLocale;\n getRowProps: GridOptions<Row>[\"getRowProps\"];\n onRowClick: GridOptions<Row>[\"onRowClick\"];\n onRowDoubleClick: GridOptions<Row>[\"onRowDoubleClick\"];\n messages: GridMessages;\n /** Whether a data cell, or a group row, opens the grid's context menu — for their `aria-keyshortcuts`. */\n cellMenu: boolean;\n groupMenu: boolean;\n}\n\ninterface GroupAriaMeta {\n posinset: number;\n setsize: number;\n}\n\n/**\n * `aria-posinset`/`aria-setsize` per group header: its 1-based position\n * among, and count of, the group headers sharing its level and immediate\n * parent. Depth-first order (see `groupRows`) keeps siblings contiguous, so\n * one pass tallies each parent's total and a second assigns each header's\n * position within it.\n */\nfunction groupAriaMeta<Row>(\n rows: readonly DisplayRow<Row>[],\n): ReadonlyMap<string, GroupAriaMeta> {\n const totals = new Map<string, number>();\n for (const entry of rows) {\n if (!(\"kind\" in entry) || entry.kind !== \"group\") continue;\n const parentKey = groupRowId(entry.path.slice(0, -1));\n totals.set(parentKey, (totals.get(parentKey) ?? 0) + 1);\n }\n\n const seen = new Map<string, number>();\n const meta = new Map<string, GroupAriaMeta>();\n for (const entry of rows) {\n if (!(\"kind\" in entry) || entry.kind !== \"group\") continue;\n const parentKey = groupRowId(entry.path.slice(0, -1));\n const posinset = (seen.get(parentKey) ?? 0) + 1;\n seen.set(parentKey, posinset);\n meta.set(entry.groupId, {\n posinset,\n setsize: totals.get(parentKey) ?? posinset,\n });\n }\n return meta;\n}\n\n/**\n * Events are delegated to the body rather than bound per cell, which is what\n * lets `GridRow` be memoised: a handler rebuilt each render is a prop that\n * changes each render, and one reaching every row would defeat the boundary\n * entirely.\n */\nexport default function GridBody<Row>({\n columns,\n definitions,\n rows,\n activeColumnId,\n nav,\n selection,\n controller,\n aggregates,\n groupAggregateDisplay,\n virtualRange,\n infiniteScroll,\n sentinelRef,\n locale,\n getRowProps,\n onRowClick,\n onRowDoubleClick,\n messages,\n cellMenu,\n groupMenu,\n}: GridBodyProps<Row>) {\n const { selectedCell, rowMode, cellMode, toggleOnClick } = selection;\n const ariaMeta = useMemo(() => groupAriaMeta(rows), [rows]);\n // The full `rows` array otherwise — `virtualRange` is `null` whenever\n // `virtualized` is off, so this slice, and the spacer rows below, are a\n // no-op that reproduces today's output exactly.\n const visibleRows =\n virtualRange === null\n ? rows\n : rows.slice(virtualRange.startIndex, virtualRange.endIndex + 1);\n const { booleanTrue, booleanFalse, blankGroupValue } = messages;\n // Keyed on the strings rather than `messages`, so the memoised rows hold\n // still under a `messages` object rebuilt on every render.\n const cellMessages = useMemo(\n () => ({ booleanTrue, booleanFalse, blankGroupValue }),\n [booleanTrue, booleanFalse, blankGroupValue],\n );\n const [resolveRowProps] = useState(() => createRowPropsResolver<Row>());\n const rowPropsOf = resolveRowProps(\n visibleRows.filter(\n (entry): entry is ResolvedRow<Row> => !(\"kind\" in entry),\n ),\n getRowProps,\n );\n\n /** The row and cell an event addresses, resolved once for every handler. */\n function targetOf(\n target: EventTarget,\n ): { position: BodyCellTarget; rowId: string } | null {\n const position = bodyCellFrom(target);\n const entry = position === null ? undefined : rows[position.rowIndex];\n if (position === null || entry === undefined || \"kind\" in entry) {\n return null;\n }\n return { position, rowId: entry.rowId };\n }\n\n function select(\n rowId: string,\n columnId: string,\n modifiers: { ctrlKey: boolean; metaKey: boolean; shiftKey: boolean },\n ): void {\n // Independent of each other: selecting a cell says nothing about its row,\n // so a grid with both on reports both. `toggleOnClick` is the rows' own.\n if (rowMode !== false) {\n selection.selectRow(rowId, intentOf(modifiers, { toggleOnClick }));\n }\n if (cellMode !== false) {\n selection.selectCell({ rowId, columnId }, intentOf(modifiers));\n }\n }\n\n /**\n * What `onRowClick`/`onRowDoubleClick` are told of a pointer event on a\n * data row — `null` off one, a group header included. Unlike `targetOf`\n * it needs no cell: the row alone is enough to report.\n */\n function rowPointerEventOf(\n event: ReactMouseEvent,\n ): RowPointerEvent<Row> | null {\n const target = bodyRowFrom(event.target);\n const entry = target === null ? undefined : rows[target.rowIndex];\n if (target === null || entry === undefined || \"kind\" in entry) {\n return null;\n }\n return {\n row: entry,\n columnId: target.columnId,\n native: {\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n altKey: event.altKey,\n button: event.button,\n },\n };\n }\n\n function reportRowPointer(\n event: ReactMouseEvent,\n callback: ((event: RowPointerEvent<Row>) => void) | undefined,\n ): void {\n if (callback === undefined) return;\n const pointer = rowPointerEventOf(event);\n if (pointer !== null) {\n callback(pointer);\n }\n }\n\n return (\n <tbody\n role=\"rowgroup\"\n className=\"grid-body\"\n onFocus={(event) => {\n const group = groupRowFrom(event.target);\n if (group !== null) {\n // One cell for the whole row — see the note on `focused` below.\n nav.focusCell(group.rowIndex, 0);\n return;\n }\n const found = targetOf(event.target);\n if (found === null) return;\n nav.focusCell(found.position.rowIndex, found.position.columnIndex);\n }}\n onClick={(event) => {\n const group = groupRowFrom(event.target);\n if (group !== null) {\n controller.toggleGroupExpansion(group.groupId);\n return;\n }\n const found = targetOf(event.target);\n if (found !== null) {\n select(found.rowId, found.position.columnId, event);\n }\n // After selecting, so a handler reading the selection sees this\n // click's.\n reportRowPointer(event, onRowClick);\n }}\n onDoubleClick={(event) => {\n reportRowPointer(event, onRowDoubleClick);\n }}\n onKeyDown={(event) => {\n if (!isOwnEvent(event)) return;\n const group = groupRowFrom(event.target);\n if (group !== null) {\n // One cell spans every column, so there is nothing to move within —\n // left/right stay a no-op rather than silently moving `nav`'s\n // stored column index off of a cell this row doesn't have.\n if (event.key === \"ArrowLeft\" || event.key === \"ArrowRight\") {\n event.preventDefault();\n return;\n }\n if (event.key === \" \" || event.key === \"Enter\") {\n event.preventDefault();\n controller.toggleGroupExpansion(group.groupId);\n return;\n }\n nav.onKeyDown(event);\n return;\n }\n\n // Space builds a selection up and Enter replaces it, matching the\n // Ctrl-click and the plain click they stand in for.\n if (event.key === \" \" || event.key === \"Enter\") {\n const found = targetOf(event.target);\n if (found === null) return;\n // Taken whether or not anything is selectable: Space would otherwise\n // scroll the grid out from under the focused cell.\n event.preventDefault();\n select(\n found.rowId,\n found.position.columnId,\n keyboardSelectIntent(event),\n );\n return;\n }\n nav.onKeyDown(event);\n }}\n >\n {virtualRange !== null && virtualRange.offsetBefore > 0 && (\n // `aria-hidden` and carrying neither `data-gridkit-column` nor\n // `data-gridkit-group`/`data-gridkit-row-index`, so `bodyCellFrom`/\n // `groupRowFrom` never mistake it for a real row — it exists purely\n // to give the browser's scrollbar the correct total height and thumb\n // position, the same way `GridFooter`'s `<tfoot>` isn't a \"row\" to\n // any of this grid's own row-counting logic.\n <tr aria-hidden=\"true\">\n <td\n style={{\n height: virtualRange.offsetBefore,\n padding: 0,\n border: \"none\",\n }}\n />\n </tr>\n )}\n {visibleRows.map((entry) => {\n if (!(\"kind\" in entry)) {\n const rowProps = rowPropsOf(entry.rowId);\n return (\n <GridRow<Row>\n key={entry.rowId}\n ref={virtualRange?.measureRow(entry.rowIndex)}\n columns={columns}\n rowId={entry.rowId}\n row={entry.row}\n rowIndex={entry.rowIndex}\n datasetIndex={entry.datasetIndex}\n activeColumnId={activeColumnId}\n selectedColumnIds={selection.selectedColumnIds}\n selected={selection.selectedRowIds.has(entry.rowId)}\n /*\n * Narrowed to this row before it crosses the boundary, so\n * that moving the selected cell re-renders the two rows it\n * moved between rather than all of them.\n */\n selectedColumnId={\n selectedCell?.rowId === entry.rowId\n ? selectedCell.columnId\n : null\n }\n focusedColumnIndex={\n nav.focus.rowIndex === entry.rowIndex\n ? nav.focus.columnIndex\n : null\n }\n rowsSelectable={rowMode !== false}\n cellsSelectable={cellMode !== false}\n contextMenu={cellMenu}\n locale={locale}\n cellMessages={cellMessages}\n rowClassName={rowProps.className}\n rowAttributes={rowProps.attributes}\n />\n );\n }\n\n if (entry.kind === \"group-summary\") {\n return (\n <GridGroupSummaryRow<Row>\n key={`${entry.groupId}-summary`}\n ref={virtualRange?.measureRow(entry.rowIndex)}\n groupId={entry.groupId}\n level={entry.level}\n rowIndex={entry.rowIndex}\n datasetIndex={entry.datasetIndex}\n results={entry.aggregates}\n aggregates={aggregates}\n columns={columns}\n locale={locale}\n />\n );\n }\n\n return (\n <GridGroupRow\n key={entry.groupId}\n ref={virtualRange?.measureRow(entry.rowIndex)}\n columnCount={columns.length}\n groupId={entry.groupId}\n level={entry.level}\n // A grouping by a column the grid does not have reads its value\n // by its kind alone.\n groupColumn={\n definitions.get(entry.columnId) ?? { field: entry.columnId }\n }\n value={entry.value}\n expanded={entry.expanded}\n count={entry.count}\n rowIndex={entry.rowIndex}\n datasetIndex={entry.datasetIndex}\n posinset={ariaMeta.get(entry.groupId)?.posinset ?? 1}\n setsize={ariaMeta.get(entry.groupId)?.setsize ?? 1}\n // Inline rendering only under \"inline\" display — under \"row\",\n // the group's own summary row (above) already shows these, and\n // showing them twice would be redundant.\n aggregates={groupAggregateDisplay === \"inline\" ? aggregates : []}\n results={entry.aggregates}\n definitions={definitions}\n locale={locale}\n cellMessages={cellMessages}\n // Ignores `nav.focus.columnIndex`: with only one cell in this\n // row, whether it holds the tab stop depends on `rowIndex`\n // alone.\n focused={nav.focus.rowIndex === entry.rowIndex}\n contextMenu={groupMenu}\n />\n );\n })}\n {virtualRange !== null && virtualRange.offsetAfter > 0 && (\n <tr aria-hidden=\"true\">\n <td\n style={{\n height: virtualRange.offsetAfter,\n padding: 0,\n border: \"none\",\n }}\n />\n </tr>\n )}\n {/*\n * Presentational, like the spacer rows above: neither carries\n * `data-gridkit-row-index`/`data-gridkit-column`, so `bodyCellFrom`/\n * `groupRowFrom` never match them, and neither is part of `rows` (the\n * array `aria-rowcount` and `useGridNavigation`'s `rowCount` are\n * computed from in `DataGrid.tsx`), so both are already excluded from\n * row counting and keyboard navigation without any extra check here.\n */}\n {infiniteScroll?.hasMore && (\n <>\n {infiniteScroll.isLoadingMore === true && (\n <tr aria-hidden=\"true\" className=\"grid-loading-row\">\n <td colSpan={columns.length} className=\"grid-loading-cell\">\n {infiniteScroll.loadingTemplate\n ? infiniteScroll.loadingTemplate()\n : messages.loadingMore}\n </td>\n </tr>\n )}\n <tr\n aria-hidden=\"true\"\n ref={sentinelRef}\n className=\"grid-sentinel-row\"\n >\n <td\n colSpan={columns.length}\n style={{ padding: 0, border: \"none\" }}\n />\n </tr>\n </>\n )}\n </tbody>\n );\n}\n","import type { ResolvedRow, RowProps } from \"@gridkitjs/core\";\n\nexport type RowAttributes = Readonly<Record<`data-${string}`, string>>;\n\n/** What `GridRow` is handed from `getRowProps`, both always present. */\nexport interface ResolvedRowProps {\n readonly className: string;\n readonly attributes: RowAttributes;\n}\n\n/** Shared by every row without attributes, so each compares equal to the last. */\nexport const NO_ATTRIBUTES: RowAttributes = {};\n\nconst NO_ROW_PROPS: ResolvedRowProps = {\n className: \"\",\n attributes: NO_ATTRIBUTES,\n};\n\nfunction sameAttributes(a: RowAttributes, b: RowAttributes): boolean {\n const keys = Object.keys(a) as (keyof RowAttributes)[];\n return (\n keys.length === Object.keys(b).length &&\n keys.every((key) => a[key] === b[key])\n );\n}\n\n/**\n * Runs `getRowProps` over the rows about to render, keeping each row's\n * attributes the same object as last time while they read the same.\n *\n * `GridRow` is memoised, and `getRowProps` returns a fresh attributes object\n * on every call — often from an inline arrow that is itself new on every\n * render — so handing those objects straight through would redraw every row\n * on every render. The class is a string and compares by value already.\n *\n * Remembers only the rows of the latest call, so a virtualized grid scrolled\n * over many rows holds no more than the ones on screen.\n */\nexport function createRowPropsResolver<Row>(): (\n rows: readonly ResolvedRow<Row>[],\n getRowProps: ((row: ResolvedRow<Row>) => RowProps) | undefined,\n) => (rowId: string) => ResolvedRowProps {\n let previous = new Map<string, RowAttributes>();\n return (rows, getRowProps) => {\n if (getRowProps === undefined) {\n previous = new Map();\n return () => NO_ROW_PROPS;\n }\n const resolved = new Map<string, ResolvedRowProps>();\n const attributesById = new Map<string, RowAttributes>();\n for (const entry of rows) {\n const { className = \"\", attributes = NO_ATTRIBUTES } = getRowProps(entry);\n const last = previous.get(entry.rowId);\n const stable =\n last !== undefined && sameAttributes(last, attributes)\n ? last\n : attributes;\n attributesById.set(entry.rowId, stable);\n resolved.set(entry.rowId, { className, attributes: stable });\n }\n previous = attributesById;\n return (rowId) => resolved.get(rowId) ?? NO_ROW_PROPS;\n };\n}\n","import { memo, type Ref } from \"react\";\nimport {\n formatGroupValue,\n resolveColumnLabel,\n type AggregateResults,\n type AggregateState,\n type FormatLocale,\n type GridMessages,\n} from \"@gridkitjs/core\";\nimport type { ColumnDefinition } from \"../DataGrid\";\nimport { classNames } from \"../classNames\";\nimport { renderAggregate } from \"./renderAggregate\";\n\ninterface GridGroupRowProps<Row> {\n /** How many columns this group's header spans, matching the grid's own count. */\n columnCount: number;\n groupId: string;\n /** Nesting depth, 0 for a top-level group — indents the header and feeds `aria-level`. */\n level: number;\n /** The column grouped by, whose label names the group and whose formatting its value reads in. */\n groupColumn: ColumnDefinition<Row>;\n /** This group's own value — the last entry of its `path`. */\n value: unknown;\n expanded: boolean;\n /** Leaf row count under this group, regardless of collapse state. */\n count: number;\n /** This row's position in the full (unsliced) display-rows array — see `ResolvedGroupRow.rowIndex`. */\n rowIndex: number;\n /** This header's absolute position in the whole dataset, unaffected by which page is showing — see `ResolvedGroupRow.datasetIndex`. */\n datasetIndex: number;\n /** This group's 1-based position among its own siblings, for `aria-posinset`. */\n posinset: number;\n /** How many siblings this group has, for `aria-setsize`. */\n setsize: number;\n /** Whether this row currently holds the grid's single tab stop. */\n focused: boolean;\n /** Whether this row opens the grid's context menu, which its `aria-keyshortcuts` says. */\n contextMenu: boolean;\n /** Active aggregates — empty when none are active, in which case no subtotal renders. */\n aggregates: AggregateState<Row>;\n /** This group's own computed results, keyed the same way `aggregates` resolves each spec's key. */\n results: AggregateResults;\n /** Every column's definition by id, hidden ones included — whose label and formatting each aggregate takes. */\n definitions: ReadonlyMap<string, ColumnDefinition<Row>>;\n /** The grid's `locale`, which values are formatted for. */\n locale: FormatLocale;\n /** The words for a boolean or missing group value, from `messages` — memoised by `GridBody`. */\n cellMessages: Pick<\n GridMessages,\n \"booleanTrue\" | \"booleanFalse\" | \"blankGroupValue\"\n >;\n ref?: Ref<HTMLTableRowElement> | undefined;\n}\n\nfunction GridGroupRowComponent<Row>({\n columnCount,\n groupId,\n level,\n groupColumn,\n value,\n expanded,\n count,\n rowIndex,\n datasetIndex,\n posinset,\n setsize,\n focused,\n contextMenu,\n aggregates,\n results,\n definitions,\n locale,\n cellMessages,\n ref,\n}: GridGroupRowProps<Row>) {\n return (\n <tr\n ref={ref}\n role=\"row\"\n // Two past the index: rows are counted from one, and the header is the\n // first of them — the same convention `GridRow` uses. Built from\n // `datasetIndex`, not the page-relative `rowIndex`, matching `GridRow`.\n aria-rowindex={datasetIndex + 2}\n // 1-based, per the WAI-ARIA treegrid pattern.\n aria-level={level + 1}\n aria-expanded={expanded}\n aria-setsize={setsize}\n aria-posinset={posinset}\n data-gridkit-group={groupId}\n // See `GridRow`'s own `data-gridkit-row-index` for why this reads off\n // the array position rather than the DOM's `sectionRowIndex`.\n data-gridkit-row-index={rowIndex}\n className={classNames(\n \"grid-group-row\",\n `is-group-level-${String(level)}`,\n )}\n >\n <td\n role=\"gridcell\"\n colSpan={columnCount}\n tabIndex={focused ? 0 : -1}\n aria-keyshortcuts={\n contextMenu ? \"Space Enter Shift+F10\" : \"Space Enter\"\n }\n className=\"grid-group-cell\"\n >\n {/*\n * The flex layout lives on this inner `div`, not the `<td>` itself:\n * a `display` other than `table-cell` on the cell element changes\n * its box type entirely, and the browser fixes that up by wrapping\n * it in an anonymous table-cell — which throws off the cell's own\n * hit-testing (a click landing where the row's bounding box says\n * the cell is can miss it and hit the table underneath instead).\n */}\n <div\n className=\"grid-group-cell-content\"\n style={{ paddingInlineStart: `${String(level * 1.25 + 0.5)}rem` }}\n >\n <span\n className={classNames(\n \"group-toggle\",\n expanded ? \"is-expanded\" : \"is-collapsed\",\n )}\n aria-hidden=\"true\"\n />\n <span className=\"group-label\">\n {resolveColumnLabel(groupColumn)}:{\" \"}\n {formatGroupValue(value, groupColumn, locale, cellMessages)}\n </span>\n <span className=\"group-count\">({count})</span>\n {aggregates.length > 0 && (\n <span className=\"group-aggregates\">\n {aggregates.map((spec) => {\n const key = spec.id ?? spec.columnId;\n const aggregateValue = results.get(key);\n const column = definitions.get(spec.columnId);\n const rendered = renderAggregate(\n aggregateValue,\n spec,\n column,\n [],\n locale,\n );\n // An explicit `id` disambiguates two specs on the same\n // column (e.g. both `sum` and `avg` of Amount) — when given,\n // it's the caller's own label for this result, so it takes\n // priority over the column's shared label.\n const aggregateLabel =\n spec.id ??\n (column === undefined\n ? spec.columnId\n : resolveColumnLabel(column));\n return (\n <span key={key} className=\"group-aggregate\">\n {aggregateLabel}: {rendered}\n </span>\n );\n })}\n </span>\n )}\n </div>\n </td>\n </tr>\n );\n}\n\n/**\n * `memo()`-wrapped for the same reason `GridRow` is: every prop here is a\n * scalar or an already-narrowed value, and no handler reaches this component\n * directly — `GridBody` delegates group-header clicks and keydowns the same\n * way it does for data rows.\n */\nconst GridGroupRow = memo(\n GridGroupRowComponent,\n) as typeof GridGroupRowComponent;\n\nexport default GridGroupRow;\n","import type { ReactNode } from \"react\";\nimport {\n formatAggregateValue,\n type AggregateSpec,\n type FormatLocale,\n} from \"@gridkitjs/core\";\nimport type { ColumnDefinition } from \"../DataGrid\";\n\n/**\n * One aggregate result as the grid shows it — in the grand-total footer, a\n * group's summary row, or inline in a group's header. The column's own\n * `footerTemplate` when it has one; otherwise the text\n * `formatAggregateValue` makes of it, with a dash standing in for an empty\n * result so a cell that has an aggregate never looks like one that has none.\n */\nexport function renderAggregate<Row>(\n value: unknown,\n spec: AggregateSpec<Row>,\n column: ColumnDefinition<Row> | undefined,\n rows: readonly Row[],\n locale: FormatLocale,\n): ReactNode {\n if (column?.footerTemplate) {\n return column.footerTemplate({ value, rows });\n }\n if (value === null || value === undefined) {\n return \"—\";\n }\n return formatAggregateValue(value, spec, column, locale);\n}\n","import { memo, type Ref } from \"react\";\nimport type {\n AggregateResults,\n AggregateState,\n FormatLocale,\n} from \"@gridkitjs/core\";\nimport type { ResolvedColumn } from \"../DataGrid\";\nimport { classNames } from \"../classNames\";\nimport { renderAggregate } from \"./renderAggregate\";\n\ninterface GridGroupSummaryRowProps<Row> {\n groupId: string;\n /** Nesting depth, matching the group's own level — indents the row the same amount `GridGroupRow` does. */\n level: number;\n /** This row's position in the full (unsliced) display-rows array — see `ResolvedGroupSummaryRow.rowIndex`. */\n rowIndex: number;\n /** This row's absolute position in the whole dataset, unaffected by which page is showing — see `ResolvedGroupSummaryRow.datasetIndex`. */\n datasetIndex: number;\n /** The group's own computed results — identical to its header's `aggregates`. */\n results: AggregateResults;\n aggregates: AggregateState<Row>;\n columns: readonly ResolvedColumn<Row>[];\n /** The grid's `locale`, which values are formatted for. */\n locale: FormatLocale;\n ref?: Ref<HTMLTableRowElement> | undefined;\n}\n\n/**\n * A group's own aggregate results, one real `<td>` per column rather than\n * text inside the header's single spanning cell — the `groupAggregateDisplay:\n * \"row\"` alternative to `GridGroupRow`'s own inline rendering. Structurally\n * mirrors `GridFooter`'s grand-total row, scoped to one group's `results`\n * instead of the dataset-wide total, and indented the same amount its own\n * `GridGroupRow` is.\n *\n * Presentational: it occupies a real row slot (counted in `rowCount`/\n * `aria-rowindex`, since it is a genuine `<tr>` inside `<tbody>`) but is\n * never a keyboard tab stop — `DataGrid.tsx`'s `isSkippableRow` steps over\n * it during arrow-key navigation the same way this component itself takes\n * no `tabIndex`, `role=\"row\"`/`\"gridcell\"` only, no interactive attributes.\n *\n * Each cell's alignment follows the same rule `GridFooter`'s own cells do:\n * the first matching spec's `AggregateSpec.alignment` override, falling\n * back to the column's own `alignment` when neither is set.\n */\nfunction GridGroupSummaryRowComponent<Row>({\n groupId,\n level,\n rowIndex,\n datasetIndex,\n results,\n aggregates,\n columns,\n locale,\n ref,\n}: GridGroupSummaryRowProps<Row>) {\n return (\n <tr\n ref={ref}\n role=\"row\"\n aria-rowindex={datasetIndex + 2}\n data-gridkit-group-summary={groupId}\n // See `GridRow`'s own `data-gridkit-row-index` for why this reads off\n // the array position rather than the DOM's `sectionRowIndex`.\n data-gridkit-row-index={rowIndex}\n className={classNames(\n \"grid-group-summary-row\",\n `is-group-level-${String(level)}`,\n )}\n >\n {columns.map((entry) => {\n const specs = aggregates.filter(\n (candidate) => candidate.columnId === entry.id,\n );\n\n return (\n <td\n key={entry.id}\n role=\"gridcell\"\n data-gridkit-column={entry.id}\n className=\"grid-group-summary-cell\"\n style={{ textAlign: specs[0]?.alignment ?? entry.alignment }}\n >\n {entry.id === columns[0]?.id && (\n <span\n className=\"grid-group-summary-indent\"\n style={{ width: `${String(level * 1.25 + 0.5)}rem` }}\n aria-hidden=\"true\"\n />\n )}\n {specs\n .map((spec) =>\n renderAggregate(\n results.get(spec.id ?? spec.columnId),\n spec,\n entry.column,\n [],\n locale,\n ),\n )\n .flatMap((rendered, index) =>\n index === 0 ? [rendered] : [\", \", rendered],\n )}\n </td>\n );\n })}\n </tr>\n );\n}\n\n/**\n * `memo()`-wrapped for the same reason `GridGroupRow`/`GridRow` are: every\n * prop here is a scalar or an already-narrowed value.\n */\nconst GridGroupSummaryRow = memo(\n GridGroupSummaryRowComponent,\n) as typeof GridGroupSummaryRowComponent;\n\nexport default GridGroupSummaryRow;\n","import {\n accessDotted,\n formatCellValue,\n type FormatLocale,\n type GridMessages,\n} from \"@gridkitjs/core\";\nimport { memo, type Ref } from \"react\";\nimport type { ResolvedColumn } from \"../DataGrid\";\nimport { ariaAttr } from \"../ariaAttr\";\nimport { classNames } from \"../classNames\";\nimport type { RowAttributes } from \"../rowProps\";\nimport { tabIndexFor } from \"../useGridNavigation\";\n\ninterface GridRowProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n rowId: string;\n row: Row;\n rowIndex: number;\n /** This row's absolute position in the whole dataset, unaffected by which page is showing — see `CellTemplateContext.datasetIndex`. */\n datasetIndex: number;\n /** The column being resized, so its cells outline with its header. */\n activeColumnId: string | null;\n selectedColumnIds: ReadonlySet<string>;\n selected: boolean;\n /** Which of this row's cells is the selected one, if any. */\n selectedColumnId: string | null;\n /** Which of this row's cells holds the grid's tab stop, if any. */\n focusedColumnIndex: number | null;\n rowsSelectable: boolean;\n cellsSelectable: boolean;\n /** Whether a cell opens the grid's context menu, which its `aria-keyshortcuts` says. */\n contextMenu: boolean;\n /** The grid's `locale`, which a cell without a template is formatted for. */\n locale: FormatLocale;\n /** A boolean cell's words, from `messages` — memoised on the two strings by `GridBody`. */\n cellMessages: Pick<GridMessages, \"booleanTrue\" | \"booleanFalse\">;\n /** The class `getRowProps` gave this row, `\"\"` for none. */\n rowClassName: string;\n /** The `data-*` attributes `getRowProps` gave this row — the same object while they read the same, so they do not defeat `memo`. */\n rowAttributes: RowAttributes;\n ref?: Ref<HTMLTableRowElement> | undefined;\n}\n\nfunction GridRowComponent<Row>({\n columns,\n rowId,\n row,\n rowIndex,\n datasetIndex,\n activeColumnId,\n selectedColumnIds,\n selected,\n selectedColumnId,\n focusedColumnIndex,\n rowsSelectable,\n cellsSelectable,\n contextMenu,\n locale,\n cellMessages,\n rowClassName,\n rowAttributes,\n ref,\n}: GridRowProps<Row>) {\n // The ContextMenu key needs no mention: it says what it does on its face.\n const shortcuts = [\n cellsSelectable ? \"Space Enter\" : \"\",\n contextMenu ? \"Shift+F10\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n return (\n <tr\n // First, so the grid's own attributes below win over one of the same\n // name: `GridBody` finds rows by them.\n {...rowAttributes}\n ref={ref}\n role=\"row\"\n // Two past the index: rows are counted from one, and the header is the\n // first of them. Built from `datasetIndex` rather than the\n // page-relative `rowIndex`, so a paginated grid still reports each\n // row's true position in the whole dataset — the two only diverge once\n // pagination is on.\n aria-rowindex={datasetIndex + 2}\n // This row's position in the full (unsliced) rows array — read by\n // `GridBody`'s event delegation (`bodyCellFrom`) instead of the DOM's own\n // `sectionRowIndex`, which under virtualization no longer matches a\n // row's array position once a leading spacer `<tr>` shifts it.\n data-gridkit-row-index={rowIndex}\n // The row's identity, for a test or a script to find it by however it\n // has moved — the index above changes with every sort.\n data-gridkit-row-id={rowId}\n // Omitted rather than `false` when rows cannot be selected, which would\n // otherwise have every row announce that it is not.\n {...ariaAttr(rowsSelectable, \"aria-selected\", selected)}\n className={classNames(\n \"grid-row\",\n selected ? \"is-selected\" : \"\",\n rowClassName,\n )}\n >\n {columns.map(({ id, column, alignment }, columnIndex) => {\n // Resolved either way, so a template never has to walk the field path\n // a second time.\n const value = accessDotted(row, column.field);\n const cellSelected = id === selectedColumnId;\n\n return (\n <td\n key={id}\n role=\"gridcell\"\n data-gridkit-column={id}\n aria-colindex={columnIndex + 1}\n tabIndex={tabIndexFor(columnIndex, focusedColumnIndex)}\n {...ariaAttr(cellsSelectable, \"aria-selected\", cellSelected)}\n {...ariaAttr(shortcuts !== \"\", \"aria-keyshortcuts\", shortcuts)}\n className={classNames(\n \"grid-cell\",\n id === activeColumnId ? \"is-resizing\" : \"\",\n cellSelected || selectedColumnIds.has(id) ? \"is-selected\" : \"\",\n column.wrap?.cells ? \"is-wrapped\" : \"\",\n column.cellClassName ?? \"\",\n )}\n style={{ textAlign: alignment }}\n >\n {column.cellTemplate\n ? column.cellTemplate({\n value,\n row,\n rowIndex,\n datasetIndex,\n rowId,\n selected,\n })\n : formatCellValue(value, column, locale, row, cellMessages)}\n </td>\n );\n })}\n </tr>\n );\n}\n\n/**\n * Selection lives at the top of the grid, so any change to it re-renders the\n * whole body — without this boundary a click would rebuild every cell of every\n * row rather than the one or two rows that changed.\n *\n * Every prop above is a scalar or already memoised for that reason, and no\n * handler reaches here at all: the body delegates its events, so a row has\n * nothing to compare that changes each render.\n *\n * `memo` erases the type parameter, and the cast puts it back — the standard\n * price of memoising a generic component.\n */\nconst GridRow = memo(GridRowComponent) as typeof GridRowComponent;\n\nexport default GridRow;\n","import type {\n AggregateResults,\n AggregateState,\n FormatLocale,\n} from \"@gridkitjs/core\";\nimport type { ResolvedColumn } from \"../DataGrid\";\nimport { renderAggregate } from \"./renderAggregate\";\n\ninterface GridFooterProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n aggregates: AggregateState<Row>;\n results: AggregateResults;\n /** Every row the grand total was computed over — what a `footerTemplate` receives as `rows`. */\n rows: readonly Row[];\n /** The grid's `locale`, which values are formatted for. */\n locale: FormatLocale;\n}\n\n/**\n * The grand-total footer — one `<tfoot>` row, one cell per column, using\n * that column's own `footerTemplate` when it defines one, its own computed\n * value formatted like the column's values when it doesn't, and a blank cell for a column\n * with no aggregate at all. Structurally mirrors `GridHeader`, minus\n * everything interactive: a footer cell is not resizable, sortable, or\n * selectable.\n *\n * A column named by more than one spec (e.g. both `sum` and `avg` of the\n * same column, disambiguated by `id`) renders every matching spec's result\n * in its one cell, comma-separated — the cell grid stays one-per-column,\n * but no result is dropped the way picking only the first match would. The\n * cell's own alignment follows the first matching spec's `AggregateSpec.\n * alignment` override, falling back to the column's own `alignment` when\n * neither is set — one `<td>` can only take one `text-align`, so a second\n * spec's own override (if it disagrees) applies only to its value, not the\n * cell.\n *\n * Sits outside `<tbody>`'s row count on purpose — a `<tfoot>` is not part\n * of `aria-rowcount`/`aria-rowindex`/keyboard navigation's `rowCount`, the\n * same way `<thead>`'s header row is counted separately from data rows.\n */\nexport default function GridFooter<Row>({\n columns,\n aggregates,\n results,\n rows,\n locale,\n}: GridFooterProps<Row>) {\n return (\n <tfoot role=\"rowgroup\">\n <tr className=\"grid-footer\" role=\"row\">\n {columns.map((entry) => {\n const specs = aggregates.filter(\n (candidate) => candidate.columnId === entry.id,\n );\n\n return (\n <td\n key={entry.id}\n role=\"gridcell\"\n data-gridkit-column={entry.id}\n className=\"grid-footer-cell\"\n style={{ textAlign: specs[0]?.alignment ?? entry.alignment }}\n >\n {specs\n .map((spec) =>\n renderAggregate(\n results.get(spec.id ?? spec.columnId),\n spec,\n entry.column,\n rows,\n locale,\n ),\n )\n // Two values in one cell need a visible separator; a single\n // one (the common case) renders exactly as before.\n .flatMap((rendered, index) =>\n index === 0 ? [rendered] : [\", \", rendered],\n )}\n </td>\n );\n })}\n </tr>\n </tfoot>\n );\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { paginationWindow, type GridMessages } from \"@gridkitjs/core\";\nimport type { PagerConfig, PagerTemplateContext } from \"../DataGrid\";\nimport {\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronsLeftIcon,\n ChevronsRightIcon,\n} from \"../icons\";\n\ninterface GridPagerProps {\n /** The same context a `pager.template` is handed. */\n pager: PagerTemplateContext;\n /** Presentation options for the pager. `undefined` renders the `\"compact\"` default with no page-size control. */\n config: PagerConfig | undefined;\n messages: GridMessages;\n}\n\ninterface PagerNavButtonProps {\n /** The modifier class beside `grid-pager-button grid-pager-nav`. */\n className: string;\n label: string;\n disabled: boolean;\n onClick: () => void;\n children: ReactNode;\n}\n\n/** One of the bar's four arrow segments: an icon, named by its message. */\nfunction PagerNavButton({\n className,\n label,\n disabled,\n onClick,\n children,\n}: PagerNavButtonProps) {\n return (\n <button\n type=\"button\"\n className={`grid-pager-button grid-pager-nav ${className}`}\n aria-label={label}\n title={label}\n disabled={disabled}\n onClick={onClick}\n >\n {children}\n </button>\n );\n}\n\n/**\n * The built-in pager: one connected bar of first/previous, the page\n * numbers (or, under the default `\"compact\"` variant, a \"Page X of Y\"\n * status), and next/last, followed — when `config.sizeOptions` is given —\n * by a page-size `<select>`. Rendered as a sibling below the table, not a\n * row inside it, the same reasoning `GroupByBar` gives for its own\n * placement: a control surface, not grid content.\n *\n * The bar holds still as the user pages through it: `paginationWindow`\n * yields a constant number of slots, and `--gridkit-pager-digits` (the page\n * count's digit count) lets the theme give every number slot the same\n * width; the compact status reserves the width of its widest text.\n *\n * Whether this mounts at all is `DataGrid.tsx`'s call (`paginated`), not\n * this component's own.\n */\nexport default function GridPager({ pager, config, messages }: GridPagerProps) {\n const { pagination, pageCount, currentPage } = pager;\n const variant = config?.variant ?? \"compact\";\n const sizeOptions = config?.sizeOptions;\n const atFirst = pagination.pageIndex <= 0;\n const atLast = pagination.pageIndex >= pageCount - 1;\n const barStyle = {\n \"--gridkit-pager-digits\": String(String(Math.max(1, pageCount)).length),\n } as CSSProperties;\n\n return (\n <div\n className=\"gridkit-grid-pager\"\n role=\"group\"\n aria-label={messages.pagerLabel}\n >\n <div className=\"grid-pager-bar\" style={barStyle}>\n <PagerNavButton\n className=\"grid-pager-first\"\n label={messages.firstPage}\n disabled={atFirst}\n onClick={() => {\n pager.goToPage(0);\n }}\n >\n <ChevronsLeftIcon />\n </PagerNavButton>\n <PagerNavButton\n className=\"grid-pager-previous\"\n label={messages.previousPage}\n disabled={atFirst}\n onClick={() => {\n pager.previousPage();\n }}\n >\n <ChevronLeftIcon />\n </PagerNavButton>\n {variant === \"numbered\" ? (\n paginationWindow(currentPage, pageCount, {\n boundaryCount: config?.boundaryCount,\n siblingCount: config?.siblingCount,\n }).map((entry, index) =>\n entry === \"ellipsis\" ? (\n <span\n key={`ellipsis-${String(index)}`}\n className=\"grid-pager-ellipsis\"\n aria-hidden=\"true\"\n >\n …\n </span>\n ) : (\n <button\n key={entry}\n type=\"button\"\n className=\"grid-pager-button grid-pager-page\"\n aria-label={messages.pageButtonLabel(entry)}\n aria-current={entry === currentPage ? \"page\" : undefined}\n onClick={() => {\n pager.goToPage(entry - 1);\n }}\n >\n {entry}\n </button>\n ),\n )\n ) : (\n <span className=\"grid-pager-status-slot\">\n <span className=\"grid-pager-status\">\n {messages.pageStatus(\n pageCount === 0 ? 0 : currentPage,\n pageCount,\n )}\n </span>\n {/* The widest the status gets, invisible, so the slot never resizes as the page changes. */}\n <span className=\"grid-pager-status-sizer\" aria-hidden=\"true\">\n {messages.pageStatus(pageCount, pageCount)}\n </span>\n </span>\n )}\n <PagerNavButton\n className=\"grid-pager-next\"\n label={messages.nextPage}\n disabled={atLast}\n onClick={() => {\n pager.nextPage();\n }}\n >\n <ChevronRightIcon />\n </PagerNavButton>\n <PagerNavButton\n className=\"grid-pager-last\"\n label={messages.lastPage}\n disabled={atLast}\n onClick={() => {\n pager.goToPage(pageCount - 1);\n }}\n >\n <ChevronsRightIcon />\n </PagerNavButton>\n </div>\n {sizeOptions !== undefined && sizeOptions.length > 0 && (\n <label className=\"grid-pager-page-size\">\n <select\n value={pagination.pageSize}\n onChange={(event) => {\n pager.setPageSize(Number(event.target.value));\n }}\n >\n {sizeOptions.map((size) => (\n <option key={size} value={size}>\n {size}\n </option>\n ))}\n </select>\n <span className=\"grid-pager-page-size-label\">\n {messages.pageSizeLabel}\n </span>\n </label>\n )}\n </div>\n );\n}\n","import { createPortal } from \"react-dom\";\nimport {\n resolveColumnLabel,\n resolveKeyboardDropTarget,\n type GridMessages,\n type GroupByState,\n} from \"@gridkitjs/core\";\nimport type { GroupByDropTarget } from \"@gridkitjs/dom\";\nimport type { ColumnDefinition, ResolvedColumn } from \"../DataGrid\";\nimport { classNames } from \"../classNames\";\nimport useGroupByDrag from \"../useGroupByDrag\";\nimport type { DataGridController } from \"../useGridController\";\n\ninterface GroupByBarProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n /** Every column's definition by id, hidden ones included, so a chip for a hidden column still carries its label. */\n definitions: ReadonlyMap<string, ColumnDefinition<Row>>;\n groupBy: GroupByState;\n /** What a chip's drag, move or remove button changes. */\n controller: DataGridController<Row>;\n /** A column's accessible name — see `DataGrid.tsx`'s own `columnName`. */\n columnName: (columnId: string) => string;\n /** Whether the header drag currently open (if any) could drop into this bar. */\n headerDragEligible: boolean;\n /**\n * Whether the header drag currently open (if any) is for a column already\n * in the group-by stack — a drag this bar rejects outright, since\n * repositioning a grouped column is the chip's job, not the header's.\n */\n headerDragBlocked: boolean;\n /** That header drag's own target within this bar, or `null`. */\n headerDropTarget: GroupByDropTarget | null;\n messages: GridMessages;\n}\n\n/**\n * The active group-by stack, outer to inner, as removable, reorderable\n * chips — and the drop target for a header dragged in from outside it.\n * Each column's own header already carries a group toggle (a pointer\n * affordance, plus `Alt+ArrowDown`) for adding or removing a level without\n * dragging at all; this bar shows the resulting stack, lets a level be\n * removed from it directly, lets a chip be dragged to reorder the stack (or\n * moved via `Ctrl+ArrowLeft`/`Ctrl+ArrowRight` on a focused one), and — for\n * a column whose header sets `groupByDraggable` and isn't grouped yet —\n * accepts a header dropped onto it, at whatever position among the existing\n * chips it's released. A header for a column already in the stack is\n * rejected outright (`is-drag-blocked`, `cursor: not-allowed`): the header\n * only ever adds, and repositioning an existing level is the chip's job.\n *\n * Whether this component mounts at all is `DataGrid.tsx`'s call\n * (`groupByBarVisibility`), not this component's own — it never bails out\n * on its own initiative once rendered.\n *\n * Chips sit outside the grid's own single-roving-tabstop model: there is no\n * shared index to keep in sync the way a row or a header cell has, so each\n * chip (and its own remove button) is simply, always `tabIndex={0}` — plain\n * DOM tab order, no roving-focus bookkeeping.\n */\nexport default function GroupByBar<Row>({\n columns,\n definitions,\n groupBy,\n controller,\n columnName,\n headerDragEligible,\n headerDragBlocked,\n headerDropTarget,\n messages,\n}: GroupByBarProps<Row>) {\n const groupByIds = groupBy.map((entry) => entry.columnId);\n\n const chipDrag = useGroupByDrag({\n groupBy,\n onDrop: (movedId, beforeColumnId) => {\n controller.moveGroupBy(movedId, beforeColumnId);\n },\n });\n\n // Mutually exclusive by construction — one pointer, so at most one of \"a\n // chip dragged within this bar\" and \"a header dragged in from outside it\"\n // is ever active at once.\n const activeDropTarget = chipDrag.dropTarget ?? headerDropTarget;\n const isDragTarget = chipDrag.draggedColumnId !== null || headerDragEligible;\n const showPlaceholder =\n groupBy.length === 0 && columns.some((entry) => entry.groupByDraggable);\n\n function labelFor(columnId: string) {\n const definition = definitions.get(columnId);\n return definition === undefined ? columnId : resolveColumnLabel(definition);\n }\n\n function moveByKeyboard(columnId: string, direction: -1 | 1): void {\n const beforeColumnId = resolveKeyboardDropTarget(\n groupByIds,\n columnId,\n direction,\n );\n if (beforeColumnId === undefined) {\n return;\n }\n controller.moveGroupBy(columnId, beforeColumnId);\n }\n\n return (\n <div\n className={classNames(\n \"gridkit-group-by-bar\",\n isDragTarget ? \"is-drag-target\" : \"\",\n headerDragBlocked ? \"is-drag-blocked\" : \"\",\n )}\n data-gridkit-group-by-bar=\"\"\n role=\"group\"\n aria-label={messages.groupByBarLabel}\n >\n {showPlaceholder && (\n <span className=\"group-by-bar-placeholder\">\n {messages.groupByBarPlaceholder}\n </span>\n )}\n {groupBy.map((entry, index) => {\n const dropBefore = activeDropTarget?.beforeColumnId === entry.columnId;\n const dropAfter =\n activeDropTarget?.beforeColumnId === null &&\n index === groupBy.length - 1;\n const dragging = chipDrag.draggedColumnId === entry.columnId;\n\n return (\n <span\n key={entry.columnId}\n className={classNames(\n \"group-by-chip\",\n dragging ? \"is-dragging\" : \"\",\n dropBefore ? \"is-drop-before\" : \"\",\n dropAfter ? \"is-drop-after\" : \"\",\n )}\n data-gridkit-group-chip={entry.columnId}\n tabIndex={0}\n aria-label={messages.groupByChipLabel(\n columnName(entry.columnId),\n index + 1,\n groupBy.length,\n )}\n aria-keyshortcuts=\"Control+ArrowLeft Control+ArrowRight\"\n onPointerDown={(event) => {\n chipDrag.startDrag(entry.columnId, event);\n }}\n onKeyDown={(event) => {\n const horizontal =\n event.key === \"ArrowLeft\" || event.key === \"ArrowRight\";\n if (horizontal && event.ctrlKey) {\n event.preventDefault();\n moveByKeyboard(\n entry.columnId,\n event.key === \"ArrowLeft\" ? -1 : 1,\n );\n }\n }}\n >\n <span className=\"group-by-chip-label\">\n {labelFor(entry.columnId)}\n </span>\n <button\n type=\"button\"\n className=\"group-by-chip-remove\"\n aria-label={messages.removeGroupBy(columnName(entry.columnId))}\n onPointerDown={(event) => {\n // Otherwise the chip's own `onPointerDown` sees this bubble\n // up and starts a drag — the same reason the header's own\n // sort toggle stops it.\n event.stopPropagation();\n }}\n onClick={() => {\n controller.toggleGroupBy(entry.columnId);\n }}\n >\n ×\n </button>\n </span>\n );\n })}\n {/*\n * Portalled to the body, the same reason the header's own drag ghost\n * is: inside the viewport the overflow that makes the grid scroll\n * would clip it, and this bar sits right above that viewport.\n */}\n {chipDrag.draggedColumnId !== null &&\n chipDrag.ghostTransform !== null &&\n createPortal(\n <span\n className=\"group-by-chip drag-ghost\"\n style={{ transform: chipDrag.ghostTransform }}\n aria-hidden=\"true\"\n >\n {labelFor(chipDrag.draggedColumnId)}\n </span>,\n document.body,\n )}\n </div>\n );\n}\n","import type { PointerEvent as ReactPointerEvent } from \"react\";\nimport type { GroupByState } from \"@gridkitjs/core\";\nimport {\n resolveGroupByDropTarget,\n type GroupByDropTarget,\n} from \"@gridkitjs/dom\";\nimport useDragReorder from \"./useDragReorder\";\n\ninterface UseGroupByDragOptions {\n groupBy: GroupByState;\n onDrop: (movedColumnId: string, beforeColumnId: string | null) => void;\n}\n\nexport interface GroupByDragApi {\n /** The chip being dragged, for as long as the drag lasts. */\n draggedColumnId: string | null;\n /** Where it would land if released now. */\n dropTarget: GroupByDropTarget | null;\n /** Where the element trailing the pointer sits, as a CSS `transform`. */\n ghostTransform: string | null;\n startDrag: (columnId: string, event: ReactPointerEvent<HTMLElement>) => void;\n /** Whether the gesture that just ended was a drag rather than a click. */\n justDragged: () => boolean;\n}\n\n/**\n * Drag-to-reorder for chips inside the group-by bar, built on the same\n * `useDragReorder` mechanics `useColumnDrag` uses for headers — only the\n * hit-testing (`resolveGroupByDropTarget`, shared with a header dropped in\n * from outside the bar) differs.\n */\nexport default function useGroupByDrag({\n groupBy,\n onDrop,\n}: UseGroupByDragOptions): GroupByDragApi {\n const drag = useDragReorder<GroupByDropTarget>({\n resolveTarget: (clientX, clientY, movedId) =>\n resolveGroupByDropTarget(clientX, clientY, movedId, groupBy),\n onDrop: (target, movedId) => {\n onDrop(movedId, target.beforeColumnId);\n },\n });\n\n return {\n draggedColumnId: drag.draggedId,\n dropTarget: drag.dropTarget,\n ghostTransform: drag.ghostTransform,\n startDrag: (columnId, event) => {\n drag.startDrag(columnId, event.currentTarget, event);\n },\n justDragged: drag.justDragged,\n };\n}\n","import {\n useRef,\n useState,\n type PointerEvent as ReactPointerEvent,\n} from \"react\";\nimport {\n NO_DRAG,\n startDragReorder,\n type DragReorderHandlers,\n type DragReorderState,\n} from \"@gridkitjs/dom\";\n\ntype UseDragReorderOptions<Target> = Pick<\n DragReorderHandlers<Target>,\n \"resolveTarget\" | \"onDrop\"\n>;\n\nexport interface DragReorderApi<Target> extends DragReorderState<Target> {\n startDrag: (\n id: string,\n grabElement: HTMLElement,\n event: ReactPointerEvent<HTMLElement>,\n ) => void;\n /**\n * Whether the gesture that just ended was a drag rather than a click, for\n * a press that has something of its own to do with a click.\n *\n * Reading it clears it, so that a press which never opened a drag at all\n * does not see the last one's answer.\n */\n justDragged: () => boolean;\n}\n\n/**\n * `@gridkitjs/dom`'s `startDragReorder`, the pointer mechanics behind every\n * drag-to-reorder gesture in the grid, with what it reports held as state\n * for the header and the group-by bar to draw. A column header drag and a\n * group-by chip drag (`useColumnDrag`, `useGroupByDrag`) share it, so they\n * can only ever differ in their own hit-testing (`resolveTarget`).\n */\nexport default function useDragReorder<Target>({\n resolveTarget,\n onDrop,\n}: UseDragReorderOptions<Target>): DragReorderApi<Target> {\n const [drag, setDrag] = useState<DragReorderState<Target>>(NO_DRAG);\n const dragged = useRef(false);\n\n function justDragged(): boolean {\n const answer = dragged.current;\n dragged.current = false;\n return answer;\n }\n\n function startDrag(\n id: string,\n grabElement: HTMLElement,\n event: ReactPointerEvent<HTMLElement>,\n ): void {\n startDragReorder(id, grabElement, event, {\n resolveTarget,\n onState(state) {\n // Latched for the `click` that follows the release, which is the\n // only thing that can tell a drag apart from a press in the same\n // spot.\n if (state.draggedId !== null) {\n dragged.current = true;\n }\n setDrag(state);\n },\n onDrop,\n });\n }\n\n // A new object each render, as `useColumnDrag`/`useColumnResize` return:\n // the handlers close over `resolveTarget`/`onDrop`, and a stable identity\n // would buy nothing.\n return {\n draggedId: drag.draggedId,\n dropTarget: drag.dropTarget,\n ghostTransform: drag.ghostTransform,\n startDrag,\n justDragged,\n };\n}\n","import {\n isColumnVisible,\n type ColumnResizeEvent,\n type ColumnSortEvent,\n type ColumnVisibilityEvent,\n type GridMessages,\n type GroupByEvent,\n type GroupExpansionEvent,\n type PaginationChangeEvent,\n type SelectionDiffEvent,\n} from \"@gridkitjs/core\";\nimport type {\n CellSelectionChangeEvent,\n ColumnDefinition,\n DataGridProps,\n} from \"./DataGrid\";\n\n/** The change callbacks of a grid's props that announce what they report. */\ntype AnnouncedProps<Row> = Pick<\n DataGridProps<Row>,\n | \"onColumnResize\"\n | \"onColumnVisibilityChange\"\n | \"onColumnSortChange\"\n | \"onGroupByChange\"\n | \"onGroupExpansionChange\"\n | \"onPaginationChange\"\n | \"onCellSelectionChange\"\n>;\n\ninterface AnnouncedCallbacksOptions<Row> {\n /** The grid's own callbacks, each called before its change is announced. */\n readonly callbacks: AnnouncedProps<Row>;\n readonly announce: (text: string) => void;\n readonly messages: GridMessages;\n /** What a column is called in an announcement. */\n readonly columnName: (columnId: string) => string;\n /** A column's definition by id, hidden or not. */\n readonly columnOf: (columnId: string) => ColumnDefinition<Row> | undefined;\n}\n\n/** What the grid hands its controller to hear each change through. */\nexport interface AnnouncedCallbacks<Row> {\n readonly onColumnResize: (event: ColumnResizeEvent) => void;\n readonly onColumnVisibilityChange: (event: ColumnVisibilityEvent) => void;\n readonly onColumnSortChange: (event: ColumnSortEvent) => void;\n readonly onGroupByChange: (event: GroupByEvent) => void;\n readonly onGroupExpansionChange: (event: GroupExpansionEvent) => void;\n readonly onPaginationChange: (event: PaginationChangeEvent) => void;\n readonly onCellSelectionChange: (\n event: CellSelectionChangeEvent<Row>,\n ) => void;\n readonly onSelectionDiff: (event: SelectionDiffEvent) => void;\n}\n\n/**\n * The grid's change callbacks, each wrapped to announce its change in the\n * live region after calling the grid's own — so a change is announced where\n * the controller reports it, the same whether a click, a key, a menu or the\n * ref made it.\n */\nexport function announcedCallbacks<Row>({\n callbacks,\n announce,\n messages,\n columnName,\n columnOf,\n}: AnnouncedCallbacksOptions<Row>): AnnouncedCallbacks<Row> {\n return {\n /**\n * Announced only once the drag ends: the controller reports the\n * continuous `\"move\"` phase as well, and a live region given every frame\n * of a drag says nothing an assistive technology can keep up with.\n */\n onColumnResize: (event) => {\n callbacks.onColumnResize?.(event);\n if (event.phase === \"end\") {\n announce(\n messages.columnResized(\n columnName(event.columnId),\n Math.round(event.width),\n ),\n );\n }\n },\n\n /**\n * Naming a column shown or hidden alone, and counting several — \"Show\n * all\" in the column chooser, or `hideColumns` given a list. A change\n * that shows some and hides others, as restoring a layout can, has no\n * one thing to say, and says nothing.\n */\n onColumnVisibilityChange: (event) => {\n callbacks.onColumnVisibilityChange?.(event);\n const { columnIds, visibility } = event;\n const [columnId] = columnIds;\n const shownCount = columnIds.filter((id) => {\n const column = columnOf(id);\n return column !== undefined && isColumnVisible(column, visibility);\n }).length;\n if (\n columnId === undefined ||\n (shownCount !== 0 && shownCount !== columnIds.length)\n ) {\n return;\n }\n const shown = shownCount > 0;\n if (columnIds.length > 1) {\n announce(\n shown\n ? messages.columnsShown(columnIds.length)\n : messages.columnsHidden(columnIds.length),\n );\n return;\n }\n announce(\n shown\n ? messages.columnShown(columnName(columnId))\n : messages.columnHidden(columnName(columnId)),\n );\n },\n\n /** A toggle, a stack, or a clear back to \"none\" each get their own. */\n onColumnSortChange: (event) => {\n callbacks.onColumnSortChange?.(event);\n const entry = event.sort.find(\n (candidate) => candidate.columnId === event.columnId,\n );\n if (entry === undefined) {\n announce(messages.sortCleared(columnName(event.columnId)));\n return;\n }\n announce(\n messages.columnSorted(\n columnName(event.columnId),\n entry.direction,\n event.sort.indexOf(entry) + 1,\n event.sort.length,\n ),\n );\n },\n\n onGroupByChange: (event) => {\n callbacks.onGroupByChange?.(event);\n const entry = event.groupBy.find(\n (candidate) => candidate.columnId === event.columnId,\n );\n if (entry === undefined) {\n announce(messages.groupingRemoved(columnName(event.columnId)));\n return;\n }\n announce(\n messages.groupedBy(\n columnName(event.columnId),\n event.groupBy.indexOf(entry) + 1,\n event.groupBy.length,\n ),\n );\n },\n\n /**\n * `groupId: null` marks `expandAll`/`collapseAll`, which touch every\n * group in one call rather than one at a time — announced as a single\n * summary instead of naming a group that doesn't apply.\n */\n onGroupExpansionChange: (event) => {\n callbacks.onGroupExpansionChange?.(event);\n if (event.groupId === null) {\n announce(\n event.expansion.length === 0\n ? messages.allGroupsExpanded\n : messages.allGroupsCollapsed,\n );\n return;\n }\n announce(\n event.expansion.includes(event.groupId)\n ? messages.groupCollapsed\n : messages.groupExpanded,\n );\n },\n\n onPaginationChange: (event) => {\n callbacks.onPaginationChange?.(event);\n announce(\n messages.pageStatus(event.pagination.pageIndex + 1, event.pageCount),\n );\n },\n\n /**\n * Unlike rows and columns, a cell selection is always exactly one cell —\n * there is no multi-cell range — so it never crosses the count's >1\n * threshold and the focused cell's own `aria-selected` is the only\n * feedback a screen-reader user would otherwise get. Announced on every\n * change that lands on a cell instead.\n */\n onCellSelectionChange: (event) => {\n callbacks.onCellSelectionChange?.(event);\n if (event.selected !== null) {\n announce(\n messages.cellSelected(\n columnName(event.selected.columnId),\n event.selected.rowIndex + 1,\n ),\n );\n }\n },\n\n /**\n * Announced only for a change touching more than one row or column. A\n * single selection is already carried by the focused member's own\n * `aria-selected`, and repeating it here would talk over that. Counted\n * by id, so rows the change touched off screen — on another page, in a\n * collapsed group — count too.\n */\n onSelectionDiff: (event) => {\n if (event.added.length + event.removed.length > 1) {\n announce(messages.selectedCount(event.selection.length, event.target));\n }\n },\n };\n}\n","import type { KeyboardEvent } from \"react\";\nimport { runCommand, type GridCommandTarget } from \"@gridkitjs/core\";\nimport { isNativeCopy } from \"@gridkitjs/dom\";\nimport type { GridCommandsApi } from \"../commands/useGridCommands\";\nimport type { DataGridController } from \"../useGridController\";\nimport { HEADER_ROW, type GridNavigationApi } from \"../useGridNavigation\";\n\ninterface UseGridCopyOptions<Row> {\n controller: DataGridController<Row>;\n commands: GridCommandsApi<Row>;\n nav: GridNavigationApi;\n}\n\nfunction isCopyKey(event: KeyboardEvent): boolean {\n return (\n (event.ctrlKey || event.metaKey) &&\n !event.altKey &&\n (event.key === \"c\" || event.key === \"C\")\n );\n}\n\n/**\n * Ctrl+C (Cmd+C on a Mac) on the grid: copies the selection, else the\n * focused cell, through the same `copy.selection` and `copy.cell` commands\n * the context menu runs — so an app that overrides one changes both. The\n * returned handler belongs on the grid root's `onKeyDown`, for keys the\n * grid itself received.\n *\n * A press in a text field inside a cell, or with text highlighted on the\n * page, is the browser's, and so is one with nothing to copy: the default\n * is prevented only once a copy ran. Like the grid's other keys, it is not\n * reported to `onCommand`, which hears of menu and API runs.\n */\nexport default function useGridCopy<Row>({\n controller,\n commands,\n nav,\n}: UseGridCopyOptions<Row>): (event: KeyboardEvent) => void {\n function run(commandId: string, target: GridCommandTarget): boolean {\n const command = commands.commands.get(commandId);\n return (\n command !== undefined && runCommand(command, commands.contextFor(target))\n );\n }\n\n /** The focused data cell as a command target, or `null` on a header or a group row. */\n function focusedCell(): GridCommandTarget | null {\n const { rowIndex, columnIndex } = nav.focus;\n if (rowIndex === HEADER_ROW) {\n return null;\n }\n const { pageRows, columns } = controller.getView();\n const entry = pageRows[rowIndex];\n const column = columns[columnIndex];\n return entry === undefined || \"kind\" in entry || column === undefined\n ? null\n : { area: \"cell\", rowId: entry.rowId, columnId: column.id };\n }\n\n return (event) => {\n if (!isCopyKey(event) || isNativeCopy(event.target)) {\n return;\n }\n const cell = focusedCell();\n if (\n run(\"copy.selection\", { area: \"grid\" }) ||\n (cell !== null && run(\"copy.cell\", cell))\n ) {\n event.preventDefault();\n }\n };\n}\n","import { useMemo } from \"react\";\nimport {\n createCommandContext,\n resolveCommands,\n runCommand,\n type GridCommand,\n type GridCommandContext,\n type GridCommandHost,\n type GridCommandSource,\n type GridCommandTarget,\n type GridMessages,\n type GridOptions,\n} from \"@gridkitjs/core\";\nimport { copyToClipboard } from \"../clipboard/copyToClipboard\";\nimport useSaveFile from \"../export/useSaveFile\";\nimport { printGrid } from \"../print/printApi\";\nimport type { ColumnResizeApi } from \"../useColumnResize\";\nimport type { DataGridController } from \"../useGridController\";\n\ninterface UseGridCommandsOptions<Row> {\n controller: DataGridController<Row>;\n /** The app's commands, over the built-ins. */\n commands: GridOptions<Row>[\"commands\"];\n onCommand: GridOptions<Row>[\"onCommand\"];\n /** The grid's messages, over the defaults — what every built-in label reads. */\n messages: GridMessages;\n announce: (text: string) => void;\n resize: ColumnResizeApi<Row>;\n /** Opens one of the grid's panels — see `useGridPanels`. */\n openPanel: GridCommandHost[\"openPanel\"];\n}\n\nexport interface GridCommandsApi<Row> {\n /** Every command the grid knows, by id. */\n commands: ReadonlyMap<string, GridCommand<Row>>;\n /** What a command needs that only the grid has: its DOM, its live region. */\n host: GridCommandHost;\n /** A command context for `target`, over the grid as it is now. */\n contextFor: (target: GridCommandTarget) => GridCommandContext<Row>;\n /** Tells `onCommand` that a command, or an inline menu item, ran. */\n report: (\n commandId: string,\n target: GridCommandTarget,\n source: GridCommandSource,\n ) => void;\n /**\n * Runs the command `commandId` on `target` when it is visible and enabled\n * there, reports it, and says whether it ran.\n */\n run: (\n commandId: string,\n target: GridCommandTarget,\n source: GridCommandSource,\n ) => boolean;\n}\n\n/**\n * The commands behind the grid's menus — the built-ins and the app's own —\n * and the context they run in. Which command shows, is enabled or does what\n * is `@gridkitjs/core`'s; the grid lends them what needs a DOM — sizing a\n * column to its content, as double-clicking its resize handle does,\n * opening its panels, downloading an export, writing the clipboard and\n * printing — and its live region.\n */\nexport default function useGridCommands<Row>({\n controller,\n commands: appCommands,\n onCommand,\n messages,\n announce,\n resize,\n openPanel,\n}: UseGridCommandsOptions<Row>): GridCommandsApi<Row> {\n const commands = useMemo(() => resolveCommands(appCommands), [appCommands]);\n const saveFile = useSaveFile({ messages, announce });\n\n const host: GridCommandHost = {\n autoFitColumns: (columnIds) => {\n const { columns } = controller.getView();\n let fitted = 0;\n for (const columnId of columnIds) {\n const entry = columns.find((candidate) => candidate.id === columnId);\n if (entry !== undefined && resize.sizeToContent(entry)) {\n fitted += 1;\n }\n }\n // Each resize announced itself, and the live region keeps only the\n // last; one message for them all replaces it before anything is read.\n if (fitted > 1) {\n announce(messages.columnsAutoFitted(fitted));\n }\n },\n openPanel,\n announce,\n saveFile,\n writeClipboard: (content) => {\n copyToClipboard(content, { messages, announce });\n },\n print: (document, options) => {\n printGrid(document, options).catch((error: unknown) => {\n console.error(\"DataGrid: the print failed.\", error);\n });\n },\n };\n\n function contextFor(target: GridCommandTarget): GridCommandContext<Row> {\n return createCommandContext({ controller, target, messages, host });\n }\n\n function report(\n commandId: string,\n target: GridCommandTarget,\n source: GridCommandSource,\n ): void {\n onCommand?.({ commandId, target, source });\n }\n\n // A new object each render, as the other hooks here return.\n return {\n commands,\n host,\n contextFor,\n report,\n run: (commandId, target, source) => {\n const command = commands.get(commandId);\n if (command === undefined) {\n console.error(`DataGrid: there is no command \\`${commandId}\\` to run.`);\n return false;\n }\n if (!runCommand(command, contextFor(target))) {\n return false;\n }\n report(commandId, target, source);\n return true;\n },\n };\n}\n","import type { CopyContent, GridMessages } from \"@gridkitjs/core\";\nimport { writeClipboard } from \"@gridkitjs/dom\";\n\ninterface CopyToClipboardOptions {\n messages: GridMessages;\n announce: (text: string) => void;\n}\n\n/**\n * The host's `writeClipboard`: puts a copy on the clipboard and says so, as\n * nothing on screen does. A copy the browser refuses is logged for the\n * developer and announced for the user, who would otherwise paste whatever\n * the clipboard held before.\n */\nexport function copyToClipboard(\n content: CopyContent,\n { messages, announce }: CopyToClipboardOptions,\n): void {\n writeClipboard(content).then(\n () => {\n announce(messages.copied(content.count, content.unit));\n },\n (error: unknown) => {\n console.error(\"DataGrid: the clipboard could not be written.\", error);\n announce(messages.copyFailed);\n },\n );\n}\n","import { useRef } from \"react\";\nimport type {\n ExportFile,\n GridCommandHost,\n GridMessages,\n} from \"@gridkitjs/core\";\nimport { downloadBlob } from \"@gridkitjs/dom\";\nimport { exportBlob } from \"./exportApi\";\n\ninterface UseSaveFileOptions {\n messages: GridMessages;\n announce: (text: string) => void;\n}\n\nfunction download(file: ExportFile): void {\n downloadBlob(exportBlob(file), file.fileName);\n}\n\n/**\n * The host's `saveFile`: downloads an export, once its writer has finished\n * writing it.\n *\n * One at a time. An export asked for while a writer is still writing the\n * last is dropped and logged, so pressing a slow export twice saves one file\n * rather than two. A writer that fails is logged for the developer and\n * announced for the user, who asked for a file that will not come.\n */\nexport default function useSaveFile({\n messages,\n announce,\n}: UseSaveFileOptions): GridCommandHost[\"saveFile\"] {\n const writingRef = useRef(false);\n\n return (file) => {\n if (writingRef.current) {\n console.error(\n \"DataGrid: an export is still being written, so this one was dropped.\",\n );\n return;\n }\n if (!(file instanceof Promise)) {\n download(file);\n return;\n }\n writingRef.current = true;\n file\n .then(download, (error: unknown) => {\n console.error(\"DataGrid: the export's writer failed.\", error);\n announce(messages.exportFailed);\n })\n .finally(() => {\n writingRef.current = false;\n });\n };\n}\n","import {\n exportFile,\n resolveExportWriters,\n type ExportFile,\n type ExportWriter,\n type GridExportOptions,\n} from \"@gridkitjs/core\";\nimport type { GridCommandsApi } from \"../commands/useGridCommands\";\n\n/** What `DataGridApi` carries for exporting. */\nexport interface GridExportApi {\n /**\n * The grid's view exported as `format` — `\"csv\"`, `\"json\"`, a format\n * registered through `exportWriters`, or a writer passed as it is — and\n * handed back as a `Blob`, under the grid's `export` option with\n * `options` over it, field by field. Nothing is downloaded:\n * `runCommand(\"export.csv\")` downloads.\n *\n * Rejects for a format no writer is registered for, and when the writer\n * fails.\n */\n exportData(\n format: string | ExportWriter,\n options?: GridExportOptions,\n ): Promise<Blob>;\n}\n\n/**\n * An export's contents as a `Blob` of its media type. Text is stored as\n * UTF-8, a byte order mark the writer put first included, so a CSV opens in\n * a spreadsheet with its accents intact. Bytes are copied: a `Blob` takes\n * no view of shared memory, which a `Uint8Array` may be.\n */\nexport function exportBlob({ content, mimeType }: ExportFile): Blob {\n const part = typeof content === \"string\" ? content : content.slice();\n return new Blob([part], { type: mimeType });\n}\n\n/** `DataGridApi.exportData`, over the grid as it is when called. */\nexport function exportApi<Row>({\n contextFor,\n}: GridCommandsApi<Row>): GridExportApi {\n return {\n exportData: async (format, options) => {\n const context = contextFor({ area: \"grid\" });\n const { export: defaults, exportWriters } = context.options;\n const file = exportFile(\n context,\n format,\n { ...defaults, ...options },\n resolveExportWriters(exportWriters),\n );\n // `exportFile` has logged the format by name; the caller is told too.\n if (file === null) {\n throw new Error(\n \"DataGrid: there is no export writer for that format — register one through `exportWriters`.\",\n );\n }\n return exportBlob(await file);\n },\n };\n}\n","import {\n exportPrintDocument,\n type PrintDocument,\n type PrintOptions,\n} from \"@gridkitjs/core\";\nimport { printDocument, printStyles } from \"@gridkitjs/dom\";\nimport type { GridCommandsApi } from \"../commands/useGridCommands\";\n\n/** What `DataGridApi` carries for printing. */\nexport interface GridPrintApi {\n /**\n * Prints the grid's view through the browser's print dialog — every row\n * the filter leaves, across pages and collapsed groups, not only those\n * drawn — under the grid's `print` option with `options` over it, field\n * by field. Resolves once the dialog has closed, or at once while another\n * print is open.\n */\n print(options?: PrintOptions): Promise<void>;\n}\n\n/**\n * Puts a print document on paper through a hidden frame, under the print\n * stylesheet for its page with `options.styles` after it. The frame sees\n * none of the page's CSS, the theme's included.\n */\nexport function printGrid(\n document: PrintDocument,\n { styles = \"\" }: PrintOptions,\n): Promise<void> {\n return printDocument({\n title: document.title,\n bodyHtml: document.bodyHtml,\n styles: printStyles(document.page) + styles,\n });\n}\n\n/** `DataGridApi.print`, over the grid as it is when called. */\nexport function printApi<Row>({\n contextFor,\n}: GridCommandsApi<Row>): GridPrintApi {\n return {\n print: (options) => {\n const context = contextFor({ area: \"grid\" });\n const merged = { ...context.options.print, ...options };\n return printGrid(exportPrintDocument(context, merged), merged);\n },\n };\n}\n","import { useLayoutEffect, useRef, useState, type RefObject } from \"react\";\nimport type {\n ResolvedMenuEntry,\n ResolvedMenuItem,\n ResolvedMenuSubmenu,\n} from \"@gridkitjs/core\";\nimport {\n attachMenu,\n type AttachedMenu,\n type MenuSubmenuFocus,\n} from \"@gridkitjs/dom\";\nimport { ariaAttr } from \"../ariaAttr\";\nimport Overlay from \"../overlay/Overlay\";\nimport { CheckIcon, ChevronRightIcon, MenuIcon } from \"./menuIcons\";\n\ninterface GridMenuProps {\n entries: readonly ResolvedMenuEntry[];\n /** The menu's accessible name. */\n label: string;\n /** The palette its submenus take — the one its own overlay took. */\n themeClassName: string;\n /** An enabled item was chosen: run it, and close every menu. */\n onRun: (item: ResolvedMenuItem) => void;\n /** Tab or Shift+Tab: close every menu. */\n onClose: () => void;\n /**\n * ArrowLeft: close this menu, which is a submenu, so focus goes back to\n * the item that opened it. Given only to a submenu; a menu without it has\n * nowhere to go back to.\n */\n onCloseSubmenu?: (() => void) | undefined;\n /**\n * Holds this menu's behaviour while it is attached, for the menu that\n * opened it to move focus in.\n */\n behaviourRef?: RefObject<AttachedMenu | null> | undefined;\n}\n\n/** The submenu open from a menu. */\ninterface OpenSubmenu {\n readonly id: string;\n /** The item it opened from, which it opens beside. */\n readonly anchor: HTMLElement;\n readonly focus: MenuSubmenuFocus;\n /** Lines its first item up with `anchor`. */\n readonly offset: number;\n}\n\n/** The item of `menu` whose id is `id`, read off the markup this drew. */\nfunction itemElement(menu: HTMLElement, id: string): HTMLElement | null {\n return (\n Array.from(\n menu.querySelectorAll<HTMLElement>(\"[data-gridkit-menu-item]\"),\n ).find((item) => item.getAttribute(\"data-gridkit-menu-item\") === id) ?? null\n );\n}\n\n/**\n * How far below a menu's top edge its first item starts: its top border and\n * padding. A submenu is styled the same, so opening it this far up lines its\n * first item up with the item that opened it, whatever the theme makes them.\n */\nfunction topInset(menu: HTMLElement): number {\n const style = getComputedStyle(menu);\n return parseFloat(style.borderTopWidth) + parseFloat(style.paddingTop);\n}\n\nfunction MenuItem({\n entry,\n expanded,\n}: {\n entry: ResolvedMenuItem | ResolvedMenuSubmenu;\n /** For a submenu item: whether its submenu is open. */\n expanded: boolean;\n}) {\n const isItem = entry.type === \"item\";\n const checked = isItem ? entry.checked : undefined;\n const shortcut = isItem ? entry.shortcut : undefined;\n return (\n <div\n role={checked === undefined ? \"menuitem\" : \"menuitemcheckbox\"}\n data-gridkit-menu-item={entry.id}\n className=\"menu-item\"\n {...ariaAttr(isItem && entry.disabled, \"aria-disabled\", true)}\n {...ariaAttr(checked !== undefined, \"aria-checked\", checked)}\n {...ariaAttr(shortcut !== undefined, \"aria-keyshortcuts\", shortcut)}\n {...ariaAttr<\"aria-haspopup\", \"menu\">(!isItem, \"aria-haspopup\", \"menu\")}\n {...ariaAttr(!isItem, \"aria-expanded\", expanded)}\n >\n <span className=\"menu-item-icon\" aria-hidden=\"true\">\n {checked === true ? <CheckIcon /> : <MenuIcon name={entry.icon} />}\n </span>\n <span className=\"menu-item-label\">{entry.label}</span>\n {/* Read out through `aria-keyshortcuts`, not as part of the name. */}\n {shortcut !== undefined && (\n <span className=\"menu-item-shortcut\" aria-hidden=\"true\">\n {shortcut}\n </span>\n )}\n {!isItem && (\n <span className=\"menu-submenu-indicator\" aria-hidden=\"true\">\n <ChevronRightIcon />\n </span>\n )}\n </div>\n );\n}\n\n/**\n * A menu resolved by `@gridkitjs/core`'s `resolveMenu`, drawn as\n * `role=\"menu\"` and made to behave as one by `@gridkitjs/dom`'s\n * `attachMenu`, which decides what every key and hover does; this draws the\n * items and which submenu is open. Shown inside an `Overlay` — which attaches\n * after this, so its initial focus lands on the item `attachMenu` made the\n * tab stop.\n *\n * A submenu is a `GridMenu` of its own, in an `Overlay` of its own anchored\n * to the item that opened it.\n */\nexport default function GridMenu({\n entries,\n label,\n themeClassName,\n onRun,\n onClose,\n onCloseSubmenu,\n behaviourRef,\n}: GridMenuProps) {\n const menuRef = useRef<HTMLDivElement>(null);\n const submenuBehaviourRef = useRef<AttachedMenu | null>(null);\n const [submenu, setSubmenu] = useState<OpenSubmenu | null>(null);\n const isSubmenu = onCloseSubmenu !== undefined;\n\n /**\n * What the behaviour's callbacks read. They are handed over once, when it\n * attaches, so they read the props and state of the latest render here.\n */\n const latest = useRef({ entries, submenu, onRun, onClose, onCloseSubmenu });\n useLayoutEffect(() => {\n latest.current = { entries, submenu, onRun, onClose, onCloseSubmenu };\n });\n\n useLayoutEffect(() => {\n const menu = menuRef.current;\n if (menu === null) {\n return undefined;\n }\n const behaviour = attachMenu(menu, {\n onActivate: (id) => {\n const item = latest.current.entries.find(\n (entry): entry is ResolvedMenuItem =>\n entry.type === \"item\" && entry.id === id,\n );\n if (item !== undefined) {\n latest.current.onRun(item);\n }\n },\n onOpenSubmenu: (id, { focus }) => {\n // Already open — the pointer opened it — so the keyboard only asks\n // for focus to move into it.\n if (latest.current.submenu?.id === id) {\n if (focus === \"first\") {\n submenuBehaviourRef.current?.focusItem(0);\n }\n return;\n }\n const anchor = itemElement(menu, id);\n if (anchor !== null) {\n setSubmenu({ id, anchor, focus, offset: -topInset(menu) });\n }\n },\n onCollapseSubmenu: () => {\n setSubmenu(null);\n },\n onCloseSubmenu: isSubmenu\n ? () => {\n latest.current.onCloseSubmenu?.();\n }\n : undefined,\n onClose: () => {\n latest.current.onClose();\n },\n });\n if (behaviourRef !== undefined) {\n behaviourRef.current = behaviour;\n }\n return () => {\n if (behaviourRef !== undefined) {\n behaviourRef.current = null;\n }\n behaviour.detach();\n };\n }, [isSubmenu, behaviourRef]);\n\n function closeSubmenu(): void {\n setSubmenu(null);\n }\n\n const openEntry =\n submenu === null\n ? undefined\n : entries.find(\n (entry): entry is ResolvedMenuSubmenu =>\n entry.type === \"submenu\" && entry.id === submenu.id,\n );\n\n return (\n <>\n <div\n ref={menuRef}\n role=\"menu\"\n aria-label={label}\n className=\"gridkit-menu\"\n >\n {entries.map((entry) =>\n entry.type === \"separator\" ? (\n <div key={entry.key} role=\"separator\" className=\"menu-separator\" />\n ) : (\n <MenuItem\n key={entry.id}\n entry={entry}\n expanded={entry.id === submenu?.id}\n />\n ),\n )}\n </div>\n {submenu !== null && openEntry !== undefined && (\n <Overlay\n key={submenu.id}\n anchor={submenu.anchor}\n placement=\"right-start\"\n offset={submenu.offset}\n initialFocus={submenu.focus}\n themeClassName={themeClassName}\n onDismiss={closeSubmenu}\n >\n <GridMenu\n entries={openEntry.items}\n label={openEntry.label}\n themeClassName={themeClassName}\n onRun={onRun}\n onClose={onClose}\n onCloseSubmenu={closeSubmenu}\n behaviourRef={submenuBehaviourRef}\n />\n </Overlay>\n )}\n </>\n );\n}\n","import { useLayoutEffect, useRef, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n attachOverlay,\n type OverlayAnchor,\n type OverlayDismissReason,\n type OverlayInitialFocus,\n type OverlayPlacement,\n} from \"@gridkitjs/dom\";\nimport { classNames } from \"../classNames\";\n\ninterface OverlayProps {\n /**\n * What the overlay opens beside: an element, or a point. It and the\n * options after it are read when the overlay attaches, and a change to any\n * of them attaches it afresh — moving focus back in — so each should stay\n * the same for as long as the overlay is open.\n */\n anchor: OverlayAnchor;\n placement?: OverlayPlacement | undefined;\n gap?: number | undefined;\n offset?: number | undefined;\n /**\n * Where focus goes on attaching — see `attachOverlay`'s option — or a ref\n * to the control it goes to, read as the overlay attaches, once its\n * children have mounted, so that it can be one of theirs. A ref holding\n * nothing sends it to the first control.\n */\n initialFocus?:\n OverlayInitialFocus | RefObject<HTMLElement | null> | undefined;\n returnFocusTo?: HTMLElement | null | undefined;\n /** See `attachOverlay`'s option: a panel whose controls change the grid under it. */\n ignoreScrollAfterInput?: boolean | undefined;\n /** See `attachOverlay`'s option: Tab stays inside, as in a dialog. */\n trapFocus?: boolean | undefined;\n /** The palette the overlay takes — see `overlayThemeClassName`. */\n themeClassName: string;\n /** The overlay asks to close; the caller unmounts it, or not. */\n onDismiss: (reason: OverlayDismissReason) => void;\n children: ReactNode;\n}\n\n/**\n * The space between a menu or panel and the element it opens below — a\n * toolbar button, a header — so its shadow does not run into that element's\n * border. Nothing opened at a point, or beside its own menu, as a submenu is,\n * takes it.\n */\nexport const ANCHOR_GAP = 4;\n\n/** `focus` as `attachOverlay` takes it, reading a ref's control now. */\nfunction attachedFocus(\n focus: OverlayProps[\"initialFocus\"],\n): OverlayInitialFocus | undefined {\n return typeof focus === \"object\" && !(focus instanceof HTMLElement)\n ? (focus.current ?? \"first\")\n : focus;\n}\n\n/**\n * The palette class an overlay opened from `element` copies:\n * `gridkit-light` or `gridkit-dark`, from the nearest ancestor carrying one,\n * or none to follow the page. An overlay renders into `document.body`, out of\n * reach of the tokens that ancestor sets.\n */\nexport function overlayThemeClassName(element: Element | null): string {\n const scope = element?.closest(\".gridkit-light, .gridkit-dark\");\n if (scope === null || scope === undefined) {\n return \"\";\n }\n return scope.classList.contains(\"gridkit-dark\")\n ? \"gridkit-dark\"\n : \"gridkit-light\";\n}\n\n/**\n * `children` in a panel portalled into `document.body` — where no scrolling\n * ancestor of the grid clips it — shown beside `anchor` by\n * `@gridkitjs/dom`'s `attachOverlay` for as long as it is mounted.\n *\n * Attached in a layout effect, which React runs after its children's: a menu\n * inside attaches its own behaviour first, so the overlay's initial focus\n * finds the item that behaviour made the tab stop. A nested overlay — a\n * submenu — mounts on a later user action than the one it opens from, so it\n * attaches after it and sits above it in the overlay stack.\n */\nexport default function Overlay({\n anchor,\n placement,\n gap,\n offset,\n initialFocus,\n returnFocusTo,\n ignoreScrollAfterInput,\n trapFocus,\n themeClassName,\n onDismiss,\n children,\n}: OverlayProps) {\n const panelRef = useRef<HTMLDivElement>(null);\n // Read through a ref, so a new handler every render does not re-attach.\n const onDismissRef = useRef(onDismiss);\n useLayoutEffect(() => {\n onDismissRef.current = onDismiss;\n });\n\n useLayoutEffect(() => {\n const panel = panelRef.current;\n if (panel === null) {\n return undefined;\n }\n return attachOverlay(anchor, panel, {\n placement,\n gap,\n offset,\n initialFocus: attachedFocus(initialFocus),\n returnFocusTo,\n ignoreScrollAfterInput,\n trapFocus,\n onDismiss: (reason) => {\n onDismissRef.current(reason);\n },\n });\n }, [\n anchor,\n placement,\n gap,\n offset,\n initialFocus,\n returnFocusTo,\n ignoreScrollAfterInput,\n trapFocus,\n ]);\n\n return createPortal(\n <div\n ref={panelRef}\n className={classNames(\"gridkit-overlay\", themeClassName)}\n >\n {children}\n </div>,\n document.body,\n );\n}\n","import type { ReactNode } from \"react\";\nimport type { BuiltInCommandIcon } from \"@gridkitjs/core\";\nimport { GroupIcon, Icon } from \"../icons\";\n\n/** A glyph for every icon key the built-in commands carry. */\nconst BUILT_IN_ICONS: Readonly<Record<BuiltInCommandIcon, () => ReactNode>> = {\n sortAscending: () => (\n <Icon>\n <path d=\"m3 8 4-4 4 4\" />\n <path d=\"M7 4v16\" />\n <path d=\"M11 12h4\" />\n <path d=\"M11 16h7\" />\n <path d=\"M11 20h10\" />\n </Icon>\n ),\n sortDescending: () => (\n <Icon>\n <path d=\"m3 16 4 4 4-4\" />\n <path d=\"M7 20V4\" />\n <path d=\"M11 4h10\" />\n <path d=\"M11 8h7\" />\n <path d=\"M11 12h4\" />\n </Icon>\n ),\n group: () => <GroupIcon />,\n hide: () => (\n <Icon>\n <path d=\"M9.88 9.88a3 3 0 1 0 4.24 4.24\" />\n <path d=\"M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68\" />\n <path d=\"M6.61 6.61A13.53 13.53 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61\" />\n <path d=\"m2 2 20 20\" />\n </Icon>\n ),\n autoFit: () => (\n <Icon>\n <path d=\"m18 8 4 4-4 4\" />\n <path d=\"M2 12h20\" />\n <path d=\"m6 8-4 4 4 4\" />\n </Icon>\n ),\n copy: () => (\n <Icon>\n <rect x=\"8\" y=\"8\" width=\"14\" height=\"14\" rx=\"2\" />\n <path d=\"M4 16a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2\" />\n </Icon>\n ),\n print: () => (\n <Icon>\n <path d=\"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2\" />\n <path d=\"M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6\" />\n <rect x=\"6\" y=\"14\" width=\"12\" height=\"8\" rx=\"1\" />\n </Icon>\n ),\n};\n\n/**\n * Looked up through a `Map`, since an item's key may be any string an app\n * chose, and one such as `\"toString\"` must find nothing rather than\n * something on `Object.prototype`.\n */\nconst ICONS = new Map(Object.entries(BUILT_IN_ICONS));\n\n/** The icon a key names, or nothing for a key the grid has no glyph for. */\nexport function MenuIcon({ name }: { name: string | undefined }) {\n const draw = name === undefined ? undefined : ICONS.get(name);\n return draw === undefined ? null : draw();\n}\n\n/** What a checked item shows in place of its icon. */\nexport function CheckIcon() {\n return (\n <Icon>\n <path d=\"M20 6 9 17l-5-5\" />\n </Icon>\n );\n}\n\n/** Marks a button that opens a menu below it. */\nexport function ChevronDownIcon() {\n return (\n <Icon>\n <path d=\"m6 9 6 6 6-6\" />\n </Icon>\n );\n}\n\n/** Marks a button going back to what a panel showed before. */\nexport function ChevronLeftIcon() {\n return (\n <Icon>\n <path d=\"m15 18-6-6 6-6\" />\n </Icon>\n );\n}\n\n/** Marks an item that opens a submenu. */\nexport function ChevronRightIcon() {\n return (\n <Icon>\n <path d=\"m9 18 6-6-6-6\" />\n </Icon>\n );\n}\n","import GridMenu from \"../menu/GridMenu\";\nimport Overlay, { ANCHOR_GAP } from \"../overlay/Overlay\";\nimport type { ContextMenuApi } from \"./useContextMenu\";\n\n/**\n * The open context menu, if any — beside the point it was asked for at, or\n * below its cell when asked for by a key — returning focus to that cell when\n * it closes, or, from the body's empty space, to wherever focus was before.\n * Rendered after the grid's tables, as every grid overlay is, so\n * the keys pressed in it reach no header or body handler on their way up\n * React's tree.\n */\nexport default function GridContextMenu({\n contextMenu,\n}: {\n contextMenu: ContextMenuApi;\n}) {\n const { menu, run, close } = contextMenu;\n if (menu === null) {\n return null;\n }\n return (\n <Overlay\n key={menu.key}\n anchor={menu.anchor}\n gap={menu.anchor instanceof Element ? ANCHOR_GAP : 0}\n returnFocusTo={menu.cell ?? undefined}\n themeClassName={menu.themeClassName}\n onDismiss={close}\n >\n <GridMenu\n entries={menu.entries}\n label={menu.label}\n themeClassName={menu.themeClassName}\n onRun={run}\n onClose={close}\n />\n </Overlay>\n );\n}\n","import {\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type RefObject,\n} from \"react\";\nimport {\n contextMenuEntries,\n hasContextMenu,\n isSameCell,\n resolveMenu,\n type GridContextMenuArea,\n type GridContextMenuTarget,\n type GridMessages,\n type GridOptions,\n type ResolvedMenuEntry,\n type ResolvedMenuItem,\n} from \"@gridkitjs/core\";\nimport {\n attachContextMenuTrigger,\n type ContextMenuRequest,\n type OverlayAnchor,\n} from \"@gridkitjs/dom\";\nimport type { GridCommandsApi } from \"../commands/useGridCommands\";\nimport { overlayThemeClassName } from \"../overlay/Overlay\";\nimport type { DataGridController } from \"../useGridController\";\nimport type { GridNavigationApi } from \"../useGridNavigation\";\nimport type { GridSelectionApi } from \"../useGridSelection\";\nimport {\n placeAt,\n placeOf,\n type ContextMenuPlace,\n type GridParts,\n} from \"./contextMenuPlaces\";\n\ninterface UseContextMenuOptions<Row> {\n /** The grid's root element: a menu is asked for on what is inside it. */\n rootRef: RefObject<HTMLElement | null>;\n headerTableRef: RefObject<HTMLTableElement | null>;\n bodyTableRef: RefObject<HTMLTableElement | null>;\n /** The body's scrolling region, whose empty space is the `body` area. */\n bodyScrollRef: RefObject<HTMLElement | null>;\n contextMenu: GridOptions<Row>[\"contextMenu\"];\n onContextMenuOpenChange: GridOptions<Row>[\"onContextMenuOpenChange\"];\n controller: DataGridController<Row>;\n commands: GridCommandsApi<Row>;\n nav: GridNavigationApi;\n selection: GridSelectionApi;\n messages: GridMessages;\n /** What a column is called in a menu's name. */\n columnName: (columnId: string) => string;\n}\n\n/** The context menu open now. */\nexport interface OpenContextMenu {\n /** Counts the openings, so one opened over another replaces it. */\n readonly key: number;\n readonly target: GridContextMenuTarget;\n readonly entries: readonly ResolvedMenuEntry[];\n /** Its accessible name. */\n readonly label: string;\n /** The point it was asked for at, or its cell when asked for by a key. */\n readonly anchor: OverlayAnchor;\n /**\n * The cell it opened on, which has focus first and gets it back after —\n * `null` in the body's empty space, which leaves focus where it was.\n */\n readonly cell: HTMLElement | null;\n readonly themeClassName: string;\n}\n\nexport interface ContextMenuApi {\n menu: OpenContextMenu | null;\n /** Whether `area` opens a menu — for the `aria-keyshortcuts` of its cells. */\n opens: (area: GridContextMenuArea) => boolean;\n /**\n * Opens the menu `target` has, as a right-click there would, beside\n * `anchor` or below its cell, and says whether it did: not for a target\n * that is not on screen, or whose menu is empty.\n */\n open: (target: GridContextMenuTarget, anchor?: OverlayAnchor) => boolean;\n /** Runs the item the user chose, reporting it if it ran, then closes the menu. */\n run: (item: ResolvedMenuItem) => void;\n close: () => void;\n}\n\n/**\n * The grid's context menu. `@gridkitjs/dom`'s trigger reports a right-click,\n * Shift+F10 or the ContextMenu key inside the grid, and the ref can ask for\n * one too; the `contextMenu` option and `@gridkitjs/core`'s `resolveMenu`\n * say what menu that place has; this holds which one is open, tells\n * `onContextMenuOpenChange`, and does what opening it means in the grid.\n *\n * Opening one on a column, row or cell that is not selected selects it\n * first, where that kind is selectable, as a click on it would — opening one\n * inside the selection keeps it, so a menu can act on everything selected.\n * Focus moves to the cell first, so closing the menu returns it there. A\n * place whose menu resolves to nothing shows the browser's own.\n */\nexport default function useContextMenu<Row>({\n rootRef,\n headerTableRef,\n bodyTableRef,\n bodyScrollRef,\n contextMenu,\n onContextMenuOpenChange,\n controller,\n commands,\n nav,\n selection,\n messages,\n columnName,\n}: UseContextMenuOptions<Row>): ContextMenuApi {\n const [menu, setMenu] = useState<OpenContextMenu | null>(null);\n /** The menu open as of the last change, ahead of the render that draws it. */\n const current = useRef<OpenContextMenu | null>(null);\n const openings = useRef(0);\n const enabled = contextMenu !== undefined && contextMenu !== false;\n\n function parts(): GridParts<Row> {\n const { columns, pageRows } = controller.getView();\n return {\n root: rootRef.current,\n headerTable: headerTableRef.current,\n bodyTable: bodyTableRef.current,\n body: bodyScrollRef.current,\n columns,\n pageRows,\n };\n }\n\n function labelOf(target: GridContextMenuTarget): string {\n switch (target.area) {\n case \"header\":\n return messages.headerMenuLabel(columnName(target.columnId));\n case \"cell\":\n return messages.cellMenuLabel;\n case \"group\":\n return messages.groupMenuLabel;\n case \"body\":\n return messages.bodyMenuLabel;\n }\n }\n\n /**\n * Selects what the menu opens on unless it is selected already, and says\n * whether it did. Each kind follows its own `selectable` mode, as a click\n * does — a cell's row and the cell itself apart — and a kind a user cannot\n * select is left alone.\n */\n function selectTarget(target: GridContextMenuTarget): boolean {\n const state = controller.getState();\n if (target.area === \"header\") {\n if (\n selection.columnMode === false ||\n state.columnSelection.includes(target.columnId)\n ) {\n return false;\n }\n controller.selectColumn(target.columnId, \"replace\");\n return true;\n }\n if (target.area !== \"cell\") {\n return false;\n }\n const cell = { rowId: target.rowId, columnId: target.columnId };\n const selectRow =\n selection.rowMode !== false && !state.rowSelection.includes(target.rowId);\n const selectCell =\n selection.cellMode !== false && !isSameCell(state.cellSelection, cell);\n if (selectRow) {\n controller.selectRow(target.rowId, \"replace\");\n }\n if (selectCell) {\n controller.selectCell(cell, \"replace\");\n }\n return selectRow || selectCell;\n }\n\n /** The menu `target` has, over the grid as it is now. */\n function resolveFor(\n target: GridContextMenuTarget,\n ): readonly ResolvedMenuEntry[] {\n const context = commands.contextFor(target);\n return resolveMenu(contextMenuEntries(contextMenu, context), {\n commands: commands.commands,\n context,\n });\n }\n\n /**\n * Shows `next` in place of the menu open, or closes it with `null`, and\n * tells `onContextMenuOpenChange` — the one closing first.\n */\n function show(next: OpenContextMenu | null): void {\n const previous = current.current;\n if (previous === next) {\n return;\n }\n current.current = next;\n setMenu(next);\n if (previous !== null) {\n onContextMenuOpenChange?.({ open: false, target: previous.target });\n }\n if (next !== null) {\n onContextMenuOpenChange?.({ open: true, target: next.target });\n }\n }\n\n function openAt(\n { target, cell, anchor }: ContextMenuPlace,\n point: OverlayAnchor | null,\n ): boolean {\n let resolved = resolveFor(target);\n if (resolved.length === 0) {\n return false;\n }\n // Resolved again against the selection the menu now acts on.\n if (selectTarget(target)) {\n resolved = resolveFor(target);\n }\n if (cell !== null && document.activeElement !== cell.element) {\n // Focused without scrolling first: a scroll would close the menu about\n // to open beside it. Moving the tab stop after it then finds the cell\n // focused already.\n cell.element.focus({ preventScroll: true });\n nav.focusCellNow(cell.rowIndex, cell.columnIndex);\n }\n openings.current += 1;\n show({\n key: openings.current,\n target,\n entries: resolved,\n label: labelOf(target),\n anchor: point ?? anchor,\n cell: cell?.element ?? null,\n themeClassName: overlayThemeClassName(rootRef.current),\n });\n return true;\n }\n\n function handleRequest({ target, point }: ContextMenuRequest): boolean {\n const place = placeAt(target, parts());\n return place !== null && openAt(place, point);\n }\n\n // The trigger is attached once, and hears every request through this.\n const latestRequest = useRef(handleRequest);\n useLayoutEffect(() => {\n latestRequest.current = handleRequest;\n });\n\n useEffect(() => {\n const root = rootRef.current;\n if (!enabled || root === null) {\n return undefined;\n }\n return attachContextMenuTrigger(root, {\n onRequest: (request) => latestRequest.current(request),\n });\n }, [rootRef, enabled]);\n\n /**\n * The cell a menu returns focus to can go with what the menu did — a\n * hidden column takes its header — and focus then falls to the page.\n * It goes to the cell now holding the grid's tab stop instead.\n */\n const shown = useRef<OpenContextMenu | null>(null);\n useLayoutEffect(() => {\n const closed = shown.current;\n shown.current = menu;\n if (\n menu === null &&\n closed !== null &&\n closed.cell !== null &&\n !closed.cell.isConnected &&\n document.activeElement === document.body\n ) {\n nav.focusTabStop();\n }\n });\n\n function close(): void {\n show(null);\n }\n\n return {\n menu,\n opens: (area) => hasContextMenu(contextMenu, area),\n open: (target, anchor) => {\n const place = placeOf(target, parts());\n return place !== null && openAt(place, anchor ?? null);\n },\n run: (item) => {\n const open = current.current;\n if (item.run() && open !== null) {\n commands.report(item.id, open.target, \"contextMenu\");\n }\n close();\n },\n close,\n };\n}\n","import {\n HEADER_ROW,\n type DisplayRow,\n type GridContextMenuTarget,\n} from \"@gridkitjs/core\";\nimport {\n bodyCellFrom,\n bodyRowFrom,\n findBodyRow,\n groupRowFrom,\n type OverlayAnchor,\n} from \"@gridkitjs/dom\";\n\n/** The cell a menu opens on, with its place in the grid's focus. */\nexport interface TargetCell {\n readonly element: HTMLTableCellElement;\n readonly rowIndex: number;\n readonly columnIndex: number;\n}\n\n/** Where a context menu opens: its target, and what it is drawn on. */\nexport interface ContextMenuPlace {\n readonly target: GridContextMenuTarget;\n /** The cell that has focus while it is open; `null` in the body's empty space. */\n readonly cell: TargetCell | null;\n /**\n * What it goes beside when asked for without a point: the cell — or, for a\n * cell scrolled out of the grid's view, the nearest point on that view's\n * edge — or the body's corner.\n */\n readonly anchor: OverlayAnchor;\n}\n\n/** The parts of the grid, as drawn now, that a place is found among. */\nexport interface GridParts<Row> {\n /** The grid's root, which scrolls sideways. */\n readonly root: HTMLElement | null;\n readonly headerTable: HTMLTableElement | null;\n readonly bodyTable: HTMLTableElement | null;\n /** The body's scrolling region, whose empty space is the `body` area. */\n readonly body: HTMLElement | null;\n /** The columns shown, in order — what a cell's column index counts. */\n readonly columns: readonly { readonly id: string }[];\n /** The rows of the page, as `data-gridkit-row-index` counts them. */\n readonly pageRows: readonly DisplayRow<Row>[];\n}\n\nfunction headerCell(\n parts: GridParts<unknown>,\n columnIndex: number,\n): TargetCell | null {\n const element = parts.headerTable?.tHead?.rows[0]?.cells[columnIndex];\n return element === undefined\n ? null\n : { element, rowIndex: HEADER_ROW, columnIndex };\n}\n\nfunction bodyCell(\n parts: GridParts<unknown>,\n rowIndex: number,\n columnIndex: number,\n): TargetCell | null {\n const element = findBodyRow(parts.bodyTable, rowIndex)?.cells[columnIndex];\n return element === undefined ? null : { element, rowIndex, columnIndex };\n}\n\n/** The part of the viewport where `element` can be seen: its grid's scrolled view. */\nfunction viewOf(element: Element, parts: GridParts<unknown>): DOMRect | null {\n const root = parts.root?.getBoundingClientRect();\n if (root === undefined) {\n return null;\n }\n const body =\n parts.body?.contains(element) === true\n ? parts.body.getBoundingClientRect()\n : root;\n const left = Math.max(root.left, body.left);\n const top = Math.max(root.top, body.top);\n return new DOMRect(\n left,\n top,\n Math.max(0, Math.min(root.right, body.right) - left),\n Math.max(0, Math.min(root.bottom, body.bottom) - top),\n );\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * A cell's place, anchored to the cell itself while any of it is in the\n * grid's view (a group row's cell can be wider than the view). One scrolled\n * wholly out of it — the ref can ask for any cell drawn — is\n * anchored to the point of the view nearest its bottom-left corner instead,\n * so the menu opens at the grid's edge rather than off in the page, over\n * whatever the grid's scrolling hides it under.\n */\nfunction onCell(\n target: GridContextMenuTarget,\n cell: TargetCell | null,\n parts: GridParts<unknown>,\n): ContextMenuPlace | null {\n if (cell === null) {\n return null;\n }\n const box = cell.element.getBoundingClientRect();\n const view = viewOf(cell.element, parts);\n if (\n view === null ||\n (box.right > view.left &&\n box.left < view.right &&\n box.bottom > view.top &&\n box.top < view.bottom)\n ) {\n return { target, cell, anchor: cell.element };\n }\n return {\n target,\n cell,\n anchor: {\n x: clamp(box.left, view.left, view.right),\n y: clamp(box.bottom, view.top, view.bottom),\n },\n };\n}\n\n/** The body's empty space, anchored to its top-left corner. */\nfunction onBody(body: HTMLElement): ContextMenuPlace {\n const { left, top } = body.getBoundingClientRect();\n return { target: { area: \"body\" }, cell: null, anchor: { x: left, y: top } };\n}\n\nfunction headerPlaceAt<Row>(\n element: Element,\n parts: GridParts<Row>,\n): ContextMenuPlace | null {\n const cell = element.closest<HTMLTableCellElement>(\"th[data-gridkit-column]\");\n const columnId = cell?.getAttribute(\"data-gridkit-column\");\n if (\n cell === null ||\n cell.parentElement !== parts.headerTable?.tHead?.rows[0] ||\n columnId === null ||\n columnId === undefined\n ) {\n return null;\n }\n return onCell(\n { area: \"header\", columnId },\n headerCell(parts, cell.cellIndex),\n parts,\n );\n}\n\n/**\n * A data cell or a group row of the body, read off the rows of the page, or\n * the body's empty space. A cell must be the one `element` is in, not one of\n * a table some cell template holds, which has rows of its own. A group's\n * summary row, with nothing of its own to act on, has no place.\n */\nfunction bodyPlaceAt<Row>(\n element: Element,\n parts: GridParts<Row>,\n): ContextMenuPlace | null {\n const { body, pageRows } = parts;\n if (body === null || !body.contains(element)) {\n return null;\n }\n const group = groupRowFrom(element);\n if (group !== null) {\n const entry = pageRows[group.rowIndex];\n const cell = bodyCell(parts, group.rowIndex, 0);\n return entry !== undefined &&\n \"kind\" in entry &&\n entry.kind === \"group\" &&\n cell?.element.contains(element) === true\n ? onCell(\n { area: \"group\", groupId: entry.groupId, columnId: entry.columnId },\n cell,\n parts,\n )\n : null;\n }\n const position = bodyCellFrom(element);\n if (position !== null) {\n const entry = pageRows[position.rowIndex];\n const cell = bodyCell(parts, position.rowIndex, position.columnIndex);\n return entry !== undefined &&\n !(\"kind\" in entry) &&\n cell?.element.contains(element) === true\n ? onCell(\n { area: \"cell\", rowId: entry.rowId, columnId: position.columnId },\n cell,\n parts,\n )\n : null;\n }\n return bodyRowFrom(element) === null ? onBody(body) : null;\n}\n\n/**\n * The place `element` is in — a header, a data cell, a group row or the\n * body's empty space — or `null` for anything else in the grid: the footer,\n * the pager, the group-by bar.\n */\nexport function placeAt<Row>(\n element: Element,\n parts: GridParts<Row>,\n): ContextMenuPlace | null {\n return headerPlaceAt(element, parts) ?? bodyPlaceAt(element, parts);\n}\n\n/**\n * The place `target` names, among what is drawn now — `null` for a column,\n * row or group not on screen: hidden, on another page, in a collapsed group\n * or outside a virtualized window.\n */\nexport function placeOf<Row>(\n target: GridContextMenuTarget,\n parts: GridParts<Row>,\n): ContextMenuPlace | null {\n const columnIndexOf = (columnId: string) =>\n parts.columns.findIndex((column) => column.id === columnId);\n switch (target.area) {\n case \"header\":\n return onCell(\n target,\n headerCell(parts, columnIndexOf(target.columnId)),\n parts,\n );\n case \"cell\": {\n const rowIndex = parts.pageRows.findIndex(\n (entry) => !(\"kind\" in entry) && entry.rowId === target.rowId,\n );\n return onCell(\n target,\n bodyCell(parts, rowIndex, columnIndexOf(target.columnId)),\n parts,\n );\n }\n case \"group\": {\n const rowIndex = parts.pageRows.findIndex(\n (entry) =>\n \"kind\" in entry &&\n entry.kind === \"group\" &&\n entry.groupId === target.groupId,\n );\n return onCell(target, bodyCell(parts, rowIndex, 0), parts);\n }\n case \"body\":\n return parts.body === null ? null : onBody(parts.body);\n }\n}\n","import { useRef, type ReactNode, type RefCallback } from \"react\";\nimport type {\n ColumnValueOptions,\n FilterState,\n GridCommandTarget,\n GridMessages,\n GridPanelKind,\n} from \"@gridkitjs/core\";\nimport ColumnChooser from \"../columnChooser/ColumnChooser\";\nimport type { GridCommandsApi } from \"../commands/useGridCommands\";\nimport FilterMenu from \"../filterMenu/FilterMenu\";\nimport useApplyFilter from \"../filterMenu/useApplyFilter\";\nimport useFilterValueCache from \"../filterMenu/useFilterValueCache\";\nimport Overlay, { ANCHOR_GAP } from \"../overlay/Overlay\";\nimport type { DataGridController } from \"../useGridController\";\nimport type { GridPanelsApi } from \"./useGridPanels\";\n\n/** What every panel is drawn with. */\nexport interface GridPanelProps<Row> {\n /** Where it was asked for — a header's names the column a panel acts on. */\n readonly target: GridCommandTarget;\n /** Read for the grid's state as each render draws it, and acted on. */\n readonly controller: DataGridController<Row>;\n /** The grid's commands, for a panel running one so `onCommand` hears it. */\n readonly commands: GridCommandsApi<Row>;\n readonly messages: GridMessages;\n /** Closes the panel, giving focus back to where it was opened from. */\n readonly close: () => void;\n /**\n * The `ref` of the control focus starts on as the panel opens — a filter\n * editor's value box. A panel giving it to none starts on its first\n * control.\n */\n readonly initialFocusRef: RefCallback<HTMLElement>;\n /**\n * Sets the grid's filter as a filter menu applies one, announcing the rows\n * it keeps once they are drawn — even when the menu has closed by then.\n */\n readonly applyFilter: (filter: FilterState<Row>) => void;\n /**\n * The values a filter checklist lists for a column, counted once and\n * handed back again while nothing they are counted from changes — kept\n * by the panel host, so reopening a column's menu reuses its list.\n */\n readonly columnValues: (columnId: string) => ColumnValueOptions;\n}\n\n/** How one kind of panel is drawn. */\ninterface PanelKind {\n readonly component: <Row>(props: GridPanelProps<Row>) => ReactNode;\n /**\n * Whether Tab stays inside the panel, as in a dialog. A panel holding a\n * draft keeps it, since tabbing out would close it and drop the draft; one\n * applying every change at once lets Tab leave.\n */\n readonly trapFocus: boolean;\n}\n\n/**\n * Each kind of panel. Keyed by `GridPanelKind`, so a kind added there fails\n * to compile until it has its entry here, and needs nothing else.\n */\nconst panelKinds: { readonly [Kind in GridPanelKind]: PanelKind } = {\n columnChooser: { component: ColumnChooser, trapFocus: false },\n filter: { component: FilterMenu, trapFocus: true },\n};\n\ninterface GridPanelsProps<Row> {\n panels: GridPanelsApi;\n controller: DataGridController<Row>;\n commands: GridCommandsApi<Row>;\n messages: GridMessages;\n}\n\n/**\n * The open panel, if any, beside where it was asked for. Rendered after the\n * grid's tables, as every grid overlay is, so the keys pressed in it reach\n * no header or body handler on their way up React's tree.\n */\nexport default function GridPanels<Row>({\n panels,\n controller,\n commands,\n messages,\n}: GridPanelsProps<Row>) {\n const initialFocus = useRef<HTMLElement>(null);\n const applyFilter = useApplyFilter(\n controller,\n messages,\n commands.host.announce,\n );\n const columnValues = useFilterValueCache(controller, messages);\n const { panel, close } = panels;\n if (panel === null) {\n return null;\n }\n const { component: Panel, trapFocus } = panelKinds[panel.kind];\n return (\n <Overlay\n key={panel.key}\n anchor={panel.anchor}\n placement={panel.placement}\n gap={panel.anchor instanceof Element ? ANCHOR_GAP : 0}\n initialFocus={initialFocus}\n returnFocusTo={panel.returnFocusTo}\n // A column the chooser hides can scroll the grid back under it.\n ignoreScrollAfterInput\n trapFocus={trapFocus}\n themeClassName={panel.themeClassName}\n onDismiss={close}\n >\n <Panel<Row>\n target={panel.target}\n controller={controller}\n commands={commands}\n messages={messages}\n close={close}\n initialFocusRef={(element) => {\n initialFocus.current = element;\n }}\n applyFilter={applyFilter}\n columnValues={columnValues}\n />\n </Overlay>\n );\n}\n","import { useLayoutEffect, useRef, useState } from \"react\";\nimport { resolveColumnChooser } from \"@gridkitjs/core\";\nimport type { GridPanelProps } from \"../panels/GridPanels\";\n\n/**\n * The column chooser: a dialog listing every data column, hidden ones\n * included, with a native checkbox each, a search box narrowing the list and\n * a \"Show all\" checkbox over what the search shows. Which columns it lists,\n * which checkbox is disabled and what \"Show all\" does are\n * `@gridkitjs/core`'s `resolveColumnChooser`'s; this draws them.\n *\n * Every change applies at once, through `showColumns` and `hideColumns`, so\n * it reports and announces as any other change to the columns does. There\n * is nothing to confirm, so nothing to cancel: Escape or a click outside\n * just closes it.\n */\nexport default function ColumnChooser<Row>({\n controller,\n messages,\n}: GridPanelProps<Row>) {\n const [search, setSearch] = useState(\"\");\n const showAllRef = useRef<HTMLInputElement>(null);\n const { entries, selectAll, toggleAll } = resolveColumnChooser({\n columns: controller.getView().dataColumns,\n visibility: controller.getState().columnVisibility,\n search,\n });\n\n // A checkbox's mixed state has no attribute, only this property.\n useLayoutEffect(() => {\n if (showAllRef.current !== null) {\n showAllRef.current.indeterminate = selectAll === \"mixed\";\n }\n });\n\n function setVisible(columnIds: readonly string[], visible: boolean): void {\n if (visible) {\n controller.showColumns(columnIds);\n } else {\n controller.hideColumns(columnIds);\n }\n }\n\n return (\n <div\n role=\"dialog\"\n aria-label={messages.columnChooserLabel}\n className=\"gridkit-column-chooser\"\n >\n <input\n type=\"search\"\n className=\"column-chooser-search\"\n aria-label={messages.columnChooserSearchLabel}\n placeholder={messages.searchPlaceholder}\n value={search}\n onChange={(event) => {\n setSearch(event.currentTarget.value);\n }}\n />\n {entries.length === 0 ? (\n <p role=\"status\" className=\"column-chooser-empty\">\n {messages.noMatchingColumns}\n </p>\n ) : (\n <>\n <label className=\"column-chooser-option column-chooser-all\">\n <input\n ref={showAllRef}\n type=\"checkbox\"\n checked={selectAll === \"checked\"}\n disabled={toggleAll === null}\n onChange={() => {\n if (toggleAll !== null) {\n setVisible(toggleAll.columnIds, toggleAll.visible);\n }\n }}\n />\n {messages.showAllColumns}\n </label>\n <ul className=\"column-chooser-list\">\n {entries.map((entry) => (\n <li key={entry.columnId}>\n <label className=\"column-chooser-option\">\n <input\n type=\"checkbox\"\n checked={entry.visible}\n disabled={entry.disabled}\n onChange={() => {\n setVisible([entry.columnId], !entry.visible);\n }}\n />\n {entry.label}\n </label>\n </li>\n ))}\n </ul>\n </>\n )}\n </div>\n );\n}\n","import { useEffect, useRef, type SubmitEvent } from \"react\";\nimport {\n resolveColumnFilterMenu,\n resolveColumnHeaderText,\n resolveMenu,\n type BuiltInCommandId,\n type ResolvedMenuEntry,\n type ResolvedMenuItem,\n} from \"@gridkitjs/core\";\nimport { ariaAttr } from \"../ariaAttr\";\nimport { MenuIcon } from \"../menu/menuIcons\";\nimport type { GridPanelProps } from \"../panels/GridPanels\";\nimport ExcelFilterEditor from \"./ExcelFilterEditor\";\nimport type { FilterEditorHandle, FilterEditorProps } from \"./filterEditor\";\nimport SimpleFilterEditor from \"./SimpleFilterEditor\";\n\n/** The sort commands offered above the editor, each hidden where its column cannot sort. */\nconst SORT_COMMANDS: readonly BuiltInCommandId[] = [\n \"sort.ascending\",\n \"sort.descending\",\n \"sort.clear\",\n];\n\nfunction isItem(entry: ResolvedMenuEntry): entry is ResolvedMenuItem {\n return entry.type === \"item\";\n}\n\n/**\n * A column's filter menu: a dialog below its header holding the column's\n * sort commands, its filter editor — the conditions, or the checklist where\n * its `ui` is `\"excel\"` — and buttons that clear the filter, cancel or\n * apply. Which sort entries show and whether \"Clear filter\" can\n * run are the commands' own, resolved by `@gridkitjs/core`'s `resolveMenu`;\n * each runs through the grid's commands, so `onCommand` hears it with the\n * source `\"filterMenu\"`, and closes the menu, as choosing a menu item does.\n *\n * The editor edits a draft, so nothing filters until it is applied: OK, or\n * Enter in a field, applies it; Cancel, Escape or a click outside drops it.\n * The menu closes once the editor has applied, and stays open while the\n * editor marks what keeps it from applying.\n */\nexport default function FilterMenu<Row>({\n target,\n controller,\n commands,\n messages,\n close,\n initialFocusRef,\n applyFilter,\n columnValues,\n}: GridPanelProps<Row>) {\n const editor = useRef<FilterEditorHandle>(null);\n const column =\n target.area === \"header\"\n ? controller\n .getView()\n .dataColumns.find((entry) => entry.id === target.columnId)\n : undefined;\n const menu =\n column === undefined\n ? null\n : resolveColumnFilterMenu(controller.getOptions(), column.column);\n\n // Opened by an app's own command on a column with no menu, or left open as\n // its column loses it: with nothing to show, nothing stays open.\n useEffect(() => {\n if (menu === null) {\n close();\n }\n });\n\n if (column === undefined || menu === null) {\n return null;\n }\n\n const resolveOptions = {\n commands: commands.commands,\n context: commands.contextFor(target),\n };\n const sortItems = resolveMenu(SORT_COMMANDS, resolveOptions).filter(isItem);\n const [clearItem] = resolveMenu([\"filter.clear\"], resolveOptions).filter(\n isItem,\n );\n\n function run(item: ResolvedMenuItem): void {\n commands.run(item.id, target, \"filterMenu\");\n close();\n }\n\n const editorProps: FilterEditorProps<Row> = {\n ref: editor,\n column,\n menu,\n controller,\n messages,\n initialFocusRef,\n applyFilter,\n };\n\n function apply(event: SubmitEvent<HTMLFormElement>): void {\n event.preventDefault();\n if (editor.current?.apply() ?? true) {\n close();\n }\n }\n\n return (\n <div\n role=\"dialog\"\n aria-label={messages.filterMenuLabel(\n resolveColumnHeaderText(column.column),\n )}\n className=\"gridkit-filter-menu\"\n >\n {/*\n * Not validated by the browser: core reads every operand an editor\n * holds, so a `type=\"number\"` input's whole-number step never blocks\n * an apply with a tooltip of the browser's own.\n */}\n <form\n className=\"filter-menu-form\"\n noValidate\n onSubmit={apply}\n onKeyDown={(event) => {\n // Enter submits a form from its text boxes but not from a picker —\n // a select, or a checklist's list; here it applies from any.\n if (\n event.key === \"Enter\" &&\n event.target instanceof Element &&\n event.target.closest(\"select, [role=listbox]\") !== null\n ) {\n event.preventDefault();\n event.currentTarget.requestSubmit();\n }\n }}\n >\n {sortItems.length > 0 && (\n <div className=\"filter-menu-sort\">\n {sortItems.map((item) => (\n <button\n key={item.id}\n type=\"button\"\n className=\"filter-menu-sort-item\"\n disabled={item.disabled}\n {...ariaAttr(\n item.checked !== undefined,\n \"aria-pressed\",\n item.checked,\n )}\n onClick={() => {\n run(item);\n }}\n >\n <span className=\"filter-menu-sort-icon\" aria-hidden=\"true\">\n <MenuIcon name={item.icon} />\n </span>\n {item.label}\n </button>\n ))}\n </div>\n )}\n {menu.ui === \"excel\" ? (\n <ExcelFilterEditor {...editorProps} columnValues={columnValues} />\n ) : (\n <SimpleFilterEditor {...editorProps} />\n )}\n <div className=\"filter-menu-actions\">\n {clearItem !== undefined && (\n <button\n type=\"button\"\n className=\"filter-menu-clear\"\n disabled={clearItem.disabled}\n onClick={() => {\n run(clearItem);\n }}\n >\n {clearItem.label}\n </button>\n )}\n <button type=\"button\" className=\"filter-menu-cancel\" onClick={close}>\n {messages.cancelFilter}\n </button>\n <button type=\"submit\" className=\"filter-menu-apply\">\n {messages.applyFilter}\n </button>\n </div>\n </form>\n </div>\n );\n}\n","import {\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useReducer,\n useRef,\n useState,\n} from \"react\";\nimport {\n describeColumnFilter,\n draftToFilter,\n filterChecklist,\n filterEditorReducer,\n initialFilterEditorDraft,\n selectAllState,\n type ColumnValueOptions,\n type FilterChecklistItem,\n type FilterEditorAction,\n type FilterOperator,\n} from \"@gridkitjs/core\";\nimport { ChevronLeftIcon } from \"../menu/menuIcons\";\nimport type { FilterEditorHandle, FilterEditorProps } from \"./filterEditor\";\nimport OperatorMenuButton from \"./OperatorMenuButton\";\nimport SimpleFilterEditor from \"./SimpleFilterEditor\";\nimport ValueChecklist from \"./ValueChecklist\";\n\nexport interface ExcelFilterEditorProps<Row> extends FilterEditorProps<Row> {\n /**\n * The values a column's checklist lists, counted over the rows the other\n * columns' filters keep — the same list again while nothing it is counted\n * from has changed.\n */\n readonly columnValues: (columnId: string) => ColumnValueOptions;\n}\n\n/** What a checklist item's toggle does to the draft. */\nfunction toggleOf<Row>(item: FilterChecklistItem): FilterEditorAction<Row> {\n return item.kind === \"blanks\"\n ? { type: \"setIncludeBlanks\", includeBlanks: !item.checked }\n : { type: \"toggleValue\", value: item.value };\n}\n\n/**\n * A filter menu's excel editor: a search box, a \"Select all\" checkbox and a\n * checklist of the values the column holds, each checked while the filter\n * keeps it — the model being `@gridkitjs/core`'s `filterEditorReducer`,\n * over the column's values as `columnValues` counts them when the menu\n * opens. The values cascade: they are those of the rows the other columns'\n * filters keep.\n *\n * The search narrows the list, and \"Select all\" acts on what it shows, as\n * in Excel; past the menu's `valueLimit` values the list waits for a search\n * first, and a search matching more lists the first of them. OK applies the\n * draft through `draftToFilter`: everything checked is no filter, anything\n * less one `in` list, OR-ed with \"is blank\" while the blanks stay checked.\n *\n * Above the search, a \"Number filters\" button opens a menu of the column's\n * conditions. Choosing one shows the simple editor in place of the\n * checklist, its first condition at the operator chosen, until \"Back to\n * values\" brings the checklist back as it was left; OK there applies the\n * conditions, which replace the column's values, as Excel's do.\n *\n * Conditions or a custom filter open with every value checked, under a note\n * saying the column is filtered otherwise. OK leaves that filter be until a\n * value is checked or unchecked, as it leaves any filter whose values are as\n * they opened.\n */\nexport default function ExcelFilterEditor<Row>({\n column,\n menu,\n controller,\n messages,\n initialFocusRef,\n applyFilter,\n columnValues,\n ref,\n}: ExcelFilterEditorProps<Row>) {\n // Read once, as the menu opens: from then on the draft is the user's.\n const [opened] = useState(() => {\n const shape = describeColumnFilter(controller.getState().filter, column.id);\n return {\n shape,\n draft: initialFilterEditorDraft(shape, columnValues(column.id)),\n };\n });\n const [draft, dispatch] = useReducer(filterEditorReducer<Row>, opened.draft);\n /**\n * The operator chosen from the menu, while a condition at it shows in place\n * of the checklist.\n */\n const [operator, setOperator] = useState<FilterOperator | null>(null);\n const conditions = useRef<FilterEditorHandle>(null);\n const conditionsFocus = useRef<HTMLElement | null>(null);\n const operatorButton = useRef<HTMLButtonElement>(null);\n /** Set as the editor switches to a condition or back, for focus to follow. */\n const switched = useRef(false);\n const selectAllRef = useRef<HTMLInputElement>(null);\n // Each a pass over every value — tens of thousands of them on a large\n // column — so worked out as the draft changes, not again as the editor\n // switches to a condition and back.\n const selectAll = useMemo(() => selectAllState(draft), [draft]);\n const checklist = useMemo(\n () =>\n filterChecklist(draft, {\n valueLimit: menu.valueLimit,\n blanksLabel: messages.filterBlanks,\n }),\n [draft, menu.valueLimit, messages.filterBlanks],\n );\n\n // A checkbox's mixed state has no attribute, only this property.\n useLayoutEffect(() => {\n if (selectAllRef.current !== null) {\n selectAllRef.current.indeterminate = selectAll === \"mixed\";\n }\n });\n\n // Once the other side is drawn: to the condition's first box, or back to\n // the button whose menu chose it.\n useLayoutEffect(() => {\n if (switched.current) {\n switched.current = false;\n (operator === null\n ? operatorButton.current\n : conditionsFocus.current\n )?.focus();\n }\n }, [operator]);\n\n /**\n * Shows a condition at `chosen` in place of the checklist, or — given\n * `null` — the checklist again.\n */\n function switchTo(chosen: FilterOperator | null): void {\n switched.current = true;\n setOperator(chosen);\n }\n\n useImperativeHandle(ref, () => ({\n apply: () => {\n if (operator !== null) {\n return conditions.current?.apply() ?? true;\n }\n const picked =\n draft.checked !== opened.draft.checked ||\n draft.includeBlanks !== opened.draft.includeBlanks;\n if (picked) {\n applyFilter(\n draftToFilter(draft, column.id, controller.getState().filter),\n );\n }\n return true;\n },\n }));\n\n if (operator !== null) {\n return (\n <>\n <button\n type=\"button\"\n className=\"filter-menu-back\"\n onClick={() => {\n switchTo(null);\n }}\n >\n <span className=\"filter-menu-back-icon\" aria-hidden=\"true\">\n <ChevronLeftIcon />\n </span>\n {messages.filterBackToValues}\n </button>\n <SimpleFilterEditor\n ref={conditions}\n column={column}\n menu={menu}\n controller={controller}\n messages={messages}\n initialFocusRef={(element) => {\n conditionsFocus.current = element;\n }}\n applyFilter={applyFilter}\n operator={operator}\n />\n </>\n );\n }\n\n const { shape } = opened;\n return (\n <div className=\"filter-menu-values\">\n {menu.operators.length > 0 && (\n <OperatorMenuButton\n ref={operatorButton}\n menu={menu}\n active={\n shape.kind === \"conditions\"\n ? shape.conditions.map((condition) => condition.operator)\n : undefined\n }\n messages={messages}\n onChoose={switchTo}\n />\n )}\n {(shape.kind === \"conditions\" || shape.kind === \"custom\") && (\n <p className=\"filter-menu-custom\">\n {shape.kind === \"conditions\"\n ? messages.filterByCondition\n : messages.customFilter}\n </p>\n )}\n <input\n ref={initialFocusRef}\n type=\"search\"\n className=\"filter-menu-search\"\n aria-label={messages.filterSearchLabel}\n placeholder={messages.searchPlaceholder}\n value={draft.search}\n onChange={(event) => {\n dispatch({ type: \"search\", search: event.currentTarget.value });\n }}\n />\n <label className=\"filter-menu-select-all\">\n <input\n ref={selectAllRef}\n type=\"checkbox\"\n checked={selectAll === \"checked\"}\n // Nothing to act on: the search matches no value.\n disabled={!checklist.needsSearch && checklist.items.length === 0}\n onChange={() => {\n dispatch({ type: \"toggleAll\" });\n }}\n />\n {messages.filterSelectAll}\n </label>\n {checklist.needsSearch ? (\n <p className=\"filter-menu-search-first\">\n {messages.filterSearchFirst(checklist.total)}\n </p>\n ) : (\n <ValueChecklist\n items={checklist.items}\n showCounts={menu.showCounts}\n label={messages.filterValuesLabel}\n onToggle={(item) => {\n dispatch(toggleOf<Row>(item));\n }}\n />\n )}\n {checklist.hiddenCount > 0 && (\n <p role=\"status\" className=\"filter-menu-more\">\n {messages.filterMoreValues(checklist.hiddenCount)}\n </p>\n )}\n </div>\n );\n}\n","import { useLayoutEffect, useRef, useState, type Ref } from \"react\";\nimport type {\n FilterOperator,\n GridMessages,\n ResolvedColumnFilterMenu,\n ResolvedMenuItem,\n} from \"@gridkitjs/core\";\nimport type { AttachedMenu } from \"@gridkitjs/dom\";\nimport GridMenu from \"../menu/GridMenu\";\nimport { CheckIcon, ChevronRightIcon } from \"../menu/menuIcons\";\nimport Overlay, { ANCHOR_GAP, overlayThemeClassName } from \"../overlay/Overlay\";\n\ninterface OperatorMenuButtonProps {\n /** The column's filter menu: the operators listed, in its family's words. */\n readonly menu: ResolvedColumnFilterMenu;\n /**\n * The operators the column's conditions use, each checked in the menu — or\n * `undefined` while the column is not filtered by conditions, when no item\n * is checkable.\n */\n readonly active: readonly FilterOperator[] | undefined;\n readonly messages: GridMessages;\n /** An operator was chosen, and the menu has closed. */\n readonly onChoose: (operator: FilterOperator) => void;\n readonly ref: Ref<HTMLButtonElement>;\n}\n\n/** The menu open beside the button. */\ninterface OpenMenu {\n readonly anchor: HTMLElement;\n readonly themeClassName: string;\n /** How far from the button it opens — see `gapBeside`. */\n readonly gap: number;\n /** The item it opens on: the first, or the last when ArrowUp opened it. */\n readonly focusItem: number;\n}\n\n/**\n * How far from the button's side its menu opens: past the edge of the filter\n * menu the button sits in, by the gap an overlay keeps from what it opens\n * beside — so it opens beside the filter menu rather than over its edge.\n * The filter menu's padding is the same either side, so the gap holds when\n * the menu flips to the left.\n */\nfunction gapBeside(button: HTMLElement): number {\n const dialog = button.closest('[role=\"dialog\"]') ?? button;\n return (\n dialog.getBoundingClientRect().right -\n button.getBoundingClientRect().right +\n ANCHOR_GAP\n );\n}\n\n/**\n * The excel editor's \"Number filters\" button, opening a menu of the\n * conditions the column offers — a `GridMenu` in an overlay of its own,\n * stacked above the filter menu, so Escape closes it alone and a click in\n * it leaves the filter menu open. It follows the WAI-ARIA menu button\n * pattern: a click, Enter, Space or ArrowDown opens the menu on its first\n * item, ArrowUp on its last, and closing it returns focus to the button.\n *\n * While the column is filtered by conditions, its operators are checked in\n * the menu, and the button carries a tick, as Excel's does.\n */\nexport default function OperatorMenuButton({\n menu,\n active,\n messages,\n onChoose,\n ref,\n}: OperatorMenuButtonProps) {\n const [open, setOpen] = useState<OpenMenu | null>(null);\n const menuBehaviourRef = useRef<AttachedMenu | null>(null);\n const label = messages.filterOperatorMenu(menu.family);\n\n // As the menu opens, after the overlay — a child, whose layout effect runs\n // first — has focused the first item.\n useLayoutEffect(() => {\n if (open !== null && open.focusItem > 0) {\n menuBehaviourRef.current?.focusItem(open.focusItem);\n }\n }, [open]);\n\n function show(button: HTMLElement, onLast = false): void {\n setOpen({\n anchor: button,\n themeClassName: overlayThemeClassName(button),\n gap: gapBeside(button),\n focusItem: onLast ? menu.operators.length - 1 : 0,\n });\n }\n\n function close(): void {\n setOpen(null);\n }\n\n const entries = menu.operators.map((operator): ResolvedMenuItem => ({\n type: \"item\",\n id: operator,\n label: messages.filterOperatorLabel(operator, menu.family),\n disabled: false,\n checked: active?.includes(operator),\n run: () => {\n close();\n onChoose(operator);\n return true;\n },\n }));\n\n return (\n <>\n <button\n ref={ref}\n type=\"button\"\n className=\"filter-menu-submenu\"\n aria-haspopup=\"menu\"\n aria-expanded={open !== null}\n onClick={(event) => {\n if (open === null) {\n show(event.currentTarget);\n } else {\n close();\n }\n }}\n onKeyDown={(event) => {\n if (\n (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") &&\n open === null\n ) {\n event.preventDefault();\n show(event.currentTarget, event.key === \"ArrowUp\");\n }\n }}\n >\n <span className=\"filter-menu-submenu-icon\" aria-hidden=\"true\">\n {active !== undefined && <CheckIcon />}\n </span>\n {label}\n <span className=\"filter-menu-submenu-indicator\" aria-hidden=\"true\">\n <ChevronRightIcon />\n </span>\n </button>\n {open !== null && (\n <Overlay\n anchor={open.anchor}\n placement=\"right-start\"\n gap={open.gap}\n returnFocusTo={open.anchor}\n themeClassName={open.themeClassName}\n onDismiss={close}\n >\n <GridMenu\n entries={entries}\n label={label}\n themeClassName={open.themeClassName}\n behaviourRef={menuBehaviourRef}\n onRun={(item) => {\n item.run();\n }}\n onClose={close}\n />\n </Overlay>\n )}\n </>\n );\n}\n","import {\n Fragment,\n useId,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n conditionRowsFrom,\n conditionsFromRows,\n describeColumnFilter,\n draftToFilter,\n filterEditorReducer,\n initialFilterEditorDraft,\n type ColumnValueOptions,\n type ConditionRowDraft,\n type FilterOperator,\n type GridMessages,\n type OperatorFilterEntry,\n} from \"@gridkitjs/core\";\nimport ConditionRow from \"./ConditionRow\";\nimport type { FilterEditorProps } from \"./filterEditor\";\n\ntype Combinator = \"and\" | \"or\";\n\n/** The conditions as typed, and how they join. */\ninterface Draft {\n readonly rows: readonly ConditionRowDraft[];\n readonly combinator: Combinator;\n}\n\nconst COMBINATORS: readonly Combinator[] = [\"and\", \"or\"];\n\n/** No condition marked invalid. */\nconst NO_ROWS: readonly number[] = [];\n\n/**\n * The values half of the draft `draftToFilter` applies: the simple editor\n * has no checklist, so none.\n */\nconst NO_VALUES: ColumnValueOptions = {\n options: [],\n total: 0,\n truncated: false,\n blanks: 0,\n};\n\n/**\n * Whether a box in `row` holds what the browser can't read as a number or a\n * date — \"1e\", a date missing its year — which it reports as empty, so the\n * row would otherwise pass for one left blank.\n */\nfunction holdsUnreadable(row: HTMLElement | null | undefined): boolean {\n return Array.from(row?.querySelectorAll(\"input\") ?? []).some(\n (input) => input.validity.badInput,\n );\n}\n\ninterface CombinatorChoiceProps {\n /** The radio buttons' shared `name`, unique to the editor. */\n readonly name: string;\n readonly combinator: Combinator;\n readonly messages: GridMessages;\n readonly onChange: (combinator: Combinator) => void;\n}\n\n/** And or Or, between the two conditions: native radio buttons, one tab stop. */\nfunction CombinatorChoice({\n name,\n combinator,\n messages,\n onChange,\n}: CombinatorChoiceProps) {\n return (\n <div\n role=\"radiogroup\"\n aria-label={messages.filterCombinatorLabel}\n className=\"filter-menu-combinator\"\n >\n {COMBINATORS.map((choice) => (\n <label key={choice} className=\"filter-menu-combinator-option\">\n <input\n type=\"radio\"\n name={name}\n checked={choice === combinator}\n onChange={() => {\n onChange(choice);\n }}\n />\n {choice === \"and\" ? messages.filterAnd : messages.filterOr}\n </label>\n ))}\n </div>\n );\n}\n\nexport interface SimpleFilterEditorProps<Row> extends FilterEditorProps<Row> {\n /**\n * The operator its first condition starts at, chosen from the excel\n * editor's operator submenu — which shows this editor in place of its\n * checklist. A checklist's values are that editor's to show, so they are\n * not called a custom filter here then.\n */\n readonly operator?: FilterOperator | undefined;\n}\n\n/**\n * A filter menu's simple editor: one condition — an operator and its value —\n * and an optional second, joined to it by and/or. It opens on the column's\n * conditions, read by `@gridkitjs/core`'s `describeColumnFilter` and\n * `conditionRowsFrom`, its first at `operator` when given one. On a filter\n * it cannot show — a checklist's values, or a custom filter — it says so\n * above empty conditions, which replace it once applied.\n *\n * The conditions are text until applied, when `conditionsFromRows` reads\n * them as the column's type filters. A condition missing a value, or holding\n * one that doesn't read, keeps the menu open: its boxes are marked invalid,\n * described by a message, and the first takes focus — unless they are as it\n * opened them, as the empty ones on a column it shows no filter for: OK then\n * closes the menu as Cancel would, rather than asking for a value.\n */\nexport default function SimpleFilterEditor<Row>({\n column,\n menu,\n controller,\n messages,\n initialFocusRef,\n applyFilter,\n operator,\n ref,\n}: SimpleFilterEditorProps<Row>) {\n const type = column.column.type;\n // Read once, as the menu opens: from then on the draft is the user's.\n const [opened] = useState(() => {\n const shape = describeColumnFilter(controller.getState().filter, column.id);\n const rows = conditionRowsFrom(shape, menu.operators, type);\n const draft: Draft = {\n // Its typed values kept, as picking the operator in the row keeps them.\n rows:\n operator === undefined\n ? rows\n : rows.map((row, index) =>\n index === 0 ? { ...row, operator } : row,\n ),\n combinator: shape.kind === \"conditions\" ? shape.combinator : \"and\",\n };\n return {\n custom:\n shape.kind === \"custom\" ||\n (shape.kind === \"values\" && operator === undefined),\n draft,\n };\n });\n const [draft, setDraft] = useState(opened.draft);\n const [invalid, setInvalid] = useState(NO_ROWS);\n const rowElements = useRef<(HTMLDivElement | null)[]>([]);\n const invalidMessageId = useId();\n const combinatorName = useId();\n\n function update(next: Draft): void {\n setDraft(next);\n setInvalid(NO_ROWS);\n }\n\n /** Puts `conditions` in place of every entry about the column. */\n function applyConditions(\n conditions: readonly OperatorFilterEntry<Row>[],\n ): void {\n const applied = filterEditorReducer(\n initialFilterEditorDraft<Row>({ kind: \"none\" }, NO_VALUES),\n { type: \"setConditions\", conditions, combinator: draft.combinator },\n );\n applyFilter(\n draftToFilter(applied, column.id, controller.getState().filter),\n );\n }\n\n useImperativeHandle(ref, () => ({\n apply: () => {\n const parsed = conditionsFromRows<Row>(draft.rows, column.id, type);\n const unreadable = draft.rows.map((_, index) =>\n holdsUnreadable(rowElements.current[index]),\n );\n const marked = draft.rows.flatMap((_, index) =>\n parsed.invalid.includes(index) || unreadable[index] === true\n ? [index]\n : [],\n );\n if (marked.length === 0) {\n applyConditions(parsed.conditions);\n return true;\n }\n // Nothing typed since it opened: OK closes it, as Cancel would, rather\n // than asking for a value.\n if (draft === opened.draft && !unreadable.includes(true)) {\n return true;\n }\n setInvalid(marked);\n return false;\n },\n }));\n\n // After the render marking it, so the box is invalid as it takes focus.\n useLayoutEffect(() => {\n const [first] = invalid;\n if (first !== undefined) {\n rowElements.current[first]\n ?.querySelector<HTMLElement>('[aria-invalid=\"true\"]')\n ?.focus();\n }\n }, [invalid]);\n\n return (\n <div className=\"filter-menu-conditions\">\n {opened.custom && (\n <p className=\"filter-menu-custom\">{messages.customFilter}</p>\n )}\n {draft.rows.map((row, index) => (\n // A row is its place: the first condition, or the second.\n <Fragment key={index}>\n {index > 0 && (\n <CombinatorChoice\n name={combinatorName}\n combinator={draft.combinator}\n messages={messages}\n onChange={(combinator) => {\n update({ ...draft, combinator });\n }}\n />\n )}\n <ConditionRow\n ref={(element) => {\n rowElements.current[index] = element;\n }}\n row={row}\n position={index + 1}\n menu={menu}\n type={type}\n messages={messages}\n invalidMessageId={\n invalid.includes(index) ? invalidMessageId : undefined\n }\n focusRef={index === 0 ? initialFocusRef : undefined}\n onChange={(next) => {\n update({\n ...draft,\n rows: draft.rows.map((current, at) =>\n at === index ? next : current,\n ),\n });\n }}\n />\n </Fragment>\n ))}\n {invalid.length > 0 && (\n <p id={invalidMessageId} className=\"filter-menu-invalid\">\n {messages.filterValueInvalid(menu.family)}\n </p>\n )}\n </div>\n );\n}\n","import type { ChangeEvent, Ref, RefCallback } from \"react\";\nimport {\n filterOperandArity,\n parseFilterOperand,\n type ColumnType,\n type ConditionRowDraft,\n type FilterOperatorFamily,\n type GridMessages,\n type ResolvedColumnFilterMenu,\n} from \"@gridkitjs/core\";\n\n/**\n * The input a column of `type` takes an operand in, each writing what\n * `@gridkitjs/core`'s `parseFilterOperand` reads: a day for a date column, a\n * day and a time for a date-time or time one.\n */\nfunction inputType(\n family: Exclude<FilterOperatorFamily, \"boolean\">,\n type: ColumnType | undefined,\n): \"text\" | \"number\" | \"date\" | \"datetime-local\" {\n switch (family) {\n case \"text\":\n return \"text\";\n case \"number\":\n return \"number\";\n case \"date\":\n return type === \"date\" ? \"date\" : \"datetime-local\";\n }\n}\n\ninterface OperandFieldProps {\n readonly family: FilterOperatorFamily;\n readonly type: ColumnType | undefined;\n readonly text: string;\n /** Its accessible name: \"Value\", or a `between`'s \"From\" or \"To\". */\n readonly label: string;\n /** The id of the message describing it while it is invalid. */\n readonly invalidMessageId: string | undefined;\n readonly fieldRef: RefCallback<HTMLElement> | undefined;\n readonly messages: GridMessages;\n readonly onChange: (text: string) => void;\n}\n\n/** One operand's box — a true/false choice on a boolean column. */\nfunction OperandField({\n family,\n type,\n text,\n label,\n invalidMessageId,\n fieldRef,\n messages,\n onChange,\n}: OperandFieldProps) {\n const field = {\n ref: fieldRef,\n className: \"filter-menu-value\",\n \"aria-label\": label,\n \"aria-invalid\": invalidMessageId === undefined ? undefined : true,\n \"aria-describedby\": invalidMessageId,\n value: text,\n onChange: (event: ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {\n onChange(event.currentTarget.value);\n },\n };\n if (family === \"boolean\") {\n // Empty to start with, as a text box is, so a second condition left\n // alone is dropped rather than applied as \"Equals true\".\n return (\n <select {...field}>\n <option value=\"\" />\n <option value=\"true\">{messages.booleanTrue}</option>\n <option value=\"false\">{messages.booleanFalse}</option>\n </select>\n );\n }\n return <input {...field} type={inputType(family, type)} />;\n}\n\ninterface ConditionRowProps {\n readonly row: ConditionRowDraft;\n /** Its place among the editor's conditions, from one — what names it. */\n readonly position: number;\n readonly menu: ResolvedColumnFilterMenu;\n readonly type: ColumnType | undefined;\n readonly messages: GridMessages;\n /**\n * The id of the message saying its value is missing or doesn't read, while\n * it is marked so: each box whose text doesn't read is then invalid, and\n * described by it.\n */\n readonly invalidMessageId: string | undefined;\n /**\n * The `ref` of the control focus starts on: its first box, or its operator\n * picker when its operator takes no operand.\n */\n readonly focusRef: RefCallback<HTMLElement> | undefined;\n readonly onChange: (row: ConditionRowDraft) => void;\n readonly ref: Ref<HTMLDivElement>;\n}\n\n/**\n * One condition of a filter menu's editor, as typed: an operator picker,\n * then a box for each operand its operator takes — none for the blanks\n * operators, two for `between`'s ends.\n */\nexport default function ConditionRow({\n row,\n position,\n menu,\n type,\n messages,\n invalidMessageId,\n focusRef,\n onChange,\n ref,\n}: ConditionRowProps) {\n const arity = filterOperandArity(row.operator);\n // A condition set in code can use an operator the column doesn't offer; it\n // is listed too, so the row shows the condition as it is.\n const operators = menu.operators.includes(row.operator)\n ? menu.operators\n : [row.operator, ...menu.operators];\n const operand = { family: menu.family, type, messages };\n\n /**\n * The message id for a box holding `text`, while the row is marked: on the\n * box that is empty or doesn't read — a `between`'s missing end, not the\n * one filled in.\n */\n function messageIdFor(text: string): string | undefined {\n return parseFilterOperand(text, type) === undefined\n ? invalidMessageId\n : undefined;\n }\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-label={messages.filterConditionLabel(position)}\n className=\"filter-menu-condition\"\n >\n <select\n ref={arity === 0 ? focusRef : undefined}\n className=\"filter-menu-operator\"\n aria-label={messages.filterOperatorFieldLabel}\n value={row.operator}\n onChange={(event) => {\n const operator = operators[event.currentTarget.selectedIndex];\n if (operator !== undefined) {\n onChange({ ...row, operator });\n }\n }}\n >\n {operators.map((operator) => (\n <option key={operator} value={operator}>\n {messages.filterOperatorLabel(operator, menu.family)}\n </option>\n ))}\n </select>\n {arity > 0 && (\n <OperandField\n {...operand}\n text={row.text}\n label={\n arity === 2 ? messages.filterFromLabel : messages.filterValueLabel\n }\n invalidMessageId={messageIdFor(row.text)}\n fieldRef={focusRef}\n onChange={(text) => {\n onChange({ ...row, text });\n }}\n />\n )}\n {arity === 2 && (\n <OperandField\n {...operand}\n text={row.textTo}\n label={messages.filterToLabel}\n invalidMessageId={messageIdFor(row.textTo)}\n fieldRef={undefined}\n onChange={(textTo) => {\n onChange({ ...row, textTo });\n }}\n />\n )}\n </div>\n );\n}\n","import { useLayoutEffect, useRef, useState } from \"react\";\nimport type { FilterChecklistItem, VisibleRange } from \"@gridkitjs/core\";\nimport {\n attachChecklist,\n createRowVirtualizer,\n type AttachedChecklist,\n type RowVirtualizer,\n} from \"@gridkitjs/dom\";\nimport { CheckIcon } from \"../menu/menuIcons\";\n\n/**\n * The height assumed for an item not yet measured: the theme's, a line of\n * text and its padding. Every mounted item is measured, so it only places\n * those scrolled past.\n */\nconst ESTIMATED_ITEM_HEIGHT = 28;\n\n/** Items mounted beyond each edge of the list's visible part. */\nconst OVERSCAN = 4;\n\nconst NO_RANGE: VisibleRange = {\n startIndex: 0,\n endIndex: -1,\n offsetBefore: 0,\n offsetAfter: 0,\n};\n\ninterface ValueChecklistProps {\n /** Every item of the list, in order — only a window of them is mounted. */\n readonly items: readonly FilterChecklistItem[];\n readonly showCounts: boolean;\n /** The list's accessible name. */\n readonly label: string;\n /** An item asks to be checked or unchecked: Space on it, or a click. */\n readonly onToggle: (item: FilterChecklistItem) => void;\n}\n\n/**\n * A filter checklist's values: a `role=\"listbox\"` with one tab stop, each\n * value an option whose `aria-checked` says whether the filter keeps it.\n * A column can hold thousands of values, so the list is windowed by\n * `@gridkitjs/dom`'s `createRowVirtualizer` — the list is its own scroll\n * element, holding only the items near its scroll position between two\n * spacers — and made to behave by `attachChecklist`, which moves focus by\n * the arrow keys, Home, End, PageUp and PageDown and reports Space or a\n * click on an item by its place in the whole list.\n *\n * An item's key holds characters no DOM attribute may, so it keys React's\n * list only; the DOM knows an item by its place, `aria-posinset` one past it.\n */\nexport default function ValueChecklist({\n items,\n showCounts,\n label,\n onToggle,\n}: ValueChecklistProps) {\n const listRef = useRef<HTMLDivElement>(null);\n const checklistRef = useRef<AttachedChecklist | null>(null);\n const [virtualizer, setVirtualizer] = useState<RowVirtualizer | null>(null);\n const [range, setRange] = useState(NO_RANGE);\n\n /**\n * What the behaviour's callbacks read. They are handed over once, when it\n * attaches, so they read the props of the latest render here.\n */\n const latest = useRef({ items, onToggle });\n useLayoutEffect(() => {\n latest.current = { items, onToggle };\n });\n\n useLayoutEffect(() => {\n const list = listRef.current;\n if (list === null) {\n return undefined;\n }\n const rows = createRowVirtualizer(list, {\n estimatedRowHeight: ESTIMATED_ITEM_HEIGHT,\n overscan: OVERSCAN,\n onRange: setRange,\n });\n const checklist = attachChecklist(list, {\n onToggle: (index) => {\n const item = latest.current.items[index];\n if (item !== undefined) {\n latest.current.onToggle(item);\n }\n },\n scrollToIndex: (index) => {\n rows.scrollToIndex(index, { block: \"nearest\" });\n },\n });\n checklistRef.current = checklist;\n setVirtualizer(rows);\n return () => {\n checklistRef.current = null;\n checklist.detach();\n rows.destroy();\n };\n }, []);\n\n useLayoutEffect(() => {\n virtualizer?.setRowCount(items.length);\n checklistRef.current?.setCount(items.length);\n }, [virtualizer, items.length]);\n\n const shown = items.slice(range.startIndex, range.endIndex + 1);\n\n return (\n <div\n ref={listRef}\n role=\"listbox\"\n aria-multiselectable=\"true\"\n aria-label={label}\n className=\"filter-menu-checklist\"\n >\n <div role=\"presentation\" style={{ height: range.offsetBefore }} />\n {shown.map((item, offset) => {\n const index = range.startIndex + offset;\n return (\n <div\n key={item.key}\n ref={virtualizer?.measureRow(index)}\n role=\"option\"\n data-gridkit-checklist-item=\"\"\n data-gridkit-checklist-index={index}\n aria-checked={item.checked}\n aria-setsize={items.length}\n aria-posinset={index + 1}\n className=\"filter-menu-option\"\n >\n <span className=\"filter-menu-option-check\" aria-hidden=\"true\">\n <CheckIcon />\n </span>\n <span className=\"filter-menu-option-label\">{item.label}</span>\n {/* Spaced, so the option's name reads \"Alice 3\", not \"Alice3\". */}\n {showCounts && (\n <>\n {\" \"}\n <span className=\"filter-menu-option-count\">\n {String(item.count)}\n </span>\n </>\n )}\n </div>\n );\n })}\n <div role=\"presentation\" style={{ height: range.offsetAfter }} />\n </div>\n );\n}\n","import { useEffect, useRef } from \"react\";\nimport type { FilterState, GridMessages } from \"@gridkitjs/core\";\nimport type { DataGridController } from \"../useGridController\";\n\n/**\n * How a filter menu applies a filter: it becomes the grid's filter, and once\n * the grid has drawn the rows it keeps, how many they are of all the rows is\n * announced — `filterResults`, \"3 of 10 rows\". Held by the panel host, which\n * outlives the menu: the menu closes as it applies, before the rows are\n * drawn.\n */\nexport default function useApplyFilter<Row>(\n controller: DataGridController<Row>,\n messages: GridMessages,\n announce: (text: string) => void,\n): (filter: FilterState<Row>) => void {\n /** The filter a menu applied, until it is announced. */\n const unannounced = useRef<FilterState<Row> | null>(null);\n\n // After the render that drew the rows, so the count is theirs — and only\n // once the grid holds the filter, which a controlled one may not.\n useEffect(() => {\n if (unannounced.current === controller.getState().filter) {\n unannounced.current = null;\n announce(\n messages.filterResults(\n controller.getView().rows.length,\n controller.getOptions().dataSource?.length ?? 0,\n ),\n );\n }\n });\n\n return (filter) => {\n unannounced.current = filter;\n controller.setFilter(filter);\n };\n}\n","import { useState } from \"react\";\nimport {\n createColumnValueOptionsCache,\n type ColumnValueOptions,\n type GridMessages,\n} from \"@gridkitjs/core\";\nimport type { DataGridController } from \"../useGridController\";\n\n/** Rows to count before the grid has any: one array, so the cache keeps its lists. */\nconst NO_ROWS: readonly never[] = [];\n\n/**\n * The values a column's filter checklist lists, counted over the rows the\n * other columns' filters keep. Held by the panel host for the grid's whole\n * life, so reopening a column's checklist hands back the list it counted\n * last time rather than counting every row again — until the rows, the\n * columns, the locale, `messages` or another column's filter change.\n *\n * `messages` is the grid's own resolved object, which keeps its identity\n * while the `messages` prop does: the cache compares it by identity.\n */\nexport default function useFilterValueCache<Row>(\n controller: DataGridController<Row>,\n messages: GridMessages,\n): (columnId: string) => ColumnValueOptions {\n const [cache] = useState(createColumnValueOptionsCache<Row>);\n\n return (columnId) => {\n const { dataSource = NO_ROWS, locale } = controller.getOptions();\n return cache.get(\n dataSource,\n controller.getView().dataColumns,\n controller.getState().filter,\n columnId,\n locale === undefined ? { messages } : { locale, messages },\n );\n };\n}\n","import { resolveColumnFilterMenu } from \"@gridkitjs/core\";\nimport type { DataGridController } from \"../useGridController\";\nimport type { GridPanelsApi } from \"./useGridPanels\";\n\n/** What `DataGridApi` carries for the grid's panels. */\nexport interface GridPanelApi {\n /**\n * Opens the column chooser at the grid's top-end corner, in place of any\n * panel open; it gives focus back to what had it when it closes.\n */\n openColumnChooser(): void;\n /**\n * Opens the filter menu of the column `columnId` below its header, in\n * place of any panel open, and says whether it opened: not for a column\n * with no filter menu, nor one not shown. It gives focus back to the\n * header when it closes.\n */\n openFilterMenu(columnId: string): boolean;\n /** Closes the filter menu, if one is open, leaving any other panel open. */\n closeFilterMenu(): void;\n}\n\n/** `DataGridApi`'s panel methods, over the grid as it is when called. */\nexport function panelApi<Row>(\n panels: GridPanelsApi,\n controller: DataGridController<Row>,\n): GridPanelApi {\n return {\n openColumnChooser: () => {\n panels.open(\"columnChooser\", { area: \"grid\" });\n },\n openFilterMenu: (columnId) => {\n const shown = controller\n .getView()\n .columns.find((entry) => entry.id === columnId);\n if (\n shown === undefined ||\n resolveColumnFilterMenu(controller.getOptions(), shown.column) === null\n ) {\n return false;\n }\n panels.open(\"filter\", { area: \"header\", columnId });\n return true;\n },\n closeFilterMenu: () => {\n if (panels.panel?.kind === \"filter\") {\n panels.close();\n }\n },\n };\n}\n","import { useLayoutEffect, useRef, useState, type RefObject } from \"react\";\nimport type { GridCommandTarget, GridPanelKind } from \"@gridkitjs/core\";\nimport type { OverlayAnchor, OverlayPlacement } from \"@gridkitjs/dom\";\nimport { overlayThemeClassName } from \"../overlay/Overlay\";\nimport type { GridNavigationApi } from \"../useGridNavigation\";\n\ninterface UseGridPanelsOptions {\n /** The grid's root element, holding the toolbar; a panel asked for from nowhere opens at its corner. */\n rootRef: RefObject<HTMLElement | null>;\n headerTableRef: RefObject<HTMLTableElement | null>;\n nav: GridNavigationApi;\n}\n\n/** The panel open now. */\nexport interface OpenPanel {\n /** Counts the openings, so one opened over another replaces it. */\n readonly key: number;\n readonly kind: GridPanelKind;\n /** Where it was asked for. */\n readonly target: GridCommandTarget;\n readonly anchor: OverlayAnchor;\n readonly placement: OverlayPlacement;\n /**\n * What gets focus back when it closes: the toolbar button or the header it\n * opened from, or, for `undefined`, whatever had focus as it opened.\n */\n readonly returnFocusTo: HTMLElement | undefined;\n readonly themeClassName: string;\n}\n\nexport interface GridPanelsApi {\n panel: OpenPanel | null;\n /** Opens the panel `kind` beside where `target` names, in place of any panel open. */\n open: (kind: GridPanelKind, target: GridCommandTarget) => void;\n close: () => void;\n}\n\n/** The element of the root's own toolbar whose `data-gridkit-toolbar-item` is `itemId`. */\nfunction toolbarItem(root: HTMLElement, itemId: string): HTMLElement | null {\n const items = root.querySelectorAll<HTMLElement>(\n \":scope > .gridkit-toolbar > [data-gridkit-toolbar-item]\",\n );\n return (\n Array.from(items).find(\n (item) => item.getAttribute(\"data-gridkit-toolbar-item\") === itemId,\n ) ??\n // In \"More\" while the toolbar is narrow: the button it is chosen from.\n Array.from(items).find((item) =>\n item.hasAttribute(\"data-gridkit-toolbar-more\"),\n ) ??\n null\n );\n}\n\nfunction headerCell(\n headerTable: HTMLTableElement | null,\n columnId: string,\n): HTMLTableCellElement | null {\n const cells = headerTable?.tHead?.rows[0]?.cells;\n return cells === undefined\n ? null\n : (Array.from(cells).find(\n (cell) => cell.getAttribute(\"data-gridkit-column\") === columnId,\n ) ?? null);\n}\n\n/**\n * The grid's panels — the column chooser and a column's filter menu —\n * opened through the command host's `openPanel`, one at a time. A panel\n * opens beside where it was asked for: below the toolbar button, below the\n * column header, or at the grid's top-end corner for a call from nowhere in\n * particular, as the ref's is.\n *\n * Opened from a menu, it opens as the menu closes, in the same render: the\n * menu hands focus back to where it was opened from, and the panel takes it\n * from there — and gives it back there when it closes.\n */\nexport default function useGridPanels({\n rootRef,\n headerTableRef,\n nav,\n}: UseGridPanelsOptions): GridPanelsApi {\n const [panel, setPanel] = useState<OpenPanel | null>(null);\n const openings = useRef(0);\n\n function placeFor(\n root: HTMLElement,\n target: GridCommandTarget,\n ): Pick<OpenPanel, \"anchor\" | \"placement\" | \"returnFocusTo\"> {\n const element =\n target.area === \"toolbar\"\n ? toolbarItem(root, target.itemId)\n : target.area === \"header\"\n ? headerCell(headerTableRef.current, target.columnId)\n : null;\n if (element !== null) {\n return {\n anchor: element,\n // The toolbar's own button sits at its far end.\n placement: target.area === \"toolbar\" ? \"bottom-end\" : \"bottom-start\",\n returnFocusTo: element,\n };\n }\n const { right, top } = root.getBoundingClientRect();\n return {\n anchor: { x: right, y: top },\n placement: \"bottom-end\",\n returnFocusTo: undefined,\n };\n }\n\n /**\n * A header the panel returns focus to can go with what it did — the\n * chooser hiding that very column — and focus then falls to the page. It\n * goes to the cell now holding the grid's tab stop instead.\n */\n const shown = useRef<OpenPanel | null>(null);\n useLayoutEffect(() => {\n const closed = shown.current;\n shown.current = panel;\n if (\n panel === null &&\n closed?.returnFocusTo?.isConnected === false &&\n document.activeElement === document.body\n ) {\n nav.focusTabStop();\n }\n });\n\n return {\n panel,\n open: (kind, target) => {\n const root = rootRef.current;\n if (root === null) {\n return;\n }\n openings.current += 1;\n setPanel({\n key: openings.current,\n kind,\n target,\n ...placeFor(root, target),\n themeClassName: overlayThemeClassName(root),\n });\n },\n close: () => {\n setPanel(null);\n },\n };\n}\n","import { useLayoutEffect, useRef, type ReactNode } from \"react\";\nimport {\n resolveToolbar,\n splitToolbarItems,\n toolbarEntries,\n type GridMessages,\n type GridOptions,\n type ResolvedMenuEntry,\n type ResolvedToolbarItem,\n type ToolbarEntry,\n} from \"@gridkitjs/core\";\nimport { attachToolbar } from \"@gridkitjs/dom\";\nimport { ariaAttr } from \"../ariaAttr\";\nimport type { GridCommandsApi } from \"../commands/useGridCommands\";\nimport { MenuIcon } from \"../menu/menuIcons\";\nimport type { DataGridController } from \"../useGridController\";\nimport ToolbarMenuButton from \"./ToolbarMenuButton\";\nimport ToolbarSearch from \"./ToolbarSearch\";\nimport useToolbarOverflow from \"./useToolbarOverflow\";\n\ninterface GridToolbarProps<Row> {\n toolbar: GridOptions<Row>[\"toolbar\"];\n /** Fills a custom entry, by its id. */\n renderItem: ((id: string) => ReactNode) | undefined;\n /** The id of the grid element the toolbar acts on. */\n gridId: string;\n controller: DataGridController<Row>;\n commands: GridCommandsApi<Row>;\n messages: GridMessages;\n announce: (text: string) => void;\n}\n\n/** `run`, also telling `onCommand` through `report` whenever it runs. */\nfunction reporting(run: () => boolean, report: () => void): () => boolean {\n return () => {\n const ran = run();\n if (ran) {\n report();\n }\n return ran;\n };\n}\n\n/** A menu's entries, each item reporting through `report` with its id when it runs. */\nfunction reportingEntries(\n entries: readonly ResolvedMenuEntry[],\n report: (commandId: string) => void,\n): readonly ResolvedMenuEntry[] {\n return entries.map((entry) => {\n switch (entry.type) {\n case \"item\":\n return {\n ...entry,\n run: reporting(entry.run, () => {\n report(entry.id);\n }),\n };\n case \"submenu\":\n return { ...entry, items: reportingEntries(entry.items, report) };\n default:\n return entry;\n }\n });\n}\n\n/**\n * A toolbar item whose `run` — or, for a dropdown, whose items' `run` —\n * also reports to `onCommand` as asked from that item, wherever it ends up\n * drawn: as itself, or in \"More\".\n */\nfunction reportingItem(\n item: ResolvedToolbarItem,\n report: (commandId: string, itemId: string) => void,\n): ResolvedToolbarItem {\n switch (item.type) {\n case \"button\":\n return {\n ...item,\n run: reporting(item.run, () => {\n report(item.id, item.id);\n }),\n };\n case \"menu\":\n return {\n ...item,\n items: reportingEntries(item.items, (commandId) => {\n report(commandId, item.id);\n }),\n };\n default:\n return item;\n }\n}\n\n/**\n * The grid's toolbar, when its `toolbar` option lists anything: the entries\n * resolved by `@gridkitjs/core`'s `resolveToolbar` and drawn as a\n * `role=\"toolbar\"`, which `@gridkitjs/dom`'s `attachToolbar` makes one tab\n * stop the arrow keys move within. Which item shows, is enabled, pressed or\n * does what is core's; this draws them, and resolves them again on every\n * render, so they follow the grid's state.\n *\n * What does not fit moves into a \"More\" menu at the end, as\n * `@gridkitjs/dom`'s `observeToolbarOverflow` measures it and core's\n * `splitToolbarItems` turns it into menu entries: a toggle a checkable item,\n * a dropdown a submenu. The search box and custom entries always stay.\n */\nexport default function GridToolbar<Row>(props: GridToolbarProps<Row>) {\n const entries = toolbarEntries(props.toolbar);\n if (entries.length === 0) {\n return null;\n }\n const label =\n (typeof props.toolbar === \"object\" ? props.toolbar.label : undefined) ??\n props.messages.toolbarLabel;\n return <Toolbar {...props} entries={entries} label={label} />;\n}\n\nfunction Toolbar<Row>({\n entries,\n label,\n renderItem,\n gridId,\n controller,\n commands,\n messages,\n announce,\n}: GridToolbarProps<Row> & {\n entries: readonly ToolbarEntry<Row>[];\n label: string;\n}) {\n const toolbarRef = useRef<HTMLDivElement>(null);\n /** Set when a menu closes, for the layout effect below. */\n const menuClosed = useRef(false);\n\n const items = resolveToolbar(entries, {\n commands: commands.commands,\n contextFor: commands.contextFor,\n }).map((item) =>\n reportingItem(item, (commandId, itemId) => {\n commands.report(commandId, { area: \"toolbar\", itemId }, \"toolbar\");\n }),\n );\n const fit = useToolbarOverflow(toolbarRef, items);\n const { shown, overflow } = splitToolbarItems(items, fit);\n\n useLayoutEffect(() => {\n const toolbar = toolbarRef.current;\n return toolbar === null ? undefined : attachToolbar(toolbar);\n }, []);\n\n /**\n * A menu returns focus to its button as it closes — but what it ran can\n * take that button away, a dropdown whose items all hid, and focus then\n * falls to the page. It comes back to the toolbar instead.\n */\n useLayoutEffect(() => {\n if (!menuClosed.current) {\n return;\n }\n menuClosed.current = false;\n const toolbar = toolbarRef.current;\n if (toolbar !== null && document.activeElement === document.body) {\n (\n toolbar.querySelector<HTMLElement>('[tabindex=\"0\"]') ??\n toolbar.querySelector<HTMLElement>(\"button, input\")\n )?.focus();\n }\n });\n\n function onMenuClose(): void {\n menuClosed.current = true;\n }\n\n function draw(item: ResolvedToolbarItem): ReactNode {\n switch (item.type) {\n case \"button\":\n return (\n <button\n key={item.key}\n type=\"button\"\n className=\"toolbar-button\"\n data-gridkit-toolbar-item={item.key}\n {...ariaAttr(item.disabled, \"aria-disabled\", true)}\n {...ariaAttr(\n item.pressed !== undefined,\n \"aria-pressed\",\n item.pressed,\n )}\n {...ariaAttr(\n item.shortcut !== undefined,\n \"aria-keyshortcuts\",\n item.shortcut,\n )}\n onClick={() => {\n item.run();\n }}\n >\n {item.icon !== undefined && (\n <span className=\"toolbar-button-icon\" aria-hidden=\"true\">\n <MenuIcon name={item.icon} />\n </span>\n )}\n {item.label}\n </button>\n );\n case \"menu\":\n return (\n <ToolbarMenuButton\n key={item.key}\n itemKey={item.key}\n label={item.label}\n icon={item.icon}\n entries={item.items}\n onMenuClose={onMenuClose}\n />\n );\n case \"search\":\n return (\n <ToolbarSearch<Row>\n key={item.key}\n itemKey={item.key}\n controller={controller}\n messages={messages}\n announce={announce}\n />\n );\n case \"separator\":\n return (\n <div\n key={item.key}\n role=\"separator\"\n aria-orientation=\"vertical\"\n className=\"toolbar-separator\"\n data-gridkit-toolbar-item={item.key}\n />\n );\n case \"spacer\":\n return (\n <div\n key={item.key}\n className=\"toolbar-spacer\"\n data-gridkit-toolbar-item={item.key}\n />\n );\n case \"custom\":\n return (\n <div\n key={item.key}\n className=\"toolbar-custom\"\n data-gridkit-toolbar-item={item.key}\n >\n {renderItem?.(item.id)}\n </div>\n );\n }\n }\n\n return (\n <div\n ref={toolbarRef}\n role=\"toolbar\"\n aria-label={label}\n aria-controls={gridId}\n className=\"gridkit-toolbar\"\n >\n {shown.map(draw)}\n {overflow.length > 0 && (\n <ToolbarMenuButton\n itemKey=\"more\"\n label={messages.moreToolbarItems}\n entries={overflow}\n more\n onMenuClose={onMenuClose}\n />\n )}\n </div>\n );\n}\n","import { useLayoutEffect, useRef, useState } from \"react\";\nimport type { ResolvedMenuEntry } from \"@gridkitjs/core\";\nimport type { AttachedMenu } from \"@gridkitjs/dom\";\nimport { ariaAttr } from \"../ariaAttr\";\nimport { classNames } from \"../classNames\";\nimport GridMenu from \"../menu/GridMenu\";\nimport { ChevronDownIcon, MenuIcon } from \"../menu/menuIcons\";\nimport Overlay, { ANCHOR_GAP, overlayThemeClassName } from \"../overlay/Overlay\";\n\ninterface ToolbarMenuButtonProps {\n /** Its `data-gridkit-toolbar-item`. */\n itemKey: string;\n /** The button's label, and its menu's accessible name. */\n label: string;\n icon?: string | undefined;\n entries: readonly ResolvedMenuEntry[];\n /** The \"More\" button, holding the entries that do not fit, rather than a dropdown. */\n more?: boolean | undefined;\n /** Its menu closed, however it did. */\n onMenuClose: () => void;\n}\n\n/** The menu open below the button. */\ninterface OpenMenu {\n readonly anchor: HTMLElement;\n readonly themeClassName: string;\n /** The item it opens on: the first, or the last when ArrowUp opened it. */\n readonly focusItem: number;\n}\n\n/**\n * A toolbar button opening a menu below it, following the WAI-ARIA menu\n * button pattern: a click, Enter, Space or ArrowDown opens the menu with\n * focus on its first item, ArrowUp on its last, and a second click closes\n * it. Closing the menu returns focus to the button. What the items do, and\n * whether each runs, is in their `run`.\n */\nexport default function ToolbarMenuButton({\n itemKey,\n label,\n icon,\n entries,\n more = false,\n onMenuClose,\n}: ToolbarMenuButtonProps) {\n const [menu, setMenu] = useState<OpenMenu | null>(null);\n const menuBehaviourRef = useRef<AttachedMenu | null>(null);\n\n // As the menu opens, after the overlay — a child, whose layout effect runs\n // first — has focused the first item.\n useLayoutEffect(() => {\n if (menu !== null && menu.focusItem > 0) {\n menuBehaviourRef.current?.focusItem(menu.focusItem);\n }\n }, [menu]);\n\n function open(button: HTMLElement, onLast = false): void {\n setMenu({\n anchor: button,\n themeClassName: overlayThemeClassName(button),\n focusItem: onLast\n ? entries.filter((entry) => entry.type !== \"separator\").length - 1\n : 0,\n });\n }\n\n function close(): void {\n setMenu(null);\n onMenuClose();\n }\n\n return (\n <>\n <button\n type=\"button\"\n className={classNames(\"toolbar-button\", more && \"toolbar-more\")}\n data-gridkit-toolbar-item={itemKey}\n {...ariaAttr(more, \"data-gridkit-toolbar-more\", \"\")}\n aria-haspopup=\"menu\"\n aria-expanded={menu !== null}\n onClick={(event) => {\n if (menu === null) {\n open(event.currentTarget);\n } else {\n close();\n }\n }}\n onKeyDown={(event) => {\n if (\n (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") &&\n menu === null\n ) {\n event.preventDefault();\n open(event.currentTarget, event.key === \"ArrowUp\");\n }\n }}\n >\n {icon !== undefined && (\n <span className=\"toolbar-button-icon\" aria-hidden=\"true\">\n <MenuIcon name={icon} />\n </span>\n )}\n {label}\n <span className=\"toolbar-button-indicator\" aria-hidden=\"true\">\n <ChevronDownIcon />\n </span>\n </button>\n {menu !== null && (\n <Overlay\n anchor={menu.anchor}\n placement=\"bottom-start\"\n gap={ANCHOR_GAP}\n returnFocusTo={menu.anchor}\n themeClassName={menu.themeClassName}\n onDismiss={close}\n >\n <GridMenu\n entries={entries}\n label={label}\n themeClassName={menu.themeClassName}\n behaviourRef={menuBehaviourRef}\n onRun={(item) => {\n item.run();\n close();\n }}\n onClose={close}\n />\n </Overlay>\n )}\n </>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport {\n searchTextOf,\n setSearchText,\n type GridMessages,\n} from \"@gridkitjs/core\";\nimport type { DataGridController } from \"../useGridController\";\n\n/** How long typing has to rest before the search applies. */\nconst SEARCH_DELAY_MS = 250;\n\n/** What the user has typed and the grid not yet applied. */\ninterface Draft {\n readonly text: string;\n /**\n * The search applied when it was typed. Once the search changes from\n * elsewhere — \"Clear filters\", a restored layout — the draft is dropped\n * and the box shows that instead.\n */\n readonly over: string;\n}\n\ninterface ToolbarSearchProps<Row> {\n /** Its `data-gridkit-toolbar-item`. */\n itemKey: string;\n controller: DataGridController<Row>;\n messages: GridMessages;\n announce: (text: string) => void;\n}\n\n/**\n * The toolbar's search box, over the filter's global text entry — the one\n * naming no column — through `@gridkitjs/core`'s `searchTextOf` and\n * `setSearchText`. It reads what it shows back from the filter, so anything\n * else that changes the search changes the box.\n *\n * Typing applies once it rests for a moment; Enter applies at once, and\n * Escape empties the box. A search the box applied is announced as the\n * number of rows it found, once the grid has drawn them.\n */\nexport default function ToolbarSearch<Row>({\n itemKey,\n controller,\n messages,\n announce,\n}: ToolbarSearchProps<Row>) {\n const applied = searchTextOf(controller.getState().filter);\n const [draft, setDraft] = useState<Draft | null>(null);\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n /** The search this box applied, until it is announced. */\n const unannounced = useRef<string | null>(null);\n const text = draft !== null && draft.over === applied ? draft.text : applied;\n\n /** Applies `next`, typed over the search `over`, unless that has changed since. */\n function apply(next: string, over: string): void {\n clearTimeout(timer.current);\n setDraft(null);\n const filter = controller.getState().filter;\n if (searchTextOf(filter) !== over) {\n return;\n }\n const searched = setSearchText(filter, next);\n if (searched !== filter) {\n unannounced.current = next;\n controller.setFilter(searched);\n }\n }\n\n // After the render that drew the rows, so the count is theirs — and only\n // once the filter holds the search, which a controlled one may not.\n useEffect(() => {\n if (unannounced.current === applied) {\n unannounced.current = null;\n announce(messages.searchResults(controller.getView().rows.length));\n }\n });\n\n useEffect(\n () => () => {\n clearTimeout(timer.current);\n },\n [],\n );\n\n return (\n <input\n type=\"search\"\n className=\"toolbar-search\"\n data-gridkit-toolbar-item={itemKey}\n aria-label={messages.searchLabel}\n placeholder={messages.searchPlaceholder}\n value={text}\n onChange={(event) => {\n const typed = event.target.value;\n setDraft({ text: typed, over: applied });\n clearTimeout(timer.current);\n timer.current = setTimeout(() => {\n apply(typed, applied);\n }, SEARCH_DELAY_MS);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n apply(text, applied);\n } else if (event.key === \"Escape\" && text !== \"\") {\n // Ahead of the browser's own clearing, which would wait out the delay.\n event.preventDefault();\n apply(\"\", applied);\n }\n }}\n />\n );\n}\n","import { useLayoutEffect, useRef, useState, type RefObject } from \"react\";\nimport type { ResolvedToolbarItem } from \"@gridkitjs/core\";\nimport { observeToolbarOverflow, type ToolbarOverflow } from \"@gridkitjs/dom\";\n\n/**\n * How many of a toolbar's items fit in it, from the start, as\n * `@gridkitjs/dom`'s `observeToolbarOverflow` measures them — every item\n * until it first reports, which it does before paint.\n *\n * Attached once, so the widths it remembers for items moved into \"More\"\n * survive, and told of new items only when the toolbar's layout — each\n * item's kind, key and label — changes, rather than on every render, which\n * resolves the items afresh. A label matters for an item in \"More\", whose\n * remembered width it makes stale.\n */\nexport default function useToolbarOverflow(\n toolbarRef: RefObject<HTMLElement | null>,\n items: readonly ResolvedToolbarItem[],\n): number {\n const [fit, setFit] = useState(items.length);\n const overflow = useRef<ToolbarOverflow | null>(null);\n const measuredLayout = useRef(\"\");\n const layout = JSON.stringify(\n items.map((item) => [\n item.type,\n item.key,\n \"label\" in item ? item.label : null,\n ]),\n );\n\n useLayoutEffect(() => {\n const toolbar = toolbarRef.current;\n if (toolbar === null || layout === measuredLayout.current) {\n return;\n }\n measuredLayout.current = layout;\n const options = { items, onChange: setFit };\n if (overflow.current === null) {\n overflow.current = observeToolbarOverflow(toolbar, options);\n } else {\n overflow.current.update(options);\n }\n }, [toolbarRef, layout, items]);\n\n useLayoutEffect(\n () => () => {\n overflow.current?.detach();\n overflow.current = null;\n measuredLayout.current = \"\";\n },\n [],\n );\n\n return fit;\n}\n","import type { PointerEvent as ReactPointerEvent } from \"react\";\nimport {\n resolveKeyboardDropTarget,\n type ColumnOrderState,\n type GroupByState,\n} from \"@gridkitjs/core\";\nimport { resolveColumnDropTarget, type ColumnDropTarget } from \"@gridkitjs/dom\";\nimport type { ResolvedColumn } from \"./DataGrid\";\nimport useDragReorder from \"./useDragReorder\";\n\ninterface UseColumnDragOptions {\n order: ColumnOrderState;\n /** What a drop onto the group-by bar is resolved against. */\n groupBy: GroupByState;\n /** Column ids whose header may be dragged into the group-by bar at all. */\n groupByDraggableIds: ReadonlySet<string>;\n onDrop: (target: ColumnDropTarget, movedId: string) => void;\n}\n\nexport interface ColumnDragApi<Row> {\n /** The column being dragged, for as long as the drag lasts. */\n draggedColumnId: string | null;\n /** Where it would land if released now. */\n dropTarget: ColumnDropTarget | null;\n /** Where the element trailing the pointer sits, as a CSS `transform`. */\n ghostTransform: string | null;\n startDrag: (\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ) => void;\n /** Moves a column one place left (`-1`) or right (`1`). */\n moveByKeyboard: (entry: ResolvedColumn<Row>, direction: -1 | 1) => void;\n /**\n * Whether the gesture that just ended was a drag rather than a click, for a\n * header that has something of its own to do with a click.\n *\n * Reading it clears it, so that a press which never opened a drag at all —\n * on a column that cannot be reordered — does not see the last one's answer.\n */\n justDragged: () => boolean;\n}\n\n/**\n * Turns a pointer drag over the header into a drop target, leaving `onDrop` to\n * apply it. Built on `useDragReorder`'s shared pointer mechanics, with\n * `@gridkitjs/dom`'s `resolveColumnDropTarget` as the hit-testing: another\n * header (reorder among columns) or the group-by bar (add this column to the\n * grouping), tried in that order.\n */\nexport default function useColumnDrag<Row>({\n order,\n groupBy,\n groupByDraggableIds,\n onDrop,\n}: UseColumnDragOptions): ColumnDragApi<Row> {\n const drag = useDragReorder<ColumnDropTarget>({\n resolveTarget: (clientX, clientY, movedId) =>\n resolveColumnDropTarget(clientX, clientY, movedId, {\n order,\n groupBy,\n groupByDraggableIds,\n }),\n onDrop,\n });\n\n function startDrag(\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ): void {\n drag.startDrag(entry.id, event.currentTarget, event);\n }\n\n function moveByKeyboard(entry: ResolvedColumn<Row>, direction: -1 | 1): void {\n const beforeId = resolveKeyboardDropTarget(order, entry.id, direction);\n if (beforeId === undefined) {\n return;\n }\n onDrop({ kind: \"column-order\", beforeId }, entry.id);\n }\n\n // A new object each render, as `useColumnResize` returns: the handlers close\n // over `order`/`groupBy`, and a stable identity would buy nothing.\n return {\n draggedColumnId: drag.draggedId,\n dropTarget: drag.dropTarget,\n ghostTransform: drag.ghostTransform,\n startDrag,\n moveByKeyboard,\n justDragged: drag.justDragged,\n };\n}\n","import {\n useState,\n type PointerEvent as ReactPointerEvent,\n type RefObject,\n} from \"react\";\nimport {\n beginColumnResize,\n clampColumnWidth,\n resolveColumnConstraints,\n sizeColumnToContent,\n type ColumnSizeDefaults,\n} from \"@gridkitjs/core\";\nimport { measureColumnContent, startColumnResizeGesture } from \"@gridkitjs/dom\";\nimport type { ResolvedColumn } from \"./DataGrid\";\nimport type { DataGridController } from \"./useGridController\";\n\ninterface UseColumnResizeOptions<Row> {\n tableRef: RefObject<HTMLTableElement | null>;\n controller: DataGridController<Row>;\n columnSizeDefaults?: Partial<ColumnSizeDefaults> | undefined;\n}\n\nexport interface ColumnResizeApi<Row> {\n /** The column being dragged, for as long as the drag lasts. */\n activeColumnId: string | null;\n startResize: (\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ) => void;\n /** Sizes a column to its content, and says whether it could: not without cells. */\n sizeToContent: (entry: ResolvedColumn<Row>) => boolean;\n nudge: (entry: ResolvedColumn<Row>, delta: number) => void;\n}\n\n/**\n * Turns pointer and keyboard input into column widths. The drag itself is\n * `@gridkitjs/dom`'s `startColumnResizeGesture`, every width comes from\n * `@gridkitjs/core`, and the grid's controller applies them; this hook holds\n * only which column is being dragged.\n */\nexport default function useColumnResize<Row>({\n tableRef,\n controller,\n columnSizeDefaults,\n}: UseColumnResizeOptions<Row>): ColumnResizeApi<Row> {\n const [activeColumnId, setActiveColumnId] = useState<string | null>(null);\n\n function startResize(\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ): void {\n // A press on the handle is never the header's, whichever button made it:\n // a reorderable header's own drag must not see it.\n event.stopPropagation();\n\n const session = beginColumnResize(\n entry.column,\n entry.width,\n event.clientX,\n columnSizeDefaults,\n );\n /** The sizing as the drag found it, which Escape puts the column back to. */\n const base = controller.getState().columnSizing;\n\n const started = startColumnResizeGesture(\n event.currentTarget,\n event,\n session,\n {\n onMove(width) {\n controller.resizeColumn(session.columnId, width, \"move\");\n },\n onEnd(width) {\n setActiveColumnId(null);\n if (width !== null) {\n controller.resizeColumn(session.columnId, width, \"end\");\n }\n },\n /**\n * Escape puts back only the dragged column's pre-drag width, merged\n * into whatever the sizing state is *now* — not the `base` snapshot\n * taken at drag-start — so a different column resized via keyboard\n * while this drag was still open keeps its change instead of being\n * clobbered by a stale restore.\n */\n onCancel() {\n setActiveColumnId(null);\n controller.cancelColumnResize(\n session.columnId,\n base,\n session.startWidth,\n );\n },\n },\n );\n if (started) {\n setActiveColumnId(session.columnId);\n }\n }\n\n function sizeToContent(entry: ResolvedColumn<Row>): boolean {\n const table = tableRef.current;\n if (table === null) {\n return false;\n }\n\n const measured = measureColumnContent(table, entry.id);\n if (measured === null) {\n return false;\n }\n\n controller.resizeColumn(\n entry.id,\n sizeColumnToContent(\n measured,\n resolveColumnConstraints(entry.column, columnSizeDefaults),\n ),\n \"end\",\n );\n return true;\n }\n\n function nudge(entry: ResolvedColumn<Row>, delta: number): void {\n controller.resizeColumn(\n entry.id,\n clampColumnWidth(\n entry.width + delta,\n resolveColumnConstraints(entry.column, columnSizeDefaults),\n ),\n \"end\",\n );\n }\n\n // A new object each render, as the other hooks here return.\n return { activeColumnId, startResize, sizeToContent, nudge };\n}\n","import { useLayoutEffect, useState, type RefObject } from \"react\";\nimport { observeElementWidth } from \"@gridkitjs/dom\";\n\n/**\n * The inner width of `ref`'s element, tracked as it changes by\n * `@gridkitjs/dom`'s `observeElementWidth`.\n *\n * A layout effect rather than an effect so the first measurement lands before\n * paint — otherwise columns show at their natural width for a frame and then\n * visibly jump once auto-fit runs. No isomorphic-layout-effect shim: React 19\n * skips layout effects on the server without a warning, and the width stays\n * `null` until the client measures.\n *\n * @param enabled Whether to observe at all. A caller that does not read the\n * width passes `false` rather than paying a re-render of the whole grid on\n * every frame of a window resize.\n */\nexport default function useElementWidth(\n ref: RefObject<HTMLElement | null>,\n enabled: boolean,\n): number | null {\n const [width, setWidth] = useState<number | null>(null);\n\n useLayoutEffect(() => {\n const element = ref.current;\n if (element === null || !enabled) {\n return undefined;\n }\n return observeElementWidth(element, setWidth);\n }, [ref, enabled]);\n\n return width;\n}\n","import { useState, useSyncExternalStore, type ReactNode } from \"react\";\nimport {\n createGridController,\n type GridController,\n type GridControllerOptions,\n type GridState,\n type GridView,\n} from \"@gridkitjs/core\";\n\n/** The grid's controller, bound to React's node type for its columns. */\nexport type DataGridController<Row> = GridController<Row, ReactNode>;\n\nexport interface GridControllerBinding<Row> {\n controller: DataGridController<Row>;\n /** The state this render draws — re-read on every change the controller commits. */\n state: GridState<Row>;\n view: GridView<Row, ReactNode>;\n}\n\n/**\n * The grid's controller, created once and handed the current props on every\n * render. The controller holds every slice of state and derives the view, so\n * this hook only keeps React in step with it: `setOptions` runs during render,\n * so the view drawn always matches the props drawn, and the subscription\n * re-renders the grid when an action commits.\n *\n * `getState` is the snapshot: the controller hands back the same object until\n * a slice changes, which is exactly the stability `useSyncExternalStore`\n * needs, and a change the props made (a controlled slice) is already in it by\n * the time it is read here. It is the server snapshot too: on the server and\n * while hydrating, the controller has seen only the props, so both sides read\n * the same initial state.\n */\nexport default function useGridController<Row>(\n options: GridControllerOptions<Row, ReactNode>,\n): GridControllerBinding<Row> {\n const [controller] = useState(() =>\n createGridController<Row, ReactNode>(options),\n );\n controller.setOptions(options);\n const state = useSyncExternalStore(\n controller.subscribe,\n controller.getState,\n controller.getState,\n );\n return { controller, state, view: controller.getView() };\n}\n","import { useEffect, useRef, type RefObject } from \"react\";\nimport { attachInfiniteScroll, type InfiniteScroll } from \"@gridkitjs/dom\";\nimport type { InfiniteScrollConfig } from \"./DataGrid\";\n\ninterface UseInfiniteScrollOptions {\n /** The `.gridkit-data-grid-body` scroll wrapper. */\n rootRef: RefObject<HTMLDivElement | null>;\n /** The always-last `<tr>` `GridBody` renders while `config?.hasMore` is true. */\n sentinelRef: RefObject<HTMLTableRowElement | null>;\n config: InfiniteScrollConfig | undefined;\n}\n\n/**\n * `@gridkitjs/dom`'s `attachInfiniteScroll` on the body, idle until the\n * effect below hands it the props. That runs after every commit: the\n * sentinel row mounts and unmounts with `hasMore`, so only after a commit is\n * `sentinelRef` current, and an update that changes nothing does nothing.\n */\nexport default function useInfiniteScroll({\n rootRef,\n sentinelRef,\n config,\n}: UseInfiniteScrollOptions): void {\n const scroll = useRef<InfiniteScroll | null>(null);\n\n useEffect(() => {\n const root = rootRef.current;\n if (root === null) {\n return undefined;\n }\n const attached = attachInfiniteScroll(root, {\n sentinel: null,\n hasMore: false,\n });\n scroll.current = attached;\n return () => {\n attached.detach();\n scroll.current = null;\n };\n }, [rootRef]);\n\n useEffect(() => {\n scroll.current?.update({\n sentinel: sentinelRef.current,\n hasMore: config?.hasMore ?? false,\n onLoadMore: config?.onLoadMore,\n isLoadingMore: config?.isLoadingMore,\n rootMargin: config?.rootMargin,\n });\n });\n}\n","import { useCallback, useLayoutEffect, useRef, type RefObject } from \"react\";\nimport { createLiveAnnouncer, type LiveAnnouncer } from \"@gridkitjs/dom\";\n\n/**\n * The grid's live region, added as the last child of `containerRef`'s element\n * once it mounts. `@gridkitjs/dom` owns the element, so React never renders\n * it and an announcement re-renders nothing.\n *\n * A layout effect, so the region is in place from the first paint — where it\n * was when React rendered it. The returned `announce` keeps its identity for\n * the grid's whole life.\n */\nexport default function useLiveAnnouncer(\n containerRef: RefObject<HTMLElement | null>,\n): (text: string) => void {\n const announcer = useRef<LiveAnnouncer | null>(null);\n\n useLayoutEffect(() => {\n const container = containerRef.current;\n if (container === null) {\n return undefined;\n }\n const created = createLiveAnnouncer(container);\n announcer.current = created;\n return () => {\n created.destroy();\n announcer.current = null;\n };\n }, [containerRef]);\n\n return useCallback((text: string) => {\n announcer.current?.announce(text);\n }, []);\n}\n","import { useLayoutEffect, useState, type RefObject } from \"react\";\nimport type { VisibleRange } from \"@gridkitjs/core\";\nimport { createRowVirtualizer, type RowVirtualizer } from \"@gridkitjs/dom\";\n\nexport interface RowVirtualizerApi extends VisibleRange {\n /** Ref callback `GridBody` attaches to each rendered row's `<tr>`, keyed by that row's index in the full array. */\n measureRow: (index: number) => (element: HTMLTableRowElement | null) => void;\n /**\n * Scrolls so `index` is visible. Two-pass for a row not currently mounted:\n * jumps to an estimated offset immediately, then — once that row mounts and\n * its real height is measured — corrects the scroll position via the\n * mounted element's own `scrollIntoView`. A row already mounted is scrolled\n * to directly, in one pass.\n */\n scrollToIndex: (index: number, options?: ScrollIntoViewOptions) => void;\n}\n\ninterface UseRowVirtualizerOptions {\n /** Whether virtualization is active at all. `false` attaches nothing — no behavioral or performance difference from not virtualizing. */\n enabled: boolean;\n /** The full row array — only its `.length` and reference identity matter here; a new reference resets the measured heights (see below). */\n rows: readonly unknown[];\n /** The `.gridkit-data-grid-body` scroll wrapper. */\n bodyScrollRef: RefObject<HTMLDivElement | null>;\n estimatedRowHeight: number;\n overscan: number;\n}\n\nconst EMPTY_RANGE: VisibleRange = {\n startIndex: 0,\n endIndex: -1,\n offsetBefore: 0,\n offsetAfter: 0,\n};\n\n/** What a row is measured with before the virtualizer exists — while nothing is rendered. */\nfunction ignoreRow(): () => void {\n return () => undefined;\n}\n\n/**\n * `@gridkitjs/dom`'s `createRowVirtualizer` on the body, with the window of\n * rows it reports held as state for `GridBody` to render. The virtualizer is\n * state too, not a ref, because `measureRow` is read while rendering: a new\n * one — `estimatedRowHeight` or `overscan` changed — re-renders every row\n * with its own ref callbacks, so the rows already mounted are measured anew.\n *\n * Layout effects, so the window settles before paint rather than showing the\n * previous one for a frame — the same reason `useElementWidth` measures in a\n * layout effect.\n *\n * The measured heights reset whenever `rows` becomes a new reference\n * (filter, sort, groupBy, or `dataSource` itself changing) rather than\n * tracking each of those individually — the simplest rule that stays\n * correct, at the cost of one remeasurement on those already-big operations.\n * Keying heights by row id instead, to survive a pure reorder, is a\n * considered, deliberately deferred enhancement.\n */\nexport default function useRowVirtualizer({\n enabled,\n rows,\n bodyScrollRef,\n estimatedRowHeight,\n overscan,\n}: UseRowVirtualizerOptions): RowVirtualizerApi {\n const [virtualizer, setVirtualizer] = useState<RowVirtualizer | null>(null);\n const [range, setRange] = useState<VisibleRange>(EMPTY_RANGE);\n\n useLayoutEffect(() => {\n const element = bodyScrollRef.current;\n if (!enabled || element === null) {\n return undefined;\n }\n const created = createRowVirtualizer(element, {\n estimatedRowHeight,\n overscan,\n onRange: setRange,\n });\n setVirtualizer(created);\n return () => {\n created.destroy();\n };\n }, [enabled, bodyScrollRef, estimatedRowHeight, overscan]);\n\n useLayoutEffect(() => {\n virtualizer?.setRowCount(rows.length);\n virtualizer?.resetHeights();\n }, [virtualizer, rows]);\n\n return {\n startIndex: range.startIndex,\n endIndex: range.endIndex,\n offsetBefore: range.offsetBefore,\n offsetAfter: range.offsetAfter,\n measureRow: virtualizer?.measureRow ?? ignoreRow,\n scrollToIndex: (index, options) => {\n virtualizer?.scrollToIndex(index, options);\n },\n };\n}\n","// React components will be exported from here. They consume the framework-agnostic logic in @gridkitjs/core.\nexport {\n DataGrid,\n type Borders,\n type CellSelectEvent,\n type CellSelectionChangeEvent,\n type ColumnDefinition,\n type ColumnSelectEvent,\n type ColumnSelectionChangeEvent,\n type ColumnsSelectEvent,\n type DataColumn,\n type DataGridApi,\n type DataGridProps,\n type GroupByBarVisibility,\n type HoverableConfig,\n type InfiniteScrollConfig,\n type PagerConfig,\n type PagerTemplateContext,\n type ReactRenderSlots,\n type ResizeMode,\n type ResolvedColumn,\n type SelectedCell,\n type SelectedColumn,\n} from \"./DataGrid/DataGrid\";\n// Re-exported so a consumer wiring up resize or selection, or typing a\n// standalone cellTemplate, needs one import and not two. The row payloads name\n// no node type of their own, so they come straight from core.\nexport type {\n CellSelectionMode,\n CellSelectionState,\n CellTemplateContext,\n ColumnResizeEvent,\n ColumnSizeDefaults,\n ColumnSizingState,\n ColumnVisibilityEvent,\n ColumnVisibilityState,\n ContextMenuOpenChangeEvent,\n FilterChangeEvent,\n FilterEntry,\n FilterState,\n GridCommand,\n GridCommandEvent,\n GridCommandTarget,\n GridContextMenuOptions,\n GridContextMenuRequest,\n GridContextMenuTarget,\n GridMessages,\n GridOptions,\n GridState,\n GridToolbarOptions,\n MenuEntry,\n SerializedGridState,\n ResolvedRow,\n RowPointerEvent,\n RowProps,\n RowSelectEvent,\n RowSelectionChangeEvent,\n RowsSelectEvent,\n SelectableConfig,\n SelectedCellRef,\n SelectionMode,\n SelectionState,\n ToolbarEntry,\n} from \"@gridkitjs/core\";\n\n// Re-exported for the same reason: saving `getState()` as JSON goes through it.\nexport { serializeGridState } from \"@gridkitjs/core\";\n\n// Reactive hooks for building custom UI outside the grid's own DOM, each\n// subscribing to `DataGridApi.subscribe` via `useSyncExternalStore`.\nexport { default as usePaginationState } from \"./DataGrid/hooks/usePaginationState\";\nexport type { PaginationStateApi } from \"./DataGrid/hooks/usePaginationState\";\nexport { default as useGroupByState } from \"./DataGrid/hooks/useGroupByState\";\nexport type { GroupByStateApi } from \"./DataGrid/hooks/useGroupByState\";\nexport { default as useColumnSortState } from \"./DataGrid/hooks/useColumnSortState\";\nexport { default as useSelectionState } from \"./DataGrid/hooks/useSelectionState\";\nexport type { SelectionStateApi } from \"./DataGrid/hooks/useSelectionState\";\nexport { default as useAggregateState } from \"./DataGrid/hooks/useAggregateState\";\nexport { default as useColumnSizingState } from \"./DataGrid/hooks/useColumnSizingState\";\nexport { default as useColumnOrderState } from \"./DataGrid/hooks/useColumnOrderState\";\nexport { default as useColumnVisibilityState } from \"./DataGrid/hooks/useColumnVisibilityState\";\nexport { default as useFilterState } from \"./DataGrid/hooks/useFilterState\";\nexport type { FilterStateApi } from \"./DataGrid/hooks/useFilterState\";\n\n// Re-exported so typing an export — its options, a writer of the app's own,\n// the file a writer gives — needs no import from core.\nexport type {\n ExportFile,\n ExportOptions,\n ExportWriter,\n GridExportOptions,\n} from \"@gridkitjs/core\";\n\n// Re-exported so typing the `print` option, or a call to `print`, needs no\n// import from core.\nexport type { PrintOptions } from \"@gridkitjs/core\";\n\n// The filter popup in its Excel-style form, spread into `DataGrid`:\n// `<DataGrid {...excelFilter} />`.\nexport { excelFilter } from \"@gridkitjs/core\";\n","import { useCallback, type RefObject } from \"react\";\nimport type { PaginationState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_PAGINATION: PaginationState = { pageIndex: 0, pageSize: 0 };\n\nexport interface PaginationStateApi {\n pagination: PaginationState;\n pageCount: number;\n goToPage: (pageIndex: number) => void;\n nextPage: () => void;\n previousPage: () => void;\n setPageSize: (pageSize: number) => void;\n}\n\n/**\n * Reactive pagination state read off a mounted `DataGrid`'s `ref`,\n * for building a pager entirely outside the grid's own DOM — a toolbar or\n * sidebar `pager.template` can't reach. Updates on every pagination change,\n * including the silent page-0 reset a filter/sort/group change triggers,\n * which carries no `onPaginationChange` of its own.\n *\n * Before the grid mounts, `pagination` reads `{ pageIndex: 0, pageSize: 0 }`\n * and `pageCount` reads `0`; the actions are no-ops until then.\n */\nexport default function usePaginationState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): PaginationStateApi {\n const pagination = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getPagination(), []),\n FALLBACK_PAGINATION,\n );\n const pageCount = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getPageCount(), []),\n 0,\n );\n\n return {\n pagination,\n pageCount,\n goToPage: (pageIndex) => {\n gridRef.current?.goToPage(pageIndex);\n },\n nextPage: () => {\n gridRef.current?.nextPage();\n },\n previousPage: () => {\n gridRef.current?.previousPage();\n },\n setPageSize: (pageSize) => {\n gridRef.current?.setPageSize(pageSize);\n },\n };\n}\n","import { useCallback, useSyncExternalStore, type RefObject } from \"react\";\nimport type { DataGridApi } from \"../DataGrid\";\n\n/**\n * Shared `useSyncExternalStore` wiring behind every public `use*State` hook\n * in this folder. Not exported — `gridRef.current` is `null` until the grid\n * mounts, so subscribing has to tolerate that, and falls back to `fallback`\n * for the same reason `getSnapshot` has to until then. The ref is `null` on\n * the server and while hydrating too, so `fallback` is the server snapshot.\n */\nexport default function useGridSnapshot<Row, T>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n getSnapshot: (api: DataGridApi<Row>) => T,\n fallback: T,\n): T {\n const subscribe = useCallback(\n (listener: () => void) => {\n const api = gridRef.current;\n if (api === null) {\n return () => {\n // Nothing was subscribed — `subscribe` itself already handles\n // that below by re-running on every render until the ref mounts.\n };\n }\n return api.subscribe(listener);\n },\n [gridRef],\n );\n\n return useSyncExternalStore(\n subscribe,\n () => {\n const api = gridRef.current;\n return api === null ? fallback : getSnapshot(api);\n },\n () => fallback,\n );\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { GroupByState, GroupExpansionState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_GROUP_BY: GroupByState = [];\nconst FALLBACK_EXPANSION: GroupExpansionState = [];\n\nexport interface GroupByStateApi {\n groupBy: GroupByState;\n groupExpansion: GroupExpansionState;\n expandAllGroups: () => void;\n collapseAllGroups: () => void;\n}\n\n/**\n * Reactive group-by and group-expansion state read off a mounted\n * `DataGrid`'s `ref`, for a group-by bar or summary sidebar living\n * outside the grid's own DOM.\n *\n * The ref's `setGroupBy` and `setGroupExpansion` change the grouping and the\n * collapsed groups for a custom group-by UI; this hook carries only the\n * all-at-once expansion actions. A specific\n * group's own computed aggregates are read off `getDisplayRows()`'s\n * per-header `aggregates` field instead of a getter here — see\n * `useAggregateState` for the grand-total equivalent.\n *\n * Before the grid mounts, both fields read as empty and the actions are\n * no-ops.\n */\nexport default function useGroupByState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): GroupByStateApi {\n const groupBy = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getGroupBy(), []),\n FALLBACK_GROUP_BY,\n );\n const groupExpansion = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getGroupExpansion(), []),\n FALLBACK_EXPANSION,\n );\n\n return {\n groupBy,\n groupExpansion,\n expandAllGroups: () => {\n gridRef.current?.expandAllGroups();\n },\n collapseAllGroups: () => {\n gridRef.current?.collapseAllGroups();\n },\n };\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { ColumnSortState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_SORT: ColumnSortState = [];\n\n/**\n * Reactive column-sort state read off a mounted `DataGrid`'s `ref`,\n * for a sort indicator living outside the grid's own DOM.\n *\n * Reads only; change the sort through the ref's `setColumnSort`, or hold it\n * yourself with the controlled `columnSort` prop.\n *\n * Before the grid mounts, reads as an empty array.\n */\nexport default function useColumnSortState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): ColumnSortState {\n return useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getColumnSort(), []),\n FALLBACK_SORT,\n );\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { CellSelectionState, SelectionState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_SELECTION: SelectionState = [];\nconst FALLBACK_CELL_SELECTION: CellSelectionState = null;\n\nexport interface SelectionStateApi {\n rowSelection: SelectionState;\n columnSelection: SelectionState;\n cellSelection: CellSelectionState;\n clearSelection: () => void;\n selectAllRows: () => void;\n}\n\n/**\n * Reactive row/column/cell selection state read off a mounted\n * `DataGrid`'s `ref`, for a \"N rows selected\" toolbar living\n * outside the grid's own DOM. One combined hook rather than three, matching\n * how `useGridSelection` already treats all three as one concern\n * internally.\n *\n * Before the grid mounts, the row/column fields read as empty arrays and\n * the cell field reads `null`; the actions are no-ops.\n */\nexport default function useSelectionState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): SelectionStateApi {\n const rowSelection = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getRowSelection(), []),\n FALLBACK_SELECTION,\n );\n const columnSelection = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getColumnSelection(), []),\n FALLBACK_SELECTION,\n );\n const cellSelection = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getCellSelection(), []),\n FALLBACK_CELL_SELECTION,\n );\n\n return {\n rowSelection,\n columnSelection,\n cellSelection,\n clearSelection: () => {\n gridRef.current?.clearSelection();\n },\n selectAllRows: () => {\n gridRef.current?.selectAllRows();\n },\n };\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { AggregateResults } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_AGGREGATES: AggregateResults = new Map();\n\n/**\n * Reactive grand-total aggregate results read off a mounted\n * `DataGrid`'s `ref`, for a summary footer or bar living outside\n * the grid's own DOM — mirroring the built-in one the grid renders itself.\n *\n * Read-only: `getAggregates` is already read-only on `DataGridApi`, computed\n * over the whole filtered/sorted dataset rather than driven by any action.\n * A specific group's own subtotal is read off `getDisplayRows()`'s\n * per-header `aggregates` field instead — see `useGroupByState`.\n *\n * Before the grid mounts, reads as an empty map.\n */\nexport default function useAggregateState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): AggregateResults {\n return useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getAggregates(), []),\n FALLBACK_AGGREGATES,\n );\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { ColumnSizingState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_SIZING: ColumnSizingState = {};\n\n/**\n * Reactive column-sizing state read off a mounted `DataGrid`'s\n * `ref`. Reads only; change the widths through the ref's `setColumnSizing`,\n * or hold them yourself with the controlled `columnSizing` prop.\n *\n * Before the grid mounts, reads as an empty object.\n */\nexport default function useColumnSizingState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): ColumnSizingState {\n return useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getColumnSizing(), []),\n FALLBACK_SIZING,\n );\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { ColumnOrderState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_ORDER: ColumnOrderState = [];\n\n/**\n * Reactive column-order state read off a mounted `DataGrid`'s\n * `ref`. Reads only; change the order through the ref's `setColumnOrder`,\n * or hold it yourself with the controlled `columnOrder` prop.\n *\n * Before the grid mounts, reads as an empty array.\n */\nexport default function useColumnOrderState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): ColumnOrderState {\n return useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getColumnOrder(), []),\n FALLBACK_ORDER,\n );\n}\n","import { useCallback, type RefObject } from \"react\";\nimport type { ColumnVisibilityState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nconst FALLBACK_VISIBILITY: ColumnVisibilityState = {};\n\n/**\n * Reactive column-visibility state read off a mounted `DataGrid`'s `ref` —\n * the columns shown or hidden since it mounted, keyed by id. Read-only:\n * change it through the ref's `showColumns`/`hideColumns`. A column absent\n * from it follows its definition's `hidden`.\n *\n * Before the grid mounts, reads as an empty object.\n */\nexport default function useColumnVisibilityState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): ColumnVisibilityState {\n return useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getColumnVisibility(), []),\n FALLBACK_VISIBILITY,\n );\n}\n","import { useCallback, useState, type RefObject } from \"react\";\nimport type { FilterState } from \"@gridkitjs/core\";\nimport type { DataGridApi } from \"../DataGrid\";\nimport useGridSnapshot from \"./useGridSnapshot\";\n\nexport interface FilterStateApi<Row> {\n filter: FilterState<Row>;\n setFilter: (filter: FilterState<Row>) => void;\n}\n\n/**\n * Reactive filter state read off a mounted `DataGrid`'s `ref`, for a filter\n * bar or search box living outside the grid's own DOM, which sees every change\n * however it was made — the toolbar's search box included. `setFilter`\n * replaces the whole filter and sends the grid back to its first page.\n *\n * Before the grid mounts, `filter` reads as an empty array and `setFilter`\n * is a no-op.\n */\nexport default function useFilterState<Row>(\n gridRef: RefObject<DataGridApi<Row> | null>,\n): FilterStateApi<Row> {\n // Held per hook rather than as one module constant: a filter is typed by\n // its row, through a predicate's parameter, so one empty array cannot\n // stand in for every `Row`. Either way it must keep its identity.\n const [fallback] = useState<FilterState<Row>>(() => []);\n const filter = useGridSnapshot(\n gridRef,\n useCallback((api: DataGridApi<Row>) => api.getFilter(), []),\n fallback,\n );\n\n return {\n filter,\n setFilter: (next) => {\n gridRef.current?.setFilter(next);\n },\n };\n}\n"],"mappings":"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","names":["useEffect","useId","useImperativeHandle","useMemo","useRef","useState","resolveColumnHeaderText","jsx","jsx","jsxs","useMemo","useState","intentOf","jsx","jsxs","memo","jsx","jsxs","memo","memo","jsx","memo","jsx","jsxs","useMemo","useState","intentOf","jsx","jsx","jsxs","createPortal","resolveColumnLabel","useState","jsx","jsxs","resolveColumnLabel","createPortal","useMemo","runCommand","useRef","useRef","document","useMemo","document","runCommand","useLayoutEffect","useRef","useState","useLayoutEffect","useRef","createPortal","jsx","useRef","useLayoutEffect","createPortal","jsx","jsxs","ChevronLeftIcon","ChevronRightIcon","Fragment","jsx","jsxs","isItem","ChevronRightIcon","useRef","useState","useLayoutEffect","jsx","useEffect","useLayoutEffect","useRef","useState","HEADER_ROW","bodyCellFrom","bodyRowFrom","findBodyRow","groupRowFrom","useState","useRef","useLayoutEffect","useEffect","useRef","useLayoutEffect","useRef","useState","Fragment","jsx","jsxs","useEffect","useRef","resolveColumnFilterMenu","resolveMenu","useImperativeHandle","useLayoutEffect","useMemo","useRef","useState","describeColumnFilter","draftToFilter","filterEditorReducer","initialFilterEditorDraft","useLayoutEffect","useRef","useState","Fragment","jsx","jsxs","useState","useRef","useLayoutEffect","ChevronRightIcon","Fragment","useLayoutEffect","useRef","useState","jsx","jsxs","jsx","jsxs","useState","draft","useRef","useLayoutEffect","Fragment","useLayoutEffect","useRef","useState","Fragment","jsx","jsxs","useRef","useState","useLayoutEffect","Fragment","jsx","jsxs","useState","shape","describeColumnFilter","initialFilterEditorDraft","filterEditorReducer","useRef","useMemo","useLayoutEffect","useImperativeHandle","draftToFilter","ChevronLeftIcon","jsx","jsxs","useRef","resolveColumnFilterMenu","useEffect","resolveMenu","useEffect","useRef","useState","NO_ROWS","jsx","useRef","resolveColumnFilterMenu","useLayoutEffect","useRef","useState","headerCell","useState","useRef","useLayoutEffect","useLayoutEffect","useRef","useLayoutEffect","useRef","useState","Fragment","jsx","jsxs","useState","useRef","useLayoutEffect","useEffect","useRef","useState","jsx","useLayoutEffect","useRef","useState","jsx","jsxs","useRef","useLayoutEffect","resolveKeyboardDropTarget","resolveKeyboardDropTarget","useState","useLayoutEffect","useState","useState","useSyncExternalStore","useEffect","useRef","useLayoutEffect","useRef","useLayoutEffect","useState","createRowVirtualizer","jsx","jsxs","useRef","useId","useMemo","useState","useEffect","resolveColumnHeaderText","useImperativeHandle","useCallback","useCallback","useSyncExternalStore","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useState","useState","useCallback"]}
|