@tldraw/commenting 0.0.0-bootstrap → 5.3.0-canary.31036673d3f8

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 (279) hide show
  1. package/README.md +0 -2
  2. package/commenting.css +1139 -329
  3. package/dist-cjs/canvas/anchor-lifecycle.js +148 -0
  4. package/dist-cjs/canvas/anchor-lifecycle.js.map +7 -0
  5. package/dist-cjs/canvas/cluster-input.js +2 -2
  6. package/dist-cjs/canvas/cluster-input.js.map +2 -2
  7. package/dist-cjs/canvas/comment-body.js +1 -1
  8. package/dist-cjs/canvas/comment-body.js.map +2 -2
  9. package/dist-cjs/canvas/comment-drafts.js +54 -0
  10. package/dist-cjs/canvas/comment-drafts.js.map +7 -0
  11. package/dist-cjs/canvas/comment-mutations.js +123 -0
  12. package/dist-cjs/canvas/comment-mutations.js.map +7 -0
  13. package/dist-cjs/canvas/comment-reactions.js +163 -0
  14. package/dist-cjs/canvas/comment-reactions.js.map +7 -0
  15. package/dist-cjs/canvas/comment-render.js +5 -3
  16. package/dist-cjs/canvas/comment-render.js.map +2 -2
  17. package/dist-cjs/canvas/comment-store.js +19 -9
  18. package/dist-cjs/canvas/comment-store.js.map +2 -2
  19. package/dist-cjs/canvas/comment-tool.js +64 -14
  20. package/dist-cjs/canvas/comment-tool.js.map +2 -2
  21. package/dist-cjs/canvas/comments-filter-menu.js +20 -38
  22. package/dist-cjs/canvas/comments-filter-menu.js.map +2 -2
  23. package/dist-cjs/canvas/comments-overflow-menu.js +22 -27
  24. package/dist-cjs/canvas/comments-overflow-menu.js.map +2 -2
  25. package/dist-cjs/canvas/comments-overlay.js +429 -474
  26. package/dist-cjs/canvas/comments-overlay.js.map +2 -2
  27. package/dist-cjs/canvas/comments-sidebar.js +35 -32
  28. package/dist-cjs/canvas/comments-sidebar.js.map +2 -2
  29. package/dist-cjs/canvas/comments-visibility-toggle.js +65 -0
  30. package/dist-cjs/canvas/comments-visibility-toggle.js.map +7 -0
  31. package/dist-cjs/canvas/context.js +17 -0
  32. package/dist-cjs/canvas/context.js.map +7 -0
  33. package/dist-cjs/canvas/hooks.js +22 -3
  34. package/dist-cjs/canvas/hooks.js.map +2 -2
  35. package/dist-cjs/canvas/options.js +19 -2
  36. package/dist-cjs/canvas/options.js.map +2 -2
  37. package/dist-cjs/canvas/pin-stacking.js +56 -0
  38. package/dist-cjs/canvas/pin-stacking.js.map +7 -0
  39. package/dist-cjs/canvas/sidebar-filters.js +2 -2
  40. package/dist-cjs/canvas/sidebar-filters.js.map +2 -2
  41. package/dist-cjs/canvas/state.js +28 -14
  42. package/dist-cjs/canvas/state.js.map +2 -2
  43. package/dist-cjs/canvas/thread-preview.js +185 -0
  44. package/dist-cjs/canvas/thread-preview.js.map +7 -0
  45. package/dist-cjs/canvas/thread-stack.js +199 -0
  46. package/dist-cjs/canvas/thread-stack.js.map +7 -0
  47. package/dist-cjs/canvas/thread-state.js +67 -21
  48. package/dist-cjs/canvas/thread-state.js.map +2 -2
  49. package/dist-cjs/canvas/thread-view.js +397 -0
  50. package/dist-cjs/canvas/thread-view.js.map +7 -0
  51. package/dist-cjs/clustering/computeClusterTable.js +4 -4
  52. package/dist-cjs/clustering/computeClusterTable.js.map +2 -2
  53. package/dist-cjs/clustering/runtime.js +119 -7
  54. package/dist-cjs/clustering/runtime.js.map +2 -2
  55. package/dist-cjs/clustering/types.js.map +1 -1
  56. package/dist-cjs/index.d.ts +763 -333
  57. package/dist-cjs/index.js +46 -28
  58. package/dist-cjs/index.js.map +2 -2
  59. package/dist-cjs/ui/byline.js +6 -4
  60. package/dist-cjs/ui/byline.js.map +2 -2
  61. package/dist-cjs/ui/comment-card.js +15 -8
  62. package/dist-cjs/ui/comment-card.js.map +2 -2
  63. package/dist-cjs/ui/comment-composer.js +137 -36
  64. package/dist-cjs/ui/comment-composer.js.map +2 -2
  65. package/dist-cjs/ui/comment-pin.js +24 -2
  66. package/dist-cjs/ui/comment-pin.js.map +2 -2
  67. package/dist-cjs/ui/comment-thread.js +9 -7
  68. package/dist-cjs/ui/comment-thread.js.map +2 -2
  69. package/dist-cjs/ui/comments-list.js +30 -18
  70. package/dist-cjs/ui/comments-list.js.map +2 -2
  71. package/dist-cjs/ui/count-badge.js +3 -2
  72. package/dist-cjs/ui/count-badge.js.map +2 -2
  73. package/dist-cjs/ui/emoji-picker.js +54 -0
  74. package/dist-cjs/ui/emoji-picker.js.map +7 -0
  75. package/dist-cjs/ui/empty-state.js +3 -3
  76. package/dist-cjs/ui/empty-state.js.map +2 -2
  77. package/dist-cjs/ui/format-time.js +4 -1
  78. package/dist-cjs/ui/format-time.js.map +2 -2
  79. package/dist-cjs/ui/reaction-picker.js +73 -0
  80. package/dist-cjs/ui/reaction-picker.js.map +7 -0
  81. package/dist-cjs/ui/reaction.js +59 -6
  82. package/dist-cjs/ui/reaction.js.map +2 -2
  83. package/dist-cjs/ui/reactions.js +20 -7
  84. package/dist-cjs/ui/reactions.js.map +2 -2
  85. package/dist-cjs/ui/{mention.js → reply-count.js} +9 -11
  86. package/dist-cjs/ui/reply-count.js.map +7 -0
  87. package/dist-cjs/ui/send-button.js +20 -1
  88. package/dist-cjs/ui/send-button.js.map +2 -2
  89. package/dist-cjs/ui/{comment-text.js → tooltip-button.js} +12 -9
  90. package/dist-cjs/ui/tooltip-button.js.map +7 -0
  91. package/dist-esm/canvas/anchor-lifecycle.mjs +128 -0
  92. package/dist-esm/canvas/anchor-lifecycle.mjs.map +7 -0
  93. package/dist-esm/canvas/cluster-input.mjs +2 -2
  94. package/dist-esm/canvas/cluster-input.mjs.map +2 -2
  95. package/dist-esm/canvas/comment-body.mjs +1 -1
  96. package/dist-esm/canvas/comment-body.mjs.map +2 -2
  97. package/dist-esm/canvas/comment-drafts.mjs +34 -0
  98. package/dist-esm/canvas/comment-drafts.mjs.map +7 -0
  99. package/dist-esm/canvas/comment-mutations.mjs +103 -0
  100. package/dist-esm/canvas/comment-mutations.mjs.map +7 -0
  101. package/dist-esm/canvas/comment-reactions.mjs +152 -0
  102. package/dist-esm/canvas/comment-reactions.mjs.map +7 -0
  103. package/dist-esm/canvas/comment-render.mjs +5 -3
  104. package/dist-esm/canvas/comment-render.mjs.map +2 -2
  105. package/dist-esm/canvas/comment-store.mjs +19 -9
  106. package/dist-esm/canvas/comment-store.mjs.map +2 -2
  107. package/dist-esm/canvas/comment-tool.mjs +67 -17
  108. package/dist-esm/canvas/comment-tool.mjs.map +2 -2
  109. package/dist-esm/canvas/comments-filter-menu.mjs +20 -38
  110. package/dist-esm/canvas/comments-filter-menu.mjs.map +2 -2
  111. package/dist-esm/canvas/comments-overflow-menu.mjs +23 -27
  112. package/dist-esm/canvas/comments-overflow-menu.mjs.map +2 -2
  113. package/dist-esm/canvas/comments-overlay.mjs +450 -479
  114. package/dist-esm/canvas/comments-overlay.mjs.map +3 -3
  115. package/dist-esm/canvas/comments-sidebar.mjs +38 -35
  116. package/dist-esm/canvas/comments-sidebar.mjs.map +2 -2
  117. package/dist-esm/canvas/comments-visibility-toggle.mjs +45 -0
  118. package/dist-esm/canvas/comments-visibility-toggle.mjs.map +7 -0
  119. package/dist-esm/canvas/context.mjs +1 -0
  120. package/dist-esm/canvas/context.mjs.map +7 -0
  121. package/dist-esm/canvas/hooks.mjs +28 -5
  122. package/dist-esm/canvas/hooks.mjs.map +2 -2
  123. package/dist-esm/canvas/options.mjs +21 -3
  124. package/dist-esm/canvas/options.mjs.map +2 -2
  125. package/dist-esm/canvas/pin-stacking.mjs +36 -0
  126. package/dist-esm/canvas/pin-stacking.mjs.map +7 -0
  127. package/dist-esm/canvas/sidebar-filters.mjs +2 -2
  128. package/dist-esm/canvas/sidebar-filters.mjs.map +2 -2
  129. package/dist-esm/canvas/state.mjs +29 -19
  130. package/dist-esm/canvas/state.mjs.map +2 -2
  131. package/dist-esm/canvas/thread-preview.mjs +170 -0
  132. package/dist-esm/canvas/thread-preview.mjs.map +7 -0
  133. package/dist-esm/canvas/thread-stack.mjs +190 -0
  134. package/dist-esm/canvas/thread-stack.mjs.map +7 -0
  135. package/dist-esm/canvas/thread-state.mjs +71 -22
  136. package/dist-esm/canvas/thread-state.mjs.map +2 -2
  137. package/dist-esm/canvas/thread-view.mjs +402 -0
  138. package/dist-esm/canvas/thread-view.mjs.map +7 -0
  139. package/dist-esm/clustering/computeClusterTable.mjs +4 -4
  140. package/dist-esm/clustering/computeClusterTable.mjs.map +2 -2
  141. package/dist-esm/clustering/runtime.mjs +119 -7
  142. package/dist-esm/clustering/runtime.mjs.map +2 -2
  143. package/dist-esm/index.d.mts +763 -333
  144. package/dist-esm/index.mjs +87 -41
  145. package/dist-esm/index.mjs.map +2 -2
  146. package/dist-esm/ui/byline.mjs +6 -4
  147. package/dist-esm/ui/byline.mjs.map +2 -2
  148. package/dist-esm/ui/comment-card.mjs +15 -8
  149. package/dist-esm/ui/comment-card.mjs.map +2 -2
  150. package/dist-esm/ui/comment-composer.mjs +148 -36
  151. package/dist-esm/ui/comment-composer.mjs.map +2 -2
  152. package/dist-esm/ui/comment-pin.mjs +24 -2
  153. package/dist-esm/ui/comment-pin.mjs.map +2 -2
  154. package/dist-esm/ui/comment-thread.mjs +9 -7
  155. package/dist-esm/ui/comment-thread.mjs.map +2 -2
  156. package/dist-esm/ui/comments-list.mjs +43 -29
  157. package/dist-esm/ui/comments-list.mjs.map +2 -2
  158. package/dist-esm/ui/count-badge.mjs +3 -2
  159. package/dist-esm/ui/count-badge.mjs.map +2 -2
  160. package/dist-esm/ui/emoji-picker.mjs +34 -0
  161. package/dist-esm/ui/emoji-picker.mjs.map +7 -0
  162. package/dist-esm/ui/empty-state.mjs +3 -3
  163. package/dist-esm/ui/empty-state.mjs.map +2 -2
  164. package/dist-esm/ui/format-time.mjs +4 -1
  165. package/dist-esm/ui/format-time.mjs.map +2 -2
  166. package/dist-esm/ui/reaction-picker.mjs +60 -0
  167. package/dist-esm/ui/reaction-picker.mjs.map +7 -0
  168. package/dist-esm/ui/reaction.mjs +60 -7
  169. package/dist-esm/ui/reaction.mjs.map +2 -2
  170. package/dist-esm/ui/reactions.mjs +21 -8
  171. package/dist-esm/ui/reactions.mjs.map +2 -2
  172. package/dist-esm/ui/reply-count.mjs +9 -0
  173. package/dist-esm/ui/reply-count.mjs.map +7 -0
  174. package/dist-esm/ui/send-button.mjs +20 -1
  175. package/dist-esm/ui/send-button.mjs.map +2 -2
  176. package/dist-esm/ui/tooltip-button.mjs +12 -0
  177. package/dist-esm/ui/tooltip-button.mjs.map +7 -0
  178. package/package.json +6 -6
  179. package/src/canvas/anchor-lifecycle.test.ts +290 -0
  180. package/src/canvas/anchor-lifecycle.ts +205 -0
  181. package/src/canvas/canvas.css +461 -46
  182. package/src/canvas/cluster-input.test.ts +31 -23
  183. package/src/canvas/cluster-input.ts +3 -4
  184. package/src/canvas/comment-body.tsx +1 -1
  185. package/src/canvas/comment-drafts.test.ts +55 -0
  186. package/src/canvas/comment-drafts.ts +46 -0
  187. package/src/canvas/comment-mutations.test.ts +410 -0
  188. package/src/canvas/comment-mutations.ts +288 -0
  189. package/src/canvas/comment-reactions.test.ts +132 -0
  190. package/src/canvas/comment-reactions.tsx +245 -0
  191. package/src/canvas/comment-render.test.ts +1 -1
  192. package/src/canvas/comment-render.ts +9 -5
  193. package/src/canvas/comment-store.ts +67 -27
  194. package/src/canvas/comment-tool.test.ts +162 -0
  195. package/src/canvas/comment-tool.tsx +105 -23
  196. package/src/canvas/comments-filter-menu.tsx +23 -32
  197. package/src/canvas/comments-overflow-menu.tsx +14 -21
  198. package/src/canvas/comments-overlay.tsx +695 -622
  199. package/src/canvas/comments-sidebar.test.ts +45 -0
  200. package/src/canvas/comments-sidebar.tsx +76 -58
  201. package/src/canvas/comments-visibility-toggle.tsx +49 -0
  202. package/src/canvas/context.ts +47 -0
  203. package/src/canvas/hooks.ts +52 -11
  204. package/src/canvas/options.test.ts +52 -2
  205. package/src/canvas/options.ts +133 -9
  206. package/src/canvas/pin-stacking.test.ts +114 -0
  207. package/src/canvas/pin-stacking.ts +57 -0
  208. package/src/canvas/sidebar-filters.ts +4 -3
  209. package/src/canvas/state.ts +92 -35
  210. package/src/canvas/thread-preview.test.ts +91 -0
  211. package/src/canvas/thread-preview.tsx +304 -0
  212. package/src/canvas/thread-stack.tsx +252 -0
  213. package/src/canvas/thread-state.test.ts +209 -0
  214. package/src/canvas/thread-state.ts +137 -36
  215. package/src/canvas/thread-view.tsx +516 -0
  216. package/src/clustering/computeClusterTable.test.ts +24 -23
  217. package/src/clustering/computeClusterTable.ts +5 -5
  218. package/src/clustering/runtime.test.ts +217 -7
  219. package/src/clustering/runtime.ts +171 -17
  220. package/src/clustering/types.ts +9 -9
  221. package/src/index.ts +76 -40
  222. package/src/ui/byline.tsx +7 -5
  223. package/src/ui/comment-card.tsx +20 -10
  224. package/src/ui/comment-composer.tsx +206 -40
  225. package/src/ui/comment-pin.tsx +26 -2
  226. package/src/ui/comment-thread.tsx +13 -6
  227. package/src/ui/comments-list.test.ts +31 -0
  228. package/src/ui/comments-list.tsx +45 -21
  229. package/src/ui/comments.css +566 -281
  230. package/src/ui/count-badge.tsx +9 -2
  231. package/src/ui/emoji-picker.test.ts +25 -0
  232. package/src/ui/emoji-picker.tsx +76 -0
  233. package/src/ui/empty-state.tsx +3 -3
  234. package/src/ui/format-time.ts +7 -2
  235. package/src/ui/reaction-picker.tsx +109 -0
  236. package/src/ui/reaction.tsx +121 -6
  237. package/src/ui/reactions.tsx +69 -10
  238. package/src/ui/reply-count.ts +16 -0
  239. package/src/ui/send-button.tsx +18 -3
  240. package/src/ui/tooltip-button.tsx +20 -0
  241. package/dist-cjs/canvas/region-options.js +0 -49
  242. package/dist-cjs/canvas/region-options.js.map +0 -7
  243. package/dist-cjs/ui/avatar.js +0 -43
  244. package/dist-cjs/ui/avatar.js.map +0 -7
  245. package/dist-cjs/ui/comment-mention.js +0 -42
  246. package/dist-cjs/ui/comment-mention.js.map +0 -7
  247. package/dist-cjs/ui/comment-text.js.map +0 -7
  248. package/dist-cjs/ui/mention-list.js +0 -70
  249. package/dist-cjs/ui/mention-list.js.map +0 -7
  250. package/dist-cjs/ui/mention-suggestion.js +0 -206
  251. package/dist-cjs/ui/mention-suggestion.js.map +0 -7
  252. package/dist-cjs/ui/mention.js.map +0 -7
  253. package/dist-cjs/ui/render-markdown.js +0 -63
  254. package/dist-cjs/ui/render-markdown.js.map +0 -7
  255. package/dist-esm/canvas/region-options.mjs +0 -29
  256. package/dist-esm/canvas/region-options.mjs.map +0 -7
  257. package/dist-esm/ui/avatar.mjs +0 -23
  258. package/dist-esm/ui/avatar.mjs.map +0 -7
  259. package/dist-esm/ui/comment-mention.mjs +0 -22
  260. package/dist-esm/ui/comment-mention.mjs.map +0 -7
  261. package/dist-esm/ui/comment-text.mjs +0 -9
  262. package/dist-esm/ui/comment-text.mjs.map +0 -7
  263. package/dist-esm/ui/mention-list.mjs +0 -50
  264. package/dist-esm/ui/mention-list.mjs.map +0 -7
  265. package/dist-esm/ui/mention-suggestion.mjs +0 -186
  266. package/dist-esm/ui/mention-suggestion.mjs.map +0 -7
  267. package/dist-esm/ui/mention.mjs +0 -11
  268. package/dist-esm/ui/mention.mjs.map +0 -7
  269. package/dist-esm/ui/render-markdown.mjs +0 -45
  270. package/dist-esm/ui/render-markdown.mjs.map +0 -7
  271. package/src/canvas/region-options.ts +0 -57
  272. package/src/ui/avatar.tsx +0 -31
  273. package/src/ui/comment-mention.ts +0 -47
  274. package/src/ui/comment-text.tsx +0 -12
  275. package/src/ui/mention-list.tsx +0 -106
  276. package/src/ui/mention-suggestion.test.ts +0 -18
  277. package/src/ui/mention-suggestion.tsx +0 -285
  278. package/src/ui/mention.tsx +0 -9
  279. package/src/ui/render-markdown.tsx +0 -72
