@ornery/ui-grid-react 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.mts +24 -2
- package/dist/index.d.ts +24 -2
- package/dist/index.js +1166 -607
- package/dist/index.mjs +1101 -549
- package/package.json +1 -1
- package/src/UiGrid.tsx +174 -47
- package/src/gridStateMath.test.ts +49 -0
- package/src/gridStateMath.ts +32 -0
- package/src/index.ts +2 -0
- package/src/rustWasmGridEngine.test.ts +56 -0
- package/src/rustWasmGridEngine.ts +21 -0
- package/src/useGridState.ts +637 -328
- package/src/useVirtualScroll.ts +11 -10
- package/src/virtualScrollMath.test.ts +44 -0
- package/src/virtualScrollMath.ts +36 -0
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,39 @@
|
|
|
1
1
|
// src/useGridState.ts
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
|
|
4
|
+
// src/gridStateMath.ts
|
|
5
|
+
import { gridColumnWidth } from "@ornery/ui-grid";
|
|
6
|
+
function orderVisibleColumns(columns, order) {
|
|
7
|
+
return [...columns].filter((column) => column.visible !== false).sort((left, right) => order.indexOf(left.name) - order.indexOf(right.name));
|
|
8
|
+
}
|
|
9
|
+
function buildGridTemplateColumns(columns) {
|
|
10
|
+
return columns.map((column) => gridColumnWidth(column)).join(" ");
|
|
11
|
+
}
|
|
12
|
+
function resolveBenchmarkIterations(iterations, configuredIterations) {
|
|
13
|
+
return Math.max(1, iterations ?? configuredIterations ?? 25);
|
|
14
|
+
}
|
|
15
|
+
function formatPaginationSummary(totalItems, firstRowIndex, lastRowIndex) {
|
|
16
|
+
if (totalItems === 0) {
|
|
17
|
+
return "0-0 of 0";
|
|
18
|
+
}
|
|
19
|
+
return `${firstRowIndex + 1}-${lastRowIndex + 1} of ${totalItems}`;
|
|
20
|
+
}
|
|
21
|
+
function computeViewportHeightPx(viewportHeight, autoViewportHeight) {
|
|
22
|
+
return `${viewportHeight ?? autoViewportHeight ?? 560}px`;
|
|
23
|
+
}
|
|
24
|
+
function computeViewportRows(viewportHeight, rowHeight) {
|
|
25
|
+
return Math.max(1, Math.ceil((viewportHeight ?? 560) / (rowHeight ?? 44)));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/useGridState.ts
|
|
3
29
|
import {
|
|
4
30
|
createGridApi,
|
|
5
31
|
getCellValue as getCellValue2,
|
|
6
32
|
setPathValue,
|
|
7
33
|
SORT_DIRECTIONS as SORT_DIRECTIONS2,
|
|
8
|
-
|
|
34
|
+
defaultGridEngine,
|
|
9
35
|
resolveGridLabels,
|
|
10
|
-
gridColumnWidth,
|
|
36
|
+
gridColumnWidth as gridColumnWidth2,
|
|
11
37
|
headerLabel as coreHeaderLabel,
|
|
12
38
|
gridSortButtonLabel,
|
|
13
39
|
gridSortAriaSort,
|
|
@@ -59,7 +85,8 @@ import {
|
|
|
59
85
|
FEATURE_INFINITE_SCROLL,
|
|
60
86
|
FEATURE_COLUMN_MOVING,
|
|
61
87
|
FEATURE_CSV_EXPORT,
|
|
62
|
-
FEATURE_AUTO_RESIZE
|
|
88
|
+
FEATURE_AUTO_RESIZE,
|
|
89
|
+
FEATURE_PINNING
|
|
63
90
|
} from "@ornery/ui-grid";
|
|
64
91
|
|
|
65
92
|
// ../ui-grid/src/lib/grid/grid.core.pagination.ts
|
|
@@ -240,12 +267,15 @@ function normalizeGridSavedState(state) {
|
|
|
240
267
|
);
|
|
241
268
|
}
|
|
242
269
|
if (state.filters && typeof state.filters === "object") {
|
|
243
|
-
normalized.filters = Object.entries(state.filters).reduce(
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
270
|
+
normalized.filters = Object.entries(state.filters).reduce(
|
|
271
|
+
(accumulator, [key, value]) => {
|
|
272
|
+
if (typeof key === "string" && isSafeStateKey(key) && typeof value === "string") {
|
|
273
|
+
accumulator[key] = value;
|
|
274
|
+
}
|
|
275
|
+
return accumulator;
|
|
276
|
+
},
|
|
277
|
+
{}
|
|
278
|
+
);
|
|
249
279
|
}
|
|
250
280
|
if (state.sort && typeof state.sort === "object") {
|
|
251
281
|
normalized.sort = {
|
|
@@ -272,6 +302,17 @@ function normalizeGridSavedState(state) {
|
|
|
272
302
|
if (state.treeView && typeof state.treeView === "object") {
|
|
273
303
|
normalized.treeView = normalizeBooleanMap(state.treeView);
|
|
274
304
|
}
|
|
305
|
+
if (state.pinning && typeof state.pinning === "object") {
|
|
306
|
+
normalized.pinning = Object.entries(state.pinning).reduce(
|
|
307
|
+
(acc, [key, value]) => {
|
|
308
|
+
if (typeof key === "string" && isSafeStateKey(key) && (value === "left" || value === "right")) {
|
|
309
|
+
acc[key] = value;
|
|
310
|
+
}
|
|
311
|
+
return acc;
|
|
312
|
+
},
|
|
313
|
+
{}
|
|
314
|
+
);
|
|
315
|
+
}
|
|
275
316
|
return normalized;
|
|
276
317
|
}
|
|
277
318
|
function normalizeBooleanMap(value) {
|
|
@@ -286,6 +327,69 @@ function isSafeStateKey(value) {
|
|
|
286
327
|
return value !== "__proto__" && value !== "constructor" && value !== "prototype";
|
|
287
328
|
}
|
|
288
329
|
|
|
330
|
+
// ../ui-grid/src/lib/grid/grid.core.pinning.ts
|
|
331
|
+
function isPinningEnabled(options) {
|
|
332
|
+
return options.enablePinning === true;
|
|
333
|
+
}
|
|
334
|
+
function isColumnPinnable(options, column) {
|
|
335
|
+
return isPinningEnabled(options) && column.enablePinning !== false;
|
|
336
|
+
}
|
|
337
|
+
function pinColumnState(current, columnName, direction) {
|
|
338
|
+
const next = { ...current };
|
|
339
|
+
if (direction === "none") {
|
|
340
|
+
delete next[columnName];
|
|
341
|
+
} else {
|
|
342
|
+
next[columnName] = direction;
|
|
343
|
+
}
|
|
344
|
+
return next;
|
|
345
|
+
}
|
|
346
|
+
function buildInitialPinnedState(columns) {
|
|
347
|
+
const state = {};
|
|
348
|
+
for (const col of columns) {
|
|
349
|
+
if (col.pinnedLeft) state[col.name] = "left";
|
|
350
|
+
else if (col.pinnedRight) state[col.name] = "right";
|
|
351
|
+
}
|
|
352
|
+
return state;
|
|
353
|
+
}
|
|
354
|
+
function computePinnedOffset(visibleColumns, pinnedColumns, column) {
|
|
355
|
+
const direction = pinnedColumns[column.name];
|
|
356
|
+
if (!direction) return null;
|
|
357
|
+
function resolveColumnWidthForOffset(column2) {
|
|
358
|
+
const w = column2.width;
|
|
359
|
+
if (!w) return "11rem";
|
|
360
|
+
if (w.includes("fr") || w.includes("minmax")) return "11rem";
|
|
361
|
+
return w;
|
|
362
|
+
}
|
|
363
|
+
if (direction === "left") {
|
|
364
|
+
const offsetParts = [];
|
|
365
|
+
for (const col of visibleColumns) {
|
|
366
|
+
if (col.name === column.name) break;
|
|
367
|
+
if (pinnedColumns[col.name] === "left") {
|
|
368
|
+
offsetParts.push(resolveColumnWidthForOffset(col));
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return {
|
|
372
|
+
side: "left",
|
|
373
|
+
offset: offsetParts.length > 0 ? `calc(${offsetParts.join(" + ")})` : "0px"
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
if (direction === "right") {
|
|
377
|
+
const offsetParts = [];
|
|
378
|
+
const reversed = [...visibleColumns].reverse();
|
|
379
|
+
for (const col of reversed) {
|
|
380
|
+
if (col.name === column.name) break;
|
|
381
|
+
if (pinnedColumns[col.name] === "right") {
|
|
382
|
+
offsetParts.push(resolveColumnWidthForOffset(col));
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return {
|
|
386
|
+
side: "right",
|
|
387
|
+
offset: offsetParts.length > 0 ? `calc(${offsetParts.join(" + ")})` : "0px"
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
|
|
289
393
|
// ../ui-grid/src/lib/grid/ui-grid.events.ts
|
|
290
394
|
function raiseGridRenderingComplete(gridApi) {
|
|
291
395
|
gridApi.core.raise.renderingComplete(gridApi);
|
|
@@ -352,6 +456,9 @@ function raiseGridAfterCellEdit(gridApi, rowEntity, column, newValue, oldValue)
|
|
|
352
456
|
function raiseGridCancelCellEdit(gridApi, rowEntity, column) {
|
|
353
457
|
gridApi.edit.raise.cancelCellEdit(rowEntity, column);
|
|
354
458
|
}
|
|
459
|
+
function raiseGridColumnPinned(gridApi, columnName, direction) {
|
|
460
|
+
gridApi.pinning.raise.columnPinned(columnName, direction);
|
|
461
|
+
}
|
|
355
462
|
|
|
356
463
|
// ../ui-grid/src/lib/grid/ui-grid.state.ts
|
|
357
464
|
function moveArrayItem(items, fromIndex, toIndex) {
|
|
@@ -393,6 +500,9 @@ function createGridRestoreMutationPlan(state) {
|
|
|
393
500
|
if (normalizedState.treeView) {
|
|
394
501
|
plan.treeView = normalizedState.treeView;
|
|
395
502
|
}
|
|
503
|
+
if (normalizedState.pinning) {
|
|
504
|
+
plan.pinning = normalizedState.pinning;
|
|
505
|
+
}
|
|
396
506
|
return plan;
|
|
397
507
|
}
|
|
398
508
|
|
|
@@ -433,6 +543,12 @@ function moveGridColumnCommand(gridApi, canMoveColumns, updateColumnOrder, fromI
|
|
|
433
543
|
return next;
|
|
434
544
|
});
|
|
435
545
|
}
|
|
546
|
+
function pinGridColumnCommand(gridApi, isPinningEnabled2, setPinnedColumns, getCurrentPinnedColumns, columnName, direction) {
|
|
547
|
+
if (!isPinningEnabled2) return;
|
|
548
|
+
const next = pinColumnState(getCurrentPinnedColumns(), columnName, direction);
|
|
549
|
+
setPinnedColumns(next);
|
|
550
|
+
raiseGridColumnPinned(gridApi, columnName, direction);
|
|
551
|
+
}
|
|
436
552
|
function seekGridPaginationCommand(gridApi, setCurrentPage, getTotalPages, getEffectivePageSize, page) {
|
|
437
553
|
const nextPage = seekGridPage(page, getTotalPages());
|
|
438
554
|
setCurrentPage(nextPage);
|
|
@@ -466,7 +582,11 @@ function restoreGridStateCommand(gridApi, state, access) {
|
|
|
466
582
|
if (restorePlan.pagination) {
|
|
467
583
|
access.setCurrentPage(restorePlan.pagination.currentPage);
|
|
468
584
|
access.setPageSize(restorePlan.pagination.pageSize);
|
|
469
|
-
raiseGridPaginationChanged(
|
|
585
|
+
raiseGridPaginationChanged(
|
|
586
|
+
gridApi,
|
|
587
|
+
restorePlan.pagination.currentPage,
|
|
588
|
+
access.getEffectivePageSize()
|
|
589
|
+
);
|
|
470
590
|
}
|
|
471
591
|
if (restorePlan.expandable) {
|
|
472
592
|
access.setExpandedRows(restorePlan.expandable);
|
|
@@ -474,6 +594,12 @@ function restoreGridStateCommand(gridApi, state, access) {
|
|
|
474
594
|
if (restorePlan.treeView) {
|
|
475
595
|
access.setExpandedTreeRows(restorePlan.treeView);
|
|
476
596
|
}
|
|
597
|
+
if (restorePlan.pinning && typeof access.setPinnedColumns === "function") {
|
|
598
|
+
access.setPinnedColumns(restorePlan.pinning);
|
|
599
|
+
for (const [col, dir] of Object.entries(restorePlan.pinning)) {
|
|
600
|
+
raiseGridColumnPinned(gridApi, col, dir);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
477
603
|
}
|
|
478
604
|
function toggleGridRowExpansionCommand(gridApi, canExpandRows, currentExpandedRows, rowId, setExpandedRows, findRowById) {
|
|
479
605
|
if (!canExpandRows) {
|
|
@@ -495,7 +621,10 @@ function collapseAllGridRowsCommand(setExpandedRows) {
|
|
|
495
621
|
setExpandedRows({});
|
|
496
622
|
}
|
|
497
623
|
function toggleGridTreeRowCommand(gridApi, currentExpandedTreeRows, rowId, setExpandedTreeRows, findRowById) {
|
|
498
|
-
const { expanded, nextExpandedTreeRows } = toggleGridTreeRowExpanded(
|
|
624
|
+
const { expanded, nextExpandedTreeRows } = toggleGridTreeRowExpanded(
|
|
625
|
+
currentExpandedTreeRows,
|
|
626
|
+
rowId
|
|
627
|
+
);
|
|
499
628
|
setExpandedTreeRows(nextExpandedTreeRows);
|
|
500
629
|
const gridRow = findRowById(rowId);
|
|
501
630
|
if (gridRow) {
|
|
@@ -630,13 +759,45 @@ function downloadGridCsvFile(csv, filename) {
|
|
|
630
759
|
}
|
|
631
760
|
|
|
632
761
|
// src/useGridState.ts
|
|
762
|
+
function escapeCssSelectorValue(value) {
|
|
763
|
+
const nativeEscape = globalThis.CSS?.escape;
|
|
764
|
+
if (typeof nativeEscape === "function") {
|
|
765
|
+
return nativeEscape(value);
|
|
766
|
+
}
|
|
767
|
+
let output = "";
|
|
768
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
769
|
+
const codePoint = value.charCodeAt(index);
|
|
770
|
+
const character = value.charAt(index);
|
|
771
|
+
if (codePoint === 0) {
|
|
772
|
+
output += "\uFFFD";
|
|
773
|
+
continue;
|
|
774
|
+
}
|
|
775
|
+
const isControlCharacter = codePoint >= 1 && codePoint <= 31 || codePoint === 127;
|
|
776
|
+
const startsWithDigit = index === 0 && codePoint >= 48 && codePoint <= 57;
|
|
777
|
+
const secondCharDigitAfterHyphen = index === 1 && codePoint >= 48 && codePoint <= 57 && value.charCodeAt(0) === 45;
|
|
778
|
+
if (isControlCharacter || startsWithDigit || secondCharDigitAfterHyphen) {
|
|
779
|
+
output += `\\${codePoint.toString(16)} `;
|
|
780
|
+
continue;
|
|
781
|
+
}
|
|
782
|
+
if (index === 0 && value.length === 1 && codePoint === 45) {
|
|
783
|
+
output += `\\${character}`;
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
const isSafeCharacter = codePoint >= 128 || codePoint === 45 || codePoint === 95 || codePoint >= 48 && codePoint <= 57 || codePoint >= 65 && codePoint <= 90 || codePoint >= 97 && codePoint <= 122;
|
|
787
|
+
output += isSafeCharacter ? character : `\\${character}`;
|
|
788
|
+
}
|
|
789
|
+
return output;
|
|
790
|
+
}
|
|
633
791
|
function useGridState(options, onRegisterApi) {
|
|
634
792
|
const [activeFilters, setActiveFilters] = useState({});
|
|
635
793
|
const [groupByColumns, setGroupByColumns] = useState([]);
|
|
636
794
|
const [collapsedGroups, setCollapsedGroups] = useState({});
|
|
637
795
|
const [columnOrder, setColumnOrder] = useState([]);
|
|
638
796
|
const [hiddenRowReasons, setHiddenRowReasons] = useState({});
|
|
639
|
-
const [sortState, setSortState] = useState({
|
|
797
|
+
const [sortState, setSortState] = useState({
|
|
798
|
+
columnName: null,
|
|
799
|
+
direction: SORT_DIRECTIONS2.none
|
|
800
|
+
});
|
|
640
801
|
const [focusedCell, setFocusedCell] = useState(null);
|
|
641
802
|
const [editingCell, setEditingCell] = useState(null);
|
|
642
803
|
const [editingValue, setEditingValue] = useState("");
|
|
@@ -652,6 +813,7 @@ function useGridState(options, onRegisterApi) {
|
|
|
652
813
|
previousVisibleRows: 0
|
|
653
814
|
});
|
|
654
815
|
const [autoViewportHeight, setAutoViewportHeight] = useState(null);
|
|
816
|
+
const [pinnedColumns, setPinnedColumns] = useState({});
|
|
655
817
|
const gridContainerRef = useRef(null);
|
|
656
818
|
const initializedGridIdRef = useRef(null);
|
|
657
819
|
const lastCanvasHeightRef = useRef(0);
|
|
@@ -683,6 +845,8 @@ function useGridState(options, onRegisterApi) {
|
|
|
683
845
|
expandedRowsRef.current = expandedRows;
|
|
684
846
|
const expandedTreeRowsRef = useRef(expandedTreeRows);
|
|
685
847
|
expandedTreeRowsRef.current = expandedTreeRows;
|
|
848
|
+
const pinnedColumnsRef = useRef(pinnedColumns);
|
|
849
|
+
pinnedColumnsRef.current = pinnedColumns;
|
|
686
850
|
const currentPageRef = useRef(currentPage);
|
|
687
851
|
currentPageRef.current = currentPage;
|
|
688
852
|
const pageSizeRef = useRef(pageSize);
|
|
@@ -693,13 +857,12 @@ function useGridState(options, onRegisterApi) {
|
|
|
693
857
|
optionsRef.current = options;
|
|
694
858
|
const rowSize = options.rowHeight ?? 44;
|
|
695
859
|
const visibleColumns = useMemo(() => {
|
|
696
|
-
|
|
697
|
-
return [...options.columnDefs].filter((column) => column.visible !== false).sort((left, right) => order.indexOf(left.name) - order.indexOf(right.name));
|
|
860
|
+
return orderVisibleColumns(options.columnDefs, columnOrder);
|
|
698
861
|
}, [options.columnDefs, columnOrder]);
|
|
699
862
|
const visibleColumnsRef = useRef(visibleColumns);
|
|
700
863
|
visibleColumnsRef.current = visibleColumns;
|
|
701
864
|
const pipeline = useMemo(() => {
|
|
702
|
-
return
|
|
865
|
+
return defaultGridEngine.buildPipeline({
|
|
703
866
|
options,
|
|
704
867
|
columns: visibleColumns,
|
|
705
868
|
activeFilters,
|
|
@@ -713,14 +876,39 @@ function useGridState(options, onRegisterApi) {
|
|
|
713
876
|
pageSize,
|
|
714
877
|
rowSize
|
|
715
878
|
});
|
|
716
|
-
}, [
|
|
879
|
+
}, [
|
|
880
|
+
options,
|
|
881
|
+
visibleColumns,
|
|
882
|
+
activeFilters,
|
|
883
|
+
sortState,
|
|
884
|
+
groupByColumns,
|
|
885
|
+
collapsedGroups,
|
|
886
|
+
hiddenRowReasons,
|
|
887
|
+
expandedRows,
|
|
888
|
+
expandedTreeRows,
|
|
889
|
+
currentPage,
|
|
890
|
+
pageSize,
|
|
891
|
+
rowSize
|
|
892
|
+
]);
|
|
717
893
|
const pipelineRef = useRef(pipeline);
|
|
718
894
|
pipelineRef.current = pipeline;
|
|
719
895
|
const labels = useMemo(() => resolveGridLabels(options.labels), [options.labels]);
|
|
720
896
|
const gridTemplateColumns = useMemo(
|
|
721
|
-
() => visibleColumns
|
|
897
|
+
() => buildGridTemplateColumns(visibleColumns),
|
|
722
898
|
[visibleColumns]
|
|
723
899
|
);
|
|
900
|
+
const isPinningEnabledFn = useCallback(() => {
|
|
901
|
+
return isPinningEnabled(optionsRef.current);
|
|
902
|
+
}, []);
|
|
903
|
+
const isColumnPinnableFn = useCallback((column) => {
|
|
904
|
+
return isColumnPinnable(optionsRef.current, column);
|
|
905
|
+
}, []);
|
|
906
|
+
const isPinnedFn = useCallback((column) => {
|
|
907
|
+
return pinnedColumnsRef.current[column.name] !== void 0;
|
|
908
|
+
}, []);
|
|
909
|
+
const pinnedOffsetFn = useCallback((column) => {
|
|
910
|
+
return computePinnedOffset(visibleColumnsRef.current, pinnedColumnsRef.current, column);
|
|
911
|
+
}, []);
|
|
724
912
|
const resolveRowId = useCallback((row) => {
|
|
725
913
|
return coreResolveGridRowId(optionsRef.current, row);
|
|
726
914
|
}, []);
|
|
@@ -732,9 +920,12 @@ function useGridState(options, onRegisterApi) {
|
|
|
732
920
|
expandedRowsRef.current
|
|
733
921
|
);
|
|
734
922
|
}, []);
|
|
735
|
-
const findRowById = useCallback(
|
|
736
|
-
|
|
737
|
-
|
|
923
|
+
const findRowById = useCallback(
|
|
924
|
+
(rowId) => {
|
|
925
|
+
return coreFindGridRowById(buildRowsFromData(optionsRef.current.data), rowId);
|
|
926
|
+
},
|
|
927
|
+
[buildRowsFromData]
|
|
928
|
+
);
|
|
738
929
|
const canExpandRowsFn = useCallback(() => {
|
|
739
930
|
return FEATURE_EXPANDABLE && canGridExpandRows(optionsRef.current);
|
|
740
931
|
}, []);
|
|
@@ -743,7 +934,12 @@ function useGridState(options, onRegisterApi) {
|
|
|
743
934
|
}, []);
|
|
744
935
|
const getCurrentPageValueFn = useCallback((totalItems) => {
|
|
745
936
|
const ti = totalItems ?? pipelineRef.current.totalItems;
|
|
746
|
-
return coreGetCurrentPageValue(
|
|
937
|
+
return coreGetCurrentPageValue(
|
|
938
|
+
optionsRef.current,
|
|
939
|
+
currentPageRef.current,
|
|
940
|
+
ti,
|
|
941
|
+
pageSizeRef.current
|
|
942
|
+
);
|
|
747
943
|
}, []);
|
|
748
944
|
const getTotalPagesValueFn = useCallback((totalItems) => {
|
|
749
945
|
const ti = totalItems ?? pipelineRef.current.totalItems;
|
|
@@ -751,32 +947,45 @@ function useGridState(options, onRegisterApi) {
|
|
|
751
947
|
}, []);
|
|
752
948
|
const getFirstRowIndexValueFn = useCallback((totalItems) => {
|
|
753
949
|
const ti = totalItems ?? pipelineRef.current.totalItems;
|
|
754
|
-
return coreGetFirstRowIndexValue(
|
|
950
|
+
return coreGetFirstRowIndexValue(
|
|
951
|
+
optionsRef.current,
|
|
952
|
+
currentPageRef.current,
|
|
953
|
+
ti,
|
|
954
|
+
pageSizeRef.current
|
|
955
|
+
);
|
|
755
956
|
}, []);
|
|
756
957
|
const getLastRowIndexValueFn = useCallback((totalItems) => {
|
|
757
958
|
const ti = totalItems ?? pipelineRef.current.totalItems;
|
|
758
|
-
return coreGetLastRowIndexValue(
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
const condition = column.cellEditableCondition ?? optionsRef.current.cellEditableCondition ?? true;
|
|
765
|
-
if (typeof condition === "boolean") return condition;
|
|
766
|
-
const context = {
|
|
767
|
-
row: row.entity,
|
|
768
|
-
column,
|
|
769
|
-
rowIndex: row.index,
|
|
770
|
-
triggerEvent
|
|
771
|
-
};
|
|
772
|
-
return condition(context);
|
|
959
|
+
return coreGetLastRowIndexValue(
|
|
960
|
+
optionsRef.current,
|
|
961
|
+
currentPageRef.current,
|
|
962
|
+
ti,
|
|
963
|
+
pageSizeRef.current
|
|
964
|
+
);
|
|
773
965
|
}, []);
|
|
966
|
+
const isCellEditable = useCallback(
|
|
967
|
+
(row, column, triggerEvent) => {
|
|
968
|
+
if (!FEATURE_CELL_EDIT) return false;
|
|
969
|
+
const editable = column.enableCellEdit ?? optionsRef.current.enableCellEdit ?? false;
|
|
970
|
+
if (!editable) return false;
|
|
971
|
+
const condition = column.cellEditableCondition ?? optionsRef.current.cellEditableCondition ?? true;
|
|
972
|
+
if (typeof condition === "boolean") return condition;
|
|
973
|
+
const context = {
|
|
974
|
+
row: row.entity,
|
|
975
|
+
column,
|
|
976
|
+
rowIndex: row.index,
|
|
977
|
+
triggerEvent
|
|
978
|
+
};
|
|
979
|
+
return condition(context);
|
|
980
|
+
},
|
|
981
|
+
[]
|
|
982
|
+
);
|
|
774
983
|
const shouldEditOnFocusFn = useCallback((column) => {
|
|
775
984
|
return column.enableCellEditOnFocus ?? optionsRef.current.enableCellEditOnFocus ?? false;
|
|
776
985
|
}, []);
|
|
777
986
|
const focusRenderedCell = useCallback((position) => {
|
|
778
987
|
const focusToken = ++renderedCellFocusTokenRef.current;
|
|
779
|
-
const selector = `.body-cell[data-row-id="${position.rowId}"][data-col-name="${position.columnName}"]`;
|
|
988
|
+
const selector = `.body-cell[data-row-id="${escapeCssSelectorValue(position.rowId)}"][data-col-name="${escapeCssSelectorValue(position.columnName)}"]`;
|
|
780
989
|
const doFocus = (retry = true) => {
|
|
781
990
|
if (focusToken !== renderedCellFocusTokenRef.current) return;
|
|
782
991
|
const container = gridContainerRef.current;
|
|
@@ -797,11 +1006,12 @@ function useGridState(options, onRegisterApi) {
|
|
|
797
1006
|
if (focusToken !== editorFocusTokenRef.current) return;
|
|
798
1007
|
const ec = editingCellRef.current;
|
|
799
1008
|
if (!ec) return;
|
|
800
|
-
const selector = `.cell-editor[data-row-id="${ec.rowId}"][data-col-name="${ec.columnName}"]`;
|
|
1009
|
+
const selector = `.cell-editor[data-row-id="${escapeCssSelectorValue(ec.rowId)}"][data-col-name="${escapeCssSelectorValue(ec.columnName)}"]`;
|
|
801
1010
|
const doFocus = (retry = true) => {
|
|
802
1011
|
if (focusToken !== editorFocusTokenRef.current) return;
|
|
803
1012
|
const currentEc = editingCellRef.current;
|
|
804
|
-
if (!currentEc || currentEc.rowId !== ec.rowId || currentEc.columnName !== ec.columnName)
|
|
1013
|
+
if (!currentEc || currentEc.rowId !== ec.rowId || currentEc.columnName !== ec.columnName)
|
|
1014
|
+
return;
|
|
805
1015
|
const container = gridContainerRef.current;
|
|
806
1016
|
if (!container) return;
|
|
807
1017
|
const input = container.querySelector(selector);
|
|
@@ -862,7 +1072,11 @@ function useGridState(options, onRegisterApi) {
|
|
|
862
1072
|
gridApiRef.current.core.raise.groupingChanged(next);
|
|
863
1073
|
},
|
|
864
1074
|
clearGrouping: () => {
|
|
865
|
-
clearGridGroupingCommand(
|
|
1075
|
+
clearGridGroupingCommand(
|
|
1076
|
+
gridApiRef.current,
|
|
1077
|
+
(grouping) => setGroupByColumns(grouping),
|
|
1078
|
+
false
|
|
1079
|
+
);
|
|
866
1080
|
},
|
|
867
1081
|
benchmark: (iterations) => {
|
|
868
1082
|
return runBenchmarkFn(iterations);
|
|
@@ -957,7 +1171,8 @@ function useGridState(options, onRegisterApi) {
|
|
|
957
1171
|
pageSize: pageSizeRef.current,
|
|
958
1172
|
totalItems: pipelineRef.current.totalItems,
|
|
959
1173
|
expandedRows: expandedRowsRef.current,
|
|
960
|
-
expandedTreeRows: expandedTreeRowsRef.current
|
|
1174
|
+
expandedTreeRows: expandedTreeRowsRef.current,
|
|
1175
|
+
pinnedColumns: pinnedColumnsRef.current
|
|
961
1176
|
});
|
|
962
1177
|
},
|
|
963
1178
|
restoreState: (state) => {
|
|
@@ -970,6 +1185,7 @@ function useGridState(options, onRegisterApi) {
|
|
|
970
1185
|
setPageSize: (ps) => setPageSize(ps),
|
|
971
1186
|
setExpandedRows: (e) => setExpandedRows(e),
|
|
972
1187
|
setExpandedTreeRows: (e) => setExpandedTreeRows(e),
|
|
1188
|
+
setPinnedColumns: (p) => setPinnedColumns(p),
|
|
973
1189
|
getEffectivePageSize: () => effectivePageSizeFn(pipelineRef.current.totalItems)
|
|
974
1190
|
});
|
|
975
1191
|
},
|
|
@@ -982,20 +1198,45 @@ function useGridState(options, onRegisterApi) {
|
|
|
982
1198
|
},
|
|
983
1199
|
endCellEdit: () => commitCellEditFn(),
|
|
984
1200
|
cancelCellEdit: () => cancelCellEditFn(),
|
|
985
|
-
getEditingCell: () => editingCellRef.current
|
|
1201
|
+
getEditingCell: () => editingCellRef.current,
|
|
1202
|
+
pinColumn: (columnName, direction) => {
|
|
1203
|
+
pinGridColumnCommand(
|
|
1204
|
+
gridApiRef.current,
|
|
1205
|
+
isPinningEnabledFn(),
|
|
1206
|
+
(v) => setPinnedColumns(v),
|
|
1207
|
+
() => pinnedColumnsRef.current,
|
|
1208
|
+
columnName,
|
|
1209
|
+
direction
|
|
1210
|
+
);
|
|
1211
|
+
}
|
|
986
1212
|
};
|
|
987
1213
|
gridApiRef.current = createGridApi(bindings);
|
|
988
1214
|
}
|
|
989
1215
|
const gridApi = gridApiRef.current;
|
|
990
|
-
const seekPageFn = useCallback(
|
|
991
|
-
|
|
1216
|
+
const seekPageFn = useCallback(
|
|
1217
|
+
(page) => {
|
|
1218
|
+
seekGridPaginationCommand(
|
|
1219
|
+
gridApiRef.current,
|
|
1220
|
+
(nextPage) => setCurrentPage(nextPage),
|
|
1221
|
+
() => getTotalPagesValueFn(),
|
|
1222
|
+
() => effectivePageSizeFn(pipelineRef.current.totalItems),
|
|
1223
|
+
page
|
|
1224
|
+
);
|
|
1225
|
+
},
|
|
1226
|
+
[getTotalPagesValueFn, effectivePageSizeFn]
|
|
1227
|
+
);
|
|
1228
|
+
const togglePinFn = useCallback((column) => {
|
|
1229
|
+
const current = pinnedColumnsRef.current[column.name];
|
|
1230
|
+
const next = current === "left" ? "right" : current === "right" ? "none" : "left";
|
|
1231
|
+
pinGridColumnCommand(
|
|
992
1232
|
gridApiRef.current,
|
|
993
|
-
(
|
|
994
|
-
() =>
|
|
995
|
-
() =>
|
|
996
|
-
|
|
1233
|
+
isPinningEnabledFn(),
|
|
1234
|
+
(v) => setPinnedColumns(v),
|
|
1235
|
+
() => pinnedColumnsRef.current,
|
|
1236
|
+
column.name,
|
|
1237
|
+
next
|
|
997
1238
|
);
|
|
998
|
-
}, [
|
|
1239
|
+
}, []);
|
|
999
1240
|
const setPaginationPageSizeFn = useCallback((ps) => {
|
|
1000
1241
|
setGridPaginationPageSizeCommand(
|
|
1001
1242
|
gridApiRef.current,
|
|
@@ -1004,17 +1245,20 @@ function useGridState(options, onRegisterApi) {
|
|
|
1004
1245
|
ps
|
|
1005
1246
|
);
|
|
1006
1247
|
}, []);
|
|
1007
|
-
const toggleRowExpansionByRefFn = useCallback(
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1248
|
+
const toggleRowExpansionByRefFn = useCallback(
|
|
1249
|
+
(row) => {
|
|
1250
|
+
const rowId = coreResolveGridRowId(optionsRef.current, row);
|
|
1251
|
+
toggleGridRowExpansionCommand(
|
|
1252
|
+
gridApiRef.current,
|
|
1253
|
+
FEATURE_EXPANDABLE && canGridExpandRows(optionsRef.current),
|
|
1254
|
+
expandedRowsRef.current,
|
|
1255
|
+
rowId,
|
|
1256
|
+
(e) => setExpandedRows(e),
|
|
1257
|
+
(resolvedRowId) => coreFindGridRowById(buildRowsFromData(optionsRef.current.data), resolvedRowId)
|
|
1258
|
+
);
|
|
1259
|
+
},
|
|
1260
|
+
[buildRowsFromData]
|
|
1261
|
+
);
|
|
1018
1262
|
const expandAllRowsFn = useCallback(() => {
|
|
1019
1263
|
if (!canGridExpandRows(optionsRef.current)) return;
|
|
1020
1264
|
expandAllGridRowsCommand(
|
|
@@ -1024,88 +1268,106 @@ function useGridState(options, onRegisterApi) {
|
|
|
1024
1268
|
);
|
|
1025
1269
|
}, [buildRowsFromData]);
|
|
1026
1270
|
const toggleAllRowsFn = useCallback(() => {
|
|
1027
|
-
const allExpanded = areAllGridRowsExpanded(
|
|
1271
|
+
const allExpanded = areAllGridRowsExpanded(
|
|
1272
|
+
buildRowsFromData(optionsRef.current.data),
|
|
1273
|
+
expandedRowsRef.current
|
|
1274
|
+
);
|
|
1028
1275
|
if (allExpanded) {
|
|
1029
1276
|
collapseAllGridRowsCommand((e) => setExpandedRows(e));
|
|
1030
1277
|
} else {
|
|
1031
1278
|
expandAllRowsFn();
|
|
1032
1279
|
}
|
|
1033
1280
|
}, [buildRowsFromData, expandAllRowsFn]);
|
|
1034
|
-
const toggleTreeRowByRefFn = useCallback(
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
rowId,
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
column
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
parseEditedValue: (column, value, oldValue) => parseGridEditedValue(column, value, oldValue),
|
|
1095
|
-
setCellValue: (rowEntity, column, value) => {
|
|
1096
|
-
const fieldPath = column.editModelField ?? column.field ?? column.name;
|
|
1097
|
-
setPathValue(rowEntity, fieldPath, value);
|
|
1281
|
+
const toggleTreeRowByRefFn = useCallback(
|
|
1282
|
+
(row) => {
|
|
1283
|
+
const rowId = coreResolveGridRowId(optionsRef.current, row);
|
|
1284
|
+
toggleGridTreeRowCommand(
|
|
1285
|
+
gridApiRef.current,
|
|
1286
|
+
expandedTreeRowsRef.current,
|
|
1287
|
+
rowId,
|
|
1288
|
+
(e) => setExpandedTreeRows(e),
|
|
1289
|
+
(resolvedRowId) => coreFindGridRowById(buildRowsFromData(optionsRef.current.data), resolvedRowId)
|
|
1290
|
+
);
|
|
1291
|
+
},
|
|
1292
|
+
[buildRowsFromData]
|
|
1293
|
+
);
|
|
1294
|
+
const expandTreeRowByRefFn = useCallback(
|
|
1295
|
+
(row) => {
|
|
1296
|
+
const rowId = coreResolveGridRowId(optionsRef.current, row);
|
|
1297
|
+
setGridTreeRowExpandedCommand(
|
|
1298
|
+
gridApiRef.current,
|
|
1299
|
+
expandedTreeRowsRef.current,
|
|
1300
|
+
rowId,
|
|
1301
|
+
true,
|
|
1302
|
+
(e) => setExpandedTreeRows(e),
|
|
1303
|
+
(resolvedRowId) => coreFindGridRowById(buildRowsFromData(optionsRef.current.data), resolvedRowId)
|
|
1304
|
+
);
|
|
1305
|
+
},
|
|
1306
|
+
[buildRowsFromData]
|
|
1307
|
+
);
|
|
1308
|
+
const collapseTreeRowByRefFn = useCallback(
|
|
1309
|
+
(row) => {
|
|
1310
|
+
const rowId = coreResolveGridRowId(optionsRef.current, row);
|
|
1311
|
+
setGridTreeRowExpandedCommand(
|
|
1312
|
+
gridApiRef.current,
|
|
1313
|
+
expandedTreeRowsRef.current,
|
|
1314
|
+
rowId,
|
|
1315
|
+
false,
|
|
1316
|
+
(e) => setExpandedTreeRows(e),
|
|
1317
|
+
(resolvedRowId) => coreFindGridRowById(buildRowsFromData(optionsRef.current.data), resolvedRowId)
|
|
1318
|
+
);
|
|
1319
|
+
},
|
|
1320
|
+
[buildRowsFromData]
|
|
1321
|
+
);
|
|
1322
|
+
const startCellEditFn = useCallback(
|
|
1323
|
+
(row, column, triggerEvent, initialValue) => {
|
|
1324
|
+
const currentValue = getCellValue2(row.entity, column);
|
|
1325
|
+
const focusToken = ++editorFocusTokenRef.current;
|
|
1326
|
+
const ec = beginGridCellEditCommand(
|
|
1327
|
+
gridApiRef.current,
|
|
1328
|
+
{
|
|
1329
|
+
setFocusedCell: (fc) => setFocusedCell(fc),
|
|
1330
|
+
setEditingCell: (ec2) => setEditingCell(ec2),
|
|
1331
|
+
setEditingValue: (ev) => setEditingValue(ev)
|
|
1332
|
+
},
|
|
1333
|
+
row,
|
|
1334
|
+
column,
|
|
1335
|
+
currentValue,
|
|
1336
|
+
triggerEvent,
|
|
1337
|
+
initialValue
|
|
1338
|
+
);
|
|
1339
|
+
if (ec) {
|
|
1340
|
+
queueMicrotask(() => focusEditorInput(focusToken));
|
|
1098
1341
|
}
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1342
|
+
},
|
|
1343
|
+
[focusEditorInput]
|
|
1344
|
+
);
|
|
1345
|
+
const commitCellEditFn = useCallback(
|
|
1346
|
+
(direction, restoreFocus = true) => {
|
|
1347
|
+
const result = commitGridCellEditCommand(gridApiRef.current, {
|
|
1348
|
+
getEditingCell: () => editingCellRef.current,
|
|
1349
|
+
getEditingValue: () => editingValueRef.current,
|
|
1350
|
+
setEditingCell: (ec) => setEditingCell(ec),
|
|
1351
|
+
setEditingValue: (ev) => setEditingValue(ev),
|
|
1352
|
+
findRowById: (rowId) => coreFindGridRowById(buildRowsFromData(optionsRef.current.data), rowId),
|
|
1353
|
+
findColumnByName: (columnName) => visibleColumnsRef.current.find((c) => c.name === columnName),
|
|
1354
|
+
parseEditedValue: (column, value, oldValue) => parseGridEditedValue(column, value, oldValue),
|
|
1355
|
+
setCellValue: (rowEntity, column, value) => {
|
|
1356
|
+
const fieldPath = column.editModelField ?? column.field ?? column.name;
|
|
1357
|
+
setPathValue(rowEntity, fieldPath, value);
|
|
1358
|
+
}
|
|
1359
|
+
});
|
|
1360
|
+
if (!result.committed || !result.row || !result.column || !result.focusTarget) return;
|
|
1361
|
+
editorFocusTokenRef.current += 1;
|
|
1362
|
+
if (direction) {
|
|
1363
|
+
const moved = moveFocusFn(result.row, result.column, direction);
|
|
1364
|
+
if (!moved) focusRenderedCell(result.focusTarget);
|
|
1365
|
+
} else if (restoreFocus) {
|
|
1366
|
+
focusRenderedCell(result.focusTarget);
|
|
1367
|
+
}
|
|
1368
|
+
},
|
|
1369
|
+
[buildRowsFromData, focusRenderedCell]
|
|
1370
|
+
);
|
|
1109
1371
|
const cancelCellEditFn = useCallback(() => {
|
|
1110
1372
|
const hadEditingCell = editingCellRef.current !== null;
|
|
1111
1373
|
const result = cancelGridCellEditCommand(gridApiRef.current, {
|
|
@@ -1119,26 +1381,32 @@ function useGridState(options, onRegisterApi) {
|
|
|
1119
1381
|
editorFocusTokenRef.current += 1;
|
|
1120
1382
|
if (result.focusTarget) focusRenderedCell(result.focusTarget);
|
|
1121
1383
|
}, [buildRowsFromData, focusRenderedCell]);
|
|
1122
|
-
const moveFocusFn = useCallback(
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1384
|
+
const moveFocusFn = useCallback(
|
|
1385
|
+
(row, column, direction, triggerEvent) => {
|
|
1386
|
+
const nextCell = findNextGridCell({
|
|
1387
|
+
rows: pipelineRef.current.visibleRows,
|
|
1388
|
+
columns: visibleColumnsRef.current,
|
|
1389
|
+
rowId: row.id,
|
|
1390
|
+
columnName: column.name,
|
|
1391
|
+
direction
|
|
1392
|
+
});
|
|
1393
|
+
if (!nextCell) return false;
|
|
1394
|
+
setFocusedCell({ rowId: nextCell.row.id, columnName: nextCell.column.name });
|
|
1395
|
+
focusRenderedCell({ rowId: nextCell.row.id, columnName: nextCell.column.name });
|
|
1396
|
+
if (shouldEditOnFocusFn(nextCell.column) && isCellEditable(nextCell.row, nextCell.column, triggerEvent)) {
|
|
1397
|
+
startCellEditFn(nextCell.row, nextCell.column, triggerEvent);
|
|
1398
|
+
}
|
|
1399
|
+
return true;
|
|
1400
|
+
},
|
|
1401
|
+
[focusRenderedCell, isCellEditable, shouldEditOnFocusFn, startCellEditFn]
|
|
1402
|
+
);
|
|
1138
1403
|
const runBenchmarkFn = useCallback((iterations) => {
|
|
1139
|
-
const safeIterations =
|
|
1404
|
+
const safeIterations = resolveBenchmarkIterations(
|
|
1405
|
+
iterations,
|
|
1406
|
+
optionsRef.current.benchmark?.iterations
|
|
1407
|
+
);
|
|
1140
1408
|
const startedAt = performance.now();
|
|
1141
|
-
let lastResult =
|
|
1409
|
+
let lastResult = defaultGridEngine.buildPipeline({
|
|
1142
1410
|
options: optionsRef.current,
|
|
1143
1411
|
columns: visibleColumnsRef.current,
|
|
1144
1412
|
activeFilters: activeFiltersRef.current,
|
|
@@ -1153,7 +1421,7 @@ function useGridState(options, onRegisterApi) {
|
|
|
1153
1421
|
rowSize: optionsRef.current.rowHeight ?? 44
|
|
1154
1422
|
});
|
|
1155
1423
|
for (let i = 1; i < safeIterations; i++) {
|
|
1156
|
-
lastResult =
|
|
1424
|
+
lastResult = defaultGridEngine.buildPipeline({
|
|
1157
1425
|
options: optionsRef.current,
|
|
1158
1426
|
columns: visibleColumnsRef.current,
|
|
1159
1427
|
activeFilters: activeFiltersRef.current,
|
|
@@ -1199,6 +1467,7 @@ function useGridState(options, onRegisterApi) {
|
|
|
1199
1467
|
setExpandedTreeRows({});
|
|
1200
1468
|
setColumnOrder(options.columnDefs.map((column) => column.name));
|
|
1201
1469
|
setGroupByColumns(options.grouping?.groupBy ?? []);
|
|
1470
|
+
setPinnedColumns(buildInitialPinnedState(options.columnDefs));
|
|
1202
1471
|
setCurrentPage(options.paginationCurrentPage ?? 1);
|
|
1203
1472
|
setPageSize(coreGetEffectivePageSize(options, 0, options.data.length));
|
|
1204
1473
|
setInfiniteScrollState({
|
|
@@ -1231,8 +1500,15 @@ function useGridState(options, onRegisterApi) {
|
|
|
1231
1500
|
const container = gridContainerRef.current;
|
|
1232
1501
|
if (!container) return;
|
|
1233
1502
|
const observer = observeGridHostSize(container, ({ height: nextHeight, width: nextWidth }) => {
|
|
1234
|
-
if (nextHeight === lastGridHeightRef.current && nextWidth === lastGridWidthRef.current)
|
|
1235
|
-
|
|
1503
|
+
if (nextHeight === lastGridHeightRef.current && nextWidth === lastGridWidthRef.current)
|
|
1504
|
+
return;
|
|
1505
|
+
raiseGridDimensionChanged(
|
|
1506
|
+
gridApi,
|
|
1507
|
+
lastGridHeightRef.current,
|
|
1508
|
+
lastGridWidthRef.current,
|
|
1509
|
+
nextHeight,
|
|
1510
|
+
nextWidth
|
|
1511
|
+
);
|
|
1236
1512
|
lastGridHeightRef.current = nextHeight;
|
|
1237
1513
|
lastGridWidthRef.current = nextWidth;
|
|
1238
1514
|
if (!options.viewportHeight && nextHeight > 0) {
|
|
@@ -1250,42 +1526,75 @@ function useGridState(options, onRegisterApi) {
|
|
|
1250
1526
|
const paginationCurrentPage = getCurrentPageValueFn();
|
|
1251
1527
|
const paginationTotalPages = getTotalPagesValueFn();
|
|
1252
1528
|
const paginationSelectedPageSize = effectivePageSizeFn(pipeline.totalItems);
|
|
1253
|
-
const viewportHeightPx =
|
|
1529
|
+
const viewportHeightPx = computeViewportHeightPx(options.viewportHeight, autoViewportHeight);
|
|
1254
1530
|
const headerLabelFn = useCallback((column) => coreHeaderLabel(column), []);
|
|
1255
|
-
const isGroupItemFn = useCallback(
|
|
1256
|
-
|
|
1531
|
+
const isGroupItemFn = useCallback(
|
|
1532
|
+
(item) => item.kind === "group",
|
|
1533
|
+
[]
|
|
1534
|
+
);
|
|
1535
|
+
const isExpandableItemFn = useCallback(
|
|
1536
|
+
(item) => item.kind === "expandable",
|
|
1537
|
+
[]
|
|
1538
|
+
);
|
|
1257
1539
|
const isRowItemFn = useCallback((item) => item.kind === "row", []);
|
|
1258
|
-
const isOddStripedRowFn = useCallback(
|
|
1540
|
+
const isOddStripedRowFn = useCallback(
|
|
1541
|
+
(item) => item.kind === "row" && item.visibleIndex % 2 === 0,
|
|
1542
|
+
[]
|
|
1543
|
+
);
|
|
1259
1544
|
const sortDirectionFn = useCallback((column) => {
|
|
1260
1545
|
return sortStateRef.current.columnName === column.name ? sortStateRef.current.direction : SORT_DIRECTIONS2.none;
|
|
1261
1546
|
}, []);
|
|
1262
|
-
const sortButtonLabelFn = useCallback(
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
const
|
|
1269
|
-
|
|
1270
|
-
|
|
1547
|
+
const sortButtonLabelFn = useCallback(
|
|
1548
|
+
(column) => {
|
|
1549
|
+
return gridSortButtonLabel(sortDirectionFn(column), labels);
|
|
1550
|
+
},
|
|
1551
|
+
[labels, sortDirectionFn]
|
|
1552
|
+
);
|
|
1553
|
+
const sortAriaSortFn = useCallback(
|
|
1554
|
+
(column) => {
|
|
1555
|
+
return gridSortAriaSort(sortDirectionFn(column));
|
|
1556
|
+
},
|
|
1557
|
+
[sortDirectionFn]
|
|
1558
|
+
);
|
|
1559
|
+
const groupingButtonLabelFn = useCallback(
|
|
1560
|
+
(column) => {
|
|
1561
|
+
return gridGroupingButtonLabel(
|
|
1562
|
+
isGridColumnGrouped(groupByColumnsRef.current, column),
|
|
1563
|
+
labels
|
|
1564
|
+
);
|
|
1565
|
+
},
|
|
1566
|
+
[labels]
|
|
1567
|
+
);
|
|
1271
1568
|
const filterValueFn = useCallback((columnName) => {
|
|
1272
1569
|
return activeFiltersRef.current[columnName] ?? "";
|
|
1273
1570
|
}, []);
|
|
1274
|
-
const filterPlaceholderFn = useCallback(
|
|
1275
|
-
|
|
1276
|
-
|
|
1571
|
+
const filterPlaceholderFn = useCallback(
|
|
1572
|
+
(column) => {
|
|
1573
|
+
return gridFilterPlaceholder(isGridColumnFilterable(optionsRef.current, column), labels);
|
|
1574
|
+
},
|
|
1575
|
+
[labels]
|
|
1576
|
+
);
|
|
1277
1577
|
const isFilterInputDisabledFn = useCallback((column) => {
|
|
1278
1578
|
return !isGridColumnFilterable(optionsRef.current, column);
|
|
1279
1579
|
}, []);
|
|
1280
|
-
const groupDisclosureLabelFn = useCallback(
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
const
|
|
1287
|
-
|
|
1288
|
-
|
|
1580
|
+
const groupDisclosureLabelFn = useCallback(
|
|
1581
|
+
(item) => {
|
|
1582
|
+
return gridGroupDisclosureLabel(item.collapsed, labels);
|
|
1583
|
+
},
|
|
1584
|
+
[labels]
|
|
1585
|
+
);
|
|
1586
|
+
const cellContextFn = useCallback(
|
|
1587
|
+
(row, column) => {
|
|
1588
|
+
return buildGridCellContext(row, column);
|
|
1589
|
+
},
|
|
1590
|
+
[]
|
|
1591
|
+
);
|
|
1592
|
+
const displayValueFn = useCallback(
|
|
1593
|
+
(row, column) => {
|
|
1594
|
+
return formatGridCellDisplayValue(cellContextFn(row, column));
|
|
1595
|
+
},
|
|
1596
|
+
[cellContextFn]
|
|
1597
|
+
);
|
|
1289
1598
|
const isFocusedCellFn = useCallback((row, column) => {
|
|
1290
1599
|
return isGridCellPosition(focusedCellRef.current, row.id, column.name);
|
|
1291
1600
|
}, []);
|
|
@@ -1295,16 +1604,19 @@ function useGridState(options, onRegisterApi) {
|
|
|
1295
1604
|
const editorInputTypeFn = useCallback((column) => {
|
|
1296
1605
|
return gridEditorInputType(column);
|
|
1297
1606
|
}, []);
|
|
1298
|
-
const expandedContextFn = useCallback(
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1607
|
+
const expandedContextFn = useCallback(
|
|
1608
|
+
(row) => {
|
|
1609
|
+
return {
|
|
1610
|
+
$implicit: row.entity,
|
|
1611
|
+
row: row.entity,
|
|
1612
|
+
rowIndex: row.index,
|
|
1613
|
+
expanded: true,
|
|
1614
|
+
...optionsRef.current.expandableRowScope ?? {}
|
|
1615
|
+
};
|
|
1616
|
+
},
|
|
1617
|
+
[]
|
|
1618
|
+
);
|
|
1619
|
+
const columnWidthFn = useCallback((column) => gridColumnWidth2(column), []);
|
|
1308
1620
|
const isColumnSortableFn = useCallback((column) => {
|
|
1309
1621
|
return isGridColumnSortable(optionsRef.current, column);
|
|
1310
1622
|
}, []);
|
|
@@ -1314,15 +1626,21 @@ function useGridState(options, onRegisterApi) {
|
|
|
1314
1626
|
const cellIndentFn = useCallback((row, column) => {
|
|
1315
1627
|
return gridCellIndent(optionsRef.current, visibleColumnsRef.current, row, column);
|
|
1316
1628
|
}, []);
|
|
1317
|
-
const treeToggleLabelFn = useCallback(
|
|
1318
|
-
|
|
1319
|
-
|
|
1629
|
+
const treeToggleLabelFn = useCallback(
|
|
1630
|
+
(row) => {
|
|
1631
|
+
return gridTreeToggleLabelForRow(expandedTreeRowsRef.current, row, labels);
|
|
1632
|
+
},
|
|
1633
|
+
[labels]
|
|
1634
|
+
);
|
|
1320
1635
|
const isTreeRowExpandedFn = useCallback((row) => {
|
|
1321
1636
|
return isGridTreeRowExpanded(expandedTreeRowsRef.current, row);
|
|
1322
1637
|
}, []);
|
|
1323
|
-
const expandToggleLabelFn = useCallback(
|
|
1324
|
-
|
|
1325
|
-
|
|
1638
|
+
const expandToggleLabelFn = useCallback(
|
|
1639
|
+
(row) => {
|
|
1640
|
+
return gridExpandToggleLabelForRow(row, labels);
|
|
1641
|
+
},
|
|
1642
|
+
[labels]
|
|
1643
|
+
);
|
|
1326
1644
|
const isGroupedFn = useCallback((column) => {
|
|
1327
1645
|
return isGridColumnGrouped(groupByColumnsRef.current, column);
|
|
1328
1646
|
}, []);
|
|
@@ -1337,8 +1655,7 @@ function useGridState(options, onRegisterApi) {
|
|
|
1337
1655
|
}, []);
|
|
1338
1656
|
const paginationSummaryFn = useCallback(() => {
|
|
1339
1657
|
const ti = pipelineRef.current.totalItems;
|
|
1340
|
-
|
|
1341
|
-
return `${getFirstRowIndexValueFn(ti) + 1}-${getLastRowIndexValueFn(ti) + 1} of ${ti}`;
|
|
1658
|
+
return formatPaginationSummary(ti, getFirstRowIndexValueFn(ti), getLastRowIndexValueFn(ti));
|
|
1342
1659
|
}, [getFirstRowIndexValueFn, getLastRowIndexValueFn]);
|
|
1343
1660
|
const pageSizeOptionsFn = useCallback(() => {
|
|
1344
1661
|
return optionsRef.current.paginationPageSizes ?? [];
|
|
@@ -1385,108 +1702,130 @@ function useGridState(options, onRegisterApi) {
|
|
|
1385
1702
|
[item.id]: !current[item.id]
|
|
1386
1703
|
}));
|
|
1387
1704
|
}, []);
|
|
1388
|
-
const focusCellFn = useCallback(
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1705
|
+
const focusCellFn = useCallback(
|
|
1706
|
+
(row, column, triggerEvent) => {
|
|
1707
|
+
const nextFocusResult = buildGridFocusCellResult({
|
|
1708
|
+
currentFocusedCell: focusedCellRef.current,
|
|
1709
|
+
currentEditingCell: editingCellRef.current,
|
|
1710
|
+
rowId: row.id,
|
|
1711
|
+
columnName: column.name,
|
|
1712
|
+
shouldEditOnFocus: shouldEditOnFocusFn(column),
|
|
1713
|
+
isCellEditable: isCellEditable(row, column, triggerEvent)
|
|
1714
|
+
});
|
|
1715
|
+
setFocusedCell(nextFocusResult.focusedCell);
|
|
1716
|
+
if (nextFocusResult.shouldBeginEdit) {
|
|
1717
|
+
startCellEditFn(row, column, triggerEvent);
|
|
1718
|
+
}
|
|
1719
|
+
},
|
|
1720
|
+
[isCellEditable, shouldEditOnFocusFn, startCellEditFn]
|
|
1721
|
+
);
|
|
1722
|
+
const handleCellKeyDownFn = useCallback(
|
|
1723
|
+
(row, column, event) => {
|
|
1724
|
+
focusCellFn(row, column, event.nativeEvent);
|
|
1725
|
+
switch (event.key) {
|
|
1726
|
+
case "ArrowLeft":
|
|
1727
|
+
event.preventDefault();
|
|
1728
|
+
moveFocusFn(row, column, "left", event.nativeEvent);
|
|
1729
|
+
return;
|
|
1730
|
+
case "ArrowRight":
|
|
1731
|
+
event.preventDefault();
|
|
1732
|
+
moveFocusFn(row, column, "right", event.nativeEvent);
|
|
1733
|
+
return;
|
|
1734
|
+
case "ArrowUp":
|
|
1735
|
+
event.preventDefault();
|
|
1736
|
+
moveFocusFn(row, column, "up", event.nativeEvent);
|
|
1737
|
+
return;
|
|
1738
|
+
case "ArrowDown":
|
|
1739
|
+
event.preventDefault();
|
|
1740
|
+
moveFocusFn(row, column, "down", event.nativeEvent);
|
|
1741
|
+
return;
|
|
1742
|
+
case "Tab":
|
|
1743
|
+
event.preventDefault();
|
|
1744
|
+
moveFocusFn(row, column, event.shiftKey ? "left" : "right", event.nativeEvent);
|
|
1745
|
+
return;
|
|
1746
|
+
case "Enter":
|
|
1747
|
+
event.preventDefault();
|
|
1748
|
+
moveFocusFn(row, column, event.shiftKey ? "up" : "down", event.nativeEvent);
|
|
1749
|
+
return;
|
|
1750
|
+
case "F2":
|
|
1751
|
+
event.preventDefault();
|
|
1752
|
+
if (isCellEditable(row, column, event.nativeEvent)) {
|
|
1753
|
+
startCellEditFn(row, column, event.nativeEvent);
|
|
1754
|
+
}
|
|
1755
|
+
return;
|
|
1756
|
+
case "Backspace":
|
|
1757
|
+
case "Delete":
|
|
1758
|
+
if (isCellEditable(row, column, event.nativeEvent)) {
|
|
1759
|
+
event.preventDefault();
|
|
1760
|
+
startCellEditFn(row, column, event.nativeEvent, "");
|
|
1761
|
+
}
|
|
1762
|
+
return;
|
|
1763
|
+
default:
|
|
1764
|
+
break;
|
|
1765
|
+
}
|
|
1766
|
+
if (isPrintableGridKey(event.key, event.ctrlKey, event.metaKey, event.altKey) && isCellEditable(row, column, event.nativeEvent)) {
|
|
1418
1767
|
event.preventDefault();
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1768
|
+
startCellEditFn(row, column, event.nativeEvent, event.key);
|
|
1769
|
+
}
|
|
1770
|
+
},
|
|
1771
|
+
[focusCellFn, moveFocusFn, isCellEditable, startCellEditFn]
|
|
1772
|
+
);
|
|
1773
|
+
const handleCellDoubleClickFn = useCallback(
|
|
1774
|
+
(row, column, event) => {
|
|
1775
|
+
focusCellFn(row, column, event.nativeEvent);
|
|
1776
|
+
if (isCellEditable(row, column, event.nativeEvent)) {
|
|
1777
|
+
startCellEditFn(row, column, event.nativeEvent);
|
|
1778
|
+
}
|
|
1779
|
+
},
|
|
1780
|
+
[focusCellFn, isCellEditable, startCellEditFn]
|
|
1781
|
+
);
|
|
1782
|
+
const updateEditingValueFn = useCallback((value) => {
|
|
1783
|
+
setEditingValue(value);
|
|
1784
|
+
}, []);
|
|
1785
|
+
const handleEditorKeyDownFn = useCallback(
|
|
1786
|
+
(event) => {
|
|
1787
|
+
if (event.key === "Escape") {
|
|
1422
1788
|
event.preventDefault();
|
|
1423
|
-
|
|
1789
|
+
cancelCellEditFn();
|
|
1424
1790
|
return;
|
|
1425
|
-
|
|
1791
|
+
}
|
|
1792
|
+
if (event.key === "Enter") {
|
|
1426
1793
|
event.preventDefault();
|
|
1427
|
-
|
|
1794
|
+
commitCellEditFn(event.shiftKey ? "up" : "down");
|
|
1428
1795
|
return;
|
|
1429
|
-
|
|
1796
|
+
}
|
|
1797
|
+
if (event.key === "Tab") {
|
|
1430
1798
|
event.preventDefault();
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1799
|
+
commitCellEditFn(event.shiftKey ? "left" : "right");
|
|
1800
|
+
}
|
|
1801
|
+
},
|
|
1802
|
+
[cancelCellEditFn, commitCellEditFn]
|
|
1803
|
+
);
|
|
1804
|
+
const handleEditorBlurFn = useCallback(
|
|
1805
|
+
(event) => {
|
|
1806
|
+
const ec = editingCellRef.current;
|
|
1807
|
+
const target = event.target;
|
|
1808
|
+
if (!ec || !target) return;
|
|
1809
|
+
if (target.dataset["rowId"] !== ec.rowId || target.dataset["colName"] !== ec.columnName)
|
|
1441
1810
|
return;
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
if (event.key === "Escape") {
|
|
1461
|
-
event.preventDefault();
|
|
1462
|
-
cancelCellEditFn();
|
|
1463
|
-
return;
|
|
1464
|
-
}
|
|
1465
|
-
if (event.key === "Enter") {
|
|
1466
|
-
event.preventDefault();
|
|
1467
|
-
commitCellEditFn(event.shiftKey ? "up" : "down");
|
|
1468
|
-
return;
|
|
1469
|
-
}
|
|
1470
|
-
if (event.key === "Tab") {
|
|
1471
|
-
event.preventDefault();
|
|
1472
|
-
commitCellEditFn(event.shiftKey ? "left" : "right");
|
|
1473
|
-
}
|
|
1474
|
-
}, [cancelCellEditFn, commitCellEditFn]);
|
|
1475
|
-
const handleEditorBlurFn = useCallback((event) => {
|
|
1476
|
-
const ec = editingCellRef.current;
|
|
1477
|
-
const target = event.target;
|
|
1478
|
-
if (!ec || !target) return;
|
|
1479
|
-
if (target.dataset["rowId"] !== ec.rowId || target.dataset["colName"] !== ec.columnName) return;
|
|
1480
|
-
commitCellEditFn(void 0, false);
|
|
1481
|
-
}, [commitCellEditFn]);
|
|
1482
|
-
const toggleRowExpansionFn = useCallback((row, event) => {
|
|
1483
|
-
event?.stopPropagation();
|
|
1484
|
-
toggleRowExpansionByRefFn(row);
|
|
1485
|
-
}, [toggleRowExpansionByRefFn]);
|
|
1486
|
-
const toggleTreeRowFn = useCallback((row, event) => {
|
|
1487
|
-
event?.stopPropagation();
|
|
1488
|
-
toggleTreeRowByRefFn(row);
|
|
1489
|
-
}, [toggleTreeRowByRefFn]);
|
|
1811
|
+
commitCellEditFn(void 0, false);
|
|
1812
|
+
},
|
|
1813
|
+
[commitCellEditFn]
|
|
1814
|
+
);
|
|
1815
|
+
const toggleRowExpansionFn = useCallback(
|
|
1816
|
+
(row, event) => {
|
|
1817
|
+
event?.stopPropagation();
|
|
1818
|
+
toggleRowExpansionByRefFn(row);
|
|
1819
|
+
},
|
|
1820
|
+
[toggleRowExpansionByRefFn]
|
|
1821
|
+
);
|
|
1822
|
+
const toggleTreeRowFn = useCallback(
|
|
1823
|
+
(row, event) => {
|
|
1824
|
+
event?.stopPropagation();
|
|
1825
|
+
toggleTreeRowByRefFn(row);
|
|
1826
|
+
},
|
|
1827
|
+
[toggleTreeRowByRefFn]
|
|
1828
|
+
);
|
|
1490
1829
|
const moveColumnFn = useCallback((fromIndex, toIndex) => {
|
|
1491
1830
|
moveGridColumnCommand(
|
|
1492
1831
|
gridApiRef.current,
|
|
@@ -1502,9 +1841,12 @@ function useGridState(options, onRegisterApi) {
|
|
|
1502
1841
|
const previousPageFn = useCallback(() => {
|
|
1503
1842
|
seekPageFn(getCurrentPageValueFn() - 1);
|
|
1504
1843
|
}, [seekPageFn, getCurrentPageValueFn]);
|
|
1505
|
-
const onPageSizeChangeFn = useCallback(
|
|
1506
|
-
|
|
1507
|
-
|
|
1844
|
+
const onPageSizeChangeFn = useCallback(
|
|
1845
|
+
(value) => {
|
|
1846
|
+
setPaginationPageSizeFn(Number(value));
|
|
1847
|
+
},
|
|
1848
|
+
[setPaginationPageSizeFn]
|
|
1849
|
+
);
|
|
1508
1850
|
const onViewportScrollFn = useCallback((startIndex) => {
|
|
1509
1851
|
if (!scrollingRef.current) {
|
|
1510
1852
|
scrollingRef.current = true;
|
|
@@ -1524,7 +1866,10 @@ function useGridState(options, onRegisterApi) {
|
|
|
1524
1866
|
state: infiniteScrollStateRef.current,
|
|
1525
1867
|
startIndex,
|
|
1526
1868
|
visibleRows: pipelineRef.current.visibleRows.length,
|
|
1527
|
-
viewportRows:
|
|
1869
|
+
viewportRows: computeViewportRows(
|
|
1870
|
+
optionsRef.current.viewportHeight,
|
|
1871
|
+
optionsRef.current.rowHeight
|
|
1872
|
+
),
|
|
1528
1873
|
threshold: optionsRef.current.infiniteScrollRowsFromEnd ?? 20,
|
|
1529
1874
|
setState: (state) => setInfiniteScrollState(state)
|
|
1530
1875
|
});
|
|
@@ -1624,29 +1969,60 @@ function useGridState(options, onRegisterApi) {
|
|
|
1624
1969
|
onPageSizeChange: onPageSizeChangeFn,
|
|
1625
1970
|
runBenchmark: runBenchmarkFn,
|
|
1626
1971
|
exportCsv: exportCsvFn,
|
|
1627
|
-
onViewportScroll: onViewportScrollFn
|
|
1972
|
+
onViewportScroll: onViewportScrollFn,
|
|
1973
|
+
// Pinning
|
|
1974
|
+
isPinned: isPinnedFn,
|
|
1975
|
+
pinnedOffset: pinnedOffsetFn,
|
|
1976
|
+
isPinningEnabled: isPinningEnabledFn,
|
|
1977
|
+
isColumnPinnable: isColumnPinnableFn,
|
|
1978
|
+
togglePin: togglePinFn,
|
|
1979
|
+
pinningFeature: FEATURE_PINNING
|
|
1628
1980
|
};
|
|
1629
1981
|
}
|
|
1630
1982
|
|
|
1631
1983
|
// src/useVirtualScroll.ts
|
|
1632
1984
|
import { useCallback as useCallback2, useRef as useRef2, useState as useState2 } from "react";
|
|
1985
|
+
|
|
1986
|
+
// src/virtualScrollMath.ts
|
|
1987
|
+
function calculateVirtualWindow(request) {
|
|
1988
|
+
const overscan = request.overscan ?? 3;
|
|
1989
|
+
if (request.itemCount <= 0 || request.itemSize <= 0) {
|
|
1990
|
+
return {
|
|
1991
|
+
visibleRange: { start: 0, end: 0 },
|
|
1992
|
+
totalHeight: Math.max(0, request.itemCount) * Math.max(0, request.itemSize),
|
|
1993
|
+
offsetY: 0
|
|
1994
|
+
};
|
|
1995
|
+
}
|
|
1996
|
+
const rawStart = Math.floor(request.scrollTop / request.itemSize) - overscan;
|
|
1997
|
+
const start = Math.max(0, rawStart);
|
|
1998
|
+
const rawEnd = rawStart + Math.ceil(request.viewportHeight / request.itemSize) + 2 * overscan;
|
|
1999
|
+
const end = Math.min(request.itemCount, rawEnd);
|
|
2000
|
+
return {
|
|
2001
|
+
visibleRange: { start, end },
|
|
2002
|
+
totalHeight: request.itemCount * request.itemSize,
|
|
2003
|
+
offsetY: start * request.itemSize
|
|
2004
|
+
};
|
|
2005
|
+
}
|
|
2006
|
+
|
|
2007
|
+
// src/useVirtualScroll.ts
|
|
1633
2008
|
function useVirtualScroll(options) {
|
|
1634
2009
|
const { itemCount, itemSize, viewportHeight, overscan = 3 } = options;
|
|
1635
2010
|
const [scrollTop, setScrollTop] = useState2(0);
|
|
1636
2011
|
const viewportRef = useRef2(null);
|
|
1637
|
-
const
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
2012
|
+
const virtualWindow = calculateVirtualWindow({
|
|
2013
|
+
itemCount,
|
|
2014
|
+
itemSize,
|
|
2015
|
+
viewportHeight,
|
|
2016
|
+
overscan,
|
|
2017
|
+
scrollTop
|
|
2018
|
+
});
|
|
1643
2019
|
const onScroll = useCallback2((event) => {
|
|
1644
2020
|
setScrollTop(event.currentTarget.scrollTop);
|
|
1645
2021
|
}, []);
|
|
1646
2022
|
return {
|
|
1647
|
-
visibleRange:
|
|
1648
|
-
totalHeight,
|
|
1649
|
-
offsetY,
|
|
2023
|
+
visibleRange: virtualWindow.visibleRange,
|
|
2024
|
+
totalHeight: virtualWindow.totalHeight,
|
|
2025
|
+
offsetY: virtualWindow.offsetY,
|
|
1650
2026
|
onScroll,
|
|
1651
2027
|
viewportRef,
|
|
1652
2028
|
scrollTop
|
|
@@ -1655,7 +2031,13 @@ function useVirtualScroll(options) {
|
|
|
1655
2031
|
|
|
1656
2032
|
// src/UiGrid.tsx
|
|
1657
2033
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1658
|
-
function UiGrid({
|
|
2034
|
+
function UiGrid({
|
|
2035
|
+
options,
|
|
2036
|
+
onRegisterApi,
|
|
2037
|
+
cellRenderer,
|
|
2038
|
+
expandableRenderer,
|
|
2039
|
+
className
|
|
2040
|
+
}) {
|
|
1659
2041
|
const state = useGridState(options, onRegisterApi);
|
|
1660
2042
|
const {
|
|
1661
2043
|
pipeline,
|
|
@@ -1719,7 +2101,16 @@ function UiGrid({ options, onRegisterApi, cellRenderer, expandableRenderer, clas
|
|
|
1719
2101
|
" ",
|
|
1720
2102
|
labels.groupRowsSuffix
|
|
1721
2103
|
] }),
|
|
1722
|
-
/* @__PURE__ */ jsx(
|
|
2104
|
+
/* @__PURE__ */ jsx(
|
|
2105
|
+
"svg",
|
|
2106
|
+
{
|
|
2107
|
+
className: "toggle-icon group-disclosure-icon",
|
|
2108
|
+
viewBox: "0 0 24 24",
|
|
2109
|
+
"aria-hidden": "true",
|
|
2110
|
+
focusable: false,
|
|
2111
|
+
children: /* @__PURE__ */ jsx("path", { d: item.collapsed ? "M10 7l5 5-5 5z" : "M7 10l5 5 5-5z" })
|
|
2112
|
+
}
|
|
2113
|
+
),
|
|
1723
2114
|
/* @__PURE__ */ jsx("span", { className: "sr-only ui-grid-sr-only", children: state.groupDisclosureLabel(item) })
|
|
1724
2115
|
]
|
|
1725
2116
|
},
|
|
@@ -1741,62 +2132,84 @@ function UiGrid({ options, onRegisterApi, cellRenderer, expandableRenderer, clas
|
|
|
1741
2132
|
}
|
|
1742
2133
|
if (item.kind !== "row") return null;
|
|
1743
2134
|
const rowItem = item;
|
|
1744
|
-
return visibleColumns.map((column) =>
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
"
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
}
|
|
1769
|
-
),
|
|
1770
|
-
expandableFeature && state.showExpandToggle(rowItem.row, column) && /* @__PURE__ */ jsx(
|
|
1771
|
-
"button",
|
|
1772
|
-
{
|
|
1773
|
-
type: "button",
|
|
1774
|
-
className: "row-toggle row-toggle-expand",
|
|
1775
|
-
"data-part": "expand-toggle",
|
|
1776
|
-
"aria-label": state.expandToggleLabel(rowItem.row),
|
|
1777
|
-
"aria-expanded": rowItem.row.expanded,
|
|
1778
|
-
onClick: (e) => state.toggleRowExpansion(rowItem.row, e),
|
|
1779
|
-
children: /* @__PURE__ */ jsx("svg", { className: "toggle-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: rowItem.row.expanded ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z" }) })
|
|
1780
|
-
}
|
|
1781
|
-
),
|
|
1782
|
-
/* @__PURE__ */ jsx("span", { className: "cell-value", children: cellEditFeature && state.isEditingCell(rowItem.row, column) ? /* @__PURE__ */ jsx(
|
|
1783
|
-
"input",
|
|
2135
|
+
return visibleColumns.map((column) => {
|
|
2136
|
+
const pinned = state.isPinned(column);
|
|
2137
|
+
const pinOffset = pinned ? state.pinnedOffset(column) : null;
|
|
2138
|
+
return /* @__PURE__ */ jsx(
|
|
2139
|
+
"div",
|
|
2140
|
+
{
|
|
2141
|
+
className: `${cellClassName(rowItem, column)}${pinned ? " is-pinned" : ""}`,
|
|
2142
|
+
"data-part": "body-cell",
|
|
2143
|
+
role: "gridcell",
|
|
2144
|
+
tabIndex: 0,
|
|
2145
|
+
"data-row-id": rowItem.row.id,
|
|
2146
|
+
"data-col-name": column.name,
|
|
2147
|
+
onFocus: () => state.focusCell(rowItem.row, column),
|
|
2148
|
+
onClick: () => state.focusCell(rowItem.row, column),
|
|
2149
|
+
onDoubleClick: (e) => state.handleCellDoubleClick(rowItem.row, column, e),
|
|
2150
|
+
onKeyDown: (e) => state.handleCellKeyDown(rowItem.row, column, e),
|
|
2151
|
+
style: {
|
|
2152
|
+
position: pinned ? "sticky" : void 0,
|
|
2153
|
+
left: pinOffset?.side === "left" ? pinOffset.offset : void 0,
|
|
2154
|
+
right: pinOffset?.side === "right" ? pinOffset.offset : void 0,
|
|
2155
|
+
zIndex: pinned ? 2 : void 0
|
|
2156
|
+
},
|
|
2157
|
+
children: /* @__PURE__ */ jsxs(
|
|
2158
|
+
"div",
|
|
1784
2159
|
{
|
|
1785
|
-
className: "cell-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
2160
|
+
className: "cell-shell",
|
|
2161
|
+
style: { paddingInlineStart: state.cellIndent(rowItem.row, column) },
|
|
2162
|
+
children: [
|
|
2163
|
+
treeViewFeature && state.showTreeToggle(rowItem.row, column) && /* @__PURE__ */ jsx(
|
|
2164
|
+
"button",
|
|
2165
|
+
{
|
|
2166
|
+
type: "button",
|
|
2167
|
+
className: "row-toggle row-toggle-tree",
|
|
2168
|
+
"data-part": "tree-toggle",
|
|
2169
|
+
"aria-label": state.treeToggleLabel(rowItem.row),
|
|
2170
|
+
"aria-expanded": state.isTreeRowExpanded(rowItem.row),
|
|
2171
|
+
onClick: (e) => state.toggleTreeRow(rowItem.row, e),
|
|
2172
|
+
children: /* @__PURE__ */ jsx("svg", { className: "toggle-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx(
|
|
2173
|
+
"path",
|
|
2174
|
+
{
|
|
2175
|
+
d: state.isTreeRowExpanded(rowItem.row) ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z"
|
|
2176
|
+
}
|
|
2177
|
+
) })
|
|
2178
|
+
}
|
|
2179
|
+
),
|
|
2180
|
+
expandableFeature && state.showExpandToggle(rowItem.row, column) && /* @__PURE__ */ jsx(
|
|
2181
|
+
"button",
|
|
2182
|
+
{
|
|
2183
|
+
type: "button",
|
|
2184
|
+
className: "row-toggle row-toggle-expand",
|
|
2185
|
+
"data-part": "expand-toggle",
|
|
2186
|
+
"aria-label": state.expandToggleLabel(rowItem.row),
|
|
2187
|
+
"aria-expanded": rowItem.row.expanded,
|
|
2188
|
+
onClick: (e) => state.toggleRowExpansion(rowItem.row, e),
|
|
2189
|
+
children: /* @__PURE__ */ jsx("svg", { className: "toggle-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: rowItem.row.expanded ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z" }) })
|
|
2190
|
+
}
|
|
2191
|
+
),
|
|
2192
|
+
/* @__PURE__ */ jsx("span", { className: "cell-value", children: cellEditFeature && state.isEditingCell(rowItem.row, column) ? /* @__PURE__ */ jsx(
|
|
2193
|
+
"input",
|
|
2194
|
+
{
|
|
2195
|
+
className: "cell-editor",
|
|
2196
|
+
"data-row-id": rowItem.row.id,
|
|
2197
|
+
"data-col-name": column.name,
|
|
2198
|
+
"aria-label": state.headerLabel(column),
|
|
2199
|
+
type: state.editorInputType(column),
|
|
2200
|
+
defaultValue: editingValue,
|
|
2201
|
+
onChange: (e) => state.updateEditingValue(e.target.value),
|
|
2202
|
+
onKeyDown: (e) => state.handleEditorKeyDown(e),
|
|
2203
|
+
onBlur: (e) => state.handleEditorBlur(e)
|
|
2204
|
+
}
|
|
2205
|
+
) : cellRenderer ? cellRenderer(state.cellContext(rowItem.row, column)) ?? state.displayValue(rowItem.row, column) : state.displayValue(rowItem.row, column) })
|
|
2206
|
+
]
|
|
1794
2207
|
}
|
|
1795
|
-
)
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
)
|
|
2208
|
+
)
|
|
2209
|
+
},
|
|
2210
|
+
`${rowItem.row.id}-${column.name}`
|
|
2211
|
+
);
|
|
2212
|
+
});
|
|
1800
2213
|
}
|
|
1801
2214
|
function cellClassName(item, column) {
|
|
1802
2215
|
const classes = ["body-cell", "ui-grid-cell"];
|
|
@@ -1826,225 +2239,364 @@ function UiGrid({ options, onRegisterApi, cellRenderer, expandableRenderer, clas
|
|
|
1826
2239
|
/* @__PURE__ */ jsx("p", { className: "deck", children: "Familiar `gridOptions` and `onRegisterApi`, built with React hooks, virtualization, grouping, sorting, filtering, and column ordering." })
|
|
1827
2240
|
] }),
|
|
1828
2241
|
/* @__PURE__ */ jsxs("div", { className: "hero-actions", children: [
|
|
1829
|
-
/* @__PURE__ */ jsx(
|
|
1830
|
-
|
|
2242
|
+
/* @__PURE__ */ jsx(
|
|
2243
|
+
"button",
|
|
2244
|
+
{
|
|
2245
|
+
type: "button",
|
|
2246
|
+
className: "action action-secondary",
|
|
2247
|
+
"data-part": "action benchmark-action",
|
|
2248
|
+
onClick: () => state.runBenchmark(),
|
|
2249
|
+
children: "Benchmark"
|
|
2250
|
+
}
|
|
2251
|
+
),
|
|
2252
|
+
csvExportFeature && /* @__PURE__ */ jsx(
|
|
2253
|
+
"button",
|
|
2254
|
+
{
|
|
2255
|
+
type: "button",
|
|
2256
|
+
className: "action action-secondary",
|
|
2257
|
+
"data-part": "action export-action",
|
|
2258
|
+
onClick: () => state.exportCsv(),
|
|
2259
|
+
children: "Export CSV"
|
|
2260
|
+
}
|
|
2261
|
+
),
|
|
1831
2262
|
/* @__PURE__ */ jsxs("div", { className: "stats-card", "data-part": "stats-card", children: [
|
|
1832
2263
|
/* @__PURE__ */ jsx("span", { children: visibleRowCount }),
|
|
1833
2264
|
/* @__PURE__ */ jsx("small", { children: labels.statsVisibleRows })
|
|
1834
2265
|
] })
|
|
1835
2266
|
] })
|
|
1836
2267
|
] }),
|
|
1837
|
-
/* @__PURE__ */ jsxs(
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
1863
|
-
labels.toolbarOf,
|
|
1864
|
-
" ",
|
|
1865
|
-
totalRows,
|
|
1866
|
-
" ",
|
|
1867
|
-
labels.toolbarRows
|
|
2268
|
+
/* @__PURE__ */ jsxs(
|
|
2269
|
+
"section",
|
|
2270
|
+
{
|
|
2271
|
+
className: "metrics-strip",
|
|
2272
|
+
"data-part": "metrics",
|
|
2273
|
+
"aria-label": "Grid performance metrics",
|
|
2274
|
+
children: [
|
|
2275
|
+
/* @__PURE__ */ jsxs("article", { "data-part": "metric-card", children: [
|
|
2276
|
+
/* @__PURE__ */ jsxs("strong", { children: [
|
|
2277
|
+
pipelineMs.toFixed(2),
|
|
2278
|
+
" ms"
|
|
2279
|
+
] }),
|
|
2280
|
+
/* @__PURE__ */ jsx("span", { children: "pipeline" })
|
|
2281
|
+
] }),
|
|
2282
|
+
/* @__PURE__ */ jsxs("article", { "data-part": "metric-card", children: [
|
|
2283
|
+
/* @__PURE__ */ jsx("strong", { children: virtualizationEnabled ? "On" : "Off" }),
|
|
2284
|
+
/* @__PURE__ */ jsx("span", { children: "virtualization" })
|
|
2285
|
+
] }),
|
|
2286
|
+
/* @__PURE__ */ jsxs("article", { "data-part": "metric-card", children: [
|
|
2287
|
+
/* @__PURE__ */ jsx("strong", { children: state.groupByColumns.length }),
|
|
2288
|
+
/* @__PURE__ */ jsx("span", { children: "group columns" })
|
|
2289
|
+
] }),
|
|
2290
|
+
/* @__PURE__ */ jsxs("article", { "data-part": "metric-card", children: [
|
|
2291
|
+
/* @__PURE__ */ jsx("strong", { children: benchmarkResult?.averageMs?.toFixed(2) || "\u2014" }),
|
|
2292
|
+
/* @__PURE__ */ jsx("span", { children: "benchmark avg" })
|
|
1868
2293
|
] })
|
|
1869
|
-
]
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
2294
|
+
]
|
|
2295
|
+
}
|
|
2296
|
+
),
|
|
2297
|
+
/* @__PURE__ */ jsxs(
|
|
2298
|
+
"section",
|
|
2299
|
+
{
|
|
2300
|
+
className: "grid-frame ui-grid",
|
|
2301
|
+
"data-part": "grid-frame",
|
|
2302
|
+
role: "grid",
|
|
2303
|
+
"aria-label": options.title ?? "Data grid",
|
|
2304
|
+
children: [
|
|
2305
|
+
/* @__PURE__ */ jsxs("div", { className: "grid-toolbar", "data-part": "grid-toolbar", children: [
|
|
2306
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2307
|
+
/* @__PURE__ */ jsx("strong", { children: visibleRowCount }),
|
|
2308
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
2309
|
+
labels.toolbarOf,
|
|
2310
|
+
" ",
|
|
2311
|
+
totalRows,
|
|
2312
|
+
" ",
|
|
2313
|
+
labels.toolbarRows
|
|
2314
|
+
] })
|
|
2315
|
+
] }),
|
|
2316
|
+
/* @__PURE__ */ jsx("p", { children: "`gridOptions` compatibility layer: sorting, filtering, grouping, column moving, templating, and virtualized rendering." })
|
|
2317
|
+
] }),
|
|
2318
|
+
/* @__PURE__ */ jsxs("div", { className: "grid-table ui-grid-contents-wrapper", "data-part": "grid-table", children: [
|
|
2319
|
+
/* @__PURE__ */ jsx(
|
|
2320
|
+
"div",
|
|
2321
|
+
{
|
|
2322
|
+
className: "header-grid ui-grid-header ui-grid-header-canvas",
|
|
2323
|
+
"data-part": "header",
|
|
2324
|
+
role: "row",
|
|
2325
|
+
style: { gridTemplateColumns },
|
|
2326
|
+
children: visibleColumns.map((column) => {
|
|
2327
|
+
const pinned = state.isPinned(column);
|
|
2328
|
+
const pinOffset = pinned ? state.pinnedOffset(column) : null;
|
|
2329
|
+
return /* @__PURE__ */ jsxs(
|
|
2330
|
+
"div",
|
|
2331
|
+
{
|
|
2332
|
+
className: `header-cell ui-grid-header-cell${sortingFeature && state.sortDirection(column) !== "none" ? " is-active" : ""}${pinned ? " is-pinned" : ""}`,
|
|
2333
|
+
"data-part": "header-cell",
|
|
2334
|
+
role: "columnheader",
|
|
2335
|
+
"aria-sort": sortingFeature ? state.sortAriaSort(column) : void 0,
|
|
2336
|
+
style: {
|
|
2337
|
+
position: pinned ? "sticky" : void 0,
|
|
2338
|
+
left: pinOffset?.side === "left" ? pinOffset.offset : void 0,
|
|
2339
|
+
right: pinOffset?.side === "right" ? pinOffset.offset : void 0,
|
|
2340
|
+
zIndex: pinned ? 2 : void 0
|
|
2341
|
+
},
|
|
2342
|
+
children: [
|
|
2343
|
+
/* @__PURE__ */ jsx("span", { className: "header-label", children: state.headerLabel(column) }),
|
|
2344
|
+
/* @__PURE__ */ jsxs("div", { className: "header-actions", children: [
|
|
2345
|
+
sortingFeature && /* @__PURE__ */ jsxs(
|
|
2346
|
+
"button",
|
|
2347
|
+
{
|
|
2348
|
+
type: "button",
|
|
2349
|
+
className: `header-action${!state.isColumnSortable(column) ? " header-action-disabled" : ""}`,
|
|
2350
|
+
disabled: !state.isColumnSortable(column),
|
|
2351
|
+
"aria-label": state.sortButtonLabel(column),
|
|
2352
|
+
title: state.sortButtonLabel(column),
|
|
2353
|
+
onClick: () => state.toggleSort(column),
|
|
2354
|
+
children: [
|
|
2355
|
+
renderSortIcon(column),
|
|
2356
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only ui-grid-sr-only", children: state.sortButtonLabel(column) })
|
|
2357
|
+
]
|
|
2358
|
+
}
|
|
2359
|
+
),
|
|
2360
|
+
groupingFeature && state.isGroupingEnabled() && column.enableGrouping !== false && /* @__PURE__ */ jsxs(
|
|
2361
|
+
"button",
|
|
2362
|
+
{
|
|
2363
|
+
type: "button",
|
|
2364
|
+
className: `chip-action${state.isGrouped(column) ? " chip-action-active" : ""}`,
|
|
2365
|
+
"data-part": "group-toggle",
|
|
2366
|
+
"aria-label": state.groupingButtonLabel(column),
|
|
2367
|
+
title: state.groupingButtonLabel(column),
|
|
2368
|
+
onClick: (e) => state.toggleGrouping(column, e),
|
|
2369
|
+
children: [
|
|
2370
|
+
/* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: "M4 6h8v4H4V6Zm0 8h8v4H4v-4Zm10-8h6v4h-6V6Zm0 8h6v4h-6v-4Z" }) }),
|
|
2371
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only ui-grid-sr-only", children: state.groupingButtonLabel(column) })
|
|
2372
|
+
]
|
|
2373
|
+
}
|
|
2374
|
+
),
|
|
2375
|
+
state.pinningFeature && state.isPinningEnabled() && state.isColumnPinnable(column) && /* @__PURE__ */ jsxs(
|
|
2376
|
+
"button",
|
|
2377
|
+
{
|
|
2378
|
+
type: "button",
|
|
2379
|
+
className: `chip-action${pinned ? " chip-action-active" : ""}`,
|
|
2380
|
+
"data-part": "pin-toggle",
|
|
2381
|
+
"aria-label": pinned ? labels.unpin : labels.pinLeft,
|
|
2382
|
+
title: pinned ? labels.unpin : labels.pinLeft,
|
|
2383
|
+
onClick: () => state.togglePin(column),
|
|
2384
|
+
children: [
|
|
2385
|
+
/* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: "M16 12V4h1V2H7v2h1v8l-2 2v2h5v6l1 1 1-1v-6h5v-2l-2-2z" }) }),
|
|
2386
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only ui-grid-sr-only", children: pinned ? labels.unpin : labels.pinLeft })
|
|
2387
|
+
]
|
|
2388
|
+
}
|
|
2389
|
+
)
|
|
2390
|
+
] })
|
|
2391
|
+
]
|
|
2392
|
+
},
|
|
2393
|
+
column.name
|
|
2394
|
+
);
|
|
2395
|
+
})
|
|
2396
|
+
}
|
|
2397
|
+
),
|
|
2398
|
+
filteringFeature && state.isFilteringEnabled() && /* @__PURE__ */ jsx(
|
|
2399
|
+
"div",
|
|
2400
|
+
{
|
|
2401
|
+
className: "filter-grid ui-grid-header",
|
|
2402
|
+
"data-part": "filters",
|
|
2403
|
+
style: { gridTemplateColumns },
|
|
2404
|
+
children: visibleColumns.map((column) => {
|
|
2405
|
+
const pinned = state.isPinned(column);
|
|
2406
|
+
const pinOffset = pinned ? state.pinnedOffset(column) : null;
|
|
2407
|
+
return /* @__PURE__ */ jsxs(
|
|
2408
|
+
"label",
|
|
2409
|
+
{
|
|
2410
|
+
className: `filter-cell ui-grid-filter-container${pinned ? " is-pinned" : ""}`,
|
|
2411
|
+
"data-part": "filter-cell",
|
|
2412
|
+
style: {
|
|
2413
|
+
position: pinned ? "sticky" : void 0,
|
|
2414
|
+
left: pinOffset?.side === "left" ? pinOffset.offset : void 0,
|
|
2415
|
+
right: pinOffset?.side === "right" ? pinOffset.offset : void 0,
|
|
2416
|
+
zIndex: pinned ? 2 : void 0
|
|
2417
|
+
},
|
|
2418
|
+
children: [
|
|
2419
|
+
/* @__PURE__ */ jsxs("span", { className: "sr-only ui-grid-sr-only", children: [
|
|
2420
|
+
labels.filterColumn,
|
|
2421
|
+
" ",
|
|
2422
|
+
state.headerLabel(column)
|
|
2423
|
+
] }),
|
|
2424
|
+
/* @__PURE__ */ jsx(
|
|
2425
|
+
"input",
|
|
2426
|
+
{
|
|
2427
|
+
className: "ui-grid-filter-input",
|
|
2428
|
+
type: "text",
|
|
2429
|
+
defaultValue: state.filterValue(column.name),
|
|
2430
|
+
placeholder: state.filterPlaceholder(column),
|
|
2431
|
+
disabled: state.isFilterInputDisabled(column),
|
|
2432
|
+
onChange: (e) => state.updateFilter(column.name, e.target.value)
|
|
2433
|
+
}
|
|
2434
|
+
)
|
|
2435
|
+
]
|
|
2436
|
+
},
|
|
2437
|
+
column.name
|
|
2438
|
+
);
|
|
2439
|
+
})
|
|
2440
|
+
}
|
|
2441
|
+
),
|
|
2442
|
+
displayItems.length > 0 ? virtualizationEnabled ? /* @__PURE__ */ jsx(
|
|
1881
2443
|
"div",
|
|
1882
2444
|
{
|
|
1883
|
-
className:
|
|
1884
|
-
"data-part": "
|
|
1885
|
-
|
|
1886
|
-
|
|
2445
|
+
className: "grid-viewport ui-grid-viewport",
|
|
2446
|
+
"data-part": "viewport",
|
|
2447
|
+
ref: virtualScroll.viewportRef,
|
|
2448
|
+
style: { height: viewportHeightPx, overflow: "auto", position: "relative" },
|
|
2449
|
+
onScroll: onViewportScroll,
|
|
2450
|
+
children: /* @__PURE__ */ jsx("div", { style: { height: `${virtualScroll.totalHeight}px`, position: "relative" }, children: /* @__PURE__ */ jsx(
|
|
2451
|
+
"div",
|
|
2452
|
+
{
|
|
2453
|
+
className: "body-grid ui-grid-canvas",
|
|
2454
|
+
"data-part": "body",
|
|
2455
|
+
role: "rowgroup",
|
|
2456
|
+
style: {
|
|
2457
|
+
gridTemplateColumns,
|
|
2458
|
+
position: "absolute",
|
|
2459
|
+
top: 0,
|
|
2460
|
+
left: 0,
|
|
2461
|
+
right: 0,
|
|
2462
|
+
transform: `translateY(${virtualScroll.offsetY}px)`
|
|
2463
|
+
},
|
|
2464
|
+
children: itemsToRender.map(renderDisplayItem)
|
|
2465
|
+
}
|
|
2466
|
+
) })
|
|
2467
|
+
}
|
|
2468
|
+
) : /* @__PURE__ */ jsx(
|
|
2469
|
+
"div",
|
|
2470
|
+
{
|
|
2471
|
+
className: "body-grid ui-grid-canvas",
|
|
2472
|
+
"data-part": "body",
|
|
2473
|
+
role: "rowgroup",
|
|
2474
|
+
style: { gridTemplateColumns },
|
|
2475
|
+
children: displayItems.map(renderDisplayItem)
|
|
2476
|
+
}
|
|
2477
|
+
) : /* @__PURE__ */ jsxs("div", { className: "empty-state ui-grid-no-row-overlay", "data-part": "empty-state", children: [
|
|
2478
|
+
/* @__PURE__ */ jsx("strong", { children: options.emptyMessage ?? labels.emptyHeading }),
|
|
2479
|
+
/* @__PURE__ */ jsx("p", { children: labels.emptyDescription })
|
|
2480
|
+
] }),
|
|
2481
|
+
paginationFeature && state.showPaginationControls() && /* @__PURE__ */ jsxs(
|
|
2482
|
+
"footer",
|
|
2483
|
+
{
|
|
2484
|
+
className: "pagination-bar ui-grid-pagination",
|
|
2485
|
+
"data-part": "pagination",
|
|
2486
|
+
role: "navigation",
|
|
2487
|
+
"aria-label": labels.paginationPage,
|
|
1887
2488
|
children: [
|
|
1888
|
-
/* @__PURE__ */ jsx("
|
|
1889
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
1890
|
-
|
|
2489
|
+
/* @__PURE__ */ jsx("p", { children: state.paginationSummary() }),
|
|
2490
|
+
/* @__PURE__ */ jsxs("div", { className: "pagination-controls", children: [
|
|
2491
|
+
/* @__PURE__ */ jsxs(
|
|
1891
2492
|
"button",
|
|
1892
2493
|
{
|
|
1893
2494
|
type: "button",
|
|
1894
|
-
className:
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
onClick: () => state.toggleSort(column),
|
|
2495
|
+
className: "action action-secondary pagination-button",
|
|
2496
|
+
"aria-label": labels.paginationPrevious,
|
|
2497
|
+
disabled: paginationCurrentPage <= 1,
|
|
2498
|
+
onClick: () => state.previousPage(),
|
|
1899
2499
|
children: [
|
|
1900
|
-
|
|
1901
|
-
|
|
2500
|
+
/* @__PURE__ */ jsx(
|
|
2501
|
+
"svg",
|
|
2502
|
+
{
|
|
2503
|
+
className: "pagination-icon",
|
|
2504
|
+
viewBox: "0 0 24 24",
|
|
2505
|
+
"aria-hidden": "true",
|
|
2506
|
+
focusable: false,
|
|
2507
|
+
children: /* @__PURE__ */ jsx("path", { d: "M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" })
|
|
2508
|
+
}
|
|
2509
|
+
),
|
|
2510
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.paginationPrevious })
|
|
1902
2511
|
]
|
|
1903
2512
|
}
|
|
1904
2513
|
),
|
|
1905
|
-
|
|
2514
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
2515
|
+
labels.paginationPage,
|
|
2516
|
+
" ",
|
|
2517
|
+
paginationCurrentPage,
|
|
2518
|
+
" ",
|
|
2519
|
+
labels.paginationOf,
|
|
2520
|
+
" ",
|
|
2521
|
+
paginationTotalPages
|
|
2522
|
+
] }),
|
|
2523
|
+
/* @__PURE__ */ jsxs(
|
|
1906
2524
|
"button",
|
|
1907
2525
|
{
|
|
1908
2526
|
type: "button",
|
|
1909
|
-
className:
|
|
1910
|
-
"
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
onClick: (e) => state.toggleGrouping(column, e),
|
|
2527
|
+
className: "action action-secondary pagination-button",
|
|
2528
|
+
"aria-label": labels.paginationNext,
|
|
2529
|
+
disabled: paginationCurrentPage >= paginationTotalPages,
|
|
2530
|
+
onClick: () => state.nextPage(),
|
|
1914
2531
|
children: [
|
|
1915
|
-
/* @__PURE__ */ jsx(
|
|
1916
|
-
|
|
2532
|
+
/* @__PURE__ */ jsx(
|
|
2533
|
+
"svg",
|
|
2534
|
+
{
|
|
2535
|
+
className: "pagination-icon",
|
|
2536
|
+
viewBox: "0 0 24 24",
|
|
2537
|
+
"aria-hidden": "true",
|
|
2538
|
+
focusable: false,
|
|
2539
|
+
children: /* @__PURE__ */ jsx("path", { d: "M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z" })
|
|
2540
|
+
}
|
|
2541
|
+
),
|
|
2542
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.paginationNext })
|
|
1917
2543
|
]
|
|
1918
2544
|
}
|
|
1919
|
-
)
|
|
2545
|
+
),
|
|
2546
|
+
state.pageSizeOptions().length > 0 && /* @__PURE__ */ jsxs("label", { className: "pagination-size", children: [
|
|
2547
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.paginationRows }),
|
|
2548
|
+
/* @__PURE__ */ jsx(
|
|
2549
|
+
"select",
|
|
2550
|
+
{
|
|
2551
|
+
"aria-label": labels.paginationRows,
|
|
2552
|
+
value: paginationSelectedPageSize,
|
|
2553
|
+
onChange: (e) => state.onPageSizeChange(e.target.value),
|
|
2554
|
+
children: state.pageSizeOptions().map((size) => /* @__PURE__ */ jsx("option", { value: size, children: size }, size))
|
|
2555
|
+
}
|
|
2556
|
+
)
|
|
2557
|
+
] })
|
|
1920
2558
|
] })
|
|
1921
2559
|
]
|
|
1922
|
-
},
|
|
1923
|
-
column.name
|
|
1924
|
-
))
|
|
1925
|
-
}
|
|
1926
|
-
),
|
|
1927
|
-
filteringFeature && state.isFilteringEnabled() && /* @__PURE__ */ jsx("div", { className: "filter-grid ui-grid-header", "data-part": "filters", style: { gridTemplateColumns }, children: visibleColumns.map((column) => /* @__PURE__ */ jsxs("label", { className: "filter-cell ui-grid-filter-container", "data-part": "filter-cell", children: [
|
|
1928
|
-
/* @__PURE__ */ jsxs("span", { className: "sr-only ui-grid-sr-only", children: [
|
|
1929
|
-
labels.filterColumn,
|
|
1930
|
-
" ",
|
|
1931
|
-
state.headerLabel(column)
|
|
1932
|
-
] }),
|
|
1933
|
-
/* @__PURE__ */ jsx(
|
|
1934
|
-
"input",
|
|
1935
|
-
{
|
|
1936
|
-
className: "ui-grid-filter-input",
|
|
1937
|
-
type: "text",
|
|
1938
|
-
defaultValue: state.filterValue(column.name),
|
|
1939
|
-
placeholder: state.filterPlaceholder(column),
|
|
1940
|
-
disabled: state.isFilterInputDisabled(column),
|
|
1941
|
-
onChange: (e) => state.updateFilter(column.name, e.target.value)
|
|
1942
|
-
}
|
|
1943
|
-
)
|
|
1944
|
-
] }, column.name)) }),
|
|
1945
|
-
displayItems.length > 0 ? virtualizationEnabled ? /* @__PURE__ */ jsx(
|
|
1946
|
-
"div",
|
|
1947
|
-
{
|
|
1948
|
-
className: "grid-viewport ui-grid-viewport",
|
|
1949
|
-
"data-part": "viewport",
|
|
1950
|
-
ref: virtualScroll.viewportRef,
|
|
1951
|
-
style: { height: viewportHeightPx, overflow: "auto", position: "relative" },
|
|
1952
|
-
onScroll: onViewportScroll,
|
|
1953
|
-
children: /* @__PURE__ */ jsx("div", { style: { height: `${virtualScroll.totalHeight}px`, position: "relative" }, children: /* @__PURE__ */ jsx(
|
|
1954
|
-
"div",
|
|
1955
|
-
{
|
|
1956
|
-
className: "body-grid ui-grid-canvas",
|
|
1957
|
-
"data-part": "body",
|
|
1958
|
-
role: "rowgroup",
|
|
1959
|
-
style: {
|
|
1960
|
-
gridTemplateColumns,
|
|
1961
|
-
position: "absolute",
|
|
1962
|
-
top: 0,
|
|
1963
|
-
left: 0,
|
|
1964
|
-
right: 0,
|
|
1965
|
-
transform: `translateY(${virtualScroll.offsetY}px)`
|
|
1966
|
-
},
|
|
1967
|
-
children: itemsToRender.map(renderDisplayItem)
|
|
1968
|
-
}
|
|
1969
|
-
) })
|
|
1970
|
-
}
|
|
1971
|
-
) : /* @__PURE__ */ jsx(
|
|
1972
|
-
"div",
|
|
1973
|
-
{
|
|
1974
|
-
className: "body-grid ui-grid-canvas",
|
|
1975
|
-
"data-part": "body",
|
|
1976
|
-
role: "rowgroup",
|
|
1977
|
-
style: { gridTemplateColumns },
|
|
1978
|
-
children: displayItems.map(renderDisplayItem)
|
|
1979
|
-
}
|
|
1980
|
-
) : /* @__PURE__ */ jsxs("div", { className: "empty-state ui-grid-no-row-overlay", "data-part": "empty-state", children: [
|
|
1981
|
-
/* @__PURE__ */ jsx("strong", { children: options.emptyMessage ?? labels.emptyHeading }),
|
|
1982
|
-
/* @__PURE__ */ jsx("p", { children: labels.emptyDescription })
|
|
1983
|
-
] }),
|
|
1984
|
-
paginationFeature && state.showPaginationControls() && /* @__PURE__ */ jsxs("footer", { className: "pagination-bar ui-grid-pagination", "data-part": "pagination", role: "navigation", "aria-label": labels.paginationPage, children: [
|
|
1985
|
-
/* @__PURE__ */ jsx("p", { children: state.paginationSummary() }),
|
|
1986
|
-
/* @__PURE__ */ jsxs("div", { className: "pagination-controls", children: [
|
|
1987
|
-
/* @__PURE__ */ jsxs(
|
|
1988
|
-
"button",
|
|
1989
|
-
{
|
|
1990
|
-
type: "button",
|
|
1991
|
-
className: "action action-secondary pagination-button",
|
|
1992
|
-
"aria-label": labels.paginationPrevious,
|
|
1993
|
-
disabled: paginationCurrentPage <= 1,
|
|
1994
|
-
onClick: () => state.previousPage(),
|
|
1995
|
-
children: [
|
|
1996
|
-
/* @__PURE__ */ jsx("svg", { className: "pagination-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: "M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" }) }),
|
|
1997
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.paginationPrevious })
|
|
1998
|
-
]
|
|
1999
2560
|
}
|
|
2000
|
-
)
|
|
2001
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
2002
|
-
labels.paginationPage,
|
|
2003
|
-
" ",
|
|
2004
|
-
paginationCurrentPage,
|
|
2005
|
-
" ",
|
|
2006
|
-
labels.paginationOf,
|
|
2007
|
-
" ",
|
|
2008
|
-
paginationTotalPages
|
|
2009
|
-
] }),
|
|
2010
|
-
/* @__PURE__ */ jsxs(
|
|
2011
|
-
"button",
|
|
2012
|
-
{
|
|
2013
|
-
type: "button",
|
|
2014
|
-
className: "action action-secondary pagination-button",
|
|
2015
|
-
"aria-label": labels.paginationNext,
|
|
2016
|
-
disabled: paginationCurrentPage >= paginationTotalPages,
|
|
2017
|
-
onClick: () => state.nextPage(),
|
|
2018
|
-
children: [
|
|
2019
|
-
/* @__PURE__ */ jsx("svg", { className: "pagination-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ jsx("path", { d: "M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z" }) }),
|
|
2020
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.paginationNext })
|
|
2021
|
-
]
|
|
2022
|
-
}
|
|
2023
|
-
),
|
|
2024
|
-
state.pageSizeOptions().length > 0 && /* @__PURE__ */ jsxs("label", { className: "pagination-size", children: [
|
|
2025
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children: labels.paginationRows }),
|
|
2026
|
-
/* @__PURE__ */ jsx(
|
|
2027
|
-
"select",
|
|
2028
|
-
{
|
|
2029
|
-
"aria-label": labels.paginationRows,
|
|
2030
|
-
value: paginationSelectedPageSize,
|
|
2031
|
-
onChange: (e) => state.onPageSizeChange(e.target.value),
|
|
2032
|
-
children: state.pageSizeOptions().map((size) => /* @__PURE__ */ jsx("option", { value: size, children: size }, size))
|
|
2033
|
-
}
|
|
2034
|
-
)
|
|
2035
|
-
] })
|
|
2561
|
+
)
|
|
2036
2562
|
] })
|
|
2037
|
-
]
|
|
2038
|
-
|
|
2039
|
-
|
|
2563
|
+
]
|
|
2564
|
+
}
|
|
2565
|
+
)
|
|
2040
2566
|
] }) });
|
|
2041
2567
|
}
|
|
2042
2568
|
|
|
2569
|
+
// src/rustWasmGridEngine.ts
|
|
2570
|
+
import { registerRustWasmGridEngine } from "@ornery/ui-grid";
|
|
2571
|
+
var uiGridWasmModulePath = "../../../dist/ui-grid-wasm/ui_grid_wasm.js";
|
|
2572
|
+
function registerReactUiGridWasmEngineFromModule(module) {
|
|
2573
|
+
registerRustWasmGridEngine({
|
|
2574
|
+
buildPipeline(context) {
|
|
2575
|
+
return module.build_pipeline_js(context);
|
|
2576
|
+
}
|
|
2577
|
+
});
|
|
2578
|
+
}
|
|
2579
|
+
async function enableReactUiGridWasmEngine() {
|
|
2580
|
+
const module = await import(
|
|
2581
|
+
/* @vite-ignore */
|
|
2582
|
+
uiGridWasmModulePath
|
|
2583
|
+
);
|
|
2584
|
+
registerReactUiGridWasmEngineFromModule(module);
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2043
2587
|
// src/index.ts
|
|
2044
2588
|
import { DEFAULT_GRID_LABELS } from "@ornery/ui-grid";
|
|
2045
2589
|
export {
|
|
2046
2590
|
DEFAULT_GRID_LABELS,
|
|
2047
2591
|
UiGrid,
|
|
2592
|
+
buildGridTemplateColumns,
|
|
2593
|
+
computeViewportHeightPx,
|
|
2594
|
+
computeViewportRows,
|
|
2595
|
+
enableReactUiGridWasmEngine,
|
|
2596
|
+
formatPaginationSummary,
|
|
2597
|
+
orderVisibleColumns,
|
|
2598
|
+
registerReactUiGridWasmEngineFromModule,
|
|
2599
|
+
resolveBenchmarkIterations,
|
|
2048
2600
|
useGridState,
|
|
2049
2601
|
useVirtualScroll
|
|
2050
2602
|
};
|