@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 @@
1
+ {"version":3,"file":"provider.js","names":[],"sources":["../src/provider.tsx"],"sourcesContent":["import { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport type { ContentKitUiAppearance } from \"./appearance.js\";\nimport { DEFAULT_DENSITY, type DensityRange } from \"./client/rendition.js\";\nimport { DensityContext } from \"./components/rendition-img.js\";\nimport { MessagesContext } from \"./i18n/context.js\";\nimport { createTranslator, resolveMessages, type ContentKitUiMessageBundle, type ContentKitUiTranslate } from \"./i18n/messages.js\";\nimport { InlinePreviewContext } from \"./react/inline-preview.js\";\nimport { AppearanceContext } from \"./scope.js\";\n\n/** Built-in bundles besides English, loaded on demand. */\nconst BUNDLES: Record<string, () => Promise<ContentKitUiMessageBundle>> = {\n de: () => import(\"./locales/de.js\").then((m) => m.de),\n es: () => import(\"./locales/es.js\").then((m) => m.es),\n ja: () => import(\"./locales/ja.js\").then((m) => m.ja),\n ko: () => import(\"./locales/ko.js\").then((m) => m.ko),\n zh: () => import(\"./locales/zh.js\").then((m) => m.zh),\n};\n\n/** The built-in bundle's language for a BCP 47 tag (\"ja-JP\" → \"ja\"); undefined for English or one we lack. */\nexport function bundleLanguage(language: string | null | undefined): string | undefined {\n const primary = language?.toLowerCase().split(/[-_]/)[0];\n return primary && primary in BUNDLES ? primary : undefined;\n}\n\nexport interface ContentKitUiProviderProps {\n appearance?: ContentKitUiAppearance;\n /** BCP 47 tag; its built-in bundle loads under `messages`. English until it arrives. */\n language?: string;\n /** Bundle(s) layered over English and the language's bundle; later entries win. */\n messages?: ContentKitUiMessageBundle | readonly ContentKitUiMessageBundle[];\n /** Host translation hook, consulted before the bundles. */\n t?: ContentKitUiTranslate;\n /** Device-pixel density range images and covers are picked for. Default [2, 3]. */\n density?: DensityRange;\n /** Playable videos preview muted inline (hover, or in view on touch). Default true. */\n inlinePreview?: boolean;\n children?: ReactNode;\n}\n\n/** Look and language for every component below. Renders no DOM; components create their own `.ckui` roots. */\nexport function ContentKitUiProvider({ appearance, language, messages, t, density = DEFAULT_DENSITY, inlinePreview = true, children }: ContentKitUiProviderProps) {\n const lang = bundleLanguage(language);\n const [loaded, setLoaded] = useState<{ lang: string; bundle: ContentKitUiMessageBundle } | null>(null);\n useEffect(() => {\n if (!lang) return;\n let live = true;\n BUNDLES[lang]!().then(\n (bundle) => live && setLoaded({ lang, bundle }),\n () => {},\n );\n return () => {\n live = false;\n };\n }, [lang]);\n const bundle = lang && loaded?.lang === lang ? loaded.bundle : undefined;\n const translator = useMemo(() => {\n const own = messages ? (Array.isArray(messages) ? messages : [messages]) : [];\n return createTranslator(resolveMessages(bundle ? [bundle, ...own] : own), t, language);\n }, [bundle, messages, t, language]);\n return (\n <AppearanceContext.Provider value={appearance}>\n <MessagesContext.Provider value={translator}>\n <DensityContext.Provider value={density}>\n <InlinePreviewContext.Provider value={inlinePreview}>{children}</InlinePreviewContext.Provider>\n </DensityContext.Provider>\n </MessagesContext.Provider>\n </AppearanceContext.Provider>\n );\n}\n"],"mappings":";;;;;;;;;AAUA,IAAM,IAAoE;CACxE,UAAU,OAAO,kBAAkB,CAAC,MAAM,MAAM,EAAE,EAAE;CACpD,UAAU,OAAO,kBAAkB,CAAC,MAAM,MAAM,EAAE,EAAE;CACpD,UAAU,OAAO,kBAAkB,CAAC,MAAM,MAAM,EAAE,EAAE;CACpD,UAAU,OAAO,kBAAkB,CAAC,MAAM,MAAM,EAAE,EAAE;CACpD,UAAU,OAAO,kBAAkB,CAAC,MAAM,MAAM,EAAE,EAAE;AACtD;AAGA,SAAgB,EAAe,GAAyD;CACtF,IAAM,IAAU,GAAU,YAAY,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC;CACtD,OAAO,KAAW,KAAW,IAAU,IAAU,KAAA;AACnD;AAkBA,SAAgB,EAAqB,EAAE,eAAY,aAAU,aAAU,MAAG,aAAU,GAAiB,mBAAgB,IAAM,eAAuC;CAChK,IAAM,IAAO,EAAe,CAAQ,GAC9B,CAAC,GAAQ,KAAa,EAAqE,IAAI;CACrG,QAAgB;EACd,IAAI,CAAC,GAAM;EACX,IAAI,IAAO;EAKX,OAJA,EAAQ,EAAK,CAAE,CAAC,CAAC,MACd,MAAW,KAAQ,EAAU;GAAE;GAAM;EAAO,CAAC,SACxC,CAAC,CACT,SACa;GACX,IAAO;EACT;CACF,GAAG,CAAC,CAAI,CAAC;CACT,IAAM,IAAS,KAAQ,GAAQ,SAAS,IAAO,EAAO,SAAS,KAAA,GACzD,IAAa,QAAc;EAC/B,IAAM,IAAM,IAAY,MAAM,QAAQ,CAAQ,IAAI,IAAW,CAAC,CAAQ,IAAK,CAAC;EAC5E,OAAO,EAAiB,EAAgB,IAAS,CAAC,GAAQ,GAAG,CAAG,IAAI,CAAG,GAAG,GAAG,CAAQ;CACvF,GAAG;EAAC;EAAQ;EAAU;EAAG;CAAQ,CAAC;CAClC,OACE,kBAAC,EAAkB,UAAnB;EAA4B,OAAO;EACjC,UAAA,kBAAC,EAAgB,UAAjB;GAA0B,OAAO;GAC/B,UAAA,kBAAC,EAAe,UAAhB;IAAyB,OAAO;IAC9B,UAAA,kBAAC,EAAqB,UAAtB;KAA+B,OAAO;KAAgB;IAAwC,CAAA;GACvE,CAAA;EACD,CAAA;CACA,CAAA;AAEhC"}
@@ -0,0 +1,33 @@
1
+ import { ContentLink } from '../urls/index.js';
2
+ export interface CanonicalContentOptions {
3
+ /** og:title. */
4
+ title?: string;
5
+ /** og:image, an absolute URL. */
6
+ image?: string;
7
+ /**
8
+ * The current location (pathname, search, hash). Default
9
+ * window.location; pass the router's so a navigation checks again.
10
+ */
11
+ location?: string;
12
+ /** Languages the content exists in, for hreflang; default every configured language. */
13
+ languages?: readonly string[];
14
+ /** The language hreflang x-default points at. */
15
+ defaultLanguage?: string;
16
+ }
17
+ export interface CanonicalContent {
18
+ /** The canonical path in the page's language; undefined until link arrives. */
19
+ path?: string;
20
+ /** Its absolute URL. */
21
+ url?: string;
22
+ /** hreflang alternates by language (and x-default). */
23
+ alternates: Record<string, string>;
24
+ }
25
+ /**
26
+ * A content page's canonical URL once its data (link) arrives: replaces the
27
+ * address with the canonical path (code spelling, merged code, current slug)
28
+ * through the provider's navigate (else history.replaceState), and keeps
29
+ * `<link rel=canonical>`, og:url, og:title, og:image and hreflang alternates
30
+ * (each language's own slug) in the head while mounted. Needs the
31
+ * provider's `urls`.
32
+ */
33
+ export declare function useCanonicalContent(content: ContentLink | null | undefined, o?: CanonicalContentOptions): CanonicalContent;
@@ -0,0 +1,88 @@
1
+ import { ContentKitContext as e, useContentURLs as t } from "./context.js";
2
+ import { useContext as n, useEffect as r, useMemo as i } from "react";
3
+ //#region src/react/canonical.ts
4
+ var a = (e, t) => ({
5
+ selector: `meta[property="${e}"]`,
6
+ create: () => o(document.createElement("meta"), "property", e),
7
+ attr: "content",
8
+ value: t
9
+ });
10
+ function o(e, t, n) {
11
+ return e.setAttribute(t, n), e;
12
+ }
13
+ var s = (e, t, n) => ({
14
+ selector: n ? `link[rel="${e}"][hreflang="${n}"]` : `link[rel="${e}"]:not([hreflang])`,
15
+ create: () => {
16
+ let t = o(document.createElement("link"), "rel", e);
17
+ return n && t.setAttribute("hreflang", n), t;
18
+ },
19
+ attr: "href",
20
+ value: t
21
+ });
22
+ function c(c, l = {}) {
23
+ let u = t(), d = n(e)?.navigate, f = l.location ?? (typeof location > "u" ? "" : location.pathname + location.search + location.hash), p = c?.content_kind, m = c?.code, h = c?.slug, g = JSON.stringify(c?.slugs ?? {}), _ = l.languages?.join(","), v = i(() => p && m ? {
24
+ content_kind: p,
25
+ code: m,
26
+ slug: h ?? "",
27
+ slugs: JSON.parse(g)
28
+ } : null, [
29
+ p,
30
+ m,
31
+ h,
32
+ g
33
+ ]), y = i(() => {
34
+ if (!v) return { alternates: {} };
35
+ let e = u.origin ?? (typeof location > "u" ? void 0 : location.origin), t = f.includes("#") ? f.slice(f.indexOf("#")) : "", n = u.canonical(f, v), r = n?.path ?? u.path(v), i = e ? u.hreflang(v, {
36
+ origin: e,
37
+ languages: _?.split(","),
38
+ defaultLanguage: l.defaultLanguage
39
+ }) : {};
40
+ return {
41
+ path: r,
42
+ url: e ? e + r : void 0,
43
+ alternates: i,
44
+ redirect: n?.redirect ? n.location + t : void 0
45
+ };
46
+ }, [
47
+ v,
48
+ f,
49
+ u,
50
+ _,
51
+ l.defaultLanguage
52
+ ]), { redirect: b } = y;
53
+ r(() => {
54
+ b && (d ? d(b, { replace: !0 }) : history.replaceState(history.state, "", b));
55
+ }, [b, d]);
56
+ let { url: x, alternates: S } = y, { title: C, image: w } = l, T = JSON.stringify(S);
57
+ return r(() => {
58
+ if (!x || typeof document > "u") return;
59
+ let e = [s("canonical", x), a("og:url", x)];
60
+ C && e.push(a("og:title", C)), w && e.push(a("og:image", w));
61
+ for (let [t, n] of Object.entries(JSON.parse(T))) e.push(s("alternate", n, t));
62
+ let t = [];
63
+ for (let n of e) {
64
+ let e = document.head.querySelector(n.selector);
65
+ if (e) {
66
+ let r = e.getAttribute(n.attr);
67
+ e.setAttribute(n.attr, n.value), t.push(() => r === null ? e.removeAttribute(n.attr) : e.setAttribute(n.attr, r));
68
+ } else {
69
+ let e = o(n.create(), n.attr, n.value);
70
+ document.head.appendChild(e), t.push(() => e.remove());
71
+ }
72
+ }
73
+ return () => t.forEach((e) => e());
74
+ }, [
75
+ x,
76
+ C,
77
+ w,
78
+ T
79
+ ]), {
80
+ path: y.path,
81
+ url: y.url,
82
+ alternates: y.alternates
83
+ };
84
+ }
85
+ //#endregion
86
+ export { c as useCanonicalContent };
87
+
88
+ //# sourceMappingURL=canonical.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.js","names":[],"sources":["../../src/react/canonical.ts"],"sourcesContent":["import { useContext, useEffect, useMemo } from \"react\";\nimport type { ContentLink } from \"../urls/index.js\";\nimport { ContentKitContext, useContentURLs } from \"./context.js\";\n\nexport interface CanonicalContentOptions {\n /** og:title. */\n title?: string;\n /** og:image, an absolute URL. */\n image?: string;\n /**\n * The current location (pathname, search, hash). Default\n * window.location; pass the router's so a navigation checks again.\n */\n location?: string;\n /** Languages the content exists in, for hreflang; default every configured language. */\n languages?: readonly string[];\n /** The language hreflang x-default points at. */\n defaultLanguage?: string;\n}\n\nexport interface CanonicalContent {\n /** The canonical path in the page's language; undefined until link arrives. */\n path?: string;\n /** Its absolute URL. */\n url?: string;\n /** hreflang alternates by language (and x-default). */\n alternates: Record<string, string>;\n}\n\ntype Tag = { selector: string; create: () => HTMLElement; attr: string; value: string };\n\nconst meta = (property: string, value: string): Tag => ({\n selector: `meta[property=\"${property}\"]`,\n create: () => withAttr(document.createElement(\"meta\"), \"property\", property),\n attr: \"content\",\n value,\n});\n\nfunction withAttr<E extends HTMLElement>(el: E, name: string, value: string): E {\n el.setAttribute(name, value);\n return el;\n}\n\nconst link = (rel: string, value: string, hreflang?: string): Tag => ({\n selector: hreflang ? `link[rel=\"${rel}\"][hreflang=\"${hreflang}\"]` : `link[rel=\"${rel}\"]:not([hreflang])`,\n create: () => {\n const el = withAttr(document.createElement(\"link\"), \"rel\", rel);\n if (hreflang) el.setAttribute(\"hreflang\", hreflang);\n return el;\n },\n attr: \"href\",\n value,\n});\n\n/**\n * A content page's canonical URL once its data (link) arrives: replaces the\n * address with the canonical path (code spelling, merged code, current slug)\n * through the provider's navigate (else history.replaceState), and keeps\n * `<link rel=canonical>`, og:url, og:title, og:image and hreflang alternates\n * (each language's own slug) in the head while mounted. Needs the\n * provider's `urls`.\n */\nexport function useCanonicalContent(content: ContentLink | null | undefined, o: CanonicalContentOptions = {}): CanonicalContent {\n const urls = useContentURLs();\n const navigate = useContext(ContentKitContext)?.navigate;\n const at = o.location ?? (typeof location === \"undefined\" ? \"\" : location.pathname + location.search + location.hash);\n const kind = content?.content_kind;\n const code = content?.code;\n const slug = content?.slug;\n const slugs = JSON.stringify(content?.slugs ?? {});\n const languages = o.languages?.join(\",\");\n const lnk = useMemo(\n () => (kind && code ? ({ content_kind: kind, code, slug: slug ?? \"\", slugs: JSON.parse(slugs) as Record<string, string> } satisfies ContentLink) : null),\n [kind, code, slug, slugs],\n );\n\n const result = useMemo((): CanonicalContent & { redirect?: string } => {\n if (!lnk) return { alternates: {} };\n const origin = urls.origin ?? (typeof location === \"undefined\" ? undefined : location.origin);\n const hash = at.includes(\"#\") ? at.slice(at.indexOf(\"#\")) : \"\";\n const c = urls.canonical(at, lnk);\n const path = c?.path ?? urls.path(lnk);\n const alternates = origin ? urls.hreflang(lnk, { origin, languages: languages?.split(\",\"), defaultLanguage: o.defaultLanguage }) : {};\n return { path, url: origin ? origin + path : undefined, alternates, redirect: c?.redirect ? c.location + hash : undefined };\n }, [lnk, at, urls, languages, o.defaultLanguage]);\n\n const { redirect } = result;\n useEffect(() => {\n if (!redirect) return;\n if (navigate) navigate(redirect, { replace: true });\n else history.replaceState(history.state, \"\", redirect);\n }, [redirect, navigate]);\n\n const { url, alternates } = result;\n const { title, image } = o;\n const alternatesKey = JSON.stringify(alternates);\n useEffect(() => {\n if (!url || typeof document === \"undefined\") return;\n const tags: Tag[] = [link(\"canonical\", url), meta(\"og:url\", url)];\n if (title) tags.push(meta(\"og:title\", title));\n if (image) tags.push(meta(\"og:image\", image));\n for (const [lang, href] of Object.entries(JSON.parse(alternatesKey) as Record<string, string>)) tags.push(link(\"alternate\", href, lang));\n const undo: (() => void)[] = [];\n for (const t of tags) {\n const found = document.head.querySelector<HTMLElement>(t.selector);\n if (found) {\n const before = found.getAttribute(t.attr);\n found.setAttribute(t.attr, t.value);\n undo.push(() => (before === null ? found.removeAttribute(t.attr) : found.setAttribute(t.attr, before)));\n } else {\n const el = withAttr(t.create(), t.attr, t.value);\n document.head.appendChild(el);\n undo.push(() => el.remove());\n }\n }\n return () => undo.forEach((u) => u());\n }, [url, title, image, alternatesKey]);\n\n return { path: result.path, url: result.url, alternates: result.alternates };\n}\n"],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import { ContentKitClient } from '../client/client.js';
2
+ import { BanScope, Decision, HeldKind, Reaction, Sort } from '../client/content/types.js';
3
+ import { AdminComment, BanInput, Comment, CommentBan, CommentStanding, FeedItem, HeldItem, ReactionCounts, RefBody } from '../client/generated/wire.js';
4
+ import { UseList } from './use-resource.js';
5
+ /** Counts after the caller's reaction changes from counts.mine to value. */
6
+ export declare function withReaction(counts: ReactionCounts, value: Reaction): ReactionCounts;
7
+ export interface UseCommentsOptions {
8
+ sort?: Sort;
9
+ /** Top-level comments per page. Default 20. */
10
+ pageSize?: number;
11
+ client?: ContentKitClient;
12
+ }
13
+ export interface UseComments extends UseList<Comment> {
14
+ /** Comments on the item, or replies to a top-level comment (replyTo); anonymous callers give anonName. */
15
+ post: (body: string, o?: {
16
+ replyTo?: string;
17
+ anonName?: string;
18
+ }) => Promise<Comment>;
19
+ edit: (id: string, body: string) => Promise<Comment>;
20
+ /** Leaves a tombstone. */
21
+ remove: (id: string) => Promise<void>;
22
+ /** Sets the caller's reaction at once, rolled back if the server refuses it. */
23
+ react: (comment: Comment, value: Reaction) => Promise<void>;
24
+ /** Restores a deleted comment (moderators). */
25
+ restore: (id: string) => Promise<void>;
26
+ }
27
+ /** An item's top-level comments, a page at a time, with every write; new comments and replies land in place. */
28
+ export declare function useComments(ref: RefBody, o?: UseCommentsOptions): UseComments;
29
+ /** A top-level comment's replies, oldest first, a page at a time; enabled false defers the first read. */
30
+ export declare function useCommentReplies(id: string, o?: {
31
+ pageSize?: number;
32
+ enabled?: boolean;
33
+ client?: ContentKitClient;
34
+ }): UseList<Comment>;
35
+ /** Whether the caller may comment on the item, the ban that stops it, and what it may do to others' comments. */
36
+ export declare function useCanComment(ref: RefBody, o?: {
37
+ client?: ContentKitClient;
38
+ }): {
39
+ standing: CommentStanding | null;
40
+ loading: boolean;
41
+ error: import('../client/errors.js').ContentKitError | undefined;
42
+ reload: () => void;
43
+ };
44
+ /** The newest published comments across the site, with their items (the host shows titles). */
45
+ export declare function useLatestComments(o?: {
46
+ pageSize?: number;
47
+ client?: ContentKitClient;
48
+ }): UseList<FeedItem>;
49
+ export interface UseAdminComments extends UseList<AdminComment> {
50
+ remove: (id: string) => Promise<void>;
51
+ restore: (id: string) => Promise<void>;
52
+ react: (comment: Comment, value: Reaction) => Promise<void>;
53
+ }
54
+ /** Staff: every comment, newest first, deleted, held and rejected ones with their bodies (CommentModerate). */
55
+ export declare function useAdminComments(o?: {
56
+ contentKind?: string;
57
+ pageSize?: number;
58
+ client?: ContentKitClient;
59
+ }): UseAdminComments;
60
+ export interface UseModerationQueue extends UseList<HeldItem> {
61
+ /** Approves (publishes) or rejects at the revision the queue listed; the item leaves the queue. */
62
+ resolve: (item: HeldItem, decision: Decision, reason?: string) => Promise<void>;
63
+ }
64
+ /** Staff: held comments or posts awaiting review, oldest first (ModerationReview). */
65
+ export declare function useModerationQueue(o?: {
66
+ kind?: HeldKind;
67
+ pageSize?: number;
68
+ client?: ContentKitClient;
69
+ }): UseModerationQueue;
70
+ export interface UseCommentBans extends UseList<CommentBan & {
71
+ id: string;
72
+ }> {
73
+ ban: (user: string, input?: BanInput) => Promise<CommentBan>;
74
+ lift: (user: string) => Promise<void>;
75
+ }
76
+ /** The bans of one scope: the caller's own ("owner") or the site's ("global", CommentBan), newest first. */
77
+ export declare function useCommentBans(o?: {
78
+ scope?: BanScope;
79
+ pageSize?: number;
80
+ enabled?: boolean;
81
+ client?: ContentKitClient;
82
+ }): UseCommentBans;
@@ -0,0 +1,147 @@
1
+ import { keyOf as e, offsetPages as t, useContentScope as n, useList as r, useResource as i } from "./use-resource.js";
2
+ import { useCallback as a } from "react";
3
+ //#region src/react/comments.ts
4
+ function o(e, t) {
5
+ return {
6
+ likes: e.likes - +(e.mine === 1) + +(t === 1),
7
+ dislikes: e.dislikes - +(e.mine === -1) + +(t === -1),
8
+ mine: t
9
+ };
10
+ }
11
+ var s = [
12
+ "comments",
13
+ "replies",
14
+ "latest",
15
+ "admin-comments"
16
+ ], c = /* @__PURE__ */ new WeakMap();
17
+ async function l(e, t, n, r) {
18
+ let i = c.get(t);
19
+ i || c.set(t, i = /* @__PURE__ */ new Map());
20
+ let a = (i.get(n.id) ?? 0) + 1;
21
+ i.set(n.id, a);
22
+ let l = (e) => t.patch((e) => s.includes(e.type), (t) => ({
23
+ ...t,
24
+ items: t.items.map((t) => t.id === n.id ? {
25
+ ...t,
26
+ ...e
27
+ } : t)
28
+ }));
29
+ l(o({
30
+ likes: n.likes,
31
+ dislikes: n.dislikes,
32
+ mine: n.mine
33
+ }, r));
34
+ try {
35
+ await e.comments.react(n.id, r);
36
+ } catch (e) {
37
+ throw i.get(n.id) === a && l({
38
+ likes: n.likes,
39
+ dislikes: n.dislikes,
40
+ mine: n.mine
41
+ }), e;
42
+ }
43
+ }
44
+ function u(i, o = {}) {
45
+ let { client: s, store: c, viewer: u } = n(o.client), d = o.pageSize ?? 20, f = o.sort ?? "newest", p = e("comments", u, i.kind, i.id, f, d), m = r(c, p, {
46
+ type: "comments",
47
+ ref: {
48
+ kind: i.kind,
49
+ id: i.id
50
+ }
51
+ }, t(d, (e, t) => s.comments.list(i, {
52
+ ...e,
53
+ sort: f
54
+ }, t))), { kind: h, id: g } = i, _ = a((e, t = {}) => s.comments.create({
55
+ kind: h,
56
+ id: g
57
+ }, {
58
+ body: e,
59
+ reply_to_id: t.replyTo,
60
+ anon_name: t.anonName
61
+ }), [
62
+ s,
63
+ h,
64
+ g
65
+ ]), v = a((e, t) => s.comments.edit(e, t), [s]), y = a((e) => s.comments.delete(e), [s]), b = a((e) => s.comments.restore(e), [s]), x = a((e, t) => l(s, c, e, t), [s, c]);
66
+ return {
67
+ ...m,
68
+ post: _,
69
+ edit: v,
70
+ remove: y,
71
+ react: x,
72
+ restore: b
73
+ };
74
+ }
75
+ function d(i, a = {}) {
76
+ let { client: o, store: s, viewer: c } = n(a.client), l = a.pageSize ?? 10, u = a.enabled === !1 ? null : e("replies", c, i, l);
77
+ return r(s, u, {
78
+ type: "replies",
79
+ id: i
80
+ }, t(l, (e, t) => o.comments.replies(i, e, t)));
81
+ }
82
+ function f(t, r = {}) {
83
+ let { client: a, store: o, viewer: s } = n(r.client), c = i(o, e("standing", s, t.kind, t.id), {
84
+ type: "standing",
85
+ ref: {
86
+ kind: t.kind,
87
+ id: t.id
88
+ }
89
+ }, (e) => a.comments.standing(t, e));
90
+ return {
91
+ standing: c.data ?? null,
92
+ loading: c.loading || !c.loaded,
93
+ error: c.error,
94
+ reload: c.reload
95
+ };
96
+ }
97
+ function p(i = {}) {
98
+ let { client: a, store: o, viewer: s } = n(i.client), c = i.pageSize ?? 20;
99
+ return r(o, e("latest", s, c), { type: "latest" }, t(c, (e, t) => a.comments.latest(e, t), !0));
100
+ }
101
+ function m(i = {}) {
102
+ let { client: o, store: s, viewer: c } = n(i.client), u = i.pageSize ?? 25, d = i.contentKind || void 0, f = r(s, e("admin-comments", c, d, u), { type: "admin-comments" }, t(u, (e, t) => o.comments.adminList({
103
+ ...e,
104
+ contentKind: d
105
+ }, t))), p = a((e) => o.comments.delete(e), [o]), m = a((e) => o.comments.restore(e), [o]), h = a((e, t) => l(o, s, e, t), [o, s]);
106
+ return {
107
+ ...f,
108
+ remove: p,
109
+ restore: m,
110
+ react: h
111
+ };
112
+ }
113
+ function h(t = {}) {
114
+ let { client: i, store: o, viewer: s } = n(t.client), c = t.kind ?? "comment", l = t.pageSize ?? 20, u = r(o, e("held", s, c, l), { type: "held" }, async (e, t) => {
115
+ let n = await i.moderation.held({
116
+ kind: c,
117
+ cursor: typeof e == "string" ? e : void 0,
118
+ limit: l
119
+ }, t);
120
+ return {
121
+ items: n.items,
122
+ next: n.next ?? null
123
+ };
124
+ }), d = a(async (e, t, n) => void await i.moderation.resolve(e, t, n), [i]);
125
+ return {
126
+ ...u,
127
+ resolve: d
128
+ };
129
+ }
130
+ function g(i = {}) {
131
+ let { client: o, store: s, viewer: c } = n(i.client), l = i.scope ?? "global", u = i.pageSize ?? 25, d = r(s, i.enabled === !1 ? null : e("bans", c, l, u), {
132
+ type: "bans",
133
+ scope: l
134
+ }, t(u, async (e, t) => (await o.bans.list(l, e, t)).map((e) => ({
135
+ ...e,
136
+ id: e.user_id
137
+ })))), f = a((e, t) => o.bans.ban(l, e, t), [o, l]), p = a((e) => o.bans.lift(l, e), [o, l]);
138
+ return {
139
+ ...d,
140
+ ban: f,
141
+ lift: p
142
+ };
143
+ }
144
+ //#endregion
145
+ export { m as useAdminComments, f as useCanComment, g as useCommentBans, d as useCommentReplies, u as useComments, p as useLatestComments, h as useModerationQueue, o as withReaction };
146
+
147
+ //# sourceMappingURL=comments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comments.js","names":[],"sources":["../../src/react/comments.ts"],"sourcesContent":["import { useCallback } from \"react\";\nimport type { ContentKitClient } from \"../client/client.js\";\nimport type { BanScope, Decision, HeldKind, Reaction, Sort } from \"../client/content/types.js\";\nimport type { AdminComment, BanInput, Comment, CommentBan, CommentStanding, FeedItem, HeldItem, ReactionCounts, RefBody } from \"../client/generated/wire.js\";\nimport type { ResourceStore } from \"./resources.js\";\nimport { keyOf, offsetPages, useContentScope, useList, useResource, type UseList } from \"./use-resource.js\";\n\n/** Counts after the caller's reaction changes from counts.mine to value. */\nexport function withReaction(counts: ReactionCounts, value: Reaction): ReactionCounts {\n const likes = counts.likes - (counts.mine === 1 ? 1 : 0) + (value === 1 ? 1 : 0);\n const dislikes = counts.dislikes - (counts.mine === -1 ? 1 : 0) + (value === -1 ? 1 : 0);\n return { likes, dislikes, mine: value };\n}\n\nconst commentLists = [\"comments\", \"replies\", \"latest\", \"admin-comments\"];\nconst tokens = new WeakMap<ResourceStore, Map<string, number>>();\n\n/** Sets the caller's reaction to a comment in every list showing it at once; rolls back on failure unless a newer one started. */\nasync function reactToComment(client: ContentKitClient, store: ResourceStore, c: Pick<Comment, \"id\" | \"likes\" | \"dislikes\" | \"mine\">, value: Reaction) {\n let t = tokens.get(store);\n if (!t) tokens.set(store, (t = new Map()));\n const token = (t.get(c.id) ?? 0) + 1;\n t.set(c.id, token);\n const put = (counts: ReactionCounts) =>\n store.patch<{ items: Comment[]; next: unknown }>(\n (tag) => commentLists.includes(tag.type),\n (page) => ({ ...page, items: page.items.map((x) => (x.id === c.id ? { ...x, ...counts } : x)) }),\n );\n put(withReaction({ likes: c.likes, dislikes: c.dislikes, mine: c.mine }, value));\n try {\n await client.comments.react(c.id, value);\n } catch (e) {\n if (t.get(c.id) === token) put({ likes: c.likes, dislikes: c.dislikes, mine: c.mine });\n throw e;\n }\n}\n\nexport interface UseCommentsOptions {\n sort?: Sort;\n /** Top-level comments per page. Default 20. */\n pageSize?: number;\n client?: ContentKitClient;\n}\n\nexport interface UseComments extends UseList<Comment> {\n /** Comments on the item, or replies to a top-level comment (replyTo); anonymous callers give anonName. */\n post: (body: string, o?: { replyTo?: string; anonName?: string }) => Promise<Comment>;\n edit: (id: string, body: string) => Promise<Comment>;\n /** Leaves a tombstone. */\n remove: (id: string) => Promise<void>;\n /** Sets the caller's reaction at once, rolled back if the server refuses it. */\n react: (comment: Comment, value: Reaction) => Promise<void>;\n /** Restores a deleted comment (moderators). */\n restore: (id: string) => Promise<void>;\n}\n\n/** An item's top-level comments, a page at a time, with every write; new comments and replies land in place. */\nexport function useComments(ref: RefBody, o: UseCommentsOptions = {}): UseComments {\n const { client, store, viewer } = useContentScope(o.client);\n const size = o.pageSize ?? 20;\n const sort = o.sort ?? \"newest\";\n const key = keyOf(\"comments\", viewer, ref.kind, ref.id, sort, size);\n const list = useList(store, key, { type: \"comments\", ref: { kind: ref.kind, id: ref.id } }, offsetPages(size, (q, signal) => client.comments.list(ref, { ...q, sort }, signal)));\n const { kind, id } = ref;\n const post = useCallback<UseComments[\"post\"]>(\n (body, p = {}) => client.comments.create({ kind, id }, { body, reply_to_id: p.replyTo, anon_name: p.anonName }),\n [client, kind, id],\n );\n const edit = useCallback((cid: string, body: string) => client.comments.edit(cid, body), [client]);\n const remove = useCallback((cid: string) => client.comments.delete(cid), [client]);\n const restore = useCallback((cid: string) => client.comments.restore(cid), [client]);\n const react = useCallback((c: Comment, v: Reaction) => reactToComment(client, store, c, v), [client, store]);\n return { ...list, post, edit, remove, react, restore };\n}\n\n/** A top-level comment's replies, oldest first, a page at a time; enabled false defers the first read. */\nexport function useCommentReplies(id: string, o: { pageSize?: number; enabled?: boolean; client?: ContentKitClient } = {}): UseList<Comment> {\n const { client, store, viewer } = useContentScope(o.client);\n const size = o.pageSize ?? 10;\n const key = o.enabled === false ? null : keyOf(\"replies\", viewer, id, size);\n return useList(store, key, { type: \"replies\", id }, offsetPages(size, (q, signal) => client.comments.replies(id, q, signal)));\n}\n\n/** Whether the caller may comment on the item, the ban that stops it, and what it may do to others' comments. */\nexport function useCanComment(ref: RefBody, o: { client?: ContentKitClient } = {}) {\n const { client, store, viewer } = useContentScope(o.client);\n const r = useResource<CommentStanding>(store, keyOf(\"standing\", viewer, ref.kind, ref.id), { type: \"standing\", ref: { kind: ref.kind, id: ref.id } }, (s) =>\n client.comments.standing(ref, s),\n );\n return { standing: r.data ?? null, loading: r.loading || !r.loaded, error: r.error, reload: r.reload };\n}\n\n/** The newest published comments across the site, with their items (the host shows titles). */\nexport function useLatestComments(o: { pageSize?: number; client?: ContentKitClient } = {}): UseList<FeedItem> {\n const { client, store, viewer } = useContentScope(o.client);\n const size = o.pageSize ?? 20;\n return useList(store, keyOf(\"latest\", viewer, size), { type: \"latest\" }, offsetPages(size, (q, signal) => client.comments.latest(q, signal), true));\n}\n\nexport interface UseAdminComments extends UseList<AdminComment> {\n remove: (id: string) => Promise<void>;\n restore: (id: string) => Promise<void>;\n react: (comment: Comment, value: Reaction) => Promise<void>;\n}\n\n/** Staff: every comment, newest first, deleted, held and rejected ones with their bodies (CommentModerate). */\nexport function useAdminComments(o: { contentKind?: string; pageSize?: number; client?: ContentKitClient } = {}): UseAdminComments {\n const { client, store, viewer } = useContentScope(o.client);\n const size = o.pageSize ?? 25;\n const kind = o.contentKind || undefined;\n const list = useList(\n store,\n keyOf(\"admin-comments\", viewer, kind, size),\n { type: \"admin-comments\" },\n offsetPages(size, (q, signal) => client.comments.adminList({ ...q, contentKind: kind }, signal)),\n );\n const remove = useCallback((id: string) => client.comments.delete(id), [client]);\n const restore = useCallback((id: string) => client.comments.restore(id), [client]);\n const react = useCallback((c: Comment, v: Reaction) => reactToComment(client, store, c, v), [client, store]);\n return { ...list, remove, restore, react };\n}\n\nexport interface UseModerationQueue extends UseList<HeldItem> {\n /** Approves (publishes) or rejects at the revision the queue listed; the item leaves the queue. */\n resolve: (item: HeldItem, decision: Decision, reason?: string) => Promise<void>;\n}\n\n/** Staff: held comments or posts awaiting review, oldest first (ModerationReview). */\nexport function useModerationQueue(o: { kind?: HeldKind; pageSize?: number; client?: ContentKitClient } = {}): UseModerationQueue {\n const { client, store, viewer } = useContentScope(o.client);\n const kind = o.kind ?? \"comment\";\n const size = o.pageSize ?? 20;\n const list = useList<HeldItem>(store, keyOf(\"held\", viewer, kind, size), { type: \"held\" }, async (cursor, signal) => {\n const page = await client.moderation.held({ kind, cursor: typeof cursor === \"string\" ? cursor : undefined, limit: size }, signal);\n return { items: page.items, next: page.next ?? null };\n });\n const resolve = useCallback(async (item: HeldItem, d: Decision, reason?: string) => void (await client.moderation.resolve(item, d, reason)), [client]);\n return { ...list, resolve };\n}\n\nexport interface UseCommentBans extends UseList<CommentBan & { id: string }> {\n ban: (user: string, input?: BanInput) => Promise<CommentBan>;\n lift: (user: string) => Promise<void>;\n}\n\n/** The bans of one scope: the caller's own (\"owner\") or the site's (\"global\", CommentBan), newest first. */\nexport function useCommentBans(o: { scope?: BanScope; pageSize?: number; enabled?: boolean; client?: ContentKitClient } = {}): UseCommentBans {\n const { client, store, viewer } = useContentScope(o.client);\n const scope = o.scope ?? \"global\";\n const size = o.pageSize ?? 25;\n const list = useList(\n store,\n o.enabled === false ? null : keyOf(\"bans\", viewer, scope, size),\n { type: \"bans\", scope },\n offsetPages(size, async (q, signal) => (await client.bans.list(scope, q, signal)).map((b) => ({ ...b, id: b.user_id }))),\n );\n const ban = useCallback((user: string, input?: BanInput) => client.bans.ban(scope, user, input), [client, scope]);\n const lift = useCallback((user: string) => client.bans.lift(scope, user), [client, scope]);\n return { ...list, ban, lift };\n}\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { ContentKitClient } from '../client/client.js';
2
+ import { ContentKitError } from '../client/errors.js';
3
+ import { Config } from '../client/generated/wire.js';
4
+ export interface UseContentConfig {
5
+ /** null until it loads (or when it fails). */
6
+ config: Config | null;
7
+ loading: boolean;
8
+ error?: ContentKitError;
9
+ }
10
+ /** What the content module allows (client.config()): one read per client, whoever the viewer is. */
11
+ export declare function useContentConfig(o?: {
12
+ client?: ContentKitClient;
13
+ }): UseContentConfig;
@@ -0,0 +1,14 @@
1
+ import { keyOf as e, useContentScope as t, useResource as n } from "./use-resource.js";
2
+ //#region src/react/config.ts
3
+ function r(r = {}) {
4
+ let { client: i, store: a } = t(r.client), o = n(a, e("config"), { type: "config" }, (e) => i.config(e));
5
+ return {
6
+ config: o.data ?? null,
7
+ loading: o.loading || !o.loaded,
8
+ error: o.error
9
+ };
10
+ }
11
+ //#endregion
12
+ export { r as useContentConfig };
13
+
14
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","names":[],"sources":["../../src/react/config.ts"],"sourcesContent":["import type { ContentKitClient } from \"../client/client.js\";\nimport type { ContentKitError } from \"../client/errors.js\";\nimport type { Config } from \"../client/generated/wire.js\";\nimport { keyOf, useContentScope, useResource } from \"./use-resource.js\";\n\nexport interface UseContentConfig {\n /** null until it loads (or when it fails). */\n config: Config | null;\n loading: boolean;\n error?: ContentKitError;\n}\n\n/** What the content module allows (client.config()): one read per client, whoever the viewer is. */\nexport function useContentConfig(o: { client?: ContentKitClient } = {}): UseContentConfig {\n const { client, store } = useContentScope(o.client);\n const r = useResource<Config>(store, keyOf(\"config\"), { type: \"config\" }, (s) => client.config(s));\n return { config: r.data ?? null, loading: r.loading || !r.loaded, error: r.error };\n}\n"],"mappings":";;AAaA,SAAgB,EAAiB,IAAmC,CAAC,GAAqB;CACxF,IAAM,EAAE,WAAQ,aAAU,EAAgB,EAAE,MAAM,GAC5C,IAAI,EAAoB,GAAO,EAAM,QAAQ,GAAG,EAAE,MAAM,SAAS,IAAI,MAAM,EAAO,OAAO,CAAC,CAAC;CACjG,OAAO;EAAE,QAAQ,EAAE,QAAQ;EAAM,SAAS,EAAE,WAAW,CAAC,EAAE;EAAQ,OAAO,EAAE;CAAM;AACnF"}
@@ -0,0 +1,48 @@
1
+ import { ContentKitClient } from '../client/client.js';
2
+ import { ContentKitError } from '../client/errors.js';
3
+ import { ContentURLs } from '../urls/index.js';
4
+ import { ReadStore } from './store.js';
5
+ /** What failed: a component's or hook's save, load or render step. */
6
+ export type ContentKitOperation = "poster.load" | "poster.frame" | "poster.save" | "slot.load" | "slot.decode" | "slot.save" | "slot.remove" | "upload" | "folder.load" | "folder.commit" | "folder.update" | "folder.process" | "crop.load" | "crop.save" | SocialOperation;
7
+ /** What failed in a content component: a load or a write. */
8
+ export type SocialOperation = "comment.load" | "comment.post" | "comment.edit" | "comment.delete" | "comment.react" | "comment.restore" | "ban.save" | "ban.lift" | "reaction.save" | "favorite.save" | "poll.load" | "poll.vote" | "poll.answer" | "poll.save" | "post.load" | "post.save" | "moderation.load" | "moderation.resolve";
9
+ /** The failure's context: the operation and, for one file, its name. */
10
+ export interface ContentKitErrorInfo {
11
+ operation: ContentKitOperation;
12
+ file?: string;
13
+ }
14
+ /**
15
+ * Every failure a component shows is also reported here (aborts excepted), so
16
+ * the host can toast or log it. Components still show it in place.
17
+ */
18
+ export type ContentKitErrorHandler = (error: ContentKitError, info: ContentKitErrorInfo) => void;
19
+ /** The host router: in-app navigation, e.g. a canonical replace. */
20
+ export type Navigate = (to: string, options?: {
21
+ replace?: boolean;
22
+ }) => void;
23
+ export interface ContentKitContextValue {
24
+ client: ContentKitClient;
25
+ /**
26
+ * The signed-in user's id as ContentKit sees it, null when signed out,
27
+ * undefined when the host does not say. Content reads are kept per viewer.
28
+ */
29
+ viewer?: string | null;
30
+ /** Asks the visitor to sign in; with it, signed-out visitors are prompted instead of acting anonymously. */
31
+ onSignIn?: () => void;
32
+ /** The host's content URL config (createContentURLs). */
33
+ urls?: ContentURLs;
34
+ navigate?: Navigate;
35
+ onError?: ContentKitErrorHandler;
36
+ /** The reads hooks share. */
37
+ store: ReadStore;
38
+ }
39
+ export declare const ContentKitContext: import('react').Context<ContentKitContextValue | null>;
40
+ /** The ContentKitProvider's value; throws outside one. */
41
+ export declare function useContentKit(): ContentKitContextValue;
42
+ /** The client a hook or component uses: its own, else the provider's; throws without either. */
43
+ export declare function useContentKitClient(own?: ContentKitClient | null): ContentKitClient;
44
+ export declare function useOptionalContentKitClient(own?: ContentKitClient | null): ContentKitClient | null;
45
+ /** The provider's content URL helpers; throws when none were given. */
46
+ export declare function useContentURLs(): ContentURLs;
47
+ /** A stable reporter: the component's own `onError`, else the provider's. */
48
+ export declare function useErrorReporter(own?: ContentKitErrorHandler): (e: unknown, operation: ContentKitOperation, file?: string) => void;
@@ -0,0 +1,37 @@
1
+ import { toContentKitError as e } from "../client/errors.js";
2
+ import { createContext as t, useCallback as n, useContext as r, useRef as i } from "react";
3
+ //#region src/react/context.ts
4
+ var a = t(null);
5
+ function o() {
6
+ let e = r(a);
7
+ if (!e) throw Error("contentkit-ui: wrap the tree in <ContentKitProvider client>");
8
+ return e;
9
+ }
10
+ function s(e) {
11
+ let t = c(e);
12
+ if (!t) throw Error("contentkit-ui: pass `client` or render inside <ContentKitProvider client>");
13
+ return t;
14
+ }
15
+ function c(e) {
16
+ let t = r(a);
17
+ return e ?? t?.client ?? null;
18
+ }
19
+ function l() {
20
+ let e = r(a)?.urls;
21
+ if (!e) throw Error("contentkit-ui: pass `urls` to <ContentKitProvider>");
22
+ return e;
23
+ }
24
+ function u(t) {
25
+ let o = r(a)?.onError, s = i(t ?? o);
26
+ return s.current = t ?? o, n((t, n, r) => {
27
+ let i = e(t);
28
+ i.code !== "aborted" && s.current?.(i, r === void 0 ? { operation: n } : {
29
+ operation: n,
30
+ file: r
31
+ });
32
+ }, []);
33
+ }
34
+ //#endregion
35
+ export { a as ContentKitContext, o as useContentKit, s as useContentKitClient, l as useContentURLs, u as useErrorReporter, c as useOptionalContentKitClient };
36
+
37
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","names":[],"sources":["../../src/react/context.ts"],"sourcesContent":["import { createContext, useCallback, useContext, useRef } from \"react\";\nimport type { ContentKitClient } from \"../client/client.js\";\nimport { toContentKitError, type ContentKitError } from \"../client/errors.js\";\nimport type { ContentURLs } from \"../urls/index.js\";\nimport type { ReadStore } from \"./store.js\";\n\n/** What failed: a component's or hook's save, load or render step. */\nexport type ContentKitOperation =\n | \"poster.load\"\n | \"poster.frame\"\n | \"poster.save\"\n | \"slot.load\"\n | \"slot.decode\"\n | \"slot.save\"\n | \"slot.remove\"\n | \"upload\"\n | \"folder.load\"\n | \"folder.commit\"\n | \"folder.update\"\n | \"folder.process\"\n | \"crop.load\"\n | \"crop.save\"\n | SocialOperation;\n\n/** What failed in a content component: a load or a write. */\nexport type SocialOperation =\n | \"comment.load\"\n | \"comment.post\"\n | \"comment.edit\"\n | \"comment.delete\"\n | \"comment.react\"\n | \"comment.restore\"\n | \"ban.save\"\n | \"ban.lift\"\n | \"reaction.save\"\n | \"favorite.save\"\n | \"poll.load\"\n | \"poll.vote\"\n | \"poll.answer\"\n | \"poll.save\"\n | \"post.load\"\n | \"post.save\"\n | \"moderation.load\"\n | \"moderation.resolve\";\n\n/** The failure's context: the operation and, for one file, its name. */\nexport interface ContentKitErrorInfo {\n operation: ContentKitOperation;\n file?: string;\n}\n\n/**\n * Every failure a component shows is also reported here (aborts excepted), so\n * the host can toast or log it. Components still show it in place.\n */\nexport type ContentKitErrorHandler = (error: ContentKitError, info: ContentKitErrorInfo) => void;\n\n/** The host router: in-app navigation, e.g. a canonical replace. */\nexport type Navigate = (to: string, options?: { replace?: boolean }) => void;\n\nexport interface ContentKitContextValue {\n client: ContentKitClient;\n /**\n * The signed-in user's id as ContentKit sees it, null when signed out,\n * undefined when the host does not say. Content reads are kept per viewer.\n */\n viewer?: string | null;\n /** Asks the visitor to sign in; with it, signed-out visitors are prompted instead of acting anonymously. */\n onSignIn?: () => void;\n /** The host's content URL config (createContentURLs). */\n urls?: ContentURLs;\n navigate?: Navigate;\n onError?: ContentKitErrorHandler;\n /** The reads hooks share. */\n store: ReadStore;\n}\n\nexport const ContentKitContext = createContext<ContentKitContextValue | null>(null);\n\n/** The ContentKitProvider's value; throws outside one. */\nexport function useContentKit(): ContentKitContextValue {\n const ctx = useContext(ContentKitContext);\n if (!ctx) throw new Error(\"contentkit-ui: wrap the tree in <ContentKitProvider client>\");\n return ctx;\n}\n\n/** The client a hook or component uses: its own, else the provider's; throws without either. */\nexport function useContentKitClient(own?: ContentKitClient | null): ContentKitClient {\n const c = useOptionalContentKitClient(own);\n if (!c) throw new Error(\"contentkit-ui: pass `client` or render inside <ContentKitProvider client>\");\n return c;\n}\n\nexport function useOptionalContentKitClient(own?: ContentKitClient | null): ContentKitClient | null {\n const ctx = useContext(ContentKitContext);\n return own ?? ctx?.client ?? null;\n}\n\n/** The provider's content URL helpers; throws when none were given. */\nexport function useContentURLs(): ContentURLs {\n const urls = useContext(ContentKitContext)?.urls;\n if (!urls) throw new Error(\"contentkit-ui: pass `urls` to <ContentKitProvider>\");\n return urls;\n}\n\n/** A stable reporter: the component's own `onError`, else the provider's. */\nexport function useErrorReporter(own?: ContentKitErrorHandler): (e: unknown, operation: ContentKitOperation, file?: string) => void {\n const ctx = useContext(ContentKitContext)?.onError;\n const handler = useRef(own ?? ctx);\n handler.current = own ?? ctx;\n return useCallback((e: unknown, operation: ContentKitOperation, file?: string) => {\n const error = toContentKitError(e);\n if (error.code !== \"aborted\") handler.current?.(error, file === undefined ? { operation } : { operation, file });\n }, []);\n}\n"],"mappings":";;;AA6EA,IAAa,IAAoB,EAA6C,IAAI;AAGlF,SAAgB,IAAwC;CACtD,IAAM,IAAM,EAAW,CAAiB;CACxC,IAAI,CAAC,GAAK,MAAU,MAAM,6DAA6D;CACvF,OAAO;AACT;AAGA,SAAgB,EAAoB,GAAiD;CACnF,IAAM,IAAI,EAA4B,CAAG;CACzC,IAAI,CAAC,GAAG,MAAU,MAAM,2EAA2E;CACnG,OAAO;AACT;AAEA,SAAgB,EAA4B,GAAwD;CAClG,IAAM,IAAM,EAAW,CAAiB;CACxC,OAAO,KAAO,GAAK,UAAU;AAC/B;AAGA,SAAgB,IAA8B;CAC5C,IAAM,IAAO,EAAW,CAAiB,CAAC,EAAE;CAC5C,IAAI,CAAC,GAAM,MAAU,MAAM,oDAAoD;CAC/E,OAAO;AACT;AAGA,SAAgB,EAAiB,GAAmG;CAClI,IAAM,IAAM,EAAW,CAAiB,CAAC,EAAE,SACrC,IAAU,EAAO,KAAO,CAAG;CAEjC,OADA,EAAQ,UAAU,KAAO,GAClB,GAAa,GAAY,GAAgC,MAAkB;EAChF,IAAM,IAAQ,EAAkB,CAAC;EACjC,AAAI,EAAM,SAAS,aAAW,EAAQ,UAAU,GAAO,MAAS,KAAA,IAAY,EAAE,aAAU,IAAI;GAAE;GAAW;EAAK,CAAC;CACjH,GAAG,CAAC,CAAC;AACP"}
@@ -0,0 +1,49 @@
1
+ import { ContentKitClient } from '../client/client.js';
2
+ import { ContentKitError } from '../client/errors.js';
3
+ import { Edit, FileInfo, RefBody } from '../client/generated/wire.js';
4
+ import { CropSource } from '../client/image.js';
5
+ import { ContentKitErrorHandler } from './context.js';
6
+ export interface EditorCropOptions {
7
+ /** save() also waits until the worker rendered the edit. Default false (an editor read shows it processing). */
8
+ wait?: boolean;
9
+ /** With the item's uploads after each save. */
10
+ onSaved?: (files: FileInfo[]) => void;
11
+ /** Every failed load or save; default the provider's. */
12
+ onError?: ContentKitErrorHandler;
13
+ /** Overrides the provider's client. */
14
+ client?: ContentKitClient;
15
+ }
16
+ /** source is the upload's editor view and its oriented size; edit its current edit. */
17
+ export type EditorCropState = {
18
+ status: "idle";
19
+ } | {
20
+ status: "loading";
21
+ } | {
22
+ status: "cropping";
23
+ source: CropSource;
24
+ edit: Edit | null;
25
+ } | {
26
+ status: "saving";
27
+ source: CropSource;
28
+ edit: Edit | null;
29
+ } | {
30
+ status: "done";
31
+ files: FileInfo[];
32
+ } | {
33
+ status: "error";
34
+ error: ContentKitError;
35
+ source?: CropSource;
36
+ edit?: Edit | null;
37
+ };
38
+ export type UseEditorCrop = EditorCropState & {
39
+ /** Commits the edit (null removes it); resolves with the item's uploads, or undefined on failure. */
40
+ save: (edit: Edit | null) => Promise<FileInfo[] | undefined>;
41
+ /** Loads the editor view again after a failure. */
42
+ retry: () => void;
43
+ };
44
+ /**
45
+ * Re-crops a kept upload: while path is set, its editor view (the original,
46
+ * oriented, unedited) loads for a cropper; save() commits an edit op. Nothing
47
+ * is uploaded. Clear path to close.
48
+ */
49
+ export declare function useEditorCrop(ref: RefBody, path: string | null | undefined, o?: EditorCropOptions): UseEditorCrop;