@@ -1,77 +1,102 @@
1
1
  import { registerTldrawLibraryVersion } from "@tldraw/utils";
2
- import { Avatar } from "./ui/avatar.mjs";
2
+ import {
3
+ Avatar,
4
+ createMentionSuggestion,
5
+ filterMentionMembers,
6
+ Mention,
7
+ MentionList
8
+ } from "@tldraw/mentions";
3
9
  import { Byline } from "./ui/byline.mjs";
4
10
  import { CommentCard } from "./ui/comment-card.mjs";
5
11
  import { CommentComposer } from "./ui/comment-composer.mjs";
6
12
  import { CountBadge } from "./ui/count-badge.mjs";
7
13
  import { CommentPin } from "./ui/comment-pin.mjs";
8
- import { CommentText } from "./ui/comment-text.mjs";
9
14
  import { CommentThread } from "./ui/comment-thread.mjs";
10
- import { CommentsList } from "./ui/comments-list.mjs";
15
+ import {
16
+ CommentsList,
17
+ isOpenInNewTabClick
18
+ } from "./ui/comments-list.mjs";
11
19
  import { EmptyState } from "./ui/empty-state.mjs";
12
20
  import { formatRelativeTime } from "./ui/format-time.mjs";
13
- import { Mention } from "./ui/mention.mjs";
14
- import { MentionList } from "./ui/mention-list.mjs";
15
21
  import {
16
- createMentionSuggestion,
17
- filterMentionMembers
18
- } from "./ui/mention-suggestion.mjs";
19
- import { Reaction } from "./ui/reaction.mjs";
20
- import { Reactions } from "./ui/reactions.mjs";
21
- import { renderMarkdown } from "./ui/render-markdown.mjs";
22
+ DEFAULT_REACTION_EMOJI,
23
+ EmojiPicker,
24
+ isAllowedReactionEmoji
25
+ } from "./ui/emoji-picker.mjs";
26
+ import {
27
+ Reaction,
28
+ defaultRenderReaction,
29
+ DefaultReactionTooltip,
30
+ DefaultReactionTooltipContent
31
+ } from "./ui/reaction.mjs";
32
+ import { ReactionPicker } from "./ui/reaction-picker.mjs";
33
+ import {
34
+ Reactions
35
+ } from "./ui/reactions.mjs";
22
36
  import { SendButton } from "./ui/send-button.mjs";
