convex-cms 0.0.6 → 0.0.7

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 (329) hide show
  1. package/README.md +68 -101
  2. package/admin/src/components/BreakingChangesWarningDialog.tsx +5 -5
  3. package/admin/src/components/BulkOperationModal.tsx +14 -14
  4. package/admin/src/components/ContentEntryEditor.tsx +8 -8
  5. package/admin/src/components/ContentTypeFormModal.tsx +122 -82
  6. package/admin/src/components/Header.tsx +5 -2
  7. package/admin/src/components/SchemaDriftWarning.tsx +126 -0
  8. package/admin/src/components/TaxonomyEditor.tsx +2 -2
  9. package/admin/src/components/TermTree.tsx +3 -3
  10. package/admin/src/components/UploadDropzone.tsx +7 -7
  11. package/admin/src/components/VersionCompare.tsx +13 -13
  12. package/admin/src/components/VersionHistory.tsx +2 -2
  13. package/admin/src/components/VersionRollbackModal.tsx +5 -5
  14. package/admin/src/components/cmsds/CmsButton.tsx +2 -2
  15. package/admin/src/components/cmsds/CmsDialog.tsx +4 -1
  16. package/admin/src/components/cmsds/CmsStatusBadge.tsx +5 -5
  17. package/admin/src/components/fields/JsonField.tsx +1 -1
  18. package/admin/src/components/fields/ReferenceField.tsx +9 -9
  19. package/admin/src/components/fields/TagField.tsx +1 -1
  20. package/admin/src/contexts/SettingsConfigContext.tsx +10 -3
  21. package/admin/src/embed/index.tsx +29 -9
  22. package/admin/src/embed/pages/ContentTypeEntries.tsx +25 -0
  23. package/admin/src/embed/pages/Entry.tsx +114 -0
  24. package/admin/src/embed/pages/Media.tsx +3 -1
  25. package/admin/src/embed/pages/NewEntry.tsx +83 -0
  26. package/admin/src/embed/pages/index.ts +3 -0
  27. package/admin/src/pages/ContentPage.tsx +27 -20
  28. package/admin/src/pages/ContentTypeEntriesPage.tsx +466 -0
  29. package/admin/src/pages/ContentTypesPage.tsx +65 -19
  30. package/admin/src/pages/DashboardPage.tsx +3 -0
  31. package/admin/src/pages/SettingsPage.tsx +4 -4
  32. package/admin/src/pages/index.ts +1 -0
  33. package/admin/src/routes/__root.tsx +10 -10
  34. package/admin/src/routes/entries/$entryId.tsx +1 -1
  35. package/admin/src/routes/entries/type/$contentTypeId.tsx +1 -1
  36. package/admin/src/styles/globals.css +31 -5
  37. package/admin/src/styles/tailwind-config.css +25 -0
  38. package/admin/src/styles/theme.css +50 -0
  39. package/admin-dist/nitro.json +1 -1
  40. package/admin-dist/public/assets/CmsEmptyState-6-PLaXtD.js +1 -0
  41. package/admin-dist/public/assets/CmsPageHeader-SoF4Epu9.js +1 -0
  42. package/admin-dist/public/assets/CmsStatusBadge-D7kYaohx.js +1 -0
  43. package/admin-dist/public/assets/{CmsSurface-DBy5Lumx.js → CmsSurface-BvksBm6W.js} +1 -1
  44. package/admin-dist/public/assets/CmsToolbar-DlZPMe2B.js +1 -0
  45. package/admin-dist/public/assets/ContentEntryEditor-C6n9xLS9.js +4 -0
  46. package/admin-dist/public/assets/TaxonomyFilter-CFX1_g8s.js +1 -0
  47. package/admin-dist/public/assets/_contentTypeId-DTv8UoTp.js +1 -0
  48. package/admin-dist/public/assets/_entryId-D3lr5Dvy.js +1 -0
  49. package/admin-dist/public/assets/alert-BAHTL6ao.js +1 -0
  50. package/admin-dist/public/assets/badge-oJv4Eai8.js +1 -0
  51. package/admin-dist/public/assets/{circle-check-big-CpLxAvEj.js → circle-check-big-3OHxNDhO.js} +1 -1
  52. package/admin-dist/public/assets/command-DwgQs69u.js +1 -0
  53. package/admin-dist/public/assets/content-CKQ4QwW2.js +1 -0
  54. package/admin-dist/public/assets/content-types-BrttaLpc.js +1 -0
  55. package/admin-dist/public/assets/globals-CoCRjt0K.css +1 -0
  56. package/admin-dist/public/assets/index-DOkgTSx0.js +1 -0
  57. package/admin-dist/public/assets/main-DV6oxWnU.js +102 -0
  58. package/admin-dist/public/assets/media-B2i-mCbx.js +1 -0
  59. package/admin-dist/public/assets/new._contentTypeId-VF63rpic.js +1 -0
  60. package/admin-dist/public/assets/pencil-CX1CiTDD.js +1 -0
  61. package/admin-dist/public/assets/refresh-cw-Cm-YOeFI.js +1 -0
  62. package/admin-dist/public/assets/{rotate-ccw-BZpZtw0N.js → rotate-ccw-B45JsL5f.js} +1 -1
  63. package/admin-dist/public/assets/scroll-area-b3A1HHR7.js +1 -0
  64. package/admin-dist/public/assets/{search-BvgYr-c9.js → search-DKKh_DdH.js} +1 -1
  65. package/admin-dist/public/assets/settings-CGVDEV1r.js +1 -0
  66. package/admin-dist/public/assets/switch-BTMY8Qnk.js +1 -0
  67. package/admin-dist/public/assets/tabs-DUQwUoIb.js +1 -0
  68. package/admin-dist/public/assets/tanstack-adapter-f7AHmQ5L.js +1 -0
  69. package/admin-dist/public/assets/taxonomies-DvMppdiD.js +1 -0
  70. package/admin-dist/public/assets/trash-D7e0uKd9.js +1 -0
  71. package/admin-dist/public/assets/{useBreadcrumbLabel-D00rvqjw.js → useBreadcrumbLabel-CF2KYwsw.js} +1 -1
  72. package/admin-dist/public/assets/usePermissions-DWBImEOW.js +1 -0
  73. package/admin-dist/server/_chunks/_libs/@date-fns/tz.mjs +2 -2
  74. package/admin-dist/server/_chunks/_libs/@radix-ui/react-avatar.mjs +1 -1
  75. package/admin-dist/server/_chunks/_libs/@radix-ui/react-collection.mjs +1 -1
  76. package/admin-dist/server/_chunks/_libs/@radix-ui/react-context.mjs +2 -2
  77. package/admin-dist/server/_chunks/_libs/@radix-ui/react-dialog.mjs +2 -2
  78. package/admin-dist/server/_chunks/_libs/@radix-ui/react-label.mjs +1 -1
  79. package/admin-dist/server/_chunks/_libs/@radix-ui/react-menu.mjs +1 -1
  80. package/admin-dist/server/_chunks/_libs/@radix-ui/react-popover.mjs +1 -1
  81. package/admin-dist/server/_chunks/_libs/@radix-ui/react-primitive.mjs +6 -72
  82. package/admin-dist/server/_chunks/_libs/@radix-ui/react-select.mjs +1 -1
  83. package/admin-dist/server/_chunks/_libs/@radix-ui/react-separator.mjs +1 -1
  84. package/admin-dist/server/_chunks/_libs/@radix-ui/react-slot.mjs +20 -435
  85. package/admin-dist/server/_chunks/_libs/@radix-ui/react-visually-hidden.mjs +30 -3
  86. package/admin-dist/server/_chunks/_libs/@tanstack/history.mjs +0 -376
  87. package/admin-dist/server/_chunks/_libs/@tanstack/react-router.mjs +168 -383
  88. package/admin-dist/server/_chunks/_libs/@tanstack/router-core.mjs +451 -1195
  89. package/admin-dist/server/_chunks/_libs/react-dom.mjs +5 -5
  90. package/admin-dist/server/_chunks/_libs/react.mjs +2 -2
  91. package/admin-dist/server/_libs/cmdk.mjs +1 -1
  92. package/admin-dist/server/_libs/convex.mjs +3 -3
  93. package/admin-dist/server/_libs/cookie-es.mjs +1 -58
  94. package/admin-dist/server/_libs/date-fns.mjs +1 -1
  95. package/admin-dist/server/_libs/lucide-react.mjs +117 -103
  96. package/admin-dist/server/_libs/seroval-plugins.mjs +1 -58
  97. package/admin-dist/server/_libs/seroval.mjs +1 -1765
  98. package/admin-dist/server/_libs/zod.mjs +1 -1
  99. package/admin-dist/server/_ssr/CmsEmptyState-BM8DghTl.mjs +38 -0
  100. package/admin-dist/server/_ssr/{CmsPageHeader-ClNPU7Up.mjs → CmsPageHeader-BHUmrIWD.mjs} +1 -1
  101. package/admin-dist/server/_ssr/{CmsStatusBadge-CojMbrY7.mjs → CmsStatusBadge-D0Zb0oRl.mjs} +7 -7
  102. package/admin-dist/server/_ssr/{CmsSurface-Dcv440rp.mjs → CmsSurface-B2eBr-47.mjs} +1 -1
  103. package/admin-dist/server/_ssr/{CmsToolbar-BKv1nL6u.mjs → CmsToolbar-BCrwg7OL.mjs} +2 -3
  104. package/admin-dist/server/_ssr/{ContentEntryEditor-weiXSBdZ.mjs → ContentEntryEditor-Cjfm0uhr.mjs} +46 -49
  105. package/admin-dist/server/_ssr/{TaxonomyFilter-BPQ57Mwk.mjs → TaxonomyFilter-C4pD0kfM.mjs} +4 -5
  106. package/admin-dist/server/_ssr/{_contentTypeId-DyyauLOs.mjs → _contentTypeId-CiDiX-p7.mjs} +34 -43
  107. package/admin-dist/server/_ssr/{_entryId-9Cafwxmw.mjs → _entryId-9GxatOkL.mjs} +35 -47
  108. package/admin-dist/server/_ssr/_tanstack-start-manifest_v-CC7UrHKE.mjs +4 -0
  109. package/admin-dist/server/_ssr/badge-EI998zba.mjs +39 -0
  110. package/admin-dist/server/_ssr/{command-CEf8YBxY.mjs → command-BLAWQhUw.mjs} +2 -2
  111. package/admin-dist/server/_ssr/{config.server-D7JHDcDv.mjs → config.server-BOr7Jxr4.mjs} +5 -14
  112. package/admin-dist/server/_ssr/{content-ZFWVzO25.mjs → content-BHX39L4D.mjs} +63 -63
  113. package/admin-dist/server/_ssr/content-types-DCzrBhTH.mjs +459 -0
  114. package/admin-dist/server/_ssr/{index-BlSIlH4Z.mjs → index-DwM_5VNP.mjs} +114 -30
  115. package/admin-dist/server/_ssr/index.mjs +3459 -62
  116. package/admin-dist/server/_ssr/{media-CD2_NUMw.mjs → media-CbzgTRRQ.mjs} +31 -43
  117. package/admin-dist/server/_ssr/{new._contentTypeId-dmZy6PBX.mjs → new._contentTypeId-6Ph-Gtlw.mjs} +33 -45
  118. package/admin-dist/server/_ssr/router-vd1nySeP.mjs +3041 -0
  119. package/admin-dist/server/_ssr/{scroll-area-BH_1K-WT.mjs → scroll-area--B9snFTJ.mjs} +1 -1
  120. package/admin-dist/server/_ssr/{settings-DVdsoWoh.mjs → settings-DlTO2JSj.mjs} +34 -43
  121. package/admin-dist/server/_ssr/{switch-DX_X8vZl.mjs → switch-C05NgNW0.mjs} +1 -1
  122. package/admin-dist/server/_ssr/{tabs-4FWM0sn8.mjs → tabs-DAk2J5xy.mjs} +9 -10
  123. package/admin-dist/server/_ssr/{tanstack-adapter-D3ZcKtbY.mjs → tanstack-adapter-DWbaPByn.mjs} +15 -1
  124. package/admin-dist/server/_ssr/{taxonomies-BHFfO9Yr.mjs → taxonomies-B8nqce6u.mjs} +35 -44
  125. package/admin-dist/server/_ssr/{trash-9tUB2KwI.mjs → trash-zdlZgpTo.mjs} +30 -39
  126. package/admin-dist/server/_ssr/{useBreadcrumbLabel-DVme3DSb.mjs → useBreadcrumbLabel-DpEKyG1h.mjs} +1 -1
  127. package/admin-dist/server/_ssr/{usePermissions-zAQj-ruE.mjs → usePermissions-olYRd9S9.mjs} +1 -1
  128. package/admin-dist/server/index.mjs +168 -203
  129. package/dist/cli/templates/cmsClient.d.ts +1 -1
  130. package/dist/cli/templates/cmsClient.d.ts.map +1 -1
  131. package/dist/cli/templates/cmsClient.js +30 -11
  132. package/dist/cli/templates/cmsClient.js.map +1 -1
  133. package/dist/cli/templates/cmsConfig.d.ts +1 -1
  134. package/dist/cli/templates/cmsConfig.d.ts.map +1 -1
  135. package/dist/cli/templates/cmsConfig.js +3 -3
  136. package/dist/client/admin/contentLock.d.ts +4 -4
  137. package/dist/client/admin/contentLock.d.ts.map +1 -1
  138. package/dist/client/admin/contentLock.js +1 -1
  139. package/dist/client/admin/contentLock.js.map +1 -1
  140. package/dist/client/admin/contentTypes.d.ts +328 -290
  141. package/dist/client/admin/contentTypes.d.ts.map +1 -1
  142. package/dist/client/admin/contentTypes.js +307 -9
  143. package/dist/client/admin/contentTypes.js.map +1 -1
  144. package/dist/client/admin/entries.d.ts +18 -19
  145. package/dist/client/admin/entries.d.ts.map +1 -1
  146. package/dist/client/admin/entries.js +33 -8
  147. package/dist/client/admin/entries.js.map +1 -1
  148. package/dist/client/admin/index.d.ts +694 -642
  149. package/dist/client/admin/index.d.ts.map +1 -1
  150. package/dist/client/admin/index.js +45 -5
  151. package/dist/client/admin/index.js.map +1 -1
  152. package/dist/client/admin/media.d.ts.map +1 -1
  153. package/dist/client/admin/taxonomies.d.ts.map +1 -1
  154. package/dist/client/admin/trash.d.ts +3 -4
  155. package/dist/client/admin/trash.d.ts.map +1 -1
  156. package/dist/client/admin/types.d.ts +185 -4
  157. package/dist/client/admin/types.d.ts.map +1 -1
  158. package/dist/client/admin/validators.d.ts +2009 -25
  159. package/dist/client/admin/validators.d.ts.map +1 -1
  160. package/dist/client/admin/validators.js +15 -4
  161. package/dist/client/admin/validators.js.map +1 -1
  162. package/dist/client/admin/versions.d.ts +1 -1
  163. package/dist/client/admin/versions.d.ts.map +1 -1
  164. package/dist/client/agentTools.d.ts +1 -4
  165. package/dist/client/agentTools.d.ts.map +1 -1
  166. package/dist/client/agentTools.js +9 -21
  167. package/dist/client/agentTools.js.map +1 -1
  168. package/dist/client/config.d.ts +10 -0
  169. package/dist/client/config.d.ts.map +1 -1
  170. package/dist/client/config.js +1 -0
  171. package/dist/client/config.js.map +1 -1
  172. package/dist/client/defineContent.d.ts +338 -0
  173. package/dist/client/defineContent.d.ts.map +1 -0
  174. package/dist/client/defineContent.js +368 -0
  175. package/dist/client/defineContent.js.map +1 -0
  176. package/dist/client/index.d.ts +2 -0
  177. package/dist/client/index.d.ts.map +1 -1
  178. package/dist/client/index.js +2 -0
  179. package/dist/client/index.js.map +1 -1
  180. package/dist/client/queryBuilder.d.ts +0 -15
  181. package/dist/client/queryBuilder.d.ts.map +1 -1
  182. package/dist/client/queryBuilder.js +0 -23
  183. package/dist/client/queryBuilder.js.map +1 -1
  184. package/dist/client/registry.d.ts +77 -0
  185. package/dist/client/registry.d.ts.map +1 -0
  186. package/dist/client/registry.js +95 -0
  187. package/dist/client/registry.js.map +1 -0
  188. package/dist/client/schema/defineContentType.d.ts +36 -24
  189. package/dist/client/schema/defineContentType.d.ts.map +1 -1
  190. package/dist/client/schema/defineContentType.js +176 -128
  191. package/dist/client/schema/defineContentType.js.map +1 -1
  192. package/dist/client/schema/typedClient.d.ts.map +1 -1
  193. package/dist/client/schema/typedClient.js +2 -10
  194. package/dist/client/schema/typedClient.js.map +1 -1
  195. package/dist/client/schema/types.d.ts +16 -9
  196. package/dist/client/schema/types.d.ts.map +1 -1
  197. package/dist/client/schema/types.js.map +1 -1
  198. package/dist/client/utils/toSlug.d.ts +60 -0
  199. package/dist/client/utils/toSlug.d.ts.map +1 -0
  200. package/dist/client/utils/toSlug.js +31 -0
  201. package/dist/client/utils/toSlug.js.map +1 -0
  202. package/dist/client/wrapper.d.ts +2 -2
  203. package/dist/client/wrapper.d.ts.map +1 -1
  204. package/dist/client/wrapper.js +22 -30
  205. package/dist/client/wrapper.js.map +1 -1
  206. package/dist/component/_generated/component.d.ts +24 -28
  207. package/dist/component/_generated/component.d.ts.map +1 -1
  208. package/dist/component/authorizationHooks.d.ts +1 -1
  209. package/dist/component/authorizationHooks.d.ts.map +1 -1
  210. package/dist/component/authorizationHooks.js +2 -2
  211. package/dist/component/authorizationHooks.js.map +1 -1
  212. package/dist/component/bulkOperations.d.ts.map +1 -1
  213. package/dist/component/bulkOperations.js +7 -4
  214. package/dist/component/bulkOperations.js.map +1 -1
  215. package/dist/component/contentEntries.d.ts +18 -56
  216. package/dist/component/contentEntries.d.ts.map +1 -1
  217. package/dist/component/contentEntries.js +45 -137
  218. package/dist/component/contentEntries.js.map +1 -1
  219. package/dist/component/contentEntryMutations.d.ts +14 -14
  220. package/dist/component/contentEntryMutations.d.ts.map +1 -1
  221. package/dist/component/contentEntryMutations.js +40 -43
  222. package/dist/component/contentEntryMutations.js.map +1 -1
  223. package/dist/component/contentEntryValidation.d.ts +3 -3
  224. package/dist/component/contentEntryValidation.js +6 -9
  225. package/dist/component/contentEntryValidation.js.map +1 -1
  226. package/dist/component/contentLock.d.ts +7 -7
  227. package/dist/component/contentLock.js +3 -3
  228. package/dist/component/contentLock.js.map +1 -1
  229. package/dist/component/contentTypeMigration.d.ts +1 -1
  230. package/dist/component/contentTypeMigration.js +2 -2
  231. package/dist/component/contentTypeMigration.js.map +1 -1
  232. package/dist/component/contentTypeMutations.d.ts.map +1 -1
  233. package/dist/component/contentTypeMutations.js +7 -6
  234. package/dist/component/contentTypeMutations.js.map +1 -1
  235. package/dist/component/convex.config.d.ts.map +1 -1
  236. package/dist/component/convex.config.js +1 -1
  237. package/dist/component/convex.config.js.map +1 -1
  238. package/dist/component/eventEmitter.d.ts +0 -1
  239. package/dist/component/eventEmitter.d.ts.map +1 -1
  240. package/dist/component/eventEmitter.js.map +1 -1
  241. package/dist/component/exportImport.d.ts +37 -37
  242. package/dist/component/exportImport.d.ts.map +1 -1
  243. package/dist/component/exportImport.js +34 -34
  244. package/dist/component/exportImport.js.map +1 -1
  245. package/dist/component/lib/deepReferenceResolver.d.ts +2 -2
  246. package/dist/component/lib/deepReferenceResolver.d.ts.map +1 -1
  247. package/dist/component/lib/deepReferenceResolver.js +13 -8
  248. package/dist/component/lib/deepReferenceResolver.js.map +1 -1
  249. package/dist/component/lib/ragContentChunker.d.ts +3 -3
  250. package/dist/component/lib/ragContentChunker.d.ts.map +1 -1
  251. package/dist/component/lib/ragContentChunker.js +4 -4
  252. package/dist/component/lib/ragContentChunker.js.map +1 -1
  253. package/dist/component/lib/referenceResolver.d.ts.map +1 -1
  254. package/dist/component/lib/referenceResolver.js +10 -17
  255. package/dist/component/lib/referenceResolver.js.map +1 -1
  256. package/dist/component/mediaAssetMutations.js +4 -4
  257. package/dist/component/mediaAssetMutations.js.map +1 -1
  258. package/dist/component/ragContentIndexer.d.ts +2 -2
  259. package/dist/component/ragContentIndexer.d.ts.map +1 -1
  260. package/dist/component/ragContentIndexer.js +44 -48
  261. package/dist/component/ragContentIndexer.js.map +1 -1
  262. package/dist/component/roles.d.ts +3 -3
  263. package/dist/component/scheduledPublish.d.ts +4 -4
  264. package/dist/component/scheduledPublish.js +3 -3
  265. package/dist/component/scheduledPublish.js.map +1 -1
  266. package/dist/component/schema.d.ts +18 -18
  267. package/dist/component/schema.js +5 -5
  268. package/dist/component/schema.js.map +1 -1
  269. package/dist/component/trash.d.ts +6 -9
  270. package/dist/component/trash.d.ts.map +1 -1
  271. package/dist/component/trash.js +12 -36
  272. package/dist/component/trash.js.map +1 -1
  273. package/dist/component/userContext.d.ts +1 -2
  274. package/dist/component/userContext.d.ts.map +1 -1
  275. package/dist/component/userContext.js +1 -2
  276. package/dist/component/userContext.js.map +1 -1
  277. package/dist/component/validators.d.ts +27 -33
  278. package/dist/component/validators.d.ts.map +1 -1
  279. package/dist/component/validators.js +3 -5
  280. package/dist/component/validators.js.map +1 -1
  281. package/dist/component/versionMutations.d.ts +1 -1
  282. package/dist/component/webhookTrigger.d.ts +14 -14
  283. package/dist/test.d.ts +30 -30
  284. package/dist/test.d.ts.map +1 -1
  285. package/dist/test.js +24 -24
  286. package/dist/test.js.map +1 -1
  287. package/package.json +1 -1
  288. package/admin-dist/public/assets/CmsEmptyState-Do_erIgn.js +0 -5
  289. package/admin-dist/public/assets/CmsPageHeader-qDwPGi48.js +0 -1
  290. package/admin-dist/public/assets/CmsStatusBadge-Dd9uToHE.js +0 -1
  291. package/admin-dist/public/assets/CmsToolbar-D1-Y-7SK.js +0 -1
  292. package/admin-dist/public/assets/ContentEntryEditor-CWBiIx52.js +0 -4
  293. package/admin-dist/public/assets/TaxonomyFilter-CdYQawxb.js +0 -1
  294. package/admin-dist/public/assets/_contentTypeId-D9VMP6Gs.js +0 -1
  295. package/admin-dist/public/assets/_entryId-2FlCfqE7.js +0 -1
  296. package/admin-dist/public/assets/alert-GxZx0y5c.js +0 -1
  297. package/admin-dist/public/assets/badge-BAlGIjop.js +0 -1
  298. package/admin-dist/public/assets/command-di7XCqcv.js +0 -1
  299. package/admin-dist/public/assets/content-D8zELsDG.js +0 -1
  300. package/admin-dist/public/assets/content-types-BmzD0krT.js +0 -2
  301. package/admin-dist/public/assets/globals-BvFfH-v9.css +0 -1
  302. package/admin-dist/public/assets/index-zqfj4T_v.js +0 -1
  303. package/admin-dist/public/assets/label-B6PPtKR5.js +0 -1
  304. package/admin-dist/public/assets/link-2-W2fVnVOf.js +0 -1
  305. package/admin-dist/public/assets/list-F8O0lZXC.js +0 -1
  306. package/admin-dist/public/assets/main-dZT72bAG.js +0 -97
  307. package/admin-dist/public/assets/media-CETueFbV.js +0 -1
  308. package/admin-dist/public/assets/new._contentTypeId-BV2-TyyR.js +0 -1
  309. package/admin-dist/public/assets/plus-AABQIF0N.js +0 -1
  310. package/admin-dist/public/assets/scroll-area-CDfk-zrz.js +0 -1
  311. package/admin-dist/public/assets/select-BuiHcMzS.js +0 -1
  312. package/admin-dist/public/assets/settings-DBxbYDvn.js +0 -1
  313. package/admin-dist/public/assets/switch-DiJvolcs.js +0 -1
  314. package/admin-dist/public/assets/tabs-Cgz6G_Xy.js +0 -1
  315. package/admin-dist/public/assets/tanstack-adapter-BknsSgra.js +0 -1
  316. package/admin-dist/public/assets/taxonomies-DOErsLl5.js +0 -1
  317. package/admin-dist/public/assets/textarea-CgggMxUX.js +0 -1
  318. package/admin-dist/public/assets/trash-BU4ANuaW.js +0 -1
  319. package/admin-dist/public/assets/triangle-alert-lvCbwp0s.js +0 -1
  320. package/admin-dist/public/assets/usePermissions-D7tQowaF.js +0 -1
  321. package/admin-dist/server/_libs/h3-v2.mjs +0 -277
  322. package/admin-dist/server/_ssr/CmsButton-DbzfJru_.mjs +0 -125
  323. package/admin-dist/server/_ssr/CmsEmptyState-CuvcXr3Z.mjs +0 -290
  324. package/admin-dist/server/_ssr/_tanstack-start-manifest_v-Dk-FIYPN.mjs +0 -4
  325. package/admin-dist/server/_ssr/content-types-D25lUE-j.mjs +0 -1312
  326. package/admin-dist/server/_ssr/label-PblVvdRv.mjs +0 -22
  327. package/admin-dist/server/_ssr/router-x6Ab8T4s.mjs +0 -1622
  328. package/admin-dist/server/_ssr/select-CrfEkFJw.mjs +0 -142
  329. package/admin-dist/server/_ssr/textarea-CZVaroMc.mjs +0 -18
