@tldraw/commenting 0.0.0-bootstrap → 5.3.0-internal.41291fb579ed

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/commenting.css +284 -153
  2. package/dist-cjs/canvas/comment-body.js +1 -1
  3. package/dist-cjs/canvas/comment-body.js.map +2 -2
  4. package/dist-cjs/canvas/comment-drafts.js +54 -0
  5. package/dist-cjs/canvas/comment-drafts.js.map +7 -0
  6. package/dist-cjs/canvas/comment-render.js +2 -0
  7. package/dist-cjs/canvas/comment-render.js.map +2 -2
  8. package/dist-cjs/canvas/comment-tool.js +55 -11
  9. package/dist-cjs/canvas/comment-tool.js.map +2 -2
  10. package/dist-cjs/canvas/comments-filter-menu.js +54 -63
  11. package/dist-cjs/canvas/comments-filter-menu.js.map +2 -2
  12. package/dist-cjs/canvas/comments-overflow-menu.js +21 -27
  13. package/dist-cjs/canvas/comments-overflow-menu.js.map +2 -2
  14. package/dist-cjs/canvas/comments-overlay.js +294 -111
  15. package/dist-cjs/canvas/comments-overlay.js.map +2 -2
  16. package/dist-cjs/canvas/comments-sidebar.js +12 -18
  17. package/dist-cjs/canvas/comments-sidebar.js.map +2 -2
  18. package/dist-cjs/canvas/comments-visibility-toggle.js +66 -0
  19. package/dist-cjs/canvas/comments-visibility-toggle.js.map +7 -0
  20. package/dist-cjs/canvas/sidebar-filters.js +2 -2
  21. package/dist-cjs/canvas/sidebar-filters.js.map +2 -2
  22. package/dist-cjs/canvas/state.js +11 -0
  23. package/dist-cjs/canvas/state.js.map +2 -2
  24. package/dist-cjs/canvas/thread-state.js +8 -1
  25. package/dist-cjs/canvas/thread-state.js.map +2 -2
  26. package/dist-cjs/clustering/runtime.js +119 -7
  27. package/dist-cjs/clustering/runtime.js.map +2 -2
  28. package/dist-cjs/index.d.ts +100 -39
  29. package/dist-cjs/index.js +7 -1
  30. package/dist-cjs/index.js.map +2 -2
  31. package/dist-cjs/ui/avatar.js +14 -6
  32. package/dist-cjs/ui/avatar.js.map +2 -2
  33. package/dist-cjs/ui/byline.js +4 -4
  34. package/dist-cjs/ui/byline.js.map +2 -2
  35. package/dist-cjs/ui/comment-author.js +17 -0
  36. package/dist-cjs/ui/comment-author.js.map +7 -0
  37. package/dist-cjs/ui/comment-card.js +4 -4
  38. package/dist-cjs/ui/comment-card.js.map +2 -2
  39. package/dist-cjs/ui/comment-composer.js +92 -29
  40. package/dist-cjs/ui/comment-composer.js.map +2 -2
  41. package/dist-cjs/ui/comment-mention.js +1 -1
  42. package/dist-cjs/ui/comment-mention.js.map +2 -2
  43. package/dist-cjs/ui/comment-pin.js +23 -3
  44. package/dist-cjs/ui/comment-pin.js.map +2 -2
  45. package/dist-cjs/ui/comment-text.js +1 -1
  46. package/dist-cjs/ui/comment-text.js.map +2 -2
  47. package/dist-cjs/ui/comment-thread.js +6 -6
  48. package/dist-cjs/ui/comment-thread.js.map +2 -2
  49. package/dist-cjs/ui/comments-list.js +12 -12
  50. package/dist-cjs/ui/comments-list.js.map +2 -2
  51. package/dist-cjs/ui/count-badge.js +1 -1
  52. package/dist-cjs/ui/count-badge.js.map +2 -2
  53. package/dist-cjs/ui/empty-state.js +3 -3
  54. package/dist-cjs/ui/empty-state.js.map +2 -2
  55. package/dist-cjs/ui/format-time.js +3 -0
  56. package/dist-cjs/ui/format-time.js.map +2 -2
  57. package/dist-cjs/ui/mention-list.js +8 -8
  58. package/dist-cjs/ui/mention-list.js.map +2 -2
  59. package/dist-cjs/ui/mention-suggestion.js +3 -3
  60. package/dist-cjs/ui/mention-suggestion.js.map +2 -2
  61. package/dist-cjs/ui/mention.js +1 -1
  62. package/dist-cjs/ui/mention.js.map +2 -2
  63. package/dist-cjs/ui/reaction.js +11 -4
  64. package/dist-cjs/ui/reaction.js.map +2 -2
  65. package/dist-cjs/ui/reactions.js +10 -2
  66. package/dist-cjs/ui/reactions.js.map +2 -2
  67. package/dist-cjs/ui/send-button.js +1 -1
  68. package/dist-cjs/ui/send-button.js.map +2 -2
  69. package/dist-cjs/ui/tooltip-button.js +32 -0
  70. package/dist-cjs/ui/tooltip-button.js.map +7 -0
  71. package/dist-esm/canvas/comment-body.mjs +1 -1
  72. package/dist-esm/canvas/comment-body.mjs.map +2 -2
  73. package/dist-esm/canvas/comment-drafts.mjs +34 -0
  74. package/dist-esm/canvas/comment-drafts.mjs.map +7 -0
  75. package/dist-esm/canvas/comment-render.mjs +2 -0
  76. package/dist-esm/canvas/comment-render.mjs.map +2 -2
  77. package/dist-esm/canvas/comment-tool.mjs +56 -12
  78. package/dist-esm/canvas/comment-tool.mjs.map +2 -2
  79. package/dist-esm/canvas/comments-filter-menu.mjs +54 -63
  80. package/dist-esm/canvas/comments-filter-menu.mjs.map +2 -2
  81. package/dist-esm/canvas/comments-overflow-menu.mjs +22 -27
  82. package/dist-esm/canvas/comments-overflow-menu.mjs.map +2 -2
  83. package/dist-esm/canvas/comments-overlay.mjs +312 -113
  84. package/dist-esm/canvas/comments-overlay.mjs.map +2 -2
  85. package/dist-esm/canvas/comments-sidebar.mjs +15 -21
  86. package/dist-esm/canvas/comments-sidebar.mjs.map +2 -2
  87. package/dist-esm/canvas/comments-visibility-toggle.mjs +46 -0
  88. package/dist-esm/canvas/comments-visibility-toggle.mjs.map +7 -0
  89. package/dist-esm/canvas/sidebar-filters.mjs +2 -2
  90. package/dist-esm/canvas/sidebar-filters.mjs.map +2 -2
  91. package/dist-esm/canvas/state.mjs +11 -0
  92. package/dist-esm/canvas/state.mjs.map +2 -2
  93. package/dist-esm/canvas/thread-state.mjs +8 -1
  94. package/dist-esm/canvas/thread-state.mjs.map +2 -2
  95. package/dist-esm/clustering/runtime.mjs +119 -7
  96. package/dist-esm/clustering/runtime.mjs.map +2 -2
  97. package/dist-esm/index.d.mts +100 -39
  98. package/dist-esm/index.mjs +11 -1
  99. package/dist-esm/index.mjs.map +2 -2
  100. package/dist-esm/ui/avatar.mjs +14 -6
  101. package/dist-esm/ui/avatar.mjs.map +2 -2
  102. package/dist-esm/ui/byline.mjs +4 -4
  103. package/dist-esm/ui/byline.mjs.map +2 -2
  104. package/dist-esm/ui/comment-author.mjs +1 -0
  105. package/dist-esm/ui/comment-author.mjs.map +7 -0
  106. package/dist-esm/ui/comment-card.mjs +4 -4
  107. package/dist-esm/ui/comment-card.mjs.map +2 -2
  108. package/dist-esm/ui/comment-composer.mjs +93 -30
  109. package/dist-esm/ui/comment-composer.mjs.map +2 -2
  110. package/dist-esm/ui/comment-mention.mjs +1 -1
  111. package/dist-esm/ui/comment-mention.mjs.map +2 -2
  112. package/dist-esm/ui/comment-pin.mjs +23 -3
  113. package/dist-esm/ui/comment-pin.mjs.map +2 -2
  114. package/dist-esm/ui/comment-text.mjs +1 -1
  115. package/dist-esm/ui/comment-text.mjs.map +2 -2
  116. package/dist-esm/ui/comment-thread.mjs +6 -6
  117. package/dist-esm/ui/comment-thread.mjs.map +2 -2
  118. package/dist-esm/ui/comments-list.mjs +12 -12
  119. package/dist-esm/ui/comments-list.mjs.map +2 -2
  120. package/dist-esm/ui/count-badge.mjs +1 -1
  121. package/dist-esm/ui/count-badge.mjs.map +2 -2
  122. package/dist-esm/ui/empty-state.mjs +3 -3
  123. package/dist-esm/ui/empty-state.mjs.map +2 -2
  124. package/dist-esm/ui/format-time.mjs +3 -0
  125. package/dist-esm/ui/format-time.mjs.map +2 -2
  126. package/dist-esm/ui/mention-list.mjs +8 -8
  127. package/dist-esm/ui/mention-list.mjs.map +2 -2
  128. package/dist-esm/ui/mention-suggestion.mjs +3 -3
  129. package/dist-esm/ui/mention-suggestion.mjs.map +2 -2
  130. package/dist-esm/ui/mention.mjs +1 -1
  131. package/dist-esm/ui/mention.mjs.map +2 -2
  132. package/dist-esm/ui/reaction.mjs +11 -4
  133. package/dist-esm/ui/reaction.mjs.map +2 -2
  134. package/dist-esm/ui/reactions.mjs +10 -2
  135. package/dist-esm/ui/reactions.mjs.map +2 -2
  136. package/dist-esm/ui/send-button.mjs +1 -1
  137. package/dist-esm/ui/send-button.mjs.map +2 -2
  138. package/dist-esm/ui/tooltip-button.mjs +12 -0
  139. package/dist-esm/ui/tooltip-button.mjs.map +7 -0
  140. package/package.json +3 -3
  141. package/src/canvas/canvas.css +79 -36
  142. package/src/canvas/comment-body.tsx +1 -1
  143. package/src/canvas/comment-drafts.test.ts +55 -0
  144. package/src/canvas/comment-drafts.ts +46 -0
  145. package/src/canvas/comment-render.test.ts +1 -1
  146. package/src/canvas/comment-render.ts +7 -2
  147. package/src/canvas/comment-tool.tsx +87 -15
  148. package/src/canvas/comments-filter-menu.tsx +27 -33
  149. package/src/canvas/comments-overflow-menu.tsx +13 -21
  150. package/src/canvas/comments-overlay.tsx +431 -144
  151. package/src/canvas/comments-sidebar.tsx +27 -28
  152. package/src/canvas/comments-visibility-toggle.tsx +50 -0
  153. package/src/canvas/sidebar-filters.ts +4 -3
  154. package/src/canvas/state.ts +22 -0
  155. package/src/canvas/thread-state.ts +13 -1
  156. package/src/clustering/runtime.test.ts +183 -7
  157. package/src/clustering/runtime.ts +164 -15
  158. package/src/index.ts +6 -0
  159. package/src/ui/avatar.tsx +15 -11
  160. package/src/ui/byline.tsx +6 -5
  161. package/src/ui/comment-author.ts +15 -0
  162. package/src/ui/comment-card.tsx +6 -5
  163. package/src/ui/comment-composer.tsx +122 -33
  164. package/src/ui/comment-mention.ts +2 -2
  165. package/src/ui/comment-pin.tsx +35 -4
  166. package/src/ui/comment-text.tsx +1 -1
  167. package/src/ui/comment-thread.tsx +8 -6
  168. package/src/ui/comments-list.tsx +19 -14
  169. package/src/ui/comments.css +205 -117
  170. package/src/ui/count-badge.tsx +1 -1
  171. package/src/ui/empty-state.tsx +3 -3
  172. package/src/ui/format-time.ts +5 -0
  173. package/src/ui/mention-list.tsx +13 -16
  174. package/src/ui/mention-suggestion.tsx +3 -3
  175. package/src/ui/mention.tsx +1 -1
  176. package/src/ui/reaction.tsx +6 -3
  177. package/src/ui/reactions.tsx +6 -2
  178. package/src/ui/send-button.tsx +1 -1
  179. package/src/ui/tooltip-button.tsx +20 -0
