@fileverse-dev/ddoc 4.1.12 → 4.2.0-durability-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/{index-wRSSphoI.mjs → index-BREkA3S3.mjs} +46457 -46084
- package/dist/{index-C4IzZi0k.mjs → index-CioSbJ2V.mjs} +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.es.js +5 -4
- package/dist/{markdown-source-pane-QRkiwIcH.mjs → markdown-source-pane-yIzyW1Ll.mjs} +2 -2
- package/dist/package/components/editor-utils.d.ts +1 -25
- package/dist/package/hooks/use-editor-commands.d.ts +20 -0
- package/dist/package/hooks/use-focus-mode.d.ts +6 -1
- package/dist/package/hooks/use-headless-editor.d.ts +9 -1
- package/dist/package/hooks/use-tab-editor.d.ts +3 -2
- package/dist/package/hooks/use-yjs-setup.d.ts +1 -0
- package/dist/package/stores/comment-store-provider.d.ts +3 -1
- package/dist/package/stores/comment-store.d.ts +15 -0
- package/dist/package/sync-local/SyncManager.d.ts +12 -7
- package/dist/package/sync-local/floor.d.ts +6 -0
- package/dist/package/sync-local/socketClient.d.ts +21 -7
- package/dist/package/sync-local/types/index.d.ts +41 -9
- package/dist/package/types.d.ts +7 -1
- package/dist/package/use-ddoc-editor.d.ts +1 -0
- package/dist/package/utils/insert-commands.d.ts +20 -0
- package/dist/package/utils/make-editor.d.ts +9 -0
- package/dist/package/utils/selection-utils.d.ts +35 -0
- package/dist/package/utils/typography.d.ts +26 -0
- package/dist/{split-view-toolbar-D2GdAA9D.mjs → split-view-toolbar-BwZg4Gmd.mjs} +2 -2
- package/dist/style.css +1 -1
- package/package.json +9 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { k as Ql, b as Zl, s as eh } from "./index-
|
|
1
|
+
import { k as Ql, b as Zl, s as eh } from "./index-BREkA3S3.mjs";
|
|
2
2
|
let An = [], Xr = [];
|
|
3
3
|
(() => {
|
|
4
4
|
let s = "lc,34,7n,7,7b,19,,,,2,,2,,,20,b,1c,l,g,,2t,7,2,6,2,2,,4,z,,u,r,2j,b,1m,9,9,,o,4,,9,,3,,5,17,3,3b,f,,w,1j,,,,4,8,4,,3,7,a,2,t,,1m,,,,2,4,8,,9,,a,2,q,,2,2,1l,,4,2,4,2,2,3,3,,u,2,3,,b,2,1l,,4,5,,2,4,,k,2,m,6,,,1m,,,2,,4,8,,7,3,a,2,u,,1n,,,,c,,9,,14,,3,,1l,3,5,3,,4,7,2,b,2,t,,1m,,2,,2,,3,,5,2,7,2,b,2,s,2,1l,2,,,2,4,8,,9,,a,2,t,,20,,4,,2,3,,,8,,29,,2,7,c,8,2q,,2,9,b,6,22,2,r,,,,,,1j,e,,5,,2,5,b,,10,9,,2u,4,,6,,2,2,2,p,2,4,3,g,4,d,,2,2,6,,f,,jj,3,qa,3,t,3,t,2,u,2,1s,2,,7,8,,2,b,9,,19,3,3b,2,y,,3a,3,4,2,9,,6,3,63,2,2,,1m,,,7,,,,,2,8,6,a,2,,1c,h,1r,4,1c,7,,,5,,14,9,c,2,w,4,2,2,,3,1k,,,2,3,,,3,1m,8,2,2,48,3,,d,,7,4,,6,,3,2,5i,1m,,5,ek,,5f,x,2da,3,3x,,2o,w,fe,6,2x,2,n9w,4,,a,w,2,28,2,7k,,3,,4,,p,2,5,,47,2,q,i,d,,12,8,p,b,1a,3,1c,,2,4,2,2,13,,1v,6,2,2,2,2,c,,8,,1b,,1f,,,3,2,2,5,2,,,16,2,8,,6m,,2,,4,,fn4,,kh,g,g,g,a6,2,gt,,6a,,45,5,1ae,3,,2,5,4,14,3,4,,4l,2,fx,4,ar,2,49,b,4w,,1i,f,1k,3,1d,4,2,2,1x,3,10,5,,8,1q,,c,2,1g,9,a,4,2,,2n,3,2,,,2,6,,4g,,3,8,l,2,1l,2,,,,,m,,e,7,3,5,5f,8,2,3,,,n,,29,,2,6,,,2,,,2,,2,6j,,2,4,6,2,,2,r,2,2d,8,2,,,2,2y,,,,2,6,,,2t,3,2,4,,5,77,9,,2,6t,,a,2,,,4,,40,4,2,2,4,,w,a,14,6,2,4,8,,9,6,2,3,1a,d,,2,ba,7,,6,,,2a,m,2,7,,2,,2,3e,6,3,,,2,,7,,,20,2,3,,,,9n,2,f0b,5,1n,7,t4,,1r,4,29,,f5k,2,43q,,,3,4,5,8,8,2,7,u,4,44,3,1iz,1j,4,1e,8,,e,,m,5,,f,11s,7,,h,2,7,,2,,5,79,7,c5,4,15s,7,31,7,240,5,gx7k,2o,3k,6o".split(",").map((e) => e ? parseInt(e, 36) : 1);
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export { PreviewDdocEditor } from './package/preview-ddoc-editor';
|
|
|
3
3
|
export { handleContentPrint } from './package/utils/handle-print';
|
|
4
4
|
export { DdocExportModal } from './package/components/export-modal';
|
|
5
5
|
export { useHeadlessEditor } from './package/hooks/use-headless-editor';
|
|
6
|
+
export { useEditorCommands } from './package/hooks/use-editor-commands';
|
|
7
|
+
export type { EditorCommand, EditorCommandId, UseEditorCommandsOptions, } from './package/hooks/use-editor-commands';
|
|
6
8
|
export { useExportHeadlessEditorContent } from './package/hooks/use-export-headless-editor-content';
|
|
7
9
|
export { mergeTabAwareYjsUpdates } from './package/components/tabs/utils/tab-utils';
|
|
8
10
|
export { validateCustomCss, sanitizeCustomCss, } from './package/utils/sanitize-css';
|
package/dist/index.es.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as e, a as o, E as t, P as d,
|
|
1
|
+
import { D as e, a as o, E as t, P as d, f as r, h as i, m as n, e as E, c as m, d as u, u as C, v as l } from "./index-BREkA3S3.mjs";
|
|
2
2
|
export {
|
|
3
3
|
e as DdocEditor,
|
|
4
4
|
o as DdocExportModal,
|
|
@@ -8,7 +8,8 @@ export {
|
|
|
8
8
|
i as handleContentPrint,
|
|
9
9
|
n as mergeTabAwareYjsUpdates,
|
|
10
10
|
E as sanitizeCustomCss,
|
|
11
|
-
|
|
12
|
-
u as
|
|
13
|
-
C as
|
|
11
|
+
m as useEditorCommands,
|
|
12
|
+
u as useExportHeadlessEditorContent,
|
|
13
|
+
C as useHeadlessEditor,
|
|
14
|
+
l as validateCustomCss
|
|
14
15
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
var Vr = Object.defineProperty;
|
|
2
2
|
var Wr = (t, e, O) => e in t ? Vr(t, e, { enumerable: !0, configurable: !0, writable: !0, value: O }) : t[e] = O;
|
|
3
3
|
var gt = (t, e, O) => Wr(t, typeof e != "symbol" ? e + "" : e, O);
|
|
4
|
-
import { j as Cr } from "./index-
|
|
4
|
+
import { j as Cr } from "./index-BREkA3S3.mjs";
|
|
5
5
|
import { useRef as pe, useEffect as St } from "react";
|
|
6
|
-
import { s as y, A as pO, T as dO, a as Gr, S as et, b as Lr, P as fO, E as j, i as QO, c as _, D as le, k as tt, F as Ar, M as Pt, W as Er, R as Ur, d as mO, N as oe, e as V, f as Mr, g as Ot, h as ce, p as $O, j as Y, t as h, l as Ir, I as rt, L as at, m as ye, n as ue, o as Qe, q as gO, r as te, u as SO, v as Br, w as Nr, x as PO, y as kO, z as Dr, B as Fr, C as Kr, G as Oe, H as ZO, J as Jr, K as kt, O as Hr, Q as ea, U as ta, V as Oa, X as ra, Y as aa, Z as ia, _ as sa, $ as na, a0 as la, a1 as oa, a2 as ca } from "./index-
|
|
6
|
+
import { s as y, A as pO, T as dO, a as Gr, S as et, b as Lr, P as fO, E as j, i as QO, c as _, D as le, k as tt, F as Ar, M as Pt, W as Er, R as Ur, d as mO, N as oe, e as V, f as Mr, g as Ot, h as ce, p as $O, j as Y, t as h, l as Ir, I as rt, L as at, m as ye, n as ue, o as Qe, q as gO, r as te, u as SO, v as Br, w as Nr, x as PO, y as kO, z as Dr, B as Fr, C as Kr, G as Oe, H as ZO, J as Jr, K as kt, O as Hr, Q as ea, U as ta, V as Oa, X as ra, Y as aa, Z as ia, _ as sa, $ as na, a0 as la, a1 as oa, a2 as ca } from "./index-CioSbJ2V.mjs";
|
|
7
7
|
class ua {
|
|
8
8
|
/**
|
|
9
9
|
Create a new completion context. (Mostly useful for testing
|
|
@@ -22,30 +22,7 @@ type PickerEntry = {
|
|
|
22
22
|
};
|
|
23
23
|
export declare const baselineFonts: PickerEntry[];
|
|
24
24
|
export declare function buildPickerEntries(consumerFonts: FontDescriptor[]): PickerEntry[];
|
|
25
|
-
export
|
|
26
|
-
export declare const getFontSizeOptions: (editor?: Editor) => {
|
|
27
|
-
title: string;
|
|
28
|
-
value: string;
|
|
29
|
-
label: string;
|
|
30
|
-
command: (editor: Editor) => void;
|
|
31
|
-
isActive: () => boolean | undefined;
|
|
32
|
-
}[];
|
|
33
|
-
export declare const getCurrentFontSize: (editor: Editor | null, currentSize: string) => string;
|
|
34
|
-
export declare const uiValueToPercentage: (uiValue: string) => string;
|
|
35
|
-
export declare const percentageToUiValue: (percentage: string) => string;
|
|
36
|
-
export declare const LINE_HEIGHT_OPTIONS: {
|
|
37
|
-
value: string;
|
|
38
|
-
label: string;
|
|
39
|
-
uiValue: string;
|
|
40
|
-
description: string;
|
|
41
|
-
}[];
|
|
42
|
-
export declare const getLineHeightOptions: () => {
|
|
43
|
-
value: string;
|
|
44
|
-
label: string;
|
|
45
|
-
uiValue: string;
|
|
46
|
-
description: string;
|
|
47
|
-
}[];
|
|
48
|
-
export declare const getCurrentLineHeight: (editor: Editor | null, currentLineHeight?: string) => string;
|
|
25
|
+
export * from '../utils/typography';
|
|
49
26
|
export declare const ERR_MSG_MAP: {
|
|
50
27
|
IMAGE_SIZE: string;
|
|
51
28
|
};
|
|
@@ -184,4 +161,3 @@ export declare const checkActiveListsAndDBlocks: (editor: Editor) => {
|
|
|
184
161
|
state: import('prosemirror-state').EditorState;
|
|
185
162
|
hasMultipleLists: boolean;
|
|
186
163
|
};
|
|
187
|
-
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/react';
|
|
2
|
+
import { UploadImageOptions } from '../utils/insert-commands';
|
|
3
|
+
|
|
4
|
+
export type EditorCommand = {
|
|
5
|
+
run: (arg?: string) => void;
|
|
6
|
+
isActive?: boolean;
|
|
7
|
+
isEnabled: boolean;
|
|
8
|
+
current?: string | null;
|
|
9
|
+
};
|
|
10
|
+
export type EditorCommandId = 'edit.undo' | 'edit.redo' | 'edit.selectAll' | 'edit.cut' | 'edit.copy' | 'edit.paste' | 'edit.pasteWithoutFormatting' | 'edit.delete' | 'edit.findReplace' | 'insert.image' | 'insert.table' | 'insert.link' | 'insert.comment' | 'insert.callout' | 'insert.quote' | 'insert.code' | 'insert.codeBlock' | 'insert.video' | 'insert.mermaid' | 'insert.plainText' | 'insert.tweet' | 'insert.soundcloud' | 'insert.divider' | 'insert.pageBreak' | 'insert.columns2' | 'insert.columns3' | 'format.bold' | 'format.italic' | 'format.underline' | 'format.strike' | 'format.superscript' | 'format.subscript' | 'format.heading' | 'format.align' | 'format.direction' | 'format.lineHeight' | 'format.fontFamily' | 'format.fontSize.increase' | 'format.fontSize.decrease' | 'format.list.bullet' | 'format.list.numbered' | 'format.list.check' | 'format.clearFormatting' | 'table.addRowAbove' | 'table.addRowBelow' | 'table.mergeCells' | 'table.deleteRow' | 'table.addColumnLeft' | 'table.addColumnRight' | 'table.deleteColumn' | 'table.toggleHeaderRow' | 'table.toggleHeaderColumn' | 'table.toggleHeaderCell' | 'table.deleteTable';
|
|
11
|
+
export type UseEditorCommandsOptions = UploadImageOptions;
|
|
12
|
+
/**
|
|
13
|
+
* Reactive, editor-derived command registry (architecture doc §2 bucket 1).
|
|
14
|
+
* INVARIANT: all isActive/current/isEnabled values are derived from the
|
|
15
|
+
* editor via `useEditorState` (Tiptap's useSyncExternalStore wrapper) — the
|
|
16
|
+
* hook holds no authoritative state of its own, so any number of instances
|
|
17
|
+
* stay in sync, and consumers only re-render when a derived value changes
|
|
18
|
+
* (deep-equality gated), not on every transaction.
|
|
19
|
+
*/
|
|
20
|
+
export declare const useEditorCommands: (editor: Editor | null, options?: UseEditorCommandsOptions) => Record<EditorCommandId, EditorCommand>;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
type UseFocusModeOptions = {
|
|
2
|
+
/** Notify callback — fires on every toggle in both modes (existing API). */
|
|
2
3
|
onFocusMode?: (isFocusMode: boolean) => void;
|
|
4
|
+
/** Controlled value (D6). Omit for the legacy internal-state behavior. */
|
|
5
|
+
isFocusMode?: boolean;
|
|
6
|
+
/** Controlled setter — receives the next value instead of internal mutation. */
|
|
7
|
+
onFocusModeChange?: (isFocusMode: boolean) => void;
|
|
3
8
|
};
|
|
4
|
-
export declare const useFocusMode: ({ onFocusMode }?: UseFocusModeOptions) => {
|
|
9
|
+
export declare const useFocusMode: ({ onFocusMode, isFocusMode: controlledValue, onFocusModeChange, }?: UseFocusModeOptions) => {
|
|
5
10
|
isFocusMode: boolean;
|
|
6
11
|
toggleFocusMode: () => Promise<void>;
|
|
7
12
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Editor, JSONContent } from '@tiptap/react';
|
|
1
|
+
import { AnyExtension, Editor, JSONContent } from '@tiptap/react';
|
|
2
2
|
import { handleMarkdownContent } from '../extensions/mardown-paste-handler';
|
|
3
3
|
import { IpfsImageUploadResponse } from '../types';
|
|
4
4
|
|
|
@@ -6,6 +6,14 @@ import * as Y from 'yjs';
|
|
|
6
6
|
export interface UseHeadlessEditorProps {
|
|
7
7
|
optionalExtensions?: string[];
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* The exact extension set the headless editor runs with. Exported so tests
|
|
11
|
+
* can build an equivalent editor without the hook.
|
|
12
|
+
*/
|
|
13
|
+
export declare const getHeadlessExtensions: (options?: {
|
|
14
|
+
ydoc?: Y.Doc;
|
|
15
|
+
optionalExtensions?: string[];
|
|
16
|
+
}) => AnyExtension[];
|
|
9
17
|
export declare const useHeadlessEditor: (props?: UseHeadlessEditorProps) => {
|
|
10
18
|
setContent: (initialContent: string | string[] | JSONContent, editor: Editor, ydoc: Y.Doc) => void;
|
|
11
19
|
getEditor: () => {
|
|
@@ -17,7 +17,6 @@ interface UseTabEditorArgs {
|
|
|
17
17
|
initialContent: DdocProps['initialContent'];
|
|
18
18
|
collaboration?: CollaborationProps;
|
|
19
19
|
isReady?: boolean;
|
|
20
|
-
isSyncing?: boolean;
|
|
21
20
|
awareness?: any;
|
|
22
21
|
disableInlineComment?: boolean;
|
|
23
22
|
isFocusMode?: boolean;
|
|
@@ -45,6 +44,8 @@ interface UseTabEditorArgs {
|
|
|
45
44
|
ignoreCorruptedData?: boolean;
|
|
46
45
|
onCollaboratorChange?: DdocProps['onCollaboratorChange'];
|
|
47
46
|
onConnect: (connectConfig: CollabConnectionConfig) => void;
|
|
47
|
+
onDisconnect: () => void;
|
|
48
|
+
isIndexeddbSynced: boolean;
|
|
48
49
|
hasCollabContentInitialised?: boolean;
|
|
49
50
|
initialiseYjsIndexedDbProvider: () => Promise<void>;
|
|
50
51
|
externalExtensions?: Record<string, AnyExtension>;
|
|
@@ -56,7 +57,7 @@ interface UseTabEditorArgs {
|
|
|
56
57
|
initialCommentAnchors?: SerializedCommentAnchor[];
|
|
57
58
|
dBlockRuntimeStateRef?: DBlockRuntimeStateRef;
|
|
58
59
|
}
|
|
59
|
-
export declare const useTabEditor: ({ ydoc, isVersionMode, hasTabState, versionId, isPreviewMode, viewerMode, initialContent, collaboration, isReady,
|
|
60
|
+
export declare const useTabEditor: ({ ydoc, isVersionMode, hasTabState, versionId, isPreviewMode, viewerMode, initialContent, collaboration, isReady, awareness, disableInlineComment, isFocusMode, onCommentInteraction, onError, ipfsImageUploadFn, metadataProxyUrl, onCopyHeadingLink, ipfsImageFetchFn, fetchV1ImageFn, isConnected, activeModel, maxTokens, isAIAgentEnabled, setCharacterCount, setWordCount, setSelectedWordCount, setPageCount, setIsContentLoading, setIsCollabContentLoading, unFocused, zoomLevel, isPresentationMode, onInvalidContentError, ignoreCorruptedData, onCollaboratorChange, onConnect, onDisconnect, isIndexeddbSynced, hasCollabContentInitialised, initialiseYjsIndexedDbProvider, externalExtensions, isContentLoading, activeTabId, tabIds, theme, editorRef, initialCommentAnchors, dBlockRuntimeStateRef, }: UseTabEditorArgs) => {
|
|
60
61
|
editor: Editor | null;
|
|
61
62
|
cachedEditorEntries: import('./use-tab-editor-cache').CachedTabEditorRenderEntry[];
|
|
62
63
|
ref: import('react').RefObject<HTMLDivElement>;
|
|
@@ -11,6 +11,7 @@ interface UseYjsSetupArgs {
|
|
|
11
11
|
export declare const useYjsSetup: ({ onChange, enableIndexeddbSync, ddocId, collaboration, onIndexedDbError, }: UseYjsSetupArgs) => {
|
|
12
12
|
ydoc: Y.Doc;
|
|
13
13
|
onConnect: (connectConfig: import('../types').CollabConnectionConfig) => void;
|
|
14
|
+
onDisconnect: () => void;
|
|
14
15
|
isReady: boolean;
|
|
15
16
|
isSyncing: boolean;
|
|
16
17
|
terminateSession: () => void;
|
|
@@ -44,9 +44,11 @@ export interface CommentStoreProviderProps {
|
|
|
44
44
|
isConnected?: boolean;
|
|
45
45
|
isLoading?: boolean;
|
|
46
46
|
isDDocOwner?: boolean;
|
|
47
|
+
/** Inline comments usable — see ddoc-editor.tsx's derivation. */
|
|
48
|
+
isInlineCommentAvailable?: boolean;
|
|
47
49
|
setUsername?: React.Dispatch<React.SetStateAction<string>>;
|
|
48
50
|
}
|
|
49
|
-
export declare const CommentStoreProvider: ({ children, editor, ydoc, isFocusMode, setActiveCommentId, focusCommentWithActiveId, setInitialComments, onNewComment, onEditComment, onEditReply, onCommentReply, onResolveComment, onUnresolveComment, onDeleteComment, onDeleteReply, onInlineComment, onComment, setCommentDrawerOpen, connectViaWallet, connectViaUsername, ensResolutionUrl, commentAnchorsRef, draftAnchorsRef, storeApiRef, initialCommentAnchors, setUsername: setUsernameProp, initialComments, username, activeCommentId, activeTabId, isConnected, isLoading, isDDocOwner, }: CommentStoreProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
export declare const CommentStoreProvider: ({ children, editor, ydoc, isFocusMode, setActiveCommentId, focusCommentWithActiveId, setInitialComments, onNewComment, onEditComment, onEditReply, onCommentReply, onResolveComment, onUnresolveComment, onDeleteComment, onDeleteReply, onInlineComment, onComment, setCommentDrawerOpen, connectViaWallet, connectViaUsername, ensResolutionUrl, commentAnchorsRef, draftAnchorsRef, storeApiRef, initialCommentAnchors, setUsername: setUsernameProp, initialComments, username, activeCommentId, activeTabId, isConnected, isLoading, isDDocOwner, isInlineCommentAvailable, }: CommentStoreProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
50
52
|
interface CommentRefsContextType {
|
|
51
53
|
commentsSectionRef: React.RefObject<HTMLDivElement>;
|
|
52
54
|
replySectionRef: React.RefObject<HTMLDivElement>;
|
|
@@ -108,6 +108,10 @@ export interface CommentStoreState {
|
|
|
108
108
|
isConnected: boolean;
|
|
109
109
|
isLoading: boolean;
|
|
110
110
|
isDDocOwner: boolean;
|
|
111
|
+
/** Inline comments usable at all (not RTC, published, not disabled) —
|
|
112
|
+
* synced from CommentStoreProvider's prop; drives insert.comment
|
|
113
|
+
* enablement in useEditorCommands. */
|
|
114
|
+
isInlineCommentAvailable: boolean;
|
|
111
115
|
onComment: (() => void) | null;
|
|
112
116
|
setCommentDrawerOpen: ((open: boolean) => void) | null;
|
|
113
117
|
connectViaWallet: (() => Promise<void>) | null;
|
|
@@ -146,6 +150,7 @@ export interface CommentStoreState {
|
|
|
146
150
|
setIsConnected: (connected: boolean) => void;
|
|
147
151
|
setIsLoading: (loading: boolean) => void;
|
|
148
152
|
setIsDDocOwner: (isOwner: boolean) => void;
|
|
153
|
+
setIsInlineCommentAvailable: (value: boolean) => void;
|
|
149
154
|
setOnComment: (fn: (() => void) | null) => void;
|
|
150
155
|
setCommentDrawerOpenFn: (fn: ((open: boolean) => void) | null) => void;
|
|
151
156
|
setConnectViaWallet: (fn: (() => Promise<void>) | null) => void;
|
|
@@ -284,4 +289,14 @@ export interface CommentStoreState {
|
|
|
284
289
|
export declare const createCommentStore: () => import('zustand').StoreApi<CommentStoreState>;
|
|
285
290
|
export declare const CommentStoreContext: React.Context<import('zustand').StoreApi<CommentStoreState> | null>;
|
|
286
291
|
export declare function useCommentStore<T>(selector: (state: CommentStoreState) => T): T;
|
|
292
|
+
/**
|
|
293
|
+
* Non-throwing variant of useCommentStore: returns undefined when no
|
|
294
|
+
* CommentStoreProvider is above the caller (e.g. useEditorCommands used
|
|
295
|
+
* outside DdocEditor). The selector's RETURN VALUE must be Object.is-stable
|
|
296
|
+
* for unchanged state (primitives or refs already held by the store) —
|
|
297
|
+
* useSyncExternalStore compares snapshots with Object.is, so a selector
|
|
298
|
+
* that constructs a fresh object/array per call would re-render forever.
|
|
299
|
+
* Selector function identity itself doesn't matter.
|
|
300
|
+
*/
|
|
301
|
+
export declare function useCommentStoreOptional<T>(selector: (state: CommentStoreState) => T): T | undefined;
|
|
287
302
|
export {};
|
|
@@ -11,21 +11,23 @@ export declare class SyncManager {
|
|
|
11
11
|
private roomKeyBytes;
|
|
12
12
|
private isOwner;
|
|
13
13
|
private updateQueue;
|
|
14
|
-
private uncommittedUpdatesIdList;
|
|
15
14
|
private contentTobeAppliedQueue;
|
|
16
15
|
private isProcessing;
|
|
17
16
|
private syncId;
|
|
17
|
+
private floor;
|
|
18
|
+
private updatesSinceSnapshot;
|
|
19
|
+
private isAuthoringSnapshot;
|
|
20
|
+
private readonly SNAPSHOT_THRESHOLD;
|
|
18
21
|
private flushTimer;
|
|
19
22
|
private readonly FLUSH_INTERVAL_MS;
|
|
20
23
|
private readonly MAX_QUEUE_SIZE;
|
|
21
24
|
private _awarenessUpdateHandler;
|
|
22
25
|
private ydoc;
|
|
23
|
-
private servicesRef;
|
|
24
26
|
private callbacksRef;
|
|
25
27
|
private onLocalUpdate?;
|
|
26
28
|
constructor(config: SyncManagerConfig, onCollabStateChange: (state: CollabState) => void);
|
|
27
29
|
/** Called by useSyncManager on every render to keep refs fresh */
|
|
28
|
-
updateRefs(
|
|
30
|
+
updateRefs(_services: CollabServices | undefined, callbacks: CollabCallbacks | undefined, onLocalUpdate?: (updatedDocContent: string, updateChunk: string) => void): void;
|
|
29
31
|
get isConnected(): boolean;
|
|
30
32
|
get isReady(): boolean;
|
|
31
33
|
get awareness(): Awareness | null;
|
|
@@ -46,21 +48,24 @@ export declare class SyncManager {
|
|
|
46
48
|
* Fire-and-forget: merge all queued updates, encrypt, and emit via Socket.IO
|
|
47
49
|
* without awaiting the server ACK. The server broadcasts to peers immediately
|
|
48
50
|
* (before MongoDB write), so content reaches observers in near-real-time.
|
|
49
|
-
* ACK callback handles updateId tracking and auto-commit asynchronously.
|
|
50
51
|
*/
|
|
51
52
|
private sendUpdateBatch;
|
|
53
|
+
private maybeAuthorSnapshotAfterSend;
|
|
54
|
+
buildPendingBeaconPayload(): string | null;
|
|
55
|
+
fireBeacon(): void;
|
|
52
56
|
forceCleanup(): void;
|
|
53
57
|
private handleConnectionError;
|
|
54
58
|
private handleReconnection;
|
|
55
59
|
private connectSocket;
|
|
56
|
-
private
|
|
60
|
+
private decodeInto;
|
|
61
|
+
private catchUpFloor;
|
|
62
|
+
private authorSnapshot;
|
|
63
|
+
private hydrate;
|
|
57
64
|
private initializeAwareness;
|
|
58
65
|
private cleanupAwareness;
|
|
59
|
-
private commitLocalContents;
|
|
60
66
|
private broadcastLocalContents;
|
|
61
67
|
private processUpdateQueue;
|
|
62
68
|
private processNextUpdate;
|
|
63
|
-
private processCommit;
|
|
64
69
|
private handleRemoteContentUpdate;
|
|
65
70
|
private applyRemoteYjsUpdate;
|
|
66
71
|
private applyQueuedRemoteContents;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ISocketInitConfig, RoomMember, SocketStatusEnum, SendUpdateResponse,
|
|
1
|
+
import { ISocketInitConfig, RoomMember, SocketStatusEnum, SendUpdateResponse, HydrationResponse, SnapshotResponse, AckResponse } from './types';
|
|
2
2
|
import { Awareness } from 'y-protocols/awareness.js';
|
|
3
3
|
|
|
4
4
|
interface ISocketClientConfig {
|
|
@@ -8,6 +8,11 @@ interface ISocketClientConfig {
|
|
|
8
8
|
ownerEdSecret?: string;
|
|
9
9
|
contractAddress?: string;
|
|
10
10
|
ownerAddress?: string;
|
|
11
|
+
ownerIdentityDid?: string;
|
|
12
|
+
editLock?: string;
|
|
13
|
+
encryptedTitle?: string;
|
|
14
|
+
identityToken?: string;
|
|
15
|
+
identityContractAddress?: string;
|
|
11
16
|
onHandshakeData?: (response: {
|
|
12
17
|
data: AckResponse;
|
|
13
18
|
roomKey: string;
|
|
@@ -20,6 +25,8 @@ interface ISocketClientConfig {
|
|
|
20
25
|
}
|
|
21
26
|
export declare class SocketClient {
|
|
22
27
|
private _socketUrl;
|
|
28
|
+
private _restBase;
|
|
29
|
+
private _lastSessionToken;
|
|
23
30
|
private _socket;
|
|
24
31
|
private _webSocketStatus;
|
|
25
32
|
private _isIntentionalDisconnect;
|
|
@@ -34,6 +41,11 @@ export declare class SocketClient {
|
|
|
34
41
|
private ownerUcan?;
|
|
35
42
|
private collaborationUcan?;
|
|
36
43
|
private ownerAddress?;
|
|
44
|
+
private ownerIdentityDid?;
|
|
45
|
+
private editLock?;
|
|
46
|
+
private encryptedTitle?;
|
|
47
|
+
private identityToken?;
|
|
48
|
+
private identityContractAddress?;
|
|
37
49
|
private roomKey;
|
|
38
50
|
private roomInfo?;
|
|
39
51
|
private awareness;
|
|
@@ -46,15 +58,17 @@ export declare class SocketClient {
|
|
|
46
58
|
sendUpdate({ update }: {
|
|
47
59
|
update: string;
|
|
48
60
|
}): Promise<SendUpdateResponse>;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
fetchHydrationRange(sinceSeq?: number): Promise<HydrationResponse>;
|
|
62
|
+
sendSnapshot({ data, floorSeq, publishedMarker, }: {
|
|
63
|
+
data: string;
|
|
64
|
+
floorSeq: number;
|
|
65
|
+
publishedMarker?: string | null;
|
|
66
|
+
}): Promise<SnapshotResponse>;
|
|
67
|
+
setDocumentMeta(): Promise<void>;
|
|
55
68
|
broadcastAwareness(awarenessUpdate: string): Promise<void>;
|
|
56
69
|
disconnect: () => void;
|
|
57
70
|
terminateSession: () => Promise<void>;
|
|
71
|
+
flushBeacon(mergedUpdate: string): void;
|
|
58
72
|
private getCollaborationKeyPair;
|
|
59
73
|
private isUcanValid;
|
|
60
74
|
private getOwnerToken;
|
|
@@ -7,6 +7,20 @@ export interface CollabConnectionConfig {
|
|
|
7
7
|
roomId: string;
|
|
8
8
|
wsUrl: string;
|
|
9
9
|
isOwner: boolean;
|
|
10
|
+
/** Host signal: doc is in an active live-collaboration context (shared / peers present). Keeps the socket connected. */
|
|
11
|
+
livePresence?: boolean;
|
|
12
|
+
/** Host signal: connect once on open to initialise durability even without an edit. */
|
|
13
|
+
connectOnOpen?: boolean;
|
|
14
|
+
/** Host signal (owner-only): the owner identity signingKey DID. Recorded by the durable server on the first owner /auth as the R3 owner binding. */
|
|
15
|
+
ownerIdentityDid?: string;
|
|
16
|
+
/** Host signal (owner-only): wrapped roomKey bytes (owner-lock construction), uploaded as the server editLock recovery artifact. Opaque to the package. */
|
|
17
|
+
editLock?: string;
|
|
18
|
+
/** Host signal (owner-only): the document title encrypted with the roomKey, uploaded as the server title recovery artifact. Opaque to the package. */
|
|
19
|
+
encryptedTitle?: string;
|
|
20
|
+
/** Host signal (owner-only): Ed25519 UCAN proving the owner identity, sent on /auth so the server binds the CRYPTOGRAPHICALLY PROVEN owner DID (not a bare asserted string). Opaque to the package. */
|
|
21
|
+
identityToken?: string;
|
|
22
|
+
/** Host signal (owner-only): the identity contract address the server reads to resolve the on-chain signingDid that verifies identityToken. */
|
|
23
|
+
identityContractAddress?: string;
|
|
10
24
|
ownerEdSecret?: string;
|
|
11
25
|
contractAddress?: string;
|
|
12
26
|
ownerAddress?: string;
|
|
@@ -21,11 +35,7 @@ export interface CollabSessionMeta {
|
|
|
21
35
|
username: string;
|
|
22
36
|
isEns?: boolean;
|
|
23
37
|
}
|
|
24
|
-
|
|
25
|
-
export interface CollabServices {
|
|
26
|
-
commitToStorage?: (file: File) => Promise<string>;
|
|
27
|
-
fetchFromStorage?: (cid: string) => Promise<any>;
|
|
28
|
-
}
|
|
38
|
+
export type CollabServices = Record<string, never>;
|
|
29
39
|
export type CollabErrorCode = 'CONNECTION_FAILED' | 'AUTH_FAILED' | 'SYNC_FAILED' | 'TIMEOUT' | 'UNKNOWN';
|
|
30
40
|
export type CollabError = {
|
|
31
41
|
code: CollabErrorCode;
|
|
@@ -145,11 +155,30 @@ export interface SendUpdateResponse extends AckResponse<{
|
|
|
145
155
|
createdAt: number;
|
|
146
156
|
}> {
|
|
147
157
|
}
|
|
148
|
-
export interface
|
|
149
|
-
|
|
150
|
-
createdAt: number;
|
|
158
|
+
export interface HydrationRow {
|
|
159
|
+
id: string;
|
|
151
160
|
documentId: string;
|
|
152
|
-
|
|
161
|
+
seq: number;
|
|
162
|
+
data: string;
|
|
163
|
+
updateType: string;
|
|
164
|
+
committed?: boolean;
|
|
165
|
+
commitCid?: string | null;
|
|
166
|
+
createdAt?: number;
|
|
167
|
+
sessionDid?: string;
|
|
168
|
+
publishedMarker?: string | null;
|
|
169
|
+
floorSeq?: number | null;
|
|
170
|
+
}
|
|
171
|
+
export interface HydrationResponse extends AckResponse<{
|
|
172
|
+
history: HydrationRow[];
|
|
173
|
+
total: number;
|
|
174
|
+
snapshot: HydrationRow | null;
|
|
175
|
+
nextSeq: number | null;
|
|
176
|
+
hasMore: boolean;
|
|
177
|
+
}> {
|
|
178
|
+
}
|
|
179
|
+
export interface SnapshotResponse extends AckResponse<{
|
|
180
|
+
id: string;
|
|
181
|
+
seq: number;
|
|
153
182
|
}> {
|
|
154
183
|
}
|
|
155
184
|
export interface ISocketInitConfig {
|
|
@@ -196,4 +225,7 @@ export interface IAuthArgs {
|
|
|
196
225
|
contractAddress?: string;
|
|
197
226
|
sessionDid?: string;
|
|
198
227
|
roomInfo?: string;
|
|
228
|
+
ownerIdentityDid?: string;
|
|
229
|
+
identityToken?: string;
|
|
230
|
+
identityContractAddress?: string;
|
|
199
231
|
}
|
package/dist/package/types.d.ts
CHANGED
|
@@ -180,8 +180,11 @@ export interface DdocProps extends CommentAccountProps {
|
|
|
180
180
|
walletAddress?: string | null;
|
|
181
181
|
username?: string | null;
|
|
182
182
|
setUsername?: React.Dispatch<SetStateAction<string>>;
|
|
183
|
-
renderNavbar?: ({ editor }: {
|
|
183
|
+
renderNavbar?: ({ editor, liveEditor, }: {
|
|
184
|
+
/** JSON snapshot — legacy field, unchanged. */
|
|
184
185
|
editor: JSONContent;
|
|
186
|
+
/** Live Tiptap editor instance (D8) — null until the editor is ready. */
|
|
187
|
+
liveEditor: Editor | null;
|
|
185
188
|
}) => JSX.Element;
|
|
186
189
|
onChange?: (updatedDocContent: string | JSONContent, updateChunk: string) => void;
|
|
187
190
|
onCollaboratorChange?: (collaborators: undefined | IDocCollabUsers[]) => void;
|
|
@@ -209,6 +212,9 @@ export interface DdocProps extends CommentAccountProps {
|
|
|
209
212
|
onComment?: () => void;
|
|
210
213
|
onInlineComment?: () => void;
|
|
211
214
|
onFocusMode?: (isFocusMode: boolean) => void;
|
|
215
|
+
/** Controlled focus mode (D6). Omit for the legacy internal-state behavior. */
|
|
216
|
+
isFocusMode?: boolean;
|
|
217
|
+
onFocusModeChange?: (isFocusMode: boolean) => void;
|
|
212
218
|
onMarkdownExport?: () => void;
|
|
213
219
|
onMarkdownImport?: () => void;
|
|
214
220
|
onPdfExport?: () => void;
|
|
@@ -28,6 +28,7 @@ export declare const useDdocEditor: ({ isPreviewMode, viewerMode, initialContent
|
|
|
28
28
|
duplicateTab: (tabId: string) => string | undefined;
|
|
29
29
|
orderTab: (destinationTabId: string, movedTabId: string) => void;
|
|
30
30
|
onConnect: (connectConfig: import('./types').CollabConnectionConfig) => void;
|
|
31
|
+
onDisconnect: () => void;
|
|
31
32
|
isReady: boolean;
|
|
32
33
|
isSyncing: boolean;
|
|
33
34
|
hasCollabContentInitialised: boolean;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Editor, Range } from '@tiptap/core';
|
|
2
|
+
import { IpfsImageUploadResponse } from '../types';
|
|
3
|
+
|
|
4
|
+
type InsertCommand = (editor: Editor, range?: Range) => void;
|
|
5
|
+
export type UploadImageOptions = {
|
|
6
|
+
onError?: (errorString: string) => void;
|
|
7
|
+
ipfsImageUploadFn?: (file: File) => Promise<IpfsImageUploadResponse>;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* File-picker image upload — mirrors the toolbar flow
|
|
11
|
+
* (editor-utils.tsx "Upload Image") and the slash "Image" item.
|
|
12
|
+
*/
|
|
13
|
+
export declare const uploadImageCommand: (editor: Editor, { onError, ipfsImageUploadFn }?: UploadImageOptions) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Insert commands shared by the slash menu and `useEditorCommands`.
|
|
16
|
+
* Bodies are moved verbatim from `slash-command-utils.tsx`; the optional
|
|
17
|
+
* `range` only differs when invoked from the slash menu.
|
|
18
|
+
*/
|
|
19
|
+
export declare const insertCommands: Record<string, InsertCommand>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared jsdom editor factory for unit tests (use-editor-commands.test.tsx,
|
|
5
|
+
* selection-utils.test.ts, ...). Collaboration owns the doc, so content must
|
|
6
|
+
* be set via `setContent` *after* construction — passing `content` to the
|
|
7
|
+
* `Editor` constructor is silently ignored once Collaboration is configured.
|
|
8
|
+
*/
|
|
9
|
+
export declare const makeEditor: (content?: string) => Editor;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cursor-relative word range in the current textblock, or null when the
|
|
5
|
+
* cursor is not adjacent to a word character (whitespace runs, empty
|
|
6
|
+
* blocks). Position math is relative ($from.start() + parentOffset), so it
|
|
7
|
+
* is schema-agnostic (works under dBlock wrappers).
|
|
8
|
+
*/
|
|
9
|
+
export declare const findWordRangeAtCursor: (editor: Editor) => {
|
|
10
|
+
from: number;
|
|
11
|
+
to: number;
|
|
12
|
+
} | null;
|
|
13
|
+
/**
|
|
14
|
+
* Ensure a text target for anchored actions (inline comments): keep any
|
|
15
|
+
* existing non-empty TextSelection; otherwise select the word under the
|
|
16
|
+
* collapsed cursor. Shares findWordRangeAtCursor with enablement so
|
|
17
|
+
* "enabled" always implies "dispatch does something".
|
|
18
|
+
*
|
|
19
|
+
* Only a TextSelection passes through untouched — a non-empty NodeSelection
|
|
20
|
+
* (e.g. an image or horizontal rule selected as a node) looks "non-empty"
|
|
21
|
+
* but has no text content, so `textBetween` over it is '' and anything
|
|
22
|
+
* downstream that needs real text (e.g. createFloatingDraft) would silently
|
|
23
|
+
* no-op. Falling through to findWordRangeAtCursor for any other selection
|
|
24
|
+
* type gives either a legitimate adjacent word or null (schema-dependent —
|
|
25
|
+
* e.g. false for a NodeSelection whose dBlock wrapper has no text).
|
|
26
|
+
*/
|
|
27
|
+
export declare const selectWordAtCursor: (editor: Editor) => boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Single enablement predicate for anchored text actions (inline comments):
|
|
30
|
+
* true when there's already a non-empty TextSelection, or a word is
|
|
31
|
+
* reachable from a collapsed cursor via findWordRangeAtCursor. Mirrors the
|
|
32
|
+
* passthrough condition in selectWordAtCursor so "enabled" always implies
|
|
33
|
+
* selectWordAtCursor will produce a real text target.
|
|
34
|
+
*/
|
|
35
|
+
export declare const hasTextTargetAtSelection: (editor: Editor) => boolean;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/core';
|
|
2
|
+
|
|
3
|
+
export declare const FONT_SIZES: readonly [8, 9, 10, 11, 12, 14, 16, 18, 24, 30, 32, 36, 48, 60, 72, 96];
|
|
4
|
+
export declare const getFontSizeOptions: (editor?: Editor) => {
|
|
5
|
+
title: string;
|
|
6
|
+
value: string;
|
|
7
|
+
label: string;
|
|
8
|
+
command: (editor: Editor) => void;
|
|
9
|
+
isActive: () => boolean | undefined;
|
|
10
|
+
}[];
|
|
11
|
+
export declare const getCurrentFontSize: (editor: Editor | null, currentSize: string) => string;
|
|
12
|
+
export declare const uiValueToPercentage: (uiValue: string) => string;
|
|
13
|
+
export declare const percentageToUiValue: (percentage: string) => string;
|
|
14
|
+
export declare const LINE_HEIGHT_OPTIONS: {
|
|
15
|
+
value: string;
|
|
16
|
+
label: string;
|
|
17
|
+
uiValue: string;
|
|
18
|
+
description: string;
|
|
19
|
+
}[];
|
|
20
|
+
export declare const getLineHeightOptions: () => {
|
|
21
|
+
value: string;
|
|
22
|
+
label: string;
|
|
23
|
+
uiValue: string;
|
|
24
|
+
description: string;
|
|
25
|
+
}[];
|
|
26
|
+
export declare const getCurrentLineHeight: (editor: Editor | null, currentLineHeight?: string) => string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { j as d } from "./index-
|
|
1
|
+
import { j as d } from "./index-BREkA3S3.mjs";
|
|
2
2
|
import { useRef as I, useState as N, useEffect as D } from "react";
|
|
3
3
|
import { DynamicDropdown as E, Tooltip as R, IconButton as O } from "@fileverse/ui";
|
|
4
|
-
import { a3 as A, a4 as P, c as y } from "./index-
|
|
4
|
+
import { a3 as A, a4 as P, c as y } from "./index-CioSbJ2V.mjs";
|
|
5
5
|
const p = (e, t, o = t) => {
|
|
6
6
|
const { state: s } = e, l = s.changeByRange((n) => {
|
|
7
7
|
const u = s.sliceDoc(n.from, n.to), r = s.sliceDoc(
|