convex-cms 0.0.3 → 0.0.5-alpha.2

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 (375) hide show
  1. package/README.md +107 -60
  2. package/admin/README.md +99 -0
  3. package/admin/src/components/AdminLayout.tsx +22 -0
  4. package/admin/src/components/BreakingChangesWarningDialog.tsx +81 -0
  5. package/admin/src/components/BulkActionBar.tsx +190 -0
  6. package/admin/src/components/BulkOperationModal.tsx +177 -0
  7. package/admin/src/components/ContentEntryEditor.tsx +1104 -0
  8. package/admin/src/components/ContentTypeFormModal.tsx +1012 -0
  9. package/admin/src/components/ErrorBoundary.tsx +83 -0
  10. package/admin/src/components/ErrorState.tsx +147 -0
  11. package/admin/src/components/Header.tsx +294 -0
  12. package/admin/src/components/RouteGuard.tsx +264 -0
  13. package/admin/src/components/Sidebar.tsx +90 -0
  14. package/admin/src/components/TaxonomyEditor.tsx +348 -0
  15. package/admin/src/components/TermTree.tsx +533 -0
  16. package/admin/src/components/UploadDropzone.tsx +383 -0
  17. package/admin/src/components/VersionCompare.tsx +250 -0
  18. package/admin/src/components/VersionHistory.tsx +279 -0
  19. package/admin/src/components/VersionRollbackModal.tsx +79 -0
  20. package/admin/src/components/cmsds/CmsButton.tsx +101 -0
  21. package/admin/src/components/cmsds/CmsDialog.tsx +139 -0
  22. package/admin/src/components/cmsds/CmsDropdown.tsx +62 -0
  23. package/admin/src/components/cmsds/CmsEmptyState.tsx +54 -0
  24. package/admin/src/components/cmsds/CmsField.tsx +47 -0
  25. package/admin/src/components/cmsds/CmsPageHeader.tsx +35 -0
  26. package/admin/src/components/cmsds/CmsStatusBadge.tsx +153 -0
  27. package/admin/src/components/cmsds/CmsSurface.tsx +52 -0
  28. package/admin/src/components/cmsds/CmsTable.tsx +164 -0
  29. package/admin/src/components/cmsds/CmsToolbar.tsx +58 -0
  30. package/admin/src/components/cmsds/index.ts +10 -0
  31. package/admin/src/components/fields/BooleanField.tsx +74 -0
  32. package/admin/src/components/fields/CategoryField.tsx +394 -0
  33. package/admin/src/components/fields/DateField.tsx +173 -0
  34. package/admin/src/components/fields/DefaultFieldRenderer.tsx +74 -0
  35. package/admin/src/components/fields/FieldRenderer.tsx +180 -0
  36. package/admin/src/components/fields/FieldWrapper.tsx +57 -0
  37. package/admin/src/components/fields/JsonField.tsx +172 -0
  38. package/admin/src/components/fields/MediaField.tsx +367 -0
  39. package/admin/src/components/fields/MultiSelectField.tsx +118 -0
  40. package/admin/src/components/fields/NumberField.tsx +77 -0
  41. package/admin/src/components/fields/ReferenceField.tsx +386 -0
  42. package/admin/src/components/fields/RichTextField.tsx +171 -0
  43. package/admin/src/components/fields/SelectField.tsx +62 -0
  44. package/admin/src/components/fields/TagField.tsx +325 -0
  45. package/admin/src/components/fields/TextAreaField.tsx +68 -0
  46. package/admin/src/components/fields/TextField.tsx +56 -0
  47. package/admin/src/components/fields/index.ts +54 -0
  48. package/admin/src/components/fields/registry.ts +64 -0
  49. package/admin/src/components/fields/types.ts +217 -0
  50. package/admin/src/components/filters/TaxonomyFilter.tsx +254 -0
  51. package/admin/src/components/filters/index.ts +1 -0
  52. package/admin/src/components/index.ts +8 -0
  53. package/admin/src/components/media/MediaAssetActions.tsx +115 -0
  54. package/admin/src/components/media/MediaAssetEditDialog.tsx +217 -0
  55. package/admin/src/components/media/MediaBulkActionBar.tsx +51 -0
  56. package/admin/src/components/media/MediaFolderActions.tsx +69 -0
  57. package/admin/src/components/media/MediaFolderEditDialog.tsx +126 -0
  58. package/admin/src/components/media/MediaMoveModal.tsx +179 -0
  59. package/admin/src/components/media/MediaPreviewModal.tsx +370 -0
  60. package/admin/src/components/media/MediaTaxonomyPicker.tsx +304 -0
  61. package/admin/src/components/media/MediaTrashBulkActionBar.tsx +59 -0
  62. package/admin/src/components/ui/accordion.tsx +64 -0
  63. package/admin/src/components/ui/alert-dialog.tsx +155 -0
  64. package/admin/src/components/ui/alert.tsx +66 -0
  65. package/admin/src/components/ui/avatar.tsx +53 -0
  66. package/admin/src/components/ui/badge.tsx +46 -0
  67. package/admin/src/components/ui/breadcrumb.tsx +109 -0
  68. package/admin/src/components/ui/button.tsx +62 -0
  69. package/admin/src/components/ui/calendar.tsx +220 -0
  70. package/admin/src/components/ui/card.tsx +92 -0
  71. package/admin/src/components/ui/checkbox.tsx +30 -0
  72. package/admin/src/components/ui/command.tsx +182 -0
  73. package/admin/src/components/ui/dialog.tsx +143 -0
  74. package/admin/src/components/ui/dropdown-menu.tsx +257 -0
  75. package/admin/src/components/ui/form.tsx +167 -0
  76. package/admin/src/components/ui/input.tsx +21 -0
  77. package/admin/src/components/ui/label.tsx +24 -0
  78. package/admin/src/components/ui/popover.tsx +46 -0
  79. package/admin/src/components/ui/scroll-area.tsx +56 -0
  80. package/admin/src/components/ui/select.tsx +190 -0
  81. package/admin/src/components/ui/separator.tsx +26 -0
  82. package/admin/src/components/ui/sheet.tsx +137 -0
  83. package/admin/src/components/ui/sidebar.tsx +724 -0
  84. package/admin/src/components/ui/skeleton.tsx +13 -0
  85. package/admin/src/components/ui/sonner.tsx +38 -0
  86. package/admin/src/components/ui/switch.tsx +31 -0
  87. package/admin/src/components/ui/table.tsx +114 -0
  88. package/admin/src/components/ui/tabs.tsx +66 -0
  89. package/admin/src/components/ui/textarea.tsx +18 -0
  90. package/admin/src/components/ui/tooltip.tsx +61 -0
  91. package/admin/src/contexts/AdminConfigContext.tsx +30 -0
  92. package/admin/src/contexts/AuthContext.tsx +330 -0
  93. package/admin/src/contexts/BreadcrumbContext.tsx +49 -0
  94. package/admin/src/contexts/SettingsConfigContext.tsx +57 -0
  95. package/admin/src/contexts/ThemeContext.tsx +91 -0
  96. package/admin/src/contexts/index.ts +20 -0
  97. package/admin/src/embed/components/EmbedHeader.tsx +103 -0
  98. package/admin/src/embed/components/EmbedLayout.tsx +29 -0
  99. package/admin/src/embed/components/EmbedSidebar.tsx +119 -0
  100. package/admin/src/embed/components/index.ts +3 -0
  101. package/admin/src/embed/contexts/ApiContext.tsx +32 -0
  102. package/admin/src/embed/index.tsx +184 -0
  103. package/admin/src/embed/navigation.tsx +202 -0
  104. package/admin/src/embed/pages/Content.tsx +19 -0
  105. package/admin/src/embed/pages/ContentTypes.tsx +19 -0
  106. package/admin/src/embed/pages/Dashboard.tsx +19 -0
  107. package/admin/src/embed/pages/Media.tsx +19 -0
  108. package/admin/src/embed/pages/Settings.tsx +22 -0
  109. package/admin/src/embed/pages/Taxonomies.tsx +22 -0
  110. package/admin/src/embed/pages/Trash.tsx +22 -0
  111. package/admin/src/embed/pages/index.ts +7 -0
  112. package/admin/src/embed/types.ts +24 -0
  113. package/admin/src/hooks/index.ts +2 -0
  114. package/admin/src/hooks/use-mobile.ts +19 -0
  115. package/admin/src/hooks/useBreadcrumbLabel.ts +15 -0
  116. package/admin/src/hooks/usePermissions.ts +211 -0
  117. package/admin/src/lib/admin-config.ts +111 -0
  118. package/admin/src/lib/cn.ts +6 -0
  119. package/admin/src/lib/config.server.ts +56 -0
  120. package/admin/src/lib/convex.ts +26 -0
  121. package/admin/src/lib/embed-adapter.ts +80 -0
  122. package/admin/src/lib/icons.tsx +96 -0
  123. package/admin/src/lib/loadAdminConfig.ts +92 -0
  124. package/admin/src/lib/motion.ts +29 -0
  125. package/admin/src/lib/navigation.ts +43 -0
  126. package/admin/src/lib/tanstack-adapter.ts +82 -0
  127. package/admin/src/pages/ContentPage.tsx +337 -0
  128. package/admin/src/pages/ContentTypesPage.tsx +457 -0
  129. package/admin/src/pages/DashboardPage.tsx +163 -0
  130. package/admin/src/pages/MediaPage.tsx +34 -0
  131. package/admin/src/pages/SettingsPage.tsx +486 -0
  132. package/admin/src/pages/TaxonomiesPage.tsx +289 -0
  133. package/admin/src/pages/TrashPage.tsx +421 -0
  134. package/admin/src/pages/index.ts +14 -0
  135. package/admin/src/routeTree.gen.ts +262 -0
  136. package/admin/src/router.tsx +22 -0
  137. package/admin/src/routes/__root.tsx +250 -0
  138. package/admin/src/routes/content-types.tsx +20 -0
  139. package/admin/src/routes/content.tsx +20 -0
  140. package/admin/src/routes/entries/$entryId.tsx +107 -0
  141. package/admin/src/routes/entries/new.$contentTypeId.tsx +69 -0
  142. package/admin/src/routes/entries/type/$contentTypeId.tsx +503 -0
  143. package/admin/src/routes/index.tsx +20 -0
  144. package/admin/src/routes/media.tsx +1095 -0
  145. package/admin/src/routes/settings.tsx +20 -0
  146. package/admin/src/routes/taxonomies.tsx +20 -0
  147. package/admin/src/routes/trash.tsx +20 -0
  148. package/admin/src/styles/globals.css +69 -0
  149. package/admin/src/styles/tailwind-config.css +74 -0
  150. package/admin/src/styles/theme.css +73 -0
  151. package/admin/src/types/index.ts +221 -0
  152. package/admin/src/utils/errorParsing.ts +163 -0
  153. package/admin/src/utils/index.ts +5 -0
  154. package/admin/src/vite-env.d.ts +14 -0
  155. package/admin/tailwind.preset.cjs +102 -0
  156. package/admin-dist/nitro.json +1 -1
  157. package/admin-dist/public/assets/{CmsEmptyState-CRswfTzk.js → CmsEmptyState-CkqBIab3.js} +2 -2
  158. package/admin-dist/public/assets/{CmsPageHeader-CirpXndm.js → CmsPageHeader-CUtl5MMG.js} +1 -1
  159. package/admin-dist/public/assets/{CmsStatusBadge-CbEUpQu-.js → CmsStatusBadge-CUYFgEe-.js} +1 -1
  160. package/admin-dist/public/assets/CmsSurface-CsJfAVa3.js +1 -0
  161. package/admin-dist/public/assets/{CmsToolbar-BI2nZOXp.js → CmsToolbar-CnfbcxeP.js} +1 -1
  162. package/admin-dist/public/assets/{ContentEntryEditor-CBeCyK_m.js → ContentEntryEditor-BU220CCy.js} +1 -1
  163. package/admin-dist/public/assets/TaxonomyFilter-CWCxC5HZ.js +1 -0
  164. package/admin-dist/public/assets/_contentTypeId-DK8cskRt.js +1 -0
  165. package/admin-dist/public/assets/{_entryId-CKU_glsK.js → _entryId-CuVMExbb.js} +1 -1
  166. package/admin-dist/public/assets/alert-CF1BSzGR.js +1 -0
  167. package/admin-dist/public/assets/{badge-hvUOzpVZ.js → badge-CmuOIVKp.js} +1 -1
  168. package/admin-dist/public/assets/{circle-check-big-CF_pR17r.js → circle-check-big-BKDVG6DU.js} +1 -1
  169. package/admin-dist/public/assets/{command-DU82cJlt.js → command-XJxnF2Sd.js} +1 -1
  170. package/admin-dist/public/assets/content-QBUxdxbS.js +1 -0
  171. package/admin-dist/public/assets/content-types-CrNEm8Hf.js +2 -0
  172. package/admin-dist/public/assets/globals-B7Wsfh_v.css +1 -0
  173. package/admin-dist/public/assets/index-C7xOwudI.js +1 -0
  174. package/admin-dist/public/assets/{label-KNtpL71g.js → label-CHCnXeBk.js} +1 -1
  175. package/admin-dist/public/assets/{link-2-Bw2aI4V4.js → link-2-Bb34judH.js} +1 -1
  176. package/admin-dist/public/assets/{list-sYepHjt_.js → list-9Pzt48ld.js} +1 -1
  177. package/admin-dist/public/assets/{main-CKj5yfEi.js → main-CjQ2VI9L.js} +3 -3
  178. package/admin-dist/public/assets/media-Dc5PWt2Q.js +1 -0
  179. package/admin-dist/public/assets/{new._contentTypeId-C3LstjNs.js → new._contentTypeId-C_I4YxIa.js} +1 -1
  180. package/admin-dist/public/assets/{plus-DUn8v_Xf.js → plus-Ceef7DHk.js} +1 -1
  181. package/admin-dist/public/assets/{rotate-ccw-DJEoHcRI.js → rotate-ccw-7k7-4VUq.js} +1 -1
  182. package/admin-dist/public/assets/scroll-area-CC6wujnp.js +1 -0
  183. package/admin-dist/public/assets/{search-MuAUDJKR.js → search-DwoUV2pv.js} +1 -1
  184. package/admin-dist/public/assets/select-hOZTp8aC.js +1 -0
  185. package/admin-dist/public/assets/settings-t2PbCZh4.js +1 -0
  186. package/admin-dist/public/assets/switch-jX2pDaNU.js +1 -0
  187. package/admin-dist/public/assets/tabs-q4EbZk7c.js +1 -0
  188. package/admin-dist/public/assets/tanstack-adapter-B-Glm4kH.js +1 -0
  189. package/admin-dist/public/assets/taxonomies-kyk5P4ZW.js +1 -0
  190. package/admin-dist/public/assets/{textarea-BTy7nwzR.js → textarea-B6SfBmr0.js} +1 -1
  191. package/admin-dist/public/assets/trash-BOCnIznD.js +1 -0
  192. package/admin-dist/public/assets/{triangle-alert-E52Vfeuh.js → triangle-alert-CXFIO_Gu.js} +1 -1
  193. package/admin-dist/public/assets/useBreadcrumbLabel-_6qBagc3.js +1 -0
  194. package/admin-dist/public/assets/{usePermissions-Basjs9BT.js → usePermissions-M1ijZ7a6.js} +1 -1
  195. package/admin-dist/server/_chunks/_libs/@tanstack/react-router.mjs +7 -0
  196. package/admin-dist/server/_ssr/{badge-6BsP37vG.mjs → CmsButton-DOiTVKQq.mjs} +33 -33
  197. package/admin-dist/server/_ssr/{CmsEmptyState-DU7-7-mV.mjs → CmsEmptyState-fbnGt3LD.mjs} +2 -2
  198. package/admin-dist/server/_ssr/{CmsPageHeader-CseW0AHm.mjs → CmsPageHeader-DHRrdOZa.mjs} +1 -1
  199. package/admin-dist/server/_ssr/{CmsStatusBadge-B_pi4KCp.mjs → CmsStatusBadge-s7obWbKZ.mjs} +2 -2
  200. package/admin-dist/server/_ssr/CmsSurface-rFoYjb62.mjs +44 -0
  201. package/admin-dist/server/_ssr/{CmsToolbar-X75ex6ek.mjs → CmsToolbar-zTE45z2q.mjs} +2 -2
  202. package/admin-dist/server/_ssr/{ContentEntryEditor-CepusRsA.mjs → ContentEntryEditor-BLoEjT_m.mjs} +12 -12
  203. package/admin-dist/server/_ssr/{TaxonomyFilter-Bwrq0-cz.mjs → TaxonomyFilter-XAtaJC2z.mjs} +5 -5
  204. package/admin-dist/server/_ssr/{_contentTypeId-BqYKEcLr.mjs → _contentTypeId-Csl4822C.mjs} +13 -13
  205. package/admin-dist/server/_ssr/{_entryId-CRfnqeDf.mjs → _entryId-D8alLFBx.mjs} +15 -15
  206. package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BffZedId.mjs +4 -0
  207. package/admin-dist/server/_ssr/{command-fy8epIKf.mjs → command-C0Di14--.mjs} +1 -1
  208. package/admin-dist/server/_ssr/{content-B5RhL7uW.mjs → content-CT-FPsmV.mjs} +170 -98
  209. package/admin-dist/server/_ssr/{content-types-BIOqCQYN.mjs → content-types-C8cBFdzE.mjs} +260 -115
  210. package/admin-dist/server/_ssr/{index-DHSHDPt1.mjs → index-BJtcrEc-.mjs} +88 -17
  211. package/admin-dist/server/_ssr/index.mjs +2 -2
  212. package/admin-dist/server/_ssr/{label-C8Dko1j7.mjs → label-qn2Afwl4.mjs} +1 -1
  213. package/admin-dist/server/_ssr/{media-CSx3XttC.mjs → media-qv5IAsMZ.mjs} +43 -43
  214. package/admin-dist/server/_ssr/{new._contentTypeId-DzanEZQM.mjs → new._contentTypeId-DdGyrhqs.mjs} +13 -13
  215. package/admin-dist/server/_ssr/{router-DDWcF-kt.mjs → router-nSVkxb6Y.mjs} +11 -11
  216. package/admin-dist/server/_ssr/{scroll-area-bjPYwhXN.mjs → scroll-area-BCinP455.mjs} +1 -1
  217. package/admin-dist/server/_ssr/{select-BUhDDf4T.mjs → select-BKQlQScw.mjs} +1 -1
  218. package/admin-dist/server/_ssr/{settings-DAsxnw2q.mjs → settings-BCr2KQlk.mjs} +236 -139
  219. package/admin-dist/server/_ssr/{switch-BgyRtQ1Z.mjs → switch-BaOi42fE.mjs} +1 -1
  220. package/admin-dist/server/_ssr/{tabs-DzMdRB1A.mjs → tabs-DYXEi9kq.mjs} +5 -3
  221. package/admin-dist/server/_ssr/tanstack-adapter-Bsz8kha-.mjs +119 -0
  222. package/admin-dist/server/_ssr/{taxonomies-C8j8g5Q5.mjs → taxonomies-CueMHTbE.mjs} +184 -73
  223. package/admin-dist/server/_ssr/{textarea-9jNeYJSc.mjs → textarea-CI0Jqx2x.mjs} +1 -1
  224. package/admin-dist/server/_ssr/{trash-DYMxwhZB.mjs → trash-DE6W8GoX.mjs} +211 -88
  225. package/admin-dist/server/_ssr/{useBreadcrumbLabel-FNSAr2Ha.mjs → useBreadcrumbLabel-B5Yi72lM.mjs} +1 -1
  226. package/admin-dist/server/_ssr/{usePermissions-BJGGahrJ.mjs → usePermissions-C3nZ-Izm.mjs} +1 -1
  227. package/admin-dist/server/index.mjs +189 -182
  228. package/dist/cli/commands/init.d.ts +6 -0
  229. package/dist/cli/commands/init.d.ts.map +1 -0
  230. package/dist/cli/commands/init.js +156 -0
  231. package/dist/cli/commands/init.js.map +1 -0
  232. package/dist/cli/index.js +6 -0
  233. package/dist/cli/index.js.map +1 -1
  234. package/dist/client/admin/bulk.d.ts +79 -0
  235. package/dist/client/admin/bulk.d.ts.map +1 -0
  236. package/dist/client/admin/bulk.js +72 -0
  237. package/dist/client/admin/bulk.js.map +1 -0
  238. package/dist/client/admin/contentLock.d.ts +118 -0
  239. package/dist/client/admin/contentLock.d.ts.map +1 -0
  240. package/dist/client/admin/contentLock.js +81 -0
  241. package/dist/client/admin/contentLock.js.map +1 -0
  242. package/dist/client/admin/contentTypes.d.ts +1204 -0
  243. package/dist/client/admin/contentTypes.d.ts.map +1 -0
  244. package/dist/client/admin/contentTypes.js +122 -0
  245. package/dist/client/admin/contentTypes.js.map +1 -0
  246. package/dist/client/admin/dashboard.d.ts +16 -0
  247. package/dist/client/admin/dashboard.d.ts.map +1 -0
  248. package/dist/client/admin/dashboard.js +33 -0
  249. package/dist/client/admin/dashboard.js.map +1 -0
  250. package/dist/client/admin/entries.d.ts +358 -0
  251. package/dist/client/admin/entries.d.ts.map +1 -0
  252. package/dist/client/admin/entries.js +220 -0
  253. package/dist/client/admin/entries.js.map +1 -0
  254. package/dist/client/admin/index.d.ts +6568 -0
  255. package/dist/client/admin/index.d.ts.map +1 -0
  256. package/dist/client/admin/index.js +305 -0
  257. package/dist/client/admin/index.js.map +1 -0
  258. package/dist/client/admin/media.d.ts +1038 -0
  259. package/dist/client/admin/media.d.ts.map +1 -0
  260. package/dist/client/admin/media.js +489 -0
  261. package/dist/client/admin/media.js.map +1 -0
  262. package/dist/client/admin/taxonomies.d.ts +339 -0
  263. package/dist/client/admin/taxonomies.d.ts.map +1 -0
  264. package/dist/client/admin/taxonomies.js +364 -0
  265. package/dist/client/admin/taxonomies.js.map +1 -0
  266. package/dist/client/admin/trash.d.ts +91 -0
  267. package/dist/client/admin/trash.d.ts.map +1 -0
  268. package/dist/client/admin/trash.js +71 -0
  269. package/dist/client/admin/trash.js.map +1 -0
  270. package/dist/client/admin/types.d.ts +320 -0
  271. package/dist/client/admin/types.d.ts.map +1 -0
  272. package/dist/client/admin/types.js +7 -0
  273. package/dist/client/admin/types.js.map +1 -0
  274. package/dist/client/admin/validators.d.ts +3886 -0
  275. package/dist/client/admin/validators.d.ts.map +1 -0
  276. package/dist/client/admin/validators.js +322 -0
  277. package/dist/client/admin/validators.js.map +1 -0
  278. package/dist/client/admin/versions.d.ts +106 -0
  279. package/dist/client/admin/versions.d.ts.map +1 -0
  280. package/dist/client/admin/versions.js +57 -0
  281. package/dist/client/admin/versions.js.map +1 -0
  282. package/dist/client/adminApiTypes.d.ts +27 -0
  283. package/dist/client/adminApiTypes.d.ts.map +1 -0
  284. package/dist/client/adminApiTypes.js +12 -0
  285. package/dist/client/adminApiTypes.js.map +1 -0
  286. package/dist/client/{admin-config.d.ts → adminConfig.d.ts} +4 -4
  287. package/dist/client/adminConfig.d.ts.map +1 -0
  288. package/dist/client/{admin-config.js → adminConfig.js} +3 -3
  289. package/dist/client/adminConfig.js.map +1 -0
  290. package/dist/client/agentTools.d.ts +11 -21
  291. package/dist/client/agentTools.d.ts.map +1 -1
  292. package/dist/client/agentTools.js +4 -4
  293. package/dist/client/index.d.ts +6 -6
  294. package/dist/client/index.d.ts.map +1 -1
  295. package/dist/client/index.js +19 -6
  296. package/dist/client/index.js.map +1 -1
  297. package/dist/client/schema/codegen.d.ts +2 -2
  298. package/dist/client/schema/codegen.d.ts.map +1 -1
  299. package/dist/client/schema/codegen.js +3 -3
  300. package/dist/client/schema/codegen.js.map +1 -1
  301. package/dist/client/schema/defineContentType.d.ts +3 -3
  302. package/dist/client/schema/defineContentType.js +3 -3
  303. package/dist/client/schema/index.d.ts +7 -7
  304. package/dist/client/schema/index.d.ts.map +1 -1
  305. package/dist/client/schema/index.js +5 -5
  306. package/dist/client/schema/index.js.map +1 -1
  307. package/dist/client/schema/schemaDrift.d.ts +1 -1
  308. package/dist/client/schema/schemaDrift.js +1 -1
  309. package/dist/client/schema/typedClient.d.ts +2 -2
  310. package/dist/client/schema/typedClient.js +2 -2
  311. package/dist/client/schema/types.d.ts +1 -1
  312. package/dist/client/schema/types.js +1 -1
  313. package/dist/client/wrapper.d.ts +108 -65
  314. package/dist/client/wrapper.d.ts.map +1 -1
  315. package/dist/client/wrapper.js +22 -22
  316. package/dist/client/wrapper.js.map +1 -1
  317. package/dist/component/contentEntries.d.ts +4 -4
  318. package/dist/component/contentEntryMutations.d.ts +46 -0
  319. package/dist/component/contentEntryMutations.d.ts.map +1 -1
  320. package/dist/component/contentEntryMutations.js +1 -1
  321. package/dist/component/contentEntryMutations.js.map +1 -1
  322. package/dist/component/contentTypeMigration.d.ts +1 -1
  323. package/dist/component/contentTypeMutations.d.ts +22 -0
  324. package/dist/component/contentTypeMutations.d.ts.map +1 -1
  325. package/dist/component/contentTypeMutations.js +1 -1
  326. package/dist/component/contentTypeMutations.js.map +1 -1
  327. package/dist/component/convex.config.d.ts +2 -2
  328. package/dist/component/convex.config.js +2 -2
  329. package/dist/component/index.d.ts +1 -1
  330. package/dist/component/index.js +1 -1
  331. package/dist/component/lib/ragContentChunker.d.ts +1 -1
  332. package/dist/component/lib/ragContentChunker.js +1 -1
  333. package/dist/component/mediaAssetMutations.d.ts +47 -0
  334. package/dist/component/mediaAssetMutations.d.ts.map +1 -1
  335. package/dist/component/mediaAssetMutations.js +1 -1
  336. package/dist/component/mediaAssetMutations.js.map +1 -1
  337. package/dist/component/roles.d.ts +1 -1
  338. package/dist/component/roles.js +1 -1
  339. package/dist/component/schema.d.ts +9 -0
  340. package/dist/component/schema.d.ts.map +1 -1
  341. package/dist/component/schema.js +1 -1
  342. package/dist/component/schema.js.map +1 -1
  343. package/dist/react/index.d.ts +2 -2
  344. package/dist/react/index.d.ts.map +1 -1
  345. package/dist/react/index.js +13 -7
  346. package/dist/react/index.js.map +1 -1
  347. package/dist/test.d.ts +2 -2
  348. package/dist/test.js +2 -2
  349. package/package.json +115 -13
  350. package/admin-dist/public/assets/ErrorState-BIVaWmom.js +0 -1
  351. package/admin-dist/public/assets/TaxonomyFilter-ChaY6Y_x.js +0 -1
  352. package/admin-dist/public/assets/_contentTypeId-DQ8k_Rvw.js +0 -1
  353. package/admin-dist/public/assets/alert-BXjTqrwQ.js +0 -1
  354. package/admin-dist/public/assets/content-_LXl3pp7.js +0 -1
  355. package/admin-dist/public/assets/content-types-KjxaXGxY.js +0 -2
  356. package/admin-dist/public/assets/globals-CS6BZ0zp.css +0 -1
  357. package/admin-dist/public/assets/index-DNGIZHL-.js +0 -1
  358. package/admin-dist/public/assets/media-Bkrkffm7.js +0 -1
  359. package/admin-dist/public/assets/scroll-area-DfIlT0in.js +0 -1
  360. package/admin-dist/public/assets/select-BD29IXCI.js +0 -1
  361. package/admin-dist/public/assets/settings-DmMyn_6A.js +0 -1
  362. package/admin-dist/public/assets/switch-h3Rrnl5i.js +0 -1
  363. package/admin-dist/public/assets/tabs-imc8h-Dp.js +0 -1
  364. package/admin-dist/public/assets/taxonomies-dAsrT65H.js +0 -1
  365. package/admin-dist/public/assets/trash-SAWKZZHv.js +0 -1
  366. package/admin-dist/public/assets/useBreadcrumbLabel-BECBMCzM.js +0 -1
  367. package/admin-dist/server/_ssr/ErrorState-cI-bKLez.mjs +0 -89
  368. package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BwDlABVk.mjs +0 -4
  369. package/admin-dist/server/_ssr/alert-CVt45UUP.mjs +0 -92
  370. package/dist/client/admin-config.d.ts.map +0 -1
  371. package/dist/client/admin-config.js.map +0 -1
  372. package/dist/client/adminApi.d.ts +0 -2273
  373. package/dist/client/adminApi.d.ts.map +0 -1
  374. package/dist/client/adminApi.js +0 -716
  375. package/dist/client/adminApi.js.map +0 -1
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Embed Navigation Context
3
+ *
4
+ * Provides router-agnostic navigation for the embedded CMS admin.
5
+ * This allows the embed to manage its own routing state without
6
+ * depending on TanStack Router or any specific router implementation.
7
+ */
8
+
9
+ import {
10
+ createContext,
11
+ useContext,
12
+ useState,
13
+ useCallback,
14
+ type ReactNode,
15
+ } from "react";
16
+
17
+ export type EmbedRoute =
18
+ | "dashboard"
19
+ | "content"
20
+ | "content-types"
21
+ | "media"
22
+ | "taxonomies"
23
+ | "settings"
24
+ | "trash"
25
+ | "entries";
26
+
27
+ export interface EmbedRouteState {
28
+ route: EmbedRoute;
29
+ params: Record<string, string>;
30
+ }
31
+
32
+ export interface EmbedNavigationContextValue {
33
+ currentRoute: EmbedRouteState;
34
+ currentPath: string;
35
+ navigate: (route: EmbedRoute, params?: Record<string, string>) => void;
36
+ navigateToEntry: (entryId: string) => void;
37
+ navigateToContentType: (contentTypeId: string) => void;
38
+ navigateToNewEntry: (contentTypeId: string) => void;
39
+ goBack: () => void;
40
+ canGoBack: boolean;
41
+ }
42
+
43
+ const EmbedNavigationContext = createContext<EmbedNavigationContextValue | null>(
44
+ null
45
+ );
46
+
47
+ function routeToPath(route: EmbedRoute, params: Record<string, string>): string {
48
+ switch (route) {
49
+ case "dashboard":
50
+ return "/";
51
+ case "content":
52
+ return "/content";
53
+ case "content-types":
54
+ return "/content-types";
55
+ case "media":
56
+ return "/media";
57
+ case "taxonomies":
58
+ return "/taxonomies";
59
+ case "settings":
60
+ return "/settings";
61
+ case "trash":
62
+ return "/trash";
63
+ case "entries": {
64
+ if (params.entryId) return `/entries/${params.entryId}`;
65
+ if (params.contentTypeId) return `/entries/type/${params.contentTypeId}`;
66
+ return "/content";
67
+ }
68
+ default:
69
+ return "/";
70
+ }
71
+ }
72
+
73
+ export interface EmbedNavigationProviderProps {
74
+ children: ReactNode;
75
+ initialRoute?: EmbedRoute;
76
+ basePath?: string;
77
+ onNavigate?: (path: string, params: Record<string, string>) => void;
78
+ }
79
+
80
+ export function EmbedNavigationProvider({
81
+ children,
82
+ initialRoute = "dashboard",
83
+ basePath = "/admin",
84
+ onNavigate,
85
+ }: EmbedNavigationProviderProps) {
86
+ const [history, setHistory] = useState<EmbedRouteState[]>([
87
+ { route: initialRoute, params: {} },
88
+ ]);
89
+ const [currentIndex, setCurrentIndex] = useState(0);
90
+
91
+ const currentRoute = history[currentIndex];
92
+ const currentPath = basePath + routeToPath(currentRoute.route, currentRoute.params);
93
+
94
+ const navigate = useCallback(
95
+ (route: EmbedRoute, params: Record<string, string> = {}) => {
96
+ const newState = { route, params };
97
+ const newHistory = [...history.slice(0, currentIndex + 1), newState];
98
+ setHistory(newHistory);
99
+ setCurrentIndex(newHistory.length - 1);
100
+
101
+ if (onNavigate) {
102
+ onNavigate(routeToPath(route, params), params);
103
+ }
104
+ },
105
+ [history, currentIndex, onNavigate]
106
+ );
107
+
108
+ const navigateToEntry = useCallback(
109
+ (entryId: string) => {
110
+ navigate("entries", { entryId });
111
+ },
112
+ [navigate]
113
+ );
114
+
115
+ const navigateToContentType = useCallback(
116
+ (contentTypeId: string) => {
117
+ navigate("entries", { contentTypeId });
118
+ },
119
+ [navigate]
120
+ );
121
+
122
+ const navigateToNewEntry = useCallback(
123
+ (contentTypeId: string) => {
124
+ navigate("entries", { contentTypeId, action: "new" });
125
+ },
126
+ [navigate]
127
+ );
128
+
129
+ const goBack = useCallback(() => {
130
+ if (currentIndex > 0) {
131
+ setCurrentIndex(currentIndex - 1);
132
+ }
133
+ }, [currentIndex]);
134
+
135
+ const value: EmbedNavigationContextValue = {
136
+ currentRoute,
137
+ currentPath,
138
+ navigate,
139
+ navigateToEntry,
140
+ navigateToContentType,
141
+ navigateToNewEntry,
142
+ goBack,
143
+ canGoBack: currentIndex > 0,
144
+ };
145
+
146
+ return (
147
+ <EmbedNavigationContext.Provider value={value}>
148
+ {children}
149
+ </EmbedNavigationContext.Provider>
150
+ );
151
+ }
152
+
153
+ export function useEmbedNavigation(): EmbedNavigationContextValue {
154
+ const context = useContext(EmbedNavigationContext);
155
+ if (!context) {
156
+ throw new Error(
157
+ "useEmbedNavigation must be used within EmbedNavigationProvider"
158
+ );
159
+ }
160
+ return context;
161
+ }
162
+
163
+ export function useEmbedParams(): Record<string, string> {
164
+ const { currentRoute } = useEmbedNavigation();
165
+ return currentRoute.params;
166
+ }
167
+
168
+ export function useEmbedRoute(): EmbedRoute {
169
+ const { currentRoute } = useEmbedNavigation();
170
+ return currentRoute.route;
171
+ }
172
+
173
+ export interface EmbedLinkProps {
174
+ to: EmbedRoute;
175
+ params?: Record<string, string>;
176
+ children: ReactNode;
177
+ className?: string;
178
+ activeClassName?: string;
179
+ }
180
+
181
+ export function EmbedLink({
182
+ to,
183
+ params = {},
184
+ children,
185
+ className = "",
186
+ activeClassName = "",
187
+ }: EmbedLinkProps) {
188
+ const { navigate, currentRoute } = useEmbedNavigation();
189
+
190
+ const isActive = currentRoute.route === to;
191
+ const finalClassName = `${className} ${isActive ? activeClassName : ""}`.trim();
192
+
193
+ return (
194
+ <button
195
+ type="button"
196
+ onClick={() => navigate(to, params)}
197
+ className={finalClassName}
198
+ >
199
+ {children}
200
+ </button>
201
+ );
202
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Embed Content Page
3
+ *
4
+ * Thin wrapper around the shared ContentPage component.
5
+ * Provides embed navigation and API access.
6
+ */
7
+
8
+ import { useApi } from "../contexts/ApiContext";
9
+ import { useEmbedNavigation } from "../navigation";
10
+ import { useEmbedAdapter } from "../../lib/embed-adapter";
11
+ import { ContentPage } from "../../pages";
12
+
13
+ export function EmbedContent() {
14
+ const api = useApi();
15
+ const embedNav = useEmbedNavigation();
16
+ const navigation = useEmbedAdapter(embedNav);
17
+
18
+ return <ContentPage api={api} navigation={navigation} />;
19
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Embed Content Types Page
3
+ *
4
+ * Thin wrapper around the shared ContentTypesPage component.
5
+ * Provides embed navigation and API access.
6
+ */
7
+
8
+ import { useApi } from "../contexts/ApiContext";
9
+ import { useEmbedNavigation } from "../navigation";
10
+ import { useEmbedAdapter } from "../../lib/embed-adapter";
11
+ import { ContentTypesPage } from "../../pages";
12
+
13
+ export function EmbedContentTypes() {
14
+ const api = useApi();
15
+ const embedNav = useEmbedNavigation();
16
+ const navigation = useEmbedAdapter(embedNav);
17
+
18
+ return <ContentTypesPage api={api} navigation={navigation} />;
19
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Embed Dashboard Page
3
+ *
4
+ * Thin wrapper around the shared DashboardPage component.
5
+ * Provides embed navigation and API access.
6
+ */
7
+
8
+ import { useApi } from "../contexts/ApiContext";
9
+ import { useEmbedNavigation } from "../navigation";
10
+ import { useEmbedAdapter } from "../../lib/embed-adapter";
11
+ import { DashboardPage } from "../../pages";
12
+
13
+ export function EmbedDashboard() {
14
+ const api = useApi();
15
+ const embedNav = useEmbedNavigation();
16
+ const navigation = useEmbedAdapter(embedNav);
17
+
18
+ return <DashboardPage api={api} navigation={navigation} />;
19
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Embed Media Page
3
+ *
4
+ * Thin wrapper around the shared MediaPage component.
5
+ * Provides embed navigation and API access.
6
+ */
7
+
8
+ import { useApi } from "../contexts/ApiContext";
9
+ import { useEmbedNavigation } from "../navigation";
10
+ import { useEmbedAdapter } from "../../lib/embed-adapter";
11
+ import { MediaPage } from "../../pages";
12
+
13
+ export function EmbedMedia() {
14
+ const api = useApi();
15
+ const embedNav = useEmbedNavigation();
16
+ const navigation = useEmbedAdapter(embedNav);
17
+
18
+ return <MediaPage api={api} navigation={navigation} />;
19
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Embed Settings Page
3
+ *
4
+ * Thin wrapper around the shared SettingsPage component.
5
+ * Provides embed navigation and API access.
6
+ *
7
+ * Note: Requires the settings namespace to be exported from defineAdminAPI.
8
+ * This feature is currently in development.
9
+ */
10
+
11
+ import { useApi } from "../contexts/ApiContext";
12
+ import { useEmbedNavigation } from "../navigation";
13
+ import { useEmbedAdapter } from "../../lib/embed-adapter";
14
+ import { SettingsPage, type SettingsPageProps } from "../../pages";
15
+
16
+ export function EmbedSettings() {
17
+ const api = useApi();
18
+ const embedNav = useEmbedNavigation();
19
+ const navigation = useEmbedAdapter(embedNav);
20
+
21
+ return <SettingsPage api={api as SettingsPageProps["api"]} navigation={navigation} />;
22
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Embed Taxonomies Page
3
+ *
4
+ * Thin wrapper around the shared TaxonomiesPage component.
5
+ * Provides embed navigation and API access.
6
+ *
7
+ * Note: Requires the taxonomies namespace to be exported from defineAdminAPI.
8
+ * This feature is currently in development.
9
+ */
10
+
11
+ import { useApi } from "../contexts/ApiContext";
12
+ import { useEmbedNavigation } from "../navigation";
13
+ import { useEmbedAdapter } from "../../lib/embed-adapter";
14
+ import { TaxonomiesPage, type TaxonomiesPageProps } from "../../pages";
15
+
16
+ export function EmbedTaxonomies() {
17
+ const api = useApi();
18
+ const embedNav = useEmbedNavigation();
19
+ const navigation = useEmbedAdapter(embedNav);
20
+
21
+ return <TaxonomiesPage api={api as TaxonomiesPageProps["api"]} navigation={navigation} />;
22
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Embed Trash Page
3
+ *
4
+ * Thin wrapper around the shared TrashPage component.
5
+ * Provides embed navigation and API access.
6
+ *
7
+ * Note: Requires the trash and bulkOperations namespaces to be exported
8
+ * from defineAdminAPI. This feature is currently in development.
9
+ */
10
+
11
+ import { useApi } from "../contexts/ApiContext";
12
+ import { useEmbedNavigation } from "../navigation";
13
+ import { useEmbedAdapter } from "../../lib/embed-adapter";
14
+ import { TrashPage, type TrashPageProps } from "../../pages";
15
+
16
+ export function EmbedTrash() {
17
+ const api = useApi();
18
+ const embedNav = useEmbedNavigation();
19
+ const navigation = useEmbedAdapter(embedNav);
20
+
21
+ return <TrashPage api={api as TrashPageProps["api"]} navigation={navigation} />;
22
+ }
@@ -0,0 +1,7 @@
1
+ export { EmbedDashboard } from "./Dashboard";
2
+ export { EmbedContent } from "./Content";
3
+ export { EmbedContentTypes } from "./ContentTypes";
4
+ export { EmbedMedia } from "./Media";
5
+ export { EmbedSettings } from "./Settings";
6
+ export { EmbedTrash } from "./Trash";
7
+ export { EmbedTaxonomies } from "./Taxonomies";
@@ -0,0 +1,24 @@
1
+ import type { AdminConfig } from "../lib/admin-config";
2
+ import type { CmsAdminApi } from "./contexts/ApiContext";
3
+
4
+ export interface CmsAdminUser {
5
+ id: string;
6
+ name?: string;
7
+ email?: string;
8
+ avatarUrl?: string;
9
+ }
10
+
11
+ export interface CmsAdminAuthConfig {
12
+ getUser: () => CmsAdminUser | null | Promise<CmsAdminUser | null>;
13
+ getUserRole: (userId: string) => string | null | Promise<string | null>;
14
+ onLogout?: () => void | Promise<void>;
15
+ }
16
+
17
+ export interface CmsAdminProps {
18
+ api: CmsAdminApi;
19
+ convexUrl: string;
20
+ config?: Partial<AdminConfig>;
21
+ auth: CmsAdminAuthConfig;
22
+ basePath?: string;
23
+ className?: string;
24
+ }
@@ -0,0 +1,2 @@
1
+ export { usePermissions, type UsePermissionsResult } from './usePermissions';
2
+ export { useBreadcrumbLabel } from './useBreadcrumbLabel';
@@ -0,0 +1,19 @@
1
+ import * as React from "react"
2
+
3
+ const MOBILE_BREAKPOINT = 768
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
+ }
13
+ mql.addEventListener("change", onChange)
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
+ return () => mql.removeEventListener("change", onChange)
16
+ }, [])
17
+
18
+ return !!isMobile
19
+ }
@@ -0,0 +1,15 @@
1
+ import { useEffect } from 'react'
2
+ import { useBreadcrumbContext } from '~/contexts/BreadcrumbContext'
3
+
4
+ export function useBreadcrumbLabel(path: string, label: string | undefined) {
5
+ const { setOverride, clearOverride } = useBreadcrumbContext()
6
+
7
+ useEffect(() => {
8
+ if (label) {
9
+ setOverride(path, label)
10
+ }
11
+ return () => {
12
+ clearOverride(path)
13
+ }
14
+ }, [path, label, setOverride, clearOverride])
15
+ }
@@ -0,0 +1,211 @@
1
+ /**
2
+ * usePermissions Hook
3
+ *
4
+ * Provides permission checking utilities for UI components.
5
+ * Enables showing/hiding or enabling/disabling features based on user permissions.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * function ContentActions({ entry }) {
10
+ * const { canEdit, canPublish, canDelete } = usePermissions();
11
+ *
12
+ * return (
13
+ * <div>
14
+ * {canEdit('contentEntries') && <button>Edit</button>}
15
+ * {canPublish() && <button>Publish</button>}
16
+ * {canDelete('contentEntries') && <button>Delete</button>}
17
+ * </div>
18
+ * );
19
+ * }
20
+ * ```
21
+ */
22
+
23
+ import { useMemo } from 'react';
24
+ import { useAuth } from '../contexts/AuthContext';
25
+ import {
26
+ hasPermission,
27
+ canAccessResource,
28
+ getResourcePermissions,
29
+ type Resource,
30
+ type Action,
31
+ type OwnershipScope,
32
+ type Permission,
33
+ } from '../../../src/component/roles';
34
+
35
+ // =============================================================================
36
+ // Types
37
+ // =============================================================================
38
+
39
+ export interface UsePermissionsResult {
40
+ /** Current user's role */
41
+ role: string | null;
42
+ /** Whether user is authenticated with a valid role */
43
+ hasRole: boolean;
44
+ /** Check a specific permission */
45
+ check: (
46
+ resource: Resource,
47
+ action: Action,
48
+ scope?: OwnershipScope
49
+ ) => boolean;
50
+ /** Check if user can access a resource at all */
51
+ canAccess: (resource: Resource) => boolean;
52
+ /** Check if user can create resources of a type */
53
+ canCreate: (resource: Resource) => boolean;
54
+ /** Check if user can read resources of a type */
55
+ canRead: (resource: Resource, scope?: OwnershipScope) => boolean;
56
+ /** Check if user can update resources of a type */
57
+ canUpdate: (resource: Resource, scope?: OwnershipScope) => boolean;
58
+ /** Check if user can delete resources of a type */
59
+ canDelete: (resource: Resource, scope?: OwnershipScope) => boolean;
60
+ /** Check if user can publish content */
61
+ canPublish: (scope?: OwnershipScope) => boolean;
62
+ /** Check if user can unpublish content */
63
+ canUnpublish: (scope?: OwnershipScope) => boolean;
64
+ /** Check if user can manage settings */
65
+ canManageSettings: () => boolean;
66
+ /** Check if user can manage content types */
67
+ canManageContentTypes: () => boolean;
68
+ /** Get all permissions for a resource */
69
+ getPermissions: (resource: Resource) => Permission[];
70
+ /** Check if user is an admin */
71
+ isAdmin: boolean;
72
+ /** Check if user is at least an editor */
73
+ isEditor: boolean;
74
+ /** Check if user is at least an author */
75
+ isAuthor: boolean;
76
+ }
77
+
78
+ // =============================================================================
79
+ // Hook
80
+ // =============================================================================
81
+
82
+ /**
83
+ * Hook for checking user permissions in UI components.
84
+ *
85
+ * Provides convenient methods for common permission checks,
86
+ * enabling permission-based UI rendering.
87
+ */
88
+ export function usePermissions(): UsePermissionsResult {
89
+ const { role } = useAuth();
90
+
91
+ return useMemo(() => {
92
+ const hasRole = !!role;
93
+
94
+ /**
95
+ * Check a specific permission.
96
+ */
97
+ const check = (
98
+ resource: Resource,
99
+ action: Action,
100
+ scope?: OwnershipScope
101
+ ): boolean => {
102
+ if (!role) return false;
103
+ return hasPermission(role, { resource, action, scope });
104
+ };
105
+
106
+ /**
107
+ * Check if user can access a resource at all.
108
+ */
109
+ const canAccess = (resource: Resource): boolean => {
110
+ if (!role) return false;
111
+ return canAccessResource(role, resource);
112
+ };
113
+
114
+ /**
115
+ * Check if user can create resources.
116
+ */
117
+ const canCreate = (resource: Resource): boolean => {
118
+ return check(resource, 'create');
119
+ };
120
+
121
+ /**
122
+ * Check if user can read resources.
123
+ */
124
+ const canRead = (resource: Resource, scope?: OwnershipScope): boolean => {
125
+ return check(resource, 'read', scope);
126
+ };
127
+
128
+ /**
129
+ * Check if user can update resources.
130
+ */
131
+ const canUpdate = (resource: Resource, scope?: OwnershipScope): boolean => {
132
+ return check(resource, 'update', scope);
133
+ };
134
+
135
+ /**
136
+ * Check if user can delete resources.
137
+ */
138
+ const canDelete = (resource: Resource, scope?: OwnershipScope): boolean => {
139
+ return check(resource, 'delete', scope);
140
+ };
141
+
142
+ /**
143
+ * Check if user can publish content.
144
+ */
145
+ const canPublish = (scope?: OwnershipScope): boolean => {
146
+ return check('contentEntries', 'publish', scope);
147
+ };
148
+
149
+ /**
150
+ * Check if user can unpublish content.
151
+ */
152
+ const canUnpublish = (scope?: OwnershipScope): boolean => {
153
+ return check('contentEntries', 'unpublish', scope);
154
+ };
155
+
156
+ /**
157
+ * Check if user can manage settings.
158
+ */
159
+ const canManageSettings = (): boolean => {
160
+ return check('settings', 'manage');
161
+ };
162
+
163
+ /**
164
+ * Check if user can manage content types.
165
+ */
166
+ const canManageContentTypes = (): boolean => {
167
+ // Need create, update, or delete on content types
168
+ return (
169
+ check('contentTypes', 'create') ||
170
+ check('contentTypes', 'update') ||
171
+ check('contentTypes', 'delete')
172
+ );
173
+ };
174
+
175
+ /**
176
+ * Get all permissions for a resource.
177
+ */
178
+ const getPermissions = (resource: Resource): Permission[] => {
179
+ if (!role) return [];
180
+ return getResourcePermissions(role, resource);
181
+ };
182
+
183
+ /**
184
+ * Role-based checks for convenience.
185
+ */
186
+ const isAdmin = role === 'admin';
187
+ const isEditor = role === 'admin' || role === 'editor';
188
+ const isAuthor = role === 'admin' || role === 'editor' || role === 'author';
189
+
190
+ return {
191
+ role,
192
+ hasRole,
193
+ check,
194
+ canAccess,
195
+ canCreate,
196
+ canRead,
197
+ canUpdate,
198
+ canDelete,
199
+ canPublish,
200
+ canUnpublish,
201
+ canManageSettings,
202
+ canManageContentTypes,
203
+ getPermissions,
204
+ isAdmin,
205
+ isEditor,
206
+ isAuthor,
207
+ };
208
+ }, [role]);
209
+ }
210
+
211
+ export default usePermissions;