@fileverse-dev/dsheet 4.1.22 → 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.
- package/dist/editor/components/editor-workbook.d.ts +6 -0
- package/dist/editor/components/sidebar/editor-right-sidebar.d.ts +3 -1
- package/dist/editor/components/sidebar/sidebar-offsets.d.ts +12 -0
- package/dist/editor/components/sidebar/sidebar-offsets.test.d.ts +1 -0
- package/dist/editor/contexts/editor-context.d.ts +5 -0
- package/dist/editor/hooks/use-editor-sync.d.ts +5 -1
- package/dist/editor/types.d.ts +42 -0
- package/dist/editor/utils/activate-sheet-for-link.d.ts +3 -0
- package/dist/editor/utils/active-sheet-keeper.d.ts +21 -0
- package/dist/editor/utils/after-update-cell.d.ts +2 -0
- package/dist/editor/utils/after-update-cell.test.d.ts +1 -0
- package/dist/editor/utils/apply-comment-markers.d.ts +3 -1
- package/dist/editor/utils/apply-comment-markers.test.d.ts +1 -0
- package/dist/editor/utils/calc-chain-ydoc-update.test.d.ts +1 -0
- package/dist/editor/utils/content-change.d.ts +48 -0
- package/dist/editor/utils/content-change.test.d.ts +1 -0
- package/dist/editor/utils/content-fingerprint.d.ts +37 -0
- package/dist/editor/utils/content-fingerprint.test.d.ts +1 -0
- package/dist/editor/utils/editor-handle.d.ts +1 -1
- package/dist/editor/utils/format-gate.d.ts +23 -0
- package/dist/editor/utils/format-gate.test.d.ts +1 -0
- package/dist/editor/utils/navigate-to-sheet.d.ts +22 -0
- package/dist/editor/utils/patch-plain-celldata.d.ts +19 -0
- package/dist/editor/utils/patch-plain-celldata.test.d.ts +1 -0
- package/dist/editor/utils/rebuild-indexeddb-store.d.ts +12 -0
- package/dist/editor/utils/rebuild-indexeddb-store.failure.test.d.ts +1 -0
- package/dist/editor/utils/rebuild-indexeddb-store.test.d.ts +1 -0
- package/dist/editor/utils/remote-apply-guard.d.ts +26 -0
- package/dist/editor/utils/remote-apply-guard.test.d.ts +1 -0
- package/dist/editor/utils/sheet-ydoc-sync-utils.d.ts +13 -4
- package/dist/editor/utils/sheet-ydoc-sync-utils.test.d.ts +1 -0
- package/dist/editor/utils/structural-edit-formula-sync.test.d.ts +1 -0
- package/dist/editor/utils/update-ydoc.d.ts +9 -1
- package/dist/{es-S4GKlN-t.js → es-BlDQ6jCL.js} +1 -0
- package/dist/{executeStringFunction-CQ922vEp.js → executeStringFunction-DKA5MuP0.js} +7092 -6760
- package/dist/formula.js +1 -1
- package/dist/{hi-DMMTDTxZ.js → hi-CP0ta0Yk.js} +1 -0
- package/dist/{index-DhQTrCQd.js → index-ypRdpDnX.js} +22623 -21716
- package/dist/index.d.ts +1 -1
- package/dist/index.es.js +16 -16
- package/dist/persistence-utils-CSKBobX8.js +151 -0
- package/dist/persistence-utils.d.ts +2 -0
- package/dist/persistence.append.test.d.ts +1 -0
- package/dist/persistence.d.ts +13 -0
- package/dist/persistence.fingerprint.test.d.ts +1 -0
- package/dist/persistence.js +122 -74
- package/dist/sheet-engine/core/api/cell.d.ts +20 -1
- package/dist/sheet-engine/core/api/remote-apply.test.d.ts +1 -0
- package/dist/sheet-engine/core/index.d.ts +1 -1
- package/dist/sheet-engine/core/locale/en.d.ts +1 -0
- package/dist/sheet-engine/core/locale/es.d.ts +1 -0
- package/dist/sheet-engine/core/locale/hi.d.ts +1 -0
- package/dist/sheet-engine/core/locale/zh.d.ts +1 -0
- package/dist/sheet-engine/core/locale/zh_tw.d.ts +1 -0
- package/dist/sheet-engine/core/modules/b6-ydoc-writes.test.d.ts +1 -0
- package/dist/sheet-engine/core/modules/border.d.ts +9 -0
- package/dist/sheet-engine/core/modules/cell-shift.d.ts +11 -0
- package/dist/sheet-engine/core/modules/cell.commit-ydoc.test.d.ts +1 -0
- package/dist/sheet-engine/core/modules/dataVerification.d.ts +15 -0
- package/dist/sheet-engine/core/modules/engine-hot-spots.test.d.ts +1 -0
- package/dist/sheet-engine/core/modules/formula-async-eval.d.ts +5 -0
- package/dist/sheet-engine/core/modules/formula-narrowing.test.d.ts +1 -0
- package/dist/sheet-engine/core/modules/formula-snapshot-eval.d.ts +2 -0
- package/dist/sheet-engine/core/modules/formula-transitive-deps.d.ts +5 -1
- package/dist/sheet-engine/core/modules/formula-warmup.d.ts +37 -0
- package/dist/sheet-engine/core/modules/formula-warmup.test.d.ts +1 -0
- package/dist/sheet-engine/core/modules/formula.d.ts +48 -1
- package/dist/sheet-engine/core/modules/formula.dep-graph.test.d.ts +1 -0
- package/dist/sheet-engine/core/modules/formula.str-change.test.d.ts +1 -0
- package/dist/sheet-engine/core/modules/formula.wide-seed.test.d.ts +1 -0
- package/dist/sheet-engine/core/modules/history-calc-chain.d.ts +33 -0
- package/dist/sheet-engine/core/modules/history-calc-chain.test.d.ts +1 -0
- package/dist/sheet-engine/core/modules/index.d.ts +3 -2
- package/dist/sheet-engine/core/paste/paste-dep-graph.test.d.ts +1 -0
- package/dist/sheet-engine/core/paste-helpers/calculate-range-cell-size.d.ts +14 -0
- package/dist/sheet-engine/core/paste-helpers/calculate-range-cell-size.test.d.ts +1 -0
- package/dist/sheet-engine/core/settings.d.ts +7 -1
- package/dist/sheet-engine/core/utils/ydoc-celldata-changes.d.ts +16 -0
- package/dist/sheet-engine/react/components/ContextMenu/sheet-tab-menu-items.d.ts +15 -0
- package/dist/sheet-engine/react/components/Workbook/api.d.ts +4 -0
- package/dist/sheet-engine/react/components/Workbook/denomination-scan.d.ts +16 -0
- package/dist/sheet-engine/react/components/Workbook/denomination-scan.test.d.ts +1 -0
- package/dist/sheet-engine/react/components/Workbook/index.d.ts +2 -0
- package/dist/style.css +1 -1
- package/dist/sync-local/SyncManager.d.ts +2 -2
- package/dist/sync-local/SyncManager.remote-apply.test.d.ts +1 -0
- package/dist/sync-local/types/index.d.ts +2 -1
- package/dist/{template-data-list-BYOIK_Nd.js → template-data-list-apgmwRAT.js} +18 -10
- package/dist/{use-xlsx-import-impl-xphBNZu3.js → use-xlsx-import-impl-DQ3tpIAe.js} +120 -119
- package/dist/{xlsx-defined-names-3g5n40BA.js → xlsx-defined-names-CVVLxbe-.js} +2 -2
- package/dist/{xlsx-export-impl-DXyQpmMi.js → xlsx-export-impl-ghSoFZBz.js} +4 -4
- package/dist/{xlsx-hyperlink-inline-Cl9CbP5N.js → xlsx-hyperlink-inline-DXj7AkSf.js} +2 -2
- package/dist/{zh-Bv4KIDiJ.js → zh-CmOCFd5t.js} +1 -0
- package/dist/{zh_tw-BdpsK45h.js → zh_tw-BqyRw1gX.js} +1 -0
- package/package.json +2 -2
- package/dist/persistence-utils-BXFajzvq.js +0 -98
|
@@ -21,6 +21,10 @@ interface EditorWorkbookProps {
|
|
|
21
21
|
dsheetId: string;
|
|
22
22
|
onDuneChartEmbed?: () => void;
|
|
23
23
|
onSheetCountChange?: (sheetCount: number) => void;
|
|
24
|
+
onCopySheetLink?: (args: {
|
|
25
|
+
sheetId: string;
|
|
26
|
+
sheetName: string;
|
|
27
|
+
}) => void;
|
|
24
28
|
sidebarActivePanel?: string | null;
|
|
25
29
|
sidebarPortalRegistry?: SidebarPortalRegistryHandle | null;
|
|
26
30
|
sidebarPortalRenderers?: Record<string, SidebarPortalRenderer>;
|
|
@@ -29,6 +33,8 @@ interface EditorWorkbookProps {
|
|
|
29
33
|
onSignInToComment?: () => void;
|
|
30
34
|
onViewerModeChange?: (mode: 'comment' | 'view') => void;
|
|
31
35
|
theme?: ThemeKey;
|
|
36
|
+
showToolbar?: boolean;
|
|
37
|
+
showFormulaBar?: boolean;
|
|
32
38
|
}
|
|
33
39
|
export declare const EditorWorkbook: React.NamedExoticComponent<EditorWorkbookProps>;
|
|
34
40
|
export {};
|
|
@@ -15,6 +15,8 @@ interface EditorRightSidebarProps {
|
|
|
15
15
|
onClose: () => void;
|
|
16
16
|
/** Read/preview mode hides the toolbar, so the sidebar starts higher. */
|
|
17
17
|
isReadOnly?: boolean;
|
|
18
|
+
showNavbar?: boolean;
|
|
19
|
+
showToolbar?: boolean;
|
|
18
20
|
}
|
|
19
|
-
export declare const EditorRightSidebar: ({ isOpen, activePanelConfig, onClose, isReadOnly, }: EditorRightSidebarProps) => import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export declare const EditorRightSidebar: ({ isOpen, activePanelConfig, onClose, isReadOnly, showNavbar, showToolbar, }: EditorRightSidebarProps) => import("react/jsx-runtime").JSX.Element;
|
|
20
22
|
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Right sidebar position below the editor chrome. Read/preview mode keeps
|
|
3
|
+
* its existing offsets (the sidebar overlays the toolbar there).
|
|
4
|
+
*/
|
|
5
|
+
export declare const getRightSidebarOffsets: ({ isReadOnly, showNavbar, showToolbar, }: {
|
|
6
|
+
isReadOnly?: boolean;
|
|
7
|
+
showNavbar?: boolean;
|
|
8
|
+
showToolbar?: boolean;
|
|
9
|
+
}) => {
|
|
10
|
+
top: string;
|
|
11
|
+
height: string;
|
|
12
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -10,6 +10,7 @@ import { UseSmartContractReturn } from '../hooks/use-smart-contract';
|
|
|
10
10
|
import { CollaborationProps, CollabState, CollabUser } from '../../sync-local/types';
|
|
11
11
|
import { Awareness } from 'y-protocols/awareness';
|
|
12
12
|
import { DSheetContentSnapshot } from '../../persistence';
|
|
13
|
+
import { DSheetContentChange } from '../utils/content-change';
|
|
13
14
|
|
|
14
15
|
import * as Y from 'yjs';
|
|
15
16
|
export interface EditorContextType {
|
|
@@ -20,6 +21,8 @@ export interface EditorContextType {
|
|
|
20
21
|
getDocumentTitle?: (dsheetId: string) => Promise<string>;
|
|
21
22
|
updateDocumentTitle?: (title: string) => void;
|
|
22
23
|
isAuthorized: boolean;
|
|
24
|
+
/** True once the sheet's meta.format is above what this client supports. */
|
|
25
|
+
formatLocked?: boolean;
|
|
23
26
|
dataBlockCalcFunction: {
|
|
24
27
|
[key: string]: {
|
|
25
28
|
[key: string]: any;
|
|
@@ -31,6 +34,7 @@ export interface EditorContextType {
|
|
|
31
34
|
};
|
|
32
35
|
}>>;
|
|
33
36
|
refreshIndexedDB: () => Promise<void>;
|
|
37
|
+
rebuildLocalStore: () => Promise<void>;
|
|
34
38
|
sheetEditorRef: React.MutableRefObject<WorkbookInstance | null>;
|
|
35
39
|
setSheetEditorRef: React.RefCallback<WorkbookInstance>;
|
|
36
40
|
ydocRef: React.MutableRefObject<Y.Doc | null>;
|
|
@@ -80,6 +84,7 @@ interface EditorProviderProps {
|
|
|
80
84
|
enableIndexeddbSync?: boolean;
|
|
81
85
|
isReadOnly?: boolean;
|
|
82
86
|
onContentUpdate?: () => void;
|
|
87
|
+
onContentChange?: (change: DSheetContentChange) => void;
|
|
83
88
|
onChange?: (data: SheetUpdateData, encodedUpdate?: string) => void;
|
|
84
89
|
collaboration?: CollaborationProps;
|
|
85
90
|
externalEditorRef?: React.Ref<DSheetEditorHandle>;
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { IndexeddbPersistence } from 'y-indexeddb';
|
|
2
2
|
import { CollaborationProps } from '../../sync-local/types';
|
|
3
|
+
import { DSheetContentChange } from '../utils/content-change';
|
|
3
4
|
import * as Y from 'yjs';
|
|
4
|
-
export declare const useEditorSync: (dsheetId: string, enableIndexeddbSync?: boolean, isReadOnly?: boolean, portalContent?: string, collaboration?: CollaborationProps,
|
|
5
|
+
export declare const useEditorSync: (dsheetId: string, enableIndexeddbSync?: boolean, isReadOnly?: boolean, portalContent?: string, collaboration?: CollaborationProps, onRemoteApplied?: (update: Uint8Array) => void, onIndexedDbError?: (error: Error) => void) => {
|
|
5
6
|
ydocRef: import('react').MutableRefObject<Y.Doc | null>;
|
|
6
7
|
persistenceRef: import('react').MutableRefObject<IndexeddbPersistence | null>;
|
|
7
8
|
syncStatus: "error" | "syncing" | "initializing" | "synced";
|
|
8
9
|
isContentBootstrapReady: boolean;
|
|
9
10
|
refreshIndexedDB: () => Promise<void>;
|
|
11
|
+
rebuildLocalStore: () => Promise<void>;
|
|
10
12
|
getContentSnapshot: () => import('../../persistence-utils').DSheetContentSnapshot;
|
|
13
|
+
getContentFingerprint: () => string | null;
|
|
14
|
+
getContentChange: () => DSheetContentChange;
|
|
11
15
|
mergeContent: (encodedState: string) => import('../../persistence-utils').DSheetContentSnapshot;
|
|
12
16
|
collabState: import('../..').CollabState;
|
|
13
17
|
isCollabReady: boolean;
|
package/dist/editor/types.d.ts
CHANGED
|
@@ -5,10 +5,13 @@ import { CollaborationProps } from '../sync-local/types';
|
|
|
5
5
|
import { CommentsConfig } from './types/comments';
|
|
6
6
|
import { SmartContractConfig } from './types/smart-contract';
|
|
7
7
|
import { ApiKeyStorage } from './utils/api-key-storage';
|
|
8
|
+
import { DSheetContentChange } from './utils/content-change';
|
|
8
9
|
import { ThemeKey } from '../sheet-engine/core/theme';
|
|
9
10
|
import { DSheetContentSnapshot } from '../persistence';
|
|
11
|
+
import { NavigateToSheetOptions } from './utils/navigate-to-sheet';
|
|
10
12
|
|
|
11
13
|
import * as Y from 'yjs';
|
|
14
|
+
export type { DSheetContentChange } from './utils/content-change';
|
|
12
15
|
export type { ThemeKey } from '../sheet-engine/core/theme';
|
|
13
16
|
export type DSheetPermissionMode = 'view' | 'comment' | 'edit';
|
|
14
17
|
export type { CommentThread, CommentReply, CommentActionParams, CommentsConfig, CommentAnchorMove, } from './types/comments';
|
|
@@ -25,12 +28,28 @@ export interface EditorValues {
|
|
|
25
28
|
}
|
|
26
29
|
export type DSheetEditorHandle = WorkbookInstance & {
|
|
27
30
|
refreshIndexedDB: () => Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Delete this sheet's IndexedDB database and rewrite it from the live
|
|
33
|
+
* document (same Y.Doc, never replaced), so local edits are kept. Resolves
|
|
34
|
+
* once the new store has synced. Resolves as a no-op when the editor is
|
|
35
|
+
* read-only, local persistence is disabled or there is no sheet id. Rejects
|
|
36
|
+
* if the rebuild fails or a refresh/unmount supersedes it. Concurrent calls share one rebuild.
|
|
37
|
+
*/
|
|
38
|
+
rebuildLocalStore: () => Promise<void>;
|
|
28
39
|
terminateSession: () => void;
|
|
29
40
|
updateCollaboratorName: (name: string) => void;
|
|
30
41
|
updateSessionTitle: (args: {
|
|
31
42
|
encryptedTitle: string;
|
|
32
43
|
documentTitle: string;
|
|
33
44
|
}) => void;
|
|
45
|
+
navigateToSheet: (sheetId: string, opts?: NavigateToSheetOptions) => Promise<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Content fingerprint: base64 state vector + ":" + deleted count. Changes
|
|
48
|
+
* on every change, deletes included; compare with === only. null until
|
|
49
|
+
* y-indexeddb is attached and synced; use fingerprintFromUpdate of the
|
|
50
|
+
* IndexedDB body then.
|
|
51
|
+
*/
|
|
52
|
+
getContentFingerprint: () => string | null;
|
|
34
53
|
};
|
|
35
54
|
export interface PanelConfig {
|
|
36
55
|
id: string;
|
|
@@ -68,6 +87,13 @@ export interface DsheetProps {
|
|
|
68
87
|
setFetchingURLData?: (fetching: boolean) => void;
|
|
69
88
|
setInputFetchURLDataBlock?: React.Dispatch<React.SetStateAction<string>>;
|
|
70
89
|
renderNavbar?: (editorValues?: EditorValues) => JSX.Element;
|
|
90
|
+
/** Mount the navbar slot. `renderNavbar` still runs when hidden, so host
|
|
91
|
+
* side effects inside it keep working. Default true. */
|
|
92
|
+
showNavbar?: boolean;
|
|
93
|
+
/** Show the sheet toolbar. Default true. */
|
|
94
|
+
showToolbar?: boolean;
|
|
95
|
+
/** Show the formula bar. Default true. */
|
|
96
|
+
showFormulaBar?: boolean;
|
|
71
97
|
enableIndexeddbSync?: boolean;
|
|
72
98
|
dsheetId: string;
|
|
73
99
|
/**
|
|
@@ -75,6 +101,18 @@ export interface DsheetProps {
|
|
|
75
101
|
* Unlike `onChange`, this does not build a plain sheet or encode the Y.Doc.
|
|
76
102
|
*/
|
|
77
103
|
onContentUpdate?: () => void;
|
|
104
|
+
/**
|
|
105
|
+
* Cheap change signal (Stabilize A1): `hasContent`, `userEdited` and the
|
|
106
|
+
* content `fingerprint`, computed without encoding the Y.Doc. At most one
|
|
107
|
+
* call per second (trailing), flushed on pagehide, beforeunload and unmount.
|
|
108
|
+
* Read full state on demand with `editorStateRef.getContentSnapshot()`.
|
|
109
|
+
*/
|
|
110
|
+
onContentChange?: (change: DSheetContentChange) => void;
|
|
111
|
+
/**
|
|
112
|
+
* @deprecated Encodes the whole Y.Doc and rebuilds a plain workbook per
|
|
113
|
+
* call. Use `onContentChange` and read full state on demand. Called at most
|
|
114
|
+
* once per second (trailing), flushed only on unload and unmount.
|
|
115
|
+
*/
|
|
78
116
|
onChange?: (updateData: SheetUpdateData, encodedUpdate?: string) => void;
|
|
79
117
|
collaboration?: CollaborationProps;
|
|
80
118
|
/** Called when local IndexedDB persistence fails. The editor and durable
|
|
@@ -112,6 +150,10 @@ export interface DsheetProps {
|
|
|
112
150
|
onDataBlockEvent?: (event: DataBlockEvent) => void;
|
|
113
151
|
onDuneChartEmbed?: () => void;
|
|
114
152
|
onSheetCountChange?: (sheetCount: number) => void;
|
|
153
|
+
onCopySheetLink?: (args: {
|
|
154
|
+
sheetId: string;
|
|
155
|
+
sheetName: string;
|
|
156
|
+
}) => void;
|
|
115
157
|
/** Fires whenever local content-sync status changes. Host apps should gate
|
|
116
158
|
* collab start/resume on 'synced' — starting before local content is fully
|
|
117
159
|
* synced is what let the RTC layer bind to a stale doc in the past. */
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { WorkbookInstance } from '../../sheet-engine/react';
|
|
2
|
+
|
|
3
|
+
export type ActiveSheetKeeper = {
|
|
4
|
+
/**
|
|
5
|
+
* Call on every Workbook ref attach. `mountKey` must change whenever the
|
|
6
|
+
* Workbook is remounted (i.e. mirror the Workbook's React `key`).
|
|
7
|
+
*/
|
|
8
|
+
onAttach: (workbook: WorkbookInstance | null, mountKey: unknown) => void;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Fortune remounts the Workbook whenever the editor bumps its render key
|
|
12
|
+
* (collab rehydration, template apply, imports), and a fresh mount resets the
|
|
13
|
+
* active sheet to the first visible one. Remember the active sheet across
|
|
14
|
+
* attaches and restore it once per mount, as soon as the new mount has sheets.
|
|
15
|
+
*
|
|
16
|
+
* The restore runs synchronously inside the ref callback (React commit phase).
|
|
17
|
+
* That only enqueues a Workbook state update (same as setState in
|
|
18
|
+
* useLayoutEffect), and it goes through the same setContext path as clicking a
|
|
19
|
+
* sheet tab.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createActiveSheetKeeper(): ActiveSheetKeeper;
|
|
@@ -51,6 +51,8 @@ interface AfterUpdateCellParams {
|
|
|
51
51
|
collabIsOwner?: boolean;
|
|
52
52
|
remoteUpdateRef?: React.MutableRefObject<boolean>;
|
|
53
53
|
localUserEditRef?: React.MutableRefObject<boolean>;
|
|
54
|
+
/** Sheet that held the cell at commit time; falls back to the current sheet. */
|
|
55
|
+
sheetId?: string;
|
|
54
56
|
}
|
|
55
57
|
/** True when data-block formulas (API / smart contract) should run for this edit. */
|
|
56
58
|
export declare const shouldExecuteDataBlocks: (params: {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -8,7 +8,9 @@ type CommentData = object | null | undefined;
|
|
|
8
8
|
* `null`, so a tiny `{ ps }` object is created in the live view only so the
|
|
9
9
|
* triangle can render. Row/column drag still owns real cell data.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* Updates the given arrays in place and returns them. Sparse celldata entries
|
|
12
|
+
* are replaced with copies, never written into, because they may be Yjs
|
|
13
|
+
* content (see ySheetArrayToPlain).
|
|
12
14
|
*/
|
|
13
15
|
export declare const applyCommentMarkers: <T>(sheets: T | null | undefined, commentData: CommentData, allowComments: boolean | undefined) => T | null | undefined;
|
|
14
16
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as Y from 'yjs';
|
|
2
|
+
/**
|
|
3
|
+
* Cheap change signal for hosts (Stabilize A1). Built from the live Y.Doc
|
|
4
|
+
* without encoding it; full state stays available through
|
|
5
|
+
* editorStateRef.getContentSnapshot().
|
|
6
|
+
*/
|
|
7
|
+
export type DSheetContentChange = {
|
|
8
|
+
/** Same meaning as dsheets.new `isEmptySheet(...) === false`. */
|
|
9
|
+
hasContent: boolean;
|
|
10
|
+
/** A local user edit has happened since this editor mounted. */
|
|
11
|
+
userEdited: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* base64 state vector + ":" + deleted count. Changes on every change,
|
|
14
|
+
* deletes included; compare with === only. null until y-indexeddb is
|
|
15
|
+
* attached and synced.
|
|
16
|
+
*/
|
|
17
|
+
fingerprint: string | null;
|
|
18
|
+
};
|
|
19
|
+
/** Default-workbook seed and legacy migration: content, but not a user edit. */
|
|
20
|
+
export declare const INIT_ORIGIN = "init";
|
|
21
|
+
/** Idle celldata compaction: rewrites storage, not a user edit. */
|
|
22
|
+
export declare const COMPACTION_ORIGIN = "compaction";
|
|
23
|
+
/**
|
|
24
|
+
* Mirrors dsheets.new `isEmptySheet` (components/dsheet-editor/editor-utils.ts):
|
|
25
|
+
* no sheets → empty; more than one sheet → content; otherwise content when
|
|
26
|
+
* sheet 0 has any config key or any celldata entry. Stops at the first live
|
|
27
|
+
* entry, so it does not walk the sheet.
|
|
28
|
+
*/
|
|
29
|
+
export declare function computeHasContent(doc: Y.Doc, dsheetId: string): boolean;
|
|
30
|
+
export type UserEditTracker = {
|
|
31
|
+
userEdited(): boolean;
|
|
32
|
+
dispose(): void;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Turns on at the first transaction that changes the document and whose
|
|
36
|
+
* origin is not a known non-user origin or the IndexedDB provider.
|
|
37
|
+
*/
|
|
38
|
+
export declare function attachUserEditTracker(doc: Y.Doc, getIndexeddbOrigin: () => unknown): UserEditTracker;
|
|
39
|
+
export declare const CONTENT_CHANGE_WAIT_MS = 1000;
|
|
40
|
+
/**
|
|
41
|
+
* At most one host call per second (trailing only); local and remote changes
|
|
42
|
+
* share the throttle. The change is built when the call fires, never per edit.
|
|
43
|
+
*/
|
|
44
|
+
export declare function createContentChangeNotifier(getChange: () => DSheetContentChange, getHandler: () => ((change: DSheetContentChange) => void) | undefined, waitMs?: number): {
|
|
45
|
+
notify: () => void;
|
|
46
|
+
flush: () => void;
|
|
47
|
+
cancel: () => any;
|
|
48
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as Y from 'yjs';
|
|
2
|
+
/**
|
|
3
|
+
* Cheap "did the document change" signal (Stabilize A1 / D6).
|
|
4
|
+
*
|
|
5
|
+
* fingerprint = base64(state vector) + ":" + deletedCount
|
|
6
|
+
*
|
|
7
|
+
* A state vector alone misses delete-only transactions (clearing a filter,
|
|
8
|
+
* dropdown, conditional format, sub-sheet or named range; undo of a typed
|
|
9
|
+
* value), because a Yjs delete adds no item. deletedCount is the total length
|
|
10
|
+
* of all deleted ranges in the document, kept as a running count so no full
|
|
11
|
+
* scan is needed per check. Compare fingerprints with === only.
|
|
12
|
+
*/
|
|
13
|
+
export type ContentFingerprintTracker = {
|
|
14
|
+
getFingerprint(): string;
|
|
15
|
+
getDeletedCount(): number;
|
|
16
|
+
dispose(): void;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Attach when the Y.Doc is created, before any provider writes to it, so the
|
|
20
|
+
* count is built from transactions. Attaching later costs one full scan.
|
|
21
|
+
*/
|
|
22
|
+
export declare function attachContentFingerprint(doc: Y.Doc): ContentFingerprintTracker;
|
|
23
|
+
/**
|
|
24
|
+
* Same value as a live tracker, for a stored body or a merge of raw rows.
|
|
25
|
+
* Builds a temporary document and scans its delete set, as getDsheetStateVector
|
|
26
|
+
* builds one. Reading the delete ranges from the encoded update instead
|
|
27
|
+
* (Y.decodeUpdate) misses GC structs that arrive without a delete range, e.g.
|
|
28
|
+
* a row written when the document received a compacted body.
|
|
29
|
+
*/
|
|
30
|
+
export declare function fingerprintFromUpdate(update: Uint8Array): string;
|
|
31
|
+
/**
|
|
32
|
+
* Same value as a live tracker, computed from a document by one scan of its
|
|
33
|
+
* delete set (under 1.5 ms at 100k cells). Used by the body reads, which
|
|
34
|
+
* already build a document from every IndexedDB row, so GC structs that
|
|
35
|
+
* arrived without a delete range are counted.
|
|
36
|
+
*/
|
|
37
|
+
export declare function fingerprintFromDocument(doc: Y.Doc): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -2,7 +2,7 @@ import { Ref } from 'react';
|
|
|
2
2
|
import { WorkbookInstance } from '../../sheet-engine/react';
|
|
3
3
|
import { DSheetEditorHandle } from '../types';
|
|
4
4
|
|
|
5
|
-
export type DSheetEditorMethods = Pick<DSheetEditorHandle, "refreshIndexedDB" | "terminateSession" | "updateCollaboratorName" | "updateSessionTitle">;
|
|
5
|
+
export type DSheetEditorMethods = Pick<DSheetEditorHandle, "refreshIndexedDB" | "rebuildLocalStore" | "terminateSession" | "updateCollaboratorName" | "updateSessionTitle" | "navigateToSheet" | "getContentFingerprint">;
|
|
6
6
|
/**
|
|
7
7
|
* Compose Fortune's regenerated imperative handle with dSheet lifecycle methods.
|
|
8
8
|
* React callback refs invoke this again after every Workbook remount, so both
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as Y from 'yjs';
|
|
2
|
+
/** Highest `meta.format` this client can write. */
|
|
3
|
+
export declare const SUPPORTED_FORMAT = 1;
|
|
4
|
+
/** Shown to the user once the sheet is locked. */
|
|
5
|
+
export declare const FORMAT_LOCKED_MESSAGE = "This sheet was updated. Reload to continue.";
|
|
6
|
+
/**
|
|
7
|
+
* Format of the sheet in `doc`. A missing map or key means 1, and so does a
|
|
8
|
+
* value that is not a number. Does not create the map when it is absent.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readFormatVersion(doc: Y.Doc, dsheetId: string): number;
|
|
11
|
+
/**
|
|
12
|
+
* True once a watched sheet of `doc` has shown a format above SUPPORTED_FORMAT.
|
|
13
|
+
* With `dsheetId` it answers for that sheet only, and also reads the doc, so
|
|
14
|
+
* it holds before the watch starts. Without it, true if any sheet is locked.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isFormatLocked(doc: Y.Doc | null | undefined, dsheetId?: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Checks `meta.format` now and while the sheet is open. On the first value
|
|
19
|
+
* above SUPPORTED_FORMAT the sheet is locked (write helpers return early) and
|
|
20
|
+
* `onLocked` runs once per watcher with that value, even if the sheet was
|
|
21
|
+
* already locked by an earlier watcher. Returns an unsubscribe function.
|
|
22
|
+
*/
|
|
23
|
+
export declare function watchFormatGate(doc: Y.Doc, dsheetId: string, onLocked: (format: number) => void): () => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type NavigableContext = {
|
|
2
|
+
currentSheetId?: string;
|
|
3
|
+
luckysheetfile?: Array<{
|
|
4
|
+
id?: string;
|
|
5
|
+
hide?: number;
|
|
6
|
+
} | null | undefined>;
|
|
7
|
+
};
|
|
8
|
+
export type NavigableEditor = {
|
|
9
|
+
getWorkbookContext?: () => NavigableContext | null | undefined;
|
|
10
|
+
getWorkbookSetContext?: () => ((recipe: (draft: unknown) => void) => void) | null | undefined;
|
|
11
|
+
};
|
|
12
|
+
export type NavigateToSheetOptions = {
|
|
13
|
+
/** How long to wait for the workbook and sheet to load. Default 10s. */
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Wait until the workbook has loaded a sheet with `sheetId`, then switch to it.
|
|
18
|
+
* Resolves `false` (never throws) when the sheet is missing after the timeout,
|
|
19
|
+
* hidden, or the switch fails. `getEditor` must return the latest instance on
|
|
20
|
+
* every call because Fortune regenerates its handle on each context change.
|
|
21
|
+
*/
|
|
22
|
+
export declare function navigateToSheet<TDraft>(getEditor: () => NavigableEditor | null | undefined, sheetId: string, activate: (draft: TDraft, sheetId: string) => void, { timeoutMs }?: NavigateToSheetOptions): Promise<boolean>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type PlainCelldataEntry = {
|
|
2
|
+
r: number;
|
|
3
|
+
c: number;
|
|
4
|
+
v: unknown;
|
|
5
|
+
};
|
|
6
|
+
export type CelldataPatch = {
|
|
7
|
+
key: string;
|
|
8
|
+
action: 'delete' | 'update';
|
|
9
|
+
v?: unknown;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Apply a remote batch of cell changes to a sheet's plain celldata array in
|
|
13
|
+
* place. Keys are `r_c` and unique within a batch.
|
|
14
|
+
*
|
|
15
|
+
* One pass over celldata finds every patched cell (A5): O(entries + changes)
|
|
16
|
+
* instead of a findIndex per changed key. The lookup is by row then column
|
|
17
|
+
* number, so the pass allocates nothing per entry.
|
|
18
|
+
*/
|
|
19
|
+
export declare function patchPlainCelldata(celldata: PlainCelldataEntry[], patches: Iterable<CelldataPatch>): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IndexeddbPersistence } from 'y-indexeddb';
|
|
2
|
+
import type * as Y from 'yjs';
|
|
3
|
+
/**
|
|
4
|
+
* D3: rebuild the local IndexedDB store from the live document.
|
|
5
|
+
*
|
|
6
|
+
* Destroys `current`, deletes the database, then attaches a new provider to
|
|
7
|
+
* the SAME live Y.Doc, so y-indexeddb writes the full current state as one
|
|
8
|
+
* fresh row. `onCreated` runs right after the new provider is constructed,
|
|
9
|
+
* before it has synced, so the caller can track it and attach listeners. The Y.Doc is never replaced or cleared. Unlike delete-and-reopen
|
|
10
|
+
* (heal), edits that exist only in the live doc are kept.
|
|
11
|
+
*/
|
|
12
|
+
export declare function rebuildIndexedDbStore(dsheetId: string, doc: Y.Doc, current: IndexeddbPersistence | null, onCreated?: (provider: IndexeddbPersistence) => void): Promise<IndexeddbPersistence>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -15,5 +15,31 @@ export declare function syncRemoteUpdateFlag(refs: RemoteApplyGuardRefs): void;
|
|
|
15
15
|
export declare function beginRemoteApply(refs: RemoteApplyGuardRefs): void;
|
|
16
16
|
export declare function endRemoteApply(refs: RemoteApplyGuardRefs): void;
|
|
17
17
|
export declare function runUnderRemoteApply(refs: RemoteApplyGuardRefs, fn: () => void): void;
|
|
18
|
+
export type StructuralRemountRefs = RemoteApplyGuardRefs & {
|
|
19
|
+
pendingRef: MutableRefObject<boolean>;
|
|
20
|
+
timerRef: MutableRefObject<number | null>;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Debounced structural remount under the remote-apply guard.
|
|
24
|
+
*
|
|
25
|
+
* The guard is begun once, right before `run`, and ended after paint, so each
|
|
26
|
+
* remount owns exactly one begin and one end. It is NOT held while the timer
|
|
27
|
+
* is merely pending or deferred by a cell edit: `remoteUpdateRef` makes
|
|
28
|
+
* handleChange, guardRemoteEcho and afterUpdateCell drop local writes, so
|
|
29
|
+
* holding it across an edit would drop the user's commit. Events that land
|
|
30
|
+
* while one is pending only re-arm its timer.
|
|
31
|
+
*
|
|
32
|
+
* While `isEditing()` is true at fire time the timer re-arms (250 ms) and the
|
|
33
|
+
* pending flag is kept; the remount runs once the edit ends.
|
|
34
|
+
*/
|
|
35
|
+
export declare function scheduleStructuralRemount(refs: StructuralRemountRefs, run: () => void, delayMs?: number, isEditing?: () => boolean): void;
|
|
36
|
+
/** Re-arm interval while a cell edit blocks the remount. */
|
|
37
|
+
export declare const STRUCTURAL_REMOUNT_EDIT_RETRY_MS = 250;
|
|
38
|
+
/**
|
|
39
|
+
* Drop a pending structural remount (observer teardown). The guard is only
|
|
40
|
+
* held while `run` executes and until paint afterwards, so there is nothing
|
|
41
|
+
* to release here.
|
|
42
|
+
*/
|
|
43
|
+
export declare function cancelStructuralRemount(refs: StructuralRemountRefs): void;
|
|
18
44
|
/** End after Workbook remount hooks have flushed (2 rAF ≈ one paint). */
|
|
19
45
|
export declare function endRemoteApplyAfterPaint(refs: RemoteApplyGuardRefs): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -2,19 +2,29 @@ import { WorkbookInstance } from '../../sheet-engine/react';
|
|
|
2
2
|
import { SheetChangePath } from './update-ydoc';
|
|
3
3
|
|
|
4
4
|
import * as Y from 'yjs';
|
|
5
|
+
export { readYdocSheetField } from './update-ydoc';
|
|
6
|
+
/** Sheet fields the per-feature Yjs hooks sync. */
|
|
7
|
+
export declare const SYNCED_SHEET_FIELDS: readonly ["calcChain", "config", "dataVerification", "luckysheet_conditionformat_save", "hyperlink", "filter", "filter_select", "liveQueryList", "dataBlockCalcFunction"];
|
|
5
8
|
type SyncContext = {
|
|
6
9
|
currentSheetId: string;
|
|
10
|
+
/** Only `field` is populated: the value stored in Yjs. */
|
|
7
11
|
oldSheet: Record<string, any>;
|
|
12
|
+
/** The engine's current value of `field` for the active sheet. */
|
|
13
|
+
newValue: any;
|
|
14
|
+
/** The engine's active sheet, for checks against its cells. */
|
|
15
|
+
engineSheet: Record<string, any> | undefined;
|
|
8
16
|
ydoc: Y.Doc;
|
|
9
17
|
};
|
|
10
18
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
19
|
+
* Old (Yjs) and new (engine) value of one field of the active sheet (A3).
|
|
20
|
+
* Reads only that field: no whole-workbook conversion, and no getSheet(),
|
|
21
|
+
* which rebuilds celldata from the dense grid.
|
|
13
22
|
*/
|
|
14
|
-
export declare const getSheetYdocSyncContext: ({ sheetEditorRef, ydocRef, dsheetId, }: {
|
|
23
|
+
export declare const getSheetYdocSyncContext: ({ sheetEditorRef, ydocRef, dsheetId, field, }: {
|
|
15
24
|
sheetEditorRef: React.RefObject<WorkbookInstance | null>;
|
|
16
25
|
ydocRef: React.RefObject<Y.Doc | null>;
|
|
17
26
|
dsheetId: string;
|
|
27
|
+
field: string;
|
|
18
28
|
}) => SyncContext | null;
|
|
19
29
|
export declare const buildMapFieldChanges: ({ sheetId, fieldPath, oldData, newData, }: {
|
|
20
30
|
sheetId: string;
|
|
@@ -28,4 +38,3 @@ export declare const applyYdocSheetChanges: ({ ydoc, dsheetId, changes, handleCo
|
|
|
28
38
|
changes: SheetChangePath[];
|
|
29
39
|
handleContentPortal?: any;
|
|
30
40
|
}) => void;
|
|
31
|
-
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -17,5 +17,13 @@ export type SheetChangePath = {
|
|
|
17
17
|
export declare const updateYdocSheetData: (ydoc: Y.Doc | null, dsheetId: string, changes: SheetChangePath[], handleContentPortal: any, onCellFormatRangesCommitted?: (commits: Array<{
|
|
18
18
|
sheetId: string;
|
|
19
19
|
ranges: CellFormatRange[];
|
|
20
|
-
}>) => void
|
|
20
|
+
}>) => void,
|
|
21
|
+
/** Transaction origin; omit for user edits. */
|
|
22
|
+
origin?: unknown) => void;
|
|
21
23
|
export declare function ySheetArrayToPlain(sheetArray: Y.Array<Y.Map>): Sheet[];
|
|
24
|
+
/**
|
|
25
|
+
* One field of one sheet, with the same value ySheetArrayToPlain gives for
|
|
26
|
+
* it, without converting the rest of the workbook (A3). Shared, read-only
|
|
27
|
+
* semantics as ySheetArrayToPlain.
|
|
28
|
+
*/
|
|
29
|
+
export declare function readYdocSheetField(ydoc: Y.Doc, dsheetId: string, sheetId: string, field: string): any;
|
|
@@ -11198,6 +11198,7 @@ If the value is FALSE, return the accrued interest from the first interest accru
|
|
|
11198
11198
|
cancelText: "Cancelar",
|
|
11199
11199
|
chooseText: "Confirmar color",
|
|
11200
11200
|
focus: "Enfocar",
|
|
11201
|
+
copyLink: "Copiar enlace a la hoja",
|
|
11201
11202
|
tipNameRepeat: "¡El nombre de la página de la pestaña no se puede repetir! Revísalo",
|
|
11202
11203
|
noMoreSheet: "El libro de trabajo contiene al menos una hoja de trabajo visual. Para eliminar la hoja de trabajo seleccionada, inserta una nueva hoja de trabajo o muestra una hoja de trabajo oculta",
|
|
11203
11204
|
confirmDelete: "¿Estás seguro de eliminar",
|