@fileverse-dev/dsheet 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +1 -0
  2. package/dist/{constants-Q8nzbvQO.js → constants-Cdz6oSCq.js} +3 -5
  3. package/dist/constants.js +1 -1
  4. package/dist/editor/components/editor-workbook-sync.d.ts +1 -1
  5. package/dist/editor/constants/shared-constants.d.ts +0 -2
  6. package/dist/editor/contexts/editor-context.d.ts +4 -0
  7. package/dist/editor/dsheet-editor.d.ts +1 -1
  8. package/dist/editor/hooks/use-celldata-compaction.d.ts +23 -0
  9. package/dist/editor/hooks/use-editor-sync.d.ts +2 -0
  10. package/dist/editor/hooks/use-xlsx-import-impl.d.ts +2 -1
  11. package/dist/editor/hooks/use-xlsx-import.d.ts +2 -1
  12. package/dist/editor/types.d.ts +8 -0
  13. package/dist/editor/utils/apply-comment-markers.d.ts +22 -0
  14. package/dist/editor/utils/compact-committed-celldata.d.ts +28 -0
  15. package/dist/editor/utils/config-ydoc-update.d.ts +20 -0
  16. package/dist/editor/utils/update-ydoc.d.ts +13 -3
  17. package/dist/executeStringFunction-DVN2p-9G.js +32625 -0
  18. package/dist/formula.js +1 -1
  19. package/dist/{index-Dql-IRPC.js → index-T7U1EYEU.js} +21792 -24680
  20. package/dist/index.es.js +39 -39
  21. package/dist/persistence-utils-DsM_MOB1.js +89 -0
  22. package/dist/persistence-utils.d.ts +17 -0
  23. package/dist/persistence.d.ts +12 -0
  24. package/dist/persistence.js +118 -0
  25. package/dist/sheet-engine/core/api/cell.d.ts +0 -20
  26. package/dist/sheet-engine/core/api/common.d.ts +2 -1
  27. package/dist/sheet-engine/core/api/index.d.ts +1 -0
  28. package/dist/sheet-engine/core/api/sheet-flowdata-lifecycle.d.ts +17 -0
  29. package/dist/sheet-engine/core/api/sheet.d.ts +5 -0
  30. package/dist/sheet-engine/core/modules/formula-worker-bridge.d.ts +1 -0
  31. package/dist/sheet-engine/core/modules/sheet-metadata-hooks.d.ts +4 -0
  32. package/dist/sheet-engine/core/modules/sheet.d.ts +17 -1
  33. package/dist/sheet-engine/core/paste/paste-border-utils.d.ts +23 -0
  34. package/dist/sheet-engine/core/settings.d.ts +1 -1
  35. package/dist/sheet-engine/core/types.d.ts +3 -0
  36. package/dist/sheet-engine/core/utils/active-draft-context.d.ts +4 -0
  37. package/dist/sheet-engine/core/utils/border-config-utils.d.ts +16 -0
  38. package/dist/sheet-engine/core/utils/cell-persist-utils.d.ts +10 -0
  39. package/dist/sheet-engine/core/utils/merge-hydrate.d.ts +15 -0
  40. package/dist/sheet-engine/core/utils/mirror-cell-format-ranges.d.ts +17 -0
  41. package/dist/sheet-engine/core/utils/range-format.d.ts +76 -0
  42. package/dist/sheet-engine/core/utils/ydoc-celldata-changes.d.ts +46 -0
  43. package/dist/sheet-engine/react/components/Workbook/api.d.ts +8 -1
  44. package/dist/sheet-engine/react/components/Workbook/index.d.ts +5 -1
  45. package/dist/use-xlsx-import-impl-B9Uq_cFK.js +1572 -0
  46. package/dist/{xlsx-export-impl-DfQuhamE.js → xlsx-export-impl-0bnKq9JC.js} +1210 -1198
  47. package/package.json +16 -6
  48. package/dist/executeStringFunction-C5hEkx9z.js +0 -27694
  49. package/dist/use-xlsx-import-impl-BsL90Hs0.js +0 -1537
