@fileverse-dev/dsheet 4.1.23 → 4.1.24-stabilise-package-2

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 (134) hide show
  1. package/README.md +10 -0
  2. package/dist/editor/components/skeleton-loader.d.ts +2 -1
  3. package/dist/editor/contexts/editor-context.d.ts +10 -0
  4. package/dist/editor/hooks/use-celldata-compaction.d.ts +44 -2
  5. package/dist/editor/hooks/use-celldata-compaction.test.d.ts +1 -0
  6. package/dist/editor/hooks/use-editor-data.d.ts +1 -0
  7. package/dist/editor/hooks/use-editor-sync.d.ts +5 -1
  8. package/dist/editor/hooks/use-editor-sync.test.d.ts +1 -0
  9. package/dist/editor/types.d.ts +44 -1
  10. package/dist/editor/utils/active-sheet-keeper.test.d.ts +1 -0
  11. package/dist/editor/utils/after-update-cell.d.ts +6 -0
  12. package/dist/editor/utils/after-update-cell.test.d.ts +1 -0
  13. package/dist/editor/utils/apply-comment-markers.d.ts +3 -1
  14. package/dist/editor/utils/apply-comment-markers.test.d.ts +1 -0
  15. package/dist/editor/utils/calc-chain-ydoc-update.test.d.ts +1 -0
  16. package/dist/editor/utils/content-change.d.ts +48 -0
  17. package/dist/editor/utils/content-change.test.d.ts +1 -0
  18. package/dist/editor/utils/content-fingerprint.d.ts +37 -0
  19. package/dist/editor/utils/content-fingerprint.test.d.ts +1 -0
  20. package/dist/editor/utils/editor-handle.d.ts +1 -1
  21. package/dist/editor/utils/format-gate.d.ts +27 -0
  22. package/dist/editor/utils/format-gate.test.d.ts +1 -0
  23. package/dist/editor/utils/legacy-on-change.d.ts +20 -0
  24. package/dist/editor/utils/legacy-on-change.test.d.ts +1 -0
  25. package/dist/editor/utils/patch-plain-celldata.d.ts +19 -0
  26. package/dist/editor/utils/patch-plain-celldata.test.d.ts +1 -0
  27. package/dist/editor/utils/rebuild-indexeddb-store.d.ts +19 -0
  28. package/dist/editor/utils/rebuild-indexeddb-store.failure.test.d.ts +1 -0
  29. package/dist/editor/utils/rebuild-indexeddb-store.test.d.ts +1 -0
  30. package/dist/editor/utils/remote-apply-guard.d.ts +45 -0
  31. package/dist/editor/utils/remote-apply-guard.test.d.ts +1 -0
  32. package/dist/editor/utils/sheet-ydoc-sync-utils.d.ts +13 -4
  33. package/dist/editor/utils/sheet-ydoc-sync-utils.test.d.ts +1 -0
  34. package/dist/editor/utils/structural-edit-formula-sync.test.d.ts +1 -0
  35. package/dist/editor/utils/structural-edit-other-tabs.test.d.ts +1 -0
  36. package/dist/editor/utils/update-ydoc.d.ts +9 -1
  37. package/dist/editor/utils/wait-for-sync.d.ts +35 -0
  38. package/dist/editor/utils/wait-for-sync.test.d.ts +1 -0
  39. package/dist/editor/utils/xlsx-export-impl.d.ts +1 -0
  40. package/dist/editor/utils/xlsx-export.d.ts +1 -0
  41. package/dist/{executeStringFunction-ZHYCWIpK.js → executeStringFunction--gHt0G5o.js} +13725 -12781
  42. package/dist/formula.js +1 -1
  43. package/dist/{index-8_qnUyMl.js → index-DTkdULNT.js} +23239 -21905
  44. package/dist/index.d.ts +2 -2
  45. package/dist/index.es.js +44 -43
  46. package/dist/persistence-utils-CSKBobX8.js +151 -0
  47. package/dist/persistence-utils.d.ts +2 -0
  48. package/dist/persistence.append.test.d.ts +1 -0
  49. package/dist/persistence.d.ts +13 -0
  50. package/dist/persistence.fingerprint.test.d.ts +1 -0
  51. package/dist/persistence.js +122 -74
  52. package/dist/sheet-engine/core/api/cell.d.ts +25 -1
  53. package/dist/sheet-engine/core/api/remote-apply.test.d.ts +1 -0
  54. package/dist/sheet-engine/core/api/sheet-flowdata-lifecycle.d.ts +1 -0
  55. package/dist/sheet-engine/core/api/sheet-flowdata-lifecycle.test.d.ts +1 -0
  56. package/dist/sheet-engine/core/index.d.ts +1 -1
  57. package/dist/sheet-engine/core/modules/b6-ydoc-writes.test.d.ts +1 -0
  58. package/dist/sheet-engine/core/modules/border.d.ts +9 -0
  59. package/dist/sheet-engine/core/modules/cell-shift-dep-graph.test.d.ts +1 -0
  60. package/dist/sheet-engine/core/modules/cell-shift.d.ts +11 -0
  61. package/dist/sheet-engine/core/modules/cell.commit-ydoc.test.d.ts +1 -0
  62. package/dist/sheet-engine/core/modules/dataVerification.d.ts +15 -0
  63. package/dist/sheet-engine/core/modules/engine-hot-spots.test.d.ts +1 -0
  64. package/dist/sheet-engine/core/modules/formula-arrow-mode.d.ts +81 -0
  65. package/dist/sheet-engine/core/modules/formula-arrow-mode.test.d.ts +1 -0
  66. package/dist/sheet-engine/core/modules/formula-async-eval.d.ts +5 -0
  67. package/dist/sheet-engine/core/modules/formula-dep-text.d.ts +23 -0
  68. package/dist/sheet-engine/core/modules/formula-dep-text.test.d.ts +1 -0
  69. package/dist/sheet-engine/core/modules/formula-edge-update.d.ts +13 -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-tab-load.test.d.ts +1 -0
  73. package/dist/sheet-engine/core/modules/formula-transitive-deps.d.ts +26 -1
  74. package/dist/sheet-engine/core/modules/formula-warmup.d.ts +33 -0
  75. package/dist/sheet-engine/core/modules/formula-warmup.test.d.ts +1 -0
  76. package/dist/sheet-engine/core/modules/formula.d.ts +119 -2
  77. package/dist/sheet-engine/core/modules/formula.dep-graph.test.d.ts +1 -0
  78. package/dist/sheet-engine/core/modules/formula.str-change.test.d.ts +1 -0
  79. package/dist/sheet-engine/core/modules/formula.wide-seed.test.d.ts +1 -0
  80. package/dist/sheet-engine/core/modules/history-calc-chain.d.ts +39 -0
  81. package/dist/sheet-engine/core/modules/history-calc-chain.test.d.ts +1 -0
  82. package/dist/sheet-engine/core/modules/history-celldata.d.ts +25 -0
  83. package/dist/sheet-engine/core/modules/history-grid-size.d.ts +16 -0
  84. package/dist/sheet-engine/core/modules/history-grid-size.test.d.ts +1 -0
  85. package/dist/sheet-engine/core/modules/index.d.ts +4 -3
  86. package/dist/sheet-engine/core/modules/rowcol-dep-graph.test.d.ts +1 -0
  87. package/dist/sheet-engine/core/modules/rowcol-refused-edit.test.d.ts +1 -0
  88. package/dist/sheet-engine/core/modules/rowcol-unloaded-history.test.d.ts +1 -0
  89. package/dist/sheet-engine/core/modules/rowcol.d.ts +8 -0
  90. package/dist/sheet-engine/core/modules/structural-edit-prep.d.ts +36 -0
  91. package/dist/sheet-engine/core/modules/structural-edit-prep.test.d.ts +1 -0
  92. package/dist/sheet-engine/core/paste/paste-dep-graph.test.d.ts +1 -0
  93. package/dist/sheet-engine/core/paste-helpers/calculate-range-cell-size.d.ts +14 -0
  94. package/dist/sheet-engine/core/paste-helpers/calculate-range-cell-size.test.d.ts +1 -0
  95. package/dist/sheet-engine/core/settings.d.ts +11 -1
  96. package/dist/sheet-engine/core/utils/ydoc-celldata-changes.d.ts +29 -2
  97. package/dist/sheet-engine/react/components/ContextMenu/FilterMenu.d.ts +2 -2
  98. package/dist/sheet-engine/react/components/ContextMenu/SheetTab.d.ts +2 -2
  99. package/dist/sheet-engine/react/components/ContextMenu/index.d.ts +2 -2
  100. package/dist/sheet-engine/react/components/NotationBoxes/shown-comments.d.ts +20 -0
  101. package/dist/sheet-engine/react/components/NotationBoxes/shown-comments.test.d.ts +1 -0
  102. package/dist/sheet-engine/react/components/SVGDefines.d.ts +2 -2
  103. package/dist/sheet-engine/react/components/SheetOverlay/editing-as-formula.d.ts +7 -0
  104. package/dist/sheet-engine/react/components/SheetOverlay/editing-as-formula.test.d.ts +1 -0
  105. package/dist/sheet-engine/react/components/SheetOverlay/hover-tracker.d.ts +44 -0
  106. package/dist/sheet-engine/react/components/SheetOverlay/hover-tracker.test.d.ts +1 -0
  107. package/dist/sheet-engine/react/components/SheetTab/index.d.ts +2 -2
  108. package/dist/sheet-engine/react/components/Toolbar/FunctionList/group-functions.d.ts +9 -0
  109. package/dist/sheet-engine/react/components/Toolbar/FunctionList/group-functions.test.d.ts +1 -0
  110. package/dist/sheet-engine/react/components/Toolbar/index.d.ts +2 -2
  111. package/dist/sheet-engine/react/components/Workbook/api.d.ts +4 -0
  112. package/dist/sheet-engine/react/components/Workbook/denomination-scan.d.ts +16 -0
  113. package/dist/sheet-engine/react/components/Workbook/denomination-scan.test.d.ts +1 -0
  114. package/dist/sheet-engine/react/components/Workbook/index.d.ts +2 -0
  115. package/dist/sheet-engine/react/components/Workbook/stable-handle.d.ts +8 -0
  116. package/dist/sheet-engine/react/components/Workbook/stable-handle.test.d.ts +1 -0
  117. package/dist/sheet-engine/react/context/index.d.ts +15 -0
  118. package/dist/sheet-engine/react/context/use-workbook-store.d.ts +30 -0
  119. package/dist/sheet-engine/react/context/workbook-store.d.ts +30 -0
  120. package/dist/sheet-engine/react/context/workbook-store.test.d.ts +1 -0
  121. package/dist/style.css +1 -1
  122. package/dist/sync-local/SyncManager.d.ts +2 -2
  123. package/dist/sync-local/SyncManager.remote-apply.test.d.ts +1 -0
  124. package/dist/sync-local/SyncManager.test.d.ts +1 -0
  125. package/dist/sync-local/socketClient.d.ts +2 -0
  126. package/dist/sync-local/socketClient.test.d.ts +1 -0
  127. package/dist/sync-local/types/index.d.ts +5 -1
  128. package/dist/{use-xlsx-import-impl-cgDH14_y.js → use-xlsx-import-impl-DhCtyQw6.js} +120 -119
  129. package/dist/{xlsx-defined-names-DCK7aKIO.js → xlsx-defined-names-COueA4FW.js} +2 -2
  130. package/dist/xlsx-export-impl-lfDXFnFW.js +903 -0
  131. package/dist/{xlsx-hyperlink-inline-T4GsXFm7.js → xlsx-hyperlink-inline-Dyo_PyAb.js} +2 -2
  132. package/package.json +1 -1
  133. package/dist/persistence-utils-BXFajzvq.js +0 -98
  134. package/dist/xlsx-export-impl-BHDWz0aW.js +0 -880
