@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.js CHANGED
@@ -20,8 +20,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- DEFAULT_GRID_LABELS: () => import_ui_grid7.DEFAULT_GRID_LABELS,
23
+ DEFAULT_GRID_LABELS: () => import_ui_grid9.DEFAULT_GRID_LABELS,
24
24
  UiGrid: () => UiGrid,
25
+ buildGridTemplateColumns: () => buildGridTemplateColumns,
26
+ computeViewportHeightPx: () => computeViewportHeightPx,
27
+ computeViewportRows: () => computeViewportRows,
28
+ enableReactUiGridWasmEngine: () => enableReactUiGridWasmEngine,
29
+ formatPaginationSummary: () => formatPaginationSummary,
30
+ orderVisibleColumns: () => orderVisibleColumns,
31
+ registerReactUiGridWasmEngineFromModule: () => registerReactUiGridWasmEngineFromModule,
32
+ resolveBenchmarkIterations: () => resolveBenchmarkIterations,
25
33
  useGridState: () => useGridState,
26
34
  useVirtualScroll: () => useVirtualScroll
27
35
  });
@@ -29,7 +37,33 @@ module.exports = __toCommonJS(index_exports);
29
37
 
30
38
  // src/useGridState.ts
31
39
  var import_react = require("react");
32
- var import_ui_grid3 = require("@ornery/ui-grid");
40
+
41
+ // src/gridStateMath.ts
42
+ var import_ui_grid = require("@ornery/ui-grid");
43
+ function orderVisibleColumns(columns, order) {
44
+ return [...columns].filter((column) => column.visible !== false).sort((left, right) => order.indexOf(left.name) - order.indexOf(right.name));
45
+ }
46
+ function buildGridTemplateColumns(columns) {
47
+ return columns.map((column) => (0, import_ui_grid.gridColumnWidth)(column)).join(" ");
48
+ }
49
+ function resolveBenchmarkIterations(iterations, configuredIterations) {
50
+ return Math.max(1, iterations ?? configuredIterations ?? 25);
51
+ }
52
+ function formatPaginationSummary(totalItems, firstRowIndex, lastRowIndex) {
53
+ if (totalItems === 0) {
54
+ return "0-0 of 0";
55
+ }
56
+ return `${firstRowIndex + 1}-${lastRowIndex + 1} of ${totalItems}`;
57
+ }
58
+ function computeViewportHeightPx(viewportHeight, autoViewportHeight) {
59
+ return `${viewportHeight ?? autoViewportHeight ?? 560}px`;
60
+ }
61
+ function computeViewportRows(viewportHeight, rowHeight) {
62
+ return Math.max(1, Math.ceil((viewportHeight ?? 560) / (rowHeight ?? 44)));
63
+ }
64
+
65
+ // src/useGridState.ts
66
+ var import_ui_grid4 = require("@ornery/ui-grid");
33
67
 
34
68
  // ../ui-grid/src/lib/grid/grid.core.pagination.ts
35
69
  function seekGridPage(page, totalPages) {
@@ -209,12 +243,15 @@ function normalizeGridSavedState(state) {
209
243
  );
210
244
  }
211
245
  if (state.filters && typeof state.filters === "object") {
212
- normalized.filters = Object.entries(state.filters).reduce((accumulator, [key, value]) => {
213
- if (typeof key === "string" && isSafeStateKey(key) && typeof value === "string") {
214
- accumulator[key] = value;
215
- }
216
- return accumulator;
217
- }, {});
246
+ normalized.filters = Object.entries(state.filters).reduce(
247
+ (accumulator, [key, value]) => {
248
+ if (typeof key === "string" && isSafeStateKey(key) && typeof value === "string") {
249
+ accumulator[key] = value;
250
+ }
251
+ return accumulator;
252
+ },
253
+ {}
254
+ );
218
255
  }
