@tldraw/commenting 0.0.0-bootstrap → 5.3.0-internal.1640468db8fd

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 (184) 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 +65 -12
  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 +304 -112
  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/options.js +1 -0
  21. package/dist-cjs/canvas/options.js.map +2 -2
  22. package/dist-cjs/canvas/sidebar-filters.js +2 -2
  23. package/dist-cjs/canvas/sidebar-filters.js.map +2 -2
  24. package/dist-cjs/canvas/state.js +11 -0
  25. package/dist-cjs/canvas/state.js.map +2 -2
  26. package/dist-cjs/canvas/thread-state.js +8 -1
  27. package/dist-cjs/canvas/thread-state.js.map +2 -2
  28. package/dist-cjs/clustering/runtime.js +119 -7
  29. package/dist-cjs/clustering/runtime.js.map +2 -2
  30. package/dist-cjs/index.d.ts +126 -41
  31. package/dist-cjs/index.js +7 -1
  32. package/dist-cjs/index.js.map +2 -2
  33. package/dist-cjs/ui/avatar.js +14 -6
  34. package/dist-cjs/ui/avatar.js.map +2 -2
  35. package/dist-cjs/ui/byline.js +4 -4
  36. package/dist-cjs/ui/byline.js.map +2 -2
  37. package/dist-cjs/ui/comment-author.js +17 -0
  38. package/dist-cjs/ui/comment-author.js.map +7 -0
  39. package/dist-cjs/ui/comment-card.js +4 -4
  40. package/dist-cjs/ui/comment-card.js.map +2 -2
  41. package/dist-cjs/ui/comment-composer.js +92 -29
  42. package/dist-cjs/ui/comment-composer.js.map +2 -2
  43. package/dist-cjs/ui/comment-mention.js +1 -1
  44. package/dist-cjs/ui/comment-mention.js.map +2 -2
  45. package/dist-cjs/ui/comment-pin.js +23 -3
  46. package/dist-cjs/ui/comment-pin.js.map +2 -2
  47. package/dist-cjs/ui/comment-text.js +1 -1
  48. package/dist-cjs/ui/comment-text.js.map +2 -2
  49. package/dist-cjs/ui/comment-thread.js +6 -6
  50. package/dist-cjs/ui/comment-thread.js.map +2 -2
  51. package/dist-cjs/ui/comments-list.js +12 -12
  52. package/dist-cjs/ui/comments-list.js.map +2 -2
  53. package/dist-cjs/ui/count-badge.js +1 -1
  54. package/dist-cjs/ui/count-badge.js.map +2 -2
  55. package/dist-cjs/ui/empty-state.js +3 -3
  56. package/dist-cjs/ui/empty-state.js.map +2 -2
  57. package/dist-cjs/ui/format-time.js +3 -0
  58. package/dist-cjs/ui/format-time.js.map +2 -2
  59. package/dist-cjs/ui/mention-list.js +8 -8
  60. package/dist-cjs/ui/mention-list.js.map +2 -2
  61. package/dist-cjs/ui/mention-suggestion.js +3 -3
  62. package/dist-cjs/ui/mention-suggestion.js.map +2 -2
  63. package/dist-cjs/ui/mention.js +1 -1
  64. package/dist-cjs/ui/mention.js.map +2 -2
  65. package/dist-cjs/ui/reaction.js +11 -4
  66. package/dist-cjs/ui/reaction.js.map +2 -2
  67. package/dist-cjs/ui/reactions.js +10 -2
  68. package/dist-cjs/ui/reactions.js.map +2 -2
  69. package/dist-cjs/ui/send-button.js +1 -1
  70. package/dist-cjs/ui/send-button.js.map +2 -2
  71. package/dist-cjs/ui/tooltip-button.js +32 -0
  72. package/dist-cjs/ui/tooltip-button.js.map +7 -0
  73. package/dist-esm/canvas/comment-body.mjs +1 -1
  74. package/dist-esm/canvas/comment-body.mjs.map +2 -2
  75. package/dist-esm/canvas/comment-drafts.mjs +34 -0
  76. package/dist-esm/canvas/comment-drafts.mjs.map +7 -0
  77. package/dist-esm/canvas/comment-render.mjs +2 -0
  78. package/dist-esm/canvas/comment-render.mjs.map +2 -2
  79. package/dist-esm/canvas/comment-tool.mjs +67 -14
  80. package/dist-esm/canvas/comment-tool.mjs.map +2 -2
  81. package/dist-esm/canvas/comments-filter-menu.mjs +54 -63
  82. package/dist-esm/canvas/comments-filter-menu.mjs.map +2 -2
  83. package/dist-esm/canvas/comments-overflow-menu.mjs +22 -27
  84. package/dist-esm/canvas/comments-overflow-menu.mjs.map +2 -2
  85. package/dist-esm/canvas/comments-overlay.mjs +322 -114
  86. package/dist-esm/canvas/comments-overlay.mjs.map +2 -2
  87. package/dist-esm/canvas/comments-sidebar.mjs +15 -21
  88. package/dist-esm/canvas/comments-sidebar.mjs.map +2 -2
  89. package/dist-esm/canvas/comments-visibility-toggle.mjs +46 -0
  90. package/dist-esm/canvas/comments-visibility-toggle.mjs.map +7 -0
  91. package/dist-esm/canvas/options.mjs +1 -0
  92. package/dist-esm/canvas/options.mjs.map +2 -2
  93. package/dist-esm/canvas/sidebar-filters.mjs +2 -2
  94. package/dist-esm/canvas/sidebar-filters.mjs.map +2 -2
  95. package/dist-esm/canvas/state.mjs +11 -0
  96. package/dist-esm/canvas/state.mjs.map +2 -2
  97. package/dist-esm/canvas/thread-state.mjs +8 -1
  98. package/dist-esm/canvas/thread-state.mjs.map +2 -2
  99. package/dist-esm/clustering/runtime.mjs +119 -7
  100. package/dist-esm/clustering/runtime.mjs.map +2 -2
  101. package/dist-esm/index.d.mts +126 -41
  102. package/dist-esm/index.mjs +11 -1
  103. package/dist-esm/index.mjs.map +2 -2
  104. package/dist-esm/ui/avatar.mjs +14 -6
  105. package/dist-esm/ui/avatar.mjs.map +2 -2
  106. package/dist-esm/ui/byline.mjs +4 -4
  107. package/dist-esm/ui/byline.mjs.map +2 -2
  108. package/dist-esm/ui/comment-author.mjs +1 -0
  109. package/dist-esm/ui/comment-author.mjs.map +7 -0
  110. package/dist-esm/ui/comment-card.mjs +4 -4
  111. package/dist-esm/ui/comment-card.mjs.map +2 -2
  112. package/dist-esm/ui/comment-composer.mjs +93 -30
  113. package/dist-esm/ui/comment-composer.mjs.map +2 -2
  114. package/dist-esm/ui/comment-mention.mjs +1 -1
  115. package/dist-esm/ui/comment-mention.mjs.map +2 -2
  116. package/dist-esm/ui/comment-pin.mjs +23 -3
  117. package/dist-esm/ui/comment-pin.mjs.map +2 -2
  118. package/dist-esm/ui/comment-text.mjs +1 -1
  119. package/dist-esm/ui/comment-text.mjs.map +2 -2
  120. package/dist-esm/ui/comment-thread.mjs +6 -6
  121. package/dist-esm/ui/comment-thread.mjs.map +2 -2
  122. package/dist-esm/ui/comments-list.mjs +12 -12
  123. package/dist-esm/ui/comments-list.mjs.map +2 -2
  124. package/dist-esm/ui/count-badge.mjs +1 -1
  125. package/dist-esm/ui/count-badge.mjs.map +2 -2
  126. package/dist-esm/ui/empty-state.mjs +3 -3
  127. package/dist-esm/ui/empty-state.mjs.map +2 -2
  128. package/dist-esm/ui/format-time.mjs +3 -0
  129. package/dist-esm/ui/format-time.mjs.map +2 -2
  130. package/dist-esm/ui/mention-list.mjs +8 -8
  131. package/dist-esm/ui/mention-list.mjs.map +2 -2
  132. package/dist-esm/ui/mention-suggestion.mjs +3 -3
  133. package/dist-esm/ui/mention-suggestion.mjs.map +2 -2
  134. package/dist-esm/ui/mention.mjs +1 -1
  135. package/dist-esm/ui/mention.mjs.map +2 -2
  136. package/dist-esm/ui/reaction.mjs +11 -4
  137. package/dist-esm/ui/reaction.mjs.map +2 -2
  138. package/dist-esm/ui/reactions.mjs +10 -2
  139. package/dist-esm/ui/reactions.mjs.map +2 -2
  140. package/dist-esm/ui/send-button.mjs +1 -1
  141. package/dist-esm/ui/send-button.mjs.map +2 -2
  142. package/dist-esm/ui/tooltip-button.mjs +12 -0
  143. package/dist-esm/ui/tooltip-button.mjs.map +7 -0
  144. package/package.json +3 -3
  145. package/src/canvas/canvas.css +79 -36
  146. package/src/canvas/comment-body.tsx +1 -1
  147. package/src/canvas/comment-drafts.test.ts +55 -0
  148. package/src/canvas/comment-drafts.ts +46 -0
  149. package/src/canvas/comment-render.test.ts +1 -1
  150. package/src/canvas/comment-render.ts +7 -2
  151. package/src/canvas/comment-tool.tsx +98 -17
  152. package/src/canvas/comments-filter-menu.tsx +27 -33
  153. package/src/canvas/comments-overflow-menu.tsx +13 -21
  154. package/src/canvas/comments-overlay.tsx +441 -145
  155. package/src/canvas/comments-sidebar.tsx +27 -28
  156. package/src/canvas/comments-visibility-toggle.tsx +50 -0
  157. package/src/canvas/options.ts +25 -0
  158. package/src/canvas/sidebar-filters.ts +4 -3
  159. package/src/canvas/state.ts +22 -0
  160. package/src/canvas/thread-state.ts +16 -3
  161. package/src/clustering/runtime.test.ts +183 -7
  162. package/src/clustering/runtime.ts +164 -15
  163. package/src/index.ts +7 -0
  164. package/src/ui/avatar.tsx +15 -11
  165. package/src/ui/byline.tsx +6 -5
  166. package/src/ui/comment-author.ts +15 -0
  167. package/src/ui/comment-card.tsx +6 -5
  168. package/src/ui/comment-composer.tsx +122 -33
  169. package/src/ui/comment-mention.ts +2 -2
  170. package/src/ui/comment-pin.tsx +35 -4
  171. package/src/ui/comment-text.tsx +1 -1
  172. package/src/ui/comment-thread.tsx +8 -6
  173. package/src/ui/comments-list.tsx +19 -14
  174. package/src/ui/comments.css +205 -117
  175. package/src/ui/count-badge.tsx +1 -1
  176. package/src/ui/empty-state.tsx +3 -3
  177. package/src/ui/format-time.ts +5 -0
  178. package/src/ui/mention-list.tsx +13 -16
  179. package/src/ui/mention-suggestion.tsx +3 -3
  180. package/src/ui/mention.tsx +1 -1
  181. package/src/ui/reaction.tsx +6 -3
  182. package/src/ui/reactions.tsx +6 -2
  183. package/src/ui/send-button.tsx +1 -1
  184. 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;
