@alaarab/ogrid-react 2.1.5 → 2.1.7
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 +78 -38
- package/package.json +2 -2
package/dist/esm/index.js
CHANGED
|
@@ -1312,6 +1312,13 @@ function validateRowIds(items, getRowId) {
|
|
|
1312
1312
|
}
|
|
1313
1313
|
var DEFAULT_DEBOUNCE_MS = 300;
|
|
1314
1314
|
var PEOPLE_SEARCH_DEBOUNCE_MS = DEFAULT_DEBOUNCE_MS;
|
|
1315
|
+
function useLatestRef(value) {
|
|
1316
|
+
const ref = useRef(value);
|
|
1317
|
+
ref.current = value;
|
|
1318
|
+
return ref;
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
// src/hooks/useFilterOptions.ts
|
|
1315
1322
|
function fieldsEqual(a, b) {
|
|
1316
1323
|
if (a.length !== b.length) return false;
|
|
1317
1324
|
for (let i = 0; i < a.length; i++) {
|
|
@@ -1319,19 +1326,23 @@ function fieldsEqual(a, b) {
|
|
|
1319
1326
|
}
|
|
1320
1327
|
return true;
|
|
1321
1328
|
}
|
|
1329
|
+
var EMPTY_FILTER_OPTIONS = {};
|
|
1330
|
+
var EMPTY_LOADING = {};
|
|
1322
1331
|
function useFilterOptions(dataSource, fields) {
|
|
1323
1332
|
const fieldsRef = useRef(fields);
|
|
1324
1333
|
if (!fieldsEqual(fieldsRef.current, fields)) {
|
|
1325
1334
|
fieldsRef.current = fields;
|
|
1326
1335
|
}
|
|
1327
1336
|
const stableFields = fieldsRef.current;
|
|
1328
|
-
const
|
|
1329
|
-
const [
|
|
1337
|
+
const dataSourceRef = useLatestRef(dataSource);
|
|
1338
|
+
const [filterOptions, setFilterOptions] = useState(EMPTY_FILTER_OPTIONS);
|
|
1339
|
+
const [loadingOptions, setLoadingOptions] = useState(EMPTY_LOADING);
|
|
1330
1340
|
const load = useCallback(async () => {
|
|
1331
|
-
const
|
|
1341
|
+
const ds = dataSourceRef.current;
|
|
1342
|
+
const fetcher = "fetchFilterOptions" in ds && typeof ds.fetchFilterOptions === "function" ? ds.fetchFilterOptions.bind(ds) : void 0;
|
|
1332
1343
|
if (!fetcher) {
|
|
1333
|
-
setFilterOptions(
|
|
1334
|
-
setLoadingOptions(
|
|
1344
|
+
setFilterOptions(EMPTY_FILTER_OPTIONS);
|
|
1345
|
+
setLoadingOptions(EMPTY_LOADING);
|
|
1335
1346
|
return;
|
|
1336
1347
|
}
|
|
1337
1348
|
const loading = {};
|
|
@@ -1350,8 +1361,8 @@ function useFilterOptions(dataSource, fields) {
|
|
|
1350
1361
|
})
|
|
1351
1362
|
);
|
|
1352
1363
|
setFilterOptions(results);
|
|
1353
|
-
setLoadingOptions(
|
|
1354
|
-
}, [
|
|
1364
|
+
setLoadingOptions(EMPTY_LOADING);
|
|
1365
|
+
}, [stableFields]);
|
|
1355
1366
|
useEffect(() => {
|
|
1356
1367
|
load().catch(() => {
|
|
1357
1368
|
});
|
|
@@ -1535,14 +1546,17 @@ function useOGridDataFetching(params) {
|
|
|
1535
1546
|
const [serverLoading, setServerLoading] = useState(true);
|
|
1536
1547
|
const fetchIdRef = useRef(0);
|
|
1537
1548
|
const [refreshCounter, setRefreshCounter] = useState(0);
|
|
1549
|
+
const dataSourceRef = useLatestRef(dataSource);
|
|
1550
|
+
const onErrorRef = useLatestRef(onError);
|
|
1538
1551
|
useEffect(() => {
|
|
1539
|
-
if (!isServerSide || !
|
|
1552
|
+
if (!isServerSide || !dataSourceRef.current) {
|
|
1540
1553
|
if (!isServerSide) setServerLoading(false);
|
|
1541
1554
|
return;
|
|
1542
1555
|
}
|
|
1556
|
+
const ds = dataSourceRef.current;
|
|
1543
1557
|
const id = ++fetchIdRef.current;
|
|
1544
1558
|
setServerLoading(true);
|
|
1545
|
-
|
|
1559
|
+
ds.fetchPage({
|
|
1546
1560
|
page,
|
|
1547
1561
|
pageSize,
|
|
1548
1562
|
sort: { field: sort.field, direction: sort.direction },
|
|
@@ -1553,22 +1567,23 @@ function useOGridDataFetching(params) {
|
|
|
1553
1567
|
setServerTotalCount(res.totalCount);
|
|
1554
1568
|
}).catch((err) => {
|
|
1555
1569
|
if (id !== fetchIdRef.current) return;
|
|
1556
|
-
|
|
1570
|
+
onErrorRef.current?.(err);
|
|
1557
1571
|
setServerItems([]);
|
|
1558
1572
|
setServerTotalCount(0);
|
|
1559
1573
|
}).finally(() => {
|
|
1560
1574
|
if (id === fetchIdRef.current) setServerLoading(false);
|
|
1561
1575
|
});
|
|
1562
|
-
}, [isServerSide,
|
|
1576
|
+
}, [isServerSide, page, pageSize, sort.field, sort.direction, stableFilters, refreshCounter]);
|
|
1563
1577
|
const displayItems = isClientSide && clientItemsAndTotal ? clientItemsAndTotal.items : serverItems;
|
|
1564
1578
|
const displayTotalCount = isClientSide && clientItemsAndTotal ? clientItemsAndTotal.totalCount : serverTotalCount;
|
|
1579
|
+
const onFirstDataRenderedRef = useLatestRef(onFirstDataRendered);
|
|
1565
1580
|
const firstDataRenderedRef = useRef(false);
|
|
1566
1581
|
useEffect(() => {
|
|
1567
1582
|
if (!firstDataRenderedRef.current && displayItems.length > 0) {
|
|
1568
1583
|
firstDataRenderedRef.current = true;
|
|
1569
|
-
|
|
1584
|
+
onFirstDataRenderedRef.current?.();
|
|
1570
1585
|
}
|
|
1571
|
-
}, [displayItems.length
|
|
1586
|
+
}, [displayItems.length]);
|
|
1572
1587
|
return {
|
|
1573
1588
|
displayItems,
|
|
1574
1589
|
displayTotalCount,
|
|
@@ -1576,11 +1591,6 @@ function useOGridDataFetching(params) {
|
|
|
1576
1591
|
refreshData: () => setRefreshCounter((prev) => prev + 1)
|
|
1577
1592
|
};
|
|
1578
1593
|
}
|
|
1579
|
-
function useLatestRef(value) {
|
|
1580
|
-
const ref = useRef(value);
|
|
1581
|
-
ref.current = value;
|
|
1582
|
-
return ref;
|
|
1583
|
-
}
|
|
1584
1594
|
var DEFAULT_PANELS = ["columns", "filters"];
|
|
1585
1595
|
function useSideBarState(params) {
|
|
1586
1596
|
const { config } = params;
|
|
@@ -1621,7 +1631,7 @@ var EMPTY_LOADING_OPTIONS2 = {};
|
|
|
1621
1631
|
function useOGrid(props, ref) {
|
|
1622
1632
|
const {
|
|
1623
1633
|
columns: columnsProp,
|
|
1624
|
-
getRowId,
|
|
1634
|
+
getRowId: getRowIdProp,
|
|
1625
1635
|
data,
|
|
1626
1636
|
dataSource,
|
|
1627
1637
|
page: controlledPage,
|
|
@@ -1636,7 +1646,7 @@ function useOGrid(props, ref) {
|
|
|
1636
1646
|
onFiltersChange,
|
|
1637
1647
|
onVisibleColumnsChange,
|
|
1638
1648
|
columnOrder,
|
|
1639
|
-
onColumnOrderChange,
|
|
1649
|
+
onColumnOrderChange: onColumnOrderChangeProp,
|
|
1640
1650
|
onColumnResized,
|
|
1641
1651
|
onColumnPinned,
|
|
1642
1652
|
defaultPageSize = DEFAULT_PAGE_SIZE,
|
|
@@ -1651,9 +1661,9 @@ function useOGrid(props, ref) {
|
|
|
1651
1661
|
suppressHorizontalScroll,
|
|
1652
1662
|
editable,
|
|
1653
1663
|
cellSelection,
|
|
1654
|
-
onCellValueChanged,
|
|
1655
|
-
onUndo,
|
|
1656
|
-
onRedo,
|
|
1664
|
+
onCellValueChanged: onCellValueChangedProp,
|
|
1665
|
+
onUndo: onUndoProp,
|
|
1666
|
+
onRedo: onRedoProp,
|
|
1657
1667
|
canUndo,
|
|
1658
1668
|
canRedo,
|
|
1659
1669
|
rowSelection = "none",
|
|
@@ -1675,6 +1685,32 @@ function useOGrid(props, ref) {
|
|
|
1675
1685
|
"aria-label": ariaLabel,
|
|
1676
1686
|
"aria-labelledby": ariaLabelledBy
|
|
1677
1687
|
} = props;
|
|
1688
|
+
const getRowIdStableRef = useLatestRef(getRowIdProp);
|
|
1689
|
+
const getRowId = useCallback((item) => getRowIdStableRef.current(item), [getRowIdStableRef]);
|
|
1690
|
+
const onColumnOrderChangeRef = useLatestRef(onColumnOrderChangeProp);
|
|
1691
|
+
const onColumnOrderChange = useMemo(
|
|
1692
|
+
() => onColumnOrderChangeProp ? (order) => onColumnOrderChangeRef.current?.(order) : void 0,
|
|
1693
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1694
|
+
[!!onColumnOrderChangeProp]
|
|
1695
|
+
);
|
|
1696
|
+
const onCellValueChangedRef = useLatestRef(onCellValueChangedProp);
|
|
1697
|
+
const onCellValueChanged = useMemo(
|
|
1698
|
+
() => onCellValueChangedProp ? (event) => onCellValueChangedRef.current?.(event) : void 0,
|
|
1699
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1700
|
+
[!!onCellValueChangedProp]
|
|
1701
|
+
);
|
|
1702
|
+
const onUndoRef = useLatestRef(onUndoProp);
|
|
1703
|
+
const onUndo = useMemo(
|
|
1704
|
+
() => onUndoProp ? () => onUndoRef.current?.() : void 0,
|
|
1705
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1706
|
+
[!!onUndoProp]
|
|
1707
|
+
);
|
|
1708
|
+
const onRedoRef = useLatestRef(onRedoProp);
|
|
1709
|
+
const onRedo = useMemo(
|
|
1710
|
+
() => onRedoProp ? () => onRedoRef.current?.() : void 0,
|
|
1711
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1712
|
+
[!!onRedoProp]
|
|
1713
|
+
);
|
|
1678
1714
|
const columnChooserPlacement = columnChooserProp === false ? "none" : columnChooserProp === "sidebar" ? "sidebar" : "toolbar";
|
|
1679
1715
|
const columns = useMemo(() => flattenColumns(columnsProp), [columnsProp]);
|
|
1680
1716
|
const isServerSide = dataSource != null;
|
|
@@ -2855,6 +2891,7 @@ function useKeyboardNavigation(params) {
|
|
|
2855
2891
|
}
|
|
2856
2892
|
function useUndoRedo(params) {
|
|
2857
2893
|
const { onCellValueChanged, maxUndoDepth = 100 } = params;
|
|
2894
|
+
const onCellValueChangedRef = useLatestRef(onCellValueChanged);
|
|
2858
2895
|
const stackRef = useRef(null);
|
|
2859
2896
|
if (stackRef.current === null) {
|
|
2860
2897
|
stackRef.current = new UndoRedoStack(maxUndoDepth);
|
|
@@ -2868,16 +2905,17 @@ function useUndoRedo(params) {
|
|
|
2868
2905
|
}, []);
|
|
2869
2906
|
const wrapped = useCallback(
|
|
2870
2907
|
(event) => {
|
|
2871
|
-
if (!
|
|
2908
|
+
if (!onCellValueChangedRef.current) return;
|
|
2872
2909
|
const stack = getStack();
|
|
2873
2910
|
stack.record(event);
|
|
2874
2911
|
if (!stack.isBatching) {
|
|
2875
2912
|
setHistoryLength(stack.historyLength);
|
|
2876
2913
|
setRedoLength(stack.redoLength);
|
|
2877
2914
|
}
|
|
2878
|
-
|
|
2915
|
+
onCellValueChangedRef.current(event);
|
|
2879
2916
|
},
|
|
2880
|
-
|
|
2917
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2918
|
+
[getStack]
|
|
2881
2919
|
);
|
|
2882
2920
|
const beginBatch = useCallback(() => {
|
|
2883
2921
|
getStack().beginBatch();
|
|
@@ -2889,7 +2927,7 @@ function useUndoRedo(params) {
|
|
|
2889
2927
|
setRedoLength(stack.redoLength);
|
|
2890
2928
|
}, [getStack]);
|
|
2891
2929
|
const undo = useCallback(() => {
|
|
2892
|
-
if (!
|
|
2930
|
+
if (!onCellValueChangedRef.current) return;
|
|
2893
2931
|
const stack = getStack();
|
|
2894
2932
|
const lastBatch = stack.undo();
|
|
2895
2933
|
if (!lastBatch) return;
|
|
@@ -2897,24 +2935,24 @@ function useUndoRedo(params) {
|
|
|
2897
2935
|
setRedoLength(stack.redoLength);
|
|
2898
2936
|
for (let i = lastBatch.length - 1; i >= 0; i--) {
|
|
2899
2937
|
const ev = lastBatch[i];
|
|
2900
|
-
|
|
2938
|
+
onCellValueChangedRef.current({
|
|
2901
2939
|
...ev,
|
|
2902
2940
|
oldValue: ev.newValue,
|
|
2903
2941
|
newValue: ev.oldValue
|
|
2904
2942
|
});
|
|
2905
2943
|
}
|
|
2906
|
-
}, [
|
|
2944
|
+
}, [getStack]);
|
|
2907
2945
|
const redo = useCallback(() => {
|
|
2908
|
-
if (!
|
|
2946
|
+
if (!onCellValueChangedRef.current) return;
|
|
2909
2947
|
const stack = getStack();
|
|
2910
2948
|
const nextBatch = stack.redo();
|
|
2911
2949
|
if (!nextBatch) return;
|
|
2912
2950
|
setHistoryLength(stack.historyLength);
|
|
2913
2951
|
setRedoLength(stack.redoLength);
|
|
2914
2952
|
for (const ev of nextBatch) {
|
|
2915
|
-
|
|
2953
|
+
onCellValueChangedRef.current(ev);
|
|
2916
2954
|
}
|
|
2917
|
-
}, [
|
|
2955
|
+
}, [getStack]);
|
|
2918
2956
|
return {
|
|
2919
2957
|
onCellValueChanged: onCellValueChanged ? wrapped : void 0,
|
|
2920
2958
|
undo,
|
|
@@ -2942,7 +2980,7 @@ function useFillHandle(params) {
|
|
|
2942
2980
|
items,
|
|
2943
2981
|
visibleCols,
|
|
2944
2982
|
editable,
|
|
2945
|
-
onCellValueChanged,
|
|
2983
|
+
onCellValueChanged: onCellValueChangedProp,
|
|
2946
2984
|
selectionRange,
|
|
2947
2985
|
setSelectionRange,
|
|
2948
2986
|
setActiveCell,
|
|
@@ -2951,13 +2989,14 @@ function useFillHandle(params) {
|
|
|
2951
2989
|
beginBatch,
|
|
2952
2990
|
endBatch
|
|
2953
2991
|
} = params;
|
|
2992
|
+
const onCellValueChangedRef = useLatestRef(onCellValueChangedProp);
|
|
2954
2993
|
const [fillDrag, setFillDrag] = useState(null);
|
|
2955
2994
|
const fillDragEndRef = useRef({ endRow: 0, endCol: 0 });
|
|
2956
2995
|
const rafRef = useRef(0);
|
|
2957
2996
|
const liveFillRangeRef = useRef(null);
|
|
2958
2997
|
const colOffsetRef = useLatestRef(colOffset);
|
|
2959
2998
|
useEffect(() => {
|
|
2960
|
-
if (!fillDrag || editable === false || !
|
|
2999
|
+
if (!fillDrag || editable === false || !onCellValueChangedRef.current || !wrapperRef.current) return;
|
|
2961
3000
|
fillDragEndRef.current = { endRow: fillDrag.startRow, endCol: fillDrag.startCol };
|
|
2962
3001
|
liveFillRangeRef.current = null;
|
|
2963
3002
|
const markedCells = /* @__PURE__ */ new Set();
|
|
@@ -3071,7 +3110,7 @@ function useFillHandle(params) {
|
|
|
3071
3110
|
const fillEvents = applyFillValues(norm, fillDrag.startRow, fillDrag.startCol, items, visibleCols);
|
|
3072
3111
|
if (fillEvents.length > 0) {
|
|
3073
3112
|
beginBatch?.();
|
|
3074
|
-
for (const evt of fillEvents)
|
|
3113
|
+
for (const evt of fillEvents) onCellValueChangedRef.current?.(evt);
|
|
3075
3114
|
endBatch?.();
|
|
3076
3115
|
}
|
|
3077
3116
|
setFillDrag(null);
|
|
@@ -3091,7 +3130,6 @@ function useFillHandle(params) {
|
|
|
3091
3130
|
visibleCols,
|
|
3092
3131
|
setSelectionRange,
|
|
3093
3132
|
setActiveCell,
|
|
3094
|
-
onCellValueChanged,
|
|
3095
3133
|
beginBatch,
|
|
3096
3134
|
endBatch,
|
|
3097
3135
|
colOffsetRef,
|
|
@@ -3572,6 +3610,7 @@ function useDataGridEditing(params) {
|
|
|
3572
3610
|
const [popoverAnchorEl, setPopoverAnchorEl] = useState(null);
|
|
3573
3611
|
const visibleColsRef = useLatestRef(params.visibleCols);
|
|
3574
3612
|
const itemsLengthRef = useLatestRef(params.itemsLength);
|
|
3613
|
+
const onCellValueChangedRef = useLatestRef(onCellValueChanged);
|
|
3575
3614
|
const commitCellEdit = useCallback(
|
|
3576
3615
|
(item, columnId, oldValue, newValue, rowIndex, globalColIndex) => {
|
|
3577
3616
|
const col = visibleColsRef.current.find((c) => c.columnId === columnId);
|
|
@@ -3585,7 +3624,7 @@ function useDataGridEditing(params) {
|
|
|
3585
3624
|
}
|
|
3586
3625
|
newValue = result.value;
|
|
3587
3626
|
}
|
|
3588
|
-
|
|
3627
|
+
onCellValueChangedRef.current?.({
|
|
3589
3628
|
item,
|
|
3590
3629
|
columnId,
|
|
3591
3630
|
oldValue,
|
|
@@ -3599,7 +3638,8 @@ function useDataGridEditing(params) {
|
|
|
3599
3638
|
setActiveCell({ rowIndex: rowIndex + 1, columnIndex: globalColIndex });
|
|
3600
3639
|
}
|
|
3601
3640
|
},
|
|
3602
|
-
|
|
3641
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3642
|
+
[setEditingCell, setPendingEditorValue, setActiveCell, visibleColsRef, itemsLengthRef]
|
|
3603
3643
|
);
|
|
3604
3644
|
const cancelPopoverEdit = useCallback(() => {
|
|
3605
3645
|
setEditingCell(null);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alaarab/ogrid-react",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.7",
|
|
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.7",
|
|
43
43
|
"@tanstack/react-virtual": "^3.0.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|