219
256
  if (state.sort && typeof state.sort === "object") {
220
257
  normalized.sort = {
@@ -241,6 +278,17 @@ function normalizeGridSavedState(state) {
241
278
  if (state.treeView && typeof state.treeView === "object") {
242
279
  normalized.treeView = normalizeBooleanMap(state.treeView);
243
280
  }
281
+ if (state.pinning && typeof state.pinning === "object") {
282
+ normalized.pinning = Object.entries(state.pinning).reduce(
283
+ (acc, [key, value]) => {
284
+ if (typeof key === "string" && isSafeStateKey(key) && (value === "left" || value === "right")) {
285
+ acc[key] = value;
286
+ }
287
+ return acc;
288
+ },
289
+ {}
290
+ );
291
+ }
244
292
  return normalized;
245
293
  }
246
294
  function normalizeBooleanMap(value) {
@@ -255,6 +303,69 @@ function isSafeStateKey(value) {
255
303
  return value !== "__proto__" && value !== "constructor" && value !== "prototype";
256
304
  }
257
305
 
306
+ // ../ui-grid/src/lib/grid/grid.core.pinning.ts
307
+ function isPinningEnabled(options) {
308
+ return options.enablePinning === true;
309
+ }
310
+ function isColumnPinnable(options, column) {
311
+ return isPinningEnabled(options) && column.enablePinning !== false;
312
+ }
313
+ function pinColumnState(current, columnName, direction) {
314
+ const next = { ...current };
315
+ if (direction === "none") {
316
+ delete next[columnName];
317
+ } else {
318
+ next[columnName] = direction;
319
+ }
320
+ return next;
321
+ }
322
+ function buildInitialPinnedState(columns) {
323
+ const state = {};
324
+ for (const col of columns) {
325
+ if (col.pinnedLeft) state[col.name] = "left";
326
+ else if (col.pinnedRight) state[col.name] = "right";
327
+ }
328
+ return state;
329
+ }
330
+ function computePinnedOffset(visibleColumns, pinnedColumns, column) {
331
+ const direction = pinnedColumns[column.name];
332
+ if (!direction) return null;
333
+ function resolveColumnWidthForOffset(column2) {
334
+ const w = column2.width;
335
+ if (!w) return "11rem";
336
+ if (w.includes("fr") || w.includes("minmax")) return "11rem";
337
+ return w;
338
+ }
339
+ if (direction === "left") {
340
+ const offsetParts = [];
341
+ for (const col of visibleColumns) {
342
+ if (col.name === column.name) break;
343
+ if (pinnedColumns[col.name] === "left") {
344
+ offsetParts.push(resolveColumnWidthForOffset(col));
345
+ }
346
+ }
347
+ return {
348
+ side: "left",
349
+ offset: offsetParts.length > 0 ? `calc(${offsetParts.join(" + ")})` : "0px"
350
+ };
351
+ }
352
+ if (direction === "right") {
353
+ const offsetParts = [];
354
+ const reversed = [...visibleColumns].reverse();
355
+ for (const col of reversed) {
356
+ if (col.name === column.name) break;
357
+ if (pinnedColumns[col.name] === "right") {
358
+ offsetParts.push(resolveColumnWidthForOffset(col));
359
+ }
360
+ }
361
+ return {
362
+ side: "right",
363
+ offset: offsetParts.length > 0 ? `calc(${offsetParts.join(" + ")})` : "0px"
364
+ };
365
+ }
366
+ return null;
367
+ }
368
+
258
369
  // ../ui-grid/src/lib/grid/ui-grid.events.ts
259
370
  function raiseGridRenderingComplete(gridApi) {
260
371
  gridApi.core.raise.renderingComplete(gridApi);
@@ -321,6 +432,9 @@ function raiseGridAfterCellEdit(gridApi, rowEntity, column, newValue, oldValue)
321
432
  function raiseGridCancelCellEdit(gridApi, rowEntity, column) {
322
433
  gridApi.edit.raise.cancelCellEdit(rowEntity, column);
323
434
  }
435
+ function raiseGridColumnPinned(gridApi, columnName, direction) {
436
+ gridApi.pinning.raise.columnPinned(columnName, direction);
437
+ }
324
438
 
325
439
  // ../ui-grid/src/lib/grid/ui-grid.state.ts
326
440
  function moveArrayItem(items, fromIndex, toIndex) {
@@ -362,6 +476,9 @@ function createGridRestoreMutationPlan(state) {
362
476
  if (normalizedState.treeView) {
363
477
  plan.treeView = normalizedState.treeView;
364
478
  }
479
+ if (normalizedState.pinning) {
480
+ plan.pinning = normalizedState.pinning;
481
+ }
365
482
  return plan;
366
483
  }
367
484
 
@@ -402,6 +519,12 @@ function moveGridColumnCommand(gridApi, canMoveColumns, updateColumnOrder, fromI
402
519
  return next;
403
520
  });
404
521
  }
522
+ function pinGridColumnCommand(gridApi, isPinningEnabled2, setPinnedColumns, getCurrentPinnedColumns, columnName, direction) {
523
+ if (!isPinningEnabled2) return;
524
+ const next = pinColumnState(getCurrentPinnedColumns(), columnName, direction);
525
+ setPinnedColumns(next);
526
+ raiseGridColumnPinned(gridApi, columnName, direction);
527
+ }
405
528
  function seekGridPaginationCommand(gridApi, setCurrentPage, getTotalPages, getEffectivePageSize, page) {
406
529
  const nextPage = seekGridPage(page, getTotalPages());
407
530
  setCurrentPage(nextPage);
@@ -435,7 +558,11 @@ function restoreGridStateCommand(gridApi, state, access) {
435
558
  if (restorePlan.pagination) {
436
559
  access.setCurrentPage(restorePlan.pagination.currentPage);
437
560
  access.setPageSize(restorePlan.pagination.pageSize);
438
- raiseGridPaginationChanged(gridApi, restorePlan.pagination.currentPage, access.getEffectivePageSize());
561
+ raiseGridPaginationChanged(
562
+ gridApi,
563
+ restorePlan.pagination.currentPage,
564
+ access.getEffectivePageSize()
565
+ );
439
566
  }
440
567
  if (restorePlan.expandable) {
441
568
  access.setExpandedRows(restorePlan.expandable);
@@ -443,6 +570,12 @@ function restoreGridStateCommand(gridApi, state, access) {
443
570
  if (restorePlan.treeView) {
444
571
  access.setExpandedTreeRows(restorePlan.treeView);
445
572
  }
573
+ if (restorePlan.pinning && typeof access.setPinnedColumns === "function") {
574
+ access.setPinnedColumns(restorePlan.pinning);
575
+ for (const [col, dir] of Object.entries(restorePlan.pinning)) {
576
+ raiseGridColumnPinned(gridApi, col, dir);
577
+ }
578
+ }
446
579
  }
447
580
  function toggleGridRowExpansionCommand(gridApi, canExpandRows, currentExpandedRows, rowId, setExpandedRows, findRowById) {
448
581
  if (!canExpandRows) {
@@ -464,7 +597,10 @@ function collapseAllGridRowsCommand(setExpandedRows) {
464
597
  setExpandedRows({});
465
598
  }
466
599
  function toggleGridTreeRowCommand(gridApi, currentExpandedTreeRows, rowId, setExpandedTreeRows, findRowById) {
467
- const { expanded, nextExpandedTreeRows } = toggleGridTreeRowExpanded(currentExpandedTreeRows, rowId);
600
+ const { expanded, nextExpandedTreeRows } = toggleGridTreeRowExpanded(
601
+ currentExpandedTreeRows,
602
+ rowId
603
+ );
468
604
  setExpandedTreeRows(nextExpandedTreeRows);
469
605
  const gridRow = findRowById(rowId);
470
606
  if (gridRow) {
@@ -599,13 +735,45 @@ function downloadGridCsvFile(csv, filename) {
599
735
  }
600
736
 
601
737
  // src/useGridState.ts
738
+ function escapeCssSelectorValue(value) {
739
+ const nativeEscape = globalThis.CSS?.escape;
740
+ if (typeof nativeEscape === "function") {
741
+ return nativeEscape(value);
742
+ }
743
+ let output = "";
744
+ for (let index = 0; index < value.length; index += 1) {
745
+ const codePoint = value.charCodeAt(index);
746
+ const character = value.charAt(index);
747
+ if (codePoint === 0) {
748
+ output += "\uFFFD";
749
+ continue;
750
+ }
751
+ const isControlCharacter = codePoint >= 1 && codePoint <= 31 || codePoint === 127;
752
+ const startsWithDigit = index === 0 && codePoint >= 48 && codePoint <= 57;
753
+ const secondCharDigitAfterHyphen = index === 1 && codePoint >= 48 && codePoint <= 57 && value.charCodeAt(0) === 45;
754
+ if (isControlCharacter || startsWithDigit || secondCharDigitAfterHyphen) {
755
+ output += `\\${codePoint.toString(16)} `;
756
+ continue;
757
+ }
758
+ if (index === 0 && value.length === 1 && codePoint === 45) {
759
+ output += `\\${character}`;
760
+ continue;
761
+ }
762
+ const isSafeCharacter = codePoint >= 128 || codePoint === 45 || codePoint === 95 || codePoint >= 48 && codePoint <= 57 || codePoint >= 65 && codePoint <= 90 || codePoint >= 97 && codePoint <= 122;
763
+ output += isSafeCharacter ? character : `\\${character}`;
764
+ }
765
+ return output;
766
+ }
602
767
  function useGridState(options, onRegisterApi) {
603
768
  const [activeFilters, setActiveFilters] = (0, import_react.useState)({});
604
769
  const [groupByColumns, setGroupByColumns] = (0, import_react.useState)([]);
605
770
  const [collapsedGroups, setCollapsedGroups] = (0, import_react.useState)({});
606
771
  const [columnOrder, setColumnOrder] = (0, import_react.useState)([]);
607
772
  const [hiddenRowReasons, setHiddenRowReasons] = (0, import_react.useState)({});
608
- const [sortState, setSortState] = (0, import_react.useState)({ columnName: null, direction: import_ui_grid3.SORT_DIRECTIONS.none });
773
+ const [sortState, setSortState] = (0, import_react.useState)({
774
+ columnName: null,
775
+ direction: import_ui_grid4.SORT_DIRECTIONS.none
776
+ });
609
777
  const [focusedCell, setFocusedCell] = (0, import_react.useState)(null);
610
778
  const [editingCell, setEditingCell] = (0, import_react.useState)(null);
611
779
  const [editingValue, setEditingValue] = (0, import_react.useState)("");
@@ -621,6 +789,7 @@ function useGridState(options, onRegisterApi) {
621
789
  previousVisibleRows: 0
622
790
  });
623
791
  const [autoViewportHeight, setAutoViewportHeight] = (0, import_react.useState)(null);
792
+ const [pinnedColumns, setPinnedColumns] = (0, import_react.useState)({});
624
793
  const gridContainerRef = (0, import_react.useRef)(null);
625
794
  const initializedGridIdRef = (0, import_react.useRef)(null);
626
795
  const lastCanvasHeightRef = (0, import_react.useRef)(0);
@@ -652,6 +821,8 @@ function useGridState(options, onRegisterApi) {
652
821
  expandedRowsRef.current = expandedRows;
653
822
  const expandedTreeRowsRef = (0, import_react.useRef)(expandedTreeRows);
654
823
  expandedTreeRowsRef.current = expandedTreeRows;
824
+ const pinnedColumnsRef = (0, import_react.useRef)(pinnedColumns);
825
+ pinnedColumnsRef.current = pinnedColumns;
655
826
  const currentPageRef = (0, import_react.useRef)(currentPage);
656
827
  currentPageRef.current = currentPage;
657
828
  const pageSizeRef = (0, import_react.useRef)(pageSize);
@@ -662,13 +833,12 @@ function useGridState(options, onRegisterApi) {
662
833
  optionsRef.current = options;
663
834
  const rowSize = options.rowHeight ?? 44;
664
835
  const visibleColumns = (0, import_react.useMemo)(() => {
665
- const order = columnOrder;
666
- return [...options.columnDefs].filter((column) => column.visible !== false).sort((left, right) => order.indexOf(left.name) - order.indexOf(right.name));
836
+ return orderVisibleColumns(options.columnDefs, columnOrder);
667
837
  }, [options.columnDefs, columnOrder]);
668
838
  const visibleColumnsRef = (0, import_react.useRef)(visibleColumns);
669
839
  visibleColumnsRef.current = visibleColumns;
670
840
  const pipeline = (0, import_react.useMemo)(() => {
671
- return (0, import_ui_grid3.buildGridPipeline)({
841
+ return import_ui_grid4.defaultGridEngine.buildPipeline({
672
842
  options,
673
843
  columns: visibleColumns,
674
844
  activeFilters,
@@ -682,70 +852,116 @@ function useGridState(options, onRegisterApi) {
682
852
  pageSize,
683
853
  rowSize
684
854
  });
685
- }, [options, visibleColumns, activeFilters, sortState, groupByColumns, collapsedGroups, hiddenRowReasons, expandedRows, expandedTreeRows, currentPage, pageSize, rowSize]);
855
+ }, [
856
+ options,
857
+ visibleColumns,
858
+ activeFilters,
859
+ sortState,
860
+ groupByColumns,
861
+ collapsedGroups,
862
+ hiddenRowReasons,
863
+ expandedRows,
864
+ expandedTreeRows,
865
+ currentPage,
866
+ pageSize,
867
+ rowSize
868
+ ]);
686
869
  const pipelineRef = (0, import_react.useRef)(pipeline);
687
870
  pipelineRef.current = pipeline;
688
- const labels = (0, import_react.useMemo)(() => (0, import_ui_grid3.resolveGridLabels)(options.labels), [options.labels]);
871
+ const labels = (0, import_react.useMemo)(() => (0, import_ui_grid4.resolveGridLabels)(options.labels), [options.labels]);
689
872
  const gridTemplateColumns = (0, import_react.useMemo)(
690
- () => visibleColumns.map((column) => (0, import_ui_grid3.gridColumnWidth)(column)).join(" "),
873
+ () => buildGridTemplateColumns(visibleColumns),
691
874
  [visibleColumns]
692
875
  );
876
+ const isPinningEnabledFn = (0, import_react.useCallback)(() => {
877
+ return isPinningEnabled(optionsRef.current);
878
+ }, []);
879
+ const isColumnPinnableFn = (0, import_react.useCallback)((column) => {
880
+ return isColumnPinnable(optionsRef.current, column);
881
+ }, []);
882
+ const isPinnedFn = (0, import_react.useCallback)((column) => {
883
+ return pinnedColumnsRef.current[column.name] !== void 0;
884
+ }, []);
885
+ const pinnedOffsetFn = (0, import_react.useCallback)((column) => {
886
+ return computePinnedOffset(visibleColumnsRef.current, pinnedColumnsRef.current, column);
887
+ }, []);
693
888
  const resolveRowId = (0, import_react.useCallback)((row) => {
694
- return (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
889
+ return (0, import_ui_grid4.resolveGridRowId)(optionsRef.current, row);
695
890
  }, []);
696
891
  const buildRowsFromData = (0, import_react.useCallback)((data) => {
697
- return (0, import_ui_grid3.buildGridRows)(
892
+ return (0, import_ui_grid4.buildGridRows)(
698
893
  { ...optionsRef.current, data },
699
894
  optionsRef.current.rowHeight ?? 44,
700
895
  hiddenRowReasonsRef.current,
701
896
  expandedRowsRef.current
702
897
  );
703
898
  }, []);
704
- const findRowById = (0, import_react.useCallback)((rowId) => {
705
- return (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), rowId);
706
- }, [buildRowsFromData]);
899
+ const findRowById = (0, import_react.useCallback)(
900
+ (rowId) => {
901
+ return (0, import_ui_grid4.findGridRowById)(buildRowsFromData(optionsRef.current.data), rowId);
902
+ },
903
+ [buildRowsFromData]
904
+ );
707
905
  const canExpandRowsFn = (0, import_react.useCallback)(() => {
708
- return import_ui_grid3.FEATURE_EXPANDABLE && (0, import_ui_grid3.canGridExpandRows)(optionsRef.current);
906
+ return import_ui_grid4.FEATURE_EXPANDABLE && (0, import_ui_grid4.canGridExpandRows)(optionsRef.current);
709
907
  }, []);
710
908
  const effectivePageSizeFn = (0, import_react.useCallback)((totalItems) => {
711
- return (0, import_ui_grid3.getEffectivePageSize)(optionsRef.current, pageSizeRef.current, totalItems);
909
+ return (0, import_ui_grid4.getEffectivePageSize)(optionsRef.current, pageSizeRef.current, totalItems);
712
910
  }, []);
713
911
  const getCurrentPageValueFn = (0, import_react.useCallback)((totalItems) => {
714
912
  const ti = totalItems ?? pipelineRef.current.totalItems;
715
- return (0, import_ui_grid3.getCurrentPageValue)(optionsRef.current, currentPageRef.current, ti, pageSizeRef.current);
913
+ return (0, import_ui_grid4.getCurrentPageValue)(
914
+ optionsRef.current,
915
+ currentPageRef.current,
916
+ ti,
917
+ pageSizeRef.current
918
+ );
716
919
  }, []);
717
920
  const getTotalPagesValueFn = (0, import_react.useCallback)((totalItems) => {
718
921
  const ti = totalItems ?? pipelineRef.current.totalItems;
719
- return (0, import_ui_grid3.getTotalPagesValue)(optionsRef.current, ti, pageSizeRef.current);
922
+ return (0, import_ui_grid4.getTotalPagesValue)(optionsRef.current, ti, pageSizeRef.current);
720
923
  }, []);
721
924
  const getFirstRowIndexValueFn = (0, import_react.useCallback)((totalItems) => {
722
925
  const ti = totalItems ?? pipelineRef.current.totalItems;
723
- return (0, import_ui_grid3.getFirstRowIndexValue)(optionsRef.current, currentPageRef.current, ti, pageSizeRef.current);
926
+ return (0, import_ui_grid4.getFirstRowIndexValue)(
927
+ optionsRef.current,
928
+ currentPageRef.current,
929
+ ti,
930
+ pageSizeRef.current
931
+ );
724
932
  }, []);
725
933
  const getLastRowIndexValueFn = (0, import_react.useCallback)((totalItems) => {
726
934
  const ti = totalItems ?? pipelineRef.current.totalItems;
727
- return (0, import_ui_grid3.getLastRowIndexValue)(optionsRef.current, currentPageRef.current, ti, pageSizeRef.current);
728
- }, []);
729
- const isCellEditable = (0, import_react.useCallback)((row, column, triggerEvent) => {
730
- if (!import_ui_grid3.FEATURE_CELL_EDIT) return false;
731
- const editable = column.enableCellEdit ?? optionsRef.current.enableCellEdit ?? false;
732
- if (!editable) return false;
733
- const condition = column.cellEditableCondition ?? optionsRef.current.cellEditableCondition ?? true;
734
- if (typeof condition === "boolean") return condition;
735
- const context = {
736
- row: row.entity,
737
- column,
738
- rowIndex: row.index,
739
- triggerEvent
740
- };
741
- return condition(context);
935
+ return (0, import_ui_grid4.getLastRowIndexValue)(
936
+ optionsRef.current,
937
+ currentPageRef.current,
938
+ ti,
939
+ pageSizeRef.current
940
+ );
742
941
  }, []);
942
+ const isCellEditable = (0, import_react.useCallback)(
943
+ (row, column, triggerEvent) => {
944
+ if (!import_ui_grid4.FEATURE_CELL_EDIT) return false;
945
+ const editable = column.enableCellEdit ?? optionsRef.current.enableCellEdit ?? false;
946
+ if (!editable) return false;
947
+ const condition = column.cellEditableCondition ?? optionsRef.current.cellEditableCondition ?? true;
948
+ if (typeof condition === "boolean") return condition;
949
+ const context = {
950
+ row: row.entity,
951
+ column,
952
+ rowIndex: row.index,
953
+ triggerEvent
954
+ };
955
+ return condition(context);
956
+ },
957
+ []
958
+ );
743
959
  const shouldEditOnFocusFn = (0, import_react.useCallback)((column) => {
744
960
  return column.enableCellEditOnFocus ?? optionsRef.current.enableCellEditOnFocus ?? false;
745
961
  }, []);
746
962
  const focusRenderedCell = (0, import_react.useCallback)((position) => {
747
963
  const focusToken = ++renderedCellFocusTokenRef.current;
748
- const selector = `.body-cell[data-row-id="${position.rowId}"][data-col-name="${position.columnName}"]`;
964
+ const selector = `.body-cell[data-row-id="${escapeCssSelectorValue(position.rowId)}"][data-col-name="${escapeCssSelectorValue(position.columnName)}"]`;
749
965
  const doFocus = (retry = true) => {
750
966
  if (focusToken !== renderedCellFocusTokenRef.current) return;
751
967
  const container = gridContainerRef.current;
@@ -766,11 +982,12 @@ function useGridState(options, onRegisterApi) {
766
982
  if (focusToken !== editorFocusTokenRef.current) return;
767
983
  const ec = editingCellRef.current;
768
984
  if (!ec) return;
769
- const selector = `.cell-editor[data-row-id="${ec.rowId}"][data-col-name="${ec.columnName}"]`;
985
+ const selector = `.cell-editor[data-row-id="${escapeCssSelectorValue(ec.rowId)}"][data-col-name="${escapeCssSelectorValue(ec.columnName)}"]`;
770
986
  const doFocus = (retry = true) => {
771
987
  if (focusToken !== editorFocusTokenRef.current) return;
772
988
  const currentEc = editingCellRef.current;
773
- if (!currentEc || currentEc.rowId !== ec.rowId || currentEc.columnName !== ec.columnName) return;
989
+ if (!currentEc || currentEc.rowId !== ec.rowId || currentEc.columnName !== ec.columnName)
990
+ return;
774
991
  const container = gridContainerRef.current;
775
992
  if (!container) return;
776
993
  const input = container.querySelector(selector);
@@ -789,12 +1006,12 @@ function useGridState(options, onRegisterApi) {
789
1006
  refresh: () => setActiveFilters((current) => ({ ...current })),
790
1007
  getVisibleRows: () => pipelineRef.current.visibleRows,
791
1008
  setRowInvisible: (row, reason = "user") => {
792
- const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
793
- setHiddenRowReasons((current) => (0, import_ui_grid3.addGridRowInvisibleReason)(current, rowId, reason));
1009
+ const rowId = (0, import_ui_grid4.resolveGridRowId)(optionsRef.current, row);
1010
+ setHiddenRowReasons((current) => (0, import_ui_grid4.addGridRowInvisibleReason)(current, rowId, reason));
794
1011
  },
795
1012
  clearRowInvisible: (row, reason = "user") => {
796
- const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
797
- setHiddenRowReasons((current) => (0, import_ui_grid3.clearGridRowInvisibleReason)(current, rowId, reason));
1013
+ const rowId = (0, import_ui_grid4.resolveGridRowId)(optionsRef.current, row);
1014
+ setHiddenRowReasons((current) => (0, import_ui_grid4.clearGridRowInvisibleReason)(current, rowId, reason));
798
1015
  },
799
1016
  setFilter: (columnName, value) => {
800
1017
  setActiveFilters((current) => {
@@ -816,14 +1033,14 @@ function useGridState(options, onRegisterApi) {
816
1033
  moveColumn: (fromIndex, toIndex) => {
817
1034
  moveGridColumnCommand(
818
1035
  gridApiRef.current,
819
- import_ui_grid3.FEATURE_COLUMN_MOVING && optionsRef.current.enableColumnMoving === true,
1036
+ import_ui_grid4.FEATURE_COLUMN_MOVING && optionsRef.current.enableColumnMoving === true,
820
1037
  (updater) => setColumnOrder((current) => updater(current)),
821
1038
  fromIndex,
822
1039
  toIndex
823
1040
  );
824
1041
  },
825
1042
  toggleGrouping: (columnName) => {
826
- if (!(import_ui_grid3.FEATURE_GROUPING && (0, import_ui_grid3.isGridGroupingEnabled)(optionsRef.current))) return;
1043
+ if (!(import_ui_grid4.FEATURE_GROUPING && (0, import_ui_grid4.isGridGroupingEnabled)(optionsRef.current))) return;
827
1044
  const current = groupByColumnsRef.current;
828
1045
  const next = current.includes(columnName) ? current.filter((n) => n !== columnName) : [...current, columnName];
829
1046
  groupByColumnsRef.current = next;
@@ -831,7 +1048,11 @@ function useGridState(options, onRegisterApi) {
831
1048
  gridApiRef.current.core.raise.groupingChanged(next);
832
1049
  },
833
1050
  clearGrouping: () => {
834
- clearGridGroupingCommand(gridApiRef.current, (grouping) => setGroupByColumns(grouping), false);
1051
+ clearGridGroupingCommand(
1052
+ gridApiRef.current,
1053
+ (grouping) => setGroupByColumns(grouping),
1054
+ false
1055
+ );
835
1056
  },
836
1057
  benchmark: (iterations) => {
837
1058
  return runBenchmarkFn(iterations);
@@ -867,7 +1088,7 @@ function useGridState(options, onRegisterApi) {
867
1088
  treeExpandRow: (row) => expandTreeRowByRefFn(row),
868
1089
  treeCollapseRow: (row) => collapseTreeRowByRefFn(row),
869
1090
  treeGetRowChildren: (row) => {
870
- const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
1091
+ const rowId = (0, import_ui_grid4.resolveGridRowId)(optionsRef.current, row);
871
1092
  return buildRowsFromData(optionsRef.current.data).filter((r) => r.parentId === rowId);
872
1093
  },
873
1094
  treeGetState: () => expandedTreeRowsRef.current,
@@ -917,7 +1138,7 @@ function useGridState(options, onRegisterApi) {
917
1138
  );
918
1139
  },
919
1140
  saveState: () => {
920
- return (0, import_ui_grid3.buildGridSavedState)({
1141
+ return (0, import_ui_grid4.buildGridSavedState)({
921
1142
  columnOrder: columnOrderRef.current,
922
1143
  activeFilters: activeFiltersRef.current,
923
1144
  sortState: sortStateRef.current,
@@ -926,7 +1147,8 @@ function useGridState(options, onRegisterApi) {
926
1147
  pageSize: pageSizeRef.current,
927
1148
  totalItems: pipelineRef.current.totalItems,
928
1149
  expandedRows: expandedRowsRef.current,
929
- expandedTreeRows: expandedTreeRowsRef.current
1150
+ expandedTreeRows: expandedTreeRowsRef.current,
1151
+ pinnedColumns: pinnedColumnsRef.current
930
1152
  });
931
1153
  },
932
1154
  restoreState: (state) => {
@@ -939,32 +1161,58 @@ function useGridState(options, onRegisterApi) {
939
1161
  setPageSize: (ps) => setPageSize(ps),
940
1162
  setExpandedRows: (e) => setExpandedRows(e),
941
1163
  setExpandedTreeRows: (e) => setExpandedTreeRows(e),
1164
+ setPinnedColumns: (p) => setPinnedColumns(p),
942
1165
  getEffectivePageSize: () => effectivePageSizeFn(pipelineRef.current.totalItems)
943
1166
  });
944
1167
  },
945
1168
  beginCellEdit: (row, columnName, triggerEvent) => {
946
- const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
947
- const gridRow = (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), rowId);
1169
+ const rowId = (0, import_ui_grid4.resolveGridRowId)(optionsRef.current, row);
1170
+ const gridRow = (0, import_ui_grid4.findGridRowById)(buildRowsFromData(optionsRef.current.data), rowId);
948
1171
  const column = visibleColumnsRef.current.find((c) => c.name === columnName);
949
1172
  if (!gridRow || !column || !isCellEditable(gridRow, column, triggerEvent)) return;
950
1173
  startCellEditFn(gridRow, column, triggerEvent);
951
1174
  },
952
1175
  endCellEdit: () => commitCellEditFn(),
953
1176
  cancelCellEdit: () => cancelCellEditFn(),
954
- getEditingCell: () => editingCellRef.current
1177
+ getEditingCell: () => editingCellRef.current,
1178
+ pinColumn: (columnName, direction) => {
1179
+ pinGridColumnCommand(
1180
+ gridApiRef.current,
1181
+ isPinningEnabledFn(),
1182
+ (v) => setPinnedColumns(v),
1183
+ () => pinnedColumnsRef.current,
1184
+ columnName,
1185
+ direction
1186
+ );
1187
+ }
955
1188
  };
956
- gridApiRef.current = (0, import_ui_grid3.createGridApi)(bindings);
1189
+ gridApiRef.current = (0, import_ui_grid4.createGridApi)(bindings);
957
1190
  }
958
1191
  const gridApi = gridApiRef.current;
959
- const seekPageFn = (0, import_react.useCallback)((page) => {
960
- seekGridPaginationCommand(
1192
+ const seekPageFn = (0, import_react.useCallback)(
1193
+ (page) => {
1194
+ seekGridPaginationCommand(
1195
+ gridApiRef.current,
1196
+ (nextPage) => setCurrentPage(nextPage),
1197
+ () => getTotalPagesValueFn(),
1198
+ () => effectivePageSizeFn(pipelineRef.current.totalItems),
1199
+ page
1200
+ );
1201
+ },
1202
+ [getTotalPagesValueFn, effectivePageSizeFn]
1203
+ );
1204
+ const togglePinFn = (0, import_react.useCallback)((column) => {
1205
+ const current = pinnedColumnsRef.current[column.name];
1206
+ const next = current === "left" ? "right" : current === "right" ? "none" : "left";
1207
+ pinGridColumnCommand(
961
1208
  gridApiRef.current,
962
- (nextPage) => setCurrentPage(nextPage),
963
- () => getTotalPagesValueFn(),
964
- () => effectivePageSizeFn(pipelineRef.current.totalItems),
965
- page
1209
+ isPinningEnabledFn(),
1210
+ (v) => setPinnedColumns(v),
1211
+ () => pinnedColumnsRef.current,
1212
+ column.name,
1213
+ next
966
1214
  );
967
- }, [getTotalPagesValueFn, effectivePageSizeFn]);
1215
+ }, []);
968
1216
  const setPaginationPageSizeFn = (0, import_react.useCallback)((ps) => {
969
1217
  setGridPaginationPageSizeCommand(
970
1218
  gridApiRef.current,
@@ -973,19 +1221,22 @@ function useGridState(options, onRegisterApi) {
973
1221
  ps
974
1222
  );
975
1223
  }, []);
976
- const toggleRowExpansionByRefFn = (0, import_react.useCallback)((row) => {
977
- const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
978
- toggleGridRowExpansionCommand(
979
- gridApiRef.current,
980
- import_ui_grid3.FEATURE_EXPANDABLE && (0, import_ui_grid3.canGridExpandRows)(optionsRef.current),
981
- expandedRowsRef.current,
982
- rowId,
983
- (e) => setExpandedRows(e),
984
- (resolvedRowId) => (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), resolvedRowId)
985
- );
986
- }, [buildRowsFromData]);
1224
+ const toggleRowExpansionByRefFn = (0, import_react.useCallback)(
1225
+ (row) => {
1226
+ const rowId = (0, import_ui_grid4.resolveGridRowId)(optionsRef.current, row);
1227
+ toggleGridRowExpansionCommand(
1228
+ gridApiRef.current,
1229
+ import_ui_grid4.FEATURE_EXPANDABLE && (0, import_ui_grid4.canGridExpandRows)(optionsRef.current),
1230
+ expandedRowsRef.current,
1231
+ rowId,
1232
+ (e) => setExpandedRows(e),
1233
+ (resolvedRowId) => (0, import_ui_grid4.findGridRowById)(buildRowsFromData(optionsRef.current.data), resolvedRowId)
1234
+ );
1235
+ },
1236
+ [buildRowsFromData]
1237
+ );
987
1238
  const expandAllRowsFn = (0, import_react.useCallback)(() => {
988
- if (!(0, import_ui_grid3.canGridExpandRows)(optionsRef.current)) return;
1239
+ if (!(0, import_ui_grid4.canGridExpandRows)(optionsRef.current)) return;
989
1240
  expandAllGridRowsCommand(
990
1241
  (data) => buildRowsFromData(data),
991
1242
  optionsRef.current.data,
@@ -993,121 +1244,145 @@ function useGridState(options, onRegisterApi) {
993
1244
  );
994
1245
  }, [buildRowsFromData]);
995
1246
  const toggleAllRowsFn = (0, import_react.useCallback)(() => {
996
- const allExpanded = (0, import_ui_grid3.areAllGridRowsExpanded)(buildRowsFromData(optionsRef.current.data), expandedRowsRef.current);
1247
+ const allExpanded = (0, import_ui_grid4.areAllGridRowsExpanded)(
1248
+ buildRowsFromData(optionsRef.current.data),
1249
+ expandedRowsRef.current
1250
+ );
997
1251
  if (allExpanded) {
998
1252
  collapseAllGridRowsCommand((e) => setExpandedRows(e));
999
1253
  } else {
1000
1254
  expandAllRowsFn();
1001
1255
  }
1002
1256
  }, [buildRowsFromData, expandAllRowsFn]);
1003
- const toggleTreeRowByRefFn = (0, import_react.useCallback)((row) => {
1004
- const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
1005
- toggleGridTreeRowCommand(
1006
- gridApiRef.current,
1007
- expandedTreeRowsRef.current,
1008
- rowId,
1009
- (e) => setExpandedTreeRows(e),
1010
- (resolvedRowId) => (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), resolvedRowId)
1011
- );
1012
- }, [buildRowsFromData]);
1013
- const expandTreeRowByRefFn = (0, import_react.useCallback)((row) => {
1014
- const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
1015
- setGridTreeRowExpandedCommand(
1016
- gridApiRef.current,
1017
- expandedTreeRowsRef.current,
1018
- rowId,
1019
- true,
1020
- (e) => setExpandedTreeRows(e),
1021
- (resolvedRowId) => (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), resolvedRowId)
1022
- );
1023
- }, [buildRowsFromData]);
1024
- const collapseTreeRowByRefFn = (0, import_react.useCallback)((row) => {
1025
- const rowId = (0, import_ui_grid3.resolveGridRowId)(optionsRef.current, row);
1026
- setGridTreeRowExpandedCommand(
1027
- gridApiRef.current,
1028
- expandedTreeRowsRef.current,
1029
- rowId,
1030
- false,
1031
- (e) => setExpandedTreeRows(e),
1032
- (resolvedRowId) => (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), resolvedRowId)
1033
- );
1034
- }, [buildRowsFromData]);
1035
- const startCellEditFn = (0, import_react.useCallback)((row, column, triggerEvent, initialValue) => {
1036
- const currentValue = (0, import_ui_grid3.getCellValue)(row.entity, column);
1037
- const focusToken = ++editorFocusTokenRef.current;
1038
- const ec = beginGridCellEditCommand(
1039
- gridApiRef.current,
1040
- {
1041
- setFocusedCell: (fc) => setFocusedCell(fc),
1042
- setEditingCell: (ec2) => setEditingCell(ec2),
1043
- setEditingValue: (ev) => setEditingValue(ev)
1044
- },
1045
- row,
1046
- column,
1047
- currentValue,
1048
- triggerEvent,
1049
- initialValue
1050
- );
1051
- if (ec) {
1052
- queueMicrotask(() => focusEditorInput(focusToken));
1053
- }
1054
- }, [focusEditorInput]);
1055
- const commitCellEditFn = (0, import_react.useCallback)((direction, restoreFocus = true) => {
1056
- const result = commitGridCellEditCommand(gridApiRef.current, {
1057
- getEditingCell: () => editingCellRef.current,
1058
- getEditingValue: () => editingValueRef.current,
1059
- setEditingCell: (ec) => setEditingCell(ec),
1060
- setEditingValue: (ev) => setEditingValue(ev),
1061
- findRowById: (rowId) => (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), rowId),
1062
- findColumnByName: (columnName) => visibleColumnsRef.current.find((c) => c.name === columnName),
1063
- parseEditedValue: (column, value, oldValue) => (0, import_ui_grid3.parseGridEditedValue)(column, value, oldValue),
1064
- setCellValue: (rowEntity, column, value) => {
1065
- const fieldPath = column.editModelField ?? column.field ?? column.name;
1066
- (0, import_ui_grid3.setPathValue)(rowEntity, fieldPath, value);
1257
+ const toggleTreeRowByRefFn = (0, import_react.useCallback)(
1258
+ (row) => {
1259
+ const rowId = (0, import_ui_grid4.resolveGridRowId)(optionsRef.current, row);
1260
+ toggleGridTreeRowCommand(
1261
+ gridApiRef.current,
1262
+ expandedTreeRowsRef.current,
1263
+ rowId,
1264
+ (e) => setExpandedTreeRows(e),
1265
+ (resolvedRowId) => (0, import_ui_grid4.findGridRowById)(buildRowsFromData(optionsRef.current.data), resolvedRowId)
1266
+ );
1267
+ },
1268
+ [buildRowsFromData]
1269
+ );
1270
+ const expandTreeRowByRefFn = (0, import_react.useCallback)(
1271
+ (row) => {
1272
+ const rowId = (0, import_ui_grid4.resolveGridRowId)(optionsRef.current, row);
1273
+ setGridTreeRowExpandedCommand(
1274
+ gridApiRef.current,
1275
+ expandedTreeRowsRef.current,
1276
+ rowId,
1277
+ true,
1278
+ (e) => setExpandedTreeRows(e),
1279
+ (resolvedRowId) => (0, import_ui_grid4.findGridRowById)(buildRowsFromData(optionsRef.current.data), resolvedRowId)
1280
+ );
1281
+ },
1282
+ [buildRowsFromData]
1283
+ );
1284
+ const collapseTreeRowByRefFn = (0, import_react.useCallback)(
1285
+ (row) => {
1286
+ const rowId = (0, import_ui_grid4.resolveGridRowId)(optionsRef.current, row);
1287
+ setGridTreeRowExpandedCommand(
1288
+ gridApiRef.current,
1289
+ expandedTreeRowsRef.current,
1290
+ rowId,
1291
+ false,
1292
+ (e) => setExpandedTreeRows(e),
1293
+ (resolvedRowId) => (0, import_ui_grid4.findGridRowById)(buildRowsFromData(optionsRef.current.data), resolvedRowId)
1294
+ );
1295
+ },
1296
+ [buildRowsFromData]
1297
+ );
1298
+ const startCellEditFn = (0, import_react.useCallback)(
1299
+ (row, column, triggerEvent, initialValue) => {
1300
+ const currentValue = (0, import_ui_grid4.getCellValue)(row.entity, column);
1301
+ const focusToken = ++editorFocusTokenRef.current;
1302
+ const ec = beginGridCellEditCommand(
1303
+ gridApiRef.current,
1304
+ {
1305
+ setFocusedCell: (fc) => setFocusedCell(fc),
1306
+ setEditingCell: (ec2) => setEditingCell(ec2),
1307
+ setEditingValue: (ev) => setEditingValue(ev)
1308
+ },
1309
+ row,
1310
+ column,
1311
+ currentValue,
1312
+ triggerEvent,
1313
+ initialValue
1314
+ );
1315
+ if (ec) {
1316
+ queueMicrotask(() => focusEditorInput(focusToken));
1067
1317
  }
1068
- });
1069
- if (!result.committed || !result.row || !result.column || !result.focusTarget) return;
1070
- editorFocusTokenRef.current += 1;
1071
- if (direction) {
1072
- const moved = moveFocusFn(result.row, result.column, direction);
1073
- if (!moved) focusRenderedCell(result.focusTarget);
1074
- } else if (restoreFocus) {
1075
- focusRenderedCell(result.focusTarget);
1076
- }
1077
- }, [buildRowsFromData, focusRenderedCell]);
1318
+ },
1319
+ [focusEditorInput]
1320
+ );
1321
+ const commitCellEditFn = (0, import_react.useCallback)(
1322
+ (direction, restoreFocus = true) => {
1323
+ const result = commitGridCellEditCommand(gridApiRef.current, {
1324
+ getEditingCell: () => editingCellRef.current,
1325
+ getEditingValue: () => editingValueRef.current,
1326
+ setEditingCell: (ec) => setEditingCell(ec),
1327
+ setEditingValue: (ev) => setEditingValue(ev),
1328
+ findRowById: (rowId) => (0, import_ui_grid4.findGridRowById)(buildRowsFromData(optionsRef.current.data), rowId),
1329
+ findColumnByName: (columnName) => visibleColumnsRef.current.find((c) => c.name === columnName),
1330
+ parseEditedValue: (column, value, oldValue) => (0, import_ui_grid4.parseGridEditedValue)(column, value, oldValue),
1331
+ setCellValue: (rowEntity, column, value) => {
1332
+ const fieldPath = column.editModelField ?? column.field ?? column.name;
1333
+ (0, import_ui_grid4.setPathValue)(rowEntity, fieldPath, value);
1334
+ }
1335
+ });
1336
+ if (!result.committed || !result.row || !result.column || !result.focusTarget) return;
1337
+ editorFocusTokenRef.current += 1;
1338
+ if (direction) {
1339
+ const moved = moveFocusFn(result.row, result.column, direction);
1340
+ if (!moved) focusRenderedCell(result.focusTarget);
1341
+ } else if (restoreFocus) {
1342
+ focusRenderedCell(result.focusTarget);
1343
+ }
1344
+ },
1345
+ [buildRowsFromData, focusRenderedCell]
1346
+ );
1078
1347
  const cancelCellEditFn = (0, import_react.useCallback)(() => {
1079
1348
  const hadEditingCell = editingCellRef.current !== null;
1080
1349
  const result = cancelGridCellEditCommand(gridApiRef.current, {
1081
1350
  getEditingCell: () => editingCellRef.current,
1082
1351
  setEditingCell: (ec) => setEditingCell(ec),
1083
1352
  setEditingValue: (ev) => setEditingValue(ev),
1084
- findRowById: (rowId) => (0, import_ui_grid3.findGridRowById)(buildRowsFromData(optionsRef.current.data), rowId),
1353
+ findRowById: (rowId) => (0, import_ui_grid4.findGridRowById)(buildRowsFromData(optionsRef.current.data), rowId),
1085
1354
  findColumnByName: (columnName) => visibleColumnsRef.current.find((c) => c.name === columnName)
1086
1355
  });
1087
1356
  if (!hadEditingCell) return;
1088
1357
  editorFocusTokenRef.current += 1;
1089
1358
  if (result.focusTarget) focusRenderedCell(result.focusTarget);
1090
1359
  }, [buildRowsFromData, focusRenderedCell]);
1091
- const moveFocusFn = (0, import_react.useCallback)((row, column, direction, triggerEvent) => {
1092
- const nextCell = (0, import_ui_grid3.findNextGridCell)({
1093
- rows: pipelineRef.current.visibleRows,
1094
- columns: visibleColumnsRef.current,
1095
- rowId: row.id,
1096
- columnName: column.name,
1097
- direction
1098
- });
1099
- if (!nextCell) return false;
1100
- setFocusedCell({ rowId: nextCell.row.id, columnName: nextCell.column.name });
1101
- focusRenderedCell({ rowId: nextCell.row.id, columnName: nextCell.column.name });
1102
- if (shouldEditOnFocusFn(nextCell.column) && isCellEditable(nextCell.row, nextCell.column, triggerEvent)) {
1103
- startCellEditFn(nextCell.row, nextCell.column, triggerEvent);
1104
- }
1105
- return true;
1106
- }, [focusRenderedCell, isCellEditable, shouldEditOnFocusFn, startCellEditFn]);
1360
+ const moveFocusFn = (0, import_react.useCallback)(
1361
+ (row, column, direction, triggerEvent) => {
1362
+ const nextCell = (0, import_ui_grid4.findNextGridCell)({
1363
+ rows: pipelineRef.current.visibleRows,
1364
+ columns: visibleColumnsRef.current,
1365
+ rowId: row.id,
1366
+ columnName: column.name,
1367
+ direction
1368
+ });
1369
+ if (!nextCell) return false;
1370
+ setFocusedCell({ rowId: nextCell.row.id, columnName: nextCell.column.name });
1371
+ focusRenderedCell({ rowId: nextCell.row.id, columnName: nextCell.column.name });
1372
+ if (shouldEditOnFocusFn(nextCell.column) && isCellEditable(nextCell.row, nextCell.column, triggerEvent)) {
1373
+ startCellEditFn(nextCell.row, nextCell.column, triggerEvent);
1374
+ }
1375
+ return true;
1376
+ },
1377
+ [focusRenderedCell, isCellEditable, shouldEditOnFocusFn, startCellEditFn]
1378
+ );
1107
1379
  const runBenchmarkFn = (0, import_react.useCallback)((iterations) => {
1108
- const safeIterations = Math.max(1, iterations ?? optionsRef.current.benchmark?.iterations ?? 25);
1380
+ const safeIterations = resolveBenchmarkIterations(
1381
+ iterations,
1382
+ optionsRef.current.benchmark?.iterations
1383
+ );
1109
1384
  const startedAt = performance.now();
1110
- let lastResult = (0, import_ui_grid3.buildGridPipeline)({
1385
+ let lastResult = import_ui_grid4.defaultGridEngine.buildPipeline({
1111
1386
  options: optionsRef.current,
1112
1387
  columns: visibleColumnsRef.current,
1113
1388
  activeFilters: activeFiltersRef.current,
@@ -1122,7 +1397,7 @@ function useGridState(options, onRegisterApi) {
1122
1397
  rowSize: optionsRef.current.rowHeight ?? 44
1123
1398
  });
1124
1399
  for (let i = 1; i < safeIterations; i++) {
1125
- lastResult = (0, import_ui_grid3.buildGridPipeline)({
1400
+ lastResult = import_ui_grid4.defaultGridEngine.buildPipeline({
1126
1401
  options: optionsRef.current,
1127
1402
  columns: visibleColumnsRef.current,
1128
1403
  activeFilters: activeFiltersRef.current,
@@ -1150,10 +1425,10 @@ function useGridState(options, onRegisterApi) {
1150
1425
  return result;
1151
1426
  }, []);
1152
1427
  const exportCsvFn = (0, import_react.useCallback)(() => {
1153
- if (!import_ui_grid3.FEATURE_CSV_EXPORT) return;
1428
+ if (!import_ui_grid4.FEATURE_CSV_EXPORT) return;
1154
1429
  const columns = visibleColumnsRef.current;
1155
- const csv = (0, import_ui_grid3.exportCsvRows)(columns, pipelineRef.current.visibleRows);
1156
- downloadGridCsvFile(csv, `${(0, import_ui_grid3.sanitizeDownloadFilename)(optionsRef.current.id)}.csv`);
1430
+ const csv = (0, import_ui_grid4.exportCsvRows)(columns, pipelineRef.current.visibleRows);
1431
+ downloadGridCsvFile(csv, `${(0, import_ui_grid4.sanitizeDownloadFilename)(optionsRef.current.id)}.csv`);
1157
1432
  }, []);
1158
1433
  (0, import_react.useEffect)(() => {
1159
1434
  if (initializedGridIdRef.current === options.id) return;
@@ -1168,8 +1443,9 @@ function useGridState(options, onRegisterApi) {
1168
1443
  setExpandedTreeRows({});
1169
1444
  setColumnOrder(options.columnDefs.map((column) => column.name));
1170
1445
  setGroupByColumns(options.grouping?.groupBy ?? []);
1446
+ setPinnedColumns(buildInitialPinnedState(options.columnDefs));
1171
1447
  setCurrentPage(options.paginationCurrentPage ?? 1);
1172
- setPageSize((0, import_ui_grid3.getEffectivePageSize)(options, 0, options.data.length));
1448
+ setPageSize((0, import_ui_grid4.getEffectivePageSize)(options, 0, options.data.length));
1173
1449
  setInfiniteScrollState({
1174
1450
  scrollUp: options.infiniteScrollUp === true,
1175
1451
  scrollDown: options.infiniteScrollDown !== false,
@@ -1181,7 +1457,7 @@ function useGridState(options, onRegisterApi) {
1181
1457
  );
1182
1458
  setSortState({
1183
1459
  columnName: initialSort?.name ?? null,
1184
- direction: initialSort?.sort?.direction ?? import_ui_grid3.SORT_DIRECTIONS.none
1460
+ direction: initialSort?.sort?.direction ?? import_ui_grid4.SORT_DIRECTIONS.none
1185
1461
  });
1186
1462
  onRegisterApi?.(gridApi);
1187
1463
  raiseGridRenderingComplete(gridApi);
@@ -1196,12 +1472,19 @@ function useGridState(options, onRegisterApi) {
1196
1472
  }
1197
1473
  }, [pipeline, gridApi, rowSize]);
1198
1474
  (0, import_react.useEffect)(() => {
1199
- if (!import_ui_grid3.FEATURE_AUTO_RESIZE || !options.enableAutoResize) return;
1475
+ if (!import_ui_grid4.FEATURE_AUTO_RESIZE || !options.enableAutoResize) return;
1200
1476
  const container = gridContainerRef.current;
1201
1477
  if (!container) return;
1202
1478
  const observer = observeGridHostSize(container, ({ height: nextHeight, width: nextWidth }) => {
1203
- if (nextHeight === lastGridHeightRef.current && nextWidth === lastGridWidthRef.current) return;
1204
- raiseGridDimensionChanged(gridApi, lastGridHeightRef.current, lastGridWidthRef.current, nextHeight, nextWidth);
1479
+ if (nextHeight === lastGridHeightRef.current && nextWidth === lastGridWidthRef.current)
1480
+ return;
1481
+ raiseGridDimensionChanged(
1482
+ gridApi,
1483
+ lastGridHeightRef.current,
1484
+ lastGridWidthRef.current,
1485
+ nextHeight,
1486
+ nextWidth
1487
+ );
1205
1488
  lastGridHeightRef.current = nextHeight;
1206
1489
  lastGridWidthRef.current = nextWidth;
1207
1490
  if (!options.viewportHeight && nextHeight > 0) {
@@ -1219,111 +1502,152 @@ function useGridState(options, onRegisterApi) {
1219
1502
  const paginationCurrentPage = getCurrentPageValueFn();
1220
1503
  const paginationTotalPages = getTotalPagesValueFn();
1221
1504
  const paginationSelectedPageSize = effectivePageSizeFn(pipeline.totalItems);
1222
- const viewportHeightPx = `${options.viewportHeight ?? autoViewportHeight ?? 560}px`;
1223
- const headerLabelFn = (0, import_react.useCallback)((column) => (0, import_ui_grid3.headerLabel)(column), []);
1224
- const isGroupItemFn = (0, import_react.useCallback)((item) => item.kind === "group", []);
1225
- const isExpandableItemFn = (0, import_react.useCallback)((item) => item.kind === "expandable", []);
1505
+ const viewportHeightPx = computeViewportHeightPx(options.viewportHeight, autoViewportHeight);
1506
+ const headerLabelFn = (0, import_react.useCallback)((column) => (0, import_ui_grid4.headerLabel)(column), []);
1507
+ const isGroupItemFn = (0, import_react.useCallback)(
1508
+ (item) => item.kind === "group",
1509
+ []
1510
+ );
1511
+ const isExpandableItemFn = (0, import_react.useCallback)(
1512
+ (item) => item.kind === "expandable",
1513
+ []
1514
+ );
1226
1515
  const isRowItemFn = (0, import_react.useCallback)((item) => item.kind === "row", []);
1227
- const isOddStripedRowFn = (0, import_react.useCallback)((item) => item.kind === "row" && item.visibleIndex % 2 === 0, []);
1516
+ const isOddStripedRowFn = (0, import_react.useCallback)(
1517
+ (item) => item.kind === "row" && item.visibleIndex % 2 === 0,
1518
+ []
1519
+ );
1228
1520
  const sortDirectionFn = (0, import_react.useCallback)((column) => {
1229
- return sortStateRef.current.columnName === column.name ? sortStateRef.current.direction : import_ui_grid3.SORT_DIRECTIONS.none;
1521
+ return sortStateRef.current.columnName === column.name ? sortStateRef.current.direction : import_ui_grid4.SORT_DIRECTIONS.none;
1230
1522
  }, []);
1231
- const sortButtonLabelFn = (0, import_react.useCallback)((column) => {
1232
- return (0, import_ui_grid3.gridSortButtonLabel)(sortDirectionFn(column), labels);
1233
- }, [labels, sortDirectionFn]);
1234
- const sortAriaSortFn = (0, import_react.useCallback)((column) => {
1235
- return (0, import_ui_grid3.gridSortAriaSort)(sortDirectionFn(column));
1236
- }, [sortDirectionFn]);
1237
- const groupingButtonLabelFn = (0, import_react.useCallback)((column) => {
1238
- return (0, import_ui_grid3.gridGroupingButtonLabel)((0, import_ui_grid3.isGridColumnGrouped)(groupByColumnsRef.current, column), labels);
1239
- }, [labels]);
1523
+ const sortButtonLabelFn = (0, import_react.useCallback)(
1524
+ (column) => {
1525
+ return (0, import_ui_grid4.gridSortButtonLabel)(sortDirectionFn(column), labels);
1526
+ },
1527
+ [labels, sortDirectionFn]
1528
+ );
1529
+ const sortAriaSortFn = (0, import_react.useCallback)(
1530
+ (column) => {
1531
+ return (0, import_ui_grid4.gridSortAriaSort)(sortDirectionFn(column));
1532
+ },
1533
+ [sortDirectionFn]
1534
+ );
1535
+ const groupingButtonLabelFn = (0, import_react.useCallback)(
1536
+ (column) => {
1537
+ return (0, import_ui_grid4.gridGroupingButtonLabel)(
1538
+ (0, import_ui_grid4.isGridColumnGrouped)(groupByColumnsRef.current, column),
1539
+ labels
1540
+ );
1541
+ },
1542
+ [labels]
1543
+ );
1240
1544
  const filterValueFn = (0, import_react.useCallback)((columnName) => {
1241
1545
  return activeFiltersRef.current[columnName] ?? "";
1242
1546
  }, []);
1243
- const filterPlaceholderFn = (0, import_react.useCallback)((column) => {
1244
- return (0, import_ui_grid3.gridFilterPlaceholder)((0, import_ui_grid3.isGridColumnFilterable)(optionsRef.current, column), labels);
1245
- }, [labels]);
1547
+ const filterPlaceholderFn = (0, import_react.useCallback)(
1548
+ (column) => {
1549
+ return (0, import_ui_grid4.gridFilterPlaceholder)((0, import_ui_grid4.isGridColumnFilterable)(optionsRef.current, column), labels);
1550
+ },
1551
+ [labels]
1552
+ );
1246
1553
  const isFilterInputDisabledFn = (0, import_react.useCallback)((column) => {
1247
- return !(0, import_ui_grid3.isGridColumnFilterable)(optionsRef.current, column);
1248
- }, []);
1249
- const groupDisclosureLabelFn = (0, import_react.useCallback)((item) => {
1250
- return (0, import_ui_grid3.gridGroupDisclosureLabel)(item.collapsed, labels);
1251
- }, [labels]);
1252
- const cellContextFn = (0, import_react.useCallback)((row, column) => {
1253
- return (0, import_ui_grid3.buildGridCellContext)(row, column);
1554
+ return !(0, import_ui_grid4.isGridColumnFilterable)(optionsRef.current, column);
1254
1555
  }, []);
1255
- const displayValueFn = (0, import_react.useCallback)((row, column) => {
1256
- return (0, import_ui_grid3.formatGridCellDisplayValue)(cellContextFn(row, column));
1257
- }, [cellContextFn]);
1556
+ const groupDisclosureLabelFn = (0, import_react.useCallback)(
1557
+ (item) => {
1558
+ return (0, import_ui_grid4.gridGroupDisclosureLabel)(item.collapsed, labels);
1559
+ },
1560
+ [labels]
1561
+ );
1562
+ const cellContextFn = (0, import_react.useCallback)(
1563
+ (row, column) => {
1564
+ return (0, import_ui_grid4.buildGridCellContext)(row, column);
1565
+ },
1566
+ []
1567
+ );
1568
+ const displayValueFn = (0, import_react.useCallback)(
1569
+ (row, column) => {
1570
+ return (0, import_ui_grid4.formatGridCellDisplayValue)(cellContextFn(row, column));
1571
+ },
1572
+ [cellContextFn]
1573
+ );
1258
1574
  const isFocusedCellFn = (0, import_react.useCallback)((row, column) => {
1259
- return (0, import_ui_grid3.isGridCellPosition)(focusedCellRef.current, row.id, column.name);
1575
+ return (0, import_ui_grid4.isGridCellPosition)(focusedCellRef.current, row.id, column.name);
1260
1576
  }, []);
1261
1577
  const isEditingCellFn = (0, import_react.useCallback)((row, column) => {
1262
- return (0, import_ui_grid3.isGridCellPosition)(editingCellRef.current, row.id, column.name);
1578
+ return (0, import_ui_grid4.isGridCellPosition)(editingCellRef.current, row.id, column.name);
1263
1579
  }, []);
1264
1580
  const editorInputTypeFn = (0, import_react.useCallback)((column) => {
1265
- return (0, import_ui_grid3.gridEditorInputType)(column);
1266
- }, []);
1267
- const expandedContextFn = (0, import_react.useCallback)((row) => {
1268
- return {
1269
- $implicit: row.entity,
1270
- row: row.entity,
1271
- rowIndex: row.index,
1272
- expanded: true,
1273
- ...optionsRef.current.expandableRowScope ?? {}
1274
- };
1581
+ return (0, import_ui_grid4.gridEditorInputType)(column);
1275
1582
  }, []);
1276
- const columnWidthFn = (0, import_react.useCallback)((column) => (0, import_ui_grid3.gridColumnWidth)(column), []);
1583
+ const expandedContextFn = (0, import_react.useCallback)(
1584
+ (row) => {
1585
+ return {
1586
+ $implicit: row.entity,
1587
+ row: row.entity,
1588
+ rowIndex: row.index,
1589
+ expanded: true,
1590
+ ...optionsRef.current.expandableRowScope ?? {}
1591
+ };
1592
+ },
1593
+ []
1594
+ );
1595
+ const columnWidthFn = (0, import_react.useCallback)((column) => (0, import_ui_grid4.gridColumnWidth)(column), []);
1277
1596
  const isColumnSortableFn = (0, import_react.useCallback)((column) => {
1278
- return (0, import_ui_grid3.isGridColumnSortable)(optionsRef.current, column);
1597
+ return (0, import_ui_grid4.isGridColumnSortable)(optionsRef.current, column);
1279
1598
  }, []);
1280
1599
  const isColumnFilterableFn = (0, import_react.useCallback)((column) => {
1281
- return (0, import_ui_grid3.isGridColumnFilterable)(optionsRef.current, column);
1600
+ return (0, import_ui_grid4.isGridColumnFilterable)(optionsRef.current, column);
1282
1601
  }, []);
1283
1602
  const cellIndentFn = (0, import_react.useCallback)((row, column) => {
1284
- return (0, import_ui_grid3.gridCellIndent)(optionsRef.current, visibleColumnsRef.current, row, column);
1603
+ return (0, import_ui_grid4.gridCellIndent)(optionsRef.current, visibleColumnsRef.current, row, column);
1285
1604
  }, []);
1286
- const treeToggleLabelFn = (0, import_react.useCallback)((row) => {
1287
- return (0, import_ui_grid3.gridTreeToggleLabelForRow)(expandedTreeRowsRef.current, row, labels);
1288
- }, [labels]);
1605
+ const treeToggleLabelFn = (0, import_react.useCallback)(
1606
+ (row) => {
1607
+ return (0, import_ui_grid4.gridTreeToggleLabelForRow)(expandedTreeRowsRef.current, row, labels);
1608
+ },
1609
+ [labels]
1610
+ );
1289
1611
  const isTreeRowExpandedFn = (0, import_react.useCallback)((row) => {
1290
- return (0, import_ui_grid3.isGridTreeRowExpanded)(expandedTreeRowsRef.current, row);
1612
+ return (0, import_ui_grid4.isGridTreeRowExpanded)(expandedTreeRowsRef.current, row);
1291
1613
  }, []);
1292
- const expandToggleLabelFn = (0, import_react.useCallback)((row) => {
1293
- return (0, import_ui_grid3.gridExpandToggleLabelForRow)(row, labels);
1294
- }, [labels]);
1614
+ const expandToggleLabelFn = (0, import_react.useCallback)(
1615
+ (row) => {
1616
+ return (0, import_ui_grid4.gridExpandToggleLabelForRow)(row, labels);
1617
+ },
1618
+ [labels]
1619
+ );
1295
1620
  const isGroupedFn = (0, import_react.useCallback)((column) => {
1296
- return (0, import_ui_grid3.isGridColumnGrouped)(groupByColumnsRef.current, column);
1621
+ return (0, import_ui_grid4.isGridColumnGrouped)(groupByColumnsRef.current, column);
1297
1622
  }, []);
1298
1623
  const showTreeToggleFn = (0, import_react.useCallback)((row, column) => {
1299
- return (0, import_ui_grid3.shouldShowGridTreeToggle)(optionsRef.current, visibleColumnsRef.current, row, column);
1624
+ return (0, import_ui_grid4.shouldShowGridTreeToggle)(optionsRef.current, visibleColumnsRef.current, row, column);
1300
1625
  }, []);
1301
1626
  const showExpandToggleFn = (0, import_react.useCallback)((row, column) => {
1302
- return (0, import_ui_grid3.shouldShowGridExpandToggle)(optionsRef.current, visibleColumnsRef.current, column);
1627
+ return (0, import_ui_grid4.shouldShowGridExpandToggle)(optionsRef.current, visibleColumnsRef.current, column);
1303
1628
  }, []);
1304
1629
  const showPaginationControlsFn = (0, import_react.useCallback)(() => {
1305
- return import_ui_grid3.FEATURE_PAGINATION && (0, import_ui_grid3.shouldShowGridPaginationControls)(optionsRef.current);
1630
+ return import_ui_grid4.FEATURE_PAGINATION && (0, import_ui_grid4.shouldShowGridPaginationControls)(optionsRef.current);
1306
1631
  }, []);
1307
1632
  const paginationSummaryFn = (0, import_react.useCallback)(() => {
1308
1633
  const ti = pipelineRef.current.totalItems;
1309
- if (ti === 0) return "0-0 of 0";
1310
- return `${getFirstRowIndexValueFn(ti) + 1}-${getLastRowIndexValueFn(ti) + 1} of ${ti}`;
1634
+ return formatPaginationSummary(ti, getFirstRowIndexValueFn(ti), getLastRowIndexValueFn(ti));
1311
1635
  }, [getFirstRowIndexValueFn, getLastRowIndexValueFn]);
1312
1636
  const pageSizeOptionsFn = (0, import_react.useCallback)(() => {
1313
1637
  return optionsRef.current.paginationPageSizes ?? [];
1314
1638
  }, []);
1315
1639
  const isGroupingEnabledFn = (0, import_react.useCallback)(() => {
1316
- return import_ui_grid3.FEATURE_GROUPING && (0, import_ui_grid3.isGridGroupingEnabled)(optionsRef.current);
1640
+ return import_ui_grid4.FEATURE_GROUPING && (0, import_ui_grid4.isGridGroupingEnabled)(optionsRef.current);
1317
1641
  }, []);
1318
1642
  const isFilteringEnabledFn = (0, import_react.useCallback)(() => {
1319
- return import_ui_grid3.FEATURE_FILTERING && (0, import_ui_grid3.isGridFilteringEnabled)(optionsRef.current);
1643
+ return import_ui_grid4.FEATURE_FILTERING && (0, import_ui_grid4.isGridFilteringEnabled)(optionsRef.current);
1320
1644
  }, []);
1321
1645
  const toggleSortFn = (0, import_react.useCallback)((column) => {
1322
- if (!import_ui_grid3.FEATURE_SORTING || !(0, import_ui_grid3.isGridColumnSortable)(optionsRef.current, column)) return;
1323
- const currentDirection = sortStateRef.current.columnName === column.name ? sortStateRef.current.direction : import_ui_grid3.SORT_DIRECTIONS.none;
1324
- const nextDirection = currentDirection === import_ui_grid3.SORT_DIRECTIONS.none ? import_ui_grid3.SORT_DIRECTIONS.asc : currentDirection === import_ui_grid3.SORT_DIRECTIONS.asc ? import_ui_grid3.SORT_DIRECTIONS.desc : import_ui_grid3.SORT_DIRECTIONS.none;
1646
+ if (!import_ui_grid4.FEATURE_SORTING || !(0, import_ui_grid4.isGridColumnSortable)(optionsRef.current, column)) return;
1647
+ const currentDirection = sortStateRef.current.columnName === column.name ? sortStateRef.current.direction : import_ui_grid4.SORT_DIRECTIONS.none;
1648
+ const nextDirection = currentDirection === import_ui_grid4.SORT_DIRECTIONS.none ? import_ui_grid4.SORT_DIRECTIONS.asc : currentDirection === import_ui_grid4.SORT_DIRECTIONS.asc ? import_ui_grid4.SORT_DIRECTIONS.desc : import_ui_grid4.SORT_DIRECTIONS.none;
1325
1649
  applyGridSortStateCommand(gridApiRef.current, (state) => setSortState(state), {
1326
- columnName: nextDirection === import_ui_grid3.SORT_DIRECTIONS.none ? null : column.name,
1650
+ columnName: nextDirection === import_ui_grid4.SORT_DIRECTIONS.none ? null : column.name,
1327
1651
  direction: nextDirection
1328
1652
  });
1329
1653
  }, []);
@@ -1341,7 +1665,7 @@ function useGridState(options, onRegisterApi) {
1341
1665
  }, []);
1342
1666
  const toggleGroupingFn = (0, import_react.useCallback)((column, event) => {
1343
1667
  event?.stopPropagation();
1344
- if (!(import_ui_grid3.FEATURE_GROUPING && (0, import_ui_grid3.isGridGroupingEnabled)(optionsRef.current))) return;
1668
+ if (!(import_ui_grid4.FEATURE_GROUPING && (0, import_ui_grid4.isGridGroupingEnabled)(optionsRef.current))) return;
1345
1669
  const current = groupByColumnsRef.current;
1346
1670
  const next = current.includes(column.name) ? current.filter((n) => n !== column.name) : [...current, column.name];
1347
1671
  groupByColumnsRef.current = next;
@@ -1354,112 +1678,134 @@ function useGridState(options, onRegisterApi) {
1354
1678
  [item.id]: !current[item.id]
1355
1679
  }));
1356
1680
  }, []);
1357
- const focusCellFn = (0, import_react.useCallback)((row, column, triggerEvent) => {
1358
- const nextFocusResult = (0, import_ui_grid3.buildGridFocusCellResult)({
1359
- currentFocusedCell: focusedCellRef.current,
1360
- currentEditingCell: editingCellRef.current,
1361
- rowId: row.id,
1362
- columnName: column.name,
1363
- shouldEditOnFocus: shouldEditOnFocusFn(column),
1364
- isCellEditable: isCellEditable(row, column, triggerEvent)
1365
- });
1366
- setFocusedCell(nextFocusResult.focusedCell);
1367
- if (nextFocusResult.shouldBeginEdit) {
1368
- startCellEditFn(row, column, triggerEvent);
1369
- }
1370
- }, [isCellEditable, shouldEditOnFocusFn, startCellEditFn]);
1371
- const handleCellKeyDownFn = (0, import_react.useCallback)((row, column, event) => {
1372
- focusCellFn(row, column, event.nativeEvent);
1373
- switch (event.key) {
1374
- case "ArrowLeft":
1375
- event.preventDefault();
1376
- moveFocusFn(row, column, "left", event.nativeEvent);
1377
- return;
1378
- case "ArrowRight":
1379
- event.preventDefault();
1380
- moveFocusFn(row, column, "right", event.nativeEvent);
1381
- return;
1382
- case "ArrowUp":
1383
- event.preventDefault();
1384
- moveFocusFn(row, column, "up", event.nativeEvent);
1385
- return;
1386
- case "ArrowDown":
1681
+ const focusCellFn = (0, import_react.useCallback)(
1682
+ (row, column, triggerEvent) => {
1683
+ const nextFocusResult = (0, import_ui_grid4.buildGridFocusCellResult)({
1684
+ currentFocusedCell: focusedCellRef.current,
1685
+ currentEditingCell: editingCellRef.current,
1686
+ rowId: row.id,
1687
+ columnName: column.name,
1688
+ shouldEditOnFocus: shouldEditOnFocusFn(column),
1689
+ isCellEditable: isCellEditable(row, column, triggerEvent)
1690
+ });
1691
+ setFocusedCell(nextFocusResult.focusedCell);
1692
+ if (nextFocusResult.shouldBeginEdit) {
1693
+ startCellEditFn(row, column, triggerEvent);
1694
+ }
1695
+ },
1696
+ [isCellEditable, shouldEditOnFocusFn, startCellEditFn]
1697
+ );
1698
+ const handleCellKeyDownFn = (0, import_react.useCallback)(
1699
+ (row, column, event) => {
1700
+ focusCellFn(row, column, event.nativeEvent);
1701
+ switch (event.key) {
1702
+ case "ArrowLeft":
1703
+ event.preventDefault();
1704
+ moveFocusFn(row, column, "left", event.nativeEvent);
1705
+ return;
1706
+ case "ArrowRight":
1707
+ event.preventDefault();
1708
+ moveFocusFn(row, column, "right", event.nativeEvent);
1709
+ return;
1710
+ case "ArrowUp":
1711
+ event.preventDefault();
1712
+ moveFocusFn(row, column, "up", event.nativeEvent);
1713
+ return;
1714
+ case "ArrowDown":
1715
+ event.preventDefault();
1716
+ moveFocusFn(row, column, "down", event.nativeEvent);
1717
+ return;
1718
+ case "Tab":
1719
+ event.preventDefault();
1720
+ moveFocusFn(row, column, event.shiftKey ? "left" : "right", event.nativeEvent);
1721
+ return;
1722
+ case "Enter":
1723
+ event.preventDefault();
1724
+ moveFocusFn(row, column, event.shiftKey ? "up" : "down", event.nativeEvent);
1725
+ return;
1726
+ case "F2":
1727
+ event.preventDefault();
1728
+ if (isCellEditable(row, column, event.nativeEvent)) {
1729
+ startCellEditFn(row, column, event.nativeEvent);
1730
+ }
1731
+ return;
1732
+ case "Backspace":
1733
+ case "Delete":
1734
+ if (isCellEditable(row, column, event.nativeEvent)) {
1735
+ event.preventDefault();
1736
+ startCellEditFn(row, column, event.nativeEvent, "");
1737
+ }
1738
+ return;
1739
+ default:
1740
+ break;
1741
+ }
1742
+ if ((0, import_ui_grid4.isPrintableGridKey)(event.key, event.ctrlKey, event.metaKey, event.altKey) && isCellEditable(row, column, event.nativeEvent)) {
1387
1743
  event.preventDefault();
1388
- moveFocusFn(row, column, "down", event.nativeEvent);
1389
- return;
1390
- case "Tab":
1744
+ startCellEditFn(row, column, event.nativeEvent, event.key);
1745
+ }
1746
+ },
1747
+ [focusCellFn, moveFocusFn, isCellEditable, startCellEditFn]
1748
+ );
1749
+ const handleCellDoubleClickFn = (0, import_react.useCallback)(
1750
+ (row, column, event) => {
1751
+ focusCellFn(row, column, event.nativeEvent);
1752
+ if (isCellEditable(row, column, event.nativeEvent)) {
1753
+ startCellEditFn(row, column, event.nativeEvent);
1754
+ }
1755
+ },
1756
+ [focusCellFn, isCellEditable, startCellEditFn]
1757
+ );
1758
+ const updateEditingValueFn = (0, import_react.useCallback)((value) => {
1759
+ setEditingValue(value);
1760
+ }, []);
1761
+ const handleEditorKeyDownFn = (0, import_react.useCallback)(
1762
+ (event) => {
1763
+ if (event.key === "Escape") {
1391
1764
  event.preventDefault();
1392
- moveFocusFn(row, column, event.shiftKey ? "left" : "right", event.nativeEvent);
1765
+ cancelCellEditFn();
1393
1766
  return;
1394
- case "Enter":
1767
+ }
1768
+ if (event.key === "Enter") {
1395
1769
  event.preventDefault();
1396
- moveFocusFn(row, column, event.shiftKey ? "up" : "down", event.nativeEvent);
1770
+ commitCellEditFn(event.shiftKey ? "up" : "down");
1397
1771
  return;
1398
- case "F2":
1772
+ }
1773
+ if (event.key === "Tab") {
1399
1774
  event.preventDefault();
1400
- if (isCellEditable(row, column, event.nativeEvent)) {
1401
- startCellEditFn(row, column, event.nativeEvent);
1402
- }
1403
- return;
1404
- case "Backspace":
1405
- case "Delete":
1406
- if (isCellEditable(row, column, event.nativeEvent)) {
1407
- event.preventDefault();
1408
- startCellEditFn(row, column, event.nativeEvent, "");
1409
- }
1775
+ commitCellEditFn(event.shiftKey ? "left" : "right");
1776
+ }
1777
+ },
1778
+ [cancelCellEditFn, commitCellEditFn]
1779
+ );
1780
+ const handleEditorBlurFn = (0, import_react.useCallback)(
1781
+ (event) => {
1782
+ const ec = editingCellRef.current;
1783
+ const target = event.target;
1784
+ if (!ec || !target) return;
1785
+ if (target.dataset["rowId"] !== ec.rowId || target.dataset["colName"] !== ec.columnName)
1410
1786
  return;
1411
- default:
1412
- break;
1413
- }
1414
- if ((0, import_ui_grid3.isPrintableGridKey)(event.key, event.ctrlKey, event.metaKey, event.altKey) && isCellEditable(row, column, event.nativeEvent)) {
1415
- event.preventDefault();
1416
- startCellEditFn(row, column, event.nativeEvent, event.key);
1417
- }
1418
- }, [focusCellFn, moveFocusFn, isCellEditable, startCellEditFn]);
1419
- const handleCellDoubleClickFn = (0, import_react.useCallback)((row, column, event) => {
1420
- focusCellFn(row, column, event.nativeEvent);
1421
- if (isCellEditable(row, column, event.nativeEvent)) {
1422
- startCellEditFn(row, column, event.nativeEvent);
1423
- }
1424
- }, [focusCellFn, isCellEditable, startCellEditFn]);
1425
- const updateEditingValueFn = (0, import_react.useCallback)((value) => {
1426
- setEditingValue(value);
1427
- }, []);
1428
- const handleEditorKeyDownFn = (0, import_react.useCallback)((event) => {
1429
- if (event.key === "Escape") {
1430
- event.preventDefault();
1431
- cancelCellEditFn();
1432
- return;
1433
- }
1434
- if (event.key === "Enter") {
1435
- event.preventDefault();
1436
- commitCellEditFn(event.shiftKey ? "up" : "down");
1437
- return;
1438
- }
1439
- if (event.key === "Tab") {
1440
- event.preventDefault();
1441
- commitCellEditFn(event.shiftKey ? "left" : "right");
1442
- }
1443
- }, [cancelCellEditFn, commitCellEditFn]);
1444
- const handleEditorBlurFn = (0, import_react.useCallback)((event) => {
1445
- const ec = editingCellRef.current;
1446
- const target = event.target;
1447
- if (!ec || !target) return;
1448
- if (target.dataset["rowId"] !== ec.rowId || target.dataset["colName"] !== ec.columnName) return;
1449
- commitCellEditFn(void 0, false);
1450
- }, [commitCellEditFn]);
1451
- const toggleRowExpansionFn = (0, import_react.useCallback)((row, event) => {
1452
- event?.stopPropagation();
1453
- toggleRowExpansionByRefFn(row);
1454
- }, [toggleRowExpansionByRefFn]);
1455
- const toggleTreeRowFn = (0, import_react.useCallback)((row, event) => {
1456
- event?.stopPropagation();
1457
- toggleTreeRowByRefFn(row);
1458
- }, [toggleTreeRowByRefFn]);
1787
+ commitCellEditFn(void 0, false);
1788
+ },
1789
+ [commitCellEditFn]
1790
+ );
1791
+ const toggleRowExpansionFn = (0, import_react.useCallback)(
1792
+ (row, event) => {
1793
+ event?.stopPropagation();
1794
+ toggleRowExpansionByRefFn(row);
1795
+ },
1796
+ [toggleRowExpansionByRefFn]
1797
+ );
1798
+ const toggleTreeRowFn = (0, import_react.useCallback)(
1799
+ (row, event) => {
1800
+ event?.stopPropagation();
1801
+ toggleTreeRowByRefFn(row);
1802
+ },
1803
+ [toggleTreeRowByRefFn]
1804
+ );
1459
1805
  const moveColumnFn = (0, import_react.useCallback)((fromIndex, toIndex) => {
1460
1806
  moveGridColumnCommand(
1461
1807
  gridApiRef.current,
1462
- import_ui_grid3.FEATURE_COLUMN_MOVING && optionsRef.current.enableColumnMoving === true,
1808
+ import_ui_grid4.FEATURE_COLUMN_MOVING && optionsRef.current.enableColumnMoving === true,
1463
1809
  (updater) => setColumnOrder((current) => updater(current)),
1464
1810
  fromIndex,
1465
1811
  toIndex
@@ -1471,9 +1817,12 @@ function useGridState(options, onRegisterApi) {
1471
1817
  const previousPageFn = (0, import_react.useCallback)(() => {
1472
1818
  seekPageFn(getCurrentPageValueFn() - 1);
1473
1819
  }, [seekPageFn, getCurrentPageValueFn]);
1474
- const onPageSizeChangeFn = (0, import_react.useCallback)((value) => {
1475
- setPaginationPageSizeFn(Number(value));
1476
- }, [setPaginationPageSizeFn]);
1820
+ const onPageSizeChangeFn = (0, import_react.useCallback)(
1821
+ (value) => {
1822
+ setPaginationPageSizeFn(Number(value));
1823
+ },
1824
+ [setPaginationPageSizeFn]
1825
+ );
1477
1826
  const onViewportScrollFn = (0, import_react.useCallback)((startIndex) => {
1478
1827
  if (!scrollingRef.current) {
1479
1828
  scrollingRef.current = true;
@@ -1486,14 +1835,17 @@ function useGridState(options, onRegisterApi) {
1486
1835
  scrollingRef.current = false;
1487
1836
  raiseGridScrollEnd(gridApiRef.current);
1488
1837
  }, 120);
1489
- const isInfiniteScrollEnabled = import_ui_grid3.FEATURE_INFINITE_SCROLL && (optionsRef.current.infiniteScrollRowsFromEnd !== void 0 || optionsRef.current.infiniteScrollUp === true || optionsRef.current.infiniteScrollDown !== void 0);
1838
+ const isInfiniteScrollEnabled = import_ui_grid4.FEATURE_INFINITE_SCROLL && (optionsRef.current.infiniteScrollRowsFromEnd !== void 0 || optionsRef.current.infiniteScrollUp === true || optionsRef.current.infiniteScrollDown !== void 0);
1490
1839
  maybeRequestInfiniteScrollCommand(gridApiRef.current, {
1491
1840
  enabled: isInfiniteScrollEnabled,
1492
1841
  virtualizationEnabled: pipelineRef.current.virtualizationEnabled,
1493
1842
  state: infiniteScrollStateRef.current,
1494
1843
  startIndex,
1495
1844
  visibleRows: pipelineRef.current.visibleRows.length,
1496
- viewportRows: Math.max(1, Math.ceil((optionsRef.current.viewportHeight ?? 560) / (optionsRef.current.rowHeight ?? 44))),
1845
+ viewportRows: computeViewportRows(
1846
+ optionsRef.current.viewportHeight,
1847
+ optionsRef.current.rowHeight
1848
+ ),
1497
1849
  threshold: optionsRef.current.infiniteScrollRowsFromEnd ?? 20,
1498
1850
  setState: (state) => setInfiniteScrollState(state)
1499
1851
  });
@@ -1562,16 +1914,16 @@ function useGridState(options, onRegisterApi) {
1562
1914
  pageSizeOptions: pageSizeOptionsFn,
1563
1915
  isCellEditable,
1564
1916
  shouldEditOnFocus: shouldEditOnFocusFn,
1565
- sortingFeature: import_ui_grid3.FEATURE_SORTING,
1566
- filteringFeature: import_ui_grid3.FEATURE_FILTERING,
1567
- groupingFeature: import_ui_grid3.FEATURE_GROUPING,
1568
- paginationFeature: import_ui_grid3.FEATURE_PAGINATION,
1569
- cellEditFeature: import_ui_grid3.FEATURE_CELL_EDIT,
1570
- expandableFeature: import_ui_grid3.FEATURE_EXPANDABLE,
1571
- treeViewFeature: import_ui_grid3.FEATURE_TREE_VIEW,
1572
- infiniteScrollFeature: import_ui_grid3.FEATURE_INFINITE_SCROLL,
1573
- columnMovingFeature: import_ui_grid3.FEATURE_COLUMN_MOVING,
1574
- csvExportFeature: import_ui_grid3.FEATURE_CSV_EXPORT,
1917
+ sortingFeature: import_ui_grid4.FEATURE_SORTING,
1918
+ filteringFeature: import_ui_grid4.FEATURE_FILTERING,
1919
+ groupingFeature: import_ui_grid4.FEATURE_GROUPING,
1920
+ paginationFeature: import_ui_grid4.FEATURE_PAGINATION,
1921
+ cellEditFeature: import_ui_grid4.FEATURE_CELL_EDIT,
1922
+ expandableFeature: import_ui_grid4.FEATURE_EXPANDABLE,
1923
+ treeViewFeature: import_ui_grid4.FEATURE_TREE_VIEW,
1924
+ infiniteScrollFeature: import_ui_grid4.FEATURE_INFINITE_SCROLL,
1925
+ columnMovingFeature: import_ui_grid4.FEATURE_COLUMN_MOVING,
1926
+ csvExportFeature: import_ui_grid4.FEATURE_CSV_EXPORT,
1575
1927
  isGroupingEnabled: isGroupingEnabledFn,
1576
1928
  isFilteringEnabled: isFilteringEnabledFn,
1577
1929
  toggleSort: toggleSortFn,
@@ -1593,29 +1945,60 @@ function useGridState(options, onRegisterApi) {
1593
1945
  onPageSizeChange: onPageSizeChangeFn,
1594
1946
  runBenchmark: runBenchmarkFn,
1595
1947
  exportCsv: exportCsvFn,
1596
- onViewportScroll: onViewportScrollFn
1948
+ onViewportScroll: onViewportScrollFn,
1949
+ // Pinning
1950
+ isPinned: isPinnedFn,
1951
+ pinnedOffset: pinnedOffsetFn,
1952
+ isPinningEnabled: isPinningEnabledFn,
1953
+ isColumnPinnable: isColumnPinnableFn,
1954
+ togglePin: togglePinFn,
1955
+ pinningFeature: import_ui_grid4.FEATURE_PINNING
1597
1956
  };
1598
1957
  }
1599
1958
 
1600
1959
  // src/useVirtualScroll.ts
1601
1960
  var import_react2 = require("react");
1961
+
1962
+ // src/virtualScrollMath.ts
1963
+ function calculateVirtualWindow(request) {
1964
+ const overscan = request.overscan ?? 3;
1965
+ if (request.itemCount <= 0 || request.itemSize <= 0) {
1966
+ return {
1967
+ visibleRange: { start: 0, end: 0 },
1968
+ totalHeight: Math.max(0, request.itemCount) * Math.max(0, request.itemSize),
1969
+ offsetY: 0
1970
+ };
1971
+ }
1972
+ const rawStart = Math.floor(request.scrollTop / request.itemSize) - overscan;
1973
+ const start = Math.max(0, rawStart);
1974
+ const rawEnd = rawStart + Math.ceil(request.viewportHeight / request.itemSize) + 2 * overscan;
1975
+ const end = Math.min(request.itemCount, rawEnd);
1976
+ return {
1977
+ visibleRange: { start, end },
1978
+ totalHeight: request.itemCount * request.itemSize,
1979
+ offsetY: start * request.itemSize
1980
+ };
1981
+ }
1982
+
1983
+ // src/useVirtualScroll.ts
1602
1984
  function useVirtualScroll(options) {
1603
1985
  const { itemCount, itemSize, viewportHeight, overscan = 3 } = options;
1604
1986
  const [scrollTop, setScrollTop] = (0, import_react2.useState)(0);
1605
1987
  const viewportRef = (0, import_react2.useRef)(null);
1606
- const rawStart = Math.floor(scrollTop / itemSize) - overscan;
1607
- const start = Math.max(0, rawStart);
1608
- const rawEnd = rawStart + Math.ceil(viewportHeight / itemSize) + 2 * overscan;
1609
- const end = Math.min(itemCount, rawEnd);
1610
- const totalHeight = itemCount * itemSize;
1611
- const offsetY = start * itemSize;
1988
+ const virtualWindow = calculateVirtualWindow({
1989
+ itemCount,
1990
+ itemSize,
1991
+ viewportHeight,
1992
+ overscan,
1993
+ scrollTop
1994
+ });
1612
1995
  const onScroll = (0, import_react2.useCallback)((event) => {
1613
1996
  setScrollTop(event.currentTarget.scrollTop);
1614
1997
  }, []);
1615
1998
  return {
1616
- visibleRange: { start, end },
1617
- totalHeight,
1618
- offsetY,
1999
+ visibleRange: virtualWindow.visibleRange,
2000
+ totalHeight: virtualWindow.totalHeight,
2001
+ offsetY: virtualWindow.offsetY,
1619
2002
  onScroll,
1620
2003
  viewportRef,
1621
2004
  scrollTop
@@ -1624,7 +2007,13 @@ function useVirtualScroll(options) {
1624
2007
 
1625
2008
  // src/UiGrid.tsx
1626
2009
  var import_jsx_runtime = require("react/jsx-runtime");
1627
- function UiGrid({ options, onRegisterApi, cellRenderer, expandableRenderer, className }) {
2010
+ function UiGrid({
2011
+ options,
2012
+ onRegisterApi,
2013
+ cellRenderer,
2014
+ expandableRenderer,
2015
+ className
2016
+ }) {
1628
2017
  const state = useGridState(options, onRegisterApi);
1629
2018
  const {
1630
2019
  pipeline,
@@ -1688,7 +2077,16 @@ function UiGrid({ options, onRegisterApi, cellRenderer, expandableRenderer, clas
1688
2077
  " ",
1689
2078
  labels.groupRowsSuffix
1690
2079
  ] }),
1691
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "toggle-icon group-disclosure-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: item.collapsed ? "M10 7l5 5-5 5z" : "M7 10l5 5 5-5z" }) }),
2080
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2081
+ "svg",
2082
+ {
2083
+ className: "toggle-icon group-disclosure-icon",
2084
+ viewBox: "0 0 24 24",
2085
+ "aria-hidden": "true",
2086
+ focusable: false,
2087
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: item.collapsed ? "M10 7l5 5-5 5z" : "M7 10l5 5 5-5z" })
2088
+ }
2089
+ ),
1692
2090
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only ui-grid-sr-only", children: state.groupDisclosureLabel(item) })
1693
2091
  ]
1694
2092
  },
@@ -1710,62 +2108,84 @@ function UiGrid({ options, onRegisterApi, cellRenderer, expandableRenderer, clas
1710
2108
  }
1711
2109
  if (item.kind !== "row") return null;
1712
2110
  const rowItem = item;
1713
- return visibleColumns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1714
- "div",
1715
- {
1716
- className: cellClassName(rowItem, column),
1717
- "data-part": "body-cell",
1718
- role: "gridcell",
1719
- tabIndex: 0,
1720
- "data-row-id": rowItem.row.id,
1721
- "data-col-name": column.name,
1722
- onFocus: () => state.focusCell(rowItem.row, column),
1723
- onClick: () => state.focusCell(rowItem.row, column),
1724
- onDoubleClick: (e) => state.handleCellDoubleClick(rowItem.row, column, e),
1725
- onKeyDown: (e) => state.handleCellKeyDown(rowItem.row, column, e),
1726
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cell-shell", style: { paddingInlineStart: state.cellIndent(rowItem.row, column) }, children: [
1727
- treeViewFeature && state.showTreeToggle(rowItem.row, column) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1728
- "button",
1729
- {
1730
- type: "button",
1731
- className: "row-toggle row-toggle-tree",
1732
- "data-part": "tree-toggle",
1733
- "aria-label": state.treeToggleLabel(rowItem.row),
1734
- "aria-expanded": state.isTreeRowExpanded(rowItem.row),
1735
- onClick: (e) => state.toggleTreeRow(rowItem.row, e),
1736
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "toggle-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: state.isTreeRowExpanded(rowItem.row) ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z" }) })
1737
- }
1738
- ),
1739
- expandableFeature && state.showExpandToggle(rowItem.row, column) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1740
- "button",
1741
- {
1742
- type: "button",
1743
- className: "row-toggle row-toggle-expand",
1744
- "data-part": "expand-toggle",
1745
- "aria-label": state.expandToggleLabel(rowItem.row),
1746
- "aria-expanded": rowItem.row.expanded,
1747
- onClick: (e) => state.toggleRowExpansion(rowItem.row, e),
1748
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "toggle-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: rowItem.row.expanded ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z" }) })
1749
- }
1750
- ),
1751
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cell-value", children: cellEditFeature && state.isEditingCell(rowItem.row, column) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1752
- "input",
2111
+ return visibleColumns.map((column) => {
2112
+ const pinned = state.isPinned(column);
2113
+ const pinOffset = pinned ? state.pinnedOffset(column) : null;
2114
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2115
+ "div",
2116
+ {
2117
+ className: `${cellClassName(rowItem, column)}${pinned ? " is-pinned" : ""}`,
2118
+ "data-part": "body-cell",
2119
+ role: "gridcell",
2120
+ tabIndex: 0,
2121
+ "data-row-id": rowItem.row.id,
2122
+ "data-col-name": column.name,
2123
+ onFocus: () => state.focusCell(rowItem.row, column),
2124
+ onClick: () => state.focusCell(rowItem.row, column),
2125
+ onDoubleClick: (e) => state.handleCellDoubleClick(rowItem.row, column, e),
2126
+ onKeyDown: (e) => state.handleCellKeyDown(rowItem.row, column, e),
2127
+ style: {
2128
+ position: pinned ? "sticky" : void 0,
2129
+ left: pinOffset?.side === "left" ? pinOffset.offset : void 0,
2130
+ right: pinOffset?.side === "right" ? pinOffset.offset : void 0,
2131
+ zIndex: pinned ? 2 : void 0
2132
+ },
2133
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2134
+ "div",
1753
2135
  {
1754
- className: "cell-editor",
1755
- "data-row-id": rowItem.row.id,
1756
- "data-col-name": column.name,
1757
- "aria-label": state.headerLabel(column),
1758
- type: state.editorInputType(column),
1759
- defaultValue: editingValue,
1760
- onChange: (e) => state.updateEditingValue(e.target.value),
1761
- onKeyDown: (e) => state.handleEditorKeyDown(e),
1762
- onBlur: (e) => state.handleEditorBlur(e)
2136
+ className: "cell-shell",
2137
+ style: { paddingInlineStart: state.cellIndent(rowItem.row, column) },
2138
+ children: [
2139
+ treeViewFeature && state.showTreeToggle(rowItem.row, column) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2140
+ "button",
2141
+ {
2142
+ type: "button",
2143
+ className: "row-toggle row-toggle-tree",
2144
+ "data-part": "tree-toggle",
2145
+ "aria-label": state.treeToggleLabel(rowItem.row),
2146
+ "aria-expanded": state.isTreeRowExpanded(rowItem.row),
2147
+ onClick: (e) => state.toggleTreeRow(rowItem.row, e),
2148
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "toggle-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2149
+ "path",
2150
+ {
2151
+ d: state.isTreeRowExpanded(rowItem.row) ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z"
2152
+ }
2153
+ ) })
2154
+ }
2155
+ ),
2156
+ expandableFeature && state.showExpandToggle(rowItem.row, column) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2157
+ "button",
2158
+ {
2159
+ type: "button",
2160
+ className: "row-toggle row-toggle-expand",
2161
+ "data-part": "expand-toggle",
2162
+ "aria-label": state.expandToggleLabel(rowItem.row),
2163
+ "aria-expanded": rowItem.row.expanded,
2164
+ onClick: (e) => state.toggleRowExpansion(rowItem.row, e),
2165
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "toggle-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: rowItem.row.expanded ? "M7 10l5 5 5-5z" : "M10 7l5 5-5 5z" }) })
2166
+ }
2167
+ ),
2168
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cell-value", children: cellEditFeature && state.isEditingCell(rowItem.row, column) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2169
+ "input",
2170
+ {
2171
+ className: "cell-editor",
2172
+ "data-row-id": rowItem.row.id,
2173
+ "data-col-name": column.name,
2174
+ "aria-label": state.headerLabel(column),
2175
+ type: state.editorInputType(column),
2176
+ defaultValue: editingValue,
2177
+ onChange: (e) => state.updateEditingValue(e.target.value),
2178
+ onKeyDown: (e) => state.handleEditorKeyDown(e),
2179
+ onBlur: (e) => state.handleEditorBlur(e)
2180
+ }
2181
+ ) : cellRenderer ? cellRenderer(state.cellContext(rowItem.row, column)) ?? state.displayValue(rowItem.row, column) : state.displayValue(rowItem.row, column) })
2182
+ ]
1763
2183
  }
1764
- ) : cellRenderer ? cellRenderer(state.cellContext(rowItem.row, column)) ?? state.displayValue(rowItem.row, column) : state.displayValue(rowItem.row, column) })
1765
- ] })
1766
- },
1767
- `${rowItem.row.id}-${column.name}`
1768
- ));
2184
+ )
2185
+ },
2186
+ `${rowItem.row.id}-${column.name}`
2187
+ );
2188
+ });
1769
2189
  }
1770
2190
  function cellClassName(item, column) {
1771
2191
  const classes = ["body-cell", "ui-grid-cell"];
@@ -1795,226 +2215,365 @@ function UiGrid({ options, onRegisterApi, cellRenderer, expandableRenderer, clas
1795
2215
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "deck", children: "Familiar `gridOptions` and `onRegisterApi`, built with React hooks, virtualization, grouping, sorting, filtering, and column ordering." })
1796
2216
  ] }),
1797
2217
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hero-actions", children: [
1798
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "action action-secondary", "data-part": "action benchmark-action", onClick: () => state.runBenchmark(), children: "Benchmark" }),
1799
- csvExportFeature && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "action action-secondary", "data-part": "action export-action", onClick: () => state.exportCsv(), children: "Export CSV" }),
2218
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2219
+ "button",
2220
+ {
2221
+ type: "button",
2222
+ className: "action action-secondary",
2223
+ "data-part": "action benchmark-action",
2224
+ onClick: () => state.runBenchmark(),
2225
+ children: "Benchmark"
2226
+ }
2227
+ ),
2228
+ csvExportFeature && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2229
+ "button",
2230
+ {
2231
+ type: "button",
2232
+ className: "action action-secondary",
2233
+ "data-part": "action export-action",
2234
+ onClick: () => state.exportCsv(),
2235
+ children: "Export CSV"
2236
+ }
2237
+ ),
1800
2238
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stats-card", "data-part": "stats-card", children: [
1801
2239
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: visibleRowCount }),
1802
2240
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: labels.statsVisibleRows })
1803
2241
  ] })
1804
2242
  ] })