@@ -0,0 +1,3041 @@
1
+ import { c as createRouter, a as createRootRoute, b as createFileRoute, l as lazyRouteComponent, O as Outlet, H as HeadContent, S as Scripts, u as useRouterState, L as Link, d as useNavigate } from "../_chunks/_libs/@tanstack/react-router.mjs";
2
+ import { r as reactExports, j as jsxRuntimeExports } from "../_chunks/_libs/react.mjs";
3
+ import { c as clsx } from "../_libs/clsx.mjs";
4
+ import { t as twMerge } from "../_libs/tailwind-merge.mjs";
5
+ import { R as Root$1, C as CollapsibleTrigger$1, a as CollapsibleContent$1 } from "../_chunks/_libs/@radix-ui/react-collapsible.mjs";
6
+ import { R as Root$3, C as Content, a as Close, T as Title, D as Description, P as Portal$2, O as Overlay } from "../_chunks/_libs/@radix-ui/react-dialog.mjs";
7
+ import { S as Slot } from "../_chunks/_libs/@radix-ui/react-slot.mjs";
8
+ import { c as cva } from "../_libs/class-variance-authority.mjs";
9
+ import { R as Root$2 } from "../_chunks/_libs/@radix-ui/react-label.mjs";
10
+ import { C as Checkbox$1, a as CheckboxIndicator } from "../_chunks/_libs/@radix-ui/react-checkbox.mjs";
11
+ import { R as Root2$2, T as Trigger$2, I as Icon$1, V as Value, P as Portal$1, C as Content2$2, a as Viewport, b as Item, c as ItemIndicator, d as ItemText, S as ScrollUpButton, e as ScrollDownButton } from "../_chunks/_libs/@radix-ui/react-select.mjs";
12
+ import { R as Root2$1, T as Trigger$1, P as Portal2, C as Content2$1, L as Label2, S as Separator2, I as Item2 } from "../_chunks/_libs/@radix-ui/react-dropdown-menu.mjs";
13
+ import { R as Root, I as Image, F as Fallback } from "../_chunks/_libs/@radix-ui/react-avatar.mjs";
14
+ import { R as Root2, T as Trigger, P as Portal, C as Content2 } from "../_chunks/_libs/@radix-ui/react-popover.mjs";
15
+ import { c as createServerFn, T as TSS_SERVER_FUNCTION, g as getServerFnById } from "./index.mjs";
16
+ import { v, c as componentsGeneric, C as ConvexReactClient, a as ConvexProvider, b as anyApi, u as useQuery, d as useMutation } from "../_libs/convex.mjs";
17
+ import { L as LoaderCircle, a as Layers, H as House, B as Bell, C as CircleQuestionMark, b as Book, c as Code, M as MessageSquare, E as ExternalLink, d as ChevronDown, U as User, e as LogOut, f as CodeXml, P as Plus, g as ChevronUp, X, h as ChevronRight, i as Check, j as CircleAlert, k as Eye, S as SquarePen, A as Archive, l as Bookmark, F as Flag, m as Heart, n as Star, o as Package, p as Phone, q as Mail, D as DollarSign, r as MapPin, s as Folder, t as Braces, u as SquareCheckBig, T as ToggleLeft, v as Hash, w as Link$1, x as Clock, y as Calendar, G as Globe, z as Lock, I as Trash2, J as Settings, K as FileCode, N as Tags, O as Image$1, Q as FileText, R as LayoutDashboard, V as FolderOpen, W as Tag, Y as List, Z as Link2, _ as FileType, $ as TextAlignStart, a0 as TriangleAlert } from "../_libs/lucide-react.mjs";
18
+ import { o as object, b as boolean, s as string, _ as _enum, n as number, a as array, r as record } from "../_libs/zod.mjs";
19
+ import "../_libs/tiny-warning.mjs";
20
+ import "../_chunks/_libs/@tanstack/router-core.mjs";
21
+ import "../_chunks/_libs/@tanstack/store.mjs";
22
+ import "../_chunks/_libs/@tanstack/history.mjs";
23
+ import "../_libs/tiny-invariant.mjs";
24
+ import "node:stream/web";
25
+ import "node:stream";
26
+ import "../_chunks/_libs/react-dom.mjs";
27
+ import "util";
28
+ import "crypto";
29
+ import "async_hooks";
30
+ import "stream";
31
+ import "../_libs/isbot.mjs";
32
+ import "../_chunks/_libs/@tanstack/react-store.mjs";
33
+ import "../_libs/use-sync-external-store.mjs";
34
+ import "../_chunks/_libs/@radix-ui/primitive.mjs";
35
+ import "../_chunks/_libs/@radix-ui/react-context.mjs";
36
+ import "../_chunks/_libs/@radix-ui/react-use-controllable-state.mjs";
37
+ import "../_chunks/_libs/@radix-ui/react-use-layout-effect.mjs";
38
+ import "../_chunks/_libs/@radix-ui/react-compose-refs.mjs";
39
+ import "../_chunks/_libs/@radix-ui/react-primitive.mjs";
40
+ import "../_chunks/_libs/@radix-ui/react-presence.mjs";
41
+ import "../_chunks/_libs/@radix-ui/react-id.mjs";
42
+ import "../_chunks/_libs/@radix-ui/react-dismissable-layer.mjs";
43
+ import "../_chunks/_libs/@radix-ui/react-use-callback-ref.mjs";
44
+ import "../_chunks/_libs/@radix-ui/react-use-escape-keydown.mjs";
45
+ import "../_chunks/_libs/@radix-ui/react-focus-scope.mjs";
46
+ import "../_chunks/_libs/@radix-ui/react-portal.mjs";
47
+ import "../_chunks/_libs/@radix-ui/react-focus-guards.mjs";
48
+ import "../_libs/react-remove-scroll.mjs";
49
+ import "../_libs/tslib.mjs";
50
+ import "../_libs/react-remove-scroll-bar.mjs";
51
+ import "../_libs/react-style-singleton.mjs";
52
+ import "../_libs/get-nonce.mjs";
53
+ import "../_libs/use-sidecar.mjs";
54
+ import "../_libs/use-callback-ref.mjs";
55
+ import "../_libs/aria-hidden.mjs";
56
+ import "../_chunks/_libs/@radix-ui/react-use-previous.mjs";
57
+ import "../_chunks/_libs/@radix-ui/react-use-size.mjs";
58
+ import "../_chunks/_libs/@radix-ui/number.mjs";
59
+ import "../_chunks/_libs/@radix-ui/react-collection.mjs";
60
+ import "../_chunks/_libs/@radix-ui/react-direction.mjs";
61
+ import "../_chunks/_libs/@radix-ui/react-popper.mjs";
62
+ import "../_chunks/_libs/@floating-ui/react-dom.mjs";
63
+ import "../_chunks/_libs/@floating-ui/dom.mjs";
64
+ import "../_chunks/_libs/@floating-ui/core.mjs";
65
+ import "../_chunks/_libs/@floating-ui/utils.mjs";
66
+ import "../_chunks/_libs/@radix-ui/react-arrow.mjs";
67
+ import "../_chunks/_libs/@radix-ui/react-visually-hidden.mjs";
68
+ import "../_chunks/_libs/@radix-ui/react-menu.mjs";
69
+ import "../_chunks/_libs/@radix-ui/react-roving-focus.mjs";
70
+ import "../_chunks/_libs/@radix-ui/react-use-is-hydrated.mjs";
71
+ import "node:async_hooks";
72
+ const globalsCss = "/assets/globals-CoCRjt0K.css";
73
+ function cn(...inputs) {
74
+ return twMerge(clsx(inputs));
75
+ }
76
+ v.union(
77
+ v.literal("admin"),
78
+ v.literal("editor"),
79
+ v.literal("author"),
80
+ v.literal("viewer")
81
+ );
82
+ const resourceValidator = v.union(
83
+ v.literal("contentTypes"),
84
+ v.literal("contentEntries"),
85
+ v.literal("mediaItems"),
86
+ v.literal("settings")
87
+ );
88
+ const actionValidator = v.union(
89
+ v.literal("create"),
90
+ v.literal("read"),
91
+ v.literal("update"),
92
+ v.literal("delete"),
93
+ v.literal("publish"),
94
+ v.literal("unpublish"),
95
+ v.literal("restore"),
96
+ v.literal("manage"),
97
+ v.literal("move")
98
+ );
99
+ v.object({
100
+ resource: resourceValidator,
101
+ action: actionValidator,
102
+ scope: v.optional(v.union(v.literal("all"), v.literal("own")))
103
+ });
104
+ function fullCrud(resource, scope = "all") {
105
+ return [
106
+ { resource, action: "create", scope },
107
+ { resource, action: "read", scope },
108
+ { resource, action: "update", scope },
109
+ { resource, action: "delete", scope }
110
+ ];
111
+ }
112
+ function readOnly(resource, scope = "all") {
113
+ return [{ resource, action: "read", scope }];
114
+ }
115
+ function publishPermissions(scope = "all") {
116
+ return [
117
+ { resource: "contentEntries", action: "publish", scope },
118
+ { resource: "contentEntries", action: "unpublish", scope }
119
+ ];
120
+ }
121
+ const ADMIN_ROLE = {
122
+ name: "admin",
123
+ displayName: "Administrator",
124
+ description: "Full access to all CMS features including settings and content type management",
125
+ isSystem: true,
126
+ permissions: [
127
+ // Content types - full management
128
+ ...fullCrud("contentTypes"),
129
+ // Content entries - full CRUD + publish
130
+ ...fullCrud("contentEntries"),
131
+ ...publishPermissions(),
132
+ { resource: "contentEntries", action: "restore" },
133
+ // Media - full management
134
+ ...fullCrud("mediaItems"),
135
+ // Settings - full access
136
+ { resource: "settings", action: "manage" },
137
+ ...readOnly("settings")
138
+ ]
139
+ };
140
+ const EDITOR_ROLE = {
141
+ name: "editor",
142
+ displayName: "Editor",
143
+ description: "Can manage all content and media, but cannot modify settings or content types",
144
+ isSystem: true,
145
+ permissions: [
146
+ // Content types - read only
147
+ ...readOnly("contentTypes"),
148
+ // Content entries - full CRUD + publish
149
+ ...fullCrud("contentEntries"),
150
+ ...publishPermissions(),
151
+ { resource: "contentEntries", action: "restore" },
152
+ // Media - full management
153
+ ...fullCrud("mediaItems")
154
+ ]
155
+ };
156
+ const AUTHOR_ROLE = {
157
+ name: "author",
158
+ displayName: "Author",
159
+ description: "Can create and manage own content and media",
160
+ isSystem: true,
161
+ permissions: [
162
+ // Content types - read only
163
+ ...readOnly("contentTypes"),
164
+ // Content entries - own content only
165
+ { resource: "contentEntries", action: "create" },
166
+ { resource: "contentEntries", action: "read", scope: "own" },
167
+ { resource: "contentEntries", action: "update", scope: "own" },
168
+ { resource: "contentEntries", action: "delete", scope: "own" },
169
+ // Authors can publish/unpublish their own content
170
+ { resource: "contentEntries", action: "publish", scope: "own" },
171
+ { resource: "contentEntries", action: "unpublish", scope: "own" },
172
+ // Media - can create and manage own, read all (for embedding)
173
+ { resource: "mediaItems", action: "create" },
174
+ { resource: "mediaItems", action: "read", scope: "all" },
175
+ // Can read all for embedding
176
+ { resource: "mediaItems", action: "update", scope: "own" },
177
+ { resource: "mediaItems", action: "delete", scope: "own" }
178
+ ]
179
+ };
180
+ const VIEWER_ROLE = {
181
+ name: "viewer",
182
+ displayName: "Viewer",
183
+ description: "Read-only access to published content and media",
184
+ isSystem: true,
185
+ permissions: [
186
+ // Content types - read only
187
+ ...readOnly("contentTypes"),
188
+ // Content entries - read published only (scope: "all" means all published)
189
+ ...readOnly("contentEntries"),
190
+ // Media - read only
191
+ ...readOnly("mediaItems")
192
+ ]
193
+ };
194
+ const DEFAULT_ROLES = {
195
+ admin: ADMIN_ROLE,
196
+ editor: EDITOR_ROLE,
197
+ author: AUTHOR_ROLE,
198
+ viewer: VIEWER_ROLE
199
+ };
200
+ function permissionMatches(granted, requested) {
201
+ if (granted.resource !== requested.resource || granted.action !== requested.action) {
202
+ return false;
203
+ }
204
+ const grantedScope = granted.scope ?? "all";
205
+ const requestedScope = requested.scope ?? "all";
206
+ if (grantedScope === "all") {
207
+ return true;
208
+ }
209
+ return requestedScope === "own";
210
+ }
211
+ function hasPermission(roleName, permission, customRoles) {
212
+ const role = DEFAULT_ROLES[roleName] ?? customRoles?.[roleName];
213
+ if (!role) {
214
+ return false;
215
+ }
216
+ return role.permissions.some((p) => permissionMatches(p, permission));
217
+ }
218
+ function getRolePermissions(roleName, customRoles) {
219
+ const role = DEFAULT_ROLES[roleName] ?? customRoles?.[roleName];
220
+ return role?.permissions ?? [];
221
+ }
222
+ function getRole(roleName, customRoles) {
223
+ return DEFAULT_ROLES[roleName] ?? customRoles?.[roleName];
224
+ }
225
+ function getResourcePermissions(roleName, resource, customRoles) {
226
+ return getRolePermissions(roleName, customRoles).filter(
227
+ (p) => p.resource === resource
228
+ );
229
+ }
230
+ function canAccessResource(roleName, resource, customRoles) {
231
+ return getResourcePermissions(roleName, resource, customRoles).length > 0;
232
+ }
233
+ const AuthContext = reactExports.createContext(null);
234
+ function AuthProvider({
235
+ children,
236
+ getUser,
237
+ getUserRole,
238
+ onLogout,
239
+ autoRedirectToLogin = false,
240
+ loginUrl = "/login"
241
+ }) {
242
+ const [user, setUser] = reactExports.useState(null);
243
+ const [role, setRole] = reactExports.useState(null);
244
+ const [authState, setAuthState] = reactExports.useState("loading");
245
+ const [error, setError] = reactExports.useState(null);
246
+ const loadAuth = reactExports.useCallback(async () => {
247
+ setAuthState("loading");
248
+ setError(null);
249
+ try {
250
+ const currentUser = await getUser();
251
+ if (!currentUser) {
252
+ setUser(null);
253
+ setRole(null);
254
+ setAuthState("unauthenticated");
255
+ if (autoRedirectToLogin && typeof window !== "undefined") {
256
+ window.location.href = loginUrl;
257
+ }
258
+ return;
259
+ }
260
+ const userRole = await getUserRole({ userId: currentUser.id });
261
+ setUser(currentUser);
262
+ setRole(userRole);
263
+ setAuthState("authenticated");
264
+ } catch (err) {
265
+ console.error("Authentication error:", err);
266
+ setUser(null);
267
+ setRole(null);
268
+ setError(err instanceof Error ? err.message : "Authentication failed");
269
+ setAuthState("error");
270
+ }
271
+ }, [getUser, getUserRole, autoRedirectToLogin, loginUrl]);
272
+ reactExports.useEffect(() => {
273
+ loadAuth();
274
+ }, [loadAuth]);
275
+ const checkPermission = reactExports.useCallback(
276
+ (permission) => {
277
+ if (!role) {
278
+ return false;
279
+ }
280
+ return hasPermission(role, permission);
281
+ },
282
+ [role]
283
+ );
284
+ const logout = reactExports.useCallback(async () => {
285
+ try {
286
+ if (onLogout) {
287
+ await onLogout();
288
+ }
289
+ setUser(null);
290
+ setRole(null);
291
+ setAuthState("unauthenticated");
292
+ if (autoRedirectToLogin && typeof window !== "undefined") {
293
+ window.location.href = loginUrl;
294
+ }
295
+ } catch (err) {
296
+ console.error("Logout error:", err);
297
+ setError(err instanceof Error ? err.message : "Logout failed");
298
+ }
299
+ }, [onLogout, autoRedirectToLogin, loginUrl]);
300
+ const refresh = reactExports.useCallback(async () => {
301
+ await loadAuth();
302
+ }, [loadAuth]);
303
+ const value = {
304
+ user,
305
+ role,
306
+ authState,
307
+ isLoading: authState === "loading",
308
+ isAuthenticated: authState === "authenticated",
309
+ error,
310
+ checkPermission,
311
+ logout,
312
+ refresh
313
+ };
314
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(AuthContext.Provider, { value, children });
315
+ }
316
+ function useAuth() {
317
+ const context = reactExports.useContext(AuthContext);
318
+ if (!context) {
319
+ throw new Error("useAuth must be used within an AuthProvider");
320
+ }
321
+ return context;
322
+ }
323
+ const ThemeContext = reactExports.createContext(null);
324
+ const STORAGE_KEY = "convex-cms-theme";
325
+ function getSystemTheme() {
326
+ if (typeof window === "undefined") return "light";
327
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
328
+ }
329
+ function getStoredTheme() {
330
+ if (typeof window === "undefined") return "system";
331
+ const stored = localStorage.getItem(STORAGE_KEY);
332
+ if (stored === "light" || stored === "dark" || stored === "system") {
333
+ return stored;
334
+ }
335
+ return "system";
336
+ }
337
+ function ThemeProvider({ children }) {
338
+ const [theme, setThemeState] = reactExports.useState(() => getStoredTheme());
339
+ const [resolvedTheme, setResolvedTheme] = reactExports.useState(() => {
340
+ const stored = getStoredTheme();
341
+ return stored === "system" ? getSystemTheme() : stored;
342
+ });
343
+ const applyTheme = reactExports.useCallback((newTheme) => {
344
+ const resolved = newTheme === "system" ? getSystemTheme() : newTheme;
345
+ setResolvedTheme(resolved);
346
+ const root = document.documentElement;
347
+ root.classList.remove("light", "dark");
348
+ root.classList.add(resolved);
349
+ }, []);
350
+ const setTheme = reactExports.useCallback(
351
+ (newTheme) => {
352
+ setThemeState(newTheme);
353
+ localStorage.setItem(STORAGE_KEY, newTheme);
354
+ applyTheme(newTheme);
355
+ },
356
+ [applyTheme]
357
+ );
358
+ reactExports.useEffect(() => {
359
+ applyTheme(theme);
360
+ }, [theme, applyTheme]);
361
+ reactExports.useEffect(() => {
362
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
363
+ const handleChange = () => {
364
+ if (theme === "system") {
365
+ applyTheme("system");
366
+ }
367
+ };
368
+ mediaQuery.addEventListener("change", handleChange);
369
+ return () => mediaQuery.removeEventListener("change", handleChange);
370
+ }, [theme, applyTheme]);
371
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(ThemeContext.Provider, { value: { theme, resolvedTheme, setTheme }, children });
372
+ }
373
+ function useTheme() {
374
+ const context = reactExports.useContext(ThemeContext);
375
+ if (!context) {
376
+ throw new Error("useTheme must be used within a ThemeProvider");
377
+ }
378
+ return context;
379
+ }
380
+ const navItemSchema = object({
381
+ id: string(),
382
+ path: string(),
383
+ label: string(),
384
+ icon: string(),
385
+ visible: boolean().default(true),
386
+ section: _enum(["main", "config"]).default("main"),
387
+ badge: string().optional(),
388
+ exact: boolean().optional()
389
+ });
390
+ const brandingSchema = object({
391
+ appName: string().default("Convex CMS"),
392
+ logo: string().optional(),
393
+ favicon: string().optional()
394
+ });
395
+ const layoutSchema = object({
396
+ sidebarWidth: number().min(200).max(400).default(256),
397
+ sidebarCollapsible: boolean().default(false)
398
+ });
399
+ const navigationSchema = object({
400
+ showDashboard: boolean().default(true),
401
+ showContent: boolean().default(true),
402
+ showMedia: boolean().default(true),
403
+ showTaxonomies: boolean().default(true),
404
+ showContentTypes: boolean().default(true),
405
+ showTrash: boolean().default(true),
406
+ showSettings: boolean().default(true),
407
+ customItems: array(navItemSchema).default([])
408
+ });
409
+ const themeSchema = object({
410
+ mode: _enum(["light", "dark", "system"]).default("system"),
411
+ allowModeSwitch: boolean().default(true),
412
+ tokens: record(string(), string()).optional()
413
+ });
414
+ const adminConfigSchema = object({
415
+ branding: brandingSchema.default(() => brandingSchema.parse({})),
416
+ layout: layoutSchema.default(() => layoutSchema.parse({})),
417
+ navigation: navigationSchema.default(() => navigationSchema.parse({})),
418
+ theme: themeSchema.default(() => themeSchema.parse({}))
419
+ });
420
+ const DEFAULT_NAV_ITEMS = [
421
+ {
422
+ id: "dashboard",
423
+ path: "/",
424
+ label: "Dashboard",
425
+ icon: "LayoutDashboard",
426
+ section: "main",
427
+ exact: true
428
+ },
429
+ { id: "content", path: "/content", label: "Content", icon: "FileText", section: "main" },
430
+ { id: "media", path: "/media", label: "Media", icon: "Image", section: "main" },
431
+ { id: "taxonomies", path: "/taxonomies", label: "Taxonomies", icon: "Tags", section: "main" },
432
+ {
433
+ id: "content-types",
434
+ path: "/content-types",
435
+ label: "Content Types",
436
+ icon: "Layers",
437
+ section: "config"
438
+ },
439
+ { id: "trash", path: "/trash", label: "Trash", icon: "Trash2", section: "config" },
440
+ { id: "settings", path: "/settings", label: "Settings", icon: "Settings", section: "config" }
441
+ ];
442
+ function resolveAdminConfig(input) {
443
+ return adminConfigSchema.parse(input ?? {});
444
+ }
445
+ function getVisibleNavItems(config) {
446
+ const visibilityMap = {
447
+ dashboard: config.navigation.showDashboard,
448
+ content: config.navigation.showContent,
449
+ media: config.navigation.showMedia,
450
+ taxonomies: config.navigation.showTaxonomies,
451
+ "content-types": config.navigation.showContentTypes,
452
+ trash: config.navigation.showTrash,
453
+ settings: config.navigation.showSettings
454
+ };
455
+ const filtered = DEFAULT_NAV_ITEMS.filter((item) => visibilityMap[item.id] !== false);
456
+ const allItems = [...filtered, ...config.navigation.customItems.filter((i) => i.visible !== false)];
457
+ return {
458
+ main: allItems.filter((i) => i.section === "main"),
459
+ config: allItems.filter((i) => i.section === "config")
460
+ };
461
+ }
462
+ const AdminConfigContext = reactExports.createContext(null);
463
+ function AdminConfigProvider({
464
+ config,
465
+ children
466
+ }) {
467
+ const navItems = getVisibleNavItems(config);
468
+ const value = { ...config, navItems };
469
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(AdminConfigContext.Provider, { value, children });
470
+ }
471
+ function useAdminConfig() {
472
+ const config = reactExports.useContext(AdminConfigContext);
473
+ if (!config) {
474
+ throw new Error("useAdminConfig must be used within AdminConfigProvider");
475
+ }
476
+ return config;
477
+ }
478
+ const api = anyApi;
479
+ componentsGeneric();
480
+ const SettingsConfigContext = reactExports.createContext(null);
481
+ function SettingsConfigProvider({
482
+ baseConfig,
483
+ children,
484
+ api: api$1
485
+ }) {
486
+ const resolvedApi = api$1 ?? api.admin;
487
+ const settings = useQuery(resolvedApi.getSettings);
488
+ const mergedConfig = reactExports.useMemo(() => {
489
+ if (!settings) return baseConfig;
490
+ return {
491
+ ...baseConfig,
492
+ navigation: {
493
+ ...baseConfig.navigation,
494
+ showMedia: baseConfig.navigation.showMedia && settings.features.mediaManagement
495
+ }
496
+ };
497
+ }, [baseConfig, settings]);
498
+ const contextValue = reactExports.useMemo(
499
+ () => ({ baseConfig, settings }),
500
+ [baseConfig, settings]
501
+ );
502
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsConfigContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntimeExports.jsx(AdminConfigProvider, { config: mergedConfig, children }) });
503
+ }
504
+ function useSettingsConfig() {
505
+ const ctx = reactExports.useContext(SettingsConfigContext);
506
+ if (!ctx) {
507
+ throw new Error("useSettingsConfig must be used within SettingsConfigProvider");
508
+ }
509
+ return ctx;
510
+ }
511
+ const BreadcrumbContext = reactExports.createContext(null);
512
+ function BreadcrumbProvider({ children }) {
513
+ const [overrides, setOverrides] = reactExports.useState(/* @__PURE__ */ new Map());
514
+ const setOverride = reactExports.useCallback((path, label) => {
515
+ setOverrides((prev) => {
516
+ const next = new Map(prev);
517
+ next.set(path, label);
518
+ return next;
519
+ });
520
+ }, []);
521
+ const clearOverride = reactExports.useCallback((path) => {
522
+ setOverrides((prev) => {
523
+ const next = new Map(prev);
524
+ next.delete(path);
525
+ return next;
526
+ });
527
+ }, []);
528
+ const value = reactExports.useMemo(
529
+ () => ({ overrides, setOverride, clearOverride }),
530
+ [overrides, setOverride, clearOverride]
531
+ );
532
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(BreadcrumbContext.Provider, { value, children });
533
+ }
534
+ function useBreadcrumbContext() {
535
+ const context = reactExports.useContext(BreadcrumbContext);
536
+ if (!context) {
537
+ throw new Error("useBreadcrumbContext must be used within a BreadcrumbProvider");
538
+ }
539
+ return context;
540
+ }
541
+ const iconRegistry = {
542
+ LayoutDashboard,
543
+ FileText,
544
+ Image: Image$1,
545
+ Layers,
546
+ Tags,
547
+ FileCode,
548
+ Settings,
549
+ Trash2,
550
+ HelpCircle: CircleQuestionMark,
551
+ Home: House,
552
+ User,
553
+ Bell,
554
+ Lock,
555
+ Globe,
556
+ Calendar,
557
+ Clock,
558
+ Link: Link$1,
559
+ Hash,
560
+ ToggleLeft,
561
+ ChevronDown,
562
+ CheckSquare: SquareCheckBig,
563
+ Braces,
564
+ Folder,
565
+ MapPin,
566
+ DollarSign,
567
+ Mail,
568
+ Phone,
569
+ Package,
570
+ Star,
571
+ Heart,
572
+ Flag,
573
+ Bookmark,
574
+ Archive,
575
+ Edit: SquarePen,
576
+ Eye,
577
+ AlertCircle: CircleAlert
578
+ };
579
+ function Icon({
580
+ name,
581
+ className = "size-5"
582
+ }) {
583
+ const IconComponent = iconRegistry[name];
584
+ if (!IconComponent) {
585
+ return null;
586
+ }
587
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(IconComponent, { className });
588
+ }
589
+ const Collapsible = Root$1;
590
+ const CollapsibleTrigger = CollapsibleTrigger$1;
591
+ const CollapsibleContent = CollapsibleContent$1;
592
+ function Dialog({
593
+ ...props
594
+ }) {
595
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Root$3, { "data-slot": "dialog", ...props });
596
+ }
597
+ function DialogPortal({
598
+ ...props
599
+ }) {
600
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$2, { "data-slot": "dialog-portal", ...props });
601
+ }
602
+ function DialogOverlay({
603
+ className,
604
+ ...props
605
+ }) {
606
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
607
+ Overlay,
608
+ {
609
+ "data-slot": "dialog-overlay",
610
+ className: cn(
611
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
612
+ className
613
+ ),
614
+ ...props
615
+ }
616
+ );
617
+ }
618
+ function DialogContent({
619
+ className,
620
+ children,
621
+ showCloseButton = true,
622
+ ...props
623
+ }) {
624
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [
625
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DialogOverlay, {}),
626
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
627
+ Content,
628
+ {
629
+ "data-slot": "dialog-content",
630
+ className: cn(
631
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg",
632
+ className
633
+ ),
634
+ ...props,
635
+ children: [
636
+ children,
637
+ showCloseButton && /* @__PURE__ */ jsxRuntimeExports.jsxs(
638
+ Close,
639
+ {
640
+ "data-slot": "dialog-close",
641
+ className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
642
+ children: [
643
+ /* @__PURE__ */ jsxRuntimeExports.jsx(X, {}),
644
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sr-only", children: "Close" })
645
+ ]
646
+ }
647
+ )
648
+ ]
649
+ }
650
+ )
651
+ ] });
652
+ }
653
+ function DialogHeader({ className, ...props }) {
654
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
655
+ "div",
656
+ {
657
+ "data-slot": "dialog-header",
658
+ className: cn("flex flex-col gap-2 text-center sm:text-left", className),
659
+ ...props
660
+ }
661
+ );
662
+ }
663
+ function DialogFooter({ className, ...props }) {
664
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
665
+ "div",
666
+ {
667
+ "data-slot": "dialog-footer",
668
+ className: cn(
669
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
670
+ className
671
+ ),
672
+ ...props
673
+ }
674
+ );
675
+ }
676
+ function DialogTitle({
677
+ className,
678
+ ...props
679
+ }) {
680
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
681
+ Title,
682
+ {
683
+ "data-slot": "dialog-title",
684
+ className: cn("text-lg leading-none font-semibold", className),
685
+ ...props
686
+ }
687
+ );
688
+ }
689
+ function DialogDescription({
690
+ className,
691
+ ...props
692
+ }) {
693
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
694
+ Description,
695
+ {
696
+ "data-slot": "dialog-description",
697
+ className: cn("text-muted-foreground text-sm", className),
698
+ ...props
699
+ }
700
+ );
701
+ }
702
+ const buttonVariants = cva(
703
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
704
+ {
705
+ variants: {
706
+ variant: {
707
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
708
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
709
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
710
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
711
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
712
+ link: "text-primary underline-offset-4 hover:underline"
713
+ },
714
+ size: {
715
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
716
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
717
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
718
+ icon: "size-9",
719
+ "icon-sm": "size-8",
720
+ "icon-lg": "size-10"
721
+ }
722
+ },
723
+ defaultVariants: {
724
+ variant: "default",
725
+ size: "default"
726
+ }
727
+ }
728
+ );
729
+ function Button({
730
+ className,
731
+ variant = "default",
732
+ size = "default",
733
+ asChild = false,
734
+ ...props
735
+ }) {
736
+ const Comp = asChild ? Slot : "button";
737
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
738
+ Comp,
739
+ {
740
+ "data-slot": "button",
741
+ "data-variant": variant,
742
+ "data-size": size,
743
+ className: cn(buttonVariants({ variant, size, className })),
744
+ ...props
745
+ }
746
+ );
747
+ }
748
+ const motion = {
749
+ fast: "duration-100 ease-out"
750
+ };
751
+ const variantMap = {
752
+ primary: "default",
753
+ secondary: "secondary",
754
+ danger: "destructive",
755
+ ghost: "ghost",
756
+ outline: "outline",
757
+ link: "link",
758
+ success: "default",
759
+ warning: "default"
760
+ };
761
+ const customVariantClasses = {
762
+ success: "bg-success text-success-foreground hover:bg-success/90 focus-visible:ring-success",
763
+ warning: "bg-warning text-warning-foreground hover:bg-warning/90 focus-visible:ring-warning"
764
+ };
765
+ const LoadingSpinner = () => /* @__PURE__ */ jsxRuntimeExports.jsxs(
766
+ "svg",
767
+ {
768
+ className: "size-4 animate-spin",
769
+ xmlns: "http://www.w3.org/2000/svg",
770
+ fill: "none",
771
+ viewBox: "0 0 24 24",
772
+ children: [
773
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
774
+ "circle",
775
+ {
776
+ className: "opacity-25",
777
+ cx: "12",
778
+ cy: "12",
779
+ r: "10",
780
+ stroke: "currentColor",
781
+ strokeWidth: "4"
782
+ }
783
+ ),
784
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
785
+ "path",
786
+ {
787
+ className: "opacity-75",
788
+ fill: "currentColor",
789
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
790
+ }
791
+ )
792
+ ]
793
+ }
794
+ );
795
+ function CmsButton({
796
+ variant = "primary",
797
+ loading,
798
+ disabled,
799
+ children,
800
+ className,
801
+ asChild,
802
+ ...props
803
+ }) {
804
+ const mappedVariant = variantMap[variant];
805
+ const customClass = customVariantClasses[variant];
806
+ if (asChild) {
807
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
808
+ Button,
809
+ {
810
+ variant: mappedVariant,
811
+ disabled: disabled || loading,
812
+ className: cn(motion.fast, customClass, className),
813
+ asChild: true,
814
+ ...props,
815
+ children
816
+ }
817
+ );
818
+ }
819
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
820
+ Button,
821
+ {
822
+ variant: mappedVariant,
823
+ disabled: disabled || loading,
824
+ className: cn(motion.fast, customClass, className),
825
+ ...props,
826
+ children: [
827
+ loading && /* @__PURE__ */ jsxRuntimeExports.jsx(LoadingSpinner, {}),
828
+ children
829
+ ]
830
+ }
831
+ );
832
+ }
833
+ const sizeClasses = {
834
+ sm: "max-w-sm",
835
+ md: "max-w-md",
836
+ lg: "max-w-lg",
837
+ xl: "max-w-xl",
838
+ "2xl": "max-w-2xl"
839
+ };
840
+ function CmsDialog({
841
+ open,
842
+ onOpenChange,
843
+ title,
844
+ description,
845
+ children,
846
+ footer,
847
+ size = "md",
848
+ className
849
+ }) {
850
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
851
+ DialogContent,
852
+ {
853
+ className: cn(
854
+ "flex max-h-[85vh] flex-col overflow-hidden",
855
+ sizeClasses[size],
856
+ className
857
+ ),
858
+ children: [
859
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { className: "shrink-0", children: [
860
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: title }),
861
+ description && /* @__PURE__ */ jsxRuntimeExports.jsx(DialogDescription, { children: description })
862
+ ] }),
863
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
864
+ "div",
865
+ {
866
+ className: "min-h-0 flex-1 overflow-y-auto py-4 [&::-webkit-scrollbar]:hidden",
867
+ style: { scrollbarWidth: "none", msOverflowStyle: "none" },
868
+ children
869
+ }
870
+ ),
871
+ footer && /* @__PURE__ */ jsxRuntimeExports.jsx(DialogFooter, { className: "shrink-0 border-t pt-4", children: footer })
872
+ ]
873
+ }
874
+ ) });
875
+ }
876
+ function CmsConfirmDialog({
877
+ open,
878
+ onOpenChange,
879
+ title,
880
+ description,
881
+ confirmLabel = "Confirm",
882
+ cancelLabel = "Cancel",
883
+ onConfirm,
884
+ onCancel,
885
+ variant = "default",
886
+ loading,
887
+ isLoading,
888
+ error
889
+ }) {
890
+ const isLoadingState = loading ?? isLoading ?? false;
891
+ const handleCancel = () => {
892
+ onCancel?.();
893
+ onOpenChange(false);
894
+ };
895
+ const handleConfirm = () => {
896
+ onConfirm();
897
+ };
898
+ const getButtonVariant = () => {
899
+ if (variant === "danger") return "danger";
900
+ if (variant === "warning") return "warning";
901
+ return "primary";
902
+ };
903
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
904
+ CmsDialog,
905
+ {
906
+ open,
907
+ onOpenChange,
908
+ title,
909
+ size: "sm",
910
+ footer: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
911
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CmsButton, { variant: "outline", onClick: handleCancel, disabled: isLoadingState, children: cancelLabel }),
912
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
913
+ CmsButton,
914
+ {
915
+ variant: getButtonVariant(),
916
+ onClick: handleConfirm,
917
+ loading: isLoadingState,
918
+ children: confirmLabel
919
+ }
920
+ )
921
+ ] }),
922
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
923
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground", children: description }),
924
+ error && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-destructive", children: error })
925
+ ] })
926
+ }
927
+ );
928
+ }
929
+ function Input({ className, type, ...props }) {
930
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
931
+ "input",
932
+ {
933
+ type,
934
+ "data-slot": "input",
935
+ className: cn(
936
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
937
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
938
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
939
+ className
940
+ ),
941
+ ...props
942
+ }
943
+ );
944
+ }
945
+ function Label({
946
+ className,
947
+ ...props
948
+ }) {
949
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
950
+ Root$2,
951
+ {
952
+ "data-slot": "label",
953
+ className: cn(
954
+ "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
955
+ className
956
+ ),
957
+ ...props
958
+ }
959
+ );
960
+ }
961
+ function Textarea({ className, ...props }) {
962
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
963
+ "textarea",
964
+ {
965
+ "data-slot": "textarea",
966
+ className: cn(
967
+ "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
968
+ className
969
+ ),
970
+ ...props
971
+ }
972
+ );
973
+ }
974
+ function Checkbox({
975
+ className,
976
+ ...props
977
+ }) {
978
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
979
+ Checkbox$1,
980
+ {
981
+ "data-slot": "checkbox",
982
+ className: cn(
983
+ "peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
984
+ className
985
+ ),
986
+ ...props,
987
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
988
+ CheckboxIndicator,
989
+ {
990
+ "data-slot": "checkbox-indicator",
991
+ className: "grid place-content-center text-current transition-none",
992
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5" })
993
+ }
994
+ )
995
+ }
996
+ );
997
+ }
998
+ function Select({
999
+ ...props
1000
+ }) {
1001
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Root2$2, { "data-slot": "select", ...props });
1002
+ }
1003
+ function SelectValue({
1004
+ ...props
1005
+ }) {
1006
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Value, { "data-slot": "select-value", ...props });
1007
+ }
1008
+ function SelectTrigger({
1009
+ className,
1010
+ size = "default",
1011
+ children,
1012
+ ...props
1013
+ }) {
1014
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1015
+ Trigger$2,
1016
+ {
1017
+ "data-slot": "select-trigger",
1018
+ "data-size": size,
1019
+ className: cn(
1020
+ "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1021
+ className
1022
+ ),
1023
+ ...props,
1024
+ children: [
1025
+ children,
1026
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Icon$1, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 opacity-50" }) })
1027
+ ]
1028
+ }
1029
+ );
1030
+ }
1031
+ function SelectContent({
1032
+ className,
1033
+ children,
1034
+ position = "item-aligned",
1035
+ align = "center",
1036
+ ...props
1037
+ }) {
1038
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
1039
+ Content2$2,
1040
+ {
1041
+ "data-slot": "select-content",
1042
+ className: cn(
1043
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
1044
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
1045
+ className
1046
+ ),
1047
+ position,
1048
+ align,
1049
+ ...props,
1050
+ children: [
1051
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectScrollUpButton, {}),
1052
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1053
+ Viewport,
1054
+ {
1055
+ className: cn(
1056
+ "p-1",
1057
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
1058
+ ),
1059
+ children
1060
+ }
1061
+ ),
1062
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectScrollDownButton, {})
1063
+ ]
1064
+ }
1065
+ ) });
1066
+ }
1067
+ function SelectItem({
1068
+ className,
1069
+ children,
1070
+ ...props
1071
+ }) {
1072
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1073
+ Item,
1074
+ {
1075
+ "data-slot": "select-item",
1076
+ className: cn(
1077
+ "focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
1078
+ className
1079
+ ),
1080
+ ...props,
1081
+ children: [
1082
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1083
+ "span",
1084
+ {
1085
+ "data-slot": "select-item-indicator",
1086
+ className: "absolute right-2 flex size-3.5 items-center justify-center",
1087
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ItemIndicator, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-4" }) })
1088
+ }
1089
+ ),
1090
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ItemText, { children })
1091
+ ]
1092
+ }
1093
+ );
1094
+ }
1095
+ function SelectScrollUpButton({
1096
+ className,
1097
+ ...props
1098
+ }) {
1099
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
1100
+ ScrollUpButton,
1101
+ {
1102
+ "data-slot": "select-scroll-up-button",
1103
+ className: cn(
1104
+ "flex cursor-default items-center justify-center py-1",
1105
+ className
1106
+ ),
1107
+ ...props,
1108
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "size-4" })
1109
+ }
1110
+ );
1111
+ }
1112
+ function SelectScrollDownButton({
1113
+ className,
1114
+ ...props
1115
+ }) {
1116
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
1117
+ ScrollDownButton,
1118
+ {
1119
+ "data-slot": "select-scroll-down-button",
1120
+ className: cn(
1121
+ "flex cursor-default items-center justify-center py-1",
1122
+ className
1123
+ ),
1124
+ ...props,
1125
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4" })
1126
+ }
1127
+ );
1128
+ }
1129
+ function BreakingChangesWarningDialog({
1130
+ isOpen,
1131
+ onClose,
1132
+ breakingChanges,
1133
+ onForceUpdate,
1134
+ onCancel,
1135
+ isLoading
1136
+ }) {
1137
+ const handleCancel = () => {
1138
+ onCancel();
1139
+ onClose();
1140
+ };
1141
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
1142
+ CmsDialog,
1143
+ {
1144
+ open: isOpen,
1145
+ onOpenChange: (open) => !open && !isLoading && handleCancel(),
1146
+ title: "Breaking Changes Detected",
1147
+ size: "lg",
1148
+ footer: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1149
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CmsButton, { variant: "outline", onClick: handleCancel, disabled: isLoading, children: "Cancel" }),
1150
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CmsButton, { variant: "danger", onClick: onForceUpdate, loading: isLoading, children: "Force Update" })
1151
+ ] }),
1152
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
1153
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "diff-modified flex items-start gap-3 rounded-lg border p-3", children: [
1154
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "mt-0.5 size-5 shrink-0 text-diff-modified" }),
1155
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
1156
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium text-diff-modified", children: "These changes may affect existing content" }),
1157
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-diff-modified-foreground", children: "The following changes could cause data loss or validation errors for existing entries. Review carefully before proceeding." })
1158
+ ] })
1159
+ ] }),
1160
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1161
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-sm font-medium text-foreground", children: [
1162
+ breakingChanges.length,
1163
+ " breaking change",
1164
+ breakingChanges.length !== 1 ? "s" : "",
1165
+ " detected:"
1166
+ ] }),
1167
+ /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "space-y-2", children: breakingChanges.map((change, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
1168
+ "li",
1169
+ {
1170
+ className: "flex items-start gap-2 rounded-md border bg-muted/30 px-3 py-2 text-sm",
1171
+ children: [
1172
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mt-0.5 size-1.5 shrink-0 rounded-full bg-warning" }),
1173
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: change })
1174
+ ]
1175
+ },
1176
+ index
1177
+ )) })
1178
+ ] }),
1179
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: 'Click "Force Update" to apply these changes anyway, or "Cancel" to go back and modify your changes.' })
1180
+ ] })
1181
+ }
1182
+ );
1183
+ }
1184
+ const FIELD_TYPE_INFO = {
1185
+ text: {
1186
+ label: "Text",
1187
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TextAlignStart, { className: "size-4" }),
1188
+ description: "Single line text input"
1189
+ },
1190
+ richText: {
1191
+ label: "Rich Text",
1192
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(FileType, { className: "size-4" }),
1193
+ description: "Multi-line formatted text"
1194
+ },
1195
+ number: {
1196
+ label: "Number",
1197
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Hash, { className: "size-4" }),
1198
+ description: "Numeric value"
1199
+ },
1200
+ boolean: {
1201
+ label: "Boolean",
1202
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(ToggleLeft, { className: "size-4" }),
1203
+ description: "True/false toggle"
1204
+ },
1205
+ date: {
1206
+ label: "Date",
1207
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Calendar, { className: "size-4" }),
1208
+ description: "Date picker"
1209
+ },
1210
+ datetime: {
1211
+ label: "Date & Time",
1212
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Calendar, { className: "size-4" }),
1213
+ description: "Date and time picker"
1214
+ },
1215
+ reference: {
1216
+ label: "Reference",
1217
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Link2, { className: "size-4" }),
1218
+ description: "Link to another content entry"
1219
+ },
1220
+ media: {
1221
+ label: "Media",
1222
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Image$1, { className: "size-4" }),
1223
+ description: "Image, video, or file"
1224
+ },
1225
+ json: {
1226
+ label: "JSON",
1227
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Braces, { className: "size-4" }),
1228
+ description: "Custom JSON data"
1229
+ },
1230
+ select: {
1231
+ label: "Select",
1232
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4" }),
1233
+ description: "Dropdown selection"
1234
+ },
1235
+ multiSelect: {
1236
+ label: "Multi-Select",
1237
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(List, { className: "size-4" }),
1238
+ description: "Multiple selections"
1239
+ },
1240
+ tags: {
1241
+ label: "Tags",
1242
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Tag, { className: "size-4" }),
1243
+ description: "Free-form tag list"
1244
+ },
1245
+ category: {
1246
+ label: "Category",
1247
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { className: "size-4" }),
1248
+ description: "Taxonomy category selection"
1249
+ }
1250
+ };
1251
+ function generateMachineName(displayName) {
1252
+ return displayName.toLowerCase().trim().replace(/[^a-z0-9\s]/g, "").replace(/\s+/g, "_").replace(/^[0-9]/, "_$&").slice(0, 64);
1253
+ }
1254
+ function isValidMachineName(name) {
1255
+ return /^[a-z][a-z0-9_]{0,63}$/.test(name);
1256
+ }
1257
+ function ContentTypeFormModal({
1258
+ isOpen,
1259
+ onClose,
1260
+ onCreated,
1261
+ onUpdated,
1262
+ contentType
1263
+ }) {
1264
+ const isEditing = !!contentType;
1265
+ const isCodeDefined = contentType?.source === "code";
1266
+ const isReadOnly = isCodeDefined;
1267
+ const [displayName, setDisplayName] = reactExports.useState("");
1268
+ const [machineName, setMachineName] = reactExports.useState("");
1269
+ const [machineNameManuallyEdited, setMachineNameManuallyEdited] = reactExports.useState(
1270
+ false
1271
+ );
1272
+ const [description, setDescription] = reactExports.useState("");
1273
+ const [singleton, setSingleton] = reactExports.useState(false);
1274
+ const [fields, setFields] = reactExports.useState([
1275
+ { name: "title", label: "Title", type: "text", required: true }
1276
+ ]);
1277
+ const [titleField, setTitleField] = reactExports.useState("title");
1278
+ const [slugField, setSlugField] = reactExports.useState("title");
1279
+ const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
1280
+ const [submitError, setSubmitError] = reactExports.useState(null);
1281
+ const [activeFieldIndex, setActiveFieldIndex] = reactExports.useState(null);
1282
+ const [showFieldEditor, setShowFieldEditor] = reactExports.useState(false);
1283
+ const [breakingChanges, setBreakingChanges] = reactExports.useState([]);
1284
+ const [showBreakingWarning, setShowBreakingWarning] = reactExports.useState(false);
1285
+ const [isForceUpdating, setIsForceUpdating] = reactExports.useState(false);
1286
+ const createContentType = useMutation(api.admin.createContentType);
1287
+ const updateContentType = useMutation(api.admin.updateContentType);
1288
+ reactExports.useEffect(() => {
1289
+ if (contentType && isOpen) {
1290
+ setDisplayName(contentType.displayName);
1291
+ setMachineName(contentType.name);
1292
+ setMachineNameManuallyEdited(true);
1293
+ setDescription(contentType.description || "");
1294
+ setSingleton(contentType.singleton || false);
1295
+ setFields(contentType.fields);
1296
+ setTitleField(contentType.titleField || "");
1297
+ setSlugField(contentType.slugField || "");
1298
+ }
1299
+ }, [contentType, isOpen]);
1300
+ const resetForm = reactExports.useCallback(() => {
1301
+ setDisplayName("");
1302
+ setMachineName("");
1303
+ setMachineNameManuallyEdited(false);
1304
+ setDescription("");
1305
+ setSingleton(false);
1306
+ setFields([
1307
+ { name: "title", label: "Title", type: "text", required: true }
1308
+ ]);
1309
+ setTitleField("title");
1310
+ setSlugField("title");
1311
+ setIsSubmitting(false);
1312
+ setSubmitError(null);
1313
+ setActiveFieldIndex(null);
1314
+ setShowFieldEditor(false);
1315
+ setBreakingChanges([]);
1316
+ setShowBreakingWarning(false);
1317
+ setIsForceUpdating(false);
1318
+ }, []);
1319
+ const handleDisplayNameChange = reactExports.useCallback(
1320
+ (value) => {
1321
+ setDisplayName(value);
1322
+ if (!machineNameManuallyEdited) {
1323
+ setMachineName(generateMachineName(value));
1324
+ }
1325
+ },
1326
+ [machineNameManuallyEdited]
1327
+ );
1328
+ const handleMachineNameChange = reactExports.useCallback((value) => {
1329
+ setMachineNameManuallyEdited(true);
1330
+ setMachineName(value.toLowerCase().replace(/[^a-z0-9_]/g, ""));
1331
+ }, []);
1332
+ const addField = reactExports.useCallback(() => {
1333
+ const newFieldName = `field_${fields.length + 1}`;
1334
+ setFields((prev) => [
1335
+ ...prev,
1336
+ {
1337
+ name: newFieldName,
1338
+ label: `Field ${prev.length + 1}`,
1339
+ type: "text",
1340
+ required: false
1341
+ }
1342
+ ]);
1343
+ setActiveFieldIndex(fields.length);
1344
+ setShowFieldEditor(true);
1345
+ }, [fields.length]);
1346
+ const removeField = reactExports.useCallback(
1347
+ (index) => {
1348
+ const fieldToRemove = fields[index];
1349
+ setFields((prev) => prev.filter((_, i) => i !== index));
1350
+ if (titleField === fieldToRemove.name) {
1351
+ const firstTextField = fields.find(
1352
+ (f, i) => i !== index && f.type === "text"
1353
+ );
1354
+ setTitleField(firstTextField?.name || "");
1355
+ }
1356
+ if (slugField === fieldToRemove.name) {
1357
+ const firstTextField = fields.find(
1358
+ (f, i) => i !== index && f.type === "text"
1359
+ );
1360
+ setSlugField(firstTextField?.name || "");
1361
+ }
1362
+ if (activeFieldIndex === index) {
1363
+ setActiveFieldIndex(null);
1364
+ setShowFieldEditor(false);
1365
+ } else if (activeFieldIndex !== null && activeFieldIndex > index) {
1366
+ setActiveFieldIndex(activeFieldIndex - 1);
1367
+ }
1368
+ },
1369
+ [fields, activeFieldIndex, titleField, slugField]
1370
+ );
1371
+ const updateField = reactExports.useCallback(
1372
+ (index, updates) => {
1373
+ setFields(
1374
+ (prev) => prev.map(
1375
+ (field, i) => i === index ? { ...field, ...updates } : field
1376
+ )
1377
+ );
1378
+ },
1379
+ []
1380
+ );
1381
+ const moveField = reactExports.useCallback((fromIndex, toIndex) => {
1382
+ setFields((prev) => {
1383
+ const newFields = [...prev];
1384
+ const [movedField] = newFields.splice(fromIndex, 1);
1385
+ newFields.splice(toIndex, 0, movedField);
1386
+ return newFields;
1387
+ });
1388
+ setActiveFieldIndex(toIndex);
1389
+ }, []);
1390
+ const validationErrors = reactExports.useMemo(() => {
1391
+ const errors = [];
1392
+ if (!displayName.trim()) {
1393
+ errors.push("Display name is required");
1394
+ }
1395
+ if (!machineName.trim()) {
1396
+ errors.push("System Name is required");
1397
+ } else if (!isValidMachineName(machineName)) {
1398
+ errors.push(
1399
+ "System Name must start with a letter and contain only lowercase letters, numbers, and underscores"
1400
+ );
1401
+ }
1402
+ if (fields.length === 0) {
1403
+ errors.push("At least one field is required");
1404
+ }
1405
+ const fieldNames = fields.map((f) => f.name);
1406
+ const duplicates = fieldNames.filter(
1407
+ (name, index) => fieldNames.indexOf(name) !== index
1408
+ );
1409
+ if (duplicates.length > 0) {
1410
+ errors.push(
1411
+ `Duplicate field names: ${[...new Set(duplicates)].join(", ")}`
1412
+ );
1413
+ }
1414
+ for (const field of fields) {
1415
+ if (!field.name.trim()) {
1416
+ errors.push(`Field "${field.label}" has an empty name`);
1417
+ } else if (!/^[a-z][a-z0-9_]{0,63}$/.test(field.name)) {
1418
+ errors.push(`Field "${field.name}" has an invalid name format`);
1419
+ }
1420
+ if (!field.label.trim()) {
1421
+ errors.push(`Field with name "${field.name}" has an empty label`);
1422
+ }
1423
+ if ((field.type === "select" || field.type === "multiSelect") && (!field.options?.options || field.options.options.length === 0)) {
1424
+ errors.push(
1425
+ `${field.type} field "${field.label}" requires at least one option`
1426
+ );
1427
+ }
1428
+ }
1429
+ return errors;
1430
+ }, [displayName, machineName, fields]);
1431
+ const textFields = reactExports.useMemo(() => fields.filter((f) => f.type === "text"), [
1432
+ fields
1433
+ ]);
1434
+ const parseBreakingChanges = (errorMessage) => {
1435
+ const lines = errorMessage.split("\n");
1436
+ return lines.filter((line) => line.trim().startsWith("-")).map((line) => line.trim().substring(2));
1437
+ };
1438
+ const handleSubmit = reactExports.useCallback(
1439
+ async (e, force = false) => {
1440
+ e.preventDefault();
1441
+ if (validationErrors.length > 0) {
1442
+ setSubmitError(validationErrors.join(". "));
1443
+ return;
1444
+ }
1445
+ setIsSubmitting(true);
1446
+ setSubmitError(null);
1447
+ try {
1448
+ if (isEditing && contentType) {
1449
+ const result = await updateContentType({
1450
+ id: contentType._id,
1451
+ displayName: displayName.trim(),
1452
+ description: description.trim() || void 0,
1453
+ fields,
1454
+ singleton,
1455
+ titleField: titleField || void 0,
1456
+ slugField: slugField || void 0,
1457
+ force
1458
+ });
1459
+ onUpdated?.(result);
1460
+ resetForm();
1461
+ onClose();
1462
+ } else {
1463
+ const result = await createContentType({
1464
+ name: machineName,
1465
+ displayName: displayName.trim(),
1466
+ description: description.trim() || void 0,
1467
+ fields,
1468
+ singleton,
1469
+ titleField: titleField || void 0,
1470
+ slugField: slugField || void 0
1471
+ });
1472
+ onCreated?.(result);
1473
+ resetForm();
1474
+ onClose();
1475
+ }
1476
+ } catch (error) {
1477
+ const message = error instanceof Error ? error.message : isEditing ? "Failed to update content type" : "Failed to create content type";
1478
+ if (isEditing && !force && message.includes("breaking change")) {
1479
+ const changes = parseBreakingChanges(message);
1480
+ setBreakingChanges(changes);
1481
+ setShowBreakingWarning(true);
1482
+ } else {
1483
+ setSubmitError(message);
1484
+ }
1485
+ } finally {
1486
+ setIsSubmitting(false);
1487
+ }
1488
+ },
1489
+ [
1490
+ validationErrors,
1491
+ isEditing,
1492
+ contentType,
1493
+ createContentType,
1494
+ updateContentType,
1495
+ machineName,
1496
+ displayName,
1497
+ description,
1498
+ fields,
1499
+ singleton,
1500
+ titleField,
1501
+ slugField,
1502
+ onCreated,
1503
+ onUpdated,
1504
+ resetForm,
1505
+ onClose
1506
+ ]
1507
+ );
1508
+ const handleForceUpdate = reactExports.useCallback(async () => {
1509
+ setIsForceUpdating(true);
1510
+ try {
1511
+ if (contentType) {
1512
+ const result = await updateContentType({
1513
+ id: contentType._id,
1514
+ displayName: displayName.trim(),
1515
+ description: description.trim() || void 0,
1516
+ fields,
1517
+ singleton,
1518
+ titleField: titleField || void 0,
1519
+ slugField: slugField || void 0,
1520
+ force: true
1521
+ });
1522
+ onUpdated?.(result);
1523
+ resetForm();
1524
+ setShowBreakingWarning(false);
1525
+ onClose();
1526
+ }
1527
+ } catch (error) {
1528
+ const message = error instanceof Error ? error.message : "Failed to update content type";
1529
+ setSubmitError(message);
1530
+ setShowBreakingWarning(false);
1531
+ } finally {
1532
+ setIsForceUpdating(false);
1533
+ }
1534
+ }, [
1535
+ contentType,
1536
+ updateContentType,
1537
+ displayName,
1538
+ description,
1539
+ fields,
1540
+ singleton,
1541
+ titleField,
1542
+ slugField,
1543
+ onUpdated,
1544
+ resetForm,
1545
+ onClose
1546
+ ]);
1547
+ const handleClose = reactExports.useCallback(() => {
1548
+ if (isSubmitting) return;
1549
+ resetForm();
1550
+ onClose();
1551
+ }, [isSubmitting, resetForm, onClose]);
1552
+ if (!isOpen) return null;
1553
+ const activeField = activeFieldIndex !== null ? fields[activeFieldIndex] : null;
1554
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1555
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1556
+ CmsDialog,
1557
+ {
1558
+ open: isOpen,
1559
+ onOpenChange: (open) => !open && handleClose(),
1560
+ title: isCodeDefined ? "View Content Type" : isEditing ? "Edit Content Type" : "Create Content Type",
1561
+ size: "2xl",
1562
+ footer: isReadOnly ? /* @__PURE__ */ jsxRuntimeExports.jsx(CmsButton, { variant: "outline", onClick: handleClose, children: "Close" }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1563
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1564
+ CmsButton,
1565
+ {
1566
+ variant: "outline",
1567
+ onClick: handleClose,
1568
+ disabled: isSubmitting,
1569
+ children: "Cancel"
1570
+ }
1571
+ ),
1572
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1573
+ CmsButton,
1574
+ {
1575
+ variant: "primary",
1576
+ onClick: handleSubmit,
1577
+ disabled: validationErrors.length > 0,
1578
+ loading: isSubmitting,
1579
+ "data-testid": isEditing ? "update-content-type-submit" : "create-content-type-submit",
1580
+ children: isEditing ? "Save Changes" : "Create Content Type"
1581
+ }
1582
+ )
1583
+ ] }),
1584
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("form", { onSubmit: handleSubmit, className: "space-y-6", children: [
1585
+ isCodeDefined && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-violet-200 bg-violet-50 p-3", children: [
1586
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CodeXml, { className: "mt-0.5 size-5 shrink-0 text-violet-600" }),
1587
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
1588
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium text-violet-900", children: "Managed by Code" }),
1589
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-violet-700", children: "This content type is defined in your codebase and cannot be edited through the admin interface. To make changes, update the definition in your code." })
1590
+ ] })
1591
+ ] }),
1592
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
1593
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-semibold text-foreground", children: "Basic Information" }),
1594
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1595
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Label, { htmlFor: "displayName", children: [
1596
+ "Display Name ",
1597
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-destructive", children: "*" })
1598
+ ] }),
1599
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1600
+ Input,
1601
+ {
1602
+ id: "displayName",
1603
+ value: displayName,
1604
+ onChange: (e) => handleDisplayNameChange(e.target.value),
1605
+ placeholder: "e.g., Blog Post",
1606
+ disabled: isSubmitting || isReadOnly,
1607
+ autoFocus: !isReadOnly,
1608
+ "data-testid": "display-name-input"
1609
+ }
1610
+ )
1611
+ ] }),
1612
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1613
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Label, { htmlFor: "machineName", children: [
1614
+ "System Name ",
1615
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-destructive", children: "*" })
1616
+ ] }),
1617
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1618
+ Input,
1619
+ {
1620
+ id: "machineName",
1621
+ value: machineName,
1622
+ onChange: (e) => handleMachineNameChange(e.target.value),
1623
+ placeholder: "e.g., blog_post",
1624
+ disabled: isSubmitting || isEditing || isReadOnly,
1625
+ className: cn(
1626
+ !isValidMachineName(machineName) && machineName && "border-destructive"
1627
+ ),
1628
+ "data-testid": "machine-name-input"
1629
+ }
1630
+ ),
1631
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: isEditing ? "System name cannot be changed after creation" : "Lowercase letters, numbers, and underscores only. Used in API queries." })
1632
+ ] }),
1633
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1634
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "description", children: "Description" }),
1635
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1636
+ Textarea,
1637
+ {
1638
+ id: "description",
1639
+ value: description,
1640
+ onChange: (e) => setDescription(e.target.value),
1641
+ placeholder: "Optional description of this content type",
1642
+ disabled: isSubmitting || isReadOnly,
1643
+ rows: 2
1644
+ }
1645
+ )
1646
+ ] }),
1647
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
1648
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1649
+ Checkbox,
1650
+ {
1651
+ id: "singleton",
1652
+ checked: singleton,
1653
+ onCheckedChange: (checked) => setSingleton(checked),
1654
+ disabled: isSubmitting || isReadOnly
1655
+ }
1656
+ ),
1657
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "singleton", className: "cursor-pointer", children: "Singleton (only one entry allowed)" })
1658
+ ] })
1659
+ ] }),
1660
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
1661
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
1662
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-semibold text-foreground", children: "Fields" }),
1663
+ !isReadOnly && /* @__PURE__ */ jsxRuntimeExports.jsxs(
1664
+ CmsButton,
1665
+ {
1666
+ type: "button",
1667
+ variant: "secondary",
1668
+ size: "sm",
1669
+ onClick: addField,
1670
+ disabled: isSubmitting,
1671
+ "data-testid": "add-field-button",
1672
+ children: [
1673
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-3.5" }),
1674
+ "Add Field"
1675
+ ]
1676
+ }
1677
+ )
1678
+ ] }),
1679
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2", children: fields.map((field, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
1680
+ "div",
1681
+ {
1682
+ className: cn(
1683
+ "flex items-center gap-2 rounded-lg border p-2 transition-colors",
1684
+ !isReadOnly && "cursor-pointer hover:bg-muted/50",
1685
+ activeFieldIndex === index && "border-primary bg-primary/5"
1686
+ ),
1687
+ onClick: () => {
1688
+ if (!isReadOnly) {
1689
+ setActiveFieldIndex(index);
1690
+ setShowFieldEditor(true);
1691
+ }
1692
+ },
1693
+ "data-testid": `field-item-${index}`,
1694
+ children: [
1695
+ !isReadOnly && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-0.5", children: [
1696
+ index > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
1697
+ "button",
1698
+ {
1699
+ type: "button",
1700
+ onClick: (e) => {
1701
+ e.stopPropagation();
1702
+ moveField(index, index - 1);
1703
+ },
1704
+ className: "rounded p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground",
1705
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "size-3" })
1706
+ }
1707
+ ),
1708
+ index < fields.length - 1 && /* @__PURE__ */ jsxRuntimeExports.jsx(
1709
+ "button",
1710
+ {
1711
+ type: "button",
1712
+ onClick: (e) => {
1713
+ e.stopPropagation();
1714
+ moveField(index, index + 1);
1715
+ },
1716
+ className: "rounded p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground",
1717
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3" })
1718
+ }
1719
+ )
1720
+ ] }),
1721
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex size-8 items-center justify-center rounded bg-muted text-muted-foreground", children: FIELD_TYPE_INFO[field.type].icon }),
1722
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
1723
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "truncate text-sm font-medium", children: field.label }),
1724
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-muted-foreground", children: [
1725
+ FIELD_TYPE_INFO[field.type].label,
1726
+ field.required && " *"
1727
+ ] })
1728
+ ] }),
1729
+ !isReadOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(
1730
+ "button",
1731
+ {
1732
+ type: "button",
1733
+ onClick: (e) => {
1734
+ e.stopPropagation();
1735
+ removeField(index);
1736
+ },
1737
+ disabled: isSubmitting || fields.length === 1,
1738
+ className: "rounded p-1 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive disabled:opacity-50",
1739
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-4" })
1740
+ }
1741
+ )
1742
+ ]
1743
+ },
1744
+ index
1745
+ )) }),
1746
+ !isReadOnly && showFieldEditor && activeField && activeFieldIndex !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(
1747
+ "div",
1748
+ {
1749
+ className: "rounded-lg border bg-muted/30 p-4",
1750
+ "data-testid": "field-editor",
1751
+ children: [
1752
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-4 flex items-center justify-between", children: [
1753
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("h5", { className: "font-medium", children: [
1754
+ "Edit Field: ",
1755
+ activeField.label
1756
+ ] }),
1757
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1758
+ "button",
1759
+ {
1760
+ type: "button",
1761
+ onClick: () => {
1762
+ setShowFieldEditor(false);
1763
+ setActiveFieldIndex(null);
1764
+ },
1765
+ className: "rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground",
1766
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-4" })
1767
+ }
1768
+ )
1769
+ ] }),
1770
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
1771
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1772
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Label, { htmlFor: "fieldLabel", children: [
1773
+ "Label ",
1774
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-destructive", children: "*" })
1775
+ ] }),
1776
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1777
+ Input,
1778
+ {
1779
+ id: "fieldLabel",
1780
+ value: activeField.label,
1781
+ onChange: (e) => updateField(activeFieldIndex, {
1782
+ label: e.target.value,
1783
+ name: machineNameManuallyEdited ? activeField.name : generateMachineName(e.target.value) || activeField.name
1784
+ }),
1785
+ disabled: isSubmitting,
1786
+ "data-testid": "field-label-input"
1787
+ }
1788
+ )
1789
+ ] }),
1790
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1791
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Label, { htmlFor: "fieldName", children: [
1792
+ "Name ",
1793
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-destructive", children: "*" })
1794
+ ] }),
1795
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1796
+ Input,
1797
+ {
1798
+ id: "fieldName",
1799
+ value: activeField.name,
1800
+ onChange: (e) => updateField(activeFieldIndex, {
1801
+ name: e.target.value.toLowerCase().replace(/[^a-z0-9_]/g, "")
1802
+ }),
1803
+ disabled: isSubmitting,
1804
+ "data-testid": "field-name-input"
1805
+ }
1806
+ )
1807
+ ] }),
1808
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1809
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Label, { htmlFor: "fieldType", children: [
1810
+ "Type ",
1811
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-destructive", children: "*" })
1812
+ ] }),
1813
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
1814
+ Select,
1815
+ {
1816
+ value: activeField.type,
1817
+ onValueChange: (value) => updateField(activeFieldIndex, {
1818
+ type: value,
1819
+ options: void 0
1820
+ }),
1821
+ disabled: isSubmitting,
1822
+ children: [
1823
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { "data-testid": "field-type-select", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, {}) }),
1824
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectContent, { children: Object.entries(FIELD_TYPE_INFO).map(([type, info]) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: type, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
1825
+ info.icon,
1826
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: info.label }),
1827
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground", children: [
1828
+ "- ",
1829
+ info.description
1830
+ ] })
1831
+ ] }) }, type)) })
1832
+ ]
1833
+ }
1834
+ )
1835
+ ] }),
1836
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
1837
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1838
+ Checkbox,
1839
+ {
1840
+ id: "fieldRequired",
1841
+ checked: activeField.required,
1842
+ onCheckedChange: (checked) => updateField(activeFieldIndex, {
1843
+ required: checked
1844
+ }),
1845
+ disabled: isSubmitting
1846
+ }
1847
+ ),
1848
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "fieldRequired", className: "cursor-pointer", children: "Required" })
1849
+ ] }),
1850
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1851
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "fieldDescription", children: "Help Text" }),
1852
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1853
+ Input,
1854
+ {
1855
+ id: "fieldDescription",
1856
+ value: activeField.description || "",
1857
+ onChange: (e) => updateField(activeFieldIndex, {
1858
+ description: e.target.value || void 0
1859
+ }),
1860
+ placeholder: "Help text shown below the field",
1861
+ disabled: isSubmitting
1862
+ }
1863
+ )
1864
+ ] }),
1865
+ (activeField.type === "select" || activeField.type === "multiSelect") && /* @__PURE__ */ jsxRuntimeExports.jsx(
1866
+ SelectOptionsEditor,
1867
+ {
1868
+ options: activeField.options?.options || [],
1869
+ onChange: (options) => updateField(activeFieldIndex, {
1870
+ options: { ...activeField.options, options }
1871
+ }),
1872
+ disabled: isSubmitting
1873
+ }
1874
+ )
1875
+ ] })
1876
+ ]
1877
+ }
1878
+ )
1879
+ ] }),
1880
+ textFields.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
1881
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-semibold text-foreground", children: "Display Settings" }),
1882
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1883
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "titleField", children: "Title Field" }),
1884
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
1885
+ Select,
1886
+ {
1887
+ value: titleField || "none",
1888
+ onValueChange: (v2) => setTitleField(v2 === "none" ? "" : v2),
1889
+ disabled: isSubmitting,
1890
+ children: [
1891
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "None" }) }),
1892
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
1893
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "none", children: "None" }),
1894
+ textFields.map((field) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: field.name, children: field.label }, field.name))
1895
+ ] })
1896
+ ]
1897
+ }
1898
+ ),
1899
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Field to display as the entry title in lists" })
1900
+ ] }),
1901
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1902
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "slugField", children: "Slug Field" }),
1903
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
1904
+ Select,
1905
+ {
1906
+ value: slugField || "none",
1907
+ onValueChange: (v2) => setSlugField(v2 === "none" ? "" : v2),
1908
+ disabled: isSubmitting,
1909
+ children: [
1910
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "None (auto-generate)" }) }),
1911
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
1912
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "none", children: "None (auto-generate)" }),
1913
+ textFields.map((field) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: field.name, children: field.label }, field.name))
1914
+ ] })
1915
+ ]
1916
+ }
1917
+ ),
1918
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Field to use for generating URL-friendly slugs" })
1919
+ ] })
1920
+ ] }),
1921
+ submitError && /* @__PURE__ */ jsxRuntimeExports.jsx(
1922
+ "div",
1923
+ {
1924
+ className: "diff-removed rounded-lg border px-3 py-2 text-sm",
1925
+ role: "alert",
1926
+ "data-testid": "submit-error",
1927
+ children: submitError
1928
+ }
1929
+ )
1930
+ ] })
1931
+ }
1932
+ ),
1933
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1934
+ BreakingChangesWarningDialog,
1935
+ {
1936
+ isOpen: showBreakingWarning,
1937
+ onClose: () => setShowBreakingWarning(false),
1938
+ breakingChanges,
1939
+ onForceUpdate: handleForceUpdate,
1940
+ onCancel: () => {
1941
+ setShowBreakingWarning(false);
1942
+ setBreakingChanges([]);
1943
+ },
1944
+ isLoading: isForceUpdating
1945
+ }
1946
+ )
1947
+ ] });
1948
+ }
1949
+ function SelectOptionsEditor({
1950
+ options,
1951
+ onChange,
1952
+ disabled
1953
+ }) {
1954
+ const addOption = () => {
1955
+ onChange([
1956
+ ...options,
1957
+ { value: `option_${options.length + 1}`, label: "" }
1958
+ ]);
1959
+ };
1960
+ const removeOption = (index) => {
1961
+ onChange(options.filter((_, i) => i !== index));
1962
+ };
1963
+ const updateOption = (index, updates) => {
1964
+ onChange(
1965
+ options.map((opt, i) => i === index ? { ...opt, ...updates } : opt)
1966
+ );
1967
+ };
1968
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1969
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Label, { children: [
1970
+ "Options ",
1971
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-destructive", children: "*" })
1972
+ ] }),
1973
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2", children: options.map((option, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
1974
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1975
+ Input,
1976
+ {
1977
+ value: option.label,
1978
+ onChange: (e) => {
1979
+ const label = e.target.value;
1980
+ const value = label.toLowerCase().replace(/[^a-z0-9]/g, "_").replace(/^_+|_+$/g, "");
1981
+ updateOption(index, { label, value });
1982
+ },
1983
+ placeholder: "Option label",
1984
+ disabled,
1985
+ className: "flex-1"
1986
+ }
1987
+ ),
1988
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1989
+ Input,
1990
+ {
1991
+ value: option.value,
1992
+ onChange: (e) => updateOption(index, {
1993
+ value: e.target.value.toLowerCase().replace(/[^a-z0-9_]/g, "")
1994
+ }),
1995
+ placeholder: "value",
1996
+ disabled,
1997
+ className: "w-32"
1998
+ }
1999
+ ),
2000
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
2001
+ "button",
2002
+ {
2003
+ type: "button",
2004
+ onClick: () => removeOption(index),
2005
+ disabled,
2006
+ className: "rounded p-1 text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
2007
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-4" })
2008
+ }
2009
+ )
2010
+ ] }, index)) }),
2011
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2012
+ CmsButton,
2013
+ {
2014
+ type: "button",
2015
+ variant: "secondary",
2016
+ size: "sm",
2017
+ onClick: addOption,
2018
+ disabled,
2019
+ children: [
2020
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-3.5" }),
2021
+ "Add Option"
2022
+ ]
2023
+ }
2024
+ )
2025
+ ] });
2026
+ }
2027
+ function Sidebar() {
2028
+ const routerState = useRouterState();
2029
+ const currentPath = routerState.location.pathname;
2030
+ const config = useAdminConfig();
2031
+ const { navItems, branding, layout } = config;
2032
+ const [isCreateModalOpen, setIsCreateModalOpen] = reactExports.useState(false);
2033
+ const contentTypesResult = useQuery(api.admin.listContentTypes, {
2034
+ isActive: true
2035
+ });
2036
+ const contentTypes = contentTypesResult?.page ?? [];
2037
+ const isActive = (to, exact) => {
2038
+ if (exact) {
2039
+ return currentPath === to;
2040
+ }
2041
+ return currentPath.startsWith(to);
2042
+ };
2043
+ const isContentActive = currentPath === "/content" || currentPath.startsWith("/entries/type/") || currentPath.startsWith("/entries/new/") || currentPath.startsWith("/entries/");
2044
+ const renderNavItem = (item) => {
2045
+ if (item.id === "content") {
2046
+ return renderContentMenu(item);
2047
+ }
2048
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
2049
+ Link,
2050
+ {
2051
+ to: item.path,
2052
+ className: cn(
2053
+ "flex items-center gap-3 rounded-md px-2 py-2 text-sm font-medium transition-colors",
2054
+ isActive(item.path, item.exact) ? "bg-sidebar-accent text-sidebar-accent-foreground" : "text-sidebar-foreground hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground"
2055
+ ),
2056
+ children: [
2057
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { name: item.icon, className: "size-5" }),
2058
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1", children: item.label }),
2059
+ item.badge && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded-full bg-sidebar-primary px-2 py-0.5 text-xs text-sidebar-primary-foreground", children: item.badge })
2060
+ ]
2061
+ },
2062
+ item.id
2063
+ );
2064
+ };
2065
+ const renderContentMenu = (item) => /* @__PURE__ */ jsxRuntimeExports.jsxs(Collapsible, { defaultOpen: isContentActive, children: [
2066
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2067
+ CollapsibleTrigger,
2068
+ {
2069
+ className: cn(
2070
+ "flex w-full items-center gap-3 rounded-md px-2 py-2 text-sm font-medium transition-colors",
2071
+ isContentActive ? "bg-sidebar-accent text-sidebar-accent-foreground" : "text-sidebar-foreground hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
2072
+ "group"
2073
+ ),
2074
+ children: [
2075
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { name: item.icon, className: "size-5" }),
2076
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 text-left", children: item.label }),
2077
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 transition-transform duration-200 group-data-[state=open]:rotate-180" })
2078
+ ]
2079
+ }
2080
+ ),
2081
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CollapsibleContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ml-5 mt-1 space-y-1 border-l border-sidebar-border pl-3", children: [
2082
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
2083
+ Link,
2084
+ {
2085
+ to: "/content",
2086
+ className: cn(
2087
+ "flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors",
2088
+ currentPath === "/content" ? "bg-sidebar-accent/60 text-sidebar-accent-foreground" : "text-sidebar-foreground/80 hover:bg-sidebar-accent/30 hover:text-sidebar-accent-foreground"
2089
+ ),
2090
+ children: "All Entries"
2091
+ }
2092
+ ),
2093
+ contentTypes.map((type) => /* @__PURE__ */ jsxRuntimeExports.jsx(
2094
+ Link,
2095
+ {
2096
+ to: "/entries/type/$contentTypeId",
2097
+ params: { contentTypeId: type._id },
2098
+ className: cn(
2099
+ "flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors",
2100
+ currentPath === `/entries/type/${type._id}` ? "bg-sidebar-accent/60 text-sidebar-accent-foreground" : "text-sidebar-foreground/80 hover:bg-sidebar-accent/30 hover:text-sidebar-accent-foreground"
2101
+ ),
2102
+ children: type.displayName
2103
+ },
2104
+ type._id
2105
+ )),
2106
+ contentTypes.length === 0 && contentTypesResult !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
2107
+ "button",
2108
+ {
2109
+ type: "button",
2110
+ onClick: () => setIsCreateModalOpen(true),
2111
+ className: "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm text-sidebar-foreground/60 hover:bg-sidebar-accent/30 hover:text-sidebar-accent-foreground",
2112
+ children: "+ Create content type"
2113
+ }
2114
+ )
2115
+ ] }) })
2116
+ ] }, item.id);
2117
+ const sidebarWidth = layout.sidebarWidth;
2118
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2119
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2120
+ "aside",
2121
+ {
2122
+ className: "fixed inset-y-0 left-0 z-50 flex flex-col border-r border-sidebar-border bg-sidebar",
2123
+ style: { width: sidebarWidth },
2124
+ children: [
2125
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-14 items-center gap-2 border-b border-sidebar-border px-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Link, { to: "/", className: "flex items-center gap-2 font-semibold text-sidebar-foreground", children: [
2126
+ branding.logo ? /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: branding.logo, alt: branding.appName, className: "size-8" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Layers, { className: "size-4" }) }),
2127
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-base", children: branding.appName })
2128
+ ] }) }),
2129
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("nav", { className: "flex-1 space-y-6 overflow-y-auto p-4", children: [
2130
+ navItems.main.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
2131
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-2 text-xs font-medium uppercase tracking-wider text-sidebar-foreground/60", children: "Main" }),
2132
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 pt-2", children: navItems.main.map(renderNavItem) })
2133
+ ] }),
2134
+ navItems.config.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
2135
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-2 text-xs font-medium uppercase tracking-wider text-sidebar-foreground/60", children: "Configuration" }),
2136
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 pt-2", children: navItems.config.map(renderNavItem) })
2137
+ ] })
2138
+ ] }),
2139
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-t border-sidebar-border p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between text-xs text-sidebar-foreground/60", children: [
2140
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Version" }),
2141
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: "0.1.0" })
2142
+ ] }) })
2143
+ ]
2144
+ }
2145
+ ),
2146
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
2147
+ ContentTypeFormModal,
2148
+ {
2149
+ isOpen: isCreateModalOpen,
2150
+ onClose: () => setIsCreateModalOpen(false)
2151
+ }
2152
+ )
2153
+ ] });
2154
+ }
2155
+ function Breadcrumb({ ...props }) {
2156
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("nav", { "aria-label": "breadcrumb", "data-slot": "breadcrumb", ...props });
2157
+ }
2158
+ function BreadcrumbList({ className, ...props }) {
2159
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2160
+ "ol",
2161
+ {
2162
+ "data-slot": "breadcrumb-list",
2163
+ className: cn(
2164
+ "text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5",
2165
+ className
2166
+ ),
2167
+ ...props
2168
+ }
2169
+ );
2170
+ }
2171
+ function BreadcrumbItem({ className, ...props }) {
2172
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2173
+ "li",
2174
+ {
2175
+ "data-slot": "breadcrumb-item",
2176
+ className: cn("inline-flex items-center gap-1.5", className),
2177
+ ...props
2178
+ }
2179
+ );
2180
+ }
2181
+ function BreadcrumbLink({
2182
+ asChild,
2183
+ className,
2184
+ ...props
2185
+ }) {
2186
+ const Comp = asChild ? Slot : "a";
2187
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2188
+ Comp,
2189
+ {
2190
+ "data-slot": "breadcrumb-link",
2191
+ className: cn("hover:text-foreground transition-colors", className),
2192
+ ...props
2193
+ }
2194
+ );
2195
+ }
2196
+ function BreadcrumbPage({ className, ...props }) {
2197
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2198
+ "span",
2199
+ {
2200
+ "data-slot": "breadcrumb-page",
2201
+ role: "link",
2202
+ "aria-disabled": "true",
2203
+ "aria-current": "page",
2204
+ className: cn("text-foreground font-normal", className),
2205
+ ...props
2206
+ }
2207
+ );
2208
+ }
2209
+ function BreadcrumbSeparator({
2210
+ children,
2211
+ className,
2212
+ ...props
2213
+ }) {
2214
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2215
+ "li",
2216
+ {
2217
+ "data-slot": "breadcrumb-separator",
2218
+ role: "presentation",
2219
+ "aria-hidden": "true",
2220
+ className: cn("[&>svg]:size-3.5", className),
2221
+ ...props,
2222
+ children: children ?? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, {})
2223
+ }
2224
+ );
2225
+ }
2226
+ function DropdownMenu({
2227
+ ...props
2228
+ }) {
2229
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Root2$1, { "data-slot": "dropdown-menu", ...props });
2230
+ }
2231
+ function DropdownMenuTrigger({
2232
+ ...props
2233
+ }) {
2234
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2235
+ Trigger$1,
2236
+ {
2237
+ "data-slot": "dropdown-menu-trigger",
2238
+ ...props
2239
+ }
2240
+ );
2241
+ }
2242
+ function DropdownMenuContent({
2243
+ className,
2244
+ sideOffset = 4,
2245
+ ...props
2246
+ }) {
2247
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal2, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2248
+ Content2$1,
2249
+ {
2250
+ "data-slot": "dropdown-menu-content",
2251
+ sideOffset,
2252
+ className: cn(
2253
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
2254
+ className
2255
+ ),
2256
+ ...props
2257
+ }
2258
+ ) });
2259
+ }
2260
+ function DropdownMenuItem({
2261
+ className,
2262
+ inset,
2263
+ variant = "default",
2264
+ ...props
2265
+ }) {
2266
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2267
+ Item2,
2268
+ {
2269
+ "data-slot": "dropdown-menu-item",
2270
+ "data-inset": inset,
2271
+ "data-variant": variant,
2272
+ className: cn(
2273
+ "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
2274
+ className
2275
+ ),
2276
+ ...props
2277
+ }
2278
+ );
2279
+ }
2280
+ function DropdownMenuLabel({
2281
+ className,
2282
+ inset,
2283
+ ...props
2284
+ }) {
2285
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2286
+ Label2,
2287
+ {
2288
+ "data-slot": "dropdown-menu-label",
2289
+ "data-inset": inset,
2290
+ className: cn(
2291
+ "px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
2292
+ className
2293
+ ),
2294
+ ...props
2295
+ }
2296
+ );
2297
+ }
2298
+ function DropdownMenuSeparator({
2299
+ className,
2300
+ ...props
2301
+ }) {
2302
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2303
+ Separator2,
2304
+ {
2305
+ "data-slot": "dropdown-menu-separator",
2306
+ className: cn("bg-border -mx-1 my-1 h-px", className),
2307
+ ...props
2308
+ }
2309
+ );
2310
+ }
2311
+ function Avatar({
2312
+ className,
2313
+ ...props
2314
+ }) {
2315
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2316
+ Root,
2317
+ {
2318
+ "data-slot": "avatar",
2319
+ className: cn(
2320
+ "relative flex size-8 shrink-0 overflow-hidden rounded-full",
2321
+ className
2322
+ ),
2323
+ ...props
2324
+ }
2325
+ );
2326
+ }
2327
+ function AvatarImage({
2328
+ className,
2329
+ ...props
2330
+ }) {
2331
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2332
+ Image,
2333
+ {
2334
+ "data-slot": "avatar-image",
2335
+ className: cn("aspect-square size-full", className),
2336
+ ...props
2337
+ }
2338
+ );
2339
+ }
2340
+ function AvatarFallback({
2341
+ className,
2342
+ ...props
2343
+ }) {
2344
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2345
+ Fallback,
2346
+ {
2347
+ "data-slot": "avatar-fallback",
2348
+ className: cn(
2349
+ "bg-muted flex size-full items-center justify-center rounded-full",
2350
+ className
2351
+ ),
2352
+ ...props
2353
+ }
2354
+ );
2355
+ }
2356
+ function Popover({
2357
+ ...props
2358
+ }) {
2359
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Root2, { "data-slot": "popover", ...props });
2360
+ }
2361
+ function PopoverTrigger({
2362
+ ...props
2363
+ }) {
2364
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger, { "data-slot": "popover-trigger", ...props });
2365
+ }
2366
+ function PopoverContent({
2367
+ className,
2368
+ align = "center",
2369
+ sideOffset = 4,
2370
+ ...props
2371
+ }) {
2372
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2373
+ Content2,
2374
+ {
2375
+ "data-slot": "popover-content",
2376
+ align,
2377
+ sideOffset,
2378
+ className: cn(
2379
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
2380
+ className
2381
+ ),
2382
+ ...props
2383
+ }
2384
+ ) });
2385
+ }
2386
+ const KEYBOARD_SHORTCUTS = [
2387
+ { keys: ["⌘", "S"], description: "Save entry" },
2388
+ { keys: ["⌘", "⇧", "P"], description: "Publish entry" },
2389
+ { keys: ["⌘", "K"], description: "Quick search" },
2390
+ { keys: ["Esc"], description: "Close modal/panel" }
2391
+ ];
2392
+ const HELP_RESOURCES = [
2393
+ { label: "Documentation", url: "https://docs.convex.dev", icon: Book },
2394
+ { label: "API Reference", url: "https://docs.convex.dev/api", icon: Code },
2395
+ { label: "Community Discord", url: "https://discord.gg/convex", icon: MessageSquare }
2396
+ ];
2397
+ const routeLabels = {
2398
+ "/": "Dashboard",
2399
+ "/content": "Content",
2400
+ "/media": "Media Library",
2401
+ "/content-types": "Content Types",
2402
+ "/settings": "Settings",
2403
+ "/taxonomies": "Taxonomies",
2404
+ "/trash": "Trash",
2405
+ "/entries": "Entries",
2406
+ "/entries/type": "Content Types",
2407
+ "/entries/new": "New Entry"
2408
+ };
2409
+ function getBreadcrumbs(pathname, appName, overrides) {
2410
+ const breadcrumbs = [{ label: appName, to: "/" }];
2411
+ const decodedPathname = decodeURIComponent(pathname);
2412
+ if (decodedPathname === "/") {
2413
+ return breadcrumbs;
2414
+ }
2415
+ const segments = decodedPathname.split("/").filter(Boolean);
2416
+ let currentPath = "";
2417
+ segments.forEach((segment, index) => {
2418
+ currentPath += `/${segment}`;
2419
+ const isLast = index === segments.length - 1;
2420
+ let label = overrides.get(currentPath) ?? routeLabels[currentPath];
2421
+ if (!label) {
2422
+ label = segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, " ");
2423
+ }
2424
+ if (isLast) {
2425
+ breadcrumbs.push({ label });
2426
+ } else {
2427
+ breadcrumbs.push({ label, to: currentPath });
2428
+ }
2429
+ });
2430
+ return breadcrumbs;
2431
+ }
2432
+ function Header() {
2433
+ const routerState = useRouterState();
2434
+ const navigate = useNavigate();
2435
+ const { branding } = useAdminConfig();
2436
+ let overrides = /* @__PURE__ */ new Map();
2437
+ try {
2438
+ const breadcrumbContext = useBreadcrumbContext();
2439
+ overrides = breadcrumbContext.overrides;
2440
+ } catch {
2441
+ }
2442
+ const breadcrumbs = getBreadcrumbs(routerState.location.pathname, branding.appName, overrides);
2443
+ let user = null;
2444
+ let role = null;
2445
+ let logout = async () => {
2446
+ };
2447
+ let isAuthenticated = false;
2448
+ try {
2449
+ const auth = useAuth();
2450
+ user = auth.user;
2451
+ role = auth.role;
2452
+ logout = auth.logout;
2453
+ isAuthenticated = auth.isAuthenticated;
2454
+ } catch {
2455
+ }
2456
+ const roleDefinition = role ? getRole(role) : null;
2457
+ const roleDisplayName = roleDefinition?.displayName ?? role ?? "No Role";
2458
+ const userDisplayName = user?.name ?? user?.email ?? "User";
2459
+ const getInitials = (name) => {
2460
+ const parts = name.split(" ");
2461
+ if (parts.length >= 2) {
2462
+ return `${parts[0][0]}${parts[1][0]}`.toUpperCase();
2463
+ }
2464
+ return name.slice(0, 2).toUpperCase();
2465
+ };
2466
+ const userInitials = user?.name ? getInitials(user.name) : "U";
2467
+ const handleLogout = async () => {
2468
+ await logout();
2469
+ };
2470
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("header", { className: "sticky top-0 z-40 flex h-14 items-center justify-between border-b border-border bg-background/95 px-6 backdrop-blur supports-[backdrop-filter]:bg-background/60", children: [
2471
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Breadcrumb, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(BreadcrumbList, { children: breadcrumbs.map((crumb, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs(reactExports.Fragment, { children: [
2472
+ index > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(BreadcrumbSeparator, {}),
2473
+ /* @__PURE__ */ jsxRuntimeExports.jsx(BreadcrumbItem, { children: crumb.to ? /* @__PURE__ */ jsxRuntimeExports.jsx(BreadcrumbLink, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Link, { to: crumb.to, className: "flex items-center gap-1.5", children: [
2474
+ index === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(House, { className: "size-3.5" }),
2475
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: crumb.label })
2476
+ ] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(BreadcrumbPage, { children: crumb.label }) })
2477
+ ] }, index)) }) }),
2478
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
2479
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Popover, { children: [
2480
+ /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { variant: "ghost", size: "icon", className: "size-9", children: [
2481
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Bell, { className: "size-4" }),
2482
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sr-only", children: "Notifications" })
2483
+ ] }) }),
2484
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(PopoverContent, { align: "end", className: "w-80", children: [
2485
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-between pb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-medium", children: "Notifications" }) }),
2486
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
2487
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Bell, { className: "size-8 text-muted-foreground/50" }),
2488
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-sm font-medium", children: "No notifications yet" }),
2489
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "You're all caught up!" })
2490
+ ] })
2491
+ ] })
2492
+ ] }),
2493
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Popover, { children: [
2494
+ /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { variant: "ghost", size: "icon", className: "size-9", children: [
2495
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CircleQuestionMark, { className: "size-4" }),
2496
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sr-only", children: "Help" })
2497
+ ] }) }),
2498
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(PopoverContent, { align: "end", className: "w-72", children: [
2499
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-medium", children: "Help & Resources" }) }),
2500
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
2501
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
2502
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h5", { className: "mb-2 text-xs font-medium text-muted-foreground", children: "Keyboard Shortcuts" }),
2503
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1", children: KEYBOARD_SHORTCUTS.map((shortcut, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
2504
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: shortcut.description }),
2505
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-0.5", children: shortcut.keys.map((key, keyIndex) => /* @__PURE__ */ jsxRuntimeExports.jsx(
2506
+ "kbd",
2507
+ {
2508
+ className: "rounded border border-border bg-muted px-1.5 py-0.5 font-mono text-xs",
2509
+ children: key
2510
+ },
2511
+ keyIndex
2512
+ )) })
2513
+ ] }, index)) })
2514
+ ] }),
2515
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
2516
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h5", { className: "mb-2 text-xs font-medium text-muted-foreground", children: "Resources" }),
2517
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1", children: HELP_RESOURCES.map((resource) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
2518
+ "a",
2519
+ {
2520
+ href: resource.url,
2521
+ target: "_blank",
2522
+ rel: "noopener noreferrer",
2523
+ className: "flex items-center gap-2 rounded-md px-2 py-1.5 text-sm hover:bg-accent",
2524
+ children: [
2525
+ /* @__PURE__ */ jsxRuntimeExports.jsx(resource.icon, { className: "size-4 text-muted-foreground" }),
2526
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1", children: resource.label }),
2527
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { className: "size-3 text-muted-foreground" })
2528
+ ]
2529
+ },
2530
+ resource.label
2531
+ )) })
2532
+ ] })
2533
+ ] })
2534
+ ] })
2535
+ ] }),
2536
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DropdownMenu, { children: [
2537
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { variant: "ghost", className: "h-9 gap-2 pl-2 pr-3", children: [
2538
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Avatar, { className: "size-6", children: [
2539
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AvatarImage, { src: user?.avatarUrl, alt: userDisplayName }),
2540
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AvatarFallback, { className: "text-xs", children: userInitials })
2541
+ ] }),
2542
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium", children: userDisplayName }),
2543
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3.5 text-muted-foreground" })
2544
+ ] }) }),
2545
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DropdownMenuContent, { align: "end", className: "w-56", children: [
2546
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DropdownMenuLabel, { className: "font-normal", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col space-y-1", children: [
2547
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: userDisplayName }),
2548
+ user?.email && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: user.email }),
2549
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: roleDisplayName })
2550
+ ] }) }),
2551
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DropdownMenuSeparator, {}),
2552
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DropdownMenuItem, { onClick: () => navigate({ to: "/settings" }), children: [
2553
+ /* @__PURE__ */ jsxRuntimeExports.jsx(User, { className: "mr-2 size-4" }),
2554
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Profile & Settings" })
2555
+ ] }),
2556
+ isAuthenticated && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2557
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DropdownMenuSeparator, {}),
2558
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DropdownMenuItem, { onClick: handleLogout, className: "text-destructive focus:text-destructive", children: [
2559
+ /* @__PURE__ */ jsxRuntimeExports.jsx(LogOut, { className: "mr-2 size-4" }),
2560
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Logout" })
2561
+ ] })
2562
+ ] })
2563
+ ] })
2564
+ ] })
2565
+ ] })
2566
+ ] });
2567
+ }
2568
+ function AdminLayout({ children }) {
2569
+ const { layout } = useAdminConfig();
2570
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-h-screen bg-background", children: [
2571
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Sidebar, {}),
2572
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 flex-col", style: { marginLeft: layout.sidebarWidth }, children: [
2573
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Header, {}),
2574
+ /* @__PURE__ */ jsxRuntimeExports.jsx("main", { className: "flex-1 overflow-auto p-6", children })
2575
+ ] })
2576
+ ] });
2577
+ }
2578
+ function DefaultLoading() {
2579
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "route-guard route-guard--loading bg-background flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-8 w-8 animate-spin text-muted-foreground" }) });
2580
+ }
2581
+ function DefaultUnauthenticated() {
2582
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "route-guard route-guard--unauthenticated", children: [
2583
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "route-guard-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2584
+ "svg",
2585
+ {
2586
+ xmlns: "http://www.w3.org/2000/svg",
2587
+ width: "48",
2588
+ height: "48",
2589
+ viewBox: "0 0 24 24",
2590
+ fill: "none",
2591
+ stroke: "currentColor",
2592
+ strokeWidth: "2",
2593
+ strokeLinecap: "round",
2594
+ strokeLinejoin: "round",
2595
+ children: [
2596
+ /* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }),
2597
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
2598
+ ]
2599
+ }
2600
+ ) }),
2601
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: "Authentication Required" }),
2602
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Please log in to access the admin panel." })
2603
+ ] });
2604
+ }
2605
+ function DefaultUnauthorized({
2606
+ requiredRole,
2607
+ requiredPermission
2608
+ }) {
2609
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "route-guard route-guard--unauthorized", children: [
2610
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "route-guard-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2611
+ "svg",
2612
+ {
2613
+ xmlns: "http://www.w3.org/2000/svg",
2614
+ width: "48",
2615
+ height: "48",
2616
+ viewBox: "0 0 24 24",
2617
+ fill: "none",
2618
+ stroke: "currentColor",
2619
+ strokeWidth: "2",
2620
+ strokeLinecap: "round",
2621
+ strokeLinejoin: "round",
2622
+ children: [
2623
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "10" }),
2624
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "4.93", y1: "4.93", x2: "19.07", y2: "19.07" })
2625
+ ]
2626
+ }
2627
+ ) }),
2628
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: "Access Denied" }),
2629
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "You don't have permission to access this page." }),
2630
+ requiredRole && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "route-guard-detail", children: [
2631
+ "Required role: ",
2632
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: requiredRole })
2633
+ ] }),
2634
+ requiredPermission && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "route-guard-detail", children: [
2635
+ "Required permission:",
2636
+ " ",
2637
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("strong", { children: [
2638
+ requiredPermission.action,
2639
+ " on ",
2640
+ requiredPermission.resource
2641
+ ] })
2642
+ ] })
2643
+ ] });
2644
+ }
2645
+ function DefaultError({ error }) {
2646
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "route-guard route-guard--error", children: [
2647
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "route-guard-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2648
+ "svg",
2649
+ {
2650
+ xmlns: "http://www.w3.org/2000/svg",
2651
+ width: "48",
2652
+ height: "48",
2653
+ viewBox: "0 0 24 24",
2654
+ fill: "none",
2655
+ stroke: "currentColor",
2656
+ strokeWidth: "2",
2657
+ strokeLinecap: "round",
2658
+ strokeLinejoin: "round",
2659
+ children: [
2660
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "10" }),
2661
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
2662
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
2663
+ ]
2664
+ }
2665
+ ) }),
2666
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: "Authentication Error" }),
2667
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: error })
2668
+ ] });
2669
+ }
2670
+ function RouteGuard({
2671
+ children,
2672
+ requiredPermission,
2673
+ requiredRole,
2674
+ loadingComponent,
2675
+ unauthenticatedComponent,
2676
+ unauthorizedComponent,
2677
+ onUnauthenticated,
2678
+ onUnauthorized
2679
+ }) {
2680
+ const { authState, role, checkPermission, error } = useAuth();
2681
+ if (authState === "loading") {
2682
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: loadingComponent ?? /* @__PURE__ */ jsxRuntimeExports.jsx(DefaultLoading, {}) });
2683
+ }
2684
+ if (authState === "error") {
2685
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(DefaultError, { error: error ?? "An error occurred" });
2686
+ }
2687
+ if (authState === "unauthenticated") {
2688
+ onUnauthenticated?.();
2689
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: unauthenticatedComponent ?? /* @__PURE__ */ jsxRuntimeExports.jsx(DefaultUnauthenticated, {}) });
2690
+ }
2691
+ if (!role) {
2692
+ onUnauthorized?.();
2693
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: unauthorizedComponent ?? /* @__PURE__ */ jsxRuntimeExports.jsx(
2694
+ DefaultUnauthorized,
2695
+ {
2696
+ requiredRole,
2697
+ requiredPermission
2698
+ }
2699
+ ) });
2700
+ }
2701
+ if (requiredRole && role !== requiredRole) {
2702
+ onUnauthorized?.();
2703
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: unauthorizedComponent ?? /* @__PURE__ */ jsxRuntimeExports.jsx(
2704
+ DefaultUnauthorized,
2705
+ {
2706
+ requiredRole,
2707
+ requiredPermission
2708
+ }
2709
+ ) });
2710
+ }
2711
+ if (requiredPermission && !checkPermission(requiredPermission)) {
2712
+ onUnauthorized?.();
2713
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: unauthorizedComponent ?? /* @__PURE__ */ jsxRuntimeExports.jsx(
2714
+ DefaultUnauthorized,
2715
+ {
2716
+ requiredRole,
2717
+ requiredPermission
2718
+ }
2719
+ ) });
2720
+ }
2721
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children });
2722
+ }
2723
+ const createSsrRpc = (functionId, importer) => {
2724
+ const url = "/_serverFn/" + functionId;
2725
+ const serverFnMeta = { id: functionId };
2726
+ const fn = async (...args) => {
2727
+ const serverFn = await getServerFnById(functionId);
2728
+ return serverFn(...args);
2729
+ };
2730
+ return Object.assign(fn, {
2731
+ url,
2732
+ serverFnMeta,
2733
+ [TSS_SERVER_FUNCTION]: true
2734
+ });
2735
+ };
2736
+ const getServerConfig = createServerFn({
2737
+ method: "GET"
2738
+ }).handler(createSsrRpc("dff4e5b7f7b29b6a323200a2df0a5335d739cf583e83c9e514598af6b5ade819"));
2739
+ const mockGetUser = () => {
2740
+ return {
2741
+ id: "mock_user_123",
2742
+ name: "Demo Admin",
2743
+ email: "admin@example.com"
2744
+ };
2745
+ };
2746
+ const mockGetUserRole = () => {
2747
+ return "admin";
2748
+ };
2749
+ const mockLogout = () => {
2750
+ console.log("Logout called (mock mode)");
2751
+ };
2752
+ const noAuthGetUser = () => null;
2753
+ const noAuthGetUserRole = () => null;
2754
+ const noAuthLogout = () => {
2755
+ };
2756
+ function getAuthConfig(authMode) {
2757
+ switch (authMode) {
2758
+ case "mock":
2759
+ case "demo":
2760
+ return {
2761
+ getUser: mockGetUser,
2762
+ getUserRole: mockGetUserRole,
2763
+ onLogout: mockLogout
2764
+ };
2765
+ case "none":
2766
+ case "disabled":
2767
+ return {
2768
+ getUser: noAuthGetUser,
2769
+ getUserRole: noAuthGetUserRole,
2770
+ onLogout: noAuthLogout
2771
+ };
2772
+ default:
2773
+ return {
2774
+ getUser: mockGetUser,
2775
+ getUserRole: mockGetUserRole,
2776
+ onLogout: mockLogout
2777
+ };
2778
+ }
2779
+ }
2780
+ const Route$a = createRootRoute({
2781
+ head: () => ({
2782
+ meta: [
2783
+ {
2784
+ charSet: "utf-8"
2785
+ },
2786
+ {
2787
+ name: "viewport",
2788
+ content: "width=device-width, initial-scale=1"
2789
+ },
2790
+ {
2791
+ title: "Convex CMS Admin"
2792
+ },
2793
+ {
2794
+ name: "description",
2795
+ content: "Admin interface for Convex CMS - manage content, media, and publishing workflows"
2796
+ }
2797
+ ],
2798
+ links: [
2799
+ { rel: "stylesheet", href: globalsCss },
2800
+ { rel: "icon", href: "/favicon.ico" }
2801
+ ]
2802
+ }),
2803
+ // Load server config at route initialization
2804
+ loader: async () => {
2805
+ const config = await getServerConfig();
2806
+ return { config };
2807
+ },
2808
+ component: RootComponent
2809
+ });
2810
+ function RootComponent() {
2811
+ const { config } = Route$a.useLoaderData();
2812
+ const authConfig = reactExports.useMemo(() => getAuthConfig(config.authMode), [config.authMode]);
2813
+ const adminConfig = reactExports.useMemo(
2814
+ () => resolveAdminConfig(config.adminConfig),
2815
+ [config.adminConfig]
2816
+ );
2817
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(RootDocument, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(ThemeProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(BreadcrumbProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(ConvexProviderWrapper, { config, adminConfig, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2818
+ AuthProvider,
2819
+ {
2820
+ getUser: authConfig.getUser,
2821
+ getUserRole: authConfig.getUserRole,
2822
+ onLogout: authConfig.onLogout,
2823
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(RouteGuard, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(AdminLayout, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Outlet, {}) }) })
2824
+ }
2825
+ ) }) }) }) });
2826
+ }
2827
+ function ConvexProviderWrapper({
2828
+ children,
2829
+ config,
2830
+ adminConfig
2831
+ }) {
2832
+ const convex = reactExports.useMemo(() => {
2833
+ if (!config.convexUrl) return null;
2834
+ return new ConvexReactClient(config.convexUrl);
2835
+ }, [config.convexUrl]);
2836
+ if (!convex) {
2837
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex min-h-screen items-center justify-center bg-background p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "diff-modified max-w-lg space-y-4 rounded-lg border p-6 text-center", children: [
2838
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-semibold text-diff-modified", children: "Convex Configuration Required" }),
2839
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-diff-modified-foreground", children: "Please provide a Convex deployment URL to connect to your backend." }),
2840
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 text-left text-sm text-diff-modified-foreground", children: [
2841
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "font-medium", children: "Options:" }),
2842
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { className: "list-inside list-disc space-y-1", children: [
2843
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
2844
+ "Run with URL:",
2845
+ " ",
2846
+ /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "rounded bg-diff-modified-bg/50 px-1", children: "npx convex-cms admin --url YOUR_URL" })
2847
+ ] }),
2848
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
2849
+ "Set environment variable:",
2850
+ " ",
2851
+ /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "rounded bg-diff-modified-bg/50 px-1", children: "CONVEX_URL=YOUR_URL" })
2852
+ ] }),
2853
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
2854
+ "Add to",
2855
+ " ",
2856
+ /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "rounded bg-diff-modified-bg/50 px-1", children: ".env.local" }),
2857
+ ":",
2858
+ " ",
2859
+ /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "rounded bg-diff-modified-bg/50 px-1", children: "CONVEX_URL=YOUR_URL" })
2860
+ ] })
2861
+ ] })
2862
+ ] }),
2863
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-sm text-diff-modified-foreground", children: [
2864
+ "Run",
2865
+ " ",
2866
+ /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "rounded bg-diff-modified-bg/50 px-1", children: "npx convex dev" }),
2867
+ " to start Convex and get your URL."
2868
+ ] })
2869
+ ] }) });
2870
+ }
2871
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(ConvexProvider, { client: convex, children: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsConfigProvider, { baseConfig: adminConfig, children }) });
2872
+ }
2873
+ function RootDocument({ children }) {
2874
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("html", { lang: "en", children: [
2875
+ /* @__PURE__ */ jsxRuntimeExports.jsx("head", { children: /* @__PURE__ */ jsxRuntimeExports.jsx(HeadContent, {}) }),
2876
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("body", { children: [
2877
+ children,
2878
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Scripts, {})
2879
+ ] })
2880
+ ] });
2881
+ }
2882
+ const $$splitComponentImporter$9 = () => import("./trash-zdlZgpTo.mjs");
2883
+ const Route$9 = createFileRoute("/trash")({
2884
+ component: lazyRouteComponent($$splitComponentImporter$9, "component")
2885
+ });
2886
+ const $$splitComponentImporter$8 = () => import("./taxonomies-B8nqce6u.mjs");
2887
+ const Route$8 = createFileRoute("/taxonomies")({
2888
+ component: lazyRouteComponent($$splitComponentImporter$8, "component")
2889
+ });
2890
+ const $$splitComponentImporter$7 = () => import("./settings-DlTO2JSj.mjs");
2891
+ const Route$7 = createFileRoute("/settings")({
2892
+ component: lazyRouteComponent($$splitComponentImporter$7, "component")
2893
+ });
2894
+ const $$splitComponentImporter$6 = () => import("./media-CbzgTRRQ.mjs");
2895
+ const Route$6 = createFileRoute("/media")({
2896
+ component: lazyRouteComponent($$splitComponentImporter$6, "component")
2897
+ });
2898
+ const $$splitComponentImporter$5 = () => import("./content-types-DCzrBhTH.mjs");
2899
+ const Route$5 = createFileRoute("/content-types")({
2900
+ component: lazyRouteComponent($$splitComponentImporter$5, "component")
2901
+ });
2902
+ const $$splitComponentImporter$4 = () => import("./content-BHX39L4D.mjs");
2903
+ const Route$4 = createFileRoute("/content")({
2904
+ component: lazyRouteComponent($$splitComponentImporter$4, "component")
2905
+ });
2906
+ const $$splitComponentImporter$3 = () => import("./index-DwM_5VNP.mjs");
2907
+ const Route$3 = createFileRoute("/")({
2908
+ component: lazyRouteComponent($$splitComponentImporter$3, "component")
2909
+ });
2910
+ const $$splitComponentImporter$2 = () => import("./_entryId-9GxatOkL.mjs");
2911
+ const Route$2 = createFileRoute("/entries/$entryId")({
2912
+ component: lazyRouteComponent($$splitComponentImporter$2, "component")
2913
+ });
2914
+ const $$splitComponentImporter$1 = () => import("./_contentTypeId-CiDiX-p7.mjs");
2915
+ const Route$1 = createFileRoute("/entries/type/$contentTypeId")({
2916
+ component: lazyRouteComponent($$splitComponentImporter$1, "component")
2917
+ });
2918
+ const $$splitComponentImporter = () => import("./new._contentTypeId-6Ph-Gtlw.mjs");
2919
+ const Route = createFileRoute("/entries/new/$contentTypeId")({
2920
+ component: lazyRouteComponent($$splitComponentImporter, "component")
2921
+ });
2922
+ const TrashRoute = Route$9.update({
2923
+ id: "/trash",
2924
+ path: "/trash",
2925
+ getParentRoute: () => Route$a
2926
+ });
2927
+ const TaxonomiesRoute = Route$8.update({
2928
+ id: "/taxonomies",
2929
+ path: "/taxonomies",
2930
+ getParentRoute: () => Route$a
2931
+ });
2932
+ const SettingsRoute = Route$7.update({
2933
+ id: "/settings",
2934
+ path: "/settings",
2935
+ getParentRoute: () => Route$a
2936
+ });
2937
+ const MediaRoute = Route$6.update({
2938
+ id: "/media",
2939
+ path: "/media",
2940
+ getParentRoute: () => Route$a
2941
+ });
2942
+ const ContentTypesRoute = Route$5.update({
2943
+ id: "/content-types",
2944
+ path: "/content-types",
2945
+ getParentRoute: () => Route$a
2946
+ });
2947
+ const ContentRoute = Route$4.update({
2948
+ id: "/content",
2949
+ path: "/content",
2950
+ getParentRoute: () => Route$a
2951
+ });
2952
+ const IndexRoute = Route$3.update({
2953
+ id: "/",
2954
+ path: "/",
2955
+ getParentRoute: () => Route$a
2956
+ });
2957
+ const EntriesEntryIdRoute = Route$2.update({
2958
+ id: "/entries/$entryId",
2959
+ path: "/entries/$entryId",
2960
+ getParentRoute: () => Route$a
2961
+ });
2962
+ const EntriesTypeContentTypeIdRoute = Route$1.update({
2963
+ id: "/entries/type/$contentTypeId",
2964
+ path: "/entries/type/$contentTypeId",
2965
+ getParentRoute: () => Route$a
2966
+ });
2967
+ const EntriesNewContentTypeIdRoute = Route.update({
2968
+ id: "/entries/new/$contentTypeId",
2969
+ path: "/entries/new/$contentTypeId",
2970
+ getParentRoute: () => Route$a
2971
+ });
2972
+ const rootRouteChildren = {
2973
+ IndexRoute,
2974
+ ContentRoute,
2975
+ ContentTypesRoute,
2976
+ MediaRoute,
2977
+ SettingsRoute,
2978
+ TaxonomiesRoute,
2979
+ TrashRoute,
2980
+ EntriesEntryIdRoute,
2981
+ EntriesNewContentTypeIdRoute,
2982
+ EntriesTypeContentTypeIdRoute
2983
+ };
2984
+ const routeTree = Route$a._addFileChildren(rootRouteChildren)._addFileTypes();
2985
+ function getRouter() {
2986
+ const router2 = createRouter({
2987
+ routeTree,
2988
+ scrollRestoration: true,
2989
+ defaultPreload: "intent"
2990
+ });
2991
+ return router2;
2992
+ }
2993
+ const router = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2994
+ __proto__: null,
2995
+ getRouter
2996
+ }, Symbol.toStringTag, { value: "Module" }));
2997
+ export {
2998
+ useAuth as A,
2999
+ Button as B,
3000
+ CmsButton as C,
3001
+ Dialog as D,
3002
+ getResourcePermissions as E,
3003
+ canAccessResource as F,
3004
+ hasPermission as G,
3005
+ Route as H,
3006
+ Input as I,
3007
+ buttonVariants as J,
3008
+ useBreadcrumbContext as K,
3009
+ Label as L,
3010
+ router as M,
3011
+ Popover as P,
3012
+ RouteGuard as R,
3013
+ Select as S,
3014
+ Textarea as T,
3015
+ SelectTrigger as a,
3016
+ SelectValue as b,
3017
+ SelectContent as c,
3018
+ SelectItem as d,
3019
+ Checkbox as e,
3020
+ cn as f,
3021
+ CmsConfirmDialog as g,
3022
+ api as h,
3023
+ CmsDialog as i,
3024
+ useTheme as j,
3025
+ DialogContent as k,
3026
+ DialogTitle as l,
3027
+ DropdownMenu as m,
3028
+ DropdownMenuTrigger as n,
3029
+ DropdownMenuContent as o,
3030
+ DropdownMenuItem as p,
3031
+ DropdownMenuSeparator as q,
3032
+ DialogHeader as r,
3033
+ DialogFooter as s,
3034
+ useSettingsConfig as t,
3035
+ useAdminConfig as u,
3036
+ ContentTypeFormModal as v,
3037
+ Route$2 as w,
3038
+ Route$1 as x,
3039
+ PopoverTrigger as y,
3040
+ PopoverContent as z
3041
+ };