@tldraw/commenting 5.3.0-internal.c5c7f1d817d0 → 5.3.0-next.2fa9c61a8de6
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/README.md +0 -2
- package/commenting.css +1040 -230
- package/dist-cjs/canvas/anchor-lifecycle.js +148 -0
- package/dist-cjs/canvas/anchor-lifecycle.js.map +7 -0
- package/dist-cjs/canvas/cluster-input.js +2 -2
- package/dist-cjs/canvas/cluster-input.js.map +2 -2
- package/dist-cjs/canvas/comment-drafts.js +54 -0
- package/dist-cjs/canvas/comment-drafts.js.map +7 -0
- package/dist-cjs/canvas/comment-mutations.js +123 -0
- package/dist-cjs/canvas/comment-mutations.js.map +7 -0
- package/dist-cjs/canvas/comment-reactions.js +163 -0
- package/dist-cjs/canvas/comment-reactions.js.map +7 -0
- package/dist-cjs/canvas/comment-render.js +5 -3
- package/dist-cjs/canvas/comment-render.js.map +2 -2
- package/dist-cjs/canvas/comment-store.js +19 -9
- package/dist-cjs/canvas/comment-store.js.map +2 -2
- package/dist-cjs/canvas/comment-tool.js +64 -14
- package/dist-cjs/canvas/comment-tool.js.map +2 -2
- package/dist-cjs/canvas/comments-filter-menu.js +20 -38
- package/dist-cjs/canvas/comments-filter-menu.js.map +2 -2
- package/dist-cjs/canvas/comments-overflow-menu.js +22 -27
- package/dist-cjs/canvas/comments-overflow-menu.js.map +2 -2
- package/dist-cjs/canvas/comments-overlay.js +377 -437
- package/dist-cjs/canvas/comments-overlay.js.map +2 -2
- package/dist-cjs/canvas/comments-sidebar.js +34 -31
- package/dist-cjs/canvas/comments-sidebar.js.map +2 -2
- package/dist-cjs/canvas/comments-visibility-toggle.js +65 -0
- package/dist-cjs/canvas/comments-visibility-toggle.js.map +7 -0
- package/dist-cjs/canvas/context.js +17 -0
- package/dist-cjs/canvas/context.js.map +7 -0
- package/dist-cjs/canvas/hooks.js +22 -3
- package/dist-cjs/canvas/hooks.js.map +2 -2
- package/dist-cjs/canvas/options.js +19 -2
- package/dist-cjs/canvas/options.js.map +2 -2
- package/dist-cjs/canvas/pin-stacking.js +56 -0
- package/dist-cjs/canvas/pin-stacking.js.map +7 -0
- package/dist-cjs/canvas/sidebar-filters.js +2 -2
- package/dist-cjs/canvas/sidebar-filters.js.map +2 -2
- package/dist-cjs/canvas/state.js +28 -14
- package/dist-cjs/canvas/state.js.map +2 -2
- package/dist-cjs/canvas/thread-preview.js +185 -0
- package/dist-cjs/canvas/thread-preview.js.map +7 -0
- package/dist-cjs/canvas/thread-stack.js +199 -0
- package/dist-cjs/canvas/thread-stack.js.map +7 -0
- package/dist-cjs/canvas/thread-state.js +67 -21
- package/dist-cjs/canvas/thread-state.js.map +2 -2
- package/dist-cjs/canvas/thread-view.js +397 -0
- package/dist-cjs/canvas/thread-view.js.map +7 -0
- package/dist-cjs/clustering/computeClusterTable.js +4 -4
- package/dist-cjs/clustering/computeClusterTable.js.map +2 -2
- package/dist-cjs/clustering/runtime.js +9 -9
- package/dist-cjs/clustering/runtime.js.map +2 -2
- package/dist-cjs/clustering/types.js.map +1 -1
- package/dist-cjs/index.d.ts +763 -353
- package/dist-cjs/index.js +46 -28
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/ui/byline.js +3 -1
- package/dist-cjs/ui/byline.js.map +2 -2
- package/dist-cjs/ui/comment-card.js +12 -5
- package/dist-cjs/ui/comment-card.js.map +2 -2
- package/dist-cjs/ui/comment-composer.js +112 -17
- package/dist-cjs/ui/comment-composer.js.map +2 -2
- package/dist-cjs/ui/comment-pin.js +20 -2
- package/dist-cjs/ui/comment-pin.js.map +2 -2
- package/dist-cjs/ui/comment-thread.js +4 -2
- package/dist-cjs/ui/comment-thread.js.map +2 -2
- package/dist-cjs/ui/comments-list.js +22 -10
- package/dist-cjs/ui/comments-list.js.map +2 -2
- package/dist-cjs/ui/count-badge.js +3 -2
- package/dist-cjs/ui/count-badge.js.map +2 -2
- package/dist-cjs/ui/emoji-picker.js +54 -0
- package/dist-cjs/ui/emoji-picker.js.map +7 -0
- package/dist-cjs/ui/format-time.js +4 -1
- package/dist-cjs/ui/format-time.js.map +2 -2
- package/dist-cjs/ui/reaction-picker.js +73 -0
- package/dist-cjs/ui/reaction-picker.js.map +7 -0
- package/dist-cjs/ui/reaction.js +50 -4
- package/dist-cjs/ui/reaction.js.map +2 -2
- package/dist-cjs/ui/reactions.js +20 -15
- package/dist-cjs/ui/reactions.js.map +2 -2
- package/dist-cjs/ui/{mention.js → reply-count.js} +9 -11
- package/dist-cjs/ui/reply-count.js.map +7 -0
- package/dist-cjs/ui/send-button.js +20 -1
- package/dist-cjs/ui/send-button.js.map +2 -2
- package/dist-cjs/ui/{comment-text.js → tooltip-button.js} +12 -9
- package/dist-cjs/ui/tooltip-button.js.map +7 -0
- package/dist-esm/canvas/anchor-lifecycle.mjs +128 -0
- package/dist-esm/canvas/anchor-lifecycle.mjs.map +7 -0
- package/dist-esm/canvas/cluster-input.mjs +2 -2
- package/dist-esm/canvas/cluster-input.mjs.map +2 -2
- package/dist-esm/canvas/comment-drafts.mjs +34 -0
- package/dist-esm/canvas/comment-drafts.mjs.map +7 -0
- package/dist-esm/canvas/comment-mutations.mjs +103 -0
- package/dist-esm/canvas/comment-mutations.mjs.map +7 -0
- package/dist-esm/canvas/comment-reactions.mjs +152 -0
- package/dist-esm/canvas/comment-reactions.mjs.map +7 -0
- package/dist-esm/canvas/comment-render.mjs +5 -3
- package/dist-esm/canvas/comment-render.mjs.map +2 -2
- package/dist-esm/canvas/comment-store.mjs +19 -9
- package/dist-esm/canvas/comment-store.mjs.map +2 -2
- package/dist-esm/canvas/comment-tool.mjs +67 -17
- package/dist-esm/canvas/comment-tool.mjs.map +2 -2
- package/dist-esm/canvas/comments-filter-menu.mjs +20 -38
- package/dist-esm/canvas/comments-filter-menu.mjs.map +2 -2
- package/dist-esm/canvas/comments-overflow-menu.mjs +23 -27
- package/dist-esm/canvas/comments-overflow-menu.mjs.map +2 -2
- package/dist-esm/canvas/comments-overlay.mjs +398 -442
- package/dist-esm/canvas/comments-overlay.mjs.map +3 -3
- package/dist-esm/canvas/comments-sidebar.mjs +37 -34
- package/dist-esm/canvas/comments-sidebar.mjs.map +2 -2
- package/dist-esm/canvas/comments-visibility-toggle.mjs +45 -0
- package/dist-esm/canvas/comments-visibility-toggle.mjs.map +7 -0
- package/dist-esm/canvas/context.mjs +1 -0
- package/dist-esm/canvas/context.mjs.map +7 -0
- package/dist-esm/canvas/hooks.mjs +28 -5
- package/dist-esm/canvas/hooks.mjs.map +2 -2
- package/dist-esm/canvas/options.mjs +21 -3
- package/dist-esm/canvas/options.mjs.map +2 -2
- package/dist-esm/canvas/pin-stacking.mjs +36 -0
- package/dist-esm/canvas/pin-stacking.mjs.map +7 -0
- package/dist-esm/canvas/sidebar-filters.mjs +2 -2
- package/dist-esm/canvas/sidebar-filters.mjs.map +2 -2
- package/dist-esm/canvas/state.mjs +29 -19
- package/dist-esm/canvas/state.mjs.map +2 -2
- package/dist-esm/canvas/thread-preview.mjs +170 -0
- package/dist-esm/canvas/thread-preview.mjs.map +7 -0
- package/dist-esm/canvas/thread-stack.mjs +190 -0
- package/dist-esm/canvas/thread-stack.mjs.map +7 -0
- package/dist-esm/canvas/thread-state.mjs +71 -22
- package/dist-esm/canvas/thread-state.mjs.map +2 -2
- package/dist-esm/canvas/thread-view.mjs +402 -0
- package/dist-esm/canvas/thread-view.mjs.map +7 -0
- package/dist-esm/clustering/computeClusterTable.mjs +4 -4
- package/dist-esm/clustering/computeClusterTable.mjs.map +2 -2
- package/dist-esm/clustering/runtime.mjs +9 -9
- package/dist-esm/clustering/runtime.mjs.map +2 -2
- package/dist-esm/index.d.mts +763 -353
- package/dist-esm/index.mjs +87 -41
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/ui/byline.mjs +3 -1
- package/dist-esm/ui/byline.mjs.map +2 -2
- package/dist-esm/ui/comment-card.mjs +12 -5
- package/dist-esm/ui/comment-card.mjs.map +2 -2
- package/dist-esm/ui/comment-composer.mjs +122 -16
- package/dist-esm/ui/comment-composer.mjs.map +2 -2
- package/dist-esm/ui/comment-pin.mjs +20 -2
- package/dist-esm/ui/comment-pin.mjs.map +2 -2
- package/dist-esm/ui/comment-thread.mjs +4 -2
- package/dist-esm/ui/comment-thread.mjs.map +2 -2
- package/dist-esm/ui/comments-list.mjs +39 -25
- package/dist-esm/ui/comments-list.mjs.map +2 -2
- package/dist-esm/ui/count-badge.mjs +3 -2
- package/dist-esm/ui/count-badge.mjs.map +2 -2
- package/dist-esm/ui/emoji-picker.mjs +34 -0
- package/dist-esm/ui/emoji-picker.mjs.map +7 -0
- package/dist-esm/ui/format-time.mjs +4 -1
- package/dist-esm/ui/format-time.mjs.map +2 -2
- package/dist-esm/ui/reaction-picker.mjs +60 -0
- package/dist-esm/ui/reaction-picker.mjs.map +7 -0
- package/dist-esm/ui/reaction.mjs +51 -5
- package/dist-esm/ui/reaction.mjs.map +2 -2
- package/dist-esm/ui/reactions.mjs +21 -16
- package/dist-esm/ui/reactions.mjs.map +2 -2
- package/dist-esm/ui/reply-count.mjs +9 -0
- package/dist-esm/ui/reply-count.mjs.map +7 -0
- package/dist-esm/ui/send-button.mjs +20 -1
- package/dist-esm/ui/send-button.mjs.map +2 -2
- package/dist-esm/ui/tooltip-button.mjs +12 -0
- package/dist-esm/ui/tooltip-button.mjs.map +7 -0
- package/package.json +6 -6
- package/src/canvas/anchor-lifecycle.test.ts +290 -0
- package/src/canvas/anchor-lifecycle.ts +205 -0
- package/src/canvas/canvas.css +439 -24
- package/src/canvas/cluster-input.test.ts +31 -23
- package/src/canvas/cluster-input.ts +3 -4
- package/src/canvas/comment-drafts.test.ts +55 -0
- package/src/canvas/comment-drafts.ts +46 -0
- package/src/canvas/comment-mutations.test.ts +410 -0
- package/src/canvas/comment-mutations.ts +288 -0
- package/src/canvas/comment-reactions.test.ts +132 -0
- package/src/canvas/comment-reactions.tsx +245 -0
- package/src/canvas/comment-render.ts +9 -5
- package/src/canvas/comment-store.ts +67 -27
- package/src/canvas/comment-tool.test.ts +162 -0
- package/src/canvas/comment-tool.tsx +105 -23
- package/src/canvas/comments-filter-menu.tsx +23 -32
- package/src/canvas/comments-overflow-menu.tsx +12 -19
- package/src/canvas/comments-overlay.tsx +602 -562
- package/src/canvas/comments-sidebar.test.ts +45 -0
- package/src/canvas/comments-sidebar.tsx +75 -57
- package/src/canvas/comments-visibility-toggle.tsx +49 -0
- package/src/canvas/context.ts +47 -0
- package/src/canvas/hooks.ts +52 -11
- package/src/canvas/options.test.ts +52 -2
- package/src/canvas/options.ts +133 -9
- package/src/canvas/pin-stacking.test.ts +114 -0
- package/src/canvas/pin-stacking.ts +57 -0
- package/src/canvas/sidebar-filters.ts +4 -3
- package/src/canvas/state.ts +92 -35
- package/src/canvas/thread-preview.test.ts +91 -0
- package/src/canvas/thread-preview.tsx +304 -0
- package/src/canvas/thread-stack.tsx +252 -0
- package/src/canvas/thread-state.test.ts +209 -0
- package/src/canvas/thread-state.ts +137 -36
- package/src/canvas/thread-view.tsx +516 -0
- package/src/clustering/computeClusterTable.test.ts +24 -23
- package/src/clustering/computeClusterTable.ts +5 -5
- package/src/clustering/runtime.test.ts +34 -0
- package/src/clustering/runtime.ts +20 -15
- package/src/clustering/types.ts +9 -9
- package/src/index.ts +76 -40
- package/src/ui/byline.tsx +4 -2
- package/src/ui/comment-card.tsx +17 -7
- package/src/ui/comment-composer.tsx +160 -13
- package/src/ui/comment-pin.tsx +22 -2
- package/src/ui/comment-thread.tsx +6 -1
- package/src/ui/comments-list.test.ts +31 -0
- package/src/ui/comments-list.tsx +32 -12
- package/src/ui/comments.css +489 -204
- package/src/ui/count-badge.tsx +9 -2
- package/src/ui/emoji-picker.test.ts +25 -0
- package/src/ui/emoji-picker.tsx +76 -0
- package/src/ui/format-time.ts +7 -2
- package/src/ui/reaction-picker.tsx +109 -0
- package/src/ui/reaction.tsx +116 -4
- package/src/ui/reactions.tsx +68 -13
- package/src/ui/reply-count.ts +16 -0
- package/src/ui/send-button.tsx +18 -3
- package/src/ui/tooltip-button.tsx +20 -0
- package/dist-cjs/canvas/region-options.js +0 -49
- package/dist-cjs/canvas/region-options.js.map +0 -7
- package/dist-cjs/ui/avatar.js +0 -51
- package/dist-cjs/ui/avatar.js.map +0 -7
- package/dist-cjs/ui/comment-mention.js +0 -42
- package/dist-cjs/ui/comment-mention.js.map +0 -7
- package/dist-cjs/ui/comment-text.js.map +0 -7
- package/dist-cjs/ui/mention-list.js +0 -70
- package/dist-cjs/ui/mention-list.js.map +0 -7
- package/dist-cjs/ui/mention-suggestion.js +0 -206
- package/dist-cjs/ui/mention-suggestion.js.map +0 -7
- package/dist-cjs/ui/mention.js.map +0 -7
- package/dist-cjs/ui/render-markdown.js +0 -63
- package/dist-cjs/ui/render-markdown.js.map +0 -7
- package/dist-esm/canvas/region-options.mjs +0 -29
- package/dist-esm/canvas/region-options.mjs.map +0 -7
- package/dist-esm/ui/avatar.mjs +0 -31
- package/dist-esm/ui/avatar.mjs.map +0 -7
- package/dist-esm/ui/comment-mention.mjs +0 -22
- package/dist-esm/ui/comment-mention.mjs.map +0 -7
- package/dist-esm/ui/comment-text.mjs +0 -9
- package/dist-esm/ui/comment-text.mjs.map +0 -7
- package/dist-esm/ui/mention-list.mjs +0 -50
- package/dist-esm/ui/mention-list.mjs.map +0 -7
- package/dist-esm/ui/mention-suggestion.mjs +0 -186
- package/dist-esm/ui/mention-suggestion.mjs.map +0 -7
- package/dist-esm/ui/mention.mjs +0 -11
- package/dist-esm/ui/mention.mjs.map +0 -7
- package/dist-esm/ui/render-markdown.mjs +0 -45
- package/dist-esm/ui/render-markdown.mjs.map +0 -7
- package/src/canvas/region-options.ts +0 -57
- package/src/ui/avatar.tsx +0 -38
- package/src/ui/comment-mention.ts +0 -47
- package/src/ui/comment-text.tsx +0 -12
- package/src/ui/mention-list.tsx +0 -106
- package/src/ui/mention-suggestion.test.ts +0 -18
- package/src/ui/mention-suggestion.tsx +0 -285
- package/src/ui/mention.tsx +0 -9
- package/src/ui/render-markdown.tsx +0 -72
package/dist-esm/index.d.mts
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
|
+
import { Avatar } from '@tldraw/mentions';
|
|
2
|
+
import { AvatarProps } from '@tldraw/mentions';
|
|
3
|
+
import { CommentAuthor } from '@tldraw/mentions';
|
|
1
4
|
import { ComponentType } from 'react';
|
|
5
|
+
import { createMentionSuggestion } from '@tldraw/mentions';
|
|
2
6
|
import { Editor } from 'tldraw';
|
|
3
7
|
import { EditorAtom } from 'tldraw';
|
|
8
|
+
import { filterMentionMembers } from '@tldraw/mentions';
|
|
4
9
|
import { JSX } from 'react/jsx-runtime';
|
|
5
|
-
import
|
|
10
|
+
import { Mention } from '@tldraw/mentions';
|
|
11
|
+
import { MentionList } from '@tldraw/mentions';
|
|
12
|
+
import { MentionListProps } from '@tldraw/mentions';
|
|
13
|
+
import { MentionMember } from '@tldraw/mentions';
|
|
14
|
+
import { MentionProps } from '@tldraw/mentions';
|
|
15
|
+
import { MentionSuggestionOptions } from '@tldraw/mentions';
|
|
16
|
+
import { MouseEvent as MouseEvent_2 } from 'react';
|
|
6
17
|
import { ReactNode } from 'react';
|
|
7
18
|
import { StateNode } from 'tldraw';
|
|
8
|
-
import type { SuggestionOptions } from '@tiptap/suggestion';
|
|
9
19
|
import { TLComment } from 'tldraw';
|
|
10
20
|
import { TLCommentAnchor } from 'tldraw';
|
|
11
21
|
import { TLCommentId } from 'tldraw';
|
|
22
|
+
import { TLCommentReaction } from 'tldraw';
|
|
23
|
+
import { TLCommentReactionId } from 'tldraw';
|
|
12
24
|
import { TLCommentThread } from 'tldraw';
|
|
13
25
|
import { TLCommentThreadId } from 'tldraw';
|
|
14
26
|
import { TLHistoryBatchOptions } from 'tldraw';
|
|
@@ -20,46 +32,35 @@ import { VecLike } from 'tldraw';
|
|
|
20
32
|
|
|
21
33
|
/**
|
|
22
34
|
* Where a thread's pin sits on the page, for each anchor kind. Null hides the pin. For imprecise
|
|
23
|
-
* shape anchors the pin uses
|
|
24
|
-
* rather than the stored `x`/`y`.
|
|
35
|
+
* shape anchors the pin uses the editor's {@link CommentingOptions.impreciseShapeAnchor} (a
|
|
36
|
+
* normalized 0–1 spot, top-right by default) rather than the stored `x`/`y`.
|
|
37
|
+
*
|
|
38
|
+
* A shape anchor's `x`/`y` are normalized within the shape's own bounds and resolved through the
|
|
39
|
+
* shape's page transform, so the pin rides every part of that transform — rotating the shape
|
|
40
|
+
* carries the pin around with it instead of leaving it behind in the bounding box.
|
|
25
41
|
* @public
|
|
26
42
|
*/
|
|
27
|
-
export declare function anchorPagePoint(editor: Editor, anchor: TLCommentAnchor
|
|
28
|
-
x: number;
|
|
29
|
-
y: number;
|
|
30
|
-
}): {
|
|
43
|
+
export declare function anchorPagePoint(editor: Editor, anchor: TLCommentAnchor): {
|
|
31
44
|
x: number;
|
|
32
45
|
y: number;
|
|
33
46
|
} | null;
|
|
34
47
|
|
|
35
|
-
|
|
36
|
-
* @public @react */
|
|
37
|
-
export declare function Avatar({ name, color, image }: AvatarProps): JSX.Element;
|
|
48
|
+
export { Avatar }
|
|
38
49
|
|
|
39
|
-
|
|
40
|
-
export declare interface AvatarProps {
|
|
41
|
-
name: string;
|
|
42
|
-
/** Background colour, used when there's no `image`. Falls back to the default avatar tint. */
|
|
43
|
-
color?: string;
|
|
44
|
-
/** Avatar image URL. When set, shows the image instead of the coloured initial. */
|
|
45
|
-
image?: string;
|
|
46
|
-
}
|
|
50
|
+
export { AvatarProps }
|
|
47
51
|
|
|
48
52
|
/** A comment's metadata line: author name, relative time, and an edited marker. @public @react */
|
|
49
53
|
export declare function Byline({ author, date, edited }: BylineProps): JSX.Element;
|
|
50
54
|
|
|
51
55
|
/** @public */
|
|
52
56
|
export declare interface BylineProps {
|
|
53
|
-
author:
|
|
57
|
+
author: CommentAuthor;
|
|
54
58
|
/** ISO datetime; formatted to relative time by the component. */
|
|
55
59
|
date: string;
|
|
56
60
|
/** Shows an "edited" marker when the comment has been edited. */
|
|
57
61
|
edited?: boolean;
|
|
58
62
|
}
|
|
59
63
|
|
|
60
|
-
/** @public @react */
|
|
61
|
-
export declare function CanvasComments(props: CanvasCommentsProps): JSX.Element | null;
|
|
62
|
-
|
|
63
64
|
/**
|
|
64
65
|
* A ready-to-use comments layer for a tldraw canvas: pins each thread at its anchor, opens a
|
|
65
66
|
* thread popover (with a reply composer) on click, and shows a composer where the comment tool
|
|
@@ -69,163 +70,48 @@ export declare function CanvasComments(props: CanvasCommentsProps): JSX.Element
|
|
|
69
70
|
* and `PinContent` slots on `CommentTool.configure({ components })`), and the pieces it composes
|
|
70
71
|
* (`CommentPin`, `CommentThread`, `CommentComposer`, the hooks, the tool) are all exported, so a
|
|
71
72
|
* consumer can rebuild this from parts instead.
|
|
73
|
+
*
|
|
74
|
+
* The host wiring — who the viewer is, how ids become names, read status, mentions — is the
|
|
75
|
+
* {@link CommentingContext}, which `CanvasCommentsSidebar` takes too, so a host mounting both can
|
|
76
|
+
* build it once and spread it into each.
|
|
77
|
+
*
|
|
78
|
+
* @public @react
|
|
79
|
+
*/
|
|
80
|
+
export declare function CanvasComments(props: CanvasCommentsProps): JSX.Element | null;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The host wiring for {@link CanvasComments} — see {@link CommentingContext}, which the sidebar
|
|
84
|
+
* takes the same fields from.
|
|
85
|
+
*
|
|
72
86
|
* @public
|
|
73
87
|
*/
|
|
74
|
-
export declare
|
|
75
|
-
/** The signed-in user's id, or null for a read-only viewer. Only a signed-in user composes. */
|
|
76
|
-
currentUserId: null | string;
|
|
77
|
-
/** Map an author id to a display name, or `undefined` when the id can't be named. */
|
|
78
|
-
resolveName(id: string): string | undefined;
|
|
79
|
-
/** Called after any comment (a new thread's first comment, or a reply) is posted. */
|
|
80
|
-
onPostComment?(comment: TLComment): void;
|
|
81
|
-
/** Whether a comment is unread for the current user (return true for unread). */
|
|
82
|
-
isCommentUnread?(commentId: TLCommentId): boolean;
|
|
83
|
-
/**
|
|
84
|
-
* Called for each unread comment shown to the user in an open thread popover, so hosts can
|
|
85
|
-
* record a read receipt. Needs `isCommentUnread` to know what's unread.
|
|
86
|
-
*/
|
|
87
|
-
onCommentRead?(commentId: TLCommentId): void;
|
|
88
|
-
/** Resolve the members matching an `@`-query in the composers (sync or async). */
|
|
89
|
-
getMentionSuggestions?(query: string): MentionMember[] | Promise<MentionMember[]>;
|
|
90
|
-
/** Override a mention-picker row's content. */
|
|
91
|
-
renderMentionSuggestion?(member: MentionMember): ReactNode;
|
|
92
|
-
/** Where imprecise shape pins sit — a normalized (0–1) spot within the shape. Default top-right. */
|
|
93
|
-
impreciseShapeAnchor?: {
|
|
94
|
-
x: number;
|
|
95
|
-
y: number;
|
|
96
|
-
};
|
|
97
|
-
/** Region comment behaviour. Region is off by default — omit this for click-only point/shape
|
|
98
|
-
* comments. Anything unset falls back to {@link DEFAULT_REGION_COMMENT_OPTIONS}. */
|
|
99
|
-
regionOptions?: Partial<RegionCommentOptions>;
|
|
100
|
-
}
|
|
88
|
+
export declare type CanvasCommentsProps = CommentingContext;
|
|
101
89
|
|
|
102
90
|
/**
|
|
103
|
-
* A comments list panel for the current page, shown while
|
|
104
|
-
* thread brings its pin into view and opens it. Batteries-included
|
|
105
|
-
* `CanvasComments`); `CommentsList` is exported for a differently-placed
|
|
91
|
+
* A comments list panel for the current page, shown while {@link commentsSidebarOpen} is set (e.g.
|
|
92
|
+
* toggled by a button). Clicking a thread brings its pin into view and opens it. Batteries-included
|
|
93
|
+
* over the store (a sibling to `CanvasComments`); `CommentsList` is exported for a differently-placed
|
|
94
|
+
* or always-on list.
|
|
106
95
|
* @public @react
|
|
107
96
|
*/
|
|
108
97
|
export declare function CanvasCommentsSidebar(props: CanvasCommentsSidebarProps): JSX.Element | null;
|
|
109
98
|
|
|
110
|
-
/**
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
*/
|
|
120
|
-
isCommentUnread?(commentId: TLCommentId): boolean;
|
|
121
|
-
/** Tool ids that show the sidebar. Defaults to the comment tool. */
|
|
122
|
-
tools?: string[];
|
|
99
|
+
/**
|
|
100
|
+
* The host wiring for {@link CanvasCommentsSidebar}: the {@link CommentingContext} fields it reads,
|
|
101
|
+
* plus the panel's own slots. A non-null `currentUserId` enables the "only your threads" filter, and
|
|
102
|
+
* an `isCommentUnread` the "only unread" one. `CanvasComments` takes the same fields, so a host
|
|
103
|
+
* mounting both can spread one object into each.
|
|
104
|
+
*
|
|
105
|
+
* @public
|
|
106
|
+
*/
|
|
107
|
+
export declare interface CanvasCommentsSidebarProps extends Pick<CommentingContext, 'currentUserId' | 'getThreadHref' | 'isCommentUnread' | 'resolveAuthor'> {
|
|
123
108
|
/** Header above the list. */
|
|
124
109
|
header?: ReactNode;
|
|
125
110
|
/** Shown when the page has no threads. */
|
|
126
111
|
empty?: ReactNode;
|
|
127
|
-
/** Where imprecise shape pins sit, so navigation centres on the same spot. Default top-right. */
|
|
128
|
-
impreciseShapeAnchor?: {
|
|
129
|
-
x: number;
|
|
130
|
-
y: number;
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* A cluster in the merge tree: a leaf (one thread) or a merged group.
|
|
136
|
-
* @public
|
|
137
|
-
*/
|
|
138
|
-
export declare interface ClusterNode {
|
|
139
|
-
/** Leaves: the thread id verbatim. Merged nodes: `cluster:${count}:${minMemberId}`. */
|
|
140
|
-
id: string;
|
|
141
|
-
/** Page space; count-weighted mean of all member leaf anchors. */
|
|
142
|
-
centroid: VecLike;
|
|
143
|
-
/** Number of member leaves. Leaves = 1. */
|
|
144
|
-
count: number;
|
|
145
|
-
/** All member thread ids, sorted lexicographically ascending. */
|
|
146
|
-
members: string[];
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** @public */
|
|
150
|
-
export declare interface ClusterOptions {
|
|
151
|
-
/** Cluster (merge) distance, screen px. Default 40. */
|
|
152
|
-
Tc?: number;
|
|
153
|
-
/** Uncluster (split) distance, screen px. Must be \> Tc. Default 1.5 · Tc. */
|
|
154
|
-
Tu?: number;
|
|
155
|
-
/** Contraction window ratio. Default 0.12. */
|
|
156
|
-
eps?: number;
|
|
157
|
-
/** Max cluster screen extent at birth, screen px. Must be \>= Tc. Default 3 · Tc. */
|
|
158
|
-
Dmax?: number;
|
|
159
|
-
/** Camera zoom bounds — pass the editor's camera constraints. Required. */
|
|
160
|
-
minZoom: number;
|
|
161
|
-
maxZoom: number;
|
|
162
|
-
/**
|
|
163
|
-
* Zoom by which every cluster has split, no matter how close its members are — including
|
|
164
|
-
* coincident anchors, which otherwise never split. Merge thresholds are capped at
|
|
165
|
-
* `maxSplitZoom / (Tu/Tc)` so the hysteresis band keeps its shape below the cap.
|
|
166
|
-
* Default 6 (600%).
|
|
167
|
-
*/
|
|
168
|
-
maxSplitZoom?: number;
|
|
169
112
|
}
|
|
170
113
|
|
|
171
|
-
|
|
172
|
-
export declare interface ClusterRuntime {
|
|
173
|
-
/** Events[0..k) are in the cursor (applied unless suppressed). Exposed for tests/debugging. */
|
|
174
|
-
readonly k: number;
|
|
175
|
-
/**
|
|
176
|
-
* Increments whenever the displayed partition changes. Subscribe to this, not `k`: detaches
|
|
177
|
-
* and suppressed-event healing change the partition without moving the cursor.
|
|
178
|
-
*/
|
|
179
|
-
readonly version: number;
|
|
180
|
-
/** Number of suppressed band events currently inside the cursor. Exposed for tests. */
|
|
181
|
-
getSuppressedCount(): number;
|
|
182
|
-
/** Number of leaves currently detached from the displayed partition. Exposed for tests. */
|
|
183
|
-
getDetachedCount(): number;
|
|
184
|
-
/** Reset state from scratch for the given zoom (cold start / after rebuild). Clears detaches. */
|
|
185
|
-
seed(zoom: number): void;
|
|
186
|
-
/**
|
|
187
|
-
* Reset state for the given zoom, carrying hysteresis state over from a previous partition
|
|
188
|
-
* (the visible map of the model being replaced). Threshold-forced events ignore history:
|
|
189
|
-
* zoom \<= zMerge is always merged, zoom \>= zSplit always split. An event inside its band
|
|
190
|
-
* keeps its previous state: merged iff its members were merged together in `previous`; a band
|
|
191
|
-
* event that was unmerged (or has no history, e.g. introduced by the rebuild) stays unmerged —
|
|
192
|
-
* inside the cursor but suppressed — until a zoom-out crosses its own zMerge, exactly like any
|
|
193
|
-
* other pending merge. Carryover is exact: no group changes state because of the swap alone.
|
|
194
|
-
* Clears detaches.
|
|
195
|
-
*/
|
|
196
|
-
seedFrom(zoom: number, previous: ReadonlyMap<string, ClusterNode>): void;
|
|
197
|
-
/** Advance/retreat the cursor for a camera change. No-op if zoom sits inside all bands. */
|
|
198
|
-
onCamera(zoom: number): void;
|
|
199
|
-
/**
|
|
200
|
-
* Remove one leaf from the displayed partition without touching the event table. Local by
|
|
201
|
-
* construction: only the nodes containing the leaf change — a badge shrinks in place (count
|
|
202
|
-
* and centroid recomputed from its remaining members), a pair collapses to its surviving
|
|
203
|
-
* leaf, and the leaf on its own disappears. Everything else is untouched, so a deletion,
|
|
204
|
-
* pop-out, or thread-open never re-flows the rest of the document. The table's thresholds
|
|
205
|
-
* around the detached leaf go stale; the caller is expected to hold a corrected rebuild and
|
|
206
|
-
* adopt it (with seedFrom) at the next zoom-out. Unknown or already-detached ids are no-ops.
|
|
207
|
-
*/
|
|
208
|
-
detachLeaf(leafId: string): void;
|
|
209
|
-
/** The displayed partition: cluster id → node, with detaches applied. Do not mutate. */
|
|
210
|
-
getVisible(): ReadonlyMap<string, ClusterNode>;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* The precomputed clustering schedule for one page's comments.
|
|
215
|
-
* @public
|
|
216
|
-
*/
|
|
217
|
-
export declare interface ClusterTable {
|
|
218
|
-
/** Sorted non-increasing by zMerge; satisfies the invariants of CLUSTERING.md §7.6. */
|
|
219
|
-
events: readonly MergeEvent[];
|
|
220
|
-
/** One node per input leaf, in input order. */
|
|
221
|
-
leaves: readonly ClusterNode[];
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/** @public */
|
|
225
|
-
export declare function collectClusterLeaves(editor: Editor, threads: readonly TLCommentThread[], openThreadId: null | string, impreciseShapeAnchor?: {
|
|
226
|
-
x: number;
|
|
227
|
-
y: number;
|
|
228
|
-
}): LeafInput[];
|
|
114
|
+
export { CommentAuthor }
|
|
229
115
|
|
|
230
116
|
/**
|
|
231
117
|
* Renders a comment's rich-text body read-only through the limited comment extension set (no
|
|
@@ -243,13 +129,13 @@ export declare interface CommentBodyProps {
|
|
|
243
129
|
}
|
|
244
130
|
|
|
245
131
|
/** A single comment: Avatar, Byline, and a body slot the consumer renders. @public @react */
|
|
246
|
-
export declare function CommentCard({ author, body, date, you, edited, actions }: CommentCardProps): JSX.Element;
|
|
132
|
+
export declare function CommentCard({ author, body, date, you, edited, actions, footer }: CommentCardProps): JSX.Element;
|
|
247
133
|
|
|
248
134
|
/** @public */
|
|
249
135
|
export declare interface CommentCardProps {
|
|
250
|
-
author:
|
|
251
|
-
/** The rendered comment body. The card doesn't dictate a format — pass a `<
|
|
252
|
-
* for
|
|
136
|
+
author: CommentAuthor;
|
|
137
|
+
/** The rendered comment body. The card doesn't dictate a format — pass a `<CommentBody>`
|
|
138
|
+
* for a comment's rich text, or any node of your own. */
|
|
253
139
|
body: ReactNode;
|
|
254
140
|
/** ISO datetime; formatted to relative time by the component. */
|
|
255
141
|
date: string;
|
|
@@ -258,6 +144,8 @@ export declare interface CommentCardProps {
|
|
|
258
144
|
edited?: boolean;
|
|
259
145
|
/** Hover-revealed controls at the card's top-right (e.g. an edit affordance). */
|
|
260
146
|
actions?: ReactNode;
|
|
147
|
+
/** Content under the body, aligned with it rather than the avatar (e.g. a `<Reactions>` row). */
|
|
148
|
+
footer?: ReactNode;
|
|
261
149
|
}
|
|
262
150
|
|
|
263
151
|
/**
|
|
@@ -267,11 +155,11 @@ export declare interface CommentCardProps {
|
|
|
267
155
|
* floating toolbar. Presentational by default; pass value/onChange/onSubmit to drive it as a form.
|
|
268
156
|
* @public @react
|
|
269
157
|
*/
|
|
270
|
-
export declare function CommentComposer({ author, placeholder, value, onChange, onSubmit, sendLabel, disabled, autoFocus, leading, getMentionSuggestions, renderMentionSuggestion }: CommentComposerProps): JSX.Element;
|
|
158
|
+
export declare function CommentComposer({ author, placeholder, value, onChange, onSubmit, sendLabel, onArrowUpWhenEmpty, disabled, autoFocus, leading, getMentionSuggestions, renderMentionSuggestion }: CommentComposerProps): JSX.Element;
|
|
271
159
|
|
|
272
160
|
/** @public */
|
|
273
161
|
export declare interface CommentComposerProps {
|
|
274
|
-
author:
|
|
162
|
+
author: CommentAuthor;
|
|
275
163
|
placeholder: string;
|
|
276
164
|
/** Controlled rich-text value. Omit for the presentational (display-only) composer. */
|
|
277
165
|
value?: TLRichText;
|
|
@@ -279,6 +167,9 @@ export declare interface CommentComposerProps {
|
|
|
279
167
|
/** Called on Send click or Enter. When set, the composer is interactive. */
|
|
280
168
|
onSubmit?(): void;
|
|
281
169
|
sendLabel?: string;
|
|
170
|
+
/** Called when Up is pressed in an empty composer — e.g. to start editing the comment above,
|
|
171
|
+
* the way chat apps edit your last message. With content in the field, Up moves the cursor. */
|
|
172
|
+
onArrowUpWhenEmpty?(): void;
|
|
282
173
|
disabled?: boolean;
|
|
283
174
|
autoFocus?: boolean;
|
|
284
175
|
/** The leading element before the field. Defaults to the author's avatar. */
|
|
@@ -309,12 +200,88 @@ export declare interface CommentingComponents {
|
|
|
309
200
|
ThreadPreview?: ComponentType<{
|
|
310
201
|
comment: TLComment;
|
|
311
202
|
}>;
|
|
203
|
+
/**
|
|
204
|
+
* A reaction's visual, given its token. The default renders the token string for the OS emoji
|
|
205
|
+
* font to draw (so the token is the emoji glyph). Override this to render your own palette —
|
|
206
|
+
* return an `<img>` for custom emoji, an SVG, or anything. The token is whatever your picker
|
|
207
|
+
* emits and is what gets stored/synced; this only controls how it's drawn.
|
|
208
|
+
*/
|
|
209
|
+
ReactionContent?: ComponentType<{
|
|
210
|
+
token: string;
|
|
211
|
+
}>;
|
|
212
|
+
/**
|
|
213
|
+
* What the add-reaction button opens: the thing that produces a reaction token. Replaces the
|
|
214
|
+
* default `<EmojiPicker>` grid. Pairs with `ReactionContent` (which draws whatever tokens this
|
|
215
|
+
* emits) and with `isAllowedReaction` (which has to accept them).
|
|
216
|
+
*/
|
|
217
|
+
ReactionPalette?: ComponentType<EmojiPickerProps>;
|
|
218
|
+
/**
|
|
219
|
+
* The hover affordance naming who reacted with an emoji. It receives the reactors and the pill
|
|
220
|
+
* (as `children`) and returns the whole thing — so it owns the tooltip, its box, size, shape, and
|
|
221
|
+
* position. Replaces the default (`DefaultReactionTooltip`). For a simple wording change, translate
|
|
222
|
+
* the `comments.reacted-*` strings instead; reach for this to change the structure — a different
|
|
223
|
+
* box, avatars, a banner anywhere on screen.
|
|
224
|
+
*/
|
|
225
|
+
ReactionTooltip?: ComponentType<ReactionTooltipProps>;
|
|
226
|
+
/** Shown where a composer would sit when the viewer can't compose (see
|
|
227
|
+
* {@link CommentingOptions.canComment} — a signed-out viewer, a viewer role, a host that
|
|
228
|
+
* turns commenting off). `context` says which surface is rendering it: the bottom of an open
|
|
229
|
+
* thread popover (`'thread'`) or the placement popover the comment tool opens (`'pending'`).
|
|
230
|
+
* Unset, those surfaces render nothing. */
|
|
231
|
+
ComposerFallback?: ComponentType<{
|
|
232
|
+
context: 'pending' | 'thread';
|
|
233
|
+
}>;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* The live, host-supplied half of commenting: who the viewer is, how author ids become names, read
|
|
238
|
+
* status, and the mention roster. (The static half is {@link CommentingOptions}, configured once on
|
|
239
|
+
* the tool.)
|
|
240
|
+
*
|
|
241
|
+
* Every commenting surface reads the same set, so a host mounting more than one — `CanvasComments`
|
|
242
|
+
* and `CanvasCommentsSidebar`, say — can build it once and spread it into each rather than
|
|
243
|
+
* repeating the props:
|
|
244
|
+
*
|
|
245
|
+
* ```tsx
|
|
246
|
+
* const commenting: CommentingContext = { currentUserId, resolveAuthor, isCommentUnread }
|
|
247
|
+
*
|
|
248
|
+
* <CanvasComments {...commenting} />
|
|
249
|
+
* <CanvasCommentsSidebar {...commenting} />
|
|
250
|
+
* ```
|
|
251
|
+
*
|
|
252
|
+
* @public
|
|
253
|
+
*/
|
|
254
|
+
export declare interface CommentingContext {
|
|
255
|
+
/** The signed-in user's id, or null for a read-only viewer. Only a signed-in user composes. */
|
|
256
|
+
currentUserId: null | string;
|
|
257
|
+
/** Map an author id to their display info, or `undefined` when the id can't be resolved. */
|
|
258
|
+
resolveAuthor(id: string): CommentAuthor | undefined;
|
|
259
|
+
/** Called after any comment (a new thread's first comment, or a reply) is posted. */
|
|
260
|
+
onPostComment?(comment: TLComment): void;
|
|
261
|
+
/** Whether a comment is unread for the current user (return true for unread). */
|
|
262
|
+
isCommentUnread?(commentId: TLCommentId): boolean;
|
|
263
|
+
/**
|
|
264
|
+
* Called for each unread comment shown to the user in an open thread popover, so hosts can
|
|
265
|
+
* record a read receipt. Needs `isCommentUnread` to know what's unread.
|
|
266
|
+
*/
|
|
267
|
+
onCommentRead?(commentId: TLCommentId): void;
|
|
268
|
+
/** Resolve the members matching an `@`-query in the composers (sync or async). */
|
|
269
|
+
getMentionSuggestions?(query: string): MentionMember[] | Promise<MentionMember[]>;
|
|
270
|
+
/** Override a mention-picker row's content. */
|
|
271
|
+
renderMentionSuggestion?(member: MentionMember): ReactNode;
|
|
272
|
+
/**
|
|
273
|
+
* The host's URL for a thread, so surfaces can link to it — e.g. the sidebar's rows render as
|
|
274
|
+
* anchors when this is present, letting ctrl/cmd-click and middle-click open the thread in a
|
|
275
|
+
* new tab (a plain click still selects the thread in place; the href isn't followed).
|
|
276
|
+
*/
|
|
277
|
+
getThreadHref?(threadId: TLCommentThreadId): string | undefined;
|
|
312
278
|
}
|
|
313
279
|
|
|
314
280
|
/**
|
|
315
281
|
* Configuration for the commenting layer. Static config only — pass it once via
|
|
316
282
|
* `CommentTool.configure({ ... })`, mirroring `ShapeUtil.configure`. Live, reactive values
|
|
317
|
-
* (`currentUserId`,
|
|
283
|
+
* (`currentUserId`, author resolution, read-status callbacks) are the `CommentingContext`, passed as
|
|
284
|
+
* props to each commenting surface.
|
|
318
285
|
*
|
|
319
286
|
* For defaults, see {@link defaultCommentingOptions}.
|
|
320
287
|
*
|
|
@@ -341,15 +308,60 @@ export declare interface CommentingOptions {
|
|
|
341
308
|
readonly dragHistory: TLHistoryBatchOptions['history'] | undefined;
|
|
342
309
|
/** Fold nearby pins into count badges as the camera zooms out. */
|
|
343
310
|
readonly enableClustering: boolean;
|
|
311
|
+
/**
|
|
312
|
+
* Whether a user may hold several emoji reactions on one comment. `true` (the default) is the
|
|
313
|
+
* Slack model: each emoji toggles independently. `false` is single-select: picking a new emoji
|
|
314
|
+
* replaces the user's existing reaction. Note this is enforced client-side; the server accepts
|
|
315
|
+
* per-emoji records either way.
|
|
316
|
+
*/
|
|
317
|
+
readonly allowMultipleReactions: boolean;
|
|
318
|
+
/**
|
|
319
|
+
* Whether a token may be added as a reaction. Defaults to {@link isAllowedReactionEmoji} against
|
|
320
|
+
* the built-in emoji palette, which is what keeps a scripted client from writing junk `emoji`
|
|
321
|
+
* values the picker would never offer. Override it alongside a custom `ReactionPalette` so the
|
|
322
|
+
* tokens that palette emits get through. Removals aren't checked — a reaction carrying an
|
|
323
|
+
* off-palette token must still be clearable.
|
|
324
|
+
*/
|
|
325
|
+
isAllowedReaction(token: string): boolean;
|
|
326
|
+
/**
|
|
327
|
+
* Whether dragging the comment tool out creates a region anchor — a comment attached to a
|
|
328
|
+
* rectangular area of the page, drawn as a dashed box with the thread's pin on the corner the
|
|
329
|
+
* drag released on. Off by default: comments attach to points and shapes only, and a drag just
|
|
330
|
+
* trails the composer. A region reveals its box while the pointer is inside it, moves by its
|
|
331
|
+
* pin, and resizes from its corners.
|
|
332
|
+
*/
|
|
333
|
+
readonly enableRegions: boolean;
|
|
334
|
+
/**
|
|
335
|
+
* Whether the viewer may participate in commenting: composing new threads and replies, editing
|
|
336
|
+
* and deleting comments, resolving threads, and moving pins or regions. Composers render when
|
|
337
|
+
* it returns true; when it returns false, the {@link CommentingComponents.ComposerFallback}
|
|
338
|
+
* slot renders in their place (or nothing, if that slot is unset) and the action affordances
|
|
339
|
+
* are hidden. Unset, participation is allowed exactly when `currentUserId` is set.
|
|
340
|
+
*
|
|
341
|
+
* Called during render via {@link useCanComment}, so reactive reads (signals) are tracked.
|
|
342
|
+
* The comment tool itself stays registered and selectable — hosts that want its toolbar button
|
|
343
|
+
* to do something else (e.g. open a sign-in dialog) can override the tool item's `onSelect`.
|
|
344
|
+
* Note posting still requires a `currentUserId` to author the records, so a callback that
|
|
345
|
+
* returns true for a signed-out viewer yields a composer whose send button stays disabled.
|
|
346
|
+
*/
|
|
347
|
+
readonly canComment: ((ctx: {
|
|
348
|
+
currentUserId: null | string;
|
|
349
|
+
editor: Editor;
|
|
350
|
+
}) => boolean) | undefined;
|
|
344
351
|
/** Normalized (0–1) spot within a shape where imprecise shape pins sit. Default top-right. */
|
|
345
352
|
readonly impreciseShapeAnchor: {
|
|
346
353
|
readonly x: number;
|
|
347
354
|
readonly y: number;
|
|
348
355
|
};
|
|
349
|
-
/**
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
356
|
+
/**
|
|
357
|
+
* Whether a comment landing on a shape anchors precisely — pinned to the exact clicked spot
|
|
358
|
+
* within the shape — or imprecisely — pinned to the shape as a whole, rendered at
|
|
359
|
+
* `impreciseShapeAnchor`. Called wherever a shape anchor is created (placing with the comment
|
|
360
|
+
* tool, dropping a dragged pin onto a shape). Always precise by default. Return `false` for
|
|
361
|
+
* shape-level anchoring, or decide from the context — the Alt key's state, or the shape itself,
|
|
362
|
+
* e.g. precise only on notes. Governs new placements only; existing anchors render as stored.
|
|
363
|
+
*/
|
|
364
|
+
shouldBePrecise(editor: Editor, context: ShapeCommentPrecisionContext): boolean;
|
|
353
365
|
/** Component overrides. See {@link CommentingComponents}. */
|
|
354
366
|
readonly components: CommentingComponents;
|
|
355
367
|
}
|
|
@@ -357,7 +369,7 @@ export declare interface CommentingOptions {
|
|
|
357
369
|
/** @public */
|
|
358
370
|
export declare interface CommentListItemProps {
|
|
359
371
|
id: string;
|
|
360
|
-
author:
|
|
372
|
+
author: CommentAuthor;
|
|
361
373
|
/** A short preview of the thread — e.g. the first comment's body. */
|
|
362
374
|
preview: ReactNode;
|
|
363
375
|
/** ISO datetime of the thread's first comment. */
|
|
@@ -369,6 +381,11 @@ export declare interface CommentListItemProps {
|
|
|
369
381
|
count?: number;
|
|
370
382
|
/** Whether this thread is the open one. */
|
|
371
383
|
selected?: boolean;
|
|
384
|
+
/**
|
|
385
|
+
* Link target for the item. When set, the row renders as an anchor so browser affordances
|
|
386
|
+
* (ctrl/cmd-click, middle-click) open it in a new tab; a plain click still calls `onSelect`.
|
|
387
|
+
*/
|
|
388
|
+
href?: string;
|
|
372
389
|
}
|
|
373
390
|
|
|
374
391
|
/** A canvas comment marker: shows its `children` (or a check when resolved). Purely
|
|
@@ -386,6 +403,40 @@ export declare interface CommentPinProps {
|
|
|
386
403
|
open?: boolean;
|
|
387
404
|
}
|
|
388
405
|
|
|
406
|
+
/**
|
|
407
|
+
* The add-reaction button for one comment. Belongs with the comment card's hover actions (under
|
|
408
|
+
* the ⋯ button) rather than in the reaction row, so opening it doesn't chase the row as reactions
|
|
409
|
+
* are added.
|
|
410
|
+
* @public @react
|
|
411
|
+
*/
|
|
412
|
+
export declare function CommentReactionPicker({ comment, currentUserId, emoji }: CommentReactionPickerProps): JSX.Element | null;
|
|
413
|
+
|
|
414
|
+
/** @public */
|
|
415
|
+
export declare interface CommentReactionPickerProps {
|
|
416
|
+
comment: TLComment;
|
|
417
|
+
/** The reacting user. Null/omitted renders nothing — there's nobody to react as. */
|
|
418
|
+
currentUserId?: null | string;
|
|
419
|
+
/** The emoji the picker offers. Defaults to `DEFAULT_REACTION_EMOJI`. */
|
|
420
|
+
emoji?: string[];
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* The tallied reaction row under one comment. Pair with `CommentReactionPicker`, which is what
|
|
425
|
+
* adds a reaction.
|
|
426
|
+
* @public @react
|
|
427
|
+
*/
|
|
428
|
+
export declare function CommentReactions({ comment, currentUserId, resolveName }: CommentReactionsProps): JSX.Element;
|
|
429
|
+
|
|
430
|
+
/** @public */
|
|
431
|
+
export declare interface CommentReactionsProps {
|
|
432
|
+
comment: TLComment;
|
|
433
|
+
/** The reacting user. Null/omitted gives a read-only row (signed out): counts show, but the
|
|
434
|
+
* pills don't toggle. */
|
|
435
|
+
currentUserId?: null | string;
|
|
436
|
+
/** Names a reactor id for the hover list. Ids it can't name fall back to the id. */
|
|
437
|
+
resolveName?(userId: string): string | undefined;
|
|
438
|
+
}
|
|
439
|
+
|
|
389
440
|
/** The funnel dropdown in the sidebar header: toggles for which threads the list shows.
|
|
390
441
|
* @public @react */
|
|
391
442
|
export declare function CommentsFilterMenu({ canFilterByAuthor, canFilterByUnread }: CommentsFilterMenuProps): JSX.Element;
|
|
@@ -444,14 +495,19 @@ export declare function CommentsMenuItem(): JSX.Element;
|
|
|
444
495
|
* @public @react */
|
|
445
496
|
export declare function CommentsOverflowMenu(): JSX.Element;
|
|
446
497
|
|
|
447
|
-
/**
|
|
448
|
-
|
|
498
|
+
/**
|
|
499
|
+
* Whether the comments sidebar (the thread list) is open. Driven by an explicit control — a button
|
|
500
|
+
* next to Share on dotcom — rather than by which tool is active, so browsing threads is separate
|
|
501
|
+
* from placing them. The comment tool additionally closes it on enter, keeping placement
|
|
502
|
+
* canvas-focused.
|
|
503
|
+
* @public
|
|
504
|
+
*/
|
|
505
|
+
export declare const commentsSidebarOpen: EditorAtom<boolean>;
|
|
449
506
|
|
|
450
|
-
/**
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
}
|
|
507
|
+
/** The sidebar header's show/hide toggle for comment pins — an eye that closes while comments
|
|
508
|
+
* are hidden. The same state as the Shift+C shortcut.
|
|
509
|
+
* @public @react */
|
|
510
|
+
export declare function CommentsVisibilityToggle(): JSX.Element;
|
|
455
511
|
|
|
456
512
|
/**
|
|
457
513
|
* A comment thread: an optional header, an optional resolved banner, the comments, and an
|
|
@@ -459,7 +515,7 @@ export declare interface CommentTextProps {
|
|
|
459
515
|
* composer's handlers; how each comment renders is overridable via `renderComment`.
|
|
460
516
|
* @public @react
|
|
461
517
|
*/
|
|
462
|
-
export declare function CommentThread({ comments, header, headerActions, resolvedBanner, composer, renderComment }: CommentThreadProps): JSX.Element;
|
|
518
|
+
export declare function CommentThread({ comments, header, headerActions, resolvedBanner, composer, footer, renderComment }: CommentThreadProps): JSX.Element;
|
|
463
519
|
|
|
464
520
|
/** @public */
|
|
465
521
|
export declare interface CommentThreadProps {
|
|
@@ -473,14 +529,19 @@ export declare interface CommentThreadProps {
|
|
|
473
529
|
resolvedBanner?: ReactNode;
|
|
474
530
|
/** Reply composer props. Omit for a read-only thread (no composer). */
|
|
475
531
|
composer?: CommentComposerProps;
|
|
532
|
+
/** Shown at the bottom of the thread (e.g. a sign-in prompt when there's no composer). When
|
|
533
|
+
* both are set, the footer renders after the composer. */
|
|
534
|
+
footer?: ReactNode;
|
|
476
535
|
/** Override how each comment renders. Defaults to `<CommentCard>`. */
|
|
477
536
|
renderComment?(comment: CommentCardProps, index: number): ReactNode;
|
|
478
537
|
}
|
|
479
538
|
|
|
480
539
|
/**
|
|
481
|
-
* The comment tool.
|
|
482
|
-
*
|
|
483
|
-
*
|
|
540
|
+
* The comment tool. Pressing down opens the comment composer immediately at the pointer, and it
|
|
541
|
+
* follows the pointer until release — like placing a sticky note — settling on a point, or on a
|
|
542
|
+
* shape when released over one. (With region comments enabled, dragging past the threshold instead
|
|
543
|
+
* draws a region rectangle.) Placement only opens a composer (via `pendingComment`); the records
|
|
544
|
+
* are created when the comment is posted.
|
|
484
545
|
* @public
|
|
485
546
|
*/
|
|
486
547
|
export declare class CommentTool extends StateNode {
|
|
@@ -506,6 +567,7 @@ export declare class CommentTool extends StateNode {
|
|
|
506
567
|
*/
|
|
507
568
|
options: CommentingOptions;
|
|
508
569
|
onEnter(): void;
|
|
570
|
+
onExit(): void;
|
|
509
571
|
onCancel(): void;
|
|
510
572
|
}
|
|
511
573
|
|
|
@@ -517,50 +579,32 @@ export declare const commentToolOverrides: TLUiOverrides;
|
|
|
517
579
|
/** @public */
|
|
518
580
|
export declare const commentTools: typeof CommentTool[];
|
|
519
581
|
|
|
520
|
-
/**
|
|
521
|
-
* Commit a comment mutation with the configured undo/redo behavior. All comment writes go through
|
|
522
|
-
* here so the {@link CommentingOptions.history} option (and {@link CommentingOptions.dragHistory}
|
|
523
|
-
* for pin re-anchors) governs whether they land on the undo stack. Defaults to `'ignore'`.
|
|
524
|
-
* @public
|
|
525
|
-
*/
|
|
526
|
-
export declare function commitCommentMutation<T>(editor: Editor, fn: () => T, kind?: 'drag' | 'mutation'): T;
|
|
527
|
-
|
|
528
|
-
/** @public */
|
|
529
|
-
export declare function computeClusterTable(leaves: readonly LeafInput[], options: ClusterOptions): ClusterTable;
|
|
530
|
-
|
|
531
582
|
/** @public @react */
|
|
532
|
-
export declare function CountBadge({ count }: CountBadgeProps): JSX.Element;
|
|
583
|
+
export declare function CountBadge({ count, open }: CountBadgeProps): JSX.Element;
|
|
533
584
|
|
|
534
585
|
/** @public */
|
|
535
586
|
export declare interface CountBadgeProps {
|
|
536
587
|
count: number;
|
|
588
|
+
/** The badge's list is showing — shows the active/selected indicator state, as an open pin does. */
|
|
589
|
+
open?: boolean;
|
|
537
590
|
}
|
|
538
591
|
|
|
539
|
-
|
|
540
|
-
export declare function createClusterRuntime(table: ClusterTable): ClusterRuntime;
|
|
592
|
+
export { createMentionSuggestion }
|
|
541
593
|
|
|
542
594
|
/**
|
|
543
|
-
*
|
|
544
|
-
*
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
*
|
|
595
|
+
* The reaction emoji palette: the small, opinionated set the picker offers *and* the set a
|
|
596
|
+
* reaction is allowed to use. It's deliberately short — a quick affordance under a comment, not a
|
|
597
|
+
* full emoji keyboard — and it's the single source of truth for "which emoji may a reaction
|
|
598
|
+
* carry". A reaction's `emoji` field is a free-form `string`, so this palette is what keeps it to
|
|
599
|
+
* real, offered emoji; check membership with {@link isAllowedReactionEmoji}. Pass a custom `emoji`
|
|
600
|
+
* array to `ReactionPicker` to offer a different set — validate against that same set if you do.
|
|
601
|
+
*
|
|
548
602
|
* @public
|
|
549
603
|
*/
|
|
550
|
-
export declare
|
|
604
|
+
export declare const DEFAULT_REACTION_EMOJI: string[];
|
|
551
605
|
|
|
552
|
-
/**
|
|
553
|
-
export declare const DEFAULT_IMPRECISE_SHAPE_ANCHOR: {
|
|
554
|
-
x: number;
|
|
555
|
-
y: number;
|
|
556
|
-
};
|
|
557
|
-
|
|
558
|
-
/** The out-of-the-box region config: disabled, and — when a consumer enables it — the current
|
|
559
|
-
* bottom-right / pointer-reveal / pin-move / corner-resize behaviour.
|
|
606
|
+
/** The out-of-the-box view: every page's threads, resolved ones hidden until asked for.
|
|
560
607
|
* @public */
|
|
561
|
-
export declare const DEFAULT_REGION_COMMENT_OPTIONS: RegionCommentOptions;
|
|
562
|
-
|
|
563
|
-
/** @public */
|
|
564
608
|
export declare const DEFAULT_SIDEBAR_FILTERS: SidebarFilters;
|
|
565
609
|
|
|
566
610
|
/**
|
|
@@ -569,18 +613,120 @@ export declare const DEFAULT_SIDEBAR_FILTERS: SidebarFilters;
|
|
|
569
613
|
* @public
|
|
570
614
|
*/
|
|
571
615
|
export declare const defaultCommentingOptions: {
|
|
572
|
-
readonly
|
|
573
|
-
readonly
|
|
616
|
+
readonly allowMultipleReactions: true;
|
|
617
|
+
readonly canComment: undefined;
|
|
574
618
|
readonly components: {};
|
|
575
619
|
readonly dragHistory: undefined;
|
|
576
620
|
readonly enableClustering: true;
|
|
621
|
+
readonly enableRegions: false;
|
|
577
622
|
readonly history: "ignore";
|
|
578
623
|
readonly impreciseShapeAnchor: {
|
|
579
624
|
readonly x: 1;
|
|
580
625
|
readonly y: 0;
|
|
581
626
|
};
|
|
627
|
+
readonly isAllowedReaction: typeof isAllowedReactionEmoji;
|
|
628
|
+
readonly shouldBePrecise: () => true;
|
|
582
629
|
};
|
|
583
630
|
|
|
631
|
+
/**
|
|
632
|
+
* The default reactor tooltip: hangs the built-in inline sentence (`DefaultReactionTooltipContent`)
|
|
633
|
+
* in a standard tooltip below the pill — the same tooltip the toolbar uses. Replace it via
|
|
634
|
+
* `CommentingComponents.ReactionTooltip` to present the reactor list any other way (a different box,
|
|
635
|
+
* avatars, a banner, anywhere on screen); it receives the pill as `children`.
|
|
636
|
+
* @public @react
|
|
637
|
+
*/
|
|
638
|
+
export declare function DefaultReactionTooltip({ reactors, children }: ReactionTooltipProps): JSX.Element;
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* The default reactor sentence naming who reacted — up to three names spelled out, then "and N
|
|
642
|
+
* others" (e.g. "You reacted", "You and Bo reacted", "You, Bo and Ada reacted", "You, Bo, Ada and 2
|
|
643
|
+
* others reacted"). The wording lives in the `comments.reacted-*` translation strings so each locale
|
|
644
|
+
* controls the grammar. Exported so a custom `ReactionTooltip` can reuse it inside its own box.
|
|
645
|
+
* @public @react
|
|
646
|
+
*/
|
|
647
|
+
export declare function DefaultReactionTooltipContent({ reactors }: {
|
|
648
|
+
reactors: ReactionReactor[];
|
|
649
|
+
}): JSX.Element | null;
|
|
650
|
+
|
|
651
|
+
/** The default reaction renderer: emits the token string for the OS emoji font to draw. @public */
|
|
652
|
+
export declare function defaultRenderReaction(token: string): ReactNode;
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Delete a comment.
|
|
656
|
+
*
|
|
657
|
+
* This is a soft delete: it sets the record's `isDeleted` flag rather than removing it, and the
|
|
658
|
+
* server prunes the comment and its reactions once the flag is persisted. That way no client ever
|
|
659
|
+
* removes records it doesn't own — a reaction belongs to whoever left it — and a server enforcing
|
|
660
|
+
* per-record permissions has a write it can check rather than a deletion it can only refuse.
|
|
661
|
+
* Deleting is the author's to do; the built-in UI only offers it on your own comments.
|
|
662
|
+
*
|
|
663
|
+
* The write is never undoable, whatever {@link CommentingOptions.history} says: the flag is
|
|
664
|
+
* write-once server-side, so an undo clearing it would be vetoed and rebased rather than bring the
|
|
665
|
+
* comment back.
|
|
666
|
+
*
|
|
667
|
+
* Deleting a thread's last comment leaves the thread with no surface — an empty thread renders
|
|
668
|
+
* nothing — and closes it if it's open. The thread record is left for the server to prune, since
|
|
669
|
+
* the deleter may not be its creator.
|
|
670
|
+
*
|
|
671
|
+
* A comment that's already deleted, or already pruned, is a no-op.
|
|
672
|
+
*
|
|
673
|
+
* @public
|
|
674
|
+
*/
|
|
675
|
+
export declare function deleteComment(editor: Editor, comment: TLComment): void;
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Delete a thread and, with it, the whole conversation.
|
|
679
|
+
*
|
|
680
|
+
* A soft delete on the same model as {@link deleteComment}: the flag goes on the thread record and
|
|
681
|
+
* the server prunes the thread, its comments, and their reactions once it's persisted. Deleting a
|
|
682
|
+
* thread is its creator's to do — a server enforcing per-record permissions vetoes anyone else —
|
|
683
|
+
* and the write is never undoable.
|
|
684
|
+
*
|
|
685
|
+
* Closes the thread if it's the open one. A thread that's already pruned is a no-op.
|
|
686
|
+
*
|
|
687
|
+
* @public
|
|
688
|
+
*/
|
|
689
|
+
export declare function deleteThread(editor: Editor, thread: TLCommentThread): void;
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Replace a comment's body and stamp it as edited, which is what renders the "(edited)" marker on
|
|
693
|
+
* its byline.
|
|
694
|
+
*
|
|
695
|
+
* Editing is the author's to do. The built-in UI only offers it on your own comments, and a server
|
|
696
|
+
* that enforces per-record permissions rejects anyone else's edit.
|
|
697
|
+
*
|
|
698
|
+
* The `comment` you pass says which comment to edit; the body lands on the version the store
|
|
699
|
+
* currently holds, so a copy you've held on to can't revert a change made since it, and can't
|
|
700
|
+
* re-create a comment that's already been removed — editing one of those does nothing.
|
|
701
|
+
*
|
|
702
|
+
* @example
|
|
703
|
+
* ```ts
|
|
704
|
+
* editComment(editor, comment, toRichText('Actually, make it dashed'))
|
|
705
|
+
* ```
|
|
706
|
+
*
|
|
707
|
+
* @public
|
|
708
|
+
*/
|
|
709
|
+
export declare function editComment(editor: Editor, comment: TLComment, body: TLRichText): void;
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* A grid of emoji to react with. Presentational and unpositioned — the host owns placement and
|
|
713
|
+
* dismissal; `ReactionPicker` renders it in a dropdown under the add-reaction button.
|
|
714
|
+
* @public @react
|
|
715
|
+
*/
|
|
716
|
+
export declare function EmojiPicker({ emoji, selected, onSelect, renderReaction }: EmojiPickerProps): JSX.Element;
|
|
717
|
+
|
|
718
|
+
/** @public */
|
|
719
|
+
export declare interface EmojiPickerProps {
|
|
720
|
+
/** The emoji to offer. Defaults to `DEFAULT_REACTION_EMOJI`. */
|
|
721
|
+
emoji?: string[];
|
|
722
|
+
/** Emoji the current user has already reacted with; shown as pressed. */
|
|
723
|
+
selected?: string[];
|
|
724
|
+
/** Called when an emoji is chosen. */
|
|
725
|
+
onSelect?(emoji: string): void;
|
|
726
|
+
/** How to draw each emoji token. Defaults to the token string (OS emoji font). */
|
|
727
|
+
renderReaction?: RenderReaction;
|
|
728
|
+
}
|
|
729
|
+
|
|
584
730
|
/** The empty state shown when a thread has no comments yet. @public @react */
|
|
585
731
|
export declare function EmptyState({ message }: EmptyStateProps): JSX.Element;
|
|
586
732
|
|
|
@@ -589,23 +735,30 @@ export declare interface EmptyStateProps {
|
|
|
589
735
|
message: string;
|
|
590
736
|
}
|
|
591
737
|
|
|
592
|
-
|
|
593
|
-
* @public */
|
|
594
|
-
export declare function filterMentionMembers(members: MentionMember[], query: string): MentionMember[];
|
|
738
|
+
export { filterMentionMembers }
|
|
595
739
|
|
|
596
740
|
/** Open a thread and bring it into view — switch to its page if needed, then center its pin. @public */
|
|
597
|
-
export declare function focusThread(editor: Editor, thread: TLCommentThread
|
|
598
|
-
x: number;
|
|
599
|
-
y: number;
|
|
600
|
-
}): void;
|
|
741
|
+
export declare function focusThread(editor: Editor, thread: TLCommentThread): void;
|
|
601
742
|
|
|
602
743
|
/**
|
|
603
|
-
* Format an ISO datetime as relative time ("2
|
|
744
|
+
* Format an ISO datetime as short relative time ("2 hr. ago", "yesterday", "last wk.").
|
|
604
745
|
* Locale-aware via Intl.RelativeTimeFormat.
|
|
605
746
|
* @public
|
|
606
747
|
*/
|
|
607
748
|
export declare function formatRelativeTime(iso: string, locale?: string): string;
|
|
608
749
|
|
|
750
|
+
/**
|
|
751
|
+
* Whether the viewer may participate in commenting, per {@link CommentingOptions.canComment}
|
|
752
|
+
* (defaulting to `currentUserId != null` when unset). Where this is false, composers give way to
|
|
753
|
+
* the {@link CommentingComponents.ComposerFallback} slot and action affordances are hidden.
|
|
754
|
+
*
|
|
755
|
+
* This is a plain, untracked read — a `canComment` callback that reads signals is not observed.
|
|
756
|
+
* In React, use {@link useCanComment} instead.
|
|
757
|
+
*
|
|
758
|
+
* @public
|
|
759
|
+
*/
|
|
760
|
+
export declare function getCanComment(editor: Editor, currentUserId: null | string | undefined): boolean;
|
|
761
|
+
|
|
609
762
|
/**
|
|
610
763
|
* The merged {@link CommentingOptions} for an editor, read off the registered comment tool (which
|
|
611
764
|
* carries them via `CommentTool.configure`). Falls back to {@link defaultCommentingOptions} when
|
|
@@ -616,161 +769,328 @@ export declare function formatRelativeTime(iso: string, locale?: string): string
|
|
|
616
769
|
*/
|
|
617
770
|
export declare function getCommentingOptions(editor: Editor): CommentingOptions;
|
|
618
771
|
|
|
772
|
+
/** All comment reactions currently in the store (non-reactive; wrap in `useValue` to react). @public */
|
|
773
|
+
export declare function getCommentReactions(editor: Editor): TLCommentReaction[];
|
|
774
|
+
|
|
619
775
|
/** Read one comment record by id, or `undefined` if the id isn't a present comment record. @public */
|
|
620
776
|
export declare function getCommentRecord(editor: Editor, id: string): TLCommentRecord | undefined;
|
|
621
777
|
|
|
622
|
-
/**
|
|
778
|
+
/**
|
|
779
|
+
* Every comment in the store, **including soft-deleted ones** awaiting the server's prune. For the
|
|
780
|
+
* set the UI shows, use {@link getLiveComments}.
|
|
781
|
+
*
|
|
782
|
+
* Non-reactive; wrap in `useValue`, or use `useComments`, to react.
|
|
783
|
+
* @public
|
|
784
|
+
*/
|
|
623
785
|
export declare function getComments(editor: Editor): TLComment[];
|
|
624
786
|
|
|
625
|
-
/**
|
|
787
|
+
/**
|
|
788
|
+
* Every comment thread in the store, **including soft-deleted ones** and ones left empty by their
|
|
789
|
+
* last comment's delete — records that are still present but awaiting the server's prune, and that
|
|
790
|
+
* nothing renders. For the set the UI shows, use {@link getLiveCommentThreads}.
|
|
791
|
+
*
|
|
792
|
+
* Non-reactive; wrap in `useValue`, or use `useCommentThreads`, to react.
|
|
793
|
+
* @public
|
|
794
|
+
*/
|
|
626
795
|
export declare function getCommentThreads(editor: Editor): TLCommentThread[];
|
|
627
796
|
|
|
628
797
|
/**
|
|
629
|
-
*
|
|
798
|
+
* The comments that should render: not soft-deleted. A deleted record lingers in the store until
|
|
799
|
+
* the server prunes it, so this — not {@link getComments} — is what a count or a list of your own
|
|
800
|
+
* should be built from.
|
|
801
|
+
*
|
|
802
|
+
* Non-reactive; the reactive equivalent is `useComments` (which also sorts oldest first).
|
|
630
803
|
* @public
|
|
631
804
|
*/
|
|
632
|
-
export declare
|
|
633
|
-
/** Unique. Thread id. Uniqueness is a precondition — throw on duplicates. */
|
|
634
|
-
id: string;
|
|
635
|
-
/** Page-space coordinates. Must be finite — throw on NaN/Infinity. */
|
|
636
|
-
point: VecLike;
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
/** An \@-mention pill for referencing a person in a comment. @public @react */
|
|
640
|
-
export declare function Mention({ name }: MentionProps): JSX.Element;
|
|
805
|
+
export declare function getLiveComments(editor: Editor): TLComment[];
|
|
641
806
|
|
|
642
807
|
/**
|
|
643
|
-
* The
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
*
|
|
808
|
+
* The comment threads that should render (pins, sidebar): live — not soft-deleted — and still
|
|
809
|
+
* holding at least one live comment. A soft-deleted thread or comment is awaiting the server's
|
|
810
|
+
* prune, as is a thread emptied by its last comment's delete; until the prune lands, the emptied
|
|
811
|
+
* thread record lingers with no surface.
|
|
812
|
+
*
|
|
813
|
+
* Non-reactive; the reactive equivalent is `useCommentThreads`.
|
|
814
|
+
* @public
|
|
647
815
|
*/
|
|
648
|
-
export declare function
|
|
649
|
-
|
|
650
|
-
/** @public */
|
|
651
|
-
export declare interface MentionListProps {
|
|
652
|
-
/** Members to choose from — already resolved for the current query by the host. */
|
|
653
|
-
members: MentionMember[];
|
|
654
|
-
/** Index of the highlighted row, driven by the composer's keyboard navigation. */
|
|
655
|
-
activeIndex?: number;
|
|
656
|
-
/** Called when a member is chosen (click, or Enter on the active row). */
|
|
657
|
-
onSelect?(member: MentionMember): void;
|
|
658
|
-
/** Shown when no member matches the query. Defaults to a translated "No matches". */
|
|
659
|
-
emptyLabel?: string;
|
|
660
|
-
/** Override a row's content (inside the selectable button). Defaults to avatar + name (+ secondary). */
|
|
661
|
-
renderMember?(member: MentionMember): ReactNode;
|
|
662
|
-
}
|
|
816
|
+
export declare function getLiveCommentThreads(editor: Editor): TLCommentThread[];
|
|
663
817
|
|
|
664
|
-
/**
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
/** Hosts may carry extra fields; a custom `renderMember` can read them. */
|
|
677
|
-
[key: string]: unknown;
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
/** @public */
|
|
681
|
-
export declare interface MentionProps {
|
|
682
|
-
name: string;
|
|
683
|
-
}
|
|
818
|
+
/**
|
|
819
|
+
* The id passed to the most recent {@link revealThread} call that `CanvasComments` hasn't served
|
|
820
|
+
* yet, or null when there's nothing outstanding. A request also clears when `CanvasComments`
|
|
821
|
+
* unmounts, since nothing is left to serve it.
|
|
822
|
+
*
|
|
823
|
+
* This is a plain, untracked read. In React, use {@link useRevealThreadPending} — but reach for
|
|
824
|
+
* this one inside a timer or callback that needs the value as of *now* rather than as of the
|
|
825
|
+
* render it closed over.
|
|
826
|
+
*
|
|
827
|
+
* @public
|
|
828
|
+
*/
|
|
829
|
+
export declare function getRevealThreadPending(editor: Editor): null | string;
|
|
684
830
|
|
|
685
|
-
/**
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
}
|
|
831
|
+
/**
|
|
832
|
+
* Whether `emoji` belongs to a reaction palette (defaults to {@link DEFAULT_REACTION_EMOJI}). Use
|
|
833
|
+
* it to reject arbitrary strings before writing a reaction, so a scripted client can't spam a
|
|
834
|
+
* comment with junk `emoji` values that the picker would never offer. Pass a custom `palette` to
|
|
835
|
+
* match a customized picker.
|
|
836
|
+
*
|
|
837
|
+
* @public
|
|
838
|
+
*/
|
|
839
|
+
export declare function isAllowedReactionEmoji(emoji: string, palette?: readonly string[]): boolean;
|
|
695
840
|
|
|
696
841
|
/**
|
|
697
|
-
*
|
|
842
|
+
* Whether a click should be left to the browser's link handling (new tab, new window, or download).
|
|
698
843
|
* @public
|
|
699
844
|
*/
|
|
700
|
-
export declare
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
}
|
|
845
|
+
export declare function isOpenInNewTabClick(e: MouseEvent_2): boolean;
|
|
846
|
+
|
|
847
|
+
export { Mention }
|
|
848
|
+
|
|
849
|
+
export { MentionList }
|
|
850
|
+
|
|
851
|
+
export { MentionListProps }
|
|
852
|
+
|
|
853
|
+
export { MentionMember }
|
|
854
|
+
|
|
855
|
+
export { MentionProps }
|
|
856
|
+
|
|
857
|
+
export { MentionSuggestionOptions }
|
|
707
858
|
|
|
708
859
|
/** The id of the one open thread (only one popover is open at a time), or null when all closed.
|
|
709
860
|
* @public */
|
|
710
861
|
export declare const openThreadId: EditorAtom<null | string>;
|
|
711
862
|
|
|
712
|
-
/**
|
|
713
|
-
*
|
|
714
|
-
*
|
|
715
|
-
*
|
|
716
|
-
*
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
863
|
+
/**
|
|
864
|
+
* Write comment records to the store, under the configured
|
|
865
|
+
* {@link CommentingOptions.history} behavior — so a record you write lands on the undo stack (or
|
|
866
|
+
* doesn't) exactly like one the built-in UI writes. Defaults to `'ignore'`.
|
|
867
|
+
*
|
|
868
|
+
* Use it to seed or import threads, and to save an edit. To delete, prefer
|
|
869
|
+
* {@link deleteComment} and {@link deleteThread} over {@link removeCommentRecords}: comments are
|
|
870
|
+
* soft-deleted, and a synced server rejects the hard delete.
|
|
871
|
+
*
|
|
872
|
+
* @public
|
|
873
|
+
*/
|
|
874
|
+
export declare function putCommentRecords(editor: Editor, records: TLCommentRecord[]): void;
|
|
722
875
|
|
|
723
|
-
/**
|
|
724
|
-
*
|
|
725
|
-
|
|
876
|
+
/**
|
|
877
|
+
* A single emoji reaction pill with a count, highlighted when the user reacted. Hovering it shows a
|
|
878
|
+
* tooltip naming who reacted (the current user included), when `enableHoverList` is set.
|
|
879
|
+
* @public @react
|
|
880
|
+
*/
|
|
881
|
+
export declare function Reaction({ emoji, count, active, reactors, enableHoverList, renderReaction, ReactionTooltip, onClick }: ReactionProps): JSX.Element;
|
|
726
882
|
|
|
727
|
-
/**
|
|
728
|
-
|
|
883
|
+
/**
|
|
884
|
+
* The add-reaction affordance: a smiley button that opens an emoji grid.
|
|
885
|
+
*
|
|
886
|
+
* Anchored to its own button rather than to the reactions row, so the menu keeps its position as
|
|
887
|
+
* reactions are added and the row reflows.
|
|
888
|
+
*
|
|
889
|
+
* Picking an emoji dismisses the grid — adding and removing alike, since either way the picker has
|
|
890
|
+
* done its job — and hands focus back to the trigger.
|
|
891
|
+
* @public @react
|
|
892
|
+
*/
|
|
893
|
+
export declare function ReactionPicker({ emoji, selected, onSelect, renderReaction, palette: Palette, menuId, className }: ReactionPickerProps): JSX.Element;
|
|
729
894
|
|
|
730
|
-
/**
|
|
731
|
-
export declare
|
|
895
|
+
/** @public */
|
|
896
|
+
export declare interface ReactionPickerProps {
|
|
897
|
+
/** The emoji to offer. Defaults to `DEFAULT_REACTION_EMOJI`. */
|
|
898
|
+
emoji?: string[];
|
|
899
|
+
/** Emoji the current user has already reacted with; shown as pressed in the grid. */
|
|
900
|
+
selected?: string[];
|
|
901
|
+
/** Called when an emoji is chosen. */
|
|
902
|
+
onSelect?(emoji: string): void;
|
|
903
|
+
/** How to draw each emoji token. Defaults to the token string (OS emoji font). */
|
|
904
|
+
renderReaction?: RenderReaction;
|
|
905
|
+
/**
|
|
906
|
+
* What the button opens — the thing that produces a token. Defaults to `EmojiPicker`, the grid of
|
|
907
|
+
* emoji. Swap it for any component taking the same props to offer something else entirely (the
|
|
908
|
+
* drawn reactions example replaces it with a canvas you draw in); the props are passed straight
|
|
909
|
+
* through either way.
|
|
910
|
+
*/
|
|
911
|
+
palette?: ComponentType<EmojiPickerProps>;
|
|
912
|
+
/**
|
|
913
|
+
* Identifies the menu in tldraw's global menu registry, which keys open/closed state by id.
|
|
914
|
+
* A thread renders one picker per comment, so this must differ per comment — sharing an id
|
|
915
|
+
* makes every picker in the thread open at once. Defaults to a per-instance generated id;
|
|
916
|
+
* pass one only for a stabler, more debuggable value.
|
|
917
|
+
*/
|
|
918
|
+
menuId?: string;
|
|
919
|
+
/** Class for the trigger button. Defaults to the card-action style, matching the ⋯ button. */
|
|
920
|
+
className?: string;
|
|
921
|
+
}
|
|
732
922
|
|
|
733
923
|
/** @public */
|
|
734
924
|
export declare interface ReactionProps {
|
|
735
925
|
emoji: string;
|
|
736
926
|
count: number;
|
|
737
927
|
active: boolean;
|
|
928
|
+
/** How to draw the emoji token. Defaults to the token string (OS emoji font). */
|
|
929
|
+
renderReaction?: RenderReaction;
|
|
930
|
+
/** Who reacted with this emoji, in reaction order — shown when the pill is hovered. */
|
|
931
|
+
reactors: ReactionReactor[];
|
|
932
|
+
/** Whether hovering shows the reactor list. Pass false to suppress it — e.g. while another
|
|
933
|
+
* popup menu on the comment is open. Defaults to true. */
|
|
934
|
+
enableHoverList?: boolean;
|
|
935
|
+
/** The hover affordance for the pill, naming who reacted. It receives the reactors and the pill
|
|
936
|
+
* itself (as `children`) and returns the whole thing — so it owns the tooltip, its box, size,
|
|
937
|
+
* shape, and position, not just the text inside. Defaults to `DefaultReactionTooltip`, which
|
|
938
|
+
* hangs the built-in inline sentence below the pill. */
|
|
939
|
+
ReactionTooltip?: ComponentType<ReactionTooltipProps>;
|
|
940
|
+
/** Called when the pill is pressed — toggles the current user's reaction. */
|
|
941
|
+
onClick?(): void;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
/** One person who reacted with a given emoji, for the hover list. @public */
|
|
945
|
+
export declare interface ReactionReactor {
|
|
946
|
+
/** Display name of the person who reacted. */
|
|
947
|
+
name: string;
|
|
948
|
+
/** True for the current user. */
|
|
949
|
+
you: boolean;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
/**
|
|
953
|
+
* The row of tallied reactions under a comment. Presentational — the host supplies the summaries
|
|
954
|
+
* and owns what toggling does. Hovering a pill lists who reacted (see `Reaction`).
|
|
955
|
+
*
|
|
956
|
+
* The add-reaction affordance is a separate component (`ReactionPicker`) so it can live outside
|
|
957
|
+
* this row — on a comment card it sits with the card's hover actions, which keeps its position
|
|
958
|
+
* fixed as reactions are added here.
|
|
959
|
+
* @public @react
|
|
960
|
+
*/
|
|
961
|
+
export declare function Reactions({ reactions, onToggle, canReact, enableHoverList, renderReaction, ReactionTooltip }: ReactionsProps): JSX.Element | null;
|
|
962
|
+
|
|
963
|
+
/** @public */
|
|
964
|
+
export declare interface ReactionsProps {
|
|
965
|
+
/** The comment's reactions, grouped by emoji. Empty renders nothing. */
|
|
966
|
+
reactions: ReactionSummary[];
|
|
967
|
+
/** Toggles the current user's reaction for an emoji. */
|
|
968
|
+
onToggle?(emoji: string): void;
|
|
969
|
+
/** Whether the current user may react. False makes the pills inert (e.g. a signed-out
|
|
970
|
+
* viewer, or a read-only thread) while still showing counts. */
|
|
971
|
+
canReact?: boolean;
|
|
972
|
+
/** Whether hovering a pill shows its reactor list. Pass false to suppress it — e.g. while
|
|
973
|
+
* another popup menu on the comment is open. Defaults to true. */
|
|
974
|
+
enableHoverList?: boolean;
|
|
975
|
+
/** How to draw each emoji token. Defaults to the token string (OS emoji font). */
|
|
976
|
+
renderReaction?: RenderReaction;
|
|
977
|
+
/** The tooltip naming who reacted, shown when a pill is hovered. Defaults to an inline sentence
|
|
978
|
+
* (`DefaultReactionTooltip`). Swap it to render the reactor list however you like. */
|
|
979
|
+
ReactionTooltip?: ComponentType<ReactionTooltipProps>;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
/** One emoji's reactions on a comment, already tallied. @public */
|
|
983
|
+
export declare interface ReactionSummary {
|
|
984
|
+
emoji: string;
|
|
985
|
+
/** How many people reacted with this emoji. */
|
|
986
|
+
count: number;
|
|
987
|
+
/** True when the current user is one of them — renders the pill highlighted. */
|
|
988
|
+
active: boolean;
|
|
989
|
+
/** Who reacted with this emoji, in reaction order — shown in the hover list. */
|
|
990
|
+
reactors: ReactionReactor[];
|
|
738
991
|
}
|
|
739
992
|
|
|
740
|
-
/**
|
|
741
|
-
export declare
|
|
993
|
+
/** @public */
|
|
994
|
+
export declare interface ReactionTooltipProps {
|
|
995
|
+
/** Who reacted with this emoji, in reaction order. */
|
|
996
|
+
reactors: ReactionReactor[];
|
|
997
|
+
/** The reaction pill to wrap. Anchor the hover affordance to this and render it. */
|
|
998
|
+
children: ReactNode;
|
|
999
|
+
}
|
|
742
1000
|
|
|
743
1001
|
/**
|
|
744
|
-
*
|
|
745
|
-
*
|
|
746
|
-
*
|
|
1002
|
+
* Keep shape-anchored threads alive across their shape's lifecycle:
|
|
1003
|
+
*
|
|
1004
|
+
* - When the shape is deleted, the thread converts to a `point` anchor at the spot its pin last
|
|
1005
|
+
* occupied, so the conversation outlives the shape instead of becoming invisible (a missing
|
|
1006
|
+
* shape has no bounds, which hides the pin).
|
|
1007
|
+
* - When the shape moves to another page, the thread follows: its `pageId` and each comment's
|
|
1008
|
+
* denormalized `pageId` update to the shape's new page, and the anchor keeps riding the shape.
|
|
1009
|
+
* - When a deleted shape comes back (a page move re-creates it with its id preserved; undoing a
|
|
1010
|
+
* delete restores it), the thread re-attaches — unless its pin was manually moved in the
|
|
1011
|
+
* meantime, in which case the manual placement wins.
|
|
1012
|
+
*
|
|
1013
|
+
* A page move is `deleteShapes` + re-create with preserved ids inside one `editor.run`, but each
|
|
1014
|
+
* store write is its own operation — so at no single moment does "this shape is being moved"
|
|
1015
|
+
* exist as an observable event. The handlers therefore cooperate across operations:
|
|
1016
|
+
* `beforeDelete` snapshots where each affected pin sits (every record is still in the store at
|
|
1017
|
+
* that point, so page bounds resolve even for children of a deleted frame); the
|
|
1018
|
+
* operation-complete pass converts threads whose shape is really gone, remembering the original
|
|
1019
|
+
* anchor; `afterCreate` notes a reappeared shape id, and the operation-complete pass restores
|
|
1020
|
+
* the anchor once the store has settled (creation order within an operation is arbitrary, so a
|
|
1021
|
+
* fresh shape may not resolve an ancestor page mid-operation). Undo/redo of a move
|
|
1022
|
+
* replays as a `parentId` update (remove + add of one id squash to an update in the history
|
|
1023
|
+
* diff), so an `afterChange` handler re-homes threads on cross-page reparents — including
|
|
1024
|
+
* threads anchored to descendants, which move with their parent without change events of their
|
|
1025
|
+
* own.
|
|
1026
|
+
*
|
|
1027
|
+
* Remote changes are ignored: the client that performed the operation runs this same
|
|
1028
|
+
* maintenance and syncs the resulting thread updates. Writes honour the
|
|
1029
|
+
* {@link CommentingOptions.history} option, so the consumer decides whether they're undoable.
|
|
1030
|
+
*
|
|
1031
|
+
* Registered by `CanvasComments` on mount; parts-built consumers can call this directly.
|
|
1032
|
+
* Returns a cleanup function that unregisters all handlers.
|
|
1033
|
+
*
|
|
747
1034
|
* @public
|
|
748
1035
|
*/
|
|
749
|
-
export declare
|
|
750
|
-
/** Whether dragging the comment tool out creates a region anchor. Off → click-only. */
|
|
751
|
-
enabled: boolean;
|
|
752
|
-
/** Which corner the pin and composer sit on, as a normalized 0–1 offset. Default bottom-right. */
|
|
753
|
-
pinCorner: VecLike;
|
|
754
|
-
/** When the dashed box and its handles reveal: while the pointer is within the region, while the
|
|
755
|
-
* pin is hovered, or only while the thread is open. */
|
|
756
|
-
reveal: 'open' | 'pin-hover' | 'pointer';
|
|
757
|
-
/** How a region is moved: dragging its pin, dragging its body, or either. */
|
|
758
|
-
move: 'body' | 'both' | 'pin';
|
|
759
|
-
/** The resize affordance: corner handles, edge handles, or none. */
|
|
760
|
-
resize: 'corners' | 'edges' | 'none';
|
|
761
|
-
}
|
|
1036
|
+
export declare function registerCommentAnchorLifecycle(editor: Editor): () => void;
|
|
762
1037
|
|
|
763
|
-
/**
|
|
764
|
-
|
|
1038
|
+
/**
|
|
1039
|
+
* Remove comment records from the store by id, under the configured
|
|
1040
|
+
* {@link CommentingOptions.history} behavior.
|
|
1041
|
+
*
|
|
1042
|
+
* This is a hard delete, which is rarely what you want for a comment or a thread: the built-in UI
|
|
1043
|
+
* soft-deletes them ({@link deleteComment}, {@link deleteThread}) so the server can prune the
|
|
1044
|
+
* records — including reactions, which belong to whoever left them rather than to the deleter. A
|
|
1045
|
+
* server that enforces per-record permissions will veto a hard delete outright. Reach for this on
|
|
1046
|
+
* a local, unsynced comment store, or to drop a reaction (which is a hard delete — see
|
|
1047
|
+
* {@link toggleCommentReaction}).
|
|
1048
|
+
*
|
|
1049
|
+
* @public
|
|
1050
|
+
*/
|
|
1051
|
+
export declare function removeCommentRecords(editor: Editor, ids: (TLCommentId | TLCommentReactionId | TLCommentThreadId)[]): void;
|
|
1052
|
+
|
|
1053
|
+
/** Render a reaction token to its visual — the emoji glyph by default. @public */
|
|
1054
|
+
export declare type RenderReaction = (token: string) => ReactNode;
|
|
765
1055
|
|
|
766
1056
|
/**
|
|
767
|
-
*
|
|
768
|
-
*
|
|
769
|
-
*
|
|
770
|
-
*
|
|
1057
|
+
* Reopen a resolved thread, clearing the resolution. A no-op on a thread that isn't resolved, and
|
|
1058
|
+
* on one that's gone. Like {@link resolveThread}, it touches only the resolution.
|
|
1059
|
+
*
|
|
1060
|
+
* @public
|
|
1061
|
+
*/
|
|
1062
|
+
export declare function reopenThread(editor: Editor, thread: TLCommentThread): void;
|
|
1063
|
+
|
|
1064
|
+
/**
|
|
1065
|
+
* Mark a thread resolved, stamping who resolved it and when. Resolved threads keep their pin (a
|
|
1066
|
+
* checked one) and are hidden from the sidebar until its "show resolved" filter is on.
|
|
1067
|
+
*
|
|
1068
|
+
* Only the resolution is written: the rest of the thread is read fresh, so resolving with a stale
|
|
1069
|
+
* copy in hand won't drag a pin back to where it used to be. A no-op on a thread that's gone.
|
|
1070
|
+
*
|
|
1071
|
+
* @public
|
|
1072
|
+
*/
|
|
1073
|
+
export declare function resolveThread(editor: Editor, thread: TLCommentThread, userId: string): void;
|
|
1074
|
+
|
|
1075
|
+
/**
|
|
1076
|
+
* Open a thread and bring it into view, given a thread id or the id of any comment in it. Use it
|
|
1077
|
+
* to jump to a thread from outside the canvas — a notification, a deep link, your own list.
|
|
1078
|
+
*
|
|
1079
|
+
* The request is served by `CanvasComments`, so it works before the records have arrived: the
|
|
1080
|
+
* layer waits for them to sync in, switches pages if it needs to, unhides pins, zooms in far
|
|
1081
|
+
* enough to split the thread out of any cluster it's folded into, and then opens it. That also
|
|
1082
|
+
* means nothing happens if `CanvasComments` isn't mounted.
|
|
1083
|
+
*
|
|
1084
|
+
* To open a thread you already hold and skip the wait, see {@link focusThread}.
|
|
1085
|
+
*
|
|
1086
|
+
* @example
|
|
1087
|
+
* ```ts
|
|
1088
|
+
* revealThread(editor, new URLSearchParams(location.search).get('comment')!)
|
|
1089
|
+
* ```
|
|
1090
|
+
*
|
|
771
1091
|
* @public
|
|
772
1092
|
*/
|
|
773
|
-
export declare function
|
|
1093
|
+
export declare function revealThread(editor: Editor, threadOrCommentId: string): void;
|
|
774
1094
|
|
|
775
1095
|
/**
|
|
776
1096
|
* Flatten a rich-text comment body to plaintext through the limited comment extension set,
|
|
@@ -780,11 +1100,12 @@ export declare function renderMarkdown(text: string): ReactNode;
|
|
|
780
1100
|
*/
|
|
781
1101
|
export declare function richTextToPlaintext(body: TLRichText, resolveName?: (id: string) => string | undefined): string;
|
|
782
1102
|
|
|
783
|
-
/** The button that posts a comment. @public @react */
|
|
1103
|
+
/** The button that posts a comment — an up arrow. @public @react */
|
|
784
1104
|
export declare function SendButton({ label, disabled, onClick }: SendButtonProps): JSX.Element;
|
|
785
1105
|
|
|
786
1106
|
/** @public */
|
|
787
1107
|
export declare interface SendButtonProps {
|
|
1108
|
+
/** The button's accessible name (e.g. "Send"). Shown as an up-arrow icon, so this is its label. */
|
|
788
1109
|
label: string;
|
|
789
1110
|
disabled?: boolean;
|
|
790
1111
|
onClick?(): void;
|
|
@@ -792,8 +1113,11 @@ export declare interface SendButtonProps {
|
|
|
792
1113
|
|
|
793
1114
|
/**
|
|
794
1115
|
* A shape anchor for a page point. `x`/`y` are the point's normalized (0–1) offset within the
|
|
795
|
-
* shape's
|
|
796
|
-
*
|
|
1116
|
+
* shape's own bounds — taken in the shape's own space, so a pin placed on a rotated shape records
|
|
1117
|
+
* the spot it was dropped on rather than a spot in the bounding box. Remembered either way: when
|
|
1118
|
+
* `precise` the pin sits at exactly `x`/`y`; otherwise it sits at the consumer's imprecise default
|
|
1119
|
+
* (top-right out of the box). Placement gestures get `precise` from the `shouldBePrecise`
|
|
1120
|
+
* commenting option (always precise, by default).
|
|
797
1121
|
* @public
|
|
798
1122
|
*/
|
|
799
1123
|
export declare function shapeAnchorAt(editor: Editor, shapeId: TLShapeId, page: {
|
|
@@ -801,6 +1125,19 @@ export declare function shapeAnchorAt(editor: Editor, shapeId: TLShapeId, page:
|
|
|
801
1125
|
y: number;
|
|
802
1126
|
}, precise: boolean): TLCommentAnchor;
|
|
803
1127
|
|
|
1128
|
+
/**
|
|
1129
|
+
* The gesture that's creating a shape anchor, passed to
|
|
1130
|
+
* {@link CommentingOptions.shouldBePrecise}: the target shape, the page point of the release, and
|
|
1131
|
+
* whether Alt was held.
|
|
1132
|
+
*
|
|
1133
|
+
* @public
|
|
1134
|
+
*/
|
|
1135
|
+
export declare interface ShapeCommentPrecisionContext {
|
|
1136
|
+
readonly shapeId: TLShapeId;
|
|
1137
|
+
readonly point: VecLike;
|
|
1138
|
+
readonly altKey: boolean;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
804
1141
|
/**
|
|
805
1142
|
* Which threads the comments sidebar shows. Held as an editor-scoped signal (the `sidebarFilters`
|
|
806
1143
|
* `EditorAtom` in `./state`) rather than component state so it survives the sidebar
|
|
@@ -824,7 +1161,18 @@ export declare interface SidebarFilters {
|
|
|
824
1161
|
export declare const sidebarFilters: EditorAtom<SidebarFilters>;
|
|
825
1162
|
|
|
826
1163
|
/**
|
|
827
|
-
*
|
|
1164
|
+
* Tally a comment's reactions into an entry per emoji, ordered by when that emoji was first used
|
|
1165
|
+
* so the row stays stable as later reactions arrive. `active` marks the emoji the current user
|
|
1166
|
+
* reacted with (the pills render those highlighted), and `reactors` lists who reacted with it, in
|
|
1167
|
+
* reaction order, for the hover list. `resolveName` names each reactor; an id it can't name falls
|
|
1168
|
+
* back to the id itself.
|
|
1169
|
+
*
|
|
1170
|
+
* @public
|
|
1171
|
+
*/
|
|
1172
|
+
export declare function summarizeReactions(reactions: TLCommentReaction[], currentUserId?: null | string, resolveName?: (userId: string) => string | undefined): ReactionSummary[];
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* Typed reads of comment records on the editor store.
|
|
828
1176
|
*
|
|
829
1177
|
* Comment threads and comments live on the editor's local store so the canvas can render them
|
|
830
1178
|
* reactively, but they are opt-in records that aren't part of the `TLRecord` union (they ride the
|
|
@@ -832,14 +1180,49 @@ export declare const sidebarFilters: EditorAtom<SidebarFilters>;
|
|
|
832
1180
|
* statically typed `Store<TLRecord>` and doesn't know about them, so every access has to reinterpret
|
|
833
1181
|
* the type. These helpers own that reinterpretation — an `unknown` hop to exactly the type the store
|
|
834
1182
|
* expects, so the rest of each call stays checked — behind one boundary, and keep call sites typed.
|
|
1183
|
+
*
|
|
1184
|
+
* Writes do the same reinterpretation, but they also answer to the undo/redo policy, so they live
|
|
1185
|
+
* with the rest of the write path in `comment-mutations.ts`.
|
|
835
1186
|
*/
|
|
836
|
-
/**
|
|
837
|
-
|
|
1187
|
+
/**
|
|
1188
|
+
* A record that lives in a comment thread: the thread itself, one of its messages, or a reaction
|
|
1189
|
+
* to one of those messages.
|
|
1190
|
+
* @public
|
|
1191
|
+
*/
|
|
1192
|
+
export declare type TLCommentRecord = TLComment | TLCommentReaction | TLCommentThread;
|
|
1193
|
+
|
|
1194
|
+
/**
|
|
1195
|
+
* Toggle one user's reaction with a given emoji on a comment.
|
|
1196
|
+
*
|
|
1197
|
+
* Each reaction is its own record keyed by (comment, user, emoji), so this only ever touches that
|
|
1198
|
+
* one user's own records — two people reacting at once never conflict. Behaviour depends on the
|
|
1199
|
+
* `allowMultipleReactions` option:
|
|
1200
|
+
*
|
|
1201
|
+
* - **multiple** (default): the emoji toggles independently — add it if absent, remove it if
|
|
1202
|
+
* present, leaving the user's other reactions alone.
|
|
1203
|
+
* - **single**: picking a new emoji first removes the user's existing reaction(s) on the comment,
|
|
1204
|
+
* then adds this one (a replace); picking the one they already have removes it.
|
|
1205
|
+
*
|
|
1206
|
+
* @public
|
|
1207
|
+
*/
|
|
1208
|
+
export declare function toggleCommentReaction(editor: Editor, comment: TLComment, userId: string, emoji: string, now?: number): void;
|
|
838
1209
|
|
|
839
1210
|
/** Toggle comment-pin visibility for an editor.
|
|
840
1211
|
* @public */
|
|
841
1212
|
export declare function toggleCommentsHidden(editor: Editor): void;
|
|
842
1213
|
|
|
1214
|
+
/** Open or close the comments sidebar for an editor.
|
|
1215
|
+
* @public */
|
|
1216
|
+
export declare function toggleCommentsSidebar(editor: Editor): void;
|
|
1217
|
+
|
|
1218
|
+
/**
|
|
1219
|
+
* Reactive React hook for {@link getCanComment}: a `canComment` callback that reads signals
|
|
1220
|
+
* re-evaluates when they change.
|
|
1221
|
+
*
|
|
1222
|
+
* @public
|
|
1223
|
+
*/
|
|
1224
|
+
export declare function useCanComment(currentUserId: null | string | undefined): boolean;
|
|
1225
|
+
|
|
843
1226
|
/**
|
|
844
1227
|
* Whether commenting is licensed for this editor. Enabled in development; in production it requires
|
|
845
1228
|
* a tldraw license that includes the commenting feature (or the collaboration umbrella that grants
|
|
@@ -860,29 +1243,56 @@ export declare function useCommentingEnabled(): boolean;
|
|
|
860
1243
|
*/
|
|
861
1244
|
export declare function useCommentingOptions(): CommentingOptions;
|
|
862
1245
|
|
|
863
|
-
/**
|
|
1246
|
+
/**
|
|
1247
|
+
* One comment's reactions, oldest first, reactively.
|
|
1248
|
+
*
|
|
1249
|
+
* @public
|
|
1250
|
+
*/
|
|
1251
|
+
export declare function useCommentReactions(editor: Editor, commentId: TLComment['id']): TLCommentReaction[];
|
|
1252
|
+
|
|
1253
|
+
/** Every live comment in the store ({@link getLiveComments}), oldest first, reactively. Group by
|
|
1254
|
+
* `threadId` for per-thread lists. @public */
|
|
864
1255
|
export declare function useComments(editor: Editor): TLComment[];
|
|
865
1256
|
|
|
866
1257
|
/** React hook for whether comment pins are hidden.
|
|
867
1258
|
* @public */
|
|
868
1259
|
export declare function useCommentsHidden(): boolean;
|
|
869
1260
|
|
|
870
|
-
/**
|
|
1261
|
+
/** React hook for whether the comments sidebar is open.
|
|
1262
|
+
* @public */
|
|
1263
|
+
export declare function useCommentsSidebarOpen(): boolean;
|
|
1264
|
+
|
|
1265
|
+
/**
|
|
1266
|
+
* The comment threads that should render (pins, sidebar), reactively — the live set described by
|
|
1267
|
+
* {@link getLiveCommentThreads}. Use `getCommentThreads` for the unfiltered set, including
|
|
1268
|
+
* soft-deleted threads awaiting the server's prune.
|
|
1269
|
+
*
|
|
1270
|
+
* @public
|
|
1271
|
+
*/
|
|
871
1272
|
export declare function useCommentThreads(editor: Editor): TLCommentThread[];
|
|
872
1273
|
|
|
873
1274
|
/** React hook for the open thread id.
|
|
874
1275
|
* @public */
|
|
875
1276
|
export declare function useOpenThreadId(): null | string;
|
|
876
1277
|
|
|
877
|
-
/**
|
|
878
|
-
* @
|
|
879
|
-
|
|
1278
|
+
/**
|
|
1279
|
+
* Reactive React hook for {@link getRevealThreadPending}.
|
|
1280
|
+
*
|
|
1281
|
+
* Use it to notice a reveal that never lands — most often a deep link to a comment that has since
|
|
1282
|
+
* been deleted. Give it a grace period before you act: a request also sits here while its records
|
|
1283
|
+
* are still syncing in, which is the normal case on a cold load. Re-check with
|
|
1284
|
+
* {@link getRevealThreadPending} when the grace period elapses, since the request can clear inside
|
|
1285
|
+
* it without this hook's value having caught up yet.
|
|
1286
|
+
*
|
|
1287
|
+
* @public
|
|
1288
|
+
*/
|
|
1289
|
+
export declare function useRevealThreadPending(): null | string;
|
|
880
1290
|
|
|
881
1291
|
/** React hook for the current sidebar filters.
|
|
882
1292
|
* @public */
|
|
883
1293
|
export declare function useSidebarFilters(): SidebarFilters;
|
|
884
1294
|
|
|
885
|
-
/** A thread's comments, oldest first, reactively. @public */
|
|
1295
|
+
/** A thread's live comments, oldest first, reactively. @public */
|
|
886
1296
|
export declare function useThreadComments(editor: Editor, threadId: TLCommentThreadId): TLComment[];
|
|
887
1297
|
|
|
888
1298
|
export { }
|