@tldraw/commenting 5.3.0-next.2fa9c61a8de6 → 5.3.0-next.7654e7ac2a02
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/commenting.css +63 -71
- package/dist-cjs/canvas/anchor-lifecycle.js +2 -2
- package/dist-cjs/canvas/anchor-lifecycle.js.map +2 -2
- package/dist-cjs/{ui/tooltip-button.js → canvas/canvas-events.js} +16 -13
- package/dist-cjs/canvas/canvas-events.js.map +7 -0
- package/dist-cjs/canvas/cluster-badge.js +121 -0
- package/dist-cjs/canvas/cluster-badge.js.map +7 -0
- package/dist-cjs/canvas/cluster-fade.js +85 -0
- package/dist-cjs/canvas/cluster-fade.js.map +7 -0
- package/dist-cjs/canvas/cluster-input.js +51 -1
- package/dist-cjs/canvas/cluster-input.js.map +2 -2
- package/dist-cjs/canvas/cluster-model.js +252 -0
- package/dist-cjs/canvas/cluster-model.js.map +7 -0
- package/dist-cjs/canvas/comment-mutations.js +57 -28
- package/dist-cjs/canvas/comment-mutations.js.map +2 -2
- package/dist-cjs/canvas/comment-reactions.js +4 -7
- package/dist-cjs/canvas/comment-reactions.js.map +2 -2
- package/dist-cjs/canvas/comment-render.js +4 -3
- package/dist-cjs/canvas/comment-render.js.map +2 -2
- package/dist-cjs/canvas/comment-store.js.map +2 -2
- package/dist-cjs/canvas/comment-tool.js +0 -1
- package/dist-cjs/canvas/comment-tool.js.map +2 -2
- package/dist-cjs/canvas/comments-filter-menu.js +11 -13
- package/dist-cjs/canvas/comments-filter-menu.js.map +2 -2
- package/dist-cjs/canvas/comments-overflow-menu.js +10 -2
- package/dist-cjs/canvas/comments-overflow-menu.js.map +2 -2
- package/dist-cjs/canvas/comments-overlay.js +77 -870
- package/dist-cjs/canvas/comments-overlay.js.map +3 -3
- package/dist-cjs/canvas/comments-sidebar.js +16 -11
- package/dist-cjs/canvas/comments-sidebar.js.map +2 -2
- package/dist-cjs/canvas/comments-visibility-toggle.js +5 -25
- package/dist-cjs/canvas/comments-visibility-toggle.js.map +2 -2
- package/dist-cjs/canvas/context.js.map +1 -1
- package/dist-cjs/canvas/hooks.js +8 -2
- package/dist-cjs/canvas/hooks.js.map +2 -2
- package/dist-cjs/canvas/license.js.map +1 -1
- package/dist-cjs/canvas/mobile-placement.js +91 -0
- package/dist-cjs/canvas/mobile-placement.js.map +7 -0
- package/dist-cjs/canvas/options.js +39 -1
- package/dist-cjs/canvas/options.js.map +2 -2
- package/dist-cjs/canvas/pending-composer.js +134 -0
- package/dist-cjs/canvas/pending-composer.js.map +7 -0
- package/dist-cjs/canvas/pin-stacking.js +26 -1
- package/dist-cjs/canvas/pin-stacking.js.map +2 -2
- package/dist-cjs/canvas/region-box.js +113 -0
- package/dist-cjs/canvas/region-box.js.map +7 -0
- package/dist-cjs/canvas/state.js.map +2 -2
- package/dist-cjs/canvas/thread-pin.js +304 -0
- package/dist-cjs/canvas/thread-pin.js.map +7 -0
- package/dist-cjs/canvas/thread-preview.js +41 -49
- package/dist-cjs/canvas/thread-preview.js.map +2 -2
- package/dist-cjs/canvas/thread-stack.js +7 -7
- package/dist-cjs/canvas/thread-stack.js.map +2 -2
- package/dist-cjs/canvas/thread-state.js +15 -0
- package/dist-cjs/canvas/thread-state.js.map +2 -2
- package/dist-cjs/canvas/thread-view.js +120 -67
- package/dist-cjs/canvas/thread-view.js.map +3 -3
- package/dist-cjs/clustering/computeClusterTable.js +2 -2
- package/dist-cjs/clustering/computeClusterTable.js.map +2 -2
- package/dist-cjs/clustering/replay.js +89 -22
- package/dist-cjs/clustering/replay.js.map +3 -3
- package/dist-cjs/clustering/runtime.js +19 -12
- package/dist-cjs/clustering/runtime.js.map +2 -2
- package/dist-cjs/clustering/types.js.map +1 -1
- package/dist-cjs/index.d.ts +323 -202
- package/dist-cjs/index.js +7 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/ui/byline.js +5 -3
- package/dist-cjs/ui/byline.js.map +2 -2
- package/dist-cjs/ui/comment-composer.js +2 -18
- package/dist-cjs/ui/comment-composer.js.map +2 -2
- package/dist-cjs/ui/comment-pin.js +2 -15
- package/dist-cjs/ui/comment-pin.js.map +2 -2
- package/dist-cjs/ui/comments-list.js +11 -24
- package/dist-cjs/ui/comments-list.js.map +2 -2
- package/dist-cjs/ui/format-time.js +12 -0
- package/dist-cjs/ui/format-time.js.map +2 -2
- package/dist-cjs/ui/icons.js +115 -0
- package/dist-cjs/ui/icons.js.map +7 -0
- package/dist-cjs/ui/reaction-picker.js +11 -13
- package/dist-cjs/ui/reaction-picker.js.map +2 -2
- package/dist-cjs/ui/reaction.js +3 -4
- package/dist-cjs/ui/reaction.js.map +2 -2
- package/dist-cjs/ui/send-button.js +2 -9
- package/dist-cjs/ui/send-button.js.map +2 -2
- package/dist-cjs/ui/visual-viewport.js +32 -0
- package/dist-cjs/ui/visual-viewport.js.map +7 -0
- package/dist-esm/canvas/anchor-lifecycle.mjs +3 -3
- package/dist-esm/canvas/anchor-lifecycle.mjs.map +2 -2
- package/dist-esm/canvas/canvas-events.mjs +15 -0
- package/dist-esm/canvas/canvas-events.mjs.map +7 -0
- package/dist-esm/canvas/cluster-badge.mjs +106 -0
- package/dist-esm/canvas/cluster-badge.mjs.map +7 -0
- package/dist-esm/canvas/cluster-fade.mjs +65 -0
- package/dist-esm/canvas/cluster-fade.mjs.map +7 -0
- package/dist-esm/canvas/cluster-input.mjs +52 -2
- package/dist-esm/canvas/cluster-input.mjs.map +2 -2
- package/dist-esm/canvas/cluster-model.mjs +236 -0
- package/dist-esm/canvas/cluster-model.mjs.map +7 -0
- package/dist-esm/canvas/comment-mutations.mjs +57 -28
- package/dist-esm/canvas/comment-mutations.mjs.map +2 -2
- package/dist-esm/canvas/comment-reactions.mjs +5 -12
- package/dist-esm/canvas/comment-reactions.mjs.map +2 -2
- package/dist-esm/canvas/comment-render.mjs +5 -4
- package/dist-esm/canvas/comment-render.mjs.map +2 -2
- package/dist-esm/canvas/comment-store.mjs.map +2 -2
- package/dist-esm/canvas/comment-tool.mjs +0 -1
- package/dist-esm/canvas/comment-tool.mjs.map +2 -2
- package/dist-esm/canvas/comments-filter-menu.mjs +12 -13
- package/dist-esm/canvas/comments-filter-menu.mjs.map +2 -2
- package/dist-esm/canvas/comments-overflow-menu.mjs +11 -2
- package/dist-esm/canvas/comments-overflow-menu.mjs.map +2 -2
- package/dist-esm/canvas/comments-overlay.mjs +54 -878
- package/dist-esm/canvas/comments-overlay.mjs.map +3 -3
- package/dist-esm/canvas/comments-sidebar.mjs +18 -14
- package/dist-esm/canvas/comments-sidebar.mjs.map +2 -2
- package/dist-esm/canvas/comments-visibility-toggle.mjs +5 -25
- package/dist-esm/canvas/comments-visibility-toggle.mjs.map +2 -2
- package/dist-esm/canvas/hooks.mjs +9 -2
- package/dist-esm/canvas/hooks.mjs.map +2 -2
- package/dist-esm/canvas/license.mjs.map +1 -1
- package/dist-esm/canvas/mobile-placement.mjs +71 -0
- package/dist-esm/canvas/mobile-placement.mjs.map +7 -0
- package/dist-esm/canvas/options.mjs +39 -1
- package/dist-esm/canvas/options.mjs.map +2 -2
- package/dist-esm/canvas/pending-composer.mjs +126 -0
- package/dist-esm/canvas/pending-composer.mjs.map +7 -0
- package/dist-esm/canvas/pin-stacking.mjs +26 -1
- package/dist-esm/canvas/pin-stacking.mjs.map +2 -2
- package/dist-esm/canvas/region-box.mjs +93 -0
- package/dist-esm/canvas/region-box.mjs.map +7 -0
- package/dist-esm/canvas/state.mjs.map +2 -2
- package/dist-esm/canvas/thread-pin.mjs +310 -0
- package/dist-esm/canvas/thread-pin.mjs.map +7 -0
- package/dist-esm/canvas/thread-preview.mjs +42 -49
- package/dist-esm/canvas/thread-preview.mjs.map +2 -2
- package/dist-esm/canvas/thread-stack.mjs +8 -9
- package/dist-esm/canvas/thread-stack.mjs.map +2 -2
- package/dist-esm/canvas/thread-state.mjs +15 -0
- package/dist-esm/canvas/thread-state.mjs.map +2 -2
- package/dist-esm/canvas/thread-view.mjs +131 -72
- package/dist-esm/canvas/thread-view.mjs.map +3 -3
- package/dist-esm/clustering/computeClusterTable.mjs +2 -2
- package/dist-esm/clustering/computeClusterTable.mjs.map +2 -2
- package/dist-esm/clustering/replay.mjs +89 -22
- package/dist-esm/clustering/replay.mjs.map +3 -3
- package/dist-esm/clustering/runtime.mjs +19 -12
- package/dist-esm/clustering/runtime.mjs.map +2 -2
- package/dist-esm/index.d.mts +323 -202
- package/dist-esm/index.mjs +16 -3
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/ui/byline.mjs +6 -4
- package/dist-esm/ui/byline.mjs.map +2 -2
- package/dist-esm/ui/comment-composer.mjs +2 -18
- package/dist-esm/ui/comment-composer.mjs.map +2 -2
- package/dist-esm/ui/comment-pin.mjs +2 -15
- package/dist-esm/ui/comment-pin.mjs.map +2 -2
- package/dist-esm/ui/comments-list.mjs +10 -23
- package/dist-esm/ui/comments-list.mjs.map +2 -2
- package/dist-esm/ui/format-time.mjs +12 -0
- package/dist-esm/ui/format-time.mjs.map +2 -2
- package/dist-esm/ui/icons.mjs +95 -0
- package/dist-esm/ui/icons.mjs.map +7 -0
- package/dist-esm/ui/reaction-picker.mjs +12 -13
- package/dist-esm/ui/reaction-picker.mjs.map +2 -2
- package/dist-esm/ui/reaction.mjs +3 -4
- package/dist-esm/ui/reaction.mjs.map +2 -2
- package/dist-esm/ui/send-button.mjs +2 -9
- package/dist-esm/ui/send-button.mjs.map +2 -2
- package/dist-esm/ui/visual-viewport.mjs +12 -0
- package/dist-esm/ui/visual-viewport.mjs.map +7 -0
- package/package.json +5 -5
- package/src/canvas/anchor-lifecycle.test.ts +2 -2
- package/src/canvas/anchor-lifecycle.ts +25 -39
- package/src/canvas/canvas-events.ts +18 -0
- package/src/canvas/canvas.css +5 -11
- package/src/canvas/cluster-badge.tsx +133 -0
- package/src/canvas/cluster-fade.ts +102 -0
- package/src/canvas/cluster-input.test.ts +148 -14
- package/src/canvas/cluster-input.ts +92 -5
- package/src/canvas/cluster-model.ts +378 -0
- package/src/canvas/comment-mutations.test.ts +46 -4
- package/src/canvas/comment-mutations.ts +115 -104
- package/src/canvas/comment-reactions.test.ts +22 -0
- package/src/canvas/comment-reactions.tsx +33 -32
- package/src/canvas/comment-render.ts +8 -8
- package/src/canvas/comment-store.ts +12 -17
- package/src/canvas/comment-tool.tsx +8 -12
- package/src/canvas/comments-filter-menu.tsx +9 -16
- package/src/canvas/comments-overflow-menu.tsx +8 -3
- package/src/canvas/comments-overlay.tsx +154 -1344
- package/src/canvas/comments-sidebar.tsx +40 -19
- package/src/canvas/comments-visibility-toggle.tsx +6 -30
- package/src/canvas/context.ts +4 -3
- package/src/canvas/hooks.test.ts +94 -0
- package/src/canvas/hooks.ts +17 -3
- package/src/canvas/license.ts +1 -1
- package/src/canvas/mobile-placement.ts +115 -0
- package/src/canvas/options.test.ts +124 -2
- package/src/canvas/options.ts +192 -58
- package/src/canvas/pending-composer.tsx +157 -0
- package/src/canvas/pin-stacking.test.ts +111 -1
- package/src/canvas/pin-stacking.ts +46 -0
- package/src/canvas/region-box.tsx +124 -0
- package/src/canvas/state.ts +20 -28
- package/src/canvas/thread-pin.tsx +418 -0
- package/src/canvas/thread-preview.tsx +77 -87
- package/src/canvas/thread-stack.tsx +19 -29
- package/src/canvas/thread-state.test.ts +51 -0
- package/src/canvas/thread-state.ts +56 -23
- package/src/canvas/thread-view.test.ts +72 -0
- package/src/canvas/thread-view.tsx +231 -133
- package/src/clustering/computeClusterTable.ts +12 -3
- package/src/clustering/replay.test.ts +0 -7
- package/src/clustering/replay.ts +131 -32
- package/src/clustering/runtime.test.ts +50 -6
- package/src/clustering/runtime.ts +42 -39
- package/src/clustering/schedule.test.ts +0 -6
- package/src/clustering/screen-offsets.test.ts +171 -0
- package/src/clustering/types.ts +10 -0
- package/src/index.ts +15 -2
- package/src/ui/byline.tsx +16 -6
- package/src/ui/comment-composer.tsx +25 -69
- package/src/ui/comment-pin.tsx +3 -16
- package/src/ui/comments-list.tsx +40 -29
- package/src/ui/comments.css +58 -60
- package/src/ui/format-time.test.ts +69 -0
- package/src/ui/format-time.ts +20 -0
- package/src/ui/icons.tsx +116 -0
- package/src/ui/reaction-picker.tsx +9 -16
- package/src/ui/reaction.tsx +10 -6
- package/src/ui/send-button.tsx +3 -8
- package/src/ui/visual-viewport.test.ts +36 -0
- package/src/ui/visual-viewport.ts +27 -0
- package/dist-cjs/ui/tooltip-button.js.map +0 -7
- package/dist-esm/ui/tooltip-button.mjs +0 -12
- package/dist-esm/ui/tooltip-button.mjs.map +0 -7
- package/src/ui/tooltip-button.tsx +0 -20
package/dist-esm/index.d.mts
CHANGED
|
@@ -31,13 +31,11 @@ import { TLUiOverrides } from 'tldraw';
|
|
|
31
31
|
import { VecLike } from 'tldraw';
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* Where a thread's pin sits on the page, for each anchor kind. Null hides the pin.
|
|
35
|
-
*
|
|
36
|
-
* normalized 0–1 spot, top-right by default) rather than the stored `x`/`y`.
|
|
34
|
+
* Where a thread's pin sits on the page, for each anchor kind. Null hides the pin. Imprecise shape
|
|
35
|
+
* anchors use {@link CommentingOptions.impreciseShapeAnchor} rather than the stored `x`/`y`.
|
|
37
36
|
*
|
|
38
|
-
* A shape anchor's `x`/`y` are normalized within the shape's
|
|
39
|
-
*
|
|
40
|
-
* carries the pin around with it instead of leaving it behind in the bounding box.
|
|
37
|
+
* A shape anchor's `x`/`y` are normalized within the shape's bounds and resolved through its page
|
|
38
|
+
* transform, so the pin rides rotation instead of being left behind in the bounding box.
|
|
41
39
|
* @public
|
|
42
40
|
*/
|
|
43
41
|
export declare function anchorPagePoint(editor: Editor, anchor: TLCommentAnchor): {
|
|
@@ -49,7 +47,11 @@ export { Avatar }
|
|
|
49
47
|
|
|
50
48
|
export { AvatarProps }
|
|
51
49
|
|
|
52
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* A comment's metadata line: author name, relative time, and an edited marker. Hovering the time
|
|
52
|
+
* shows the full date and time in a tooltip.
|
|
53
|
+
* @public @react
|
|
54
|
+
*/
|
|
53
55
|
export declare function Byline({ author, date, edited }: BylineProps): JSX.Element;
|
|
54
56
|
|
|
55
57
|
/** @public */
|
|
@@ -66,14 +68,11 @@ export declare interface BylineProps {
|
|
|
66
68
|
* thread popover (with a reply composer) on click, and shows a composer where the comment tool
|
|
67
69
|
* placed a new thread. Reads/writes comment records straight from `editor.store`.
|
|
68
70
|
*
|
|
69
|
-
* It's
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
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.
|
|
71
|
+
* It's the batteries-included default: every visible piece is a slot on
|
|
72
|
+
* `CommentTool.configure({ components })`, and the pieces it composes (`CommentPin`,
|
|
73
|
+
* `CommentThread`, `CommentComposer`, the hooks, the tool) are all exported, so a consumer can
|
|
74
|
+
* rebuild it from parts instead. The host wiring is the {@link CommentingContext}, which
|
|
75
|
+
* `CanvasCommentsSidebar` takes too.
|
|
77
76
|
*
|
|
78
77
|
* @public @react
|
|
79
78
|
*/
|
|
@@ -200,34 +199,49 @@ export declare interface CommentingComponents {
|
|
|
200
199
|
ThreadPreview?: ComponentType<{
|
|
201
200
|
comment: TLComment;
|
|
202
201
|
}>;
|
|
202
|
+
/**
|
|
203
|
+
* A whole sidebar row. Replaces the default `<CommentListItem>`, which is exported — so a row
|
|
204
|
+
* that only adds an unread dot or a status chip can spread these props into it. Use
|
|
205
|
+
* `ThreadPreview` instead when only the preview text is changing.
|
|
206
|
+
*/
|
|
207
|
+
ThreadRow?: ComponentType<CommentListItemRenderProps & {
|
|
208
|
+
thread: TLCommentThread;
|
|
209
|
+
}>;
|
|
210
|
+
/**
|
|
211
|
+
* Extra controls in an open thread's header, added ahead of the built-in resolve and dismiss
|
|
212
|
+
* buttons rather than replacing them. "Copy link" is already built in whenever the host supplies
|
|
213
|
+
* `getThreadHref`.
|
|
214
|
+
*/
|
|
215
|
+
ThreadActions?: ComponentType<{
|
|
216
|
+
comments: TLComment[];
|
|
217
|
+
thread: TLCommentThread;
|
|
218
|
+
}>;
|
|
203
219
|
/**
|
|
204
220
|
* A reaction's visual, given its token. The default renders the token string for the OS emoji
|
|
205
|
-
* font to draw
|
|
206
|
-
*
|
|
207
|
-
* emits and is what gets stored/synced; this only controls how it's drawn.
|
|
221
|
+
* font. Override to draw a custom palette — an `<img>`, an SVG, anything. The token is what gets
|
|
222
|
+
* stored and synced; this only controls how it's drawn.
|
|
208
223
|
*/
|
|
209
224
|
ReactionContent?: ComponentType<{
|
|
210
225
|
token: string;
|
|
211
226
|
}>;
|
|
212
227
|
/**
|
|
213
|
-
* What the add-reaction button opens
|
|
214
|
-
*
|
|
215
|
-
*
|
|
228
|
+
* What the add-reaction button opens. Replaces the default `<EmojiPicker>` grid. Pairs with
|
|
229
|
+
* `ReactionContent` (which draws the tokens this emits) and `isAllowedReaction` (which must
|
|
230
|
+
* accept them).
|
|
216
231
|
*/
|
|
217
232
|
ReactionPalette?: ComponentType<EmojiPickerProps>;
|
|
218
233
|
/**
|
|
219
|
-
* The hover affordance naming who reacted with an emoji.
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
* the `comments.reacted-*` strings instead; reach for this to change the structure — a different
|
|
223
|
-
* box, avatars, a banner anywhere on screen.
|
|
234
|
+
* The hover affordance naming who reacted with an emoji. Receives the reactors and the pill (as
|
|
235
|
+
* `children`) and owns the whole thing — box, size, shape, position. For a wording change,
|
|
236
|
+
* translate the `comments.reacted-*` strings instead.
|
|
224
237
|
*/
|
|
225
238
|
ReactionTooltip?: ComponentType<ReactionTooltipProps>;
|
|
226
|
-
/**
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
239
|
+
/**
|
|
240
|
+
* Shown where a composer would sit when the viewer can't compose (see
|
|
241
|
+
* {@link CommentingOptions.canComment}). `context` is the surface rendering it: an open thread
|
|
242
|
+
* popover (`'thread'`) or the comment tool's placement popover (`'pending'`). Unset, those
|
|
243
|
+
* surfaces render nothing.
|
|
244
|
+
*/
|
|
231
245
|
ComposerFallback?: ComponentType<{
|
|
232
246
|
context: 'pending' | 'thread';
|
|
233
247
|
}>;
|
|
@@ -261,10 +275,11 @@ export declare interface CommentingContext {
|
|
|
261
275
|
/** Whether a comment is unread for the current user (return true for unread). */
|
|
262
276
|
isCommentUnread?(commentId: TLCommentId): boolean;
|
|
263
277
|
/**
|
|
264
|
-
* Called
|
|
265
|
-
* record
|
|
278
|
+
* Called with every unread comment shown to the user in an open thread popover, batched per
|
|
279
|
+
* report, so hosts can record read receipts without a write per comment. Needs
|
|
280
|
+
* `isCommentUnread` to know what's unread.
|
|
266
281
|
*/
|
|
267
|
-
|
|
282
|
+
onCommentsRead?(commentIds: TLCommentId[]): void;
|
|
268
283
|
/** Resolve the members matching an `@`-query in the composers (sync or async). */
|
|
269
284
|
getMentionSuggestions?(query: string): MentionMember[] | Promise<MentionMember[]>;
|
|
270
285
|
/** Override a mention-picker row's content. */
|
|
@@ -294,11 +309,9 @@ export declare interface CommentingContext {
|
|
|
294
309
|
*/
|
|
295
310
|
export declare interface CommentingOptions {
|
|
296
311
|
/**
|
|
297
|
-
* How comment mutations
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
* already removed, and undoing a resolve/edit reverts their newer state. Safe only single-player
|
|
301
|
-
* or on a non-synced local comment store.
|
|
312
|
+
* How comment mutations interact with the editor undo stack. Defaults to `'ignore'` — comments
|
|
313
|
+
* are deliberately not undoable (see `TLComment`). `'record'` is a multiplayer footgun: undoing
|
|
314
|
+
* a delete resurrects a thread a collaborator already removed. Safe only single-player.
|
|
302
315
|
*/
|
|
303
316
|
readonly history: TLHistoryBatchOptions['history'];
|
|
304
317
|
/**
|
|
@@ -316,56 +329,77 @@ export declare interface CommentingOptions {
|
|
|
316
329
|
*/
|
|
317
330
|
readonly allowMultipleReactions: boolean;
|
|
318
331
|
/**
|
|
319
|
-
* Whether a token may be added as a reaction. Defaults to {@link isAllowedReactionEmoji}
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
* off-palette token must still be clearable.
|
|
332
|
+
* Whether a token may be added as a reaction. Defaults to {@link isAllowedReactionEmoji}, which
|
|
333
|
+
* keeps a scripted client from writing junk values the picker would never offer. Override
|
|
334
|
+
* alongside a custom `ReactionPalette`. Removals aren't checked — an off-palette reaction must
|
|
335
|
+
* still be clearable.
|
|
324
336
|
*/
|
|
325
337
|
isAllowedReaction(token: string): boolean;
|
|
326
338
|
/**
|
|
327
339
|
* Whether dragging the comment tool out creates a region anchor — a comment attached to a
|
|
328
|
-
* rectangular area
|
|
329
|
-
*
|
|
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.
|
|
340
|
+
* rectangular area, drawn as a dashed box with the pin on the corner the drag released on. Off
|
|
341
|
+
* by default, where comments attach to points and shapes only and a drag trails the composer.
|
|
332
342
|
*/
|
|
333
343
|
readonly enableRegions: boolean;
|
|
334
344
|
/**
|
|
335
|
-
* Whether the viewer may participate in commenting: composing
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
* are hidden. Unset, participation is allowed exactly when `currentUserId` is set.
|
|
345
|
+
* Whether the viewer may participate in commenting: composing, editing, deleting, resolving, and
|
|
346
|
+
* moving pins. When false, {@link CommentingComponents.ComposerFallback} renders in the
|
|
347
|
+
* composer's place and action affordances are hidden. Unset, participation is allowed exactly
|
|
348
|
+
* when `currentUserId` is set.
|
|
340
349
|
*
|
|
341
|
-
* Called during render via {@link useCanComment}, so
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
* returns true for a signed-out viewer yields a composer whose send button stays disabled.
|
|
350
|
+
* Called during render via {@link useCanComment}, so signal reads are tracked. Posting still
|
|
351
|
+
* needs a `currentUserId`, so returning true for a signed-out viewer yields a composer whose
|
|
352
|
+
* send button stays disabled. A callback that throws is logged and read as false, rather than
|
|
353
|
+
* taking the comments layer down with it.
|
|
346
354
|
*/
|
|
347
355
|
readonly canComment: ((ctx: {
|
|
348
356
|
currentUserId: null | string;
|
|
349
357
|
editor: Editor;
|
|
350
358
|
}) => boolean) | undefined;
|
|
359
|
+
/**
|
|
360
|
+
* Whether the viewer may make a particular write against a particular record: editing or
|
|
361
|
+
* deleting a comment, or deleting a thread. Unset, each is its record's owner's to make
|
|
362
|
+
* ({@link defaultCanModifyComment}) — you edit and delete your own comments, and delete threads
|
|
363
|
+
* you started. Override it to widen that (a workspace admin or moderator who may remove
|
|
364
|
+
* anyone's comment) or to narrow it (no edits after an hour). Where it returns false the
|
|
365
|
+
* affordance isn't rendered.
|
|
366
|
+
*
|
|
367
|
+
* Checked after {@link CommentingOptions.canComment}, which gates commenting as a whole: a
|
|
368
|
+
* viewer who may not participate gets no action affordances at all, whatever this returns.
|
|
369
|
+
*
|
|
370
|
+
* Called during render via {@link useCanModifyComment}, so reactive reads (signals) are tracked.
|
|
371
|
+
* A callback that throws is logged and read as false: an affordance is withheld rather than the
|
|
372
|
+
* comments layer lost, and a denial is what a server enforcing the same rule would have said.
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
* ```tsx
|
|
376
|
+
* CommentTool.configure({
|
|
377
|
+
* canModifyComment: (ctx) =>
|
|
378
|
+
* // Moderators may delete anything; everything else stays the owner's to do.
|
|
379
|
+
* (ctx.action !== 'edit-comment' && isModerator(ctx.currentUserId)) ||
|
|
380
|
+
* defaultCanModifyComment(ctx),
|
|
381
|
+
* })
|
|
382
|
+
* ```
|
|
383
|
+
*/
|
|
384
|
+
readonly canModifyComment: ((ctx: CommentModificationContext) => boolean) | undefined;
|
|
351
385
|
/** Normalized (0–1) spot within a shape where imprecise shape pins sit. Default top-right. */
|
|
352
386
|
readonly impreciseShapeAnchor: {
|
|
353
387
|
readonly x: number;
|
|
354
388
|
readonly y: number;
|
|
355
389
|
};
|
|
356
390
|
/**
|
|
357
|
-
* Whether a comment landing on a shape
|
|
358
|
-
*
|
|
359
|
-
*
|
|
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.
|
|
391
|
+
* Whether a comment landing on a shape pins to the exact clicked spot, or to the shape as a
|
|
392
|
+
* whole (rendered at `impreciseShapeAnchor`). Always precise by default; return `false`, or
|
|
393
|
+
* decide from the context. Governs new placements only — existing anchors render as stored.
|
|
363
394
|
*/
|
|
364
395
|
shouldBePrecise(editor: Editor, context: ShapeCommentPrecisionContext): boolean;
|
|
365
396
|
/** Component overrides. See {@link CommentingComponents}. */
|
|
366
397
|
readonly components: CommentingComponents;
|
|
367
398
|
}
|
|
368
399
|
|
|
400
|
+
/** One thread's row in a {@link CommentsList}. @public @react */
|
|
401
|
+
export declare function CommentListItem({ id, author, preview, date, resolved, page, count, selected, reactions, href, resolvedLabel, onSelect }: CommentListItemRenderProps): JSX.Element;
|
|
402
|
+
|
|
369
403
|
/** @public */
|
|
370
404
|
export declare interface CommentListItemProps {
|
|
371
405
|
id: string;
|
|
@@ -381,6 +415,9 @@ export declare interface CommentListItemProps {
|
|
|
381
415
|
count?: number;
|
|
382
416
|
/** Whether this thread is the open one. */
|
|
383
417
|
selected?: boolean;
|
|
418
|
+
/** Tallied reactions for the row (a thread's, or a single comment's when the row is one
|
|
419
|
+
* comment), shown as inert pills under the preview. Omit to hide. */
|
|
420
|
+
reactions?: ReactionSummary[];
|
|
384
421
|
/**
|
|
385
422
|
* Link target for the item. When set, the row renders as an anchor so browser affordances
|
|
386
423
|
* (ctrl/cmd-click, middle-click) open it in a new tab; a plain click still calls `onSelect`.
|
|
@@ -388,6 +425,51 @@ export declare interface CommentListItemProps {
|
|
|
388
425
|
href?: string;
|
|
389
426
|
}
|
|
390
427
|
|
|
428
|
+
/**
|
|
429
|
+
* What a row is rendered with: the item, plus the list-level wiring it needs to be interactive.
|
|
430
|
+
* A custom row gets the same props the default `<CommentListItem>` does, so it can wrap the
|
|
431
|
+
* default rather than reimplement it.
|
|
432
|
+
*
|
|
433
|
+
* @public
|
|
434
|
+
*/
|
|
435
|
+
export declare interface CommentListItemRenderProps extends CommentListItemProps {
|
|
436
|
+
/** Label for a resolved thread's marker on its row. */
|
|
437
|
+
resolvedLabel?: string;
|
|
438
|
+
/** Called with the thread id when the row is chosen. */
|
|
439
|
+
onSelect?(id: string): void;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* A commenting write that belongs to someone in particular, and the record it targets — the
|
|
444
|
+
* argument to {@link CommentingOptions.canModifyComment}.
|
|
445
|
+
*
|
|
446
|
+
* Resolving, reopening, reacting, and moving a pin aren't here: none of them is anyone's in
|
|
447
|
+
* particular, so {@link CommentingOptions.canComment} is the only gate on them.
|
|
448
|
+
*
|
|
449
|
+
* @public
|
|
450
|
+
*/
|
|
451
|
+
export declare type CommentModification = {
|
|
452
|
+
readonly action: 'delete-comment';
|
|
453
|
+
readonly comment: TLComment;
|
|
454
|
+
} | {
|
|
455
|
+
readonly action: 'delete-thread';
|
|
456
|
+
readonly thread: TLCommentThread;
|
|
457
|
+
} | {
|
|
458
|
+
readonly action: 'edit-comment';
|
|
459
|
+
readonly comment: TLComment;
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* The argument to {@link CommentingOptions.canModifyComment}: which write, against which record,
|
|
464
|
+
* and by whom.
|
|
465
|
+
*
|
|
466
|
+
* @public
|
|
467
|
+
*/
|
|
468
|
+
export declare type CommentModificationContext = {
|
|
469
|
+
readonly currentUserId: null | string;
|
|
470
|
+
readonly editor: Editor;
|
|
471
|
+
} & CommentModification;
|
|
472
|
+
|
|
391
473
|
/** A canvas comment marker: shows its `children` (or a check when resolved). Purely
|
|
392
474
|
* presentational — it reflects open/resolved state via CSS; wrap it to make it clickable.
|
|
393
475
|
* @public @react */
|
|
@@ -404,9 +486,8 @@ export declare interface CommentPinProps {
|
|
|
404
486
|
}
|
|
405
487
|
|
|
406
488
|
/**
|
|
407
|
-
* The add-reaction button for one comment. Belongs with the comment card's hover actions
|
|
408
|
-
*
|
|
409
|
-
* are added.
|
|
489
|
+
* The add-reaction button for one comment. Belongs with the comment card's hover actions rather
|
|
490
|
+
* than in the reaction row, so opening it doesn't chase the row as reactions are added.
|
|
410
491
|
* @public @react
|
|
411
492
|
*/
|
|
412
493
|
export declare function CommentReactionPicker({ comment, currentUserId, emoji }: CommentReactionPickerProps): JSX.Element | null;
|
|
@@ -433,7 +514,7 @@ export declare interface CommentReactionsProps {
|
|
|
433
514
|
/** The reacting user. Null/omitted gives a read-only row (signed out): counts show, but the
|
|
434
515
|
* pills don't toggle. */
|
|
435
516
|
currentUserId?: null | string;
|
|
436
|
-
/** Names a reactor id for the hover list. Ids it can't name fall back to
|
|
517
|
+
/** Names a reactor id for the hover list. Ids it can't name fall back to a generic "Someone". */
|
|
437
518
|
resolveName?(userId: string): string | undefined;
|
|
438
519
|
}
|
|
439
520
|
|
|
@@ -477,8 +558,12 @@ export declare interface CommentsListProps {
|
|
|
477
558
|
empty?: ReactNode;
|
|
478
559
|
/** Label for a resolved thread's marker on its row. Defaults to "Resolved". */
|
|
479
560
|
resolvedLabel?: string;
|
|
480
|
-
/**
|
|
481
|
-
|
|
561
|
+
/**
|
|
562
|
+
* Override how each item renders. Defaults to `<CommentListItem>`, which is exported — so a
|
|
563
|
+
* row that only adds something can spread these props into it rather than start over. The list
|
|
564
|
+
* supplies the key, so a custom row doesn't need one.
|
|
565
|
+
*/
|
|
566
|
+
renderItem?(props: CommentListItemRenderProps): ReactNode;
|
|
482
567
|
}
|
|
483
568
|
|
|
484
569
|
/**
|
|
@@ -496,10 +581,8 @@ export declare function CommentsMenuItem(): JSX.Element;
|
|
|
496
581
|
export declare function CommentsOverflowMenu(): JSX.Element;
|
|
497
582
|
|
|
498
583
|
/**
|
|
499
|
-
* Whether the comments sidebar (the thread list) is open. Driven by an explicit control
|
|
500
|
-
*
|
|
501
|
-
* from placing them. The comment tool additionally closes it on enter, keeping placement
|
|
502
|
-
* canvas-focused.
|
|
584
|
+
* Whether the comments sidebar (the thread list) is open. Driven by an explicit control rather than
|
|
585
|
+
* by which tool is active, so browsing threads is separate from placing them.
|
|
503
586
|
* @public
|
|
504
587
|
*/
|
|
505
588
|
export declare const commentsSidebarOpen: EditorAtom<boolean>;
|
|
@@ -537,11 +620,10 @@ export declare interface CommentThreadProps {
|
|
|
537
620
|
}
|
|
538
621
|
|
|
539
622
|
/**
|
|
540
|
-
* The comment tool. Pressing down opens the comment composer
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
* are created when the comment is posted.
|
|
623
|
+
* The comment tool. Pressing down opens the comment composer at the pointer and it follows until
|
|
624
|
+
* release — like placing a sticky note — settling on a point, or on a shape when released over one.
|
|
625
|
+
* With region comments enabled, dragging past the threshold draws a region rectangle instead.
|
|
626
|
+
* Placement only opens a composer; the records are created when the comment is posted.
|
|
545
627
|
* @public
|
|
546
628
|
*/
|
|
547
629
|
export declare class CommentTool extends StateNode {
|
|
@@ -572,7 +654,7 @@ export declare class CommentTool extends StateNode {
|
|
|
572
654
|
}
|
|
573
655
|
|
|
574
656
|
/** Registers the comment tool in the UI (icon, label, shortcut). Compose into your overrides.
|
|
575
|
-
* Once registered, tldraw's `
|
|
657
|
+
* Once registered, tldraw's `DefaultQuickActionsContent` shows the comment button.
|
|
576
658
|
* @public */
|
|
577
659
|
export declare const commentToolOverrides: TLUiOverrides;
|
|
578
660
|
|
|
@@ -607,6 +689,18 @@ export declare const DEFAULT_REACTION_EMOJI: string[];
|
|
|
607
689
|
* @public */
|
|
608
690
|
export declare const DEFAULT_SIDEBAR_FILTERS: SidebarFilters;
|
|
609
691
|
|
|
692
|
+
/**
|
|
693
|
+
* The default {@link CommentingOptions.canModifyComment}: a write is its record's owner's to make —
|
|
694
|
+
* a comment's author edits and deletes it, a thread's creator deletes the thread — and a viewer
|
|
695
|
+
* with no identity may make none of them.
|
|
696
|
+
*
|
|
697
|
+
* Exported so a callback can widen the default rather than restate it:
|
|
698
|
+
* `(ctx) => isModerator(ctx.currentUserId) || defaultCanModifyComment(ctx)`.
|
|
699
|
+
*
|
|
700
|
+
* @public
|
|
701
|
+
*/
|
|
702
|
+
export declare function defaultCanModifyComment(ctx: CommentModificationContext): boolean;
|
|
703
|
+
|
|
610
704
|
/**
|
|
611
705
|
* The default {@link CommentingOptions}. Override via `CommentTool.configure({ ... })`.
|
|
612
706
|
*
|
|
@@ -615,6 +709,7 @@ export declare const DEFAULT_SIDEBAR_FILTERS: SidebarFilters;
|
|
|
615
709
|
export declare const defaultCommentingOptions: {
|
|
616
710
|
readonly allowMultipleReactions: true;
|
|
617
711
|
readonly canComment: undefined;
|
|
712
|
+
readonly canModifyComment: undefined;
|
|
618
713
|
readonly components: {};
|
|
619
714
|
readonly dragHistory: undefined;
|
|
620
715
|
readonly enableClustering: true;
|
|
@@ -654,21 +749,18 @@ export declare function defaultRenderReaction(token: string): ReactNode;
|
|
|
654
749
|
/**
|
|
655
750
|
* Delete a comment.
|
|
656
751
|
*
|
|
657
|
-
* This is a soft delete: it sets
|
|
658
|
-
*
|
|
659
|
-
*
|
|
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.
|
|
752
|
+
* This is a soft delete: it sets `isDeleted` rather than removing the record, and the server prunes
|
|
753
|
+
* the comment and its reactions once the flag is persisted — so no client removes records it
|
|
754
|
+
* doesn't own, and a server enforcing per-record permissions has a write it can check.
|
|
662
755
|
*
|
|
663
|
-
*
|
|
664
|
-
*
|
|
665
|
-
* comment back.
|
|
756
|
+
* Deleting is the author's to do by default; {@link CommentingOptions.canModifyComment} widens
|
|
757
|
+
* that, as does its counterpart on the server.
|
|
666
758
|
*
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
* the deleter may not be its creator.
|
|
759
|
+
* Never undoable, whatever {@link CommentingOptions.history} says: the flag is write-once
|
|
760
|
+
* server-side, so an undo clearing it would be vetoed rather than bring the comment back.
|
|
670
761
|
*
|
|
671
|
-
*
|
|
762
|
+
* Deleting a thread's last comment closes it and leaves the thread record for the server to prune,
|
|
763
|
+
* since the deleter may not be its creator. An already-deleted comment is a no-op.
|
|
672
764
|
*
|
|
673
765
|
* @public
|
|
674
766
|
*/
|
|
@@ -677,27 +769,23 @@ export declare function deleteComment(editor: Editor, comment: TLComment): void;
|
|
|
677
769
|
/**
|
|
678
770
|
* Delete a thread and, with it, the whole conversation.
|
|
679
771
|
*
|
|
680
|
-
* A soft delete on the same model as {@link deleteComment}: the
|
|
681
|
-
*
|
|
682
|
-
*
|
|
683
|
-
*
|
|
684
|
-
*
|
|
685
|
-
* Closes the thread if it's the open one. A thread that's already pruned is a no-op.
|
|
772
|
+
* A soft delete on the same model as {@link deleteComment}: the server prunes the thread, its
|
|
773
|
+
* comments, and their reactions once the flag is persisted. Deleting a thread is its creator's to
|
|
774
|
+
* do by default ({@link CommentingOptions.canModifyComment}), and the write is never undoable.
|
|
775
|
+
* Closes the thread if it's the open one; a pruned thread is a no-op.
|
|
686
776
|
*
|
|
687
777
|
* @public
|
|
688
778
|
*/
|
|
689
779
|
export declare function deleteThread(editor: Editor, thread: TLCommentThread): void;
|
|
690
780
|
|
|
691
781
|
/**
|
|
692
|
-
* Replace a comment's body and stamp it as edited, which
|
|
693
|
-
*
|
|
782
|
+
* Replace a comment's body and stamp it as edited, which renders the "(edited)" marker on its
|
|
783
|
+
* byline. Editing is the author's to do by default ({@link CommentingOptions.canModifyComment}),
|
|
784
|
+
* and a server enforcing per-record permissions rejects anyone else's. Widening one end without the
|
|
785
|
+
* other leaves an edit that's offered and then rejected, so widen both.
|
|
694
786
|
*
|
|
695
|
-
*
|
|
696
|
-
*
|
|
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.
|
|
787
|
+
* The body lands on the version the store currently holds, so a stale copy can't revert a later
|
|
788
|
+
* change or re-create a removed comment — editing one of those does nothing.
|
|
701
789
|
*
|
|
702
790
|
* @example
|
|
703
791
|
* ```ts
|
|
@@ -740,6 +828,13 @@ export { filterMentionMembers }
|
|
|
740
828
|
/** Open a thread and bring it into view — switch to its page if needed, then center its pin. @public */
|
|
741
829
|
export declare function focusThread(editor: Editor, thread: TLCommentThread): void;
|
|
742
830
|
|
|
831
|
+
/**
|
|
832
|
+
* Format an ISO datetime as a full date and time ("Tuesday, July 22, 2025 at 4:44 PM").
|
|
833
|
+
* Locale-aware via Intl.DateTimeFormat.
|
|
834
|
+
* @public
|
|
835
|
+
*/
|
|
836
|
+
export declare function formatFullDateTime(iso: string, locale?: string): string;
|
|
837
|
+
|
|
743
838
|
/**
|
|
744
839
|
* Format an ISO datetime as short relative time ("2 hr. ago", "yesterday", "last wk.").
|
|
745
840
|
* Locale-aware via Intl.RelativeTimeFormat.
|
|
@@ -749,16 +844,30 @@ export declare function formatRelativeTime(iso: string, locale?: string): string
|
|
|
749
844
|
|
|
750
845
|
/**
|
|
751
846
|
* Whether the viewer may participate in commenting, per {@link CommentingOptions.canComment}
|
|
752
|
-
* (defaulting to `currentUserId != null` when unset).
|
|
753
|
-
* the {@link CommentingComponents.ComposerFallback} slot and action affordances are hidden.
|
|
847
|
+
* (defaulting to `currentUserId != null` when unset). A callback that throws denies.
|
|
754
848
|
*
|
|
755
|
-
* This is a plain, untracked read —
|
|
756
|
-
* In React, use {@link useCanComment} instead.
|
|
849
|
+
* This is a plain, untracked read — in React, use {@link useCanComment} instead.
|
|
757
850
|
*
|
|
758
851
|
* @public
|
|
759
852
|
*/
|
|
760
853
|
export declare function getCanComment(editor: Editor, currentUserId: null | string | undefined): boolean;
|
|
761
854
|
|
|
855
|
+
/**
|
|
856
|
+
* Whether the viewer may make a given write against a given record, per
|
|
857
|
+
* {@link CommentingOptions.canModifyComment} (defaulting to {@link defaultCanModifyComment} when
|
|
858
|
+
* unset). Where this is false the affordance isn't rendered.
|
|
859
|
+
*
|
|
860
|
+
* This is the per-record rule alone: the built-in UI additionally requires
|
|
861
|
+
* {@link CommentingOptions.canComment}, since a viewer who may not participate gets no action
|
|
862
|
+
* affordances at all.
|
|
863
|
+
*
|
|
864
|
+
* A plain, untracked read — a `canModifyComment` callback that reads signals is not observed. In
|
|
865
|
+
* React, use {@link useCanModifyComment} instead.
|
|
866
|
+
*
|
|
867
|
+
* @public
|
|
868
|
+
*/
|
|
869
|
+
export declare function getCanModifyComment(editor: Editor, currentUserId: null | string | undefined, modification: CommentModification): boolean;
|
|
870
|
+
|
|
762
871
|
/**
|
|
763
872
|
* The merged {@link CommentingOptions} for an editor, read off the registered comment tool (which
|
|
764
873
|
* carries them via `CommentTool.configure`). Falls back to {@link defaultCommentingOptions} when
|
|
@@ -785,9 +894,8 @@ export declare function getCommentRecord(editor: Editor, id: string): TLCommentR
|
|
|
785
894
|
export declare function getComments(editor: Editor): TLComment[];
|
|
786
895
|
|
|
787
896
|
/**
|
|
788
|
-
* Every comment thread in the store, **including soft-deleted
|
|
789
|
-
*
|
|
790
|
-
* nothing renders. For the set the UI shows, use {@link getLiveCommentThreads}.
|
|
897
|
+
* Every comment thread in the store, **including soft-deleted and emptied ones** awaiting the
|
|
898
|
+
* server's prune, which nothing renders. For the set the UI shows, use {@link getLiveCommentThreads}.
|
|
791
899
|
*
|
|
792
900
|
* Non-reactive; wrap in `useValue`, or use `useCommentThreads`, to react.
|
|
793
901
|
* @public
|
|
@@ -796,8 +904,7 @@ export declare function getCommentThreads(editor: Editor): TLCommentThread[];
|
|
|
796
904
|
|
|
797
905
|
/**
|
|
798
906
|
* The comments that should render: not soft-deleted. A deleted record lingers in the store until
|
|
799
|
-
* the server prunes it, so this
|
|
800
|
-
* should be built from.
|
|
907
|
+
* the server prunes it, so build counts and lists from this rather than {@link getComments}.
|
|
801
908
|
*
|
|
802
909
|
* Non-reactive; the reactive equivalent is `useComments` (which also sorts oldest first).
|
|
803
910
|
* @public
|
|
@@ -805,10 +912,9 @@ export declare function getCommentThreads(editor: Editor): TLCommentThread[];
|
|
|
805
912
|
export declare function getLiveComments(editor: Editor): TLComment[];
|
|
806
913
|
|
|
807
914
|
/**
|
|
808
|
-
* The comment threads that should render (pins, sidebar):
|
|
809
|
-
*
|
|
810
|
-
*
|
|
811
|
-
* thread record lingers with no surface.
|
|
915
|
+
* The comment threads that should render (pins, sidebar): not soft-deleted, and still holding at
|
|
916
|
+
* least one live comment. A thread emptied by its last comment's delete lingers with no surface
|
|
917
|
+
* until the server's prune lands.
|
|
812
918
|
*
|
|
813
919
|
* Non-reactive; the reactive equivalent is `useCommentThreads`.
|
|
814
920
|
* @public
|
|
@@ -817,12 +923,10 @@ export declare function getLiveCommentThreads(editor: Editor): TLCommentThread[]
|
|
|
817
923
|
|
|
818
924
|
/**
|
|
819
925
|
* The id passed to the most recent {@link revealThread} call that `CanvasComments` hasn't served
|
|
820
|
-
* yet, or null
|
|
821
|
-
* unmounts, since nothing is left to serve it.
|
|
926
|
+
* yet, or null. A request also clears when `CanvasComments` unmounts.
|
|
822
927
|
*
|
|
823
|
-
* This is a plain, untracked read
|
|
824
|
-
*
|
|
825
|
-
* render it closed over.
|
|
928
|
+
* This is a plain, untracked read — in React, use {@link useRevealThreadPending}, unless you need
|
|
929
|
+
* the value as of *now* rather than as of the render you closed over.
|
|
826
930
|
*
|
|
827
931
|
* @public
|
|
828
932
|
*/
|
|
@@ -861,13 +965,11 @@ export { MentionSuggestionOptions }
|
|
|
861
965
|
export declare const openThreadId: EditorAtom<null | string>;
|
|
862
966
|
|
|
863
967
|
/**
|
|
864
|
-
* Write comment records to the store, under the configured
|
|
865
|
-
*
|
|
866
|
-
* doesn't) exactly like one the built-in UI writes. Defaults to `'ignore'`.
|
|
968
|
+
* Write comment records to the store, under the configured {@link CommentingOptions.history}
|
|
969
|
+
* behavior. Defaults to `'ignore'`.
|
|
867
970
|
*
|
|
868
|
-
* Use it to seed or import threads, and to save an edit. To delete, prefer
|
|
869
|
-
* {@link
|
|
870
|
-
* soft-deleted, and a synced server rejects the hard delete.
|
|
971
|
+
* Use it to seed or import threads, and to save an edit. To delete, prefer {@link deleteComment}
|
|
972
|
+
* and {@link deleteThread}: comments are soft-deleted, and a synced server rejects the hard delete.
|
|
871
973
|
*
|
|
872
974
|
* @public
|
|
873
975
|
*/
|
|
@@ -990,6 +1092,19 @@ export declare interface ReactionSummary {
|
|
|
990
1092
|
reactors: ReactionReactor[];
|
|
991
1093
|
}
|
|
992
1094
|
|
|
1095
|
+
/**
|
|
1096
|
+
* The reaction fields {@link summarizeReactions} needs — a structural subset of
|
|
1097
|
+
* {@link tldraw#TLCommentReaction}, so tallies can also be built from rows synced outside the
|
|
1098
|
+
* editor store.
|
|
1099
|
+
*
|
|
1100
|
+
* @public
|
|
1101
|
+
*/
|
|
1102
|
+
export declare interface ReactionSummaryInput {
|
|
1103
|
+
userId: string;
|
|
1104
|
+
emoji: string;
|
|
1105
|
+
createdAt: number;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
993
1108
|
/** @public */
|
|
994
1109
|
export declare interface ReactionTooltipProps {
|
|
995
1110
|
/** Who reacted with this emoji, in reaction order. */
|
|
@@ -1001,35 +1116,26 @@ export declare interface ReactionTooltipProps {
|
|
|
1001
1116
|
/**
|
|
1002
1117
|
* Keep shape-anchored threads alive across their shape's lifecycle:
|
|
1003
1118
|
*
|
|
1004
|
-
* - When the shape is deleted, the thread converts to a `point` anchor
|
|
1005
|
-
*
|
|
1006
|
-
* shape has no bounds, which hides the pin).
|
|
1119
|
+
* - When the shape is deleted, the thread converts to a `point` anchor where its pin last sat, so
|
|
1120
|
+
* the conversation outlives the shape instead of becoming invisible.
|
|
1007
1121
|
* - When the shape moves to another page, the thread follows: its `pageId` and each comment's
|
|
1008
|
-
* denormalized `pageId` update
|
|
1009
|
-
* - When a deleted shape comes back
|
|
1010
|
-
*
|
|
1011
|
-
* meantime, in which case the manual placement wins.
|
|
1122
|
+
* denormalized `pageId` update, and the anchor keeps riding the shape.
|
|
1123
|
+
* - When a deleted shape comes back, the thread re-attaches — unless its pin was manually moved in
|
|
1124
|
+
* the meantime, in which case the manual placement wins.
|
|
1012
1125
|
*
|
|
1013
1126
|
* A page move is `deleteShapes` + re-create with preserved ids inside one `editor.run`, but each
|
|
1014
|
-
* store write is its own operation
|
|
1015
|
-
*
|
|
1016
|
-
*
|
|
1017
|
-
* that
|
|
1018
|
-
*
|
|
1019
|
-
*
|
|
1020
|
-
*
|
|
1021
|
-
*
|
|
1022
|
-
*
|
|
1023
|
-
*
|
|
1024
|
-
*
|
|
1025
|
-
*
|
|
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.
|
|
1127
|
+
* store write is its own operation, so "this shape is being moved" is never observable as a single
|
|
1128
|
+
* event. The handlers therefore cooperate across operations: `beforeDelete` snapshots where each
|
|
1129
|
+
* affected pin sits, the operation-complete pass converts threads whose shape is really gone, and
|
|
1130
|
+
* `afterCreate` plus that same pass restore the anchor once the store has settled. Undo/redo of a
|
|
1131
|
+
* move replays as a `parentId` update, so `afterChange` re-homes threads on cross-page reparents —
|
|
1132
|
+
* including threads anchored to descendants, which move without change events of their own.
|
|
1133
|
+
*
|
|
1134
|
+
* Remote changes are ignored: the client that performed the operation runs this same maintenance
|
|
1135
|
+
* and syncs the result. Writes honour the {@link CommentingOptions.history} option.
|
|
1136
|
+
*
|
|
1137
|
+
* Registered by `CanvasComments` on mount; parts-built consumers can call this directly. Returns a
|
|
1138
|
+
* cleanup function that unregisters all handlers.
|
|
1033
1139
|
*
|
|
1034
1140
|
* @public
|
|
1035
1141
|
*/
|
|
@@ -1039,12 +1145,10 @@ export declare function registerCommentAnchorLifecycle(editor: Editor): () => vo
|
|
|
1039
1145
|
* Remove comment records from the store by id, under the configured
|
|
1040
1146
|
* {@link CommentingOptions.history} behavior.
|
|
1041
1147
|
*
|
|
1042
|
-
* This is a hard delete, which is rarely what you want
|
|
1043
|
-
*
|
|
1044
|
-
*
|
|
1045
|
-
*
|
|
1046
|
-
* a local, unsynced comment store, or to drop a reaction (which is a hard delete — see
|
|
1047
|
-
* {@link toggleCommentReaction}).
|
|
1148
|
+
* This is a hard delete, which is rarely what you want: the built-in UI soft-deletes
|
|
1149
|
+
* ({@link deleteComment}, {@link deleteThread}) so the server can prune the records, and a server
|
|
1150
|
+
* enforcing per-record permissions vetoes a hard delete outright. Reach for this on a local,
|
|
1151
|
+
* unsynced store, or to drop a reaction (see {@link toggleCommentReaction}).
|
|
1048
1152
|
*
|
|
1049
1153
|
* @public
|
|
1050
1154
|
*/
|
|
@@ -1065,21 +1169,20 @@ export declare function reopenThread(editor: Editor, thread: TLCommentThread): v
|
|
|
1065
1169
|
* Mark a thread resolved, stamping who resolved it and when. Resolved threads keep their pin (a
|
|
1066
1170
|
* checked one) and are hidden from the sidebar until its "show resolved" filter is on.
|
|
1067
1171
|
*
|
|
1068
|
-
* Only the resolution is written
|
|
1069
|
-
*
|
|
1172
|
+
* Only the resolution is written — the rest of the thread is read fresh, so a stale copy can't drag
|
|
1173
|
+
* a pin back. A no-op on a thread that's gone.
|
|
1070
1174
|
*
|
|
1071
1175
|
* @public
|
|
1072
1176
|
*/
|
|
1073
1177
|
export declare function resolveThread(editor: Editor, thread: TLCommentThread, userId: string): void;
|
|
1074
1178
|
|
|
1075
1179
|
/**
|
|
1076
|
-
* Open a thread and bring it into view, given a thread id or the id of any comment in it. Use it
|
|
1077
|
-
*
|
|
1180
|
+
* Open a thread and bring it into view, given a thread id or the id of any comment in it. Use it to
|
|
1181
|
+
* jump to a thread from outside the canvas — a notification, a deep link, your own list.
|
|
1078
1182
|
*
|
|
1079
|
-
* The request is served by `CanvasComments`, so it works before the records have arrived: the
|
|
1080
|
-
*
|
|
1081
|
-
*
|
|
1082
|
-
* means nothing happens if `CanvasComments` isn't mounted.
|
|
1183
|
+
* The request is served by `CanvasComments`, so it works before the records have arrived: the layer
|
|
1184
|
+
* waits for them, switches pages, unhides pins, and zooms far enough to split the thread out of any
|
|
1185
|
+
* cluster. That also means nothing happens if `CanvasComments` isn't mounted.
|
|
1083
1186
|
*
|
|
1084
1187
|
* To open a thread you already hold and skip the wait, see {@link focusThread}.
|
|
1085
1188
|
*
|
|
@@ -1113,11 +1216,9 @@ export declare interface SendButtonProps {
|
|
|
1113
1216
|
|
|
1114
1217
|
/**
|
|
1115
1218
|
* A shape anchor for a page point. `x`/`y` are the point's normalized (0–1) offset within the
|
|
1116
|
-
* shape's own bounds
|
|
1117
|
-
*
|
|
1118
|
-
*
|
|
1119
|
-
* (top-right out of the box). Placement gestures get `precise` from the `shouldBePrecise`
|
|
1120
|
-
* commenting option (always precise, by default).
|
|
1219
|
+
* shape's own bounds, taken in the shape's own space, so a pin on a rotated shape records the spot
|
|
1220
|
+
* it was dropped on. Remembered either way: when `precise` the pin sits at exactly `x`/`y`,
|
|
1221
|
+
* otherwise at the consumer's imprecise default.
|
|
1121
1222
|
* @public
|
|
1122
1223
|
*/
|
|
1123
1224
|
export declare function shapeAnchorAt(editor: Editor, shapeId: TLShapeId, page: {
|
|
@@ -1160,29 +1261,45 @@ export declare interface SidebarFilters {
|
|
|
1160
1261
|
* @public */
|
|
1161
1262
|
export declare const sidebarFilters: EditorAtom<SidebarFilters>;
|
|
1162
1263
|
|
|
1264
|
+
/** A list row paired with the sort key that isn't part of what the row displays. @public */
|
|
1265
|
+
export declare interface SidebarRow {
|
|
1266
|
+
item: CommentListItemProps;
|
|
1267
|
+
/** When the thread's most recent comment was posted — what the list orders by. */
|
|
1268
|
+
lastActivity: number;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1163
1271
|
/**
|
|
1164
|
-
*
|
|
1165
|
-
*
|
|
1166
|
-
*
|
|
1167
|
-
*
|
|
1168
|
-
*
|
|
1272
|
+
* Order the list: unresolved threads first, then by most recent activity, id as a stable tiebreak.
|
|
1273
|
+
* Recency is the thread's *latest* comment, not its first, so a thread someone just replied to rises
|
|
1274
|
+
* to the top instead of staying wherever it was started. (The row still shows the thread's opening
|
|
1275
|
+
* comment and its date — that's what identifies the thread; only the ordering follows the replies.)
|
|
1276
|
+
*
|
|
1277
|
+
* Exported so a hand-built list can match the sidebar's ordering instead of re-deriving it.
|
|
1169
1278
|
*
|
|
1170
1279
|
* @public
|
|
1171
1280
|
*/
|
|
1172
|
-
export declare function
|
|
1281
|
+
export declare function sortSidebarRows(rows: readonly SidebarRow[]): readonly SidebarRow[];
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
* Tally a comment's reactions into an entry per emoji, ordered by when that emoji was first used so
|
|
1285
|
+
* the row stays stable as later reactions arrive. `active` marks the current user's emoji and
|
|
1286
|
+
* `reactors` lists who reacted, in reaction order. `resolveName` names each reactor; an id it can't
|
|
1287
|
+
* name falls back to a generic "Someone", never the raw user id.
|
|
1288
|
+
*
|
|
1289
|
+
* @public
|
|
1290
|
+
*/
|
|
1291
|
+
export declare function summarizeReactions(reactions: readonly ReactionSummaryInput[], currentUserId?: null | string, resolveName?: (userId: string) => string | undefined): ReactionSummary[];
|
|
1173
1292
|
|
|
1174
1293
|
/**
|
|
1175
1294
|
* Typed reads of comment records on the editor store.
|
|
1176
1295
|
*
|
|
1177
|
-
* Comment
|
|
1178
|
-
*
|
|
1179
|
-
*
|
|
1180
|
-
*
|
|
1181
|
-
* the type. These helpers own that reinterpretation — an `unknown` hop to exactly the type the store
|
|
1182
|
-
* expects, so the rest of each call stays checked — behind one boundary, and keep call sites typed.
|
|
1296
|
+
* Comment records live on the editor's local store so the canvas can render them reactively, but
|
|
1297
|
+
* they're opt-in and aren't part of the `TLRecord` union — so `editor.store` is statically typed
|
|
1298
|
+
* `Store<TLRecord>` and every access has to reinterpret the type. These helpers own that
|
|
1299
|
+
* reinterpretation behind one boundary and keep call sites typed.
|
|
1183
1300
|
*
|
|
1184
|
-
* Writes do the same
|
|
1185
|
-
*
|
|
1301
|
+
* Writes do the same, but also answer to the undo/redo policy, so they live in
|
|
1302
|
+
* `comment-mutations.ts`.
|
|
1186
1303
|
*/
|
|
1187
1304
|
/**
|
|
1188
1305
|
* A record that lives in a comment thread: the thread itself, one of its messages, or a reaction
|
|
@@ -1194,14 +1311,12 @@ export declare type TLCommentRecord = TLComment | TLCommentReaction | TLCommentT
|
|
|
1194
1311
|
/**
|
|
1195
1312
|
* Toggle one user's reaction with a given emoji on a comment.
|
|
1196
1313
|
*
|
|
1197
|
-
* Each reaction is its own record keyed by (comment, user, emoji), so this only
|
|
1198
|
-
*
|
|
1199
|
-
* `allowMultipleReactions
|
|
1314
|
+
* Each reaction is its own record keyed by (comment, user, emoji), so this only touches that user's
|
|
1315
|
+
* own records and two people reacting at once never conflict. Behaviour depends on
|
|
1316
|
+
* `allowMultipleReactions`:
|
|
1200
1317
|
*
|
|
1201
|
-
* - **multiple** (default): the emoji toggles independently
|
|
1202
|
-
*
|
|
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.
|
|
1318
|
+
* - **multiple** (default): the emoji toggles independently, leaving other reactions alone.
|
|
1319
|
+
* - **single**: a new emoji replaces the user's existing reaction; the same one removes it.
|
|
1205
1320
|
*
|
|
1206
1321
|
* @public
|
|
1207
1322
|
*/
|
|
@@ -1223,6 +1338,14 @@ export declare function toggleCommentsSidebar(editor: Editor): void;
|
|
|
1223
1338
|
*/
|
|
1224
1339
|
export declare function useCanComment(currentUserId: null | string | undefined): boolean;
|
|
1225
1340
|
|
|
1341
|
+
/**
|
|
1342
|
+
* Reactive React hook for {@link getCanModifyComment}: a `canModifyComment` callback that reads
|
|
1343
|
+
* signals re-evaluates when they change.
|
|
1344
|
+
*
|
|
1345
|
+
* @public
|
|
1346
|
+
*/
|
|
1347
|
+
export declare function useCanModifyComment(currentUserId: null | string | undefined, modification: CommentModification): boolean;
|
|
1348
|
+
|
|
1226
1349
|
/**
|
|
1227
1350
|
* Whether commenting is licensed for this editor. Enabled in development; in production it requires
|
|
1228
1351
|
* a tldraw license that includes the commenting feature (or the collaboration umbrella that grants
|
|
@@ -1230,7 +1353,7 @@ export declare function useCanComment(currentUserId: null | string | undefined):
|
|
|
1230
1353
|
* pending, so gated UI stays hidden until the license is confirmed.
|
|
1231
1354
|
*
|
|
1232
1355
|
* The built-in commenting components (`CanvasComments`, `CanvasCommentsSidebar`, and the comment
|
|
1233
|
-
* tool's
|
|
1356
|
+
* tool's Quick Action) gate on this. Use it to gate any custom commenting UI the same way.
|
|
1234
1357
|
* @public
|
|
1235
1358
|
*/
|
|
1236
1359
|
export declare function useCommentingEnabled(): boolean;
|
|
@@ -1278,11 +1401,9 @@ export declare function useOpenThreadId(): null | string;
|
|
|
1278
1401
|
/**
|
|
1279
1402
|
* Reactive React hook for {@link getRevealThreadPending}.
|
|
1280
1403
|
*
|
|
1281
|
-
* Use it to notice a reveal that never lands —
|
|
1282
|
-
*
|
|
1283
|
-
*
|
|
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.
|
|
1404
|
+
* Use it to notice a reveal that never lands — usually a deep link to a deleted comment. Give it a
|
|
1405
|
+
* grace period first, since a request also sits here while its records sync in, and re-check with
|
|
1406
|
+
* {@link getRevealThreadPending} when it elapses.
|
|
1286
1407
|
*
|
|
1287
1408
|
* @public
|
|
1288
1409
|
*/
|