convex-cms 0.0.3 → 0.0.5-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -60
- package/admin/README.md +99 -0
- package/admin/src/components/AdminLayout.tsx +22 -0
- package/admin/src/components/BreakingChangesWarningDialog.tsx +81 -0
- package/admin/src/components/BulkActionBar.tsx +190 -0
- package/admin/src/components/BulkOperationModal.tsx +177 -0
- package/admin/src/components/ContentEntryEditor.tsx +1104 -0
- package/admin/src/components/ContentTypeFormModal.tsx +1012 -0
- package/admin/src/components/ErrorBoundary.tsx +83 -0
- package/admin/src/components/ErrorState.tsx +147 -0
- package/admin/src/components/Header.tsx +294 -0
- package/admin/src/components/RouteGuard.tsx +264 -0
- package/admin/src/components/Sidebar.tsx +90 -0
- package/admin/src/components/TaxonomyEditor.tsx +348 -0
- package/admin/src/components/TermTree.tsx +533 -0
- package/admin/src/components/UploadDropzone.tsx +383 -0
- package/admin/src/components/VersionCompare.tsx +250 -0
- package/admin/src/components/VersionHistory.tsx +279 -0
- package/admin/src/components/VersionRollbackModal.tsx +79 -0
- package/admin/src/components/cmsds/CmsButton.tsx +101 -0
- package/admin/src/components/cmsds/CmsDialog.tsx +139 -0
- package/admin/src/components/cmsds/CmsDropdown.tsx +62 -0
- package/admin/src/components/cmsds/CmsEmptyState.tsx +54 -0
- package/admin/src/components/cmsds/CmsField.tsx +47 -0
- package/admin/src/components/cmsds/CmsPageHeader.tsx +35 -0
- package/admin/src/components/cmsds/CmsStatusBadge.tsx +153 -0
- package/admin/src/components/cmsds/CmsSurface.tsx +52 -0
- package/admin/src/components/cmsds/CmsTable.tsx +164 -0
- package/admin/src/components/cmsds/CmsToolbar.tsx +58 -0
- package/admin/src/components/cmsds/index.ts +10 -0
- package/admin/src/components/fields/BooleanField.tsx +74 -0
- package/admin/src/components/fields/CategoryField.tsx +394 -0
- package/admin/src/components/fields/DateField.tsx +173 -0
- package/admin/src/components/fields/DefaultFieldRenderer.tsx +74 -0
- package/admin/src/components/fields/FieldRenderer.tsx +180 -0
- package/admin/src/components/fields/FieldWrapper.tsx +57 -0
- package/admin/src/components/fields/JsonField.tsx +172 -0
- package/admin/src/components/fields/MediaField.tsx +367 -0
- package/admin/src/components/fields/MultiSelectField.tsx +118 -0
- package/admin/src/components/fields/NumberField.tsx +77 -0
- package/admin/src/components/fields/ReferenceField.tsx +386 -0
- package/admin/src/components/fields/RichTextField.tsx +171 -0
- package/admin/src/components/fields/SelectField.tsx +62 -0
- package/admin/src/components/fields/TagField.tsx +325 -0
- package/admin/src/components/fields/TextAreaField.tsx +68 -0
- package/admin/src/components/fields/TextField.tsx +56 -0
- package/admin/src/components/fields/index.ts +54 -0
- package/admin/src/components/fields/registry.ts +64 -0
- package/admin/src/components/fields/types.ts +217 -0
- package/admin/src/components/filters/TaxonomyFilter.tsx +254 -0
- package/admin/src/components/filters/index.ts +1 -0
- package/admin/src/components/index.ts +8 -0
- package/admin/src/components/media/MediaAssetActions.tsx +115 -0
- package/admin/src/components/media/MediaAssetEditDialog.tsx +217 -0
- package/admin/src/components/media/MediaBulkActionBar.tsx +51 -0
- package/admin/src/components/media/MediaFolderActions.tsx +69 -0
- package/admin/src/components/media/MediaFolderEditDialog.tsx +126 -0
- package/admin/src/components/media/MediaMoveModal.tsx +179 -0
- package/admin/src/components/media/MediaPreviewModal.tsx +370 -0
- package/admin/src/components/media/MediaTaxonomyPicker.tsx +304 -0
- package/admin/src/components/media/MediaTrashBulkActionBar.tsx +59 -0
- package/admin/src/components/ui/accordion.tsx +64 -0
- package/admin/src/components/ui/alert-dialog.tsx +155 -0
- package/admin/src/components/ui/alert.tsx +66 -0
- package/admin/src/components/ui/avatar.tsx +53 -0
- package/admin/src/components/ui/badge.tsx +46 -0
- package/admin/src/components/ui/breadcrumb.tsx +109 -0
- package/admin/src/components/ui/button.tsx +62 -0
- package/admin/src/components/ui/calendar.tsx +220 -0
- package/admin/src/components/ui/card.tsx +92 -0
- package/admin/src/components/ui/checkbox.tsx +30 -0
- package/admin/src/components/ui/command.tsx +182 -0
- package/admin/src/components/ui/dialog.tsx +143 -0
- package/admin/src/components/ui/dropdown-menu.tsx +257 -0
- package/admin/src/components/ui/form.tsx +167 -0
- package/admin/src/components/ui/input.tsx +21 -0
- package/admin/src/components/ui/label.tsx +24 -0
- package/admin/src/components/ui/popover.tsx +46 -0
- package/admin/src/components/ui/scroll-area.tsx +56 -0
- package/admin/src/components/ui/select.tsx +190 -0
- package/admin/src/components/ui/separator.tsx +26 -0
- package/admin/src/components/ui/sheet.tsx +137 -0
- package/admin/src/components/ui/sidebar.tsx +724 -0
- package/admin/src/components/ui/skeleton.tsx +13 -0
- package/admin/src/components/ui/sonner.tsx +38 -0
- package/admin/src/components/ui/switch.tsx +31 -0
- package/admin/src/components/ui/table.tsx +114 -0
- package/admin/src/components/ui/tabs.tsx +66 -0
- package/admin/src/components/ui/textarea.tsx +18 -0
- package/admin/src/components/ui/tooltip.tsx +61 -0
- package/admin/src/contexts/AdminConfigContext.tsx +30 -0
- package/admin/src/contexts/AuthContext.tsx +330 -0
- package/admin/src/contexts/BreadcrumbContext.tsx +49 -0
- package/admin/src/contexts/SettingsConfigContext.tsx +57 -0
- package/admin/src/contexts/ThemeContext.tsx +91 -0
- package/admin/src/contexts/index.ts +20 -0
- package/admin/src/embed/components/EmbedHeader.tsx +103 -0
- package/admin/src/embed/components/EmbedLayout.tsx +29 -0
- package/admin/src/embed/components/EmbedSidebar.tsx +119 -0
- package/admin/src/embed/components/index.ts +3 -0
- package/admin/src/embed/contexts/ApiContext.tsx +32 -0
- package/admin/src/embed/index.tsx +184 -0
- package/admin/src/embed/navigation.tsx +202 -0
- package/admin/src/embed/pages/Content.tsx +19 -0
- package/admin/src/embed/pages/ContentTypes.tsx +19 -0
- package/admin/src/embed/pages/Dashboard.tsx +19 -0
- package/admin/src/embed/pages/Media.tsx +19 -0
- package/admin/src/embed/pages/Settings.tsx +22 -0
- package/admin/src/embed/pages/Taxonomies.tsx +22 -0
- package/admin/src/embed/pages/Trash.tsx +22 -0
- package/admin/src/embed/pages/index.ts +7 -0
- package/admin/src/embed/types.ts +24 -0
- package/admin/src/hooks/index.ts +2 -0
- package/admin/src/hooks/use-mobile.ts +19 -0
- package/admin/src/hooks/useBreadcrumbLabel.ts +15 -0
- package/admin/src/hooks/usePermissions.ts +211 -0
- package/admin/src/lib/admin-config.ts +111 -0
- package/admin/src/lib/cn.ts +6 -0
- package/admin/src/lib/config.server.ts +56 -0
- package/admin/src/lib/convex.ts +26 -0
- package/admin/src/lib/embed-adapter.ts +80 -0
- package/admin/src/lib/icons.tsx +96 -0
- package/admin/src/lib/loadAdminConfig.ts +92 -0
- package/admin/src/lib/motion.ts +29 -0
- package/admin/src/lib/navigation.ts +43 -0
- package/admin/src/lib/tanstack-adapter.ts +82 -0
- package/admin/src/pages/ContentPage.tsx +337 -0
- package/admin/src/pages/ContentTypesPage.tsx +457 -0
- package/admin/src/pages/DashboardPage.tsx +163 -0
- package/admin/src/pages/MediaPage.tsx +34 -0
- package/admin/src/pages/SettingsPage.tsx +486 -0
- package/admin/src/pages/TaxonomiesPage.tsx +289 -0
- package/admin/src/pages/TrashPage.tsx +421 -0
- package/admin/src/pages/index.ts +14 -0
- package/admin/src/routeTree.gen.ts +262 -0
- package/admin/src/router.tsx +22 -0
- package/admin/src/routes/__root.tsx +250 -0
- package/admin/src/routes/content-types.tsx +20 -0
- package/admin/src/routes/content.tsx +20 -0
- package/admin/src/routes/entries/$entryId.tsx +107 -0
- package/admin/src/routes/entries/new.$contentTypeId.tsx +69 -0
- package/admin/src/routes/entries/type/$contentTypeId.tsx +503 -0
- package/admin/src/routes/index.tsx +20 -0
- package/admin/src/routes/media.tsx +1095 -0
- package/admin/src/routes/settings.tsx +20 -0
- package/admin/src/routes/taxonomies.tsx +20 -0
- package/admin/src/routes/trash.tsx +20 -0
- package/admin/src/styles/globals.css +69 -0
- package/admin/src/styles/tailwind-config.css +74 -0
- package/admin/src/styles/theme.css +73 -0
- package/admin/src/types/index.ts +221 -0
- package/admin/src/utils/errorParsing.ts +163 -0
- package/admin/src/utils/index.ts +5 -0
- package/admin/src/vite-env.d.ts +14 -0
- package/admin/tailwind.preset.cjs +102 -0
- package/admin-dist/nitro.json +1 -1
- package/admin-dist/public/assets/{CmsEmptyState-CRswfTzk.js → CmsEmptyState-CkqBIab3.js} +2 -2
- package/admin-dist/public/assets/{CmsPageHeader-CirpXndm.js → CmsPageHeader-CUtl5MMG.js} +1 -1
- package/admin-dist/public/assets/{CmsStatusBadge-CbEUpQu-.js → CmsStatusBadge-CUYFgEe-.js} +1 -1
- package/admin-dist/public/assets/CmsSurface-CsJfAVa3.js +1 -0
- package/admin-dist/public/assets/{CmsToolbar-BI2nZOXp.js → CmsToolbar-CnfbcxeP.js} +1 -1
- package/admin-dist/public/assets/{ContentEntryEditor-CBeCyK_m.js → ContentEntryEditor-BU220CCy.js} +1 -1
- package/admin-dist/public/assets/TaxonomyFilter-CWCxC5HZ.js +1 -0
- package/admin-dist/public/assets/_contentTypeId-DK8cskRt.js +1 -0
- package/admin-dist/public/assets/{_entryId-CKU_glsK.js → _entryId-CuVMExbb.js} +1 -1
- package/admin-dist/public/assets/alert-CF1BSzGR.js +1 -0
- package/admin-dist/public/assets/{badge-hvUOzpVZ.js → badge-CmuOIVKp.js} +1 -1
- package/admin-dist/public/assets/{circle-check-big-CF_pR17r.js → circle-check-big-BKDVG6DU.js} +1 -1
- package/admin-dist/public/assets/{command-DU82cJlt.js → command-XJxnF2Sd.js} +1 -1
- package/admin-dist/public/assets/content-QBUxdxbS.js +1 -0
- package/admin-dist/public/assets/content-types-CrNEm8Hf.js +2 -0
- package/admin-dist/public/assets/globals-B7Wsfh_v.css +1 -0
- package/admin-dist/public/assets/index-C7xOwudI.js +1 -0
- package/admin-dist/public/assets/{label-KNtpL71g.js → label-CHCnXeBk.js} +1 -1
- package/admin-dist/public/assets/{link-2-Bw2aI4V4.js → link-2-Bb34judH.js} +1 -1
- package/admin-dist/public/assets/{list-sYepHjt_.js → list-9Pzt48ld.js} +1 -1
- package/admin-dist/public/assets/{main-CKj5yfEi.js → main-CjQ2VI9L.js} +3 -3
- package/admin-dist/public/assets/media-Dc5PWt2Q.js +1 -0
- package/admin-dist/public/assets/{new._contentTypeId-C3LstjNs.js → new._contentTypeId-C_I4YxIa.js} +1 -1
- package/admin-dist/public/assets/{plus-DUn8v_Xf.js → plus-Ceef7DHk.js} +1 -1
- package/admin-dist/public/assets/{rotate-ccw-DJEoHcRI.js → rotate-ccw-7k7-4VUq.js} +1 -1
- package/admin-dist/public/assets/scroll-area-CC6wujnp.js +1 -0
- package/admin-dist/public/assets/{search-MuAUDJKR.js → search-DwoUV2pv.js} +1 -1
- package/admin-dist/public/assets/select-hOZTp8aC.js +1 -0
- package/admin-dist/public/assets/settings-t2PbCZh4.js +1 -0
- package/admin-dist/public/assets/switch-jX2pDaNU.js +1 -0
- package/admin-dist/public/assets/tabs-q4EbZk7c.js +1 -0
- package/admin-dist/public/assets/tanstack-adapter-B-Glm4kH.js +1 -0
- package/admin-dist/public/assets/taxonomies-kyk5P4ZW.js +1 -0
- package/admin-dist/public/assets/{textarea-BTy7nwzR.js → textarea-B6SfBmr0.js} +1 -1
- package/admin-dist/public/assets/trash-BOCnIznD.js +1 -0
- package/admin-dist/public/assets/{triangle-alert-E52Vfeuh.js → triangle-alert-CXFIO_Gu.js} +1 -1
- package/admin-dist/public/assets/useBreadcrumbLabel-_6qBagc3.js +1 -0
- package/admin-dist/public/assets/{usePermissions-Basjs9BT.js → usePermissions-M1ijZ7a6.js} +1 -1
- package/admin-dist/server/_chunks/_libs/@tanstack/react-router.mjs +7 -0
- package/admin-dist/server/_ssr/{badge-6BsP37vG.mjs → CmsButton-DOiTVKQq.mjs} +33 -33
- package/admin-dist/server/_ssr/{CmsEmptyState-DU7-7-mV.mjs → CmsEmptyState-fbnGt3LD.mjs} +2 -2
- package/admin-dist/server/_ssr/{CmsPageHeader-CseW0AHm.mjs → CmsPageHeader-DHRrdOZa.mjs} +1 -1
- package/admin-dist/server/_ssr/{CmsStatusBadge-B_pi4KCp.mjs → CmsStatusBadge-s7obWbKZ.mjs} +2 -2
- package/admin-dist/server/_ssr/CmsSurface-rFoYjb62.mjs +44 -0
- package/admin-dist/server/_ssr/{CmsToolbar-X75ex6ek.mjs → CmsToolbar-zTE45z2q.mjs} +2 -2
- package/admin-dist/server/_ssr/{ContentEntryEditor-CepusRsA.mjs → ContentEntryEditor-BLoEjT_m.mjs} +12 -12
- package/admin-dist/server/_ssr/{TaxonomyFilter-Bwrq0-cz.mjs → TaxonomyFilter-XAtaJC2z.mjs} +5 -5
- package/admin-dist/server/_ssr/{_contentTypeId-BqYKEcLr.mjs → _contentTypeId-Csl4822C.mjs} +13 -13
- package/admin-dist/server/_ssr/{_entryId-CRfnqeDf.mjs → _entryId-D8alLFBx.mjs} +15 -15
- package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BffZedId.mjs +4 -0
- package/admin-dist/server/_ssr/{command-fy8epIKf.mjs → command-C0Di14--.mjs} +1 -1
- package/admin-dist/server/_ssr/{content-B5RhL7uW.mjs → content-CT-FPsmV.mjs} +170 -98
- package/admin-dist/server/_ssr/{content-types-BIOqCQYN.mjs → content-types-C8cBFdzE.mjs} +260 -115
- package/admin-dist/server/_ssr/{index-DHSHDPt1.mjs → index-BJtcrEc-.mjs} +88 -17
- package/admin-dist/server/_ssr/index.mjs +2 -2
- package/admin-dist/server/_ssr/{label-C8Dko1j7.mjs → label-qn2Afwl4.mjs} +1 -1
- package/admin-dist/server/_ssr/{media-CSx3XttC.mjs → media-qv5IAsMZ.mjs} +43 -43
- package/admin-dist/server/_ssr/{new._contentTypeId-DzanEZQM.mjs → new._contentTypeId-DdGyrhqs.mjs} +13 -13
- package/admin-dist/server/_ssr/{router-DDWcF-kt.mjs → router-nSVkxb6Y.mjs} +11 -11
- package/admin-dist/server/_ssr/{scroll-area-bjPYwhXN.mjs → scroll-area-BCinP455.mjs} +1 -1
- package/admin-dist/server/_ssr/{select-BUhDDf4T.mjs → select-BKQlQScw.mjs} +1 -1
- package/admin-dist/server/_ssr/{settings-DAsxnw2q.mjs → settings-BCr2KQlk.mjs} +236 -139
- package/admin-dist/server/_ssr/{switch-BgyRtQ1Z.mjs → switch-BaOi42fE.mjs} +1 -1
- package/admin-dist/server/_ssr/{tabs-DzMdRB1A.mjs → tabs-DYXEi9kq.mjs} +5 -3
- package/admin-dist/server/_ssr/tanstack-adapter-Bsz8kha-.mjs +119 -0
- package/admin-dist/server/_ssr/{taxonomies-C8j8g5Q5.mjs → taxonomies-CueMHTbE.mjs} +184 -73
- package/admin-dist/server/_ssr/{textarea-9jNeYJSc.mjs → textarea-CI0Jqx2x.mjs} +1 -1
- package/admin-dist/server/_ssr/{trash-DYMxwhZB.mjs → trash-DE6W8GoX.mjs} +211 -88
- package/admin-dist/server/_ssr/{useBreadcrumbLabel-FNSAr2Ha.mjs → useBreadcrumbLabel-B5Yi72lM.mjs} +1 -1
- package/admin-dist/server/_ssr/{usePermissions-BJGGahrJ.mjs → usePermissions-C3nZ-Izm.mjs} +1 -1
- package/admin-dist/server/index.mjs +189 -182
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +156 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/index.js +6 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/client/admin/bulk.d.ts +79 -0
- package/dist/client/admin/bulk.d.ts.map +1 -0
- package/dist/client/admin/bulk.js +72 -0
- package/dist/client/admin/bulk.js.map +1 -0
- package/dist/client/admin/contentLock.d.ts +118 -0
- package/dist/client/admin/contentLock.d.ts.map +1 -0
- package/dist/client/admin/contentLock.js +81 -0
- package/dist/client/admin/contentLock.js.map +1 -0
- package/dist/client/admin/contentTypes.d.ts +1204 -0
- package/dist/client/admin/contentTypes.d.ts.map +1 -0
- package/dist/client/admin/contentTypes.js +122 -0
- package/dist/client/admin/contentTypes.js.map +1 -0
- package/dist/client/admin/dashboard.d.ts +16 -0
- package/dist/client/admin/dashboard.d.ts.map +1 -0
- package/dist/client/admin/dashboard.js +33 -0
- package/dist/client/admin/dashboard.js.map +1 -0
- package/dist/client/admin/entries.d.ts +358 -0
- package/dist/client/admin/entries.d.ts.map +1 -0
- package/dist/client/admin/entries.js +220 -0
- package/dist/client/admin/entries.js.map +1 -0
- package/dist/client/admin/index.d.ts +6568 -0
- package/dist/client/admin/index.d.ts.map +1 -0
- package/dist/client/admin/index.js +305 -0
- package/dist/client/admin/index.js.map +1 -0
- package/dist/client/admin/media.d.ts +1038 -0
- package/dist/client/admin/media.d.ts.map +1 -0
- package/dist/client/admin/media.js +489 -0
- package/dist/client/admin/media.js.map +1 -0
- package/dist/client/admin/taxonomies.d.ts +339 -0
- package/dist/client/admin/taxonomies.d.ts.map +1 -0
- package/dist/client/admin/taxonomies.js +364 -0
- package/dist/client/admin/taxonomies.js.map +1 -0
- package/dist/client/admin/trash.d.ts +91 -0
- package/dist/client/admin/trash.d.ts.map +1 -0
- package/dist/client/admin/trash.js +71 -0
- package/dist/client/admin/trash.js.map +1 -0
- package/dist/client/admin/types.d.ts +320 -0
- package/dist/client/admin/types.d.ts.map +1 -0
- package/dist/client/admin/types.js +7 -0
- package/dist/client/admin/types.js.map +1 -0
- package/dist/client/admin/validators.d.ts +3886 -0
- package/dist/client/admin/validators.d.ts.map +1 -0
- package/dist/client/admin/validators.js +322 -0
- package/dist/client/admin/validators.js.map +1 -0
- package/dist/client/admin/versions.d.ts +106 -0
- package/dist/client/admin/versions.d.ts.map +1 -0
- package/dist/client/admin/versions.js +57 -0
- package/dist/client/admin/versions.js.map +1 -0
- package/dist/client/adminApiTypes.d.ts +27 -0
- package/dist/client/adminApiTypes.d.ts.map +1 -0
- package/dist/client/adminApiTypes.js +12 -0
- package/dist/client/adminApiTypes.js.map +1 -0
- package/dist/client/{admin-config.d.ts → adminConfig.d.ts} +4 -4
- package/dist/client/adminConfig.d.ts.map +1 -0
- package/dist/client/{admin-config.js → adminConfig.js} +3 -3
- package/dist/client/adminConfig.js.map +1 -0
- package/dist/client/agentTools.d.ts +11 -21
- package/dist/client/agentTools.d.ts.map +1 -1
- package/dist/client/agentTools.js +4 -4
- package/dist/client/index.d.ts +6 -6
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +19 -6
- package/dist/client/index.js.map +1 -1
- package/dist/client/schema/codegen.d.ts +2 -2
- package/dist/client/schema/codegen.d.ts.map +1 -1
- package/dist/client/schema/codegen.js +3 -3
- package/dist/client/schema/codegen.js.map +1 -1
- package/dist/client/schema/defineContentType.d.ts +3 -3
- package/dist/client/schema/defineContentType.js +3 -3
- package/dist/client/schema/index.d.ts +7 -7
- package/dist/client/schema/index.d.ts.map +1 -1
- package/dist/client/schema/index.js +5 -5
- package/dist/client/schema/index.js.map +1 -1
- package/dist/client/schema/schemaDrift.d.ts +1 -1
- package/dist/client/schema/schemaDrift.js +1 -1
- package/dist/client/schema/typedClient.d.ts +2 -2
- package/dist/client/schema/typedClient.js +2 -2
- package/dist/client/schema/types.d.ts +1 -1
- package/dist/client/schema/types.js +1 -1
- package/dist/client/wrapper.d.ts +108 -65
- package/dist/client/wrapper.d.ts.map +1 -1
- package/dist/client/wrapper.js +22 -22
- package/dist/client/wrapper.js.map +1 -1
- package/dist/component/contentEntries.d.ts +4 -4
- package/dist/component/contentEntryMutations.d.ts +46 -0
- package/dist/component/contentEntryMutations.d.ts.map +1 -1
- package/dist/component/contentEntryMutations.js +1 -1
- package/dist/component/contentEntryMutations.js.map +1 -1
- package/dist/component/contentTypeMigration.d.ts +1 -1
- package/dist/component/contentTypeMutations.d.ts +22 -0
- package/dist/component/contentTypeMutations.d.ts.map +1 -1
- package/dist/component/contentTypeMutations.js +1 -1
- package/dist/component/contentTypeMutations.js.map +1 -1
- package/dist/component/convex.config.d.ts +2 -2
- package/dist/component/convex.config.js +2 -2
- package/dist/component/index.d.ts +1 -1
- package/dist/component/index.js +1 -1
- package/dist/component/lib/ragContentChunker.d.ts +1 -1
- package/dist/component/lib/ragContentChunker.js +1 -1
- package/dist/component/mediaAssetMutations.d.ts +47 -0
- package/dist/component/mediaAssetMutations.d.ts.map +1 -1
- package/dist/component/mediaAssetMutations.js +1 -1
- package/dist/component/mediaAssetMutations.js.map +1 -1
- package/dist/component/roles.d.ts +1 -1
- package/dist/component/roles.js +1 -1
- package/dist/component/schema.d.ts +9 -0
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +1 -1
- package/dist/component/schema.js.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +13 -7
- package/dist/react/index.js.map +1 -1
- package/dist/test.d.ts +2 -2
- package/dist/test.js +2 -2
- package/package.json +115 -13
- package/admin-dist/public/assets/ErrorState-BIVaWmom.js +0 -1
- package/admin-dist/public/assets/TaxonomyFilter-ChaY6Y_x.js +0 -1
- package/admin-dist/public/assets/_contentTypeId-DQ8k_Rvw.js +0 -1
- package/admin-dist/public/assets/alert-BXjTqrwQ.js +0 -1
- package/admin-dist/public/assets/content-_LXl3pp7.js +0 -1
- package/admin-dist/public/assets/content-types-KjxaXGxY.js +0 -2
- package/admin-dist/public/assets/globals-CS6BZ0zp.css +0 -1
- package/admin-dist/public/assets/index-DNGIZHL-.js +0 -1
- package/admin-dist/public/assets/media-Bkrkffm7.js +0 -1
- package/admin-dist/public/assets/scroll-area-DfIlT0in.js +0 -1
- package/admin-dist/public/assets/select-BD29IXCI.js +0 -1
- package/admin-dist/public/assets/settings-DmMyn_6A.js +0 -1
- package/admin-dist/public/assets/switch-h3Rrnl5i.js +0 -1
- package/admin-dist/public/assets/tabs-imc8h-Dp.js +0 -1
- package/admin-dist/public/assets/taxonomies-dAsrT65H.js +0 -1
- package/admin-dist/public/assets/trash-SAWKZZHv.js +0 -1
- package/admin-dist/public/assets/useBreadcrumbLabel-BECBMCzM.js +0 -1
- package/admin-dist/server/_ssr/ErrorState-cI-bKLez.mjs +0 -89
- package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BwDlABVk.mjs +0 -4
- package/admin-dist/server/_ssr/alert-CVt45UUP.mjs +0 -92
- package/dist/client/admin-config.d.ts.map +0 -1
- package/dist/client/admin-config.js.map +0 -1
- package/dist/client/adminApi.d.ts +0 -2273
- package/dist/client/adminApi.d.ts.map +0 -1
- package/dist/client/adminApi.js +0 -716
- package/dist/client/adminApi.js.map +0 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export interface NavItem {
|
|
4
|
+
id: string;
|
|
5
|
+
path: string;
|
|
6
|
+
label: string;
|
|
7
|
+
icon: string;
|
|
8
|
+
visible?: boolean;
|
|
9
|
+
section: "main" | "config";
|
|
10
|
+
badge?: string;
|
|
11
|
+
exact?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const navItemSchema = z.object({
|
|
15
|
+
id: z.string(),
|
|
16
|
+
path: z.string(),
|
|
17
|
+
label: z.string(),
|
|
18
|
+
icon: z.string(),
|
|
19
|
+
visible: z.boolean().default(true),
|
|
20
|
+
section: z.enum(["main", "config"]).default("main"),
|
|
21
|
+
badge: z.string().optional(),
|
|
22
|
+
exact: z.boolean().optional(),
|
|
23
|
+
}) satisfies z.ZodType<NavItem>;
|
|
24
|
+
|
|
25
|
+
const brandingSchema = z.object({
|
|
26
|
+
appName: z.string().default("Convex CMS"),
|
|
27
|
+
logo: z.string().optional(),
|
|
28
|
+
favicon: z.string().optional(),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const layoutSchema = z.object({
|
|
32
|
+
sidebarWidth: z.number().min(200).max(400).default(256),
|
|
33
|
+
sidebarCollapsible: z.boolean().default(false),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const navigationSchema = z.object({
|
|
37
|
+
showDashboard: z.boolean().default(true),
|
|
38
|
+
showContent: z.boolean().default(true),
|
|
39
|
+
showMedia: z.boolean().default(true),
|
|
40
|
+
showTaxonomies: z.boolean().default(true),
|
|
41
|
+
showContentTypes: z.boolean().default(true),
|
|
42
|
+
showTrash: z.boolean().default(true),
|
|
43
|
+
showSettings: z.boolean().default(true),
|
|
44
|
+
customItems: z.array(navItemSchema).default([]),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const themeSchema = z.object({
|
|
48
|
+
mode: z.enum(["light", "dark", "system"]).default("system"),
|
|
49
|
+
allowModeSwitch: z.boolean().default(true),
|
|
50
|
+
tokens: z.record(z.string(), z.string()).optional(),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export const adminConfigSchema = z.object({
|
|
54
|
+
branding: brandingSchema.default(() => brandingSchema.parse({})),
|
|
55
|
+
layout: layoutSchema.default(() => layoutSchema.parse({})),
|
|
56
|
+
navigation: navigationSchema.default(() => navigationSchema.parse({})),
|
|
57
|
+
theme: themeSchema.default(() => themeSchema.parse({})),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export type AdminConfig = z.infer<typeof adminConfigSchema>;
|
|
61
|
+
|
|
62
|
+
export const DEFAULT_NAV_ITEMS: NavItem[] = [
|
|
63
|
+
{
|
|
64
|
+
id: "dashboard",
|
|
65
|
+
path: "/",
|
|
66
|
+
label: "Dashboard",
|
|
67
|
+
icon: "LayoutDashboard",
|
|
68
|
+
section: "main",
|
|
69
|
+
exact: true,
|
|
70
|
+
},
|
|
71
|
+
{ id: "content", path: "/content", label: "Content", icon: "FileText", section: "main" },
|
|
72
|
+
{ id: "media", path: "/media", label: "Media", icon: "Image", section: "main" },
|
|
73
|
+
{ id: "taxonomies", path: "/taxonomies", label: "Taxonomies", icon: "Tags", section: "main" },
|
|
74
|
+
{
|
|
75
|
+
id: "content-types",
|
|
76
|
+
path: "/content-types",
|
|
77
|
+
label: "Content Types",
|
|
78
|
+
icon: "Layers",
|
|
79
|
+
section: "config",
|
|
80
|
+
},
|
|
81
|
+
{ id: "trash", path: "/trash", label: "Trash", icon: "Trash2", section: "config" },
|
|
82
|
+
{ id: "settings", path: "/settings", label: "Settings", icon: "Settings", section: "config" },
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
export function resolveAdminConfig(input?: Partial<AdminConfig>): AdminConfig {
|
|
86
|
+
return adminConfigSchema.parse(input ?? {});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function getVisibleNavItems(config: AdminConfig): { main: NavItem[]; config: NavItem[] } {
|
|
90
|
+
const visibilityMap: Record<string, boolean> = {
|
|
91
|
+
dashboard: config.navigation.showDashboard,
|
|
92
|
+
content: config.navigation.showContent,
|
|
93
|
+
media: config.navigation.showMedia,
|
|
94
|
+
taxonomies: config.navigation.showTaxonomies,
|
|
95
|
+
"content-types": config.navigation.showContentTypes,
|
|
96
|
+
trash: config.navigation.showTrash,
|
|
97
|
+
settings: config.navigation.showSettings,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const filtered = DEFAULT_NAV_ITEMS.filter((item) => visibilityMap[item.id] !== false);
|
|
101
|
+
const allItems = [...filtered, ...config.navigation.customItems.filter((i) => i.visible !== false)];
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
main: allItems.filter((i) => i.section === "main"),
|
|
105
|
+
config: allItems.filter((i) => i.section === "config"),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function defineAdminConfig(config: Partial<AdminConfig>): Partial<AdminConfig> {
|
|
110
|
+
return config;
|
|
111
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createServerFn } from "@tanstack/react-start";
|
|
2
|
+
import type { AdminConfig } from "./admin-config";
|
|
3
|
+
import { loadAdminConfig } from "./loadAdminConfig";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Server function to retrieve runtime configuration.
|
|
7
|
+
*
|
|
8
|
+
* Configuration is loaded from (in order of precedence):
|
|
9
|
+
* 1. Environment variable CONVEX_CMS_ADMIN_CONFIG (JSON string)
|
|
10
|
+
* 2. Config file (cms-admin.config.ts/js/mjs) in project root
|
|
11
|
+
*
|
|
12
|
+
* This code-first approach allows configuration to be:
|
|
13
|
+
* - Committed to git and reviewed in PRs
|
|
14
|
+
* - Type-safe with TypeScript
|
|
15
|
+
* - Consistent across dev/staging/production
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // cms-admin.config.ts
|
|
19
|
+
* import { defineAdminConfig } from "convex-cms";
|
|
20
|
+
*
|
|
21
|
+
* export default defineAdminConfig({
|
|
22
|
+
* branding: { appName: "My CMS" },
|
|
23
|
+
* navigation: { showTaxonomies: false },
|
|
24
|
+
* });
|
|
25
|
+
*/
|
|
26
|
+
export const getServerConfig = createServerFn({ method: "GET" }).handler(
|
|
27
|
+
async () => {
|
|
28
|
+
let adminConfig: Partial<AdminConfig> = {};
|
|
29
|
+
|
|
30
|
+
const configEnv = process.env.CONVEX_CMS_ADMIN_CONFIG;
|
|
31
|
+
if (configEnv) {
|
|
32
|
+
try {
|
|
33
|
+
adminConfig = JSON.parse(configEnv) as Partial<AdminConfig>;
|
|
34
|
+
} catch {
|
|
35
|
+
console.warn("Failed to parse CONVEX_CMS_ADMIN_CONFIG as JSON");
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
try {
|
|
39
|
+
adminConfig = await loadAdminConfig();
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.warn("Failed to load admin config from file:", error);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
convexUrl: process.env.CONVEX_URL || process.env.VITE_CONVEX_URL || "",
|
|
47
|
+
authMode: process.env.AUTH_MODE || process.env.VITE_AUTH_MODE || "demo",
|
|
48
|
+
adminConfig,
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Type for the server config response.
|
|
55
|
+
*/
|
|
56
|
+
export type ServerConfig = Awaited<ReturnType<typeof getServerConfig>>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convex client utilities for the Admin UI
|
|
3
|
+
*
|
|
4
|
+
* This module provides helpers for interacting with the Convex CMS component
|
|
5
|
+
* from within the admin application.
|
|
6
|
+
*
|
|
7
|
+
* NOTE: The Convex API types are generated when running `npx convex dev`.
|
|
8
|
+
* Until then, TypeScript may show import errors which can be ignored.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useQuery, useMutation } from "convex/react";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Re-export Convex hooks for convenience
|
|
15
|
+
*/
|
|
16
|
+
export { useQuery, useMutation };
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Access to the generated Convex API
|
|
20
|
+
* This will be available once `npx convex dev` is run
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* import { api } from '~/lib/convex'
|
|
24
|
+
* const contentTypes = useQuery(api.convexCms.contentEntries.get, { id: '...' })
|
|
25
|
+
*/
|
|
26
|
+
export { api } from "../../convex/_generated/api";
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embed Navigation Adapter
|
|
3
|
+
*
|
|
4
|
+
* Implements the AdminNavigation interface for the embed navigation system,
|
|
5
|
+
* allowing shared page components to work with embedded CMS.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useMemo, useCallback } from "react";
|
|
9
|
+
import type { AdminNavigation } from "./navigation";
|
|
10
|
+
import type { EmbedNavigationContextValue, EmbedRoute } from "../embed/navigation";
|
|
11
|
+
|
|
12
|
+
function pathToRoute(path: string): { route: EmbedRoute; params: Record<string, string> } {
|
|
13
|
+
if (path === "/" || path === "") {
|
|
14
|
+
return { route: "dashboard", params: {} };
|
|
15
|
+
}
|
|
16
|
+
if (path === "/content") {
|
|
17
|
+
return { route: "content", params: {} };
|
|
18
|
+
}
|
|
19
|
+
if (path === "/content-types") {
|
|
20
|
+
return { route: "content-types", params: {} };
|
|
21
|
+
}
|
|
22
|
+
if (path === "/media") {
|
|
23
|
+
return { route: "media", params: {} };
|
|
24
|
+
}
|
|
25
|
+
if (path === "/taxonomies") {
|
|
26
|
+
return { route: "taxonomies", params: {} };
|
|
27
|
+
}
|
|
28
|
+
if (path === "/settings") {
|
|
29
|
+
return { route: "settings", params: {} };
|
|
30
|
+
}
|
|
31
|
+
if (path === "/trash") {
|
|
32
|
+
return { route: "trash", params: {} };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const entryMatch = path.match(/^\/entries\/([^/]+)$/);
|
|
36
|
+
if (entryMatch) {
|
|
37
|
+
return { route: "entries", params: { entryId: entryMatch[1] } };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const typeMatch = path.match(/^\/entries\/type\/([^/]+)$/);
|
|
41
|
+
if (typeMatch) {
|
|
42
|
+
return { route: "entries", params: { contentTypeId: typeMatch[1] } };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const newEntryMatch = path.match(/^\/entries\/new\/([^/]+)$/);
|
|
46
|
+
if (newEntryMatch) {
|
|
47
|
+
return { route: "entries", params: { contentTypeId: newEntryMatch[1], action: "new" } };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return { route: "dashboard", params: {} };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function useEmbedAdapter(
|
|
54
|
+
embedNav: EmbedNavigationContextValue
|
|
55
|
+
): AdminNavigation {
|
|
56
|
+
const handleNavigate = useCallback(
|
|
57
|
+
(path: string, params?: Record<string, string>) => {
|
|
58
|
+
const resolved = pathToRoute(path);
|
|
59
|
+
const mergedParams = { ...resolved.params, ...params };
|
|
60
|
+
embedNav.navigate(resolved.route, mergedParams);
|
|
61
|
+
},
|
|
62
|
+
[embedNav]
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return useMemo(
|
|
66
|
+
() => ({
|
|
67
|
+
navigate: handleNavigate,
|
|
68
|
+
currentRoute: embedNav.currentPath,
|
|
69
|
+
params: embedNav.currentRoute.params,
|
|
70
|
+
canGoBack: embedNav.canGoBack,
|
|
71
|
+
goBack: embedNav.goBack,
|
|
72
|
+
navigateToEntry: embedNav.navigateToEntry,
|
|
73
|
+
navigateToContentType: embedNav.navigateToContentType,
|
|
74
|
+
navigateToNewEntry: (contentTypeId: string) => {
|
|
75
|
+
embedNav.navigate("entries", { contentTypeId, action: "new" });
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
78
|
+
[handleNavigate, embedNav]
|
|
79
|
+
);
|
|
80
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LayoutDashboard,
|
|
3
|
+
FileText,
|
|
4
|
+
Image,
|
|
5
|
+
Layers,
|
|
6
|
+
Tags,
|
|
7
|
+
FileCode,
|
|
8
|
+
Settings,
|
|
9
|
+
Trash2,
|
|
10
|
+
type LucideIcon,
|
|
11
|
+
HelpCircle,
|
|
12
|
+
Home,
|
|
13
|
+
User,
|
|
14
|
+
Bell,
|
|
15
|
+
Lock,
|
|
16
|
+
Globe,
|
|
17
|
+
Calendar,
|
|
18
|
+
Clock,
|
|
19
|
+
Link,
|
|
20
|
+
Hash,
|
|
21
|
+
ToggleLeft,
|
|
22
|
+
ChevronDown,
|
|
23
|
+
CheckSquare,
|
|
24
|
+
Braces,
|
|
25
|
+
Folder,
|
|
26
|
+
MapPin,
|
|
27
|
+
DollarSign,
|
|
28
|
+
Mail,
|
|
29
|
+
Phone,
|
|
30
|
+
Package,
|
|
31
|
+
Star,
|
|
32
|
+
Heart,
|
|
33
|
+
Flag,
|
|
34
|
+
Bookmark,
|
|
35
|
+
Archive,
|
|
36
|
+
Edit,
|
|
37
|
+
Eye,
|
|
38
|
+
AlertCircle,
|
|
39
|
+
} from "lucide-react";
|
|
40
|
+
|
|
41
|
+
const iconRegistry: Record<string, LucideIcon> = {
|
|
42
|
+
LayoutDashboard,
|
|
43
|
+
FileText,
|
|
44
|
+
Image,
|
|
45
|
+
Layers,
|
|
46
|
+
Tags,
|
|
47
|
+
FileCode,
|
|
48
|
+
Settings,
|
|
49
|
+
Trash2,
|
|
50
|
+
HelpCircle,
|
|
51
|
+
Home,
|
|
52
|
+
User,
|
|
53
|
+
Bell,
|
|
54
|
+
Lock,
|
|
55
|
+
Globe,
|
|
56
|
+
Calendar,
|
|
57
|
+
Clock,
|
|
58
|
+
Link,
|
|
59
|
+
Hash,
|
|
60
|
+
ToggleLeft,
|
|
61
|
+
ChevronDown,
|
|
62
|
+
CheckSquare,
|
|
63
|
+
Braces,
|
|
64
|
+
Folder,
|
|
65
|
+
MapPin,
|
|
66
|
+
DollarSign,
|
|
67
|
+
Mail,
|
|
68
|
+
Phone,
|
|
69
|
+
Package,
|
|
70
|
+
Star,
|
|
71
|
+
Heart,
|
|
72
|
+
Flag,
|
|
73
|
+
Bookmark,
|
|
74
|
+
Archive,
|
|
75
|
+
Edit,
|
|
76
|
+
Eye,
|
|
77
|
+
AlertCircle,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export function getIcon(name: string): LucideIcon | undefined {
|
|
81
|
+
return iconRegistry[name];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function Icon({
|
|
85
|
+
name,
|
|
86
|
+
className = "size-5",
|
|
87
|
+
}: {
|
|
88
|
+
name: string;
|
|
89
|
+
className?: string;
|
|
90
|
+
}) {
|
|
91
|
+
const IconComponent = iconRegistry[name];
|
|
92
|
+
if (!IconComponent) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
return <IconComponent className={className} />;
|
|
96
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Config File Loader
|
|
3
|
+
*
|
|
4
|
+
* Loads admin configuration from a config file in the user's project directory.
|
|
5
|
+
* Similar to how Vite loads vite.config.ts, this enables code-first configuration
|
|
6
|
+
* that can be committed to git and reviewed in PRs.
|
|
7
|
+
*
|
|
8
|
+
* Supported file names (in order of precedence):
|
|
9
|
+
* - cms-admin.config.ts
|
|
10
|
+
* - cms-admin.config.js
|
|
11
|
+
* - cms-admin.config.mjs
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // cms-admin.config.ts
|
|
15
|
+
* import { defineAdminConfig } from "convex-cms";
|
|
16
|
+
*
|
|
17
|
+
* export default defineAdminConfig({
|
|
18
|
+
* branding: { appName: "My CMS" },
|
|
19
|
+
* navigation: { showTaxonomies: false },
|
|
20
|
+
* });
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { pathToFileURL } from "url";
|
|
24
|
+
import { existsSync } from "fs";
|
|
25
|
+
import { resolve, dirname } from "path";
|
|
26
|
+
import type { AdminConfig } from "./admin-config";
|
|
27
|
+
|
|
28
|
+
const CONFIG_FILE_NAMES = [
|
|
29
|
+
"cms-admin.config.ts",
|
|
30
|
+
"cms-admin.config.js",
|
|
31
|
+
"cms-admin.config.mjs",
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
let cachedConfig: Partial<AdminConfig> | null = null;
|
|
35
|
+
let cachedConfigPath: string | null = null;
|
|
36
|
+
|
|
37
|
+
function findProjectRoot(startDir: string): string {
|
|
38
|
+
let dir = startDir;
|
|
39
|
+
while (dir !== dirname(dir)) {
|
|
40
|
+
if (existsSync(resolve(dir, "package.json"))) {
|
|
41
|
+
return dir;
|
|
42
|
+
}
|
|
43
|
+
dir = dirname(dir);
|
|
44
|
+
}
|
|
45
|
+
return startDir;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function loadAdminConfig(
|
|
49
|
+
cwd?: string,
|
|
50
|
+
): Promise<Partial<AdminConfig>> {
|
|
51
|
+
const projectRoot = cwd ?? findProjectRoot(process.cwd());
|
|
52
|
+
|
|
53
|
+
for (const fileName of CONFIG_FILE_NAMES) {
|
|
54
|
+
const configPath = resolve(projectRoot, fileName);
|
|
55
|
+
if (existsSync(configPath)) {
|
|
56
|
+
if (cachedConfig && cachedConfigPath === configPath) {
|
|
57
|
+
return cachedConfig;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
const configUrl = pathToFileURL(configPath).href;
|
|
62
|
+
let loadedConfig: Partial<AdminConfig>;
|
|
63
|
+
|
|
64
|
+
if (configPath.endsWith(".ts")) {
|
|
65
|
+
const importPath = `${configUrl}?ts=${Date.now()}`;
|
|
66
|
+
const configModule = await import(importPath);
|
|
67
|
+
loadedConfig = configModule.default ?? configModule;
|
|
68
|
+
} else {
|
|
69
|
+
const configModule = await import(configUrl);
|
|
70
|
+
loadedConfig = configModule.default ?? configModule;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
cachedConfig = loadedConfig;
|
|
74
|
+
cachedConfigPath = configPath;
|
|
75
|
+
return loadedConfig;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.warn(`Failed to load ${fileName}:`, error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return {};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function clearConfigCache(): void {
|
|
86
|
+
cachedConfig = null;
|
|
87
|
+
cachedConfigPath = null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function getConfigPath(): string | null {
|
|
91
|
+
return cachedConfigPath;
|
|
92
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const motion = {
|
|
2
|
+
fast: 'duration-100 ease-out',
|
|
3
|
+
base: 'duration-200 ease-out',
|
|
4
|
+
smooth: 'duration-300 ease-out',
|
|
5
|
+
spring: 'duration-300 ease-[cubic-bezier(0.34,1.56,0.64,1)]',
|
|
6
|
+
} as const
|
|
7
|
+
|
|
8
|
+
export const transitions = {
|
|
9
|
+
fadeIn: 'animate-in fade-in',
|
|
10
|
+
fadeOut: 'animate-out fade-out',
|
|
11
|
+
slideInFromTop: 'animate-in slide-in-from-top-2',
|
|
12
|
+
slideInFromBottom: 'animate-in slide-in-from-bottom-2',
|
|
13
|
+
slideInFromLeft: 'animate-in slide-in-from-left-2',
|
|
14
|
+
slideInFromRight: 'animate-in slide-in-from-right-2',
|
|
15
|
+
zoomIn: 'animate-in zoom-in-95',
|
|
16
|
+
zoomOut: 'animate-out zoom-out-95',
|
|
17
|
+
} as const
|
|
18
|
+
|
|
19
|
+
export const hover = {
|
|
20
|
+
lift: 'hover:-translate-y-0.5 hover:shadow-md',
|
|
21
|
+
glow: 'hover:shadow-[0_0_15px_-3px_var(--color-primary)]',
|
|
22
|
+
scale: 'hover:scale-[1.02]',
|
|
23
|
+
brighten: 'hover:brightness-110',
|
|
24
|
+
} as const
|
|
25
|
+
|
|
26
|
+
export const focus = {
|
|
27
|
+
ring: 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
|
28
|
+
subtle: 'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',
|
|
29
|
+
} as const
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Navigation Interface
|
|
3
|
+
*
|
|
4
|
+
* Provides router-agnostic navigation that works with both TanStack Router (CLI)
|
|
5
|
+
* and the custom embed navigation system.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const ROUTES = {
|
|
9
|
+
DASHBOARD: "/",
|
|
10
|
+
CONTENT: "/content",
|
|
11
|
+
CONTENT_TYPES: "/content-types",
|
|
12
|
+
MEDIA: "/media",
|
|
13
|
+
SETTINGS: "/settings",
|
|
14
|
+
TRASH: "/trash",
|
|
15
|
+
TAXONOMIES: "/taxonomies",
|
|
16
|
+
ENTRY: "/entries/:entryId",
|
|
17
|
+
ENTRIES_BY_TYPE: "/entries/type/:contentTypeId",
|
|
18
|
+
NEW_ENTRY: "/entries/new/:contentTypeId",
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
21
|
+
export type RouteKey = keyof typeof ROUTES;
|
|
22
|
+
|
|
23
|
+
export interface AdminNavigation {
|
|
24
|
+
navigate: (route: string, params?: Record<string, string>) => void;
|
|
25
|
+
currentRoute: string;
|
|
26
|
+
params: Record<string, string>;
|
|
27
|
+
canGoBack: boolean;
|
|
28
|
+
goBack: () => void;
|
|
29
|
+
navigateToEntry: (entryId: string) => void;
|
|
30
|
+
navigateToContentType: (contentTypeId: string) => void;
|
|
31
|
+
navigateToNewEntry: (contentTypeId: string) => void;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function buildRoute(
|
|
35
|
+
template: string,
|
|
36
|
+
params: Record<string, string>
|
|
37
|
+
): string {
|
|
38
|
+
let result = template;
|
|
39
|
+
for (const [key, value] of Object.entries(params)) {
|
|
40
|
+
result = result.replace(`:${key}`, value);
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TanStack Router Adapter
|
|
3
|
+
*
|
|
4
|
+
* Implements the AdminNavigation interface for TanStack Router,
|
|
5
|
+
* allowing shared page components to work with CLI routes.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useNavigate, useLocation, useParams } from "@tanstack/react-router";
|
|
9
|
+
import { useMemo, useCallback } from "react";
|
|
10
|
+
import type { AdminNavigation } from "./navigation";
|
|
11
|
+
|
|
12
|
+
export function useTanStackNavigation(): AdminNavigation {
|
|
13
|
+
const navigate = useNavigate();
|
|
14
|
+
const location = useLocation();
|
|
15
|
+
const params = useParams({ strict: false }) as Record<string, string>;
|
|
16
|
+
|
|
17
|
+
const handleNavigate = useCallback(
|
|
18
|
+
(route: string, routeParams?: Record<string, string>) => {
|
|
19
|
+
let path = route;
|
|
20
|
+
if (routeParams) {
|
|
21
|
+
for (const [key, value] of Object.entries(routeParams)) {
|
|
22
|
+
path = path.replace(`:${key}`, value).replace(`$${key}`, value);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
navigate({ to: path as any });
|
|
26
|
+
},
|
|
27
|
+
[navigate]
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const navigateToEntry = useCallback(
|
|
31
|
+
(entryId: string) => {
|
|
32
|
+
navigate({ to: "/entries/$entryId", params: { entryId } });
|
|
33
|
+
},
|
|
34
|
+
[navigate]
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const navigateToContentType = useCallback(
|
|
38
|
+
(contentTypeId: string) => {
|
|
39
|
+
navigate({
|
|
40
|
+
to: "/entries/type/$contentTypeId",
|
|
41
|
+
params: { contentTypeId },
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
[navigate]
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const navigateToNewEntry = useCallback(
|
|
48
|
+
(contentTypeId: string) => {
|
|
49
|
+
navigate({
|
|
50
|
+
to: "/entries/new/$contentTypeId",
|
|
51
|
+
params: { contentTypeId },
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
[navigate]
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const goBack = useCallback(() => {
|
|
58
|
+
window.history.back();
|
|
59
|
+
}, []);
|
|
60
|
+
|
|
61
|
+
return useMemo(
|
|
62
|
+
() => ({
|
|
63
|
+
navigate: handleNavigate,
|
|
64
|
+
currentRoute: location.pathname,
|
|
65
|
+
params: params ?? {},
|
|
66
|
+
canGoBack: window.history.length > 1,
|
|
67
|
+
goBack,
|
|
68
|
+
navigateToEntry,
|
|
69
|
+
navigateToContentType,
|
|
70
|
+
navigateToNewEntry,
|
|
71
|
+
}),
|
|
72
|
+
[
|
|
73
|
+
handleNavigate,
|
|
74
|
+
location.pathname,
|
|
75
|
+
params,
|
|
76
|
+
goBack,
|
|
77
|
+
navigateToEntry,
|
|
78
|
+
navigateToContentType,
|
|
79
|
+
navigateToNewEntry,
|
|
80
|
+
]
|
|
81
|
+
);
|
|
82
|
+
}
|