@liveblocks/react-ui 1.12.0-initial1

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 (391) hide show
  1. package/README.md +65 -0
  2. package/dist/components/Comment.js +473 -0
  3. package/dist/components/Comment.js.map +1 -0
  4. package/dist/components/Comment.mjs +447 -0
  5. package/dist/components/Comment.mjs.map +1 -0
  6. package/dist/components/Composer.js +299 -0
  7. package/dist/components/Composer.js.map +1 -0
  8. package/dist/components/Composer.mjs +297 -0
  9. package/dist/components/Composer.mjs.map +1 -0
  10. package/dist/components/InboxNotification.js +374 -0
  11. package/dist/components/InboxNotification.js.map +1 -0
  12. package/dist/components/InboxNotification.mjs +372 -0
  13. package/dist/components/InboxNotification.mjs.map +1 -0
  14. package/dist/components/InboxNotificationList.js +19 -0
  15. package/dist/components/InboxNotificationList.js.map +1 -0
  16. package/dist/components/InboxNotificationList.mjs +17 -0
  17. package/dist/components/InboxNotificationList.mjs.map +1 -0
  18. package/dist/components/Thread.js +188 -0
  19. package/dist/components/Thread.js.map +1 -0
  20. package/dist/components/Thread.mjs +167 -0
  21. package/dist/components/Thread.mjs.map +1 -0
  22. package/dist/components/internal/Attribution.js +26 -0
  23. package/dist/components/internal/Attribution.js.map +1 -0
  24. package/dist/components/internal/Attribution.mjs +24 -0
  25. package/dist/components/internal/Attribution.mjs.map +1 -0
  26. package/dist/components/internal/Avatar.js +40 -0
  27. package/dist/components/internal/Avatar.js.map +1 -0
  28. package/dist/components/internal/Avatar.mjs +38 -0
  29. package/dist/components/internal/Avatar.mjs.map +1 -0
  30. package/dist/components/internal/Button.js +24 -0
  31. package/dist/components/internal/Button.js.map +1 -0
  32. package/dist/components/internal/Button.mjs +22 -0
  33. package/dist/components/internal/Button.mjs.map +1 -0
  34. package/dist/components/internal/Dropdown.js +72 -0
  35. package/dist/components/internal/Dropdown.js.map +1 -0
  36. package/dist/components/internal/Dropdown.mjs +47 -0
  37. package/dist/components/internal/Dropdown.mjs.map +1 -0
  38. package/dist/components/internal/Emoji.js +18 -0
  39. package/dist/components/internal/Emoji.js.map +1 -0
  40. package/dist/components/internal/Emoji.mjs +16 -0
  41. package/dist/components/internal/Emoji.mjs.map +1 -0
  42. package/dist/components/internal/EmojiPicker.js +186 -0
  43. package/dist/components/internal/EmojiPicker.js.map +1 -0
  44. package/dist/components/internal/EmojiPicker.mjs +162 -0
  45. package/dist/components/internal/EmojiPicker.mjs.map +1 -0
  46. package/dist/components/internal/Icon.js +28 -0
  47. package/dist/components/internal/Icon.js.map +1 -0
  48. package/dist/components/internal/Icon.mjs +24 -0
  49. package/dist/components/internal/Icon.mjs.map +1 -0
  50. package/dist/components/internal/InboxNotificationThread.js +116 -0
  51. package/dist/components/internal/InboxNotificationThread.js.map +1 -0
  52. package/dist/components/internal/InboxNotificationThread.mjs +112 -0
  53. package/dist/components/internal/InboxNotificationThread.mjs.map +1 -0
  54. package/dist/components/internal/List.js +34 -0
  55. package/dist/components/internal/List.js.map +1 -0
  56. package/dist/components/internal/List.mjs +32 -0
  57. package/dist/components/internal/List.mjs.map +1 -0
  58. package/dist/components/internal/Room.js +22 -0
  59. package/dist/components/internal/Room.js.map +1 -0
  60. package/dist/components/internal/Room.mjs +20 -0
  61. package/dist/components/internal/Room.mjs.map +1 -0
  62. package/dist/components/internal/Tooltip.js +91 -0
  63. package/dist/components/internal/Tooltip.js.map +1 -0
  64. package/dist/components/internal/Tooltip.mjs +65 -0
  65. package/dist/components/internal/Tooltip.mjs.map +1 -0
  66. package/dist/components/internal/User.js +41 -0
  67. package/dist/components/internal/User.js.map +1 -0
  68. package/dist/components/internal/User.mjs +39 -0
  69. package/dist/components/internal/User.mjs.map +1 -0
  70. package/dist/components.js +64 -0
  71. package/dist/components.js.map +1 -0
  72. package/dist/components.mjs +41 -0
  73. package/dist/components.mjs.map +1 -0
  74. package/dist/config.js +33 -0
  75. package/dist/config.js.map +1 -0
  76. package/dist/config.mjs +30 -0
  77. package/dist/config.mjs.map +1 -0
  78. package/dist/constants.js +10 -0
  79. package/dist/constants.js.map +1 -0
  80. package/dist/constants.mjs +6 -0
  81. package/dist/constants.mjs.map +1 -0
  82. package/dist/icons/ArrowDown.js +15 -0
  83. package/dist/icons/ArrowDown.js.map +1 -0
  84. package/dist/icons/ArrowDown.mjs +13 -0
  85. package/dist/icons/ArrowDown.mjs.map +1 -0
  86. package/dist/icons/Check.js +15 -0
  87. package/dist/icons/Check.js.map +1 -0
  88. package/dist/icons/Check.mjs +13 -0
  89. package/dist/icons/Check.mjs.map +1 -0
  90. package/dist/icons/Cross.js +17 -0
  91. package/dist/icons/Cross.js.map +1 -0
  92. package/dist/icons/Cross.mjs +15 -0
  93. package/dist/icons/Cross.mjs.map +1 -0
  94. package/dist/icons/Delete.js +15 -0
  95. package/dist/icons/Delete.js.map +1 -0
  96. package/dist/icons/Delete.mjs +13 -0
  97. package/dist/icons/Delete.mjs.map +1 -0
  98. package/dist/icons/Edit.js +15 -0
  99. package/dist/icons/Edit.js.map +1 -0
  100. package/dist/icons/Edit.mjs +13 -0
  101. package/dist/icons/Edit.mjs.map +1 -0
  102. package/dist/icons/Ellipsis.js +26 -0
  103. package/dist/icons/Ellipsis.js.map +1 -0
  104. package/dist/icons/Ellipsis.mjs +24 -0
  105. package/dist/icons/Ellipsis.mjs.map +1 -0
  106. package/dist/icons/Emoji.js +27 -0
  107. package/dist/icons/Emoji.js.map +1 -0
  108. package/dist/icons/Emoji.mjs +25 -0
  109. package/dist/icons/Emoji.mjs.map +1 -0
  110. package/dist/icons/EmojiAdd.js +29 -0
  111. package/dist/icons/EmojiAdd.js.map +1 -0
  112. package/dist/icons/EmojiAdd.mjs +27 -0
  113. package/dist/icons/EmojiAdd.mjs.map +1 -0
  114. package/dist/icons/Mention.js +17 -0
  115. package/dist/icons/Mention.js.map +1 -0
  116. package/dist/icons/Mention.mjs +15 -0
  117. package/dist/icons/Mention.mjs.map +1 -0
  118. package/dist/icons/Missing.js +19 -0
  119. package/dist/icons/Missing.js.map +1 -0
  120. package/dist/icons/Missing.mjs +17 -0
  121. package/dist/icons/Missing.mjs.map +1 -0
  122. package/dist/icons/Resolve.js +19 -0
  123. package/dist/icons/Resolve.js.map +1 -0
  124. package/dist/icons/Resolve.mjs +17 -0
  125. package/dist/icons/Resolve.mjs.map +1 -0
  126. package/dist/icons/Resolved.js +21 -0
  127. package/dist/icons/Resolved.js.map +1 -0
  128. package/dist/icons/Resolved.mjs +19 -0
  129. package/dist/icons/Resolved.mjs.map +1 -0
  130. package/dist/icons/Search.js +15 -0
  131. package/dist/icons/Search.js.map +1 -0
  132. package/dist/icons/Search.mjs +13 -0
  133. package/dist/icons/Search.mjs.map +1 -0
  134. package/dist/icons/Send.js +15 -0
  135. package/dist/icons/Send.js.map +1 -0
  136. package/dist/icons/Send.mjs +13 -0
  137. package/dist/icons/Send.mjs.map +1 -0
  138. package/dist/icons/Spinner.js +22 -0
  139. package/dist/icons/Spinner.js.map +1 -0
  140. package/dist/icons/Spinner.mjs +20 -0
  141. package/dist/icons/Spinner.mjs.map +1 -0
  142. package/dist/index.d.mts +476 -0
  143. package/dist/index.d.ts +476 -0
  144. package/dist/index.js +20 -0
  145. package/dist/index.js.map +1 -0
  146. package/dist/index.mjs +11 -0
  147. package/dist/index.mjs.map +1 -0
  148. package/dist/overrides.js +100 -0
  149. package/dist/overrides.js.map +1 -0
  150. package/dist/overrides.mjs +77 -0
  151. package/dist/overrides.mjs.map +1 -0
  152. package/dist/primitives/Comment/index.js +113 -0
  153. package/dist/primitives/Comment/index.js.map +1 -0
  154. package/dist/primitives/Comment/index.mjs +109 -0
  155. package/dist/primitives/Comment/index.mjs.map +1 -0
  156. package/dist/primitives/Comment/utils.js +25 -0
  157. package/dist/primitives/Comment/utils.js.map +1 -0
  158. package/dist/primitives/Comment/utils.mjs +20 -0
  159. package/dist/primitives/Comment/utils.mjs.map +1 -0
  160. package/dist/primitives/Composer/contexts.js +34 -0
  161. package/dist/primitives/Composer/contexts.js.map +1 -0
  162. package/dist/primitives/Composer/contexts.mjs +27 -0
  163. package/dist/primitives/Composer/contexts.mjs.map +1 -0
  164. package/dist/primitives/Composer/index.js +771 -0
  165. package/dist/primitives/Composer/index.js.map +1 -0
  166. package/dist/primitives/Composer/index.mjs +762 -0
  167. package/dist/primitives/Composer/index.mjs.map +1 -0
  168. package/dist/primitives/Composer/utils.js +102 -0
  169. package/dist/primitives/Composer/utils.js.map +1 -0
  170. package/dist/primitives/Composer/utils.mjs +93 -0
  171. package/dist/primitives/Composer/utils.mjs.map +1 -0
  172. package/dist/primitives/EmojiPicker/contexts.js +19 -0
  173. package/dist/primitives/EmojiPicker/contexts.js.map +1 -0
  174. package/dist/primitives/EmojiPicker/contexts.mjs +16 -0
  175. package/dist/primitives/EmojiPicker/contexts.mjs.map +1 -0
  176. package/dist/primitives/EmojiPicker/index.js +434 -0
  177. package/dist/primitives/EmojiPicker/index.js.map +1 -0
  178. package/dist/primitives/EmojiPicker/index.mjs +430 -0
  179. package/dist/primitives/EmojiPicker/index.mjs.map +1 -0
  180. package/dist/primitives/EmojiPicker/utils.js +329 -0
  181. package/dist/primitives/EmojiPicker/utils.js.map +1 -0
  182. package/dist/primitives/EmojiPicker/utils.mjs +325 -0
  183. package/dist/primitives/EmojiPicker/utils.mjs.map +1 -0
  184. package/dist/primitives/Timestamp.js +121 -0
  185. package/dist/primitives/Timestamp.js.map +1 -0
  186. package/dist/primitives/Timestamp.mjs +119 -0
  187. package/dist/primitives/Timestamp.mjs.map +1 -0
  188. package/dist/primitives/index.d.mts +502 -0
  189. package/dist/primitives/index.d.ts +502 -0
  190. package/dist/primitives/index.js +16 -0
  191. package/dist/primitives/index.js.map +1 -0
  192. package/dist/primitives/index.mjs +9 -0
  193. package/dist/primitives/index.mjs.map +1 -0
  194. package/dist/primitives/internal/Emoji.js +30 -0
  195. package/dist/primitives/internal/Emoji.js.map +1 -0
  196. package/dist/primitives/internal/Emoji.mjs +28 -0
  197. package/dist/primitives/internal/Emoji.mjs.map +1 -0
  198. package/dist/shared.js +21 -0
  199. package/dist/shared.js.map +1 -0
  200. package/dist/shared.mjs +19 -0
  201. package/dist/shared.mjs.map +1 -0
  202. package/dist/slate/plugins/auto-formatting.js +83 -0
  203. package/dist/slate/plugins/auto-formatting.js.map +1 -0
  204. package/dist/slate/plugins/auto-formatting.mjs +81 -0
  205. package/dist/slate/plugins/auto-formatting.mjs.map +1 -0
  206. package/dist/slate/plugins/auto-links.js +175 -0
  207. package/dist/slate/plugins/auto-links.js.map +1 -0
  208. package/dist/slate/plugins/auto-links.mjs +172 -0
  209. package/dist/slate/plugins/auto-links.mjs.map +1 -0
  210. package/dist/slate/plugins/empty-clear-formatting.js +18 -0
  211. package/dist/slate/plugins/empty-clear-formatting.js.map +1 -0
  212. package/dist/slate/plugins/empty-clear-formatting.mjs +16 -0
  213. package/dist/slate/plugins/empty-clear-formatting.mjs.map +1 -0
  214. package/dist/slate/plugins/mentions.js +112 -0
  215. package/dist/slate/plugins/mentions.js.map +1 -0
  216. package/dist/slate/plugins/mentions.mjs +105 -0
  217. package/dist/slate/plugins/mentions.mjs.map +1 -0
  218. package/dist/slate/utils/get-character.js +50 -0
  219. package/dist/slate/utils/get-character.js.map +1 -0
  220. package/dist/slate/utils/get-character.mjs +47 -0
  221. package/dist/slate/utils/get-character.mjs.map +1 -0
  222. package/dist/slate/utils/get-dom-range.js +17 -0
  223. package/dist/slate/utils/get-dom-range.js.map +1 -0
  224. package/dist/slate/utils/get-dom-range.mjs +15 -0
  225. package/dist/slate/utils/get-dom-range.mjs.map +1 -0
  226. package/dist/slate/utils/get-match-range.js +53 -0
  227. package/dist/slate/utils/get-match-range.js.map +1 -0
  228. package/dist/slate/utils/get-match-range.mjs +51 -0
  229. package/dist/slate/utils/get-match-range.mjs.map +1 -0
  230. package/dist/slate/utils/is-empty-string.js +8 -0
  231. package/dist/slate/utils/is-empty-string.js.map +1 -0
  232. package/dist/slate/utils/is-empty-string.mjs +6 -0
  233. package/dist/slate/utils/is-empty-string.mjs.map +1 -0
  234. package/dist/slate/utils/is-empty.js +10 -0
  235. package/dist/slate/utils/is-empty.js.map +1 -0
  236. package/dist/slate/utils/is-empty.mjs +8 -0
  237. package/dist/slate/utils/is-empty.mjs.map +1 -0
  238. package/dist/slate/utils/is-selection-collapsed.js +10 -0
  239. package/dist/slate/utils/is-selection-collapsed.js.map +1 -0
  240. package/dist/slate/utils/is-selection-collapsed.mjs +8 -0
  241. package/dist/slate/utils/is-selection-collapsed.mjs.map +1 -0
  242. package/dist/slate/utils/marks.js +43 -0
  243. package/dist/slate/utils/marks.js.map +1 -0
  244. package/dist/slate/utils/marks.mjs +38 -0
  245. package/dist/slate/utils/marks.mjs.map +1 -0
  246. package/dist/utils/Persist.js +85 -0
  247. package/dist/utils/Persist.js.map +1 -0
  248. package/dist/utils/Persist.mjs +81 -0
  249. package/dist/utils/Persist.mjs.map +1 -0
  250. package/dist/utils/Portal.js +27 -0
  251. package/dist/utils/Portal.js.map +1 -0
  252. package/dist/utils/Portal.mjs +25 -0
  253. package/dist/utils/Portal.mjs.map +1 -0
  254. package/dist/utils/capitalize.js +8 -0
  255. package/dist/utils/capitalize.js.map +1 -0
  256. package/dist/utils/capitalize.mjs +6 -0
  257. package/dist/utils/capitalize.mjs.map +1 -0
  258. package/dist/utils/chunk.js +12 -0
  259. package/dist/utils/chunk.js.map +1 -0
  260. package/dist/utils/chunk.mjs +10 -0
  261. package/dist/utils/chunk.mjs.map +1 -0
  262. package/dist/utils/clamp.js +8 -0
  263. package/dist/utils/clamp.js.map +1 -0
  264. package/dist/utils/clamp.mjs +6 -0
  265. package/dist/utils/clamp.mjs.map +1 -0
  266. package/dist/utils/class-names.js +8 -0
  267. package/dist/utils/class-names.js.map +1 -0
  268. package/dist/utils/class-names.mjs +6 -0
  269. package/dist/utils/class-names.mjs.map +1 -0
  270. package/dist/utils/exists.js +8 -0
  271. package/dist/utils/exists.js.map +1 -0
  272. package/dist/utils/exists.mjs +6 -0
  273. package/dist/utils/exists.mjs.map +1 -0
  274. package/dist/utils/find-last-index.js +15 -0
  275. package/dist/utils/find-last-index.js.map +1 -0
  276. package/dist/utils/find-last-index.mjs +13 -0
  277. package/dist/utils/find-last-index.mjs.map +1 -0
  278. package/dist/utils/flush-sync.js +12 -0
  279. package/dist/utils/flush-sync.js.map +1 -0
  280. package/dist/utils/flush-sync.mjs +10 -0
  281. package/dist/utils/flush-sync.mjs.map +1 -0
  282. package/dist/utils/get-initials.js +13 -0
  283. package/dist/utils/get-initials.js.map +1 -0
  284. package/dist/utils/get-initials.mjs +11 -0
  285. package/dist/utils/get-initials.mjs.map +1 -0
  286. package/dist/utils/intl.js +24 -0
  287. package/dist/utils/intl.js.map +1 -0
  288. package/dist/utils/intl.mjs +20 -0
  289. package/dist/utils/intl.mjs.map +1 -0
  290. package/dist/utils/is-apple.js +9 -0
  291. package/dist/utils/is-apple.js.map +1 -0
  292. package/dist/utils/is-apple.mjs +7 -0
  293. package/dist/utils/is-apple.mjs.map +1 -0
  294. package/dist/utils/is-key.js +26 -0
  295. package/dist/utils/is-key.js.map +1 -0
  296. package/dist/utils/is-key.mjs +24 -0
  297. package/dist/utils/is-key.mjs.map +1 -0
  298. package/dist/utils/memoize.js +19 -0
  299. package/dist/utils/memoize.js.map +1 -0
  300. package/dist/utils/memoize.mjs +17 -0
  301. package/dist/utils/memoize.mjs.map +1 -0
  302. package/dist/utils/pluralize.js +8 -0
  303. package/dist/utils/pluralize.js.map +1 -0
  304. package/dist/utils/pluralize.mjs +6 -0
  305. package/dist/utils/pluralize.mjs.map +1 -0
  306. package/dist/utils/request-idle-callback.js +15 -0
  307. package/dist/utils/request-idle-callback.js.map +1 -0
  308. package/dist/utils/request-idle-callback.mjs +12 -0
  309. package/dist/utils/request-idle-callback.mjs.map +1 -0
  310. package/dist/utils/request-submit.js +20 -0
  311. package/dist/utils/request-submit.js.map +1 -0
  312. package/dist/utils/request-submit.mjs +18 -0
  313. package/dist/utils/request-submit.mjs.map +1 -0
  314. package/dist/utils/url.js +22 -0
  315. package/dist/utils/url.js.map +1 -0
  316. package/dist/utils/url.mjs +20 -0
  317. package/dist/utils/url.mjs.map +1 -0
  318. package/dist/utils/use-controllable-state.js +34 -0
  319. package/dist/utils/use-controllable-state.js.map +1 -0
  320. package/dist/utils/use-controllable-state.mjs +32 -0
  321. package/dist/utils/use-controllable-state.mjs.map +1 -0
  322. package/dist/utils/use-id.js +29 -0
  323. package/dist/utils/use-id.js.map +1 -0
  324. package/dist/utils/use-id.mjs +27 -0
  325. package/dist/utils/use-id.mjs.map +1 -0
  326. package/dist/utils/use-index.js +32 -0
  327. package/dist/utils/use-index.js.map +1 -0
  328. package/dist/utils/use-index.mjs +30 -0
  329. package/dist/utils/use-index.mjs.map +1 -0
  330. package/dist/utils/use-initial.js +10 -0
  331. package/dist/utils/use-initial.js.map +1 -0
  332. package/dist/utils/use-initial.mjs +8 -0
  333. package/dist/utils/use-initial.mjs.map +1 -0
  334. package/dist/utils/use-interval.js +24 -0
  335. package/dist/utils/use-interval.js.map +1 -0
  336. package/dist/utils/use-interval.mjs +22 -0
  337. package/dist/utils/use-interval.mjs.map +1 -0
  338. package/dist/utils/use-latest.js +14 -0
  339. package/dist/utils/use-latest.js.map +1 -0
  340. package/dist/utils/use-latest.mjs +12 -0
  341. package/dist/utils/use-latest.mjs.map +1 -0
  342. package/dist/utils/use-layout-effect.js +8 -0
  343. package/dist/utils/use-layout-effect.js.map +1 -0
  344. package/dist/utils/use-layout-effect.mjs +6 -0
  345. package/dist/utils/use-layout-effect.mjs.map +1 -0
  346. package/dist/utils/use-refs.js +24 -0
  347. package/dist/utils/use-refs.js.map +1 -0
  348. package/dist/utils/use-refs.mjs +22 -0
  349. package/dist/utils/use-refs.mjs.map +1 -0
  350. package/dist/utils/use-rerender.js +14 -0
  351. package/dist/utils/use-rerender.js.map +1 -0
  352. package/dist/utils/use-rerender.mjs +12 -0
  353. package/dist/utils/use-rerender.mjs.map +1 -0
  354. package/dist/utils/use-transition.js +12 -0
  355. package/dist/utils/use-transition.js.map +1 -0
  356. package/dist/utils/use-transition.mjs +10 -0
  357. package/dist/utils/use-transition.mjs.map +1 -0
  358. package/dist/utils/use-visible.js +48 -0
  359. package/dist/utils/use-visible.js.map +1 -0
  360. package/dist/utils/use-visible.mjs +46 -0
  361. package/dist/utils/use-visible.mjs.map +1 -0
  362. package/dist/utils/visually-hidden.js +17 -0
  363. package/dist/utils/visually-hidden.js.map +1 -0
  364. package/dist/utils/visually-hidden.mjs +15 -0
  365. package/dist/utils/visually-hidden.mjs.map +1 -0
  366. package/dist/utils/wrap.js +9 -0
  367. package/dist/utils/wrap.js.map +1 -0
  368. package/dist/utils/wrap.mjs +7 -0
  369. package/dist/utils/wrap.mjs.map +1 -0
  370. package/dist/version.js +10 -0
  371. package/dist/version.js.map +1 -0
  372. package/dist/version.mjs +6 -0
  373. package/dist/version.mjs.map +1 -0
  374. package/package.json +142 -0
  375. package/primitives/README.md +5 -0
  376. package/primitives/package.json +4 -0
  377. package/src/styles/constants.css +17 -0
  378. package/src/styles/dark/attributes.css +8 -0
  379. package/src/styles/dark/index.css +29 -0
  380. package/src/styles/dark/media-query.css +7 -0
  381. package/src/styles/index.css +1437 -0
  382. package/src/styles/utils.css +36 -0
  383. package/styles/dark/attributes.css +1 -0
  384. package/styles/dark/attributes.css.d.ts +1 -0
  385. package/styles/dark/attributes.css.map +1 -0
  386. package/styles/dark/media-query.css +1 -0
  387. package/styles/dark/media-query.css.d.ts +1 -0
  388. package/styles/dark/media-query.css.map +1 -0
  389. package/styles.css +1 -0
  390. package/styles.css.d.ts +1 -0
  391. package/styles.css.map +1 -0