package/dist/index.es.js CHANGED
@@ -1,7 +1,7 @@
1
- import { C as s, a as t, b as o, S as r, d as l, i as n, e as i, T as d, f as S, g as c, h, j as m, k as p, l as C, n as u, o as E, p as F, q as g, s as x, t as R, u as L, v as f, w as A, x as I, z as w, A as T, B as b, D as v, E as M, F as D, G as k, H as V, I as X, J as z, K as P, L as U, M as _, N as y } from "./index-Dql-IRPC.js";
2
- import { bW as G, bX as H, bY as O, c0 as j, bi as J, e as K, f as N, h as Y, a as q, cm as W, as as Z, cu as Q } from "./executeStringFunction-C5hEkx9z.js";
1
+ import { C as s, a as t, b as o, S as r, d as l, i as d, e as n, T as i, f as c, g as S, h, j as m, k as p, l as C, n as u, o as E, p as F, q as g, s as x, t as R, u as f, v as A, w as L, x as w, z as I, A as T, B as v, D, E as M } from "./index-T7U1EYEU.js";
2
+ import { cm as k, cn as V, co as X, ct as z, bj as P, e as U, f as _, l as j, a as y, d2 as B, d3 as O, b2 as G, d4 as H, d5 as q, d9 as J, da as K, dc as N, D as Y, dr as Z, dR as Q, aX as W } from "./executeStringFunction-DVN2p-9G.js";
3
3
  import { FLVURL as ee } from "@fileverse-dev/formulajs";
