@fileverse-dev/dsheet 4.1.22 → 4.1.23-stabilise-package-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.
Files changed (106) hide show
  1. package/README.md +10 -0
  2. package/dist/editor/components/editor-workbook.d.ts +6 -0
  3. package/dist/editor/components/sidebar/editor-right-sidebar.d.ts +3 -1
  4. package/dist/editor/components/sidebar/sidebar-offsets.d.ts +12 -0
  5. package/dist/editor/components/sidebar/sidebar-offsets.test.d.ts +1 -0
  6. package/dist/editor/contexts/editor-context.d.ts +7 -0
  7. package/dist/editor/hooks/use-editor-data.d.ts +1 -0
  8. package/dist/editor/hooks/use-editor-sync.d.ts +5 -1
  9. package/dist/editor/types.d.ts +54 -1
  10. package/dist/editor/utils/activate-sheet-for-link.d.ts +3 -0
  11. package/dist/editor/utils/active-sheet-keeper.d.ts +21 -0
  12. package/dist/editor/utils/after-update-cell.d.ts +6 -0
  13. package/dist/editor/utils/after-update-cell.test.d.ts +1 -0
  14. package/dist/editor/utils/apply-comment-markers.d.ts +3 -1
  15. package/dist/editor/utils/apply-comment-markers.test.d.ts +1 -0
  16. package/dist/editor/utils/calc-chain-ydoc-update.test.d.ts +1 -0
  17. package/dist/editor/utils/content-change.d.ts +48 -0
  18. package/dist/editor/utils/content-change.test.d.ts +1 -0
  19. package/dist/editor/utils/content-fingerprint.d.ts +37 -0
  20. package/dist/editor/utils/content-fingerprint.test.d.ts +1 -0
  21. package/dist/editor/utils/editor-handle.d.ts +1 -1
  22. package/dist/editor/utils/format-gate.d.ts +27 -0
  23. package/dist/editor/utils/format-gate.test.d.ts +1 -0
  24. package/dist/editor/utils/legacy-on-change.d.ts +20 -0
  25. package/dist/editor/utils/legacy-on-change.test.d.ts +1 -0
  26. package/dist/editor/utils/navigate-to-sheet.d.ts +22 -0
  27. package/dist/editor/utils/patch-plain-celldata.d.ts +19 -0
  28. package/dist/editor/utils/patch-plain-celldata.test.d.ts +1 -0
  29. package/dist/editor/utils/rebuild-indexeddb-store.d.ts +19 -0
  30. package/dist/editor/utils/rebuild-indexeddb-store.failure.test.d.ts +1 -0
  31. package/dist/editor/utils/rebuild-indexeddb-store.test.d.ts +1 -0
  32. package/dist/editor/utils/remote-apply-guard.d.ts +48 -0
  33. package/dist/editor/utils/remote-apply-guard.test.d.ts +1 -0
  34. package/dist/editor/utils/sheet-ydoc-sync-utils.d.ts +13 -4
  35. package/dist/editor/utils/sheet-ydoc-sync-utils.test.d.ts +1 -0
  36. package/dist/editor/utils/structural-edit-formula-sync.test.d.ts +1 -0
  37. package/dist/editor/utils/update-ydoc.d.ts +9 -1
  38. package/dist/editor/utils/wait-for-sync.d.ts +35 -0
  39. package/dist/editor/utils/wait-for-sync.test.d.ts +1 -0
  40. package/dist/{es-S4GKlN-t.js → es-BlDQ6jCL.js} +1 -0
  41. package/dist/{executeStringFunction-CQ922vEp.js → executeStringFunction-D5BTPrXL.js} +10265 -9843
  42. package/dist/formula.js +1 -1
  43. package/dist/{hi-DMMTDTxZ.js → hi-CP0ta0Yk.js} +1 -0
  44. package/dist/{index-DhQTrCQd.js → index-BXNWi7s5.js} +22557 -21465
  45. package/dist/index.d.ts +1 -1
  46. package/dist/index.es.js +31 -31
  47. package/dist/persistence-utils-CSKBobX8.js +151 -0
  48. package/dist/persistence-utils.d.ts +2 -0
  49. package/dist/persistence.append.test.d.ts +1 -0
  50. package/dist/persistence.d.ts +13 -0
  51. package/dist/persistence.fingerprint.test.d.ts +1 -0
  52. package/dist/persistence.js +122 -74
  53. package/dist/sheet-engine/core/api/cell.d.ts +20 -1
  54. package/dist/sheet-engine/core/api/remote-apply.test.d.ts +1 -0
  55. package/dist/sheet-engine/core/api/sheet-flowdata-lifecycle.d.ts +1 -0
  56. package/dist/sheet-engine/core/api/sheet-flowdata-lifecycle.test.d.ts +1 -0
  57. package/dist/sheet-engine/core/index.d.ts +1 -1
  58. package/dist/sheet-engine/core/locale/en.d.ts +1 -0
  59. package/dist/sheet-engine/core/locale/es.d.ts +1 -0
  60. package/dist/sheet-engine/core/locale/hi.d.ts +1 -0
  61. package/dist/sheet-engine/core/locale/zh.d.ts +1 -0
  62. package/dist/sheet-engine/core/locale/zh_tw.d.ts +1 -0
  63. package/dist/sheet-engine/core/modules/b6-ydoc-writes.test.d.ts +1 -0
  64. package/dist/sheet-engine/core/modules/border.d.ts +9 -0
  65. package/dist/sheet-engine/core/modules/cell-shift.d.ts +11 -0
  66. package/dist/sheet-engine/core/modules/cell.commit-ydoc.test.d.ts +1 -0
  67. package/dist/sheet-engine/core/modules/dataVerification.d.ts +15 -0
  68. package/dist/sheet-engine/core/modules/engine-hot-spots.test.d.ts +1 -0
  69. package/dist/sheet-engine/core/modules/formula-async-eval.d.ts +5 -0
  70. package/dist/sheet-engine/core/modules/formula-narrowing.test.d.ts +1 -0
  71. package/dist/sheet-engine/core/modules/formula-snapshot-eval.d.ts +2 -0
  72. package/dist/sheet-engine/core/modules/formula-transitive-deps.d.ts +5 -1
  73. package/dist/sheet-engine/core/modules/formula-warmup.d.ts +37 -0
  74. package/dist/sheet-engine/core/modules/formula-warmup.test.d.ts +1 -0
  75. package/dist/sheet-engine/core/modules/formula.d.ts +57 -1
  76. package/dist/sheet-engine/core/modules/formula.dep-graph.test.d.ts +1 -0
  77. package/dist/sheet-engine/core/modules/formula.str-change.test.d.ts +1 -0
  78. package/dist/sheet-engine/core/modules/formula.wide-seed.test.d.ts +1 -0
  79. package/dist/sheet-engine/core/modules/history-calc-chain.d.ts +39 -0
  80. package/dist/sheet-engine/core/modules/history-calc-chain.test.d.ts +1 -0
  81. package/dist/sheet-engine/core/modules/history-grid-size.d.ts +16 -0
  82. package/dist/sheet-engine/core/modules/history-grid-size.test.d.ts +1 -0
  83. package/dist/sheet-engine/core/modules/index.d.ts +3 -2
  84. package/dist/sheet-engine/core/paste/paste-dep-graph.test.d.ts +1 -0
  85. package/dist/sheet-engine/core/paste-helpers/calculate-range-cell-size.d.ts +14 -0
  86. package/dist/sheet-engine/core/paste-helpers/calculate-range-cell-size.test.d.ts +1 -0
  87. package/dist/sheet-engine/core/settings.d.ts +15 -1
  88. package/dist/sheet-engine/core/utils/ydoc-celldata-changes.d.ts +29 -2
  89. package/dist/sheet-engine/react/components/ContextMenu/sheet-tab-menu-items.d.ts +15 -0
  90. package/dist/sheet-engine/react/components/Workbook/api.d.ts +4 -0
  91. package/dist/sheet-engine/react/components/Workbook/denomination-scan.d.ts +16 -0
  92. package/dist/sheet-engine/react/components/Workbook/denomination-scan.test.d.ts +1 -0
  93. package/dist/sheet-engine/react/components/Workbook/index.d.ts +2 -0
  94. package/dist/style.css +1 -1
  95. package/dist/sync-local/SyncManager.d.ts +2 -2
  96. package/dist/sync-local/SyncManager.remote-apply.test.d.ts +1 -0
  97. package/dist/sync-local/types/index.d.ts +2 -1
  98. package/dist/{template-data-list-BYOIK_Nd.js → template-data-list-apgmwRAT.js} +18 -10
  99. package/dist/{use-xlsx-import-impl-xphBNZu3.js → use-xlsx-import-impl-gsG9w9qV.js} +120 -119
  100. package/dist/{xlsx-defined-names-3g5n40BA.js → xlsx-defined-names-dZveijsB.js} +2 -2
  101. package/dist/{xlsx-export-impl-DXyQpmMi.js → xlsx-export-impl-B10lK_L2.js} +4 -4
  102. package/dist/{xlsx-hyperlink-inline-Cl9CbP5N.js → xlsx-hyperlink-inline-BFbPe75M.js} +2 -2
  103. package/dist/{zh-Bv4KIDiJ.js → zh-CmOCFd5t.js} +1 -0
  104. package/dist/{zh_tw-BdpsK45h.js → zh_tw-BqyRw1gX.js} +1 -0
  105. package/package.json +2 -2
  106. package/dist/persistence-utils-BXFajzvq.js +0 -98
