@fileverse-dev/ddoc 3.2.9 → 3.3.0-viem-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 (34) hide show
  1. package/dist/index.es.js +45022 -34621
  2. package/dist/package/components/inline-comment/comment-card.d.ts +19 -1
  3. package/dist/package/components/inline-comment/comment-drawer-constants.d.ts +1 -0
  4. package/dist/package/components/inline-comment/comment-drawer-desktop.d.ts +35 -0
  5. package/dist/package/components/inline-comment/comment-drawer-mobile.d.ts +43 -0
  6. package/dist/package/components/inline-comment/comment-floating-layout.d.ts +2 -0
  7. package/dist/package/components/inline-comment/comment-reply-input.d.ts +1 -1
  8. package/dist/package/components/inline-comment/context/types.d.ts +9 -1
  9. package/dist/package/components/inline-comment/floating-comment/suggestion-draft-floating-card.d.ts +17 -0
  10. package/dist/package/components/inline-comment/floating-comment/suggestion-thread-floating-card.d.ts +15 -0
  11. package/dist/package/components/inline-comment/floating-comment/types.d.ts +6 -1
  12. package/dist/package/components/inline-comment/floating-comment-layout-utils.d.ts +9 -2
  13. package/dist/package/components/inline-comment/mobile-inline-comment-sheet.d.ts +15 -0
  14. package/dist/package/components/inline-comment/mobile-suggestion-draft-sheet.d.ts +15 -0
  15. package/dist/package/components/inline-comment/suggestion-diff-summary.d.ts +11 -0
  16. package/dist/package/components/inline-comment/types.d.ts +1 -0
  17. package/dist/package/components/inline-comment/use-comment-drawer-drafts.d.ts +22 -0
  18. package/dist/package/components/inline-comment/use-comment-drawer-filters.d.ts +40 -0
  19. package/dist/package/components/inline-comment/use-comment-drawer-focus.d.ts +17 -0
  20. package/dist/package/components/inline-comment/use-comment-drawer-lifecycle.d.ts +13 -0
  21. package/dist/package/components/inline-comment/use-is-selected-content-deleted.d.ts +1 -1
  22. package/dist/package/components/inline-comment/use-mobile-comment-navigation.d.ts +20 -0
  23. package/dist/package/extensions/comment/comment-decoration-plugin.d.ts +34 -7
  24. package/dist/package/extensions/comment/comment.d.ts +5 -0
  25. package/dist/package/extensions/suggestion/suggestion-tracking-extension.d.ts +45 -0
  26. package/dist/package/hooks/use-editing-context.d.ts +2 -0
  27. package/dist/package/hooks/use-tab-editor.d.ts +4 -1
  28. package/dist/package/stores/comment-store-provider.d.ts +1 -1
  29. package/dist/package/stores/comment-store.d.ts +84 -0
  30. package/dist/package/types.d.ts +9 -0
  31. package/dist/package/use-ddoc-editor.d.ts +3 -1
  32. package/dist/style.css +1 -1
  33. package/package.json +2 -2
  34. package/dist/package/utils/getAddressName.d.ts +0 -7
@@ -1,4 +1,22 @@
1
- import { CommentCardProps } from './types';
1
+ import { MouseEvent } from 'react';
2
+ import { CommentCardProps, CommentReplyProps, EnsStatus } from './types';
2
3
 
4
+ export declare const CommentReply: ({ commentId, replyId, reply, username, createdAt, isThreadResolved, }: CommentReplyProps) => import("react/jsx-runtime").JSX.Element;
5
+ interface CommentRepliesThreadProps {
6
+ id?: string;
7
+ displayedReplies: CommentCardProps['replies'];
8
+ ensStatus: EnsStatus;
9
+ handleReplyToggleClick: (event: MouseEvent<HTMLElement>) => void;
10
+ isCommentDrawerContext?: boolean;
11
+ isResolved?: boolean;
12
+ replyToggleLabel: string;
13
+ shouldShowReplyThread: boolean;
14
+ shouldShowReplyToggle: boolean;
15
+ shouldShowResolvedMobileReplyCount: boolean;
16
+ showAllReplies: boolean;
17
+ visibleReplies: CommentCardProps['replies'];
18
+ }
19
+ export declare const CommentRepliesThread: ({ id, displayedReplies, ensStatus, handleReplyToggleClick, isCommentDrawerContext, isResolved, replyToggleLabel, shouldShowReplyThread, shouldShowReplyToggle, shouldShowResolvedMobileReplyCount, showAllReplies, visibleReplies, }: CommentRepliesThreadProps) => import("react/jsx-runtime").JSX.Element | null;
3
20
  export declare const CommentCard: (props: CommentCardProps) => import("react/jsx-runtime").JSX.Element;
4
21
  export declare const UserDisplaySkeleton: () => import("react/jsx-runtime").JSX.Element;
