@openrails/contentkit-ui 0.0.0-placeholder → 0.68.0

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 (367) hide show
  1. package/README.md +424 -1
  2. package/dist/appearance.d.ts +38 -0
  3. package/dist/appearance.js +15 -0
  4. package/dist/appearance.js.map +1 -0
  5. package/dist/assets/hash.worker-BYfo-7MQ.js.map +1 -0
  6. package/dist/client/aspect.d.ts +6 -0
  7. package/dist/client/aspect.js +17 -0
  8. package/dist/client/aspect.js.map +1 -0
  9. package/dist/client/client.d.ts +51 -0
  10. package/dist/client/client.js +35 -0
  11. package/dist/client/client.js.map +1 -0
  12. package/dist/client/codes.d.ts +12 -0
  13. package/dist/client/codes.js +19 -0
  14. package/dist/client/codes.js.map +1 -0
  15. package/dist/client/content/bans.d.ts +15 -0
  16. package/dist/client/content/bans.js +40 -0
  17. package/dist/client/content/bans.js.map +1 -0
  18. package/dist/client/content/comments.d.ts +36 -0
  19. package/dist/client/content/comments.js +93 -0
  20. package/dist/client/content/comments.js.map +1 -0
  21. package/dist/client/content/favorites.d.ts +14 -0
  22. package/dist/client/content/favorites.js +42 -0
  23. package/dist/client/content/favorites.js.map +1 -0
  24. package/dist/client/content/moderation.d.ts +18 -0
  25. package/dist/client/content/moderation.js +37 -0
  26. package/dist/client/content/moderation.js.map +1 -0
  27. package/dist/client/content/polls.d.ts +47 -0
  28. package/dist/client/content/polls.js +148 -0
  29. package/dist/client/content/polls.js.map +1 -0
  30. package/dist/client/content/posts.d.ts +44 -0
  31. package/dist/client/content/posts.js +91 -0
  32. package/dist/client/content/posts.js.map +1 -0
  33. package/dist/client/content/reactions.d.ts +12 -0
  34. package/dist/client/content/reactions.js +36 -0
  35. package/dist/client/content/reactions.js.map +1 -0
  36. package/dist/client/content/types.d.ts +91 -0
  37. package/dist/client/content/types.js +8 -0
  38. package/dist/client/content/types.js.map +1 -0
  39. package/dist/client/crop.d.ts +32 -0
  40. package/dist/client/crop.js +103 -0
  41. package/dist/client/crop.js.map +1 -0
  42. package/dist/client/errors.d.ts +54 -0
  43. package/dist/client/errors.js +80 -0
  44. package/dist/client/errors.js.map +1 -0
  45. package/dist/client/gallery.d.ts +43 -0
  46. package/dist/client/gallery.js +86 -0
  47. package/dist/client/gallery.js.map +1 -0
  48. package/dist/client/generated/error-codes.d.ts +5 -0
  49. package/dist/client/generated/error-codes.js +131 -0
  50. package/dist/client/generated/error-codes.js.map +1 -0
  51. package/dist/client/generated/routes.d.ts +1086 -0
  52. package/dist/client/generated/routes.js +1400 -0
  53. package/dist/client/generated/routes.js.map +1 -0
  54. package/dist/client/generated/wire.d.ts +630 -0
  55. package/dist/client/generated/wire.js +6 -0
  56. package/dist/client/generated/wire.js.map +1 -0
  57. package/dist/client/http.d.ts +79 -0
  58. package/dist/client/http.js +74 -0
  59. package/dist/client/http.js.map +1 -0
  60. package/dist/client/image.d.ts +24 -0
  61. package/dist/client/image.js +65 -0
  62. package/dist/client/image.js.map +1 -0
  63. package/dist/client/index.d.ts +33 -0
  64. package/dist/client/media/api.d.ts +36 -0
  65. package/dist/client/media/api.js +61 -0
  66. package/dist/client/media/api.js.map +1 -0
  67. package/dist/client/media/client.d.ts +247 -0
  68. package/dist/client/media/client.js +407 -0
  69. package/dist/client/media/client.js.map +1 -0
  70. package/dist/client/media/encode.d.ts +3 -0
  71. package/dist/client/media/encode.js +8 -0
  72. package/dist/client/media/encode.js.map +1 -0
  73. package/dist/client/media/hash-stream.d.ts +6 -0
  74. package/dist/client/media/hash-stream.js +16 -0
  75. package/dist/client/media/hash-stream.js.map +1 -0
  76. package/dist/client/media/hash.d.ts +12 -0
  77. package/dist/client/media/hash.js +48 -0
  78. package/dist/client/media/hash.js.map +1 -0
  79. package/dist/client/media/hash.worker-inline.js +18 -0
  80. package/dist/client/media/hash.worker-inline.js.map +1 -0
  81. package/dist/client/media/pacer.d.ts +21 -0
  82. package/dist/client/media/pacer.js +25 -0
  83. package/dist/client/media/pacer.js.map +1 -0
  84. package/dist/client/media/queue.d.ts +112 -0
  85. package/dist/client/media/queue.js +274 -0
  86. package/dist/client/media/queue.js.map +1 -0
  87. package/dist/client/media/ref.d.ts +6 -0
  88. package/dist/client/media/ref.js +10 -0
  89. package/dist/client/media/ref.js.map +1 -0
  90. package/dist/client/media/rules.d.ts +52 -0
  91. package/dist/client/media/rules.js +139 -0
  92. package/dist/client/media/rules.js.map +1 -0
  93. package/dist/client/media/transport.d.ts +13 -0
  94. package/dist/client/media/transport.js +33 -0
  95. package/dist/client/media/transport.js.map +1 -0
  96. package/dist/client/media/windows.d.ts +15 -0
  97. package/dist/client/media/windows.js +39 -0
  98. package/dist/client/media/windows.js.map +1 -0
  99. package/dist/client/playback.d.ts +200 -0
  100. package/dist/client/playback.js +142 -0
  101. package/dist/client/playback.js.map +1 -0
  102. package/dist/client/player.d.ts +102 -0
  103. package/dist/client/player.js +155 -0
  104. package/dist/client/player.js.map +1 -0
  105. package/dist/client/public.d.ts +25 -0
  106. package/dist/client/public.js +18 -0
  107. package/dist/client/public.js.map +1 -0
  108. package/dist/client/rendition.d.ts +19 -0
  109. package/dist/client/rendition.js +16 -0
  110. package/dist/client/rendition.js.map +1 -0
  111. package/dist/client/route.d.ts +39 -0
  112. package/dist/client/route.js +31 -0
  113. package/dist/client/route.js.map +1 -0
  114. package/dist/client/taxonomy.d.ts +30 -0
  115. package/dist/client/taxonomy.js +77 -0
  116. package/dist/client/taxonomy.js.map +1 -0
  117. package/dist/client.js +33 -0
  118. package/dist/components/encode-progress.d.ts +15 -0
  119. package/dist/components/encode-progress.js +49 -0
  120. package/dist/components/encode-progress.js.map +1 -0
  121. package/dist/components/hover-preview.d.ts +29 -0
  122. package/dist/components/hover-preview.js +49 -0
  123. package/dist/components/hover-preview.js.map +1 -0
  124. package/dist/components/image-crop-dialog.d.ts +48 -0
  125. package/dist/components/image-crop-dialog.js +359 -0
  126. package/dist/components/image-crop-dialog.js.map +1 -0
  127. package/dist/components/lazy-mount.d.ts +10 -0
  128. package/dist/components/lazy-mount.js +22 -0
  129. package/dist/components/lazy-mount.js.map +1 -0
  130. package/dist/components/media-folder-editor.d.ts +45 -0
  131. package/dist/components/media-folder-editor.js +564 -0
  132. package/dist/components/media-folder-editor.js.map +1 -0
  133. package/dist/components/media-gallery.d.ts +54 -0
  134. package/dist/components/media-gallery.js +597 -0
  135. package/dist/components/media-gallery.js.map +1 -0
  136. package/dist/components/media-readiness-notice.d.ts +24 -0
  137. package/dist/components/media-readiness-notice.js +61 -0
  138. package/dist/components/media-readiness-notice.js.map +1 -0
  139. package/dist/components/player-controls.d.ts +71 -0
  140. package/dist/components/player-controls.js +264 -0
  141. package/dist/components/player-controls.js.map +1 -0
  142. package/dist/components/progress.d.ts +5 -0
  143. package/dist/components/progress.js +14 -0
  144. package/dist/components/progress.js.map +1 -0
  145. package/dist/components/rendition-img.d.ts +34 -0
  146. package/dist/components/rendition-img.js +78 -0
  147. package/dist/components/rendition-img.js.map +1 -0
  148. package/dist/components/slot-editor.d.ts +95 -0
  149. package/dist/components/slot-editor.js +182 -0
  150. package/dist/components/slot-editor.js.map +1 -0
  151. package/dist/components/slot-image.d.ts +23 -0
  152. package/dist/components/slot-image.js +48 -0
  153. package/dist/components/slot-image.js.map +1 -0
  154. package/dist/components/slot-upload.d.ts +41 -0
  155. package/dist/components/slot-upload.js +213 -0
  156. package/dist/components/slot-upload.js.map +1 -0
  157. package/dist/components/social/bans.d.ts +42 -0
  158. package/dist/components/social/bans.js +300 -0
  159. package/dist/components/social/bans.js.map +1 -0
  160. package/dist/components/social/comments.d.ts +42 -0
  161. package/dist/components/social/comments.js +517 -0
  162. package/dist/components/social/comments.js.map +1 -0
  163. package/dist/components/social/engagement.d.ts +45 -0
  164. package/dist/components/social/engagement.js +129 -0
  165. package/dist/components/social/engagement.js.map +1 -0
  166. package/dist/components/social/index.d.ts +6 -0
  167. package/dist/components/social/moderation.d.ts +32 -0
  168. package/dist/components/social/moderation.js +383 -0
  169. package/dist/components/social/moderation.js.map +1 -0
  170. package/dist/components/social/parts.d.ts +50 -0
  171. package/dist/components/social/parts.js +106 -0
  172. package/dist/components/social/parts.js.map +1 -0
  173. package/dist/components/social/poll-editor.d.ts +34 -0
  174. package/dist/components/social/poll-editor.js +567 -0
  175. package/dist/components/social/poll-editor.js.map +1 -0
  176. package/dist/components/social/poll.d.ts +30 -0
  177. package/dist/components/social/poll.js +252 -0
  178. package/dist/components/social/poll.js.map +1 -0
  179. package/dist/components/sortable-list.d.ts +29 -0
  180. package/dist/components/sortable-list.js +121 -0
  181. package/dist/components/sortable-list.js.map +1 -0
  182. package/dist/components/video-mini-player.d.ts +35 -0
  183. package/dist/components/video-mini-player.js +236 -0
  184. package/dist/components/video-mini-player.js.map +1 -0
  185. package/dist/components/video-player.d.ts +146 -0
  186. package/dist/components/video-player.js +630 -0
  187. package/dist/components/video-player.js.map +1 -0
  188. package/dist/components/video-poster-picker.d.ts +59 -0
  189. package/dist/components/video-poster-picker.js +335 -0
  190. package/dist/components/video-poster-picker.js.map +1 -0
  191. package/dist/components/video-poster.d.ts +24 -0
  192. package/dist/components/video-poster.js +46 -0
  193. package/dist/components/video-poster.js.map +1 -0
  194. package/dist/i18n/context.d.ts +4 -0
  195. package/dist/i18n/context.js +11 -0
  196. package/dist/i18n/context.js.map +1 -0
  197. package/dist/i18n/messages.d.ts +40 -0
  198. package/dist/i18n/messages.js +94 -0
  199. package/dist/i18n/messages.js.map +1 -0
  200. package/dist/index.d.ts +23 -0
  201. package/dist/index.js +41 -0
  202. package/dist/locales/de.d.ts +2 -0
  203. package/dist/locales/de.js +271 -0
  204. package/dist/locales/de.js.map +1 -0
  205. package/dist/locales/en.d.ts +457 -0
  206. package/dist/locales/en.js +271 -0
  207. package/dist/locales/en.js.map +1 -0
  208. package/dist/locales/es.d.ts +2 -0
  209. package/dist/locales/es.js +271 -0
  210. package/dist/locales/es.js.map +1 -0
  211. package/dist/locales/ja.d.ts +2 -0
  212. package/dist/locales/ja.js +271 -0
  213. package/dist/locales/ja.js.map +1 -0
  214. package/dist/locales/ko.d.ts +2 -0
  215. package/dist/locales/ko.js +271 -0
  216. package/dist/locales/ko.js.map +1 -0
  217. package/dist/locales/social/de.d.ts +2 -0
  218. package/dist/locales/social/de.js +198 -0
  219. package/dist/locales/social/de.js.map +1 -0
  220. package/dist/locales/social/en.d.ts +195 -0
  221. package/dist/locales/social/en.js +198 -0
  222. package/dist/locales/social/en.js.map +1 -0
  223. package/dist/locales/social/es.d.ts +2 -0
  224. package/dist/locales/social/es.js +198 -0
  225. package/dist/locales/social/es.js.map +1 -0
  226. package/dist/locales/social/ja.d.ts +2 -0
  227. package/dist/locales/social/ja.js +198 -0
  228. package/dist/locales/social/ja.js.map +1 -0
  229. package/dist/locales/social/ko.d.ts +2 -0
  230. package/dist/locales/social/ko.js +198 -0
  231. package/dist/locales/social/ko.js.map +1 -0
  232. package/dist/locales/social/zh.d.ts +2 -0
  233. package/dist/locales/social/zh.js +198 -0
  234. package/dist/locales/social/zh.js.map +1 -0
  235. package/dist/locales/zh.d.ts +2 -0
  236. package/dist/locales/zh.js +271 -0
  237. package/dist/locales/zh.js.map +1 -0
  238. package/dist/provider.d.ts +22 -0
  239. package/dist/provider.js +59 -0
  240. package/dist/provider.js.map +1 -0
  241. package/dist/react/canonical.d.ts +33 -0
  242. package/dist/react/canonical.js +88 -0
  243. package/dist/react/canonical.js.map +1 -0
  244. package/dist/react/comments.d.ts +82 -0
  245. package/dist/react/comments.js +147 -0
  246. package/dist/react/comments.js.map +1 -0
  247. package/dist/react/config.d.ts +13 -0
  248. package/dist/react/config.js +14 -0
  249. package/dist/react/config.js.map +1 -0
  250. package/dist/react/context.d.ts +48 -0
  251. package/dist/react/context.js +37 -0
  252. package/dist/react/context.js.map +1 -0
  253. package/dist/react/crop.d.ts +49 -0
  254. package/dist/react/crop.js +107 -0
  255. package/dist/react/crop.js.map +1 -0
  256. package/dist/react/engagement.d.ts +38 -0
  257. package/dist/react/engagement.js +88 -0
  258. package/dist/react/engagement.js.map +1 -0
  259. package/dist/react/folder.d.ts +83 -0
  260. package/dist/react/folder.js +183 -0
  261. package/dist/react/folder.js.map +1 -0
  262. package/dist/react/gallery.d.ts +140 -0
  263. package/dist/react/gallery.js +477 -0
  264. package/dist/react/gallery.js.map +1 -0
  265. package/dist/react/index.d.ts +21 -0
  266. package/dist/react/inline-preview.d.ts +24 -0
  267. package/dist/react/inline-preview.js +76 -0
  268. package/dist/react/inline-preview.js.map +1 -0
  269. package/dist/react/player.d.ts +70 -0
  270. package/dist/react/player.js +214 -0
  271. package/dist/react/player.js.map +1 -0
  272. package/dist/react/polls.d.ts +74 -0
  273. package/dist/react/polls.js +176 -0
  274. package/dist/react/polls.js.map +1 -0
  275. package/dist/react/posts.d.ts +59 -0
  276. package/dist/react/posts.js +149 -0
  277. package/dist/react/posts.js.map +1 -0
  278. package/dist/react/provider.d.ts +23 -0
  279. package/dist/react/provider.js +35 -0
  280. package/dist/react/provider.js.map +1 -0
  281. package/dist/react/public.d.ts +39 -0
  282. package/dist/react/public.js +70 -0
  283. package/dist/react/public.js.map +1 -0
  284. package/dist/react/read.d.ts +52 -0
  285. package/dist/react/read.js +143 -0
  286. package/dist/react/read.js.map +1 -0
  287. package/dist/react/resources.d.ts +70 -0
  288. package/dist/react/resources.js +247 -0
  289. package/dist/react/resources.js.map +1 -0
  290. package/dist/react/slot.d.ts +102 -0
  291. package/dist/react/slot.js +181 -0
  292. package/dist/react/slot.js.map +1 -0
  293. package/dist/react/store.d.ts +51 -0
  294. package/dist/react/store.js +164 -0
  295. package/dist/react/store.js.map +1 -0
  296. package/dist/react/upload.d.ts +85 -0
  297. package/dist/react/upload.js +150 -0
  298. package/dist/react/upload.js.map +1 -0
  299. package/dist/react/use-resource.d.ts +43 -0
  300. package/dist/react/use-resource.js +66 -0
  301. package/dist/react/use-resource.js.map +1 -0
  302. package/dist/react/video.d.ts +118 -0
  303. package/dist/react/video.js +184 -0
  304. package/dist/react/video.js.map +1 -0
  305. package/dist/react/viewport.d.ts +19 -0
  306. package/dist/react/viewport.js +30 -0
  307. package/dist/react/viewport.js.map +1 -0
  308. package/dist/react.js +21 -0
  309. package/dist/scope.d.ts +14 -0
  310. package/dist/scope.js +30 -0
  311. package/dist/scope.js.map +1 -0
  312. package/dist/styles.css +3 -0
  313. package/dist/ui/alert-dialog.d.ts +18 -0
  314. package/dist/ui/alert-dialog.js +86 -0
  315. package/dist/ui/alert-dialog.js.map +1 -0
  316. package/dist/ui/alert.d.ts +10 -0
  317. package/dist/ui/alert.js +38 -0
  318. package/dist/ui/alert.js.map +1 -0
  319. package/dist/ui/avatar.d.ts +11 -0
  320. package/dist/ui/avatar.js +31 -0
  321. package/dist/ui/avatar.js.map +1 -0
  322. package/dist/ui/badge.d.ts +7 -0
  323. package/dist/ui/badge.js +31 -0
  324. package/dist/ui/badge.js.map +1 -0
  325. package/dist/ui/button.d.ts +8 -0
  326. package/dist/ui/button.js +46 -0
  327. package/dist/ui/button.js.map +1 -0
  328. package/dist/ui/dialog.d.ts +17 -0
  329. package/dist/ui/dialog.js +91 -0
  330. package/dist/ui/dialog.js.map +1 -0
  331. package/dist/ui/dropdown-menu.d.ts +15 -0
  332. package/dist/ui/dropdown-menu.js +105 -0
  333. package/dist/ui/dropdown-menu.js.map +1 -0
  334. package/dist/ui/input.d.ts +3 -0
  335. package/dist/ui/input.js +17 -0
  336. package/dist/ui/input.js.map +1 -0
  337. package/dist/ui/label.d.ts +3 -0
  338. package/dist/ui/label.js +15 -0
  339. package/dist/ui/label.js.map +1 -0
  340. package/dist/ui/progress.d.ts +7 -0
  341. package/dist/ui/progress.js +31 -0
  342. package/dist/ui/progress.js.map +1 -0
  343. package/dist/ui/select.d.ts +15 -0
  344. package/dist/ui/select.js +98 -0
  345. package/dist/ui/select.js.map +1 -0
  346. package/dist/ui/skeleton.d.ts +2 -0
  347. package/dist/ui/skeleton.js +14 -0
  348. package/dist/ui/skeleton.js.map +1 -0
  349. package/dist/ui/slider.d.ts +3 -0
  350. package/dist/ui/slider.js +35 -0
  351. package/dist/ui/slider.js.map +1 -0
  352. package/dist/ui/switch.d.ts +5 -0
  353. package/dist/ui/switch.js +20 -0
  354. package/dist/ui/switch.js.map +1 -0
  355. package/dist/ui/tabs.d.ts +10 -0
  356. package/dist/ui/tabs.js +47 -0
  357. package/dist/ui/tabs.js.map +1 -0
  358. package/dist/ui/textarea.d.ts +3 -0
  359. package/dist/ui/textarea.js +15 -0
  360. package/dist/ui/textarea.js.map +1 -0
  361. package/dist/ui/toggle-group.d.ts +5 -0
  362. package/dist/ui/toggle-group.js +23 -0
  363. package/dist/ui/toggle-group.js.map +1 -0
  364. package/dist/urls/index.d.ts +100 -0
  365. package/dist/urls.js +118 -0
  366. package/dist/urls.js.map +1 -0
  367. package/package.json +113 -3
