//#region src/types/basic.d.ts /** Cell data type primitive types */ type CellDataType = "text" | "number" | "boolean" | "date" | "dateString" | "dateTime" | "dateTimeString" | "object"; /** Cell value type */ type CellValue = string | number | boolean | Date | object | null; /** Row ID type for transaction operations */ type RowId = string | number; /** Sort direction type */ type SortDirection = "asc" | "desc" | null; /** Sort model type */ type SortModel = { colId: string; direction: SortDirection; }; /** Cell position */ interface CellPosition { row: number; col: number; } /** Cell range */ interface CellRange { startRow: number; startCol: number; endRow: number; endCol: number; } /** Selection state */ interface SelectionState { /** Active cell position */ activeCell: CellPosition | null; /** Selection range */ range: CellRange | null; /** Anchor cell for shift-extend selection */ anchor: CellPosition | null; /** Whether selection mode is active (ctrl held) */ selectionMode: boolean; } /** Edit state */ interface EditState { /** Row index */ row: number; /** Column index */ col: number; /** Initial value */ initialValue: CellValue; /** Current value */ currentValue: CellValue; } /** Fill handle state */ interface FillHandleState { /** Source range */ sourceRange: CellRange; /** Target row */ targetRow: number; /** Target column */ targetCol: number; } /** Event emitted when a cell value is changed via editing, fill drag, or paste */ interface CellValueChangedEvent { /** Stable row ID (from getRowId) */ rowId: RowId; /** Column index */ colIndex: number; /** Column field name */ field: string; /** Previous cell value */ oldValue: CellValue; /** New cell value */ newValue: CellValue; /** The full row data object */ rowData: TData; } /** The slot is the virtualized row, this represents the state of the slot */ interface SlotState { /** Slot ID */ slotId: string; /** Row index */ rowIndex: number; /** Row data */ rowData: unknown; /** Translate Y position of the slot, we use translateY to optimize the rendering of the slots (Relies on the GP) */ translateY: number; } //#endregion //#region src/types/highlighting.d.ts /** * Minimal column info for highlighting context. * Uses structural typing to avoid circular dependency with columns.ts. */ interface HighlightColumnInfo { field: string; colId?: string; } /** * Unified context for row, column, and cell highlighting. * * - Row context: `rowIndex` is set, `colIndex` is null * - Column context: `colIndex` is set, `rowIndex` is null * - Cell context: both `rowIndex` and `colIndex` are set */ interface HighlightContext> { /** Row index. Null for column-only context. */ rowIndex: number | null; /** Column index. Null for row-only context. */ colIndex: number | null; /** Column definition. Present for column and cell contexts. */ column?: HighlightColumnInfo; /** Row data. Present for row and cell contexts. */ rowData?: TData; /** Currently hovered cell position, null if not hovering */ hoverPosition: CellPosition | null; /** Currently active (focused) cell position */ activeCell: CellPosition | null; /** Current selection range */ selectionRange: CellRange | null; /** Whether this row/column/cell is hovered (respects hoverScope) */ isHovered: boolean; /** Whether this row/column contains or is the active cell */ isActive: boolean; /** Whether this row/column/cell overlaps or is in the selection range */ isSelected: boolean; } /** * Grid-level highlighting options. * Hover tracking is automatically enabled when any highlighting callback is defined. * Each callback type has its own natural interpretation of `isHovered`: * - computeRowClasses: isHovered = mouse is on any cell in this row * - computeColumnClasses: isHovered = mouse is on any cell in this column * - computeCellClasses: isHovered = mouse is on this exact cell * * For a crosshair effect, implement both computeRowClasses and computeColumnClasses. */ interface HighlightingOptions> { /** * Row-level class callback. * Classes returned are applied to the row container element. * Context has `rowIndex` set, `colIndex` is null. * `isHovered` is true when the mouse is on any cell in this row. * @returns Array of CSS class names */ computeRowClasses?: (context: HighlightContext) => string[]; /** * Column-level class callback. * Classes returned are applied to all cells in that column (not header). * Context has `colIndex` set, `rowIndex` is null. * `isHovered` is true when the mouse is on any cell in this column. * @returns Array of CSS class names */ computeColumnClasses?: (context: HighlightContext) => string[]; /** * Cell-level class callback. * Classes returned are applied to individual cells for fine-grained control. * Context has both `rowIndex` and `colIndex` set. * `isHovered` is true only when the mouse is on this exact cell. * @returns Array of CSS class names */ computeCellClasses?: (context: HighlightContext) => string[]; } //#endregion //#region src/types/renderers.d.ts /** * Cell renderer params. * * `value` is the value the renderer should display. If the column declares a * `valueFormatter`, `value` is its output (a string); otherwise it's the raw * cell value. Read the raw value from `rowData[column.field]` if the renderer * needs it independently. */ interface CellRendererParams { /** Post-formatter display value, or raw CellValue when no formatter is set */ value: CellValue; /** Row data */ rowData: TData; /** Column definition */ column: ColumnDefinition; /** Row index */ rowIndex: number; /** Column index */ colIndex: number; /** Is active cell */ isActive: boolean; /** Is selected cell */ isSelected: boolean; /** Is editing cell */ isEditing: boolean; } /** Edit renderer params */ interface EditRendererParams extends CellRendererParams { /** Initial value */ initialValue: CellValue; /** On value change */ onValueChange: (newValue: CellValue) => void; /** On commit */ onCommit: () => void; /** On cancel */ onCancel: () => void; } /** Header renderer params */ interface HeaderRendererParams { /** Column definition */ column: ColumnDefinition; /** Column index */ colIndex: number; /** Sort direction */ sortDirection?: SortDirection; /** Sort index */ sortIndex?: number; /** Whether column is sortable */ sortable: boolean; /** Whether column is filterable */ filterable: boolean; /** Whether column has an active filter */ hasFilter: boolean; /** On sort */ onSort: (direction: SortDirection | null, addToExisting: boolean) => void; /** On filter click */ onFilterClick: () => void; } //#endregion //#region src/types/columns.d.ts /** Column definition */ interface ColumnDefinition { field: string; colId?: string; cellDataType: CellDataType; width: number; headerName?: string; editable?: boolean; /** Whether column is sortable. Default: true when sortingEnabled */ sortable?: boolean; /** Whether column is filterable. Default: true */ filterable?: boolean; /** Whether column is hidden. Hidden columns are not rendered but still exist in the definition. Default: false */ hidden?: boolean; /** Whether column is resizable by dragging the header edge. Default: true */ resizable?: boolean; /** Minimum width in pixels when resizing. Default: 50 */ minWidth?: number; /** Maximum width in pixels when resizing. Default: undefined (no limit) */ maxWidth?: number; /** Whether column can be moved/reordered by dragging the header. Default: true */ movable?: boolean; /** Whether this column acts as a drag handle for row dragging. Default: false */ rowDrag?: boolean; /** * Whether double-clicking a non-editable cell opens a read-only peek overlay * that wraps the value across multiple lines. Ignored when `editable` is true * (double-click starts editing instead). Default: true. */ peekable?: boolean; /** * Whether to set a native `title` attribute on cells in this column so the * browser shows the full formatted value on hover. Useful when text is * truncated by the cell width. Default: true. Set false to opt out — e.g. * for cells whose custom renderer already provides its own tooltip. */ tooltip?: boolean; /** * Whether long cell text wraps onto additional lines instead of being * truncated with an ellipsis. Wrapped text is clipped to the fixed row * height (rows do not auto-grow) — use `peekable` (double-click) or the * native `tooltip` to read the full value. Only affects the default text * renderer, not custom `cellRenderer` output. Default: false. */ wrapText?: boolean; /** Renderer key for adapter lookup, or inline renderer function */ cellRenderer?: string | ((params: CellRendererParams) => unknown); editRenderer?: string | ((params: EditRendererParams) => unknown); headerRenderer?: string | ((params: HeaderRendererParams) => unknown); /** * Converts a cell value to its display string. Used by the default cell renderer * when no `cellRenderer` is provided. Useful for `object`-type columns where the * default JSON.stringify may not be suitable (e.g., display a single field of an object). * * Display-only: the values-mode filter groups checkbox entries by this label, * but the filter model (and any server request) always carries RAW values. */ valueFormatter?: (value: CellValue) => string; /** * Pre-supplied set of all possible values for the filter popup's "values" mode. * When provided, the grid skips scanning row data to discover distinct values — * use this for large datasets to avoid an O(n) scan when the value domain is * known up front (e.g., enums, fixed tag lists). Values are still de-duplicated * and sorted by their display string. * * Supply RAW values. When the column also has a `valueFormatter` that collapses * several raw values into one label, this list must contain the FULL raw domain: * values-mode filtering matches raw values, so raws missing from this list can * never be selected and their rows would be hidden by a values filter. */ distinctValues?: CellValue[]; /** * Per-column override for column-level highlighting. * If defined, overrides grid-level computeColumnClasses for this column. * Context has `colIndex` set, `rowIndex` is null. * @returns Array of CSS class names to apply to all cells in this column */ computeColumnClasses?: (context: HighlightContext) => string[]; /** * Per-column override for cell-level highlighting. * If defined, overrides grid-level computeCellClasses for cells in this column. * Context has both `rowIndex` and `colIndex` set. * @returns Array of CSS class names to apply to individual cells */ computeCellClasses?: (context: HighlightContext) => string[]; } //#endregion //#region src/types/filters.d.ts /** Text filter operators */ type TextFilterOperator = "contains" | "notContains" | "equals" | "notEquals" | "startsWith" | "endsWith" | "blank" | "notBlank"; /** Number filter operators (symbols for display) */ type NumberFilterOperator = "=" | "!=" | ">" | "<" | ">=" | "<=" | "between" | "blank" | "notBlank"; /** Date filter operators */ type DateFilterOperator = "=" | "!=" | ">" | "<" | "between" | "blank" | "notBlank"; /** Filter combination mode */ type FilterCombination = "and" | "or"; /** Text filter condition */ interface TextFilterCondition { type: "text"; operator: TextFilterOperator; value?: string; /** * Raw cell values selected in values (checkbox) mode. * * These are raw values, never formatted labels: server-side data sources * receive them as-is in `DataSourceRequest.filter`, and display formatting * (`ColumnDefinition.valueFormatter`) never enters the filter model. Treat * the set as immutable — replace it to change the selection. When * serializing a request for a server, convert the Set to an array. */ selectedValues?: Set; /** Include blank values */ includeBlank?: boolean; } /** Number filter condition */ interface NumberFilterCondition { type: "number"; operator: NumberFilterOperator; value?: number; /** Second value for "between" operator */ valueTo?: number; } /** Date filter condition */ interface DateFilterCondition { type: "date"; operator: DateFilterOperator; value?: Date | string; /** Second value for "between" operator */ valueTo?: Date | string; } /** Union of filter condition types */ type FilterCondition = TextFilterCondition | NumberFilterCondition | DateFilterCondition; /** A visibly grouped set of conditions joined by one operator. */ interface FilterConditionGroup { conditions: FilterCondition[]; combination: FilterCombination; } /** Column filter model with one explicit level of condition groups. */ interface ColumnFilterModel { groups: FilterConditionGroup[]; combination: FilterCombination; } /** * Condition shape accepted when restoring a filter created before grouped * composition was introduced. */ type LegacyFilterCondition = FilterCondition & { /** Operator connecting this condition to the next. */ nextOperator?: FilterCombination; }; /** Legacy left-to-right column filter model accepted as migration input. */ interface LegacyColumnFilterModel { conditions: LegacyFilterCondition[]; combination: FilterCombination; } /** Canonical or legacy input accepted by the imperative filter API. */ type ColumnFilterInput = ColumnFilterModel | LegacyColumnFilterModel; /** Filter model type - maps column ID to filter */ type FilterModel = Record; //#endregion //#region src/types/data-source.d.ts /** Data loading mode advertised by a data source */ type DataSourceLoadMode = "all" | "paginated"; /** Absolute row range requested from a data source. endRow is exclusive. */ interface DataSourceRange { /** First row index to fetch */ startRow: number; /** First row index after the requested range */ endRow: number; } /** Data source request */ interface DataSourceRequest { /** Absolute row range to fetch. endRow is exclusive. */ range: DataSourceRange; /** Sort */ sort?: SortModel[]; /** Filter */ filter?: FilterModel; /** * Per-field value formatters, derived from column definitions. * Client data sources use these only for free-text condition operators * (contains, equals, ...) so they match the displayed value the user * typed against. Values-mode `selectedValues` always hold raw values and * ignore them. Server-side data sources may ignore them entirely. */ valueFormatters?: Record string>; } /** Data source response */ interface DataSourceResponse { /** Rows */ rows: TData[]; /** Total rows */ totalRows: number; } /** Data source interface */ interface DataSource { /** * Loading mode preferred by this data source. * Undefined is treated as "all". */ readonly loadMode?: DataSourceLoadMode; /** Query data based on the request (range, sort, filter). */ query(request: DataSourceRequest): Promise>; /** Optional cleanup method to release resources */ destroy?: () => void; /** Move a row */ moveRow?: (fromIndex: number, toIndex: number) => void; } //#endregion //#region src/types/instructions.d.ts /** Create slot instruction */ interface CreateSlotInstruction { type: "CREATE_SLOT"; slotId: string; } /** Destroy slot instruction */ interface DestroySlotInstruction { type: "DESTROY_SLOT"; slotId: string; } /** Assign slot instruction */ interface AssignSlotInstruction { type: "ASSIGN_SLOT"; slotId: string; rowIndex: number; rowData: unknown; } /** Move slot instruction */ interface MoveSlotInstruction { type: "MOVE_SLOT"; slotId: string; translateY: number; } /** Set active cell instruction */ interface SetActiveCellInstruction { type: "SET_ACTIVE_CELL"; position: CellPosition | null; } /** Set hover position instruction (for highlighting) */ interface SetHoverPositionInstruction { type: "SET_HOVER_POSITION"; position: CellPosition | null; } /** Set selection range instruction */ interface SetSelectionRangeInstruction { type: "SET_SELECTION_RANGE"; range: CellRange | null; } /** Update visible range instruction - emitted on scroll or when selection moves outside visible viewport */ interface UpdateVisibleRangeInstruction { type: "UPDATE_VISIBLE_RANGE"; start: number; end: number; /** * Y offset for the rows wrapper container when virtualization is active. * This allows rows to use small translateY values (viewport-relative) * instead of absolute positions (millions of pixels). */ rowsWrapperOffset: number; } /** Start edit instruction */ interface StartEditInstruction { type: "START_EDIT"; row: number; col: number; initialValue: CellValue; } /** Stop edit instruction */ interface StopEditInstruction { type: "STOP_EDIT"; } /** Commit edit instruction */ interface CommitEditInstruction { type: "COMMIT_EDIT"; row: number; col: number; value: CellValue; } /** Open a peek overlay on a cell */ interface StartPeekInstruction { type: "START_PEEK"; row: number; col: number; } /** Close the active peek overlay */ interface StopPeekInstruction { type: "STOP_PEEK"; } /** Programmatic scroll instruction — tells the framework to set container.scrollTop */ interface ScrollToInstruction { type: "SCROLL_TO"; scrollTop: number; } /** Set content size instruction */ interface SetContentSizeInstruction { type: "SET_CONTENT_SIZE"; width: number; height: number; viewportWidth: number; viewportHeight: number; /** * Y offset for the rows wrapper container when virtualization is active. * This allows rows to use small translateY values (viewport-relative) * instead of absolute positions (millions of pixels). */ rowsWrapperOffset: number; } /** Update header instruction */ interface UpdateHeaderInstruction { type: "UPDATE_HEADER"; colIndex: number; column: ColumnDefinition; sortDirection?: SortDirection; sortIndex?: number; /** Whether column has an active filter */ hasFilter: boolean; } /** Open filter popup instruction */ interface OpenFilterPopupInstruction { type: "OPEN_FILTER_POPUP"; colIndex: number; column: ColumnDefinition; anchorRect: { top: number; left: number; width: number; height: number; }; distinctValues: CellValue[]; currentFilter?: ColumnFilterModel; } /** Close filter popup instruction */ interface CloseFilterPopupInstruction { type: "CLOSE_FILTER_POPUP"; } /** Start fill instruction */ interface StartFillInstruction { type: "START_FILL"; sourceRange: CellRange; } /** Update fill instruction */ interface UpdateFillInstruction { type: "UPDATE_FILL"; targetRow: number; targetCol: number; } /** Commit fill instruction */ interface CommitFillInstruction { type: "COMMIT_FILL"; filledCells: Array<{ row: number; col: number; value: CellValue; }>; } /** Cancel fill instruction */ interface CancelFillInstruction { type: "CANCEL_FILL"; } /** Data loading instruction */ interface DataLoadingInstruction { type: "DATA_LOADING"; } /** Data loaded instruction */ interface DataLoadedInstruction { type: "DATA_LOADED"; totalRows: number; } /** Data error instruction */ interface DataErrorInstruction { type: "DATA_ERROR"; error: string; } /** Columns changed (after resize, reorder, etc.) */ interface ColumnsChangedInstruction { type: "COLUMNS_CHANGED"; columns: ColumnDefinition[]; } /** Union type of all instructions */ type GridInstruction = /** Slot lifecycle */ CreateSlotInstruction | DestroySlotInstruction | AssignSlotInstruction | MoveSlotInstruction | /** Scroll */ ScrollToInstruction | /** Selection */ SetActiveCellInstruction | SetSelectionRangeInstruction | UpdateVisibleRangeInstruction | /** Highlighting */ SetHoverPositionInstruction | /** Editing */ StartEditInstruction | StopEditInstruction | CommitEditInstruction | /** Peek (read-only expand) */ StartPeekInstruction | StopPeekInstruction | /** Layout */ SetContentSizeInstruction | UpdateHeaderInstruction | /** Filter popup */ OpenFilterPopupInstruction | CloseFilterPopupInstruction | /** Fill handle */ StartFillInstruction | UpdateFillInstruction | CommitFillInstruction | CancelFillInstruction | /** Data */ DataLoadingInstruction | DataLoadedInstruction | DataErrorInstruction | /** Column changes */ ColumnsChangedInstruction; /** Instruction listener: Single instruction Listener that receives a single instruction, used by frameworks to update their state */ type InstructionListener = (instruction: GridInstruction) => void; /** Batch instruction listener: Batch instruction Listener that receives an array of instructions, used by frameworks to update their state */ type BatchInstructionListener = (instructions: GridInstruction[]) => void; //#endregion //#region src/types/options.d.ts /** Row loading mode used by GridCore. "auto" follows the data source preference. */ type RowLoadingMode = "auto" | DataSourceLoadMode; /** Preset for how quickly paginated rows are evicted from memory. */ type RowCacheEviction = "aggressive" | "balanced" | "conservative"; /** Cache controls for paginated row loading. */ interface RowCacheOptions { /** Rows per server request. Default: 100. */ pageSize?: number; /** Pages to prefetch before and after the visible page. Default depends on eviction preset. */ prefetchPages?: number; /** Maximum loaded pages kept in memory. Default depends on eviction preset. */ maxPages?: number; /** Eviction preset. Default: "balanced". */ eviction?: RowCacheEviction; } /** Grid row loading options. */ interface RowLoadingOptions { /** Loading mode. Default: "auto". */ mode?: RowLoadingMode; /** Cache options used when paginated loading is active. */ cache?: RowCacheOptions; } /** Grid core options */ interface GridCoreOptions { /** Column definitions */ columns: ColumnDefinition[]; /** Data source */ dataSource: DataSource; /** Row height */ rowHeight: number; /** Header height: Default to row height */ headerHeight?: number; /** Overscan: How many rows to render outside the viewport */ overscan?: number; /** * Maximum velocity (logical px/ms) that stacked touch flicks can * accumulate while scroll virtualization is active (datasets exceeding * the browser scroll limit). Higher values traverse huge datasets faster * but need a larger `overscan` (10–12 recommended) so rendering keeps up. * Default: 20 × rowHeight, i.e. about 20,000 rows per second. */ maxFlingVelocity?: number; /** Row loading and cache behavior. Server data sources use paginated loading by default. */ rowLoading?: RowLoadingOptions; /** Enable/disable sorting globally. Default: true */ sortingEnabled?: boolean; /** Function to extract unique ID from row. Required for mutations. */ getRowId?: (row: TData) => RowId; /** Row/column/cell highlighting configuration */ highlighting?: HighlightingOptions; /** Called when a cell value is changed via editing, fill drag, or paste. Requires getRowId. */ onCellValueChanged?: (event: CellValueChangedEvent) => void; /** Whether clicking and dragging any cell in a row drags the entire row instead of starting selection. Default: false */ rowDragEntireRow?: boolean; /** Called when a row is dropped after dragging. Consumer is responsible for data reordering. */ onRowDragEnd?: (sourceIndex: number, targetIndex: number) => void; /** Called when a column is resized. */ onColumnResized?: (colIndex: number, newWidth: number) => void; /** Called when a column is moved/reordered. */ onColumnMoved?: (fromIndex: number, toIndex: number) => void; } //#endregion //#region src/types/input.d.ts /** Framework-agnostic pointer/mouse event data */ interface PointerEventData { /** X coordinate relative to viewport */ clientX: number; /** Y coordinate relative to viewport */ clientY: number; /** Mouse button (0 = left, 1 = middle, 2 = right) */ button: number; /** Whether Shift key is pressed */ shiftKey: boolean; /** Whether Ctrl key is pressed */ ctrlKey: boolean; /** Whether Meta/Command key is pressed */ metaKey: boolean; /** Pointer ID for setPointerCapture — only used by framework wrappers */ pointerId?: number; /** Pointer type (mouse, touch, pen) — used to adapt drag behavior for touch */ pointerType?: string; } /** Framework-agnostic keyboard event data */ interface KeyEventData { /** Key value (e.g., 'Enter', 'ArrowUp', 'a') */ key: string; /** Whether Shift key is pressed */ shiftKey: boolean; /** Whether Ctrl key is pressed */ ctrlKey: boolean; /** Whether Meta/Command key is pressed */ metaKey: boolean; } /** Container bounds and scroll position */ interface ContainerBounds { /** Top position relative to viewport */ top: number; /** Left position relative to viewport */ left: number; /** Container width */ width: number; /** Container height */ height: number; /** Current scroll top position */ scrollTop: number; /** Current scroll left position */ scrollLeft: number; } /** Result from mouse/pointer input handlers */ interface InputResult { /** Whether to call preventDefault() on the event */ preventDefault: boolean; /** Whether to call stopPropagation() on the event */ stopPropagation: boolean; /** Whether framework should focus the container element */ focusContainer?: boolean; /** Type of drag operation to start (framework manages global listeners) */ startDrag?: "selection" | "fill" | "column-resize" | "column-move" | "row-drag" | "row-drag-pending"; /** * Whether the framework should track a pending cell tap (touch only). * Selection is deferred until the tap is confirmed on pointerup within * the tap slop, so scroll gestures never select a cell. */ startTap?: boolean; } /** Result from keyboard input handler */ interface KeyboardResult { /** Whether to call preventDefault() on the event */ preventDefault: boolean; /** Cell to scroll into view (if navigation occurred) */ scrollToCell?: CellPosition; } /** Result from drag move handler */ interface DragMoveResult { /** Target row index */ targetRow: number; /** Target column index */ targetCol: number; /** Auto-scroll deltas (null if no auto-scroll needed) */ autoScroll: { dx: number; dy: number; } | null; } /** Options for InputHandler constructor */ interface InputHandlerDeps { /** Get header height */ getHeaderHeight: () => number; /** Get row height */ getRowHeight: () => number; /** Get column positions array (indexed by visible column) */ getColumnPositions: () => number[]; /** Get visible column count */ getColumnCount: () => number; /** * Convert visible column index to original column index. * Used when columns can be hidden. Returns the original index for selection tracking. * If not provided, visible index is used directly (no hidden columns). */ getOriginalColumnIndex?: (visibleIndex: number) => number; /** Get column widths array (indexed by visible column) */ getColumnWidths?: () => number[]; } /** Column resize drag state */ interface ColumnResizeDragState { colIndex: number; initialWidth: number; currentWidth: number; } /** Column move drag state */ interface ColumnMoveDragState { sourceColIndex: number; currentX: number; currentY: number; dropTargetIndex: number | null; ghostWidth: number; ghostHeight: number; } /** Row drag state */ interface RowDragState { sourceRowIndex: number; currentX: number; currentY: number; dropTargetIndex: number | null; /** Pre-computed translateY for the drop indicator inside the rows wrapper */ dropIndicatorY: number; } /** Current drag state for UI rendering */ interface DragState { /** Whether any drag operation is active */ isDragging: boolean; /** Type of active drag operation */ dragType: "selection" | "fill" | "column-resize" | "column-move" | "row-drag" | null; /** Source range for fill operations */ fillSourceRange: CellRange | null; /** Current fill target position */ fillTarget: { row: number; col: number; } | null; /** Column resize state (when dragType is "column-resize") */ columnResize: ColumnResizeDragState | null; /** Column move state (when dragType is "column-move") */ columnMove: ColumnMoveDragState | null; /** Row drag state (when dragType is "row-drag") */ rowDrag: RowDragState | null; } //#endregion //#region src/selection.d.ts type Direction = "up" | "down" | "left" | "right"; interface SelectionManagerOptions { getRowCount: () => number; getColumnCount: () => number; getCellValue: (row: number, col: number) => CellValue; getRowData: (row: number) => unknown; getColumn: (col: number) => ColumnDefinition | undefined; setCellValue: (row: number, col: number, value: CellValue) => void; } interface PasteResult { handled: boolean; changedCells: Array<{ row: number; col: number; value: CellValue; }>; } /** * Manages Excel-style cell selection, keyboard navigation, and clipboard operations. */ declare class SelectionManager { private state; private readonly options; private readonly emitter; private clipboardSnapshot; onInstruction: (listener: InstructionListener) => () => void; private readonly emit; constructor(options: SelectionManagerOptions); getState(): SelectionState; getActiveCell(): CellPosition | null; getSelectionRange(): CellRange | null; isSelected(row: number, col: number): boolean; isActiveCell(row: number, col: number): boolean; /** * Start a selection at the given cell. * @param cell - The cell to select * @param opts.shift - Extend selection from anchor (range select) * @param opts.ctrl - Toggle selection mode */ startSelection(cell: CellPosition, opts?: { shift?: boolean; ctrl?: boolean; }): void; /** * Move focus in a direction, optionally extending the selection. */ moveFocus(direction: Direction, extend?: boolean): void; /** * Select all cells in the grid (Ctrl+A). */ selectAll(): void; /** * Clear the current selection. */ clearSelection(): void; /** * Set the active cell directly. */ setActiveCell(row: number, col: number): void; /** * Set the selection range directly. */ setSelectionRange(range: CellRange): void; /** * Get the data from the currently selected cells as a 2D array. */ getSelectedData(): CellValue[][]; /** * Copy the selected data to the clipboard (Ctrl+C). */ copySelectionToClipboard(): Promise; /** * Paste text data into the active cell or selected target range. */ pasteClipboardText(text: string): PasteResult; /** * Clean up resources for garbage collection. */ destroy(): void; private clampPosition; private getEffectiveRange; private createClipboardSnapshot; private getPasteSourceCells; private applyPasteSource; private applyPasteCell; private getSourceCellForTarget; private isSingleSourceCell; private getMaxSourceColumnCount; } //#endregion //#region src/fill.d.ts interface FillManagerOptions { getRowCount: () => number; getColumnCount: () => number; getCellValue: (row: number, col: number) => CellValue; getColumn: (col: number) => ColumnDefinition | undefined; setCellValue: (row: number, col: number, value: CellValue) => void; } /** * Manages fill handle operations including pattern detection and auto-fill. */ declare class FillManager { private state; private readonly options; private readonly emitter; onInstruction: (listener: InstructionListener) => () => void; private readonly emit; constructor(options: FillManagerOptions); getState(): FillHandleState | null; isActive(): boolean; /** * Start a fill drag operation from a source range. */ startFillDrag(sourceRange: CellRange): void; /** * Update the fill drag target position. */ updateFillDrag(targetRow: number, targetCol: number): void; /** * Commit the fill operation - apply pattern to target cells. */ commitFillDrag(): void; /** * Cancel the fill operation. */ cancelFillDrag(): void; /** * Clean up resources for garbage collection. */ destroy(): void; /** * Calculate the values to fill based on source pattern. */ private calculateFilledCells; private getSourceColumnValues; private detectPattern; private applyPattern; } //#endregion //#region src/input/column-resize-drag.d.ts declare class ColumnResizeDrag { private active; private colIndex; private startX; private initialWidth; private currentWidth; private readonly core; constructor(core: GridCore); get isActive(): boolean; start(colIndex: number, colWidth: number, event: PointerEventData): InputResult; move(event: PointerEventData, bounds: ContainerBounds): DragMoveResult; end(): void; getState(): ColumnResizeDragState | null; } //#endregion //#region src/input/column-move-drag.d.ts declare class ColumnMoveDrag { private readonly gesture; private sourceColIndex; private shiftKey; private ghostWidth; private ghostHeight; private readonly core; private deps; constructor(core: GridCore, deps: InputHandlerDeps); updateDeps(deps: InputHandlerDeps): void; get isActive(): boolean; get isDraggingForDisplay(): boolean; start(colIndex: number, colWidth: number, colHeight: number, event: PointerEventData): InputResult; move(event: PointerEventData, bounds: ContainerBounds): DragMoveResult | null; end(cycleSortDirection: (current: SortDirection | null | undefined) => SortDirection | null): void; private commitMove; private treatAsHeaderClick; private reset; getState(): ColumnMoveDragState | null; } //#endregion //#region src/input/row-drag.d.ts declare class RowDrag { private readonly gesture; private sourceRowIndex; private readonly core; private deps; constructor(core: GridCore, deps: InputHandlerDeps); updateDeps(deps: InputHandlerDeps): void; get isActive(): boolean; get isDraggingForDisplay(): boolean; start(sourceRowIndex: number, clientX: number, clientY: number): void; move(event: PointerEventData, bounds: ContainerBounds): DragMoveResult | null; end(): void; getState(): RowDragState | null; } //#endregion //#region src/input/selection-drag.d.ts declare class SelectionDrag { private active; private readonly core; constructor(core: GridCore); get isActive(): boolean; start(): void; moveToTarget(row: number, col: number): void; end(): void; } //#endregion //#region src/input/fill-drag.d.ts declare class FillDrag { private active; private sourceRange; private target; private readonly core; constructor(core: GridCore); get isActive(): boolean; get stateSnapshot(): { sourceRange: CellRange | null; target: { row: number; col: number; } | null; }; start(activeCell: CellPosition | null, selectionRange: CellRange | null): InputResult; moveToTarget(row: number, col: number): void; end(): void; } //#endregion //#region src/input/interaction-constants.d.ts /** * Maximum pointer travel (px) for a gesture to still count as a tap. * Beyond this the gesture is treated as a scroll/drag. */ declare const TAP_SLOP_PX = 10; /** Hold duration (ms) required to confirm a row drag on touch devices. */ declare const ROW_DRAG_HOLD_MS = 300; //#endregion //#region src/input-handler.d.ts declare class InputHandler { private readonly core; private deps; readonly columnResize: ColumnResizeDrag; readonly columnMove: ColumnMoveDrag; readonly rowDrag: RowDrag; readonly selectionDrag: SelectionDrag; readonly fillDrag: FillDrag; private readonly pendingRowDrag; private readonly pendingCellTap; private readonly keyboard; constructor(core: GridCore, deps: InputHandlerDeps); /** Update dependencies (called when options change) */ updateDeps(deps: Partial): void; getDragState(): DragState; private getDragType; handleHeaderMouseDown(colIndex: number, colWidth: number, colHeight: number, event: PointerEventData): InputResult; handleHeaderResizeMouseDown(colIndex: number, colWidth: number, event: PointerEventData): InputResult; handleCellMouseDown(rowIndex: number, colIndex: number, event: PointerEventData): InputResult; private startPendingRowDrag; private startRowDrag; private startSelectionClick; handleCellDoubleClick(rowIndex: number, colIndex: number): void; handleCellMouseEnter(rowIndex: number, colIndex: number): void; handleCellMouseLeave(): void; handleFillHandleMouseDown(activeCell: CellPosition | null, selectionRange: CellRange | null, _event: PointerEventData): InputResult; handleHeaderClick(colId: string, addToExisting: boolean): void; startSelectionDrag(): void; confirmPendingRowDrag(): boolean; cancelPendingRowDrag(): void; confirmPendingCellTap(): boolean; cancelPendingCellTap(): void; handleDragMove(event: PointerEventData, bounds: ContainerBounds): DragMoveResult | null; private selectionFillMove; handleDragEnd(): void; handleWheel(deltaY: number, deltaX: number, dampening: number): { dy: number; dx: number; } | null; handleKeyDown(event: KeyEventData, activeCell: CellPosition | null, editingCell: { row: number; col: number; } | null, filterPopupOpen: boolean): KeyboardResult; } //#endregion //#region src/managers/highlight-manager.d.ts interface HighlightManagerOptions { getActiveCell: () => CellPosition | null; getSelectionRange: () => CellRange | null; getColumn: (colIndex: number) => ColumnDefinition | undefined; } /** * Manages row/column/cell highlighting state and class computation. * Emits SET_HOVER_POSITION instructions when hover position changes. */ declare class HighlightManager> { private readonly options; private highlightingOptions; private hoverPosition; private readonly emitter; onInstruction: (listener: InstructionListener) => () => void; private readonly emit; private readonly rowClassCache; private readonly columnClassCache; private readonly cellClassCache; constructor(options: HighlightManagerOptions, highlightingOptions?: HighlightingOptions); /** * Check if highlighting is enabled (any callback defined). * Hover tracking is automatically enabled when highlighting is enabled. */ isEnabled(): boolean; /** * Update highlighting options. Clears all caches. */ updateOptions(options: HighlightingOptions): void; /** * Set the current hover position. Clears caches and emits instruction. * Hover tracking is automatically enabled when any highlighting callback is defined. */ setHoverPosition(position: CellPosition | null): void; /** * Get the current hover position */ getHoverPosition(): CellPosition | null; /** * Called when selection changes. Clears all caches. */ onSelectionChange(): void; /** * Build context for row highlighting callback. * Returns context with `rowIndex` set, `colIndex` is null. * `isHovered` is true when the mouse is on any cell in this row. */ buildRowContext(rowIndex: number, rowData?: TData): HighlightContext; /** * Build context for column highlighting callback. * Returns context with `colIndex` set, `rowIndex` is null. * `isHovered` is true when the mouse is on any cell in this column. */ buildColumnContext(colIndex: number, column: ColumnDefinition): HighlightContext; /** * Build context for cell highlighting callback. * Returns context with both `rowIndex` and `colIndex` set. * `isHovered` is true only when the mouse is on this exact cell. */ buildCellContext(rowIndex: number, colIndex: number, column: ColumnDefinition, rowData?: TData): HighlightContext; /** * Compute row classes using cache and user callback */ computeRowClasses(rowIndex: number, rowData?: TData): string[]; /** * Compute column classes using cache and user callback (or per-column override) */ computeColumnClasses(colIndex: number, column: ColumnDefinition): string[]; /** * Compute cell classes using cache and user callback (or per-column override) */ computeCellClasses(rowIndex: number, colIndex: number, column: ColumnDefinition, rowData?: TData): string[]; /** * Compute combined cell classes (column + cell classes flattened) */ computeCombinedCellClasses(rowIndex: number, colIndex: number, column: ColumnDefinition, rowData?: TData): string[]; /** * Clear all caches */ clearAllCaches(): void; /** * Destroy the manager and release resources */ destroy(): void; } //#endregion //#region src/managers/sort-filter-manager.d.ts interface SortFilterManagerOptions { /** Get all columns */ getColumns: () => ColumnDefinition[]; /** Check if sorting is enabled globally */ isSortingEnabled: () => boolean; /** Get cached rows for distinct value computation */ getCachedRows: () => Map; /** Called when sort/filter changes to trigger data refresh */ onSortFilterChange: () => Promise; /** Called after data refresh to update UI */ onDataRefreshed: () => void; } /** * Manages sorting and filtering state and operations. */ declare class SortFilterManager> { private readonly options; private readonly emitter; private sortModel; private filterModel; private openFilterColIndex; private readonly scanWarnedCols; private readonly truncationWarnedCols; private readonly typeMismatchWarnedCols; onInstruction: (listener: InstructionListener) => () => void; private readonly emit; constructor(options: SortFilterManagerOptions); setSort(colId: string, direction: SortDirection | null, addToExisting?: boolean): Promise; getSortModel(): SortModel[]; setFilter(colId: string, filter: ColumnFilterInput | string | null): Promise; /** * Lint for hand-constructed filter models: values-mode `selectedValues` * match by strict raw identity (`"5"` never matches `5`, an ISO string * never matches a `Date`), so an all-string selection on a column whose * raw type is not a string will match nothing. This typically comes from * a lossy round-trip — filter state restored via `JSON.parse` or built * from URL params, where numbers and Dates arrive as strings. The mistake * is otherwise silent because `Set` typechecks against * `Set`; warn once per column. */ private warnTypeMismatchedSelectedValues; getFilterModel(): FilterModel; /** * Check if a column has an active filter */ hasActiveFilter(colId: string): boolean; /** * Check if a column is sortable */ isColumnSortable(colIndex: number): boolean; /** * Check if a column is filterable */ isColumnFilterable(colIndex: number): boolean; /** * Get distinct values for a column (for filter dropdowns). * * When the column defines `distinctValues`, that list is used directly * (deduplicated + sorted by display string). Otherwise the manager scans * every cached row to compute the set. The previous stride-sampling * fallback was removed because the stride could share a factor with a * repeating value pool, causing some values to be unreachable (the * `bio` field in the demo dataset was a real example: stride 15 with a * pool size of 6 yielded only 2 of 6 values). * * For datasets above {@link DISTINCT_SCAN_WARN_THRESHOLD}, a one-time * console warning advises the consumer to pre-supply `distinctValues` * on the column to skip the full scan. * * Values are deduplicated by RAW identity ({@link rawValueKey}), not by * display label: when a `valueFormatter` collapses several raw values into * one label, every raw value survives so the popup can select them all. * Consequently `maxValues` caps raw values, not labels. If the cap * truncates the domain of a formatted column, a one-time warning is * emitted because ticking a label can no longer cover unscanned raws. */ getDistinctValuesForColumn(colId: string, maxValues?: number): CellValue[]; private scanDistinctValues; /** * Normalize a cell value into a dedup key and the value to store. * Arrays are sorted lexicographically so different orderings produce the * same key. The key is the RAW identity ({@link rawValueKey}) — display * formatting is intentionally not part of it, so raw values that share a * label all survive deduplication and the values-mode filter can select * every one of them. */ private normalizeDistinctValue; /** * Values-mode filtering matches raw values, so when the distinct scan of a * formatted column is cut off at the cap, ticking a label cannot cover the * raw values that were never scanned — rows rendering that label would be * silently hidden. Warn once per column and advise supplying the full raw * domain via `ColumnDefinition.distinctValues`. */ private warnTruncatedFormattedDomain; /** * Open filter popup for a column (toggles if already open for same column) * * @param computeDistinctValues Whether the adapter's popup needs a values list. */ openFilterPopup(colIndex: number, anchorRect: { top: number; left: number; width: number; height: number; }, computeDistinctValues?: boolean): void; /** * Close filter popup */ closeFilterPopup(): void; /** * Get sort info map for header rendering */ getSortInfoMap(): Map; destroy(): void; } //#endregion //#region src/indexed-data-store/indexed-data-store.d.ts interface IndexedDataStoreOptions { /** Function to extract unique ID from row. Required for mutations. */ getRowId: (row: TData) => RowId; /** Custom field accessor for nested properties */ getFieldValue?: (row: TData, field: string) => CellValue; } /** * Row registry backing the mutable client data source. * * Holds rows in insertion order with an id → index map for O(1) lookup and a * refcounted distinct-value index per field (for filter UIs). Sorting and * filtering are applied by the data source on top of `getAllRows()`. */ declare class IndexedDataStore { private rows; private readonly rowById; private readonly distinctValues; private readonly options; constructor(options: IndexedDataStoreOptions, initialData?: TData[]); /** Clear all data and internal indexes. */ clear(): void; /** Replace all data (used for initial load or full refresh). */ setData(data: TData[]): void; getRowById(id: RowId): TData | undefined; getTotalRowCount(): number; /** All rows, in storage order, as a new array. */ getAllRows(): TData[]; /** Distinct values for a field (for filter UI). */ getDistinctValues(field: string): CellValue[]; /** Append rows. Rows whose id already exists are skipped with a warning. */ addRows(rows: TData[]): void; private addRow; /** * Remove rows by ID in a single pass. Returns the number of rows actually * removed (unknown ids are ignored). */ removeRows(ids: RowId[]): number; /** Update a single field on a row, keeping the distinct-value index in sync. */ updateCell(id: RowId, field: string, value: CellValue): void; /** Update multiple fields on a row. */ updateRow(id: RowId, data: Partial): void; /** * Move a row from one position to another in storage order. When no sort * is active the new order is reflected on the next fetch. */ moveRow(fromIndex: number, toIndex: number): void; private rebuildIdIndex; } //#endregion //#region src/indexed-data-store/field-helpers.d.ts /** * Default field value accessor supporting dot notation. * @example * getFieldValue({ user: { name: "John" } }, "user.name") // "John" */ declare function getFieldValue(row: TData, field: string): CellValue; /** * Set field value supporting dot notation. * Creates nested objects if they don't exist. * @example * const obj = { user: {} }; * setFieldValue(obj, "user.name", "John"); * // obj is now { user: { name: "John" } } */ declare function setFieldValue(row: TData, field: string, value: CellValue): void; //#endregion //#region src/filtering/index.d.ts /** * Check if two dates are on the same day. */ declare function isSameDay(date1: Date, date2: Date): boolean; /** * Evaluate a text filter condition against a cell value. * * Values mode (`selectedValues`) compares RAW values via {@link rawValueKey}; * the formatter is never consulted, so the filter model matches what a * server-side data source receives. The `formatter` only applies to free-text * condition operators (contains, equals, ...), where the user types the text * they see on screen. */ declare function evaluateTextCondition(cellValue: CellValue, condition: TextFilterCondition, formatter?: (v: CellValue) => string): boolean; /** * Evaluate a number filter condition against a cell value. */ declare function evaluateNumberCondition(cellValue: CellValue, condition: NumberFilterCondition): boolean; /** * Evaluate a date filter condition against a cell value. */ declare function evaluateDateCondition(cellValue: CellValue, condition: DateFilterCondition): boolean; /** * Evaluate a column filter model against a cell value. Conditions are joined * inside their explicit group, then groups are joined at the model level. * Legacy flat inputs retain their historical left-to-right truth table by * first normalizing to an equivalent grouped model. */ declare function evaluateColumnFilter(cellValue: CellValue, filter: ColumnFilterInput, formatter?: (v: CellValue) => string): boolean; /** * Check if a row passes all filters in a filter model. * `getValueFormatter` — when provided — lets free-text condition operators * compare the formatted (displayed) cell value instead of the raw string. * Values-mode `selectedValues` always compare raw values and ignore it. */ declare function rowPassesFilter(row: TData, filterModel: FilterModel, getFieldValue: (row: TData, field: string) => CellValue, getValueFormatter?: (field: string) => ((v: CellValue) => string) | undefined): boolean; //#endregion //#region src/managers/transaction-manager.d.ts interface AddTransaction { type: "ADD"; rows: TData[]; } interface RemoveTransaction { type: "REMOVE"; rowIds: RowId[]; } interface UpdateCellTransaction { type: "UPDATE_CELL"; rowId: RowId; field: string; value: CellValue; } interface UpdateRowTransaction { type: "UPDATE_ROW"; rowId: RowId; data: Partial; } type Transaction = AddTransaction | RemoveTransaction | UpdateCellTransaction | UpdateRowTransaction; interface TransactionResult { added: number; removed: number; updated: number; } interface TransactionManagerOptions { /** Debounce time in milliseconds. Default 50. Set to 0 for sync. */ debounceMs: number; /** The indexed data store to apply transactions to */ store: IndexedDataStore; /** Callback when transactions are processed */ onProcessed?: (result: TransactionResult) => void; } /** * Manages a queue of data mutations with debounced batch processing. * Supports ADD, REMOVE, UPDATE_CELL, and UPDATE_ROW operations. */ declare class TransactionManager { private queue; private debounceTimer; private pendingPromise; private readonly options; constructor(options: TransactionManagerOptions); /** * Queue rows to be added. */ add(rows: TData[]): void; /** * Queue rows to be removed by ID. */ remove(rowIds: RowId[]): void; /** * Queue a cell update. */ updateCell(rowId: RowId, field: string, value: CellValue): void; /** * Queue a row update (multiple fields). */ updateRow(rowId: RowId, data: Partial): void; /** * Force immediate processing of queued transactions. * Returns a promise that resolves when processing is complete. */ flush(): Promise; /** * Check if there are pending transactions. */ hasPending(): boolean; /** * Get count of pending transactions. */ getPendingCount(): number; /** * Clear all pending transactions without processing. */ clear(): void; /** * Schedule processing after throttle delay. * Uses throttle pattern: if a timer is already pending, new transactions * are added to the queue but don't reset the timer. This ensures updates * are processed even when they arrive faster than the throttle interval. */ private scheduleProcessing; /** * Process all queued transactions. */ private processQueue; } //#endregion //#region src/grid-core.d.ts declare class GridCore { private readonly config; private columns; private columnPositions; private readonly batcher; private readonly viewport; private scrollTopOverride; private readonly rowData; readonly selection: SelectionManager; readonly fill: FillManager; readonly input: InputHandler; readonly highlight: HighlightManager | null; readonly sortFilter: SortFilterManager; private readonly slotPool; private readonly editManager; private readonly scrollVirtualization; private readonly view; private isDestroyed; constructor(options: GridCoreOptions); /** * Subscribe to batched instructions for efficient React/Vue state updates. * Batch listeners receive arrays of instructions instead of individual ones. */ onBatchInstruction(listener: BatchInstructionListener): () => void; /** * Initialize the grid and load initial data. */ initialize(): Promise; /** * Update viewport measurements and sync slots. * When scroll virtualization is active, maps the DOM scroll position to the actual row position. */ setViewport(scrollTop: number, scrollLeft: number, width: number, height: number): void; setSort(colId: string, direction: SortDirection | null, addToExisting?: boolean): Promise; setFilter(colId: string, filter: ColumnFilterInput | string | null): Promise; hasActiveFilter(colId: string): boolean; /** * Open a column filter popup. * Adapters can skip distinct-value computation when their popup only uses * condition inputs, such as number and date filters. */ openFilterPopup(colIndex: number, anchorRect: { top: number; left: number; width: number; height: number; }, computeDistinctValues?: boolean): void; closeFilterPopup(): void; getSortModel(): SortModel[]; getFilterModel(): FilterModel; startEdit(row: number, col: number): void; /** * Open a read-only peek overlay on a cell. The default cell renderer is * shown in a multi-line container so long values are fully visible. * Returns true if the peek opened (column must be `peekable !== false` * and not currently being edited). */ startPeek(row: number, col: number): boolean; /** Close any active peek overlay. */ stopPeek(): void; getPeekState(): { row: number; col: number; } | null; updateEditValue(value: CellValue): void; commitEdit(): void; cancelEdit(): void; pasteClipboardText(text: string): boolean; getEditState(): EditState | null; getCellValue(row: number, col: number): CellValue; setCellValue(row: number, col: number, value: CellValue): void; private clearSelectionIfInvalid; private computeColumnPositions; private columnOperationDeps; /** * Set the displayed width of a column and recompute layout. `width` is the * post-redistribution displayed width — the stored `column.width` is * back-solved so the column ends up exactly `width` pixels wide. */ setColumnWidth(colIndex: number, width: number): void; /** * Move a column from one index to another and recompute layout. */ moveColumn(fromIndex: number, toIndex: number): void; /** * Commit a row drag operation. Reorders data if the data source supports it, * then invokes the onRowDragEnd callback. * * Optimized: instead of a full refresh (fetchData + rebuild all slots), we * update the cachedRows map in-place to mirror the splice the data source * performed, then only update the affected slots. */ commitRowDrag(sourceIndex: number, targetIndex: number): void; /** * Whether the entire row is draggable. */ isRowDragEntireRow(): boolean; getColumns(): ColumnDefinition[]; getColumnPositions(): number[]; getRowCount(): number; getRowHeight(): number; getHeaderHeight(): number; getTotalWidth(): number; getTotalHeight(): number; isScalingActive(): boolean; /** * Maximum accumulated touch-fling velocity (logical px/ms) used by the * synthetic scroller while scroll virtualization is active. */ getMaxFlingVelocity(): number; getScrollRatio(): number; getVisibleRowRange(): { start: number; end: number; }; /** Used structurally by `scrollCellIntoView` in the framework wrappers. */ getScrollTopForRow(rowIndex: number): number; getRowIndexAtDisplayY(viewportY: number, virtualScrollTop: number): number; /** * Get the translateY position for a row inside the rows wrapper. * Accounts for scroll virtualization (compressed coordinates). */ getRowTranslateY(rowIndex: number): number; getRowData(rowIndex: number): TData | undefined; /** * Refresh data from the data source. */ refresh(): Promise; /** * Fast-path refresh for transaction-based mutations. * Only re-fetches the visible window instead of all rows. * Use this when data was mutated via MutableDataSource transactions. */ refreshFromTransaction(): Promise; /** * Refresh slot display without refetching data. * Useful after in-place data modifications like fill operations. */ refreshSlotData(): void; /** * Update the data source and refresh. * Preserves grid state (sort, filter, scroll position). * Cancels any active edit and clamps selection to valid range. */ setDataSource(dataSource: DataSource): Promise; /** * Update columns and recompute layout. */ setColumns(columns: ColumnDefinition[]): void; /** * Destroy the grid core and release all references. * Call this before discarding the GridCore to ensure proper cleanup. * This method is idempotent - safe to call multiple times. */ destroy(): void; } //#endregion //#region src/sorting/parallel-sort-manager.d.ts interface ParallelSortOptions { /** Maximum number of workers (default: navigator.hardwareConcurrency || 4) */ maxWorkers?: number; /** Threshold for parallel sorting (default: 400000) */ parallelThreshold?: number; /** Minimum chunk size (default: 50000) */ minChunkSize?: number; } //#endregion //#region src/data-source/client-data-source.d.ts interface ClientDataSourceOptions { /** Custom field accessor for nested properties */ getFieldValue?: (row: TData, field: string) => CellValue; /** * Lookup for a field's valueFormatter. Lets free-text filter conditions * compare against the displayed (formatted) value the user typed against. * Values-mode `selectedValues` compare raw values and never use it. */ getValueFormatter?: (field: string) => ((v: CellValue) => string) | undefined; /** Use Web Worker for sorting large datasets (default: true) */ useWorker?: boolean; /** Options for parallel sorting (only used when useWorker is true) */ parallelSort?: ParallelSortOptions | false; } /** * Creates a client-side data source that holds all data in memory. * Sorting and filtering are performed client-side. * For large datasets, sorting is automatically offloaded to a Web Worker. */ declare function createClientDataSource(data: TData[], options?: ClientDataSourceOptions): DataSource; /** * Convenience function to create a data source from an array. * This provides backwards compatibility with the old `rowData` prop. */ declare function createDataSourceFromArray(data: TData[]): DataSource; //#endregion //#region src/data-source/server-data-source.d.ts type ServerQueryFunction = (request: DataSourceRequest) => Promise>; interface ServerDataSourceOptions { /** Server data sources use paginated loading by default. */ loadMode?: DataSourceLoadMode; } /** * Creates a server-side data source that delegates all operations to the server. * The query function receives sort/filter/range params to pass to the API. */ declare function createServerDataSource(queryFn: ServerQueryFunction, options?: ServerDataSourceOptions): DataSource; //#endregion //#region src/data-source/mutable-data-source.d.ts /** Callback for data change notifications */ type DataChangeListener = (result: TransactionResult) => void; /** * Data source with mutation capabilities. * Extends DataSource with add, remove, and update operations. */ interface MutableDataSource extends DataSource { /** Add rows to the data source. Queued and processed after debounce. */ addRows(rows: TData[]): void; /** Remove rows by ID. Queued and processed after debounce. */ removeRows(ids: RowId[]): void; /** Update a cell value. Queued and processed after debounce. */ updateCell(id: RowId, field: string, value: CellValue): void; /** Update multiple fields on a row. Queued and processed after debounce. */ updateRow(id: RowId, data: Partial): void; /** Force immediate processing of queued transactions. */ flushTransactions(): Promise; /** Check if there are pending transactions. */ hasPendingTransactions(): boolean; /** Get distinct values for a field (for filter UI). */ getDistinctValues(field: string): CellValue[]; /** Get a row by ID. */ getRowById(id: RowId): TData | undefined; /** Get total row count. */ getTotalRowCount(): number; /** Subscribe to data change notifications. Returns unsubscribe function. */ subscribe(listener: DataChangeListener): () => void; /** Clear all data from the data source. */ clear(): void; /** Move a row from one display position to another. */ moveRow(fromIndex: number, toIndex: number): void; } interface MutableClientDataSourceOptions { /** Function to extract unique ID from row. Required. */ getRowId: (row: TData) => RowId; /** Custom field accessor for nested properties. */ getFieldValue?: (row: TData, field: string) => CellValue; /** * Lookup for a field's valueFormatter. Lets free-text filter conditions * compare against the displayed (formatted) value. Values-mode * `selectedValues` compare raw values and never use it. */ getValueFormatter?: (field: string) => ((v: CellValue) => string) | undefined; /** Debounce time for transactions in ms. Default 50. Set to 0 for sync. */ debounceMs?: number; /** Callback when transactions are processed. */ onTransactionProcessed?: (result: TransactionResult) => void; /** Use Web Worker for sorting large datasets (default: true) */ useWorker?: boolean; /** Options for parallel sorting (only used when useWorker is true) */ parallelSort?: ParallelSortOptions | false; } /** * Creates a mutable client-side data source with transaction support. * Uses IndexedDataStore for efficient incremental operations. * For large datasets, sorting is automatically offloaded to a Web Worker. */ declare function createMutableClientDataSource(data: TData[], options: MutableClientDataSourceOptions): MutableDataSource; //#endregion //#region src/filtering/normalize.d.ts /** Check whether a filter still uses the legacy flat condition list. */ declare const isLegacyColumnFilterModel: (filter: ColumnFilterInput) => filter is LegacyColumnFilterModel; /** * Convert a legacy left-to-right filter into the canonical one-level grouped * representation. Canonical inputs are returned unchanged. */ declare const normalizeColumnFilterModel: (filter: ColumnFilterInput) => ColumnFilterModel; //#endregion //#region src/filtering/distinct-entries.d.ts /** One checkbox row in the values-mode filter popup. */ interface DistinctValueEntry { /** Formatted display string shown next to the checkbox. */ label: string; /** All raw values that format to this label. Ticking the label selects them all. */ values: CellValue[]; } /** * Canonical identity key for a raw cell value, used to compare values-mode * selections against cell values without ever consulting a formatter. * * Type-prefixed so raw `5` and raw `"5"` never collide. Arrays are sorted by * their elements' own keys first so element order is irrelevant (same rule as * the distinct-value scan). Objects rely on JSON.stringify, so key order matters * for them — a pre-existing limitation of distinct-value identity. */ declare const rawValueKey: (value: CellValue) => string; /** * Whether a cell value counts as blank for filtering purposes: null, * undefined, empty string, or empty array (e.g. a tags column with no tags). * Blank cells are matched via `TextFilterCondition.includeBlank` — the * popup's "(Blanks)" checkbox — never via `selectedValues`. */ declare const isBlankCellValue: (value: CellValue) => boolean; /** * Group raw distinct values by their display label. * * Multiple raw values can format to the same label; the returned entry keeps * every one of them so that applying the filter selects all rows rendering * that label. Blank values are skipped (the popup exposes them through the * dedicated "include blanks" checkbox), arrays are normalized to sorted * copies, and raws are deduplicated within a group by {@link rawValueKey}. */ declare const groupDistinctValues: (values: readonly CellValue[], formatter?: (v: CellValue) => string) => DistinctValueEntry[]; /** * Map a filter model's raw `selectedValues` back to the popup labels that * should render as ticked. A label is ticked when at least one of its raw * values is selected (data may have changed since the filter was applied). */ declare const labelsForSelectedValues: (entries: readonly DistinctValueEntry[], selectedValues: ReadonlySet) => Set; /** * Collect the raw values behind the ticked labels — the set to store in * `TextFilterCondition.selectedValues` on apply. */ declare const rawValuesForLabels: (entries: readonly DistinctValueEntry[], labels: ReadonlySet) => Set; //#endregion //#region src/utils/positioning.d.ts /** * Calculate cumulative column positions (prefix sums) * Returns an array where positions[i] is the left position of column i * positions[columns.length] is the total width */ declare const calculateColumnPositions: (columns: ColumnDefinition[]) => number[]; /** * Get total width from column positions */ declare const getTotalWidth: (columnPositions: number[]) => number; /** * Calculate scaled column positions when container is wider than total column widths. * Columns expand proportionally based on their original width ratios. * * @param columns - Column definitions with original widths * @param containerWidth - Available container width * @returns Object with positions array and widths array */ declare const calculateScaledColumnPositions: (columns: ColumnDefinition[], containerWidth: number) => { positions: number[]; widths: number[]; }; /** * Find column index at a given X coordinate */ declare const findColumnAtX: (x: number, columnPositions: number[]) => number; //#endregion //#region src/utils/classNames.d.ts /** * Check if a cell is within the selection range */ declare const isCellSelected: (row: number, col: number, selectionRange: CellRange | null) => boolean; /** * Check if a cell is the active cell */ declare const isCellActive: (row: number, col: number, activeCell: CellPosition | null) => boolean; /** * Check if a row is within the visible range (not in overscan) */ declare const isRowVisible: (row: number, visibleRowRange: { start: number; end: number; } | null) => boolean; /** * Check if a cell is being edited */ declare const isCellEditing: (row: number, col: number, editingCell: { row: number; col: number; } | null) => boolean; /** * Check if a cell is in the fill preview range (vertical-only fill) */ declare const isCellInFillPreview: (row: number, col: number, isDraggingFill: boolean, fillSourceRange: CellRange | null, fillTarget: { row: number; col: number; } | null) => boolean; /** * Build cell CSS classes based on state */ declare const buildCellClasses: (isActive: boolean, isSelected: boolean, isEditing: boolean, inFillPreview: boolean) => string; //#endregion //#region src/types/ui-state.d.ts interface SlotData { slotId: string; rowIndex: number; rowData: TData; translateY: number; } interface HeaderData { column: ColumnDefinition; sortDirection?: SortDirection; sortIndex?: number; hasFilter: boolean; } interface FilterPopupState { isOpen: boolean; colIndex: number; column: ColumnDefinition | null; anchorRect: { top: number; left: number; width: number; height: number; } | null; distinctValues: CellValue[]; currentFilter?: ColumnFilterModel; } interface InitialStateArgs { initialWidth?: number; initialHeight?: number; } declare const createInitialState: (args?: InitialStateArgs) => GridState; interface GridState { slots: Map>; activeCell: CellPosition | null; selectionRange: CellRange | null; editingCell: { row: number; col: number; initialValue: CellValue; } | null; /** Cell currently shown in a read-only peek overlay (multi-line expand on double-click) */ peekCell: CellPosition | null; contentWidth: number; contentHeight: number; /** Viewport width (container's visible width) for column scaling */ viewportWidth: number; /** Viewport height (container's visible height) for loader positioning */ viewportHeight: number; /** Y offset for rows wrapper when virtualization is active (keeps row translateY values small) */ rowsWrapperOffset: number; headers: Map; filterPopup: FilterPopupState | null; isLoading: boolean; error: string | null; totalRows: number; /** Visible row range (start inclusive, end inclusive). Used to prevent selection showing in overscan. */ visibleRowRange: { start: number; end: number; } | null; /** Currently hovered cell position (for highlighting) */ hoverPosition: CellPosition | null; /** Columns updated by core (after resize/reorder). Null means use props. */ columns: ColumnDefinition[] | null; /** Pending programmatic scroll — framework should apply to container and clear */ pendingScrollTop: number | null; } //#endregion //#region src/state-reducer.d.ts /** * Apply a single instruction to mutable slot/header Maps and return * other state changes as a partial object. * * Returns `null` when only the Maps were mutated (no primitive field changes). */ declare const applyInstruction: (instruction: GridInstruction, slots: Map>, headers: Map) => Partial> | null; //#endregion //#region src/utils/scroll-helpers.d.ts /** * Column geometry needed to scroll a cell horizontally into view. * Columns are not scroll-virtualized, so positions map 1:1 to scrollLeft. */ interface ColumnScrollGeometry { /** Original column index of the target cell (matches the active cell) */ colIndex: number; /** Visible columns with their original indices, in render order */ visibleColumns: readonly { originalIndex: number; }[]; /** X positions of visible columns within the scrollable content */ columnPositions: readonly number[]; /** Widths of visible columns */ columnWidths: readonly number[]; } /** * Scroll a cell into view if needed, on both axes. * * The header is rendered outside the scroll container (flex column layout), * so all coordinates are relative to the body scroll container. * * When scroll virtualization is active, slot.translateY is relative to the * first visible row, and the rows wrapper is offset by rowsWrapperOffset. * The actual DOM position of a row is: rowsWrapperOffset + slot.translateY. * * Horizontal scrolling only happens when column geometry is provided; the * resulting native scroll event drives header sync and setViewport as usual. */ declare const scrollCellIntoView: (core: { getScrollTopForRow(row: number): number; }, container: HTMLElement, row: number, rowHeight: number, slots: Map, rowsWrapperOffset?: number, columns?: ColumnScrollGeometry) => void; //#endregion //#region src/utils/format-helpers.d.ts /** * Convert a CellValue to a display string. * * - null/undefined → "" * - arrays → items joined with ", " * - Date → String(value) * - plain object → JSON.stringify(value) * - primitives → String(value) * * An optional `formatter` (from `ColumnDefinition.valueFormatter`) overrides * the default logic for non-null values. */ declare const formatCellValue: (value: CellValue, formatter?: (v: CellValue) => string) => string; //#endregion //#region src/utils/fill-helpers.d.ts interface VisibleColumnInfo { column: ColumnDefinition; originalIndex: number; } interface FillHandlePosition { top: number; left: number; } interface CalculateFillHandlePositionParams { activeCell: CellPosition | null; selectionRange: CellRange | null; slots: Map; columns: ColumnDefinition[]; visibleColumnsWithIndices: VisibleColumnInfo[]; columnPositions: number[]; columnWidths: number[]; rowHeight: number; } /** * Calculate the fill handle position (bottom-right corner of active cell or selection). * Returns null if no cell is active, columns are not editable, or the target is not visible. */ declare const calculateFillHandlePosition: (params: CalculateFillHandlePositionParams) => FillHandlePosition | null; //#endregion //#region src/utils/popup-position.d.ts /** * Framework-agnostic popup positioning utility. * Calculates the position for a popup element anchored to a header cell, * with viewport boundary clamping. */ interface PopupPosition { top: number; left: number; minWidth: number; } /** * Calculate the position for a filter popup anchored below a header cell. * Clamps to viewport edges and flips above the header if there is not enough * space below. */ declare const calculateFilterPopupPosition: (headerCell: HTMLElement, popupEl: HTMLElement, viewportPadding?: number) => PopupPosition; //#endregion //#region src/utils/peek-select-all.d.ts /** * Scope Ctrl/Cmd+A to the peek overlay's content. * * Pure CSS (`user-select: none` outside the overlay) only hides the visual * highlight — the browser still constructs a Selection range across the whole * document, and form controls use a separate selection model that CSS does * not affect. This helper intercepts the shortcut, builds a Range covering * the overlay node, and installs it as the active Selection so only the * overlay's text is highlighted. * * Returns a cleanup function the caller invokes on unmount. * SSR-safe: no-op when `document` is undefined. */ declare const bindPeekSelectAll: (overlay: HTMLElement) => (() => void); //#endregion //#region src/i18n.d.ts /** Labels for the filter operator dropdowns, keyed by semantic meaning. */ interface GridFilterOperatorLabels { /** Text operator: contains */ contains: string; /** Text operator: does not contain */ notContains: string; /** Text operator: starts with */ startsWith: string; /** Text operator: ends with */ endsWith: string; /** Shared "equals" (= for number/date, equals for text) */ equals: string; /** Shared "does not equal" (!= / notEquals) */ notEquals: string; /** Number/date operator: greater than */ greaterThan: string; /** Number/date operator: less than */ lessThan: string; /** Number operator: greater than or equal */ greaterThanOrEqual: string; /** Number operator: less than or equal */ lessThanOrEqual: string; /** Number/date operator: between */ between: string; /** Shared "is blank" operator */ blank: string; /** Shared "is not blank" operator */ notBlank: string; } /** * All user-visible grid labels. Strings containing `{token}` placeholders are * templates interpolated by {@link formatLabel}; the documented tokens are * `{column}`, `{count}`, and `{message}`. */ interface GridLabels { /** Filter popup title template. Token: `{column}`. */ filterTitle: string; /** Combination toggle: AND */ and: string; /** Combination toggle: OR */ or: string; /** Filter value input placeholder */ valuePlaceholder: string; /** "between" second-input separator */ betweenSeparator: string; /** "+ Add condition" button */ addCondition: string; /** Remove-condition button glyph */ removeCondition: string; /** "+ Add group" button */ addGroup: string; /** Remove-group button glyph */ removeGroup: string; /** Clear button */ clear: string; /** Apply button */ apply: string; /** Values mode toggle */ valuesMode: string; /** Condition mode toggle */ conditionMode: string; /** Values-mode search input placeholder */ searchPlaceholder: string; /** Select all button */ selectAll: string; /** Deselect all button */ deselectAll: string; /** "(Blanks)" checkbox label */ blanks: string; /** Too-many-values message template. Token: `{count}`. */ tooManyValues: string; /** Empty grid message */ emptyState: string; /** Error message prefix template. Token: `{message}`. */ errorPrefix: string; /** Filter operator labels */ operators: GridFilterOperatorLabels; } /** * Consumer overrides for grid labels. Every top-level label and every nested * operator label can be changed independently. */ type GridLabelOverrides = Omit, "operators"> & { operators?: Partial; }; /** English defaults for every grid label. */ declare const defaultGridLabels: GridLabels; /** * Merge a partial label set over the English defaults, producing a complete * `GridLabels`. Top-level keys are shallow-merged and `operators` is merged * one level deep; the defaults are never mutated. */ declare const resolveGridLabels: (overrides?: GridLabelOverrides) => GridLabels; /** * Interpolate `{token}` placeholders in a label template. Unknown tokens are * left untouched and missing params are skipped, so this never throws. */ declare const formatLabel: (template: string, params?: Record) => string; /** A single operator option rendered in a filter dropdown. */ interface FilterOperatorOption { value: TOperator; label: string; } /** Text filter operators in display order. */ declare const getTextOperatorOptions: (labels: GridLabels) => FilterOperatorOption[]; /** Number filter operators in display order. */ declare const getNumberOperatorOptions: (labels: GridLabels) => FilterOperatorOption[]; /** Date filter operators in display order. */ declare const getDateOperatorOptions: (labels: GridLabels) => FilterOperatorOption[]; //#endregion //#region src/adapter/pointer-event.d.ts /** * Convert a DOM PointerEvent into the framework-agnostic PointerEventData * shape consumed by core.input.*. * * Used by framework wrappers so each pointer-down handler doesn't have to * spell out the 8-field literal. */ declare const toPointerEventData: (event: PointerEvent) => PointerEventData; //#endregion //#region src/adapter/auto-scroll.d.ts /** * Continuous scroll driver used while a drag (selection, fill, row-drag) * leaves the viewport. The caller provides the scroll element getter and * a tick callback that re-processes the most recent pointer event after * each programmatic scroll, so the visible region catches up under the * pointer. * * Framework-agnostic: accepts plain getter/callback functions and relies * only on setInterval + element.scrollTop/scrollLeft. */ declare class AutoScrollDriver { private intervalId; private lastPointerEvent; private readonly getBodyEl; private readonly onTick; constructor(getBodyEl: () => HTMLElement | null, onTick: (event: PointerEvent) => void); recordPointer(event: PointerEvent): void; clearPointer(): void; start(dx: number, dy: number): void; stop(): void; } //#endregion //#region src/adapter/pending-row-drag.d.ts interface PendingRowDragDeps { getCore: () => GridCore | null; getContainer: () => HTMLElement | null; isBrowser: boolean; onDragConfirmed: (state: DragState) => void; } /** * Row-drag pending state machine. When a row-drag handle is pressed, we * must distinguish a tap/click (no drag) from an intentional hold (drag). * * Algorithm: * - start() arms a 300ms timer and listens for pointermove/up on document. * - If the pointer moves >10px before the timer fires → cancel (treat as tap). * - If the pointer releases before the timer fires → cancel. * - If the timer fires first → confirm: lock container overflow, block * touchmove, capture the pointer, and tell the caller the drag is live. * * Framework-agnostic: accepts plain getter/callback deps and touches only * the document/element DOM APIs. Wrappers gate construction on browser. */ declare class PendingRowDragController { private timer; private capture; private savedContainerOverflow; private readonly blockTouchMove; private readonly deps; constructor(deps: PendingRowDragDeps); start(event: PointerEvent): void; cancel(): void; private reset; releaseLocks(): void; private confirm; private lockContainer; private applyPointerCapture; } //#endregion //#region src/adapter/pending-cell-tap.d.ts interface PendingCellTapDeps { getCore: () => GridCore | null; isBrowser: boolean; /** Called after a tap confirmed selection (wrapper focuses the container). */ onTapConfirmed: () => void; } /** * Tap confirmation state machine for touch cell selection. On touch, * selection is deferred from pointerdown to a confirmed tap so a scroll * gesture never selects a cell (and never shows the fill handle). * * Algorithm: * - start() listens for pointermove/up/cancel on document. * - If the pointer moves beyond the tap slop → cancel (it is a scroll; * covers scaled mode where the synthetic scroller keeps pointermove alive). * - On pointercancel → cancel (native scroll claimed the gesture in * non-scaled mode, or a system gesture took over). * - On pointerup within the slop → confirm: core applies the selection. * * Framework-agnostic: accepts plain getter/callback deps and touches only * the document DOM APIs. Wrappers gate construction on browser. */ declare class PendingCellTapController { private cleanup; private readonly deps; constructor(deps: PendingCellTapDeps); start(event: PointerEvent): void; cancel(): void; private detachListeners; } //#endregion //#region src/adapter/touch-scroll.d.ts interface TouchScrollDeps { getCore: () => GridCore | null; /** The overflow:auto body element that owns the grid scrollbars. */ getScrollEl: () => HTMLElement | null; isBrowser: boolean; } /** * Synthetic touch scrolling for scaled grids. When scroll virtualization * compresses the DOM scroll space (scrollRatio < 1), native touch scrolling * gets amplified through the ratio and the fling momentum no longer matches * the finger. This controller takes over touch gestures in that regime: * content tracks the finger 1:1 in logical space and release flings decay * with a consistent, platform-independent curve. * * Performance contract: only a passive touchstart (plus a passive wheel * listener that cancels flings) is attached permanently. The non-passive * touchmove and the end listeners are attached per-gesture, and only when * scaling is active — small grids keep fully native, compositor-driven * scrolling with zero added cost. * * Collaborators: `TouchPolicy` owns the element's touch-action policy, * `SyntheticScroll` bridges the fractional position to the core, and * `FlingAnimator` runs the release momentum. */ declare class TouchScrollController { private readonly deps; private readonly scroll; private readonly fling; private attachedEl; private policy; private gesture; private gestureCleanup; private dragFrame; private pendingDragTarget; constructor(deps: TouchScrollDeps); attach(): void; detach(): void; /** Rebind policy updates after the host replaces its GridCore instance. */ syncCore(): void; /** Cancel an in-flight fling (call before programmatic scrollTop writes). */ stop(): void; private resolveContext; private readonly onWheel; private readonly onTouchStart; private startTouchGesture; private attachGestureListeners; private clearGesture; /** Drop the gesture and hand scrolling back to the browser. */ private abandonGesture; private trackedTouch; private readonly onTouchMove; private scheduleDragApply; private flushPendingDrag; /** * Render a drag position. While the finger is down the workload is * self-limiting (content moves at most one screen per gesture), so every * coalesced frame runs the full pipeline — throttling under the finger * reads as jank, not speed. */ private applyDragTarget; private readonly onTouchEnd; private readonly onTouchCancel; } //#endregion //#region src/adapter/batch-applier.d.ts type EditingCell = { row: number; col: number; initialValue: CellValue; } | null; /** * A "setters bag" the wrapper provides. Each setter pokes a framework- * specific reactive primitive (signal.set, ref.value =, dispatch action). * The batch applier itself is pure and reactivity-agnostic. */ interface BatchChangeSetters { setContentWidth: (v: number) => void; setContentHeight: (v: number) => void; setRowsWrapperOffset: (v: number) => void; setIsLoading: (v: boolean) => void; setErrorMessage: (v: string | null) => void; setTotalRows: (v: number) => void; setPendingScrollTop: (v: number | null) => void; setActiveCell: (v: CellPosition | null) => void; setSelectionRange: (v: CellRange | null) => void; setEditingCell: (v: EditingCell) => void; setHoverPosition: (v: CellPosition | null) => void; setPeekCell: (v: CellPosition | null) => void; setColumnsOverride: (v: ColumnDefinition[]) => void; onFilterPopupChange: (v: FilterPopupState | null) => void; } type MutableMaps = { slots: Map; headers: Map; }; /** * Apply a batch of grid instructions to a snapshot of slots/headers while * dispatching scalar changes through the provided setters. Returns the * new slot/header maps so the wrapper can commit them to its reactive * containers in one step. */ declare const applyBatchInstructions: (instructions: readonly GridInstruction[], currentSlots: Map, currentHeaders: Map, setters: BatchChangeSetters) => MutableMaps; //#endregion //#region src/adapter/data-source-owner.d.ts /** * Manages the "owned vs. provided" DataSource lifecycle shared by every * framework wrapper: wrap a raw `rows` array when the user didn't provide * their own DataSource, detect changes to `rows` / `columns` between * renders so we don't re-apply unchanged inputs, and destroy the owned * DataSource on teardown. * * The owner is framework-agnostic: it doesn't subscribe to anything. * Wrappers drive it from their own reactivity system (signal effects, * useEffect, watch) and react to its return values. */ declare class DataSourceOwner { private owned; private lastAppliedRows; private lastAppliedColumns; /** * Call once on setup. If the user provided a DataSource, use it. * Otherwise build one from the initial rows array and remember it * for later destruction. */ initialize(provided: DataSource | null, initialRows: TData[]): DataSource; /** * Call when the `rows` input changes. Returns a new owned DataSource * if one was rebuilt (caller should push it to core via setDataSource), * or null if nothing changed or a provided DataSource is in use. */ syncRows(rows: TData[], provided: DataSource | null): DataSource | null; /** * Call when the `columns` input changes. Returns true if the reference * is new and the caller should push to core via setColumns; false if * unchanged. */ syncColumns(columns: ColumnDefinition[]): boolean; /** Destroy the owned DataSource, if any. Safe to call multiple times. */ destroy(): void; } //#endregion //#region src/adapter/input-event-adapter.d.ts interface InputEventAdapterDeps { getCore: () => GridCore | null; getBodyEl: () => HTMLElement | null; autoScroll: AutoScrollDriver; pendingRowDrag: PendingRowDragController; pendingCellTap: PendingCellTapController; onDragStateChange: (state: DragState) => void; } interface CellPointerAction { preventDefault: boolean; focusContainer: boolean; } interface FillPointerAction { preventDefault: boolean; stopPropagation: boolean; } interface DragEndResult { wasRowDrag: boolean; } /** * Shared event-to-core adapter consumed by every framework wrapper. * * Each method accepts a DOM event (PointerEvent/KeyboardEvent) plus any * caller-side state the core needs, converts the event to the framework- * agnostic PointerEventData/KeyEventData shape, forwards it to core's * input handler, and performs the side effects that would otherwise be * reimplemented in each wrapper (drag-start dispatch, pointer capture, * auto-scroll start/stop, row-drag teardown). * * Methods return primitive "hint" objects so the wrapper can apply the * DOM actions that are framework-specific (preventDefault, focus, scroll * to cell, release container locks). */ declare class InputEventAdapter { private readonly deps; constructor(deps: InputEventAdapterDeps); headerPointerDown(colIndex: number, colWidth: number, colHeight: number, event: PointerEvent): boolean; resizePointerDown(colIndex: number, colWidth: number, event: PointerEvent): boolean; cellPointerDown(rowIndex: number, colIndex: number, event: PointerEvent): CellPointerAction; cellPointerEnter(rowIndex: number, colIndex: number): void; cellPointerLeave(): void; fillHandlePointerDown(activeCell: CellPosition | null, selectionRange: CellRange | null, event: PointerEvent): FillPointerAction; dragMove(event: PointerEvent): void; documentPointerMove(event: PointerEvent): boolean; documentPointerUp(): DragEndResult; wheel(deltaY: number, deltaX: number, dampening: number): { dy: number; dx: number; } | null; keyDown(event: KeyboardEvent, activeCell: CellPosition | null, editingCell: { row: number; col: number; } | null, filterPopupOpen: boolean): KeyboardResult; pasteText(text: string, editingCell: { row: number; col: number; } | null, filterPopupOpen: boolean): boolean; private dispatchCellDragStart; } //#endregion export { type AssignSlotInstruction, AutoScrollDriver, type BatchChangeSetters, type BatchInstructionListener, type CalculateFillHandlePositionParams, type CancelFillInstruction, type CellDataType, type CellPointerAction, type CellPosition, type CellRange, type CellRendererParams, type CellValue, type CellValueChangedEvent, type CloseFilterPopupInstruction, type ColumnDefinition, type ColumnFilterInput, type ColumnFilterModel, type ColumnMoveDragState, type ColumnResizeDragState, type ColumnScrollGeometry, type ColumnsChangedInstruction, type CommitEditInstruction, type CommitFillInstruction, type ContainerBounds, type CreateSlotInstruction, type DataChangeListener, type DataErrorInstruction, type DataLoadedInstruction, type DataLoadingInstruction, type DataSource, type DataSourceLoadMode, DataSourceOwner, type DataSourceRange, type DataSourceRequest, type DataSourceResponse, type DateFilterCondition, type DateFilterOperator, type DestroySlotInstruction, type Direction, type DistinctValueEntry, type DragEndResult, type DragMoveResult, type DragState, type EditRendererParams, type EditState, type FillHandlePosition, type FillHandleState, type FillPointerAction, type FilterCombination, type FilterCondition, type FilterConditionGroup, type FilterModel, type FilterOperatorOption, type FilterPopupState, GridCore, type GridCoreOptions, type GridFilterOperatorLabels, type GridInstruction, type GridLabelOverrides, type GridLabels, type GridState, type HeaderData, type HeaderRendererParams, type HighlightContext, type HighlightingOptions, IndexedDataStore, type IndexedDataStoreOptions, type InitialStateArgs, InputEventAdapter, type InputEventAdapterDeps, InputHandler, type InputHandlerDeps, type InputResult, type InstructionListener, type KeyEventData, type KeyboardResult, type LegacyColumnFilterModel, type LegacyFilterCondition, type MoveSlotInstruction, type MutableClientDataSourceOptions, type MutableDataSource, type NumberFilterCondition, type NumberFilterOperator, type OpenFilterPopupInstruction, type ParallelSortOptions, PendingCellTapController, type PendingCellTapDeps, PendingRowDragController, type PendingRowDragDeps, type PointerEventData, type PopupPosition, ROW_DRAG_HOLD_MS, type RowCacheEviction, type RowCacheOptions, type RowDragState, type RowId, type RowLoadingMode, type RowLoadingOptions, type SelectionState, type ServerDataSourceOptions, type SetActiveCellInstruction, type SetContentSizeInstruction, type SetHoverPositionInstruction, type SetSelectionRangeInstruction, type SlotData, type SlotState, type SortDirection, type SortModel, type StartEditInstruction, type StartFillInstruction, type StartPeekInstruction, type StopEditInstruction, type StopPeekInstruction, TAP_SLOP_PX, type TextFilterCondition, type TextFilterOperator, TouchScrollController, type TouchScrollDeps, type Transaction, TransactionManager, type TransactionManagerOptions, type TransactionResult, type UpdateFillInstruction, type UpdateHeaderInstruction, type VisibleColumnInfo, applyBatchInstructions, applyInstruction, bindPeekSelectAll, buildCellClasses, calculateColumnPositions, calculateFillHandlePosition, calculateFilterPopupPosition, calculateScaledColumnPositions, createClientDataSource, createDataSourceFromArray, createInitialState, createMutableClientDataSource, createServerDataSource, defaultGridLabels, evaluateColumnFilter, evaluateDateCondition, evaluateNumberCondition, evaluateTextCondition, findColumnAtX, formatCellValue, formatLabel, getDateOperatorOptions, getFieldValue, getNumberOperatorOptions, getTextOperatorOptions, getTotalWidth, groupDistinctValues, isBlankCellValue, isCellActive, isCellEditing, isCellInFillPreview, isCellSelected, isLegacyColumnFilterModel, isRowVisible, isSameDay, labelsForSelectedValues, normalizeColumnFilterModel, rawValueKey, rawValuesForLabels, resolveGridLabels, rowPassesFilter, scrollCellIntoView, setFieldValue, toPointerEventData };