1805
2243
  ] }),
1806
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "metrics-strip", "data-part": "metrics", "aria-label": "Grid performance metrics", children: [
1807
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-part": "metric-card", children: [
1808
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("strong", { children: [
1809
- pipelineMs.toFixed(2),
1810
- " ms"
1811
- ] }),
1812
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "pipeline" })
1813
- ] }),
1814
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-part": "metric-card", children: [
1815
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: virtualizationEnabled ? "On" : "Off" }),
1816
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "virtualization" })
1817
- ] }),
1818
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-part": "metric-card", children: [
1819
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: state.groupByColumns.length }),
1820
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "group columns" })
1821
- ] }),
1822
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-part": "metric-card", children: [
1823
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: benchmarkResult?.averageMs?.toFixed(2) || "\u2014" }),
1824
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "benchmark avg" })
1825
- ] })
1826
- ] }),
1827
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "grid-frame ui-grid", "data-part": "grid-frame", role: "grid", "aria-label": options.title ?? "Data grid", children: [
1828
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid-toolbar", "data-part": "grid-toolbar", children: [
1829
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1830
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: visibleRowCount }),
1831
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
1832
- labels.toolbarOf,
1833
- " ",
1834
- totalRows,
1835
- " ",
1836
- labels.toolbarRows
2244
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2245
+ "section",
2246
+ {
2247
+ className: "metrics-strip",
2248
+ "data-part": "metrics",
2249
+ "aria-label": "Grid performance metrics",
2250
+ children: [
2251
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-part": "metric-card", children: [
2252
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("strong", { children: [
2253
+ pipelineMs.toFixed(2),
2254
+ " ms"
2255
+ ] }),
2256
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "pipeline" })
2257
+ ] }),
2258
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-part": "metric-card", children: [
2259
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: virtualizationEnabled ? "On" : "Off" }),
2260
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "virtualization" })
2261
+ ] }),
2262
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-part": "metric-card", children: [
2263
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: state.groupByColumns.length }),
2264
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "group columns" })
2265
+ ] }),
2266
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-part": "metric-card", children: [
2267
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: benchmarkResult?.averageMs?.toFixed(2) || "\u2014" }),
2268
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "benchmark avg" })
1837
2269
  ] })