@@ -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 {};
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Pure (DOM-free, ctx-free) logic that decides what an arrow key does while a
3
+ * formula is being edited.
4
+ *
5
+ * GRID - not editing: arrows move the grid selection
6
+ * TEXT_EDIT - arrows move the text caret
7
+ * REFERENCE_READY - next arrow inserts a new cell reference at the caret
8
+ * REFERENCE_ACTIVE - arrows move/extend the reference that was just inserted
9
+ */
10
+ export type FormulaArrowMode = 'GRID' | 'TEXT_EDIT' | 'REFERENCE_READY' | 'REFERENCE_ACTIVE';
11
+ /** Sticky, user-controlled (F2). `null` = automatic behavior. */
12
+ export type FormulaArrowOverride = null | 'TEXT_EDIT' | 'REFERENCE';
13
+ export type TokenKind = 'EQ' | 'SPACE' | 'STRING' | 'REF' | 'NAME' | 'NUMBER' | 'FUNC_NAME' | 'LPAREN' | 'RPAREN' | 'COMMA' | 'OPERATOR' | 'POSTFIX' | 'UNKNOWN';
14
+ export type Token = {
15
+ kind: TokenKind;
16
+ start: number;
17
+ end: number;
18
+ text: string;
19
+ /** STRING / quoted sheet name: closing quote present. */
20
+ terminated?: boolean;
21
+ /** REF that is not (yet) a complete reference, e.g. `A1:A`, `A1:`. */
22
+ partial?: boolean;
23
+ };
24
+ /** Never throws. Offsets index into `text` as given. */
25
+ export declare function tokenizeFormula(text: string): Token[];
26
+ export type CaretContext = {
27
+ inString: boolean;
28
+ /** Caret strictly inside a non-string token (e.g. `A|1`, `SU|M(`). */
29
+ insideToken: Token | null;
30
+ /** REF token the caret is inside or right after (start < caret <= end). */
31
+ touchingRef: Token | null;
32
+ prevSig: Token | null;
33
+ nextSig: Token | null;
34
+ };
35
+ export declare function getCaretContext(tokens: Token[], caret: number): CaretContext;
36
+ /**
37
+ * True when a new operand (cell reference) can be entered at the caret:
38
+ * the previous significant token wants an operand, the caret is not inside a
39
+ * string or token, and no operand sits immediately to the right.
40
+ */
41
+ export declare function isOperandSlot(ctx: CaretContext): boolean;
42
+ export type ArrowModeInput = {
43
+ editing: boolean;
44
+ /** Full editor text (offsets of `caretOffset` index into it). */
45
+ text: string;
46
+ /** null when the caret is not inside the editor. */
47
+ caretOffset: number | null;
48
+ override: FormulaArrowOverride;
49
+ /** false for sessions opened on an existing formula (F2 / dblclick / bar). */
50
+ autoAllowed: boolean;
51
+ /**
52
+ * The engine is driving a reference right now (mouse drag, or a reference the
53
+ * keyboard just inserted and the caret is still on).
54
+ */
55
+ refActive: boolean;
56
+ };
57
+ /** Decision priority from the product spec, evaluated in this exact order. */
58
+ export declare function resolveArrowMode(input: ArrowModeInput): FormulaArrowMode;
59
+ /**
60
+ * F2 while editing a formula: flip between caret and reference selection.
61
+ *
62
+ * Toggles the stored override once one exists, so a second press always undoes
63
+ * the first, even at a caret where the derived mode cannot change (e.g. after
64
+ * `)`). With no stored override, flips from the mode the user is looking at.
65
+ */
66
+ export declare function overrideAfterF2(mode: FormulaArrowMode, current?: FormulaArrowOverride): FormulaArrowOverride;
67
+ /**
68
+ * Rule 4: keys typed while a reference is active end the arrow-driven
69
+ * reference. The next mode is then derived from the caret position
70
+ * (operator or `,` -> READY, `)` or anything else -> TEXT_EDIT).
71
+ * keyCode based because it is called from keyup/keydown handlers.
72
+ */
73
+ export declare function isTextChangingKeyCode(kcode: number): boolean;
74
+ /**
75
+ * Keys that edit characters *inside* a reference token (letters, digits incl.
76
+ * numpad digits, Backspace/Delete). Typing them over an arrow-inserted
77
+ * reference makes it a hand-edited token, so its highlight must be dropped.
78
+ * Operators, commas and spaces are not here: they end the reference but leave
79
+ * its highlight alone (see `isTextChangingKeyCode`).
80
+ */
81
+ export declare function isReferenceDirtyingKeyCode(kcode: number): boolean;
@@ -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;
@@ -0,0 +1,23 @@
1
+ import { Context } from '../context';
2
+ import { WideRange } from './formula-transitive-deps';
3
+
4
+ /** Same cap as `execfunction` (MAX_RANGE_DEPS in formula.ts). */
5
+ export declare const MAX_TEXT_RANGE_DEPS = 10000;
6
+ export type FormulaTextDeps = {
7
+ /** `${sheetId}:${r}:${c}` of every cell the formula reads. */
8
+ deps: Set<string>;
9
+ /** Too wide or unresolvable to list. */
10
+ wide: boolean;
11
+ /**
12
+ * The ranges that made it wide, as `execfunction` records them. `null` when
13
+ * the formula is wide but its ranges can't be read from its text (an
14
+ * unresolved tab, INDIRECT, OFFSET, a whole row or column of a tab with no
15
+ * grid): it joins every commit's walk. `[]` when it is not wide.
16
+ */
17
+ wideRanges: WideRange[] | null;
18
+ };
19
+ /**
20
+ * Collect the references of formula text `f` (with its leading `=`) written
21
+ * in cell (`r`, `c`) of tab `sheetId`.
22
+ */
23
+ export declare function collectFormulaTextDeps(ctx: Context, f: string, sheetId: string, r: number, c: number): FormulaTextDeps;
@@ -0,0 +1,13 @@
1
+ import { Context } from '../context';
2
+
3
+ /**
4
+ * Set the edges of the formula `f` written in (`r`, `c`) of tab `sheetId`, or
5
+ * drop them when `f` is null (the value is no longer a formula).
6
+ */
7
+ export declare function setFormulaEdgesFromText(ctx: Context, r: number, c: number, sheetId: string, f: string | null): void;
8
+ /**
9
+ * A chain entry whose cell isn't here yet (a peer's chain can arrive before
10
+ * its cells): it can't be read, so it runs on every commit until the cell
11
+ * arrives and replaces this.
12
+ */
13
+ export declare function markFormulaEdgesUnknown(ctx: Context, r: number, c: number, sheetId: string): void;
@@ -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[];
@@ -1,7 +1,32 @@
1
1
  /** Cell / formula key format used in depsByCell and revDepsByCell. */