@@ -738,6 +738,7 @@ declare const _default: {
738
738
  cancelText: string;
739
739
  chooseText: string;
740
740
  focus: string;
741
+ copyLink: string;
741
742
  tipNameRepeat: string;
742
743
  noMoreSheet: string;
743
744
  confirmDelete: string;
@@ -1,4 +1,13 @@
1
1
  import { Context } from '../context';
2
2
 
3
3
  export declare function getBorderInfoComputeRange(ctx: Context, dataset_row_st: number, dataset_row_ed: number, dataset_col_st: number, dataset_col_ed: number, sheetId?: string): Record<string, any>;
4
+ /**
5
+ * getBorderInfoComputeRange for the current sheet's canvas draw, cached (C6).
6
+ * The draw re-expanded every borderInfo entry on every repaint. Keyed by the
7
+ * identities of borderInfo, merge, rowhidden and colhidden (Immer gives each
8
+ * a new identity on change; merged cells' `mc` follows `merge`), the grid
9
+ * size and the drawn bounds, so redraws for scroll-back, selection moves,
10
+ * edits and remote cells reuse the result. Callers only read it.
11
+ */
12
+ export declare function getBorderInfoComputeRangeCached(ctx: Context, dataset_row_st: number, dataset_row_ed: number, dataset_col_st: number, dataset_col_ed: number): Record<string, any>;
4
13
  export declare function getBorderInfoCompute(ctx: Context, sheetId?: string): any;
@@ -0,0 +1,11 @@
1
+ import { Context } from '../context';
2
+
3
+ /** A selection rectangle: `row` and `column` are [start, end]. */
4
+ export type CellShiftRange = {
5
+ row: number[];
6
+ column: number[];
7
+ };
8
+ /** Delete the selected cells and shift the rest left or up. */
9
+ export declare function deleteCellsShift(ctx: Context, direction: 'left' | 'up', range: CellShiftRange): void;
10
+ /** Insert empty cells at the selection and shift the rest right or down. */
11
+ export declare function insertCellsShift(ctx: Context, direction: 'right' | 'down', range: CellShiftRange): void;
@@ -2,6 +2,20 @@ import { Context, GlobalCache } from '..';
2
2
 
3
3
  export declare function dataRangeSelection(ctx: Context, cache: GlobalCache, rangT: string, type: string, value: string): void;
4
4
  export declare function getDropdownList(ctx: Context, txt: string): (string | number | boolean)[];
5
+ type DropdownOptions = {
6
+ list: (string | number | boolean)[];
7
+ set: Set<unknown>;
8
+ };
9
+ /**
10
+ * Parsed dropdown options, cached per option text (C7). The canvas validates
11
+ * every visible dropdown cell on every draw, and getDropdownList re-splits
12
+ * and de-duplicates with list.includes, O(L^2) per cell. When the options
13
+ * come from a cell range, the key also includes the identity of the source
14
+ * sheet's data, so an edit there re-reads the range. Shared and read-only.
15
+ */
16
+ export declare function getDropdownOptions(ctx: Context, txt: string): DropdownOptions;
17
+ /** `value1.split(',')`, memoized for the canvas pill colours (C7). */
18
+ export declare function splitDropdownOptions(value1: string): string[];
5
19
  export declare function validateIdCard(ctx: Context, idCard: string): boolean;
6
20
  export declare function validateCellData(ctx: Context, item: any, cellValue: any): any;
7
21
  export declare function checkboxChange(ctx: Context, r: number, c: number): void;
@@ -17,3 +31,4 @@ export declare function setDropdownValue(ctx: Context, value: string, arr: any,
17
31
  column: number;
18
32
  }): void;