37
+ import { registerCommentAnchorLifecycle } from "./canvas/anchor-lifecycle.mjs";
23
38
  import { CommentBody } from "./canvas/comment-body.mjs";
24
39
  import {
25
- CommentTool,
26
- commentToolOverrides,
27
- commentTools
28
- } from "./canvas/comment-tool.mjs";
29
- import { collectClusterLeaves } from "./canvas/cluster-input.mjs";
30
- import { computeClusterTable } from "./clustering/computeClusterTable.mjs";
40
+ deleteComment,
41
+ deleteThread,
42
+ editComment,
43
+ putCommentRecords,
44
+ removeCommentRecords,
45
+ reopenThread,
46
+ resolveThread
47
+ } from "./canvas/comment-mutations.mjs";
31
48
  import {
49
+ CommentReactionPicker,
50
+ CommentReactions,
51
+ summarizeReactions,
52
+ toggleCommentReaction,
53
+ useCommentReactions
54
+ } from "./canvas/comment-reactions.mjs";
55
+ import { CommentTool, commentToolOverrides, commentTools } from "./canvas/comment-tool.mjs";
56
+ import {
57
+ getCommentReactions,
32
58
  getCommentRecord,
33
59
  getComments,
34
60
  getCommentThreads,
35
- putCommentRecords,
36
- removeCommentRecords
61
+ getLiveComments,
62
+ getLiveCommentThreads
37
63
  } from "./canvas/comment-store.mjs";
