@rowsncolumns/y-spreadsheet 15.0.2 → 15.0.3

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.
@@ -23,6 +23,18 @@ export type UseYSpreadsheetPropsV2<T extends CellData, S extends Sheet, C extend
23
23
  * convention to remain wire-compatible.
24
24
  */
25
25
  awarenessScopeId?: string;
26
+ /**
27
+ * Whether this client may persist to the shared document (the host's
28
+ * edit permission; `false` for view-only sessions). Published on awareness
29
+ * as `canWrite` and consulted by the leader election: the leader is the
30
+ * peer that evaluates backend/agent recalc backlogs and writes the computed
31
+ * values back, so a client whose writes the server refuses must never win —
32
+ * every value it computed would be dropped. Peers whose awareness state has
33
+ * no `canWrite` field (older clients, REST writers) count as writers. When
34
+ * no writer is present there is no leader: nothing could persist the values
35
+ * anyway. Default: `true`.
36
+ */
37
+ canWrite?: boolean;
26
38
  userId: string | number;
27
39
  title: string;
28
40
  sheetId: number;
@@ -142,7 +154,7 @@ export type UseYSpreadsheetPropsV2<T extends CellData, S extends Sheet, C extend
142
154
  };
143
155
  export type YRowData = Y.Map<Y.Array<CellData | null>>;
144
156
  export type YSheetData = Y.Array<YRowData | null>;
