@rowsncolumns/spreadsheet 10.4.13 → 10.5.1

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.
Files changed (35) hide show
  1. package/dist/cjs/components/canvas-grid/index.d.ts.map +1 -1
  2. package/dist/cjs/components/canvas-grid/index.js +122 -98
  3. package/dist/cjs/components/canvas-grid/typings.d.ts +10 -0
  4. package/dist/cjs/components/canvas-grid/typings.d.ts.map +1 -1
  5. package/dist/cjs/components/cell-editor/index.d.ts.map +1 -1
  6. package/dist/cjs/components/cell-editor/index.js +16 -12
  7. package/dist/cjs/components/range-selector/index.d.ts.map +1 -1
  8. package/dist/cjs/components/range-selector/index.js +54 -34
  9. package/dist/cjs/components/toolbar/font-family-selector.d.ts +6 -1
  10. package/dist/cjs/components/toolbar/font-family-selector.d.ts.map +1 -1
  11. package/dist/cjs/components/toolbar/font-family-selector.js +1 -2
  12. package/dist/cjs/hooks/use-fonts.d.ts +23 -2
  13. package/dist/cjs/hooks/use-fonts.d.ts.map +1 -1
  14. package/dist/cjs/hooks/use-fonts.js +33 -3
  15. package/dist/cjs/hooks/use-selection.d.ts.map +1 -1
  16. package/dist/cjs/hooks/use-selection.js +62 -16
  17. package/dist/cjs/release-date.js +1 -1
  18. package/dist/esm/components/canvas-grid/index.d.ts.map +1 -1
  19. package/dist/esm/components/canvas-grid/index.js +65 -37
  20. package/dist/esm/components/canvas-grid/typings.d.ts +10 -0
  21. package/dist/esm/components/canvas-grid/typings.d.ts.map +1 -1
  22. package/dist/esm/components/cell-editor/index.d.ts.map +1 -1
  23. package/dist/esm/components/cell-editor/index.js +6 -2
  24. package/dist/esm/components/range-selector/index.d.ts.map +1 -1
  25. package/dist/esm/components/range-selector/index.js +56 -36
  26. package/dist/esm/components/toolbar/font-family-selector.d.ts +6 -1
  27. package/dist/esm/components/toolbar/font-family-selector.d.ts.map +1 -1
  28. package/dist/esm/components/toolbar/font-family-selector.js +1 -2
  29. package/dist/esm/hooks/use-fonts.d.ts +23 -2
  30. package/dist/esm/hooks/use-fonts.d.ts.map +1 -1
  31. package/dist/esm/hooks/use-fonts.js +28 -2
  32. package/dist/esm/hooks/use-selection.d.ts.map +1 -1
  33. package/dist/esm/hooks/use-selection.js +62 -17
  34. package/dist/esm/release-date.js +1 -1
  35. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { findLastContentfulCell, isNull } from "@rowsncolumns/grid";
1
+ import { findLastContentfulCell, isCellWithinBounds, isNull, } from "@rowsncolumns/grid";
2
2
  import { cellToArea } from "@rowsncolumns/grid";
3
3
  import { getOwnerDocument, useIsomorphicLayoutEffect } from "@rowsncolumns/grid";
4
4
  import { Align, cellIdentifier, cellRangeToBounds, clampCellCoords, clampIndex, Direction, findNextCellInDataRegion, findNextCellWithinBounds, getBoundedCells, isAreasEqual, isEqualCells, MouseButtonCodes, newSelectionFromDrag, selectionSpansCells, } from "@rowsncolumns/grid";
@@ -157,6 +157,51 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
157
157
  useIsomorphicLayoutEffect(() => {
158
158
  activeCellRef.current = activeCell;
159
159
  }, [activeCell]);
