@fileverse-dev/dsheet 4.1.21 → 4.1.23-stabilise-package-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 (97) hide show
  1. package/dist/editor/components/editor-workbook.d.ts +6 -0
  2. package/dist/editor/components/sidebar/editor-right-sidebar.d.ts +3 -1
  3. package/dist/editor/components/sidebar/sidebar-offsets.d.ts +12 -0
  4. package/dist/editor/components/sidebar/sidebar-offsets.test.d.ts +1 -0
  5. package/dist/editor/contexts/editor-context.d.ts +5 -0
  6. package/dist/editor/hooks/use-editor-sync.d.ts +5 -1
  7. package/dist/editor/types.d.ts +42 -0
  8. package/dist/editor/utils/activate-sheet-for-link.d.ts +3 -0
  9. package/dist/editor/utils/active-sheet-keeper.d.ts +21 -0
  10. package/dist/editor/utils/after-update-cell.d.ts +2 -0
  11. package/dist/editor/utils/after-update-cell.test.d.ts +1 -0
  12. package/dist/editor/utils/apply-comment-markers.d.ts +3 -1
  13. package/dist/editor/utils/apply-comment-markers.test.d.ts +1 -0
  14. package/dist/editor/utils/calc-chain-ydoc-update.test.d.ts +1 -0
  15. package/dist/editor/utils/content-change.d.ts +48 -0
  16. package/dist/editor/utils/content-change.test.d.ts +1 -0
  17. package/dist/editor/utils/content-fingerprint.d.ts +37 -0
  18. package/dist/editor/utils/content-fingerprint.test.d.ts +1 -0
  19. package/dist/editor/utils/editor-handle.d.ts +1 -1
  20. package/dist/editor/utils/format-gate.d.ts +23 -0
  21. package/dist/editor/utils/format-gate.test.d.ts +1 -0
  22. package/dist/editor/utils/navigate-to-sheet.d.ts +22 -0
  23. package/dist/editor/utils/patch-plain-celldata.d.ts +19 -0
  24. package/dist/editor/utils/patch-plain-celldata.test.d.ts +1 -0
  25. package/dist/editor/utils/rebuild-indexeddb-store.d.ts +12 -0
  26. package/dist/editor/utils/rebuild-indexeddb-store.failure.test.d.ts +1 -0
  27. package/dist/editor/utils/rebuild-indexeddb-store.test.d.ts +1 -0
  28. package/dist/editor/utils/remote-apply-guard.d.ts +26 -0
  29. package/dist/editor/utils/remote-apply-guard.test.d.ts +1 -0
  30. package/dist/editor/utils/sheet-ydoc-sync-utils.d.ts +13 -4
  31. package/dist/editor/utils/sheet-ydoc-sync-utils.test.d.ts +1 -0
  32. package/dist/editor/utils/structural-edit-formula-sync.test.d.ts +1 -0
  33. package/dist/editor/utils/update-ydoc.d.ts +9 -1
  34. package/dist/{es-S4GKlN-t.js → es-BlDQ6jCL.js} +1 -0
  35. package/dist/{executeStringFunction-CQ922vEp.js → executeStringFunction-DKA5MuP0.js} +7092 -6760
  36. package/dist/formula.js +1 -1
  37. package/dist/{hi-DMMTDTxZ.js → hi-CP0ta0Yk.js} +1 -0
  38. package/dist/{index-BZbTaVjU.js → index-ypRdpDnX.js} +22658 -21718
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.es.js +16 -16
  41. package/dist/persistence-utils-CSKBobX8.js +151 -0
  42. package/dist/persistence-utils.d.ts +2 -0
  43. package/dist/persistence.append.test.d.ts +1 -0
  44. package/dist/persistence.d.ts +13 -0
  45. package/dist/persistence.fingerprint.test.d.ts +1 -0
  46. package/dist/persistence.js +122 -74
  47. package/dist/sheet-engine/core/api/cell.d.ts +20 -1
  48. package/dist/sheet-engine/core/api/remote-apply.test.d.ts +1 -0
  49. package/dist/sheet-engine/core/index.d.ts +1 -1
  50. package/dist/sheet-engine/core/locale/en.d.ts +1 -0
  51. package/dist/sheet-engine/core/locale/es.d.ts +1 -0
  52. package/dist/sheet-engine/core/locale/hi.d.ts +1 -0
  53. package/dist/sheet-engine/core/locale/zh.d.ts +1 -0
  54. package/dist/sheet-engine/core/locale/zh_tw.d.ts +1 -0
  55. package/dist/sheet-engine/core/modules/b6-ydoc-writes.test.d.ts +1 -0
  56. package/dist/sheet-engine/core/modules/border.d.ts +9 -0
  57. package/dist/sheet-engine/core/modules/cell-shift.d.ts +11 -0
  58. package/dist/sheet-engine/core/modules/cell.commit-ydoc.test.d.ts +1 -0
  59. package/dist/sheet-engine/core/modules/dataVerification.d.ts +15 -0
  60. package/dist/sheet-engine/core/modules/engine-hot-spots.test.d.ts +1 -0
  61. package/dist/sheet-engine/core/modules/formula-async-eval.d.ts +5 -0
  62. package/dist/sheet-engine/core/modules/formula-narrowing.test.d.ts +1 -0
  63. package/dist/sheet-engine/core/modules/formula-snapshot-eval.d.ts +2 -0
  64. package/dist/sheet-engine/core/modules/formula-transitive-deps.d.ts +5 -1
  65. package/dist/sheet-engine/core/modules/formula-warmup.d.ts +37 -0
  66. package/dist/sheet-engine/core/modules/formula-warmup.test.d.ts +1 -0
  67. package/dist/sheet-engine/core/modules/formula.d.ts +48 -1
  68. package/dist/sheet-engine/core/modules/formula.dep-graph.test.d.ts +1 -0
  69. package/dist/sheet-engine/core/modules/formula.str-change.test.d.ts +1 -0
  70. package/dist/sheet-engine/core/modules/formula.wide-seed.test.d.ts +1 -0
  71. package/dist/sheet-engine/core/modules/history-calc-chain.d.ts +33 -0
  72. package/dist/sheet-engine/core/modules/history-calc-chain.test.d.ts +1 -0
  73. package/dist/sheet-engine/core/modules/index.d.ts +3 -2
  74. package/dist/sheet-engine/core/paste/paste-dep-graph.test.d.ts +1 -0
  75. package/dist/sheet-engine/core/paste-helpers/calculate-range-cell-size.d.ts +14 -0
  76. package/dist/sheet-engine/core/paste-helpers/calculate-range-cell-size.test.d.ts +1 -0
  77. package/dist/sheet-engine/core/settings.d.ts +7 -1
  78. package/dist/sheet-engine/core/utils/ydoc-celldata-changes.d.ts +16 -0
  79. package/dist/sheet-engine/react/components/ContextMenu/sheet-tab-menu-items.d.ts +15 -0
  80. package/dist/sheet-engine/react/components/Workbook/api.d.ts +4 -0
  81. package/dist/sheet-engine/react/components/Workbook/denomination-scan.d.ts +16 -0
  82. package/dist/sheet-engine/react/components/Workbook/denomination-scan.test.d.ts +1 -0
  83. package/dist/sheet-engine/react/components/Workbook/index.d.ts +2 -0
  84. package/dist/style.css +1 -1
  85. package/dist/sync-local/SyncManager.d.ts +5 -2
  86. package/dist/sync-local/SyncManager.mirror.test.d.ts +1 -0
  87. package/dist/sync-local/SyncManager.remote-apply.test.d.ts +1 -0
  88. package/dist/sync-local/types/index.d.ts +5 -3
  89. package/dist/{template-data-list-BYOIK_Nd.js → template-data-list-apgmwRAT.js} +18 -10
  90. package/dist/{use-xlsx-import-impl-Bzyh3J-h.js → use-xlsx-import-impl-DQ3tpIAe.js} +120 -119
  91. package/dist/{xlsx-defined-names-CGkkDs3a.js → xlsx-defined-names-CVVLxbe-.js} +2 -2
  92. package/dist/{xlsx-export-impl-8QvOUcjc.js → xlsx-export-impl-ghSoFZBz.js} +4 -4
  93. package/dist/{xlsx-hyperlink-inline-CEmgXple.js → xlsx-hyperlink-inline-DXj7AkSf.js} +2 -2
  94. package/dist/{zh-Bv4KIDiJ.js → zh-CmOCFd5t.js} +1 -0
  95. package/dist/{zh_tw-BdpsK45h.js → zh_tw-BqyRw1gX.js} +1 -0
  96. package/package.json +2 -2
  97. package/dist/persistence-utils-BXFajzvq.js +0 -98