145
- export declare const useYSpreadsheetV2: <T extends CellData, S extends Sheet, C extends EmbeddedChart, O extends EmbeddedObject>({ onChangeSheetData, onChangeSheets, onChangeTables, onChangeCharts, onChangeEmbeds, onChangeConditionalFormats, onChangeDataValidations, onChangeCitations, onAfterBroadcastPatch, recalcCellsMaxEntries, onChangeNamedRanges, onChangeProtectedRanges, onChangePivotTables, enqueueCalculation, enqueueGraphOperation, reevaluateDerivationsForCells, onChangeCellXfs, onChangeSharedStrings, calculateNow, onChangeActiveSheet, clientOnlyFunctionPattern, initialSheets, awarenessScopeId, userId, title, sheetId, activeCell, kind, agentInitiator, selections, doc, provider, useV3, sheetDataVersion, onMigrationComplete, deleteV2AfterMigration, skipInitialSync, supportLegacySharedStringsArray, }: UseYSpreadsheetPropsV2<T, S, C, O>) => {
157
+ export declare const useYSpreadsheetV2: <T extends CellData, S extends Sheet, C extends EmbeddedChart, O extends EmbeddedObject>({ onChangeSheetData, onChangeSheets, onChangeTables, onChangeCharts, onChangeEmbeds, onChangeConditionalFormats, onChangeDataValidations, onChangeCitations, onAfterBroadcastPatch, recalcCellsMaxEntries, onChangeNamedRanges, onChangeProtectedRanges, onChangePivotTables, enqueueCalculation, enqueueGraphOperation, reevaluateDerivationsForCells, onChangeCellXfs, onChangeSharedStrings, calculateNow, onChangeActiveSheet, clientOnlyFunctionPattern, initialSheets, awarenessScopeId, canWrite, userId, title, sheetId, activeCell, kind, agentInitiator, selections, doc, provider, useV3, sheetDataVersion, onMigrationComplete, deleteV2AfterMigration, skipInitialSync, supportLegacySharedStringsArray, }: UseYSpreadsheetPropsV2<T, S, C, O>) => {
146
158
  synced: boolean;
147
159
  users: Collaborator[];
148
160
  onBroadcastPatch: (patches: [patch: SpreadsheetPatch<Patch>, type?: HistoryType | undefined | null][]) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"use-yspreadsheet-v2.d.ts","sourceRoot":"","sources":["../../use-yspreadsheet-v2.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-yspreadsheet-v2.d.ts","sourceRoot":"","sources":["../../use-yspreadsheet-v2.ts"],"names":[],"mappings":"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"}
@@ -57,10 +57,10 @@ var observables_1 = require("./observables");
57
57
  // Add a single null entry to the YSheetData
58
58
  var origin = "local";
59
59
  var useYSpreadsheetV2 = function (_a) {
60
- var onChangeSheetData = _a.onChangeSheetData, onChangeSheets = _a.onChangeSheets, onChangeTables = _a.onChangeTables, onChangeCharts = _a.onChangeCharts, onChangeEmbeds = _a.onChangeEmbeds, onChangeConditionalFormats = _a.onChangeConditionalFormats, onChangeDataValidations = _a.onChangeDataValidations, onChangeCitations = _a.onChangeCitations, onAfterBroadcastPatch = _a.onAfterBroadcastPatch, recalcCellsMaxEntries = _a.recalcCellsMaxEntries, onChangeNamedRanges = _a.onChangeNamedRanges, onChangeProtectedRanges = _a.onChangeProtectedRanges, onChangePivotTables = _a.onChangePivotTables, enqueueCalculation = _a.enqueueCalculation, enqueueGraphOperation = _a.enqueueGraphOperation, reevaluateDerivationsForCells = _a.reevaluateDerivationsForCells, onChangeCellXfs = _a.onChangeCellXfs, onChangeSharedStrings = _a.onChangeSharedStrings, calculateNow = _a.calculateNow, onChangeActiveSheet = _a.onChangeActiveSheet, clientOnlyFunctionPattern = _a.clientOnlyFunctionPattern, initialSheets = _a.initialSheets, awarenessScopeId = _a.awarenessScopeId, userId = _a.userId, title = _a.title, sheetId = _a.sheetId, activeCell = _a.activeCell, kind = _a.kind, agentInitiator = _a.agentInitiator, selections = _a.selections, doc = _a.doc, provider = _a.provider, _b = _a.useV3, useV3 = _b === void 0 ? false : _b, _c = _a.sheetDataVersion, sheetDataVersion = _c === void 0 ? "v2" : _c, onMigrationComplete = _a.onMigrationComplete, _d = _a.deleteV2AfterMigration, deleteV2AfterMigration = _d === void 0 ? false : _d, _e = _a.skipInitialSync, skipInitialSync = _e === void 0 ? false : _e, _f = _a.supportLegacySharedStringsArray, supportLegacySharedStringsArray = _f === void 0 ? false : _f;
61
- var _g = tslib_1.__read((0, react_1.useState)(false), 2), synced = _g[0], setSynced = _g[1];
62
- var _h = tslib_1.__read((0, react_1.useState)([]), 2), users = _h[0], setUsers = _h[1];
63
- var _j = tslib_1.__read((0, react_1.useState)(false), 2), isLeader = _j[0], setIsLeader = _j[1];
60
+ var onChangeSheetData = _a.onChangeSheetData, onChangeSheets = _a.onChangeSheets, onChangeTables = _a.onChangeTables, onChangeCharts = _a.onChangeCharts, onChangeEmbeds = _a.onChangeEmbeds, onChangeConditionalFormats = _a.onChangeConditionalFormats, onChangeDataValidations = _a.onChangeDataValidations, onChangeCitations = _a.onChangeCitations, onAfterBroadcastPatch = _a.onAfterBroadcastPatch, recalcCellsMaxEntries = _a.recalcCellsMaxEntries, onChangeNamedRanges = _a.onChangeNamedRanges, onChangeProtectedRanges = _a.onChangeProtectedRanges, onChangePivotTables = _a.onChangePivotTables, enqueueCalculation = _a.enqueueCalculation, enqueueGraphOperation = _a.enqueueGraphOperation, reevaluateDerivationsForCells = _a.reevaluateDerivationsForCells, onChangeCellXfs = _a.onChangeCellXfs, onChangeSharedStrings = _a.onChangeSharedStrings, calculateNow = _a.calculateNow, onChangeActiveSheet = _a.onChangeActiveSheet, clientOnlyFunctionPattern = _a.clientOnlyFunctionPattern, initialSheets = _a.initialSheets, awarenessScopeId = _a.awarenessScopeId, _b = _a.canWrite, canWrite = _b === void 0 ? true : _b, userId = _a.userId, title = _a.title, sheetId = _a.sheetId, activeCell = _a.activeCell, kind = _a.kind, agentInitiator = _a.agentInitiator, selections = _a.selections, doc = _a.doc, provider = _a.provider, _c = _a.useV3, useV3 = _c === void 0 ? false : _c, _d = _a.sheetDataVersion, sheetDataVersion = _d === void 0 ? "v2" : _d, onMigrationComplete = _a.onMigrationComplete, _e = _a.deleteV2AfterMigration, deleteV2AfterMigration = _e === void 0 ? false : _e, _f = _a.skipInitialSync, skipInitialSync = _f === void 0 ? false : _f, _g = _a.supportLegacySharedStringsArray, supportLegacySharedStringsArray = _g === void 0 ? false : _g;
61
+ var _h = tslib_1.__read((0, react_1.useState)(false), 2), synced = _h[0], setSynced = _h[1];
62
+ var _j = tslib_1.__read((0, react_1.useState)([]), 2), users = _j[0], setUsers = _j[1];
63
+ var _k = tslib_1.__read((0, react_1.useState)(false), 2), isLeader = _k[0], setIsLeader = _k[1];
64
64
  var isLeaderRef = (0, react_1.useRef)(false);
65
65
  var resolvedAwarenessScopeId = awarenessScopeId;
66
66
  // Listen to awareness
@@ -76,22 +76,30 @@ var useYSpreadsheetV2 = function (_a) {
76
76
  return (state === null || state === void 0 ? void 0 : state.docGuid) === resolvedAwarenessScopeId;
77
77
  })
78
78
  : entries;
79
- if (!docStates.length) {
80
- setIsLeader(false);
81
- return;
82
- }
83
- var states = docStates.map(function (_a) {
79
+ // Only peers that can persist may lead (see `canWrite`). A view-only
80
+ // client's recalc write-backs are refused by the server, so electing it
81
+ // silently drops every computed value. A missing field is a writer.
82
+ var writers = docStates
83
+ .filter(function (_a) {
84
+ var _b = tslib_1.__read(_a, 2), _ = _b[0], state = _b[1];
85
+ return (state === null || state === void 0 ? void 0 : state.canWrite) !== false;
86
+ })
87
+ .map(function (_a) {
84
88
  var _b = tslib_1.__read(_a, 1), clientId = _b[0];
85
89
  return clientId;
86
90
  });
87
- var minId = Math.min.apply(Math, tslib_1.__spreadArray([], tslib_1.__read(states), false));
91
+ if (!canWrite || !writers.length) {
92
+ setIsLeader(false);
93
+ return;
94
+ }
95
+ var minId = Math.min.apply(Math, tslib_1.__spreadArray([], tslib_1.__read(writers), false));
88
96
  // Always include self in the elec
89
97
  setIsLeader(doc.clientID === minId);
90
98
  };
91
99
  awareness.on("change", updateLeader);
92
100
  updateLeader(); // Initial check
93
101
  return function () { return awareness.off("change", updateLeader); };
94
- }, [awareness, doc, resolvedAwarenessScopeId]);
102
+ }, [awareness, doc, resolvedAwarenessScopeId, canWrite]);
95
103
  (0, ui_1.useIsomorphicLayoutEffect)(function () {
96
104
  isLeaderRef.current = isLeader;
97
105
  }, [isLeader]);
