@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.js CHANGED
@@ -17344,13 +17344,16 @@ function rangesEqual(left, right) {
17344
17344
  function isPrintableKey(event) {
17345
17345
  return event.key.length === 1 && !event.altKey && !event.ctrlKey && !event.metaKey;
17346
17346
  }
17347
- function isInteractiveFocusTarget(target, container) {
17347
+ function getInteractiveFocusTarget(target) {
17348
17348
  if (!(target instanceof Element)) {
17349
- return false;
17349
+ return null;
17350
17350
  }
17351
- const interactiveElement = target.closest(
17351
+ return target.closest(
17352
17352
  "a[href], button, input, select, textarea, [contenteditable=''], [contenteditable='true'], [role='button'], [role='menu'], [role='menuitem'], [role='textbox'], [tabindex]:not([tabindex='-1'])"
17353
17353
  );
17354
+ }
17355
+ function isInteractiveFocusTarget(target, container) {
17356
+ const interactiveElement = getInteractiveFocusTarget(target);
17354
17357
  return Boolean(interactiveElement && interactiveElement !== container && container.contains(interactiveElement));
17355
17358
  }
17356
17359
  function buildPrefixSums(values) {
@@ -21056,8 +21059,10 @@ function GridRow({
21056
21059
  onCellClick,
21057
21060
  onCellDoubleClick,
21058
21061
  onCellPointerDown,
21062
+ onEditingBlur,
21059
21063
  onEditingCancel,
21060
21064
  onEditingCommit,
21065
+ onEditingNavigate,
21061
21066
  onEditingValueChange,
21062
21067
  onRowHeaderRef,
21063
21068
  onRowPointerDown,
@@ -21343,7 +21348,7 @@ function GridRow({
21343
21348
  "input",
21344
21349
  {
21345
21350
  autoFocus: true,
21346
- onBlur: onEditingCommit,
21351
+ onBlur: onEditingBlur,
21347
21352
  onChange: (event) => onEditingValueChange(event.target.value),
21348
21353
  onKeyDown: (event) => {
21349
21354
  event.stopPropagation();
@@ -21355,6 +21360,11 @@ function GridRow({
21355
21360
  if (event.key === "Escape") {
21356
21361
  event.preventDefault();
21357
21362
  onEditingCancel();
21363
+ return;
21364
+ }
21365
+ if (event.key === "ArrowDown" || event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp") {
21366
+ event.preventDefault();
21367
+ onEditingNavigate(event.key, event.currentTarget.value);
21358
21368
  }
21359
21369
  },
21360
21370
  style: {
@@ -21430,7 +21440,7 @@ function GridRow({
21430
21440
  ] });
21431
21441
  }
21432
21442
  var MemoGridRow = React4.memo(GridRow, (prev, next) => {
21433
- 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) {
21443
+ 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) {
21434
21444
  return false;
21435
21445
  }
21436
21446
  const prevEditingCol = prev.editingCell?.row === prev.actualRow ? prev.editingCell.col : -1;
@@ -21531,6 +21541,9 @@ function XlsxGrid({
21531
21541
  const scrollRef = React4.useRef(null);
21532
21542
  const wrapperRef = React4.useRef(null);
21533
21543
  const tableRef = React4.useRef(null);
21544
+ const gridKeyboardActiveRef = React4.useRef(false);
21545
+ const gridKeyboardHandlerRef = React4.useRef(null);
21546
+ const axisSelectionRef = React4.useRef(null);
21534
21547
  const scrollBodyCanvasRef = React4.useRef(null);
21535
21548
  const topBodyCanvasRef = React4.useRef(null);
21536
21549
  const leftBodyCanvasRef = React4.useRef(null);
@@ -23172,9 +23185,50 @@ function XlsxGrid({
23172
23185
  selectionPreviewRangeRef.current = null;
23173
23186
  setInteractionMode("idle");
23174
23187
  }, [activeSheetIndex, clearGlobalCursor, revision]);
23175
- const focusGrid = React4.useCallback((options) => {
23176
- scrollRef.current?.focus(options);
23188
+ const focusGridElement = React4.useCallback((element, options) => {
23189
+ if (document.activeElement !== element) {
23190
+ element.focus(options ?? { preventScroll: true });
23191
+ }
23177
23192
  }, []);
23193
+ const focusGrid = React4.useCallback((options) => {
23194
+ const scroller = scrollRef.current;
23195
+ if (scroller) {
23196
+ gridKeyboardActiveRef.current = true;
23197
+ focusGridElement(scroller, options);
23198
+ }
23199
+ }, [focusGridElement]);
23200
+ React4.useEffect(() => {
23201
+ const handleDocumentPointerDown = (event) => {
23202
+ const scroller = scrollRef.current;
23203
+ if (!scroller || !(event.target instanceof Node) || !scroller.contains(event.target)) {
23204
+ gridKeyboardActiveRef.current = false;
23205
+ return;
23206
+ }
23207
+ if (isInteractiveFocusTarget(event.target, scroller)) {
23208
+ gridKeyboardActiveRef.current = false;
23209
+ return;
23210
+ }
23211
+ gridKeyboardActiveRef.current = true;
23212
+ focusGridElement(scroller);
23213
+ };
23214
+ const handleDocumentKeyDown = (event) => {
23215
+ if (!gridKeyboardActiveRef.current || event.defaultPrevented) {
23216
+ return;
23217
+ }
23218
+ const scroller = scrollRef.current;
23219
+ const interactiveTarget = getInteractiveFocusTarget(event.target);
23220
+ if (!scroller || interactiveTarget && interactiveTarget !== scroller) {
23221
+ return;
23222
+ }
23223
+ gridKeyboardHandlerRef.current?.(event);
23224
+ };
23225
+ document.addEventListener("pointerdown", handleDocumentPointerDown, true);
23226
+ document.addEventListener("keydown", handleDocumentKeyDown);
23227
+ return () => {
23228
+ document.removeEventListener("pointerdown", handleDocumentPointerDown, true);
23229
+ document.removeEventListener("keydown", handleDocumentKeyDown);
23230
+ };
23231
+ }, [focusGridElement]);
23178
23232
  const openHyperlink = React4.useCallback((target, location) => {
23179
23233
  const internalTarget = parseInternalSheetLink(location ?? target);
23180
23234
  if (internalTarget) {
@@ -23213,21 +23267,74 @@ function XlsxGrid({
23213
23267
  return;
23214
23268
  }
23215
23269
  if (readOnly) {
23270
+ editingCellRef.current = null;
23216
23271
  setEditingCell(null);
23217
23272
  setEditingValue("");
23218
23273
  focusGrid();
23219
23274
  return;
23220
23275
  }
23221
23276
  setCellValue(editingCell, editingValue);
23277
+ editingCellRef.current = null;
23222
23278
  setEditingCell(null);
23223
23279
  setEditingValue("");
23224
23280
  focusGrid();
23225
23281
  }, [editingCell, editingValue, focusGrid, readOnly, setCellValue]);
23226
23282
  const cancelEditing = React4.useCallback(() => {
23283
+ editingCellRef.current = null;
23227
23284
  setEditingCell(null);
23228
23285
  setEditingValue("");
23229
23286
  focusGrid();
23230
23287
  }, [focusGrid]);
23288
+ const handleEditingBlur = React4.useCallback(() => {
23289
+ if (!editingCellRef.current) {
23290
+ return;
23291
+ }
23292
+ commitEditing();
23293
+ }, [commitEditing]);
23294
+ const handleEditingNavigate = React4.useCallback((key, value) => {
23295
+ const cell = editingCellRef.current;
23296
+ if (!cell) {
23297
+ return;
23298
+ }
23299
+ const currentRowIndex = rowIndexByActual.get(cell.row);
23300
+ const currentColIndex = colIndexByActual.get(cell.col);
23301
+ if (currentRowIndex === void 0 || currentColIndex === void 0) {
23302
+ if (!readOnlyRef.current) {
23303
+ setCellValue(cell, value);
23304
+ }
23305
+ editingCellRef.current = null;
23306
+ setEditingCell(null);
23307
+ setEditingValue("");
23308
+ focusGrid();
23309
+ return;
23310
+ }
23311
+ let nextRowIndex = currentRowIndex;
23312
+ let nextColIndex = currentColIndex;
23313
+ switch (key) {
23314
+ case "ArrowDown":
23315
+ nextRowIndex += 1;
23316
+ break;
23317
+ case "ArrowLeft":
23318
+ nextColIndex -= 1;
23319
+ break;
23320
+ case "ArrowRight":
23321
+ nextColIndex += 1;
23322
+ break;
23323
+ case "ArrowUp":
23324
+ nextRowIndex -= 1;
23325
+ break;
23326
+ default:
23327
+ return;
23328
+ }
23329
+ if (!readOnlyRef.current) {
23330
+ setCellValue(cell, value);
23331
+ }
23332
+ editingCellRef.current = null;
23333
+ setEditingCell(null);
23334
+ setEditingValue("");
23335
+ moveSelection(nextRowIndex, nextColIndex, false);
23336
+ focusGrid();
23337
+ }, [colIndexByActual, focusGrid, rowIndexByActual, setCellValue, visibleCols, visibleRows]);
23231
23338
  React4.useEffect(() => {
23232
23339
  commitEditingRef.current = commitEditing;
23233
23340
  }, [commitEditing]);
@@ -24200,6 +24307,7 @@ function XlsxGrid({
24200
24307
  overlay.style.visibility = "visible";
24201
24308
  }, [getCellData, resolveOverlayRect, zoomFactor]);
24202
24309
  const commitSelectionRange = React4.useCallback((range) => {
24310
+ gridKeyboardActiveRef.current = true;
24203
24311
  const normalized = normalizeRange2(range);
24204
24312
  if (selectionRef.current && rangesEqual(selectionRef.current, normalized) && isSameCell(activeCellRef.current, normalized.end) && selectedChartIdRef.current === null && selectedImageIdRef.current === null) {
24205
24313
  return;
@@ -24493,6 +24601,23 @@ function XlsxGrid({
24493
24601
  if (nextRange && (dragState?.didDrag || !dragState?.committedOnPointerDown)) {
24494
24602
  selectionPreviewRangeRef.current = nextRange;
24495
24603
  displayedSelectionRef.current = nextRange;
24604
+ if (dragState?.axis === "column") {
24605
+ const normalized = normalizeRange2(nextRange);
24606
+ axisSelectionRef.current = {
24607
+ axis: "column",
24608
+ startCol: normalized.start.col,
24609
+ endCol: normalized.end.col
24610
+ };
24611
+ } else if (dragState?.axis === "row") {
24612
+ const normalized = normalizeRange2(nextRange);
24613
+ axisSelectionRef.current = {
24614
+ axis: "row",
24615
+ startRow: normalized.start.row,
24616
+ endRow: normalized.end.row
24617
+ };
24618
+ } else {
24619
+ axisSelectionRef.current = null;
24620
+ }
24496
24621
  commitSelectionRange(nextRange);
24497
24622
  } else if (!nextRange) {
24498
24623
  selectionPreviewRangeRef.current = null;
@@ -24611,6 +24736,7 @@ function XlsxGrid({
24611
24736
  }
24612
24737
  event.preventDefault();
24613
24738
  focusGrid();
24739
+ axisSelectionRef.current = null;
24614
24740
  const targetCell = event.currentTarget.colSpan > 1 || event.currentTarget.rowSpan > 1 ? resolvePointerCellFromGeometry(event.clientX, event.clientY) ?? cell : cell;
24615
24741
  const currentSelection = selectionRef.current;
24616
24742
  const anchor = event.shiftKey && currentSelection ? currentSelection.start : targetCell;
@@ -24686,6 +24812,7 @@ function XlsxGrid({
24686
24812
  event.clientX,
24687
24813
  event.clientY
24688
24814
  );
24815
+ axisSelectionRef.current = { axis: "row", startRow: anchorRow, endRow: actualRow };
24689
24816
  commitSelectionRange(initialRange);
24690
24817
  }, [commitSelectionRange, firstVisibleCol, focusGrid, lastVisibleCol, resolveRowPointerOrigin]);
24691
24818
  const handleColumnPointerDown = React4.useCallback((event, actualCol) => {
@@ -24717,6 +24844,7 @@ function XlsxGrid({
24717
24844
  event.clientX,
24718
24845
  event.clientY
24719
24846
  );
24847
+ axisSelectionRef.current = { axis: "column", startCol: anchorCol, endCol: actualCol };
24720
24848
  commitSelectionRange(initialRange);
24721
24849
  }, [commitSelectionRange, firstVisibleRow, focusGrid, lastVisibleRow, resolveColumnPointerOrigin]);
24722
24850
  const handleRowResizePointerDown = React4.useCallback((event, actualRow, rowHeight) => {
@@ -24973,6 +25101,7 @@ function XlsxGrid({
24973
25101
  }
24974
25102
  event.preventDefault();
24975
25103
  focusGrid();
25104
+ axisSelectionRef.current = null;
24976
25105
  const currentSelection = selectionRef.current;
24977
25106
  const anchor = event.shiftKey && currentSelection ? currentSelection.start : cell;
24978
25107
  const initialRange = normalizeRange2({ start: anchor, end: cell });
@@ -25082,6 +25211,7 @@ function XlsxGrid({
25082
25211
  event.clientX,
25083
25212
  event.clientY
25084
25213
  );
25214
+ axisSelectionRef.current = { axis: "column", startCol: anchorCol, endCol: actualCol };
25085
25215
  commitSelectionRange(initialRange);
25086
25216
  }, [
25087
25217
  colIndexByActual,
@@ -25140,6 +25270,7 @@ function XlsxGrid({
25140
25270
  event.clientX,
25141
25271
  event.clientY
25142
25272
  );
25273
+ axisSelectionRef.current = { axis: "row", startRow: anchorRow, endRow: actualRow };
25143
25274
  commitSelectionRange(initialRange);
25144
25275
  }, [
25145
25276
  colPrefixSums,
@@ -27646,6 +27777,11 @@ function XlsxGrid({
27646
27777
  if (nextRow === void 0 || nextCol === void 0) {
27647
27778
  return;
27648
27779
  }
27780
+ const nextRange = { start: { row: nextRow, col: nextCol }, end: { row: nextRow, col: nextCol } };
27781
+ axisSelectionRef.current = null;
27782
+ selectionPreviewRangeRef.current = null;
27783
+ displayedSelectionRef.current = nextRange;
27784
+ applyPreviewOverlay(nextRange);
27649
27785
  selectCell({ row: nextRow, col: nextCol }, extend ? { extend: true } : void 0);
27650
27786
  ensureCellVisible(clampedRowIndex, clampedColIndex);
27651
27787
  }
@@ -27669,6 +27805,214 @@ function XlsxGrid({
27669
27805
  const targetOffset = direction > 0 ? currentOffset + viewportWidth : currentOffset - viewportWidth;
27670
27806
  return Math.max(0, Math.min(findIndexForOffsetPrefix(colPrefixSums, targetOffset), visibleCols.length - 1));
27671
27807
  }
27808
+ function resolveColumnSelectionNavigation(eventKey) {
27809
+ const axisSelection = axisSelectionRef.current;
27810
+ if (axisSelection?.axis !== "column" || firstVisibleRow === void 0) {
27811
+ return null;
27812
+ }
27813
+ const startCol = Math.min(axisSelection.startCol, axisSelection.endCol);
27814
+ const endCol = Math.max(axisSelection.startCol, axisSelection.endCol);
27815
+ const targetCol = eventKey === "ArrowLeft" ? startCol - 1 : eventKey === "ArrowRight" ? endCol + 1 : null;
27816
+ if (targetCol === null) {
27817
+ return null;
27818
+ }
27819
+ const rowIndex = rowIndexByActual.get(firstVisibleRow);
27820
+ const colIndex = colIndexByActual.get(targetCol);
27821
+ if (rowIndex === void 0 || colIndex === void 0) {
27822
+ return null;
27823
+ }
27824
+ return { colIndex, rowIndex };
27825
+ }
27826
+ function resolveRowSelectionNavigation(eventKey) {
27827
+ const axisSelection = axisSelectionRef.current;
27828
+ if (axisSelection?.axis !== "row" || firstVisibleCol === void 0) {
27829
+ return null;
27830
+ }
27831
+ const startRow = Math.min(axisSelection.startRow, axisSelection.endRow);
27832
+ const endRow = Math.max(axisSelection.startRow, axisSelection.endRow);
27833
+ const targetRow = eventKey === "ArrowUp" ? startRow - 1 : eventKey === "ArrowDown" ? endRow + 1 : null;
27834
+ if (targetRow === null) {
27835
+ return null;
27836
+ }
27837
+ const rowIndex = rowIndexByActual.get(targetRow);
27838
+ const colIndex = colIndexByActual.get(firstVisibleCol);
27839
+ if (rowIndex === void 0 || colIndex === void 0) {
27840
+ return null;
27841
+ }
27842
+ return { colIndex, rowIndex };
27843
+ }
27844
+ function handleGridKeyDown(event) {
27845
+ if (editingCell) {
27846
+ return;
27847
+ }
27848
+ if (!readOnly && (event.metaKey || event.ctrlKey) && !event.altKey) {
27849
+ const normalizedKey = event.key.toLowerCase();
27850
+ if (normalizedKey === "z" && event.shiftKey) {
27851
+ event.preventDefault();
27852
+ redo();
27853
+ return;
27854
+ }
27855
+ if (normalizedKey === "z") {
27856
+ event.preventDefault();
27857
+ undo();
27858
+ return;
27859
+ }
27860
+ if (normalizedKey === "y") {
27861
+ event.preventDefault();
27862
+ redo();
27863
+ return;
27864
+ }
27865
+ }
27866
+ const currentCell = resolveCurrentCell();
27867
+ if (!currentCell) {
27868
+ return;
27869
+ }
27870
+ const currentRowIndex = rowIndexByActual.get(currentCell.row) ?? 0;
27871
+ const currentColIndex = colIndexByActual.get(currentCell.col) ?? 0;
27872
+ const isCommandNavigation = event.ctrlKey || event.metaKey;
27873
+ if (!readOnly && isPrintableKey(event)) {
27874
+ event.preventDefault();
27875
+ startEditing(currentCell, event.key);
27876
+ return;
27877
+ }
27878
+ switch (event.key) {
27879
+ case "ArrowDown":
27880
+ event.preventDefault();
27881
+ if (!event.shiftKey && !isCommandNavigation) {
27882
+ const target = resolveRowSelectionNavigation(event.key);
27883
+ if (target) {
27884
+ moveSelection(target.rowIndex, target.colIndex, false);
27885
+ break;
27886
+ }
27887
+ }
27888
+ moveSelection(
27889
+ isCommandNavigation ? rowIndexByActual.get(resolveLastUsedVisibleIndex(visibleRows, activeSheet?.maxUsedRow ?? -1)) ?? visibleRows.length - 1 : currentRowIndex + 1,
27890
+ currentColIndex,
27891
+ event.shiftKey
27892
+ );
27893
+ break;
27894
+ case "ArrowUp":
27895
+ event.preventDefault();
27896
+ if (!event.shiftKey && !isCommandNavigation) {
27897
+ const target = resolveRowSelectionNavigation(event.key);
27898
+ if (target) {
27899
+ moveSelection(target.rowIndex, target.colIndex, false);
27900
+ break;
27901
+ }
27902
+ }
27903
+ moveSelection(
27904
+ isCommandNavigation ? rowIndexByActual.get(resolveFirstUsedVisibleIndex(visibleRows, activeSheet?.minUsedRow ?? -1)) ?? 0 : currentRowIndex - 1,
27905
+ currentColIndex,
27906
+ event.shiftKey
27907
+ );
27908
+ break;
27909
+ case "ArrowLeft":
27910
+ event.preventDefault();
27911
+ if (!event.shiftKey && !isCommandNavigation) {
27912
+ const target = resolveColumnSelectionNavigation(event.key);
27913
+ if (target) {
27914
+ moveSelection(target.rowIndex, target.colIndex, false);
27915
+ break;
27916
+ }
27917
+ }
27918
+ moveSelection(
27919
+ currentRowIndex,
27920
+ isCommandNavigation ? colIndexByActual.get(resolveFirstUsedVisibleIndex(visibleCols, activeSheet?.minUsedCol ?? -1)) ?? 0 : currentColIndex - 1,
27921
+ event.shiftKey
27922
+ );
27923
+ break;
27924
+ case "ArrowRight":
27925
+ event.preventDefault();
27926
+ if (!event.shiftKey && !isCommandNavigation) {
27927
+ const target = resolveColumnSelectionNavigation(event.key);
27928
+ if (target) {
27929
+ moveSelection(target.rowIndex, target.colIndex, false);
27930
+ break;
27931
+ }
27932
+ }
27933
+ moveSelection(
27934
+ currentRowIndex,
27935
+ isCommandNavigation ? colIndexByActual.get(resolveLastUsedVisibleIndex(visibleCols, activeSheet?.maxUsedCol ?? -1)) ?? visibleCols.length - 1 : currentColIndex + 1,
27936
+ event.shiftKey
27937
+ );
27938
+ break;
27939
+ case "Home":
27940
+ event.preventDefault();
27941
+ moveSelection(
27942
+ isCommandNavigation ? rowIndexByActual.get(resolveFirstUsedVisibleIndex(visibleRows, activeSheet?.minUsedRow ?? -1)) ?? 0 : currentRowIndex,
27943
+ colIndexByActual.get(resolveFirstUsedVisibleIndex(visibleCols, activeSheet?.minUsedCol ?? -1)) ?? 0,
27944
+ event.shiftKey
27945
+ );
27946
+ break;
27947
+ case "End":
27948
+ event.preventDefault();
27949
+ moveSelection(
27950
+ isCommandNavigation ? rowIndexByActual.get(resolveLastUsedVisibleIndex(visibleRows, activeSheet?.maxUsedRow ?? -1)) ?? visibleRows.length - 1 : currentRowIndex,
27951
+ colIndexByActual.get(resolveLastUsedVisibleIndex(visibleCols, activeSheet?.maxUsedCol ?? -1)) ?? visibleCols.length - 1,
27952
+ event.shiftKey
27953
+ );
27954
+ break;
27955
+ case "PageDown":
27956
+ event.preventDefault();
27957
+ if (event.altKey) {
27958
+ moveSelection(currentRowIndex, resolvePageColIndex(currentColIndex, 1), event.shiftKey);
27959
+ break;
27960
+ }
27961
+ moveSelection(resolvePageRowIndex(currentRowIndex, 1), currentColIndex, event.shiftKey);
27962
+ break;
27963
+ case "PageUp":
27964
+ event.preventDefault();
27965
+ if (event.altKey) {
27966
+ moveSelection(currentRowIndex, resolvePageColIndex(currentColIndex, -1), event.shiftKey);
27967
+ break;
27968
+ }
27969
+ moveSelection(resolvePageRowIndex(currentRowIndex, -1), currentColIndex, event.shiftKey);
27970
+ break;
27971
+ case "Tab":
27972
+ event.preventDefault();
27973
+ if (event.shiftKey) {
27974
+ moveSelection(
27975
+ currentColIndex > 0 ? currentRowIndex : currentRowIndex - 1,
27976
+ currentColIndex > 0 ? currentColIndex - 1 : visibleCols.length - 1,
27977
+ false
27978
+ );
27979
+ } else {
27980
+ moveSelection(
27981
+ currentColIndex < visibleCols.length - 1 ? currentRowIndex : currentRowIndex + 1,
27982
+ currentColIndex < visibleCols.length - 1 ? currentColIndex + 1 : 0,
27983
+ false
27984
+ );
27985
+ }
27986
+ break;
27987
+ case "Enter":
27988
+ event.preventDefault();
27989
+ if (event.metaKey || event.ctrlKey || event.altKey) {
27990
+ break;
27991
+ }
27992
+ if (event.shiftKey) {
27993
+ moveSelection(currentRowIndex - 1, currentColIndex, false);
27994
+ break;
27995
+ }
27996
+ moveSelection(currentRowIndex + 1, currentColIndex, false);
27997
+ break;
27998
+ case "Backspace":
27999
+ case "Delete":
28000
+ if (!readOnly) {
28001
+ event.preventDefault();
28002
+ clearSelectedCells();
28003
+ }
28004
+ break;
28005
+ case "F2":
28006
+ if (!readOnly) {
28007
+ event.preventDefault();
28008
+ startEditing(currentCell);
28009
+ }
28010
+ break;
28011
+ default:
28012
+ break;
28013
+ }
28014
+ }
28015
+ gridKeyboardHandlerRef.current = handleGridKeyDown;
27672
28016
  const scrollerViewportProps = {
27673
28017
  key: activeTabIndex,
27674
28018
  ref: scrollRef,
@@ -27704,153 +28048,20 @@ function XlsxGrid({
27704
28048
  if (isInteractiveFocusTarget(event.target, event.currentTarget)) {
27705
28049
  return;
27706
28050
  }
27707
- if (document.activeElement !== event.currentTarget) {
27708
- event.currentTarget.focus({ preventScroll: true });
27709
- }
28051
+ gridKeyboardActiveRef.current = true;
28052
+ focusGridElement(event.currentTarget);
27710
28053
  },
27711
- onKeyDown: (event) => {
27712
- if (editingCell) {
27713
- return;
27714
- }
27715
- if (!readOnly && (event.metaKey || event.ctrlKey) && !event.altKey) {
27716
- const normalizedKey = event.key.toLowerCase();
27717
- if (normalizedKey === "z" && event.shiftKey) {
27718
- event.preventDefault();
27719
- redo();
27720
- return;
27721
- }
27722
- if (normalizedKey === "z") {
27723
- event.preventDefault();
27724
- undo();
27725
- return;
27726
- }
27727
- if (normalizedKey === "y") {
27728
- event.preventDefault();
27729
- redo();
27730
- return;
27731
- }
27732
- }
27733
- const currentCell = resolveCurrentCell();
27734
- if (!currentCell) {
27735
- return;
27736
- }
27737
- const currentRowIndex = rowIndexByActual.get(currentCell.row) ?? 0;
27738
- const currentColIndex = colIndexByActual.get(currentCell.col) ?? 0;
27739
- const isCommandNavigation = event.ctrlKey || event.metaKey;
27740
- if (!readOnly && isPrintableKey(event)) {
27741
- event.preventDefault();
27742
- startEditing(currentCell, event.key);
28054
+ onClickCapture: (event) => {
28055
+ if (isInteractiveFocusTarget(event.target, event.currentTarget)) {
27743
28056
  return;
27744
28057
  }
27745
- switch (event.key) {
27746
- case "ArrowDown":
27747
- event.preventDefault();
27748
- moveSelection(
27749
- isCommandNavigation ? rowIndexByActual.get(resolveLastUsedVisibleIndex(visibleRows, activeSheet?.maxUsedRow ?? -1)) ?? visibleRows.length - 1 : currentRowIndex + 1,
27750
- currentColIndex,
27751
- event.shiftKey
27752
- );
27753
- break;
27754
- case "ArrowUp":
27755
- event.preventDefault();
27756
- moveSelection(
27757
- isCommandNavigation ? rowIndexByActual.get(resolveFirstUsedVisibleIndex(visibleRows, activeSheet?.minUsedRow ?? -1)) ?? 0 : currentRowIndex - 1,
27758
- currentColIndex,
27759
- event.shiftKey
27760
- );
27761
- break;
27762
- case "ArrowLeft":
27763
- event.preventDefault();
27764
- moveSelection(
27765
- currentRowIndex,
27766
- isCommandNavigation ? colIndexByActual.get(resolveFirstUsedVisibleIndex(visibleCols, activeSheet?.minUsedCol ?? -1)) ?? 0 : currentColIndex - 1,
27767
- event.shiftKey
27768
- );
27769
- break;
27770
- case "ArrowRight":
27771
- event.preventDefault();
27772
- moveSelection(
27773
- currentRowIndex,
27774
- isCommandNavigation ? colIndexByActual.get(resolveLastUsedVisibleIndex(visibleCols, activeSheet?.maxUsedCol ?? -1)) ?? visibleCols.length - 1 : currentColIndex + 1,
27775
- event.shiftKey
27776
- );
27777
- break;
27778
- case "Home":
27779
- event.preventDefault();
27780
- moveSelection(
27781
- isCommandNavigation ? rowIndexByActual.get(resolveFirstUsedVisibleIndex(visibleRows, activeSheet?.minUsedRow ?? -1)) ?? 0 : currentRowIndex,
27782
- colIndexByActual.get(resolveFirstUsedVisibleIndex(visibleCols, activeSheet?.minUsedCol ?? -1)) ?? 0,
27783
- event.shiftKey
27784
- );
27785
- break;
27786
- case "End":
27787
- event.preventDefault();
27788
- moveSelection(
27789
- isCommandNavigation ? rowIndexByActual.get(resolveLastUsedVisibleIndex(visibleRows, activeSheet?.maxUsedRow ?? -1)) ?? visibleRows.length - 1 : currentRowIndex,
27790
- colIndexByActual.get(resolveLastUsedVisibleIndex(visibleCols, activeSheet?.maxUsedCol ?? -1)) ?? visibleCols.length - 1,
27791
- event.shiftKey
27792
- );
27793
- break;
27794
- case "PageDown":
27795
- event.preventDefault();
27796
- if (event.altKey) {
27797
- moveSelection(currentRowIndex, resolvePageColIndex(currentColIndex, 1), event.shiftKey);
27798
- break;
27799
- }
27800
- moveSelection(resolvePageRowIndex(currentRowIndex, 1), currentColIndex, event.shiftKey);
27801
- break;
27802
- case "PageUp":
27803
- event.preventDefault();
27804
- if (event.altKey) {
27805
- moveSelection(currentRowIndex, resolvePageColIndex(currentColIndex, -1), event.shiftKey);
27806
- break;
27807
- }
27808
- moveSelection(resolvePageRowIndex(currentRowIndex, -1), currentColIndex, event.shiftKey);
27809
- break;
27810
- case "Tab":
27811
- event.preventDefault();
27812
- if (event.shiftKey) {
27813
- moveSelection(
27814
- currentColIndex > 0 ? currentRowIndex : currentRowIndex - 1,
27815
- currentColIndex > 0 ? currentColIndex - 1 : visibleCols.length - 1,
27816
- false
27817
- );
27818
- } else {
27819
- moveSelection(
27820
- currentColIndex < visibleCols.length - 1 ? currentRowIndex : currentRowIndex + 1,
27821
- currentColIndex < visibleCols.length - 1 ? currentColIndex + 1 : 0,
27822
- false
27823
- );
27824
- }
27825
- break;
27826
- case "Enter":
27827
- event.preventDefault();
27828
- if (event.metaKey || event.ctrlKey || event.altKey) {
27829
- break;
27830
- }
27831
- if (event.shiftKey) {
27832
- moveSelection(currentRowIndex - 1, currentColIndex, false);
27833
- break;
27834
- }
27835
- moveSelection(currentRowIndex + 1, currentColIndex, false);
27836
- break;
27837
- case "Backspace":
27838
- case "Delete":
27839
- if (!readOnly) {
27840
- event.preventDefault();
27841
- clearSelectedCells();
27842
- }
27843
- break;
27844
- case "F2":
27845
- if (!readOnly) {
27846
- event.preventDefault();
27847
- startEditing(currentCell);
27848
- }
27849
- break;
27850
- default:
27851
- break;
27852
- }
28058
+ gridKeyboardActiveRef.current = true;
28059
+ focusGridElement(event.currentTarget);
28060
+ },
28061
+ onFocus: () => {
28062
+ gridKeyboardActiveRef.current = true;
27853
28063
  },
28064
+ onKeyDown: handleGridKeyDown,
27854
28065
  onPaste: (event) => {
27855
28066
  if (editingCell || readOnly) {
27856
28067
  return;
@@ -28100,7 +28311,7 @@ function XlsxGrid({
28100
28311
  {
28101
28312
  ref: editingInputRef,
28102
28313
  autoFocus: true,
28103
- onBlur: commitEditing,
28314
+ onBlur: handleEditingBlur,
28104
28315
  onChange: (event) => setEditingValue(event.target.value),
28105
28316
  onKeyDown: (event) => {
28106
28317
  event.stopPropagation();
@@ -28112,6 +28323,11 @@ function XlsxGrid({
28112
28323
  if (event.key === "Escape") {
28113
28324
  event.preventDefault();
28114
28325
  cancelEditing();
28326
+ return;
28327
+ }
28328
+ if (event.key === "ArrowDown" || event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp") {
28329
+ event.preventDefault();
28330
+ handleEditingNavigate(event.key, event.currentTarget.value);
28115
28331
  }
28116
28332
  },
28117
28333
  style: {
@@ -28266,8 +28482,10 @@ function XlsxGrid({
28266
28482
  onCellClick: handleCellClick,
28267
28483
  onCellDoubleClick: handleCellDoubleClick,
28268
28484
  onCellPointerDown: handleCellPointerDown,
28485
+ onEditingBlur: handleEditingBlur,
28269
28486
  onEditingCancel: cancelEditing,
28270
28487
  onEditingCommit: commitEditing,
28488
+ onEditingNavigate: handleEditingNavigate,
28271
28489
  onEditingValueChange: setEditingValue,
28272
28490
  headerLabelLiveScale,
28273
28491
  onRowHeaderRef: setRowHeaderRef,