@fileverse-dev/dsheet 4.1.1-edit-mode-16 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +7 -9
  2. package/dist/{constants-B3rfAvvz.js → constants-CRFfbkoQ.js} +22 -79
  3. package/dist/constants.d.ts +2 -2
  4. package/dist/constants.js +3 -3
  5. package/dist/editor/components/editor-workbook.d.ts +1 -5
  6. package/dist/editor/components/permission-chip.d.ts +1 -5
  7. package/dist/editor/contexts/editor-context.d.ts +2 -11
  8. package/dist/editor/dsheet-editor.d.ts +2 -3
  9. package/dist/editor/hooks/use-collab-awareness.d.ts +6 -3
  10. package/dist/editor/hooks/use-editor-data.d.ts +2 -2
  11. package/dist/editor/hooks/use-editor-sync.d.ts +2 -6
  12. package/dist/editor/types/comments.d.ts +11 -0
  13. package/dist/editor/types.d.ts +4 -30
  14. package/dist/editor/utils/apply-comment-markers.d.ts +3 -11
  15. package/dist/editor/utils/comment-anchors-ydoc.d.ts +32 -0
  16. package/dist/editor/utils/remap-comment-anchors.d.ts +26 -0
  17. package/dist/{executeStringFunction-CxsiamWG.js → executeStringFunction-BJ00H04h.js} +1144 -1101
  18. package/dist/formula.js +1 -1
  19. package/dist/{index-DQvYqAJz.js → index-CsYiH7pp.js} +23501 -23656
  20. package/dist/index.d.ts +3 -4
  21. package/dist/index.es.js +52 -55
  22. package/dist/persistence-utils-DsM_MOB1.js +89 -0
  23. package/dist/persistence-utils.d.ts +0 -6
  24. package/dist/persistence.js +1 -1
  25. package/dist/sheet-engine/core/index.d.ts +1 -1
  26. package/dist/sheet-engine/core/settings.d.ts +40 -0
  27. package/dist/sheet-engine/core/utils/comment-anchor-move.d.ts +17 -0
  28. package/dist/sheet-engine/react/components/Toolbar/index.d.ts +0 -1
  29. package/dist/sheet-engine/react/components/Workbook/index.d.ts +0 -1
  30. package/dist/style.css +1 -1
  31. package/dist/sync-local/SyncManager.d.ts +9 -54
  32. package/dist/sync-local/index.d.ts +1 -1
  33. package/dist/sync-local/socketClient.d.ts +8 -75
  34. package/dist/sync-local/types/index.d.ts +15 -111
  35. package/dist/sync-local/useSyncManager.d.ts +0 -4
  36. package/dist/sync-local/utils/objectToFile.d.ts +1 -0
  37. package/dist/{use-xlsx-import-impl-DjiPGIoS.js → use-xlsx-import-impl-OXKPbMbG.js} +148 -148
  38. package/dist/{xlsx-defined-names-Dr4_psg0.js → xlsx-defined-names-Klp22jvp.js} +2 -2
  39. package/dist/{xlsx-export-impl-D2YNoxJm.js → xlsx-export-impl-Y8hmWj_I.js} +4 -4
  40. package/dist/{xlsx-hyperlink-inline-BkLFFNwP.js → xlsx-hyperlink-inline-DNeesFv6.js} +2 -2
  41. package/package.json +2 -2
  42. package/dist/editor/components/editor-workbook-controls.d.ts +0 -11
  43. package/dist/editor/components/permission-chip-model.d.ts +0 -34
  44. package/dist/editor/components/permission-chip.test.d.ts +0 -1
  45. package/dist/editor/hooks/collaboration-lifecycle.d.ts +0 -35
  46. package/dist/editor/hooks/collaboration-lifecycle.test.d.ts +0 -1
  47. package/dist/editor/utils/detach-workbook-data.d.ts +0 -8
  48. package/dist/editor/utils/detach-workbook-data.test.d.ts +0 -1
  49. package/dist/editor/utils/editor-handle.d.ts +0 -11
  50. package/dist/editor/utils/editor-handle.test.d.ts +0 -1
  51. package/dist/persistence-utils-BXFajzvq.js +0 -98
  52. package/dist/persistence-utils.test.d.ts +0 -1
  53. package/dist/sync-local/crypto/room-key.d.ts +0 -2
  54. package/dist/sync-local/crypto/room-key.test.d.ts +0 -1
  55. package/dist/sync-local/floor.d.ts +0 -8
  56. package/dist/sync-local/floor.test.d.ts +0 -1
  57. package/dist/sync-local/presence.d.ts +0 -13
  58. package/dist/sync-local/presence.test.d.ts +0 -1
  59. package/dist/sync-local/session-tools.d.ts +0 -31
  60. package/dist/sync-local/session-tools.test.d.ts +0 -1
  61. /package/dist/editor/{components/editor-workbook-controls.test.d.ts → utils/remap-comment-anchors.test.d.ts} +0 -0