2
2
  export declare function toFormulaDepCellKey(sheetId: string, r: number, c: number): string;
3
+ /** A range a wide formula reads (more cells than get individual edges). */
4
+ export type WideRange = {
5
+ sheetId: string;
6
+ startRow: number;
7
+ endRow: number;
8
+ startCol: number;
9
+ endCol: number;
10
+ };
11
+ /**
12
+ * Wide formulas (ranges over MAX_RANGE_DEPS cells record no cell edges).
13
+ * `ranges` holds the ranges of those whose ranges could be read; a key in
14
+ * `keys` without an entry in `ranges` can't be bounded, so it joins every walk.
15
+ */
16
+ export type WideFormulaIndex = {
17
+ keys: Iterable<string>;
18
+ ranges: Map<string, WideRange[]>;
19
+ };
3
20
  /**
4
21
  * Walk revDepsByCell from a changed cell to collect every formula cell that
5
22
  * must recalculate (direct + transitive dependents).
23
+ *
24
+ * `extraFormulaSeeds` are formulas that run on every commit whatever the
25
+ * graph says (named ranges covering the edited cell). They join the same
26
+ * walk, so formulas that read their results are reached too.
27
+ *
28
+ * A wide formula joins the walk only when one of its ranges holds the edited
29
+ * cell or a formula cell the walk reaches; one whose ranges can't be read
30
+ * joins every walk. It then seeds the walk like any other formula.
6
31
  */
