@ricsam/react-spreadsheets 0.0.9 → 0.0.11

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/react-spreadsheets",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "type": "commonjs"
5
5
  }
package/dist/mjs/lib.mjs CHANGED
@@ -1326,6 +1326,7 @@ var resizeCellSnapAnchorToNearestEdges = (anchor, rect, handle, columnWidths, ro
1326
1326
 
1327
1327
  // src/spreadsheet/spreadsheet.tsx
1328
1328
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1329
+ var SPREADSHEET_OVERLAY_SELECTOR = "[data-rsp-overlay]";
1329
1330
  var resolveGridLineColor = (probe, colorScheme) => {
1330
1331
  const fallback = colorScheme === "dark" ? "#232c3d" : "#e8ebf1";
1331
1332
  if (!probe || typeof getComputedStyle !== "function") {
@@ -2286,6 +2287,12 @@ var Spreadsheet = forwardRef(({
2286
2287
  });
2287
2288
  }, [selectionManager, clipboardManager, disableClipboard]);
2288
2289
  const handleWheel = useCallback3((e) => {
2290
+ const target = e.target;
2291
+ const currentTarget = e.currentTarget;
2292
+ const overlay = target instanceof Element ? target.closest(SPREADSHEET_OVERLAY_SELECTOR) : null;
2293
+ if (overlay && currentTarget instanceof Node && currentTarget.contains(overlay)) {
2294
+ return;
2295
+ }
2289
2296
  e.preventDefault();
2290
2297
  e.stopPropagation();
2291
2298
  setViewport((previous) => ({
@@ -3011,6 +3018,7 @@ var Spreadsheet = forwardRef(({
3011
3018
  const isTextBox = child.component === "RichText";
3012
3019
  const isMinimized = Boolean(child.minimized && !isTextBox);
3013
3020
  return /* @__PURE__ */ jsxs2("div", {
3021
+ "data-rsp-overlay": child.id,
3014
3022
  style: {
3015
3023
  position: "absolute",
3016
3024
  width: child.width,
@@ -3079,7 +3087,7 @@ Spreadsheet.displayName = "Spreadsheet";
3079
3087
  // src/workbook/workbook.tsx
3080
3088
  import {
3081
3089
  parseCellReference as parseCellReference2,
3082
- getCellReference as getCellReference3
3090
+ getCellReference as getCellReference2
3083
3091
  } from "@ricsam/formula-engine";
3084
3092
  import React3, { useCallback as useCallback4, useMemo as useMemo2, useRef as useRef4, useState as useState6 } from "react";
3085
3093
 
@@ -3207,9 +3215,24 @@ import { indexToColumn as indexToColumn2 } from "@ricsam/formula-engine";
3207
3215
  class WorkbookSelectionManager {
3208
3216
  managers = new Map;
3209
3217
  lastFocusedManager = null;
3218
+ lastSelections = [];
3219
+ selectionsByView = new Map;
3210
3220
  listeners = new Set;
3211
3221
  cleanupFunctions = new Map;
3212
3222
  pendingRangeFocus = null;
3223
+ applyingRangeFocus = new Set;
3224
+ getViewKey(context) {
3225
+ return JSON.stringify([context.workbookName, context.sheetName, context.viewId ?? null]);
3226
+ }
3227
+ cloneSmArea(area) {
3228
+ return {
3229
+ start: { row: area.start.row, col: area.start.col },
3230
+ end: {
3231
+ row: area.end.row.type === "infinity" ? { type: "infinity" } : { type: "number", value: area.end.row.value },
3232
+ col: area.end.col.type === "infinity" ? { type: "infinity" } : { type: "number", value: area.end.col.value }
3233
+ }
3234
+ };
3235
+ }
3213
3236
  smAreaToSpreadsheetRange(area) {
3214
3237
  const rowEnd = area.end.row.type === "infinity" ? { type: "infinity", sign: "positive" } : { type: "number", value: area.end.row.value };
3215
3238
  const colEnd = area.end.col.type === "infinity" ? { type: "infinity", sign: "positive" } : { type: "number", value: area.end.col.value };
@@ -3240,43 +3263,69 @@ class WorkbookSelectionManager {
3240
3263
  range: this.smAreaToSpreadsheetRange(this.spreadsheetRangeToSmArea(address.range))
3241
3264
  };
3242
3265
  }
3243
- matchesContext(address, context) {
3244
- return address.workbookName === context.workbookName && address.sheetName === context.sheetName;
3266
+ areasToRangeAddresses(areas, context) {
3267
+ return areas.map((area) => ({
3268
+ workbookName: context.workbookName,
3269
+ sheetName: context.sheetName,
3270
+ range: this.smAreaToSpreadsheetRange(area)
3271
+ }));
3272
+ }
3273
+ rememberSelections(manager, context, areas = manager.getState().selections) {
3274
+ const cachedAreas = areas.map((area) => this.cloneSmArea(area));
3275
+ this.selectionsByView.set(this.getViewKey(context), cachedAreas);
3276
+ this.lastFocusedManager = { sm: manager, context };
3277
+ this.lastSelections = this.areasToRangeAddresses(cachedAreas, context);
3278
+ }
3279
+ matchesContext(address, context, viewId) {
3280
+ return address.workbookName === context.workbookName && address.sheetName === context.sheetName && (viewId === undefined || context.viewId === viewId);
3245
3281
  }
3246
3282
  applyRangeFocus(manager, context, request) {
3247
3283
  const selection = this.spreadsheetRangeToSmArea(request.address.range);
3248
- manager.setState({ selections: [selection] });
3249
- manager.focus();
3284
+ this.applyingRangeFocus.add(manager);
3285
+ try {
3286
+ manager.replaceSelections([selection]);
3287
+ manager.focus();
3288
+ } finally {
3289
+ this.applyingRangeFocus.delete(manager);
3290
+ }
3250
3291
  manager.revealRange(selection, request.options);
3251
- this.lastFocusedManager = { sm: manager, context };
3292
+ this.rememberSelections(manager, context, [selection]);
3252
3293
  this.emitChange();
3253
3294
  }
3254
3295
  applyPendingRangeFocusOnMount(manager, context) {
3255
3296
  const pending = this.pendingRangeFocus;
3256
- if (!pending || !this.matchesContext(pending.address, context))
3297
+ if (!pending || !this.matchesContext(pending.address, context, pending.options.viewId))
3257
3298
  return;
3258
3299
  queueMicrotask(() => {
3259
3300
  if (this.pendingRangeFocus !== pending)
3260
3301
  return;
3261
3302
  const mountedContext = this.managers.get(manager);
3262
- if (!mountedContext || !this.matchesContext(pending.address, mountedContext))
3303
+ if (!mountedContext || !this.matchesContext(pending.address, mountedContext, pending.options.viewId)) {
3263
3304
  return;
3305
+ }
3264
3306
  this.pendingRangeFocus = null;
3265
3307
  this.applyRangeFocus(manager, mountedContext, pending);
3266
3308
  });
3267
3309
  }
3268
3310
  add(manager, context) {
3269
- this.managers.set(manager, context);
3311
+ const registeredContext = { ...context };
3312
+ this.managers.set(manager, registeredContext);
3313
+ const cachedSelections = this.selectionsByView.get(this.getViewKey(registeredContext));
3314
+ if (cachedSelections && manager.getState().selections.length === 0) {
3315
+ manager.replaceSelections(cachedSelections);
3316
+ }
3270
3317
  const focusCleanup = manager.observeStateChange((state) => state.hasFocus, (hasFocus) => {
3271
- if (hasFocus) {
3272
- this.lastFocusedManager = { sm: manager, context };
3318
+ if (hasFocus && !this.applyingRangeFocus.has(manager)) {
3319
+ this.rememberSelections(manager, registeredContext);
3273
3320
  this.emitChange();
3274
3321
  }
3275
3322
  });
3276
3323
  const selectionCleanup = manager.observeStateChange((state) => JSON.stringify(state.selections), (selectionsJson) => {
3324
+ if (this.applyingRangeFocus.has(manager))
3325
+ return;
3277
3326
  const selections = JSON.parse(selectionsJson);
3278
3327
  if (selections && selections.length > 0) {
3279
- this.lastFocusedManager = { sm: manager, context };
3328
+ this.rememberSelections(manager, registeredContext, selections);
3280
3329
  this.emitChange();
3281
3330
  }
3282
3331
  });
@@ -3286,27 +3335,19 @@ class WorkbookSelectionManager {
3286
3335
  this.managers.delete(manager);
3287
3336
  this.cleanupFunctions.delete(manager);
3288
3337
  if (this.lastFocusedManager?.sm === manager) {
3338
+ this.rememberSelections(manager, registeredContext);
3289
3339
  this.lastFocusedManager = null;
3290
3340
  }
3291
3341
  };
3292
3342
  this.cleanupFunctions.set(manager, cleanup);
3293
- this.applyPendingRangeFocusOnMount(manager, context);
3343
+ this.applyPendingRangeFocusOnMount(manager, registeredContext);
3294
3344
  return cleanup;
3295
3345
  }
3296
3346
  getLastFocusedSelectionManager() {
3297
3347
  return this.lastFocusedManager;
3298
3348
  }
3299
3349
  getSelections() {
3300
- if (!this.lastFocusedManager) {
3301
- return [];
3302
- }
3303
- const { sm, context } = this.lastFocusedManager;
3304
- const state = sm.getState();
3305
- return state.selections.map((area) => ({
3306
- workbookName: context.workbookName,
3307
- sheetName: context.sheetName,
3308
- range: this.smAreaToSpreadsheetRange(area)
3309
- }));
3350
+ return this.lastSelections.map((selection) => this.cloneRangeAddress(selection));
3310
3351
  }
3311
3352
  getLastSelection() {
3312
3353
  const selections = this.getSelections();
@@ -3355,35 +3396,37 @@ class WorkbookSelectionManager {
3355
3396
  return `[${workbookName}]${sheetRef}!${rangeStr}`;
3356
3397
  }
3357
3398
  blur() {
3358
- this.managers.forEach((context, manager) => {
3399
+ this.managers.forEach((_context, manager) => {
3359
3400
  manager.clearSelections();
3360
3401
  manager.blur();
3361
3402
  });
3403
+ this.selectionsByView.clear();
3362
3404
  this.lastFocusedManager = null;
3405
+ this.lastSelections = [];
3363
3406
  this.emitChange();
3364
3407
  }
3365
- focusWorkbook(workbookName) {
3408
+ focusWorkbook(workbookName, viewId) {
3366
3409
  for (const [manager, context] of this.managers) {
3367
- if (context.workbookName === workbookName) {
3410
+ if (context.workbookName === workbookName && (viewId === undefined || context.viewId === viewId)) {
3368
3411
  manager.focus();
3369
- this.lastFocusedManager = { sm: manager, context };
3412
+ this.rememberSelections(manager, context);
3370
3413
  this.emitChange();
3371
3414
  return;
3372
3415
  }
3373
3416
  }
3374
3417
  }
3375
- focusSheet(workbookName, sheetName) {
3418
+ focusSheet(workbookName, sheetName, viewId) {
3376
3419
  for (const [manager, context] of this.managers) {
3377
- if (context.workbookName === workbookName && context.sheetName === sheetName) {
3420
+ if (context.workbookName === workbookName && context.sheetName === sheetName && (viewId === undefined || context.viewId === viewId)) {
3378
3421
  manager.focus();
3379
- this.lastFocusedManager = { sm: manager, context };
3422
+ this.rememberSelections(manager, context);
3380
3423
  this.emitChange();
3381
3424
  return true;
3382
3425
  }
3383
3426
  }
3384
3427
  return false;
3385
3428
  }
3386
- focusCell(workbookName, sheetName, row, col) {
3429
+ focusCell(workbookName, sheetName, row, col, options = {}) {
3387
3430
  return this.focusRange({
3388
3431
  workbookName,
3389
3432
  sheetName,
@@ -3394,7 +3437,7 @@ class WorkbookSelectionManager {
3394
3437
  col: { type: "number", value: col }
3395
3438
  }
3396
3439
  }
3397
- });
3440
+ }, options);
3398
3441
  }
3399
3442
  focusRange(address, options = {}) {
3400
3443
  const request = {
@@ -3402,7 +3445,7 @@ class WorkbookSelectionManager {
3402
3445
  options: { ...options }
3403
3446
  };
3404
3447
  for (const [manager, context] of this.managers) {
3405
- if (!this.matchesContext(request.address, context))
3448
+ if (!this.matchesContext(request.address, context, request.options.viewId))
3406
3449
  continue;
3407
3450
  this.pendingRangeFocus = null;
3408
3451
  this.applyRangeFocus(manager, context, request);
@@ -3411,6 +3454,9 @@ class WorkbookSelectionManager {
3411
3454
  this.pendingRangeFocus = request;
3412
3455
  return false;
3413
3456
  }
3457
+ cancelPendingFocusRange() {
3458
+ this.pendingRangeFocus = null;
3459
+ }
3414
3460
  emitChange() {
3415
3461
  const currentSelection = this.getLastSelection();
3416
3462
  const selections = currentSelection ? [currentSelection] : [];
@@ -3589,7 +3635,7 @@ class WorkbookClipboardManager extends ClipboardUtils {
3589
3635
  };
3590
3636
  this.copiedCells.push(cellAddress);
3591
3637
  const value = this.engine.getCellValue(cellAddress, false);
3592
- const formula = cellData.get(getCellReference3(cellAddress));
3638
+ const formula = cellData.get(getCellReference2(cellAddress));
3593
3639
  valueExportGrid[relative.rowIndex][relative.columnIndex] = getCellDisplayValue(value);
3594
3640
  formulaExportGrid[relative.rowIndex][relative.columnIndex] = formula;
3595
3641
  });
@@ -3637,6 +3683,7 @@ function FormulaSheet({
3637
3683
  verboseErrors = false,
3638
3684
  selection,
3639
3685
  selectionManager,
3686
+ viewId,
3640
3687
  customCellStyle,
3641
3688
  customCellRenderer,
3642
3689
  onCellDataChangeError = queueCellEditError,
@@ -3808,7 +3855,8 @@ function FormulaSheet({
3808
3855
  if (selectionManager) {
3809
3856
  const workbookManagerCleanup = selectionManager.add(spreadsheetSelectionManager, {
3810
3857
  workbookName,
3811
- sheetName
3858
+ sheetName,
3859
+ ...viewId === undefined ? {} : { viewId }
3812
3860
  });
3813
3861
  cleanups.push(workbookManagerCleanup);
3814
3862
  }
@@ -3829,6 +3877,7 @@ function FormulaSheet({
3829
3877
  selectionManager,
3830
3878
  sheetName,
3831
3879
  showFormulas,
3880
+ viewId,
3832
3881
  workbookName
3833
3882
  ]);
3834
3883
  if (!sheet) {
@@ -3968,7 +4017,7 @@ function FormulaSheet({
3968
4017
  return style;
3969
4018
  },
3970
4019
  customCellRenderer: (cell) => {
3971
- const cellRef = getCellReference3({
4020
+ const cellRef = getCellReference2({
3972
4021
  colIndex: cell.colIndex,
3973
4022
  rowIndex: cell.rowIndex
3974
4023
  });
@@ -4062,6 +4111,7 @@ function FormulaWorkbook({
4062
4111
  onActiveSheetChange,
4063
4112
  verboseErrors = false,
4064
4113
  selectionManager,
4114
+ viewId,
4065
4115
  components,
4066
4116
  sheetOverlayChildren,
4067
4117
  sheetSelectedOverlayIds,
@@ -4229,6 +4279,7 @@ function FormulaWorkbook({
4229
4279
  engine,
4230
4280
  verboseErrors,
4231
4281
  selectionManager,
4282
+ viewId,
4232
4283
  ...rest,
4233
4284
  components,
4234
4285
  overlayChildren: activeSheetOverlayChildren,
@@ -4456,4 +4507,4 @@ export {
4456
4507
  useResizeObserver
4457
4508
  };
4458
4509
 
4459
- //# debugId=58E97FA1EA7F33CF64756E2164756E21
4510
+ //# debugId=7847981F1291DEF064756E2164756E21