1838
- ] }),
1839
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "`gridOptions` compatibility layer: sorting, filtering, grouping, column moving, templating, and virtualized rendering." })
1840
- ] }),
1841
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid-table ui-grid-contents-wrapper", "data-part": "grid-table", children: [
1842
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1843
- "div",
1844
- {
1845
- className: "header-grid ui-grid-header ui-grid-header-canvas",
1846
- "data-part": "header",
1847
- role: "row",
1848
- style: { gridTemplateColumns },
1849
- children: visibleColumns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2270
+ ]
2271
+ }
2272
+ ),
2273
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2274
+ "section",
2275
+ {
2276
+ className: "grid-frame ui-grid",
2277
+ "data-part": "grid-frame",
2278
+ role: "grid",
2279
+ "aria-label": options.title ?? "Data grid",
2280
+ children: [
2281
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid-toolbar", "data-part": "grid-toolbar", children: [
2282
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
2283
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: visibleRowCount }),
2284
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
2285
+ labels.toolbarOf,
2286
+ " ",
2287
+ totalRows,
2288
+ " ",
2289
+ labels.toolbarRows
2290
+ ] })
2291
+ ] }),
2292
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "`gridOptions` compatibility layer: sorting, filtering, grouping, column moving, templating, and virtualized rendering." })
2293
+ ] }),
2294
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid-table ui-grid-contents-wrapper", "data-part": "grid-table", children: [
2295
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2296
+ "div",
2297
+ {
2298
+ className: "header-grid ui-grid-header ui-grid-header-canvas",
2299
+ "data-part": "header",
2300
+ role: "row",
2301
+ style: { gridTemplateColumns },
2302
+ children: visibleColumns.map((column) => {
2303
+ const pinned = state.isPinned(column);
2304
+ const pinOffset = pinned ? state.pinnedOffset(column) : null;
2305
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2306
+ "div",
2307
+ {
2308
+ className: `header-cell ui-grid-header-cell${sortingFeature && state.sortDirection(column) !== "none" ? " is-active" : ""}${pinned ? " is-pinned" : ""}`,
2309
+ "data-part": "header-cell",
2310
+ role: "columnheader",
2311
+ "aria-sort": sortingFeature ? state.sortAriaSort(column) : void 0,
2312
+ style: {
2313
+ position: pinned ? "sticky" : void 0,
2314
+ left: pinOffset?.side === "left" ? pinOffset.offset : void 0,
2315
+ right: pinOffset?.side === "right" ? pinOffset.offset : void 0,
2316
+ zIndex: pinned ? 2 : void 0
2317
+ },
2318
+ children: [
2319
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "header-label", children: state.headerLabel(column) }),
2320
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "header-actions", children: [
2321
+ sortingFeature && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2322
+ "button",
2323
+ {
2324
+ type: "button",
2325
+ className: `header-action${!state.isColumnSortable(column) ? " header-action-disabled" : ""}`,
2326
+ disabled: !state.isColumnSortable(column),
2327
+ "aria-label": state.sortButtonLabel(column),
2328
+ title: state.sortButtonLabel(column),
2329
+ onClick: () => state.toggleSort(column),
2330
+ children: [
2331
+ renderSortIcon(column),
2332
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only ui-grid-sr-only", children: state.sortButtonLabel(column) })
2333
+ ]
2334
+ }
2335
+ ),
2336
+ groupingFeature && state.isGroupingEnabled() && column.enableGrouping !== false && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2337
+ "button",
2338
+ {
2339
+ type: "button",
2340
+ className: `chip-action${state.isGrouped(column) ? " chip-action-active" : ""}`,
2341
+ "data-part": "group-toggle",
2342
+ "aria-label": state.groupingButtonLabel(column),
2343
+ title: state.groupingButtonLabel(column),
2344
+ onClick: (e) => state.toggleGrouping(column, e),
2345
+ children: [
2346
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 6h8v4H4V6Zm0 8h8v4H4v-4Zm10-8h6v4h-6V6Zm0 8h6v4h-6v-4Z" }) }),
2347
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only ui-grid-sr-only", children: state.groupingButtonLabel(column) })
2348
+ ]
2349
+ }
2350
+ ),
2351
+ state.pinningFeature && state.isPinningEnabled() && state.isColumnPinnable(column) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2352
+ "button",
2353
+ {
2354
+ type: "button",
2355
+ className: `chip-action${pinned ? " chip-action-active" : ""}`,
2356
+ "data-part": "pin-toggle",
2357
+ "aria-label": pinned ? labels.unpin : labels.pinLeft,
2358
+ title: pinned ? labels.unpin : labels.pinLeft,
2359
+ onClick: () => state.togglePin(column),
2360
+ children: [
2361
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M16 12V4h1V2H7v2h1v8l-2 2v2h5v6l1 1 1-1v-6h5v-2l-2-2z" }) }),
2362
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only ui-grid-sr-only", children: pinned ? labels.unpin : labels.pinLeft })
2363
+ ]
2364
+ }
2365
+ )
2366
+ ] })
2367
+ ]
2368
+ },
2369
+ column.name
2370
+ );
2371
+ })
2372
+ }
2373
+ ),
2374
+ filteringFeature && state.isFilteringEnabled() && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2375
+ "div",
2376
+ {
2377
+ className: "filter-grid ui-grid-header",
2378
+ "data-part": "filters",
2379
+ style: { gridTemplateColumns },
2380
+ children: visibleColumns.map((column) => {
2381
+ const pinned = state.isPinned(column);
2382
+ const pinOffset = pinned ? state.pinnedOffset(column) : null;
2383
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2384
+ "label",
2385
+ {
2386
+ className: `filter-cell ui-grid-filter-container${pinned ? " is-pinned" : ""}`,
2387
+ "data-part": "filter-cell",
2388
+ style: {
2389
+ position: pinned ? "sticky" : void 0,
2390
+ left: pinOffset?.side === "left" ? pinOffset.offset : void 0,
2391
+ right: pinOffset?.side === "right" ? pinOffset.offset : void 0,
2392
+ zIndex: pinned ? 2 : void 0
2393
+ },
2394
+ children: [
2395
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "sr-only ui-grid-sr-only", children: [
2396
+ labels.filterColumn,
2397
+ " ",
2398
+ state.headerLabel(column)
2399
+ ] }),
2400
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2401
+ "input",
2402
+ {
2403
+ className: "ui-grid-filter-input",
2404
+ type: "text",
2405
+ defaultValue: state.filterValue(column.name),
2406
+ placeholder: state.filterPlaceholder(column),
2407
+ disabled: state.isFilterInputDisabled(column),
2408
+ onChange: (e) => state.updateFilter(column.name, e.target.value)
2409
+ }
2410
+ )
2411
+ ]
2412
+ },
2413
+ column.name
2414
+ );
2415
+ })
2416
+ }
2417
+ ),
2418
+ displayItems.length > 0 ? virtualizationEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1850
2419
  "div",