@@ -1,6 +1,7 @@
1
1
  import { ComponentType } from 'react';
2
2
  import { Editor } from 'tldraw';
3
3
  import { EditorAtom } from 'tldraw';
4
+ import { JsonObject } from 'tldraw';
4
5
  import { JSX } from 'react/jsx-runtime';
5
6
  import type { MentionNodeAttrs } from '@tiptap/extension-mention';
6
7
  import { ReactNode } from 'react';
@@ -34,15 +35,11 @@ export declare function anchorPagePoint(editor: Editor, anchor: TLCommentAnchor,
34
35
 
35
36
  /** A commenter's avatar — their image if provided, otherwise a single-initial coloured circle.
36
37
  * @public @react */
37
- export declare function Avatar({ name, color, image }: AvatarProps): JSX.Element;
38
+ export declare function Avatar({ author }: AvatarProps): JSX.Element;
38
39
 
39
40
  /** @public */
40
41
  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;
42
+ author: CommentAuthor;
46
43
  }
47
44
 
48
45
  /** A comment's metadata line: author name, relative time, and an edited marker. @public @react */
@@ -50,7 +47,7 @@ export declare function Byline({ author, date, edited }: BylineProps): JSX.Eleme
50
47
 
51
48
  /** @public */
52
49
  export declare interface BylineProps {
53
- author: string;
50
+ author: CommentAuthor;
54
51
  /** ISO datetime; formatted to relative time by the component. */
55
52
  date: string;
56
53
  /** Shows an "edited" marker when the comment has been edited. */
@@ -74,8 +71,8 @@ export declare function CanvasComments(props: CanvasCommentsProps): JSX.Element
74
71
  export declare interface CanvasCommentsProps {
75
72
  /** The signed-in user's id, or null for a read-only viewer. Only a signed-in user composes. */
76
73
  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;
74
+ /** Map an author id to their display info, or `undefined` when the id can't be resolved. */
75
+ resolveAuthor(id: string): CommentAuthor | undefined;
79
76
  /** Called after any comment (a new thread's first comment, or a reply) is posted. */
80
77
  onPostComment?(comment: TLComment): void;
81
78
  /** Whether a comment is unread for the current user (return true for unread). */
@@ -100,17 +97,18 @@ export declare interface CanvasCommentsProps {
100
97
  }
101
98
 
102
99
  /**
103
- * A comments list panel for the current page, shown while the comment tool is active. Clicking a
104
- * thread brings its pin into view and opens it. Batteries-included over the store (a sibling to
105
- * `CanvasComments`); `CommentsList` is exported for a differently-placed or always-on list.
100
+ * A comments list panel for the current page, shown while {@link commentsSidebarOpen} is set (e.g.
101
+ * toggled by a button). Clicking a thread brings its pin into view and opens it. Batteries-included
102
+ * over the store (a sibling to `CanvasComments`); `CommentsList` is exported for a differently-placed
103
+ * or always-on list.
106
104
  * @public @react
107
105
  */
108
106
  export declare function CanvasCommentsSidebar(props: CanvasCommentsSidebarProps): JSX.Element | null;
109
107
 
110
108
  /** @public */
111
109
  export declare interface CanvasCommentsSidebarProps {
112
- /** Map an author id to a display name, or `undefined` when the id can't be named. */
113
- resolveName(id: string): string | undefined;
110
+ /** Map an author id to their display info, or `undefined` when the id can't be resolved. */
111
+ resolveAuthor(id: string): CommentAuthor | undefined;
114
112
  /** The signed-in user's id. Enables the "only your threads" filter when present. */
115
113
  currentUserId?: string;
116
114
  /**
@@ -118,8 +116,6 @@ export declare interface CanvasCommentsSidebarProps {
118
116
  * "only unread" filter when present.
119
117
  */
120
118
  isCommentUnread?(commentId: TLCommentId): boolean;
121
- /** Tool ids that show the sidebar. Defaults to the comment tool. */
122
- tools?: string[];
123
119
  /** Header above the list. */
124
120
  header?: ReactNode;
125
121
  /** Shown when the page has no threads. */
@@ -170,23 +166,43 @@ export declare interface ClusterOptions {
170
166
 
171
167
  /** @public */
172
168
  export declare interface ClusterRuntime {
173
- /** Events[0..k) are active. Exposed for tests and debugging. */
169
+ /** Events[0..k) are in the cursor (applied unless suppressed). Exposed for tests/debugging. */
174
170
  readonly k: number;
175
- /** Reset state from scratch for the given zoom (cold start / after rebuild). */
171
+ /**
172
+ * Increments whenever the displayed partition changes. Subscribe to this, not `k`: detaches
173
+ * and suppressed-event healing change the partition without moving the cursor.
174
+ */
175
+ readonly version: number;
176
+ /** Number of suppressed band events currently inside the cursor. Exposed for tests. */
177
+ getSuppressedCount(): number;
178
+ /** Number of leaves currently detached from the displayed partition. Exposed for tests. */
179
+ getDetachedCount(): number;
180
+ /** Reset state from scratch for the given zoom (cold start / after rebuild). Clears detaches. */
176
181
  seed(zoom: number): void;
177
182
  /**
178
183
  * Reset state for the given zoom, carrying hysteresis state over from a previous partition
179
184
  * (the visible map of the model being replaced). Threshold-forced events ignore history:
180
- * zoom \<= zMerge is always active, zoom \>= zSplit always inactive. An event inside its band
181
- * is active iff its members were merged together in `previous`; a band event with no history
182
- * (e.g. introduced by the rebuild) stays inactive until the next zoom-out crosses its zMerge.
183
- * Active events must form a prefix of the table, so classification stops at the first
184
- * inactive event; later band-active events conservatively resolve to split.
185
+ * zoom \<= zMerge is always merged, zoom \>= zSplit always split. An event inside its band
186
+ * keeps its previous state: merged iff its members were merged together in `previous`; a band
187
+ * event that was unmerged (or has no history, e.g. introduced by the rebuild) stays unmerged
188
+ * inside the cursor but suppressed until a zoom-out crosses its own zMerge, exactly like any
189
+ * other pending merge. Carryover is exact: no group changes state because of the swap alone.
190
+ * Clears detaches.
185
191
  */
186
192
  seedFrom(zoom: number, previous: ReadonlyMap<string, ClusterNode>): void;
187
193
  /** Advance/retreat the cursor for a camera change. No-op if zoom sits inside all bands. */
188
194
  onCamera(zoom: number): void;
189
- /** The current partition: cluster id → node. Do not mutate. */
195
+ /**
196
+ * Remove one leaf from the displayed partition without touching the event table. Local by
197
+ * construction: only the nodes containing the leaf change — a badge shrinks in place (count
198
+ * and centroid recomputed from its remaining members), a pair collapses to its surviving
199
+ * leaf, and the leaf on its own disappears. Everything else is untouched, so a deletion,
200
+ * pop-out, or thread-open never re-flows the rest of the document. The table's thresholds
201
+ * around the detached leaf go stale; the caller is expected to hold a corrected rebuild and
202
+ * adopt it (with seedFrom) at the next zoom-out. Unknown or already-detached ids are no-ops.
203
+ */
204
+ detachLeaf(leafId: string): void;
205
+ /** The displayed partition: cluster id → node, with detaches applied. Do not mutate. */
190
206
  getVisible(): ReadonlyMap<string, ClusterNode>;
191
207
  }
192
208
 
@@ -207,6 +223,20 @@ export declare function collectClusterLeaves(editor: Editor, threads: readonly T
207
223
  y: number;
208
224
  }): LeafInput[];
209
225
 
226
+ /** A comment author's display identity, resolved from an author id.
227
+ * @public */
228
+ export declare interface CommentAuthor {
229
+ name: string;
230
+ /** The author's color (any CSS color) — colors their avatar and pins.
231
+ * Omit for the default tint. */
232
+ color?: string;
233
+ /** Avatar image URL. When set, avatars show the image instead of the colored initial;
234
+ * the canvas pin keeps the initial-on-color. */
235
+ image?: string;
236
+ /** User-defined metadata for the author, never read by the toolkit (like a shape's `meta`). */
237
+ meta?: JsonObject;
238
+ }
239
+
210
240
  /**
211
241
  * Renders a comment's rich-text body read-only through the limited comment extension set (no
212
242
  * headings), so formatting (bold, links, lists, highlight) is preserved rather than flattened, and
@@ -227,7 +257,7 @@ export declare function CommentCard({ author, body, date, you, edited, actions }
227
257
 
228
258
  /** @public */
229
259
  export declare interface CommentCardProps {
230
- author: string;
260
+ author: CommentAuthor;
231
261
  /** The rendered comment body. The card doesn't dictate a format — pass a `<CommentText>`
232
262
  * for markdown, a rich-text render, or any node. */
233
263
  body: ReactNode;
@@ -251,7 +281,7 @@ export declare function CommentComposer({ author, placeholder, value, onChange,
251
281
 
252
282
  /** @public */
253
283
  export declare interface CommentComposerProps {
254
- author: string;
284
+ author: CommentAuthor;
255
285
  placeholder: string;
256
286
  /** Controlled rich-text value. Omit for the presentational (display-only) composer. */
257
287
  value?: TLRichText;
@@ -337,7 +367,7 @@ export declare interface CommentingOptions {
337
367
  /** @public */
338
368
  export declare interface CommentListItemProps {
339
369
  id: string;
340
- author: string;
370
+ author: CommentAuthor;
341
371
  /** A short preview of the thread — e.g. the first comment's body. */
342
372
  preview: ReactNode;
343
373
  /** ISO datetime of the thread's first comment. */
@@ -354,7 +384,7 @@ export declare interface CommentListItemProps {
354
384
  /** A canvas comment marker: shows its `children` (or a check when resolved). Purely
355
385
  * presentational — it reflects open/resolved state via CSS; wrap it to make it clickable.
356
386
  * @public @react */
357
- export declare function CommentPin({ children, resolved, open }: CommentPinProps): JSX.Element;
387
+ export declare function CommentPin({ children, resolved, open, color }: CommentPinProps): JSX.Element;
358
388
 
359
389
  /** @public */
360
390
  export declare interface CommentPinProps {
@@ -364,6 +394,9 @@ export declare interface CommentPinProps {
364
394
  resolved?: boolean;
365
395
  /** The pin's thread is open — shows the active/selected indicator state. */
366
396
  open?: boolean;
397
+ /** Background color (any CSS color). Falls back to the default pin tint.
398
+ * Ignored while resolved — resolved pins are always grey. */
399
+ color?: string;
367
400
  }
368
401
 
369
402
  /** The funnel dropdown in the sidebar header: toggles for which threads the list shows.
@@ -424,6 +457,20 @@ export declare function CommentsMenuItem(): JSX.Element;
424
457
  * @public @react */
425
458
  export declare function CommentsOverflowMenu(): JSX.Element;
426
459
 
460
+ /**
461
+ * Whether the comments sidebar (the thread list) is open. Driven by an explicit control — a button
462
+ * next to Share on dotcom — rather than by which tool is active, so browsing threads is separate
463
+ * from placing them. The comment tool additionally closes it on enter, keeping placement
464
+ * canvas-focused.
465
+ * @public
466
+ */
467
+ export declare const commentsSidebarOpen: EditorAtom<boolean>;
468
+
469
+ /** The sidebar header's show/hide toggle for comment pins — an eye that closes while comments
470
+ * are hidden. The same state as the Shift+C shortcut.
471
+ * @public @react */
472
+ export declare function CommentsVisibilityToggle(): JSX.Element;
473
+
427
474
  /** A comment's body, rendered as markdown (bold, italic, code, links, lists). @public @react */
428
475
  export declare function CommentText({ text }: CommentTextProps): JSX.Element;
429
476
 
@@ -458,9 +505,11 @@ export declare interface CommentThreadProps {
458
505
  }
459
506
 
460
507
  /**
461
- * The comment tool. A click starts a point/shape thread (the pin tracks the shape it lands on);
462
- * dragging out a rectangle starts a region thread anchored to that area. Placement only opens a
463
- * composer (via `pendingComment`); the records are created when the comment is posted.
508
+ * The comment tool. Pressing down opens the comment composer immediately at the pointer, and it
509
+ * follows the pointer until release — like placing a sticky note settling on a point, or on a
510
+ * shape when released over one. (With region comments enabled, dragging past the threshold instead
511
+ * draws a region rectangle.) Placement only opens a composer (via `pendingComment`); the records
512
+ * are created when the comment is posted.
464
513
  * @public
465
514
  */
466
515
  export declare class CommentTool extends StateNode {
@@ -486,6 +535,7 @@ export declare class CommentTool extends StateNode {
486
535
  */
487
536
  options: CommentingOptions;
488
537
  onEnter(): void;
538
+ onExit(): void;
489
539
  onCancel(): void;
490
540
  }
491
541
 
@@ -540,7 +590,8 @@ export declare const DEFAULT_IMPRECISE_SHAPE_ANCHOR: {
540
590
  * @public */
541
591
  export declare const DEFAULT_REGION_COMMENT_OPTIONS: RegionCommentOptions;
542
592
 
543
- /** @public */
593
+ /** The out-of-the-box view: every page's threads, resolved ones hidden until asked for.
594
+ * @public */
544
595
  export declare const DEFAULT_SIDEBAR_FILTERS: SidebarFilters;
545
596
 
546
597
  /**
@@ -641,14 +692,10 @@ export declare interface MentionListProps {
641
692
  renderMember?(member: MentionMember): ReactNode;
642
693
  }
643
694
 
644
- /** A person the composer's \@-mention picker can offer. @public */
645
- export declare interface MentionMember {
695
+ /** A person the composer's \@-mention picker can offer: a {@link CommentAuthor} plus its id and
696
+ * picker-only display fields. @public */
697
+ export declare interface MentionMember extends CommentAuthor {
646
698
  id: string;
647
- name: string;
648
- /** Avatar image URL. Falls back to a coloured initial when omitted. */
649
- avatar?: string;
650
- /** Avatar background colour, used when there's no `avatar` image. */
651
- color?: string;
652
699
  /** A secondary line under the name — e.g. an email or handle. Omit for a single-line row. */
653
700
  secondary?: string;
654
701
  /** Marks the current user; shown as a "(You)" suffix after the name. */
@@ -720,6 +767,12 @@ export declare interface ReactionProps {
720
767
  /** The row of reactions under a comment, plus an add-reaction button. @public @react */
721
768
  export declare function Reactions(): JSX.Element;
722
769
 
770
+ /** A region anchor's pin corner: the corner its creating drag released on, when recorded, else
771
+ * the editor's configured default. @public */
772
+ export declare function regionAnchorPinCorner(editor: Editor, anchor: Extract<TLCommentAnchor, {
773
+ type: 'region';
774
+ }>): VecLike;
775
+
723
776
  /**
724
777
  * The configurable dimensions of region comments — a design surface for prototyping the interaction
725
778
  * before settling it. Region is **off by default**, so a consumer that leaves it unset keeps plain
@@ -820,6 +873,10 @@ export declare type TLCommentRecord = TLComment | TLCommentThread;
820
873
  * @public */
821
874
  export declare function toggleCommentsHidden(editor: Editor): void;
822
875
 
876
+ /** Open or close the comments sidebar for an editor.
877
+ * @public */
878
+ export declare function toggleCommentsSidebar(editor: Editor): void;
879
+
823
880
  /**
824
881
  * Whether commenting is licensed for this editor. Enabled in development; in production it requires
825
882
  * a tldraw license that includes the commenting feature (or the collaboration umbrella that grants
@@ -847,6 +904,10 @@ export declare function useComments(editor: Editor): TLComment[];
847
904
  * @public */
848
905
  export declare function useCommentsHidden(): boolean;
849
906
 
907
+ /** React hook for whether the comments sidebar is open.
908
+ * @public */
909
+ export declare function useCommentsSidebarOpen(): boolean;
910
+
850
911
  /** All comment threads in the store, reactively. @public */
851
912
  export declare function useCommentThreads(editor: Editor): TLCommentThread[];
852
913
 
package/dist-cjs/index.js CHANGED
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  CommentsList: () => import_comments_list.CommentsList,
34
34
  CommentsMenuItem: () => import_comments_menu_item.CommentsMenuItem,
35
35
  CommentsOverflowMenu: () => import_comments_overflow_menu.CommentsOverflowMenu,
36
+ CommentsVisibilityToggle: () => import_comments_visibility_toggle.CommentsVisibilityToggle,
36
37
  CountBadge: () => import_count_badge.CountBadge,
37
38
  DEFAULT_IMPRECISE_SHAPE_ANCHOR: () => import_thread_state.DEFAULT_IMPRECISE_SHAPE_ANCHOR,
38
39
  DEFAULT_REGION_COMMENT_OPTIONS: () => import_region_options.DEFAULT_REGION_COMMENT_OPTIONS,
@@ -48,6 +49,7 @@ __export(index_exports, {
48
49
  commentToolOverrides: () => import_comment_tool.commentToolOverrides,
49
50
  commentTools: () => import_comment_tool.commentTools,
50
51
  commentsHidden: () => import_state.commentsHidden,
52
+ commentsSidebarOpen: () => import_state.commentsSidebarOpen,
51
53
  commitCommentMutation: () => import_state.commitCommentMutation,
52
54
  computeClusterTable: () => import_computeClusterTable.computeClusterTable,
53
55
  createClusterRuntime: () => import_runtime.createClusterRuntime,
@@ -63,17 +65,20 @@ __export(index_exports, {
63
65
  openThreadId: () => import_state.openThreadId,
64
66
  pendingComment: () => import_state.pendingComment,
65
67
  putCommentRecords: () => import_comment_store.putCommentRecords,
68
+ regionAnchorPinCorner: () => import_thread_state.regionAnchorPinCorner,
66
69
  removeCommentRecords: () => import_comment_store.removeCommentRecords,
67
70
  renderMarkdown: () => import_render_markdown.renderMarkdown,
68
71
  richTextToPlaintext: () => import_rich_text.richTextToPlaintext,
69
72
  shapeAnchorAt: () => import_thread_state.shapeAnchorAt,
70
73
  sidebarFilters: () => import_state.sidebarFilters,
71
74
  toggleCommentsHidden: () => import_state.toggleCommentsHidden,
75
+ toggleCommentsSidebar: () => import_state.toggleCommentsSidebar,
72
76
  useCommentThreads: () => import_hooks.useCommentThreads,
73
77
  useCommentingEnabled: () => import_license.useCommentingEnabled,
74
78
  useCommentingOptions: () => import_options.useCommentingOptions,
75
79
  useComments: () => import_hooks.useComments,
76
80
  useCommentsHidden: () => import_state.useCommentsHidden,
81
+ useCommentsSidebarOpen: () => import_state.useCommentsSidebarOpen,
77
82
  useOpenThreadId: () => import_state.useOpenThreadId,
78
83
  usePendingComment: () => import_state.usePendingComment,
79
84
  useSidebarFilters: () => import_state.useSidebarFilters,
@@ -110,6 +115,7 @@ var import_comments_menu_item = require("./canvas/comments-menu-item");
110
115
  var import_comments_overlay = require("./canvas/comments-overlay");
111
116
  var import_options = require("./canvas/options");
112
117
  var import_comments_overflow_menu = require("./canvas/comments-overflow-menu");
118
+ var import_comments_visibility_toggle = require("./canvas/comments-visibility-toggle");
113
119
  var import_comments_sidebar = require("./canvas/comments-sidebar");
114
120
  var import_hooks = require("./canvas/hooks");
115
121
  var import_license = require("./canvas/license");
@@ -120,7 +126,7 @@ var import_state = require("./canvas/state");
120
126
  var import_thread_state = require("./canvas/thread-state");
121
127
  (0, import_utils.registerTldrawLibraryVersion)(
122
128
  "@tldraw/commenting",
123
- "0.0.0-bootstrap",
129
+ "5.3.0-internal.41291fb579ed",
124
130
  "cjs"
125
131
  );
126
132
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["import { registerTldrawLibraryVersion } from '@tldraw/utils'\n\n// Presentational commenting components. These are tldraw-independent and can be used to build\n// custom commenting UI.\nexport { Avatar, type AvatarProps } from './ui/avatar'\nexport { Byline, type BylineProps } from './ui/byline'\nexport { CommentCard, type CommentCardProps } from './ui/comment-card'\nexport { CommentComposer, type CommentComposerProps } from './ui/comment-composer'\nexport { CountBadge, type CountBadgeProps } from './ui/count-badge'\nexport { CommentPin, type CommentPinProps } from './ui/comment-pin'\nexport { CommentText, type CommentTextProps } from './ui/comment-text'\nexport { CommentThread, type CommentThreadProps } from './ui/comment-thread'\nexport { CommentsList, type CommentListItemProps, type CommentsListProps } from './ui/comments-list'\nexport { EmptyState, type EmptyStateProps } from './ui/empty-state'\nexport { formatRelativeTime } from './ui/format-time'\nexport { Mention, type MentionProps } from './ui/mention'\nexport { MentionList, type MentionListProps, type MentionMember } from './ui/mention-list'\nexport {\n\tcreateMentionSuggestion,\n\tfilterMentionMembers,\n\ttype MentionSuggestionOptions,\n} from './ui/mention-suggestion'\nexport { Reaction, type ReactionProps } from './ui/reaction'\nexport { Reactions } from './ui/reactions'\nexport { renderMarkdown } from './ui/render-markdown'\nexport { SendButton, type SendButtonProps } from './ui/send-button'\n\n// The tldraw-coupled commenting layer: the comment tool, reactive hooks over the comment\n// records, a rich-text body renderer, and a batteries-included <CanvasComments> overlay. Pairs\n// with the presentational components above.\nexport { CommentBody, type CommentBodyProps } from './canvas/comment-body'\nexport {\n\tCommentTool,\n\tcommentToolOverrides,\n\tcommentTools,\n\ttype PendingComment,\n} from './canvas/comment-tool'\nexport { collectClusterLeaves } from './canvas/cluster-input'\nexport { computeClusterTable } from './clustering/computeClusterTable'\nexport {\n\tgetCommentRecord,\n\tgetComments,\n\tgetCommentThreads,\n\tputCommentRecords,\n\tremoveCommentRecords,\n\ttype TLCommentRecord,\n} from './canvas/comment-store'\nexport { createClusterRuntime, type ClusterRuntime } from './clustering/runtime'\nexport type {\n\tClusterNode,\n\tClusterOptions,\n\tClusterTable,\n\tLeafInput,\n\tMergeEvent,\n} from './clustering/types'\nexport { CommentsFilterMenu, type CommentsFilterMenuProps } from './canvas/comments-filter-menu'\nexport { CommentsMenuItem } from './canvas/comments-menu-item'\nexport { CanvasComments, type CanvasCommentsProps } from './canvas/comments-overlay'\nexport {\n\ttype CommentingComponents,\n\ttype CommentingOptions,\n\tdefaultCommentingOptions,\n\tgetCommentingOptions,\n\tuseCommentingOptions,\n} from './canvas/options'\nexport { CommentsOverflowMenu } from './canvas/comments-overflow-menu'\nexport { CanvasCommentsSidebar, type CanvasCommentsSidebarProps } from './canvas/comments-sidebar'\nexport { useComments, useCommentThreads, useThreadComments } from './canvas/hooks'\nexport { useCommentingEnabled } from './canvas/license'\nexport { DEFAULT_REGION_COMMENT_OPTIONS, type RegionCommentOptions } from './canvas/region-options'\nexport { richTextToPlaintext } from './canvas/rich-text'\nexport { DEFAULT_SIDEBAR_FILTERS, type SidebarFilters } from './canvas/sidebar-filters'\nexport {\n\tcommentsHidden,\n\tcommitCommentMutation,\n\topenThreadId,\n\tpendingComment,\n\tsidebarFilters,\n\ttoggleCommentsHidden,\n\tuseCommentsHidden,\n\tuseOpenThreadId,\n\tusePendingComment,\n\tuseSidebarFilters,\n} from './canvas/state'\nexport {\n\tanchorPagePoint,\n\tDEFAULT_IMPRECISE_SHAPE_ANCHOR,\n\tfocusThread,\n\tshapeAnchorAt,\n} from './canvas/thread-state'\n\nregisterTldrawLibraryVersion(\n\t(globalThis as any).TLDRAW_LIBRARY_NAME,\n\t(globalThis as any).TLDRAW_LIBRARY_VERSION,\n\t(globalThis as any).TLDRAW_LIBRARY_MODULES\n)\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA6C;AAI7C,oBAAyC;AACzC,oBAAyC;AACzC,0BAAmD;AACnD,8BAA2D;AAC3D,yBAAiD;AACjD,yBAAiD;AACjD,0BAAmD;AACnD,4BAAuD;AACvD,2BAAgF;AAChF,yBAAiD;AACjD,yBAAmC;AACnC,qBAA2C;AAC3C,0BAAuE;AACvE,gCAIO;AACP,sBAA6C;AAC7C,uBAA0B;AAC1B,6BAA+B;AAC/B,yBAAiD;AAKjD,0BAAmD;AACnD,0BAKO;AACP,2BAAqC;AACrC,iCAAoC;AACpC,2BAOO;AACP,qBAA0D;AAQ1D,kCAAiE;AACjE,gCAAiC;AACjC,8BAAyD;AACzD,qBAMO;AACP,oCAAqC;AACrC,8BAAuE;AACvE,mBAAkE;AAClE,qBAAqC;AACrC,4BAA0E;AAC1E,uBAAoC;AACpC,6BAA6D;AAC7D,mBAWO;AACP,0BAKO;AAAA,IAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;",
4
+ "sourcesContent": ["import { registerTldrawLibraryVersion } from '@tldraw/utils'\n\n// Presentational commenting components. These are tldraw-independent and can be used to build\n// custom commenting UI.\nexport { Avatar, type AvatarProps } from './ui/avatar'\nexport { Byline, type BylineProps } from './ui/byline'\nexport { type CommentAuthor } from './ui/comment-author'\nexport { CommentCard, type CommentCardProps } from './ui/comment-card'\nexport { CommentComposer, type CommentComposerProps } from './ui/comment-composer'\nexport { CountBadge, type CountBadgeProps } from './ui/count-badge'\nexport { CommentPin, type CommentPinProps } from './ui/comment-pin'\nexport { CommentText, type CommentTextProps } from './ui/comment-text'\nexport { CommentThread, type CommentThreadProps } from './ui/comment-thread'\nexport { CommentsList, type CommentListItemProps, type CommentsListProps } from './ui/comments-list'\nexport { EmptyState, type EmptyStateProps } from './ui/empty-state'\nexport { formatRelativeTime } from './ui/format-time'\nexport { Mention, type MentionProps } from './ui/mention'\nexport { MentionList, type MentionListProps, type MentionMember } from './ui/mention-list'\nexport {\n\tcreateMentionSuggestion,\n\tfilterMentionMembers,\n\ttype MentionSuggestionOptions,\n} from './ui/mention-suggestion'\nexport { Reaction, type ReactionProps } from './ui/reaction'\nexport { Reactions } from './ui/reactions'\nexport { renderMarkdown } from './ui/render-markdown'\nexport { SendButton, type SendButtonProps } from './ui/send-button'\n\n// The tldraw-coupled commenting layer: the comment tool, reactive hooks over the comment\n// records, a rich-text body renderer, and a batteries-included <CanvasComments> overlay. Pairs\n// with the presentational components above.\nexport { CommentBody, type CommentBodyProps } from './canvas/comment-body'\nexport {\n\tCommentTool,\n\tcommentToolOverrides,\n\tcommentTools,\n\ttype PendingComment,\n} from './canvas/comment-tool'\nexport { collectClusterLeaves } from './canvas/cluster-input'\nexport { computeClusterTable } from './clustering/computeClusterTable'\nexport {\n\tgetCommentRecord,\n\tgetComments,\n\tgetCommentThreads,\n\tputCommentRecords,\n\tremoveCommentRecords,\n\ttype TLCommentRecord,\n} from './canvas/comment-store'\nexport { createClusterRuntime, type ClusterRuntime } from './clustering/runtime'\nexport type {\n\tClusterNode,\n\tClusterOptions,\n\tClusterTable,\n\tLeafInput,\n\tMergeEvent,\n} from './clustering/types'\nexport { CommentsFilterMenu, type CommentsFilterMenuProps } from './canvas/comments-filter-menu'\nexport { CommentsMenuItem } from './canvas/comments-menu-item'\nexport { CanvasComments, type CanvasCommentsProps } from './canvas/comments-overlay'\nexport {\n\ttype CommentingComponents,\n\ttype CommentingOptions,\n\tdefaultCommentingOptions,\n\tgetCommentingOptions,\n\tuseCommentingOptions,\n} from './canvas/options'\nexport { CommentsOverflowMenu } from './canvas/comments-overflow-menu'\nexport { CommentsVisibilityToggle } from './canvas/comments-visibility-toggle'\nexport { CanvasCommentsSidebar, type CanvasCommentsSidebarProps } from './canvas/comments-sidebar'\nexport { useComments, useCommentThreads, useThreadComments } from './canvas/hooks'\nexport { useCommentingEnabled } from './canvas/license'\nexport { DEFAULT_REGION_COMMENT_OPTIONS, type RegionCommentOptions } from './canvas/region-options'\nexport { richTextToPlaintext } from './canvas/rich-text'\nexport { DEFAULT_SIDEBAR_FILTERS, type SidebarFilters } from './canvas/sidebar-filters'\nexport {\n\tcommentsHidden,\n\tcommentsSidebarOpen,\n\tcommitCommentMutation,\n\topenThreadId,\n\tpendingComment,\n\tsidebarFilters,\n\ttoggleCommentsHidden,\n\ttoggleCommentsSidebar,\n\tuseCommentsHidden,\n\tuseCommentsSidebarOpen,\n\tuseOpenThreadId,\n\tusePendingComment,\n\tuseSidebarFilters,\n} from './canvas/state'\nexport {\n\tanchorPagePoint,\n\tDEFAULT_IMPRECISE_SHAPE_ANCHOR,\n\tfocusThread,\n\tregionAnchorPinCorner,\n\tshapeAnchorAt,\n} from './canvas/thread-state'\n\nregisterTldrawLibraryVersion(\n\t(globalThis as any).TLDRAW_LIBRARY_NAME,\n\t(globalThis as any).TLDRAW_LIBRARY_VERSION,\n\t(globalThis as any).TLDRAW_LIBRARY_MODULES\n)\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA6C;AAI7C,oBAAyC;AACzC,oBAAyC;AAEzC,0BAAmD;AACnD,8BAA2D;AAC3D,yBAAiD;AACjD,yBAAiD;AACjD,0BAAmD;AACnD,4BAAuD;AACvD,2BAAgF;AAChF,yBAAiD;AACjD,yBAAmC;AACnC,qBAA2C;AAC3C,0BAAuE;AACvE,gCAIO;AACP,sBAA6C;AAC7C,uBAA0B;AAC1B,6BAA+B;AAC/B,yBAAiD;AAKjD,0BAAmD;AACnD,0BAKO;AACP,2BAAqC;AACrC,iCAAoC;AACpC,2BAOO;AACP,qBAA0D;AAQ1D,kCAAiE;AACjE,gCAAiC;AACjC,8BAAyD;AACzD,qBAMO;AACP,oCAAqC;AACrC,wCAAyC;AACzC,8BAAuE;AACvE,mBAAkE;AAClE,qBAAqC;AACrC,4BAA0E;AAC1E,uBAAoC;AACpC,6BAA6D;AAC7D,mBAcO;AACP,0BAMO;AAAA,IAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;",
6
6
  "names": []
7
7
  }
@@ -26,17 +26,25 @@ var import_tldraw = require("tldraw");
26
26
  function initial(name) {
27
27
  return ((0, import_tldraw.getFirstCharacter)(name.trim()) || "?").toUpperCase();
28
28
  }
29
- function Avatar({ name, color, image }) {
30
- if (image) {
31
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { className: "cmt-avatar cmt-avatar--image", src: image, alt: "", "aria-hidden": "true" });
29
+ function Avatar({ author }) {
30
+ if (author.image) {
31
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
32
+ "img",
33
+ {
34
+ className: "tlui-cmt-avatar tlui-cmt-avatar--image",
35
+ src: author.image,
36
+ alt: "",
37
+ "aria-hidden": "true"
38
+ }
39
+ );
32
40
  }
33
41
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
34
42
  "div",
35
43
  {
36
- className: "cmt-avatar",
44
+ className: "tlui-cmt-avatar",
37
45
  "aria-hidden": "true",
38
- style: color ? { backgroundColor: color } : void 0,
39
- children: initial(name)
46
+ style: author.color ? { backgroundColor: author.color } : void 0,
47
+ children: initial(author.name)
40
48
  }
41
49
  );
42
50
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/ui/avatar.tsx"],
4
- "sourcesContent": ["import { getFirstCharacter } from 'tldraw'\n\n/** @public */\nexport interface AvatarProps {\n\tname: string\n\t/** Background colour, used when there's no `image`. Falls back to the default avatar tint. */\n\tcolor?: string\n\t/** Avatar image URL. When set, shows the image instead of the coloured initial. */\n\timage?: string\n}\n\nfunction initial(name: string) {\n\treturn (getFirstCharacter(name.trim()) || '?').toUpperCase()\n}\n\n/** A commenter's avatar \u2014 their image if provided, otherwise a single-initial coloured circle.\n * @public @react */\nexport function Avatar({ name, color, image }: AvatarProps) {\n\tif (image) {\n\t\treturn <img className=\"cmt-avatar cmt-avatar--image\" src={image} alt=\"\" aria-hidden=\"true\" />\n\t}\n\treturn (\n\t\t<div\n\t\t\tclassName=\"cmt-avatar\"\n\t\t\taria-hidden=\"true\"\n\t\t\tstyle={color ? { backgroundColor: color } : undefined}\n\t\t>\n\t\t\t{initial(name)}\n\t\t</div>\n\t)\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBS;AAnBT,oBAAkC;AAWlC,SAAS,QAAQ,MAAc;AAC9B,cAAQ,iCAAkB,KAAK,KAAK,CAAC,KAAK,KAAK,YAAY;AAC5D;AAIO,SAAS,OAAO,EAAE,MAAM,OAAO,MAAM,GAAgB;AAC3D,MAAI,OAAO;AACV,WAAO,4CAAC,SAAI,WAAU,gCAA+B,KAAK,OAAO,KAAI,IAAG,eAAY,QAAO;AAAA,EAC5F;AACA,SACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAU;AAAA,MACV,eAAY;AAAA,MACZ,OAAO,QAAQ,EAAE,iBAAiB,MAAM,IAAI;AAAA,MAE3C,kBAAQ,IAAI;AAAA;AAAA,EACd;AAEF;",
4
+ "sourcesContent": ["import { getFirstCharacter } from 'tldraw'\nimport { CommentAuthor } from './comment-author'\n\n/** @public */\nexport interface AvatarProps {\n\tauthor: CommentAuthor\n}\n\nfunction initial(name: string) {\n\treturn (getFirstCharacter(name.trim()) || '?').toUpperCase()\n}\n\n/** A commenter's avatar \u2014 their image if provided, otherwise a single-initial coloured circle.\n * @public @react */\nexport function Avatar({ author }: AvatarProps) {\n\tif (author.image) {\n\t\treturn (\n\t\t\t<img\n\t\t\t\tclassName=\"tlui-cmt-avatar tlui-cmt-avatar--image\"\n\t\t\t\tsrc={author.image}\n\t\t\t\talt=\"\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t/>\n\t\t)\n\t}\n\treturn (\n\t\t<div\n\t\t\tclassName=\"tlui-cmt-avatar\"\n\t\t\taria-hidden=\"true\"\n\t\t\tstyle={author.color ? { backgroundColor: author.color } : undefined}\n\t\t>\n\t\t\t{initial(author.name)}\n\t\t</div>\n\t)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBG;AAjBH,oBAAkC;AAQlC,SAAS,QAAQ,MAAc;AAC9B,cAAQ,iCAAkB,KAAK,KAAK,CAAC,KAAK,KAAK,YAAY;AAC5D;AAIO,SAAS,OAAO,EAAE,OAAO,GAAgB;AAC/C,MAAI,OAAO,OAAO;AACjB,WACC;AAAA,MAAC;AAAA;AAAA,QACA,WAAU;AAAA,QACV,KAAK,OAAO;AAAA,QACZ,KAAI;AAAA,QACJ,eAAY;AAAA;AAAA,IACb;AAAA,EAEF;AACA,SACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAU;AAAA,MACV,eAAY;AAAA,MACZ,OAAO,OAAO,QAAQ,EAAE,iBAAiB,OAAO,MAAM,IAAI;AAAA,MAEzD,kBAAQ,OAAO,IAAI;AAAA;AAAA,EACrB;AAEF;",
6
6
  "names": []
7
7
  }
@@ -24,11 +24,11 @@ module.exports = __toCommonJS(byline_exports);
24
24
  var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_format_time = require("./format-time");
26
26
  function Byline({ author, date, edited }) {
27
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cmt-head", children: [
28
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cmt-author", children: author }),
29
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "cmt-time", children: [
27
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "tlui-cmt-head", children: [
28
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tlui-cmt-author", children: author.name }),
29
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "tlui-cmt-time", children: [
30
30
  (0, import_format_time.formatRelativeTime)(date),
31
- edited && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cmt-edited", children: " \xB7 edited" })
31
+ edited && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tlui-cmt-edited", children: " \xB7 edited" })
32
32
  ] })
33
33
  ] });
34
34
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/ui/byline.tsx"],
4
- "sourcesContent": ["import { formatRelativeTime } from './format-time'\n\n/** @public */\nexport interface BylineProps {\n\tauthor: string\n\t/** ISO datetime; formatted to relative time by the component. */\n\tdate: string\n\t/** Shows an \"edited\" marker when the comment has been edited. */\n\tedited?: boolean\n}\n\n/** A comment's metadata line: author name, relative time, and an edited marker. @public @react */\nexport function Byline({ author, date, edited }: BylineProps) {\n\treturn (\n\t\t<div className=\"cmt-head\">\n\t\t\t<span className=\"cmt-author\">{author}</span>\n\t\t\t<span className=\"cmt-time\">\n\t\t\t\t{formatRelativeTime(date)}\n\t\t\t\t{edited && <span className=\"cmt-edited\"> \u00B7 edited</span>}\n\t\t\t</span>\n\t\t</div>\n\t)\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAeG;AAfH,yBAAmC;AAY5B,SAAS,OAAO,EAAE,QAAQ,MAAM,OAAO,GAAgB;AAC7D,SACC,6CAAC,SAAI,WAAU,YACd;AAAA,gDAAC,UAAK,WAAU,cAAc,kBAAO;AAAA,IACrC,6CAAC,UAAK,WAAU,YACd;AAAA,iDAAmB,IAAI;AAAA,MACvB,UAAU,4CAAC,UAAK,WAAU,cAAa,0BAAS;AAAA,OAClD;AAAA,KACD;AAEF;",
4
+ "sourcesContent": ["import { CommentAuthor } from './comment-author'\nimport { formatRelativeTime } from './format-time'\n\n/** @public */\nexport interface BylineProps {\n\tauthor: CommentAuthor\n\t/** ISO datetime; formatted to relative time by the component. */\n\tdate: string\n\t/** Shows an \"edited\" marker when the comment has been edited. */\n\tedited?: boolean\n}\n\n/** A comment's metadata line: author name, relative time, and an edited marker. @public @react */\nexport function Byline({ author, date, edited }: BylineProps) {\n\treturn (\n\t\t<div className=\"tlui-cmt-head\">\n\t\t\t<span className=\"tlui-cmt-author\">{author.name}</span>\n\t\t\t<span className=\"tlui-cmt-time\">\n\t\t\t\t{formatRelativeTime(date)}\n\t\t\t\t{edited && <span className=\"tlui-cmt-edited\"> \u00B7 edited</span>}\n\t\t\t</span>\n\t\t</div>\n\t)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBG;AAfH,yBAAmC;AAY5B,SAAS,OAAO,EAAE,QAAQ,MAAM,OAAO,GAAgB;AAC7D,SACC,6CAAC,SAAI,WAAU,iBACd;AAAA,gDAAC,UAAK,WAAU,mBAAmB,iBAAO,MAAK;AAAA,IAC/C,6CAAC,UAAK,WAAU,iBACd;AAAA,iDAAmB,IAAI;AAAA,MACvB,UAAU,4CAAC,UAAK,WAAU,mBAAkB,0BAAS;AAAA,OACvD;AAAA,KACD;AAEF;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+ var comment_author_exports = {};
16
+ module.exports = __toCommonJS(comment_author_exports);
17
+ //# sourceMappingURL=comment-author.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ui/comment-author.ts"],
4
+ "sourcesContent": ["import { JsonObject } from 'tldraw'\n\n/** A comment author's display identity, resolved from an author id.\n * @public */\nexport interface CommentAuthor {\n\tname: string\n\t/** The author's color (any CSS color) \u2014 colors their avatar and pins.\n\t * Omit for the default tint. */\n\tcolor?: string\n\t/** Avatar image URL. When set, avatars show the image instead of the colored initial;\n\t * the canvas pin keeps the initial-on-color. */\n\timage?: string\n\t/** User-defined metadata for the author, never read by the toolkit (like a shape's `meta`). */\n\tmeta?: JsonObject\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
6
+ "names": []
7
+ }
@@ -25,13 +25,13 @@ var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_avatar = require("./avatar");
26
26
  var import_byline = require("./byline");
27
27
  function CommentCard({ author, body, date, you, edited, actions }) {
28
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: you ? "cmt-card cmt-card--you" : "cmt-card", children: [
29
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_avatar.Avatar, { name: author }),
30
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cmt-body", children: [
28
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: you ? "tlui-cmt-card tlui-cmt-card--you" : "tlui-cmt-card", children: [
29
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_avatar.Avatar, { author }),
30
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "tlui-cmt-body", children: [
31
31
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_byline.Byline, { author, date, edited }),
32
32
  body
33
33
  ] }),
34
- actions !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cmt-card__actions", children: actions })
34
+ actions !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tlui-cmt-card__actions", children: actions })
35
35
  ] });
36
36
  }
37
37
  //# sourceMappingURL=comment-card.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/ui/comment-card.tsx"],
4
- "sourcesContent": ["import { ReactNode } from 'react'\nimport { Avatar } from './avatar'\nimport { Byline } from './byline'\n\n/** @public */\nexport interface CommentCardProps {\n\tauthor: string\n\t/** The rendered comment body. The card doesn't dictate a format \u2014 pass a `<CommentText>`\n\t * for markdown, a rich-text render, or any node. */\n\tbody: ReactNode\n\t/** ISO datetime; formatted to relative time by the component. */\n\tdate: string\n\tyou: boolean\n\t/** Whether the comment has been edited (shows an \"edited\" marker). */\n\tedited?: boolean\n\t/** Hover-revealed controls at the card's top-right (e.g. an edit affordance). */\n\tactions?: ReactNode\n}\n\n/** A single comment: Avatar, Byline, and a body slot the consumer renders. @public @react */\nexport function CommentCard({ author, body, date, you, edited, actions }: CommentCardProps) {\n\treturn (\n\t\t<div className={you ? 'cmt-card cmt-card--you' : 'cmt-card'}>\n\t\t\t<Avatar name={author} />\n\t\t\t<div className=\"cmt-body\">\n\t\t\t\t<Byline author={author} date={date} edited={edited} />\n\t\t\t\t{body}\n\t\t\t</div>\n\t\t\t{actions !== undefined && <div className=\"cmt-card__actions\">{actions}</div>}\n\t\t</div>\n\t)\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBG;AAtBH,oBAAuB;AACvB,oBAAuB;AAkBhB,SAAS,YAAY,EAAE,QAAQ,MAAM,MAAM,KAAK,QAAQ,QAAQ,GAAqB;AAC3F,SACC,6CAAC,SAAI,WAAW,MAAM,2BAA2B,YAChD;AAAA,gDAAC,wBAAO,MAAM,QAAQ;AAAA,IACtB,6CAAC,SAAI,WAAU,YACd;AAAA,kDAAC,wBAAO,QAAgB,MAAY,QAAgB;AAAA,MACnD;AAAA,OACF;AAAA,IACC,YAAY,UAAa,4CAAC,SAAI,WAAU,qBAAqB,mBAAQ;AAAA,KACvE;AAEF;",
4
+ "sourcesContent": ["import { ReactNode } from 'react'\nimport { Avatar } from './avatar'\nimport { Byline } from './byline'\nimport { CommentAuthor } from './comment-author'\n\n/** @public */\nexport interface CommentCardProps {\n\tauthor: CommentAuthor\n\t/** The rendered comment body. The card doesn't dictate a format \u2014 pass a `<CommentText>`\n\t * for markdown, a rich-text render, or any node. */\n\tbody: ReactNode\n\t/** ISO datetime; formatted to relative time by the component. */\n\tdate: string\n\tyou: boolean\n\t/** Whether the comment has been edited (shows an \"edited\" marker). */\n\tedited?: boolean\n\t/** Hover-revealed controls at the card's top-right (e.g. an edit affordance). */\n\tactions?: ReactNode\n}\n\n/** A single comment: Avatar, Byline, and a body slot the consumer renders. @public @react */\nexport function CommentCard({ author, body, date, you, edited, actions }: CommentCardProps) {\n\treturn (\n\t\t<div className={you ? 'tlui-cmt-card tlui-cmt-card--you' : 'tlui-cmt-card'}>\n\t\t\t<Avatar author={author} />\n\t\t\t<div className=\"tlui-cmt-body\">\n\t\t\t\t<Byline author={author} date={date} edited={edited} />\n\t\t\t\t{body}\n\t\t\t</div>\n\t\t\t{actions !== undefined && <div className=\"tlui-cmt-card__actions\">{actions}</div>}\n\t\t</div>\n\t)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBG;AAvBH,oBAAuB;AACvB,oBAAuB;AAmBhB,SAAS,YAAY,EAAE,QAAQ,MAAM,MAAM,KAAK,QAAQ,QAAQ,GAAqB;AAC3F,SACC,6CAAC,SAAI,WAAW,MAAM,qCAAqC,iBAC1D;AAAA,gDAAC,wBAAO,QAAgB;AAAA,IACxB,6CAAC,SAAI,WAAU,iBACd;AAAA,kDAAC,wBAAO,QAAgB,MAAY,QAAgB;AAAA,MACnD;AAAA,OACF;AAAA,IACC,YAAY,UAAa,4CAAC,SAAI,WAAU,0BAA0B,mBAAQ;AAAA,KAC5E;AAEF;",
6
6
  "names": []
7
7
  }