@@ -243,6 +251,12 @@ var useYSpreadsheetV2 = function (_a) {
243
251
  return source === "backend" || source === "agent";
244
252
  });
245
253
  }, [yRecalcCells]);
254
+ /**
255
+ * Set once the initial sync has built the dependency graph and replayed the
256
+ * backlog, so a later leadership hand-over can replay it again.
257
+ */
258
+ var graphReadyRef = (0, react_1.useRef)(false);
259
+ var initialSyncTimerRef = (0, react_1.useRef)(null);
246
260
  // Trigger cell recalcs
247
261
  var syncRecalcCells = (0, react_1.useCallback)(function (recalcCells, origin) {
248
262
  var e_2, _a;
@@ -460,6 +474,24 @@ var useYSpreadsheetV2 = function (_a) {
460
474
  onMigrationComplete,
461
475
  deleteV2AfterMigration,
462
476
  ]);
477
+ /**
478
+ * Replay the backend/agent recalc backlog into the local graph — and, on
479
+ * the leader, evaluate it. Only the leader clears the entries, and only once
480
+ * they sit in its calculation queue: a non-leader merely graph-enqueues
481
+ * (no evaluation), so if it deleted them the leader would never recompute
482
+ * the backlog at all.
483
+ */
484
+ var drainBacklog = (0, react_1.useCallback)(function () {
485
+ var backlog = getBacklog();
486
+ if (!backlog.length)
487
+ return;
488
+ syncRecalcCells(backlog, "backend");
489
+ if (isLeaderRef.current) {
490
+ doc.transact(function () {
491
+ yRecalcCells.delete(0, yRecalcCells.length);
492
+ }, origin);
493
+ }
494
+ }, [getBacklog, syncRecalcCells, doc, yRecalcCells]);
463
495
  // Synced
464
496
  var onSynced = (0, react_1.useCallback)(function () {
465
497
  if (!synced) {
@@ -469,42 +501,48 @@ var useYSpreadsheetV2 = function (_a) {
469
501
  (0, react_dom_1.flushSync)(function () {
470
502
  setupInitialSync();
471
503
  });
472
- // Build dependency graph, then sync backlog cells
473
- requestAnimationFrame(function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
474
- var backlog;
504
+ // Build dependency graph, then sync backlog cells. Deferred through a
505
+ // timer, not `requestAnimationFrame`: rAF is paused in background tabs,
506
+ // which left a backgrounded leader's backlog unevaluated indefinitely.
507
+ initialSyncTimerRef.current = setTimeout(function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
475
508
  return tslib_1.__generator(this, function (_a) {
476
509
  switch (_a.label) {
477
- case 0: return [4 /*yield*/, calculateNow({
478
- disableEvaluation: true,
479
- shouldResetCellDependencyGraph: true,
480
- })];
510
+ case 0:
511
+ initialSyncTimerRef.current = null;
512
+ return [4 /*yield*/, calculateNow({
513
+ disableEvaluation: true,
514
+ shouldResetCellDependencyGraph: true,
515
+ })];
481
516
  case 1:
482
517
  _a.sent();
483
- backlog = getBacklog();
484
- if (backlog.length) {
485
- syncRecalcCells(backlog, "backend");
486
- // Clear processed backlog entries from yRecalcCells
487
- doc.transact(function () {
488
- yRecalcCells.delete(0, yRecalcCells.length);
489
- }, origin);
490
- }
518
+ // Sync backlog after graph is initialized
519
+ drainBacklog();
520
+ graphReadyRef.current = true;
491
521
  return [2 /*return*/];
492
522
  }
493
523
  });
494
- }); });
524
+ }); }, 0);
495
525
  }