160
+ /**
161
+ * The last active cell this hook itself emitted. When the `activeCell` prop
162
+ * moves without a grid gesture — undo/redo restoring the cursor, a host
163
+ * navigating — the arrow-key anchor (`selectionStart`/`selectionEnd`) must
164
+ * follow it, or the next arrow key moves from where the cursor was before
165
+ * (rowsncolumns/spreadsheet#1124). Cells the hook emitted itself are skipped:
166
+ * Cmd+click anchors at the range's `start`, not the top-left it emits, and
167
+ * Shift+Arrow never emits at all, so its fixed anchor survives.
168
+ */
169
+ const lastEmittedActiveCellRef = useRef(null);
170
+ const emitActiveCell = useCallback((sheetId, cell) => {
171
+ lastEmittedActiveCellRef.current = cell;
172
+ onChangeActiveCell?.(sheetId, cell);
173
+ }, [onChangeActiveCell]);
174
+ useIsomorphicLayoutEffect(() => {
175
+ if (!activeCell)
176
+ return;
177
+ const emitted = lastEmittedActiveCellRef.current;
178
+ if (emitted &&
179
+ emitted.rowIndex === activeCell.rowIndex &&
180
+ emitted.columnIndex === activeCell.columnIndex) {
181
+ return;
182
+ }
183
+ if (isSelecting.current || isFilling.current || isDragging.current)
184
+ return;
185
+ const range = selections[selections.length - 1]?.range;
186
+ if (range && isCellWithinBounds(activeCell, range)) {
187
+ // Keep the selection; anchor at the active cell and let the far corner
188
+ // be the moving end so Shift+Arrow extends from here.
189
+ selectionStart.current = activeCell;
190
+ selectionEnd.current = {
191
+ rowIndex: activeCell.rowIndex === range.startRowIndex
192
+ ? range.endRowIndex
193
+ : range.startRowIndex,
194
+ columnIndex: activeCell.columnIndex === range.startColumnIndex
195
+ ? range.endColumnIndex
196
+ : range.startColumnIndex,
197
+ };
198
+ }
199
+ else {
200
+ selectionStart.current = activeCell;
201
+ selectionEnd.current = activeCell;
202
+ }
203
+ // eslint-disable-next-line react-hooks/exhaustive-deps
204
+ }, [sheetId, activeCell?.rowIndex, activeCell?.columnIndex]);
160
205
  useIsomorphicLayoutEffect(() => {
161
206
  mergedCellsRef.current = mergedCells;
162
207
  }, [mergedCells]);
@@ -269,7 +314,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
269
314
  if (!range) {
270
315
  return;
271
316
  }
272
- onChangeActiveCell?.(sheetId, {
317
+ emitActiveCell(sheetId, {
273
318
  rowIndex: range.startRowIndex,
274
319
  columnIndex: range.startColumnIndex,
275
320
  });
@@ -279,7 +324,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
279
324
  }, [
280
325
  sheetId,
281
326
  onChangeSelections,
282
- onChangeActiveCell,
327
+ emitActiveCell,
283
328
  selectionFromStartEnd,
284
329
  isCellOutOfBounds,
285
330
  selectionPolicy,
@@ -305,7 +350,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
305
350
  columnIndex: bounds.startColumnIndex,
306
351
  };
307
352
  /* Keep track of first cell that was selected by user */
308
- onChangeActiveCell?.(sheetId, coords);
353
+ emitActiveCell(sheetId, coords);
309
354
  if (newSelectionMode === "clear") {
310
355
  clearSelections();
311
356
  }
@@ -321,7 +366,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
321
366
  appendSelection,
322
367
  newSelectionMode,
323
368
  clearSelections,
324
- onChangeActiveCell,
369
+ emitActiveCell,
325
370
  selectionFromStartEnd,
326
371
  isCellOutOfBounds,
327
372
  ]);
