@alaarab/ogrid-react 2.1.7 → 2.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -74,6 +74,9 @@ function getCellValue(item, col) {
74
74
  if (col.valueGetter) return col.valueGetter(item);
75
75
  return item[col.columnId];
76
76
  }
77
+ function isColumnEditable(col, item) {
78
+ return col.editable === true || typeof col.editable === "function" && col.editable(item);
79
+ }
77
80
  function isColumnGroupDef(c) {
78
81
  return "children" in c && Array.isArray(c.children);
79
82
  }
@@ -735,9 +738,9 @@ function getHeaderFilterConfig(col, input) {
735
738
  function getCellRenderDescriptor(item, col, rowIndex, colIdx, input) {
736
739
  const rowId = input.getRowId(item);
737
740
  const globalColIndex = colIdx + input.colOffset;
738
- const colEditable = col.editable === true || typeof col.editable === "function" && col.editable(item);
739
- const canEditInline = input.editable !== false && !!colEditable && !!input.onCellValueChanged && typeof col.cellEditor !== "function";
740
- const canEditPopup = input.editable !== false && !!colEditable && !!input.onCellValueChanged && typeof col.cellEditor === "function" && col.cellEditorPopup !== false;
741
+ const colEditable = isColumnEditable(col, item);
742
+ const canEditInline = input.editable !== false && colEditable && !!input.onCellValueChanged && typeof col.cellEditor !== "function";
743
+ const canEditPopup = input.editable !== false && colEditable && !!input.onCellValueChanged && typeof col.cellEditor === "function" && col.cellEditorPopup !== false;
741
744
  const canEditAny = canEditInline || canEditPopup;
742
745
  const isEditing = input.editingCell?.rowId === rowId && input.editingCell?.columnId === col.columnId;
743
746
  const isActive = !input.isDragging && input.activeCell?.rowIndex === rowIndex && input.activeCell?.columnIndex === globalColIndex;
@@ -850,6 +853,18 @@ function measureRange(container, range, colOffset) {
850
853
  height: brRect.bottom - tlRect.top
851
854
  };
852
855
  }
856
+ function buildCellIndex(container) {
857
+ const index = /* @__PURE__ */ new Map();
858
+ if (!container) return index;
859
+ const cells = container.querySelectorAll("[data-row-index][data-col-index]");
860
+ for (let i = 0; i < cells.length; i++) {
861
+ const el = cells[i];
862
+ const r = el.getAttribute("data-row-index") ?? "";
863
+ const c = el.getAttribute("data-col-index") ?? "";
864
+ index.set(`${r},${c}`, el);
865
+ }
866
+ return index;
867
+ }
853
868
  function injectGlobalStyles(id, css) {
854
869
  if (typeof document === "undefined") return;
855
870
  if (document.getElementById(id)) return;
@@ -1003,8 +1018,7 @@ function applyCellDeletion(range, items, visibleCols) {
1003
1018
  if (r >= items.length || c >= visibleCols.length) continue;
1004
1019
  const item = items[r];
1005
1020
  const col = visibleCols[c];
1006
- const colEditable = col.editable === true || typeof col.editable === "function" && col.editable(item);
1007
- if (!colEditable) continue;
1021
+ if (!isColumnEditable(col, item)) continue;
1008
1022
  const oldValue = getCellValue(item, col);
1009
1023
  const result = parseValue("", oldValue, item, col);
1010
1024
  if (!result.valid) continue;
@@ -1100,8 +1114,7 @@ function applyPastedValues(parsedRows, anchorRow, anchorCol, items, visibleCols)
1100
1114
  if (targetRow >= items.length || targetCol >= visibleCols.length) continue;
1101
1115
  const item = items[targetRow];
1102
1116
  const col = visibleCols[targetCol];
1103
- const colEditable = col.editable === true || typeof col.editable === "function" && col.editable(item);
1104
- if (!colEditable) continue;
1117
+ if (!isColumnEditable(col, item)) continue;
1105
1118
  const rawValue = cells[c] ?? "";
1106
1119
  const oldValue = getCellValue(item, col);
1107
1120
  const result = parseValue(rawValue, oldValue, item, col);
@@ -1124,8 +1137,7 @@ function applyCutClear(cutRange, items, visibleCols) {
1124
1137
  if (r >= items.length || c >= visibleCols.length) continue;
1125
1138
  const item = items[r];
1126
1139
  const col = visibleCols[c];
1127
- const colEditable = col.editable === true || typeof col.editable === "function" && col.editable(item);
1128
- if (!colEditable) continue;
1140
+ if (!isColumnEditable(col, item)) continue;
1129
1141
  const oldValue = getCellValue(item, col);
1130
1142
  const result = parseValue("", oldValue, item, col);
1131
1143
  if (!result.valid) continue;
@@ -1152,8 +1164,7 @@ function applyFillValues(range, sourceRow, sourceCol, items, visibleCols) {
1152
1164
  if (row >= items.length || col >= visibleCols.length) continue;
1153
1165
  const item = items[row];
1154
1166
  const colDef = visibleCols[col];
1155
- const colEditable = colDef.editable === true || typeof colDef.editable === "function" && colDef.editable(item);
1156
- if (!colEditable) continue;
1167
+ if (!isColumnEditable(colDef, item)) continue;
1157
1168
  const oldValue = getCellValue(item, colDef);
1158
1169
  const result = parseValue(startValue, oldValue, item, colDef);
1159
1170
  if (!result.valid) continue;
@@ -2267,18 +2278,6 @@ function useCellSelection(params) {
2267
2278
  useEffect(() => {
2268
2279
  const markedCells = /* @__PURE__ */ new Set();
2269
2280
  let cellIndex = null;
2270
- const buildCellIndex = () => {
2271
- const wrapper = wrapperRef.current;
2272
- if (!wrapper) return;
2273
- cellIndex = /* @__PURE__ */ new Map();
2274
- const cells = wrapper.querySelectorAll("[data-row-index][data-col-index]");
2275
- for (let i = 0; i < cells.length; i++) {
2276
- const el = cells[i];
2277
- const r = el.getAttribute("data-row-index") ?? "";
2278
- const c = el.getAttribute("data-col-index") ?? "";
2279
- cellIndex.set(`${r},${c}`, el);
2280
- }
2281
- };
2282
2281
  const styleCellInRange = (el, r, c, minR, maxR, minC, maxC, anchor) => {
2283
2282
  if (!el.hasAttribute(DRAG_ATTR)) el.setAttribute(DRAG_ATTR, "");
2284
2283
  const isAnchor = anchor && r === anchor.row && c === anchor.col;
@@ -2318,13 +2317,13 @@ function useCellSelection(params) {
2318
2317
  markedCells.delete(el);
2319
2318
  }
2320
2319
  }
2321
- if (!cellIndex) buildCellIndex();
2320
+ if (!cellIndex) cellIndex = buildCellIndex(wrapperRef.current);
2322
2321
  for (let r = minR; r <= maxR; r++) {
2323
2322
  for (let c = minC; c <= maxC; c++) {
2324
2323
  const key = `${r},${c + colOff}`;
2325
2324
  let el = cellIndex?.get(key);
2326
2325
  if (el && !el.isConnected) {
2327
- buildCellIndex();
2326
+ cellIndex = buildCellIndex(wrapperRef.current);
2328
2327
  el = cellIndex?.get(key);
2329
2328
  }
2330
2329
  if (el) {
@@ -2423,7 +2422,7 @@ function useCellSelection(params) {
2423
2422
  if (!dragMovedRef.current) {
2424
2423
  dragMovedRef.current = true;
2425
2424
  setIsDragging(true);
2426
- buildCellIndex();
2425
+ cellIndex = buildCellIndex(wrapperRef.current);
2427
2426
  }
2428
2427
  lastMousePosRef.current = { cx: e.clientX, cy: e.clientY };
2429
2428
  updateAutoScroll();
@@ -3000,20 +2999,7 @@ function useFillHandle(params) {
3000
2999
  fillDragEndRef.current = { endRow: fillDrag.startRow, endCol: fillDrag.startCol };
3001
3000
  liveFillRangeRef.current = null;
3002
3001
  const markedCells = /* @__PURE__ */ new Set();
3003
- let cellIndex = null;
3004
- const buildCellIndex = () => {
3005
- const wrapper = wrapperRef.current;
3006
- if (!wrapper) return;
3007
- cellIndex = /* @__PURE__ */ new Map();
3008
- const cells = wrapper.querySelectorAll("[data-row-index][data-col-index]");
3009
- for (let i = 0; i < cells.length; i++) {
3010
- const el = cells[i];
3011
- const r = el.getAttribute("data-row-index") ?? "";
3012
- const c = el.getAttribute("data-col-index") ?? "";
3013
- cellIndex.set(`${r},${c}`, el);
3014
- }
3015
- };
3016
- buildCellIndex();
3002
+ let cellIndex = buildCellIndex(wrapperRef.current);
3017
3003
  const applyDragAttrs = (range) => {
3018
3004
  const wrapper = wrapperRef.current;
3019
3005
  if (!wrapper) return;
@@ -3035,8 +3021,8 @@ function useFillHandle(params) {
3035
3021
  const key = `${r},${c + colOff}`;
3036
3022
  let el = cellIndex?.get(key);
3037
3023
  if (el && !el.isConnected) {
3038
- buildCellIndex();
3039
- el = cellIndex?.get(key);
3024
+ cellIndex = buildCellIndex(wrapperRef.current);
3025
+ el = cellIndex.get(key);
3040
3026
  }
3041
3027
  if (el) {
3042
3028
  if (!el.hasAttribute(DRAG_ATTR2)) el.setAttribute(DRAG_ATTR2, "");
@@ -3050,7 +3036,6 @@ function useFillHandle(params) {
3050
3036
  el.removeAttribute(DRAG_ATTR2);
3051
3037
  }
3052
3038
  markedCells.clear();
3053
- cellIndex = null;
3054
3039
  };
3055
3040
  let lastFillMousePos = null;
3056
3041
  const resolveRange = (cx, cy) => {
@@ -3605,7 +3590,9 @@ function useDataGridEditing(params) {
3605
3590
  pendingEditorValue,
3606
3591
  setPendingEditorValue,
3607
3592
  onCellValueChanged,
3608
- setActiveCell
3593
+ setActiveCell,
3594
+ setSelectionRange,
3595
+ colOffset
3609
3596
  } = params;
3610
3597
  const [popoverAnchorEl, setPopoverAnchorEl] = useState(null);
3611
3598
  const visibleColsRef = useLatestRef(params.visibleCols);
@@ -3635,11 +3622,14 @@ function useDataGridEditing(params) {
3635
3622
  setPopoverAnchorEl(null);
3636
3623
  setPendingEditorValue(void 0);
3637
3624
  if (rowIndex < itemsLengthRef.current - 1) {
3638
- setActiveCell({ rowIndex: rowIndex + 1, columnIndex: globalColIndex });
3625
+ const newRow = rowIndex + 1;
3626
+ const localCol = globalColIndex - colOffset;
3627
+ setActiveCell({ rowIndex: newRow, columnIndex: globalColIndex });
3628
+ setSelectionRange({ startRow: newRow, startCol: localCol, endRow: newRow, endCol: localCol });
3639
3629
  }
3640
3630
  },
3641
3631
  // eslint-disable-next-line react-hooks/exhaustive-deps
3642
- [setEditingCell, setPendingEditorValue, setActiveCell, visibleColsRef, itemsLengthRef]
3632
+ [setEditingCell, setPendingEditorValue, setActiveCell, setSelectionRange, colOffset, visibleColsRef, itemsLengthRef]
3643
3633
  );
3644
3634
  const cancelPopoverEdit = useCallback(() => {
3645
3635
  setEditingCell(null);
@@ -3915,6 +3905,7 @@ function useDataGridState(params) {
3915
3905
  });
3916
3906
  const {
3917
3907
  selectionRange,
3908
+ setSelectionRange,
3918
3909
  cutRange,
3919
3910
  copyRange,
3920
3911
  isDragging,
@@ -3928,7 +3919,9 @@ function useDataGridState(params) {
3928
3919
  visibleCols,
3929
3920
  itemsLength: items.length,
3930
3921
  onCellValueChanged,
3931
- setActiveCell
3922
+ setActiveCell,
3923
+ setSelectionRange,
3924
+ colOffset
3932
3925
  });
3933
3926
  const {
3934
3927
  sortBy,
@@ -3939,6 +3932,7 @@ function useDataGridState(params) {
3939
3932
  loadingFilterOptions,
3940
3933
  peopleSearch
3941
3934
  } = props;
3935
+ const hasPeopleSearch = !!peopleSearch;
3942
3936
  const onFilterChangeRef = useLatestRef(onFilterChange);
3943
3937
  const peopleSearchRef = useLatestRef(peopleSearch);
3944
3938
  const stableOnFilterChange = useCallback(
@@ -3958,7 +3952,7 @@ function useDataGridState(params) {
3958
3952
  onFilterChange: stableOnFilterChange,
3959
3953
  filterOptions,
3960
3954
  loadingFilterOptions,
3961
- peopleSearch: peopleSearch ? stablePeopleSearch : void 0
3955
+ peopleSearch: hasPeopleSearch ? stablePeopleSearch : void 0
3962
3956
  }),
3963
3957
  [
3964
3958
  sortBy,
@@ -3968,7 +3962,7 @@ function useDataGridState(params) {
3968
3962
  stableOnFilterChange,
3969
3963
  filterOptions,
3970
3964
  loadingFilterOptions,
3971
- peopleSearch,
3965
+ hasPeopleSearch,
3972
3966
  stablePeopleSearch
3973
3967
  ]
3974
3968
  );
@@ -24,6 +24,13 @@ export interface UseDataGridEditingParams<T> {
24
24
  rowIndex: number;
25
25
  columnIndex: number;
26
26
  } | null) => void;
27
+ setSelectionRange: (range: {
28
+ startRow: number;
29
+ startCol: number;
30
+ endRow: number;
31
+ endCol: number;
32
+ } | null) => void;
33
+ colOffset: number;
27
34
  }
28
35
  export interface UseDataGridEditingResult<T> {
29
36
  editing: DataGridEditingState<T>;
@@ -1,4 +1,4 @@
1
- export { escapeCsvValue, buildCsvHeader, buildCsvRows, exportToCsv, triggerCsvDownload, getCellValue, flattenColumns, buildHeaderRows, getFilterField, mergeFilter, deriveFilterOptionsFromData, getMultiSelectFilterFields, getStatusBarParts, getDataGridStatusBarConfig, getPaginationViewModel, PAGE_SIZE_OPTIONS, MAX_PAGE_BUTTONS, GRID_CONTEXT_MENU_ITEMS, COLUMN_HEADER_MENU_ITEMS, getContextMenuHandlers, getColumnHeaderMenuItems, formatShortcut, parseValue, numberParser, currencyParser, dateParser, emailParser, booleanParser, computeAggregations, processClientSideData, computeNextSortState, measureColumnContentWidth, AUTOSIZE_EXTRA_PX, AUTOSIZE_MAX_PX, findCtrlArrowTarget, computeTabNavigation, rangesEqual, clampSelectionToBounds, computeAutoScrollSpeed, formatCellValueForTsv, formatSelectionAsTsv, parseTsvClipboard, applyPastedValues, applyCutClear, applyFillValues, computeArrowNavigation, applyCellDeletion, applyRangeRowSelection, computeRowSelectionState, UndoRedoStack, } from '@alaarab/ogrid-core';
1
+ export { escapeCsvValue, buildCsvHeader, buildCsvRows, exportToCsv, triggerCsvDownload, getCellValue, flattenColumns, buildHeaderRows, getFilterField, mergeFilter, deriveFilterOptionsFromData, getMultiSelectFilterFields, getStatusBarParts, getDataGridStatusBarConfig, getPaginationViewModel, PAGE_SIZE_OPTIONS, MAX_PAGE_BUTTONS, GRID_CONTEXT_MENU_ITEMS, COLUMN_HEADER_MENU_ITEMS, getContextMenuHandlers, getColumnHeaderMenuItems, formatShortcut, parseValue, numberParser, currencyParser, dateParser, emailParser, booleanParser, computeAggregations, processClientSideData, computeNextSortState, measureColumnContentWidth, AUTOSIZE_EXTRA_PX, AUTOSIZE_MAX_PX, findCtrlArrowTarget, computeTabNavigation, rangesEqual, clampSelectionToBounds, computeAutoScrollSpeed, formatCellValueForTsv, formatSelectionAsTsv, parseTsvClipboard, applyPastedValues, applyCutClear, applyFillValues, computeArrowNavigation, applyCellDeletion, applyRangeRowSelection, computeRowSelectionState, UndoRedoStack, buildCellIndex, } from '@alaarab/ogrid-core';
2
2
  export type { CsvColumn, StatusBarPart, StatusBarPartsInput, GridContextMenuItem, GridContextMenuHandlerProps, PaginationViewModel, ParseValueResult, AggregationResult, IColumnHeaderMenuItem, ColumnHeaderMenuInput, ColumnHeaderMenuHandlers, ArrowNavigationContext, ArrowNavigationResult, } from '@alaarab/ogrid-core';
3
3
  export { getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, getCellInteractionProps, } from './dataGridViewModel';
4
4
  export type { HeaderFilterConfigInput, HeaderFilterConfig, CellRenderDescriptorInput, CellRenderDescriptor, CellRenderMode, CellInteractionHandlers, } from './dataGridViewModel';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid-react",
3
- "version": "2.1.7",
3
+ "version": "2.1.8",
4
4
  "description": "OGrid React – React hooks, headless components, and utilities for OGrid data grids.",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -39,7 +39,7 @@
39
39
  "node": ">=18"
40
40
  },
41
41
  "dependencies": {
42
- "@alaarab/ogrid-core": "2.1.7",
42
+ "@alaarab/ogrid-core": "2.1.8",
43
43
  "@tanstack/react-virtual": "^3.0.0"
44
44
  },
45
45
  "peerDependencies": {