1851
2420
  {
1852
- className: `header-cell ui-grid-header-cell${sortingFeature && state.sortDirection(column) !== "none" ? " is-active" : ""}`,
1853
- "data-part": "header-cell",
1854
- role: "columnheader",
1855
- "aria-sort": sortingFeature ? state.sortAriaSort(column) : void 0,
2421
+ className: "grid-viewport ui-grid-viewport",
2422
+ "data-part": "viewport",
2423
+ ref: virtualScroll.viewportRef,
2424
+ style: { height: viewportHeightPx, overflow: "auto", position: "relative" },
2425
+ onScroll: onViewportScroll,
2426
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: `${virtualScroll.totalHeight}px`, position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2427
+ "div",
2428
+ {
2429
+ className: "body-grid ui-grid-canvas",
2430
+ "data-part": "body",
2431
+ role: "rowgroup",
2432
+ style: {
2433
+ gridTemplateColumns,
2434
+ position: "absolute",
2435
+ top: 0,
2436
+ left: 0,
2437
+ right: 0,
2438
+ transform: `translateY(${virtualScroll.offsetY}px)`
2439
+ },
2440
+ children: itemsToRender.map(renderDisplayItem)
2441
+ }
2442
+ ) })
2443
+ }
2444
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2445
+ "div",
2446
+ {
2447
+ className: "body-grid ui-grid-canvas",
2448
+ "data-part": "body",
2449
+ role: "rowgroup",
2450
+ style: { gridTemplateColumns },
2451
+ children: displayItems.map(renderDisplayItem)
2452
+ }
2453
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "empty-state ui-grid-no-row-overlay", "data-part": "empty-state", children: [
2454
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: options.emptyMessage ?? labels.emptyHeading }),
2455
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: labels.emptyDescription })
2456
+ ] }),
2457
+ paginationFeature && state.showPaginationControls() && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2458
+ "footer",
2459
+ {
2460
+ className: "pagination-bar ui-grid-pagination",
2461
+ "data-part": "pagination",
2462
+ role: "navigation",
2463
+ "aria-label": labels.paginationPage,
1856
2464
  children: [
1857
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "header-label", children: state.headerLabel(column) }),
1858
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "header-actions", children: [
1859
- sortingFeature && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2465
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: state.paginationSummary() }),
2466
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "pagination-controls", children: [
2467
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1860
2468
  "button",
1861
2469
  {
1862
2470
  type: "button",
1863
- className: `header-action${!state.isColumnSortable(column) ? " header-action-disabled" : ""}`,
1864
- disabled: !state.isColumnSortable(column),
1865
- "aria-label": state.sortButtonLabel(column),
1866
- title: state.sortButtonLabel(column),
1867
- onClick: () => state.toggleSort(column),
2471
+ className: "action action-secondary pagination-button",
2472
+ "aria-label": labels.paginationPrevious,
2473
+ disabled: paginationCurrentPage <= 1,
2474
+ onClick: () => state.previousPage(),
1868
2475
  children: [
1869
- renderSortIcon(column),
1870
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only ui-grid-sr-only", children: state.sortButtonLabel(column) })
2476
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2477
+ "svg",
2478
+ {
2479
+ className: "pagination-icon",
2480
+ viewBox: "0 0 24 24",
2481
+ "aria-hidden": "true",
2482
+ focusable: false,
2483
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" })
2484
+ }
2485
+ ),
2486
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: labels.paginationPrevious })
1871
2487
  ]