package/README.md CHANGED
@@ -1,21 +1,19 @@
1
- # Fileverse DSheet
1
+ # Fileverse dSheet
2
2
 
3
3
  [![NPM](https://img.shields.io/npm/v/@fileverse-dev/dsheet)](https://www.npmjs.com/package/@fileverse-dev/dsheet)
4
4
  [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
5
5
 
6
- [dsheets.new](http://dsheets.new/) is your decentralised alternative to google sheets & excel. Use it to read, manipulate, and even write onchain data, in real-time. Built on the same middleware as ddocs.new, the app is privacy-first, self-sovereign, and gives you full control over your data <3
6
+ [dsheets.new](http://dsheets.new/) is your end-to-end encrypted alternative to Google Sheets & Excel. Use it to read, manipulate, and even write financial data, in real-time. Built on the same middleware as ddocs.new, the app is privacy-focused, sovereign, and gives you full control over your data.
7
7
 
8
- ## 👩‍🏭 Features:
8
+ ## 𓆣 Features include:
9
9
  - End-to-end encryption
10
10
  - Local & peer-to-peer storage
11
- - Query live data from APIs & smart contracts
12
- - Write onchain: simulate + submit transactions (V0.3)
11
+ - Query live data from APIs & even smart contracts
12
+ - Enable dark mode and other color themes
13
13
  - Use a familiar spreadsheets interface & functions (VLOOKUP, INDEX, MATCH…)
14
- - Granular access permissions (email, wallet, ENS)
14
+ - Granular access permissions (e.g., give view, comment, edit, suggest access to specific email addresses)
15
15
 
16
- [**Try Live Demo →**](https://fileverse-dsheet.vercel.app/)
17
-
18
- ![image](https://github.com/user-attachments/assets/b3953811-3e02-43ac-9e8e-ee0c3923a22f)
16
+ <img width="1532" height="974" alt="dsheetsnew" src="https://github.com/user-attachments/assets/8bd67463-e999-41f4-b414-9d017fbf9466" />
19
17
 
20
18
 
21
19
  ## Installation
@@ -1,5 +1,5 @@
1
- import { E as l, S as u } from "./crypto-constants-ZTlAYRUf.js";
2
- const h = l, S = u, _ = [
1
+ import { E as a, S as n } from "./crypto-constants-ZTlAYRUf.js";
2
+ const E = a, d = n, f = [
3
3
  {
4
4
  id: "0",
5
5
  name: "Sheet1",
@@ -7,7 +7,7 @@ const h = l, S = u, _ = [
7
7
  config: {},
8
8
  order: 0
9
9
  }
10
- ], g = [
10
+ ], m = [
11
11
  "undo",
12
12
  "redo",
13
13
  "format-painter",
@@ -45,7 +45,7 @@ const h = l, S = u, _ = [
45
45
  "quick-formula",
46
46
  "dataVerification",
47
47
  "search"
48
- ], p = [
48
+ ], u = [
49
49
  "cut",
50
50
  "copy",
51
51
  "paste",
@@ -82,7 +82,7 @@ const h = l, S = u, _ = [
82
82
  "freeze-row",
83
83
  "|",
84
84
  "clear-format"
85
- ], C = [
85
+ ], S = [
86
86
  "cut",
87
87
  "copy",
88
88
  "paste",
@@ -119,14 +119,14 @@ const h = l, S = u, _ = [
119
119
  "freeze-column",
120
120
  "|",
121
121
  "clear-format"
122
- ], w = {
122
+ ], _ = {
123
123
  height: null,
124
124
  isShow: !1,
125
125
  left: null,
126
126
  top: null,
127
127
  value: "",
128
128
  width: null
129
- }, a = "#9CA3AF", s = [
129
+ }, l = "#5298FF", r = [
130
130
  "#30bced",
131
131
  "#6eeb83",
132
132
  "#fa69d1",
@@ -136,81 +136,24 @@ const h = l, S = u, _ = [
136
136
  "#0ad7f2",
137
137
  "#1bff39"
138
138
  ];
139
- function A(o) {
140
- const t = /* @__PURE__ */ new Map();
141
- return o.forEach((r) => {
142
- const i = r == null ? void 0 : r.socketId, e = r == null ? void 0 : r.user;
143
- typeof i == "string" && e && t.set(i, {
144
- name: e.name ?? "",
145
- color: e.color ?? a,
146
- isEns: e.isEns ?? ""
147
- });
148
- }), t;
139
+ function c(e) {
140
+ return r[e % r.length];
149
141
  }
150
- function L(o, t) {
151
- const r = o.map((e) => {
152
- const n = t.get(e);
153
- return n ? {
154
- clientId: e,
155
- name: n.name,
156
- color: n.color,
157
- isEns: n.isEns,
158
- isPlaceholder: !1
159
- } : {
160
- clientId: e,
161
- name: "",
162
- color: a,
163
- isEns: "",
164
- isPlaceholder: !0
165
- };
166
- });
167
- r.sort((e, n) => !!e.isPlaceholder != !!n.isPlaceholder ? e.isPlaceholder ? 1 : -1 : String(e.clientId).localeCompare(String(n.clientId)));
168
- const i = /* @__PURE__ */ new Set();
169
- return r.filter((e) => e.isPlaceholder || !e.name ? !0 : i.has(e.name) ? !1 : (i.add(e.name), !0));
170
- }
171
- function R(o, t) {
172
- const r = new Set(
173
- o.filter(({ isPlaceholder: e, name: n }) => !e && n).map(({ name: e }) => e)
174
- );
175
- t.forEach((e, n) => {
176
- r.has(n) || t.delete(n);
177
- });
178
- const i = /* @__PURE__ */ new Set();
179
- return o.forEach((e) => {
180
- if (e.isPlaceholder || !e.name) return;
181
- let n = t.get(e.name);
182
- (!n || i.has(n)) && (n = s.find((c) => !i.has(c)) ?? n ?? s[t.size % s.length], t.set(e.name, n)), i.add(n), e.color = n;
183
- }), o;
184
- }
185
- function O(o, t) {
186
- return o.slice().sort().map((r) => {
187
- const i = t.get(r);
188
- return i ? `${r}:${i.name}:${i.isEns}` : `${r}:?`;
189
- }).join("|");
190
- }
191
- const d = "#5298FF";
192
- function f(o) {
193
- return s[o % s.length];
194
- }
195
- function E() {
142
+ function i() {
196
143
  return "#" + Math.floor(Math.random() * 16777215).toString(16).padStart(6, "0");
197
144
  }
198
- function P(o, t, r) {
199
- return t || (o ? d : r != null ? f(r) : E());
145
+ function h(e, o, t) {
146
+ return e ? l : o ?? (t != null ? c(t) : i());
200
147
  }
201
148
  export {
202
- w as C,
203
- _ as D,
204
- h as E,
205
- C as H,
206
- S,
207
- g as T,
208
- R as a,
209
- A as b,
210
- s as c,
211
- p as d,
212
- d as e,
213
- O as i,
214
- L as m,
215
- P as p
149
+ _ as C,
150
+ f as D,
151
+ E,
152
+ S as H,
153
+ d as S,
154
+ m as T,
155
+ r as a,
156
+ u as b,
157
+ l as c,
158
+ h as p
216
159
  };
@@ -1,5 +1,5 @@
1
1
  export { ERROR_MESSAGES_FLAG, SERVICES_API_KEY, } from './editor/constants/shared-constants';
2
- export { COLLAB_PRESENCE_COLORS } from './sync-local/presence';
3
2
  export declare const ENS_PRESENCE_COLOR = "#5298FF";
4
- /** Explicit awareness color, else ENS brand color, palette, or random fallback. */
3
+ export declare const COLLAB_PRESENCE_COLORS: readonly ["#30bced", "#6eeb83", "#fa69d1", "#ecd444", "#ee6352", "#db3041", "#0ad7f2", "#1bff39"];
4
+ /** ENS brand color, else `color`, else palette by `clientId`, else random. */
5
5
  export declare function presenceColor(isEns: boolean | undefined, color?: string, clientId?: number): string;
package/dist/constants.js CHANGED
@@ -1,8 +1,8 @@
1
- import { c as R, e as _, E as C, S as s, p as O } from "./constants-B3rfAvvz.js";
1
+ import { a as R, c as _, E as C, S as a, p as s } from "./constants-CRFfbkoQ.js";
2
2
  export {
3
3
  R as COLLAB_PRESENCE_COLORS,
4
4
  _ as ENS_PRESENCE_COLOR,
5
5
  C as ERROR_MESSAGES_FLAG,
6
- s as SERVICES_API_KEY,
7
- O as presenceColor
6
+ a as SERVICES_API_KEY,
7
+ s as presenceColor
8
8
  };
@@ -1,7 +1,7 @@
1
1
  import { default as React } from 'react';
2
2
  import { SidebarPortalRegistryHandle, SidebarPortalRenderer } from '../../sheet-engine/react';
3
3
  import { ThemeKey } from '../../sheet-engine/core/theme';
4
- import { OnboardingHandlerType, DSheetPermissionMode } from '../types';
4
+ import { OnboardingHandlerType } from '../types';
5
5
  import { CommentsConfig } from '../types/comments';
6
6
 
7
7
  type OnboardingHandler = OnboardingHandlerType;
@@ -24,10 +24,6 @@ interface EditorWorkbookProps {
24
24
  sidebarActivePanel?: string | null;
25
25
  sidebarPortalRegistry?: SidebarPortalRegistryHandle | null;
26
26
  sidebarPortalRenderers?: Record<string, SidebarPortalRenderer>;
27
- permissionMode?: DSheetPermissionMode | null;
28
- onEnterEdit?: () => void;
29
- onSignInToComment?: () => void;
30
- onViewerModeChange?: (mode: 'comment' | 'view') => void;
31
27
  theme?: ThemeKey;
32
28
  }
33
29
  export declare const EditorWorkbook: React.NamedExoticComponent<EditorWorkbookProps>;
@@ -1,11 +1,7 @@
1
1
  import { default as React } from 'react';
2
- import { DSheetPermissionMode } from '../types';
3
2
 
4
3
  interface PermissionChipProps {
5
- mode: DSheetPermissionMode;
6
- onEnterEdit?: () => void;
7
- onSignInToComment?: () => void;
8
- onViewerModeChange?: (mode: 'comment' | 'view') => void;
4
+ allowComments: boolean;
9
5
  }
10
6
  export declare const PermissionChip: React.FC<PermissionChipProps>;
11
7
  export {};
@@ -1,7 +1,7 @@
1
1
  import { default as React } from 'react';
2
2
  import { LiveQueryData, Sheet, WorkbookInstance } from '../../sheet-engine/react';
3
3
  import { IndexeddbPersistence } from 'y-indexeddb';
4
- import { SheetUpdateData, DataBlockEvent, DSheetEditorHandle } from '../types';
4
+ import { SheetUpdateData, DataBlockEvent } from '../types';
5
5
  import { CommentsConfig } from '../types/comments';
6
6
  import { ApiKeyStorage } from '../utils/api-key-storage';
7
7
  import { OpenApiKeyModalFn } from '../utils/data-block-error-handler';
@@ -32,7 +32,6 @@ export interface EditorContextType {
32
32
  }>>;
33
33
  refreshIndexedDB: () => Promise<void>;
34
34
  sheetEditorRef: React.MutableRefObject<WorkbookInstance | null>;
35
- setSheetEditorRef: React.RefCallback<WorkbookInstance>;
36
35
  ydocRef: React.MutableRefObject<Y.Doc | null>;
37
36
  persistenceRef: React.MutableRefObject<IndexeddbPersistence | null>;
38
37
  sheetData: Sheet[];
@@ -46,7 +45,6 @@ export interface EditorContextType {
46
45
  setForceSheetRender: React.Dispatch<React.SetStateAction<number>>;
47
46
  syncStatus: 'initializing' | 'syncing' | 'synced' | 'error';
48
47
  collabEnabled?: boolean;
49
- isLiveCollabSession: boolean;
50
48
  collabIsOwner?: boolean;
51
49
  collabState?: CollabState;
52
50
  isCollabReady?: boolean;
@@ -81,8 +79,7 @@ interface EditorProviderProps {
81
79
  onContentUpdate?: () => void;
82
80
  onChange?: (data: SheetUpdateData, encodedUpdate?: string) => void;
83
81
  collaboration?: CollaborationProps;
84
- externalEditorRef?: React.Ref<DSheetEditorHandle>;
85
- legacyEditorRef?: React.Ref<DSheetEditorHandle>;
82
+ externalEditorRef?: React.MutableRefObject<WorkbookInstance | null>;
86
83
  commentsConfig?: CommentsConfig;
87
84
  editorStateRef?: React.MutableRefObject<{
88
85
  refreshIndexedDB: () => Promise<void>;
@@ -90,10 +87,6 @@ interface EditorProviderProps {
90
87
  mergeContent: (encodedState: string) => DSheetContentSnapshot;
91
88
  terminateSession?: () => void;
92
89
  updateCollaboratorName?: (name: string) => void;
93
- updateSessionTitle?: (args: {
94
- encryptedTitle: string;
95
- documentTitle: string;
96
- }) => void;
97
90
  rehydrateAfterCollabSync?: (reason?: string) => boolean;
98
91
  } | null>;
99
92
  enableLiveQuery?: boolean;
@@ -102,8 +95,6 @@ interface EditorProviderProps {
102
95
  onDataBlockEvent?: (event: DataBlockEvent) => void;
103
96
  smartContracts?: SmartContractConfig;
104
97
  onContentSyncStatusChange?: (status: 'initializing' | 'syncing' | 'synced' | 'error') => void;
105
- onCollaborationInitializationComplete?: (result: 'ready' | 'error') => void;
106
- onIndexedDbError?: (error: Error) => void;
107
98
  }
108
99
  export declare const EditorProvider: React.FC<EditorProviderProps>;
109
100
  export declare const useEditor: () => EditorContextType;
@@ -1,5 +1,4 @@
1
- import { default as React } from 'react';
2
- import { DSheetEditorHandle, DsheetProps } from './types';
1
+ import { DsheetProps } from './types';
3
2
 
4
3
  /**
5
4
  * SpreadsheetEditor component that provides a collaborative spreadsheet interface
@@ -8,5 +7,5 @@ import { DSheetEditorHandle, DsheetProps } from './types';
8
7
  * @param props - Component properties
9
8
  * @returns The SpreadsheetEditor component
10
9
  */
11
- declare const SpreadsheetEditor: React.ForwardRefExoticComponent<DsheetProps & React.RefAttributes<DSheetEditorHandle>>;
10
+ declare const SpreadsheetEditor: ({ isReadOnly, allowSheetDownload, renderNavbar, enableIndexeddbSync, dsheetId, portalContent, onContentUpdate, onChange, username, selectedTemplate, toggleTemplateSidebar, isTemplateOpen, onboardingComplete, onboardingCompleteLocalStorageKey, onboardingHandler, commentsConfig, setFetchingURLData, setShowFetchURLModal, setInputFetchURLDataBlock, sheetEditorRef: externalSheetEditorRef, onDuneChartEmbed, onSheetCountChange, isAuthorized, getDocumentTitle, updateDocumentTitle, editorStateRef, setSelectedTemplate, isNewSheet, liveQueryRefreshRate, enableLiveQuery, collaboration, customPanels, apiKeyStorage, onDataBlockEvent, smartContracts, theme, onContentSyncStatusChange, }: DsheetProps) => JSX.Element;
12
11
  export default SpreadsheetEditor;
@@ -1,14 +1,17 @@
1
1
  import { Awareness } from 'y-protocols/awareness';
2
2
  import { WorkbookInstance } from '../../sheet-engine/react';
3
+ import { CollabUser } from '../../sync-local/types';
3
4
 
4
5
  /**
5
6
  * Reads remote cursor positions from Yjs awareness and keeps Fortune sheet's
6
7
  * native presence list in sync. Fortune renders colored cell borders + username
7
8
  * labels automatically via context.presences[].
8
9
  *
9
- * The host collaborator roster is emitted by SocketClient from the
10
- * authoritative server room-members list. This hook owns only cell cursors.
10
+ * Also emits the full collaborator list (including the local user) via
11
+ * `onCollaboratorsChange` so host apps can render navbar chips. This mirrors
12
+ * ddoc's editor-layer awareness handler, which maps awareness.states →
13
+ * `{ clientId, ...user }` and fires on every awareness update + once on mount.
11
14
  */
12
- export declare const useCollabAwareness: (awareness: Awareness | null | undefined, sheetEditorRef: React.MutableRefObject<WorkbookInstance | null>) => {
15
+ export declare const useCollabAwareness: (awareness: Awareness | null | undefined, sheetEditorRef: React.MutableRefObject<WorkbookInstance | null>, onCollaboratorsChange?: (collaborators: CollabUser[]) => void) => {
13
16
  localColor: "#30bced" | "#6eeb83" | "#fa69d1" | "#ecd444" | "#ee6352" | "#db3041" | "#0ad7f2" | "#1bff39";
14
17
  };
@@ -8,7 +8,7 @@ import * as Y from 'yjs';
8
8
  * Hook for managing sheet data
9
9
  * Handles initialization, updates, and persistence of sheet data
10
10
  */
11
- export declare const useEditorData: (ydocRef: React.MutableRefObject<Y.Doc | null>, dsheetId: string, sheetEditorRef: React.MutableRefObject<WorkbookInstance | null>, setForceSheetRender?: React.Dispatch<React.SetStateAction<number>>, isReadOnly?: boolean, onChange?: (data: Sheet[]) => void, syncStatus?: "initializing" | "syncing" | "synced" | "error", isContentBootstrapReady?: boolean, commentData?: object, dataBlockCalcFunction?: {
11
+ export declare const useEditorData: (ydocRef: React.MutableRefObject<Y.Doc | null>, dsheetId: string, sheetEditorRef: React.MutableRefObject<WorkbookInstance | null>, setForceSheetRender?: React.Dispatch<React.SetStateAction<number>>, portalContent?: string, isReadOnly?: boolean, onChange?: (data: Sheet[]) => void, syncStatus?: "initializing" | "syncing" | "synced" | "error", commentData?: object, dataBlockCalcFunction?: {
12
12
  [key: string]: {
13
13
  [key: string]: any;
14
14
  };
@@ -16,7 +16,7 @@ export declare const useEditorData: (ydocRef: React.MutableRefObject<Y.Doc | nul
16
16
  [key: string]: {
17
17
  [key: string]: any;
18
18
  };
19
- }>>, enableLiveQuery?: boolean, liveQueryRefreshRate?: number, apiKeyStorage?: ApiKeyStorage, openApiKeyModal?: OpenApiKeyModalFn, onDataBlockEvent?: (event: DataBlockEvent) => void, allowComments?: boolean, collabEnabled?: boolean) => {
19
+ }>>, enableLiveQuery?: boolean, liveQueryRefreshRate?: number, apiKeyStorage?: ApiKeyStorage, openApiKeyModal?: OpenApiKeyModalFn, onDataBlockEvent?: (event: DataBlockEvent) => void, allowComments?: boolean, hasCollabContentInitialised?: boolean, collabEnabled?: boolean) => {
20
20
  sheetData: Sheet[];
21
21
  setSheetData: import('react').Dispatch<import('react').SetStateAction<Sheet[]>>;
22
22
  currentDataRef: import('react').MutableRefObject<Sheet[]>;
@@ -1,11 +1,11 @@
1
1
  import { IndexeddbPersistence } from 'y-indexeddb';
2
2
  import { CollaborationProps } from '../../sync-local/types';
3
3
  import * as Y from 'yjs';
4
- export declare const useEditorSync: (dsheetId: string, enableIndexeddbSync?: boolean, isReadOnly?: boolean, portalContent?: string, collaboration?: CollaborationProps, onCollabUpdate?: (fullState: string, updateChunk: string) => void, onIndexedDbError?: (error: Error) => void) => {
4
+ export declare const useEditorSync: (dsheetId: string, enableIndexeddbSync?: boolean, isReadOnly?: boolean, collaboration?: CollaborationProps, onCollabUpdate?: (fullState: string, updateChunk: string) => void) => {
5
5
  ydocRef: import('react').MutableRefObject<Y.Doc | null>;
6
6
  persistenceRef: import('react').MutableRefObject<IndexeddbPersistence | null>;
7
7
  syncStatus: "error" | "syncing" | "initializing" | "synced";
8
- isContentBootstrapReady: boolean;
8
+ isSyncedRef: import('react').MutableRefObject<boolean>;
9
9
  refreshIndexedDB: () => Promise<void>;
10
10
  getContentSnapshot: () => import('../../persistence-utils').DSheetContentSnapshot;
11
11
  mergeContent: (encodedState: string) => import('../../persistence-utils').DSheetContentSnapshot;
@@ -13,10 +13,6 @@ export declare const useEditorSync: (dsheetId: string, enableIndexeddbSync?: boo
13
13
  isCollabReady: boolean;
14
14
  isCollabSyncing: boolean;
15
15
  terminateSession: () => void;
16
- updateTitle: (args: {
17
- encryptedTitle: string;
18
- documentTitle: string;
19
- }) => void;
20
16
  awareness: import('y-protocols/awareness.js').Awareness | null;
21
17
  hasCollabContentInitialised: boolean;
22
18
  };
@@ -1,5 +1,7 @@
1
1
  import { default as React } from 'react';
2
+ import { CommentAnchorMove } from '../../sheet-engine/core/settings';
2
3
 
4
+ export type { CommentAnchorMove };
3
5
  export interface CommentThread {
4
6
  id: string;
5
7
  key: string;
@@ -12,6 +14,8 @@ export interface CommentThread {
12
14
  replies: CommentReply[];
13
15
  isResolved?: boolean;
14
16
  isDeleted?: boolean;
17
+ /** IPFS/indexer hash — stable across local `comment-*` ids and on-chain uuids. */
18
+ contentHash?: string;
15
19
  }
16
20
  export interface CommentReply {
17
21
  id: string;
@@ -41,6 +45,11 @@ export interface CommentsConfig {
41
45
  commentsData: Record<string, CommentThread>;
42
46
  onSendComment: (key: string, textareaId: string) => void;
43
47
  onCommentAction: (action: CommentActionParams) => void;
48
+ /**
49
+ * Called after row/column drag-drop or a cell-range move so the host can
50
+ * remap comment keys. Use `remapCommentAnchors` from the package.
51
+ */
52
+ onCellPositionsChanged?: (move: CommentAnchorMove) => void;
44
53
  userName?: string;
45
54
  ownerAddress?: string;
46
55
  currentUserAddress?: string;
@@ -118,6 +127,8 @@ export interface CommentCellUIProps {
118
127
  dragHandler: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
119
128
  isHover?: boolean;
120
129
  disabled?: boolean;
130
+ isAuthenticated?: boolean;
131
+ unauthenticatedFallback?: React.ReactNode;
121
132
  }
122
133
  export interface CommentsContentProps {
123
134
  sheetEditorRef: React.RefObject<SheetEditorRef>;
@@ -10,8 +10,7 @@ import { DSheetContentSnapshot } from '../persistence';
10
10
 
11
11
  import * as Y from 'yjs';
12
12
  export type { ThemeKey } from '../sheet-engine/core/theme';
13
- export type DSheetPermissionMode = 'view' | 'comment' | 'edit';
14
- export type { CommentThread, CommentReply, CommentActionParams, CommentsConfig, } from './types/comments';
13
+ export type { CommentThread, CommentReply, CommentActionParams, CommentsConfig, CommentAnchorMove, } from './types/comments';
15
14
  export { CommentAction } from './types/comments';
16
15
  export interface SheetUpdateData {
17
16
  data: Sheet[];
@@ -23,15 +22,6 @@ export interface EditorValues {
23
22
  openPanel: (panelId: string) => void;
24
23
  closePanel: () => void;
25
24
  }
26
- export type DSheetEditorHandle = WorkbookInstance & {
27
- refreshIndexedDB: () => Promise<void>;
28
- terminateSession: () => void;
29
- updateCollaboratorName: (name: string) => void;
30
- updateSessionTitle: (args: {
31
- encryptedTitle: string;
32
- documentTitle: string;
33
- }) => void;
34
- };
35
25
  export interface PanelConfig {
36
26
  id: string;
37
27
  header: {
@@ -77,23 +67,9 @@ export interface DsheetProps {
77
67
  onContentUpdate?: () => void;
78
68
  onChange?: (updateData: SheetUpdateData, encodedUpdate?: string) => void;
79
69
  collaboration?: CollaborationProps;
80
- /** Called when local IndexedDB persistence fails. The editor and durable
81
- * collaboration continue using the in-memory Y.Doc, matching dDoc. */
82
- onIndexedDbError?: (error: Error) => void;
83
70
  username?: string;
84
71
  portalContent?: string;
85
72
  isReadOnly?: boolean;
86
- /** Permission status displayed above the toolbar. When omitted, read-only
87
- * sheets retain the existing View/View-and-comment behavior. */
88
- permissionMode?: DSheetPermissionMode;
89
- /** Called when a read-only consumer asks to elevate to edit mode. The host
90
- * owns access proof, loading, errors, and the resulting mode transition. */
91
- onEnterEdit?: () => void;
92
- /** Called when an invited commenter needs to authenticate before the host can
93
- * recover comment capability. */
94
- onSignInToComment?: () => void;
95
- /** Lets the host toggle a recovered commenter between comment and view mode. */
96
- onViewerModeChange?: (mode: 'comment' | 'view') => void;
97
73
  allowSheetDownload?: boolean;
98
74
  isTemplateOpen?: boolean;
99
75
  selectedTemplate?: string;
@@ -104,8 +80,9 @@ export interface DsheetProps {
104
80
  setForceSheetRender?: React.Dispatch<React.SetStateAction<number>>;
105
81
  commentsConfig?: CommentsConfig;
106
82
  toggleTemplateSidebar?: () => void;
107
- /** Legacy ref prop. Standard React refs are also supported. */
108
- sheetEditorRef?: React.Ref<DSheetEditorHandle>;
83
+ sheetEditorRef?: RefObject<WorkbookInstance & {
84
+ refreshIndexedDB: () => Promise<void>;
85
+ }>;
109
86
  /** Override where datablock API keys are stored (default: localStorage). */
110
87
  apiKeyStorage?: ApiKeyStorage;
111
88
  /** Optional lifecycle events for analytics / side-effects. */
@@ -116,9 +93,6 @@ export interface DsheetProps {
116
93
  * collab start/resume on 'synced' — starting before local content is fully
117
94
  * synced is what let the RTC layer bind to a stale doc in the past. */
118
95
  onContentSyncStatusChange?: (status: 'initializing' | 'syncing' | 'synced' | 'error') => void;
119
- /** Fires once the first collaboration sync has been reconciled with the
120
- * workbook, or when that reconciliation fails. */
121
- onCollaborationInitializationComplete?: (result: 'ready' | 'error') => void;
122
96
  editorStateRef?: React.MutableRefObject<{
123
97
  refreshIndexedDB: () => Promise<void>;
124
98
  getContentSnapshot: () => DSheetContentSnapshot;
@@ -4,17 +4,9 @@ type CommentData = object | null | undefined;
4
4
  * the consumer-provided `commentData`.
5
5
  *
6
6
  * `ps` is a per-client, permission-gated *view overlay* — it is NOT persisted in
7
- * ydoc. Every path that rebuilds sheet data from ydoc (portal load, collab sync
8
- * remount, remote cell edits) produces cells WITHOUT `ps`, so this must run on
9
- * each such snapshot or the red-triangle indicator vanishes. Because it is
10
- * gated on the local `allowComments` permission, it must never be written back
11
- * to shared ydoc state — doing so would let one viewer wipe markers for all.
12
- *
13
- * Handles both shapes:
14
- * - Dense `sheet.data` (the live active sheet in `luckysheetfile`).
15
- * - Sparse `sheet.celldata` (plain snapshots from `ySheetArrayToPlain`, and
16
- * inactive sheets). `initSheetData()` converts celldata → data on activation,
17
- * so `ps` set on celldata carries through.
7
+ * ydoc (`shouldPersistCelldataCell` ignores marker-only cells). Empty cells are
8
+ * `null`, so a tiny `{ ps }` object is created in the live view only so the
9
+ * triangle can render. Row/column drag still owns real cell data.
18
10
  *
19
11
  * Mutates in place and returns the same array.
20
12
  */
@@ -0,0 +1,32 @@
1
+ import * as Y from 'yjs';
2
+ /** Sibling share key on the same Y.Doc as the sheet array. */
3
+ export declare function getCommentAnchorsMapKey(dsheetId: string): string;
4
+ export declare function getCommentAnchorsYMap(ydoc: Y.Doc, dsheetId: string): Y.Map<string>;
5
+ export declare function readCommentAnchorsFromYdoc(ydoc: Y.Doc | null | undefined, dsheetId: string): Record<string, string>;
6
+ type CommentAnchorRecord = {
7
+ id?: string;
8
+ key?: string;
9
+ contentHash?: string;
10
+ };
11
+ /**
12
+ * Re-key comments by identity first (id, then contentHash), then the comment's
13
+ * own current cell-key. Stale cell-key aliases that now belong to another
14
+ * thread must not steal or duplicate it.
15
+ */
16
+ export declare function applyCommentAnchorMap<T extends CommentAnchorRecord>(commentsData: Record<string, T> | null | undefined, anchors: Record<string, string>): Record<string, T>;
17
+ export declare function applyYdocCommentAnchors<T extends CommentAnchorRecord>(commentsData: Record<string, T> | object | null | undefined, ydoc: Y.Doc | null | undefined, dsheetId: string): Record<string, T>;
18
+ /**
19
+ * Persist current commentId/contentHash → cell-key into ydoc so viewers/publish
20
+ * see the remapped positions. No-ops when the map already matches.
21
+ */
22
+ export declare function writeCommentAnchorsToYdoc({ ydoc, dsheetId, commentsData, handleContentPortal, skipUnmapped, keyMoves, }: {
23
+ ydoc: Y.Doc | null | undefined;
24
+ dsheetId: string;
25
+ commentsData: Record<string, CommentAnchorRecord> | null | undefined;
26
+ handleContentPortal?: () => void;
27
+ /** When the map already has entries, skip comments that are not in it yet. */
28
+ skipUnmapped?: boolean;
29
+ /** old cell-key → new cell-key so indexer keys still resolve after remap. */
30
+ keyMoves?: Record<string, string>;
31
+ }): void;
32
+ export {};
@@ -0,0 +1,26 @@
1
+ import { CommentAnchorMove } from '../../sheet-engine/core/settings';
2
+
3
+ /**
4
+ * old cell-key → new cell-key, matched by comment id. Used when writing
5
+ * ydoc aliases so indexer keys still resolve after a remap.
6
+ */
7
+ export declare function commentKeyMovesById<T extends {
8
+ id?: string;
9
+ key?: string;
10
+ }>(before: Record<string, T>, after: Record<string, T>): Record<string, string>;
11
+ /**
12
+ * Remap in-memory comment keys after a row/column drag, cell-range move,
13
+ * or insert/delete of rows/columns.
14
+ *
15
+ * - Row/column drag: apply the full permutation `indexMap` (no collisions).
16
+ * - Cells: comments in the source rectangle follow the offset; comments that
17
+ * only lived in the destination are detached to `WITHOUT_CELL_<id>` so they
18
+ * remain in the sidebar instead of colliding with the incoming thread.
19
+ * - Insert: comments at/after the insertion point shift by `count`.
20
+ * - Delete: comments on removed rows/cols are detached; later ones shift up/left.
21
+ */
22
+ export declare function remapCommentAnchors<T extends {
23
+ key?: string;
24
+ id?: string;
25
+ }>(commentsData: Record<string, T>, move: CommentAnchorMove): Record<string, T>;
26
+ export type { CommentAnchorMove };