@extend-ai/react-xlsx 0.10.1 → 0.10.2

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.cjs CHANGED
@@ -17376,13 +17376,16 @@ function rangesEqual(left, right) {
17376
17376
  function isPrintableKey(event) {
17377
17377
  return event.key.length === 1 && !event.altKey && !event.ctrlKey && !event.metaKey;
17378
17378
  }
17379
- function isInteractiveFocusTarget(target, container) {
17379
+ function getInteractiveFocusTarget(target) {
17380
17380
  if (!(target instanceof Element)) {
17381
- return false;
17381
+ return null;
17382
17382
  }
17383
- const interactiveElement = target.closest(
17383
+ return target.closest(
17384
17384
  "a[href], button, input, select, textarea, [contenteditable=''], [contenteditable='true'], [role='button'], [role='menu'], [role='menuitem'], [role='textbox'], [tabindex]:not([tabindex='-1'])"
17385
17385
  );
17386
+ }
17387
+ function isInteractiveFocusTarget(target, container) {
17388
+ const interactiveElement = getInteractiveFocusTarget(target);
17386
17389
  return Boolean(interactiveElement && interactiveElement !== container && container.contains(interactiveElement));
17387
17390
  }
17388
17391
  function buildPrefixSums(values) {
@@ -21088,8 +21091,10 @@ function GridRow({
21088
21091
  onCellClick,
21089
21092
  onCellDoubleClick,
21090
21093
  onCellPointerDown,
21094
+ onEditingBlur,
21091
21095
  onEditingCancel,
21092
21096
  onEditingCommit,
21097
+ onEditingNavigate,
21093
21098
  onEditingValueChange,
21094
21099
  onRowHeaderRef,
21095
21100
  onRowPointerDown,
@@ -21375,7 +21380,7 @@ function GridRow({
21375
21380
  "input",
21376
21381
  {
21377
21382
  autoFocus: true,
21378
- onBlur: onEditingCommit,
21383
+ onBlur: onEditingBlur,
21379
21384
  onChange: (event) => onEditingValueChange(event.target.value),
21380
21385
  onKeyDown: (event) => {
21381
21386
  event.stopPropagation();
@@ -21387,6 +21392,11 @@ function GridRow({
21387
21392
  if (event.key === "Escape") {
21388
21393
  event.preventDefault();
21389
21394
  onEditingCancel();
21395
+ return;
21396
+ }
21397
+ if (event.key === "ArrowDown" || event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp") {
21398
+ event.preventDefault();
21399
+ onEditingNavigate(event.key, event.currentTarget.value);
21390
21400
  }
21391
21401
  },
21392
21402
  style: {
@@ -21462,7 +21472,7 @@ function GridRow({
21462
21472
  ] });
21463
21473
  }
21464
21474
  var MemoGridRow = React4.memo(GridRow, (prev, next) => {
21465
- if (prev.actualRow !== next.actualRow || prev.rowHeight !== next.rowHeight || prev.headerLabelLiveScale !== next.headerLabelLiveScale || prev.palette !== next.palette || prev.readOnly !== next.readOnly || prev.visibleCols !== next.visibleCols || prev.leadingSpacerWidth !== next.leadingSpacerWidth || prev.rowHeaderWidth !== next.rowHeaderWidth || prev.stickyLeftByCol !== next.stickyLeftByCol || prev.stickyTop !== next.stickyTop || prev.trailingSpacerWidth !== next.trailingSpacerWidth || prev.zoomFactor !== next.zoomFactor || prev.getCellData !== next.getCellData || prev.onCellClick !== next.onCellClick || prev.onCellDoubleClick !== next.onCellDoubleClick || prev.onCellPointerDown !== next.onCellPointerDown || prev.onEditingCancel !== next.onEditingCancel || prev.onEditingCommit !== next.onEditingCommit || prev.onEditingValueChange !== next.onEditingValueChange || prev.onRowHeaderRef !== next.onRowHeaderRef || prev.onRowPointerDown !== next.onRowPointerDown || prev.onRowResizePointerDown !== next.onRowResizePointerDown || prev.renderCellAdornment !== next.renderCellAdornment) {
21475
+ if (prev.actualRow !== next.actualRow || prev.rowHeight !== next.rowHeight || prev.headerLabelLiveScale !== next.headerLabelLiveScale || prev.palette !== next.palette || prev.readOnly !== next.readOnly || prev.visibleCols !== next.visibleCols || prev.leadingSpacerWidth !== next.leadingSpacerWidth || prev.rowHeaderWidth !== next.rowHeaderWidth || prev.stickyLeftByCol !== next.stickyLeftByCol || prev.stickyTop !== next.stickyTop || prev.trailingSpacerWidth !== next.trailingSpacerWidth || prev.zoomFactor !== next.zoomFactor || prev.getCellData !== next.getCellData || prev.onCellClick !== next.onCellClick || prev.onCellDoubleClick !== next.onCellDoubleClick || prev.onCellPointerDown !== next.onCellPointerDown || prev.onEditingBlur !== next.onEditingBlur || prev.onEditingCancel !== next.onEditingCancel || prev.onEditingCommit !== next.onEditingCommit || prev.onEditingNavigate !== next.onEditingNavigate || prev.onEditingValueChange !== next.onEditingValueChange || prev.onRowHeaderRef !== next.onRowHeaderRef || prev.onRowPointerDown !== next.onRowPointerDown || prev.onRowResizePointerDown !== next.onRowResizePointerDown || prev.renderCellAdornment !== next.renderCellAdornment) {
21466
21476
  return false;
21467
21477
  }
21468
21478
  const prevEditingCol = prev.editingCell?.row === prev.actualRow ? prev.editingCell.col : -1;
@@ -21563,6 +21573,9 @@ function XlsxGrid({
21563
21573
  const scrollRef = React4.useRef(null);
21564
21574
  const wrapperRef = React4.useRef(null);
21565
21575
  const tableRef = React4.useRef(null);
21576
+ const gridKeyboardActiveRef = React4.useRef(false);
21577
+ const gridKeyboardHandlerRef = React4.useRef(null);
21578
+ const axisSelectionRef = React4.useRef(null);
21566
21579
  const scrollBodyCanvasRef = React4.useRef(null);
21567
21580
  const topBodyCanvasRef = React4.useRef(null);
21568
21581
  const leftBodyCanvasRef = React4.useRef(null);
@@ -23204,9 +23217,50 @@ function XlsxGrid({
23204
23217
  selectionPreviewRangeRef.current = null;
23205
23218
  setInteractionMode("idle");
23206
23219
  }, [activeSheetIndex, clearGlobalCursor, revision]);
23207
- const focusGrid = React4.useCallback((options) => {
23208
- scrollRef.current?.focus(options);
23220
+ const focusGridElement = React4.useCallback((element, options) => {
23221
+ if (document.activeElement !== element) {
23222
+ element.focus(options ?? { preventScroll: true });
23223
+ }
23209
23224
  }, []);
23225
+ const focusGrid = React4.useCallback((options) => {
23226
+ const scroller = scrollRef.current;
23227
+ if (scroller) {
23228
+ gridKeyboardActiveRef.current = true;
23229
+ focusGridElement(scroller, options);
23230
+ }
23231
+ }, [focusGridElement]);
23232
+ React4.useEffect(() => {
23233
+ const handleDocumentPointerDown = (event) => {
23234
+ const scroller = scrollRef.current;
23235
+ if (!scroller || !(event.target instanceof Node) || !scroller.contains(event.target)) {
23236
+ gridKeyboardActiveRef.current = false;
23237
+ return;
23238
+ }
23239
+ if (isInteractiveFocusTarget(event.target, scroller)) {
23240
+ gridKeyboardActiveRef.current = false;
23241
+ return;
23242
+ }
23243
+ gridKeyboardActiveRef.current = true;
23244
+ focusGridElement(scroller);
23245
+ };
23246
+ const handleDocumentKeyDown = (event) => {
23247
+ if (!gridKeyboardActiveRef.current || event.defaultPrevented) {
23248
+ return;
23249
+ }
23250
+ const scroller = scrollRef.current;
23251
+ const interactiveTarget = getInteractiveFocusTarget(event.target);
23252
+ if (!scroller || interactiveTarget && interactiveTarget !== scroller) {
23253
+ return;
23254
+ }
23255
+ gridKeyboardHandlerRef.current?.(event);
23256
+ };
23257
+ document.addEventListener("pointerdown", handleDocumentPointerDown, true);
23258
+ document.addEventListener("keydown", handleDocumentKeyDown);
23259
+ return () => {
23260
+ document.removeEventListener("pointerdown", handleDocumentPointerDown, true);
23261
+ document.removeEventListener("keydown", handleDocumentKeyDown);
23262
+ };
23263
+ }, [focusGridElement]);
23210
23264
  const openHyperlink = React4.useCallback((target, location) => {
23211
23265
  const internalTarget = parseInternalSheetLink(location ?? target);
23212
23266
  if (internalTarget) {
@@ -23245,21 +23299,74 @@ function XlsxGrid({
23245
23299
  return;
23246
23300
  }
23247
23301
  if (readOnly) {
23302
+ editingCellRef.current = null;
23248
23303
  setEditingCell(null);
23249
23304
  setEditingValue("");
23250
23305
  focusGrid();
23251
23306
  return;
23252
23307
  }
23253
23308
  setCellValue(editingCell, editingValue);
23309
+ editingCellRef.current = null;
23254
23310
  setEditingCell(null);
23255
23311
  setEditingValue("");
23256
23312
  focusGrid();
23257
23313
  }, [editingCell, editingValue, focusGrid, readOnly, setCellValue]);
23258
23314
  const cancelEditing = React4.useCallback(() => {
23315
+ editingCellRef.current = null;
23259
23316
  setEditingCell(null);
23260
23317
  setEditingValue("");
23261
23318
  focusGrid();
23262
23319
  }, [focusGrid]);
23320
+ const handleEditingBlur = React4.useCallback(() => {
23321
+ if (!editingCellRef.current) {
23322
+ return;
23323
+ }
23324
+ commitEditing();
23325
+ }, [commitEditing]);
23326
+ const handleEditingNavigate = React4.useCallback((key, value) => {
23327
+ const cell = editingCellRef.current;
23328
+ if (!cell) {
23329
+ return;
23330
+ }
23331
+ const currentRowIndex = rowIndexByActual.get(cell.row);
23332
+ const currentColIndex = colIndexByActual.get(cell.col);
23333
+ if (currentRowIndex === void 0 || currentColIndex === void 0) {
23334
+ if (!readOnlyRef.current) {
23335
+ setCellValue(cell, value);
23336
+ }
23337
+ editingCellRef.current = null;
23338
+ setEditingCell(null);
23339
+ setEditingValue("");
23340
+ focusGrid();
23341
+ return;
23342
+ }
23343
+ let nextRowIndex = currentRowIndex;
23344
+ let nextColIndex = currentColIndex;
23345
+ switch (key) {
23346
+ case "ArrowDown":
23347
+ nextRowIndex += 1;
23348
+ break;
23349
+ case "ArrowLeft":
23350
+ nextColIndex -= 1;
23351
+ break;
23352
+ case "ArrowRight":
23353
+ nextColIndex += 1;
23354
+ break;
23355
+ case "ArrowUp":
23356
+ nextRowIndex -= 1;
23357
+ break;
23358
+ default:
23359
+ return;
23360
+ }
23361
+ if (!readOnlyRef.current) {
23362
+ setCellValue(cell, value);
23363
+ }
23364
+ editingCellRef.current = null;
23365
+ setEditingCell(null);
23366
+ setEditingValue("");
23367
+ moveSelection(nextRowIndex, nextColIndex, false);
23368
+ focusGrid();
23369
+ }, [colIndexByActual, focusGrid, rowIndexByActual, setCellValue, visibleCols, visibleRows]);
23263
23370
  React4.useEffect(() => {
23264
23371
  commitEditingRef.current = commitEditing;
23265
23372
  }, [commitEditing]);
@@ -24232,6 +24339,7 @@ function XlsxGrid({
24232
24339
  overlay.style.visibility = "visible";
24233
24340
  }, [getCellData, resolveOverlayRect, zoomFactor]);
24234
24341
  const commitSelectionRange = React4.useCallback((range) => {
24342
+ gridKeyboardActiveRef.current = true;
24235
24343
  const normalized = normalizeRange2(range);
24236
24344
  if (selectionRef.current && rangesEqual(selectionRef.current, normalized) && isSameCell(activeCellRef.current, normalized.end) && selectedChartIdRef.current === null && selectedImageIdRef.current === null) {
24237
24345
  return;
@@ -24525,6 +24633,23 @@ function XlsxGrid({
24525
24633
  if (nextRange && (dragState?.didDrag || !dragState?.committedOnPointerDown)) {
24526
24634
  selectionPreviewRangeRef.current = nextRange;
24527
24635
  displayedSelectionRef.current = nextRange;
24636
+ if (dragState?.axis === "column") {
24637
+ const normalized = normalizeRange2(nextRange);
24638
+ axisSelectionRef.current = {
24639
+ axis: "column",
24640
+ startCol: normalized.start.col,
24641
+ endCol: normalized.end.col
24642
+ };
24643
+ } else if (dragState?.axis === "row") {
24644
+ const normalized = normalizeRange2(nextRange);
24645
+ axisSelectionRef.current = {
24646
+ axis: "row",
24647
+ startRow: normalized.start.row,
24648
+ endRow: normalized.end.row
24649
+ };
24650
+ } else {
24651
+ axisSelectionRef.current = null;
24652
+ }
24528
24653
  commitSelectionRange(nextRange);
24529
24654
  } else if (!nextRange) {
24530
24655
  selectionPreviewRangeRef.current = null;
@@ -24643,6 +24768,7 @@ function XlsxGrid({
24643
24768
  }
24644
24769
  event.preventDefault();
24645
24770
  focusGrid();
24771
+ axisSelectionRef.current = null;
24646
24772
  const targetCell = event.currentTarget.colSpan > 1 || event.currentTarget.rowSpan > 1 ? resolvePointerCellFromGeometry(event.clientX, event.clientY) ?? cell : cell;
24647
24773
  const currentSelection = selectionRef.current;
24648
24774
  const anchor = event.shiftKey && currentSelection ? currentSelection.start : targetCell;
@@ -24718,6 +24844,7 @@ function XlsxGrid({
24718
24844
  event.clientX,
24719
24845
  event.clientY
24720
24846
  );
24847
+ axisSelectionRef.current = { axis: "row", startRow: anchorRow, endRow: actualRow };
24721
24848
  commitSelectionRange(initialRange);
24722
24849
  }, [commitSelectionRange, firstVisibleCol, focusGrid, lastVisibleCol, resolveRowPointerOrigin]);
24723
24850
  const handleColumnPointerDown = React4.useCallback((event, actualCol) => {
@@ -24749,6 +24876,7 @@ function XlsxGrid({
24749
24876
  event.clientX,
24750
24877
  event.clientY
24751
24878
  );
24879
+ axisSelectionRef.current = { axis: "column", startCol: anchorCol, endCol: actualCol };
24752
24880
  commitSelectionRange(initialRange);
24753
24881
  }, [commitSelectionRange, firstVisibleRow, focusGrid, lastVisibleRow, resolveColumnPointerOrigin]);
24754
24882
  const handleRowResizePointerDown = React4.useCallback((event, actualRow, rowHeight) => {
@@ -25005,6 +25133,7 @@ function XlsxGrid({
25005
25133
  }
25006
25134
  event.preventDefault();
25007
25135
  focusGrid();
25136
+ axisSelectionRef.current = null;
25008
25137
  const currentSelection = selectionRef.current;
25009
25138
  const anchor = event.shiftKey && currentSelection ? currentSelection.start : cell;
25010
25139
  const initialRange = normalizeRange2({ start: anchor, end: cell });
@@ -25114,6 +25243,7 @@ function XlsxGrid({
25114
25243
  event.clientX,
25115
25244
  event.clientY
25116
25245
  );
25246
+ axisSelectionRef.current = { axis: "column", startCol: anchorCol, endCol: actualCol };
25117
25247
  commitSelectionRange(initialRange);
25118
25248
  }, [
25119
25249
  colIndexByActual,
@@ -25172,6 +25302,7 @@ function XlsxGrid({
25172
25302
  event.clientX,
25173
25303
  event.clientY
25174
25304
  );
25305
+ axisSelectionRef.current = { axis: "row", startRow: anchorRow, endRow: actualRow };
25175
25306
  commitSelectionRange(initialRange);
25176
25307
  }, [
25177
25308
  colPrefixSums,
@@ -27678,6 +27809,11 @@ function XlsxGrid({
27678
27809
  if (nextRow === void 0 || nextCol === void 0) {
27679
27810
  return;
27680
27811
  }
27812
+ const nextRange = { start: { row: nextRow, col: nextCol }, end: { row: nextRow, col: nextCol } };
27813
+ axisSelectionRef.current = null;
27814
+ selectionPreviewRangeRef.current = null;
27815
+ displayedSelectionRef.current = nextRange;
27816
+ applyPreviewOverlay(nextRange);
27681
27817
  selectCell({ row: nextRow, col: nextCol }, extend ? { extend: true } : void 0);
27682
27818
  ensureCellVisible(clampedRowIndex, clampedColIndex);
27683
27819
  }
@@ -27701,6 +27837,214 @@ function XlsxGrid({
27701
27837
  const targetOffset = direction > 0 ? currentOffset + viewportWidth : currentOffset - viewportWidth;
27702
27838
  return Math.max(0, Math.min(findIndexForOffsetPrefix(colPrefixSums, targetOffset), visibleCols.length - 1));
27703
27839
  }
27840
+ function resolveColumnSelectionNavigation(eventKey) {
27841
+ const axisSelection = axisSelectionRef.current;
27842
+ if (axisSelection?.axis !== "column" || firstVisibleRow === void 0) {
27843
+ return null;
27844
+ }
27845
+ const startCol = Math.min(axisSelection.startCol, axisSelection.endCol);
27846
+ const endCol = Math.max(axisSelection.startCol, axisSelection.endCol);
27847
+ const targetCol = eventKey === "ArrowLeft" ? startCol - 1 : eventKey === "ArrowRight" ? endCol + 1 : null;
27848
+ if (targetCol === null) {
27849
+ return null;
27850
+ }
27851
+ const rowIndex = rowIndexByActual.get(firstVisibleRow);
27852
+ const colIndex = colIndexByActual.get(targetCol);
27853
+ if (rowIndex === void 0 || colIndex === void 0) {
27854
+ return null;
27855
+ }
27856
+ return { colIndex, rowIndex };
27857
+ }
27858
+ function resolveRowSelectionNavigation(eventKey) {
27859
+ const axisSelection = axisSelectionRef.current;
27860
+ if (axisSelection?.axis !== "row" || firstVisibleCol === void 0) {
27861
+ return null;
27862
+ }
27863
+ const startRow = Math.min(axisSelection.startRow, axisSelection.endRow);
27864
+ const endRow = Math.max(axisSelection.startRow, axisSelection.endRow);
27865
+ const targetRow = eventKey === "ArrowUp" ? startRow - 1 : eventKey === "ArrowDown" ? endRow + 1 : null;
27866
+ if (targetRow === null) {
27867
+ return null;
27868
+ }
27869
+ const rowIndex = rowIndexByActual.get(targetRow);
27870
+ const colIndex = colIndexByActual.get(firstVisibleCol);
27871
+ if (rowIndex === void 0 || colIndex === void 0) {
27872
+ return null;
27873
+ }
27874
+ return { colIndex, rowIndex };
27875
+ }
27876
+ function handleGridKeyDown(event) {
27877
+ if (editingCell) {
27878
+ return;
27879
+ }
27880
+ if (!readOnly && (event.metaKey || event.ctrlKey) && !event.altKey) {
27881
+ const normalizedKey = event.key.toLowerCase();
27882
+ if (normalizedKey === "z" && event.shiftKey) {
27883
+ event.preventDefault();
27884
+ redo();
27885
+ return;
27886
+ }
27887
+ if (normalizedKey === "z") {
27888
+ event.preventDefault();
27889
+ undo();
27890
+ return;
27891
+ }
27892
+ if (normalizedKey === "y") {
27893
+ event.preventDefault();
27894
+ redo();
27895
+ return;
27896
+ }
27897
+ }
27898
+ const currentCell = resolveCurrentCell();
27899
+ if (!currentCell) {
27900
+ return;
27901
+ }
27902
+ const currentRowIndex = rowIndexByActual.get(currentCell.row) ?? 0;
27903
+ const currentColIndex = colIndexByActual.get(currentCell.col) ?? 0;
27904
+ const isCommandNavigation = event.ctrlKey || event.metaKey;
27905
+ if (!readOnly && isPrintableKey(event)) {
27906
+ event.preventDefault();
27907
+ startEditing(currentCell, event.key);
27908
+ return;
27909
+ }
27910
+ switch (event.key) {
27911
+ case "ArrowDown":
27912
+ event.preventDefault();
27913
+ if (!event.shiftKey && !isCommandNavigation) {
27914
+ const target = resolveRowSelectionNavigation(event.key);
27915
+ if (target) {
27916
+ moveSelection(target.rowIndex, target.colIndex, false);
27917
+ break;
27918
+ }
27919
+ }
27920
+ moveSelection(
27921
+ isCommandNavigation ? rowIndexByActual.get(resolveLastUsedVisibleIndex(visibleRows, activeSheet?.maxUsedRow ?? -1)) ?? visibleRows.length - 1 : currentRowIndex + 1,
27922
+ currentColIndex,
27923
+ event.shiftKey
27924
+ );
27925
+ break;
27926
+ case "ArrowUp":
27927
+ event.preventDefault();
27928
+ if (!event.shiftKey && !isCommandNavigation) {
27929
+ const target = resolveRowSelectionNavigation(event.key);
27930
+ if (target) {
27931
+ moveSelection(target.rowIndex, target.colIndex, false);
27932
+ break;
27933
+ }
27934
+ }
27935
+ moveSelection(
27936
+ isCommandNavigation ? rowIndexByActual.get(resolveFirstUsedVisibleIndex(visibleRows, activeSheet?.minUsedRow ?? -1)) ?? 0 : currentRowIndex - 1,
27937
+ currentColIndex,
27938
+ event.shiftKey
27939
+ );
27940
+ break;
27941
+ case "ArrowLeft":
27942
+ event.preventDefault();
27943
+ if (!event.shiftKey && !isCommandNavigation) {
27944
+ const target = resolveColumnSelectionNavigation(event.key);
27945
+ if (target) {
27946
+ moveSelection(target.rowIndex, target.colIndex, false);
27947
+ break;
27948
+ }
27949
+ }
27950
+ moveSelection(
27951
+ currentRowIndex,
27952
+ isCommandNavigation ? colIndexByActual.get(resolveFirstUsedVisibleIndex(visibleCols, activeSheet?.minUsedCol ?? -1)) ?? 0 : currentColIndex - 1,
27953
+ event.shiftKey
27954
+ );
27955
+ break;
27956
+ case "ArrowRight":
27957
+ event.preventDefault();
27958
+ if (!event.shiftKey && !isCommandNavigation) {
27959
+ const target = resolveColumnSelectionNavigation(event.key);
27960
+ if (target) {
27961
+ moveSelection(target.rowIndex, target.colIndex, false);
27962
+ break;
27963
+ }
27964
+ }
27965
+ moveSelection(
27966
+ currentRowIndex,
27967
+ isCommandNavigation ? colIndexByActual.get(resolveLastUsedVisibleIndex(visibleCols, activeSheet?.maxUsedCol ?? -1)) ?? visibleCols.length - 1 : currentColIndex + 1,
27968
+ event.shiftKey
27969
+ );
27970
+ break;
27971
+ case "Home":
27972
+ event.preventDefault();
27973
+ moveSelection(
27974
+ isCommandNavigation ? rowIndexByActual.get(resolveFirstUsedVisibleIndex(visibleRows, activeSheet?.minUsedRow ?? -1)) ?? 0 : currentRowIndex,
27975
+ colIndexByActual.get(resolveFirstUsedVisibleIndex(visibleCols, activeSheet?.minUsedCol ?? -1)) ?? 0,
27976
+ event.shiftKey
27977
+ );
27978
+ break;
27979
+ case "End":
27980
+ event.preventDefault();
27981
+ moveSelection(
27982
+ isCommandNavigation ? rowIndexByActual.get(resolveLastUsedVisibleIndex(visibleRows, activeSheet?.maxUsedRow ?? -1)) ?? visibleRows.length - 1 : currentRowIndex,
27983
+ colIndexByActual.get(resolveLastUsedVisibleIndex(visibleCols, activeSheet?.maxUsedCol ?? -1)) ?? visibleCols.length - 1,
27984
+ event.shiftKey
27985
+ );
27986
+ break;
27987
+ case "PageDown":
27988
+ event.preventDefault();
27989
+ if (event.altKey) {
27990
+ moveSelection(currentRowIndex, resolvePageColIndex(currentColIndex, 1), event.shiftKey);
27991
+ break;
27992
+ }
27993
+ moveSelection(resolvePageRowIndex(currentRowIndex, 1), currentColIndex, event.shiftKey);
27994
+ break;
27995
+ case "PageUp":
27996
+ event.preventDefault();
27997
+ if (event.altKey) {
27998
+ moveSelection(currentRowIndex, resolvePageColIndex(currentColIndex, -1), event.shiftKey);
27999
+ break;
28000
+ }
28001
+ moveSelection(resolvePageRowIndex(currentRowIndex, -1), currentColIndex, event.shiftKey);
28002
+ break;
28003
+ case "Tab":
28004
+ event.preventDefault();
28005
+ if (event.shiftKey) {
28006
+ moveSelection(
28007
+ currentColIndex > 0 ? currentRowIndex : currentRowIndex - 1,
28008
+ currentColIndex > 0 ? currentColIndex - 1 : visibleCols.length - 1,
28009
+ false
28010
+ );
28011
+ } else {
28012
+ moveSelection(
28013
+ currentColIndex < visibleCols.length - 1 ? currentRowIndex : currentRowIndex + 1,
28014
+ currentColIndex < visibleCols.length - 1 ? currentColIndex + 1 : 0,
28015
+ false
28016
+ );
28017
+ }
28018
+ break;
28019
+ case "Enter":
28020
+ event.preventDefault();
28021
+ if (event.metaKey || event.ctrlKey || event.altKey) {
28022
+ break;
28023
+ }
28024
+ if (event.shiftKey) {
28025
+ moveSelection(currentRowIndex - 1, currentColIndex, false);
28026
+ break;
28027
+ }
28028
+ moveSelection(currentRowIndex + 1, currentColIndex, false);
28029
+ break;
28030
+ case "Backspace":
28031
+ case "Delete":
28032
+ if (!readOnly) {
28033
+ event.preventDefault();
28034
+ clearSelectedCells();
28035
+ }
28036
+ break;
28037
+ case "F2":
28038
+ if (!readOnly) {
28039
+ event.preventDefault();
28040
+ startEditing(currentCell);
28041
+ }
28042
+ break;
28043
+ default:
28044
+ break;
28045
+ }
28046
+ }
28047
+ gridKeyboardHandlerRef.current = handleGridKeyDown;
27704
28048
  const scrollerViewportProps = {
27705
28049
  key: activeTabIndex,
27706
28050
  ref: scrollRef,
@@ -27736,153 +28080,20 @@ function XlsxGrid({
27736
28080
  if (isInteractiveFocusTarget(event.target, event.currentTarget)) {
27737
28081
  return;
27738
28082
  }
27739
- if (document.activeElement !== event.currentTarget) {
27740
- event.currentTarget.focus({ preventScroll: true });
27741
- }
28083
+ gridKeyboardActiveRef.current = true;
28084
+ focusGridElement(event.currentTarget);
27742
28085
  },
27743
- onKeyDown: (event) => {
27744
- if (editingCell) {
27745
- return;
27746
- }
27747
- if (!readOnly && (event.metaKey || event.ctrlKey) && !event.altKey) {
27748
- const normalizedKey = event.key.toLowerCase();
27749
- if (normalizedKey === "z" && event.shiftKey) {
27750
- event.preventDefault();
27751
- redo();
27752
- return;
27753
- }
27754
- if (normalizedKey === "z") {
27755
- event.preventDefault();
27756
- undo();
27757
- return;
27758
- }
27759
- if (normalizedKey === "y") {
27760
- event.preventDefault();
27761
- redo();
27762
- return;
27763
- }
27764
- }
27765
- const currentCell = resolveCurrentCell();
27766
- if (!currentCell) {
27767
- return;
27768
- }
27769
- const currentRowIndex = rowIndexByActual.get(currentCell.row) ?? 0;
27770
- const currentColIndex = colIndexByActual.get(currentCell.col) ?? 0;
27771
- const isCommandNavigation = event.ctrlKey || event.metaKey;
27772
- if (!readOnly && isPrintableKey(event)) {
27773
- event.preventDefault();
27774
- startEditing(currentCell, event.key);
28086
+ onClickCapture: (event) => {
28087
+ if (isInteractiveFocusTarget(event.target, event.currentTarget)) {
27775
28088
  return;
27776
28089
  }
27777
- switch (event.key) {
27778
- case "ArrowDown":
27779
- event.preventDefault();
27780
- moveSelection(
27781
- isCommandNavigation ? rowIndexByActual.get(resolveLastUsedVisibleIndex(visibleRows, activeSheet?.maxUsedRow ?? -1)) ?? visibleRows.length - 1 : currentRowIndex + 1,
27782
- currentColIndex,
27783
- event.shiftKey
27784
- );
27785
- break;
27786
- case "ArrowUp":
27787
- event.preventDefault();
27788
- moveSelection(
27789
- isCommandNavigation ? rowIndexByActual.get(resolveFirstUsedVisibleIndex(visibleRows, activeSheet?.minUsedRow ?? -1)) ?? 0 : currentRowIndex - 1,
27790
- currentColIndex,
27791
- event.shiftKey
27792
- );
27793
- break;
27794
- case "ArrowLeft":
27795
- event.preventDefault();
27796
- moveSelection(
27797
- currentRowIndex,
27798
- isCommandNavigation ? colIndexByActual.get(resolveFirstUsedVisibleIndex(visibleCols, activeSheet?.minUsedCol ?? -1)) ?? 0 : currentColIndex - 1,
27799
- event.shiftKey
27800
- );
27801
- break;
27802
- case "ArrowRight":
27803
- event.preventDefault();
27804
- moveSelection(
27805
- currentRowIndex,
27806
- isCommandNavigation ? colIndexByActual.get(resolveLastUsedVisibleIndex(visibleCols, activeSheet?.maxUsedCol ?? -1)) ?? visibleCols.length - 1 : currentColIndex + 1,
27807
- event.shiftKey
27808
- );
27809
- break;
27810
- case "Home":
27811
- event.preventDefault();
27812
- moveSelection(
27813
- isCommandNavigation ? rowIndexByActual.get(resolveFirstUsedVisibleIndex(visibleRows, activeSheet?.minUsedRow ?? -1)) ?? 0 : currentRowIndex,
27814
- colIndexByActual.get(resolveFirstUsedVisibleIndex(visibleCols, activeSheet?.minUsedCol ?? -1)) ?? 0,
27815
- event.shiftKey
27816
- );
27817
- break;
27818
- case "End":
27819
- event.preventDefault();
27820
- moveSelection(
27821
- isCommandNavigation ? rowIndexByActual.get(resolveLastUsedVisibleIndex(visibleRows, activeSheet?.maxUsedRow ?? -1)) ?? visibleRows.length - 1 : currentRowIndex,
27822
- colIndexByActual.get(resolveLastUsedVisibleIndex(visibleCols, activeSheet?.maxUsedCol ?? -1)) ?? visibleCols.length - 1,
27823
- event.shiftKey
27824
- );
27825
- break;
27826
- case "PageDown":
27827
- event.preventDefault();
27828
- if (event.altKey) {
27829
- moveSelection(currentRowIndex, resolvePageColIndex(currentColIndex, 1), event.shiftKey);
27830
- break;
27831
- }
27832
- moveSelection(resolvePageRowIndex(currentRowIndex, 1), currentColIndex, event.shiftKey);
27833
- break;
27834
- case "PageUp":
27835
- event.preventDefault();
27836
- if (event.altKey) {
27837
- moveSelection(currentRowIndex, resolvePageColIndex(currentColIndex, -1), event.shiftKey);
27838
- break;
27839
- }
27840
- moveSelection(resolvePageRowIndex(currentRowIndex, -1), currentColIndex, event.shiftKey);
27841
- break;
27842
- case "Tab":
27843
- event.preventDefault();
27844
- if (event.shiftKey) {
27845
- moveSelection(
27846
- currentColIndex > 0 ? currentRowIndex : currentRowIndex - 1,
27847
- currentColIndex > 0 ? currentColIndex - 1 : visibleCols.length - 1,
27848
- false
27849
- );
27850
- } else {
27851
- moveSelection(
27852
- currentColIndex < visibleCols.length - 1 ? currentRowIndex : currentRowIndex + 1,
27853
- currentColIndex < visibleCols.length - 1 ? currentColIndex + 1 : 0,
27854
- false
27855
- );
27856
- }
27857
- break;
27858
- case "Enter":
27859
- event.preventDefault();
27860
- if (event.metaKey || event.ctrlKey || event.altKey) {
27861
- break;
27862
- }
27863
- if (event.shiftKey) {
27864
- moveSelection(currentRowIndex - 1, currentColIndex, false);
27865
- break;
27866
- }
27867
- moveSelection(currentRowIndex + 1, currentColIndex, false);
27868
- break;
27869
- case "Backspace":
27870
- case "Delete":
27871
- if (!readOnly) {
27872
- event.preventDefault();
27873
- clearSelectedCells();
27874
- }
27875
- break;
27876
- case "F2":
27877
- if (!readOnly) {
27878
- event.preventDefault();
27879
- startEditing(currentCell);
27880
- }
27881
- break;
27882
- default:
27883
- break;
27884
- }
28090
+ gridKeyboardActiveRef.current = true;
28091
+ focusGridElement(event.currentTarget);
28092
+ },
28093
+ onFocus: () => {
28094
+ gridKeyboardActiveRef.current = true;
27885
28095
  },
28096
+ onKeyDown: handleGridKeyDown,
27886
28097
  onPaste: (event) => {
27887
28098
  if (editingCell || readOnly) {
27888
28099
  return;
@@ -28132,7 +28343,7 @@ function XlsxGrid({
28132
28343
  {
28133
28344
  ref: editingInputRef,
28134
28345
  autoFocus: true,
28135
- onBlur: commitEditing,
28346
+ onBlur: handleEditingBlur,
28136
28347
  onChange: (event) => setEditingValue(event.target.value),
28137
28348
  onKeyDown: (event) => {
28138
28349
  event.stopPropagation();
@@ -28144,6 +28355,11 @@ function XlsxGrid({
28144
28355
  if (event.key === "Escape") {
28145
28356
  event.preventDefault();
28146
28357
  cancelEditing();
28358
+ return;
28359
+ }
28360
+ if (event.key === "ArrowDown" || event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp") {
28361
+ event.preventDefault();
28362
+ handleEditingNavigate(event.key, event.currentTarget.value);
28147
28363
  }
28148
28364
  },
28149
28365
  style: {
@@ -28298,8 +28514,10 @@ function XlsxGrid({
28298
28514
  onCellClick: handleCellClick,
28299
28515
  onCellDoubleClick: handleCellDoubleClick,
28300
28516
  onCellPointerDown: handleCellPointerDown,
28517
+ onEditingBlur: handleEditingBlur,
28301
28518
  onEditingCancel: cancelEditing,
28302
28519
  onEditingCommit: commitEditing,
28520
+ onEditingNavigate: handleEditingNavigate,
28303
28521
  onEditingValueChange: setEditingValue,
28304
28522
  headerLabelLiveScale,
28305
28523
  onRowHeaderRef: setRowHeaderRef,