1872
2488
  }
1873
2489
  ),
1874
- groupingFeature && state.isGroupingEnabled() && column.enableGrouping !== false && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2490
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
2491
+ labels.paginationPage,
2492
+ " ",
2493
+ paginationCurrentPage,
2494
+ " ",
2495
+ labels.paginationOf,
2496
+ " ",
2497
+ paginationTotalPages
2498
+ ] }),
2499
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1875
2500
  "button",
1876
2501
  {
1877
2502
  type: "button",
1878
- className: `chip-action${state.isGrouped(column) ? " chip-action-active" : ""}`,
1879
- "data-part": "group-toggle",
1880
- "aria-label": state.groupingButtonLabel(column),
1881
- title: state.groupingButtonLabel(column),
1882
- onClick: (e) => state.toggleGrouping(column, e),
2503
+ className: "action action-secondary pagination-button",
2504
+ "aria-label": labels.paginationNext,
2505
+ disabled: paginationCurrentPage >= paginationTotalPages,
2506
+ onClick: () => state.nextPage(),
1883
2507
  children: [
1884
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 6h8v4H4V6Zm0 8h8v4H4v-4Zm10-8h6v4h-6V6Zm0 8h6v4h-6v-4Z" }) }),
1885
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only ui-grid-sr-only", children: state.groupingButtonLabel(column) })
2508
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2509
+ "svg",
2510
+ {
2511
+ className: "pagination-icon",
2512
+ viewBox: "0 0 24 24",
2513
+ "aria-hidden": "true",
2514
+ focusable: false,
2515
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z" })
2516
+ }
2517
+ ),
2518
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: labels.paginationNext })
1886
2519
  ]