22
+ export {};
@@ -0,0 +1 @@
1
+ export declare const ALL_TABS_OPTION_ID = "__all_tabs__";
@@ -0,0 +1,35 @@
1
+ import { IComment } from '../../extensions/comment';
2
+
3
+ interface DrawerSelectOption {
4
+ id: string;
5
+ label: string;
6
+ }
7
+ interface CommentDrawerDesktopProps {
8
+ activeCommentId: string | null;
9
+ commentType: string;
10
+ commentTypeOptions: DrawerSelectOption[];
11
+ filteredComments: IComment[];
12
+ isCollaborationEnabled: boolean;
13
+ isCommentTypeSelectOpen: boolean;
14
+ isConnected: boolean;
15
+ isNavbarVisible: boolean;
16
+ isOpen: boolean;
17
+ isPresentationMode: boolean;
18
+ isPreviewMode: boolean;
19
+ isTabSelectOpen: boolean;
20
+ newCommentTabId: string;
21
+ onClose: () => void;
22
+ onCommentFocus: (commentId: string, tabId?: string) => void;
23
+ onCommentTypeChange: (commentType: string) => void;
24
+ onCommentTypeSelectOpenChange: (open: boolean) => void;
25
+ onReset: () => void;
26
+ onTabChange: (tabId: string) => void;
27
+ onTabSelectOpenChange: (open: boolean) => void;
28
+ sectionLabel: string;
29
+ selectedTab: string;
30
+ selectedTabLabel: string;
31
+ tabList: DrawerSelectOption[];
32
+ tabNameById: Record<string, string>;
33
+ }
34
+ export declare const CommentDrawerDesktop: ({ activeCommentId, commentType, commentTypeOptions, filteredComments, isCollaborationEnabled, isCommentTypeSelectOpen, isConnected, isNavbarVisible, isOpen, isPresentationMode, isPreviewMode, isTabSelectOpen, newCommentTabId, onClose, onCommentFocus, onCommentTypeChange, onCommentTypeSelectOpenChange, onReset, onTabChange, onTabSelectOpenChange, sectionLabel, selectedTab, selectedTabLabel, tabList, tabNameById, }: CommentDrawerDesktopProps) => import("react/jsx-runtime").JSX.Element;
35
+ export {};
@@ -0,0 +1,43 @@
1
+ import { IComment } from '../../extensions/comment';
2
+ import { InlineCommentDraft, SuggestionFloatingDraftCard } from './context/types';
3
+
4
+ interface CommentDrawerMobileProps {
5
+ activeCommentId: string | null;
6
+ activeDraft: InlineCommentDraft | null;
7
+ activeDraftId: string | null;
8
+ activeSuggestionDraftCard: SuggestionFloatingDraftCard | null;
9
+ canGoToNextMobileComment: boolean;
10
+ canGoToPreviousMobileComment: boolean;
11
+ comments: IComment[];
12
+ isCollaborationEnabled: boolean;
13
+ isCommentMobileFocused: boolean;
14
+ isConnected: boolean;
15
+ isDiscardCommentOverlayVisible: boolean;
16
+ isDiscardSuggestionOverlayVisible: boolean;
17
+ isInlineDraftOpen: boolean;
18
+ isMobileDrawerVisible: boolean;
19
+ isNavbarVisible: boolean;
20
+ isPresentationMode: boolean;
21
+ mobileActiveCommentsCount: number;
22
+ mobileDraftRef: React.RefObject<HTMLDivElement>;
23
+ mobileFocusedCommentIndex: number;
24
+ onAttemptCloseNewComment: () => void;
25
+ onAttemptCloseSuggestionDraft: () => void;
26
+ onCancelDiscardComment: () => void;
27
+ onCancelDiscardSuggestion: () => void;
28
+ onCloseDrawer: () => void;
29
+ onCommentFocus: (commentId: string, tabId?: string) => void;
30
+ onCreateComment: () => void;
31
+ onDiscardSuggestionDraft: () => void;
32
+ onFocusSuggestionDraft: () => void;
33
+ onNextMobileComment: () => void;
34
+ onPreviousMobileComment: () => void;
35
+ onStartNewMobileComment: () => void;
36
+ onSubmitSuggestionDraft: () => void;
37
+ onUpdateInlineDraftText: (draftId: string, text: string) => void;
38
+ onViewAllComments: () => void;
39
+ tabNameById: Record<string, string>;
40
+ username: string | null;
41
+ }
42
+ export declare const CommentDrawerMobile: ({ activeCommentId, activeDraft, activeDraftId, activeSuggestionDraftCard, canGoToNextMobileComment, canGoToPreviousMobileComment, comments, isCollaborationEnabled, isCommentMobileFocused, isConnected, isDiscardCommentOverlayVisible, isDiscardSuggestionOverlayVisible, isInlineDraftOpen, isMobileDrawerVisible, isNavbarVisible, isPresentationMode, mobileActiveCommentsCount, mobileDraftRef, mobileFocusedCommentIndex, onAttemptCloseNewComment, onAttemptCloseSuggestionDraft, onCancelDiscardComment, onCancelDiscardSuggestion, onCloseDrawer, onCommentFocus, onCreateComment, onDiscardSuggestionDraft, onFocusSuggestionDraft, onNextMobileComment, onPreviousMobileComment, onStartNewMobileComment, onSubmitSuggestionDraft, onUpdateInlineDraftText, onViewAllComments, tabNameById, username, }: CommentDrawerMobileProps) => import("react/jsx-runtime").JSX.Element;
43
+ export {};
@@ -1,4 +1,6 @@
1
1
  export declare const FLOATING_COMMENT_CARD_GAP = 8;