@@ -400,12 +445,12 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
400
445
  const handleSetActiveCell = useCallbackRef(useCallback((sheetId, coords, shouldScroll = true, align) => {
401
446
  selectionStart.current = coords;
402
447
  selectionEnd.current = coords;
403
- onChangeActiveCell?.(sheetId, coords);
448
+ emitActiveCell(sheetId, coords);
404
449
  /* Scroll to the cell */
405
450
  if (shouldScroll && coords) {
406
451
  scrollToCell(coords, align);
407
452
  }
408
- }, [onChangeActiveCell, scrollToCell]));
453
+ }, [emitActiveCell, scrollToCell]));
409
454
  /**
410
455
  * Navigate selection using keyboard
411
456
  * @param direction
@@ -1053,7 +1098,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1053
1098
  const newSelection = removeSelectionByIndex(cellIndex);
1054
1099
  const nextActiveCell = getPossibleActiveCellFromSelections(newSelection);
1055
1100
  if (nextActiveCell !== null) {
1056
- onChangeActiveCell?.(sheetId, nextActiveCell);
1101
+ emitActiveCell(sheetId, nextActiveCell);
1057
1102
  }
1058
1103
  if (newSelection.length === 1 &&
1059
1104
  cellEqualsSelection(nextActiveCell, newSelection)) {
@@ -1107,7 +1152,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1107
1152
  modifySelection,
1108
1153
  mouseDownInterceptor,
1109
1154
  newSelection,
1110
- onChangeActiveCell,
1155
+ emitActiveCell,
1111
1156
  removeSelectionByIndex,
1112
1157
  selectionLeftBound,
1113
1158
  selectionTopBound,
@@ -1190,7 +1235,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1190
1235
  const direction = isShiftKey ? Direction.Up : Direction.Down;
1191
1236
  const nextCell = findNextCellWithinBounds(activeCellBounds, range, direction);
1192
1237
  if (nextCell) {
1193
- onChangeActiveCell?.(sheetId, nextCell);
1238
+ emitActiveCell(sheetId, nextCell);
1194
1239
  scrollToCell(nextCell);
1195
1240
  }
1196
1241
  }
@@ -1211,7 +1256,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1211
1256
  const direction = isShiftKey ? Direction.Left : Direction.Right;
1212
1257
  const nextCell = findNextCellWithinBounds(activeCellBounds, range, direction);
1213
1258
  if (nextCell) {
1214
- onChangeActiveCell?.(sheetId, nextCell);
1259
+ emitActiveCell(sheetId, nextCell);
1215
1260
  scrollToCell(nextCell);
1216
1261
  }
1217
1262
  }
@@ -1262,7 +1307,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1262
1307
  activeCell,
1263
1308
  selections,
1264
1309
  keyNavigate,
1265
- onChangeActiveCell,
1310
+ emitActiveCell,
1266
1311
  pageDown,
1267
1312
  pageLeft,
1268
1313
  pageRight,
@@ -1419,7 +1464,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1419
1464
  // The active cell normally anchors the surviving corner; if it fell in the cleared band,
1420
1465
  // move it to the remaining range's top-left so it never points at a deselected cell.
1421
1466
  if (!cellInRange(activeCell, shrink.remaining)) {
1422
- onChangeActiveCell?.(sheetId, {
1467
+ emitActiveCell(sheetId, {
1423
1468
  rowIndex: shrink.remaining.startRowIndex,
1424
1469
  columnIndex: shrink.remaining.startColumnIndex,
1425
1470
  });
@@ -1470,7 +1515,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1470
1515
  focus,
1471
1516
  handleFillMouseMove,
1472
1517
  onChangeSelections,
1473
- onChangeActiveCell,
1518
+ emitActiveCell,
1474
1519
  onFill,
1475
1520
  onFillHandleRelease,
1476
1521
  onFillShrink,
@@ -1568,7 +1613,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1568
1613
  columnIndex: toSelection.range.startColumnIndex,
1569
1614
  };
1570
1615
  /* Pick the first cell as activee cell */
1571
- onChangeActiveCell?.(sheetId, coords);
1616
+ emitActiveCell(sheetId, coords);
1572
1617
  /* Update selection start */
1573
1618
  selectionStart.current = coords;
1574
1619
  if (selectionSpansCells(toSelection?.range)) {
@@ -1604,7 +1649,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1604
1649
  onMoveSelection?.(sheetId, fromSelection, toSelection);
1605
1650
  return;
1606
1651
  }
1607
- onChangeActiveCell?.(sheetId, {
1652
+ emitActiveCell(sheetId, {
1608
1653
  rowIndex: fromSelection.range.startRowIndex,
1609
1654
  columnIndex: fromSelection.range.startColumnIndex,
1610
1655
  });
@@ -1642,7 +1687,7 @@ export const useSelection = ({ sheetId, activeCell, onChangeActiveCell, selectio
1642
1687
  getValue,
1643
1688
  handleSelectionMouseMove,
1644
1689
  focus,
1645
- onChangeActiveCell,
1690
+ emitActiveCell,
1646
1691
  onChangeSelections,
1647
1692
  ]);
1648
1693
  /**
@@ -1,3 +1,3 @@
1
1
  export const releaseDate =
2
2
  // @ts-ignore
3
- new Date("2026-10-08") ?? new Date("2025-06-18");
3
+ new Date("2026-10-12") ?? new Date("2025-06-18");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rowsncolumns/spreadsheet",
3
- "version": "10.4.13",
3
+ "version": "10.5.1",
4
4
  "author": "Vinay M",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "main": "./dist/cjs/index.js",