1887
2520
  }
1888
- )
2521
+ ),
2522
+ state.pageSizeOptions().length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "pagination-size", children: [
2523
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: labels.paginationRows }),
2524
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2525
+ "select",
2526
+ {
2527
+ "aria-label": labels.paginationRows,
2528
+ value: paginationSelectedPageSize,
2529
+ onChange: (e) => state.onPageSizeChange(e.target.value),
2530
+ children: state.pageSizeOptions().map((size) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: size, children: size }, size))
2531
+ }
2532
+ )
2533
+ ] })
1889
2534
  ] })
1890
2535
  ]
1891
- },
1892
- column.name
1893
- ))
1894
- }
1895
- ),
1896
- filteringFeature && state.isFilteringEnabled() && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "filter-grid ui-grid-header", "data-part": "filters", style: { gridTemplateColumns }, children: visibleColumns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter-cell ui-grid-filter-container", "data-part": "filter-cell", children: [
1897
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "sr-only ui-grid-sr-only", children: [
1898
- labels.filterColumn,
1899
- " ",
1900
- state.headerLabel(column)
1901
- ] }),
1902
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1903
- "input",
1904
- {
1905
- className: "ui-grid-filter-input",
1906
- type: "text",
1907
- defaultValue: state.filterValue(column.name),
1908
- placeholder: state.filterPlaceholder(column),
1909
- disabled: state.isFilterInputDisabled(column),
1910
- onChange: (e) => state.updateFilter(column.name, e.target.value)
1911
- }
1912
- )
1913
- ] }, column.name)) }),
1914
- displayItems.length > 0 ? virtualizationEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1915
- "div",
1916
- {
1917
- className: "grid-viewport ui-grid-viewport",
1918
- "data-part": "viewport",
1919
- ref: virtualScroll.viewportRef,
1920
- style: { height: viewportHeightPx, overflow: "auto", position: "relative" },
1921
- onScroll: onViewportScroll,
1922
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: `${virtualScroll.totalHeight}px`, position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1923
- "div",
1924
- {
1925
- className: "body-grid ui-grid-canvas",
1926
- "data-part": "body",
1927
- role: "rowgroup",
1928
- style: {
1929
- gridTemplateColumns,
1930
- position: "absolute",
1931
- top: 0,
1932
- left: 0,
1933
- right: 0,
1934
- transform: `translateY(${virtualScroll.offsetY}px)`
1935
- },
1936
- children: itemsToRender.map(renderDisplayItem)
1937
- }
1938
- ) })
1939
- }
1940
- ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1941
- "div",
1942
- {
1943
- className: "body-grid ui-grid-canvas",
1944
- "data-part": "body",
1945
- role: "rowgroup",
1946
- style: { gridTemplateColumns },
1947
- children: displayItems.map(renderDisplayItem)
1948
- }
1949
- ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "empty-state ui-grid-no-row-overlay", "data-part": "empty-state", children: [
1950
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: options.emptyMessage ?? labels.emptyHeading }),
1951
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: labels.emptyDescription })
1952
- ] }),
1953
- paginationFeature && state.showPaginationControls() && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("footer", { className: "pagination-bar ui-grid-pagination", "data-part": "pagination", role: "navigation", "aria-label": labels.paginationPage, children: [
1954
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: state.paginationSummary() }),
1955
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "pagination-controls", children: [
1956
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1957
- "button",
1958
- {
1959
- type: "button",
1960
- className: "action action-secondary pagination-button",
1961
- "aria-label": labels.paginationPrevious,
1962
- disabled: paginationCurrentPage <= 1,
1963
- onClick: () => state.previousPage(),
1964
- children: [
1965
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "pagination-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" }) }),
1966
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: labels.paginationPrevious })
1967
- ]
1968
2536
  }