4
- import { E as se, S as te } from "./constants-Q8nzbvQO.js";
4
+ import { E as se, S as te } from "./constants-Cdz6oSCq.js";
5
5
  export {
6
6
  s as CommentAction,
7
7
  t as CommentCellUI,
@@ -10,50 +10,50 @@ export {
10
10
  l as DSheetSkeleton,
11
11
  se as ERROR_MESSAGES_FLAG,
12
12
  ee as FLVURL,
13
- n as FortuneCore,
13
+ d as FortuneCore,
14
14
  te as SERVICES_API_KEY,
15
- i as SupportedChain,
16
- d as TEMPLATES,
17
- S as api,
18
- G as clearColumnsCellsFormat,
19
- c as clearFilter,
20
- H as clearRowsCellsFormat,
21
- O as clearSelectedCellFormat,
15
+ n as SupportedChain,
16
+ i as TEMPLATES,
17
+ c as api,
18
+ k as clearColumnsCellsFormat,
19
+ S as clearFilter,
20
+ V as clearRowsCellsFormat,
21
+ X as clearSelectedCellFormat,
22
22
  h as createFilter,
23
- j as deleteRowCol,
24
- J as deleteSelectedCellText,
23
+ z as deleteRowCol,
24
+ P as deleteSelectedCellText,
25
25
  m as describeMatchedShortcut,
26
- K as executeStringFunction,
27
- N as formulaResponseUiSync,
28
- Y as getFlowdata,
26
+ U as executeStringFunction,
27
+ _ as formulaResponseUiSync,
28
+ j as getFlowdata,
29
29
  p as getRemoveDuplicatesErrorMessage,
30
30
  C as getRemoveDuplicatesPreview,
31
- q as getSheetIndex,
31
+ y as getSheetIndex,
32
32
  u as handleCSVUpload,
33
33
  E as handleCopy,
34
34
  F as handleExportToCSV,
35
35
  g as handleExportToJSON,
36
36
  x as handleExportToXLSX,
37
- R as handleFreeze,
38
- L as handleHorizontalAlign,
39
- f as handleLink,
40
- A as handleMerge,
41
- I as handlePasteByClick,
42
- w as handleSort,
43
- T as handleTextSize,
44
- b as handleVerticalAlign,
45
- v as importSpreadsheetFile,
46
- W as insertRowCol,
47
- M as isBrowserZoomShortcut,
48
- D as isFormulaListShortcut,
49
- k as isOpenShortcutsModalShortcut,
50
- Z as jfrefreshgrid,
51
- Q as loadLocale,
52
- V as removeActiveImage,
53
- X as removeDuplicates,
54
- z as showImgChooser,
55
- P as toolbarItemClickHandler,
56
- U as updateFormat,
57
- _ as useEnsStatus,
58
- y as useXLSXImport
37
+ B as handleFreeze,
38
+ O as handleHorizontalAlign,
39
+ G as handleLink,
40
+ H as handleMerge,
41
+ R as handlePasteByClick,
42
+ q as handleSort,
43
+ J as handleTextSize,
44
+ K as handleVerticalAlign,
45
+ f as importSpreadsheetFile,
46
+ N as insertRowCol,
47
+ A as isBrowserZoomShortcut,
48
+ L as isFormulaListShortcut,
49
+ w as isOpenShortcutsModalShortcut,
50
+ Y as jfrefreshgrid,
51
+ Z as loadLocale,
52
+ I as removeActiveImage,
53
+ T as removeDuplicates,
54
+ v as showImgChooser,
55
+ Q as toolbarItemClickHandler,
56
+ W as updateFormat,
57
+ D as useEnsStatus,
58
+ M as useXLSXImport
59
59
  };
@@ -0,0 +1,89 @@
1
+ import * as c from "yjs";
2
+ const u = typeof Buffer == "function";
3
+ typeof TextDecoder == "function" && new TextDecoder();
4
+ typeof TextEncoder == "function" && new TextEncoder();
5
+ const b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", s = Array.prototype.slice.call(b), l = ((t) => {
6
+ let e = {};
7
+ return t.forEach((r, o) => e[r] = o), e;
8
+ })(s), g = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/, f = String.fromCharCode.bind(String), h = typeof Uint8Array.from == "function" ? Uint8Array.from.bind(Uint8Array) : (t) => new Uint8Array(Array.prototype.slice.call(t, 0)), S = (t) => t.replace(/=/g, "").replace(/[+\/]/g, (e) => e == "+" ? "-" : "_"), A = (t) => t.replace(/[^A-Za-z0-9\+\/]/g, ""), E = (t) => {
9
+ let e, r, o, n, a = "";
10
+ const p = t.length % 3;
11
+ for (let i = 0; i < t.length; ) {
12
+ if ((r = t.charCodeAt(i++)) > 255 || (o = t.charCodeAt(i++)) > 255 || (n = t.charCodeAt(i++)) > 255)
13
+ throw new TypeError("invalid character found");
14
+ e = r << 16 | o << 8 | n, a += s[e >> 18 & 63] + s[e >> 12 & 63] + s[e >> 6 & 63] + s[e & 63];
15
+ }
16
+ return p ? a.slice(0, p - 3) + "===".substring(p) : a;
17
+ }, U = typeof btoa == "function" ? (t) => btoa(t) : u ? (t) => Buffer.from(t, "binary").toString("base64") : E, d = u ? (t) => Buffer.from(t).toString("base64") : (t) => {
18
+ let r = [];
19
+ for (let o = 0, n = t.length; o < n; o += 4096)
20
+ r.push(f.apply(null, t.subarray(o, o + 4096)));
21
+ return U(r.join(""));
22
+ }, m = (t, e = !1) => e ? S(d(t)) : d(t), _ = (t) => {
23
+ if (t = t.replace(/\s+/g, ""), !g.test(t))
24
+ throw new TypeError("malformed base64.");
25
+ t += "==".slice(2 - (t.length & 3));
26
+ let e, r, o, n = [];
27
+ for (let a = 0; a < t.length; )
28
+ e = l[t.charAt(a++)] << 18 | l[t.charAt(a++)] << 12 | (r = l[t.charAt(a++)]) << 6 | (o = l[t.charAt(a++)]), r === 64 ? n.push(f(e >> 16 & 255)) : o === 64 ? n.push(f(e >> 16 & 255, e >> 8 & 255)) : n.push(f(e >> 16 & 255, e >> 8 & 255, e & 255));
29
+ return n.join("");
30
+ }, w = typeof atob == "function" ? (t) => atob(A(t)) : u ? (t) => Buffer.from(t, "base64").toString("binary") : _, D = u ? (t) => h(Buffer.from(t, "base64")) : (t) => h(w(t).split("").map((e) => e.charCodeAt(0))), T = (t) => D(C(t)), C = (t) => A(t.replace(/[-_]/g, (e) => e == "-" ? "+" : "/")), P = 8e3, x = (t) => t instanceof Error ? t : new Error(String(t)), v = async (t, e) => {
31
+ let r;
32
+ try {
33
+ return await Promise.race([
34
+ t,
35
+ new Promise((o, n) => {
36
+ r = setTimeout(
37
+ () => n(new Error("dSheet IndexedDB operation timed out")),
38
+ e
39
+ );
40
+ })
41
+ ]);
42
+ } finally {
43
+ r && clearTimeout(r);
44
+ }
45
+ }, y = (t, e, r) => ({
46
+ dsheetId: t,
47
+ status: e,
48
+ encodedState: null,
49
+ stateVector: null,
50
+ ...r ? { error: x(r) } : {}
51
+ }), B = (t, e) => {
52
+ const r = c.encodeStateAsUpdate(e);
53
+ return {
54
+ dsheetId: t,
55
+ status: r.length <= 2 ? "empty" : "available",
56
+ encodedState: m(r),
57
+ stateVector: m(c.encodeStateVector(e))
58
+ };
59
+ }, z = (t, e, r) => {
60
+ if (!r)
61
+ return y(
62
+ t,
63
+ "unavailable",
64
+ new Error("dSheet document is not ready")
65
+ );
66
+ let o;
67
+ const n = new c.Doc();
68
+ try {
69
+ o = T(e), c.applyUpdate(n, o);
70
+ } catch (a) {
71
+ return y(t, "corrupt", a);
72
+ } finally {
73
+ n.destroy();
74
+ }
75
+ try {
76
+ return c.applyUpdate(r, o, "dsheet-package-ingress"), B(t, r);
77
+ } catch (a) {
78
+ return y(t, "corrupt", a);
79
+ }
80
+ };
81
+ export {
82
+ P as D,
83
+ m as f,
84
+ z as m,
85
+ B as s,
86
+ T as t,
87
+ y as u,
88
+ v as w
89
+ };
@@ -0,0 +1,17 @@
1
+ import * as Y from 'yjs';
2
+ export declare const DEFAULT_DSHEET_PERSISTENCE_TIMEOUT_MS = 8000;
3
+ export type DSheetContentStatus = 'available' | 'empty' | 'missing' | 'corrupt' | 'timed-out' | 'unavailable';
4
+ export type DSheetContentSnapshot = {
5
+ dsheetId: string;
6
+ status: DSheetContentStatus;
7
+ encodedState: string | null;
8
+ stateVector: string | null;
9
+ error?: Error;
10
+ };
11
+ export type DSheetContentReadOptions = {
12
+ timeoutMs?: number;
13
+ };
14
+ export declare const withDsheetPersistenceTimeout: <T>(promise: Promise<T>, timeoutMs: number) => Promise<T>;
15
+ export declare const unavailableDsheetContentSnapshot: (dsheetId: string, status: Exclude<DSheetContentStatus, "available" | "empty">, error?: unknown) => DSheetContentSnapshot;
16
+ export declare const snapshotDsheetDocument: (dsheetId: string, doc: Y.Doc) => DSheetContentSnapshot;
17
+ export declare const mergeDsheetContentIntoDocument: (dsheetId: string, encodedState: string, doc: Y.Doc | null) => DSheetContentSnapshot;
@@ -0,0 +1,12 @@
1
+ import { DSheetContentReadOptions, DSheetContentSnapshot } from './persistence-utils';
2
+
3
+ export type { DSheetContentReadOptions, DSheetContentSnapshot, DSheetContentStatus, } from './persistence-utils';
4
+ export declare const getDsheetStateVector: (encodedState: string | Uint8Array) => string;
5
+ /**
6
+ * Read the package-owned Y-IndexedDB database without attaching another
7
+ * persistence writer. Completed reads are never cached.
8
+ */
9
+ export declare const readDsheetContent: (dsheetId: string, options?: DSheetContentReadOptions) => Promise<DSheetContentSnapshot>;
10
+ /** Merge content into the package-owned Y-IndexedDB document. */
11
+ export declare const mergeDsheetContent: (dsheetId: string, encodedState: string, options?: DSheetContentReadOptions) => Promise<DSheetContentSnapshot>;
12
+ export declare const deleteDsheetContent: (dsheetId: string) => Promise<void>;
@@ -0,0 +1,118 @@
1
+ import { t as D, f as h, D as b, u as p, w as S, s as w } from "./persistence-utils-DsM_MOB1.js";
2
+ import * as u from "yjs";
3
+ import { clearDocument as v, IndexeddbPersistence as E } from "y-indexeddb";
4
+ const f = /* @__PURE__ */ new Map(), M = (e) => {
5
+ const o = new u.Doc();
6
+ try {
7
+ return u.applyUpdate(
8
+ o,
9
+ typeof e == "string" ? D(e) : e
10
+ ), h(u.encodeStateVector(o));
11
+ } finally {
12
+ o.destroy();
13
+ }
14
+ }, x = (e, o) => new Promise((s) => {
15
+ const a = new u.Doc();
16
+ let r = null, t = null, i = !1, m = !1;
17
+ const y = (n) => {
18
+ i || (i = !0, clearTimeout(g), r == null || r.close(), a.destroy(), s(n));
19
+ }, c = (n, d) => y(p(e, n, d)), g = setTimeout(() => {
20
+ try {
21
+ t == null || t.abort();
22
+ } catch {
23
+ }
24
+ c("timed-out", new Error("dSheet IndexedDB read timed out"));
25
+ }, o);
26
+ let l;
27
+ try {
28
+ l = indexedDB.open(e);
29
+ } catch (n) {
30
+ c("unavailable", n);
31
+ return;
32
+ }
33
+ l.onupgradeneeded = () => {
34
+ var n;
35
+ m = !0, (n = l.transaction) == null || n.abort();
36
+ }, l.onerror = () => {
37
+ m ? y(p(e, "missing")) : c("unavailable", l.error);
38
+ }, l.onsuccess = () => {
39
+ if (r = l.result, !r.objectStoreNames.contains("updates") || !r.objectStoreNames.contains("custom")) {
40
+ c("corrupt", new Error("dSheet IndexedDB schema is invalid"));
41
+ return;
42
+ }
43
+ try {
44
+ t = r.transaction("updates", "readonly");
45
+ const n = t.objectStore("updates").getAll();
46
+ n.onerror = () => c("unavailable", n.error), n.onsuccess = () => {
47
+ try {
48
+ for (const d of n.result ?? []) {
49
+ if (!(d instanceof Uint8Array))
50
+ throw new Error("dSheet IndexedDB contains a non-Yjs update");
51
+ u.applyUpdate(a, d);
52
+ }
53
+ } catch (d) {
54
+ c("corrupt", d);
55
+ }
56
+ }, t.oncomplete = () => y(w(e, a)), t.onabort = () => {
57
+ i || c("unavailable", t == null ? void 0 : t.error);
58
+ }, t.onerror = () => {
59
+ i || c("unavailable", t == null ? void 0 : t.error);
60
+ };
61
+ } catch (n) {
62
+ c("unavailable", n);
63
+ }
64
+ };
65
+ }), B = async (e, o) => {
66
+ if (typeof indexedDB > "u")
67
+ return p(
68
+ e,
69
+ "unavailable",
70
+ new Error("IndexedDB is unavailable")
71
+ );
72
+ const s = indexedDB;
73
+ if (s.databases)
74
+ try {
75
+ if (!(await s.databases()).some((r) => r.name === e))
76
+ return p(e, "missing");
77
+ } catch {
78
+ }
79
+ return x(e, o);
80
+ }, A = (e, o = {}) => {
81
+ const s = f.get(e);
82
+ if (s) return s;
83
+ const a = B(
84
+ e,
85
+ o.timeoutMs ?? b
86
+ ).finally(() => {
87
+ f.get(e) === a && f.delete(e);
88
+ });
89
+ return f.set(e, a), a;
90
+ }, C = async (e, o, s = {}) => {
91
+ const a = s.timeoutMs ?? b, r = new u.Doc();
92
+ try {
93
+ u.applyUpdate(r, D(o), "dsheet-package-ingress");
94
+ } catch (i) {
95
+ return r.destroy(), p(e, "corrupt", i);
96
+ }
97
+ let t = null;
98
+ try {
99
+ return t = new E(e, r), await S(t.whenSynced, a), w(e, r);
100
+ } catch (i) {
101
+ return p(
102
+ e,
103
+ /timed out/i.test(String(i)) ? "timed-out" : "unavailable",
104
+ i
105
+ );
106
+ } finally {
107
+ await (t == null ? void 0 : t.destroy().catch(() => {
108
+ })), r.destroy();
109
+ }
110
+ }, j = async (e) => {
111
+ f.delete(e), typeof indexedDB < "u" && await v(e);
112
+ };
113
+ export {
114
+ j as deleteDsheetContent,
115
+ M as getDsheetStateVector,
116
+ C as mergeDsheetContent,
117
+ A as readDsheetContent
118
+ };
@@ -6,26 +6,6 @@ export declare function getCellValue(ctx: Context, row: number, column: number,
6
6
  type?: keyof Cell;
7
7
  }): any;