38
- import { createClusterRuntime } from "./clustering/runtime.mjs";
39
64
  import { CommentsFilterMenu } from "./canvas/comments-filter-menu.mjs";
40
65
  import { CommentsMenuItem } from "./canvas/comments-menu-item.mjs";
41
66
  import { CanvasComments } from "./canvas/comments-overlay.mjs";
42
67
  import {
43
68
  defaultCommentingOptions,
69
+ getCanComment,
44
70
  getCommentingOptions,
71
+ useCanComment,
45
72
  useCommentingOptions
46
73
  } from "./canvas/options.mjs";
47
74
  import { CommentsOverflowMenu } from "./canvas/comments-overflow-menu.mjs";
75
+ import { CommentsVisibilityToggle } from "./canvas/comments-visibility-toggle.mjs";
48
76
  import { CanvasCommentsSidebar } from "./canvas/comments-sidebar.mjs";
49
77
  import { useComments, useCommentThreads, useThreadComments } from "./canvas/hooks.mjs";
50
78
  import { useCommentingEnabled } from "./canvas/license.mjs";
51
- import { DEFAULT_REGION_COMMENT_OPTIONS } from "./canvas/region-options.mjs";
52
79
  import { richTextToPlaintext } from "./canvas/rich-text.mjs";
53
80
  import { DEFAULT_SIDEBAR_FILTERS } from "./canvas/sidebar-filters.mjs";
54
81
  import {
55
82
  commentsHidden,
56
- commitCommentMutation,
83
+ commentsSidebarOpen,
84
+ getRevealThreadPending,
57
85
  openThreadId,
58
- pendingComment,
86
+ revealThread,
59
87
  sidebarFilters,
60
88
  toggleCommentsHidden,
89
+ toggleCommentsSidebar,
61
90
  useCommentsHidden,
91
+ useCommentsSidebarOpen,
62
92
  useOpenThreadId,
63
- usePendingComment,
93
+ useRevealThreadPending,
64
94
  useSidebarFilters
65
95
  } from "./canvas/state.mjs";
66
- import {
67
- anchorPagePoint,
68
- DEFAULT_IMPRECISE_SHAPE_ANCHOR,
69
- focusThread,
70
- shapeAnchorAt
71
- } from "./canvas/thread-state.mjs";
96
+ import { anchorPagePoint, focusThread, shapeAnchorAt } from "./canvas/thread-state.mjs";
72
97
  registerTldrawLibraryVersion(
73
98
  "@tldraw/commenting",
74
- "0.0.0-bootstrap",
99
+ "5.3.0-canary.31036673d3f8",
75
100
  "esm"
76
101
  );