2
+ export declare const FLOATING_COMMENT_BOTTOM_SPACE = 48;
3
+ export declare const FLOATING_COMMENT_RIGHT_SPACE = 48;
2
4
  export declare const enum FloatingLayoutInvalidationFlag {
3
5
  None = 0,
4
6
  Anchor = 1,
@@ -4,5 +4,5 @@ interface CommentReplyInputProps {
4
4
  replyCount: number;
5
5
  isCollaborationEnabled: boolean;
6
6
  }
7
- export declare const CommentReplyInput: ({ commentId, replyCount, isCollaborationEnabled, }: CommentReplyInputProps) => import("react/jsx-runtime").JSX.Element;
7
+ export declare const CommentReplyInput: ({ commentId, replyCount, isCollaborationEnabled, commentUsername, }: CommentReplyInputProps) => import("react/jsx-runtime").JSX.Element;
8
8
  export {};
@@ -26,7 +26,15 @@ export interface CommentFloatingThreadCard extends CommentFloatingBaseCard {
26
26
  type: 'thread';
27
27
  commentId: string;
28
28
  }
29
- export type CommentFloatingCard = CommentFloatingDraftCard | CommentFloatingThreadCard;
29
+ export interface SuggestionFloatingDraftCard extends CommentFloatingBaseCard {
30
+ type: 'suggestion-draft';
31
+ suggestionId: string;
32
+ /** Accumulated inserted text from the live suggestion context. */
33
+ insertedText: string;
34
+ /** Pasted link href for link suggestions. */
35
+ linkHref?: string;
36
+ }
37
+ export type CommentFloatingCard = CommentFloatingDraftCard | CommentFloatingThreadCard | SuggestionFloatingDraftCard;
30
38
  export interface InlineCommentData {
31
39
  highlightedTextContent?: string;
32
40
  inlineCommentText: string;
@@ -0,0 +1,17 @@
1
+ import { SuggestionDraftFloatingCardProps } from './types';
2
+
3
+ /**
4
+ * SuggestionDraftFloatingCard
5
+ *
6
+ * Shown while a viewer is composing a suggestion (in suggestion mode).
7
+ * Uses the same one-line diff format as the submitted thread card
8
+ * (Add: "X" / Delete: "X" / Replace: "X" with "Y") plus a Submit action
9
+ * and a Discard (X) button.
10
+ *
11
+ * When the viewer hasn't joined yet (no username / wallet), the card
12
+ * renders FloatingAuthPrompt inside — same pattern as the inline-comment
13
+ * draft card. The first keystroke that triggered this card is preserved
14
+ * as the draft's first character; once the viewer joins, the card
15
+ * transitions to the normal diff/Submit UI without losing what they typed.
16
+ */
17
+ export declare const SuggestionDraftFloatingCard: ({ card, isHidden, registerCardNode, }: SuggestionDraftFloatingCardProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,15 @@
1
+ import { ThreadFloatingCardProps } from './types';
2
+
3
+ /**
4
+ * SuggestionThreadFloatingCard
5
+ *
6
+ * Shown in place of the generic ThreadFloatingCard for submitted suggestions
7
+ * (comments with `isSuggestion: true`). Renders the Figma-specified layout:
8
+ * author + timestamp header, Accept/Reject (owner) or Withdraw (author)
9
+ * actions, a one-line diff summary (Add/Delete/Replace), and a reply input.
10
+ *
11
+ * Renders from the underlying IComment — the same source ThreadFloatingCard
12
+ * uses — so once a draft is submitted, nothing else in the pipeline needs
13
+ * to change to show the suggestion here.
14
+ */
15
+ export declare const SuggestionThreadFloatingCard: ({ thread, comment, isHidden, registerCardNode, isCollaborationEnabled, }: ThreadFloatingCardProps) => import("react/jsx-runtime").JSX.Element | null;
@@ -1,7 +1,7 @@
1
1
  import { Editor } from '@tiptap/react';
2
2
  import { ReactNode, RefObject } from 'react';
3
3
  import { IComment } from '../../../extensions/comment';
4
- import { CommentFloatingDraftCard, CommentFloatingThreadCard } from '../context/types';
4
+ import { CommentFloatingDraftCard, CommentFloatingThreadCard, SuggestionFloatingDraftCard } from '../context/types';
5
5
 
6
6
  export type RegisterCardNode = (floatingCardId: string, node: HTMLDivElement | null) => void;
7
7
  export interface CommentFloatingContainerProps {
@@ -32,3 +32,8 @@ export interface ThreadFloatingCardProps {
32
32
  registerCardNode: RegisterCardNode;
33
33
  isCollaborationEnabled?: boolean;
34
34
  }
35
+ export interface SuggestionDraftFloatingCardProps {
36
+ card: SuggestionFloatingDraftCard;
37
+ isHidden: boolean;
38
+ registerCardNode: RegisterCardNode;
39
+ }
@@ -2,7 +2,7 @@ import { Editor } from '@tiptap/react';
2
2
  import { FloatingLayoutInvalidationFlag, FloatingCardLayoutInput } from './comment-floating-layout';
3
3
  import { CommentFloatingCard } from './context/types';
4
4
 
5
- export type AnchorType = 'draft' | 'thread';
5
+ export type AnchorType = 'draft' | 'thread' | 'suggestion-draft';
6
6
  export interface CachedAnchorRect {
7
7
  top: number;
8
8
  height: number;
@@ -40,6 +40,9 @@ export declare const FLOATING_VIEWPORT_BUFFER_MULTIPLIER = 1;
40
40
  export declare const getAnchorIdentity: (floatingCard: CommentFloatingCard) => {
41
41
  anchorId: string;
42
42
  anchorType: "draft";
43
+ } | {
44
+ anchorId: string;
45
+ anchorType: "suggestion-draft";
43
46
  } | {
44
47
  anchorId: string;
45
48
  anchorType: "thread";
@@ -65,7 +68,11 @@ export declare const getRect: ({ elements, viewportTop, viewportBottom, }: {
65
68
  elements: HTMLElement[];
66
69
  viewportTop: number;
67
70
  viewportBottom: number;
68
- }) => DOMRect | null;
71
+ }) => {
72
+ top: number;
73
+ height: number;
74
+ intersectsViewport: boolean;
75
+ } | null;
69
76
  export declare const reconcileOrderedFloatingCardIds: ({ previousOrderedFloatingCardIds, nextFloatingCards, getPos, }: {
70
77
  previousOrderedFloatingCardIds: string[];
71
78
  nextFloatingCards: CommentFloatingCard[];
@@ -0,0 +1,15 @@
1
+ import { InlineCommentDraft } from './context/types';
2
+
3
+ interface MobileInlineCommentProps {
4
+ activeDraft: InlineCommentDraft | null;
5
+ activeDraftId: string | null;
6
+ isDiscardCommentOverlayVisible: boolean;
7
+ mobileDraftRef: React.RefObject<HTMLDivElement>;
8
+ onAttemptClose: () => void;
9
+ onCancelDiscard: () => void;
10
+ onConfirmDiscard: () => void;
11
+ onSubmit: () => void;
12
+ onUpdateDraftText: (draftId: string, text: string) => void;
13
+ }
14
+ export declare const MobileInlineComment: ({ activeDraft, activeDraftId, isDiscardCommentOverlayVisible, mobileDraftRef, onAttemptClose, onCancelDiscard, onConfirmDiscard, onSubmit, onUpdateDraftText, }: MobileInlineCommentProps) => import("react/jsx-runtime").JSX.Element;
15
+ export {};
@@ -0,0 +1,15 @@
1
+ import { SuggestionFloatingDraftCard } from './context/types';
2
+
3
+ interface MobileSuggestionDraftProps {
4
+ activeSuggestionDraftCard: SuggestionFloatingDraftCard;
5
+ isConnected: boolean;
6
+ isDiscardSuggestionOverlayVisible: boolean;
7
+ username: string | null;
8
+ onAttemptClose: () => void;
9
+ onCancelDiscard: () => void;
10
+ onConfirmDiscard: () => void;
11
+ onFocusSuggestionText: () => void;
12
+ onSubmit: () => void;
13
+ }
14
+ export declare const MobileSuggestionDraft: ({ activeSuggestionDraftCard, isConnected, isDiscardSuggestionOverlayVisible, username, onAttemptClose, onCancelDiscard, onConfirmDiscard, onFocusSuggestionText, onSubmit, }: MobileSuggestionDraftProps) => import("react/jsx-runtime").JSX.Element;
15
+ export {};
@@ -0,0 +1,11 @@
1
+ import { SuggestionType } from '../../types';
2
+
3
+ interface SuggestionDiffSummaryProps {
4
+ suggestionType?: SuggestionType | null;
5
+ originalContent?: string;
6
+ suggestedContent?: string;
7
+ emptyText?: string;
8
+ className?: string;
9
+ }
10
+ export declare const SuggestionDiffSummary: ({ suggestionType, originalContent, suggestedContent, emptyText, className, }: SuggestionDiffSummaryProps) => import("react/jsx-runtime").JSX.Element | null;
11
+ export {};
@@ -50,6 +50,7 @@ export interface CommentCardProps extends IComment {
50
50
  activeCommentId?: string;
51
51
  isDisabled?: boolean;
52
52
  isCommentOwner?: boolean;
53
+ canResolveComment?: boolean;
53
54
  version?: string;
54
55
  emptyComment?: boolean;
55
56
  isFocused?: boolean;
@@ -0,0 +1,22 @@
1
+ import { SuggestionFloatingDraftCard } from './context/types';
2
+
3
+ interface UseCommentDrawerDraftsProps {
4
+ selectedCommentTabId: string;
5
+ setOpenReplyId: (commentId: string | null) => void;
6
+ }
7
+ export declare const useCommentDrawerDrafts: ({ selectedCommentTabId, setOpenReplyId, }: UseCommentDrawerDraftsProps) => {
8
+ activeDraft: import('./context/types').InlineCommentDraft | null;
9
+ activeDraftId: string | null;
10
+ activeSuggestionDraftCard: SuggestionFloatingDraftCard | null;
11
+ handleCreateComment: () => void;
12
+ handleDiscardSuggestionDraft: () => void;
13
+ handleStartNewMobileComment: () => void;
14
+ handleSubmitSuggestionDraft: () => void;
15
+ isDiscardCommentOverlayVisible: boolean;
16
+ isDiscardSuggestionOverlayVisible: boolean;
17
+ isInlineDraftOpen: boolean;
18
+ setIsDiscardCommentOverlayVisible: import('react').Dispatch<import('react').SetStateAction<boolean>>;
19
+ setIsDiscardSuggestionOverlayVisible: import('react').Dispatch<import('react').SetStateAction<boolean>>;
20
+ updateInlineDraftText: (draftId: string, value: string) => void;
21
+ };
22
+ export {};
@@ -0,0 +1,40 @@
1
+ import { IComment } from '../../extensions/comment';
2
+ import { Tab } from '../tabs/utils/tab-utils';
3
+
4
+ export declare const commentTypeOptions: {
5
+ id: string;
6
+ label: string;
7
+ }[];
8
+ interface UseCommentDrawerFiltersProps {
9
+ activeTabId: string;
10
+ comments: IComment[];
11
+ tabs: Tab[];
12
+ }
13
+ export declare const useCommentDrawerFilters: ({ activeTabId, comments, tabs, }: UseCommentDrawerFiltersProps) => {
14
+ closeFilterSelects: () => void;
15
+ commentType: string;
16
+ commentTypeOptions: {
17
+ id: string;
18
+ label: string;
19
+ }[];
20
+ filteredComments: IComment[];
21
+ handleCommentTypeSelectOpenChange: (open: boolean) => void;
22
+ handleTabSelectOpenChange: (open: boolean) => void;
23
+ isCommentTypeSelectOpen: boolean;
24
+ isTabSelectOpen: boolean;
25
+ resetFilters: () => void;
26
+ sectionLabel: string;
27
+ selectedCommentTabId: string;
28
+ selectedTab: string;
29
+ selectedTabLabel: string;
30
+ setCommentType: import('react').Dispatch<import('react').SetStateAction<string>>;
31
+ setTab: import('react').Dispatch<import('react').SetStateAction<string>>;
32
+ tabList: {
33
+ id: string;
34
+ label: string;
35
+ }[];
36
+ tabNameById: {
37
+ [k: string]: string;
38
+ };
39
+ };
40
+ export {};
@@ -0,0 +1,17 @@
1
+ import { IComment } from '../../extensions/comment';
2
+
3
+ interface UseCommentDrawerFocusProps {
4
+ activeTabId: string;
5
+ comments: IComment[];
6
+ focusCommentInEditor: (commentId: string, options?: {
7
+ source?: 'explicit-ui';
8
+ }) => void;
9
+ isBelow1280px: boolean;
10
+ onTabChange?: (tabId: string) => void;
11
+ setOpenReplyId: (commentId: string | null) => void;
12
+ }
13
+ export declare const useCommentDrawerFocus: ({ activeTabId, comments, focusCommentInEditor, isBelow1280px, onTabChange, setOpenReplyId, }: UseCommentDrawerFocusProps) => {
14
+ clearPendingCommentFocus: () => void;
15
+ handleCommentFocus: (commentId: string, commentTabId?: string) => void;
16
+ };
17
+ export {};
@@ -0,0 +1,13 @@
1
+ interface UseCommentDrawerLifecycleProps {
2
+ activeSuggestionDraftCard: unknown;
3
+ closeFilterSelects: () => void;
4
+ isBelow1280px: boolean;
5
+ isCommentMobileFocused: boolean;
6
+ isInlineDraftOpen: boolean;
7
+ isOpen: boolean;
8
+ onClose: () => void;
9
+ setIsDiscardCommentOverlayVisible: (visible: boolean) => void;
10
+ setIsDiscardSuggestionOverlayVisible: (visible: boolean) => void;
11
+ }
12
+ export declare const useCommentDrawerLifecycle: ({ activeSuggestionDraftCard, closeFilterSelects, isBelow1280px, isCommentMobileFocused, isInlineDraftOpen, isOpen, onClose, setIsDiscardCommentOverlayVisible, setIsDiscardSuggestionOverlayVisible, }: UseCommentDrawerLifecycleProps) => void;
13
+ export {};
@@ -1 +1 @@
1
- export declare function useIsSelectedContentDeleted(commentId: string | undefined, selectedContent: string | undefined, commentTabId: string | undefined): boolean;
1
+ export declare function useIsSelectedContentDeleted(commentId: string | undefined, selectedContent: string | undefined, commentTabId: string | undefined, isSuggestion?: boolean): boolean;
@@ -0,0 +1,20 @@
1
+ import { RefObject } from 'react';
2
+ import { IComment } from '../../extensions/comment';
3
+
4
+ interface UseMobileCommentNavigationProps {
5
+ comments: IComment[];
6
+ mobileDrawerRef: RefObject<HTMLDivElement>;
7
+ onCommentFocus: (commentId: string, tabId?: string) => void;
8
+ openReplyId: string | null;
9
+ setOpenReplyId: (commentId: string | null) => void;
10
+ }
11
+ export declare const useMobileCommentNavigation: ({ comments, mobileDrawerRef, onCommentFocus, openReplyId, setOpenReplyId, }: UseMobileCommentNavigationProps) => {
12
+ canGoToNextMobileComment: boolean;
13
+ canGoToPreviousMobileComment: boolean;
14
+ handleNextMobileComment: () => void;
15
+ handlePreviousMobileComment: () => void;
16
+ handleViewAllComments: () => void;
17
+ mobileActiveCommentsCount: number;
18
+ mobileFocusedCommentIndex: number;
19
+ };
20
+ export {};
@@ -2,6 +2,7 @@ import { Extension, Editor } from '@tiptap/core';
2
2
  import { EditorState, PluginKey } from '@tiptap/pm/state';
3
3
  import { Transform } from '@tiptap/pm/transform';
4
4
  import { DecorationSet } from '@tiptap/pm/view';
5
+ import { SuggestionType } from '../../types';
5
6
 
6
7
  import * as Y from 'yjs';
7
8
  export interface CommentAnchor {
@@ -10,6 +11,10 @@ export interface CommentAnchor {
10
11
  anchorTo: Y.RelativePosition;
11
12
  resolved: boolean;
12
13
  deleted: boolean;
14
+ isSuggestion?: boolean;
15
+ suggestionType?: SuggestionType;
16
+ originalContent?: string;
17
+ suggestedContent?: string;
13
18
  }
14
19
  interface CommentDecorationPluginState {
15
20
  decorations: DecorationSet;
@@ -34,7 +39,15 @@ export type CommentAnchorTransactionChange = {
34
39
  } & CommentAnchorRange & CommentAnchorRelativeRange);
35
40
  export declare const commentDecorationPluginKey: PluginKey<CommentDecorationPluginState>;
36
41
  export declare function resolveCommentAnchorRangeInState(anchor: Pick<CommentAnchor, 'anchorFrom' | 'anchorTo'>, state: EditorState): CommentAnchorRange | null;
42
+ /**
43
+ * Resolve anchorFrom to a single absolute position.
44
+ * Used for 'add' suggestion anchors where anchorFrom === anchorTo (cursor,
45
+ * no initial selection) — resolveCommentAnchorRangeInState rejects from >= to,
46
+ * so we need a separate path that allows a point position.
47
+ */
48
+ export declare function resolveCommentAnchorPointInState(anchor: Pick<CommentAnchor, 'anchorFrom'>, state: EditorState): number | null;
37
49
  export declare function resolveCommentAnchorRangeForAnalysis(anchor: Pick<CommentAnchor, 'id' | 'anchorFrom' | 'anchorTo'>, state: EditorState): CommentAnchorRange | null;
50
+ export declare function resolveCommentAnchorPointForAnalysis(anchor: Pick<CommentAnchor, 'id' | 'anchorFrom'>, state: EditorState): number | null;
38
51
  /**
39
52
  * Analyze transaction changes to classify each active anchor's mutation status.
40
53
  *
@@ -42,15 +55,16 @@ export declare function resolveCommentAnchorRangeForAnalysis(anchor: Pick<Commen
42
55
  * whether each anchor remains unchanged, gets edited, or is deleted.
43
56
  *
44
57
  * Classification rules (in order):
45
- * 1. Skip deleted or resolved anchors → 'unchanged'
46
- * 2. If anchor has no old position → 'unchanged'
47
- * 3. If no changed ranges touch the anchor → 'unchanged'
48
- * 4. If any changed range fully covers the anchor → 'deleted' (full-span replacement)
49
- * 5. If combined changed ranges fully cover the anchor → 'deleted' (multi-step removal)
50
- * 6. If anchor maps through transform check if position or content changed:
58
+ * 1. If the transform preserves positions → 'unchanged'
59
+ * 2. Skip deleted or resolved anchors → 'unchanged'
60
+ * 3. If anchor has no old position → 'unchanged'
61
+ * 4. If no changed ranges touch the anchor → 'unchanged'
62
+ * 5. If any changed range fully covers the anchor → 'deleted' (full-span replacement)
63
+ * 6. If combined changed ranges fully cover the anchor 'deleted' (multi-step removal)
64
+ * 7. If anchor maps through transform → check if position or content changed:
51
65
  * a. If both unchanged → 'unchanged'
52
66
  * b. Otherwise → 'edited' (return new position and relative anchor)
53
- * 7. If mapping fails → 'deleted'
67
+ * 8. If mapping fails → 'deleted'
54
68
  */
55
69
  export declare function analyzeCommentAnchorTransactionChanges(anchors: CommentAnchor[], oldState: EditorState, newState: EditorState, transform: Transform): CommentAnchorTransactionChange[];
56
70
  export interface CommentDecorationOptions {
@@ -63,8 +77,21 @@ export declare const CommentDecorationExtension: Extension<CommentDecorationOpti
63
77
  * These are consumed by the draft-creation flow and transaction-analysis layer.
64
78
  */
65
79
  export declare function createCommentAnchorFromEditor(editor: Editor, from: number, to: number): CommentAnchorRelativeRange | null;
80
+ /**
81
+ * Create a point anchor (anchorFrom === anchorTo) at a single doc position.
82
+ * Used by the suggestion-mode draft flow when the viewer places a cursor
83
+ * without selecting text — createCommentAnchorFromEditor rejects from >= to
84
+ * since an empty range is invalid for regular comments.
85
+ */
86
+ export declare function createCommentAnchorPointFromEditor(editor: Editor, pos: number): CommentAnchorRelativeRange | null;
66
87
  export declare function createCommentAnchorFromSelection(editor: Editor): CommentAnchorRelativeRange | null;
67
88
  export declare function triggerDecorationRebuild(editor: Editor): void;
68
89
  export declare function getCommentAtPosition(editor: Editor, pos: number, getAnchors: () => CommentAnchor[]): CommentAnchor | null;
69
90
  export declare function getCommentAnchorRange(editor: Editor, commentId: string, getAnchors: () => CommentAnchor[]): CommentAnchorRange | null;
91
+ /**
92
+ * Apply the accepted suggestion's change to the document.
93
+ * Called by the store's acceptSuggestion action before resolving on-chain.
94
+ * Returns false if the anchor can't be resolved or the suggestion type is unknown.
95
+ */
96
+ export declare function applyAcceptedSuggestion(editor: Editor, anchor: CommentAnchor): boolean;
70
97
  export {};
@@ -2,6 +2,7 @@ import { Mark, Range } from '@tiptap/core';
2
2
  import { Mark as PMMark } from '@tiptap/pm/model';
3
3
  import { PluginKey, EditorState } from '@tiptap/pm/state';
4
4
  import { DecorationSet } from '@tiptap/pm/view';
5
+ import { SuggestionType } from '../../types';
5
6
 
6
7
  declare module '@tiptap/core' {
7
8
  interface Commands<ReturnType> {
@@ -93,6 +94,10 @@ export interface IComment {
93
94
  deleted?: boolean;
94
95
  commentIndex?: number;
95
96
  version?: string;
97
+ isSuggestion?: boolean;
98
+ suggestionType?: SuggestionType;
99
+ originalContent?: string;
100
+ suggestedContent?: string;
96
101
  }
97
102
  export declare const CommentExtension: Mark<CommentOptions, CommentStorage>;
98
103
  export {};
@@ -0,0 +1,45 @@
1
+ import { Extension } from '@tiptap/core';
2
+ import { PluginKey } from '@tiptap/pm/state';
3
+ import { SuggestionType } from '../../types';
4
+ import { CommentAnchor } from '../comment/comment-decoration-plugin';
5
+
6
+ import * as Y from 'yjs';
7
+ export interface SuggestionReadyData {
8
+ suggestionId: string;
9
+ anchorFrom: Y.RelativePosition;
10
+ anchorTo: Y.RelativePosition;
11
+ suggestionType: SuggestionType;
12
+ originalContent: string;
13
+ suggestedContent: string;
14
+ }
15
+ export interface SuggestionTrackingOptions {
16
+ /** Returns true when the editor is in suggestion mode. */
17
+ getIsSuggestionMode: () => boolean;
18
+ /** Viewer types text with a collapsed cursor (Add gesture). */
19
+ onTextInput: (text: string) => void;
20
+ /** Viewer types text over a non-empty selection (Replace gesture). */
21
+ onReplaceTyping: (from: number, to: number, text: string) => void;
22
+ /** Viewer presses Backspace/Delete with a non-empty selection. */
23
+ onDeleteSelection: (from: number, to: number) => void;
24
+ /** Viewer pastes a link over selected text. */
25
+ onPasteLink: (from: number, to: number, href: string) => void;
26
+ /**
27
+ * Viewer presses Backspace/Delete with a collapsed cursor.
28
+ * The consumer decides whether this should shrink an active draft or create
29
+ * a new one-character delete suggestion at the caret.
30
+ */
31
+ onDeleteAtCursor: (direction: 'backward' | 'forward') => void;
32
+ /**
33
+ * Browser attempted to delete a concrete range without an explicit
34
+ * user selection (for example, a beforeinput/IME path that bypassed
35
+ * keydown). Lets the consumer preserve "undo active draft" semantics
36
+ * while still creating delete drafts for normal text.
37
+ */
38
+ onDeleteRangeWithoutSelection: (from: number, to: number) => void;
39
+ /** Viewer presses Cmd+Z (or Ctrl+Z). Shrinks the active draft by one keystroke. */
40
+ onUndo: () => void;
41
+ onLiveSuggestion?: ((anchor: CommentAnchor) => void) | null;
42
+ onSuggestionReady?: ((data: SuggestionReadyData) => void) | null;
43
+ }
44
+ export declare const suggestionTrackingPluginKey: PluginKey<null>;
45
+ export declare const SuggestionTrackingExtension: Extension<SuggestionTrackingOptions, any>;
@@ -4,6 +4,7 @@ type EditingContextType = {
4
4
  isPreviewMode: boolean;
5
5
  isPresentationMode?: boolean;
6
6
  isCollaboratorsDoc?: boolean;
7
+ isSuggestionMode?: boolean;
7
8
  };
8
9
  export declare const useEditingContext: () => EditingContextType;
9
10
  type EditingProviderProps = {
@@ -12,6 +13,7 @@ type EditingProviderProps = {
12
13
  isPresentationMode?: boolean;
13
14
  isCollaboratorsDoc?: boolean;
14
15
  isPreviewEditor?: boolean;
16
+ isSuggestionMode?: boolean;
15
17
  };
16
18
  export declare const EditingProvider: React.FC<EditingProviderProps>;
17
19
  export {};
@@ -12,6 +12,7 @@ interface UseTabEditorArgs {
12
12
  hasTabState?: boolean;
13
13
  versionId?: string;
14
14
  isPreviewMode?: boolean;
15
+ viewerMode?: DdocProps['viewerMode'];
15
16
  initialContent: DdocProps['initialContent'];
16
17
  collaboration?: CollaborationProps;
17
18
  isReady?: boolean;
@@ -51,7 +52,7 @@ interface UseTabEditorArgs {
51
52
  editorRef?: MutableRefObject<Editor | null>;
52
53
  initialCommentAnchors?: SerializedCommentAnchor[];
53
54
  }
54
- export declare const useTabEditor: ({ ydoc, isVersionMode, hasTabState, versionId, isPreviewMode, initialContent, collaboration, isReady, isSyncing, awareness, disableInlineComment, isFocusMode, onCommentInteraction, onError, ipfsImageUploadFn, metadataProxyUrl, onCopyHeadingLink, ipfsImageFetchFn, fetchV1ImageFn, isConnected, activeModel, maxTokens, isAIAgentEnabled, setCharacterCount, setWordCount, setPageCount, setIsContentLoading, setIsCollabContentLoading, unFocused, zoomLevel, isPresentationMode, onInvalidContentError, ignoreCorruptedData, onCollaboratorChange, onConnect, hasCollabContentInitialised, initialiseYjsIndexedDbProvider, externalExtensions, isContentLoading, activeTabId, theme, editorRef, initialCommentAnchors, }: UseTabEditorArgs) => {
55
+ export declare const useTabEditor: ({ ydoc, isVersionMode, hasTabState, versionId, isPreviewMode, viewerMode, initialContent, collaboration, isReady, isSyncing, awareness, disableInlineComment, isFocusMode, onCommentInteraction, onError, ipfsImageUploadFn, metadataProxyUrl, onCopyHeadingLink, ipfsImageFetchFn, fetchV1ImageFn, isConnected, activeModel, maxTokens, isAIAgentEnabled, setCharacterCount, setWordCount, setPageCount, setIsContentLoading, setIsCollabContentLoading, unFocused, zoomLevel, isPresentationMode, onInvalidContentError, ignoreCorruptedData, onCollaboratorChange, onConnect, hasCollabContentInitialised, initialiseYjsIndexedDbProvider, externalExtensions, isContentLoading, activeTabId, theme, editorRef, initialCommentAnchors, }: UseTabEditorArgs) => {
55
56
  editor: Editor | null;
56
57
  ref: import('react').RefObject<HTMLDivElement>;
57
58
  slides: string[];
@@ -63,5 +64,7 @@ export declare const useTabEditor: ({ ydoc, isVersionMode, hasTabState, versionI
63
64
  focusCommentWithActiveId: (id: string) => void;
64
65
  isContentLoading: boolean | undefined;
65
66
  commentAnchorsRef: MutableRefObject<CommentAnchor[]>;
67
+ draftAnchorsRef: MutableRefObject<CommentAnchor[]>;
68
+ storeApiRef: MutableRefObject<import('zustand').StoreApi<import('../stores/comment-store').CommentStoreState> | null>;
66
69
  };
67
70
  export {};
@@ -46,7 +46,7 @@ export interface CommentStoreProviderProps {
46
46
  isDDocOwner?: boolean;
47
47
  setUsername?: React.Dispatch<React.SetStateAction<string>>;
48
48
  }
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, initialCommentAnchors, setUsername: setUsernameProp, initialComments, username, activeCommentId, activeTabId, isConnected, isLoading, isDDocOwner, }: CommentStoreProviderProps) => import("react/jsx-runtime").JSX.Element;
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;
50
50
  interface CommentRefsContextType {
51
51
  commentsSectionRef: React.RefObject<HTMLDivElement>;
52
52
  replySectionRef: React.RefObject<HTMLDivElement>;