@tldraw/commenting 0.0.0-bootstrap

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 (242) hide show
  1. package/README.md +11 -0
  2. package/commenting.css +832 -0
  3. package/dist-cjs/canvas/cluster-input.js +40 -0
  4. package/dist-cjs/canvas/cluster-input.js.map +7 -0
  5. package/dist-cjs/canvas/comment-body.js +31 -0
  6. package/dist-cjs/canvas/comment-body.js.map +7 -0
  7. package/dist-cjs/canvas/comment-render.js +72 -0
  8. package/dist-cjs/canvas/comment-render.js.map +7 -0
  9. package/dist-cjs/canvas/comment-store.js +48 -0
  10. package/dist-cjs/canvas/comment-store.js.map +7 -0
  11. package/dist-cjs/canvas/comment-tool.js +160 -0
  12. package/dist-cjs/canvas/comment-tool.js.map +7 -0
  13. package/dist-cjs/canvas/comments-filter-menu.js +109 -0
  14. package/dist-cjs/canvas/comments-filter-menu.js.map +7 -0
  15. package/dist-cjs/canvas/comments-menu-item.js +42 -0
  16. package/dist-cjs/canvas/comments-menu-item.js.map +7 -0
  17. package/dist-cjs/canvas/comments-overflow-menu.js +64 -0
  18. package/dist-cjs/canvas/comments-overflow-menu.js.map +7 -0
  19. package/dist-cjs/canvas/comments-overlay.js +1081 -0
  20. package/dist-cjs/canvas/comments-overlay.js.map +7 -0
  21. package/dist-cjs/canvas/comments-sidebar.js +134 -0
  22. package/dist-cjs/canvas/comments-sidebar.js.map +7 -0
  23. package/dist-cjs/canvas/hooks.js +45 -0
  24. package/dist-cjs/canvas/hooks.js.map +7 -0
  25. package/dist-cjs/canvas/license.js +28 -0
  26. package/dist-cjs/canvas/license.js.map +7 -0
  27. package/dist-cjs/canvas/options.js +45 -0
  28. package/dist-cjs/canvas/options.js.map +7 -0
  29. package/dist-cjs/canvas/region-options.js +49 -0
  30. package/dist-cjs/canvas/region-options.js.map +7 -0
  31. package/dist-cjs/canvas/rich-text.js +28 -0
  32. package/dist-cjs/canvas/rich-text.js.map +7 -0
  33. package/dist-cjs/canvas/sidebar-filters.js +30 -0
  34. package/dist-cjs/canvas/sidebar-filters.js.map +7 -0
  35. package/dist-cjs/canvas/state.js +76 -0
  36. package/dist-cjs/canvas/state.js.map +7 -0
  37. package/dist-cjs/canvas/thread-state.js +81 -0
  38. package/dist-cjs/canvas/thread-state.js.map +7 -0
  39. package/dist-cjs/clustering/computeClusterTable.js +83 -0
  40. package/dist-cjs/clustering/computeClusterTable.js.map +7 -0
  41. package/dist-cjs/clustering/mst.js +117 -0
  42. package/dist-cjs/clustering/mst.js.map +7 -0
  43. package/dist-cjs/clustering/replay.js +275 -0
  44. package/dist-cjs/clustering/replay.js.map +7 -0
  45. package/dist-cjs/clustering/runtime.js +134 -0
  46. package/dist-cjs/clustering/runtime.js.map +7 -0
  47. package/dist-cjs/clustering/schedule.js +170 -0
  48. package/dist-cjs/clustering/schedule.js.map +7 -0
  49. package/dist-cjs/clustering/types.js +17 -0
  50. package/dist-cjs/clustering/types.js.map +7 -0
  51. package/dist-cjs/index.d.ts +868 -0
  52. package/dist-cjs/index.js +126 -0
  53. package/dist-cjs/index.js.map +7 -0
  54. package/dist-cjs/ui/avatar.js +43 -0
  55. package/dist-cjs/ui/avatar.js.map +7 -0
  56. package/dist-cjs/ui/byline.js +35 -0
  57. package/dist-cjs/ui/byline.js.map +7 -0
  58. package/dist-cjs/ui/comment-card.js +37 -0
  59. package/dist-cjs/ui/comment-card.js.map +7 -0
  60. package/dist-cjs/ui/comment-composer.js +136 -0
  61. package/dist-cjs/ui/comment-composer.js.map +7 -0
  62. package/dist-cjs/ui/comment-extensions.js +37 -0
  63. package/dist-cjs/ui/comment-extensions.js.map +7 -0
  64. package/dist-cjs/ui/comment-mention.js +42 -0
  65. package/dist-cjs/ui/comment-mention.js.map +7 -0
  66. package/dist-cjs/ui/comment-pin.js +29 -0
  67. package/dist-cjs/ui/comment-pin.js.map +7 -0
  68. package/dist-cjs/ui/comment-text.js +29 -0
  69. package/dist-cjs/ui/comment-text.js.map +7 -0
  70. package/dist-cjs/ui/comment-thread.js +45 -0
  71. package/dist-cjs/ui/comment-thread.js.map +7 -0
  72. package/dist-cjs/ui/comments-list.js +106 -0
  73. package/dist-cjs/ui/comments-list.js.map +7 -0
  74. package/dist-cjs/ui/count-badge.js +28 -0
  75. package/dist-cjs/ui/count-badge.js.map +7 -0
  76. package/dist-cjs/ui/empty-state.js +31 -0
  77. package/dist-cjs/ui/empty-state.js.map +7 -0
  78. package/dist-cjs/ui/format-time.js +46 -0
  79. package/dist-cjs/ui/format-time.js.map +7 -0
  80. package/dist-cjs/ui/mention-list.js +70 -0
  81. package/dist-cjs/ui/mention-list.js.map +7 -0
  82. package/dist-cjs/ui/mention-suggestion.js +206 -0
  83. package/dist-cjs/ui/mention-suggestion.js.map +7 -0
  84. package/dist-cjs/ui/mention.js +31 -0
  85. package/dist-cjs/ui/mention.js.map +7 -0
  86. package/dist-cjs/ui/reaction.js +31 -0
  87. package/dist-cjs/ui/reaction.js.map +7 -0
  88. package/dist-cjs/ui/reactions.js +34 -0
  89. package/dist-cjs/ui/reactions.js.map +7 -0
  90. package/dist-cjs/ui/render-markdown.js +63 -0
  91. package/dist-cjs/ui/render-markdown.js.map +7 -0
  92. package/dist-cjs/ui/send-button.js +28 -0
  93. package/dist-cjs/ui/send-button.js.map +7 -0
  94. package/dist-esm/canvas/cluster-input.mjs +20 -0
  95. package/dist-esm/canvas/cluster-input.mjs.map +7 -0
  96. package/dist-esm/canvas/comment-body.mjs +11 -0
  97. package/dist-esm/canvas/comment-body.mjs.map +7 -0
  98. package/dist-esm/canvas/comment-render.mjs +52 -0
  99. package/dist-esm/canvas/comment-render.mjs.map +7 -0
  100. package/dist-esm/canvas/comment-store.mjs +28 -0
  101. package/dist-esm/canvas/comment-store.mjs.map +7 -0
  102. package/dist-esm/canvas/comment-tool.mjs +142 -0
  103. package/dist-esm/canvas/comment-tool.mjs.map +7 -0
  104. package/dist-esm/canvas/comments-filter-menu.mjs +99 -0
  105. package/dist-esm/canvas/comments-filter-menu.mjs.map +7 -0
  106. package/dist-esm/canvas/comments-menu-item.mjs +22 -0
  107. package/dist-esm/canvas/comments-menu-item.mjs.map +7 -0
  108. package/dist-esm/canvas/comments-overflow-menu.mjs +53 -0
  109. package/dist-esm/canvas/comments-overflow-menu.mjs.map +7 -0
  110. package/dist-esm/canvas/comments-overlay.mjs +1094 -0
  111. package/dist-esm/canvas/comments-overlay.mjs.map +7 -0
  112. package/dist-esm/canvas/comments-sidebar.mjs +120 -0
  113. package/dist-esm/canvas/comments-sidebar.mjs.map +7 -0
  114. package/dist-esm/canvas/hooks.mjs +25 -0
  115. package/dist-esm/canvas/hooks.mjs.map +7 -0
  116. package/dist-esm/canvas/license.mjs +8 -0
  117. package/dist-esm/canvas/license.mjs.map +7 -0
  118. package/dist-esm/canvas/options.mjs +27 -0
  119. package/dist-esm/canvas/options.mjs.map +7 -0
  120. package/dist-esm/canvas/region-options.mjs +29 -0
  121. package/dist-esm/canvas/region-options.mjs.map +7 -0
  122. package/dist-esm/canvas/rich-text.mjs +8 -0
  123. package/dist-esm/canvas/rich-text.mjs.map +7 -0
  124. package/dist-esm/canvas/sidebar-filters.mjs +10 -0
  125. package/dist-esm/canvas/sidebar-filters.mjs.map +7 -0
  126. package/dist-esm/canvas/state.mjs +60 -0
  127. package/dist-esm/canvas/state.mjs.map +7 -0
  128. package/dist-esm/canvas/thread-state.mjs +61 -0
  129. package/dist-esm/canvas/thread-state.mjs.map +7 -0
  130. package/dist-esm/clustering/computeClusterTable.mjs +63 -0
  131. package/dist-esm/clustering/computeClusterTable.mjs.map +7 -0
  132. package/dist-esm/clustering/mst.mjs +97 -0
  133. package/dist-esm/clustering/mst.mjs.map +7 -0
  134. package/dist-esm/clustering/replay.mjs +255 -0
  135. package/dist-esm/clustering/replay.mjs.map +7 -0
  136. package/dist-esm/clustering/runtime.mjs +114 -0
  137. package/dist-esm/clustering/runtime.mjs.map +7 -0
  138. package/dist-esm/clustering/schedule.mjs +150 -0
  139. package/dist-esm/clustering/schedule.mjs.map +7 -0
  140. package/dist-esm/clustering/types.mjs +1 -0
  141. package/dist-esm/clustering/types.mjs.map +7 -0
  142. package/dist-esm/index.d.mts +868 -0
  143. package/dist-esm/index.mjs +139 -0
  144. package/dist-esm/index.mjs.map +7 -0
  145. package/dist-esm/ui/avatar.mjs +23 -0
  146. package/dist-esm/ui/avatar.mjs.map +7 -0
  147. package/dist-esm/ui/byline.mjs +15 -0
  148. package/dist-esm/ui/byline.mjs.map +7 -0
  149. package/dist-esm/ui/comment-card.mjs +17 -0
  150. package/dist-esm/ui/comment-card.mjs.map +7 -0
  151. package/dist-esm/ui/comment-composer.mjs +116 -0
  152. package/dist-esm/ui/comment-composer.mjs.map +7 -0
  153. package/dist-esm/ui/comment-extensions.mjs +17 -0
  154. package/dist-esm/ui/comment-extensions.mjs.map +7 -0
  155. package/dist-esm/ui/comment-mention.mjs +22 -0
  156. package/dist-esm/ui/comment-mention.mjs.map +7 -0
  157. package/dist-esm/ui/comment-pin.mjs +9 -0
  158. package/dist-esm/ui/comment-pin.mjs.map +7 -0
  159. package/dist-esm/ui/comment-text.mjs +9 -0
  160. package/dist-esm/ui/comment-text.mjs.map +7 -0
  161. package/dist-esm/ui/comment-thread.mjs +25 -0
  162. package/dist-esm/ui/comment-thread.mjs.map +7 -0
  163. package/dist-esm/ui/comments-list.mjs +86 -0
  164. package/dist-esm/ui/comments-list.mjs.map +7 -0
  165. package/dist-esm/ui/count-badge.mjs +8 -0
  166. package/dist-esm/ui/count-badge.mjs.map +7 -0
  167. package/dist-esm/ui/empty-state.mjs +11 -0
  168. package/dist-esm/ui/empty-state.mjs.map +7 -0
  169. package/dist-esm/ui/format-time.mjs +26 -0
  170. package/dist-esm/ui/format-time.mjs.map +7 -0
  171. package/dist-esm/ui/mention-list.mjs +50 -0
  172. package/dist-esm/ui/mention-list.mjs.map +7 -0
  173. package/dist-esm/ui/mention-suggestion.mjs +186 -0
  174. package/dist-esm/ui/mention-suggestion.mjs.map +7 -0
  175. package/dist-esm/ui/mention.mjs +11 -0
  176. package/dist-esm/ui/mention.mjs.map +7 -0
  177. package/dist-esm/ui/reaction.mjs +11 -0
  178. package/dist-esm/ui/reaction.mjs.map +7 -0
  179. package/dist-esm/ui/reactions.mjs +14 -0
  180. package/dist-esm/ui/reactions.mjs.map +7 -0
  181. package/dist-esm/ui/render-markdown.mjs +45 -0
  182. package/dist-esm/ui/render-markdown.mjs.map +7 -0
  183. package/dist-esm/ui/send-button.mjs +8 -0
  184. package/dist-esm/ui/send-button.mjs.map +7 -0
  185. package/package.json +71 -0
  186. package/src/canvas/canvas.css +148 -0
  187. package/src/canvas/cluster-input.test.ts +223 -0
  188. package/src/canvas/cluster-input.ts +29 -0
  189. package/src/canvas/comment-body.tsx +21 -0
  190. package/src/canvas/comment-render.test.ts +90 -0
  191. package/src/canvas/comment-render.ts +92 -0
  192. package/src/canvas/comment-store.ts +55 -0
  193. package/src/canvas/comment-tool.tsx +200 -0
  194. package/src/canvas/comments-filter-menu.tsx +104 -0
  195. package/src/canvas/comments-menu-item.tsx +24 -0
  196. package/src/canvas/comments-overflow-menu.tsx +62 -0
  197. package/src/canvas/comments-overlay.tsx +1460 -0
  198. package/src/canvas/comments-sidebar.tsx +184 -0
  199. package/src/canvas/hooks.ts +28 -0
  200. package/src/canvas/license.ts +15 -0
  201. package/src/canvas/options.test.ts +127 -0
  202. package/src/canvas/options.ts +111 -0
  203. package/src/canvas/region-options.ts +57 -0
  204. package/src/canvas/rich-text.ts +15 -0
  205. package/src/canvas/sidebar-filters.ts +25 -0
  206. package/src/canvas/state.ts +102 -0
  207. package/src/canvas/thread-state.ts +91 -0
  208. package/src/clustering/computeClusterTable.test.ts +299 -0
  209. package/src/clustering/computeClusterTable.ts +82 -0
  210. package/src/clustering/locality.test.ts +189 -0
  211. package/src/clustering/mst.test.ts +383 -0
  212. package/src/clustering/mst.ts +134 -0
  213. package/src/clustering/replay.test.ts +547 -0
  214. package/src/clustering/replay.ts +326 -0
  215. package/src/clustering/runtime.test.ts +596 -0
  216. package/src/clustering/runtime.ts +153 -0
  217. package/src/clustering/schedule.test.ts +514 -0
  218. package/src/clustering/schedule.ts +184 -0
  219. package/src/clustering/types.ts +102 -0
  220. package/src/index.ts +96 -0
  221. package/src/ui/avatar.tsx +31 -0
  222. package/src/ui/byline.tsx +23 -0
  223. package/src/ui/comment-card.tsx +32 -0
  224. package/src/ui/comment-composer.tsx +179 -0
  225. package/src/ui/comment-extensions.ts +25 -0
  226. package/src/ui/comment-mention.ts +47 -0
  227. package/src/ui/comment-pin.tsx +21 -0
  228. package/src/ui/comment-text.tsx +12 -0
  229. package/src/ui/comment-thread.tsx +56 -0
  230. package/src/ui/comments-list.tsx +139 -0
  231. package/src/ui/comments.css +678 -0
  232. package/src/ui/count-badge.tsx +9 -0
  233. package/src/ui/empty-state.tsx +16 -0
  234. package/src/ui/format-time.ts +29 -0
  235. package/src/ui/mention-list.tsx +106 -0
  236. package/src/ui/mention-suggestion.test.ts +18 -0
  237. package/src/ui/mention-suggestion.tsx +285 -0
  238. package/src/ui/mention.tsx +9 -0
  239. package/src/ui/reaction.tsx +16 -0
  240. package/src/ui/reactions.tsx +15 -0
  241. package/src/ui/render-markdown.tsx +72 -0
  242. package/src/ui/send-button.tsx +15 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ui/comment-text.tsx"],