1969
- ),
1970
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
1971
- labels.paginationPage,
1972
- " ",
1973
- paginationCurrentPage,
1974
- " ",
1975
- labels.paginationOf,
1976
- " ",
1977
- paginationTotalPages
1978
- ] }),
1979
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1980
- "button",
1981
- {
1982
- type: "button",
1983
- className: "action action-secondary pagination-button",
1984
- "aria-label": labels.paginationNext,
1985
- disabled: paginationCurrentPage >= paginationTotalPages,
1986
- onClick: () => state.nextPage(),
1987
- children: [
1988
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "pagination-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z" }) }),
1989
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: labels.paginationNext })
1990
- ]
1991
- }
1992
- ),
1993
- state.pageSizeOptions().length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "pagination-size", children: [
1994
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: labels.paginationRows }),
1995
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1996
- "select",
1997
- {
1998
- "aria-label": labels.paginationRows,
1999
- value: paginationSelectedPageSize,
2000
- onChange: (e) => state.onPageSizeChange(e.target.value),
2001
- children: state.pageSizeOptions().map((size) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: size, children: size }, size))
2002
- }
2003
- )
2004
- ] })
2537
+ )
2005
2538
  ] })
2006
- ] })
2007
- ] })
2008
- ] })
2539
+ ]
2540
+ }
2541
+ )
2009
2542
  ] }) });
2010
2543
  }
2011
2544
 
2545
+ // src/rustWasmGridEngine.ts
2546
+ var import_ui_grid8 = require("@ornery/ui-grid");
2547
+ var uiGridWasmModulePath = "../../../dist/ui-grid-wasm/ui_grid_wasm.js";
2548
+ function registerReactUiGridWasmEngineFromModule(module2) {
2549
+ (0, import_ui_grid8.registerRustWasmGridEngine)({
2550
+ buildPipeline(context) {
2551
+ return module2.build_pipeline_js(context);
2552
+ }
2553
+ });
2554
+ }
2555
+ async function enableReactUiGridWasmEngine() {
2556
+ const module2 = await import(
2557
+ /* @vite-ignore */
2558
+ uiGridWasmModulePath
2559
+ );
2560
+ registerReactUiGridWasmEngineFromModule(module2);
2561
+ }
2562
+
2012
2563
  // src/index.ts
2013
- var import_ui_grid7 = require("@ornery/ui-grid");
2564
+ var import_ui_grid9 = require("@ornery/ui-grid");
2014
2565
  // Annotate the CommonJS export names for ESM import in node:
2015
2566
  0 && (module.exports = {
2016
2567
  DEFAULT_GRID_LABELS,
2017
2568
  UiGrid,
2569
+ buildGridTemplateColumns,
2570
+ computeViewportHeightPx,
2571
+ computeViewportRows,
2572
+ enableReactUiGridWasmEngine,
2573
+ formatPaginationSummary,
2574
+ orderVisibleColumns,
2575
+ registerReactUiGridWasmEngineFromModule,
2576
+ resolveBenchmarkIterations,
2018
2577
  useGridState,
2019
2578
  useVirtualScroll
2020
2579
  });