8
8
  export declare function setCellValue(ctx: Context, row: number, column: number, value: any, cellInput: HTMLDivElement | null, options?: CommonOptions, callAfterUpdate?: boolean): void;
9
- /**
10
- * Apply a cell value coming from a remote RTC peer, verbatim.
11
- *
12
- * This differs from `setCellValue` in two important ways and must be used for
13
- * every Yjs-driven remote apply:
14
- *
15
- * 1. It NEVER runs the formula engine and NEVER fires the local-edit hooks
16
- * (`onLocalCellEdit` / `afterUpdateCell`). The peer already computed the
17
- * value, so we use the synced `v`/`m`/`f` as-is. This avoids both
18
- * recomputation divergence and an update loop back into Yjs.
19
- *
20
- * 2. It PRESERVES the formula calc list. The regular `setCellValue` object
21
- * branch calls `delFunctionGroup`, which removes the cell from `calcChain`
22
- * and strips its dependency edges. Because `execFunctionGroup` walks
23
- * `calcChain` to decide what to recompute, dropping a formula cell there
24
- * permanently breaks its reactivity on that client (even after RTC stops).
25
- * Here we instead keep formula cells registered via
26
- * `insertUpdateFunctionGroup`, so they stay reactive to future local edits
27
- * on both owner and peer.
28
- */
29
9
  export declare function applyRemoteCellValue(ctx: Context, row: number, column: number, value: any, options?: CommonOptions): void;