@@ -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[][];
@@ -79,6 +112,16 @@ export declare function getcellrange(ctx: Context, txt: string, formulaId?: stri
79
112
  export declare function getAllFunctionGroup(ctx: Context): any[];
80
113
  export declare function delFunctionGroup(ctx: Context, r: number, c: number, id?: string): void;
81
114
  export declare function insertUpdateFunctionGroup(ctx: Context, r: number, c: number, id?: string, calcChainSet?: Set<string>): void;
115
+ /**
116
+ * Drop every recorded formula dependency, back to a fresh mount's state, and
117
+ * mark the graph incomplete (A4, C8).
118
+ */
119
+ export declare function resetFormulaDependencyIndexes(ctx: Context): void;
120
+ /**
121
+ * End of a full pass that started at `epoch` (C8): every formula in the chain
122
+ * has recorded its dependencies, unless the graph was invalidated meanwhile.
123
+ */
124
+ export declare function finishFullFormulaPass(ctx: Context, epoch: number | null | undefined): void;
82
125
  export declare function execfunction(ctx: Context, txt: string, r: number, c: number, id?: string, calcChainSet?: Set<string>, isrefresh?: boolean, notInsertFunc?: boolean): any[];
83
126
  export declare function groupValuesRefresh(ctx: Context): void;
84
127
  /** Apply worker chunk output onto the live context (main thread only). */
@@ -158,12 +201,16 @@ export declare function markRangeSelectionDirty(ctx: Context): void;
158
201
  export declare function getFormulaRangeIndexForKeyboardSync($editor: HTMLDivElement): number | null;
159
202
  export declare function handleFormulaInput(ctx: Context, $copyTo: HTMLDivElement | null | undefined, $editor: HTMLDivElement, kcode: number, preText?: string, refreshRangeSelect?: boolean): void;
160
203
  export declare function toggleFormulaAbsoluteReferenceAtCaret(ctx: Context, $copyTo: HTMLDivElement | null | undefined, $editor: HTMLDivElement | null | undefined): boolean;
204
+ export type FormulaTabs = {
205
+ editedTab: string;
206
+ formulaTab: string;
207
+ };
161
208
  /** True while picking a range for a formula (sheet selection drives references). */
162
209
  export declare function isLegacyFormulaRangeMode(ctx: Context): boolean;
163
210
  export declare function israngeseleciton(ctx: Context, istooltip?: boolean): boolean;
164
211
  export declare function isFormulaReferenceInputMode(ctx: Context): boolean;
165
212
  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;
213
+ export declare function functionStrChange(txt: string, type: string, rc: 'row' | 'col', orient: string | null, stindex: number, step: number, tabs: FormulaTabs): string;
167
214
  export declare function rangeSetValue(ctx: Context, cellInput: HTMLDivElement, selected: any, fxInput?: HTMLDivElement | null): void;
168
215
  export declare function onFormulaRangeDragEnd(ctx: Context): void;
169
216
  export declare function rangeDrag(ctx: Context, e: MouseEvent, cellInput: HTMLDivElement, scrollLeft: number, scrollTop: number, container: HTMLDivElement, fxInput?: HTMLDivElement | null): void;
@@ -0,0 +1,33 @@
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
+ export declare function reregisterRestoredFormulas(ctx: Context, restored: RestoredCell[]): void;
@@ -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,9 @@ 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) => void;
33
35
  afterSelectionChange?: (sheetId: string, selection: Selection) => void;
