gp-grid-core 0.1.4 → 0.1.5
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.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ type Row = unknown;
|
|
|
8
8
|
/** Sort direction type */
|
|
9
9
|
type SortDirection = "asc" | "desc";
|
|
10
10
|
/** Sort model type */
|
|
11
|
-
type SortModel
|
|
11
|
+
type SortModel = {
|
|
12
12
|
colId: string;
|
|
13
13
|
direction: SortDirection;
|
|
14
14
|
};
|
|
@@ -88,7 +88,7 @@ interface DataSourceRequest {
|
|
|
88
88
|
pageSize: number;
|
|
89
89
|
};
|
|
90
90
|
/** Sort */
|
|
91
|
-
sort?: SortModel
|
|
91
|
+
sort?: SortModel[];
|
|
92
92
|
/** Filter */
|
|
93
93
|
filter?: FilterModel;
|
|
94
94
|
}
|
|
@@ -469,7 +469,7 @@ declare class GridCore<TData extends Row = Row> {
|
|
|
469
469
|
* Force refresh all slot data (used after filtering/sorting when data changes)
|
|
470
470
|
*/
|
|
471
471
|
private refreshAllSlots;
|
|
472
|
-
getSortModel(): SortModel
|
|
472
|
+
getSortModel(): SortModel[];
|
|
473
473
|
getFilterModel(): FilterModel;
|
|
474
474
|
startEdit(row: number, col: number): void;
|
|
475
475
|
updateEditValue(value: CellValue): void;
|
|
@@ -630,5 +630,5 @@ declare function getSharedSortWorker(): SortWorkerManager;
|
|
|
630
630
|
*/
|
|
631
631
|
declare function terminateSharedSortWorker(): void;
|
|
632
632
|
//#endregion
|
|
633
|
-
export { type AssignSlotInstruction, type BatchInstructionListener, type CancelFillInstruction, type CellDataType, type CellPosition, type CellRange, type CellRendererParams, type CellValue, type ColumnDefinition, type CommitEditInstruction, type CommitFillInstruction, type CreateSlotInstruction, type DataErrorInstruction, type DataLoadedInstruction, type DataLoadingInstruction, type DataSource, type DataSourceRequest, type DataSourceResponse, type DestroySlotInstruction, type Direction, type EditRendererParams, type EditState, type FillHandleState, FillManager, type FilterModel, GridCore, type GridCoreOptions, type GridInstruction, type HeaderRendererParams, type InstructionListener, type MoveSlotInstruction, type Row, SelectionManager, type SelectionState, type SetActiveCellInstruction, type SetContentSizeInstruction, type SetSelectionRangeInstruction, type SlotState, type SortDirection, type SortModel
|
|
633
|
+
export { type AssignSlotInstruction, type BatchInstructionListener, type CancelFillInstruction, type CellDataType, type CellPosition, type CellRange, type CellRendererParams, type CellValue, type ColumnDefinition, type CommitEditInstruction, type CommitFillInstruction, type CreateSlotInstruction, type DataErrorInstruction, type DataLoadedInstruction, type DataLoadingInstruction, type DataSource, type DataSourceRequest, type DataSourceResponse, type DestroySlotInstruction, type Direction, type EditRendererParams, type EditState, type FillHandleState, FillManager, type FilterModel, GridCore, type GridCoreOptions, type GridInstruction, type HeaderRendererParams, type InstructionListener, type MoveSlotInstruction, type Row, SelectionManager, type SelectionState, type SetActiveCellInstruction, type SetContentSizeInstruction, type SetSelectionRangeInstruction, type SlotState, type SortDirection, type SortModel, SortWorkerManager, type StartEditInstruction, type StartFillInstruction, type StopEditInstruction, type UpdateFillInstruction, type UpdateHeaderInstruction, createClientDataSource, createDataSourceFromArray, createServerDataSource, getSharedSortWorker, terminateSharedSortWorker };
|
|
634
634
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/selection.ts","../src/fill.ts","../src/grid-core.ts","../src/data-source.ts","../src/worker-manager.ts"],"sourcesContent":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/selection.ts","../src/fill.ts","../src/grid-core.ts","../src/data-source.ts","../src/worker-manager.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["data: CellValue[][]","row: CellValue[]","result: Array<{ row: number; col: number; value: CellValue }>","values: CellValue[]","diffs: number[]","instructions: GridInstruction[]","slotsToRecycle: string[]","newSlot: SlotState","request: DataSourceRequest","value: unknown","value: unknown","compareValues","request: SortWorkerRequest","request: SortIndicesRequest","request: SortMultiColumnRequest","request: SortStringHashesRequest","groups: { start: number; end: number }[]","sharedWorkerManager: SortWorkerManager | null","getFieldValue","sortedIndices: Uint32Array","originalStrings: string[]","hashChunks: number[][]","columnValues: number[][]","directions: Array<\"asc\" | \"desc\">","mapped: number","hashes: number[]","value: unknown"],"sources":["../src/selection.ts","../src/fill.ts","../src/grid-core.ts","../src/sort-worker.ts","../src/worker-manager.ts","../src/data-source.ts"],"sourcesContent":["// gp-grid-core/src/selection.ts\n\nimport type {\n CellPosition,\n CellRange,\n SelectionState,\n GridInstruction,\n InstructionListener,\n CellValue,\n ColumnDefinition,\n Row,\n} from \"./types\";\n\nexport type Direction = \"up\" | \"down\" | \"left\" | \"right\";\n\nexport interface SelectionManagerOptions {\n getRowCount: () => number;\n getColumnCount: () => number;\n getCellValue: (row: number, col: number) => CellValue;\n getRowData: (row: number) => Row | undefined;\n getColumn: (col: number) => ColumnDefinition | undefined;\n}\n\n/**\n * Manages Excel-style cell selection, keyboard navigation, and clipboard operations.\n */\nexport class SelectionManager {\n private state: SelectionState = {\n activeCell: null,\n range: null,\n anchor: null,\n selectionMode: false,\n };\n\n private options: SelectionManagerOptions;\n private listeners: InstructionListener[] = [];\n\n constructor(options: SelectionManagerOptions) {\n this.options = options;\n }\n\n // ===========================================================================\n // Instruction Emission\n // ===========================================================================\n\n onInstruction(listener: InstructionListener): () => void {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n private emit(instruction: GridInstruction): void {\n for (const listener of this.listeners) {\n listener(instruction);\n }\n }\n\n // ===========================================================================\n // State Accessors\n // ===========================================================================\n\n getState(): SelectionState {\n return { ...this.state };\n }\n\n getActiveCell(): CellPosition | null {\n return this.state.activeCell;\n }\n\n getSelectionRange(): CellRange | null {\n return this.state.range;\n }\n\n isSelected(row: number, col: number): boolean {\n const { range } = this.state;\n if (!range) return false;\n\n const minRow = Math.min(range.startRow, range.endRow);\n const maxRow = Math.max(range.startRow, range.endRow);\n const minCol = Math.min(range.startCol, range.endCol);\n const maxCol = Math.max(range.startCol, range.endCol);\n\n return row >= minRow && row <= maxRow && col >= minCol && col <= maxCol;\n }\n\n isActiveCell(row: number, col: number): boolean {\n const { activeCell } = this.state;\n return activeCell?.row === row && activeCell?.col === col;\n }\n\n // ===========================================================================\n // Selection Operations\n // ===========================================================================\n\n /**\n * Start a selection at the given cell.\n * @param cell - The cell to select\n * @param opts.shift - Extend selection from anchor (range select)\n * @param opts.ctrl - Toggle selection mode\n */\n startSelection(\n cell: CellPosition,\n opts: { shift?: boolean; ctrl?: boolean } = {}\n ): void {\n // console.log(\"[GP-Grid Selection] startSelection:\", { cell, opts, listenerCount: this.listeners.length });\n const { shift = false, ctrl = false } = opts;\n const { row, col } = this.clampPosition(cell);\n\n if (shift && this.state.anchor) {\n // Extend selection from anchor to current cell\n this.state.range = {\n startRow: this.state.anchor.row,\n startCol: this.state.anchor.col,\n endRow: row,\n endCol: col,\n };\n this.state.activeCell = { row, col };\n } else {\n // Start new selection\n this.state.activeCell = { row, col };\n this.state.anchor = { row, col };\n this.state.range = null;\n }\n\n this.state.selectionMode = ctrl;\n\n // console.log(\"[GP-Grid Selection] Emitting SET_ACTIVE_CELL:\", this.state.activeCell);\n this.emit({ type: \"SET_ACTIVE_CELL\", position: this.state.activeCell });\n // console.log(\"[GP-Grid Selection] Emitting SET_SELECTION_RANGE:\", this.state.range);\n this.emit({ type: \"SET_SELECTION_RANGE\", range: this.state.range });\n }\n\n /**\n * Move focus in a direction, optionally extending the selection.\n */\n moveFocus(direction: Direction, extend: boolean = false): void {\n if (!this.state.activeCell) {\n // No active cell, select first cell\n this.startSelection({ row: 0, col: 0 });\n return;\n }\n\n const { row, col } = this.state.activeCell;\n let newRow = row;\n let newCol = col;\n\n switch (direction) {\n case \"up\":\n newRow = Math.max(0, row - 1);\n break;\n case \"down\":\n newRow = Math.min(this.options.getRowCount() - 1, row + 1);\n break;\n case \"left\":\n newCol = Math.max(0, col - 1);\n break;\n case \"right\":\n newCol = Math.min(this.options.getColumnCount() - 1, col + 1);\n break;\n }\n\n if (extend) {\n // Extend selection (Shift+Arrow)\n if (!this.state.anchor) {\n this.state.anchor = { row, col };\n }\n\n this.state.range = {\n startRow: this.state.anchor.row,\n startCol: this.state.anchor.col,\n endRow: newRow,\n endCol: newCol,\n };\n this.state.activeCell = { row: newRow, col: newCol };\n\n this.emit({ type: \"SET_ACTIVE_CELL\", position: this.state.activeCell });\n this.emit({ type: \"SET_SELECTION_RANGE\", range: this.state.range });\n } else {\n // Move without extending\n this.state.activeCell = { row: newRow, col: newCol };\n this.state.anchor = { row: newRow, col: newCol };\n this.state.range = null;\n\n this.emit({ type: \"SET_ACTIVE_CELL\", position: this.state.activeCell });\n this.emit({ type: \"SET_SELECTION_RANGE\", range: null });\n }\n }\n\n /**\n * Select all cells in the grid (Ctrl+A).\n */\n selectAll(): void {\n const rowCount = this.options.getRowCount();\n const colCount = this.options.getColumnCount();\n\n if (rowCount === 0 || colCount === 0) return;\n\n this.state.range = {\n startRow: 0,\n startCol: 0,\n endRow: rowCount - 1,\n endCol: colCount - 1,\n };\n\n // Keep active cell if exists, otherwise set to first cell\n if (!this.state.activeCell) {\n this.state.activeCell = { row: 0, col: 0 };\n this.emit({ type: \"SET_ACTIVE_CELL\", position: this.state.activeCell });\n }\n\n this.emit({ type: \"SET_SELECTION_RANGE\", range: this.state.range });\n }\n\n /**\n * Clear the current selection.\n */\n clearSelection(): void {\n this.state.activeCell = null;\n this.state.range = null;\n this.state.anchor = null;\n this.state.selectionMode = false;\n\n this.emit({ type: \"SET_ACTIVE_CELL\", position: null });\n this.emit({ type: \"SET_SELECTION_RANGE\", range: null });\n }\n\n /**\n * Set the active cell directly.\n */\n setActiveCell(row: number, col: number): void {\n const clamped = this.clampPosition({ row, col });\n this.state.activeCell = clamped;\n this.state.anchor = clamped;\n this.state.range = null;\n\n this.emit({ type: \"SET_ACTIVE_CELL\", position: this.state.activeCell });\n this.emit({ type: \"SET_SELECTION_RANGE\", range: null });\n }\n\n /**\n * Set the selection range directly.\n */\n setSelectionRange(range: CellRange): void {\n this.state.range = range;\n this.emit({ type: \"SET_SELECTION_RANGE\", range: this.state.range });\n }\n\n // ===========================================================================\n // Data Extraction\n // ===========================================================================\n\n /**\n * Get the data from the currently selected cells as a 2D array.\n */\n getSelectedData(): CellValue[][] {\n const { range, activeCell } = this.state;\n\n if (!range && !activeCell) {\n return [];\n }\n\n const effectiveRange = range || {\n startRow: activeCell!.row,\n startCol: activeCell!.col,\n endRow: activeCell!.row,\n endCol: activeCell!.col,\n };\n\n const minRow = Math.min(effectiveRange.startRow, effectiveRange.endRow);\n const maxRow = Math.max(effectiveRange.startRow, effectiveRange.endRow);\n const minCol = Math.min(effectiveRange.startCol, effectiveRange.endCol);\n const maxCol = Math.max(effectiveRange.startCol, effectiveRange.endCol);\n\n const data: CellValue[][] = [];\n\n for (let r = minRow; r <= maxRow; r++) {\n const row: CellValue[] = [];\n for (let c = minCol; c <= maxCol; c++) {\n row.push(this.options.getCellValue(r, c));\n }\n data.push(row);\n }\n\n return data;\n }\n\n /**\n * Copy the selected data to the clipboard (Ctrl+C).\n */\n async copySelectionToClipboard(): Promise<void> {\n const data = this.getSelectedData();\n if (data.length === 0) return;\n\n // Convert to tab-separated values (Excel-compatible)\n const tsv = data\n .map((row) =>\n row.map((cell) => (cell == null ? \"\" : String(cell))).join(\"\\t\")\n )\n .join(\"\\n\");\n\n try {\n await navigator.clipboard.writeText(tsv);\n } catch (err) {\n // Fallback for older browsers\n const textarea = document.createElement(\"textarea\");\n textarea.value = tsv;\n textarea.style.position = \"fixed\";\n textarea.style.left = \"-9999px\";\n document.body.appendChild(textarea);\n textarea.select();\n document.execCommand(\"copy\");\n document.body.removeChild(textarea);\n }\n }\n\n // ===========================================================================\n // Helpers\n // ===========================================================================\n\n private clampPosition(pos: CellPosition): CellPosition {\n const rowCount = this.options.getRowCount();\n const colCount = this.options.getColumnCount();\n\n return {\n row: Math.max(0, Math.min(pos.row, rowCount - 1)),\n col: Math.max(0, Math.min(pos.col, colCount - 1)),\n };\n }\n}\n\n","// gp-grid-core/src/fill.ts\n\nimport type {\n CellRange,\n CellValue,\n FillHandleState,\n GridInstruction,\n InstructionListener,\n ColumnDefinition,\n} from \"./types\";\n\nexport interface FillManagerOptions {\n getRowCount: () => number;\n getColumnCount: () => number;\n getCellValue: (row: number, col: number) => CellValue;\n getColumn: (col: number) => ColumnDefinition | undefined;\n setCellValue: (row: number, col: number, value: CellValue) => void;\n}\n\n/**\n * Manages fill handle operations including pattern detection and auto-fill.\n */\nexport class FillManager {\n private state: FillHandleState | null = null;\n private options: FillManagerOptions;\n private listeners: InstructionListener[] = [];\n\n constructor(options: FillManagerOptions) {\n this.options = options;\n }\n\n // ===========================================================================\n // Instruction Emission\n // ===========================================================================\n\n onInstruction(listener: InstructionListener): () => void {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n private emit(instruction: GridInstruction): void {\n for (const listener of this.listeners) {\n listener(instruction);\n }\n }\n\n // ===========================================================================\n // State Accessors\n // ===========================================================================\n\n getState(): FillHandleState | null {\n return this.state ? { ...this.state } : null;\n }\n\n isActive(): boolean {\n return this.state !== null;\n }\n\n // ===========================================================================\n // Fill Handle Operations\n // ===========================================================================\n\n /**\n * Start a fill drag operation from a source range.\n */\n startFillDrag(sourceRange: CellRange): void {\n this.state = {\n sourceRange,\n targetRow: sourceRange.endRow,\n targetCol: sourceRange.endCol,\n };\n\n this.emit({ type: \"START_FILL\", sourceRange });\n }\n\n /**\n * Update the fill drag target position.\n */\n updateFillDrag(targetRow: number, targetCol: number): void {\n if (!this.state) return;\n\n // Clamp to valid bounds\n const rowCount = this.options.getRowCount();\n const colCount = this.options.getColumnCount();\n\n targetRow = Math.max(0, Math.min(targetRow, rowCount - 1));\n targetCol = Math.max(0, Math.min(targetCol, colCount - 1));\n\n this.state.targetRow = targetRow;\n this.state.targetCol = targetCol;\n\n this.emit({ type: \"UPDATE_FILL\", targetRow, targetCol });\n }\n\n /**\n * Commit the fill operation - apply pattern to target cells.\n */\n commitFillDrag(): void {\n if (!this.state) return;\n\n const { sourceRange, targetRow, targetCol } = this.state;\n const filledCells = this.calculateFilledCells(sourceRange, targetRow, targetCol);\n\n // Apply values\n for (const { row, col, value } of filledCells) {\n this.options.setCellValue(row, col, value);\n }\n\n this.emit({ type: \"COMMIT_FILL\", filledCells });\n\n this.state = null;\n }\n\n /**\n * Cancel the fill operation.\n */\n cancelFillDrag(): void {\n if (!this.state) return;\n\n this.state = null;\n this.emit({ type: \"CANCEL_FILL\" });\n }\n\n // ===========================================================================\n // Pattern Detection & Fill Logic\n // ===========================================================================\n\n /**\n * Calculate the values to fill based on source pattern.\n */\n private calculateFilledCells(\n sourceRange: CellRange,\n targetRow: number,\n targetCol: number\n ): Array<{ row: number; col: number; value: CellValue }> {\n const result: Array<{ row: number; col: number; value: CellValue }> = [];\n\n const srcMinRow = Math.min(sourceRange.startRow, sourceRange.endRow);\n const srcMaxRow = Math.max(sourceRange.startRow, sourceRange.endRow);\n const srcMinCol = Math.min(sourceRange.startCol, sourceRange.endCol);\n const srcMaxCol = Math.max(sourceRange.startCol, sourceRange.endCol);\n\n // Determine fill direction\n const fillDown = targetRow > srcMaxRow;\n const fillUp = targetRow < srcMinRow;\n const fillRight = targetCol > srcMaxCol;\n const fillLeft = targetCol < srcMinCol;\n\n // For now, we only support vertical fills (most common use case)\n if (fillDown || fillUp) {\n for (let col = srcMinCol; col <= srcMaxCol; col++) {\n const sourceValues = this.getSourceColumnValues(srcMinRow, srcMaxRow, col);\n const pattern = this.detectPattern(sourceValues);\n\n if (fillDown) {\n for (let row = srcMaxRow + 1; row <= targetRow; row++) {\n const fillIndex = row - srcMaxRow - 1;\n const value = this.applyPattern(pattern, sourceValues, fillIndex);\n result.push({ row, col, value });\n }\n } else if (fillUp) {\n for (let row = srcMinRow - 1; row >= targetRow; row--) {\n const fillIndex = srcMinRow - row - 1;\n const value = this.applyPattern(pattern, sourceValues, fillIndex, true);\n result.push({ row, col, value });\n }\n }\n }\n }\n\n // Horizontal fill\n if (fillRight || fillLeft) {\n for (let row = srcMinRow; row <= srcMaxRow; row++) {\n const sourceValues = this.getSourceRowValues(srcMinCol, srcMaxCol, row);\n const pattern = this.detectPattern(sourceValues);\n\n if (fillRight) {\n for (let col = srcMaxCol + 1; col <= targetCol; col++) {\n const fillIndex = col - srcMaxCol - 1;\n const value = this.applyPattern(pattern, sourceValues, fillIndex);\n result.push({ row, col, value });\n }\n } else if (fillLeft) {\n for (let col = srcMinCol - 1; col >= targetCol; col--) {\n const fillIndex = srcMinCol - col - 1;\n const value = this.applyPattern(pattern, sourceValues, fillIndex, true);\n result.push({ row, col, value });\n }\n }\n }\n }\n\n return result;\n }\n\n private getSourceColumnValues(minRow: number, maxRow: number, col: number): CellValue[] {\n const values: CellValue[] = [];\n for (let row = minRow; row <= maxRow; row++) {\n values.push(this.options.getCellValue(row, col));\n }\n return values;\n }\n\n private getSourceRowValues(minCol: number, maxCol: number, row: number): CellValue[] {\n const values: CellValue[] = [];\n for (let col = minCol; col <= maxCol; col++) {\n values.push(this.options.getCellValue(row, col));\n }\n return values;\n }\n\n // ===========================================================================\n // Pattern Types\n // ===========================================================================\n\n private detectPattern(values: CellValue[]): FillPattern {\n if (values.length === 0) {\n return { type: \"constant\", value: null };\n }\n\n if (values.length === 1) {\n return { type: \"constant\", value: values[0] ?? null };\n }\n\n // Check for numeric sequence\n const numbers = values.map((v) => (typeof v === \"number\" ? v : Number(v)));\n if (numbers.every((n) => !isNaN(n))) {\n // Check for arithmetic sequence\n const diffs: number[] = [];\n for (let i = 1; i < numbers.length; i++) {\n diffs.push(numbers[i]! - numbers[i - 1]!);\n }\n\n const allSameDiff = diffs.every((d) => d === diffs[0]);\n if (allSameDiff && diffs[0] !== undefined) {\n return { type: \"arithmetic\", start: numbers[0]!, step: diffs[0] };\n }\n }\n\n // Check for repeating pattern\n return { type: \"repeat\", values };\n }\n\n private applyPattern(\n pattern: FillPattern,\n sourceValues: CellValue[],\n fillIndex: number,\n reverse: boolean = false\n ): CellValue {\n switch (pattern.type) {\n case \"constant\":\n return pattern.value;\n\n case \"arithmetic\": {\n const multiplier = reverse ? -(fillIndex + 1) : fillIndex + 1;\n const lastValue = reverse ? pattern.start : pattern.start + pattern.step * (sourceValues.length - 1);\n return lastValue + pattern.step * multiplier;\n }\n\n case \"repeat\": {\n const len = pattern.values.length;\n if (len === 0) return null;\n if (reverse) {\n // For reverse, cycle backwards\n const idx = (len - 1 - (fillIndex % len) + len) % len;\n return pattern.values[idx] ?? null;\n }\n return pattern.values[fillIndex % len] ?? null;\n }\n }\n }\n}\n\n// ===========================================================================\n// Pattern Types\n// ===========================================================================\n\ntype FillPattern =\n | { type: \"constant\"; value: CellValue }\n | { type: \"arithmetic\"; start: number; step: number }\n | { type: \"repeat\"; values: CellValue[] };\n\n","// gp-grid-core/src/grid-core.ts\n\nimport type {\n GridCoreOptions,\n GridInstruction,\n InstructionListener,\n BatchInstructionListener,\n ColumnDefinition,\n CellValue,\n DataSource,\n DataSourceRequest,\n Row,\n SortModel,\n SortDirection,\n FilterModel,\n SlotState,\n EditState,\n} from \"./types\";\nimport { SelectionManager } from \"./selection\";\nimport { FillManager } from \"./fill\";\n\n// =============================================================================\n// Slot Pool Manager\n// =============================================================================\n\ninterface SlotPoolState {\n slots: Map<string, SlotState>;\n /** Maps rowIndex to slotId for quick lookup */\n rowToSlot: Map<number, string>;\n nextSlotId: number;\n}\n\n// =============================================================================\n// GridCore\n// =============================================================================\n\nexport class GridCore<TData extends Row = Row> {\n // Maximum safe CSS height to avoid browser rendering issues with extreme values\n // Using 1M as a safer limit (some browsers have issues even at 10M)\n private static readonly MAX_SAFE_HEIGHT = 1_000_000; // 1M pixels\n\n // Configuration\n private columns: ColumnDefinition[];\n private dataSource: DataSource<TData>;\n private rowHeight: number;\n private headerHeight: number;\n private overscan: number;\n\n // Viewport state\n private scrollTop: number = 0;\n private scrollLeft: number = 0;\n private viewportWidth: number = 800;\n private viewportHeight: number = 600;\n\n // Data state\n private cachedRows: Map<number, TData> = new Map();\n private totalRows: number = 0;\n private currentPageIndex: number = 0;\n // Use large page size to avoid excessive pagination for client-side data sources\n private pageSize: number = 1000000;\n\n // Sort & Filter\n private sortModel: SortModel[] = [];\n private filterModel: FilterModel = {};\n\n // Slot pool\n private slotPool: SlotPoolState = {\n slots: new Map(),\n rowToSlot: new Map(),\n nextSlotId: 0,\n };\n\n // Managers\n public readonly selection: SelectionManager;\n public readonly fill: FillManager;\n\n // Edit state\n private editState: EditState | null = null;\n\n // Column positions (computed)\n private columnPositions: number[] = [];\n\n // Instruction listeners\n private listeners: InstructionListener[] = [];\n private batchListeners: BatchInstructionListener[] = [];\n\n constructor(options: GridCoreOptions<TData>) {\n this.columns = options.columns;\n this.dataSource = options.dataSource;\n this.rowHeight = options.rowHeight;\n this.headerHeight = options.headerHeight ?? options.rowHeight;\n this.overscan = options.overscan ?? 3;\n\n this.computeColumnPositions();\n\n // Initialize selection manager\n this.selection = new SelectionManager({\n getRowCount: () => this.totalRows,\n getColumnCount: () => this.columns.length,\n getCellValue: (row, col) => this.getCellValue(row, col),\n getRowData: (row) => this.cachedRows.get(row),\n getColumn: (col) => this.columns[col],\n });\n\n // Forward selection instructions\n this.selection.onInstruction((instruction) => this.emit(instruction));\n\n // Initialize fill manager\n this.fill = new FillManager({\n getRowCount: () => this.totalRows,\n getColumnCount: () => this.columns.length,\n getCellValue: (row, col) => this.getCellValue(row, col),\n getColumn: (col) => this.columns[col],\n setCellValue: (row, col, value) => this.setCellValue(row, col, value),\n });\n\n // Forward fill instructions\n this.fill.onInstruction((instruction) => this.emit(instruction));\n }\n\n // ===========================================================================\n // Instruction System\n // ===========================================================================\n\n onInstruction(listener: InstructionListener): () => void {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n /**\n * Subscribe to batched instructions for efficient React state updates.\n * Batch listeners receive arrays of instructions instead of individual ones.\n */\n onBatchInstruction(listener: BatchInstructionListener): () => void {\n this.batchListeners.push(listener);\n return () => {\n this.batchListeners = this.batchListeners.filter((l) => l !== listener);\n };\n }\n\n private emit(instruction: GridInstruction): void {\n // console.log(\"[GP-Grid Core] emit:\", instruction.type, { \n // listenerCount: this.listeners.length, \n // batchListenerCount: this.batchListeners.length \n // });\n // Emit to individual listeners\n for (const listener of this.listeners) {\n listener(instruction);\n }\n // Also emit as a single-item batch\n for (const listener of this.batchListeners) {\n listener([instruction]);\n }\n }\n\n private emitBatch(instructions: GridInstruction[]): void {\n if (instructions.length === 0) return;\n \n // console.log(\"[GP-Grid Core] emitBatch:\", instructions.map(i => i.type), {\n // batchListenerCount: this.batchListeners.length\n // });\n // Emit to batch listeners as a single batch\n for (const listener of this.batchListeners) {\n listener(instructions);\n }\n // Also emit to individual listeners for backwards compatibility\n for (const instruction of instructions) {\n for (const listener of this.listeners) {\n listener(instruction);\n }\n }\n }\n\n // ===========================================================================\n // Initialization\n // ===========================================================================\n\n /**\n * Initialize the grid and load initial data.\n */\n async initialize(): Promise<void> {\n await this.fetchData();\n this.syncSlots();\n this.emitContentSize();\n this.emitHeaders();\n }\n\n // ===========================================================================\n // Viewport Management\n // ===========================================================================\n\n /**\n * Update viewport measurements and sync slots.\n */\n setViewport(\n scrollTop: number,\n scrollLeft: number,\n width: number,\n height: number\n ): void {\n const changed =\n this.scrollTop !== scrollTop ||\n this.scrollLeft !== scrollLeft ||\n this.viewportWidth !== width ||\n this.viewportHeight !== height;\n\n if (!changed) return;\n\n this.scrollTop = scrollTop;\n this.scrollLeft = scrollLeft;\n this.viewportWidth = width;\n this.viewportHeight = height;\n\n this.syncSlots();\n }\n\n // ===========================================================================\n // Slot Pool Management (Virtual Scroll)\n // ===========================================================================\n\n /**\n * Synchronize slots with current viewport position.\n * This implements the slot recycling strategy.\n */\n private syncSlots(): void {\n // Use virtual scroll position for row calculations\n const virtualScrollTop = this.getVirtualScrollTop();\n\n // Calculate visible rows based on virtual scroll position\n // Viewport height stays the same (we don't compress the viewport)\n const visibleStartRow = Math.max(0, Math.floor(virtualScrollTop / this.rowHeight) - this.overscan);\n const visibleEndRow = Math.min(\n this.totalRows - 1,\n Math.ceil((virtualScrollTop + this.viewportHeight) / this.rowHeight) + this.overscan\n );\n\n if (this.totalRows === 0 || visibleEndRow < visibleStartRow) {\n // No rows to display - destroy all slots\n this.destroyAllSlots();\n return;\n }\n\n const requiredRows = new Set<number>();\n for (let row = visibleStartRow; row <= visibleEndRow; row++) {\n requiredRows.add(row);\n }\n\n const instructions: GridInstruction[] = [];\n\n // Find slots that are no longer needed\n const slotsToRecycle: string[] = [];\n for (const [slotId, slot] of this.slotPool.slots) {\n if (!requiredRows.has(slot.rowIndex)) {\n slotsToRecycle.push(slotId);\n this.slotPool.rowToSlot.delete(slot.rowIndex);\n } else {\n requiredRows.delete(slot.rowIndex);\n }\n }\n\n // Assign recycled slots to new rows\n const rowsNeedingSlots = Array.from(requiredRows);\n for (let i = 0; i < rowsNeedingSlots.length; i++) {\n const rowIndex = rowsNeedingSlots[i]!;\n const rowData = this.cachedRows.get(rowIndex);\n\n if (i < slotsToRecycle.length) {\n // Recycle existing slot\n const slotId = slotsToRecycle[i]!;\n const slot = this.slotPool.slots.get(slotId)!;\n const translateY = this.getRowTranslateY(rowIndex);\n\n slot.rowIndex = rowIndex;\n slot.rowData = rowData ?? {};\n slot.translateY = translateY;\n\n this.slotPool.rowToSlot.set(rowIndex, slotId);\n\n instructions.push({\n type: \"ASSIGN_SLOT\",\n slotId,\n rowIndex,\n rowData: rowData ?? {},\n });\n instructions.push({\n type: \"MOVE_SLOT\",\n slotId,\n translateY,\n });\n } else {\n // Create new slot\n const slotId = `slot-${this.slotPool.nextSlotId++}`;\n const translateY = this.getRowTranslateY(rowIndex);\n\n const newSlot: SlotState = {\n slotId,\n rowIndex,\n rowData: rowData ?? {},\n translateY,\n };\n\n this.slotPool.slots.set(slotId, newSlot);\n this.slotPool.rowToSlot.set(rowIndex, slotId);\n\n instructions.push({ type: \"CREATE_SLOT\", slotId });\n instructions.push({\n type: \"ASSIGN_SLOT\",\n slotId,\n rowIndex,\n rowData: rowData ?? {},\n });\n instructions.push({\n type: \"MOVE_SLOT\",\n slotId,\n translateY,\n });\n }\n }\n\n // Destroy excess slots\n for (let i = rowsNeedingSlots.length; i < slotsToRecycle.length; i++) {\n const slotId = slotsToRecycle[i]!;\n this.slotPool.slots.delete(slotId);\n instructions.push({ type: \"DESTROY_SLOT\", slotId });\n }\n\n // Update positions of existing slots that haven't moved\n for (const [slotId, slot] of this.slotPool.slots) {\n const expectedY = this.getRowTranslateY(slot.rowIndex);\n if (slot.translateY !== expectedY) {\n slot.translateY = expectedY;\n instructions.push({\n type: \"MOVE_SLOT\",\n slotId,\n translateY: expectedY,\n });\n }\n }\n\n this.emitBatch(instructions);\n }\n\n private destroyAllSlots(): void {\n const instructions: GridInstruction[] = [];\n for (const slotId of this.slotPool.slots.keys()) {\n instructions.push({ type: \"DESTROY_SLOT\", slotId });\n }\n this.slotPool.slots.clear();\n this.slotPool.rowToSlot.clear();\n this.emitBatch(instructions);\n }\n\n /**\n * Get the virtual (unscaled) height of the entire grid content.\n */\n private getVirtualHeight(): number {\n return this.totalRows * this.rowHeight + this.headerHeight;\n }\n\n /**\n * Get the display height (capped) for the content sizer.\n * This is the height that will be used in CSS for the scrollable area.\n */\n private getDisplayHeight(): number {\n return Math.min(this.getVirtualHeight(), GridCore.MAX_SAFE_HEIGHT);\n }\n\n /**\n * Check if scaling is needed (virtual height exceeds safe limit).\n */\n private needsScaling(): boolean {\n return this.getVirtualHeight() > GridCore.MAX_SAFE_HEIGHT;\n }\n\n /**\n * Get the scroll progress as a value from 0 to 1.\n * 0 = scrolled to top, 1 = scrolled to bottom.\n */\n private getScrollProgress(): number {\n const displayHeight = this.getDisplayHeight();\n const maxScroll = displayHeight - this.viewportHeight;\n if (maxScroll <= 0) return 0;\n return Math.min(1, Math.max(0, this.scrollTop / maxScroll));\n }\n\n /**\n * Convert display scroll position to virtual scroll position.\n * Uses proportional mapping when content exceeds safe limits.\n */\n private getVirtualScrollTop(): number {\n if (!this.needsScaling()) {\n return this.scrollTop;\n }\n const virtualHeight = this.getVirtualHeight();\n const maxVirtualScroll = virtualHeight - this.viewportHeight;\n return this.getScrollProgress() * maxVirtualScroll;\n }\n\n /**\n * Get the translateY for a row that keeps values within safe CSS limits.\n * Uses proportional positioning when content exceeds safe limits.\n */\n private getRowTranslateY(rowIndex: number): number {\n const virtualY = rowIndex * this.rowHeight + this.headerHeight;\n\n if (!this.needsScaling()) {\n return virtualY;\n }\n\n // When scaling is needed, we use a formula that:\n // 1. Keeps all translateY values within displayHeight bounds\n // 2. Preserves visual row spacing (no compression)\n // 3. Maps scroll position proportionally\n //\n // Formula: translateY = virtualY + scrollProgress * (displayHeight - virtualHeight)\n // This shifts all positions by an offset that depends on scroll progress.\n const displayHeight = this.getDisplayHeight();\n const virtualHeight = this.getVirtualHeight();\n const scrollProgress = this.getScrollProgress();\n\n const translateY = virtualY + scrollProgress * (displayHeight - virtualHeight);\n\n // Clamp to safe bounds - overscan rows might slightly exceed\n // Negative values are fine (rows above viewport), but cap the maximum\n return Math.min(translateY, displayHeight);\n }\n\n // ===========================================================================\n // Data Fetching\n // ===========================================================================\n\n private async fetchData(): Promise<void> {\n this.emit({ type: \"DATA_LOADING\" });\n\n try {\n const request: DataSourceRequest = {\n pagination: {\n pageIndex: this.currentPageIndex,\n pageSize: this.pageSize,\n },\n sort: this.sortModel.length > 0 ? this.sortModel : undefined,\n filter: Object.keys(this.filterModel).length > 0 ? this.filterModel : undefined,\n };\n\n const response = await this.dataSource.fetch(request);\n\n // Cache the fetched rows\n this.cachedRows.clear();\n response.rows.forEach((row, index) => {\n this.cachedRows.set(this.currentPageIndex * this.pageSize + index, row);\n });\n\n this.totalRows = response.totalRows;\n\n // For client-side data source, fetch all data for simplicity\n // (the client data source handles filtering/sorting internally)\n if (response.totalRows > response.rows.length && this.currentPageIndex === 0) {\n // Fetch all remaining pages for client-side mode\n await this.fetchAllData();\n }\n\n this.emit({ type: \"DATA_LOADED\", totalRows: this.totalRows });\n } catch (error) {\n this.emit({\n type: \"DATA_ERROR\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n private async fetchAllData(): Promise<void> {\n // Fetch all data in chunks for client-side data source\n const totalPages = Math.ceil(this.totalRows / this.pageSize);\n\n for (let page = 1; page < totalPages; page++) {\n const request: DataSourceRequest = {\n pagination: {\n pageIndex: page,\n pageSize: this.pageSize,\n },\n sort: this.sortModel.length > 0 ? this.sortModel : undefined,\n filter: Object.keys(this.filterModel).length > 0 ? this.filterModel : undefined,\n };\n\n const response = await this.dataSource.fetch(request);\n response.rows.forEach((row, index) => {\n this.cachedRows.set(page * this.pageSize + index, row);\n });\n }\n }\n\n // ===========================================================================\n // Sort & Filter\n // ===========================================================================\n\n async setSort(\n colId: string,\n direction: SortDirection | null,\n addToExisting: boolean = false\n ): Promise<void> {\n // console.log(\"[GP-Grid Core] setSort:\", { colId, direction, addToExisting });\n const existingIndex = this.sortModel.findIndex((s) => s.colId === colId);\n\n if (!addToExisting) {\n this.sortModel = direction === null ? [] : [{ colId, direction }];\n } else {\n if (direction === null) {\n if (existingIndex >= 0) {\n this.sortModel.splice(existingIndex, 1);\n }\n } else if (existingIndex >= 0) {\n this.sortModel[existingIndex]!.direction = direction;\n } else {\n this.sortModel.push({ colId, direction });\n }\n }\n\n // console.log(\"[GP-Grid Core] setSort - fetching sorted data...\");\n await this.fetchData();\n // Refresh all slots with newly sorted data\n this.refreshAllSlots();\n this.emitHeaders();\n // console.log(\"[GP-Grid Core] setSort - complete\");\n }\n\n async setFilter(colId: string, value: string): Promise<void> {\n if (value === \"\") {\n delete this.filterModel[colId];\n } else {\n this.filterModel[colId] = value;\n }\n\n await this.fetchData();\n // Force refresh all slots since filtered data changed\n this.refreshAllSlots();\n this.emitContentSize();\n }\n\n /**\n * Force refresh all slot data (used after filtering/sorting when data changes)\n */\n private refreshAllSlots(): void {\n const instructions: GridInstruction[] = [];\n\n for (const [slotId, slot] of this.slotPool.slots) {\n // Check if row index is still valid\n if (slot.rowIndex >= 0 && slot.rowIndex < this.totalRows) {\n const rowData = this.cachedRows.get(slot.rowIndex);\n const translateY = this.getRowTranslateY(slot.rowIndex);\n\n slot.rowData = rowData ?? {};\n slot.translateY = translateY;\n\n instructions.push({\n type: \"ASSIGN_SLOT\",\n slotId,\n rowIndex: slot.rowIndex,\n rowData: rowData ?? {},\n });\n instructions.push({\n type: \"MOVE_SLOT\",\n slotId,\n translateY,\n });\n }\n }\n\n this.emitBatch(instructions);\n\n // Also sync slots to handle any rows that went out of bounds\n this.syncSlots();\n }\n\n getSortModel(): SortModel[] {\n return [...this.sortModel];\n }\n\n getFilterModel(): FilterModel {\n return { ...this.filterModel };\n }\n\n // ===========================================================================\n // Editing\n // ===========================================================================\n\n startEdit(row: number, col: number): void {\n const column = this.columns[col];\n if (!column || column.editable !== true) return;\n\n const initialValue = this.getCellValue(row, col);\n this.editState = {\n row,\n col,\n initialValue,\n currentValue: initialValue,\n };\n\n this.emit({\n type: \"START_EDIT\",\n row,\n col,\n initialValue,\n });\n }\n\n updateEditValue(value: CellValue): void {\n if (this.editState) {\n this.editState.currentValue = value;\n }\n }\n\n commitEdit(): void {\n if (!this.editState) return;\n\n const { row, col, currentValue } = this.editState;\n this.setCellValue(row, col, currentValue);\n\n this.emit({\n type: \"COMMIT_EDIT\",\n row,\n col,\n value: currentValue,\n });\n\n this.editState = null;\n this.emit({ type: \"STOP_EDIT\" });\n\n // Update the slot displaying this row\n const slotId = this.slotPool.rowToSlot.get(row);\n if (slotId) {\n const rowData = this.cachedRows.get(row);\n if (rowData) {\n this.emit({\n type: \"ASSIGN_SLOT\",\n slotId,\n rowIndex: row,\n rowData,\n });\n }\n }\n }\n\n cancelEdit(): void {\n this.editState = null;\n this.emit({ type: \"STOP_EDIT\" });\n }\n\n getEditState(): EditState | null {\n return this.editState ? { ...this.editState } : null;\n }\n\n // ===========================================================================\n // Cell Value Access\n // ===========================================================================\n\n getCellValue(row: number, col: number): CellValue {\n const rowData = this.cachedRows.get(row);\n if (!rowData) return null;\n\n const column = this.columns[col];\n if (!column) return null;\n\n return this.getFieldValue(rowData, column.field);\n }\n\n setCellValue(row: number, col: number, value: CellValue): void {\n const rowData = this.cachedRows.get(row);\n if (!rowData || typeof rowData !== \"object\") return;\n\n const column = this.columns[col];\n if (!column) return;\n\n this.setFieldValue(rowData as Record<string, unknown>, column.field, value);\n }\n\n private getFieldValue(data: TData, field: string): CellValue {\n const parts = field.split(\".\");\n let value: unknown = data;\n\n for (const part of parts) {\n if (value == null || typeof value !== \"object\") {\n return null;\n }\n value = (value as Record<string, unknown>)[part];\n }\n\n return (value ?? null) as CellValue;\n }\n\n private setFieldValue(data: Record<string, unknown>, field: string, value: CellValue): void {\n const parts = field.split(\".\");\n let obj = data;\n\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!;\n if (!(part in obj)) {\n obj[part] = {};\n }\n obj = obj[part] as Record<string, unknown>;\n }\n\n const lastPart = parts[parts.length - 1]!;\n obj[lastPart] = value;\n }\n\n // ===========================================================================\n // Layout Helpers\n // ===========================================================================\n\n private computeColumnPositions(): void {\n this.columnPositions = [0];\n let pos = 0;\n for (const col of this.columns) {\n pos += col.width;\n this.columnPositions.push(pos);\n }\n }\n\n private emitContentSize(): void {\n const width = this.columnPositions[this.columnPositions.length - 1] ?? 0;\n // Use scaled display height to keep CSS values within safe browser limits\n const height = this.getDisplayHeight();\n this.emit({ type: \"SET_CONTENT_SIZE\", width, height });\n }\n\n private emitHeaders(): void {\n const sortInfoMap = new Map<string, { direction: SortDirection; index: number }>();\n this.sortModel.forEach((sort, index) => {\n sortInfoMap.set(sort.colId, { direction: sort.direction, index: index + 1 });\n });\n\n for (let i = 0; i < this.columns.length; i++) {\n const column = this.columns[i]!;\n const colId = column.colId ?? column.field;\n const sortInfo = sortInfoMap.get(colId);\n\n this.emit({\n type: \"UPDATE_HEADER\",\n colIndex: i,\n column,\n sortDirection: sortInfo?.direction,\n sortIndex: sortInfo?.index,\n });\n }\n }\n\n // ===========================================================================\n // Public Accessors\n // ===========================================================================\n\n getColumns(): ColumnDefinition[] {\n return this.columns;\n }\n\n getColumnPositions(): number[] {\n return [...this.columnPositions];\n }\n\n getRowCount(): number {\n return this.totalRows;\n }\n\n getRowHeight(): number {\n return this.rowHeight;\n }\n\n getHeaderHeight(): number {\n return this.headerHeight;\n }\n\n getTotalWidth(): number {\n return this.columnPositions[this.columnPositions.length - 1] ?? 0;\n }\n\n getTotalHeight(): number {\n return this.totalRows * this.rowHeight + this.headerHeight;\n }\n\n getRowData(rowIndex: number): TData | undefined {\n return this.cachedRows.get(rowIndex);\n }\n\n /**\n * Get the display Y position for a row (accounting for scaling).\n * Used by UI adapters for scroll-into-view functionality.\n */\n getDisplayYForRow(rowIndex: number): number {\n return this.getRowTranslateY(rowIndex);\n }\n\n /**\n * Check if scaling is currently active.\n */\n isScalingActive(): boolean {\n return this.needsScaling();\n }\n\n /**\n * Convert a display Y position to a row index.\n * Used by UI adapters for mouse coordinate conversion during drag operations.\n * @param displayY The Y position in display coordinates (relative to content area, after header)\n * @param scrollTop The current scroll position\n */\n getRowIndexAtDisplayY(displayY: number, scrollTop: number): number {\n if (!this.needsScaling()) {\n return Math.floor(displayY / this.rowHeight);\n }\n\n // With scaling, we need to invert the proportional mapping\n // displayY was calculated based on slots positioned at:\n // translateY = virtualY + scrollProgress * (displayHeight - virtualHeight)\n //\n // So to get virtualY from a display position, we invert:\n // virtualY = displayY - scrollProgress * (displayHeight - virtualHeight)\n const displayHeight = this.getDisplayHeight();\n const virtualHeight = this.getVirtualHeight();\n const maxScroll = displayHeight - this.viewportHeight;\n const scrollProgress = maxScroll > 0 ? Math.min(1, Math.max(0, scrollTop / maxScroll)) : 0;\n\n const virtualY = displayY - scrollProgress * (displayHeight - virtualHeight);\n return Math.floor(virtualY / this.rowHeight);\n }\n\n /**\n * Calculate the scroll position needed to make a row visible.\n * For scaling mode: uses proportional mapping (rowIndex/totalRows ≈ scrollTop/maxScroll)\n * Used by UI adapters for scroll-into-view functionality.\n */\n getScrollTopForRow(rowIndex: number): number {\n if (!this.needsScaling()) {\n // Without scaling, simple linear mapping\n return Math.max(0, rowIndex * this.rowHeight);\n }\n\n // With scaling: use proportional mapping\n // rowIndex / totalRows ≈ scrollTop / maxScroll\n const displayHeight = this.getDisplayHeight();\n const maxScroll = Math.max(0, displayHeight - this.viewportHeight);\n const progress = this.totalRows > 0 ? rowIndex / this.totalRows : 0;\n\n return Math.min(maxScroll, Math.max(0, progress * maxScroll));\n }\n\n /**\n * Get the currently visible row range (excluding overscan).\n * Returns { start, end } row indices that are fully visible in the viewport.\n * Used by UI adapters for scroll-into-view functionality.\n */\n getVisibleRowRange(): { start: number; end: number } {\n const virtualScrollTop = this.getVirtualScrollTop();\n // The header takes up space in the viewport, so subtract it from available data area\n const dataAreaHeight = Math.max(0, this.viewportHeight - this.headerHeight);\n\n // First fully visible row\n const start = Math.max(0, Math.ceil(virtualScrollTop / this.rowHeight));\n // Last fully visible row\n const end = Math.min(\n this.totalRows - 1,\n Math.floor((virtualScrollTop + dataAreaHeight) / this.rowHeight) - 1\n );\n return { start: Math.min(start, end), end };\n }\n\n // ===========================================================================\n // Data Updates\n // ===========================================================================\n\n /**\n * Refresh data from the data source.\n */\n async refresh(): Promise<void> {\n await this.fetchData();\n this.syncSlots();\n this.emitContentSize();\n }\n\n /**\n * Refresh slot display without refetching data.\n * Useful after in-place data modifications like fill operations.\n */\n refreshSlotData(): void {\n this.refreshAllSlots();\n }\n\n /**\n * Update the data source and refresh.\n */\n async setDataSource(dataSource: DataSource<TData>): Promise<void> {\n this.dataSource = dataSource;\n await this.refresh();\n }\n\n /**\n * Update columns and recompute layout.\n */\n setColumns(columns: ColumnDefinition[]): void {\n this.columns = columns;\n this.computeColumnPositions();\n this.emitContentSize();\n this.emitHeaders();\n this.syncSlots();\n }\n}\n\n","// gp-grid-core/src/sort-worker.ts\n// Web Worker for sorting large datasets off the main thread\n\nimport type { SortModel, CellValue } from \"./types\";\n\n// =============================================================================\n// Worker Message Types\n// =============================================================================\n\nexport interface SortWorkerRequest {\n type: \"sort\";\n id: number;\n data: unknown[];\n sortModel: SortModel[];\n}\n\nexport interface SortIndicesRequest {\n type: \"sortIndices\";\n id: number;\n values: Float64Array;\n direction: \"asc\" | \"desc\";\n}\n\nexport interface SortMultiColumnRequest {\n type: \"sortMultiColumn\";\n id: number;\n /** Array of column values, each as Float64Array */\n columns: Float64Array[];\n /** Direction for each column: 1 for asc, -1 for desc */\n directions: Int8Array;\n}\n\nexport interface SortWorkerResponse {\n type: \"sorted\";\n id: number;\n data: unknown[];\n}\n\nexport interface SortIndicesResponse {\n type: \"sortedIndices\";\n id: number;\n indices: Uint32Array;\n}\n\nexport interface SortMultiColumnResponse {\n type: \"sortedMultiColumn\";\n id: number;\n indices: Uint32Array;\n}\n\nexport interface SortStringHashesRequest {\n type: \"sortStringHashes\";\n id: number;\n /** Array of hash chunks: [chunk0Values, chunk1Values, chunk2Values] */\n hashChunks: Float64Array[];\n direction: \"asc\" | \"desc\";\n}\n\nexport interface SortStringHashesResponse {\n type: \"sortedStringHashes\";\n id: number;\n indices: Uint32Array;\n /** Pairs of indices that had hash collisions (all chunks equal) */\n collisionPairs: Uint32Array;\n}\n\n// =============================================================================\n// Sorting Functions (duplicated from data-source.ts for worker isolation)\n// =============================================================================\n\nfunction getFieldValue(row: unknown, field: string): CellValue {\n const parts = field.split(\".\");\n let value: unknown = row;\n\n for (const part of parts) {\n if (value == null || typeof value !== \"object\") {\n return null;\n }\n value = (value as Record<string, unknown>)[part];\n }\n\n return (value ?? null) as CellValue;\n}\n\nfunction compareValues(a: CellValue, b: CellValue): number {\n // Null handling\n if (a == null && b == null) return 0;\n if (a == null) return 1;\n if (b == null) return -1;\n\n // Numeric comparison\n const aNum = Number(a);\n const bNum = Number(b);\n if (!isNaN(aNum) && !isNaN(bNum)) {\n return aNum - bNum;\n }\n\n // Date comparison\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() - b.getTime();\n }\n\n // String comparison\n return String(a).localeCompare(String(b));\n}\n\nfunction sortData<T>(data: T[], sortModel: SortModel[]): T[] {\n return [...data].sort((a, b) => {\n for (const { colId, direction } of sortModel) {\n const aVal = getFieldValue(a, colId);\n const bVal = getFieldValue(b, colId);\n const comparison = compareValues(aVal, bVal);\n\n if (comparison !== 0) {\n return direction === \"asc\" ? comparison : -comparison;\n }\n }\n return 0;\n });\n}\n\n// =============================================================================\n// Worker Code String (for inline worker creation)\n// =============================================================================\n\n/**\n * Inline worker code as a string for Blob URL creation.\n * This allows the worker to function without bundler-specific configuration.\n */\nexport const SORT_WORKER_CODE = `\n// Inline sort worker code\nfunction getFieldValue(row, field) {\n const parts = field.split(\".\");\n let value = row;\n\n for (const part of parts) {\n if (value == null || typeof value !== \"object\") {\n return null;\n }\n value = value[part];\n }\n\n return value ?? null;\n}\n\nfunction compareValues(a, b) {\n if (a == null && b == null) return 0;\n if (a == null) return 1;\n if (b == null) return -1;\n\n const aNum = Number(a);\n const bNum = Number(b);\n if (!isNaN(aNum) && !isNaN(bNum)) {\n return aNum - bNum;\n }\n\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() - b.getTime();\n }\n\n return String(a).localeCompare(String(b));\n}\n\nfunction sortData(data, sortModel) {\n return [...data].sort((a, b) => {\n for (const { colId, direction } of sortModel) {\n const aVal = getFieldValue(a, colId);\n const bVal = getFieldValue(b, colId);\n const comparison = compareValues(aVal, bVal);\n\n if (comparison !== 0) {\n return direction === \"asc\" ? comparison : -comparison;\n }\n }\n return 0;\n });\n}\n\n// Index-based sorting - much faster for large datasets\n// Uses Transferable typed arrays for zero-copy transfer\nfunction sortIndices(values, direction) {\n const len = values.length;\n const indices = new Uint32Array(len);\n for (let i = 0; i < len; i++) indices[i] = i;\n\n // Sort indices by values\n const mult = direction === \"asc\" ? 1 : -1;\n indices.sort((a, b) => {\n const va = values[a];\n const vb = values[b];\n if (va < vb) return -1 * mult;\n if (va > vb) return 1 * mult;\n return 0;\n });\n\n return indices;\n}\n\n// Multi-column sorting - compares columns in priority order\nfunction sortMultiColumn(columns, directions) {\n const len = columns[0].length;\n const numCols = columns.length;\n const indices = new Uint32Array(len);\n for (let i = 0; i < len; i++) indices[i] = i;\n\n indices.sort((a, b) => {\n for (let c = 0; c < numCols; c++) {\n const va = columns[c][a];\n const vb = columns[c][b];\n if (va < vb) return -1 * directions[c];\n if (va > vb) return 1 * directions[c];\n // Equal - continue to next column\n }\n return 0;\n });\n\n return indices;\n}\n\n// String hash sorting with collision detection\nfunction sortStringHashes(hashChunks, direction) {\n const len = hashChunks[0].length;\n const numChunks = hashChunks.length;\n const indices = new Uint32Array(len);\n for (let i = 0; i < len; i++) indices[i] = i;\n\n const mult = direction === \"asc\" ? 1 : -1;\n const collisions = []; // Track collision pairs\n\n indices.sort((a, b) => {\n for (let c = 0; c < numChunks; c++) {\n const va = hashChunks[c][a];\n const vb = hashChunks[c][b];\n if (va < vb) return -1 * mult;\n if (va > vb) return 1 * mult;\n }\n // All chunks equal = collision, record for fallback\n collisions.push(a, b);\n return 0; // Stable sort preserves original order\n });\n\n return { indices, collisionPairs: new Uint32Array(collisions) };\n}\n\nself.onmessage = function(e) {\n const { type, id } = e.data;\n\n if (type === \"sort\") {\n try {\n const { data, sortModel } = e.data;\n const sorted = sortData(data, sortModel);\n self.postMessage({ type: \"sorted\", id, data: sorted });\n } catch (error) {\n self.postMessage({ type: \"error\", id, error: String(error) });\n }\n } else if (type === \"sortIndices\") {\n try {\n const { values, direction } = e.data;\n const indices = sortIndices(values, direction);\n // Transfer the indices buffer back (zero-copy)\n self.postMessage({ type: \"sortedIndices\", id, indices }, [indices.buffer]);\n } catch (error) {\n self.postMessage({ type: \"error\", id, error: String(error) });\n }\n } else if (type === \"sortMultiColumn\") {\n try {\n const { columns, directions } = e.data;\n const indices = sortMultiColumn(columns, directions);\n self.postMessage({ type: \"sortedMultiColumn\", id, indices }, [indices.buffer]);\n } catch (error) {\n self.postMessage({ type: \"error\", id, error: String(error) });\n }\n } else if (type === \"sortStringHashes\") {\n try {\n const { hashChunks, direction } = e.data;\n const result = sortStringHashes(hashChunks, direction);\n self.postMessage(\n { type: \"sortedStringHashes\", id, indices: result.indices, collisionPairs: result.collisionPairs },\n [result.indices.buffer, result.collisionPairs.buffer]\n );\n } catch (error) {\n self.postMessage({ type: \"error\", id, error: String(error) });\n }\n }\n};\n`;\n\n// =============================================================================\n// Export for use as module worker (if bundler supports it)\n// =============================================================================\n\n// This handles incoming messages when running as a module worker\ndeclare const self: DedicatedWorkerGlobalScope;\n\nif (typeof self !== \"undefined\" && typeof self.onmessage !== \"undefined\") {\n self.onmessage = (e: MessageEvent<SortWorkerRequest>) => {\n const { type, id, data, sortModel } = e.data;\n\n if (type === \"sort\") {\n try {\n const sorted = sortData(data, sortModel);\n self.postMessage({ type: \"sorted\", id, data: sorted } as SortWorkerResponse);\n } catch (error) {\n self.postMessage({ type: \"error\", id, error: String(error) });\n }\n }\n };\n}\n","// gp-grid-core/src/worker-manager.ts\n// Manages Web Worker lifecycle for sorting operations\n\nimport type { SortDirection } from \"./types\";\nimport { SORT_WORKER_CODE } from \"./sort-worker\";\nimport type {\n SortWorkerRequest,\n SortWorkerResponse,\n SortIndicesRequest,\n SortIndicesResponse,\n SortMultiColumnRequest,\n SortMultiColumnResponse,\n SortStringHashesRequest,\n SortStringHashesResponse,\n} from \"./sort-worker\";\n\n// =============================================================================\n// SortWorkerManager\n// =============================================================================\n\n/**\n * Manages a Web Worker for sorting large datasets off the main thread.\n * Uses an inline worker (Blob URL) for maximum compatibility across bundlers.\n */\nexport class SortWorkerManager {\n private worker: Worker | null = null;\n private workerUrl: string | null = null;\n private pendingRequests: Map<\n number,\n {\n resolve: (data: unknown) => void;\n reject: (error: Error) => void;\n }\n > = new Map();\n private nextRequestId: number = 0;\n private isTerminated: boolean = false;\n\n /**\n * Sort data using a Web Worker.\n * The worker is lazily initialized on first use.\n */\n async sortInWorker<T>(data: T[], sortModel: SortModel[]): Promise<T[]> {\n if (this.isTerminated) {\n throw new Error(\"SortWorkerManager has been terminated\");\n }\n\n // Lazy initialization\n if (!this.worker) {\n this.initializeWorker();\n }\n\n const id = this.nextRequestId++;\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: resolve as (data: unknown) => void,\n reject,\n });\n\n const request: SortWorkerRequest = {\n type: \"sort\",\n id,\n data,\n sortModel,\n };\n\n this.worker!.postMessage(request);\n });\n }\n\n /**\n * Sort indices using a Web Worker with Transferable typed arrays.\n * This is much faster than sortInWorker for large datasets because\n * it avoids the serialization overhead of transferring full objects.\n */\n async sortIndices(values: number[], direction: SortDirection): Promise<Uint32Array> {\n if (this.isTerminated) {\n throw new Error(\"SortWorkerManager has been terminated\");\n }\n\n // Lazy initialization\n if (!this.worker) {\n this.initializeWorker();\n }\n\n const id = this.nextRequestId++;\n\n // Convert to typed array for efficient transfer\n const valuesArray = new Float64Array(values);\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: resolve as (data: unknown) => void,\n reject,\n });\n\n const request: SortIndicesRequest = {\n type: \"sortIndices\",\n id,\n values: valuesArray,\n direction,\n };\n\n // Transfer the values buffer (zero-copy)\n this.worker!.postMessage(request, [valuesArray.buffer]);\n });\n }\n\n /**\n * Sort by multiple columns using a Web Worker with Transferable typed arrays.\n * Each column's values are passed as a Float64Array, enabling fast multi-column sorting.\n * @param columns Array of column values (each as number[])\n * @param directions Array of directions for each column (\"asc\" or \"desc\")\n */\n async sortMultiColumn(\n columns: number[][],\n directions: SortDirection[]\n ): Promise<Uint32Array> {\n if (this.isTerminated) {\n throw new Error(\"SortWorkerManager has been terminated\");\n }\n\n // Lazy initialization\n if (!this.worker) {\n this.initializeWorker();\n }\n\n const id = this.nextRequestId++;\n\n // Convert to typed arrays for efficient transfer\n const columnArrays = columns.map(col => new Float64Array(col));\n const directionArray = new Int8Array(directions.map(d => d === \"asc\" ? 1 : -1));\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: resolve as (data: unknown) => void,\n reject,\n });\n\n const request: SortMultiColumnRequest = {\n type: \"sortMultiColumn\",\n id,\n columns: columnArrays,\n directions: directionArray,\n };\n\n // Transfer all column buffers (zero-copy)\n const transferables = columnArrays.map(arr => arr.buffer);\n transferables.push(directionArray.buffer);\n this.worker!.postMessage(request, transferables);\n });\n }\n\n /**\n * Sort string values using multiple hash chunks with collision detection.\n * Returns sorted indices and handles hash collisions using localeCompare fallback.\n * @param hashChunks Array of hash chunk arrays (one per chunk, each chunk as Float64Array)\n * @param direction Sort direction (\"asc\" or \"desc\")\n * @param originalStrings Original string values for collision fallback\n */\n async sortStringHashes(\n hashChunks: Float64Array[],\n direction: SortDirection,\n originalStrings: string[]\n ): Promise<Uint32Array> {\n if (this.isTerminated) {\n throw new Error(\"SortWorkerManager has been terminated\");\n }\n\n // Lazy initialization\n if (!this.worker) {\n this.initializeWorker();\n }\n\n const id = this.nextRequestId++;\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: (data: unknown) => {\n const response = data as { indices: Uint32Array; collisionPairs: Uint32Array };\n const { indices, collisionPairs } = response;\n\n // Handle collisions using localeCompare on original strings\n if (collisionPairs.length > 0) {\n this.resolveCollisions(indices, collisionPairs, originalStrings, direction);\n }\n\n resolve(indices);\n },\n reject,\n });\n\n const request: SortStringHashesRequest = {\n type: \"sortStringHashes\",\n id,\n hashChunks,\n direction,\n };\n\n // Transfer all hash chunk buffers (zero-copy)\n const transferables = hashChunks.map(arr => arr.buffer);\n this.worker!.postMessage(request, transferables);\n });\n }\n\n /**\n * Resolve hash collisions by re-sorting collision groups using localeCompare.\n */\n private resolveCollisions(\n indices: Uint32Array,\n collisionPairs: Uint32Array,\n originalStrings: string[],\n direction: SortDirection\n ): void {\n // Build collision groups from pairs\n // collisionPairs contains pairs: [a1, b1, a2, b2, ...]\n // We need to find consecutive runs of equal-hash elements in the sorted indices\n\n // Create a set of indices that are involved in collisions\n const collisionIndices = new Set<number>();\n for (let i = 0; i < collisionPairs.length; i++) {\n collisionIndices.add(collisionPairs[i]!);\n }\n\n if (collisionIndices.size === 0) return;\n\n // Find collision groups in the sorted indices array\n const groups: { start: number; end: number }[] = [];\n let groupStart = -1;\n\n for (let i = 0; i < indices.length; i++) {\n const idx = indices[i]!;\n if (collisionIndices.has(idx)) {\n if (groupStart === -1) {\n groupStart = i;\n }\n } else {\n if (groupStart !== -1) {\n groups.push({ start: groupStart, end: i });\n groupStart = -1;\n }\n }\n }\n // Handle group at the end\n if (groupStart !== -1) {\n groups.push({ start: groupStart, end: indices.length });\n }\n\n // Sort each collision group using localeCompare\n const mult = direction === \"asc\" ? 1 : -1;\n for (const group of groups) {\n // Extract the slice of indices for this group\n const slice = Array.from(indices.slice(group.start, group.end));\n\n // Sort by original strings\n slice.sort((a, b) => {\n return mult * originalStrings[a]!.localeCompare(originalStrings[b]!);\n });\n\n // Write back\n for (let i = 0; i < slice.length; i++) {\n indices[group.start + i] = slice[i]!;\n }\n }\n }\n\n /**\n * Initialize the worker using an inline Blob URL.\n * This works without bundler-specific configuration.\n */\n private initializeWorker(): void {\n // Check if Web Workers are available\n if (typeof Worker === \"undefined\") {\n throw new Error(\"Web Workers are not available in this environment\");\n }\n\n // Create Blob URL from inline worker code\n const blob = new Blob([SORT_WORKER_CODE], { type: \"application/javascript\" });\n this.workerUrl = URL.createObjectURL(blob);\n this.worker = new Worker(this.workerUrl);\n\n // Handle messages from worker\n this.worker.onmessage = (e: MessageEvent<SortWorkerResponse | SortIndicesResponse | SortMultiColumnResponse | SortStringHashesResponse | { type: \"error\"; id: number; error: string }>) => {\n const { id } = e.data;\n const pending = this.pendingRequests.get(id);\n\n if (!pending) {\n return;\n }\n\n this.pendingRequests.delete(id);\n\n if (e.data.type === \"sorted\") {\n pending.resolve(e.data.data);\n } else if (e.data.type === \"sortedIndices\") {\n pending.resolve(e.data.indices);\n } else if (e.data.type === \"sortedMultiColumn\") {\n pending.resolve(e.data.indices);\n } else if (e.data.type === \"sortedStringHashes\") {\n pending.resolve({ indices: e.data.indices, collisionPairs: e.data.collisionPairs });\n } else if (e.data.type === \"error\") {\n pending.reject(new Error((e.data as { error: string }).error));\n }\n };\n\n // Handle worker errors\n this.worker.onerror = (e) => {\n // Reject all pending requests\n for (const [id, pending] of this.pendingRequests) {\n pending.reject(new Error(`Worker error: ${e.message}`));\n this.pendingRequests.delete(id);\n }\n };\n }\n\n /**\n * Terminate the worker and clean up resources.\n */\n terminate(): void {\n if (this.worker) {\n this.worker.terminate();\n this.worker = null;\n }\n\n if (this.workerUrl) {\n URL.revokeObjectURL(this.workerUrl);\n this.workerUrl = null;\n }\n\n // Reject any pending requests\n for (const [, pending] of this.pendingRequests) {\n pending.reject(new Error(\"Worker terminated\"));\n }\n this.pendingRequests.clear();\n this.isTerminated = true;\n }\n\n /**\n * Check if the worker is currently available.\n */\n isAvailable(): boolean {\n return !this.isTerminated && typeof Worker !== \"undefined\";\n }\n}\n\n// =============================================================================\n// Singleton Instance (optional usage pattern)\n// =============================================================================\n\nlet sharedWorkerManager: SortWorkerManager | null = null;\n\n/**\n * Get a shared SortWorkerManager instance.\n * Useful when multiple data sources should share the same worker.\n */\nexport function getSharedSortWorker(): SortWorkerManager {\n if (!sharedWorkerManager) {\n sharedWorkerManager = new SortWorkerManager();\n }\n return sharedWorkerManager;\n}\n\n/**\n * Terminate the shared worker and release resources.\n */\nexport function terminateSharedSortWorker(): void {\n if (sharedWorkerManager) {\n sharedWorkerManager.terminate();\n sharedWorkerManager = null;\n }\n}\n","// gp-grid-core/src/data-source.ts\n\nimport type {\n DataSource,\n DataSourceRequest,\n DataSourceResponse,\n Row,\n SortModel,\n FilterModel,\n CellValue,\n} from \"./types\";\nimport { SortWorkerManager } from \"./worker-manager\";\n\n// =============================================================================\n// Configuration\n// =============================================================================\n\n/** Threshold for using Web Worker (rows). Below this, sync sort is used. */\nconst WORKER_THRESHOLD = 200000;\n\n/** Number of 10-character chunks for string hashing (30 chars total) */\nconst HASH_CHUNK_COUNT = 3;\n\n// =============================================================================\n// Client Data Source (In-Memory)\n// =============================================================================\n\n/**\n * Creates a client-side data source that holds all data in memory.\n * Sorting and filtering are performed client-side.\n * For large datasets (10k+ rows), sorting is automatically offloaded to a Web Worker.\n */\nexport function createClientDataSource<TData extends Row = Row>(\n data: TData[],\n options: {\n /** Custom field accessor for nested properties */\n getFieldValue?: (row: TData, field: string) => CellValue;\n /** Use Web Worker for sorting large datasets (default: true) */\n useWorker?: boolean;\n } = {}\n): DataSource<TData> {\n const { getFieldValue = defaultGetFieldValue, useWorker = true } = options;\n\n // Create worker manager only if useWorker is enabled\n const workerManager = useWorker ? new SortWorkerManager() : null;\n\n return {\n async fetch(request: DataSourceRequest): Promise<DataSourceResponse<TData>> {\n let processedData = [...data];\n\n // Apply filters (always sync - filtering is fast)\n if (request.filter && Object.keys(request.filter).length > 0) {\n processedData = applyFilters(processedData, request.filter, getFieldValue);\n }\n\n // Apply sorting (async with worker for large datasets)\n if (request.sort && request.sort.length > 0) {\n // Use worker-based index sorting for large datasets (all column types)\n const canUseWorkerSort = workerManager &&\n workerManager.isAvailable() &&\n processedData.length >= WORKER_THRESHOLD;\n\n if (canUseWorkerSort) {\n let sortedIndices: Uint32Array;\n\n // For single-column string sorting, use multi-hash approach with collision fallback\n if (request.sort.length === 1) {\n const { colId, direction } = request.sort[0]!;\n\n // Detect column type by sampling first non-null value\n let isStringColumn = false;\n for (const row of processedData) {\n const val = getFieldValue(row, colId);\n if (val != null) {\n isStringColumn = typeof val === \"string\";\n break;\n }\n }\n\n if (isStringColumn) {\n // Use multi-hash sorting for strings\n const originalStrings: string[] = [];\n const hashChunks: number[][] = Array.from({ length: HASH_CHUNK_COUNT }, () => []);\n\n for (const row of processedData) {\n const val = getFieldValue(row, colId);\n const str = val == null ? \"\" : String(val);\n originalStrings.push(str);\n const hashes = stringToSortableHashes(str);\n for (let c = 0; c < HASH_CHUNK_COUNT; c++) {\n hashChunks[c]!.push(hashes[c]!);\n }\n }\n\n // Convert to Float64Arrays for transfer to worker\n const hashChunkArrays = hashChunks.map(chunk => new Float64Array(chunk));\n\n sortedIndices = await workerManager.sortStringHashes(\n hashChunkArrays,\n direction,\n originalStrings\n );\n } else {\n // Use single-value sorting for numeric columns\n const values = processedData.map(row => {\n const val = getFieldValue(row, colId);\n return toSortableNumber(val);\n });\n sortedIndices = await workerManager.sortIndices(values, direction);\n }\n } else {\n // Multi-column sorting: use single hash per value (existing approach)\n const columnValues: number[][] = [];\n const directions: Array<\"asc\" | \"desc\"> = [];\n\n for (const { colId, direction } of request.sort) {\n const values = processedData.map(row => {\n const val = getFieldValue(row, colId);\n return toSortableNumber(val);\n });\n columnValues.push(values);\n directions.push(direction);\n }\n\n sortedIndices = await workerManager.sortMultiColumn(columnValues, directions);\n }\n\n // Reorder data using sorted indices\n const reordered = new Array<TData>(processedData.length);\n for (let i = 0; i < sortedIndices.length; i++) {\n reordered[i] = processedData[sortedIndices[i]!]!;\n }\n processedData = reordered;\n } else {\n // Use sync sorting for small datasets or when worker is unavailable\n processedData = applySort(processedData, request.sort, getFieldValue);\n }\n }\n\n const totalRows = processedData.length;\n\n // Apply pagination\n const { pageIndex, pageSize } = request.pagination;\n const startIndex = pageIndex * pageSize;\n const rows = processedData.slice(startIndex, startIndex + pageSize);\n\n return { rows, totalRows };\n },\n };\n}\n\n// =============================================================================\n// Server Data Source\n// =============================================================================\n\nexport type ServerFetchFunction<TData> = (\n request: DataSourceRequest\n) => Promise<DataSourceResponse<TData>>;\n\n/**\n * Creates a server-side data source that delegates all operations to the server.\n * The fetch function receives sort/filter/pagination params to pass to the API.\n */\nexport function createServerDataSource<TData extends Row = Row>(\n fetchFn: ServerFetchFunction<TData>\n): DataSource<TData> {\n return {\n async fetch(request: DataSourceRequest): Promise<DataSourceResponse<TData>> {\n return fetchFn(request);\n },\n };\n}\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Convert any cell value to a sortable number.\n * Strings are converted using a lexicographic hash of the first 8 characters.\n * This preserves sort order for strings that differ within the first 8 chars.\n */\nfunction toSortableNumber(val: CellValue): number {\n if (val == null) return Number.MAX_VALUE; // nulls sort last\n\n // Numbers pass through directly\n if (typeof val === \"number\") return val;\n\n // Dates convert to timestamp\n if (val instanceof Date) return val.getTime();\n\n // Strings: convert to lexicographic hash\n if (typeof val === \"string\") {\n return stringToSortableNumber(val);\n }\n\n // Fallback: try to convert to number\n const num = Number(val);\n return isNaN(num) ? 0 : num;\n}\n\n/**\n * Convert a string to a sortable number using first 10 characters.\n * Uses base 36 (alphanumeric) to fit more characters within float64 safe precision.\n * (36^10 ≈ 3.6×10¹⁵, within MAX_SAFE_INTEGER ~9×10¹⁵)\n * This allows sorting strings that share long prefixes (e.g., \"Person Giuseppe\" vs \"Person Giovanni\").\n */\nfunction stringToSortableNumber(str: string): number {\n const s = str.toLowerCase();\n const len = Math.min(s.length, 10);\n let hash = 0;\n\n // Pack characters into a number using base 36 encoding\n // Maps a-z to 0-25, 0-9 to 26-35, space/other to 0\n for (let i = 0; i < len; i++) {\n const code = s.charCodeAt(i);\n let mapped: number;\n if (code >= 97 && code <= 122) {\n // a-z -> 0-25\n mapped = code - 97;\n } else if (code >= 48 && code <= 57) {\n // 0-9 -> 26-35\n mapped = code - 48 + 26;\n } else {\n // space and other chars -> 0 (sorts first)\n mapped = 0;\n }\n hash = hash * 36 + mapped;\n }\n\n // Pad shorter strings to ensure \"a\" < \"ab\"\n for (let i = len; i < 10; i++) {\n hash = hash * 36;\n }\n\n return hash;\n}\n\n/**\n * Convert a string to multiple sortable hash values (one per 10-char chunk).\n * This allows correct sorting of strings longer than 10 characters.\n * Returns HASH_CHUNK_COUNT hashes, each covering 10 characters.\n */\nfunction stringToSortableHashes(str: string): number[] {\n const s = str.toLowerCase();\n const hashes: number[] = [];\n\n for (let chunk = 0; chunk < HASH_CHUNK_COUNT; chunk++) {\n const start = chunk * 10;\n let hash = 0;\n\n for (let i = 0; i < 10; i++) {\n const charIndex = start + i;\n const code = charIndex < s.length ? s.charCodeAt(charIndex) : 0;\n let mapped: number;\n if (code >= 97 && code <= 122) {\n // a-z -> 0-25\n mapped = code - 97;\n } else if (code >= 48 && code <= 57) {\n // 0-9 -> 26-35\n mapped = code - 48 + 26;\n } else {\n // space and other chars -> 0 (sorts first)\n mapped = 0;\n }\n hash = hash * 36 + mapped;\n }\n hashes.push(hash);\n }\n\n return hashes;\n}\n\nfunction defaultGetFieldValue<TData>(row: TData, field: string): CellValue {\n const parts = field.split(\".\");\n let value: unknown = row;\n\n for (const part of parts) {\n if (value == null || typeof value !== \"object\") {\n return null;\n }\n value = (value as Record<string, unknown>)[part];\n }\n\n return (value ?? null) as CellValue;\n}\n\nfunction applyFilters<TData>(\n data: TData[],\n filterModel: FilterModel,\n getFieldValue: (row: TData, field: string) => CellValue\n): TData[] {\n const filterEntries = Object.entries(filterModel).filter(([, value]) => value !== \"\");\n\n if (filterEntries.length === 0) {\n return data;\n }\n\n return data.filter((row) => {\n for (const [field, filterValue] of filterEntries) {\n const cellValue = getFieldValue(row, field);\n const cellStr = String(cellValue ?? \"\").toLowerCase();\n const filterStr = filterValue.toLowerCase();\n\n if (!cellStr.includes(filterStr)) {\n return false;\n }\n }\n return true;\n });\n}\n\nfunction applySort<TData>(\n data: TData[],\n sortModel: SortModel[],\n getFieldValue: (row: TData, field: string) => CellValue\n): TData[] {\n return [...data].sort((a, b) => {\n for (const { colId, direction } of sortModel) {\n const aVal = getFieldValue(a, colId);\n const bVal = getFieldValue(b, colId);\n const comparison = compareValues(aVal, bVal);\n\n if (comparison !== 0) {\n return direction === \"asc\" ? comparison : -comparison;\n }\n }\n return 0;\n });\n}\n\nfunction compareValues(a: CellValue, b: CellValue): number {\n // Null handling\n if (a == null && b == null) return 0;\n if (a == null) return 1;\n if (b == null) return -1;\n\n // Numeric comparison\n const aNum = Number(a);\n const bNum = Number(b);\n if (!isNaN(aNum) && !isNaN(bNum)) {\n return aNum - bNum;\n }\n\n // Date comparison\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() - b.getTime();\n }\n\n // String comparison\n return String(a).localeCompare(String(b));\n}\n\n// =============================================================================\n// Utility: Create Data Source from Array (Legacy Support)\n// =============================================================================\n\n/**\n * Convenience function to create a data source from an array.\n * This provides backwards compatibility with the old `rowData` prop.\n */\nexport function createDataSourceFromArray<TData extends Row = Row>(\n data: TData[]\n): DataSource<TData> {\n return createClientDataSource(data);\n}\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["data: CellValue[][]","row: CellValue[]","result: Array<{ row: number; col: number; value: CellValue }>","values: CellValue[]","diffs: number[]","instructions: GridInstruction[]","slotsToRecycle: string[]","newSlot: SlotState","request: DataSourceRequest","value: unknown","value: unknown","compareValues","request: SortWorkerRequest","request: SortIndicesRequest","request: SortMultiColumnRequest","request: SortStringHashesRequest","groups: { start: number; end: number }[]","sharedWorkerManager: SortWorkerManager | null","getFieldValue","sortedIndices: Uint32Array","originalStrings: string[]","hashChunks: number[][]","columnValues: number[][]","directions: Array<\"asc\" | \"desc\">","mapped: number","hashes: number[]","value: unknown"],"sources":["../src/selection.ts","../src/fill.ts","../src/grid-core.ts","../src/sort-worker.ts","../src/worker-manager.ts","../src/data-source.ts"],"sourcesContent":["// gp-grid-core/src/selection.ts\n\nimport type {\n CellPosition,\n CellRange,\n SelectionState,\n GridInstruction,\n InstructionListener,\n CellValue,\n ColumnDefinition,\n Row,\n} from \"./types\";\n\nexport type Direction = \"up\" | \"down\" | \"left\" | \"right\";\n\nexport interface SelectionManagerOptions {\n getRowCount: () => number;\n getColumnCount: () => number;\n getCellValue: (row: number, col: number) => CellValue;\n getRowData: (row: number) => Row | undefined;\n getColumn: (col: number) => ColumnDefinition | undefined;\n}\n\n/**\n * Manages Excel-style cell selection, keyboard navigation, and clipboard operations.\n */\nexport class SelectionManager {\n private state: SelectionState = {\n activeCell: null,\n range: null,\n anchor: null,\n selectionMode: false,\n };\n\n private options: SelectionManagerOptions;\n private listeners: InstructionListener[] = [];\n\n constructor(options: SelectionManagerOptions) {\n this.options = options;\n }\n\n // ===========================================================================\n // Instruction Emission\n // ===========================================================================\n\n onInstruction(listener: InstructionListener): () => void {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n private emit(instruction: GridInstruction): void {\n for (const listener of this.listeners) {\n listener(instruction);\n }\n }\n\n // ===========================================================================\n // State Accessors\n // ===========================================================================\n\n getState(): SelectionState {\n return { ...this.state };\n }\n\n getActiveCell(): CellPosition | null {\n return this.state.activeCell;\n }\n\n getSelectionRange(): CellRange | null {\n return this.state.range;\n }\n\n isSelected(row: number, col: number): boolean {\n const { range } = this.state;\n if (!range) return false;\n\n const minRow = Math.min(range.startRow, range.endRow);\n const maxRow = Math.max(range.startRow, range.endRow);\n const minCol = Math.min(range.startCol, range.endCol);\n const maxCol = Math.max(range.startCol, range.endCol);\n\n return row >= minRow && row <= maxRow && col >= minCol && col <= maxCol;\n }\n\n isActiveCell(row: number, col: number): boolean {\n const { activeCell } = this.state;\n return activeCell?.row === row && activeCell?.col === col;\n }\n\n // ===========================================================================\n // Selection Operations\n // ===========================================================================\n\n /**\n * Start a selection at the given cell.\n * @param cell - The cell to select\n * @param opts.shift - Extend selection from anchor (range select)\n * @param opts.ctrl - Toggle selection mode\n */\n startSelection(\n cell: CellPosition,\n opts: { shift?: boolean; ctrl?: boolean } = {}\n ): void {\n // console.log(\"[GP-Grid Selection] startSelection:\", { cell, opts, listenerCount: this.listeners.length });\n const { shift = false, ctrl = false } = opts;\n const { row, col } = this.clampPosition(cell);\n\n if (shift && this.state.anchor) {\n // Extend selection from anchor to current cell\n this.state.range = {\n startRow: this.state.anchor.row,\n startCol: this.state.anchor.col,\n endRow: row,\n endCol: col,\n };\n this.state.activeCell = { row, col };\n } else {\n // Start new selection\n this.state.activeCell = { row, col };\n this.state.anchor = { row, col };\n this.state.range = null;\n }\n\n this.state.selectionMode = ctrl;\n\n // console.log(\"[GP-Grid Selection] Emitting SET_ACTIVE_CELL:\", this.state.activeCell);\n this.emit({ type: \"SET_ACTIVE_CELL\", position: this.state.activeCell });\n // console.log(\"[GP-Grid Selection] Emitting SET_SELECTION_RANGE:\", this.state.range);\n this.emit({ type: \"SET_SELECTION_RANGE\", range: this.state.range });\n }\n\n /**\n * Move focus in a direction, optionally extending the selection.\n */\n moveFocus(direction: Direction, extend: boolean = false): void {\n if (!this.state.activeCell) {\n // No active cell, select first cell\n this.startSelection({ row: 0, col: 0 });\n return;\n }\n\n const { row, col } = this.state.activeCell;\n let newRow = row;\n let newCol = col;\n\n switch (direction) {\n case \"up\":\n newRow = Math.max(0, row - 1);\n break;\n case \"down\":\n newRow = Math.min(this.options.getRowCount() - 1, row + 1);\n break;\n case \"left\":\n newCol = Math.max(0, col - 1);\n break;\n case \"right\":\n newCol = Math.min(this.options.getColumnCount() - 1, col + 1);\n break;\n }\n\n if (extend) {\n // Extend selection (Shift+Arrow)\n if (!this.state.anchor) {\n this.state.anchor = { row, col };\n }\n\n this.state.range = {\n startRow: this.state.anchor.row,\n startCol: this.state.anchor.col,\n endRow: newRow,\n endCol: newCol,\n };\n this.state.activeCell = { row: newRow, col: newCol };\n\n this.emit({ type: \"SET_ACTIVE_CELL\", position: this.state.activeCell });\n this.emit({ type: \"SET_SELECTION_RANGE\", range: this.state.range });\n } else {\n // Move without extending\n this.state.activeCell = { row: newRow, col: newCol };\n this.state.anchor = { row: newRow, col: newCol };\n this.state.range = null;\n\n this.emit({ type: \"SET_ACTIVE_CELL\", position: this.state.activeCell });\n this.emit({ type: \"SET_SELECTION_RANGE\", range: null });\n }\n }\n\n /**\n * Select all cells in the grid (Ctrl+A).\n */\n selectAll(): void {\n const rowCount = this.options.getRowCount();\n const colCount = this.options.getColumnCount();\n\n if (rowCount === 0 || colCount === 0) return;\n\n this.state.range = {\n startRow: 0,\n startCol: 0,\n endRow: rowCount - 1,\n endCol: colCount - 1,\n };\n\n // Keep active cell if exists, otherwise set to first cell\n if (!this.state.activeCell) {\n this.state.activeCell = { row: 0, col: 0 };\n this.emit({ type: \"SET_ACTIVE_CELL\", position: this.state.activeCell });\n }\n\n this.emit({ type: \"SET_SELECTION_RANGE\", range: this.state.range });\n }\n\n /**\n * Clear the current selection.\n */\n clearSelection(): void {\n this.state.activeCell = null;\n this.state.range = null;\n this.state.anchor = null;\n this.state.selectionMode = false;\n\n this.emit({ type: \"SET_ACTIVE_CELL\", position: null });\n this.emit({ type: \"SET_SELECTION_RANGE\", range: null });\n }\n\n /**\n * Set the active cell directly.\n */\n setActiveCell(row: number, col: number): void {\n const clamped = this.clampPosition({ row, col });\n this.state.activeCell = clamped;\n this.state.anchor = clamped;\n this.state.range = null;\n\n this.emit({ type: \"SET_ACTIVE_CELL\", position: this.state.activeCell });\n this.emit({ type: \"SET_SELECTION_RANGE\", range: null });\n }\n\n /**\n * Set the selection range directly.\n */\n setSelectionRange(range: CellRange): void {\n this.state.range = range;\n this.emit({ type: \"SET_SELECTION_RANGE\", range: this.state.range });\n }\n\n // ===========================================================================\n // Data Extraction\n // ===========================================================================\n\n /**\n * Get the data from the currently selected cells as a 2D array.\n */\n getSelectedData(): CellValue[][] {\n const { range, activeCell } = this.state;\n\n if (!range && !activeCell) {\n return [];\n }\n\n const effectiveRange = range || {\n startRow: activeCell!.row,\n startCol: activeCell!.col,\n endRow: activeCell!.row,\n endCol: activeCell!.col,\n };\n\n const minRow = Math.min(effectiveRange.startRow, effectiveRange.endRow);\n const maxRow = Math.max(effectiveRange.startRow, effectiveRange.endRow);\n const minCol = Math.min(effectiveRange.startCol, effectiveRange.endCol);\n const maxCol = Math.max(effectiveRange.startCol, effectiveRange.endCol);\n\n const data: CellValue[][] = [];\n\n for (let r = minRow; r <= maxRow; r++) {\n const row: CellValue[] = [];\n for (let c = minCol; c <= maxCol; c++) {\n row.push(this.options.getCellValue(r, c));\n }\n data.push(row);\n }\n\n return data;\n }\n\n /**\n * Copy the selected data to the clipboard (Ctrl+C).\n */\n async copySelectionToClipboard(): Promise<void> {\n const data = this.getSelectedData();\n if (data.length === 0) return;\n\n // Convert to tab-separated values (Excel-compatible)\n const tsv = data\n .map((row) =>\n row.map((cell) => (cell == null ? \"\" : String(cell))).join(\"\\t\")\n )\n .join(\"\\n\");\n\n try {\n await navigator.clipboard.writeText(tsv);\n } catch (err) {\n // Fallback for older browsers\n const textarea = document.createElement(\"textarea\");\n textarea.value = tsv;\n textarea.style.position = \"fixed\";\n textarea.style.left = \"-9999px\";\n document.body.appendChild(textarea);\n textarea.select();\n document.execCommand(\"copy\");\n document.body.removeChild(textarea);\n }\n }\n\n // ===========================================================================\n // Helpers\n // ===========================================================================\n\n private clampPosition(pos: CellPosition): CellPosition {\n const rowCount = this.options.getRowCount();\n const colCount = this.options.getColumnCount();\n\n return {\n row: Math.max(0, Math.min(pos.row, rowCount - 1)),\n col: Math.max(0, Math.min(pos.col, colCount - 1)),\n };\n }\n}\n\n","// gp-grid-core/src/fill.ts\n\nimport type {\n CellRange,\n CellValue,\n FillHandleState,\n GridInstruction,\n InstructionListener,\n ColumnDefinition,\n} from \"./types\";\n\nexport interface FillManagerOptions {\n getRowCount: () => number;\n getColumnCount: () => number;\n getCellValue: (row: number, col: number) => CellValue;\n getColumn: (col: number) => ColumnDefinition | undefined;\n setCellValue: (row: number, col: number, value: CellValue) => void;\n}\n\n/**\n * Manages fill handle operations including pattern detection and auto-fill.\n */\nexport class FillManager {\n private state: FillHandleState | null = null;\n private options: FillManagerOptions;\n private listeners: InstructionListener[] = [];\n\n constructor(options: FillManagerOptions) {\n this.options = options;\n }\n\n // ===========================================================================\n // Instruction Emission\n // ===========================================================================\n\n onInstruction(listener: InstructionListener): () => void {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n private emit(instruction: GridInstruction): void {\n for (const listener of this.listeners) {\n listener(instruction);\n }\n }\n\n // ===========================================================================\n // State Accessors\n // ===========================================================================\n\n getState(): FillHandleState | null {\n return this.state ? { ...this.state } : null;\n }\n\n isActive(): boolean {\n return this.state !== null;\n }\n\n // ===========================================================================\n // Fill Handle Operations\n // ===========================================================================\n\n /**\n * Start a fill drag operation from a source range.\n */\n startFillDrag(sourceRange: CellRange): void {\n this.state = {\n sourceRange,\n targetRow: sourceRange.endRow,\n targetCol: sourceRange.endCol,\n };\n\n this.emit({ type: \"START_FILL\", sourceRange });\n }\n\n /**\n * Update the fill drag target position.\n */\n updateFillDrag(targetRow: number, targetCol: number): void {\n if (!this.state) return;\n\n // Clamp to valid bounds\n const rowCount = this.options.getRowCount();\n const colCount = this.options.getColumnCount();\n\n targetRow = Math.max(0, Math.min(targetRow, rowCount - 1));\n targetCol = Math.max(0, Math.min(targetCol, colCount - 1));\n\n this.state.targetRow = targetRow;\n this.state.targetCol = targetCol;\n\n this.emit({ type: \"UPDATE_FILL\", targetRow, targetCol });\n }\n\n /**\n * Commit the fill operation - apply pattern to target cells.\n */\n commitFillDrag(): void {\n if (!this.state) return;\n\n const { sourceRange, targetRow, targetCol } = this.state;\n const filledCells = this.calculateFilledCells(sourceRange, targetRow, targetCol);\n\n // Apply values\n for (const { row, col, value } of filledCells) {\n this.options.setCellValue(row, col, value);\n }\n\n this.emit({ type: \"COMMIT_FILL\", filledCells });\n\n this.state = null;\n }\n\n /**\n * Cancel the fill operation.\n */\n cancelFillDrag(): void {\n if (!this.state) return;\n\n this.state = null;\n this.emit({ type: \"CANCEL_FILL\" });\n }\n\n // ===========================================================================\n // Pattern Detection & Fill Logic\n // ===========================================================================\n\n /**\n * Calculate the values to fill based on source pattern.\n */\n private calculateFilledCells(\n sourceRange: CellRange,\n targetRow: number,\n targetCol: number\n ): Array<{ row: number; col: number; value: CellValue }> {\n const result: Array<{ row: number; col: number; value: CellValue }> = [];\n\n const srcMinRow = Math.min(sourceRange.startRow, sourceRange.endRow);\n const srcMaxRow = Math.max(sourceRange.startRow, sourceRange.endRow);\n const srcMinCol = Math.min(sourceRange.startCol, sourceRange.endCol);\n const srcMaxCol = Math.max(sourceRange.startCol, sourceRange.endCol);\n\n // Determine fill direction\n const fillDown = targetRow > srcMaxRow;\n const fillUp = targetRow < srcMinRow;\n const fillRight = targetCol > srcMaxCol;\n const fillLeft = targetCol < srcMinCol;\n\n // For now, we only support vertical fills (most common use case)\n if (fillDown || fillUp) {\n for (let col = srcMinCol; col <= srcMaxCol; col++) {\n const sourceValues = this.getSourceColumnValues(srcMinRow, srcMaxRow, col);\n const pattern = this.detectPattern(sourceValues);\n\n if (fillDown) {\n for (let row = srcMaxRow + 1; row <= targetRow; row++) {\n const fillIndex = row - srcMaxRow - 1;\n const value = this.applyPattern(pattern, sourceValues, fillIndex);\n result.push({ row, col, value });\n }\n } else if (fillUp) {\n for (let row = srcMinRow - 1; row >= targetRow; row--) {\n const fillIndex = srcMinRow - row - 1;\n const value = this.applyPattern(pattern, sourceValues, fillIndex, true);\n result.push({ row, col, value });\n }\n }\n }\n }\n\n // Horizontal fill\n if (fillRight || fillLeft) {\n for (let row = srcMinRow; row <= srcMaxRow; row++) {\n const sourceValues = this.getSourceRowValues(srcMinCol, srcMaxCol, row);\n const pattern = this.detectPattern(sourceValues);\n\n if (fillRight) {\n for (let col = srcMaxCol + 1; col <= targetCol; col++) {\n const fillIndex = col - srcMaxCol - 1;\n const value = this.applyPattern(pattern, sourceValues, fillIndex);\n result.push({ row, col, value });\n }\n } else if (fillLeft) {\n for (let col = srcMinCol - 1; col >= targetCol; col--) {\n const fillIndex = srcMinCol - col - 1;\n const value = this.applyPattern(pattern, sourceValues, fillIndex, true);\n result.push({ row, col, value });\n }\n }\n }\n }\n\n return result;\n }\n\n private getSourceColumnValues(minRow: number, maxRow: number, col: number): CellValue[] {\n const values: CellValue[] = [];\n for (let row = minRow; row <= maxRow; row++) {\n values.push(this.options.getCellValue(row, col));\n }\n return values;\n }\n\n private getSourceRowValues(minCol: number, maxCol: number, row: number): CellValue[] {\n const values: CellValue[] = [];\n for (let col = minCol; col <= maxCol; col++) {\n values.push(this.options.getCellValue(row, col));\n }\n return values;\n }\n\n // ===========================================================================\n // Pattern Types\n // ===========================================================================\n\n private detectPattern(values: CellValue[]): FillPattern {\n if (values.length === 0) {\n return { type: \"constant\", value: null };\n }\n\n if (values.length === 1) {\n return { type: \"constant\", value: values[0] ?? null };\n }\n\n // Check for numeric sequence\n const numbers = values.map((v) => (typeof v === \"number\" ? v : Number(v)));\n if (numbers.every((n) => !isNaN(n))) {\n // Check for arithmetic sequence\n const diffs: number[] = [];\n for (let i = 1; i < numbers.length; i++) {\n diffs.push(numbers[i]! - numbers[i - 1]!);\n }\n\n const allSameDiff = diffs.every((d) => d === diffs[0]);\n if (allSameDiff && diffs[0] !== undefined) {\n return { type: \"arithmetic\", start: numbers[0]!, step: diffs[0] };\n }\n }\n\n // Check for repeating pattern\n return { type: \"repeat\", values };\n }\n\n private applyPattern(\n pattern: FillPattern,\n sourceValues: CellValue[],\n fillIndex: number,\n reverse: boolean = false\n ): CellValue {\n switch (pattern.type) {\n case \"constant\":\n return pattern.value;\n\n case \"arithmetic\": {\n const multiplier = reverse ? -(fillIndex + 1) : fillIndex + 1;\n const lastValue = reverse ? pattern.start : pattern.start + pattern.step * (sourceValues.length - 1);\n return lastValue + pattern.step * multiplier;\n }\n\n case \"repeat\": {\n const len = pattern.values.length;\n if (len === 0) return null;\n if (reverse) {\n // For reverse, cycle backwards\n const idx = (len - 1 - (fillIndex % len) + len) % len;\n return pattern.values[idx] ?? null;\n }\n return pattern.values[fillIndex % len] ?? null;\n }\n }\n }\n}\n\n// ===========================================================================\n// Pattern Types\n// ===========================================================================\n\ntype FillPattern =\n | { type: \"constant\"; value: CellValue }\n | { type: \"arithmetic\"; start: number; step: number }\n | { type: \"repeat\"; values: CellValue[] };\n\n","// gp-grid-core/src/grid-core.ts\n\nimport type {\n GridCoreOptions,\n GridInstruction,\n InstructionListener,\n BatchInstructionListener,\n ColumnDefinition,\n CellValue,\n DataSource,\n DataSourceRequest,\n Row,\n SortModel,\n SortDirection,\n FilterModel,\n SlotState,\n EditState,\n} from \"./types\";\nimport { SelectionManager } from \"./selection\";\nimport { FillManager } from \"./fill\";\n\n// =============================================================================\n// Slot Pool Manager\n// =============================================================================\n\ninterface SlotPoolState {\n slots: Map<string, SlotState>;\n /** Maps rowIndex to slotId for quick lookup */\n rowToSlot: Map<number, string>;\n nextSlotId: number;\n}\n\n// =============================================================================\n// GridCore\n// =============================================================================\n\nexport class GridCore<TData extends Row = Row> {\n // Maximum safe CSS height to avoid browser rendering issues with extreme values\n // Using 1M as a safer limit (some browsers have issues even at 10M)\n private static readonly MAX_SAFE_HEIGHT = 1_000_000; // 1M pixels\n\n // Configuration\n private columns: ColumnDefinition[];\n private dataSource: DataSource<TData>;\n private rowHeight: number;\n private headerHeight: number;\n private overscan: number;\n\n // Viewport state\n private scrollTop: number = 0;\n private scrollLeft: number = 0;\n private viewportWidth: number = 800;\n private viewportHeight: number = 600;\n\n // Data state\n private cachedRows: Map<number, TData> = new Map();\n private totalRows: number = 0;\n private currentPageIndex: number = 0;\n // Use large page size to avoid excessive pagination for client-side data sources\n private pageSize: number = 1000000;\n\n // Sort & Filter\n private sortModel: SortModel[] = [];\n private filterModel: FilterModel = {};\n\n // Slot pool\n private slotPool: SlotPoolState = {\n slots: new Map(),\n rowToSlot: new Map(),\n nextSlotId: 0,\n };\n\n // Managers\n public readonly selection: SelectionManager;\n public readonly fill: FillManager;\n\n // Edit state\n private editState: EditState | null = null;\n\n // Column positions (computed)\n private columnPositions: number[] = [];\n\n // Instruction listeners\n private listeners: InstructionListener[] = [];\n private batchListeners: BatchInstructionListener[] = [];\n\n constructor(options: GridCoreOptions<TData>) {\n this.columns = options.columns;\n this.dataSource = options.dataSource;\n this.rowHeight = options.rowHeight;\n this.headerHeight = options.headerHeight ?? options.rowHeight;\n this.overscan = options.overscan ?? 3;\n\n this.computeColumnPositions();\n\n // Initialize selection manager\n this.selection = new SelectionManager({\n getRowCount: () => this.totalRows,\n getColumnCount: () => this.columns.length,\n getCellValue: (row, col) => this.getCellValue(row, col),\n getRowData: (row) => this.cachedRows.get(row),\n getColumn: (col) => this.columns[col],\n });\n\n // Forward selection instructions\n this.selection.onInstruction((instruction) => this.emit(instruction));\n\n // Initialize fill manager\n this.fill = new FillManager({\n getRowCount: () => this.totalRows,\n getColumnCount: () => this.columns.length,\n getCellValue: (row, col) => this.getCellValue(row, col),\n getColumn: (col) => this.columns[col],\n setCellValue: (row, col, value) => this.setCellValue(row, col, value),\n });\n\n // Forward fill instructions\n this.fill.onInstruction((instruction) => this.emit(instruction));\n }\n\n // ===========================================================================\n // Instruction System\n // ===========================================================================\n\n onInstruction(listener: InstructionListener): () => void {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n /**\n * Subscribe to batched instructions for efficient React state updates.\n * Batch listeners receive arrays of instructions instead of individual ones.\n */\n onBatchInstruction(listener: BatchInstructionListener): () => void {\n this.batchListeners.push(listener);\n return () => {\n this.batchListeners = this.batchListeners.filter((l) => l !== listener);\n };\n }\n\n private emit(instruction: GridInstruction): void {\n // console.log(\"[GP-Grid Core] emit:\", instruction.type, { \n // listenerCount: this.listeners.length, \n // batchListenerCount: this.batchListeners.length \n // });\n // Emit to individual listeners\n for (const listener of this.listeners) {\n listener(instruction);\n }\n // Also emit as a single-item batch\n for (const listener of this.batchListeners) {\n listener([instruction]);\n }\n }\n\n private emitBatch(instructions: GridInstruction[]): void {\n if (instructions.length === 0) return;\n \n // console.log(\"[GP-Grid Core] emitBatch:\", instructions.map(i => i.type), {\n // batchListenerCount: this.batchListeners.length\n // });\n // Emit to batch listeners as a single batch\n for (const listener of this.batchListeners) {\n listener(instructions);\n }\n // Also emit to individual listeners for backwards compatibility\n for (const instruction of instructions) {\n for (const listener of this.listeners) {\n listener(instruction);\n }\n }\n }\n\n // ===========================================================================\n // Initialization\n // ===========================================================================\n\n /**\n * Initialize the grid and load initial data.\n */\n async initialize(): Promise<void> {\n await this.fetchData();\n this.syncSlots();\n this.emitContentSize();\n this.emitHeaders();\n }\n\n // ===========================================================================\n // Viewport Management\n // ===========================================================================\n\n /**\n * Update viewport measurements and sync slots.\n */\n setViewport(\n scrollTop: number,\n scrollLeft: number,\n width: number,\n height: number\n ): void {\n const changed =\n this.scrollTop !== scrollTop ||\n this.scrollLeft !== scrollLeft ||\n this.viewportWidth !== width ||\n this.viewportHeight !== height;\n\n if (!changed) return;\n\n this.scrollTop = scrollTop;\n this.scrollLeft = scrollLeft;\n this.viewportWidth = width;\n this.viewportHeight = height;\n\n this.syncSlots();\n }\n\n // ===========================================================================\n // Slot Pool Management (Virtual Scroll)\n // ===========================================================================\n\n /**\n * Synchronize slots with current viewport position.\n * This implements the slot recycling strategy.\n */\n private syncSlots(): void {\n // Use virtual scroll position for row calculations\n const virtualScrollTop = this.getVirtualScrollTop();\n\n // Calculate visible rows based on virtual scroll position\n // Viewport height stays the same (we don't compress the viewport)\n const visibleStartRow = Math.max(0, Math.floor(virtualScrollTop / this.rowHeight) - this.overscan);\n const visibleEndRow = Math.min(\n this.totalRows - 1,\n Math.ceil((virtualScrollTop + this.viewportHeight) / this.rowHeight) + this.overscan\n );\n\n if (this.totalRows === 0 || visibleEndRow < visibleStartRow) {\n // No rows to display - destroy all slots\n this.destroyAllSlots();\n return;\n }\n\n const requiredRows = new Set<number>();\n for (let row = visibleStartRow; row <= visibleEndRow; row++) {\n requiredRows.add(row);\n }\n\n const instructions: GridInstruction[] = [];\n\n // Find slots that are no longer needed\n const slotsToRecycle: string[] = [];\n for (const [slotId, slot] of this.slotPool.slots) {\n if (!requiredRows.has(slot.rowIndex)) {\n slotsToRecycle.push(slotId);\n this.slotPool.rowToSlot.delete(slot.rowIndex);\n } else {\n requiredRows.delete(slot.rowIndex);\n }\n }\n\n // Assign recycled slots to new rows\n const rowsNeedingSlots = Array.from(requiredRows);\n for (let i = 0; i < rowsNeedingSlots.length; i++) {\n const rowIndex = rowsNeedingSlots[i]!;\n const rowData = this.cachedRows.get(rowIndex);\n\n if (i < slotsToRecycle.length) {\n // Recycle existing slot\n const slotId = slotsToRecycle[i]!;\n const slot = this.slotPool.slots.get(slotId)!;\n const translateY = this.getRowTranslateY(rowIndex);\n\n slot.rowIndex = rowIndex;\n slot.rowData = rowData ?? {};\n slot.translateY = translateY;\n\n this.slotPool.rowToSlot.set(rowIndex, slotId);\n\n instructions.push({\n type: \"ASSIGN_SLOT\",\n slotId,\n rowIndex,\n rowData: rowData ?? {},\n });\n instructions.push({\n type: \"MOVE_SLOT\",\n slotId,\n translateY,\n });\n } else {\n // Create new slot\n const slotId = `slot-${this.slotPool.nextSlotId++}`;\n const translateY = this.getRowTranslateY(rowIndex);\n\n const newSlot: SlotState = {\n slotId,\n rowIndex,\n rowData: rowData ?? {},\n translateY,\n };\n\n this.slotPool.slots.set(slotId, newSlot);\n this.slotPool.rowToSlot.set(rowIndex, slotId);\n\n instructions.push({ type: \"CREATE_SLOT\", slotId });\n instructions.push({\n type: \"ASSIGN_SLOT\",\n slotId,\n rowIndex,\n rowData: rowData ?? {},\n });\n instructions.push({\n type: \"MOVE_SLOT\",\n slotId,\n translateY,\n });\n }\n }\n\n // Destroy excess slots\n for (let i = rowsNeedingSlots.length; i < slotsToRecycle.length; i++) {\n const slotId = slotsToRecycle[i]!;\n this.slotPool.slots.delete(slotId);\n instructions.push({ type: \"DESTROY_SLOT\", slotId });\n }\n\n // Update positions of existing slots that haven't moved\n for (const [slotId, slot] of this.slotPool.slots) {\n const expectedY = this.getRowTranslateY(slot.rowIndex);\n if (slot.translateY !== expectedY) {\n slot.translateY = expectedY;\n instructions.push({\n type: \"MOVE_SLOT\",\n slotId,\n translateY: expectedY,\n });\n }\n }\n\n this.emitBatch(instructions);\n }\n\n private destroyAllSlots(): void {\n const instructions: GridInstruction[] = [];\n for (const slotId of this.slotPool.slots.keys()) {\n instructions.push({ type: \"DESTROY_SLOT\", slotId });\n }\n this.slotPool.slots.clear();\n this.slotPool.rowToSlot.clear();\n this.emitBatch(instructions);\n }\n\n /**\n * Get the virtual (unscaled) height of the entire grid content.\n */\n private getVirtualHeight(): number {\n return this.totalRows * this.rowHeight + this.headerHeight;\n }\n\n /**\n * Get the display height (capped) for the content sizer.\n * This is the height that will be used in CSS for the scrollable area.\n */\n private getDisplayHeight(): number {\n return Math.min(this.getVirtualHeight(), GridCore.MAX_SAFE_HEIGHT);\n }\n\n /**\n * Check if scaling is needed (virtual height exceeds safe limit).\n */\n private needsScaling(): boolean {\n return this.getVirtualHeight() > GridCore.MAX_SAFE_HEIGHT;\n }\n\n /**\n * Get the scroll progress as a value from 0 to 1.\n * 0 = scrolled to top, 1 = scrolled to bottom.\n */\n private getScrollProgress(): number {\n const displayHeight = this.getDisplayHeight();\n const maxScroll = displayHeight - this.viewportHeight;\n if (maxScroll <= 0) return 0;\n return Math.min(1, Math.max(0, this.scrollTop / maxScroll));\n }\n\n /**\n * Convert display scroll position to virtual scroll position.\n * Uses proportional mapping when content exceeds safe limits.\n */\n private getVirtualScrollTop(): number {\n if (!this.needsScaling()) {\n return this.scrollTop;\n }\n const virtualHeight = this.getVirtualHeight();\n const maxVirtualScroll = virtualHeight - this.viewportHeight;\n return this.getScrollProgress() * maxVirtualScroll;\n }\n\n /**\n * Get the translateY for a row that keeps values within safe CSS limits.\n * Uses proportional positioning when content exceeds safe limits.\n */\n private getRowTranslateY(rowIndex: number): number {\n const virtualY = rowIndex * this.rowHeight + this.headerHeight;\n\n if (!this.needsScaling()) {\n return virtualY;\n }\n\n // When scaling is needed, we use a formula that:\n // 1. Keeps all translateY values within displayHeight bounds\n // 2. Preserves visual row spacing (no compression)\n // 3. Maps scroll position proportionally\n //\n // Formula: translateY = virtualY + scrollProgress * (displayHeight - virtualHeight)\n // This shifts all positions by an offset that depends on scroll progress.\n const displayHeight = this.getDisplayHeight();\n const virtualHeight = this.getVirtualHeight();\n const scrollProgress = this.getScrollProgress();\n\n const translateY = virtualY + scrollProgress * (displayHeight - virtualHeight);\n\n // Clamp to safe bounds - overscan rows might slightly exceed\n // Negative values are fine (rows above viewport), but cap the maximum\n return Math.min(translateY, displayHeight);\n }\n\n // ===========================================================================\n // Data Fetching\n // ===========================================================================\n\n private async fetchData(): Promise<void> {\n this.emit({ type: \"DATA_LOADING\" });\n\n try {\n const request: DataSourceRequest = {\n pagination: {\n pageIndex: this.currentPageIndex,\n pageSize: this.pageSize,\n },\n sort: this.sortModel.length > 0 ? this.sortModel : undefined,\n filter: Object.keys(this.filterModel).length > 0 ? this.filterModel : undefined,\n };\n\n const response = await this.dataSource.fetch(request);\n\n // Cache the fetched rows\n this.cachedRows.clear();\n response.rows.forEach((row, index) => {\n this.cachedRows.set(this.currentPageIndex * this.pageSize + index, row);\n });\n\n this.totalRows = response.totalRows;\n\n // For client-side data source, fetch all data for simplicity\n // (the client data source handles filtering/sorting internally)\n if (response.totalRows > response.rows.length && this.currentPageIndex === 0) {\n // Fetch all remaining pages for client-side mode\n await this.fetchAllData();\n }\n\n this.emit({ type: \"DATA_LOADED\", totalRows: this.totalRows });\n } catch (error) {\n this.emit({\n type: \"DATA_ERROR\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n private async fetchAllData(): Promise<void> {\n // Fetch all data in chunks for client-side data source\n const totalPages = Math.ceil(this.totalRows / this.pageSize);\n\n for (let page = 1; page < totalPages; page++) {\n const request: DataSourceRequest = {\n pagination: {\n pageIndex: page,\n pageSize: this.pageSize,\n },\n sort: this.sortModel.length > 0 ? this.sortModel : undefined,\n filter: Object.keys(this.filterModel).length > 0 ? this.filterModel : undefined,\n };\n\n const response = await this.dataSource.fetch(request);\n response.rows.forEach((row, index) => {\n this.cachedRows.set(page * this.pageSize + index, row);\n });\n }\n }\n\n // ===========================================================================\n // Sort & Filter\n // ===========================================================================\n\n async setSort(\n colId: string,\n direction: SortDirection | null,\n addToExisting: boolean = false\n ): Promise<void> {\n // console.log(\"[GP-Grid Core] setSort:\", { colId, direction, addToExisting });\n const existingIndex = this.sortModel.findIndex((s) => s.colId === colId);\n\n if (!addToExisting) {\n this.sortModel = direction === null ? [] : [{ colId, direction }];\n } else {\n if (direction === null) {\n if (existingIndex >= 0) {\n this.sortModel.splice(existingIndex, 1);\n }\n } else if (existingIndex >= 0) {\n this.sortModel[existingIndex]!.direction = direction;\n } else {\n this.sortModel.push({ colId, direction });\n }\n }\n\n // console.log(\"[GP-Grid Core] setSort - fetching sorted data...\");\n await this.fetchData();\n // Refresh all slots with newly sorted data\n this.refreshAllSlots();\n this.emitHeaders();\n // console.log(\"[GP-Grid Core] setSort - complete\");\n }\n\n async setFilter(colId: string, value: string): Promise<void> {\n if (value === \"\") {\n delete this.filterModel[colId];\n } else {\n this.filterModel[colId] = value;\n }\n\n await this.fetchData();\n // Force refresh all slots since filtered data changed\n this.refreshAllSlots();\n this.emitContentSize();\n }\n\n /**\n * Force refresh all slot data (used after filtering/sorting when data changes)\n */\n private refreshAllSlots(): void {\n const instructions: GridInstruction[] = [];\n\n for (const [slotId, slot] of this.slotPool.slots) {\n // Check if row index is still valid\n if (slot.rowIndex >= 0 && slot.rowIndex < this.totalRows) {\n const rowData = this.cachedRows.get(slot.rowIndex);\n const translateY = this.getRowTranslateY(slot.rowIndex);\n\n slot.rowData = rowData ?? {};\n slot.translateY = translateY;\n\n instructions.push({\n type: \"ASSIGN_SLOT\",\n slotId,\n rowIndex: slot.rowIndex,\n rowData: rowData ?? {},\n });\n instructions.push({\n type: \"MOVE_SLOT\",\n slotId,\n translateY,\n });\n }\n }\n\n this.emitBatch(instructions);\n\n // Also sync slots to handle any rows that went out of bounds\n this.syncSlots();\n }\n\n getSortModel(): SortModel[] {\n return [...this.sortModel];\n }\n\n getFilterModel(): FilterModel {\n return { ...this.filterModel };\n }\n\n // ===========================================================================\n // Editing\n // ===========================================================================\n\n startEdit(row: number, col: number): void {\n const column = this.columns[col];\n if (!column || column.editable !== true) return;\n\n const initialValue = this.getCellValue(row, col);\n this.editState = {\n row,\n col,\n initialValue,\n currentValue: initialValue,\n };\n\n this.emit({\n type: \"START_EDIT\",\n row,\n col,\n initialValue,\n });\n }\n\n updateEditValue(value: CellValue): void {\n if (this.editState) {\n this.editState.currentValue = value;\n }\n }\n\n commitEdit(): void {\n if (!this.editState) return;\n\n const { row, col, currentValue } = this.editState;\n this.setCellValue(row, col, currentValue);\n\n this.emit({\n type: \"COMMIT_EDIT\",\n row,\n col,\n value: currentValue,\n });\n\n this.editState = null;\n this.emit({ type: \"STOP_EDIT\" });\n\n // Update the slot displaying this row\n const slotId = this.slotPool.rowToSlot.get(row);\n if (slotId) {\n const rowData = this.cachedRows.get(row);\n if (rowData) {\n this.emit({\n type: \"ASSIGN_SLOT\",\n slotId,\n rowIndex: row,\n rowData,\n });\n }\n }\n }\n\n cancelEdit(): void {\n this.editState = null;\n this.emit({ type: \"STOP_EDIT\" });\n }\n\n getEditState(): EditState | null {\n return this.editState ? { ...this.editState } : null;\n }\n\n // ===========================================================================\n // Cell Value Access\n // ===========================================================================\n\n getCellValue(row: number, col: number): CellValue {\n const rowData = this.cachedRows.get(row);\n if (!rowData) return null;\n\n const column = this.columns[col];\n if (!column) return null;\n\n return this.getFieldValue(rowData, column.field);\n }\n\n setCellValue(row: number, col: number, value: CellValue): void {\n const rowData = this.cachedRows.get(row);\n if (!rowData || typeof rowData !== \"object\") return;\n\n const column = this.columns[col];\n if (!column) return;\n\n this.setFieldValue(rowData as Record<string, unknown>, column.field, value);\n }\n\n private getFieldValue(data: TData, field: string): CellValue {\n const parts = field.split(\".\");\n let value: unknown = data;\n\n for (const part of parts) {\n if (value == null || typeof value !== \"object\") {\n return null;\n }\n value = (value as Record<string, unknown>)[part];\n }\n\n return (value ?? null) as CellValue;\n }\n\n private setFieldValue(data: Record<string, unknown>, field: string, value: CellValue): void {\n const parts = field.split(\".\");\n let obj = data;\n\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!;\n if (!(part in obj)) {\n obj[part] = {};\n }\n obj = obj[part] as Record<string, unknown>;\n }\n\n const lastPart = parts[parts.length - 1]!;\n obj[lastPart] = value;\n }\n\n // ===========================================================================\n // Layout Helpers\n // ===========================================================================\n\n private computeColumnPositions(): void {\n this.columnPositions = [0];\n let pos = 0;\n for (const col of this.columns) {\n pos += col.width;\n this.columnPositions.push(pos);\n }\n }\n\n private emitContentSize(): void {\n const width = this.columnPositions[this.columnPositions.length - 1] ?? 0;\n // Use scaled display height to keep CSS values within safe browser limits\n const height = this.getDisplayHeight();\n this.emit({ type: \"SET_CONTENT_SIZE\", width, height });\n }\n\n private emitHeaders(): void {\n const sortInfoMap = new Map<string, { direction: SortDirection; index: number }>();\n this.sortModel.forEach((sort, index) => {\n sortInfoMap.set(sort.colId, { direction: sort.direction, index: index + 1 });\n });\n\n for (let i = 0; i < this.columns.length; i++) {\n const column = this.columns[i]!;\n const colId = column.colId ?? column.field;\n const sortInfo = sortInfoMap.get(colId);\n\n this.emit({\n type: \"UPDATE_HEADER\",\n colIndex: i,\n column,\n sortDirection: sortInfo?.direction,\n sortIndex: sortInfo?.index,\n });\n }\n }\n\n // ===========================================================================\n // Public Accessors\n // ===========================================================================\n\n getColumns(): ColumnDefinition[] {\n return this.columns;\n }\n\n getColumnPositions(): number[] {\n return [...this.columnPositions];\n }\n\n getRowCount(): number {\n return this.totalRows;\n }\n\n getRowHeight(): number {\n return this.rowHeight;\n }\n\n getHeaderHeight(): number {\n return this.headerHeight;\n }\n\n getTotalWidth(): number {\n return this.columnPositions[this.columnPositions.length - 1] ?? 0;\n }\n\n getTotalHeight(): number {\n return this.totalRows * this.rowHeight + this.headerHeight;\n }\n\n getRowData(rowIndex: number): TData | undefined {\n return this.cachedRows.get(rowIndex);\n }\n\n /**\n * Get the display Y position for a row (accounting for scaling).\n * Used by UI adapters for scroll-into-view functionality.\n */\n getDisplayYForRow(rowIndex: number): number {\n return this.getRowTranslateY(rowIndex);\n }\n\n /**\n * Check if scaling is currently active.\n */\n isScalingActive(): boolean {\n return this.needsScaling();\n }\n\n /**\n * Convert a display Y position to a row index.\n * Used by UI adapters for mouse coordinate conversion during drag operations.\n * @param displayY The Y position in display coordinates (relative to content area, after header)\n * @param scrollTop The current scroll position\n */\n getRowIndexAtDisplayY(displayY: number, scrollTop: number): number {\n if (!this.needsScaling()) {\n return Math.floor(displayY / this.rowHeight);\n }\n\n // With scaling, we need to invert the proportional mapping\n // displayY was calculated based on slots positioned at:\n // translateY = virtualY + scrollProgress * (displayHeight - virtualHeight)\n //\n // So to get virtualY from a display position, we invert:\n // virtualY = displayY - scrollProgress * (displayHeight - virtualHeight)\n const displayHeight = this.getDisplayHeight();\n const virtualHeight = this.getVirtualHeight();\n const maxScroll = displayHeight - this.viewportHeight;\n const scrollProgress = maxScroll > 0 ? Math.min(1, Math.max(0, scrollTop / maxScroll)) : 0;\n\n const virtualY = displayY - scrollProgress * (displayHeight - virtualHeight);\n return Math.floor(virtualY / this.rowHeight);\n }\n\n /**\n * Calculate the scroll position needed to make a row visible.\n * For scaling mode: uses proportional mapping (rowIndex/totalRows ≈ scrollTop/maxScroll)\n * Used by UI adapters for scroll-into-view functionality.\n */\n getScrollTopForRow(rowIndex: number): number {\n if (!this.needsScaling()) {\n // Without scaling, simple linear mapping\n return Math.max(0, rowIndex * this.rowHeight);\n }\n\n // With scaling: use proportional mapping\n // rowIndex / totalRows ≈ scrollTop / maxScroll\n const displayHeight = this.getDisplayHeight();\n const maxScroll = Math.max(0, displayHeight - this.viewportHeight);\n const progress = this.totalRows > 0 ? rowIndex / this.totalRows : 0;\n\n return Math.min(maxScroll, Math.max(0, progress * maxScroll));\n }\n\n /**\n * Get the currently visible row range (excluding overscan).\n * Returns { start, end } row indices that are fully visible in the viewport.\n * Used by UI adapters for scroll-into-view functionality.\n */\n getVisibleRowRange(): { start: number; end: number } {\n const virtualScrollTop = this.getVirtualScrollTop();\n // The header takes up space in the viewport, so subtract it from available data area\n const dataAreaHeight = Math.max(0, this.viewportHeight - this.headerHeight);\n\n // First fully visible row\n const start = Math.max(0, Math.ceil(virtualScrollTop / this.rowHeight));\n // Last fully visible row\n const end = Math.min(\n this.totalRows - 1,\n Math.floor((virtualScrollTop + dataAreaHeight) / this.rowHeight) - 1\n );\n return { start: Math.min(start, end), end };\n }\n\n // ===========================================================================\n // Data Updates\n // ===========================================================================\n\n /**\n * Refresh data from the data source.\n */\n async refresh(): Promise<void> {\n await this.fetchData();\n this.syncSlots();\n this.emitContentSize();\n }\n\n /**\n * Refresh slot display without refetching data.\n * Useful after in-place data modifications like fill operations.\n */\n refreshSlotData(): void {\n this.refreshAllSlots();\n }\n\n /**\n * Update the data source and refresh.\n */\n async setDataSource(dataSource: DataSource<TData>): Promise<void> {\n this.dataSource = dataSource;\n await this.refresh();\n }\n\n /**\n * Update columns and recompute layout.\n */\n setColumns(columns: ColumnDefinition[]): void {\n this.columns = columns;\n this.computeColumnPositions();\n this.emitContentSize();\n this.emitHeaders();\n this.syncSlots();\n }\n}\n\n","// gp-grid-core/src/sort-worker.ts\n// Web Worker for sorting large datasets off the main thread\n\nimport type { SortModel, CellValue } from \"./types\";\n\n// =============================================================================\n// Worker Message Types\n// =============================================================================\n\nexport interface SortWorkerRequest {\n type: \"sort\";\n id: number;\n data: unknown[];\n sortModel: SortModel[];\n}\n\nexport interface SortIndicesRequest {\n type: \"sortIndices\";\n id: number;\n values: Float64Array;\n direction: \"asc\" | \"desc\";\n}\n\nexport interface SortMultiColumnRequest {\n type: \"sortMultiColumn\";\n id: number;\n /** Array of column values, each as Float64Array */\n columns: Float64Array[];\n /** Direction for each column: 1 for asc, -1 for desc */\n directions: Int8Array;\n}\n\nexport interface SortWorkerResponse {\n type: \"sorted\";\n id: number;\n data: unknown[];\n}\n\nexport interface SortIndicesResponse {\n type: \"sortedIndices\";\n id: number;\n indices: Uint32Array;\n}\n\nexport interface SortMultiColumnResponse {\n type: \"sortedMultiColumn\";\n id: number;\n indices: Uint32Array;\n}\n\nexport interface SortStringHashesRequest {\n type: \"sortStringHashes\";\n id: number;\n /** Array of hash chunks: [chunk0Values, chunk1Values, chunk2Values] */\n hashChunks: Float64Array[];\n direction: \"asc\" | \"desc\";\n}\n\nexport interface SortStringHashesResponse {\n type: \"sortedStringHashes\";\n id: number;\n indices: Uint32Array;\n /** Pairs of indices that had hash collisions (all chunks equal) */\n collisionPairs: Uint32Array;\n}\n\n// =============================================================================\n// Sorting Functions (duplicated from data-source.ts for worker isolation)\n// =============================================================================\n\nfunction getFieldValue(row: unknown, field: string): CellValue {\n const parts = field.split(\".\");\n let value: unknown = row;\n\n for (const part of parts) {\n if (value == null || typeof value !== \"object\") {\n return null;\n }\n value = (value as Record<string, unknown>)[part];\n }\n\n return (value ?? null) as CellValue;\n}\n\nfunction compareValues(a: CellValue, b: CellValue): number {\n // Null handling\n if (a == null && b == null) return 0;\n if (a == null) return 1;\n if (b == null) return -1;\n\n // Numeric comparison\n const aNum = Number(a);\n const bNum = Number(b);\n if (!isNaN(aNum) && !isNaN(bNum)) {\n return aNum - bNum;\n }\n\n // Date comparison\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() - b.getTime();\n }\n\n // String comparison\n return String(a).localeCompare(String(b));\n}\n\nfunction sortData<T>(data: T[], sortModel: SortModel[]): T[] {\n return [...data].sort((a, b) => {\n for (const { colId, direction } of sortModel) {\n const aVal = getFieldValue(a, colId);\n const bVal = getFieldValue(b, colId);\n const comparison = compareValues(aVal, bVal);\n\n if (comparison !== 0) {\n return direction === \"asc\" ? comparison : -comparison;\n }\n }\n return 0;\n });\n}\n\n// =============================================================================\n// Worker Code String (for inline worker creation)\n// =============================================================================\n\n/**\n * Inline worker code as a string for Blob URL creation.\n * This allows the worker to function without bundler-specific configuration.\n */\nexport const SORT_WORKER_CODE = `\n// Inline sort worker code\nfunction getFieldValue(row, field) {\n const parts = field.split(\".\");\n let value = row;\n\n for (const part of parts) {\n if (value == null || typeof value !== \"object\") {\n return null;\n }\n value = value[part];\n }\n\n return value ?? null;\n}\n\nfunction compareValues(a, b) {\n if (a == null && b == null) return 0;\n if (a == null) return 1;\n if (b == null) return -1;\n\n const aNum = Number(a);\n const bNum = Number(b);\n if (!isNaN(aNum) && !isNaN(bNum)) {\n return aNum - bNum;\n }\n\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() - b.getTime();\n }\n\n return String(a).localeCompare(String(b));\n}\n\nfunction sortData(data, sortModel) {\n return [...data].sort((a, b) => {\n for (const { colId, direction } of sortModel) {\n const aVal = getFieldValue(a, colId);\n const bVal = getFieldValue(b, colId);\n const comparison = compareValues(aVal, bVal);\n\n if (comparison !== 0) {\n return direction === \"asc\" ? comparison : -comparison;\n }\n }\n return 0;\n });\n}\n\n// Index-based sorting - much faster for large datasets\n// Uses Transferable typed arrays for zero-copy transfer\nfunction sortIndices(values, direction) {\n const len = values.length;\n const indices = new Uint32Array(len);\n for (let i = 0; i < len; i++) indices[i] = i;\n\n // Sort indices by values\n const mult = direction === \"asc\" ? 1 : -1;\n indices.sort((a, b) => {\n const va = values[a];\n const vb = values[b];\n if (va < vb) return -1 * mult;\n if (va > vb) return 1 * mult;\n return 0;\n });\n\n return indices;\n}\n\n// Multi-column sorting - compares columns in priority order\nfunction sortMultiColumn(columns, directions) {\n const len = columns[0].length;\n const numCols = columns.length;\n const indices = new Uint32Array(len);\n for (let i = 0; i < len; i++) indices[i] = i;\n\n indices.sort((a, b) => {\n for (let c = 0; c < numCols; c++) {\n const va = columns[c][a];\n const vb = columns[c][b];\n if (va < vb) return -1 * directions[c];\n if (va > vb) return 1 * directions[c];\n // Equal - continue to next column\n }\n return 0;\n });\n\n return indices;\n}\n\n// String hash sorting with collision detection\nfunction sortStringHashes(hashChunks, direction) {\n const len = hashChunks[0].length;\n const numChunks = hashChunks.length;\n const indices = new Uint32Array(len);\n for (let i = 0; i < len; i++) indices[i] = i;\n\n const mult = direction === \"asc\" ? 1 : -1;\n const collisions = []; // Track collision pairs\n\n indices.sort((a, b) => {\n for (let c = 0; c < numChunks; c++) {\n const va = hashChunks[c][a];\n const vb = hashChunks[c][b];\n if (va < vb) return -1 * mult;\n if (va > vb) return 1 * mult;\n }\n // All chunks equal = collision, record for fallback\n collisions.push(a, b);\n return 0; // Stable sort preserves original order\n });\n\n return { indices, collisionPairs: new Uint32Array(collisions) };\n}\n\nself.onmessage = function(e) {\n const { type, id } = e.data;\n\n if (type === \"sort\") {\n try {\n const { data, sortModel } = e.data;\n const sorted = sortData(data, sortModel);\n self.postMessage({ type: \"sorted\", id, data: sorted });\n } catch (error) {\n self.postMessage({ type: \"error\", id, error: String(error) });\n }\n } else if (type === \"sortIndices\") {\n try {\n const { values, direction } = e.data;\n const indices = sortIndices(values, direction);\n // Transfer the indices buffer back (zero-copy)\n self.postMessage({ type: \"sortedIndices\", id, indices }, [indices.buffer]);\n } catch (error) {\n self.postMessage({ type: \"error\", id, error: String(error) });\n }\n } else if (type === \"sortMultiColumn\") {\n try {\n const { columns, directions } = e.data;\n const indices = sortMultiColumn(columns, directions);\n self.postMessage({ type: \"sortedMultiColumn\", id, indices }, [indices.buffer]);\n } catch (error) {\n self.postMessage({ type: \"error\", id, error: String(error) });\n }\n } else if (type === \"sortStringHashes\") {\n try {\n const { hashChunks, direction } = e.data;\n const result = sortStringHashes(hashChunks, direction);\n self.postMessage(\n { type: \"sortedStringHashes\", id, indices: result.indices, collisionPairs: result.collisionPairs },\n [result.indices.buffer, result.collisionPairs.buffer]\n );\n } catch (error) {\n self.postMessage({ type: \"error\", id, error: String(error) });\n }\n }\n};\n`;\n\n// =============================================================================\n// Export for use as module worker (if bundler supports it)\n// =============================================================================\n\n// This handles incoming messages when running as a module worker\ninterface WorkerGlobalScopeMinimal {\n onmessage: ((e: MessageEvent) => void) | null;\n postMessage(message: unknown): void;\n}\ndeclare const self: WorkerGlobalScopeMinimal;\n\nif (typeof self !== \"undefined\" && typeof self.onmessage !== \"undefined\") {\n self.onmessage = (e: MessageEvent<SortWorkerRequest>) => {\n const { type, id, data, sortModel } = e.data;\n\n if (type === \"sort\") {\n try {\n const sorted = sortData(data, sortModel);\n self.postMessage({ type: \"sorted\", id, data: sorted } as SortWorkerResponse);\n } catch (error) {\n self.postMessage({ type: \"error\", id, error: String(error) });\n }\n }\n };\n}\n","// gp-grid-core/src/worker-manager.ts\n// Manages Web Worker lifecycle for sorting operations\n\nimport type { SortDirection, SortModel } from \"./types\";\nimport { SORT_WORKER_CODE } from \"./sort-worker\";\nimport type {\n SortWorkerRequest,\n SortWorkerResponse,\n SortIndicesRequest,\n SortIndicesResponse,\n SortMultiColumnRequest,\n SortMultiColumnResponse,\n SortStringHashesRequest,\n SortStringHashesResponse,\n} from \"./sort-worker\";\n\n// =============================================================================\n// SortWorkerManager\n// =============================================================================\n\n/**\n * Manages a Web Worker for sorting large datasets off the main thread.\n * Uses an inline worker (Blob URL) for maximum compatibility across bundlers.\n */\nexport class SortWorkerManager {\n private worker: Worker | null = null;\n private workerUrl: string | null = null;\n private pendingRequests: Map<\n number,\n {\n resolve: (data: unknown) => void;\n reject: (error: Error) => void;\n }\n > = new Map();\n private nextRequestId: number = 0;\n private isTerminated: boolean = false;\n\n /**\n * Sort data using a Web Worker.\n * The worker is lazily initialized on first use.\n */\n async sortInWorker<T>(data: T[], sortModel: SortModel[]): Promise<T[]> {\n if (this.isTerminated) {\n throw new Error(\"SortWorkerManager has been terminated\");\n }\n\n // Lazy initialization\n if (!this.worker) {\n this.initializeWorker();\n }\n\n const id = this.nextRequestId++;\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: resolve as (data: unknown) => void,\n reject,\n });\n\n const request: SortWorkerRequest = {\n type: \"sort\",\n id,\n data,\n sortModel,\n };\n\n this.worker!.postMessage(request);\n });\n }\n\n /**\n * Sort indices using a Web Worker with Transferable typed arrays.\n * This is much faster than sortInWorker for large datasets because\n * it avoids the serialization overhead of transferring full objects.\n */\n async sortIndices(\n values: number[],\n direction: SortDirection,\n ): Promise<Uint32Array> {\n if (this.isTerminated) {\n throw new Error(\"SortWorkerManager has been terminated\");\n }\n\n // Lazy initialization\n if (!this.worker) {\n this.initializeWorker();\n }\n\n const id = this.nextRequestId++;\n\n // Convert to typed array for efficient transfer\n const valuesArray = new Float64Array(values);\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: resolve as (data: unknown) => void,\n reject,\n });\n\n const request: SortIndicesRequest = {\n type: \"sortIndices\",\n id,\n values: valuesArray,\n direction,\n };\n\n // Transfer the values buffer (zero-copy)\n this.worker!.postMessage(request, [valuesArray.buffer]);\n });\n }\n\n /**\n * Sort by multiple columns using a Web Worker with Transferable typed arrays.\n * Each column's values are passed as a Float64Array, enabling fast multi-column sorting.\n * @param columns Array of column values (each as number[])\n * @param directions Array of directions for each column (\"asc\" or \"desc\")\n */\n async sortMultiColumn(\n columns: number[][],\n directions: SortDirection[],\n ): Promise<Uint32Array> {\n if (this.isTerminated) {\n throw new Error(\"SortWorkerManager has been terminated\");\n }\n\n // Lazy initialization\n if (!this.worker) {\n this.initializeWorker();\n }\n\n const id = this.nextRequestId++;\n\n // Convert to typed arrays for efficient transfer\n const columnArrays = columns.map((col) => new Float64Array(col));\n const directionArray = new Int8Array(\n directions.map((d) => (d === \"asc\" ? 1 : -1)),\n );\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: resolve as (data: unknown) => void,\n reject,\n });\n\n const request: SortMultiColumnRequest = {\n type: \"sortMultiColumn\",\n id,\n columns: columnArrays,\n directions: directionArray,\n };\n\n // Transfer all column buffers (zero-copy)\n const transferables = columnArrays.map((arr) => arr.buffer);\n transferables.push(directionArray.buffer);\n this.worker!.postMessage(request, transferables);\n });\n }\n\n /**\n * Sort string values using multiple hash chunks with collision detection.\n * Returns sorted indices and handles hash collisions using localeCompare fallback.\n * @param hashChunks Array of hash chunk arrays (one per chunk, each chunk as Float64Array)\n * @param direction Sort direction (\"asc\" or \"desc\")\n * @param originalStrings Original string values for collision fallback\n */\n async sortStringHashes(\n hashChunks: Float64Array[],\n direction: SortDirection,\n originalStrings: string[],\n ): Promise<Uint32Array> {\n if (this.isTerminated) {\n throw new Error(\"SortWorkerManager has been terminated\");\n }\n\n // Lazy initialization\n if (!this.worker) {\n this.initializeWorker();\n }\n\n const id = this.nextRequestId++;\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: (data: unknown) => {\n const response = data as {\n indices: Uint32Array;\n collisionPairs: Uint32Array;\n };\n const { indices, collisionPairs } = response;\n\n // Handle collisions using localeCompare on original strings\n if (collisionPairs.length > 0) {\n this.resolveCollisions(\n indices,\n collisionPairs,\n originalStrings,\n direction,\n );\n }\n\n resolve(indices);\n },\n reject,\n });\n\n const request: SortStringHashesRequest = {\n type: \"sortStringHashes\",\n id,\n hashChunks,\n direction,\n };\n\n // Transfer all hash chunk buffers (zero-copy)\n const transferables = hashChunks.map((arr) => arr.buffer);\n this.worker!.postMessage(request, transferables);\n });\n }\n\n /**\n * Resolve hash collisions by re-sorting collision groups using localeCompare.\n */\n private resolveCollisions(\n indices: Uint32Array,\n collisionPairs: Uint32Array,\n originalStrings: string[],\n direction: SortDirection,\n ): void {\n // Build collision groups from pairs\n // collisionPairs contains pairs: [a1, b1, a2, b2, ...]\n // We need to find consecutive runs of equal-hash elements in the sorted indices\n\n // Create a set of indices that are involved in collisions\n const collisionIndices = new Set<number>();\n for (let i = 0; i < collisionPairs.length; i++) {\n collisionIndices.add(collisionPairs[i]!);\n }\n\n if (collisionIndices.size === 0) return;\n\n // Find collision groups in the sorted indices array\n const groups: { start: number; end: number }[] = [];\n let groupStart = -1;\n\n for (let i = 0; i < indices.length; i++) {\n const idx = indices[i]!;\n if (collisionIndices.has(idx)) {\n if (groupStart === -1) {\n groupStart = i;\n }\n } else {\n if (groupStart !== -1) {\n groups.push({ start: groupStart, end: i });\n groupStart = -1;\n }\n }\n }\n // Handle group at the end\n if (groupStart !== -1) {\n groups.push({ start: groupStart, end: indices.length });\n }\n\n // Sort each collision group using localeCompare\n const mult = direction === \"asc\" ? 1 : -1;\n for (const group of groups) {\n // Extract the slice of indices for this group\n const slice = Array.from(indices.slice(group.start, group.end));\n\n // Sort by original strings\n slice.sort((a, b) => {\n return mult * originalStrings[a]!.localeCompare(originalStrings[b]!);\n });\n\n // Write back\n for (let i = 0; i < slice.length; i++) {\n indices[group.start + i] = slice[i]!;\n }\n }\n }\n\n /**\n * Initialize the worker using an inline Blob URL.\n * This works without bundler-specific configuration.\n */\n private initializeWorker(): void {\n // Check if Web Workers are available\n if (typeof Worker === \"undefined\") {\n throw new Error(\"Web Workers are not available in this environment\");\n }\n\n // Create Blob URL from inline worker code\n const blob = new Blob([SORT_WORKER_CODE], {\n type: \"application/javascript\",\n });\n this.workerUrl = URL.createObjectURL(blob);\n this.worker = new Worker(this.workerUrl);\n\n // Handle messages from worker\n this.worker.onmessage = (\n e: MessageEvent<\n | SortWorkerResponse\n | SortIndicesResponse\n | SortMultiColumnResponse\n | SortStringHashesResponse\n | { type: \"error\"; id: number; error: string }\n >,\n ) => {\n const { id } = e.data;\n const pending = this.pendingRequests.get(id);\n\n if (!pending) {\n return;\n }\n\n this.pendingRequests.delete(id);\n\n if (e.data.type === \"sorted\") {\n pending.resolve(e.data.data);\n } else if (e.data.type === \"sortedIndices\") {\n pending.resolve(e.data.indices);\n } else if (e.data.type === \"sortedMultiColumn\") {\n pending.resolve(e.data.indices);\n } else if (e.data.type === \"sortedStringHashes\") {\n pending.resolve({\n indices: e.data.indices,\n collisionPairs: e.data.collisionPairs,\n });\n } else if (e.data.type === \"error\") {\n pending.reject(new Error((e.data as { error: string }).error));\n }\n };\n\n // Handle worker errors\n this.worker.onerror = (e) => {\n // Reject all pending requests\n for (const [id, pending] of this.pendingRequests) {\n pending.reject(new Error(`Worker error: ${e.message}`));\n this.pendingRequests.delete(id);\n }\n };\n }\n\n /**\n * Terminate the worker and clean up resources.\n */\n terminate(): void {\n if (this.worker) {\n this.worker.terminate();\n this.worker = null;\n }\n\n if (this.workerUrl) {\n URL.revokeObjectURL(this.workerUrl);\n this.workerUrl = null;\n }\n\n // Reject any pending requests\n for (const [, pending] of this.pendingRequests) {\n pending.reject(new Error(\"Worker terminated\"));\n }\n this.pendingRequests.clear();\n this.isTerminated = true;\n }\n\n /**\n * Check if the worker is currently available.\n */\n isAvailable(): boolean {\n return !this.isTerminated && typeof Worker !== \"undefined\";\n }\n}\n\n// =============================================================================\n// Singleton Instance (optional usage pattern)\n// =============================================================================\n\nlet sharedWorkerManager: SortWorkerManager | null = null;\n\n/**\n * Get a shared SortWorkerManager instance.\n * Useful when multiple data sources should share the same worker.\n */\nexport function getSharedSortWorker(): SortWorkerManager {\n if (!sharedWorkerManager) {\n sharedWorkerManager = new SortWorkerManager();\n }\n return sharedWorkerManager;\n}\n\n/**\n * Terminate the shared worker and release resources.\n */\nexport function terminateSharedSortWorker(): void {\n if (sharedWorkerManager) {\n sharedWorkerManager.terminate();\n sharedWorkerManager = null;\n }\n}\n","// gp-grid-core/src/data-source.ts\n\nimport type {\n DataSource,\n DataSourceRequest,\n DataSourceResponse,\n Row,\n SortModel,\n FilterModel,\n CellValue,\n} from \"./types\";\nimport { SortWorkerManager } from \"./worker-manager\";\n\n// =============================================================================\n// Configuration\n// =============================================================================\n\n/** Threshold for using Web Worker (rows). Below this, sync sort is used. */\nconst WORKER_THRESHOLD = 200000;\n\n/** Number of 10-character chunks for string hashing (30 chars total) */\nconst HASH_CHUNK_COUNT = 3;\n\n// =============================================================================\n// Client Data Source (In-Memory)\n// =============================================================================\n\n/**\n * Creates a client-side data source that holds all data in memory.\n * Sorting and filtering are performed client-side.\n * For large datasets (10k+ rows), sorting is automatically offloaded to a Web Worker.\n */\nexport function createClientDataSource<TData extends Row = Row>(\n data: TData[],\n options: {\n /** Custom field accessor for nested properties */\n getFieldValue?: (row: TData, field: string) => CellValue;\n /** Use Web Worker for sorting large datasets (default: true) */\n useWorker?: boolean;\n } = {}\n): DataSource<TData> {\n const { getFieldValue = defaultGetFieldValue, useWorker = true } = options;\n\n // Create worker manager only if useWorker is enabled\n const workerManager = useWorker ? new SortWorkerManager() : null;\n\n return {\n async fetch(request: DataSourceRequest): Promise<DataSourceResponse<TData>> {\n let processedData = [...data];\n\n // Apply filters (always sync - filtering is fast)\n if (request.filter && Object.keys(request.filter).length > 0) {\n processedData = applyFilters(processedData, request.filter, getFieldValue);\n }\n\n // Apply sorting (async with worker for large datasets)\n if (request.sort && request.sort.length > 0) {\n // Use worker-based index sorting for large datasets (all column types)\n const canUseWorkerSort = workerManager &&\n workerManager.isAvailable() &&\n processedData.length >= WORKER_THRESHOLD;\n\n if (canUseWorkerSort) {\n let sortedIndices: Uint32Array;\n\n // For single-column string sorting, use multi-hash approach with collision fallback\n if (request.sort.length === 1) {\n const { colId, direction } = request.sort[0]!;\n\n // Detect column type by sampling first non-null value\n let isStringColumn = false;\n for (const row of processedData) {\n const val = getFieldValue(row, colId);\n if (val != null) {\n isStringColumn = typeof val === \"string\";\n break;\n }\n }\n\n if (isStringColumn) {\n // Use multi-hash sorting for strings\n const originalStrings: string[] = [];\n const hashChunks: number[][] = Array.from({ length: HASH_CHUNK_COUNT }, () => []);\n\n for (const row of processedData) {\n const val = getFieldValue(row, colId);\n const str = val == null ? \"\" : String(val);\n originalStrings.push(str);\n const hashes = stringToSortableHashes(str);\n for (let c = 0; c < HASH_CHUNK_COUNT; c++) {\n hashChunks[c]!.push(hashes[c]!);\n }\n }\n\n // Convert to Float64Arrays for transfer to worker\n const hashChunkArrays = hashChunks.map(chunk => new Float64Array(chunk));\n\n sortedIndices = await workerManager.sortStringHashes(\n hashChunkArrays,\n direction,\n originalStrings\n );\n } else {\n // Use single-value sorting for numeric columns\n const values = processedData.map(row => {\n const val = getFieldValue(row, colId);\n return toSortableNumber(val);\n });\n sortedIndices = await workerManager.sortIndices(values, direction);\n }\n } else {\n // Multi-column sorting: use single hash per value (existing approach)\n const columnValues: number[][] = [];\n const directions: Array<\"asc\" | \"desc\"> = [];\n\n for (const { colId, direction } of request.sort) {\n const values = processedData.map(row => {\n const val = getFieldValue(row, colId);\n return toSortableNumber(val);\n });\n columnValues.push(values);\n directions.push(direction);\n }\n\n sortedIndices = await workerManager.sortMultiColumn(columnValues, directions);\n }\n\n // Reorder data using sorted indices\n const reordered = new Array<TData>(processedData.length);\n for (let i = 0; i < sortedIndices.length; i++) {\n reordered[i] = processedData[sortedIndices[i]!]!;\n }\n processedData = reordered;\n } else {\n // Use sync sorting for small datasets or when worker is unavailable\n processedData = applySort(processedData, request.sort, getFieldValue);\n }\n }\n\n const totalRows = processedData.length;\n\n // Apply pagination\n const { pageIndex, pageSize } = request.pagination;\n const startIndex = pageIndex * pageSize;\n const rows = processedData.slice(startIndex, startIndex + pageSize);\n\n return { rows, totalRows };\n },\n };\n}\n\n// =============================================================================\n// Server Data Source\n// =============================================================================\n\nexport type ServerFetchFunction<TData> = (\n request: DataSourceRequest\n) => Promise<DataSourceResponse<TData>>;\n\n/**\n * Creates a server-side data source that delegates all operations to the server.\n * The fetch function receives sort/filter/pagination params to pass to the API.\n */\nexport function createServerDataSource<TData extends Row = Row>(\n fetchFn: ServerFetchFunction<TData>\n): DataSource<TData> {\n return {\n async fetch(request: DataSourceRequest): Promise<DataSourceResponse<TData>> {\n return fetchFn(request);\n },\n };\n}\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Convert any cell value to a sortable number.\n * Strings are converted using a lexicographic hash of the first 8 characters.\n * This preserves sort order for strings that differ within the first 8 chars.\n */\nfunction toSortableNumber(val: CellValue): number {\n if (val == null) return Number.MAX_VALUE; // nulls sort last\n\n // Numbers pass through directly\n if (typeof val === \"number\") return val;\n\n // Dates convert to timestamp\n if (val instanceof Date) return val.getTime();\n\n // Strings: convert to lexicographic hash\n if (typeof val === \"string\") {\n return stringToSortableNumber(val);\n }\n\n // Fallback: try to convert to number\n const num = Number(val);\n return isNaN(num) ? 0 : num;\n}\n\n/**\n * Convert a string to a sortable number using first 10 characters.\n * Uses base 36 (alphanumeric) to fit more characters within float64 safe precision.\n * (36^10 ≈ 3.6×10¹⁵, within MAX_SAFE_INTEGER ~9×10¹⁵)\n * This allows sorting strings that share long prefixes (e.g., \"Person Giuseppe\" vs \"Person Giovanni\").\n */\nfunction stringToSortableNumber(str: string): number {\n const s = str.toLowerCase();\n const len = Math.min(s.length, 10);\n let hash = 0;\n\n // Pack characters into a number using base 36 encoding\n // Maps a-z to 0-25, 0-9 to 26-35, space/other to 0\n for (let i = 0; i < len; i++) {\n const code = s.charCodeAt(i);\n let mapped: number;\n if (code >= 97 && code <= 122) {\n // a-z -> 0-25\n mapped = code - 97;\n } else if (code >= 48 && code <= 57) {\n // 0-9 -> 26-35\n mapped = code - 48 + 26;\n } else {\n // space and other chars -> 0 (sorts first)\n mapped = 0;\n }\n hash = hash * 36 + mapped;\n }\n\n // Pad shorter strings to ensure \"a\" < \"ab\"\n for (let i = len; i < 10; i++) {\n hash = hash * 36;\n }\n\n return hash;\n}\n\n/**\n * Convert a string to multiple sortable hash values (one per 10-char chunk).\n * This allows correct sorting of strings longer than 10 characters.\n * Returns HASH_CHUNK_COUNT hashes, each covering 10 characters.\n */\nfunction stringToSortableHashes(str: string): number[] {\n const s = str.toLowerCase();\n const hashes: number[] = [];\n\n for (let chunk = 0; chunk < HASH_CHUNK_COUNT; chunk++) {\n const start = chunk * 10;\n let hash = 0;\n\n for (let i = 0; i < 10; i++) {\n const charIndex = start + i;\n const code = charIndex < s.length ? s.charCodeAt(charIndex) : 0;\n let mapped: number;\n if (code >= 97 && code <= 122) {\n // a-z -> 0-25\n mapped = code - 97;\n } else if (code >= 48 && code <= 57) {\n // 0-9 -> 26-35\n mapped = code - 48 + 26;\n } else {\n // space and other chars -> 0 (sorts first)\n mapped = 0;\n }\n hash = hash * 36 + mapped;\n }\n hashes.push(hash);\n }\n\n return hashes;\n}\n\nfunction defaultGetFieldValue<TData>(row: TData, field: string): CellValue {\n const parts = field.split(\".\");\n let value: unknown = row;\n\n for (const part of parts) {\n if (value == null || typeof value !== \"object\") {\n return null;\n }\n value = (value as Record<string, unknown>)[part];\n }\n\n return (value ?? null) as CellValue;\n}\n\nfunction applyFilters<TData>(\n data: TData[],\n filterModel: FilterModel,\n getFieldValue: (row: TData, field: string) => CellValue\n): TData[] {\n const filterEntries = Object.entries(filterModel).filter(([, value]) => value !== \"\");\n\n if (filterEntries.length === 0) {\n return data;\n }\n\n return data.filter((row) => {\n for (const [field, filterValue] of filterEntries) {\n const cellValue = getFieldValue(row, field);\n const cellStr = String(cellValue ?? \"\").toLowerCase();\n const filterStr = filterValue.toLowerCase();\n\n if (!cellStr.includes(filterStr)) {\n return false;\n }\n }\n return true;\n });\n}\n\nfunction applySort<TData>(\n data: TData[],\n sortModel: SortModel[],\n getFieldValue: (row: TData, field: string) => CellValue\n): TData[] {\n return [...data].sort((a, b) => {\n for (const { colId, direction } of sortModel) {\n const aVal = getFieldValue(a, colId);\n const bVal = getFieldValue(b, colId);\n const comparison = compareValues(aVal, bVal);\n\n if (comparison !== 0) {\n return direction === \"asc\" ? comparison : -comparison;\n }\n }\n return 0;\n });\n}\n\nfunction compareValues(a: CellValue, b: CellValue): number {\n // Null handling\n if (a == null && b == null) return 0;\n if (a == null) return 1;\n if (b == null) return -1;\n\n // Numeric comparison\n const aNum = Number(a);\n const bNum = Number(b);\n if (!isNaN(aNum) && !isNaN(bNum)) {\n return aNum - bNum;\n }\n\n // Date comparison\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() - b.getTime();\n }\n\n // String comparison\n return String(a).localeCompare(String(b));\n}\n\n// =============================================================================\n// Utility: Create Data Source from Array (Legacy Support)\n// =============================================================================\n\n/**\n * Convenience function to create a data source from an array.\n * This provides backwards compatibility with the old `rowData` prop.\n */\nexport function createDataSourceFromArray<TData extends Row = Row>(\n data: TData[]\n): DataSource<TData> {\n return createClientDataSource(data);\n}\n\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "gp-grid-core",
|
|
3
3
|
"description": "A high-performance, framework-agnostic TypeScript data grid core with virtual scrolling",
|
|
4
4
|
"private": false,
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.5",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|