@@ -0,0 +1,45 @@
1
+ import { ContentKitClient } from '../../client/client.js';
2
+ import { ReactionCounts, RefBody } from '../../client/generated/wire.js';
3
+ import { ContentKitUiAppearance } from '../../appearance.js';
4
+ import { ContentKitErrorHandler } from '../../react/context.js';
5
+ export interface ReactionButtonsProps {
6
+ item: RefBody;
7
+ /** Counts the host already has, used instead of reading them. */
8
+ counts?: ReactionCounts;
9
+ /** Offer dislike too. Default true. */
10
+ dislike?: boolean;
11
+ /** Asks a signed-out visitor to sign in where the server takes no anonymous reactions (default the provider's). */
12
+ onSignIn?: () => void;
13
+ size?: "sm" | "default";
14
+ client?: ContentKitClient;
15
+ onError?: ContentKitErrorHandler;
16
+ className?: string;
17
+ appearance?: ContentKitUiAppearance;
18
+ }
19
+ /**
20
+ * Like and dislike toggles with counts: they change at once and roll back if
21
+ * the server refuses. Signed out, they react anonymously where the server
22
+ * allows it (`Config.anonymous.reactions`) and ask to sign in elsewhere.
23
+ */
24
+ export declare function ReactionButtons({ item, counts: initial, dislike, onSignIn, size, client, onError, className, appearance }: ReactionButtonsProps): import('react').JSX.Element;
25
+ export interface FavoriteButtonProps {
26
+ item: RefBody;
27
+ /** Whether it is favorited and the item's count, as the host already has them: both given, nothing is read. */
28
+ favorited?: boolean;
29
+ count?: number;
30
+ /** Show the item's favorite count. Default true. */
31
+ showCount?: boolean;
32
+ /** Show the label beside the icon. Default true. */
33
+ label?: boolean;
34
+ /** Asks a signed-out visitor to sign in (default the provider's). */
35
+ onSignIn?: () => void;
36
+ /** After each saved change. */
37
+ onChange?: (favorited: boolean) => void;
38
+ size?: "sm" | "default";
39
+ client?: ContentKitClient;
40
+ onError?: ContentKitErrorHandler;
41
+ className?: string;
42
+ appearance?: ContentKitUiAppearance;
43
+ }
44
+ /** Adds the item to the signed-in visitor's favorites, or removes it, with the server's count; changes at once and rolls back if refused. */
45
+ export declare function FavoriteButton({ item, favorited, count, showCount, label, onSignIn, onChange, size, client, onError, className, appearance }: FavoriteButtonProps): import('react').JSX.Element;
@@ -0,0 +1,129 @@
1
+ import { toContentKitError as e } from "../../client/errors.js";
2
+ import { useMessages as t } from "../../i18n/context.js";
3
+ import { ContentKitUiRoot as n } from "../../scope.js";
4
+ import { ContentKitContext as r, useErrorReporter as i } from "../../react/context.js";
5
+ import { Button as a } from "../../ui/button.js";
6
+ import { useContentConfig as o } from "../../react/config.js";
7
+ import { contentError as s } from "./parts.js";
8
+ import { useFavorite as c, useReaction as l } from "../../react/engagement.js";
9
+ import { useContext as u, useState as d } from "react";
10
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
11
+ import { cn as m } from "cn";
12
+ import { FavouriteIcon as h, ThumbsDownIcon as g, ThumbsUpIcon as _ } from "@hugeicons/core-free-icons";
13
+ import { HugeiconsIcon as v } from "@hugeicons/react";
14
+ //#region src/components/social/engagement.tsx
15
+ var y = (e, t) => new Intl.NumberFormat(t, {
16
+ notation: "compact",
17
+ maximumFractionDigits: 1
18
+ }).format(e);
19
+ function b({ item: c, counts: h, dislike: b = !0, onSignIn: x, size: S = "default", client: C, onError: w, className: T, appearance: E }) {
20
+ let D = t(), { t: O } = D, k = l(c, {
21
+ initial: h,
22
+ client: C
23
+ }), A = u(r), { config: j } = o({ client: C }), M = x ?? A?.onSignIn, N = A?.viewer === null && j?.anonymous.reactions === !1, P = i(w), [F, I] = d(null), L = (t) => {
24
+ if (N) return M?.();
25
+ I(null), k.toggle(t).catch((t) => {
26
+ let n = e(t);
27
+ if (n.code === "unauthorized" && M) return M();
28
+ I(n), P(n, "reaction.save");
29
+ });
30
+ }, R = S === "sm" ? "sm" : "default", z = N ? O("reactions.signIn") : void 0, B = N && !M;
31
+ return /* @__PURE__ */ p(n, {
32
+ appearance: E,
33
+ className: m("inline-flex flex-wrap items-center gap-1 text-sm", T),
34
+ "data-ckui": "reaction-buttons",
35
+ children: [/* @__PURE__ */ p("div", {
36
+ className: "inline-flex items-center gap-1",
37
+ children: [/* @__PURE__ */ p(a, {
38
+ variant: k.counts.mine === 1 ? "secondary" : "ghost",
39
+ size: R,
40
+ "aria-pressed": k.counts.mine === 1,
41
+ "aria-label": O("reactions.like"),
42
+ title: z,
43
+ disabled: B,
44
+ onClick: () => L(1),
45
+ children: [/* @__PURE__ */ f(v, {
46
+ icon: _,
47
+ strokeWidth: 2
48
+ }), /* @__PURE__ */ f("span", { children: y(k.counts.likes, D.language) })]
49
+ }), b && /* @__PURE__ */ p(a, {
50
+ variant: k.counts.mine === -1 ? "secondary" : "ghost",
51
+ size: R,
52
+ "aria-pressed": k.counts.mine === -1,
53
+ "aria-label": O("reactions.dislike"),
54
+ title: z,
55
+ disabled: B,
56
+ onClick: () => L(-1),
57
+ children: [/* @__PURE__ */ f(v, {
58
+ icon: g,
59
+ strokeWidth: 2
60
+ }), /* @__PURE__ */ f("span", { children: y(k.counts.dislikes, D.language) })]
61
+ })]
62
+ }), F && /* @__PURE__ */ f("span", {
63
+ role: "alert",
64
+ className: "text-xs text-destructive",
65
+ children: F.code === "rate_limited" || F.code === "forbidden" ? s(D, F) : O("reactions.failed")
66
+ })]
67
+ });
68
+ }
69
+ function x({ item: o, favorited: l, count: g, showCount: _ = !0, label: b = !0, onSignIn: x, onChange: S, size: C = "default", client: w, onError: T, className: E, appearance: D }) {
70
+ let O = t(), { t: k } = O, A = u(r), j = c(o, {
71
+ initial: l !== void 0 && g !== void 0 ? {
72
+ favorited: l,
73
+ count: g
74
+ } : void 0,
75
+ client: w
76
+ }), M = x ?? A?.onSignIn, N = i(T), [P, F] = d(null), [I, L] = d(""), R = _ ? j.count : void 0, z = () => {
77
+ if (A?.viewer === null) return M?.();
78
+ F(null);
79
+ let t = !j.favorited;
80
+ j.set(t).then(() => {
81
+ L(k(t ? "favorites.added" : "favorites.removed")), S?.(t);
82
+ }, (t) => {
83
+ let n = e(t);
84
+ if (n.code === "unauthorized" && M) return M();
85
+ F(n), N(n, "favorite.save");
86
+ });
87
+ }, B = k(A?.viewer === null && M ? "favorites.signIn" : j.favorited ? "favorites.remove" : "favorites.add");
88
+ return /* @__PURE__ */ p(n, {
89
+ appearance: D,
90
+ className: m("inline-flex flex-wrap items-center gap-2 text-sm", E),
91
+ "data-ckui": "favorite-button",
92
+ children: [
93
+ /* @__PURE__ */ p(a, {
94
+ variant: j.favorited ? "secondary" : "outline",
95
+ size: b ? C === "sm" ? "sm" : "default" : C === "sm" ? "icon-sm" : "icon",
96
+ "aria-pressed": j.favorited,
97
+ "aria-label": b ? void 0 : B,
98
+ disabled: j.pending,
99
+ onClick: z,
100
+ children: [
101
+ /* @__PURE__ */ f(v, {
102
+ icon: h,
103
+ strokeWidth: 2,
104
+ className: m(j.favorited && "fill-current text-destructive")
105
+ }),
106
+ b && /* @__PURE__ */ f("span", { children: B }),
107
+ R !== void 0 && /* @__PURE__ */ f("span", {
108
+ className: "tabular-nums text-muted-foreground",
109
+ children: y(Math.max(0, R), O.language)
110
+ })
111
+ ]
112
+ }),
113
+ /* @__PURE__ */ f("span", {
114
+ className: "sr-only",
115
+ role: "status",
116
+ children: I
117
+ }),
118
+ P && /* @__PURE__ */ f("span", {
119
+ role: "alert",
120
+ className: "text-xs text-destructive",
121
+ children: s(O, P)
122
+ })
123
+ ]
124
+ });
125
+ }
126
+ //#endregion
127
+ export { x as FavoriteButton, b as ReactionButtons };
128
+
129
+ //# sourceMappingURL=engagement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engagement.js","names":[],"sources":["../../../src/components/social/engagement.tsx"],"sourcesContent":["import { FavouriteIcon, ThumbsDownIcon, ThumbsUpIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useContext, useState } from \"react\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { ContentKitError } from \"../../client/errors.js\";\nimport { toContentKitError } from \"../../client/errors.js\";\nimport type { ReactionCounts, RefBody } from \"../../client/generated/wire.js\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext, useErrorReporter, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useContentConfig } from \"../../react/config.js\";\nimport { useFavorite, useReaction } from \"../../react/engagement.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { contentError } from \"./parts.js\";\n\n\nconst compact = (n: number, language?: string) => new Intl.NumberFormat(language, { notation: \"compact\", maximumFractionDigits: 1 }).format(n);\n\nexport interface ReactionButtonsProps {\n item: RefBody;\n /** Counts the host already has, used instead of reading them. */\n counts?: ReactionCounts;\n /** Offer dislike too. Default true. */\n dislike?: boolean;\n /** Asks a signed-out visitor to sign in where the server takes no anonymous reactions (default the provider's). */\n onSignIn?: () => void;\n size?: \"sm\" | \"default\";\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/**\n * Like and dislike toggles with counts: they change at once and roll back if\n * the server refuses. Signed out, they react anonymously where the server\n * allows it (`Config.anonymous.reactions`) and ask to sign in elsewhere.\n */\nexport function ReactionButtons({ item, counts: initial, dislike = true, onSignIn, size = \"default\", client, onError, className, appearance }: ReactionButtonsProps) {\n const m = useMessages();\n const { t } = m;\n const r = useReaction(item, { initial, client });\n const ctx = useContext(ContentKitContext);\n const { config } = useContentConfig({ client });\n const signIn = onSignIn ?? ctx?.onSignIn;\n // Signed out where the server takes no anonymous reactions.\n const mustSignIn = ctx?.viewer === null && config?.anonymous.reactions === false;\n const report = useErrorReporter(onError);\n const [error, setError] = useState<ContentKitError | null>(null);\n const toggle = (v: 1 | -1) => {\n if (mustSignIn) return signIn?.();\n setError(null);\n r.toggle(v).catch((e) => {\n const err = toContentKitError(e);\n if (err.code === \"unauthorized\" && signIn) return signIn();\n setError(err);\n report(err, \"reaction.save\");\n });\n };\n const btn = size === \"sm\" ? \"sm\" : \"default\";\n const hint = mustSignIn ? t(\"reactions.signIn\") : undefined;\n const disabled = mustSignIn && !signIn;\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"inline-flex flex-wrap items-center gap-1 text-sm\", className)} data-ckui=\"reaction-buttons\">\n <div className=\"inline-flex items-center gap-1\">\n <Button variant={r.counts.mine === 1 ? \"secondary\" : \"ghost\"} size={btn} aria-pressed={r.counts.mine === 1} aria-label={t(\"reactions.like\")} title={hint} disabled={disabled} onClick={() => toggle(1)}>\n <HugeiconsIcon icon={ThumbsUpIcon} strokeWidth={2} />\n <span>{compact(r.counts.likes, m.language)}</span>\n </Button>\n {dislike && (\n <Button variant={r.counts.mine === -1 ? \"secondary\" : \"ghost\"} size={btn} aria-pressed={r.counts.mine === -1} aria-label={t(\"reactions.dislike\")} title={hint} disabled={disabled} onClick={() => toggle(-1)}>\n <HugeiconsIcon icon={ThumbsDownIcon} strokeWidth={2} />\n <span>{compact(r.counts.dislikes, m.language)}</span>\n </Button>\n )}\n </div>\n {error && (\n <span role=\"alert\" className=\"text-xs text-destructive\">\n {error.code === \"rate_limited\" || error.code === \"forbidden\" ? contentError(m, error) : t(\"reactions.failed\")}\n </span>\n )}\n </ContentKitUiRoot>\n );\n}\n\nexport interface FavoriteButtonProps {\n item: RefBody;\n /** Whether it is favorited and the item's count, as the host already has them: both given, nothing is read. */\n favorited?: boolean;\n count?: number;\n /** Show the item's favorite count. Default true. */\n showCount?: boolean;\n /** Show the label beside the icon. Default true. */\n label?: boolean;\n /** Asks a signed-out visitor to sign in (default the provider's). */\n onSignIn?: () => void;\n /** After each saved change. */\n onChange?: (favorited: boolean) => void;\n size?: \"sm\" | \"default\";\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** Adds the item to the signed-in visitor's favorites, or removes it, with the server's count; changes at once and rolls back if refused. */\nexport function FavoriteButton({ item, favorited, count, showCount = true, label = true, onSignIn, onChange, size = \"default\", client, onError, className, appearance }: FavoriteButtonProps) {\n const m = useMessages();\n const { t } = m;\n const ctx = useContext(ContentKitContext);\n const f = useFavorite(item, { initial: favorited !== undefined && count !== undefined ? { favorited, count } : undefined, client });\n const signIn = onSignIn ?? ctx?.onSignIn;\n const report = useErrorReporter(onError);\n const [error, setError] = useState<ContentKitError | null>(null);\n const [status, setStatus] = useState(\"\");\n const shown = showCount ? f.count : undefined;\n const click = () => {\n if (ctx?.viewer === null) return signIn?.();\n setError(null);\n const next = !f.favorited;\n f.set(next).then(\n () => {\n setStatus(t(next ? \"favorites.added\" : \"favorites.removed\"));\n onChange?.(next);\n },\n (e) => {\n const err = toContentKitError(e);\n if (err.code === \"unauthorized\" && signIn) return signIn();\n setError(err);\n report(err, \"favorite.save\");\n },\n );\n };\n const text = t(ctx?.viewer === null && signIn ? \"favorites.signIn\" : f.favorited ? \"favorites.remove\" : \"favorites.add\");\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"inline-flex flex-wrap items-center gap-2 text-sm\", className)} data-ckui=\"favorite-button\">\n <Button\n variant={f.favorited ? \"secondary\" : \"outline\"}\n size={label ? (size === \"sm\" ? \"sm\" : \"default\") : size === \"sm\" ? \"icon-sm\" : \"icon\"}\n aria-pressed={f.favorited}\n aria-label={label ? undefined : text}\n disabled={f.pending}\n onClick={click}\n >\n <HugeiconsIcon icon={FavouriteIcon} strokeWidth={2} className={cn(f.favorited && \"fill-current text-destructive\")} />\n {label && <span>{text}</span>}\n {shown !== undefined && <span className=\"tabular-nums text-muted-foreground\">{compact(Math.max(0, shown), m.language)}</span>}\n </Button>\n <span className=\"sr-only\" role=\"status\">\n {status}\n </span>\n {error && (\n <span role=\"alert\" className=\"text-xs text-destructive\">\n {contentError(m, error)}\n </span>\n )}\n </ContentKitUiRoot>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { Comments, type CommentsProps } from './comments.js';
2
+ export { BanNotice, CommentBanDialog, CommentBans, type CommentBanDialogProps, type CommentBansProps } from './bans.js';
3
+ export { FavoriteButton, ReactionButtons, type FavoriteButtonProps, type ReactionButtonsProps } from './engagement.js';
4
+ export { Poll, type PollProps } from './poll.js';
5
+ export { PollEditor, type PollEditorProps } from './poll-editor.js';
6
+ export { CommentModeration, type CommentModerationProps, type ModerationSection } from './moderation.js';
@@ -0,0 +1,32 @@
1
+ import { ContentKitClient } from '../../client/client.js';
2
+ import { PublicUser } from '../../client/generated/wire.js';
3
+ import { ContentKitUiAppearance } from '../../appearance.js';
4
+ import { ContentKitErrorHandler } from '../../react/context.js';
5
+ export type ModerationSection = "comments" | "queue" | "bans";
6
+ export interface CommentModerationProps {
7
+ /** Content kinds offered as a filter of the comment list: codes, or codes with labels. */
8
+ contentKinds?: readonly (string | {
9
+ value: string;
10
+ label: string;
11
+ })[];
12
+ /** A link to a commented item. */
13
+ itemHref?: (item: {
14
+ kind: string;
15
+ id: string;
16
+ }) => string | undefined;
17
+ userHref?: (user: PublicUser) => string | undefined;
18
+ /** The sections, in order. Default all: every comment, the review queue, the site's bans. */
19
+ sections?: readonly ModerationSection[];
20
+ pageSize?: number;
21
+ client?: ContentKitClient;
22
+ onError?: ContentKitErrorHandler;
23
+ className?: string;
24
+ appearance?: ContentKitUiAppearance;
25
+ }
26
+ /**
27
+ * Staff: every comment (deleted, held and rejected ones with their text) to
28
+ * delete, restore or ban its author; the review queue of held comments and
29
+ * posts to approve or reject; and the site's comment bans. Each section
30
+ * shows what the caller's permissions allow and says so when they don't.
31
+ */
32
+ export declare function CommentModeration({ sections, className, appearance, ...p }: CommentModerationProps): import('react').JSX.Element;
@@ -0,0 +1,383 @@
1
+ import { toContentKitError as e } from "../../client/errors.js";
2
+ import { useMessages as t } from "../../i18n/context.js";
3
+ import { ContentKitUiRoot as n } from "../../scope.js";
4
+ import { useErrorReporter as r } from "../../react/context.js";
5
+ import { Button as i } from "../../ui/button.js";
6
+ import { useAdminComments as a, useModerationQueue as o } from "../../react/comments.js";
7
+ import { Badge as s } from "../../ui/badge.js";
8
+ import { Input as c } from "../../ui/input.js";
9
+ import { Select as l, SelectContent as u, SelectItem as d, SelectTrigger as f, SelectValue as p } from "../../ui/select.js";
10
+ import { Skeleton as m } from "../../ui/skeleton.js";
11
+ import { ErrorLine as h, RelativeTime as g, UserAvatar as _, UserName as v, contentError as y } from "./parts.js";
12
+ import { CommentBanDialog as b, CommentBans as x } from "./bans.js";
13
+ import { Tabs as S, TabsContent as C, TabsList as w, TabsTrigger as T } from "../../ui/tabs.js";
14
+ import { useMemo as E, useState as D } from "react";
15
+ import { jsx as O, jsxs as k } from "react/jsx-runtime";
16
+ import { cn as A } from "cn";
17
+ //#region src/components/social/moderation.tsx
18
+ function j({ sections: e = [
19
+ "comments",
20
+ "queue",
21
+ "bans"
22
+ ], className: r, appearance: i, ...a }) {
23
+ let { t: o } = t(), [s, c] = D(e[0] ?? "comments"), l = {
24
+ comments: o("moderation.all"),
25
+ queue: o("moderation.queue"),
26
+ bans: o("moderation.bans")
27
+ };
28
+ return /* @__PURE__ */ k(n, {
29
+ appearance: i,
30
+ className: A("grid gap-4 text-sm", r),
31
+ "data-ckui": "comment-moderation",
32
+ children: [/* @__PURE__ */ O("h2", {
33
+ className: "text-base font-semibold",
34
+ children: o("moderation.title")
35
+ }), /* @__PURE__ */ k(S, {
36
+ value: s,
37
+ onValueChange: (e) => c(e),
38
+ children: [
39
+ e.length > 1 && /* @__PURE__ */ O(w, { children: e.map((e) => /* @__PURE__ */ O(T, {
40
+ value: e,
41
+ children: l[e]
42
+ }, e)) }),
43
+ e.includes("comments") && /* @__PURE__ */ O(C, {
44
+ value: "comments",
45
+ className: "pt-3",
46
+ children: /* @__PURE__ */ O(N, { ...a })
47
+ }),
48
+ e.includes("queue") && /* @__PURE__ */ O(C, {
49
+ value: "queue",
50
+ className: "pt-3",
51
+ children: /* @__PURE__ */ O(P, { ...a })
52
+ }),
53
+ e.includes("bans") && /* @__PURE__ */ O(C, {
54
+ value: "bans",
55
+ className: "pt-3",
56
+ children: /* @__PURE__ */ O(x, {
57
+ scope: "global",
58
+ pageSize: a.pageSize,
59
+ userHref: a.userHref,
60
+ client: a.client,
61
+ onError: a.onError
62
+ })
63
+ })
64
+ ]
65
+ })]
66
+ });
67
+ }
68
+ function M(e) {
69
+ return e.deleted ? "deleted" : e.moderation === "held" ? "held" : e.moderation === "rejected" ? "rejected" : "published";
70
+ }
71
+ function N(n) {
72
+ let { t: o } = t(), c = E(() => (n.contentKinds ?? []).map((e) => typeof e == "string" ? {
73
+ value: e,
74
+ label: e
75
+ } : e), [n.contentKinds]), [m, y] = D(""), x = a({
76
+ contentKind: m,
77
+ pageSize: n.pageSize,
78
+ client: n.client
79
+ }), S = r(n.onError), [C, w] = D(null), [T, j] = D(null), N = (t, n) => {
80
+ w(null), n().catch((n) => {
81
+ let r = e(n);
82
+ w(r), S(r, t);
83
+ });
84
+ };
85
+ return /* @__PURE__ */ k("div", {
86
+ className: "grid gap-3",
87
+ children: [
88
+ c.length > 0 && /* @__PURE__ */ k(l, {
89
+ value: m,
90
+ onValueChange: (e) => y(String(e ?? "")),
91
+ children: [/* @__PURE__ */ O(f, {
92
+ size: "sm",
93
+ "aria-label": o("moderation.kind"),
94
+ children: /* @__PURE__ */ O(p, { children: (e) => e ? c.find((t) => t.value === e)?.label ?? e : o("moderation.allKinds") })
95
+ }), /* @__PURE__ */ k(u, { children: [/* @__PURE__ */ O(d, {
96
+ value: "",
97
+ children: o("moderation.allKinds")
98
+ }), c.map((e) => /* @__PURE__ */ O(d, {
99
+ value: e.value,
100
+ children: e.label
101
+ }, e.value))] })]
102
+ }),
103
+ /* @__PURE__ */ O(h, { error: C }),
104
+ /* @__PURE__ */ O(I, {
105
+ loading: x.loading,
106
+ error: x.error,
107
+ empty: o("moderation.empty"),
108
+ count: x.items.length,
109
+ reload: x.reload,
110
+ children: x.items.map((e) => {
111
+ let t = e.author?.username ?? e.anon_name ?? e.user_id ?? o("comments.anonymous"), r = M(e), a = n.itemHref?.({
112
+ kind: e.content_kind,
113
+ id: e.content_id
114
+ });
115
+ return /* @__PURE__ */ k("li", {
116
+ className: "grid gap-2 p-3",
117
+ "data-ckui": "admin-comment",
118
+ "data-status": r,
119
+ children: [
120
+ /* @__PURE__ */ k("div", {
121
+ className: "flex flex-wrap items-center gap-x-2 gap-y-1",
122
+ children: [
123
+ /* @__PURE__ */ O(_, {
124
+ user: e.author,
125
+ name: t,
126
+ size: "sm"
127
+ }),
128
+ /* @__PURE__ */ O(v, {
129
+ user: e.author,
130
+ name: t,
131
+ href: n.userHref
132
+ }),
133
+ /* @__PURE__ */ O(g, {
134
+ at: e.created_at,
135
+ className: "text-xs text-muted-foreground"
136
+ }),
137
+ /* @__PURE__ */ O(s, {
138
+ variant: r === "published" ? "outline" : r === "held" ? "secondary" : "destructive",
139
+ children: o(`moderation.${r}`)
140
+ }),
141
+ e.reply_to_id && /* @__PURE__ */ O(s, {
142
+ variant: "outline",
143
+ children: o("moderation.reply")
144
+ }),
145
+ /* @__PURE__ */ k("span", {
146
+ className: "text-xs text-muted-foreground",
147
+ children: [
148
+ o("moderation.on"),
149
+ " ",
150
+ a ? /* @__PURE__ */ k("a", {
151
+ className: "hover:underline",
152
+ href: a,
153
+ children: [
154
+ e.content_kind,
155
+ "/",
156
+ e.content_id
157
+ ]
158
+ }) : `${e.content_kind}/${e.content_id}`
159
+ ]
160
+ })
161
+ ]
162
+ }),
163
+ /* @__PURE__ */ O("p", {
164
+ className: A("line-clamp-4 break-words whitespace-pre-wrap", e.deleted && "text-muted-foreground line-through"),
165
+ children: e.body
166
+ }),
167
+ e.moderation_reason && /* @__PURE__ */ O("p", {
168
+ className: "text-xs text-muted-foreground",
169
+ children: o("moderation.heldBecause", { reason: e.moderation_reason })
170
+ }),
171
+ /* @__PURE__ */ k("div", {
172
+ className: "flex flex-wrap gap-2",
173
+ children: [e.deleted ? /* @__PURE__ */ O(i, {
174
+ size: "sm",
175
+ variant: "outline",
176
+ onClick: () => N("comment.restore", () => x.restore(e.id)),
177
+ children: o("moderation.restore")
178
+ }) : /* @__PURE__ */ O(i, {
179
+ size: "sm",
180
+ variant: "destructive",
181
+ onClick: () => N("comment.delete", () => x.remove(e.id)),
182
+ children: o("moderation.delete")
183
+ }), e.user_id && /* @__PURE__ */ O(i, {
184
+ size: "sm",
185
+ variant: "ghost",
186
+ onClick: () => j({
187
+ id: e.user_id,
188
+ name: t
189
+ }),
190
+ children: o("comments.ban")
191
+ })]
192
+ })
193
+ ]
194
+ }, e.id);
195
+ })
196
+ }),
197
+ x.hasMore && /* @__PURE__ */ O(i, {
198
+ variant: "outline",
199
+ className: "justify-self-center",
200
+ disabled: x.loadingMore,
201
+ onClick: () => void x.loadMore(),
202
+ children: o("moderation.loadMore")
203
+ }),
204
+ T && /* @__PURE__ */ O(b, {
205
+ open: !0,
206
+ onOpenChange: (e) => !e && j(null),
207
+ user: T,
208
+ scopes: ["global"],
209
+ client: n.client,
210
+ onError: n.onError
211
+ })
212
+ ]
213
+ });
214
+ }
215
+ function P(e) {
216
+ let { t: n } = t(), [r, a] = D("comment"), s = o({
217
+ kind: r,
218
+ pageSize: e.pageSize,
219
+ client: e.client
220
+ });
221
+ return /* @__PURE__ */ k("div", {
222
+ className: "grid gap-3",
223
+ children: [
224
+ /* @__PURE__ */ O("div", {
225
+ className: "flex gap-2",
226
+ role: "group",
227
+ "aria-label": n("moderation.queue"),
228
+ children: ["comment", "post"].map((e) => /* @__PURE__ */ O(i, {
229
+ size: "sm",
230
+ variant: r === e ? "default" : "outline",
231
+ "aria-pressed": r === e,
232
+ onClick: () => a(e),
233
+ children: n(e === "post" ? "moderation.queuePosts" : "moderation.queueComments")
234
+ }, e))
235
+ }),
236
+ /* @__PURE__ */ O(I, {
237
+ loading: s.loading,
238
+ error: s.error,
239
+ empty: n("moderation.queueEmpty"),
240
+ count: s.items.length,
241
+ reload: s.reload,
242
+ children: s.items.map((t) => /* @__PURE__ */ O(F, {
243
+ item: t,
244
+ itemHref: e.itemHref,
245
+ userHref: e.userHref,
246
+ onResolve: s.resolve,
247
+ reload: s.reload,
248
+ onError: e.onError
249
+ }, t.id))
250
+ }),
251
+ s.hasMore && /* @__PURE__ */ O(i, {
252
+ variant: "outline",
253
+ className: "justify-self-center",
254
+ disabled: s.loadingMore,
255
+ onClick: () => void s.loadMore(),
256
+ children: n("moderation.loadMore")
257
+ })
258
+ ]
259
+ });
260
+ }
261
+ function F(n) {
262
+ let a = t(), { t: o } = a, s = r(n.onError), { item: l } = n, [u, d] = D(!1), [f, p] = D(""), [m, b] = D(!1), [x, S] = D(null), C = l.author?.username ?? l.anon_name ?? l.author_id ?? o("comments.anonymous"), w = n.itemHref?.({
263
+ kind: l.ref.content_kind,
264
+ id: l.ref.content_id
265
+ }), T = async (t) => {
266
+ b(!0), S(null);
267
+ try {
268
+ await n.onResolve(l, t, t === "reject" && f.trim() || void 0);
269
+ } catch (t) {
270
+ let r = e(t);
271
+ s(r, "moderation.resolve"), r.code === "not_found" || r.code === "conflict" ? (S(o("moderation.stale")), n.reload()) : S(y(a, r));
272
+ } finally {
273
+ b(!1);
274
+ }
275
+ };
276
+ return /* @__PURE__ */ k("li", {
277
+ className: "grid gap-2 p-3",
278
+ "data-ckui": "held-item",
279
+ children: [
280
+ /* @__PURE__ */ k("div", {
281
+ className: "flex flex-wrap items-center gap-x-2 gap-y-1",
282
+ children: [
283
+ /* @__PURE__ */ O(_, {
284
+ user: l.author,
285
+ name: C,
286
+ size: "sm"
287
+ }),
288
+ /* @__PURE__ */ O(v, {
289
+ user: l.author,
290
+ name: C,
291
+ href: n.userHref
292
+ }),
293
+ /* @__PURE__ */ O(g, {
294
+ at: l.held_at,
295
+ className: "text-xs text-muted-foreground"
296
+ }),
297
+ w && /* @__PURE__ */ k("a", {
298
+ className: "text-xs text-muted-foreground hover:underline",
299
+ href: w,
300
+ children: [
301
+ o("moderation.on"),
302
+ " ",
303
+ l.ref.content_kind,
304
+ "/",
305
+ l.ref.content_id
306
+ ]
307
+ })
308
+ ]
309
+ }),
310
+ l.title && /* @__PURE__ */ O("p", {
311
+ className: "font-medium",
312
+ children: l.title
313
+ }),
314
+ /* @__PURE__ */ O("p", {
315
+ className: "line-clamp-6 break-words whitespace-pre-wrap",
316
+ children: l.body
317
+ }),
318
+ (l.reason || l.error) && /* @__PURE__ */ O("p", {
319
+ className: "text-xs text-muted-foreground",
320
+ children: o("moderation.heldBecause", { reason: l.reason || l.error || "" })
321
+ }),
322
+ u && /* @__PURE__ */ O(c, {
323
+ value: f,
324
+ maxLength: 500,
325
+ placeholder: o("moderation.rejectReason"),
326
+ "aria-label": o("moderation.rejectReason"),
327
+ onChange: (e) => p(e.target.value),
328
+ autoFocus: !0
329
+ }),
330
+ /* @__PURE__ */ k("div", {
331
+ className: "flex flex-wrap gap-2",
332
+ children: [
333
+ /* @__PURE__ */ O(i, {
334
+ size: "sm",
335
+ disabled: m,
336
+ onClick: () => void T("approve"),
337
+ children: o("moderation.approve")
338
+ }),
339
+ /* @__PURE__ */ O(i, {
340
+ size: "sm",
341
+ variant: "destructive",
342
+ disabled: m,
343
+ onClick: () => u ? void T("reject") : d(!0),
344
+ children: o("moderation.reject")
345
+ }),
346
+ u && /* @__PURE__ */ O(i, {
347
+ size: "sm",
348
+ variant: "ghost",
349
+ onClick: () => d(!1),
350
+ children: o("common.cancel")
351
+ })
352
+ ]
353
+ }),
354
+ x && /* @__PURE__ */ O(h, { children: x })
355
+ ]
356
+ });
357
+ }
358
+ function I(e) {
359
+ let n = t(), { t: r } = n;
360
+ return e.loading && !e.count ? /* @__PURE__ */ k("div", {
361
+ className: "grid gap-3",
362
+ "aria-busy": !0,
363
+ children: [/* @__PURE__ */ O(m, { className: "h-16 w-full" }), /* @__PURE__ */ O(m, { className: "h-16 w-full" })]
364
+ }) : e.error && !e.count ? /* @__PURE__ */ k("div", {
365
+ className: "grid justify-items-start gap-2",
366
+ children: [/* @__PURE__ */ O(h, { children: e.error.code === "forbidden" || e.error.code === "unauthorized" ? y(n, e.error) : r("moderation.loadFailed") }), /* @__PURE__ */ O(i, {
367
+ size: "sm",
368
+ variant: "outline",
369
+ onClick: e.reload,
370
+ children: r("common.retry")
371
+ })]
372
+ }) : e.count ? /* @__PURE__ */ O("ul", {
373
+ className: "grid divide-y divide-border rounded-lg border border-border",
374
+ children: e.children
375
+ }) : /* @__PURE__ */ O("p", {
376
+ className: "text-muted-foreground",
377
+ children: e.empty
378
+ });
379
+ }
380
+ //#endregion
381
+ export { j as CommentModeration };
382
+
383
+ //# sourceMappingURL=moderation.js.map