7
- export declare function collectTransitiveFormulaDependents(originCellKey: string, revDepsByCell: Map<string, Set<string>>): Set<string>;
32
+ export declare function collectTransitiveFormulaDependents(originCellKey: string, revDepsByCell: Map<string, Set<string>>, extraFormulaSeeds?: Iterable<string>, wide?: WideFormulaIndex): Set<string>;
@@ -0,0 +1,33 @@
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 reading formulas 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
+ * Walk the calc chain in slices and read every formula's references, then
16
+ * mark the graph complete (C8). Resolves 'aborted' if the graph is cleared
17
+ * while it runs or `isCancelled` says so. A tab with no grid is read from its
18
+ * `celldata`.
19
+ *
20
+ * Pass a getter to read the latest context in each slice (the Workbook does);
21
+ * a plain context is used as is.
22
+ */
23
+ export declare function warmFormulaDependencyGraph(ctxOrGetter: Context | (() => Context), opts: FormulaWarmupOptions): Promise<FormulaWarmupResult>;
24
+ /**
25
+ * Run the warm-up in the app: on `trigger()` (data ready after mount) and
26
+ * again `FORMULA_WARMUP_DEBOUNCE_MS` after each `markDepGraphIncomplete()`.
27
+ * Slices run in idle callbacks (setTimeout without requestIdleCallback) and
28
+ * only while the page is visible.
29
+ */
30
+ export declare function scheduleFormulaWarmup(getCtx: () => Context): {
31
+ trigger(): void;
32
+ dispose(): void;
33
+ };
@@ -1,7 +1,9 @@
1
1
  import { Cell, CellMatrix, Rect, Selection } from '../types';
