@alaarab/ogrid-react 2.1.10 → 2.1.12
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/esm/index.js +172 -26
- package/dist/types/hooks/useDataGridInteraction.d.ts +2 -0
- package/dist/types/hooks/useDataGridTableOrchestration.d.ts +3 -0
- package/dist/types/hooks/useFillHandle.d.ts +2 -0
- package/dist/types/hooks/useKeyboardNavigation.d.ts +2 -0
- package/dist/types/hooks/useVirtualScroll.d.ts +6 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/types/dataGridTypes.d.ts +2 -0
- package/dist/types/utils/index.d.ts +1 -0
- package/package.json +2 -2
package/dist/esm/index.js
CHANGED
|
@@ -566,20 +566,31 @@ function processClientSideData(data, columns, filters, sortBy, sortDirection) {
|
|
|
566
566
|
if (Number.isNaN(bt)) return 1 * dir;
|
|
567
567
|
return at === bt ? 0 : at > bt ? dir : -dir;
|
|
568
568
|
});
|
|
569
|
-
} else {
|
|
569
|
+
} else if (!compare) {
|
|
570
|
+
const keyCache = /* @__PURE__ */ new Map();
|
|
571
|
+
for (let i = 0; i < sortable.length; i++) {
|
|
572
|
+
const row = sortable[i];
|
|
573
|
+
const v = sortCol ? getCellValue(row, sortCol) : row[sortBy];
|
|
574
|
+
if (v == null) {
|
|
575
|
+
keyCache.set(row, void 0);
|
|
576
|
+
} else if (typeof v === "number") {
|
|
577
|
+
keyCache.set(row, v);
|
|
578
|
+
} else {
|
|
579
|
+
keyCache.set(row, String(v).toLowerCase());
|
|
580
|
+
}
|
|
581
|
+
}
|
|
570
582
|
sortable.sort((a, b) => {
|
|
571
|
-
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
if (av
|
|
575
|
-
if (
|
|
576
|
-
if (bv == null) return 1 * dir;
|
|
583
|
+
const av = keyCache.get(a);
|
|
584
|
+
const bv = keyCache.get(b);
|
|
585
|
+
if (av === void 0 && bv === void 0) return 0;
|
|
586
|
+
if (av === void 0) return -1 * dir;
|
|
587
|
+
if (bv === void 0) return 1 * dir;
|
|
577
588
|
if (typeof av === "number" && typeof bv === "number")
|
|
578
589
|
return av === bv ? 0 : av > bv ? dir : -dir;
|
|
579
|
-
|
|
580
|
-
const bs = String(bv).toLowerCase();
|
|
581
|
-
return as === bs ? 0 : as > bs ? dir : -dir;
|
|
590
|
+
return av === bv ? 0 : av > bv ? dir : -dir;
|
|
582
591
|
});
|
|
592
|
+
} else {
|
|
593
|
+
sortable.sort((a, b) => compare(a, b) * dir);
|
|
583
594
|
}
|
|
584
595
|
return sortable;
|
|
585
596
|
}
|
|
@@ -735,7 +746,77 @@ function getHeaderFilterConfig(col, input) {
|
|
|
735
746
|
}
|
|
736
747
|
return base;
|
|
737
748
|
}
|
|
738
|
-
|
|
749
|
+
var _CellDescriptorCache = class _CellDescriptorCache2 {
|
|
750
|
+
constructor() {
|
|
751
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
752
|
+
this.lastVersion = "";
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Compute a version string from the volatile parts of CellRenderDescriptorInput.
|
|
756
|
+
* This string changes whenever any input that affects per-cell output changes.
|
|
757
|
+
* Cheap to compute (simple string concat) — O(1) regardless of grid size.
|
|
758
|
+
*/
|
|
759
|
+
static computeVersion(input) {
|
|
760
|
+
const ec = input.editingCell;
|
|
761
|
+
const ac = input.activeCell;
|
|
762
|
+
const sr = input.selectionRange;
|
|
763
|
+
const cr = input.cutRange;
|
|
764
|
+
const cp = input.copyRange;
|
|
765
|
+
return (ec ? `${String(ec.rowId)}\0${ec.columnId}` : "") + "" + (ac ? `${ac.rowIndex}\0${ac.columnIndex}` : "") + "" + (sr ? `${sr.startRow}\0${sr.startCol}\0${sr.endRow}\0${sr.endCol}` : "") + "" + (cr ? `${cr.startRow}\0${cr.startCol}\0${cr.endRow}\0${cr.endCol}` : "") + "" + (cp ? `${cp.startRow}\0${cp.startCol}\0${cp.endRow}\0${cp.endCol}` : "") + "" + (input.isDragging ? "1" : "0") + "" + (input.editable !== false ? "1" : "0") + "" + (input.onCellValueChanged ? "1" : "0");
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Get a cached descriptor or compute a new one.
|
|
769
|
+
*
|
|
770
|
+
* @param rowIndex - Row index in the dataset.
|
|
771
|
+
* @param colIdx - Column index within the visible columns.
|
|
772
|
+
* @param version - Volatile version string (from CellDescriptorCache.computeVersion).
|
|
773
|
+
* @param compute - Factory function called on cache miss.
|
|
774
|
+
* @returns The descriptor (cached or freshly computed).
|
|
775
|
+
*/
|
|
776
|
+
get(rowIndex, colIdx, version, compute) {
|
|
777
|
+
const key = rowIndex * _CellDescriptorCache2.MAX_COL_STRIDE + colIdx;
|
|
778
|
+
const entry = this.cache.get(key);
|
|
779
|
+
if (entry !== void 0 && entry.version === version) {
|
|
780
|
+
return entry.descriptor;
|
|
781
|
+
}
|
|
782
|
+
const descriptor = compute();
|
|
783
|
+
this.cache.set(key, { version, descriptor });
|
|
784
|
+
return descriptor;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Update the last-seen version and return it.
|
|
788
|
+
* Call once per render pass to track whether any volatile state changed.
|
|
789
|
+
* If the version is unchanged from last render, the entire render is a no-op for all cells.
|
|
790
|
+
*/
|
|
791
|
+
updateVersion(version) {
|
|
792
|
+
this.lastVersion = version;
|
|
793
|
+
}
|
|
794
|
+
/** The last version string set via updateVersion(). */
|
|
795
|
+
get currentVersion() {
|
|
796
|
+
return this.lastVersion;
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Clear all cached entries. Call when the grid's data changes (new items array,
|
|
800
|
+
* different column count, etc.) to prevent stale cell values from being served.
|
|
801
|
+
*/
|
|
802
|
+
clear() {
|
|
803
|
+
this.cache.clear();
|
|
804
|
+
}
|
|
805
|
+
};
|
|
806
|
+
_CellDescriptorCache.MAX_COL_STRIDE = 1024;
|
|
807
|
+
var CellDescriptorCache = _CellDescriptorCache;
|
|
808
|
+
function getCellRenderDescriptor(item, col, rowIndex, colIdx, input, cache) {
|
|
809
|
+
if (cache !== void 0) {
|
|
810
|
+
return cache.get(
|
|
811
|
+
rowIndex,
|
|
812
|
+
colIdx,
|
|
813
|
+
cache.currentVersion,
|
|
814
|
+
() => computeCellDescriptor(item, col, rowIndex, colIdx, input)
|
|
815
|
+
);
|
|
816
|
+
}
|
|
817
|
+
return computeCellDescriptor(item, col, rowIndex, colIdx, input);
|
|
818
|
+
}
|
|
819
|
+
function computeCellDescriptor(item, col, rowIndex, colIdx, input) {
|
|
739
820
|
const rowId = input.getRowId(item);
|
|
740
821
|
const globalColIndex = colIdx + input.colOffset;
|
|
741
822
|
const colEditable = isColumnEditable(col, item);
|
|
@@ -1291,6 +1372,7 @@ function validateColumns(columns) {
|
|
|
1291
1372
|
console.warn("[OGrid] columns prop is empty or not an array");
|
|
1292
1373
|
return;
|
|
1293
1374
|
}
|
|
1375
|
+
const isDev = typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
1294
1376
|
const ids = /* @__PURE__ */ new Set();
|
|
1295
1377
|
for (const col of columns) {
|
|
1296
1378
|
if (!col.columnId) {
|
|
@@ -1300,10 +1382,25 @@ function validateColumns(columns) {
|
|
|
1300
1382
|
console.warn(`[OGrid] Duplicate columnId: "${col.columnId}"`);
|
|
1301
1383
|
}
|
|
1302
1384
|
ids.add(col.columnId);
|
|
1385
|
+
if (isDev && col.editable === true && col.cellEditor == null) {
|
|
1386
|
+
console.warn(
|
|
1387
|
+
`[OGrid] Column "${col.columnId}" has editable=true but no cellEditor defined. Cells will not open an editor on double-click. Set cellEditor to 'text', 'select', 'checkbox', 'date', or a custom component.`
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
function validateVirtualScrollConfig(config) {
|
|
1393
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") return;
|
|
1394
|
+
if (config.enabled !== true) return;
|
|
1395
|
+
if (!config.rowHeight || config.rowHeight <= 0) {
|
|
1396
|
+
console.warn(
|
|
1397
|
+
"[OGrid] virtualScroll.enabled is true but rowHeight is missing or <= 0. Set a positive rowHeight (e.g. virtualScroll: { enabled: true, rowHeight: 36 }) for correct virtual scrolling behavior."
|
|
1398
|
+
);
|
|
1303
1399
|
}
|
|
1304
1400
|
}
|
|
1305
1401
|
function validateRowIds(items, getRowId) {
|
|
1306
1402
|
if (typeof process !== "undefined" && process.env.NODE_ENV === "production") return;
|
|
1403
|
+
if (!getRowId) return;
|
|
1307
1404
|
const ids = /* @__PURE__ */ new Set();
|
|
1308
1405
|
const limit = Math.min(items.length, 100);
|
|
1309
1406
|
for (let i = 0; i < limit; i++) {
|
|
@@ -2690,7 +2787,11 @@ function useKeyboardNavigation(params) {
|
|
|
2690
2787
|
const { items, visibleCols, colOffset, hasCheckboxCol, visibleColumnCount, getRowId } = data;
|
|
2691
2788
|
const { activeCell, selectionRange, editingCell, selectedRowIds } = state;
|
|
2692
2789
|
const { setActiveCell, setSelectionRange, setEditingCell, handleRowCheckboxChange, handleCopy, handleCut, handlePaste, setContextMenu, onUndo, onRedo, clearClipboardRanges } = handlers;
|
|
2693
|
-
const { editable, onCellValueChanged, rowSelection, wrapperRef } = features;
|
|
2790
|
+
const { editable, onCellValueChanged, rowSelection, wrapperRef, onKeyDown, fillDown } = features;
|
|
2791
|
+
if (onKeyDown) {
|
|
2792
|
+
onKeyDown(e);
|
|
2793
|
+
if (e.defaultPrevented) return;
|
|
2794
|
+
}
|
|
2694
2795
|
const maxRowIndex = items.length - 1;
|
|
2695
2796
|
const maxColIndex = visibleColumnCount - 1 + colOffset;
|
|
2696
2797
|
if (items.length === 0) return;
|
|
@@ -2879,6 +2980,15 @@ function useKeyboardNavigation(params) {
|
|
|
2879
2980
|
}
|
|
2880
2981
|
}
|
|
2881
2982
|
break;
|
|
2983
|
+
case "d":
|
|
2984
|
+
if (e.ctrlKey || e.metaKey) {
|
|
2985
|
+
if (editingCell != null) break;
|
|
2986
|
+
if (editable !== false && fillDown) {
|
|
2987
|
+
e.preventDefault();
|
|
2988
|
+
fillDown();
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
break;
|
|
2882
2992
|
case "Delete":
|
|
2883
2993
|
case "Backspace": {
|
|
2884
2994
|
if (editingCell != null) break;
|
|
@@ -3170,7 +3280,26 @@ function useFillHandle(params) {
|
|
|
3170
3280
|
},
|
|
3171
3281
|
[]
|
|
3172
3282
|
);
|
|
3173
|
-
|
|
3283
|
+
const itemsRef = useLatestRef(items);
|
|
3284
|
+
const visibleColsRef = useLatestRef(visibleCols);
|
|
3285
|
+
const fillDown = useCallback(() => {
|
|
3286
|
+
const range = selectionRangeRef.current;
|
|
3287
|
+
if (!range || editable === false || !onCellValueChangedRef.current) return;
|
|
3288
|
+
const norm = normalizeSelectionRange(range);
|
|
3289
|
+
const fillEvents = applyFillValues(
|
|
3290
|
+
norm,
|
|
3291
|
+
norm.startRow,
|
|
3292
|
+
norm.startCol,
|
|
3293
|
+
itemsRef.current,
|
|
3294
|
+
visibleColsRef.current
|
|
3295
|
+
);
|
|
3296
|
+
if (fillEvents.length > 0) {
|
|
3297
|
+
beginBatch?.();
|
|
3298
|
+
for (const evt of fillEvents) onCellValueChangedRef.current(evt);
|
|
3299
|
+
endBatch?.();
|
|
3300
|
+
}
|
|
3301
|
+
}, [editable, beginBatch, endBatch]);
|
|
3302
|
+
return { fillDrag, setFillDrag, handleFillHandleMouseDown, fillDown };
|
|
3174
3303
|
}
|
|
3175
3304
|
function useTableLayout(params) {
|
|
3176
3305
|
const {
|
|
@@ -3710,7 +3839,8 @@ function useDataGridInteraction(params) {
|
|
|
3710
3839
|
setActiveCell,
|
|
3711
3840
|
handleRowCheckboxChange,
|
|
3712
3841
|
setContextMenuPosition,
|
|
3713
|
-
wrapperRef
|
|
3842
|
+
wrapperRef,
|
|
3843
|
+
onKeyDown
|
|
3714
3844
|
} = params;
|
|
3715
3845
|
const undoRedo = useUndoRedo({ onCellValueChanged: onCellValueChangedProp });
|
|
3716
3846
|
const onCellValueChanged = undoRedo.onCellValueChanged;
|
|
@@ -3747,13 +3877,7 @@ function useDataGridInteraction(params) {
|
|
|
3747
3877
|
},
|
|
3748
3878
|
[handleCellMouseDownBase, clearClipboardRanges, wrapperRef]
|
|
3749
3879
|
);
|
|
3750
|
-
const {
|
|
3751
|
-
data: { items, visibleCols, colOffset, hasCheckboxCol, visibleColumnCount, getRowId },
|
|
3752
|
-
state: { activeCell, selectionRange, editingCell, selectedRowIds },
|
|
3753
|
-
handlers: { setActiveCell, setSelectionRange, setEditingCell, handleRowCheckboxChange, handleCopy, handleCut, handlePaste, setContextMenu: setContextMenuPosition, onUndo: undoRedo.undo, onRedo: undoRedo.redo, clearClipboardRanges },
|
|
3754
|
-
features: { editable, onCellValueChanged, rowSelection: rowSelection ?? "none", wrapperRef }
|
|
3755
|
-
});
|
|
3756
|
-
const { handleFillHandleMouseDown } = useFillHandle({
|
|
3880
|
+
const { handleFillHandleMouseDown, fillDown } = useFillHandle({
|
|
3757
3881
|
items,
|
|
3758
3882
|
visibleCols,
|
|
3759
3883
|
editable,
|
|
@@ -3766,6 +3890,12 @@ function useDataGridInteraction(params) {
|
|
|
3766
3890
|
beginBatch: undoRedo.beginBatch,
|
|
3767
3891
|
endBatch: undoRedo.endBatch
|
|
3768
3892
|
});
|
|
3893
|
+
const { handleGridKeyDown } = useKeyboardNavigation({
|
|
3894
|
+
data: { items, visibleCols, colOffset, hasCheckboxCol, visibleColumnCount, getRowId },
|
|
3895
|
+
state: { activeCell, selectionRange, editingCell, selectedRowIds },
|
|
3896
|
+
handlers: { setActiveCell, setSelectionRange, setEditingCell, handleRowCheckboxChange, handleCopy, handleCut, handlePaste, setContextMenu: setContextMenuPosition, onUndo: undoRedo.undo, onRedo: undoRedo.redo, clearClipboardRanges },
|
|
3897
|
+
features: { editable, onCellValueChanged, rowSelection: rowSelection ?? "none", wrapperRef, onKeyDown, fillDown }
|
|
3898
|
+
});
|
|
3769
3899
|
const hasCellSelection = selectionRange != null || activeCell != null;
|
|
3770
3900
|
const interactionState = useMemo(() => ({
|
|
3771
3901
|
activeCell: cellSelection ? activeCell : null,
|
|
@@ -3867,7 +3997,8 @@ function useDataGridState(params) {
|
|
|
3867
3997
|
onAutosizeColumn,
|
|
3868
3998
|
pinnedColumns,
|
|
3869
3999
|
onColumnPinned,
|
|
3870
|
-
onCellError
|
|
4000
|
+
onCellError,
|
|
4001
|
+
onKeyDown
|
|
3871
4002
|
} = props;
|
|
3872
4003
|
const cellSelection = cellSelectionProp !== false;
|
|
3873
4004
|
const {
|
|
@@ -3936,7 +4067,8 @@ function useDataGridState(params) {
|
|
|
3936
4067
|
setActiveCell,
|
|
3937
4068
|
handleRowCheckboxChange,
|
|
3938
4069
|
setContextMenuPosition,
|
|
3939
|
-
wrapperRef
|
|
4070
|
+
wrapperRef,
|
|
4071
|
+
onKeyDown
|
|
3940
4072
|
});
|
|
3941
4073
|
const {
|
|
3942
4074
|
selectionRange,
|
|
@@ -5771,16 +5903,20 @@ function useVirtualizer(options) {
|
|
|
5771
5903
|
}
|
|
5772
5904
|
|
|
5773
5905
|
// src/hooks/useVirtualScroll.ts
|
|
5774
|
-
var
|
|
5906
|
+
var DEFAULT_PASSTHROUGH_THRESHOLD = 100;
|
|
5775
5907
|
function useVirtualScroll(params) {
|
|
5776
5908
|
const {
|
|
5777
5909
|
totalRows,
|
|
5778
5910
|
rowHeight,
|
|
5779
5911
|
enabled,
|
|
5780
5912
|
overscan = 5,
|
|
5913
|
+
threshold = DEFAULT_PASSTHROUGH_THRESHOLD,
|
|
5781
5914
|
containerRef
|
|
5782
5915
|
} = params;
|
|
5783
|
-
|
|
5916
|
+
useEffect(() => {
|
|
5917
|
+
validateVirtualScrollConfig({ enabled, rowHeight });
|
|
5918
|
+
}, []);
|
|
5919
|
+
const isActive = enabled && totalRows >= threshold;
|
|
5784
5920
|
const getScrollElement = useCallback(
|
|
5785
5921
|
() => containerRef.current,
|
|
5786
5922
|
[containerRef]
|
|
@@ -5954,6 +6090,7 @@ function useDataGridTableOrchestration(params) {
|
|
|
5954
6090
|
rowHeight: virtualRowHeight,
|
|
5955
6091
|
enabled: virtualScrollEnabled,
|
|
5956
6092
|
overscan: virtualScroll?.overscan,
|
|
6093
|
+
threshold: virtualScroll?.threshold,
|
|
5957
6094
|
containerRef: wrapperRef
|
|
5958
6095
|
});
|
|
5959
6096
|
const editCallbacks = useMemo(
|
|
@@ -5968,6 +6105,14 @@ function useDataGridTableOrchestration(params) {
|
|
|
5968
6105
|
const pendingEditorValueRef = useLatestRef(pendingEditorValue);
|
|
5969
6106
|
const popoverAnchorElRef = useLatestRef(popoverAnchorEl);
|
|
5970
6107
|
const selectedRowIdsRef = useLatestRef(selectedRowIds);
|
|
6108
|
+
const cellDescriptorCacheRef = useRef(new CellDescriptorCache());
|
|
6109
|
+
const currentVersion = CellDescriptorCache.computeVersion(cellDescriptorInput);
|
|
6110
|
+
cellDescriptorCacheRef.current.updateVersion(currentVersion);
|
|
6111
|
+
const prevItemsRef = useRef(items);
|
|
6112
|
+
if (prevItemsRef.current !== items) {
|
|
6113
|
+
prevItemsRef.current = items;
|
|
6114
|
+
cellDescriptorCacheRef.current.clear();
|
|
6115
|
+
}
|
|
5971
6116
|
const handleSingleRowClick = useCallback((e) => {
|
|
5972
6117
|
if (rowSelection !== "single") return;
|
|
5973
6118
|
const rowId = e.currentTarget.dataset.rowId;
|
|
@@ -6030,6 +6175,7 @@ function useDataGridTableOrchestration(params) {
|
|
|
6030
6175
|
interactionHandlers,
|
|
6031
6176
|
// Stable refs for volatile state
|
|
6032
6177
|
cellDescriptorInputRef,
|
|
6178
|
+
cellDescriptorCacheRef,
|
|
6033
6179
|
pendingEditorValueRef,
|
|
6034
6180
|
popoverAnchorElRef,
|
|
6035
6181
|
selectedRowIdsRef,
|
|
@@ -7300,4 +7446,4 @@ function renderFilterContent(filterType, state, options, isLoadingOptions, selec
|
|
|
7300
7446
|
return null;
|
|
7301
7447
|
}
|
|
7302
7448
|
|
|
7303
|
-
export { BaseColumnHeaderMenu, BaseDropIndicator, BaseEmptyState, BaseInlineCellEditor, BaseLoadingOverlay, CELL_PADDING, CHECKBOX_COLUMN_WIDTH, COLUMN_HEADER_MENU_ITEMS, CURSOR_CELL_STYLE, CellErrorBoundary, DEFAULT_MIN_COLUMN_WIDTH, DateFilterContent, EmptyState, GRID_BORDER_RADIUS, GRID_CONTEXT_MENU_ITEMS, GRID_ROOT_STYLE, GridContextMenu, MAX_PAGE_BUTTONS, MarchingAntsOverlay, NOOP3 as NOOP, OGridLayout, PAGE_SIZE_OPTIONS, POPOVER_ANCHOR_STYLE, PREVENT_DEFAULT, ROW_NUMBER_COLUMN_WIDTH, STOP_PROPAGATION, SideBar, StatusBar, UndoRedoStack, areGridRowPropsEqual, booleanParser, buildCsvHeader, buildCsvRows, buildHeaderRows, buildInlineEditorProps2 as buildInlineEditorProps, buildPopoverEditorProps2 as buildPopoverEditorProps, clampSelectionToBounds, computeAggregations, computeAutoScrollSpeed, computeTabNavigation, createOGrid, currencyParser, dateParser, deriveFilterOptionsFromData, editorInputStyle, editorWrapperStyle, emailParser, escapeCsvValue, exportToCsv, findCtrlArrowTarget, flattenColumns, formatCellValueForTsv, formatSelectionAsTsv, formatShortcut, getCellInteractionProps, getCellRenderDescriptor, getCellValue, getColumnHeaderFilterStateParams, getColumnHeaderMenuItems, getContextMenuHandlers, getDataGridStatusBarConfig, getDateFilterContentProps, getFilterField, getHeaderFilterConfig, getMultiSelectFilterFields, getPaginationViewModel, getStatusBarParts, isInSelectionRange, isRowInRange, mergeFilter, normalizeSelectionRange, numberParser, parseTsvClipboard, parseValue, processClientSideData, rangesEqual, renderFilterContent, resolveCellDisplayContent2 as resolveCellDisplayContent, resolveCellStyle2 as resolveCellStyle, richSelectDropdownStyle, richSelectNoMatchesStyle, richSelectOptionHighlightedStyle, richSelectOptionStyle, richSelectWrapperStyle, selectChevronStyle, selectDisplayStyle, selectEditorStyle, toUserLike, triggerCsvDownload, useActiveCell, useCellEditing, useCellSelection, useClipboard, useColumnChooserState, useColumnHeaderFilterState, useColumnMeta, useColumnReorder, useColumnResize, useContextMenu, useDataGridState, useDataGridTableOrchestration, useDateFilterState, useDebounce, useFillHandle, useFilterOptions, useInlineCellEditorState, useKeyboardNavigation, useLatestRef, useListVirtualizer, useMultiSelectFilterState, useOGrid, usePaginationControls, usePeopleFilterState, useRichSelectState, useRowSelection, useSelectState, useSideBarState, useTableLayout, useTextFilterState, useUndoRedo, useVirtualScroll };
|
|
7449
|
+
export { BaseColumnHeaderMenu, BaseDropIndicator, BaseEmptyState, BaseInlineCellEditor, BaseLoadingOverlay, CELL_PADDING, CHECKBOX_COLUMN_WIDTH, COLUMN_HEADER_MENU_ITEMS, CURSOR_CELL_STYLE, CellDescriptorCache, CellErrorBoundary, DEFAULT_MIN_COLUMN_WIDTH, DateFilterContent, EmptyState, GRID_BORDER_RADIUS, GRID_CONTEXT_MENU_ITEMS, GRID_ROOT_STYLE, GridContextMenu, MAX_PAGE_BUTTONS, MarchingAntsOverlay, NOOP3 as NOOP, OGridLayout, PAGE_SIZE_OPTIONS, POPOVER_ANCHOR_STYLE, PREVENT_DEFAULT, ROW_NUMBER_COLUMN_WIDTH, STOP_PROPAGATION, SideBar, StatusBar, UndoRedoStack, areGridRowPropsEqual, booleanParser, buildCsvHeader, buildCsvRows, buildHeaderRows, buildInlineEditorProps2 as buildInlineEditorProps, buildPopoverEditorProps2 as buildPopoverEditorProps, clampSelectionToBounds, computeAggregations, computeAutoScrollSpeed, computeTabNavigation, createOGrid, currencyParser, dateParser, deriveFilterOptionsFromData, editorInputStyle, editorWrapperStyle, emailParser, escapeCsvValue, exportToCsv, findCtrlArrowTarget, flattenColumns, formatCellValueForTsv, formatSelectionAsTsv, formatShortcut, getCellInteractionProps, getCellRenderDescriptor, getCellValue, getColumnHeaderFilterStateParams, getColumnHeaderMenuItems, getContextMenuHandlers, getDataGridStatusBarConfig, getDateFilterContentProps, getFilterField, getHeaderFilterConfig, getMultiSelectFilterFields, getPaginationViewModel, getStatusBarParts, isInSelectionRange, isRowInRange, mergeFilter, normalizeSelectionRange, numberParser, parseTsvClipboard, parseValue, processClientSideData, rangesEqual, renderFilterContent, resolveCellDisplayContent2 as resolveCellDisplayContent, resolveCellStyle2 as resolveCellStyle, richSelectDropdownStyle, richSelectNoMatchesStyle, richSelectOptionHighlightedStyle, richSelectOptionStyle, richSelectWrapperStyle, selectChevronStyle, selectDisplayStyle, selectEditorStyle, toUserLike, triggerCsvDownload, useActiveCell, useCellEditing, useCellSelection, useClipboard, useColumnChooserState, useColumnHeaderFilterState, useColumnMeta, useColumnReorder, useColumnResize, useContextMenu, useDataGridState, useDataGridTableOrchestration, useDateFilterState, useDebounce, useFillHandle, useFilterOptions, useInlineCellEditorState, useKeyboardNavigation, useLatestRef, useListVirtualizer, useMultiSelectFilterState, useOGrid, usePaginationControls, usePeopleFilterState, useRichSelectState, useRowSelection, useSelectState, useSideBarState, useTableLayout, useTextFilterState, useUndoRedo, useVirtualScroll };
|
|
@@ -45,6 +45,8 @@ export interface UseDataGridInteractionParams<T> {
|
|
|
45
45
|
y: number;
|
|
46
46
|
} | null) => void;
|
|
47
47
|
wrapperRef: RefObject<HTMLDivElement | null>;
|
|
48
|
+
/** Custom keydown handler — called before grid default. preventDefault() suppresses grid handling. */
|
|
49
|
+
onKeyDown?: (event: React.KeyboardEvent) => void;
|
|
48
50
|
}
|
|
49
51
|
export interface UseDataGridInteractionResult<T> {
|
|
50
52
|
interaction: DataGridCellInteractionState;
|
|
@@ -6,6 +6,7 @@ import type { UseColumnReorderResult } from './useColumnReorder';
|
|
|
6
6
|
import type { UseVirtualScrollResult } from './useVirtualScroll';
|
|
7
7
|
import type { HeaderFilterConfigInput, CellRenderDescriptorInput } from '../utils';
|
|
8
8
|
import type { IStatusBarProps, RowId, HeaderRow } from '../types';
|
|
9
|
+
import { CellDescriptorCache } from '@alaarab/ogrid-core';
|
|
9
10
|
/** Parameters for the orchestration hook. */
|
|
10
11
|
export interface UseDataGridTableOrchestrationParams<T> {
|
|
11
12
|
props: IOGridDataGridProps<T>;
|
|
@@ -67,6 +68,8 @@ export interface UseDataGridTableOrchestrationResult<T> {
|
|
|
67
68
|
handleCellContextMenu: DataGridContextMenuState['handleCellContextMenu'];
|
|
68
69
|
};
|
|
69
70
|
cellDescriptorInputRef: React.MutableRefObject<CellRenderDescriptorInput<T>>;
|
|
71
|
+
/** Per-grid descriptor cache. Eliminates redundant getCellRenderDescriptor allocations for unchanged cells. */
|
|
72
|
+
cellDescriptorCacheRef: React.MutableRefObject<CellDescriptorCache>;
|
|
70
73
|
pendingEditorValueRef: React.MutableRefObject<unknown>;
|
|
71
74
|
popoverAnchorElRef: React.MutableRefObject<HTMLElement | null>;
|
|
72
75
|
selectedRowIdsRef: React.MutableRefObject<Set<RowId>>;
|
|
@@ -24,6 +24,8 @@ export interface UseFillHandleResult {
|
|
|
24
24
|
startCol: number;
|
|
25
25
|
} | null) => void;
|
|
26
26
|
handleFillHandleMouseDown: (e: React.MouseEvent) => void;
|
|
27
|
+
/** Fill the current selection down from the top row (Ctrl+D). No-op if no selection or editable=false. */
|
|
28
|
+
fillDown: () => void;
|
|
27
29
|
}
|
|
28
30
|
/**
|
|
29
31
|
* Manages Excel-style fill handle drag-to-fill for cell ranges.
|
|
@@ -34,6 +34,8 @@ export interface UseKeyboardNavigationParams<T> {
|
|
|
34
34
|
onCellValueChanged: ((event: ICellValueChangedEvent<T>) => void) | undefined;
|
|
35
35
|
rowSelection: RowSelectionMode;
|
|
36
36
|
wrapperRef: React.RefObject<HTMLElement | null>;
|
|
37
|
+
onKeyDown?: (event: React.KeyboardEvent) => void;
|
|
38
|
+
fillDown?: () => void;
|
|
37
39
|
};
|
|
38
40
|
}
|
|
39
41
|
export interface UseKeyboardNavigationResult {
|
|
@@ -11,6 +11,11 @@ export interface UseVirtualScrollParams {
|
|
|
11
11
|
enabled: boolean;
|
|
12
12
|
/** Number of extra rows to render outside the visible area. Default: 5. */
|
|
13
13
|
overscan?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Minimum row count before virtual scrolling activates. Default: 100.
|
|
16
|
+
* When totalRows < threshold, all rows render without virtualization.
|
|
17
|
+
*/
|
|
18
|
+
threshold?: number;
|
|
14
19
|
/** Ref to the scrollable container element. */
|
|
15
20
|
containerRef: RefObject<HTMLElement | null>;
|
|
16
21
|
}
|
|
@@ -27,7 +32,7 @@ export interface UseVirtualScrollResult {
|
|
|
27
32
|
/**
|
|
28
33
|
* Wraps TanStack Virtual for row virtualization.
|
|
29
34
|
* When disabled or when totalRows < threshold, returns a pass-through (all rows visible).
|
|
30
|
-
* @param params - Total rows, row height, enabled flag, overscan, and container ref.
|
|
35
|
+
* @param params - Total rows, row height, enabled flag, overscan, threshold, and container ref.
|
|
31
36
|
* @returns Virtualizer instance, total height, visible range, and scrollToIndex helper.
|
|
32
37
|
*/
|
|
33
38
|
export declare function useVirtualScroll(params: UseVirtualScrollParams): UseVirtualScrollResult;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export { BaseDropIndicator } from './components/BaseDropIndicator';
|
|
|
32
32
|
export type { BaseDropIndicatorProps } from './components/BaseDropIndicator';
|
|
33
33
|
export { DateFilterContent, getColumnHeaderFilterStateParams, getDateFilterContentProps, } from './components/ColumnHeaderFilterContent';
|
|
34
34
|
export type { IColumnHeaderFilterProps, DateFilterContentProps, DateFilterClassNames, } from './components/ColumnHeaderFilterContent';
|
|
35
|
-
export { escapeCsvValue, buildCsvHeader, buildCsvRows, exportToCsv, triggerCsvDownload, getCellValue, flattenColumns, buildHeaderRows, getFilterField, mergeFilter, deriveFilterOptionsFromData, getMultiSelectFilterFields, getStatusBarParts, getDataGridStatusBarConfig, GRID_CONTEXT_MENU_ITEMS, COLUMN_HEADER_MENU_ITEMS, getContextMenuHandlers, getColumnHeaderMenuItems, formatShortcut, getPaginationViewModel, PAGE_SIZE_OPTIONS, MAX_PAGE_BUTTONS, getHeaderFilterConfig, getCellRenderDescriptor, isRowInRange, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, getCellInteractionProps, parseValue, numberParser, currencyParser, dateParser, emailParser, booleanParser, computeAggregations, processClientSideData, areGridRowPropsEqual, findCtrlArrowTarget, computeTabNavigation, rangesEqual, clampSelectionToBounds, computeAutoScrollSpeed, formatCellValueForTsv, formatSelectionAsTsv, parseTsvClipboard, UndoRedoStack, } from './utils';
|
|
35
|
+
export { escapeCsvValue, buildCsvHeader, buildCsvRows, exportToCsv, triggerCsvDownload, getCellValue, flattenColumns, buildHeaderRows, getFilterField, mergeFilter, deriveFilterOptionsFromData, getMultiSelectFilterFields, getStatusBarParts, getDataGridStatusBarConfig, GRID_CONTEXT_MENU_ITEMS, COLUMN_HEADER_MENU_ITEMS, getContextMenuHandlers, getColumnHeaderMenuItems, formatShortcut, getPaginationViewModel, PAGE_SIZE_OPTIONS, MAX_PAGE_BUTTONS, getHeaderFilterConfig, getCellRenderDescriptor, CellDescriptorCache, isRowInRange, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, getCellInteractionProps, parseValue, numberParser, currencyParser, dateParser, emailParser, booleanParser, computeAggregations, processClientSideData, areGridRowPropsEqual, findCtrlArrowTarget, computeTabNavigation, rangesEqual, clampSelectionToBounds, computeAutoScrollSpeed, formatCellValueForTsv, formatSelectionAsTsv, parseTsvClipboard, UndoRedoStack, } from './utils';
|
|
36
36
|
export type { CsvColumn, StatusBarPart, StatusBarPartsInput, GridContextMenuItem, GridContextMenuHandlerProps, PaginationViewModel, HeaderFilterConfigInput, HeaderFilterConfig, CellRenderDescriptorInput, CellRenderDescriptor, CellRenderMode, CellInteractionHandlers, ParseValueResult, AggregationResult, GridRowComparatorProps, IColumnHeaderMenuItem, ColumnHeaderMenuInput, ColumnHeaderMenuHandlers, } from './utils';
|
|
37
37
|
export { renderFilterContent } from './components/ColumnHeaderFilterRenderers';
|
|
38
38
|
export type { FilterContentRenderers, MultiSelectRendererProps, TextRendererProps, PeopleRendererProps, DateRendererProps, } from './components/ColumnHeaderFilterRenderers';
|
|
@@ -175,4 +175,6 @@ export interface IOGridDataGridProps<T> {
|
|
|
175
175
|
onCellError?: (error: Error, errorInfo: React.ErrorInfo) => void;
|
|
176
176
|
'aria-label'?: string;
|
|
177
177
|
'aria-labelledby'?: string;
|
|
178
|
+
/** Custom keydown handler. Called before grid's built-in handling. Call event.preventDefault() to suppress grid default. */
|
|
179
|
+
onKeyDown?: (event: React.KeyboardEvent) => void;
|
|
178
180
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { escapeCsvValue, buildCsvHeader, buildCsvRows, exportToCsv, triggerCsvDownload, getCellValue, flattenColumns, buildHeaderRows, getFilterField, mergeFilter, deriveFilterOptionsFromData, getMultiSelectFilterFields, getStatusBarParts, getDataGridStatusBarConfig, getPaginationViewModel, PAGE_SIZE_OPTIONS, MAX_PAGE_BUTTONS, GRID_CONTEXT_MENU_ITEMS, COLUMN_HEADER_MENU_ITEMS, getContextMenuHandlers, getColumnHeaderMenuItems, formatShortcut, parseValue, numberParser, currencyParser, dateParser, emailParser, booleanParser, computeAggregations, processClientSideData, computeNextSortState, measureColumnContentWidth, AUTOSIZE_EXTRA_PX, AUTOSIZE_MAX_PX, findCtrlArrowTarget, computeTabNavigation, rangesEqual, clampSelectionToBounds, computeAutoScrollSpeed, formatCellValueForTsv, formatSelectionAsTsv, parseTsvClipboard, applyPastedValues, applyCutClear, applyFillValues, computeArrowNavigation, applyCellDeletion, applyRangeRowSelection, computeRowSelectionState, UndoRedoStack, buildCellIndex, } from '@alaarab/ogrid-core';
|
|
2
2
|
export type { CsvColumn, StatusBarPart, StatusBarPartsInput, GridContextMenuItem, GridContextMenuHandlerProps, PaginationViewModel, ParseValueResult, AggregationResult, IColumnHeaderMenuItem, ColumnHeaderMenuInput, ColumnHeaderMenuHandlers, ArrowNavigationContext, ArrowNavigationResult, } from '@alaarab/ogrid-core';
|
|
3
3
|
export { getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, getCellInteractionProps, } from './dataGridViewModel';
|
|
4
|
+
export { CellDescriptorCache } from '@alaarab/ogrid-core';
|
|
4
5
|
export type { HeaderFilterConfigInput, HeaderFilterConfig, CellRenderDescriptorInput, CellRenderDescriptor, CellRenderMode, CellInteractionHandlers, } from './dataGridViewModel';
|
|
5
6
|
export { areGridRowPropsEqual, isRowInRange } from './gridRowComparator';
|
|
6
7
|
export type { GridRowComparatorProps } from './gridRowComparator';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alaarab/ogrid-react",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.12",
|
|
4
4
|
"description": "OGrid React – React hooks, headless components, and utilities for OGrid data grids.",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"node": ">=18"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@alaarab/ogrid-core": "2.1.
|
|
42
|
+
"@alaarab/ogrid-core": "2.1.12",
|
|
43
43
|
"@tanstack/react-virtual": "^3.0.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|