496
526
  setSynced(true);
497
527
  }
498
- }, [
499
- calculateNow,
500
- setupInitialSync,
501
- synced,
502
- syncRecalcCells,
503
- getBacklog,
504
- doc,
505
- yRecalcCells,
506
- skipInitialSync,
507
- ]);
528
+ }, [calculateNow, setupInitialSync, synced, drainBacklog, skipInitialSync]);
529
+ // A client that becomes leader after its initial sync (the previous leader
530
+ // left, or the election settled late) takes over whatever backlog is still
531
+ // in the document: as a non-leader it only mirrored those cells into its
532
+ // graph, so it evaluates them now — and only now clears them.
533
+ (0, ui_1.useIsomorphicLayoutEffect)(function () {
534
+ if (!isLeader || !synced || !graphReadyRef.current)
535
+ return;
536
+ drainBacklog();
537
+ }, [isLeader, synced, drainBacklog]);
538
+ (0, ui_1.useIsomorphicLayoutEffect)(function () {
539
+ return function () {
540
+ if (initialSyncTimerRef.current !== null) {
541
+ clearTimeout(initialSyncTimerRef.current);
542
+ initialSyncTimerRef.current = null;
543
+ }
544
+ };
545
+ }, []);
508
546
  // Sync state
509
547
  if ((provider === null || provider === void 0 ? void 0 : provider.synced) && !synced) {
510
548
  onSynced();
@@ -663,24 +701,45 @@ var useYSpreadsheetV2 = function (_a) {
663
701
  if (!synced) {
664
702
  return;
665
703
  }
704
+ var pending = new Set();
666
705
  // Sync all cells that are updated in the backend
667
706
  // // Observe recalc cells separat
668
707
  var onRecalcCellsChange = function (event) {
669
708
  var patches = (0, observables_1.getPatchDeltasFromEvent)(event);
670
709
  var origin = event.transaction.origin;
671
710
  if (origin !== "local") {
672
- requestAnimationFrame(function () {
711
+ // A timer, not `requestAnimationFrame`: rAF is paused in background
712
+ // tabs, so a backgrounded leader would stop evaluating remote patches.
713
+ var timer_1 = setTimeout(function () {
714
+ pending.delete(timer_1);
673
715
  syncRecalcCells(patches, origin);
674
- });
716
+ }, 0);
717
+ pending.add(timer_1);
675
718
  }
676
719
  };
677
720
  // Skip the first recalc cells change
678
721
  var sub = (0, observables_1.createObservable)(yRecalcCells).subscribe(onRecalcCellsChange);
679
- return function () { return sub.unsubscribe(); };
722
+ return function () {
723
+ var e_8, _a;
724
+ sub.unsubscribe();
725
+ try {
726
+ for (var pending_1 = tslib_1.__values(pending), pending_1_1 = pending_1.next(); !pending_1_1.done; pending_1_1 = pending_1.next()) {
727
+ var timer = pending_1_1.value;
728
+ clearTimeout(timer);
729
+ }
730
+ }
731
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
732
+ finally {
733
+ try {
734
+ if (pending_1_1 && !pending_1_1.done && (_a = pending_1.return)) _a.call(pending_1);
735
+ }
736
+ finally { if (e_8) throw e_8.error; }
737
+ }
738
+ };
680
739
  }, [syncRecalcCells, recalcCellsMaxEntries, synced, yRecalcCells]);
681
740
  // Broadcast patch