30
10
  export declare function clearCell(ctx: Context, row: number, column: number, options?: CommonOptions): void;
31
11
  export declare function setCellFormat(ctx: Context, row: number, column: number, attr: keyof Cell, value: any, options?: CommonOptions): void;
@@ -1,12 +1,13 @@
1
1
  import { Context } from '../context';
2
2
  import { CellMatrix, CellWithRowAndCol, Sheet } from '../types';
3
+ import { CellFormatRange } from '../utils/range-format';
3
4
 
4
5
  export type CommonOptions = {
5
6
  index?: number;
6
7
  id?: string;
7
8
  };
8
9
  export declare const dataToCelldata: (data: CellMatrix | undefined) => CellWithRowAndCol[];
9
- export declare const celldataToData: (celldata: CellWithRowAndCol[], rowCount?: number, colCount?: number) => CellMatrix | null;
10
+ export declare const celldataToData: (celldata: CellWithRowAndCol[], rowCount?: number, colCount?: number, cellFormatRanges?: CellFormatRange[], merge?: Record<string, any> | null) => CellMatrix | null;
10
11
  export declare function getSheet(ctx: Context, options?: CommonOptions): Sheet;
11
12
  export declare function getSheetWithLatestCelldata(ctx: Context, options?: CommonOptions): {
12
13
  celldata: CellWithRowAndCol[];
@@ -7,5 +7,6 @@ export * from './rowcol';
7
7
  export * from './range';
8
8
  export * from './merge';
9
9
  export * from './sheet';
10
+ export * from './sheet-flowdata-lifecycle';
10
11
  export * from './workbook';
11
12
  export * from '../modules/error-state-helpers';
@@ -0,0 +1,17 @@
1
+ import { Context } from '../context';
2
+
3
+ /** Drop cached dense-sheet set (e.g. after structural workbook changes). */
4
+ export declare function invalidateSheetsRequiredDenseCache(): void;
5
+ /**
6
+ * Sheets that must keep dense `data` while `activeSheetId` is active:
7
+ * the active tab, tabs its formulas read, and tabs with formulas that read it.
8
+ */
9
+ export declare function getSheetsRequiredDense(ctx: Context, activeSheetId: string): Set<string>;
10
+ /** Sheets the formula worker needs dense — active refs plus any tab with formulas. */
11
+ export declare function getSheetsNeededForWorkerSnapshot(ctx: Context): Set<string>;
12
+ export declare function demoteSheetToCelldata(ctx: Context, sheetId: string): void;
13
+ /**
14
+ * On tab switch: persist outgoing config, demote tabs not needed dense,
15
+ * hydrate active tab + cross-sheet references.
16
+ */
17
+ export declare function syncAndDemoteInactiveFlowdata(ctx: Context, activeSheetId: string, previousSheetId: string | null): Set<string>;
@@ -5,6 +5,11 @@ import { CellMatrix, Sheet } from '../types';
5
5
  export declare function getAllSheets(ctx: Context): Sheet[];
6
6
  export { getSheet };
7
7
  export declare function initSheetData(draftCtx: Context, index: number, newData: Sheet): CellMatrix | null;
8
+ /** Build dense `data` from sparse `celldata` when a sheet is activated or referenced. */
9
+ export declare function ensureSheetFlowdata(ctx: Context, options?: {
10
+ index?: number;
11
+ id?: string;
12
+ }): CellMatrix | null;
8
13
  export declare function hideSheet(ctx: Context, sheetId: string): void;
9
14
  export declare function showSheet(ctx: Context, sheetId: string): void;
10
15
  export declare function copySheet(ctx: Context, sheetId: string): void;
@@ -2,6 +2,7 @@ import { Context } from '../context';
2
2
  import { SnapshotEvalInput, SnapshotEvalOutput, SnapshotFormulaCell, evalFormulasInSnapshot } from './formula-snapshot-eval';
3
3
  import { FORMULA_WORKER_CHUNK_SIZE } from './formula-async-eval';
4
4
 
5
+ export declare function invalidateFormulaWorkerSnapshot(): void;
5
6
  export declare function buildSnapshotEvalInput(ctx: Context, formulas: SnapshotFormulaCell[]): SnapshotEvalInput;
6
7
  export declare function buildWorkerEvalInput(ctx: Context, formulas: SnapshotFormulaCell[]): Omit<SnapshotEvalInput, 'sheets'>;
7
8
  export declare function initFormulaWorkerSnapshot(ctx: Context, snapshotKey: string): boolean;
@@ -3,5 +3,9 @@ import { Context } from '../context';
3
3
  /**
4
4
  * Defer sheet-level metadata hooks until after React applies Immer updates, so
5
5
  * getSheet() / Yjs diff see dataVerification, CF rules, and hyperlinks from paste/cut.
6
+ *
7
+ * Capture the hook fns themselves (not `ctx.hooks`): paste runs inside produce,
8
+ * and reading a draft `hooks` proxy after it is revoked throws
9
+ * "Cannot perform 'get' on a proxy that has been revoked".
6
10
  */
7
11
  export declare function scheduleSheetMetadataSyncHooks(ctx: Context): void;
@@ -1,7 +1,23 @@
1
1
  import { Context } from '../context';
2
2
  import { Settings } from '../settings';
3
- import { CellMatrix, Sheet } from '../types';
3
+ import { CellMatrix, Sheet, SheetConfig } from '../types';
4
+ import { CellFormatRange } from '../utils/range-format';
4
5
 
6
+ /**
7
+ * Persist active ctx.config onto ONE sheet file only.
8
+ * If Immer wrote keys (e.g. cellFormatRanges) on file.config but not ctx.config,
9
+ * keep those instead of wiping them with a blind replace.
10
+ * Never touches other sheets.
11
+ */
12
+ export declare function assignActiveConfigToSheetFile(file: Sheet, activeConfig: SheetConfig | undefined): void;
13
+ /**
14
+ * Promote format-only cells in a rectangle into cellFormatRanges.
15
+ * Scans only [r1..r2]×[c1..c2]. Returns new ranges if anything changed.
16
+ *
17
+ * Writes through luckysheetfile[i].config (same as toolbar) so Immer undo
18
+ * history tracks the change and peers get the reverse via afterConfigChanges.
19
+ */
20
+ export declare function syncFormatOnlyRectIntoRanges(ctx: Context, cfg: SheetConfig | undefined, data: CellMatrix | null | undefined, r1: number, r2: number, c1: number, c2: number): CellFormatRange[] | null;
5
21
  export declare function storeSheetParamALL(ctx: Context): void;
6
22
  export declare function changeSheet(ctx: Context, id: string, isPivotInitial?: boolean, isNewSheet?: boolean, isCopySheet?: boolean): void;
7
23
  export declare function addSheet(ctx: Context, settings?: Required<Settings>, newSheetID?: string | undefined, // if action is from websocket, there will be a new sheetID
@@ -0,0 +1,23 @@
1
+ export declare function isTransparentBorderColor(color: string): boolean;
2
+ export declare function isMeaningfulBorderSide(side: {
3
+ style?: number;
4
+ color?: string;
5
+ } | undefined): boolean;
6
+ export declare function filterMeaningfulBorderSides(sides: {
7
+ l?: {
8
+ style?: number;
9
+ color?: string;
10
+ };
11
+ r?: {
12
+ style?: number;
13
+ color?: string;
14
+ };
15
+ t?: {
16
+ style?: number;
17
+ color?: string;
18
+ };
19
+ b?: {
20
+ style?: number;
21
+ color?: string;
22
+ };
23
+ }): typeof sides;
@@ -23,7 +23,7 @@ export type Hooks = {
23
23
  cellDataChange?: () => void;
24
24
  hyperlinkChange?: () => void;
25
25
  updateCellYdoc?: (changes: SheetChangePath[]) => void;
26
- updateAllCell?: (sheetId: string) => void;
26
+ updateAllCell?: (sheetId: string, caller?: string) => void;
27
27
  beforeUpdateCell?: (r: number, c: number, value: any) => boolean;
28
28
  /** Clears RTC remote-apply lock so local edits can run data-block formulas. */
29
29
  onLocalCellEdit?: () => void;
@@ -1,5 +1,6 @@
1
1
  import { Patch as ImmerPatch } from 'immer';
2
2
  import { PatchOptions } from './utils';
3
+ import { CellFormatRange } from './utils/range-format';
3
4
 
4
5
  export type Op = {
5
6
  op: 'replace' | 'remove' | 'add' | 'insertRowCol' | 'deleteRowCol' | 'addSheet' | 'deleteSheet';
@@ -140,6 +141,8 @@ export type SheetConfig = {
140
141
  customHeight?: Record<string, number>;
141
142
  customWidth?: Record<string, number>;
142
143
  borderInfo?: any[];
144
+ /** Range-level cell formatting for empty cells (toolbar bulk format). */
145
+ cellFormatRanges?: CellFormatRange[];
143
146
  authority?: any;
144
147
  rowReadOnly?: Record<number, number>;
145
148
  colReadOnly?: Record<number, number>;
@@ -0,0 +1,4 @@
1
+ import { Context } from '../context';
2
+
3
+ export declare function setActiveDraftContext(ctx: Context | null): void;
4
+ export declare function getActiveDraftContext(): Context | null;
@@ -0,0 +1,16 @@
1
+ import { Context } from '../context';
2
+
3
+ export type BorderSelection = {
4
+ row: [number, number];
5
+ column: [number, number];
6
+ };
7
+ /**
8
+ * Remap borderInfo after a row/column reorder (header drag).
9
+ * Uses the same old→new index map as remapCellFormatRanges.
10
+ * O(border entries × span) — only runs on drag drop, not per-frame.
11
+ */
12
+ export declare function remapBorderInfo(borderInfo: any[] | undefined, axis: 'row' | 'column', indexMap: Record<number, number>): any[];
13
+ /** Remove border entries overlapping a single selection (cell + range types). */
14
+ export declare function removeBorderInfoForSelection(borderInfo: any[], rowSt: number, rowEd: number, colSt: number, colEd: number): any[];
15
+ export declare function removeBorderInfoInSelections(borderInfo: any[] | undefined, selections: BorderSelection[]): any[];
16
+ export declare function syncBorderInfoToYdoc(ctx: Context, borderInfo: any[]): void;
@@ -0,0 +1,10 @@
1
+ import { Cell } from '../types';
2
+
3
+ export declare const CELL_FORMAT_ATTRS: readonly ["tb", "ht", "vt", "tr", "fs", "ff", "fc", "bl", "it", "un", "cl", "bg", "ct"];
4
+ export type CellFormatAttr = (typeof CELL_FORMAT_ATTRS)[number];
5
+ export declare function hasCellMeaningfulContent(cell: Cell | string | number | boolean | null | undefined): boolean;
6
+ export declare function isFormatOnlyEmptyCell(cell: Cell | string | number | boolean | null | undefined): boolean;
7
+ /** Pull only present format attrs from a format-only empty cell (cheap, no clone). */
8
+ export declare function extractCellFormatAttrs(cell: Cell | string | number | boolean | null | undefined): Partial<Record<CellFormatAttr, unknown>> | null;
9
+ export declare function shouldPersistCelldataCell(cell: Cell | string | number | boolean | null | undefined): boolean;
10
+ export declare function celldataEntryEqual(existing: unknown, next: unknown): boolean;
@@ -0,0 +1,15 @@
1
+ import { CellMatrix } from '../types';
2
+
3
+ type MergeEntry = {
4
+ r?: number;
5
+ c?: number;
6
+ rs?: number;
7
+ cs?: number;
8
+ };
9
+ /**
10
+ * Rebuild merge anchor + shadow `mc` refs on dense data from config.merge.
11
+ * Cheap: O(merge area), not O(grid). Safe to call on every hydrate — idempotent.
12
+ * Covers docs whose shadow cells were dropped by earlier compaction.
13
+ */
14
+ export declare function applyMergeConfigToData(data: CellMatrix | null | undefined, merge: Record<string, MergeEntry> | null | undefined): void;
15
+ export {};
@@ -0,0 +1,17 @@
1
+ import { Context } from '../context';
2
+ import { CellFormatRange } from './range-format';
3
+
4
+ /**
5
+ * Keep workbook config.cellFormatRanges aligned with a ydoc commit.
6
+ * Cheap no-op when already equal. Mutates ctx in place (immer draft or produce).
7
+ */
8
+ export declare function mirrorCellFormatRangesIntoContext(ctx: Context, sheetId: string, ranges: CellFormatRange[]): boolean;
9
+ export type CellFormatRangesCommit = {
10
+ sheetId: string;
11
+ ranges: CellFormatRange[];
12
+ };
13
+ /**
14
+ * Apply ydoc-committed ranges into the live workbook.
15
+ * Prefers the in-flight immer draft (same edit); falls back to a produce() update.
16
+ */
17
+ export declare function applyCellFormatRangesCommits(commits: CellFormatRangesCommit[], setContext?: ((updater: (prev: Context) => Context) => void) | null): void;