19
33
  export declare function confirmMessage(ctx: Context, generalDialog: any, dataVerification: any): boolean;
34
+ export {};
@@ -37,6 +37,11 @@ export type FormulaAsyncEvalJob = {
37
37
  impactedByCircular: string[];
38
38
  cycleNodes: string[];
39
39
  workerSnapshotKey: string;
40
+ /**
41
+ * Set on a forced full pass: the dependency-graph epoch it started at. The
42
+ * last chunk marks the graph complete if the epoch is unchanged (C8).
43
+ */
44
+ fullPassEpoch?: number | null;
40
45
  nextIndex: number;
41
46
  total: number;
42
47
  debug?: FormulaEvalDebug;
@@ -20,6 +20,8 @@ export type SnapshotFormulaResult = {
20
20
  spe?: unknown;
21
21
  deps: string[];
22
22
  isError: boolean;
23
+ /** Read a sheet name that doesn't exist; the main thread keeps it on every commit's run list (C8). */
24
+ unresolvedSheetRef?: boolean;
23
25
  };
24
26
  export type SnapshotEvalInput = {
25
27
  sheets: SnapshotSheet[];
@@ -3,5 +3,9 @@ export declare function toFormulaDepCellKey(sheetId: string, r: number, c: numbe
3
3
  /**
4
4
  * Walk revDepsByCell from a changed cell to collect every formula cell that
5
5
  * must recalculate (direct + transitive dependents).
6
+ *
7
+ * `extraFormulaSeeds` are formulas that run on every commit whatever the
8
+ * graph says (very large ranges, named ranges covering the edited cell). They
9
+ * join the same walk, so formulas that read their results are reached too.
6
10
  */
7
- export declare function collectTransitiveFormulaDependents(originCellKey: string, revDepsByCell: Map<string, Set<string>>): Set<string>;
11
+ export declare function collectTransitiveFormulaDependents(originCellKey: string, revDepsByCell: Map<string, Set<string>>, extraFormulaSeeds?: Iterable<string>): Set<string>;
@@ -0,0 +1,37 @@
1
+ import { Context } from '../context';
2
+
3
+ export declare const FORMULA_WARMUP_BUDGET_MS = 8;
4
+ export declare const FORMULA_WARMUP_DEBOUNCE_MS = 2000;
5
+ export declare const FORMULA_WARMUP_IDLE_TIMEOUT_MS = 1000;
6
+ export type FormulaWarmupResult = 'complete' | 'aborted';
7
+ export type FormulaWarmupOptions = {
8
+ /** Longest a slice keeps evaluating before it yields (default 8). */
9
+ budgetMs: number;
10
+ /** Runs the next slice later (idle callback in the app). */
11
+ schedule: (cb: () => void) => void;
12
+ isCancelled?: () => boolean;
13
+ };
14
+ /**
15
+ * Formula functions that are `async` (they fetch over the network, e.g.
16
+ * ETHERSCAN, EOA). The warm-up records their arguments but never calls them.
17
+ */
18
+ export declare function isAsyncFormulaFunction(name: string): boolean;
19
+ /**
20
+ * Walk the calc chain in slices and record every formula's dependencies, then
21
+ * mark the graph complete (C8). Resolves 'aborted' if the graph is cleared
22
+ * while it runs, a tab holding formulas is sparse, or `isCancelled` says so.
23
+ *
24
+ * Pass a getter to read the latest context in each slice (the Workbook does);
25
+ * a plain context is used as is.
26
+ */
27
+ export declare function warmFormulaDependencyGraph(ctxOrGetter: Context | (() => Context), opts: FormulaWarmupOptions): Promise<FormulaWarmupResult>;
28
+ /**
29
+ * Run the warm-up in the app: on `trigger()` (data ready after mount) and
30
+ * again `FORMULA_WARMUP_DEBOUNCE_MS` after each `markDepGraphIncomplete()`.
31
+ * Slices run in idle callbacks (setTimeout without requestIdleCallback) and
32
+ * only while the page is visible.
33
+ */
34
+ export declare function scheduleFormulaWarmup(getCtx: () => Context): {
35
+ trigger(): void;
36
+ dispose(): void;
37
+ };
@@ -51,6 +51,24 @@ export declare class FormulaCache {
51
51
  * affect them even when no precise reverse edge exists.
52
52
  */
53
53
  formulasWithWideRangeDeps: Set<string>;
54
+ /**
55
+ * True once a full pass has evaluated every formula in the chain since the
56
+ * indexes were last reset, so `revDepsByCell` lists every dependent of every
57
+ * cell (C8). While true, a commit to a cell with no dependents runs no
58
+ * formula pass. Cleared by `markDepGraphIncomplete`.
59
+ */
60
+ depGraphComplete: boolean;
61
+ /**
62
+ * Bumped each time the flag is cleared. A deferred full pass records it at
63
+ * start and sets the flag only if nothing cleared it while it ran.
64
+ */
65
+ depGraphEpoch: number;
66
+ /**
67
+ * Grid size (`rows x cols`) of each dense tab when the graph was completed.
68
+ * Whole-row and whole-column references were recorded at that size, so a
69
+ * commit to a tab that has grown since takes the full pass again.
70
+ */
71
+ depGraphSheetSizes: Map<string, string>;
54
72
  /**
55
73
  * Dependency collection state for the currently-parsed formula, set by `execfunction`.
56
74
  * When null, dependency recording is disabled.
@@ -66,6 +84,21 @@ export declare class FormulaCache {
66
84
  hits: number;
67
85
  misses: number;
68
86
  };
87
+ /**
88
+ * Drop every recorded formula dependency, back to the state a fresh mount
89
+ * has. Used when a sheet's formula list is replaced from outside the
90
+ * engine (a collaborator's calcChain change, A4).
91
+ */
92
+ resetDependencyIndexes(): void;
93
+ /**
94
+ * The graph may miss edges: formulas moved, were rewritten or entered the
95
+ * chain without being evaluated. Commits take the full pass again until the
96
+ * next full pass completes.
97
+ */
98
+ markDepGraphIncomplete(): void;
99
+ /** Called after each `markDepGraphIncomplete` (the C8 warm-up re-runs). */
100
+ depGraphIncompleteListeners: Set<() => void>;
101
+ onDepGraphIncomplete(listener: () => void): () => void;
69
102
  constructor();
70
103
  materializeFullRangeFragment(context: Context, sheetId: string, flowdata: CellMatrix | null | undefined, startRow: number, endRow: number, startCol: number, endCol: number): {
71
104
  fragment: any[][];
@@ -77,8 +110,27 @@ export declare class FormulaCache {
77
110
  export declare function iscelldata(txt: string): boolean;
78
111
  export declare function getcellrange(ctx: Context, txt: string, formulaId?: string): any;
79
112
  export declare function getAllFunctionGroup(ctx: Context): any[];
113
+ /**
114
+ * delFunctionGroup for many cells of one sheet: the chain and the dynamic
115
+ * array list are filtered once, not scanned and copied per cell. Same result
116
+ * as calling delFunctionGroup for each cell.
117
+ */
118
+ export declare function delFunctionGroupBatch(ctx: Context, id: string, cells: {
119
+ r: number;
120
+ c: number;
121
+ }[]): void;
80
122
  export declare function delFunctionGroup(ctx: Context, r: number, c: number, id?: string): void;
81
123
  export declare function insertUpdateFunctionGroup(ctx: Context, r: number, c: number, id?: string, calcChainSet?: Set<string>): void;
124
+ /**
125
+ * Drop every recorded formula dependency, back to a fresh mount's state, and
126
+ * mark the graph incomplete (A4, C8).
127
+ */
128
+ export declare function resetFormulaDependencyIndexes(ctx: Context): void;
129
+ /**
130
+ * End of a full pass that started at `epoch` (C8): every formula in the chain
131
+ * has recorded its dependencies, unless the graph was invalidated meanwhile.
132
+ */
133
+ export declare function finishFullFormulaPass(ctx: Context, epoch: number | null | undefined): void;
82
134
  export declare function execfunction(ctx: Context, txt: string, r: number, c: number, id?: string, calcChainSet?: Set<string>, isrefresh?: boolean, notInsertFunc?: boolean): any[];
83
135
  export declare function groupValuesRefresh(ctx: Context): void;
84
136
  /** Apply worker chunk output onto the live context (main thread only). */
@@ -158,12 +210,16 @@ export declare function markRangeSelectionDirty(ctx: Context): void;
158
210
  export declare function getFormulaRangeIndexForKeyboardSync($editor: HTMLDivElement): number | null;
159
211
  export declare function handleFormulaInput(ctx: Context, $copyTo: HTMLDivElement | null | undefined, $editor: HTMLDivElement, kcode: number, preText?: string, refreshRangeSelect?: boolean): void;
160
212
  export declare function toggleFormulaAbsoluteReferenceAtCaret(ctx: Context, $copyTo: HTMLDivElement | null | undefined, $editor: HTMLDivElement | null | undefined): boolean;
213
+ export type FormulaTabs = {
214
+ editedTab: string;
215
+ formulaTab: string;
216
+ };
161
217
  /** True while picking a range for a formula (sheet selection drives references). */
162
218
  export declare function isLegacyFormulaRangeMode(ctx: Context): boolean;
163
219
  export declare function israngeseleciton(ctx: Context, istooltip?: boolean): boolean;
164
220
  export declare function isFormulaReferenceInputMode(ctx: Context): boolean;
165
221
  export declare function maybeRecoverDirtyRangeSelection(ctx: Context): boolean;
166
- export declare function functionStrChange(txt: string, type: string, rc: 'row' | 'col', orient: string | null, stindex: number, step: number): string;
222
+ export declare function functionStrChange(txt: string, type: string, rc: 'row' | 'col', orient: string | null, stindex: number, step: number, tabs: FormulaTabs): string;
167
223
  export declare function rangeSetValue(ctx: Context, cellInput: HTMLDivElement, selected: any, fxInput?: HTMLDivElement | null): void;
168
224
  export declare function onFormulaRangeDragEnd(ctx: Context): void;
169
225
  export declare function rangeDrag(ctx: Context, e: MouseEvent, cellInput: HTMLDivElement, scrollLeft: number, scrollTop: number, container: HTMLDivElement, fxInput?: HTMLDivElement | null): void;
@@ -0,0 +1,39 @@
1
+ import { Patch } from 'immer';
2
+ import { Context } from '../context';
3
+
4
+ /**
5
+ * Undo and redo apply Immer patches that address `calcChain` by array index.
6
+ * After a collaborator's formula list has replaced the sheet's chain (A4),
7
+ * those indexes point into a different array, so replaying them can truncate
8
+ * it and drop the collaborator's formulas; the calcChain hook would then
9
+ * delete those entries from Yjs for everyone.
10
+ *
11
+ * So history never restores `calcChain` from patches. The cells it restores
12
+ * are re-registered from their own `f` instead (`reregisterRestoredFormulas`).
13
+ */
14
+ export type RestoredCell = {
15
+ sheetIndex: number;
16
+ r: number;
17
+ c: number | null;
18
+ };
19
+ /**
20
+ * `patches` without the calcChain ones, and the cells whose formulas must be
21
+ * re-registered afterwards. When a patch replaces a whole sheet or grid the
22
+ * cells can't be listed, so history is left as it was (`restored` is null).
23
+ */
24
+ export declare function planHistoryPatches(patches: Patch[]): {
25
+ patches: Patch[];
26
+ restored: RestoredCell[] | null;
27
+ };
28
+ /**
29
+ * Register the restored cells that hold a formula and drop the ones that no
30
+ * longer do. Run on a draft after the patches were applied. The graph is left
31
+ * incomplete: restored formulas are not evaluated.
32
+ *
33
+ * A row-level patch lists every cell of the row, so most restored cells are
34
+ * unchanged. The chain is read once into a set; only a formula missing from it
35
+ * is added and only an entry whose cell lost its formula is removed (in one
36
+ * batch). Calling insertUpdateFunctionGroup / delFunctionGroup per cell
37
+ * scanned the chain each time: 6.8 s for 1,000 formulas on 1,000 rows.
38
+ */
39
+ export declare function reregisterRestoredFormulas(ctx: Context, restored: RestoredCell[]): void;
@@ -0,0 +1,16 @@
1
+ import { Patch } from 'immer';
2
+ import { Context } from '../context';
3
+
4
+ export type GridSizeChange = {
5
+ sheetId: string;
6
+ path: ['row'] | ['column'];
7
+ value: number;
8
+ type: 'update';
9
+ };
10
+ /**
11
+ * Undo and redo of a row/column insert or delete change a sheet's `row` /
12
+ * `column`. The forward edit writes them to Yjs (`emitGridSizeToYdoc`); history
13
+ * wrote the restored cells only, so a peer kept the grown grid until a later
14
+ * effect fixed it, and only for the current sheet.
15
+ */
16
+ export declare function gridSizeChangesFromPatches(ctxAfter: Context, patches: Patch[]): GridSizeChange[];
@@ -33,16 +33,17 @@ export { cfSplitRange } from './conditionalFormat';
33
33
  export { CFSplitRange } from './ConditionFormat';
34
34
  export { updateMoreCell, getRegStr, getDataArr } from './splitColumn';
35
35
  export { applyLocation, getOptionValue, getSelectRange, } from './locationCondition';
36
- export { getDropdownList, setDropdownValue, confirmMessage, cellFocus, validateCellData, } from './dataVerification';
36
+ export { getDropdownList, setDropdownValue, confirmMessage, cellFocus, validateCellData, splitDropdownOptions, getDropdownOptions, } from './dataVerification';
37
37
  export { setConditionRules, CF_DATE_DEFAULT_FORMAT, parseCfDateConditionForUi, formatCfDatePresetSnapshot, parseDdMmYyyyToSerial, } from './ConditionFormat';
38
38
  export { handleOverlayTouchStart, handleOverlayTouchEnd } from './mobile';
39
39
  export { MAX_ZOOM_RATIO, MIN_ZOOM_RATIO } from './zoom';
40
40
  export { jfrefreshgrid } from './refresh';
41
+ export { deleteCellsShift, insertCellsShift } from './cell-shift';
41
42
  export { sanitizeDuneUrl, insertDuneChart, onIframeMoveStart, onIframeResizeStart, onIframeMove, onIframeMoveEnd, onIframeResize, onIframeResizeEnd, } from './iframe';
42
43
  export { setCellError, clearCellError, overShowError, } from './error-state-helpers';
43
44
  export { checkCellIsLocked } from './protection';
44
45
  export { detectDateFormat, isdatatypemulti, diff, isdatetime, isRealNull, isRealNum, isNumericCellType, } from './validation';
45
- export { iscelldata, getcellrange, execfunction, execFunctionGroup, refreshFormulasUsingDefinedNames, runFormulaEvalChunk, applyWorkerFormulaChunkResults, insertUpdateFunctionGroup, functionCopy, } from './formula';
46
+ export { iscelldata, getcellrange, execfunction, execFunctionGroup, refreshFormulasUsingDefinedNames, runFormulaEvalChunk, applyWorkerFormulaChunkResults, finishFullFormulaPass, resetFormulaDependencyIndexes, insertUpdateFunctionGroup, functionCopy, } from './formula';
46
47
  export { checkCF, getComputeMap } from './ConditionFormat';
47
48
  export { isValidDefinedNameIdentifier, getDefinedNameDisplayRange, findDefinedNameForSelection, findDefinedNameByName, resolveDefinedNameForFormula, addDefinedName, updateDefinedName, deleteDefinedName, selectDefinedName, openNamedRangesSidebar, scheduleDefinedNamesSync, shiftDefinedNamesOnInsert, shiftDefinedNamesOnDelete, removeDefinedNamesForSheet, } from './namedRanges';
48
49
  export { getdatabyselection, getQKBorder } from './cell';
@@ -1,5 +1,18 @@
1
1
  import { Context } from '../context';
2
2
 
3
+ type Measure2d = {
4
+ measureText(t: string): {
5
+ width: number;
6
+ };
7
+ font: string;
8
+ };
9
+ /** Drop cached widths, e.g. after web fonts load and change the metrics. */
10
+ export declare function clearSingleLineCache(): void;
11
+ /**
12
+ * Width of one line of text in `font`, from canvas measureText, cached by
13
+ * (font, text). No DOM layout is involved.
14
+ */
15
+ export declare function measureSingleLine(font: string, text: string, ctx2d: Measure2d): number;
3
16
  export declare function calculateRangeCellSize(ctx: Context, sheetId: string, startRow: number, endRow: number, startCol: number, endCol: number, maxColumnWidth?: number): {
4
17
  rowMax: Record<number, number>;
5
18
  colMax: Record<number, number>;
@@ -9,3 +22,4 @@ export declare const updateSheetCellSizes: (ctx: Context, sheetIndex: number, me
9
22
  rowMax: Record<number, number>;
10
23
  colMax: Record<number, number>;
11
24
  }, maxColumnWidth?: number) => void;
25
+ export {};
@@ -29,7 +29,17 @@ export type Hooks = {
29
29
  beforeUpdateCell?: (r: number, c: number, value: any) => boolean;
30
30
  /** Clears RTC remote-apply lock so local edits can run data-block formulas. */
31
31
  onLocalCellEdit?: () => void;
32
- afterUpdateCell?: (row: number, column: number, oldValue: any, newValue: any) => void;
32
+ afterUpdateCell?: (row: number, column: number, oldValue: any, newValue: any,
33
+ /** Sheet that held the cell when it was committed (updateCell only). */
34
+ sheetId?: string,
35
+ /**
36
+ * `skipPersist`: the caller writes this cell to Yjs in its own batch (paste
37
+ * and fill), after the cell is final. Persisting here too wrote the
38
+ * pre-format value first, so every formula was written twice.
39
+ */
40
+ options?: {
41
+ skipPersist?: boolean;
42
+ }) => void;
33
43
  afterSelectionChange?: (sheetId: string, selection: Selection) => void;
34
44
  beforeRenderRowHeaderCell?: (rowNumber: string, rowIndex: number, top: number, width: number, height: number, ctx: CanvasRenderingContext2D) => boolean;
35
45
  afterRenderRowHeaderCell?: (rowNumber: string, rowIndex: number, top: number, width: number, height: number, ctx: CanvasRenderingContext2D) => void;
@@ -83,6 +93,10 @@ export type Hooks = {
83
93
  afterDeleteSheet?: (id: string) => void;
84
94
  beforeUpdateSheetName?: (id: string, oldName: string, newName: string) => boolean;
85
95
  afterUpdateSheetName?: (id: string, oldName: string, newName: string) => void;
96
+ onCopySheetLink?: (args: {
97
+ sheetId: string;
98
+ sheetName: string;
99
+ }) => void;
86
100
  afterImagesChange?: () => void;
87
101
  afterIframesChange?: () => void;
88
102
  afterFrozenChange?: () => void;
@@ -1,6 +1,17 @@
1
1
  import { Context } from '../context';
2
2
  import { Cell, CellWithRowAndCol } from '../types';
3
3
 
4
+ /** Receives changes instead of the updateCellYdoc hook (see createYdocBatch). */
5
+ export type YdocChangeSink = (changes: any[]) => void;
6
+ /**
7
+ * Collect the Yjs changes of one structural edit and send them in a single
8
+ * updateCellYdoc call, so the edit is one transaction and one update for peers
9
+ * (an insert used to send four and a delete five).
10
+ */
11
+ export declare function createYdocBatch(ctx: Context): {
12
+ sink: YdocChangeSink;
13
+ flush: () => void;
14
+ };
4
15
  export type CelldataYdocChange = {
5
16
  sheetId: string;
6
17
  path: string[];
@@ -17,13 +28,29 @@ export declare function cellsEqualForYdocPersist(before: unknown, after: unknown
17
28
  export declare function snapshotPersistedCelldataInRange(data: unknown[][] | null | undefined, r1: number, r2: number, c1: number, c2: number, celldata?: CellWithRowAndCol[] | null): Map<string, Cell | string | number | boolean>;
18
29
  export declare function appendCelldataDiffChange(changes: CelldataYdocChange[], sheetId: string, r: number, c: number, cell: unknown, beforePersisted?: Map<string, Cell | string | number | boolean>): void;
19
30
  export declare function buildCelldataChangesForRange(sheetId: string, data: unknown[][], r1: number, r2: number, c1: number, c2: number, beforePersisted?: Map<string, Cell | string | number | boolean>): CelldataYdocChange[];
20
- export declare function emitCelldataRangeDiffToYdoc(ctx: Context, sheetId: string, data: unknown[][], r1: number, r2: number, c1: number, c2: number, beforePersisted?: Map<string, Cell | string | number | boolean>): void;
31
+ export declare function emitCelldataRangeDiffToYdoc(ctx: Context, sheetId: string, data: unknown[][], r1: number, r2: number, c1: number, c2: number, beforePersisted?: Map<string, Cell | string | number | boolean>, sink?: YdocChangeSink): void;
32
+ /** Formula text per tab and cell key, taken before a structural edit rewrites it. */
33
+ export type FormulaTextSnapshot = Map<string, Map<string, string>>;
34
+ /**
35
+ * Snapshot formula text on every hydrated tab. A row/column insert or delete
36
+ * rewrites formulas on all tabs, but only the edited tab's shifted range is
37
+ * diffed to Yjs, so the rest has to be found by comparing against this.
38
+ */
39
+ export declare function snapshotFormulaTexts(ctx: Context): FormulaTextSnapshot;
40
+ /**
41
+ * Emit cells whose formula text changed since `before`, so peers see the
42
+ * rewrite. On the edited tab, cells at or past (`editedFromR`, `editedFromC`)
43
+ * are skipped: the range diff already writes them. `before` keys are
44
+ * pre-edit coordinates, which equal post-edit ones for every cell outside
45
+ * that range.
46
+ */
47
+ export declare function emitRewrittenFormulasToYdoc(ctx: Context, before: FormulaTextSnapshot, editedSheetId: string, editedFromR: number, editedFromC: number, sink?: YdocChangeSink): void;
21
48
  /**
22
49
  * After delete row/col, emit deletes for persisted keys that now sit past the
23
50
  * shrunken grid. Range diffs only visit coordinates still inside `data`, so
24
51
  * tail keys would otherwise resurrect on peers/reload.
25
52
  */
26
- export declare function emitCelldataDeletesBeyondGrid(ctx: Context, sheetId: string, beforePersisted: Map<string, Cell | string | number | boolean> | undefined, rowCount: number, colCount: number): void;
53
+ export declare function emitCelldataDeletesBeyondGrid(ctx: Context, sheetId: string, beforePersisted: Map<string, Cell | string | number | boolean> | undefined, rowCount: number, colCount: number, sink?: YdocChangeSink): void;
27
54
  export type MergeBounds = {
28
55
  minR: number;
29
56
  minC: number;
@@ -0,0 +1,15 @@
1
+ export declare const COPY_SHEET_LINK_ITEM = "copy-link";
2
+ type ReadOnlyFlags = {
3
+ isFlvReadOnly?: boolean;
4
+ allowEdit?: boolean;
5
+ };
6
+ type CopyLinkHooks = {
7
+ onCopySheetLink?: unknown;
8
+ };
9
+ export declare function isSheetTabReadOnly(ctx: ReadOnlyFlags): boolean;
10
+ export declare function canOpenSheetTabMenu(ctx: ReadOnlyFlags, hooks: CopyLinkHooks): boolean;
11
+ export declare function getVisibleSheetTabMenuItems(items: string[], opts: {
12
+ readOnly: boolean;
13
+ hasCopyLink: boolean;
14
+ }): string[];
15
+ export {};
@@ -31,6 +31,10 @@ export declare function generateAPIs(context: Context, setContext: (recipe: (ctx
31
31
  applyRemoteCellValue: (row: number, column: number, value: any, options?: api.CommonOptions & {
32
32
  type?: keyof Cell;
33
33
  }) => void;
34
+ /** Remote formula-list change, applied in place (A4). */
35
+ setSheetCalcChain: (calcChain: Sheet["calcChain"], options?: api.CommonOptions) => void;
36
+ /** Remote cell batch: one quiet update, off the local undo stack (A5). */
37
+ applyRemoteCells: (cells: api.RemoteCellChange[], options?: api.CommonOptions, onSkip?: (cell: api.RemoteCellChange, error: unknown) => void) => void;
34
38
  setCellError: (row: number, column: number, errorMessage: {
35
39
  title: string;
36
40
  message: string;
@@ -0,0 +1,16 @@
1
+ import { Cell } from '../../../core/types';
2
+
3
+ /**
4
+ * True when any displayed value (`m`) contains BTC, ETH or SOL. Walks the grid
5
+ * in place and returns at the first hit; no intermediate cell list is built.
6
+ */
7
+ export declare function hasDenominatedCell(data: (Cell | null)[][]): boolean;
8
+ type BannerDoc = Pick<Document, 'getElementById' | 'getElementsByClassName'>;
9
+ /**
10
+ * Show or hide the crypto-denomination banner and move the scrollbar and
11
+ * add-row bar to match. A no-op when the host has not mounted the banner
12
+ * element; call again later (for example on selection change) to retry.
13
+ * Returns true when the banner element was found.
14
+ */
15
+ export declare function applyDenominationBanner(denominated: boolean, doc?: BannerDoc): boolean;
16
+ export {};
@@ -33,6 +33,8 @@ declare const Workbook: React.ForwardRefExoticComponent<Settings & AdditionalPro
33
33
  applyRemoteCellValue: (row: number, column: number, value: any, options?: api.CommonOptions & {
34
34
  type?: keyof import('../../../core').Cell;
35
35
  }) => void;
36
+ setSheetCalcChain: (calcChain: SheetType["calcChain"], options?: api.CommonOptions) => void;
37
+ applyRemoteCells: (cells: api.RemoteCellChange[], options?: api.CommonOptions, onSkip?: (cell: api.RemoteCellChange, error: unknown) => void) => void;
36
38
  setCellError: (row: number, column: number, errorMessage: {
37
39
  title: string;
38
40
  message: string;