2
2
  import { Context } from '../context';
3
+ import { FormulaArrowMode, FormulaArrowOverride } from './formula-arrow-mode';
3
4
  import { FormulaAsyncEvalJob } from './formula-async-eval';
4
5
  import { RangePassCacheEntry } from './formula-range-cache';
6
+ import { WideRange } from './formula-transitive-deps';
5
7
  import { SnapshotEvalOutput } from './formula-snapshot-eval';
6
8
 
7
9
  /** True when the formula is only numeric ops on TODAY()/NOW() (incl. unary +/−); used to display serials as dates. */
@@ -28,6 +30,9 @@ export declare class FormulaCache {
28
30
  rangedrag_row_start?: boolean;
29
31
  rangeSelectionActive?: boolean | null;
30
32
  keyboardRangeSelectionLock?: boolean;
33
+ arrowOverride?: FormulaArrowOverride;
34
+ arrowAutoAllowed?: boolean;
35
+ arrowSessionCell?: [number, number];
31
36
  /** True after arrow/Shift+arrow moved `func_selectedrange` without updating yellow selection. */
32
37
  formulaKeyboardRefSync?: boolean;
33
38
  formulaEditorOwner?: 'cell' | 'fx' | null;
@@ -51,6 +56,32 @@ export declare class FormulaCache {
51
56
  * affect them even when no precise reverse edge exists.
52
57
  */
53
58
  formulasWithWideRangeDeps: Set<string>;
59
+ /**
60
+ * The ranges of the wide formulas whose ranges could be read, by formula
61
+ * key. A wide formula joins a commit's walk only when one of these holds the
62
+ * edited cell or a formula cell the walk reaches. A key in
63
+ * `formulasWithWideRangeDeps` with no entry here (an unresolved tab, an
64
+ * unreadable range) joins every walk.
65
+ */
66
+ wideRangesByFormula: Map<string, WideRange[]>;
67
+ /**
68
+ * True once a full pass has evaluated every formula in the chain since the
69
+ * indexes were last reset, so `revDepsByCell` lists every dependent of every
70
+ * cell (C8). While true, a commit to a cell with no dependents runs no
71
+ * formula pass. Cleared by `markDepGraphIncomplete`.
72
+ */
73
+ depGraphComplete: boolean;
74
+ /**
75
+ * Bumped each time the flag is cleared. A deferred full pass records it at
76
+ * start and sets the flag only if nothing cleared it while it ran.
77
+ */
78
+ depGraphEpoch: number;
79
+ /**
80
+ * Grid size (`rows x cols`) of each dense tab when the graph was completed.
81
+ * Whole-row and whole-column references were recorded at that size, so a
82
+ * commit to a tab that has grown since takes the full pass again.
83
+ */
84
+ depGraphSheetSizes: Map<string, string>;
54
85
  /**
55
86
  * Dependency collection state for the currently-parsed formula, set by `execfunction`.
56
87
  * When null, dependency recording is disabled.
@@ -59,6 +90,10 @@ export declare class FormulaCache {
59
90
  originKey: string;
60
91
  deps: Set<string>;
61
92
  hasWideRangeDep: boolean;
93
+ /** Ranges over the cap, in the order they were read. */
94
+ wideRanges: WideRange[];
95
+ /** A wide dependency whose range can't be bounded (unresolved tab). */
96
+ wideUnreadable: boolean;
62
97
  };
63
98
  /** Step 2: per execFunctionGroup pass cache for materialized range reads. */
64
99
  rangeValuePassCache?: Map<string, RangePassCacheEntry>;
@@ -66,6 +101,21 @@ export declare class FormulaCache {
66
101
  hits: number;
67
102
  misses: number;
68
103
  };
104
+ /**
105
+ * Drop every recorded formula dependency, back to the state a fresh mount
106
+ * has. Used when a sheet's formula list is replaced from outside the
107
+ * engine (a collaborator's calcChain change, A4).
108
+ */
109
+ resetDependencyIndexes(): void;
110
+ /**
111
+ * The graph may miss edges: formulas moved, were rewritten or entered the
112
+ * chain without being evaluated. Commits take the full pass again until the
113
+ * next full pass completes.
114
+ */
115
+ markDepGraphIncomplete(): void;
116
+ /** Called after each `markDepGraphIncomplete` (the C8 warm-up re-runs). */
117
+ depGraphIncompleteListeners: Set<() => void>;
118
+ onDepGraphIncomplete(listener: () => void): () => void;
69
119
  constructor();
70
120
  materializeFullRangeFragment(context: Context, sheetId: string, flowdata: CellMatrix | null | undefined, startRow: number, endRow: number, startCol: number, endCol: number): {
71
121
  fragment: any[][];
@@ -77,10 +127,46 @@ export declare class FormulaCache {
77
127
  export declare function iscelldata(txt: string): boolean;
78
128
  export declare function getcellrange(ctx: Context, txt: string, formulaId?: string): any;
79
129
  export declare function getAllFunctionGroup(ctx: Context): any[];
130
+ /** Remove the dependency edges recorded for a cell that is no longer a formula. */
131
+ export declare function dropDependencyEdges(ctx: Context, r: number, c: number, id: string): void;
132
+ /**
133
+ * delFunctionGroup for many cells of one sheet: the chain and the dynamic
134
+ * array list are filtered once, not scanned and copied per cell. Same result
135
+ * as calling delFunctionGroup for each cell.
136
+ */
137
+ export declare function delFunctionGroupBatch(ctx: Context, id: string, cells: {
138
+ r: number;
139
+ c: number;
140
+ }[]): void;
80
141
  export declare function delFunctionGroup(ctx: Context, r: number, c: number, id?: string): void;
81
142
  export declare function insertUpdateFunctionGroup(ctx: Context, r: number, c: number, id?: string, calcChainSet?: Set<string>): void;
143
+ /**
144
+ * Drop every recorded formula dependency, back to a fresh mount's state, and
145
+ * mark the graph incomplete (A4, C8).
146
+ */
147
+ export declare function resetFormulaDependencyIndexes(ctx: Context): void;
148
+ /**
149
+ * End of a full pass that started at `epoch` (C8): every formula in the chain
150
+ * has recorded its dependencies, unless the graph was invalidated meanwhile.
151
+ */
152
+ export declare function finishFullFormulaPass(ctx: Context, epoch: number | null | undefined): void;
153
+ /**
154
+ * A tab that is loaded after the graph was completed keeps the flag on (K60,
155
+ * PR 466): loading builds the grid from `celldata` and does not change the
156
+ * tab's structure, and the text index already treated a whole-row or column
157
+ * reference to a tab with no grid as wide. Without a recorded size the first
158
+ * commit on the tab would take the full pass and clear the flag.
159
+ */
160
+ export declare function recordLoadedSheetSize(ctx: Context, sheetId: string | undefined, data: CellMatrix | null | undefined): void;
161
+ /**
162
+ * INDIRECT and OFFSET would resolve references at run time, which the graph
163
+ * cannot see. Today both evaluate to an error (formulajs implements neither),
164
+ * but formulas using them are kept on every commit's run list regardless.
165
+ */
166
+ export declare const RUNTIME_REFERENCE_RE: RegExp;
82
167
  export declare function execfunction(ctx: Context, txt: string, r: number, c: number, id?: string, calcChainSet?: Set<string>, isrefresh?: boolean, notInsertFunc?: boolean): any[];
83
168
  export declare function groupValuesRefresh(ctx: Context): void;
169
+ export declare function mergeFormulaDeps(ctx: Context, originKey: string, deps: Iterable<string>): void;
84
170
  /** Apply worker chunk output onto the live context (main thread only). */
85
171
  export declare function applyWorkerFormulaChunkResults(ctx: Context, output: SnapshotEvalOutput, impactedByCircular: Set<string>, cycleNodes: Set<string>, calcChainKeys?: string[], data?: CellMatrix | null): void;
86
172
  /** Run up to `chunkSize` formulas from an async job. Returns true when job is complete. */
@@ -98,6 +184,14 @@ export declare function execFunctionGroup(ctx: Context, origin_r: number, origin
98
184
  * without resizing `luckysheet_select_save`.
99
185
  */
100
186
  export declare function seedFormulaFuncSelectedRangeFromLastSelection(ctx: Context): boolean;
187
+ /**
188
+ * Explicit reference selection (F2) with the caret on an existing reference:
189
+ * seed the keyboard range from *that reference*, so the first arrow moves it
190
+ * from where it is (`=SUM(A1|)` + Right -> `=SUM(B1)`), not from the edited
191
+ * cell. Replaces any stale `func_selectedrange`. Returns false when the caret
192
+ * is not on a complete reference on the visible sheet.
193
+ */
194
+ export declare function seedFormulaFuncSelectedRangeFromTouchedReference(ctx: Context): boolean;
101
195
  export declare function createFormulaRangeSelect(ctx: Context, select: {
102
196
  rangeIndex: number;
103
197
  } & Rect): void;
@@ -146,7 +240,7 @@ export declare function isBareCellOrRangeOnlyFormula(formulaText: string): boole
146
240
  * disable sheet-driven range selection until the caret reaches a fresh insertion slot
147
241
  * (comma, open paren, operator, etc.) or the user starts an active range drag.
148
242
  */
149
- export declare function suppressFormulaRangeSelectionForInitialEdit(ctx: Context): void;
243
+ export declare function suppressFormulaRangeSelectionForInitialEdit(ctx: Context, cell?: [number, number]): void;
150
244
  export declare function isCaretAtValidFormulaRangeInsertionPoint(editor: HTMLElement | null): boolean;
151
245
  export declare function markRangeSelectionDirty(ctx: Context): void;
152
246
  /**
@@ -158,12 +252,35 @@ export declare function markRangeSelectionDirty(ctx: Context): void;
158
252
  export declare function getFormulaRangeIndexForKeyboardSync($editor: HTMLDivElement): number | null;
159
253
  export declare function handleFormulaInput(ctx: Context, $copyTo: HTMLDivElement | null | undefined, $editor: HTMLDivElement, kcode: number, preText?: string, refreshRangeSelect?: boolean): void;
160
254
  export declare function toggleFormulaAbsoluteReferenceAtCaret(ctx: Context, $copyTo: HTMLDivElement | null | undefined, $editor: HTMLDivElement | null | undefined): boolean;
255
+ export type FormulaTabs = {
256
+ editedTab: string;
257
+ formulaTab: string;
258
+ };
161
259
  /** True while picking a range for a formula (sheet selection drives references). */
162
260
  export declare function isLegacyFormulaRangeMode(ctx: Context): boolean;
163
261
  export declare function israngeseleciton(ctx: Context, istooltip?: boolean): boolean;
262
+ /**
263
+ * Start (or end) an arrow-key session with the defaults: automatic reference
264
+ * selection on, no F2 override. Call when a session opens on a cell that does
265
+ * not hold a formula, and when one ends.
266
+ */
267
+ export declare function resetFormulaArrowSession(ctx: Context): void;
268
+ /** The F2 override / auto flag in effect for the cell being edited right now. */
269
+ export declare function getFormulaArrowSession(ctx: Context): {
270
+ override: FormulaArrowOverride;
271
+ autoAllowed: boolean;
272
+ };
273
+ /** F2 pressed while editing: store the new override for this cell's session. */
274
+ export declare function setFormulaArrowOverride(ctx: Context, override: FormulaArrowOverride): void;
275
+ /**
276
+ * Single source of truth for what an arrow key does while editing.
277
+ * Thin ctx/DOM adapter over the pure `resolveArrowMode`.
278
+ */
279
+ export declare function getFormulaArrowMode(ctx: Context): FormulaArrowMode;
280
+ /** True while arrows should drive a cell reference (READY or ACTIVE). */
164
281
  export declare function isFormulaReferenceInputMode(ctx: Context): boolean;
165
282
  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;
283
+ export declare function functionStrChange(txt: string, type: string, rc: 'row' | 'col', orient: string | null, stindex: number, step: number, tabs: FormulaTabs): string;
167
284
  export declare function rangeSetValue(ctx: Context, cellInput: HTMLDivElement, selected: any, fxInput?: HTMLDivElement | null): void;
168
285
  export declare function onFormulaRangeDragEnd(ctx: Context): void;
169
286
  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,25 @@
1
+ /**
2
+ * A structural edit rewrites the cross-tab formulas of a tab that is not
3
+ * loaded in its `celldata`, as one replacement of the whole array (PR 466 N1).
4
+ * Undo and redo replay that replacement, so the engine is right; the Yjs write
5
+ * for it compares the two arrays here.
6
+ *
7
+ * Only formulas that name another tab (they contain `!`) are compared. Those
8
+ * are the cells a structural edit on another tab can rewrite; a cell a
9
+ * collaborator changed in between is not written back.
10
+ */
11
+ type CelldataEntry = {
12
+ r: number;
13
+ c: number;
14
+ v?: any;
15
+ };
16
+ export type CelldataArrayChange = {
17
+ sheetId: string;
18
+ path: ['celldata'];
19
+ key: string;
20
+ value: CelldataEntry | null;
21
+ type: 'update' | 'delete';
22
+ };
23
+ /** The Yjs changes that turn `before` into `after` for the cross-tab formulas. */
24
+ export declare function celldataArrayChanges(sheetId: string, before: CelldataEntry[] | undefined, after: CelldataEntry[] | undefined): CelldataArrayChange[];
25
+ export {};
@@ -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[];
@@ -4,7 +4,7 @@ export { default as clipboard } from './clipboard';
4
4
  export { moveToEnd, getRangeRectsByCharacterOffset } from './cursor';
5
5
  export { getDateBaseLocale, getCanonicalDateDisplayFormat, getCanonicalDateEditFormat, getDateEditFormatForCell, isUsDateBaseLocale, normalizeDateBaseLocale, shouldPreserveDateFormatForEdit, setDateBaseLocale, } from './date-base-locale';
6
6
  export { update, is_date, valueShowEs, isTypedCurrencyDisplayFormat, isCurrencyLikeNumberFormat, buildFiatCurrencyFormat, quoteSsfLiteral, } from './format';
7
- export { FormulaCache, groupValuesRefresh, setCaretPosition, getrangeseleciton, getFormulaEditorOwner, rangeHightlightselected, handleFormulaInput, israngeseleciton, createRangeHightlight, createFormulaRangeSelect, maybeRecoverDirtyRangeSelection, delFunctionGroup, functionHTMLGenerate, onFormulaRangeDragEnd, rangeDrag, rangeSetValue, remapFormulaReferencesByMap, getFormulaRangeIndexAtCaret, isCaretAtValidFormulaRangeInsertionPoint, isLegacyFormulaRangeMode, markRangeSelectionDirty, getFormulaRangeIndexForKeyboardSync, isFormulaReferenceInputMode, seedFormulaFuncSelectedRangeFromLastSelection, functionStrChange, setFormulaEditorOwner, getAllFunctionGroup, suppressFormulaRangeSelectionForInitialEdit, ensureFormulaRangeToSheet, shouldPreserveFormulaEditOnSheetSwitch, activateSheetForNavigation, returnToFormulaOriginSheet, } from './formula';
7
+ export { FormulaCache, groupValuesRefresh, setCaretPosition, getrangeseleciton, getFormulaEditorOwner, rangeHightlightselected, handleFormulaInput, israngeseleciton, createRangeHightlight, createFormulaRangeSelect, maybeRecoverDirtyRangeSelection, delFunctionGroup, functionHTMLGenerate, onFormulaRangeDragEnd, rangeDrag, rangeSetValue, remapFormulaReferencesByMap, getFormulaRangeIndexAtCaret, isCaretAtValidFormulaRangeInsertionPoint, isLegacyFormulaRangeMode, markRangeSelectionDirty, getFormulaRangeIndexForKeyboardSync, isFormulaReferenceInputMode, seedFormulaFuncSelectedRangeFromLastSelection, functionStrChange, setFormulaEditorOwner, getAllFunctionGroup, suppressFormulaRangeSelectionForInitialEdit, resetFormulaArrowSession, ensureFormulaRangeToSheet, shouldPreserveFormulaEditOnSheetSwitch, activateSheetForNavigation, returnToFormulaOriginSheet, } from './formula';
8
8
  export { FORMULA_ASYNC_CHUNK_SIZE, FORMULA_ASYNC_EVAL_THRESHOLD, FORMULA_WORKER_CHUNK_SIZE, FORMULA_WORKER_THRESHOLD, isFormulaEvalPending, } from './formula-async-eval';
9
9
  export type { FormulaAsyncEvalJob } from './formula-async-eval';
10
10
  export { initFreeze } from './freeze';
@@ -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';