77
102
  export {
@@ -83,56 +108,77 @@ export {
83
108
  CommentCard,
84
109
  CommentComposer,
85
110
  CommentPin,
86
- CommentText,
111
+ CommentReactionPicker,
112
+ CommentReactions,
87
113
  CommentThread,
88
114
  CommentTool,
89
115
  CommentsFilterMenu,
90
116
  CommentsList,
91
117
  CommentsMenuItem,
92
118
  CommentsOverflowMenu,
119
+ CommentsVisibilityToggle,
93
120
  CountBadge,
94
- DEFAULT_IMPRECISE_SHAPE_ANCHOR,
95
- DEFAULT_REGION_COMMENT_OPTIONS,
121
+ DEFAULT_REACTION_EMOJI,
96
122
  DEFAULT_SIDEBAR_FILTERS,
123
+ DefaultReactionTooltip,
124
+ DefaultReactionTooltipContent,
125
+ EmojiPicker,
97
126
  EmptyState,
98
127
  Mention,
99
128
  MentionList,
100
129
  Reaction,
130
+ ReactionPicker,
101
131
  Reactions,
102
132
  SendButton,
103
133
  anchorPagePoint,
104
- collectClusterLeaves,
105
134
  commentToolOverrides,
106
135
  commentTools,
107
136
  commentsHidden,
108
- commitCommentMutation,
109
- computeClusterTable,
110
- createClusterRuntime,
137
+ commentsSidebarOpen,
111
138
  createMentionSuggestion,
112
139
  defaultCommentingOptions,
140
+ defaultRenderReaction,
141
+ deleteComment,
142
+ deleteThread,
143
+ editComment,
113
144
  filterMentionMembers,
114
145
  focusThread,
115
146
  formatRelativeTime,
147
+ getCanComment,
148
+ getCommentReactions,
116
149
  getCommentRecord,
117
150
  getCommentThreads,
118
151
  getCommentingOptions,
119
152
  getComments,
153
+ getLiveCommentThreads,
154
+ getLiveComments,
155
+ getRevealThreadPending,
156
+ isAllowedReactionEmoji,
157
+ isOpenInNewTabClick,
120
158
  openThreadId,
121
- pendingComment,
122
159
  putCommentRecords,
160
+ registerCommentAnchorLifecycle,
123
161
  removeCommentRecords,
124
- renderMarkdown,
162
+ reopenThread,
163
+ resolveThread,
164
+ revealThread,
125
165
  richTextToPlaintext,
126
166
  shapeAnchorAt,
127
167
  sidebarFilters,
168
+ summarizeReactions,
169
+ toggleCommentReaction,
128
170
  toggleCommentsHidden,
171
+ toggleCommentsSidebar,
172
+ useCanComment,
173
+ useCommentReactions,
129
174
  useCommentThreads,
130
175
  useCommentingEnabled,
131
176
  useCommentingOptions,
132
177
  useComments,
133
178
  useCommentsHidden,
179
+ useCommentsSidebarOpen,
134
180
  useOpenThreadId,
135
- usePendingComment,
181
+ useRevealThreadPending,
136
182
  useSidebarFilters,
137
183
  useThreadComments
138
184
  };
@@ -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,SAAS,oCAAoC;AAI7C,SAAS,cAAgC;AACzC,SAAS,cAAgC;AACzC,SAAS,mBAA0C;AACnD,SAAS,uBAAkD;AAC3D,SAAS,kBAAwC;AACjD,SAAS,kBAAwC;AACjD,SAAS,mBAA0C;AACnD,SAAS,qBAA8C;AACvD,SAAS,oBAAuE;AAChF,SAAS,kBAAwC;AACjD,SAAS,0BAA0B;AACnC,SAAS,eAAkC;AAC3C,SAAS,mBAA8D;AACvE;AAAA,EACC;AAAA,EACA;AAAA,OAEM;AACP,SAAS,gBAAoC;AAC7C,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAC/B,SAAS,kBAAwC;AAKjD,SAAS,mBAA0C;AACnD;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OAEM;AACP,SAAS,4BAA4B;AACrC,SAAS,2BAA2B;AACpC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEM;AACP,SAAS,4BAAiD;AAQ1D,SAAS,0BAAwD;AACjE,SAAS,wBAAwB;AACjC,SAAS,sBAAgD;AACzD;AAAA,EAGC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,4BAA4B;AACrC,SAAS,6BAA8D;AACvE,SAAS,aAAa,mBAAmB,yBAAyB;AAClE,SAAS,4BAA4B;AACrC,SAAS,sCAAiE;AAC1E,SAAS,2BAA2B;AACpC,SAAS,+BAAoD;AAC7D;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAEP;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. The mention picker, pill, and avatar are re-exported from @tldraw/mentions\n// so the commenting public API is unchanged.\nexport {\n\tAvatar,\n\ttype AvatarProps,\n\ttype CommentAuthor,\n\tcreateMentionSuggestion,\n\tfilterMentionMembers,\n\tMention,\n\tMentionList,\n\ttype MentionListProps,\n\ttype MentionMember,\n\ttype MentionProps,\n\ttype MentionSuggestionOptions,\n} from '@tldraw/mentions'\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 { CommentThread, type CommentThreadProps } from './ui/comment-thread'\nexport {\n\tCommentsList,\n\tisOpenInNewTabClick,\n\ttype CommentListItemProps,\n\ttype CommentsListProps,\n} from './ui/comments-list'\nexport { EmptyState, type EmptyStateProps } from './ui/empty-state'\nexport { formatRelativeTime } from './ui/format-time'\nexport {\n\tDEFAULT_REACTION_EMOJI,\n\tEmojiPicker,\n\ttype EmojiPickerProps,\n\tisAllowedReactionEmoji,\n} from './ui/emoji-picker'\nexport {\n\tReaction,\n\ttype ReactionProps,\n\ttype RenderReaction,\n\tdefaultRenderReaction,\n\tDefaultReactionTooltip,\n\tDefaultReactionTooltipContent,\n\ttype ReactionTooltipProps,\n} from './ui/reaction'\nexport { ReactionPicker, type ReactionPickerProps } from './ui/reaction-picker'\nexport {\n\tReactions,\n\ttype ReactionReactor,\n\ttype ReactionsProps,\n\ttype ReactionSummary,\n} from './ui/reactions'\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 { registerCommentAnchorLifecycle } from './canvas/anchor-lifecycle'\nexport { CommentBody, type CommentBodyProps } from './canvas/comment-body'\nexport {\n\tdeleteComment,\n\tdeleteThread,\n\teditComment,\n\tputCommentRecords,\n\tremoveCommentRecords,\n\treopenThread,\n\tresolveThread,\n} from './canvas/comment-mutations'\nexport {\n\tCommentReactionPicker,\n\ttype CommentReactionPickerProps,\n\tCommentReactions,\n\ttype CommentReactionsProps,\n\tsummarizeReactions,\n\ttoggleCommentReaction,\n\tuseCommentReactions,\n} from './canvas/comment-reactions'\nexport { CommentTool, commentToolOverrides, commentTools } from './canvas/comment-tool'\nexport {\n\tgetCommentReactions,\n\tgetCommentRecord,\n\tgetComments,\n\tgetCommentThreads,\n\tgetLiveComments,\n\tgetLiveCommentThreads,\n\ttype TLCommentRecord,\n} from './canvas/comment-store'\nexport { type CommentingContext } from './canvas/context'\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\tgetCanComment,\n\tgetCommentingOptions,\n\ttype ShapeCommentPrecisionContext,\n\tuseCanComment,\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 { richTextToPlaintext } from './canvas/rich-text'\nexport { DEFAULT_SIDEBAR_FILTERS, type SidebarFilters } from './canvas/sidebar-filters'\nexport {\n\tcommentsHidden,\n\tcommentsSidebarOpen,\n\tgetRevealThreadPending,\n\topenThreadId,\n\trevealThread,\n\tsidebarFilters,\n\ttoggleCommentsHidden,\n\ttoggleCommentsSidebar,\n\tuseCommentsHidden,\n\tuseCommentsSidebarOpen,\n\tuseOpenThreadId,\n\tuseRevealThreadPending,\n\tuseSidebarFilters,\n} from './canvas/state'\nexport { anchorPagePoint, focusThread, shapeAnchorAt } 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,SAAS,oCAAoC;AAK7C;AAAA,EACC;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKM;AACP,SAAS,cAAgC;AACzC,SAAS,mBAA0C;AACnD,SAAS,uBAAkD;AAC3D,SAAS,kBAAwC;AACjD,SAAS,kBAAwC;AACjD,SAAS,qBAA8C;AACvD;AAAA,EACC;AAAA,EACA;AAAA,OAGM;AACP,SAAS,kBAAwC;AACjD,SAAS,0BAA0B;AACnC;AAAA,EACC;AAAA,EACA;AAAA,EAEA;AAAA,OACM;AACP;AAAA,EACC;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,OAEM;AACP,SAAS,sBAAgD;AACzD;AAAA,EACC;AAAA,OAIM;AACP,SAAS,kBAAwC;AAKjD,SAAS,sCAAsC;AAC/C,SAAS,mBAA0C;AACnD;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP;AAAA,EACC;AAAA,EAEA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,aAAa,sBAAsB,oBAAoB;AAChE;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEM;AAEP,SAAS,0BAAwD;AACjE,SAAS,wBAAwB;AACjC,SAAS,sBAAgD;AACzD;AAAA,EAGC;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,OACM;AACP,SAAS,4BAA4B;AACrC,SAAS,gCAAgC;AACzC,SAAS,6BAA8D;AACvE,SAAS,aAAa,mBAAmB,yBAAyB;AAClE,SAAS,4BAA4B;AACrC,SAAS,2BAA2B;AACpC,SAAS,+BAAoD;AAC7D;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,iBAAiB,aAAa,qBAAqB;AAE5D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,11 +1,13 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Avatar } from "@tldraw/mentions";
2
3
  import { formatRelativeTime } from "./format-time.mjs";
3
4
  function Byline({ author, date, edited }) {
4
- return /* @__PURE__ */ jsxs("div", { className: "cmt-head", children: [
5
- /* @__PURE__ */ jsx("span", { className: "cmt-author", children: author }),
6
- /* @__PURE__ */ jsxs("span", { className: "cmt-time", children: [
5
+ return /* @__PURE__ */ jsxs("div", { className: "tlui-cmt-head", children: [
6
+ /* @__PURE__ */ jsx(Avatar, { author }),
7
+ /* @__PURE__ */ jsx("span", { className: "tlui-cmt-author", children: author.name }),
8
+ /* @__PURE__ */ jsxs("span", { className: "tlui-cmt-time", children: [
7
9
  formatRelativeTime(date),
8
- edited && /* @__PURE__ */ jsx("span", { className: "cmt-edited", children: " \xB7 edited" })
10
+ edited && /* @__PURE__ */ jsx("span", { className: "tlui-cmt-edited", children: " \xB7 edited" })
9
11
  ] })
10
12
  ] });
11
13
  }
@@ -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": "AAeG,cACA,YADA;AAfH,SAAS,0BAA0B;AAY5B,SAAS,OAAO,EAAE,QAAQ,MAAM,OAAO,GAAgB;AAC7D,SACC,qBAAC,SAAI,WAAU,YACd;AAAA,wBAAC,UAAK,WAAU,cAAc,kBAAO;AAAA,IACrC,qBAAC,UAAK,WAAU,YACd;AAAA,yBAAmB,IAAI;AAAA,MACvB,UAAU,oBAAC,UAAK,WAAU,cAAa,0BAAS;AAAA,OAClD;AAAA,KACD;AAEF;",
4
+ "sourcesContent": ["import { Avatar, type CommentAuthor } from '@tldraw/mentions'\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<Avatar author={author} />\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": "AAgBG,cAEA,YAFA;AAhBH,SAAS,cAAkC;AAC3C,SAAS,0BAA0B;AAY5B,SAAS,OAAO,EAAE,QAAQ,MAAM,OAAO,GAAgB;AAC7D,SACC,qBAAC,SAAI,WAAU,iBACd;AAAA,wBAAC,UAAO,QAAgB;AAAA,IACxB,oBAAC,UAAK,WAAU,mBAAmB,iBAAO,MAAK;AAAA,IAC/C,qBAAC,UAAK,WAAU,iBACd;AAAA,yBAAmB,IAAI;AAAA,MACvB,UAAU,oBAAC,UAAK,WAAU,mBAAkB,0BAAS;AAAA,OACvD;AAAA,KACD;AAEF;",
6
6
  "names": []
7
7
  }
@@ -1,14 +1,21 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { Avatar } from "./avatar.mjs";
3
2
  import { Byline } from "./byline.mjs";
4
- function CommentCard({ author, body, date, you, edited, actions }) {
5
- return /* @__PURE__ */ jsxs("div", { className: you ? "cmt-card cmt-card--you" : "cmt-card", children: [
6
- /* @__PURE__ */ jsx(Avatar, { name: author }),
7
- /* @__PURE__ */ jsxs("div", { className: "cmt-body", children: [
8
- /* @__PURE__ */ jsx(Byline, { author, date, edited }),
9
- body
3
+ function CommentCard({
4
+ author,
5
+ body,
6
+ date,
7
+ you,
8
+ edited,
9
+ actions,
10
+ footer
11
+ }) {
12
+ return /* @__PURE__ */ jsxs("div", { className: you ? "tlui-cmt-card tlui-cmt-card--you" : "tlui-cmt-card", children: [
13
+ /* @__PURE__ */ jsx(Byline, { author, date, edited }),
14
+ /* @__PURE__ */ jsxs("div", { className: "tlui-cmt-body", children: [
15
+ body,
16
+ footer
10
17
  ] }),
11
- actions !== void 0 && /* @__PURE__ */ jsx("div", { className: "cmt-card__actions", children: actions })
18
+ actions !== void 0 && /* @__PURE__ */ jsx("div", { className: "tlui-cmt-card__actions", children: actions })
12
19
  ] });
13
20
  }
14
21
  export {
@@ -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": "AAuBG,cACA,YADA;AAtBH,SAAS,cAAc;AACvB,SAAS,cAAc;AAkBhB,SAAS,YAAY,EAAE,QAAQ,MAAM,MAAM,KAAK,QAAQ,QAAQ,GAAqB;AAC3F,SACC,qBAAC,SAAI,WAAW,MAAM,2BAA2B,YAChD;AAAA,wBAAC,UAAO,MAAM,QAAQ;AAAA,IACtB,qBAAC,SAAI,WAAU,YACd;AAAA,0BAAC,UAAO,QAAgB,MAAY,QAAgB;AAAA,MACnD;AAAA,OACF;AAAA,IACC,YAAY,UAAa,oBAAC,SAAI,WAAU,qBAAqB,mBAAQ;AAAA,KACvE;AAEF;",
4
+ "sourcesContent": ["import { type CommentAuthor } from '@tldraw/mentions'\nimport { ReactNode } from 'react'\nimport { Byline } from './byline'\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 `<CommentBody>`\n\t * for a comment's rich text, or any node of your own. */\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\t/** Content under the body, aligned with it rather than the avatar (e.g. a `<Reactions>` row). */\n\tfooter?: ReactNode\n}\n\n/** A single comment: Avatar, Byline, and a body slot the consumer renders. @public @react */\nexport function CommentCard({\n\tauthor,\n\tbody,\n\tdate,\n\tyou,\n\tedited,\n\tactions,\n\tfooter,\n}: CommentCardProps) {\n\treturn (\n\t\t<div className={you ? 'tlui-cmt-card tlui-cmt-card--you' : 'tlui-cmt-card'}>\n\t\t\t<Byline author={author} date={date} edited={edited} />\n\t\t\t<div className=\"tlui-cmt-body\">\n\t\t\t\t{body}\n\t\t\t\t{footer}\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": "AAiCG,cACA,YADA;AA/BH,SAAS,cAAc;AAoBhB,SAAS,YAAY;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAqB;AACpB,SACC,qBAAC,SAAI,WAAW,MAAM,qCAAqC,iBAC1D;AAAA,wBAAC,UAAO,QAAgB,MAAY,QAAgB;AAAA,IACpD,qBAAC,SAAI,WAAU,iBACb;AAAA;AAAA,MACA;AAAA,OACF;AAAA,IACC,YAAY,UAAa,oBAAC,SAAI,WAAU,0BAA0B,mBAAQ;AAAA,KAC5E;AAEF;",
6
6
  "names": []
7
7
  }
@@ -1,12 +1,20 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { Extension } from "@tiptap/core";
3
2
  import { EditorContent, useEditor } from "@tiptap/react";
4
- import { useEffect, useMemo, useRef, useState } from "react";
3
+ import {
4
+ Avatar,
5
+ createMentionExtension,
6
+ createMentionSuggestion,
7
+ isMentionPickerOpen
8
+ } from "@tldraw/mentions";
9
+ import {
10
+ useEffect,
11
+ useLayoutEffect,
12
+ useMemo,
13
+ useRef,
14
+ useState
15
+ } from "react";
5
16
  import { isEqual, useMaybeEditor } from "tldraw";
6
- import { Avatar } from "./avatar.mjs";
7
17
  import { commentTipTapExtensions, EMPTY_COMMENT, isCommentEmpty } from "./comment-extensions.mjs";
8
- import { commentMention } from "./comment-mention.mjs";
9
- import { createMentionSuggestion, isMentionPickerOpen } from "./mention-suggestion.mjs";
10
18
  import { SendButton } from "./send-button.mjs";
11
19
  function CommentComposer({
12
20
  author,
@@ -15,6 +23,7 @@ function CommentComposer({
15
23
  onChange,
16
24
  onSubmit,
17
25
  sendLabel = "Send",
26
+ onArrowUpWhenEmpty,
18
27
  disabled,
19
28
  autoFocus,
20
29
  leading,
@@ -27,6 +36,8 @@ function CommentComposer({
27
36
  onChangeRef.current = onChange;
28
37
  const onSubmitRef = useRef(onSubmit);
29
38
  onSubmitRef.current = onSubmit;
39
+ const onArrowUpWhenEmptyRef = useRef(onArrowUpWhenEmpty);
40
+ onArrowUpWhenEmptyRef.current = onArrowUpWhenEmpty;
30
41
  const disabledRef = useRef(disabled);
31
42
  disabledRef.current = disabled;
32
43
  const getMentionSuggestionsRef = useRef(getMentionSuggestions);
@@ -34,31 +45,55 @@ function CommentComposer({
34
45
  const renderMentionSuggestionRef = useRef(renderMentionSuggestion);
35
46
  renderMentionSuggestionRef.current = renderMentionSuggestion;
36
47
  const [isEmpty, setIsEmpty] = useState(() => !value || isCommentEmpty(value));
37
- const submitExtension = useMemo(
38
- () => Extension.create({
39
- name: "commentComposerSubmit",
40
- priority: 1e3,
41
- addKeyboardShortcuts() {
42
- return {
43
- Enter: () => {
44
- if (isMentionPickerOpen()) return false;
45
- if (!disabledRef.current) onSubmitRef.current?.();
46
- return true;
47
- }
48
- };
49
- }
50
- }),
51
- []
52
- );
48
+ const [expanded, setExpanded] = useState(false);
49
+ const expandedRef = useRef(expanded);
50
+ expandedRef.current = expanded;
51
+ const inputWrapRef = useRef(null);
52
+ const mirrorRef = useRef(null);
53
+ const remeasure = () => {
54
+ const wrap = inputWrapRef.current;
55
+ const mirror = mirrorRef.current;
56
+ const editor2 = editorRef.current;
57
+ if (!wrap || !mirror || !editor2) return;
58
+ if (editor2.isEmpty) {
59
+ if (expandedRef.current) setExpanded(false);
60
+ return;
61
+ }
62
+ if (wrap.clientWidth === 0) return;
63
+ const doc = editor2.state.doc;
64
+ const multiBlock = doc.childCount > 1 || doc.firstChild !== null && doc.firstChild.type.name !== "paragraph";
65
+ if (multiBlock) {
66
+ if (!expandedRef.current) setExpanded(true);
67
+ return;
68
+ }
69
+ const field = wrap.parentElement;
70
+ const send = field ? field.querySelector(".tlui-cmt-send") : null;
71
+ const input = wrap.querySelector(".tlui-cmt-input");
72
+ if (!send || !input) return;
73
+ mirror.innerHTML = input.innerHTML;
74
+ const textWidth = mirror.offsetWidth;
75
+ const wrapStyle = getComputedStyle(wrap);
76
+ const wrapPadX = parseFloat(wrapStyle.paddingLeft) + parseFloat(wrapStyle.paddingRight);
77
+ const collapsedAvailable = wrap.clientWidth - wrapPadX - (expandedRef.current ? send.offsetWidth + 6 : 0);
78
+ if (!expandedRef.current && textWidth > collapsedAvailable - 8) {
79
+ setExpanded(true);
80
+ } else if (expandedRef.current && textWidth < collapsedAvailable - 24) {
81
+ setExpanded(false);
82
+ }
83
+ };
84
+ const remeasureRef = useRef(remeasure);
85
+ remeasureRef.current = remeasure;
86
+ const editorRef = useRef(null);
87
+ const replayingEnter = useRef(false);
53
88
  const mentionsEnabled = !!getMentionSuggestions;
54
89
  const hasCustomRow = !!renderMentionSuggestion;
55
90
  const extensions = useMemo(() => {
56
- const list = [...commentTipTapExtensions, submitExtension];
91
+ const list = [...commentTipTapExtensions];
57
92
  if (mentionsEnabled) {
58
93
  const resolveSuggestions = (query) => getMentionSuggestionsRef.current?.(query) ?? [];
59
94
  const renderRow = hasCustomRow ? (member) => renderMentionSuggestionRef.current?.(member) : void 0;
60
95
  list.push(
61
- commentMention({
96
+ createMentionExtension({
62
97
  suggestion: createMentionSuggestion(resolveSuggestions, {
63
98
  renderMember: renderRow,
64
99
  editor: tlEditor
@@ -66,10 +101,10 @@ function CommentComposer({
66
101
  })
67
102
  );
68
103
  } else {
69
- list.push(commentMention({ suggestion: { char: "@", allow: () => false } }));
104
+ list.push(createMentionExtension({ suggestion: { char: "@", allow: () => false } }));
70
105
  }
71
106
  return list;
72
- }, [submitExtension, mentionsEnabled, hasCustomRow, tlEditor]);
107
+ }, [mentionsEnabled, hasCustomRow, tlEditor]);
73
108
  const editor = useEditor(
74
109
  {
75
110
  extensions,
@@ -80,34 +115,111 @@ function CommentComposer({
80
115
  // mirrors RichTextArea's setup.
81
116
  enableCoreExtensions: { textDirection: false },
82
117
  textDirection: "auto",
83
- editorProps: { attributes: { class: "cmt-input" } },
118
+ editorProps: {
119
+ attributes: {
120
+ class: "tlui-cmt-input",
121
+ "aria-label": placeholder,
122
+ role: "textbox",
123
+ "aria-multiline": "true"
124
+ },
125
+ // Runs before every keymap plugin, so it can distinguish Shift+Enter from Enter — an
126
+ // `Enter` keymap binding also fires on Shift+Enter and would otherwise swallow it.
127
+ handleKeyDown: (_view, event) => {
128
+ if (replayingEnter.current) return false;
129
+ if (event.key === "ArrowUp" && !event.isComposing) {
130
+ if (onArrowUpWhenEmptyRef.current && editorRef.current?.isEmpty && !isMentionPickerOpen()) {
131
+ onArrowUpWhenEmptyRef.current();
132
+ return true;
133
+ }
134
+ return false;
135
+ }
136
+ if (event.key !== "Enter" || event.isComposing) return false;
137
+ if (isMentionPickerOpen()) return false;
138
+ if (event.shiftKey && !event.metaKey && !event.ctrlKey && !event.altKey) {
139
+ if (editorRef.current?.isEmpty) return true;
140
+ replayingEnter.current = true;
141
+ try {
142
+ editorRef.current?.commands.enter();
143
+ } finally {
144
+ replayingEnter.current = false;
145
+ }
146
+ return true;
147
+ }
148
+ if (!disabledRef.current) onSubmitRef.current?.();
149
+ return true;
150
+ }
151
+ },
84
152
  onUpdate: ({ editor: editor2 }) => {
85
153
  setIsEmpty(editor2.isEmpty);
154
+ remeasureRef.current();
86
155
  onChangeRef.current?.(editor2.getJSON());
87
156
  }
88
157
  },
89
- [interactive]
158
+ [interactive, placeholder]
90
159
  );
160
+ editorRef.current = editor;
91
161
  useEffect(() => {
92
162
  if (!editor || value === void 0) return;
93
163
  if (isEqual(editor.getJSON(), value)) return;
94
164
  editor.commands.setContent(value);
95
165
  setIsEmpty(editor.isEmpty);
96
166
  }, [editor, value]);
167
+ useLayoutEffect(() => {
168
+ remeasureRef.current();
169
+ }, [editor, value]);
97
170
  useEffect(() => {
98
171
  if (!autoFocus || !editor) return;
99
172
  const raf = requestAnimationFrame(() => editor.commands.focus("end"));
100
173
  return () => cancelAnimationFrame(raf);
101
174
  }, [autoFocus, editor]);
102
- return /* @__PURE__ */ jsxs("div", { className: "cmt-composer", children: [
103
- leading ?? /* @__PURE__ */ jsx(Avatar, { name: author }),
104
- /* @__PURE__ */ jsxs("div", { className: "cmt-composer__field", children: [
105
- /* @__PURE__ */ jsxs("div", { className: "cmt-composer__input-wrap", children: [
106
- /* @__PURE__ */ jsx(EditorContent, { editor }),
107
- isEmpty && /* @__PURE__ */ jsx("div", { className: "cmt-input__placeholder", "aria-hidden": "true", children: placeholder })
108
- ] }),
109
- interactive && /* @__PURE__ */ jsx(SendButton, { label: sendLabel, onClick: onSubmit, disabled })
110
- ] })
175
+ useEffect(() => {
176
+ const wrap = inputWrapRef.current;
177
+ if (!wrap) return;
178
+ const onWheel = (e) => {
179
+ const input = wrap.querySelector(".tlui-cmt-input");
180
+ if (!input || input.scrollHeight <= input.clientHeight) return;
181
+ const atTop = input.scrollTop <= 0;
182
+ const atBottom = input.scrollTop >= input.scrollHeight - input.clientHeight - 1;
183
+ if (e.deltaY < 0 && !atTop || e.deltaY > 0 && !atBottom) {
184
+ e.stopPropagation();
185
+ }
186
+ };
187
+ wrap.addEventListener("wheel", onWheel);
188
+ return () => wrap.removeEventListener("wheel", onWheel);
189
+ }, []);
190
+ const focusEditorFromField = (e) => {
191
+ const target = e.target;
192
+ if (target.closest(".tlui-cmt-input") || target.closest(".tlui-cmt-send")) return;
193
+ e.preventDefault();
194
+ editor?.commands.focus("end");
195
+ };
196
+ return /* @__PURE__ */ jsxs("div", { className: "tlui-cmt-composer", children: [
197
+ leading ?? /* @__PURE__ */ jsx(Avatar, { author }),
198
+ /* @__PURE__ */ jsxs(
199
+ "div",
200
+ {
201
+ className: [
202
+ "tlui-cmt-composer__field",
203
+ interactive && expanded && "tlui-cmt-composer__field--expanded"
204
+ ].filter(Boolean).join(" "),
205
+ onMouseDown: interactive ? focusEditorFromField : void 0,
206
+ children: [
207
+ /* @__PURE__ */ jsxs("div", { className: "tlui-cmt-composer__input-wrap", ref: inputWrapRef, children: [
208
+ /* @__PURE__ */ jsx(EditorContent, { editor }),
209
+ isEmpty && /* @__PURE__ */ jsx("div", { className: "tlui-cmt-input__placeholder", "aria-hidden": "true", children: placeholder }),
210
+ /* @__PURE__ */ jsx(
211
+ "div",
212
+ {
213
+ className: "tlui-cmt-composer__mirror tlui-cmt-input",
214
+ ref: mirrorRef,
215
+ "aria-hidden": "true"
216
+ }
217
+ )
218
+ ] }),
219
+ interactive && /* @__PURE__ */ jsx(SendButton, { label: sendLabel, onClick: onSubmit, disabled })
220
+ ]
221
+ }
222
+ )
111
223
  ] });
112
224
  }
113
225
  export {