682
741
  var onBroadcastPatch = (0, react_1.useCallback)(function (patches) {
683
- var e_8, _a, e_9, _b;
742
+ var e_9, _a, e_10, _b;
684
743
  var _c;
685
744
  // Ignore push flag
686
745
  var disableRecalc = Boolean(patches.find(function (_a) {
@@ -716,12 +775,12 @@ var useYSpreadsheetV2 = function (_a) {
716
775
  }
717
776
  }
718
777
  }
719
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
778
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
720
779
  finally {
721
780
  try {
722
781
  if (patches_1_1 && !patches_1_1.done && (_a = patches_1.return)) _a.call(patches_1);
723
782
  }
724
- finally { if (e_8) throw e_8.error; }
783
+ finally { if (e_9) throw e_9.error; }
725
784
  }
726
785
  // Containment for this non-leader write path: an error may only
727
786
  // fill a cell with no effective value (the blank-after-reload case)
@@ -746,12 +805,12 @@ var useYSpreadsheetV2 = function (_a) {
746
805
  persistableErrorCellPatches_1.push(tslib_1.__assign(tslib_1.__assign({}, errorPatch), { value: (0, helpers_1.mergeErrorEffectiveValueIntoCellData)(currentCellData, incomingCellData) }));
747
806
  }
748
807
  }
749
- catch (e_9_1) { e_9 = { error: e_9_1 }; }
808
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
750
809
  finally {
751
810
  try {
752
811
  if (errorCellPatches_1_1 && !errorCellPatches_1_1.done && (_b = errorCellPatches_1.return)) _b.call(errorCellPatches_1);
753
812
  }
754
- finally { if (e_9) throw e_9.error; }
813
+ finally { if (e_10) throw e_10.error; }
755
814
  }
756
815
  if (persistableErrorCellPatches_1.length) {
757
816
  doc.transact(function () {
@@ -766,7 +825,7 @@ var useYSpreadsheetV2 = function (_a) {
766
825
  return;
767
826
  }
768
827
  doc.transact(function () {
769
- var e_10, _a, e_11, _b;
828
+ var e_11, _a, e_12, _b;
770
829
  var _c, _d, _e, _f;
771
830
  try {
772
831
  for (var patches_2 = tslib_1.__values(patches), patches_2_1 = patches_2.next(); !patches_2_1.done; patches_2_1 = patches_2.next()) {
@@ -793,7 +852,7 @@ var useYSpreadsheetV2 = function (_a) {
793
852
  (0, helpers_1.applyMapPatches)(yCellXfs, patches_4);
794
853
  }
795
854
  try {
796
- for (var _j = (e_11 = void 0, tslib_1.__values(documentMap.entries())), _k = _j.next(); !_k.done; _k = _j.next()) {
855
+ for (var _j = (e_12 = void 0, tslib_1.__values(documentMap.entries())), _k = _j.next(); !_k.done; _k = _j.next()) {
797
856
  var _l = tslib_1.__read(_k.value, 2), mappingKey = _l[0], _m = tslib_1.__read(_l[1], 1), ydoc = _m[0];
798
857
  if (patch === null || patch === void 0 ? void 0 : patch[mappingKey]) {
799
858
  var patches_5 = (_e = patch[mappingKey]) === null || _e === void 0 ? void 0 : _e[patchKey];
@@ -812,12 +871,12 @@ var useYSpreadsheetV2 = function (_a) {
812
871
  }
813
872
  }
814
873
  }
815
- catch (e_11_1) { e_11 = { error: e_11_1 }; }
874
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
816
875
  finally {
817
876
  try {
818
877
  if (_k && !_k.done && (_b = _j.return)) _b.call(_j);
819
878
  }
820
- finally { if (e_11) throw e_11.error; }
879
+ finally { if (e_12) throw e_12.error; }
821
880
  }
822
881
  // Recalc cells
823
882
  if ((_f = patch.recalcCells) === null || _f === void 0 ? void 0 : _f[type]) {
@@ -834,12 +893,12 @@ var useYSpreadsheetV2 = function (_a) {
834
893
  }
835
894
  }
836
895
  }
837
- catch (e_10_1) { e_10 = { error: e_10_1 }; }
896
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
838
897
  finally {
839
898
  try {
840
899
  if (patches_2_1 && !patches_2_1.done && (_a = patches_2.return)) _a.call(patches_2);
841
900
  }
842
- finally { if (e_10) throw e_10.error; }
901
+ finally { if (e_11) throw e_11.error; }
843
902
  }
844
903
  }, origin);
845
904
  onAfterBroadcastPatch === null || onAfterBroadcastPatch === void 0 ? void 0 : onAfterBroadcastPatch(patches, doc);
@@ -875,7 +934,7 @@ var useYSpreadsheetV2 = function (_a) {
875
934
  // Awareness
876
935
  (0, ui_1.useIsomorphicLayoutEffect)(function () {
877
936
  var onChangeAwareness = function () {
878
- var e_12, _a;
937
+ var e_13, _a;
879
938
  var _b, _c, _d, _e, _f;
880
939
  if (awareness) {
881
940
  var collaborators = [];
@@ -915,12 +974,12 @@ var useYSpreadsheetV2 = function (_a) {
915
974
  });
916
975
  }
917
976
  }
918
- catch (e_12_1) { e_12 = { error: e_12_1 }; }
977
+ catch (e_13_1) { e_13 = { error: e_13_1 }; }
919
978
  finally {
920
979
  try {
921
980
  if (_h && !_h.done && (_a = _g.return)) _a.call(_g);
922
981
  }
923
- finally { if (e_12) throw e_12.error; }
982
+ finally { if (e_13) throw e_13.error; }
924
983
  }
925
984
  setUsers(collaborators);
926
985
  }
@@ -942,6 +1001,7 @@ var useYSpreadsheetV2 = function (_a) {
942
1001
  awareness.setLocalStateField("userId", userId);
943
1002
  awareness.setLocalStateField("title", title);
944
1003
  awareness.setLocalStateField("sheetId", sheetId);
1004
+ awareness.setLocalStateField("canWrite", canWrite);
945
1005
  if (resolvedAwarenessScopeId) {
946
1006
  awareness.setLocalStateField("docGuid", resolvedAwarenessScopeId);
947
1007
  }
@@ -963,6 +1023,7 @@ var useYSpreadsheetV2 = function (_a) {
963
1023
  }, [
964
1024
  awareness,
965
1025
  resolvedAwarenessScopeId,
1026
+ canWrite,
966
1027
  userId,
967
1028
  title,
968
1029
  sheetId,
@@ -23,6 +23,18 @@ export type UseYSpreadsheetPropsV2<T extends CellData, S extends Sheet, C extend
23
23
  * convention to remain wire-compatible.
24
24
  */
25
25
  awarenessScopeId?: string;
26
+ /**
27
+ * Whether this client may persist to the shared document (the host's
28
+ * edit permission; `false` for view-only sessions). Published on awareness
29
+ * as `canWrite` and consulted by the leader election: the leader is the
30
+ * peer that evaluates backend/agent recalc backlogs and writes the computed
31
+ * values back, so a client whose writes the server refuses must never win —
32
+ * every value it computed would be dropped. Peers whose awareness state has
33
+ * no `canWrite` field (older clients, REST writers) count as writers. When
34
+ * no writer is present there is no leader: nothing could persist the values
35
+ * anyway. Default: `true`.
36
+ */
37
+ canWrite?: boolean;
26
38
  userId: string | number;
27
39
  title: string;
28
40
  sheetId: number;
@@ -142,7 +154,7 @@ export type UseYSpreadsheetPropsV2<T extends CellData, S extends Sheet, C extend
142
154
  };
143
155
  export type YRowData = Y.Map<Y.Array<CellData | null>>;
144
156
  export type YSheetData = Y.Array<YRowData | null>;
145
- export declare const useYSpreadsheetV2: <T extends CellData, S extends Sheet, C extends EmbeddedChart, O extends EmbeddedObject>({ onChangeSheetData, onChangeSheets, onChangeTables, onChangeCharts, onChangeEmbeds, onChangeConditionalFormats, onChangeDataValidations, onChangeCitations, onAfterBroadcastPatch, recalcCellsMaxEntries, onChangeNamedRanges, onChangeProtectedRanges, onChangePivotTables, enqueueCalculation, enqueueGraphOperation, reevaluateDerivationsForCells, onChangeCellXfs, onChangeSharedStrings, calculateNow, onChangeActiveSheet, clientOnlyFunctionPattern, initialSheets, awarenessScopeId, userId, title, sheetId, activeCell, kind, agentInitiator, selections, doc, provider, useV3, sheetDataVersion, onMigrationComplete, deleteV2AfterMigration, skipInitialSync, supportLegacySharedStringsArray, }: UseYSpreadsheetPropsV2<T, S, C, O>) => {
157
+ export declare const useYSpreadsheetV2: <T extends CellData, S extends Sheet, C extends EmbeddedChart, O extends EmbeddedObject>({ onChangeSheetData, onChangeSheets, onChangeTables, onChangeCharts, onChangeEmbeds, onChangeConditionalFormats, onChangeDataValidations, onChangeCitations, onAfterBroadcastPatch, recalcCellsMaxEntries, onChangeNamedRanges, onChangeProtectedRanges, onChangePivotTables, enqueueCalculation, enqueueGraphOperation, reevaluateDerivationsForCells, onChangeCellXfs, onChangeSharedStrings, calculateNow, onChangeActiveSheet, clientOnlyFunctionPattern, initialSheets, awarenessScopeId, canWrite, userId, title, sheetId, activeCell, kind, agentInitiator, selections, doc, provider, useV3, sheetDataVersion, onMigrationComplete, deleteV2AfterMigration, skipInitialSync, supportLegacySharedStringsArray, }: UseYSpreadsheetPropsV2<T, S, C, O>) => {
146
158
  synced: boolean;
147
159
  users: Collaborator[];
148
160
  onBroadcastPatch: (patches: [patch: SpreadsheetPatch<Patch>, type?: HistoryType | undefined | null][]) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"use-yspreadsheet-v2.d.ts","sourceRoot":"","sources":["../../use-yspreadsheet-v2.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-yspreadsheet-v2.d.ts","sourceRoot":"","sources":["../../use-yspreadsheet-v2.ts"],"names":[],"mappings":"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"}
@@ -52,7 +52,7 @@ const getUserEnteredValueFromYDocV3 = (ySheetDataV3, sheetId, rowIndex, columnIn
52
52
  import { createDeepObservable, createObservable, createSheetDataObservable, getPatchDeltasFromEvent, } from "./observables";
53
53
  // Add a single null entry to the YSheetData
54
54
  const origin = "local";
55
- export const useYSpreadsheetV2 = ({ onChangeSheetData, onChangeSheets, onChangeTables, onChangeCharts, onChangeEmbeds, onChangeConditionalFormats, onChangeDataValidations, onChangeCitations, onAfterBroadcastPatch, recalcCellsMaxEntries, onChangeNamedRanges, onChangeProtectedRanges, onChangePivotTables, enqueueCalculation, enqueueGraphOperation, reevaluateDerivationsForCells, onChangeCellXfs, onChangeSharedStrings, calculateNow, onChangeActiveSheet, clientOnlyFunctionPattern, initialSheets, awarenessScopeId, userId, title, sheetId, activeCell, kind, agentInitiator, selections, doc, provider, useV3 = false, sheetDataVersion = "v2", onMigrationComplete, deleteV2AfterMigration = false, skipInitialSync = false, supportLegacySharedStringsArray = false, }) => {
55
+ export const useYSpreadsheetV2 = ({ onChangeSheetData, onChangeSheets, onChangeTables, onChangeCharts, onChangeEmbeds, onChangeConditionalFormats, onChangeDataValidations, onChangeCitations, onAfterBroadcastPatch, recalcCellsMaxEntries, onChangeNamedRanges, onChangeProtectedRanges, onChangePivotTables, enqueueCalculation, enqueueGraphOperation, reevaluateDerivationsForCells, onChangeCellXfs, onChangeSharedStrings, calculateNow, onChangeActiveSheet, clientOnlyFunctionPattern, initialSheets, awarenessScopeId, canWrite = true, userId, title, sheetId, activeCell, kind, agentInitiator, selections, doc, provider, useV3 = false, sheetDataVersion = "v2", onMigrationComplete, deleteV2AfterMigration = false, skipInitialSync = false, supportLegacySharedStringsArray = false, }) => {
56
56
  const [synced, setSynced] = useState(false);
57
57
  const [users, setUsers] = useState([]);
58
58
  const [isLeader, setIsLeader] = useState(false);
@@ -68,19 +68,24 @@ export const useYSpreadsheetV2 = ({ onChangeSheetData, onChangeSheets, onChangeT
68
68
  const docStates = resolvedAwarenessScopeId
69
69
  ? entries.filter(([_, state]) => state?.docGuid === resolvedAwarenessScopeId)
70
70
  : entries;
71
- if (!docStates.length) {
71
+ // Only peers that can persist may lead (see `canWrite`). A view-only
72
+ // client's recalc write-backs are refused by the server, so electing it
73
+ // silently drops every computed value. A missing field is a writer.
74
+ const writers = docStates
75
+ .filter(([_, state]) => state?.canWrite !== false)
76
+ .map(([clientId]) => clientId);
77
+ if (!canWrite || !writers.length) {
72
78
  setIsLeader(false);
73
79
  return;
74
80
  }
75
- const states = docStates.map(([clientId]) => clientId);
76
- const minId = Math.min(...states);
81
+ const minId = Math.min(...writers);
77
82
  // Always include self in the elec
78
83
  setIsLeader(doc.clientID === minId);
79
84
  };
80
85
  awareness.on("change", updateLeader);
81
86
  updateLeader(); // Initial check
82
87
  return () => awareness.off("change", updateLeader);
83
- }, [awareness, doc, resolvedAwarenessScopeId]);
88
+ }, [awareness, doc, resolvedAwarenessScopeId, canWrite]);
84
89
  useIsomorphicLayoutEffect(() => {
85
90
  isLeaderRef.current = isLeader;
86
91
  }, [isLeader]);
@@ -219,6 +224,12 @@ export const useYSpreadsheetV2 = ({ onChangeSheetData, onChangeSheets, onChangeT
219
224
  .flatMap((entry) => entry.patches)
220
225
  .filter(([, , source]) => source === "backend" || source === "agent");
221
226
  }, [yRecalcCells]);
227
+ /**
228
+ * Set once the initial sync has built the dependency graph and replayed the
229
+ * backlog, so a later leadership hand-over can replay it again.
230
+ */
231
+ const graphReadyRef = useRef(false);
232
+ const initialSyncTimerRef = useRef(null);
222
233
  // Trigger cell recalcs
223
234
  const syncRecalcCells = useCallback((recalcCells, origin) => {
224
235
  for (const [_, position, source] of recalcCells) {
@@ -389,6 +400,24 @@ export const useYSpreadsheetV2 = ({ onChangeSheetData, onChangeSheets, onChangeT
389
400
  onMigrationComplete,
390
401
  deleteV2AfterMigration,
391
402
  ]);
403
+ /**
404
+ * Replay the backend/agent recalc backlog into the local graph — and, on
405
+ * the leader, evaluate it. Only the leader clears the entries, and only once
406
+ * they sit in its calculation queue: a non-leader merely graph-enqueues
407
+ * (no evaluation), so if it deleted them the leader would never recompute
408
+ * the backlog at all.
409
+ */
410
+ const drainBacklog = useCallback(() => {
411
+ const backlog = getBacklog();
412
+ if (!backlog.length)
413
+ return;
414
+ syncRecalcCells(backlog, "backend");
415
+ if (isLeaderRef.current) {
416
+ doc.transact(() => {
417
+ yRecalcCells.delete(0, yRecalcCells.length);
418
+ }, origin);
419
+ }
420
+ }, [getBacklog, syncRecalcCells, doc, yRecalcCells]);
392
421
  // Synced
393
422
  const onSynced = useCallback(() => {
394
423
  if (!synced) {
@@ -398,35 +427,40 @@ export const useYSpreadsheetV2 = ({ onChangeSheetData, onChangeSheets, onChangeT
398
427
  flushSync(() => {
399
428
  setupInitialSync();
400
429
  });
401
- // Build dependency graph, then sync backlog cells
402
- requestAnimationFrame(async () => {
430
+ // Build dependency graph, then sync backlog cells. Deferred through a
431
+ // timer, not `requestAnimationFrame`: rAF is paused in background tabs,
432
+ // which left a backgrounded leader's backlog unevaluated indefinitely.
433
+ initialSyncTimerRef.current = setTimeout(async () => {
434
+ initialSyncTimerRef.current = null;
403
435
  await calculateNow({
404
436
  disableEvaluation: true,
405
437
  shouldResetCellDependencyGraph: true,
406
438
  });
407
439
  // Sync backlog after graph is initialized
408
- const backlog = getBacklog();
409
- if (backlog.length) {
410
- syncRecalcCells(backlog, "backend");
411
- // Clear processed backlog entries from yRecalcCells
412
- doc.transact(() => {
413
- yRecalcCells.delete(0, yRecalcCells.length);
414
- }, origin);
415
- }
416
- });
440
+ drainBacklog();
441
+ graphReadyRef.current = true;
442
+ }, 0);
417
443
  }
418
444
  setSynced(true);
419
445
  }
420
- }, [
421
- calculateNow,
422
- setupInitialSync,
423
- synced,
424
- syncRecalcCells,
425
- getBacklog,
426
- doc,
427
- yRecalcCells,
428
- skipInitialSync,
429
- ]);
446
+ }, [calculateNow, setupInitialSync, synced, drainBacklog, skipInitialSync]);
447
+ // A client that becomes leader after its initial sync (the previous leader
448
+ // left, or the election settled late) takes over whatever backlog is still
449
+ // in the document: as a non-leader it only mirrored those cells into its
450
+ // graph, so it evaluates them now — and only now clears them.
451
+ useIsomorphicLayoutEffect(() => {
452
+ if (!isLeader || !synced || !graphReadyRef.current)
453
+ return;
454
+ drainBacklog();
455
+ }, [isLeader, synced, drainBacklog]);
456
+ useIsomorphicLayoutEffect(() => {
457
+ return () => {
458
+ if (initialSyncTimerRef.current !== null) {
459
+ clearTimeout(initialSyncTimerRef.current);
460
+ initialSyncTimerRef.current = null;
461
+ }
462
+ };
463
+ }, []);
430
464
  // Sync state
431
465
  if (provider?.synced && !synced) {
432
466
  onSynced();
@@ -557,20 +591,29 @@ export const useYSpreadsheetV2 = ({ onChangeSheetData, onChangeSheets, onChangeT
557
591
  if (!synced) {
558
592
  return;
559
593
  }
594
+ const pending = new Set();
560
595
  // Sync all cells that are updated in the backend
561
596
  // // Observe recalc cells separat
562
597
  const onRecalcCellsChange = (event) => {
563
598
  const patches = getPatchDeltasFromEvent(event);
564
599
  const origin = event.transaction.origin;
565
600
  if (origin !== "local") {
566
- requestAnimationFrame(() => {
601
+ // A timer, not `requestAnimationFrame`: rAF is paused in background
602
+ // tabs, so a backgrounded leader would stop evaluating remote patches.
603
+ const timer = setTimeout(() => {
604
+ pending.delete(timer);
567
605
  syncRecalcCells(patches, origin);
568
- });
606
+ }, 0);
607
+ pending.add(timer);
569
608
  }
570
609
  };
571
610
  // Skip the first recalc cells change
572
611
  const sub = createObservable(yRecalcCells).subscribe(onRecalcCellsChange);
573
- return () => sub.unsubscribe();
612
+ return () => {
613
+ sub.unsubscribe();
614
+ for (const timer of pending)
615
+ clearTimeout(timer);
616
+ };
574
617
  }, [syncRecalcCells, recalcCellsMaxEntries, synced, yRecalcCells]);
575
618
  // Broadcast patch
576
619
  const onBroadcastPatch = useCallback((patches) => {
@@ -777,6 +820,7 @@ export const useYSpreadsheetV2 = ({ onChangeSheetData, onChangeSheets, onChangeT
777
820
  awareness.setLocalStateField("userId", userId);
778
821
  awareness.setLocalStateField("title", title);
779
822
  awareness.setLocalStateField("sheetId", sheetId);
823
+ awareness.setLocalStateField("canWrite", canWrite);
780
824
  if (resolvedAwarenessScopeId) {
781
825
  awareness.setLocalStateField("docGuid", resolvedAwarenessScopeId);
782
826
  }
@@ -798,6 +842,7 @@ export const useYSpreadsheetV2 = ({ onChangeSheetData, onChangeSheets, onChangeT
798
842
  }, [
799
843
  awareness,
800
844
  resolvedAwarenessScopeId,
845
+ canWrite,
801
846
  userId,
802
847
  title,
803
848
  sheetId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rowsncolumns/y-spreadsheet",
3
- "version": "15.0.2",
3
+ "version": "15.0.3",
4
4
  "main": "./dist/cjs/index.js",
5
5
  "module": "./dist/esm/index.js",
6
6
  "exports": {