34
36
  beforeRenderRowHeaderCell?: (rowNumber: string, rowIndex: number, top: number, width: number, height: number, ctx: CanvasRenderingContext2D) => boolean;
35
37
  afterRenderRowHeaderCell?: (rowNumber: string, rowIndex: number, top: number, width: number, height: number, ctx: CanvasRenderingContext2D) => void;
@@ -83,6 +85,10 @@ export type Hooks = {
83
85
  afterDeleteSheet?: (id: string) => void;
84
86
  beforeUpdateSheetName?: (id: string, oldName: string, newName: string) => boolean;
85
87
  afterUpdateSheetName?: (id: string, oldName: string, newName: string) => void;
88
+ onCopySheetLink?: (args: {
89
+ sheetId: string;
90
+ sheetName: string;
91
+ }) => void;
86
92
  afterImagesChange?: () => void;
87
93
  afterIframesChange?: () => void;
88
94
  afterFrozenChange?: () => void;
@@ -18,6 +18,22 @@ export declare function snapshotPersistedCelldataInRange(data: unknown[][] | nul
18
18
  export declare function appendCelldataDiffChange(changes: CelldataYdocChange[], sheetId: string, r: number, c: number, cell: unknown, beforePersisted?: Map<string, Cell | string | number | boolean>): void;
19
19
  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
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;
21
+ /** Formula text per tab and cell key, taken before a structural edit rewrites it. */
22
+ export type FormulaTextSnapshot = Map<string, Map<string, string>>;
23
+ /**
24
+ * Snapshot formula text on every hydrated tab. A row/column insert or delete
25
+ * rewrites formulas on all tabs, but only the edited tab's shifted range is
26
+ * diffed to Yjs, so the rest has to be found by comparing against this.
27
+ */
28
+ export declare function snapshotFormulaTexts(ctx: Context): FormulaTextSnapshot;
29
+ /**
30
+ * Emit cells whose formula text changed since `before`, so peers see the
31
+ * rewrite. On the edited tab, cells at or past (`editedFromR`, `editedFromC`)
32
+ * are skipped: the range diff already writes them. `before` keys are
33
+ * pre-edit coordinates, which equal post-edit ones for every cell outside
34
+ * that range.
35
+ */
36
+ export declare function emitRewrittenFormulasToYdoc(ctx: Context, before: FormulaTextSnapshot, editedSheetId: string, editedFromR: number, editedFromC: number): void;
21
37
  /**
22
38
  * After delete row/col, emit deletes for persisted keys that now sit past the
23
39
  * shrunken grid. Range diffs only visit coordinates still inside `data`, so
@@ -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;