@@ -326,6 +356,15 @@ export declare interface CommentingOptions {
326
356
  readonly x: number;
327
357
  readonly y: number;
328
358
  };
359
+ /**
360
+ * Whether a comment landing on a shape anchors precisely — pinned to the exact clicked spot
361
+ * within the shape — or imprecisely — pinned to the shape as a whole, rendered at
362
+ * `impreciseShapeAnchor`. Called wherever a shape anchor is created (placing with the comment
363
+ * tool, dropping a dragged pin onto a shape). Always precise by default. Return `false` for
364
+ * shape-level anchoring, or decide from the context — the Alt key's state, or the shape itself,
365
+ * e.g. precise only on notes. Governs new placements only; existing anchors render as stored.
366
+ */
367
+ shouldBePrecise(editor: Editor, context: ShapeCommentPrecisionContext): boolean;
329
368
  /** Screen-pixel margin by which the viewport is inflated when culling cluster badges. */
330
369
  readonly clusterCullMargin: number;
331
370
  /** How far past a cluster's split zoom to land when expanding it (1.05 = 5% overshoot). */
@@ -337,7 +376,7 @@ export declare interface CommentingOptions {
337
376
  /** @public */
338
377
  export declare interface CommentListItemProps {
339
378
  id: string;
340
- author: string;
379
+ author: CommentAuthor;
341
380
  /** A short preview of the thread — e.g. the first comment's body. */
342
381
  preview: ReactNode;
343
382
  /** ISO datetime of the thread's first comment. */
@@ -354,7 +393,7 @@ export declare interface CommentListItemProps {
354
393
  /** A canvas comment marker: shows its `children` (or a check when resolved). Purely
355
394
  * presentational — it reflects open/resolved state via CSS; wrap it to make it clickable.
356
395
  * @public @react */
357
- export declare function CommentPin({ children, resolved, open }: CommentPinProps): JSX.Element;
396
+ export declare function CommentPin({ children, resolved, open, color }: CommentPinProps): JSX.Element;
358
397
 
359
398
  /** @public */
360
399
  export declare interface CommentPinProps {
@@ -364,6 +403,9 @@ export declare interface CommentPinProps {
364
403
  resolved?: boolean;
365
404
  /** The pin's thread is open — shows the active/selected indicator state. */
366
405
  open?: boolean;
406
+ /** Background color (any CSS color). Falls back to the default pin tint.
407
+ * Ignored while resolved — resolved pins are always grey. */
408
+ color?: string;
367
409
  }
368
410
 
369
411
  /** The funnel dropdown in the sidebar header: toggles for which threads the list shows.
@@ -424,6 +466,20 @@ export declare function CommentsMenuItem(): JSX.Element;
424
466
  * @public @react */
425
467
  export declare function CommentsOverflowMenu(): JSX.Element;
426
468
 
469
+ /**
470
+ * Whether the comments sidebar (the thread list) is open. Driven by an explicit control — a button
471
+ * next to Share on dotcom — rather than by which tool is active, so browsing threads is separate
472
+ * from placing them. The comment tool additionally closes it on enter, keeping placement
473
+ * canvas-focused.
474
+ * @public
475
+ */
476
+ export declare const commentsSidebarOpen: EditorAtom<boolean>;
477
+
478
+ /** The sidebar header's show/hide toggle for comment pins — an eye that closes while comments
479
+ * are hidden. The same state as the Shift+C shortcut.
480
+ * @public @react */
481
+ export declare function CommentsVisibilityToggle(): JSX.Element;
482
+
427
483
  /** A comment's body, rendered as markdown (bold, italic, code, links, lists). @public @react */
428
484
  export declare function CommentText({ text }: CommentTextProps): JSX.Element;
429
485
 
@@ -458,9 +514,11 @@ export declare interface CommentThreadProps {
458
514
  }
459
515
 
460
516
  /**
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.
517
+ * The comment tool. Pressing down opens the comment composer immediately at the pointer, and it
518
+ * follows the pointer until release — like placing a sticky note settling on a point, or on a
519
+ * shape when released over one. (With region comments enabled, dragging past the threshold instead
520
+ * draws a region rectangle.) Placement only opens a composer (via `pendingComment`); the records
521
+ * are created when the comment is posted.
464
522
  * @public
465
523
  */
466
524
  export declare class CommentTool extends StateNode {
@@ -486,6 +544,7 @@ export declare class CommentTool extends StateNode {
486
544
  */
487
545
  options: CommentingOptions;
488
546
  onEnter(): void;
547
+ onExit(): void;
489
548
  onCancel(): void;
490
549
  }
491
550
 
@@ -540,7 +599,8 @@ export declare const DEFAULT_IMPRECISE_SHAPE_ANCHOR: {
540
599
  * @public */
541
600
  export declare const DEFAULT_REGION_COMMENT_OPTIONS: RegionCommentOptions;
542
601
 
543
- /** @public */
602
+ /** The out-of-the-box view: every page's threads, resolved ones hidden until asked for.
603
+ * @public */
544
604
  export declare const DEFAULT_SIDEBAR_FILTERS: SidebarFilters;
545
605
 
546
606
  /**
@@ -559,6 +619,7 @@ export declare const defaultCommentingOptions: {
559
619
  readonly x: 1;
560
620
  readonly y: 0;
561
621
  };
622
+ readonly shouldBePrecise: () => true;
562
623
  };
563
624
 
564
625
  /** The empty state shown when a thread has no comments yet. @public @react */
@@ -641,14 +702,10 @@ export declare interface MentionListProps {
641
702
  renderMember?(member: MentionMember): ReactNode;
642
703
  }
643
704
 
644
- /** A person the composer's \@-mention picker can offer. @public */
645
- export declare interface MentionMember {
705
+ /** A person the composer's \@-mention picker can offer: a {@link CommentAuthor} plus its id and
706
+ * picker-only display fields. @public */
707
+ export declare interface MentionMember extends CommentAuthor {
646
708
  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
709
  /** A secondary line under the name — e.g. an email or handle. Omit for a single-line row. */
653
710
  secondary?: string;
654
711
  /** Marks the current user; shown as a "(You)" suffix after the name. */
@@ -720,6 +777,12 @@ export declare interface ReactionProps {
720
777
  /** The row of reactions under a comment, plus an add-reaction button. @public @react */
721
778
  export declare function Reactions(): JSX.Element;
722
779
 
780
+ /** A region anchor's pin corner: the corner its creating drag released on, when recorded, else
781
+ * the editor's configured default. @public */
782
+ export declare function regionAnchorPinCorner(editor: Editor, anchor: Extract<TLCommentAnchor, {
783
+ type: 'region';
784
+ }>): VecLike;
785
+
723
786
  /**
724
787
  * The configurable dimensions of region comments — a design surface for prototyping the interaction
725
788
  * before settling it. Region is **off by default**, so a consumer that leaves it unset keeps plain
@@ -772,8 +835,9 @@ export declare interface SendButtonProps {
772
835
 
773
836
  /**
774
837
  * A shape anchor for a page point. `x`/`y` are the point's normalized (0–1) offset within the
775
- * shape's page bounds, remembered either way. When `precise` (Alt held) the pin sits at exactly
776
- * `x`/`y`; otherwise it sits at the consumer's imprecise default (top-right out of the box).
838
+ * shape's page bounds, remembered either way. When `precise` the pin sits at exactly `x`/`y`;
839
+ * otherwise it sits at the consumer's imprecise default (top-right out of the box). Placement
840
+ * gestures get `precise` from the `shouldBePrecise` commenting option (always precise, by default).
777
841
  * @public
778
842
  */
779
843
  export declare function shapeAnchorAt(editor: Editor, shapeId: TLShapeId, page: {
@@ -781,6 +845,19 @@ export declare function shapeAnchorAt(editor: Editor, shapeId: TLShapeId, page:
781
845
  y: number;
782
846
  }, precise: boolean): TLCommentAnchor;
783
847
 
848
+ /**
849
+ * The gesture that's creating a shape anchor, passed to
850
+ * {@link CommentingOptions.shouldBePrecise}: the target shape, the page point of the release, and
851
+ * whether Alt was held.
852
+ *
853
+ * @public
854
+ */
855
+ export declare interface ShapeCommentPrecisionContext {
856
+ readonly shapeId: TLShapeId;
857
+ readonly point: VecLike;
858
+ readonly altKey: boolean;
859
+ }
860
+
784
861
  /**
785
862
  * Which threads the comments sidebar shows. Held as an editor-scoped signal (the `sidebarFilters`
786
863
  * `EditorAtom` in `./state`) rather than component state so it survives the sidebar
@@ -820,6 +897,10 @@ export declare type TLCommentRecord = TLComment | TLCommentThread;
820
897
  * @public */
821
898
  export declare function toggleCommentsHidden(editor: Editor): void;
822
899
 
900
+ /** Open or close the comments sidebar for an editor.
901
+ * @public */
902
+ export declare function toggleCommentsSidebar(editor: Editor): void;
903
+
823
904
  /**
824
905
  * Whether commenting is licensed for this editor. Enabled in development; in production it requires
825
906
  * a tldraw license that includes the commenting feature (or the collaboration umbrella that grants
@@ -847,6 +928,10 @@ export declare function useComments(editor: Editor): TLComment[];
847
928
  * @public */
848
929
  export declare function useCommentsHidden(): boolean;
849
930
 
931
+ /** React hook for whether the comments sidebar is open.
932
+ * @public */
933
+ export declare function useCommentsSidebarOpen(): boolean;
934
+
850
935
  /** All comment threads in the store, reactively. @public */
851
936
  export declare function useCommentThreads(editor: Editor): TLCommentThread[];
852
937
 
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.1640468db8fd",
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\ttype ShapeCommentPrecisionContext,\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,qBAOO;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
  }