package/README.md ADDED
@@ -0,0 +1,65 @@
1
+ <p align="center">
2
+ <a href="https://liveblocks.io#gh-light-mode-only">
3
+ <img src="https://raw.githubusercontent.com/liveblocks/liveblocks/main/.github/assets/header-light.svg" alt="Liveblocks" />
4
+ </a>
5
+ <a href="https://liveblocks.io#gh-dark-mode-only">
6
+ <img src="https://raw.githubusercontent.com/liveblocks/liveblocks/main/.github/assets/header-dark.svg" alt="Liveblocks" />
7
+ </a>
8
+ </p>
9
+
10
+ # `@liveblocks/react-comments`
11
+
12
+ <p>
13
+ <a href="https://npmjs.org/package/@liveblocks/react-ui">
14
+ <img src="https://img.shields.io/npm/v/@liveblocks/react-ui?style=flat&label=npm&color=c33" alt="NPM" />
15
+ </a>
16
+ <a href="https://bundlephobia.com/package/@liveblocks/react-ui">
17
+ <img src="https://img.shields.io/bundlephobia/minzip/@liveblocks/react-ui?style=flat&label=size&color=09f" alt="Size" />
18
+ </a>
19
+ <a href="https://github.com/liveblocks/liveblocks/blob/main/LICENSE">
20
+ <img src="https://img.shields.io/github/license/liveblocks/liveblocks?style=flat&label=license&color=f80" alt="License" />
21
+ </a>
22
+ </p>
23
+
24
+ `@liveblocks/react-ui` provides [React](https://reactjs.org/) pre-built
25
+ components for the [Liveblocks](https://liveblocks.io/) products.
26
+
27
+ ## Installation
28
+
29
+ ```
30
+ npm install @liveblocks/client @liveblocks/react @liveblocks/react-ui
31
+ ```
32
+
33
+ ## Documentation
34
+
35
+ Read the
36
+ [documentation](https://liveblocks.io/docs/api-reference/liveblocks-react-ui)
37
+ for guides and API references.
38
+
39
+ ## Examples
40
+
41
+ Explore our [collaborative examples](https://liveblocks.io/examples) to help you
42
+ get started.
43
+
44
+ > All examples are open-source and live in this repository, within
45
+ > [`/examples`](../../examples).
46
+
47
+ ## Releases
48
+
49
+ See the [latest changes](https://github.com/liveblocks/liveblocks/releases) or
50
+ learn more about
51
+ [upcoming releases](https://github.com/liveblocks/liveblocks/milestones).
52
+
53
+ ## Community
54
+
55
+ - [Discord](https://liveblocks.io/discord) - To get involved with the Liveblocks
56
+ community, ask questions and share tips.
57
+ - [X](https://x.com/liveblocks) - To receive updates, announcements, blog posts,
58
+ and general Liveblocks tips.
59
+
60
+ ## License
61
+
62
+ Licensed under the Apache License 2.0, Copyright © 2021-present
63
+ [Liveblocks](https://liveblocks.io).
64
+
65
+ See [LICENSE](../../LICENSE) for more information.
@@ -0,0 +1,473 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var react = require('@liveblocks/react');
5
+ var TogglePrimitive = require('@radix-ui/react-toggle');
6
+ var React = require('react');
7
+ var Check = require('../icons/Check.js');
8
+ var Cross = require('../icons/Cross.js');
9
+ var Delete = require('../icons/Delete.js');
10
+ var Edit = require('../icons/Edit.js');
11
+ var Ellipsis = require('../icons/Ellipsis.js');
12
+ var EmojiAdd = require('../icons/EmojiAdd.js');
13
+ var overrides = require('../overrides.js');
14
+ var index$1 = require('../primitives/Comment/index.js');
15
+ var index = require('../primitives/Composer/index.js');
16
+ var Timestamp = require('../primitives/Timestamp.js');
17
+ var shared = require('../shared.js');
18
+ var mentions = require('../slate/plugins/mentions.js');
19
+ var classNames = require('../utils/class-names.js');
20
+ var useRefs = require('../utils/use-refs.js');
21
+ var useVisible = require('../utils/use-visible.js');
22
+ var Composer = require('./Composer.js');
23
+ var Avatar = require('./internal/Avatar.js');
24
+ var Button = require('./internal/Button.js');
25
+ var Dropdown = require('./internal/Dropdown.js');
26
+ var Emoji = require('./internal/Emoji.js');
27
+ var EmojiPicker = require('./internal/EmojiPicker.js');
28
+ var List = require('./internal/List.js');
29
+ var Tooltip = require('./internal/Tooltip.js');
30
+ var User = require('./internal/User.js');
31
+ var TooltipPrimitive = require('@radix-ui/react-tooltip');
32
+ var PopoverPrimitive = require('@radix-ui/react-popover');
33
+ var DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
34
+
35
+ function _interopNamespaceDefault(e) {
36
+ var n = Object.create(null);
37
+ if (e) {
38
+ Object.keys(e).forEach(function (k) {
39
+ if (k !== 'default') {
40
+ var d = Object.getOwnPropertyDescriptor(e, k);
41
+ Object.defineProperty(n, k, d.get ? d : {
42
+ enumerable: true,
43
+ get: function () { return e[k]; }
44
+ });
45
+ }
46
+ });
47
+ }
48
+ n.default = e;
49
+ return Object.freeze(n);
50
+ }
51
+
52
+ var TogglePrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(TogglePrimitive);
53
+
54
+ const REACTIONS_TRUNCATE = 5;
55
+ function CommentMention({
56
+ userId,
57
+ className,
58
+ ...props
59
+ }) {
60
+ const currentId = shared.useCurrentUserId();
61
+ return /* @__PURE__ */ React.createElement(index$1.Mention, {
62
+ className: classNames.classNames("lb-comment-mention", className),
63
+ "data-self": userId === currentId ? "" : void 0,
64
+ ...props
65
+ }, mentions.MENTION_CHARACTER, /* @__PURE__ */ React.createElement(User.User, {
66
+ userId
67
+ }));
68
+ }
69
+ function CommentLink({
70
+ href,
71
+ children,
72
+ className,
73
+ ...props
74
+ }) {
75
+ return /* @__PURE__ */ React.createElement(index$1.Link, {
76
+ className: classNames.classNames("lb-comment-link", className),
77
+ href,
78
+ ...props
79
+ }, children);
80
+ }
81
+ function CommentNonInteractiveLink({
82
+ href: _href,
83
+ children,
84
+ className,
85
+ ...props
86
+ }) {
87
+ return /* @__PURE__ */ React.createElement("span", {
88
+ className: classNames.classNames("lb-comment-link", className),
89
+ ...props
90
+ }, children);
91
+ }
92
+ const CommentReactionButton = React.forwardRef(({ reaction, overrides: overrides$1, className, ...props }, forwardedRef) => {
93
+ const $ = overrides.useOverrides(overrides$1);
94
+ return /* @__PURE__ */ React.createElement(Button.Button, {
95
+ className: classNames.classNames("lb-comment-reaction", className),
96
+ variant: "outline",
97
+ "aria-label": $.COMMENT_REACTION_DESCRIPTION(
98
+ reaction.emoji,
99
+ reaction.users.length
100
+ ),
101
+ ...props,
102
+ ref: forwardedRef
103
+ }, /* @__PURE__ */ React.createElement(Emoji.Emoji, {
104
+ className: "lb-comment-reaction-emoji",
105
+ emoji: reaction.emoji
106
+ }), /* @__PURE__ */ React.createElement("span", {
107
+ className: "lb-comment-reaction-count"
108
+ }, reaction.users.length));
109
+ });
110
+ const CommentReaction = React.forwardRef(({ comment, reaction, overrides: overrides$1, disabled, ...props }, forwardedRef) => {
111
+ const { useAddReaction, useRemoveReaction } = react.useRoomContextBundle();
112
+ const addReaction = useAddReaction();
113
+ const removeReaction = useRemoveReaction();
114
+ const currentId = shared.useCurrentUserId();
115
+ const isActive = React.useMemo(() => {
116
+ return reaction.users.some((users) => users.id === currentId);
117
+ }, [currentId, reaction]);
118
+ const $ = overrides.useOverrides(overrides$1);
119
+ const tooltipContent = React.useMemo(
120
+ () => /* @__PURE__ */ React.createElement("span", null, $.COMMENT_REACTION_LIST(
121
+ /* @__PURE__ */ React.createElement(List.List, {
122
+ values: reaction.users.map((users, index) => /* @__PURE__ */ React.createElement(User.User, {
123
+ key: users.id,
124
+ userId: users.id,
125
+ capitalize: index === 0,
126
+ replaceSelf: true
127
+ })),
128
+ formatRemaining: $.LIST_REMAINING_USERS,
129
+ truncate: REACTIONS_TRUNCATE
130
+ }),
131
+ reaction.emoji,
132
+ reaction.users.length
133
+ )),
134
+ [$, reaction]
135
+ );
136
+ const handlePressedChange = React.useCallback(
137
+ (isPressed) => {
138
+ if (isPressed) {
139
+ addReaction({
140
+ threadId: comment.threadId,
141
+ commentId: comment.id,
142
+ emoji: reaction.emoji
143
+ });
144
+ } else {
145
+ removeReaction({
146
+ threadId: comment.threadId,
147
+ commentId: comment.id,
148
+ emoji: reaction.emoji
149
+ });
150
+ }
151
+ },
152
+ [addReaction, comment.threadId, comment.id, reaction.emoji, removeReaction]
153
+ );
154
+ return /* @__PURE__ */ React.createElement(Tooltip.Tooltip, {
155
+ content: tooltipContent,
156
+ multiline: true,
157
+ className: "lb-comment-reaction-tooltip"
158
+ }, /* @__PURE__ */ React.createElement(TogglePrimitive__namespace.Root, {
159
+ asChild: true,
160
+ pressed: isActive,
161
+ onPressedChange: handlePressedChange,
162
+ disabled,
163
+ ref: forwardedRef
164
+ }, /* @__PURE__ */ React.createElement(CommentReactionButton, {
165
+ "data-self": isActive ? "" : void 0,
166
+ reaction,
167
+ overrides: overrides$1,
168
+ ...props
169
+ })));
170
+ });
171
+ const CommentNonInteractiveReaction = React.forwardRef(({ reaction, overrides, ...props }, forwardedRef) => {
172
+ const currentId = shared.useCurrentUserId();
173
+ const isActive = React.useMemo(() => {
174
+ return reaction.users.some((users) => users.id === currentId);
175
+ }, [currentId, reaction]);
176
+ return /* @__PURE__ */ React.createElement(CommentReactionButton, {
177
+ disableable: false,
178
+ "data-self": isActive ? "" : void 0,
179
+ reaction,
180
+ overrides,
181
+ ...props,
182
+ ref: forwardedRef
183
+ });
184
+ });
185
+ const Comment = React.forwardRef(
186
+ ({
187
+ comment,
188
+ indentContent = true,
189
+ showDeleted,
190
+ showActions = "hover",
191
+ showReactions = true,
192
+ onAuthorClick,
193
+ onMentionClick,
194
+ onCommentEdit,
195
+ onCommentDelete,
196
+ overrides: overrides$1,
197
+ className,
198
+ additionalActions,
199
+ additionalActionsClassName,
200
+ markThreadAsReadWhenVisible,
201
+ ...props
202
+ }, forwardedRef) => {
203
+ const {
204
+ useDeleteComment,
205
+ useEditComment,
206
+ useAddReaction,
207
+ useRemoveReaction,
208
+ useMarkThreadAsRead,
209
+ useSelf
210
+ } = react.useRoomContextBundle();
211
+ const ref = React.useRef(null);
212
+ const mergedRefs = useRefs.useRefs(forwardedRef, ref);
213
+ const self = useSelf();
214
+ const deleteComment = useDeleteComment();
215
+ const editComment = useEditComment();
216
+ const addReaction = useAddReaction();
217
+ const removeReaction = useRemoveReaction();
218
+ const markThreadAsRead = useMarkThreadAsRead();
219
+ const $ = overrides.useOverrides(overrides$1);
220
+ const [isEditing, setEditing] = React.useState(false);
221
+ const [isTarget, setTarget] = React.useState(false);
222
+ const [isMoreActionOpen, setMoreActionOpen] = React.useState(false);
223
+ const [isReactionActionOpen, setReactionActionOpen] = React.useState(false);
224
+ const markVisibleThreadAsRead = React.useCallback(() => {
225
+ if (markThreadAsReadWhenVisible) {
226
+ markThreadAsRead(markThreadAsReadWhenVisible);
227
+ }
228
+ }, [markThreadAsRead, markThreadAsReadWhenVisible]);
229
+ useVisible.useVisibleCallback(ref, markVisibleThreadAsRead, {
230
+ enabled: Boolean(markThreadAsReadWhenVisible)
231
+ });
232
+ const stopPropagation = React.useCallback((event) => {
233
+ event.stopPropagation();
234
+ }, []);
235
+ const handleEdit = React.useCallback(() => {
236
+ setEditing(true);
237
+ }, []);
238
+ const handleEditCancel = React.useCallback(
239
+ (event) => {
240
+ event.stopPropagation();
241
+ setEditing(false);
242
+ },
243
+ []
244
+ );
245
+ const handleEditSubmit = React.useCallback(
246
+ ({ body }, event) => {
247
+ onCommentEdit?.(comment);
248
+ event.preventDefault();
249
+ setEditing(false);
250
+ editComment({
251
+ commentId: comment.id,
252
+ threadId: comment.threadId,
253
+ body
254
+ });
255
+ },
256
+ [comment, editComment, onCommentEdit]
257
+ );
258
+ const handleDelete = React.useCallback(() => {
259
+ onCommentDelete?.(comment);
260
+ deleteComment({
261
+ commentId: comment.id,
262
+ threadId: comment.threadId
263
+ });
264
+ }, [comment, deleteComment, onCommentDelete]);
265
+ const handleAuthorClick = React.useCallback(
266
+ (event) => {
267
+ onAuthorClick?.(comment.userId, event);
268
+ },
269
+ [comment.userId, onAuthorClick]
270
+ );
271
+ const handleReactionSelect = React.useCallback(
272
+ (emoji) => {
273
+ const reactionIndex = comment.reactions.findIndex(
274
+ (reaction) => reaction.emoji === emoji
275
+ );
276
+ if (reactionIndex >= 0 && self?.id && comment.reactions[reactionIndex].users.some(
277
+ (user) => user.id === self?.id
278
+ )) {
279
+ removeReaction({
280
+ threadId: comment.threadId,
281
+ commentId: comment.id,
282
+ emoji
283
+ });
284
+ } else {
285
+ addReaction({
286
+ threadId: comment.threadId,
287
+ commentId: comment.id,
288
+ emoji
289
+ });
290
+ }
291
+ },
292
+ [
293
+ addReaction,
294
+ comment.id,
295
+ comment.reactions,
296
+ comment.threadId,
297
+ removeReaction,
298
+ self?.id
299
+ ]
300
+ );
301
+ React.useEffect(() => {
302
+ const isWindowDefined = typeof window !== "undefined";
303
+ if (!isWindowDefined)
304
+ return;
305
+ const hash = window.location.hash;
306
+ const commentId = hash.slice(1);
307
+ if (commentId === comment.id) {
308
+ setTarget(true);
309
+ }
310
+ }, []);
311
+ if (!showDeleted && !comment.body) {
312
+ return null;
313
+ }
314
+ return /* @__PURE__ */ React.createElement(TooltipPrimitive.TooltipProvider, null, /* @__PURE__ */ React.createElement("div", {
315
+ id: comment.id,
316
+ className: classNames.classNames(
317
+ "lb-root lb-comment",
318
+ indentContent && "lb-comment:indent-content",
319
+ showActions === "hover" && "lb-comment:show-actions-hover",
320
+ (isMoreActionOpen || isReactionActionOpen) && "lb-comment:action-open",
321
+ className
322
+ ),
323
+ "data-deleted": !comment.body ? "" : void 0,
324
+ "data-editing": isEditing ? "" : void 0,
325
+ "data-target": isTarget ? "" : void 0,
326
+ dir: $.dir,
327
+ ...props,
328
+ ref: mergedRefs
329
+ }, /* @__PURE__ */ React.createElement("div", {
330
+ className: "lb-comment-header"
331
+ }, /* @__PURE__ */ React.createElement("div", {
332
+ className: "lb-comment-details"
333
+ }, /* @__PURE__ */ React.createElement(Avatar.Avatar, {
334
+ className: "lb-comment-avatar",
335
+ userId: comment.userId,
336
+ onClick: handleAuthorClick
337
+ }), /* @__PURE__ */ React.createElement("span", {
338
+ className: "lb-comment-details-labels"
339
+ }, /* @__PURE__ */ React.createElement(User.User, {
340
+ className: "lb-comment-author",
341
+ userId: comment.userId,
342
+ onClick: handleAuthorClick
343
+ }), /* @__PURE__ */ React.createElement("span", {
344
+ className: "lb-comment-date"
345
+ }, /* @__PURE__ */ React.createElement(Timestamp.Timestamp, {
346
+ locale: $.locale,
347
+ date: comment.createdAt,
348
+ className: "lb-comment-date-created"
349
+ }), comment.editedAt && comment.body && /* @__PURE__ */ React.createElement(React.Fragment, null, " ", /* @__PURE__ */ React.createElement("span", {
350
+ className: "lb-comment-date-edited"
351
+ }, $.COMMENT_EDITED))))), showActions && !isEditing && /* @__PURE__ */ React.createElement("div", {
352
+ className: classNames.classNames(
353
+ "lb-comment-actions",
354
+ additionalActionsClassName
355
+ )
356
+ }, additionalActions ?? null, showReactions && /* @__PURE__ */ React.createElement(EmojiPicker.EmojiPicker, {
357
+ onEmojiSelect: handleReactionSelect,
358
+ onOpenChange: setReactionActionOpen
359
+ }, /* @__PURE__ */ React.createElement(Tooltip.Tooltip, {
360
+ content: $.COMMENT_ADD_REACTION
361
+ }, /* @__PURE__ */ React.createElement(PopoverPrimitive.PopoverTrigger, {
362
+ asChild: true
363
+ }, /* @__PURE__ */ React.createElement(Button.Button, {
364
+ className: "lb-comment-action",
365
+ onClick: stopPropagation,
366
+ "aria-label": $.COMMENT_ADD_REACTION
367
+ }, /* @__PURE__ */ React.createElement(EmojiAdd.EmojiAddIcon, {
368
+ className: "lb-button-icon"
369
+ }))))), comment.userId === self?.id && /* @__PURE__ */ React.createElement(Dropdown.Dropdown, {
370
+ open: isMoreActionOpen,
371
+ onOpenChange: setMoreActionOpen,
372
+ align: "end",
373
+ content: /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Dropdown.DropdownItem, {
374
+ onSelect: handleEdit,
375
+ onClick: stopPropagation
376
+ }, /* @__PURE__ */ React.createElement(Edit.EditIcon, {
377
+ className: "lb-dropdown-item-icon"
378
+ }), $.COMMENT_EDIT), /* @__PURE__ */ React.createElement(Dropdown.DropdownItem, {
379
+ onSelect: handleDelete,
380
+ onClick: stopPropagation
381
+ }, /* @__PURE__ */ React.createElement(Delete.DeleteIcon, {
382
+ className: "lb-dropdown-item-icon"
383
+ }), $.COMMENT_DELETE))
384
+ }, /* @__PURE__ */ React.createElement(Tooltip.Tooltip, {
385
+ content: $.COMMENT_MORE
386
+ }, /* @__PURE__ */ React.createElement(DropdownMenuPrimitive.DropdownMenuTrigger, {
387
+ asChild: true
388
+ }, /* @__PURE__ */ React.createElement(Button.Button, {
389
+ className: "lb-comment-action",
390
+ disabled: !comment.body,
391
+ onClick: stopPropagation,
392
+ "aria-label": $.COMMENT_MORE
393
+ }, /* @__PURE__ */ React.createElement(Ellipsis.EllipsisIcon, {
394
+ className: "lb-button-icon"
395
+ }))))))), /* @__PURE__ */ React.createElement("div", {
396
+ className: "lb-comment-content"
397
+ }, isEditing ? /* @__PURE__ */ React.createElement(Composer.Composer, {
398
+ className: "lb-comment-composer",
399
+ onComposerSubmit: handleEditSubmit,
400
+ defaultValue: comment.body,
401
+ autoFocus: true,
402
+ showAttribution: false,
403
+ actions: /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Tooltip.Tooltip, {
404
+ content: $.COMMENT_EDIT_COMPOSER_CANCEL,
405
+ "aria-label": $.COMMENT_EDIT_COMPOSER_CANCEL
406
+ }, /* @__PURE__ */ React.createElement(Button.Button, {
407
+ className: "lb-composer-action",
408
+ onClick: handleEditCancel
409
+ }, /* @__PURE__ */ React.createElement(Cross.CrossIcon, {
410
+ className: "lb-button-icon"
411
+ }))), /* @__PURE__ */ React.createElement(Tooltip.ShortcutTooltip, {
412
+ content: $.COMMENT_EDIT_COMPOSER_SAVE,
413
+ shortcut: /* @__PURE__ */ React.createElement(Tooltip.ShortcutTooltipKey, {
414
+ name: "enter"
415
+ })
416
+ }, /* @__PURE__ */ React.createElement(index.Submit, {
417
+ asChild: true
418
+ }, /* @__PURE__ */ React.createElement(Button.Button, {
419
+ variant: "primary",
420
+ className: "lb-composer-action",
421
+ onClick: stopPropagation,
422
+ "aria-label": $.COMMENT_EDIT_COMPOSER_SAVE
423
+ }, /* @__PURE__ */ React.createElement(Check.CheckIcon, {
424
+ className: "lb-button-icon"
425
+ }))))),
426
+ overrides: {
427
+ COMPOSER_PLACEHOLDER: $.COMMENT_EDIT_COMPOSER_PLACEHOLDER
428
+ }
429
+ }) : comment.body ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(index$1.Body, {
430
+ className: "lb-comment-body",
431
+ body: comment.body,
432
+ components: {
433
+ Mention: ({ userId }) => /* @__PURE__ */ React.createElement(CommentMention, {
434
+ userId,
435
+ onClick: (event) => onMentionClick?.(userId, event)
436
+ }),
437
+ Link: CommentLink
438
+ }
439
+ }), showReactions && comment.reactions.length > 0 && /* @__PURE__ */ React.createElement("div", {
440
+ className: "lb-comment-reactions"
441
+ }, comment.reactions.map((reaction) => /* @__PURE__ */ React.createElement(CommentReaction, {
442
+ key: reaction.emoji,
443
+ comment,
444
+ reaction,
445
+ overrides: overrides$1
446
+ })), /* @__PURE__ */ React.createElement(EmojiPicker.EmojiPicker, {
447
+ onEmojiSelect: handleReactionSelect
448
+ }, /* @__PURE__ */ React.createElement(Tooltip.Tooltip, {
449
+ content: $.COMMENT_ADD_REACTION
450
+ }, /* @__PURE__ */ React.createElement(PopoverPrimitive.PopoverTrigger, {
451
+ asChild: true
452
+ }, /* @__PURE__ */ React.createElement(Button.Button, {
453
+ className: "lb-comment-reaction lb-comment-reaction-add",
454
+ variant: "outline",
455
+ onClick: stopPropagation,
456
+ "aria-label": $.COMMENT_ADD_REACTION
457
+ }, /* @__PURE__ */ React.createElement(EmojiAdd.EmojiAddIcon, {
458
+ className: "lb-button-icon"
459
+ }))))))) : /* @__PURE__ */ React.createElement("div", {
460
+ className: "lb-comment-body"
461
+ }, /* @__PURE__ */ React.createElement("p", {
462
+ className: "lb-comment-deleted"
463
+ }, $.COMMENT_DELETED)))));
464
+ }
465
+ );
466
+
467
+ exports.Comment = Comment;
468
+ exports.CommentLink = CommentLink;
469
+ exports.CommentMention = CommentMention;
470
+ exports.CommentNonInteractiveLink = CommentNonInteractiveLink;
471
+ exports.CommentNonInteractiveReaction = CommentNonInteractiveReaction;
472
+ exports.CommentReaction = CommentReaction;
473
+ //# sourceMappingURL=Comment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Comment.js","sources":["../../src/components/Comment.tsx"],"sourcesContent":["\"use client\";\n\nimport type {\n CommentData,\n CommentReaction as CommentReactionData,\n} from \"@liveblocks/core\";\nimport { useRoomContextBundle } from \"@liveblocks/react\";\nimport * as TogglePrimitive from \"@radix-ui/react-toggle\";\nimport type {\n ComponentPropsWithoutRef,\n FormEvent,\n MouseEvent,\n ReactNode,\n SyntheticEvent,\n} from \"react\";\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { CheckIcon } from \"../icons/Check\";\nimport { CrossIcon } from \"../icons/Cross\";\nimport { DeleteIcon } from \"../icons/Delete\";\nimport { EditIcon } from \"../icons/Edit\";\nimport { EllipsisIcon } from \"../icons/Ellipsis\";\nimport { EmojiAddIcon } from \"../icons/EmojiAdd\";\nimport type {\n CommentOverrides,\n ComposerOverrides,\n GlobalOverrides,\n} from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport type { ComposerSubmitComment } from \"../primitives\";\nimport * as CommentPrimitive from \"../primitives/Comment\";\nimport type {\n CommentBodyLinkProps,\n CommentBodyMentionProps,\n CommentLinkProps,\n CommentMentionProps,\n} from \"../primitives/Comment/types\";\nimport * as ComposerPrimitive from \"../primitives/Composer\";\nimport { Timestamp } from \"../primitives/Timestamp\";\nimport { useCurrentUserId } from \"../shared\";\nimport { MENTION_CHARACTER } from \"../slate/plugins/mentions\";\nimport { classNames } from \"../utils/class-names\";\nimport { useRefs } from \"../utils/use-refs\";\nimport { useVisibleCallback } from \"../utils/use-visible\";\nimport { Composer } from \"./Composer\";\nimport { Avatar } from \"./internal/Avatar\";\nimport { Button } from \"./internal/Button\";\nimport { Dropdown, DropdownItem, DropdownTrigger } from \"./internal/Dropdown\";\nimport { Emoji } from \"./internal/Emoji\";\nimport { EmojiPicker, EmojiPickerTrigger } from \"./internal/EmojiPicker\";\nimport { List } from \"./internal/List\";\nimport {\n ShortcutTooltip,\n ShortcutTooltipKey,\n Tooltip,\n TooltipProvider,\n} from \"./internal/Tooltip\";\nimport { User } from \"./internal/User\";\n\nconst REACTIONS_TRUNCATE = 5;\n\nexport interface CommentProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * The comment to display.\n */\n comment: CommentData;\n\n /**\n * How to show or hide the actions.\n */\n showActions?: boolean | \"hover\";\n\n /**\n * Whether to show the comment if it was deleted. If set to `false`, it will render deleted comments as `null`.\n */\n showDeleted?: boolean;\n\n /**\n * Whether to show reactions.\n */\n showReactions?: boolean;\n\n /**\n * Whether to indent the comment's content.\n */\n indentContent?: boolean;\n\n /**\n * The event handler called when the comment is edited.\n */\n onCommentEdit?: (comment: CommentData) => void;\n\n /**\n * The event handler called when the comment is deleted.\n */\n onCommentDelete?: (comment: CommentData) => void;\n\n /**\n * The event handler called when clicking on the author.\n */\n onAuthorClick?: (userId: string, event: MouseEvent<HTMLElement>) => void;\n\n /**\n * The event handler called when clicking on a mention.\n */\n onMentionClick?: (userId: string, event: MouseEvent<HTMLElement>) => void;\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<GlobalOverrides & CommentOverrides & ComposerOverrides>;\n\n /**\n * @internal\n */\n markThreadAsReadWhenVisible?: string;\n\n /**\n * @internal\n */\n additionalActions?: ReactNode;\n\n /**\n * @internal\n */\n additionalActionsClassName?: string;\n}\n\ninterface CommentReactionButtonProps\n extends ComponentPropsWithoutRef<typeof Button> {\n reaction: CommentReactionData;\n overrides?: Partial<GlobalOverrides & CommentOverrides>;\n}\n\ninterface CommentReactionProps extends ComponentPropsWithoutRef<\"button\"> {\n comment: CommentData;\n reaction: CommentReactionData;\n overrides?: Partial<GlobalOverrides & CommentOverrides>;\n}\n\ntype CommentNonInteractiveReactionProps = Omit<CommentReactionProps, \"comment\">;\n\nexport function CommentMention({\n userId,\n className,\n ...props\n}: CommentBodyMentionProps & CommentMentionProps) {\n const currentId = useCurrentUserId();\n return (\n <CommentPrimitive.Mention\n className={classNames(\"lb-comment-mention\", className)}\n data-self={userId === currentId ? \"\" : undefined}\n {...props}\n >\n {MENTION_CHARACTER}\n <User userId={userId} />\n </CommentPrimitive.Mention>\n );\n}\n\nexport function CommentLink({\n href,\n children,\n className,\n ...props\n}: CommentBodyLinkProps & CommentLinkProps) {\n return (\n <CommentPrimitive.Link\n className={classNames(\"lb-comment-link\", className)}\n href={href}\n {...props}\n >\n {children}\n </CommentPrimitive.Link>\n );\n}\n\nexport function CommentNonInteractiveLink({\n href: _href,\n children,\n className,\n ...props\n}: CommentBodyLinkProps & CommentLinkProps) {\n return (\n <span className={classNames(\"lb-comment-link\", className)} {...props}>\n {children}\n </span>\n );\n}\n\nconst CommentReactionButton = forwardRef<\n HTMLButtonElement,\n CommentReactionButtonProps\n>(({ reaction, overrides, className, ...props }, forwardedRef) => {\n const $ = useOverrides(overrides);\n return (\n <Button\n className={classNames(\"lb-comment-reaction\", className)}\n variant=\"outline\"\n aria-label={$.COMMENT_REACTION_DESCRIPTION(\n reaction.emoji,\n reaction.users.length\n )}\n {...props}\n ref={forwardedRef}\n >\n <Emoji className=\"lb-comment-reaction-emoji\" emoji={reaction.emoji} />\n <span className=\"lb-comment-reaction-count\">{reaction.users.length}</span>\n </Button>\n );\n});\n\nexport const CommentReaction = forwardRef<\n HTMLButtonElement,\n CommentReactionProps\n>(({ comment, reaction, overrides, disabled, ...props }, forwardedRef) => {\n const { useAddReaction, useRemoveReaction } = useRoomContextBundle();\n const addReaction = useAddReaction();\n const removeReaction = useRemoveReaction();\n const currentId = useCurrentUserId();\n const isActive = useMemo(() => {\n return reaction.users.some((users) => users.id === currentId);\n }, [currentId, reaction]);\n const $ = useOverrides(overrides);\n const tooltipContent = useMemo(\n () => (\n <span>\n {$.COMMENT_REACTION_LIST(\n <List\n values={reaction.users.map((users, index) => (\n <User\n key={users.id}\n userId={users.id}\n capitalize={index === 0}\n replaceSelf\n />\n ))}\n formatRemaining={$.LIST_REMAINING_USERS}\n truncate={REACTIONS_TRUNCATE}\n />,\n reaction.emoji,\n reaction.users.length\n )}\n </span>\n ),\n [$, reaction]\n );\n\n const handlePressedChange = useCallback(\n (isPressed: boolean) => {\n if (isPressed) {\n addReaction({\n threadId: comment.threadId,\n commentId: comment.id,\n emoji: reaction.emoji,\n });\n } else {\n removeReaction({\n threadId: comment.threadId,\n commentId: comment.id,\n emoji: reaction.emoji,\n });\n }\n },\n [addReaction, comment.threadId, comment.id, reaction.emoji, removeReaction]\n );\n\n return (\n <Tooltip\n content={tooltipContent}\n multiline\n className=\"lb-comment-reaction-tooltip\"\n >\n <TogglePrimitive.Root\n asChild\n pressed={isActive}\n onPressedChange={handlePressedChange}\n disabled={disabled}\n ref={forwardedRef}\n >\n <CommentReactionButton\n data-self={isActive ? \"\" : undefined}\n reaction={reaction}\n overrides={overrides}\n {...props}\n />\n </TogglePrimitive.Root>\n </Tooltip>\n );\n});\n\nexport const CommentNonInteractiveReaction = forwardRef<\n HTMLButtonElement,\n CommentNonInteractiveReactionProps\n>(({ reaction, overrides, ...props }, forwardedRef) => {\n const currentId = useCurrentUserId();\n const isActive = useMemo(() => {\n return reaction.users.some((users) => users.id === currentId);\n }, [currentId, reaction]);\n\n return (\n <CommentReactionButton\n disableable={false}\n data-self={isActive ? \"\" : undefined}\n reaction={reaction}\n overrides={overrides}\n {...props}\n ref={forwardedRef}\n />\n );\n});\n\n/**\n * Displays a single comment.\n *\n * @example\n * <>\n * {thread.comments.map((comment) => (\n * <Comment key={comment.id} comment={comment} />\n * ))}\n * </>\n */\nexport const Comment = forwardRef<HTMLDivElement, CommentProps>(\n (\n {\n comment,\n indentContent = true,\n showDeleted,\n showActions = \"hover\",\n showReactions = true,\n onAuthorClick,\n onMentionClick,\n onCommentEdit,\n onCommentDelete,\n overrides,\n className,\n additionalActions,\n additionalActionsClassName,\n markThreadAsReadWhenVisible,\n ...props\n },\n forwardedRef\n ) => {\n const {\n useDeleteComment,\n useEditComment,\n useAddReaction,\n useRemoveReaction,\n useMarkThreadAsRead,\n useSelf,\n } = useRoomContextBundle();\n const ref = useRef<HTMLDivElement>(null);\n const mergedRefs = useRefs(forwardedRef, ref);\n const self = useSelf();\n const deleteComment = useDeleteComment();\n const editComment = useEditComment();\n const addReaction = useAddReaction();\n const removeReaction = useRemoveReaction();\n const markThreadAsRead = useMarkThreadAsRead();\n const $ = useOverrides(overrides);\n const [isEditing, setEditing] = useState(false);\n const [isTarget, setTarget] = useState(false);\n const [isMoreActionOpen, setMoreActionOpen] = useState(false);\n const [isReactionActionOpen, setReactionActionOpen] = useState(false);\n\n const markVisibleThreadAsRead = useCallback(() => {\n if (markThreadAsReadWhenVisible) {\n markThreadAsRead(markThreadAsReadWhenVisible);\n }\n }, [markThreadAsRead, markThreadAsReadWhenVisible]);\n\n useVisibleCallback(ref, markVisibleThreadAsRead, {\n enabled: Boolean(markThreadAsReadWhenVisible),\n });\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n const handleEdit = useCallback(() => {\n setEditing(true);\n }, []);\n\n const handleEditCancel = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n setEditing(false);\n },\n []\n );\n\n const handleEditSubmit = useCallback(\n ({ body }: ComposerSubmitComment, event: FormEvent<HTMLFormElement>) => {\n // TODO: Add a way to preventDefault from within this callback, to override the default behavior (e.g. showing a confirmation dialog)\n onCommentEdit?.(comment);\n\n event.preventDefault();\n setEditing(false);\n editComment({\n commentId: comment.id,\n threadId: comment.threadId,\n body,\n });\n },\n [comment, editComment, onCommentEdit]\n );\n\n const handleDelete = useCallback(() => {\n // TODO: Add a way to preventDefault from within this callback, to override the default behavior (e.g. showing a confirmation dialog)\n onCommentDelete?.(comment);\n\n deleteComment({\n commentId: comment.id,\n threadId: comment.threadId,\n });\n }, [comment, deleteComment, onCommentDelete]);\n\n const handleAuthorClick = useCallback(\n (event: MouseEvent<HTMLElement>) => {\n onAuthorClick?.(comment.userId, event);\n },\n [comment.userId, onAuthorClick]\n );\n\n const handleReactionSelect = useCallback(\n (emoji: string) => {\n const reactionIndex = comment.reactions.findIndex(\n (reaction) => reaction.emoji === emoji\n );\n\n if (\n reactionIndex >= 0 &&\n self?.id &&\n comment.reactions[reactionIndex].users.some(\n (user) => user.id === self?.id\n )\n ) {\n removeReaction({\n threadId: comment.threadId,\n commentId: comment.id,\n emoji,\n });\n } else {\n addReaction({\n threadId: comment.threadId,\n commentId: comment.id,\n emoji,\n });\n }\n },\n [\n addReaction,\n comment.id,\n comment.reactions,\n comment.threadId,\n removeReaction,\n self?.id,\n ]\n );\n\n useEffect(() => {\n const isWindowDefined = typeof window !== \"undefined\";\n if (!isWindowDefined) return;\n\n const hash = window.location.hash;\n const commentId = hash.slice(1);\n\n if (commentId === comment.id) {\n setTarget(true);\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (!showDeleted && !comment.body) {\n return null;\n }\n\n return (\n <TooltipProvider>\n <div\n id={comment.id}\n className={classNames(\n \"lb-root lb-comment\",\n indentContent && \"lb-comment:indent-content\",\n showActions === \"hover\" && \"lb-comment:show-actions-hover\",\n (isMoreActionOpen || isReactionActionOpen) &&\n \"lb-comment:action-open\",\n className\n )}\n data-deleted={!comment.body ? \"\" : undefined}\n data-editing={isEditing ? \"\" : undefined}\n // In some cases, `:target` doesn't work as expected so we also define it manually.\n data-target={isTarget ? \"\" : undefined}\n dir={$.dir}\n {...props}\n ref={mergedRefs}\n >\n <div className=\"lb-comment-header\">\n <div className=\"lb-comment-details\">\n <Avatar\n className=\"lb-comment-avatar\"\n userId={comment.userId}\n onClick={handleAuthorClick}\n />\n <span className=\"lb-comment-details-labels\">\n <User\n className=\"lb-comment-author\"\n userId={comment.userId}\n onClick={handleAuthorClick}\n />\n <span className=\"lb-comment-date\">\n <Timestamp\n locale={$.locale}\n date={comment.createdAt}\n className=\"lb-comment-date-created\"\n />\n {comment.editedAt && comment.body && (\n <>\n {\" \"}\n <span className=\"lb-comment-date-edited\">\n {$.COMMENT_EDITED}\n </span>\n </>\n )}\n </span>\n </span>\n </div>\n {showActions && !isEditing && (\n <div\n className={classNames(\n \"lb-comment-actions\",\n additionalActionsClassName\n )}\n >\n {additionalActions ?? null}\n {showReactions && (\n <EmojiPicker\n onEmojiSelect={handleReactionSelect}\n onOpenChange={setReactionActionOpen}\n >\n <Tooltip content={$.COMMENT_ADD_REACTION}>\n <EmojiPickerTrigger asChild>\n <Button\n className=\"lb-comment-action\"\n onClick={stopPropagation}\n aria-label={$.COMMENT_ADD_REACTION}\n >\n <EmojiAddIcon className=\"lb-button-icon\" />\n </Button>\n </EmojiPickerTrigger>\n </Tooltip>\n </EmojiPicker>\n )}\n {comment.userId === self?.id && (\n <Dropdown\n open={isMoreActionOpen}\n onOpenChange={setMoreActionOpen}\n align=\"end\"\n content={\n <>\n <DropdownItem\n onSelect={handleEdit}\n onClick={stopPropagation}\n >\n <EditIcon className=\"lb-dropdown-item-icon\" />\n {$.COMMENT_EDIT}\n </DropdownItem>\n <DropdownItem\n onSelect={handleDelete}\n onClick={stopPropagation}\n >\n <DeleteIcon className=\"lb-dropdown-item-icon\" />\n {$.COMMENT_DELETE}\n </DropdownItem>\n </>\n }\n >\n <Tooltip content={$.COMMENT_MORE}>\n <DropdownTrigger asChild>\n <Button\n className=\"lb-comment-action\"\n disabled={!comment.body}\n onClick={stopPropagation}\n aria-label={$.COMMENT_MORE}\n >\n <EllipsisIcon className=\"lb-button-icon\" />\n </Button>\n </DropdownTrigger>\n </Tooltip>\n </Dropdown>\n )}\n </div>\n )}\n </div>\n <div className=\"lb-comment-content\">\n {isEditing ? (\n <Composer\n className=\"lb-comment-composer\"\n onComposerSubmit={handleEditSubmit}\n defaultValue={comment.body}\n autoFocus\n showAttribution={false}\n actions={\n <>\n <Tooltip\n content={$.COMMENT_EDIT_COMPOSER_CANCEL}\n aria-label={$.COMMENT_EDIT_COMPOSER_CANCEL}\n >\n <Button\n className=\"lb-composer-action\"\n onClick={handleEditCancel}\n >\n <CrossIcon className=\"lb-button-icon\" />\n </Button>\n </Tooltip>\n <ShortcutTooltip\n content={$.COMMENT_EDIT_COMPOSER_SAVE}\n shortcut={<ShortcutTooltipKey name=\"enter\" />}\n >\n <ComposerPrimitive.Submit asChild>\n <Button\n variant=\"primary\"\n className=\"lb-composer-action\"\n onClick={stopPropagation}\n aria-label={$.COMMENT_EDIT_COMPOSER_SAVE}\n >\n <CheckIcon className=\"lb-button-icon\" />\n </Button>\n </ComposerPrimitive.Submit>\n </ShortcutTooltip>\n </>\n }\n overrides={{\n COMPOSER_PLACEHOLDER: $.COMMENT_EDIT_COMPOSER_PLACEHOLDER,\n }}\n />\n ) : comment.body ? (\n <>\n <CommentPrimitive.Body\n className=\"lb-comment-body\"\n body={comment.body}\n components={{\n Mention: ({ userId }) => (\n <CommentMention\n userId={userId}\n onClick={(event) => onMentionClick?.(userId, event)}\n />\n ),\n Link: CommentLink,\n }}\n />\n {showReactions && comment.reactions.length > 0 && (\n <div className=\"lb-comment-reactions\">\n {comment.reactions.map((reaction) => (\n <CommentReaction\n key={reaction.emoji}\n comment={comment}\n reaction={reaction}\n overrides={overrides}\n />\n ))}\n <EmojiPicker onEmojiSelect={handleReactionSelect}>\n <Tooltip content={$.COMMENT_ADD_REACTION}>\n <EmojiPickerTrigger asChild>\n <Button\n className=\"lb-comment-reaction lb-comment-reaction-add\"\n variant=\"outline\"\n onClick={stopPropagation}\n aria-label={$.COMMENT_ADD_REACTION}\n >\n <EmojiAddIcon className=\"lb-button-icon\" />\n </Button>\n </EmojiPickerTrigger>\n </Tooltip>\n </EmojiPicker>\n </div>\n )}\n </>\n ) : (\n <div className=\"lb-comment-body\">\n <p className=\"lb-comment-deleted\">{$.COMMENT_DELETED}</p>\n </div>\n )}\n </div>\n </div>\n </TooltipProvider>\n );\n }\n);\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA;AAmFO;AAAwB;AAC7B;AACA;AAEF;AACE;AACA;AACG;AACsD;AACd;AACnC;AAGH;AAAK;AAGZ;AAEO;AAAqB;AAC1B;AACA;AACA;AAEF;AACE;AACG;AACmD;AAClD;AACI;AAKV;AAEO;AAAmC;AAClC;AACN;AACA;AAEF;AACE;AACG;AAAuD;AAAO;AAInE;AAEA;AAIE;AACA;AACG;AACuD;AAC9C;AACM;AACH;AACM;AACjB;AACI;AACC;AAEJ;AAAgB;AAA4C;AAC5D;AAAe;AAGtB;AAEa;AAIX;AACA;AACA;AACA;AACA;AACE;AAA4D;AAE9D;AACA;AAAuB;AAGd;AACA;AAEI;AACY;AACG;AACQ;AACX;AAEd;AACkB;AACT;AACZ;AACS;AACM;AAEnB;AAEU;AAGd;AAA4B;AAExB;AACE;AAAY;AACQ;AACC;AACH;AACjB;AAED;AAAe;AACK;AACC;AACH;AACjB;AACH;AACF;AAC0E;AAG5E;AACG;AACU;AACA;AACC;AAET;AACQ;AACE;AACQ;AACjB;AACK;AAEJ;AAC4B;AAC3B;AACA;AACI;AAKd;AAEa;AAIX;AACA;AACE;AAA4D;AAG9D;AACG;AACc;AACc;AAC3B;AACA;AACI;AACC;AAGX;AAYO;AAAgB;AAEnB;AACE;AACgB;AAChB;AACc;AACE;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACG;AAIL;AAAM;AACJ;AACA;AACA;AACA;AACA;AACA;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACE;AACE;AAA4C;AAC9C;AAGF;AAAiD;AACH;AAG9C;AACE;AAAsB;AAGxB;AACE;AAAe;AAGjB;AAAyB;AAErB;AACA;AAAgB;AAClB;AACC;AAGH;AAAyB;AAGrB;AAEA;AACA;AACA;AAAY;AACS;AACD;AAClB;AACD;AACH;AACoC;AAGtC;AAEE;AAEA;AAAc;AACO;AACD;AACnB;AAGH;AAA0B;AAEtB;AAAqC;AACvC;AAC8B;AAGhC;AAA6B;AAEzB;AAAwC;AACL;AAGnC;AAGyC;AACT;AAG9B;AAAe;AACK;AACC;AACnB;AACD;AAED;AAAY;AACQ;AACC;AACnB;AACD;AACH;AACF;AACA;AACE;AACQ;AACA;AACA;AACR;AACM;AACR;AAGF;AACE;AACA;AAAsB;AAEtB;AACA;AAEA;AACE;AAAc;AAChB;AAGF;AACE;AAAO;AAGT;AAEK;AACa;AACD;AACT;AACiB;AACU;AAEzB;AACF;AACF;AACmC;AACJ;AAEF;AACtB;AACH;AACC;AAEJ;AAAc;AACZ;AAAc;AACZ;AACW;AACM;AACP;AAEV;AAAe;AACb;AACW;AACM;AACP;AAEV;AAAe;AACb;AACW;AACI;AACJ;AAKP;AAAe;AASvB;AACY;AACT;AACA;AACF;AAIG;AACgB;AACD;AAEb;AAAmB;AACjB;AAA0B;AACxB;AACW;AACD;AACK;AAEb;AAAuB;AAO/B;AACO;AACQ;AACR;AAGD;AACW;AACD;AAER;AAAmB;AAGrB;AACW;AACD;AAER;AAAqB;AAG1B;AAGD;AAAmB;AACjB;AAAuB;AACrB;AACW;AACS;AACV;AACK;AAEb;AAAuB;AASvC;AAAc;AAEV;AACW;AACQ;AACI;AACb;AACQ;AAGZ;AACY;AACG;AAEb;AACW;AACD;AAER;AAAoB;AAGxB;AACY;AACA;AAAwB;AAAQ;AAE1C;AAAgC;AAC9B;AACS;AACE;AACD;AACK;AAEb;AAAoB;AAI7B;AAES;AACe;AAC1B;AAIC;AACW;AACI;AACF;AAEP;AACC;AACkD;AACpD;AAEI;AACR;AAGC;AAAc;AAEV;AACe;AACd;AACA;AACA;AAGH;AAA2B;AACzB;AAAmB;AACjB;AAA0B;AACxB;AACW;AACF;AACC;AACK;AAEb;AAAuB;AASrC;AAAc;AACZ;AAAY;AAKvB;AAGN;;;;;;;"}