4
+ "sourcesContent": ["import { renderMarkdown } from './render-markdown'\n\n/** @public */\nexport interface CommentTextProps {\n\t/** Rich text body, authored as markdown. */\n\ttext: string\n}\n\n/** A comment's body, rendered as markdown (bold, italic, code, links, lists). @public @react */\nexport function CommentText({ text }: CommentTextProps) {\n\treturn <div className=\"cmt-text\">{renderMarkdown(text)}</div>\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAUQ;AAVR,6BAA+B;AASxB,SAAS,YAAY,EAAE,KAAK,GAAqB;AACvD,SAAO,4CAAC,SAAI,WAAU,YAAY,qDAAe,IAAI,GAAE;AACxD;",
6
+ "names": []
7
+ }
@@ -0,0 +1,45 @@
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 __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var comment_thread_exports = {};
20
+ __export(comment_thread_exports, {
21
+ CommentThread: () => CommentThread
22
+ });
23
+ module.exports = __toCommonJS(comment_thread_exports);
24
+ var import_jsx_runtime = require("react/jsx-runtime");
25
+ var import_comment_card = require("./comment-card");
26
+ var import_comment_composer = require("./comment-composer");
27
+ function CommentThread({
28
+ comments,
29
+ header,
30
+ headerActions,
31
+ resolvedBanner,
32
+ composer,
33
+ renderComment
34
+ }) {
35
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cmt-thread", children: [
36
+ (header !== void 0 || headerActions !== void 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cmt-thread__header", children: [
37
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cmt-thread__title", children: header }),
38
+ headerActions !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cmt-thread__actions", children: headerActions })
39
+ ] }),
40
+ resolvedBanner !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cmt-thread__resolved", children: resolvedBanner }),
41
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cmt-thread__list", children: comments.map((comment, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: renderComment ? renderComment(comment, i) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_comment_card.CommentCard, { ...comment }) }, i)) }),
42
+ composer !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_comment_composer.CommentComposer, { ...composer })
43
+ ] });
44
+ }
45
+ //# sourceMappingURL=comment-thread.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ui/comment-thread.tsx"],
4
+ "sourcesContent": ["import { ReactNode } from 'react'\nimport { CommentCard, CommentCardProps } from './comment-card'\nimport { CommentComposer, CommentComposerProps } from './comment-composer'\n\n/** @public */\nexport interface CommentThreadProps {\n\t/** The thread's comments, already adapted to card props (oldest first). */\n\tcomments: CommentCardProps[]\n\t/** Optional header, e.g. \"Thread\". Omit for no header. */\n\theader?: ReactNode\n\t/** Action controls shown at the right of the header (resolve, delete, dismiss\u2026). */\n\theaderActions?: ReactNode\n\t/** When set, shows a banner above the comments (e.g. \"Resolved by Jess\"). */\n\tresolvedBanner?: ReactNode\n\t/** Reply composer props. Omit for a read-only thread (no composer). */\n\tcomposer?: CommentComposerProps\n\t/** Override how each comment renders. Defaults to `<CommentCard>`. */\n\trenderComment?(comment: CommentCardProps, index: number): ReactNode\n}\n\n/**\n * A comment thread: an optional header, an optional resolved banner, the comments, and an\n * optional reply composer. Presentational \u2014 you supply the comments (as card props) and the\n * composer's handlers; how each comment renders is overridable via `renderComment`.\n * @public @react\n */\nexport function CommentThread({\n\tcomments,\n\theader,\n\theaderActions,\n\tresolvedBanner,\n\tcomposer,\n\trenderComment,\n}: CommentThreadProps) {\n\treturn (\n\t\t<div className=\"cmt-thread\">\n\t\t\t{(header !== undefined || headerActions !== undefined) && (\n\t\t\t\t<div className=\"cmt-thread__header\">\n\t\t\t\t\t<span className=\"cmt-thread__title\">{header}</span>\n\t\t\t\t\t{headerActions !== undefined && (\n\t\t\t\t\t\t<div className=\"cmt-thread__actions\">{headerActions}</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{resolvedBanner !== undefined && <div className=\"cmt-thread__resolved\">{resolvedBanner}</div>}\n\t\t\t<div className=\"cmt-thread__list\">\n\t\t\t\t{comments.map((comment, i) => (\n\t\t\t\t\t<div key={i}>\n\t\t\t\t\t\t{renderComment ? renderComment(comment, i) : <CommentCard {...comment} />}\n\t\t\t\t\t</div>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t\t{composer !== undefined && <CommentComposer {...composer} />}\n\t\t</div>\n\t)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAqCI;AApCJ,0BAA8C;AAC9C,8BAAsD;AAwB/C,SAAS,cAAc;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAuB;AACtB,SACC,6CAAC,SAAI,WAAU,cACZ;AAAA,gBAAW,UAAa,kBAAkB,WAC3C,6CAAC,SAAI,WAAU,sBACd;AAAA,kDAAC,UAAK,WAAU,qBAAqB,kBAAO;AAAA,MAC3C,kBAAkB,UAClB,4CAAC,SAAI,WAAU,uBAAuB,yBAAc;AAAA,OAEtD;AAAA,IAEA,mBAAmB,UAAa,4CAAC,SAAI,WAAU,wBAAwB,0BAAe;AAAA,IACvF,4CAAC,SAAI,WAAU,oBACb,mBAAS,IAAI,CAAC,SAAS,MACvB,4CAAC,SACC,0BAAgB,cAAc,SAAS,CAAC,IAAI,4CAAC,mCAAa,GAAG,SAAS,KAD9D,CAEV,CACA,GACF;AAAA,IACC,aAAa,UAAa,4CAAC,2CAAiB,GAAG,UAAU;AAAA,KAC3D;AAEF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,106 @@
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 __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var comments_list_exports = {};
20
+ __export(comments_list_exports, {
21
+ CommentsList: () => CommentsList
22
+ });
23
+ module.exports = __toCommonJS(comments_list_exports);
24
+ var import_jsx_runtime = require("react/jsx-runtime");
25
+ var import_avatar = require("./avatar");
26
+ var import_byline = require("./byline");
27
+ function CommentsList({
28
+ items,
29
+ onSelect,
30
+ header,
31
+ headerAction,
32
+ empty,
33
+ resolvedLabel,
34
+ renderItem
35
+ }) {
36
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cmt-list", children: [
37
+ (header !== void 0 || headerAction) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cmt-list__header", children: [
38
+ header !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cmt-list__header-title", children: header }),
39
+ headerAction
40
+ ] }),
41
+ items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cmt-list__empty", children: empty }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cmt-list__items", children: items.map(
42
+ (item) => renderItem ? renderItem(item) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43
+ CommentListItem,
44
+ {
45
+ ...item,
46
+ resolvedLabel,
47
+ onSelect
48
+ },
49
+ item.id
50
+ )
51
+ ) })
52
+ ] });
53
+ }
54
+ function CommentListItem({
55
+ id,
56
+ author,
57
+ preview,
58
+ date,
59
+ resolved,
60
+ page,
61
+ count,
62
+ selected,
63
+ resolvedLabel = "Resolved",
64
+ onSelect
65
+ }) {
66
+ const handleClick = () => {
67
+ if (onSelect) onSelect(id);
68
+ };
69
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
70
+ "button",
71
+ {
72
+ type: "button",
73
+ className: selected ? "cmt-list__item cmt-list__item--selected" : "cmt-list__item",
74
+ "data-resolved": resolved || void 0,
75
+ onClick: handleClick,
76
+ children: [
77
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_avatar.Avatar, { name: author }),
78
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cmt-list__item-body", children: [
79
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_byline.Byline, { author, date }),
80
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cmt-list__item-preview", children: preview }),
81
+ (resolved || page !== void 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cmt-list__item-meta", children: [
82
+ resolved && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "cmt-list__item-resolved", children: [
83
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CheckIcon, {}),
84
+ resolvedLabel
85
+ ] }),
86
+ page !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cmt-list__item-page", children: page })
87
+ ] })
88
+ ] }),
89
+ count !== void 0 && count > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cmt-list__item-count", children: count })
90
+ ]
91
+ }
92
+ );
93
+ }
94
+ function CheckIcon() {
95
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
96
+ "path",
97
+ {
98
+ d: "M2.5 6.2 4.7 8.4 9.5 3.6",
99
+ stroke: "currentColor",
100
+ strokeWidth: "1.5",
101
+ strokeLinecap: "round",
102
+ strokeLinejoin: "round"
103
+ }
104
+ ) });
105
+ }
106
+ //# sourceMappingURL=comments-list.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ui/comments-list.tsx"],
4
+ "sourcesContent": ["import { ReactNode } from 'react'\nimport { Avatar } from './avatar'\nimport { Byline } from './byline'\n\n/** @public */\nexport interface CommentListItemProps {\n\tid: string\n\tauthor: string\n\t/** A short preview of the thread \u2014 e.g. the first comment's body. */\n\tpreview: ReactNode\n\t/** ISO datetime of the thread's first comment. */\n\tdate: string\n\tresolved?: boolean\n\t/** Name of the page the thread lives on, shown as a small label. Omit to hide. */\n\tpage?: string\n\t/** Total comments in the thread. */\n\tcount?: number\n\t/** Whether this thread is the open one. */\n\tselected?: boolean\n}\n\n/** @public */\nexport interface CommentsListProps {\n\titems: CommentListItemProps[]\n\t/** Called with a thread id when an item is chosen. */\n\tonSelect?(id: string): void\n\t/** Shown above the list (e.g. \"Comments\"). Omit for none. */\n\theader?: ReactNode\n\t/** Rendered at the right of the header row \u2014 e.g. a filter menu. */\n\theaderAction?: ReactNode\n\t/** Shown in place of the list when there are no threads. */\n\tempty?: ReactNode\n\t/** Label for a resolved thread's marker on its row. Defaults to \"Resolved\". */\n\tresolvedLabel?: string\n\t/** Override how each item renders. Defaults to `<CommentListItem>`. */\n\trenderItem?(item: CommentListItemProps): ReactNode\n}\n\n/**\n * A scrollable list of comment threads \u2014 each an avatar, byline, and a one-line preview.\n * Presentational: you supply the items (already summarised) and an `onSelect` handler; the canvas\n * `CanvasCommentsSidebar` wires it to the store, but a consumer can build their own list from this.\n * @public @react\n */\nexport function CommentsList({\n\titems,\n\tonSelect,\n\theader,\n\theaderAction,\n\tempty,\n\tresolvedLabel,\n\trenderItem,\n}: CommentsListProps) {\n\treturn (\n\t\t<div className=\"cmt-list\">\n\t\t\t{(header !== undefined || headerAction) && (\n\t\t\t\t<div className=\"cmt-list__header\">\n\t\t\t\t\t{header !== undefined && <span className=\"cmt-list__header-title\">{header}</span>}\n\t\t\t\t\t{headerAction}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{items.length === 0 ? (\n\t\t\t\t<div className=\"cmt-list__empty\">{empty}</div>\n\t\t\t) : (\n\t\t\t\t<div className=\"cmt-list__items\">\n\t\t\t\t\t{items.map((item) =>\n\t\t\t\t\t\trenderItem ? (\n\t\t\t\t\t\t\trenderItem(item)\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<CommentListItem\n\t\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\t\t{...item}\n\t\t\t\t\t\t\t\tresolvedLabel={resolvedLabel}\n\t\t\t\t\t\t\t\tonSelect={onSelect}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\nfunction CommentListItem({\n\tid,\n\tauthor,\n\tpreview,\n\tdate,\n\tresolved,\n\tpage,\n\tcount,\n\tselected,\n\tresolvedLabel = 'Resolved',\n\tonSelect,\n}: CommentListItemProps & { resolvedLabel?: string; onSelect?(id: string): void }) {\n\tconst handleClick = () => {\n\t\tif (onSelect) onSelect(id)\n\t}\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName={selected ? 'cmt-list__item cmt-list__item--selected' : 'cmt-list__item'}\n\t\t\tdata-resolved={resolved || undefined}\n\t\t\tonClick={handleClick}\n\t\t>\n\t\t\t<Avatar name={author} />\n\t\t\t<div className=\"cmt-list__item-body\">\n\t\t\t\t<Byline author={author} date={date} />\n\t\t\t\t<div className=\"cmt-list__item-preview\">{preview}</div>\n\t\t\t\t{(resolved || page !== undefined) && (\n\t\t\t\t\t<div className=\"cmt-list__item-meta\">\n\t\t\t\t\t\t{resolved && (\n\t\t\t\t\t\t\t<span className=\"cmt-list__item-resolved\">\n\t\t\t\t\t\t\t\t<CheckIcon />\n\t\t\t\t\t\t\t\t{resolvedLabel}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{page !== undefined && <span className=\"cmt-list__item-page\">{page}</span>}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t{count !== undefined && count > 1 && <span className=\"cmt-list__item-count\">{count}</span>}\n\t\t</button>\n\t)\n}\n\nfunction CheckIcon() {\n\treturn (\n\t\t<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n\t\t\t<path\n\t\t\t\td=\"M2.5 6.2 4.7 8.4 9.5 3.6\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"1.5\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t/>\n\t\t</svg>\n\t)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwDI;AAvDJ,oBAAuB;AACvB,oBAAuB;AA0ChB,SAAS,aAAa;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAsB;AACrB,SACC,6CAAC,SAAI,WAAU,YACZ;AAAA,gBAAW,UAAa,iBACzB,6CAAC,SAAI,WAAU,oBACb;AAAA,iBAAW,UAAa,4CAAC,UAAK,WAAU,0BAA0B,kBAAO;AAAA,MACzE;AAAA,OACF;AAAA,IAEA,MAAM,WAAW,IACjB,4CAAC,SAAI,WAAU,mBAAmB,iBAAM,IAExC,4CAAC,SAAI,WAAU,mBACb,gBAAM;AAAA,MAAI,CAAC,SACX,aACC,WAAW,IAAI,IAEf;AAAA,QAAC;AAAA;AAAA,UAEC,GAAG;AAAA,UACJ;AAAA,UACA;AAAA;AAAA,QAHK,KAAK;AAAA,MAIX;AAAA,IAEF,GACD;AAAA,KAEF;AAEF;AAEA,SAAS,gBAAgB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AACD,GAAmF;AAClF,QAAM,cAAc,MAAM;AACzB,QAAI,SAAU,UAAS,EAAE;AAAA,EAC1B;AACA,SACC;AAAA,IAAC;AAAA;AAAA,MACA,MAAK;AAAA,MACL,WAAW,WAAW,4CAA4C;AAAA,MAClE,iBAAe,YAAY;AAAA,MAC3B,SAAS;AAAA,MAET;AAAA,oDAAC,wBAAO,MAAM,QAAQ;AAAA,QACtB,6CAAC,SAAI,WAAU,uBACd;AAAA,sDAAC,wBAAO,QAAgB,MAAY;AAAA,UACpC,4CAAC,SAAI,WAAU,0BAA0B,mBAAQ;AAAA,WAC/C,YAAY,SAAS,WACtB,6CAAC,SAAI,WAAU,uBACb;AAAA,wBACA,6CAAC,UAAK,WAAU,2BACf;AAAA,0DAAC,aAAU;AAAA,cACV;AAAA,eACF;AAAA,YAEA,SAAS,UAAa,4CAAC,UAAK,WAAU,uBAAuB,gBAAK;AAAA,aACpE;AAAA,WAEF;AAAA,QACC,UAAU,UAAa,QAAQ,KAAK,4CAAC,UAAK,WAAU,wBAAwB,iBAAM;AAAA;AAAA;AAAA,EACpF;AAEF;AAEA,SAAS,YAAY;AACpB,SACC,4CAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,eAAY,QACvE;AAAA,IAAC;AAAA;AAAA,MACA,GAAE;AAAA,MACF,QAAO;AAAA,MACP,aAAY;AAAA,MACZ,eAAc;AAAA,MACd,gBAAe;AAAA;AAAA,EAChB,GACD;AAEF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,28 @@
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 __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var count_badge_exports = {};
20
+ __export(count_badge_exports, {
21
+ CountBadge: () => CountBadge
22
+ });
23
+ module.exports = __toCommonJS(count_badge_exports);
24
+ var import_jsx_runtime = require("react/jsx-runtime");
25
+ function CountBadge({ count }) {
26
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cmt-count-badge", children: count });
27
+ }
28
+ //# sourceMappingURL=count-badge.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ui/count-badge.tsx"],
4
+ "sourcesContent": ["/** @public */\nexport interface CountBadgeProps {\n\tcount: number\n}\n\n/** @public @react */\nexport function CountBadge({ count }: CountBadgeProps) {\n\treturn <div className=\"cmt-count-badge\">{count}</div>\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOQ;AADD,SAAS,WAAW,EAAE,MAAM,GAAoB;AACtD,SAAO,4CAAC,SAAI,WAAU,mBAAmB,iBAAM;AAChD;",
6
+ "names": []
7
+ }
@@ -0,0 +1,31 @@
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 __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var empty_state_exports = {};
20
+ __export(empty_state_exports, {
21
+ EmptyState: () => EmptyState
22
+ });
23
+ module.exports = __toCommonJS(empty_state_exports);
24
+ var import_jsx_runtime = require("react/jsx-runtime");
25
+ function EmptyState({ message }) {
26
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cmt-empty", children: [
27
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cmt-empty__icon", "aria-hidden": "true", children: "\u{1F4AC}" }),
28
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "cmt-empty__message", children: message })
29
+ ] });
30
+ }
31
+ //# sourceMappingURL=empty-state.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ui/empty-state.tsx"],
4
+ "sourcesContent": ["/** @public */\nexport interface EmptyStateProps {\n\tmessage: string\n}\n\n/** The empty state shown when a thread has no comments yet. @public @react */\nexport function EmptyState({ message }: EmptyStateProps) {\n\treturn (\n\t\t<div className=\"cmt-empty\">\n\t\t\t<div className=\"cmt-empty__icon\" aria-hidden=\"true\">\n\t\t\t\t\uD83D\uDCAC\n\t\t\t</div>\n\t\t\t<p className=\"cmt-empty__message\">{message}</p>\n\t\t</div>\n\t)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQE;AAFK,SAAS,WAAW,EAAE,QAAQ,GAAoB;AACxD,SACC,6CAAC,SAAI,WAAU,aACd;AAAA,gDAAC,SAAI,WAAU,mBAAkB,eAAY,QAAO,uBAEpD;AAAA,IACA,4CAAC,OAAE,WAAU,sBAAsB,mBAAQ;AAAA,KAC5C;AAEF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,46 @@
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 __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var format_time_exports = {};
20
+ __export(format_time_exports, {
21
+ formatRelativeTime: () => formatRelativeTime
22
+ });
23
+ module.exports = __toCommonJS(format_time_exports);
24
+ const DIVISIONS = [
25
+ { amount: 60, unit: "second" },
26
+ { amount: 60, unit: "minute" },
27
+ { amount: 24, unit: "hour" },
28
+ { amount: 7, unit: "day" },
29
+ { amount: 4.34524, unit: "week" },
30
+ { amount: 12, unit: "month" },
31
+ { amount: Number.POSITIVE_INFINITY, unit: "year" }
32
+ ];
33
+ function formatRelativeTime(iso, locale = "en") {
34
+ const then = new Date(iso).getTime();
35
+ if (Number.isNaN(then)) return "";
36
+ const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
37
+ let duration = (then - Date.now()) / 1e3;
38
+ for (const division of DIVISIONS) {
39
+ if (Math.abs(duration) < division.amount) {
40
+ return rtf.format(Math.round(duration), division.unit);
41
+ }
42
+ duration /= division.amount;
43
+ }
44
+ return "";
45
+ }
46
+ //# sourceMappingURL=format-time.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ui/format-time.ts"],
4
+ "sourcesContent": ["const DIVISIONS = [\n\t{ amount: 60, unit: 'second' },\n\t{ amount: 60, unit: 'minute' },\n\t{ amount: 24, unit: 'hour' },\n\t{ amount: 7, unit: 'day' },\n\t{ amount: 4.34524, unit: 'week' },\n\t{ amount: 12, unit: 'month' },\n\t{ amount: Number.POSITIVE_INFINITY, unit: 'year' },\n] as const\n\n/**\n * Format an ISO datetime as relative time (\"2 hours ago\", \"yesterday\", \"last week\").\n * Locale-aware via Intl.RelativeTimeFormat.\n * @public\n */\nexport function formatRelativeTime(iso: string, locale = 'en'): string {\n\tconst then = new Date(iso).getTime()\n\tif (Number.isNaN(then)) return ''\n\n\tconst rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' })\n\tlet duration = (then - Date.now()) / 1000\n\tfor (const division of DIVISIONS) {\n\t\tif (Math.abs(duration) < division.amount) {\n\t\t\treturn rtf.format(Math.round(duration), division.unit)\n\t\t}\n\t\tduration /= division.amount\n\t}\n\treturn ''\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAAM,YAAY;AAAA,EACjB,EAAE,QAAQ,IAAI,MAAM,SAAS;AAAA,EAC7B,EAAE,QAAQ,IAAI,MAAM,SAAS;AAAA,EAC7B,EAAE,QAAQ,IAAI,MAAM,OAAO;AAAA,EAC3B,EAAE,QAAQ,GAAG,MAAM,MAAM;AAAA,EACzB,EAAE,QAAQ,SAAS,MAAM,OAAO;AAAA,EAChC,EAAE,QAAQ,IAAI,MAAM,QAAQ;AAAA,EAC5B,EAAE,QAAQ,OAAO,mBAAmB,MAAM,OAAO;AAClD;AAOO,SAAS,mBAAmB,KAAa,SAAS,MAAc;AACtE,QAAM,OAAO,IAAI,KAAK,GAAG,EAAE,QAAQ;AACnC,MAAI,OAAO,MAAM,IAAI,EAAG,QAAO;AAE/B,QAAM,MAAM,IAAI,KAAK,mBAAmB,QAAQ,EAAE,SAAS,OAAO,CAAC;AACnE,MAAI,YAAY,OAAO,KAAK,IAAI,KAAK;AACrC,aAAW,YAAY,WAAW;AACjC,QAAI,KAAK,IAAI,QAAQ,IAAI,SAAS,QAAQ;AACzC,aAAO,IAAI,OAAO,KAAK,MAAM,QAAQ,GAAG,SAAS,IAAI;AAAA,IACtD;AACA,gBAAY,SAAS;AAAA,EACtB;AACA,SAAO;AACR;",
6
+ "names": []
7
+ }
@@ -0,0 +1,70 @@
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 __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var mention_list_exports = {};
20
+ __export(mention_list_exports, {
21
+ MentionList: () => MentionList
22
+ });
23
+ module.exports = __toCommonJS(mention_list_exports);
24
+ var import_jsx_runtime = require("react/jsx-runtime");
25
+ var import_tldraw = require("tldraw");
26
+ var import_avatar = require("./avatar");
27
+ function DefaultMemberRow({ member }) {
28
+ const msg = (0, import_tldraw.useTranslation)();
29
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
30
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_avatar.Avatar, { name: member.name, color: member.color, image: member.avatar }),
31
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "cmt-mention-list__text", children: [
32
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "cmt-mention-list__name", children: [
33
+ member.name,
34
+ member.you && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cmt-mention-list__you", children: `(${msg("comments.mention-you")})` })
35
+ ] }),
36
+ member.secondary && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cmt-mention-list__secondary", children: member.secondary })
37
+ ] })
38
+ ] });
39
+ }
40
+ function MentionList({
41
+ members,
42
+ activeIndex = 0,
43
+ onSelect,
44
+ emptyLabel,
45
+ renderMember
46
+ }) {
47
+ const msg = (0, import_tldraw.useTranslation)();
48
+ if (members.length === 0) {
49
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cmt-mention-list cmt-mention-list--empty", children: emptyLabel ?? msg("comments.mention-no-matches") });
50
+ }
51
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cmt-mention-list", role: "listbox", children: members.map((member, i) => {
52
+ const active = i === activeIndex;
53
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
54
+ "button",
55
+ {
56
+ type: "button",
57
+ role: "option",
58
+ "aria-selected": active,
59
+ className: active ? "cmt-mention-list__item cmt-mention-list__item--active" : "cmt-mention-list__item",
60
+ onMouseDown: (e) => e.preventDefault(),
61
+ onClick: () => {
62
+ if (onSelect) onSelect(member);
63
+ },
64
+ children: renderMember ? renderMember(member) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultMemberRow, { member })
65
+ },
66
+ member.id
67
+ );
68
+ }) });
69
+ }
70
+ //# sourceMappingURL=mention-list.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ui/mention-list.tsx"],
4
+ "sourcesContent": ["import { ReactNode } from 'react'\nimport { useTranslation } from 'tldraw'\nimport { Avatar } from './avatar'\n\n/** A person the composer's \\@-mention picker can offer. @public */\nexport interface MentionMember {\n\tid: string\n\tname: string\n\t/** Avatar image URL. Falls back to a coloured initial when omitted. */\n\tavatar?: string\n\t/** Avatar background colour, used when there's no `avatar` image. */\n\tcolor?: string\n\t/** A secondary line under the name \u2014 e.g. an email or handle. Omit for a single-line row. */\n\tsecondary?: string\n\t/** Marks the current user; shown as a \"(You)\" suffix after the name. */\n\tyou?: boolean\n\t/** Hosts may carry extra fields; a custom `renderMember` can read them. */\n\t[key: string]: unknown\n}\n\n/** @public */\nexport interface MentionListProps {\n\t/** Members to choose from \u2014 already resolved for the current query by the host. */\n\tmembers: MentionMember[]\n\t/** Index of the highlighted row, driven by the composer's keyboard navigation. */\n\tactiveIndex?: number\n\t/** Called when a member is chosen (click, or Enter on the active row). */\n\tonSelect?(member: MentionMember): void\n\t/** Shown when no member matches the query. Defaults to a translated \"No matches\". */\n\temptyLabel?: string\n\t/** Override a row's content (inside the selectable button). Defaults to avatar + name (+ secondary). */\n\trenderMember?(member: MentionMember): ReactNode\n}\n\n/** The default row content: avatar, name (with a \"(You)\" marker), and an optional secondary line. */\nfunction DefaultMemberRow({ member }: { member: MentionMember }) {\n\tconst msg = useTranslation()\n\treturn (\n\t\t<>\n\t\t\t<Avatar name={member.name} color={member.color} image={member.avatar} />\n\t\t\t<span className=\"cmt-mention-list__text\">\n\t\t\t\t<span className=\"cmt-mention-list__name\">\n\t\t\t\t\t{member.name}\n\t\t\t\t\t{member.you && (\n\t\t\t\t\t\t<span className=\"cmt-mention-list__you\">{`(${msg('comments.mention-you')})`}</span>\n\t\t\t\t\t)}\n\t\t\t\t</span>\n\t\t\t\t{member.secondary && (\n\t\t\t\t\t<span className=\"cmt-mention-list__secondary\">{member.secondary}</span>\n\t\t\t\t)}\n\t\t\t</span>\n\t\t</>\n\t)\n}\n\n/**\n * The \\@-mention member picker: a popover list of people to mention, shown as the user types after\n * `@`. Presentational \u2014 the composer's suggestion plugin owns resolution, keyboard navigation, and\n * placement, and drives this with the host-resolved `members` and the highlighted `activeIndex`.\n * @public @react\n */\nexport function MentionList({\n\tmembers,\n\tactiveIndex = 0,\n\tonSelect,\n\temptyLabel,\n\trenderMember,\n}: MentionListProps) {\n\tconst msg = useTranslation()\n\tif (members.length === 0) {\n\t\treturn (\n\t\t\t<div className=\"cmt-mention-list cmt-mention-list--empty\">\n\t\t\t\t{emptyLabel ?? msg('comments.mention-no-matches')}\n\t\t\t</div>\n\t\t)\n\t}\n\treturn (\n\t\t<div className=\"cmt-mention-list\" role=\"listbox\">\n\t\t\t{members.map((member, i) => {\n\t\t\t\tconst active = i === activeIndex\n\t\t\t\treturn (\n\t\t\t\t\t<button\n\t\t\t\t\t\tkey={member.id}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\trole=\"option\"\n\t\t\t\t\t\taria-selected={active}\n\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\tactive\n\t\t\t\t\t\t\t\t? 'cmt-mention-list__item cmt-mention-list__item--active'\n\t\t\t\t\t\t\t\t: 'cmt-mention-list__item'\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Keep the composer focused on a row press: it's portaled outside the editor, so a\n\t\t\t\t\t\t// bare mousedown would blur the composer \u2014 which now dismisses the picker \u2014 before\n\t\t\t\t\t\t// the click could select. Selection runs on click; focus stays put.\n\t\t\t\t\t\tonMouseDown={(e) => e.preventDefault()}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tif (onSelect) onSelect(member)\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{renderMember ? renderMember(member) : <DefaultMemberRow member={member} />}\n\t\t\t\t\t</button>\n\t\t\t\t)\n\t\t\t})}\n\t\t</div>\n\t)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAsCE;AArCF,oBAA+B;AAC/B,oBAAuB;AAiCvB,SAAS,iBAAiB,EAAE,OAAO,GAA8B;AAChE,QAAM,UAAM,8BAAe;AAC3B,SACC,4EACC;AAAA,gDAAC,wBAAO,MAAM,OAAO,MAAM,OAAO,OAAO,OAAO,OAAO,OAAO,QAAQ;AAAA,IACtE,6CAAC,UAAK,WAAU,0BACf;AAAA,mDAAC,UAAK,WAAU,0BACd;AAAA,eAAO;AAAA,QACP,OAAO,OACP,4CAAC,UAAK,WAAU,yBAAyB,cAAI,IAAI,sBAAsB,CAAC,KAAI;AAAA,SAE9E;AAAA,MACC,OAAO,aACP,4CAAC,UAAK,WAAU,+BAA+B,iBAAO,WAAU;AAAA,OAElE;AAAA,KACD;AAEF;AAQO,SAAS,YAAY;AAAA,EAC3B;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AACD,GAAqB;AACpB,QAAM,UAAM,8BAAe;AAC3B,MAAI,QAAQ,WAAW,GAAG;AACzB,WACC,4CAAC,SAAI,WAAU,4CACb,wBAAc,IAAI,6BAA6B,GACjD;AAAA,EAEF;AACA,SACC,4CAAC,SAAI,WAAU,oBAAmB,MAAK,WACrC,kBAAQ,IAAI,CAAC,QAAQ,MAAM;AAC3B,UAAM,SAAS,MAAM;AACrB,WACC;AAAA,MAAC;AAAA;AAAA,QAEA,MAAK;AAAA,QACL,MAAK;AAAA,QACL,iBAAe;AAAA,QACf,WACC,SACG,0DACA;AAAA,QAKJ,aAAa,CAAC,MAAM,EAAE,eAAe;AAAA,QACrC,SAAS,MAAM;AACd,cAAI,SAAU,UAAS,MAAM;AAAA,QAC9B;AAAA,QAEC,yBAAe,aAAa,MAAM,IAAI,4CAAC,oBAAiB,QAAgB;AAAA;AAAA,MAjBpE,OAAO;AAAA,IAkBb;AAAA,EAEF,CAAC,GACF;AAEF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,206 @@
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 __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var mention_suggestion_exports = {};
20
+ __export(mention_suggestion_exports, {
21
+ createMentionSuggestion: () => createMentionSuggestion,
22
+ filterMentionMembers: () => filterMentionMembers,
23
+ isMentionPickerOpen: () => isMentionPickerOpen
24
+ });
25
+ module.exports = __toCommonJS(mention_suggestion_exports);
26
+ var import_jsx_runtime = require("react/jsx-runtime");
27
+ var import_react = require("@tiptap/react");
28
+ var import_react2 = require("react");
29
+ var import_tldraw = require("tldraw");
30
+ var import_mention_list = require("./mention-list");
31
+ const MentionPopup = (0, import_react2.forwardRef)(function MentionPopup2({ items, command, renderMember }, ref) {
32
+ const [activeIndex, setActiveIndex] = (0, import_react2.useState)(0);
33
+ const [prevItems, setPrevItems] = (0, import_react2.useState)(items);
34
+ if (items !== prevItems) {
35
+ setPrevItems(items);
36
+ setActiveIndex(0);
37
+ }
38
+ const select = (member) => {
39
+ if (member) command({ id: member.id, label: member.name });
40
+ };
41
+ (0, import_react2.useImperativeHandle)(ref, () => ({
42
+ onKeyDown: ({ event }) => {
43
+ if (items.length === 0) return false;
44
+ if (event.key === "ArrowUp") {
45
+ setActiveIndex((i) => (i + items.length - 1) % items.length);
46
+ return true;
47
+ }
48
+ if (event.key === "ArrowDown") {
49
+ setActiveIndex((i) => (i + 1) % items.length);
50
+ return true;
51
+ }
52
+ if (event.key === "Enter" || event.key === "Tab") {
53
+ select(items[activeIndex] ?? items[0]);
54
+ return true;
55
+ }
56
+ return false;
57
+ }
58
+ }));
59
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
60
+ import_mention_list.MentionList,
61
+ {
62
+ members: items,
63
+ activeIndex,
64
+ onSelect: select,
65
+ renderMember
66
+ }
67
+ );
68
+ });
69
+ const MAX_SUGGESTIONS = 8;
70
+ function filterMentionMembers(members, query) {
71
+ const q = query.toLowerCase();
72
+ return members.filter((m) => m.name.toLowerCase().includes(q)).slice(0, MAX_SUGGESTIONS);
73
+ }
74
+ const mentionPickerOpen = (0, import_tldraw.atom)("isMentionPickerOpen", false);
75
+ function isMentionPickerOpen() {
76
+ return mentionPickerOpen.get();
77
+ }
78
+ function createMentionSuggestion(getSuggestions, options = {}) {
79
+ return {
80
+ char: "@",
81
+ items: ({ query }) => getSuggestions(query),
82
+ render: () => {
83
+ let renderer = null;
84
+ let container = null;
85
+ let editorEl = null;
86
+ let canvasEl = null;
87
+ let stopCameraReaction = null;
88
+ let anchorPage = null;
89
+ let popupWidth = 0;
90
+ const applyScreen = (left, top, width) => {
91
+ if (!container) return;
92
+ container.style.left = `${left}px`;
93
+ container.style.top = `${top + 4}px`;
94
+ container.style.width = `${width}px`;
95
+ };
96
+ const place = () => {
97
+ if (!container || !editorEl || container.style.display === "none") return;
98
+ const field = editorEl.closest(".cmt-composer__field") ?? editorEl;
99
+ const rect = field.getBoundingClientRect();
100
+ popupWidth = rect.width;
101
+ anchorPage = options.editor?.screenToPage({ x: rect.left, y: rect.bottom }) ?? null;
102
+ applyScreen(rect.left, rect.bottom, rect.width);
103
+ };
104
+ const reposition = () => {
105
+ if (!anchorPage || !options.editor) return;
106
+ const s = options.editor.pageToScreen(anchorPage);
107
+ applyScreen(s.x, s.y, popupWidth);
108
+ };
109
+ const startFollowing = () => {
110
+ window.addEventListener("scroll", place, true);
111
+ window.addEventListener("resize", place);
112
+ if (options.editor) {
113
+ stopCameraReaction = (0, import_tldraw.react)("anchor mention popup to camera", () => {
114
+ options.editor.getCamera();
115
+ reposition();
116
+ });
117
+ }
118
+ };
119
+ const stopFollowing = () => {
120
+ window.removeEventListener("scroll", place, true);
121
+ window.removeEventListener("resize", place);
122
+ stopCameraReaction?.();
123
+ stopCameraReaction = null;
124
+ anchorPage = null;
125
+ };
126
+ const hide = () => {
127
+ if (container) container.style.display = "none";
128
+ mentionPickerOpen.set(false);
129
+ };
130
+ const onWheel = (e) => {
131
+ if (e.isSpecialRedispatchedEvent || !canvasEl) return;
132
+ const list = container?.querySelector(".cmt-mention-list");
133
+ if (list && list.scrollHeight > list.clientHeight) return;
134
+ e.preventDefault();
135
+ const redispatched = new WheelEvent("wheel", e);
136
+ redispatched.isSpecialRedispatchedEvent = true;
137
+ canvasEl.dispatchEvent(redispatched);
138
+ };
139
+ return {
140
+ onStart: (props) => {
141
+ renderer = new import_react.ReactRenderer(MentionPopup, {
142
+ props: {
143
+ items: props.items,
144
+ command: props.command,
145
+ renderMember: options.renderMember
146
+ },
147
+ editor: props.editor
148
+ });
149
+ editorEl = props.editor.view.dom;
150
+ editorEl.addEventListener("blur", hide);
151
+ container = document.createElement("div");
152
+ container.className = "cmt-mention-popup";
153
+ container.appendChild(renderer.element);
154
+ const themed = editorEl.closest(".tl-container");
155
+ (themed ?? document.body).appendChild(container);
156
+ canvasEl = themed?.querySelector(".tl-canvas") ?? null;
157
+ container.addEventListener("wheel", onWheel, { passive: false });
158
+ place();
159
+ startFollowing();
160
+ mentionPickerOpen.set(true);
161
+ },
162
+ onUpdate: (props) => {
163
+ if (renderer)
164
+ renderer.updateProps({
165
+ items: props.items,
166
+ command: props.command,
167
+ renderMember: options.renderMember
168
+ });
169
+ if (container) container.style.display = "";
170
+ mentionPickerOpen.set(true);
171
+ place();
172
+ },
173
+ onKeyDown: (props) => {
174
+ if (!isMentionPickerOpen()) return false;
175
+ if (props.event.key === "Escape") {
176
+ hide();
177
+ props.event.stopPropagation();
178
+ return true;
179
+ }
180
+ if (props.event.key === "Enter" || props.event.key === "Tab") {
181
+ const completed = renderer?.ref?.onKeyDown(props) ?? false;
182
+ if (!completed) {
183
+ hide();
184
+ props.event.stopPropagation();
185
+ }
186
+ return true;
187
+ }
188
+ if (renderer && renderer.ref) return renderer.ref.onKeyDown(props);
189
+ return false;
190
+ },
191
+ onExit: () => {
192
+ stopFollowing();
193
+ if (editorEl) editorEl.removeEventListener("blur", hide);
194
+ if (container) container.removeEventListener("wheel", onWheel);
195
+ if (container) container.remove();
196
+ if (renderer) renderer.destroy();
197
+ renderer = null;
198
+ container = null;
199
+ canvasEl = null;
200
+ mentionPickerOpen.set(false);
201
+ }
202
+ };
203
+ }
204
+ };
205
+ }
206
+ //# sourceMappingURL=mention-suggestion.js.map