convex-cms 0.0.5-alpha.4 → 0.0.6
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 +3 -3
- package/admin/src/components/Sidebar.tsx +150 -58
- package/admin/src/components/ui/collapsible.tsx +7 -0
- package/admin/src/embed/components/EmbedSidebar.tsx +163 -68
- package/admin-dist/nitro.json +1 -1
- package/admin-dist/public/assets/{CmsEmptyState-CkqBIab3.js → CmsEmptyState-Do_erIgn.js} +1 -1
- package/admin-dist/public/assets/{CmsPageHeader-CUtl5MMG.js → CmsPageHeader-qDwPGi48.js} +1 -1
- package/admin-dist/public/assets/{CmsStatusBadge-CUYFgEe-.js → CmsStatusBadge-Dd9uToHE.js} +1 -1
- package/admin-dist/public/assets/{CmsSurface-CsJfAVa3.js → CmsSurface-DBy5Lumx.js} +1 -1
- package/admin-dist/public/assets/{CmsToolbar-CnfbcxeP.js → CmsToolbar-D1-Y-7SK.js} +1 -1
- package/admin-dist/public/assets/ContentEntryEditor-CWBiIx52.js +4 -0
- package/admin-dist/public/assets/{TaxonomyFilter-CWCxC5HZ.js → TaxonomyFilter-CdYQawxb.js} +1 -1
- package/admin-dist/public/assets/_contentTypeId-D9VMP6Gs.js +1 -0
- package/admin-dist/public/assets/_entryId-2FlCfqE7.js +1 -0
- package/admin-dist/public/assets/{alert-CF1BSzGR.js → alert-GxZx0y5c.js} +1 -1
- package/admin-dist/public/assets/{badge-CmuOIVKp.js → badge-BAlGIjop.js} +1 -1
- package/admin-dist/public/assets/{circle-check-big-BKDVG6DU.js → circle-check-big-CpLxAvEj.js} +1 -1
- package/admin-dist/public/assets/{command-XJxnF2Sd.js → command-di7XCqcv.js} +1 -1
- package/admin-dist/public/assets/content-D8zELsDG.js +1 -0
- package/admin-dist/public/assets/{content-types-CrNEm8Hf.js → content-types-BmzD0krT.js} +2 -2
- package/admin-dist/public/assets/globals-BvFfH-v9.css +1 -0
- package/admin-dist/public/assets/{index-C7xOwudI.js → index-zqfj4T_v.js} +1 -1
- package/admin-dist/public/assets/{label-CHCnXeBk.js → label-B6PPtKR5.js} +1 -1
- package/admin-dist/public/assets/{link-2-Bb34judH.js → link-2-W2fVnVOf.js} +1 -1
- package/admin-dist/public/assets/{list-9Pzt48ld.js → list-F8O0lZXC.js} +1 -1
- package/admin-dist/public/assets/main-dZT72bAG.js +97 -0
- package/admin-dist/public/assets/media-CETueFbV.js +1 -0
- package/admin-dist/public/assets/new._contentTypeId-BV2-TyyR.js +1 -0
- package/admin-dist/public/assets/{plus-Ceef7DHk.js → plus-AABQIF0N.js} +1 -1
- package/admin-dist/public/assets/{rotate-ccw-7k7-4VUq.js → rotate-ccw-BZpZtw0N.js} +1 -1
- package/admin-dist/public/assets/{scroll-area-CC6wujnp.js → scroll-area-CDfk-zrz.js} +1 -1
- package/admin-dist/public/assets/{search-DwoUV2pv.js → search-BvgYr-c9.js} +1 -1
- package/admin-dist/public/assets/{select-hOZTp8aC.js → select-BuiHcMzS.js} +1 -1
- package/admin-dist/public/assets/settings-DBxbYDvn.js +1 -0
- package/admin-dist/public/assets/{switch-jX2pDaNU.js → switch-DiJvolcs.js} +1 -1
- package/admin-dist/public/assets/tabs-Cgz6G_Xy.js +1 -0
- package/admin-dist/public/assets/{tanstack-adapter-B-Glm4kH.js → tanstack-adapter-BknsSgra.js} +1 -1
- package/admin-dist/public/assets/taxonomies-DOErsLl5.js +1 -0
- package/admin-dist/public/assets/{textarea-B6SfBmr0.js → textarea-CgggMxUX.js} +1 -1
- package/admin-dist/public/assets/{trash-BOCnIznD.js → trash-BU4ANuaW.js} +1 -1
- package/admin-dist/public/assets/{triangle-alert-CXFIO_Gu.js → triangle-alert-lvCbwp0s.js} +1 -1
- package/admin-dist/public/assets/{useBreadcrumbLabel-_6qBagc3.js → useBreadcrumbLabel-D00rvqjw.js} +1 -1
- package/admin-dist/public/assets/{usePermissions-M1ijZ7a6.js → usePermissions-D7tQowaF.js} +1 -1
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-collapsible.mjs +144 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-slot.mjs +21 -21
- package/admin-dist/server/_libs/lucide-react.mjs +131 -124
- package/admin-dist/server/_ssr/{CmsButton-DOiTVKQq.mjs → CmsButton-DbzfJru_.mjs} +1 -1
- package/admin-dist/server/_ssr/{CmsEmptyState-fbnGt3LD.mjs → CmsEmptyState-CuvcXr3Z.mjs} +3 -3
- package/admin-dist/server/_ssr/{CmsPageHeader-DHRrdOZa.mjs → CmsPageHeader-ClNPU7Up.mjs} +1 -1
- package/admin-dist/server/_ssr/{CmsStatusBadge-s7obWbKZ.mjs → CmsStatusBadge-CojMbrY7.mjs} +2 -2
- package/admin-dist/server/_ssr/{CmsSurface-rFoYjb62.mjs → CmsSurface-Dcv440rp.mjs} +1 -1
- package/admin-dist/server/_ssr/{CmsToolbar-zTE45z2q.mjs → CmsToolbar-BKv1nL6u.mjs} +2 -2
- package/admin-dist/server/_ssr/{ContentEntryEditor-BLoEjT_m.mjs → ContentEntryEditor-weiXSBdZ.mjs} +35 -51
- package/admin-dist/server/_ssr/{TaxonomyFilter-XAtaJC2z.mjs → TaxonomyFilter-BPQ57Mwk.mjs} +7 -7
- package/admin-dist/server/_ssr/{_contentTypeId-Csl4822C.mjs → _contentTypeId-DyyauLOs.mjs} +24 -23
- package/admin-dist/server/_ssr/{_entryId-D8alLFBx.mjs → _entryId-9Cafwxmw.mjs} +22 -21
- package/admin-dist/server/_ssr/_tanstack-start-manifest_v-Dk-FIYPN.mjs +4 -0
- package/admin-dist/server/_ssr/{command-C0Di14--.mjs → command-CEf8YBxY.mjs} +1 -1
- package/admin-dist/server/_ssr/{content-CT-FPsmV.mjs → content-ZFWVzO25.mjs} +20 -19
- package/admin-dist/server/_ssr/{content-types-C8cBFdzE.mjs → content-types-D25lUE-j.mjs} +18 -17
- package/admin-dist/server/_ssr/{index-BJtcrEc-.mjs → index-BlSIlH4Z.mjs} +10 -9
- package/admin-dist/server/_ssr/index.mjs +2 -2
- package/admin-dist/server/_ssr/{label-qn2Afwl4.mjs → label-PblVvdRv.mjs} +1 -1
- package/admin-dist/server/_ssr/{media-qv5IAsMZ.mjs → media-CD2_NUMw.mjs} +683 -314
- package/admin-dist/server/_ssr/{new._contentTypeId-DdGyrhqs.mjs → new._contentTypeId-dmZy6PBX.mjs} +20 -19
- package/admin-dist/server/_ssr/{router-nSVkxb6Y.mjs → router-x6Ab8T4s.mjs} +109 -43
- package/admin-dist/server/_ssr/{scroll-area-BCinP455.mjs → scroll-area-BH_1K-WT.mjs} +1 -1
- package/admin-dist/server/_ssr/{select-BKQlQScw.mjs → select-CrfEkFJw.mjs} +2 -2
- package/admin-dist/server/_ssr/{settings-BCr2KQlk.mjs → settings-DVdsoWoh.mjs} +158 -105
- package/admin-dist/server/_ssr/{switch-BaOi42fE.mjs → switch-DX_X8vZl.mjs} +1 -1
- package/admin-dist/server/_ssr/{tabs-DYXEi9kq.mjs → tabs-4FWM0sn8.mjs} +3 -3
- package/admin-dist/server/_ssr/{tanstack-adapter-Bsz8kha-.mjs → tanstack-adapter-D3ZcKtbY.mjs} +1 -1
- package/admin-dist/server/_ssr/{taxonomies-CueMHTbE.mjs → taxonomies-BHFfO9Yr.mjs} +21 -20
- package/admin-dist/server/_ssr/{textarea-CI0Jqx2x.mjs → textarea-CZVaroMc.mjs} +1 -1
- package/admin-dist/server/_ssr/{trash-DE6W8GoX.mjs → trash-9tUB2KwI.mjs} +14 -13
- package/admin-dist/server/_ssr/{useBreadcrumbLabel-B5Yi72lM.mjs → useBreadcrumbLabel-DVme3DSb.mjs} +1 -1
- package/admin-dist/server/_ssr/{usePermissions-C3nZ-Izm.mjs → usePermissions-zAQj-ruE.mjs} +1 -1
- package/admin-dist/server/index.mjs +188 -188
- package/dist/cli/commands/init.d.ts +12 -2
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +136 -138
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/index.js +2 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/templates/admin.d.ts +10 -0
- package/dist/cli/templates/admin.d.ts.map +1 -0
- package/dist/cli/templates/admin.js +212 -0
- package/dist/cli/templates/admin.js.map +1 -0
- package/dist/cli/templates/cmsClient.d.ts +7 -0
- package/dist/cli/templates/cmsClient.d.ts.map +1 -0
- package/dist/cli/templates/cmsClient.js +36 -0
- package/dist/cli/templates/cmsClient.js.map +1 -0
- package/dist/cli/templates/cmsConfig.d.ts +7 -0
- package/dist/cli/templates/cmsConfig.d.ts.map +1 -0
- package/dist/cli/templates/cmsConfig.js +86 -0
- package/dist/cli/templates/cmsConfig.js.map +1 -0
- package/dist/cli/templates/index.d.ts +10 -0
- package/dist/cli/templates/index.d.ts.map +1 -0
- package/dist/cli/templates/index.js +10 -0
- package/dist/cli/templates/index.js.map +1 -0
- package/dist/cli/templates/schemas/blog.d.ts +8 -0
- package/dist/cli/templates/schemas/blog.d.ts.map +1 -0
- package/dist/cli/templates/schemas/blog.js +103 -0
- package/dist/cli/templates/schemas/blog.js.map +1 -0
- package/dist/cli/templates/schemas/docs.d.ts +8 -0
- package/dist/cli/templates/schemas/docs.d.ts.map +1 -0
- package/dist/cli/templates/schemas/docs.js +110 -0
- package/dist/cli/templates/schemas/docs.js.map +1 -0
- package/dist/cli/templates/schemas/index.d.ts +11 -0
- package/dist/cli/templates/schemas/index.d.ts.map +1 -0
- package/dist/cli/templates/schemas/index.js +13 -0
- package/dist/cli/templates/schemas/index.js.map +1 -0
- package/dist/cli/templates/schemas/landing.d.ts +8 -0
- package/dist/cli/templates/schemas/landing.d.ts.map +1 -0
- package/dist/cli/templates/schemas/landing.js +135 -0
- package/dist/cli/templates/schemas/landing.js.map +1 -0
- package/dist/cli/utils/fileUtils.d.ts +21 -0
- package/dist/cli/utils/fileUtils.d.ts.map +1 -0
- package/dist/cli/utils/fileUtils.js +95 -0
- package/dist/cli/utils/fileUtils.js.map +1 -0
- package/dist/cli/utils/prompts.d.ts +25 -0
- package/dist/cli/utils/prompts.d.ts.map +1 -0
- package/dist/cli/utils/prompts.js +87 -0
- package/dist/cli/utils/prompts.js.map +1 -0
- package/dist/client/agentTools.d.ts +1 -1427
- package/dist/client/agentTools.d.ts.map +1 -1
- package/dist/component/contentTypeMutations.d.ts +1 -1
- package/dist/test.d.ts +5 -0
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +0 -1
- package/dist/test.js.map +1 -1
- package/package.json +28 -28
- package/admin/README.md +0 -99
- package/admin-dist/public/assets/ContentEntryEditor-BU220CCy.js +0 -4
- package/admin-dist/public/assets/_contentTypeId-DK8cskRt.js +0 -1
- package/admin-dist/public/assets/_entryId-CuVMExbb.js +0 -1
- package/admin-dist/public/assets/content-QBUxdxbS.js +0 -1
- package/admin-dist/public/assets/globals-B7Wsfh_v.css +0 -1
- package/admin-dist/public/assets/main-CjQ2VI9L.js +0 -97
- package/admin-dist/public/assets/media-Dc5PWt2Q.js +0 -1
- package/admin-dist/public/assets/new._contentTypeId-C_I4YxIa.js +0 -1
- package/admin-dist/public/assets/settings-t2PbCZh4.js +0 -1
- package/admin-dist/public/assets/tabs-q4EbZk7c.js +0 -1
- package/admin-dist/public/assets/taxonomies-kyk5P4ZW.js +0 -1
- package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BffZedId.mjs +0 -4
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ They work together through the same CMS component.
|
|
|
87
87
|
### 1. Install
|
|
88
88
|
|
|
89
89
|
```bash
|
|
90
|
-
|
|
90
|
+
pnpm add convex-cms
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
### 2. Add the Component
|
|
@@ -104,7 +104,7 @@ export default app;
|
|
|
104
104
|
|
|
105
105
|
### 3. Choose Your Setup
|
|
106
106
|
|
|
107
|
-
**For Admin UI:** Run `
|
|
107
|
+
**For Admin UI:** Run `pnpm convex-cms init` then `pnpm convex-cms admin`
|
|
108
108
|
→ [Full Admin UI Setup](./docs/guides/admin-ui-setup.md)
|
|
109
109
|
|
|
110
110
|
**For Custom Functions:** Create a CMS client and use it in your functions
|
|
@@ -144,7 +144,7 @@ export default app;
|
|
|
144
144
|
|
|
145
145
|
| Mode | Command | Best For |
|
|
146
146
|
|------|---------|----------|
|
|
147
|
-
| **CLI** | `
|
|
147
|
+
| **CLI** | `pnpm convex-cms admin` | Development |
|
|
148
148
|
| **Embed** | `<CmsAdmin api={api.admin} />` | Production |
|
|
149
149
|
|
|
150
150
|
Both modes call the same functions from your `convex/admin.ts`.
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
1
2
|
import { Link, useRouterState } from "@tanstack/react-router";
|
|
2
|
-
import {
|
|
3
|
+
import { useQuery } from "convex/react";
|
|
4
|
+
import { Layers, ChevronDown } from "lucide-react";
|
|
3
5
|
import { cn } from "~/lib/cn";
|
|
4
6
|
import { useAdminConfig } from "~/contexts";
|
|
5
7
|
import { Icon } from "~/lib/icons";
|
|
8
|
+
import { api } from "../../convex/_generated/api";
|
|
9
|
+
import {
|
|
10
|
+
Collapsible,
|
|
11
|
+
CollapsibleTrigger,
|
|
12
|
+
CollapsibleContent,
|
|
13
|
+
} from "~/components/ui/collapsible";
|
|
14
|
+
import { ContentTypeFormModal } from "~/components/ContentTypeFormModal";
|
|
6
15
|
import type { NavItem } from "~/lib/admin-config";
|
|
7
16
|
|
|
8
17
|
export function Sidebar() {
|
|
@@ -11,6 +20,13 @@ export function Sidebar() {
|
|
|
11
20
|
const config = useAdminConfig();
|
|
12
21
|
const { navItems, branding, layout } = config;
|
|
13
22
|
|
|
23
|
+
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
|
24
|
+
|
|
25
|
+
const contentTypesResult = useQuery(api.admin.listContentTypes, {
|
|
26
|
+
isActive: true,
|
|
27
|
+
});
|
|
28
|
+
const contentTypes = contentTypesResult?.page ?? [];
|
|
29
|
+
|
|
14
30
|
const isActive = (to: string, exact?: boolean) => {
|
|
15
31
|
if (exact) {
|
|
16
32
|
return currentPath === to;
|
|
@@ -18,73 +34,149 @@ export function Sidebar() {
|
|
|
18
34
|
return currentPath.startsWith(to);
|
|
19
35
|
};
|
|
20
36
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
const isContentActive =
|
|
38
|
+
currentPath === "/content" ||
|
|
39
|
+
currentPath.startsWith("/entries/type/") ||
|
|
40
|
+
currentPath.startsWith("/entries/new/") ||
|
|
41
|
+
currentPath.startsWith("/entries/");
|
|
42
|
+
|
|
43
|
+
const renderNavItem = (item: NavItem) => {
|
|
44
|
+
if (item.id === "content") {
|
|
45
|
+
return renderContentMenu(item);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<Link
|
|
50
|
+
key={item.id}
|
|
51
|
+
to={item.path}
|
|
52
|
+
className={cn(
|
|
53
|
+
"flex items-center gap-3 rounded-md px-2 py-2 text-sm font-medium transition-colors",
|
|
54
|
+
isActive(item.path, item.exact)
|
|
55
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
56
|
+
: "text-sidebar-foreground hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground"
|
|
57
|
+
)}
|
|
58
|
+
>
|
|
59
|
+
<Icon name={item.icon} className="size-5" />
|
|
60
|
+
<span className="flex-1">{item.label}</span>
|
|
61
|
+
{item.badge && (
|
|
62
|
+
<span className="rounded-full bg-sidebar-primary px-2 py-0.5 text-xs text-sidebar-primary-foreground">
|
|
63
|
+
{item.badge}
|
|
64
|
+
</span>
|
|
65
|
+
)}
|
|
66
|
+
</Link>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const renderContentMenu = (item: NavItem) => (
|
|
71
|
+
<Collapsible key={item.id} defaultOpen={isContentActive}>
|
|
72
|
+
<CollapsibleTrigger
|
|
73
|
+
className={cn(
|
|
74
|
+
"flex w-full items-center gap-3 rounded-md px-2 py-2 text-sm font-medium transition-colors",
|
|
75
|
+
isContentActive
|
|
76
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
77
|
+
: "text-sidebar-foreground hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
|
|
78
|
+
"group"
|
|
79
|
+
)}
|
|
80
|
+
>
|
|
81
|
+
<Icon name={item.icon} className="size-5" />
|
|
82
|
+
<span className="flex-1 text-left">{item.label}</span>
|
|
83
|
+
<ChevronDown className="size-4 transition-transform duration-200 group-data-[state=open]:rotate-180" />
|
|
84
|
+
</CollapsibleTrigger>
|
|
85
|
+
<CollapsibleContent>
|
|
86
|
+
<div className="ml-5 mt-1 space-y-1 border-l border-sidebar-border pl-3">
|
|
87
|
+
<Link
|
|
88
|
+
to="/content"
|
|
89
|
+
className={cn(
|
|
90
|
+
"flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors",
|
|
91
|
+
currentPath === "/content"
|
|
92
|
+
? "bg-sidebar-accent/60 text-sidebar-accent-foreground"
|
|
93
|
+
: "text-sidebar-foreground/80 hover:bg-sidebar-accent/30 hover:text-sidebar-accent-foreground"
|
|
94
|
+
)}
|
|
95
|
+
>
|
|
96
|
+
All Entries
|
|
97
|
+
</Link>
|
|
98
|
+
{contentTypes.map((type) => (
|
|
99
|
+
<Link
|
|
100
|
+
key={type._id}
|
|
101
|
+
to="/entries/type/$contentTypeId"
|
|
102
|
+
params={{ contentTypeId: type._id }}
|
|
103
|
+
className={cn(
|
|
104
|
+
"flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors",
|
|
105
|
+
currentPath === `/entries/type/${type._id}`
|
|
106
|
+
? "bg-sidebar-accent/60 text-sidebar-accent-foreground"
|
|
107
|
+
: "text-sidebar-foreground/80 hover:bg-sidebar-accent/30 hover:text-sidebar-accent-foreground"
|
|
108
|
+
)}
|
|
109
|
+
>
|
|
110
|
+
{type.displayName}
|
|
111
|
+
</Link>
|
|
112
|
+
))}
|
|
113
|
+
{contentTypes.length === 0 && contentTypesResult !== undefined && (
|
|
114
|
+
<button
|
|
115
|
+
type="button"
|
|
116
|
+
onClick={() => setIsCreateModalOpen(true)}
|
|
117
|
+
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"
|
|
118
|
+
>
|
|
119
|
+
+ Create content type
|
|
120
|
+
</button>
|
|
121
|
+
)}
|
|
122
|
+
</div>
|
|
123
|
+
</CollapsibleContent>
|
|
124
|
+
</Collapsible>
|
|
40
125
|
);
|
|
41
126
|
|
|
42
127
|
const sidebarWidth = layout.sidebarWidth;
|
|
43
128
|
|
|
44
129
|
return (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
<
|
|
130
|
+
<>
|
|
131
|
+
<aside
|
|
132
|
+
className="fixed inset-y-0 left-0 z-50 flex flex-col border-r border-sidebar-border bg-sidebar"
|
|
133
|
+
style={{ width: sidebarWidth }}
|
|
134
|
+
>
|
|
135
|
+
<div className="flex h-14 items-center gap-2 border-b border-sidebar-border px-4">
|
|
136
|
+
<Link to="/" className="flex items-center gap-2 font-semibold text-sidebar-foreground">
|
|
137
|
+
{branding.logo ? (
|
|
138
|
+
<img src={branding.logo} alt={branding.appName} className="size-8" />
|
|
139
|
+
) : (
|
|
140
|
+
<div className="flex size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
141
|
+
<Layers className="size-4" />
|
|
142
|
+
</div>
|
|
143
|
+
)}
|
|
144
|
+
<span className="text-base">{branding.appName}</span>
|
|
145
|
+
</Link>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<nav className="flex-1 space-y-6 overflow-y-auto p-4">
|
|
149
|
+
{navItems.main.length > 0 && (
|
|
150
|
+
<div className="space-y-1">
|
|
151
|
+
<span className="px-2 text-xs font-medium uppercase tracking-wider text-sidebar-foreground/60">
|
|
152
|
+
Main
|
|
153
|
+
</span>
|
|
154
|
+
<div className="space-y-1 pt-2">{navItems.main.map(renderNavItem)}</div>
|
|
56
155
|
</div>
|
|
57
156
|
)}
|
|
58
|
-
<span className="text-base">{branding.appName}</span>
|
|
59
|
-
</Link>
|
|
60
|
-
</div>
|
|
61
157
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
158
|
+
{navItems.config.length > 0 && (
|
|
159
|
+
<div className="space-y-1">
|
|
160
|
+
<span className="px-2 text-xs font-medium uppercase tracking-wider text-sidebar-foreground/60">
|
|
161
|
+
Configuration
|
|
162
|
+
</span>
|
|
163
|
+
<div className="space-y-1 pt-2">{navItems.config.map(renderNavItem)}</div>
|
|
164
|
+
</div>
|
|
165
|
+
)}
|
|
166
|
+
</nav>
|
|
71
167
|
|
|
72
|
-
|
|
73
|
-
<div className="
|
|
74
|
-
<span
|
|
75
|
-
|
|
76
|
-
</span>
|
|
77
|
-
<div className="space-y-1 pt-2">{navItems.config.map(renderNavItem)}</div>
|
|
168
|
+
<div className="border-t border-sidebar-border p-4">
|
|
169
|
+
<div className="flex items-center justify-between text-xs text-sidebar-foreground/60">
|
|
170
|
+
<span>Version</span>
|
|
171
|
+
<span className="font-mono">0.1.0</span>
|
|
78
172
|
</div>
|
|
79
|
-
)}
|
|
80
|
-
</nav>
|
|
81
|
-
|
|
82
|
-
<div className="border-t border-sidebar-border p-4">
|
|
83
|
-
<div className="flex items-center justify-between text-xs text-sidebar-foreground/60">
|
|
84
|
-
<span>Version</span>
|
|
85
|
-
<span className="font-mono">0.1.0</span>
|
|
86
173
|
</div>
|
|
87
|
-
</
|
|
88
|
-
|
|
174
|
+
</aside>
|
|
175
|
+
|
|
176
|
+
<ContentTypeFormModal
|
|
177
|
+
isOpen={isCreateModalOpen}
|
|
178
|
+
onClose={() => setIsCreateModalOpen(false)}
|
|
179
|
+
/>
|
|
180
|
+
</>
|
|
89
181
|
);
|
|
90
182
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
|
|
2
|
+
|
|
3
|
+
const Collapsible = CollapsiblePrimitive.Root;
|
|
4
|
+
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
|
|
5
|
+
const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;
|
|
6
|
+
|
|
7
|
+
export { Collapsible, CollapsibleTrigger, CollapsibleContent };
|
|
@@ -5,11 +5,20 @@
|
|
|
5
5
|
* the EmbedNavigation context for navigation instead of TanStack Router.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { useQuery } from "convex/react";
|
|
10
|
+
import { Layers, ChevronDown } from "lucide-react";
|
|
9
11
|
import { cn } from "../../lib/cn";
|
|
10
12
|
import { useAdminConfig } from "../../contexts";
|
|
11
13
|
import { Icon } from "../../lib/icons";
|
|
12
14
|
import { useEmbedNavigation, type EmbedRoute } from "../navigation";
|
|
15
|
+
import { useApi } from "../contexts/ApiContext";
|
|
16
|
+
import {
|
|
17
|
+
Collapsible,
|
|
18
|
+
CollapsibleTrigger,
|
|
19
|
+
CollapsibleContent,
|
|
20
|
+
} from "../../components/ui/collapsible";
|
|
21
|
+
import { ContentTypeFormModal } from "../../components/ContentTypeFormModal";
|
|
13
22
|
import type { NavItem } from "../../lib/admin-config";
|
|
14
23
|
|
|
15
24
|
function pathToRoute(path: string): EmbedRoute {
|
|
@@ -25,95 +34,181 @@ function pathToRoute(path: string): EmbedRoute {
|
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
export function EmbedSidebar() {
|
|
28
|
-
const { currentPath, navigate } = useEmbedNavigation();
|
|
37
|
+
const { currentPath, navigate, navigateToContentType } = useEmbedNavigation();
|
|
29
38
|
const config = useAdminConfig();
|
|
30
39
|
const { navItems, branding, layout } = config;
|
|
40
|
+
const api = useApi();
|
|
41
|
+
|
|
42
|
+
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
|
43
|
+
|
|
44
|
+
const contentTypesResult = useQuery(api.listContentTypes, {
|
|
45
|
+
isActive: true,
|
|
46
|
+
});
|
|
47
|
+
const contentTypes = contentTypesResult?.page ?? [];
|
|
48
|
+
|
|
49
|
+
const normalizedPath = currentPath.replace(/^\/admin/, "");
|
|
31
50
|
|
|
32
51
|
const isActive = (path: string, exact?: boolean) => {
|
|
33
|
-
const normalizedCurrent = currentPath.replace(/^\/admin/, "");
|
|
34
52
|
if (exact) {
|
|
35
|
-
return
|
|
53
|
+
return normalizedPath === path;
|
|
36
54
|
}
|
|
37
|
-
return
|
|
55
|
+
return normalizedPath.startsWith(path);
|
|
38
56
|
};
|
|
39
57
|
|
|
58
|
+
const isContentActive =
|
|
59
|
+
normalizedPath === "/content" ||
|
|
60
|
+
normalizedPath.startsWith("/entries/type/") ||
|
|
61
|
+
normalizedPath.startsWith("/entries/new/") ||
|
|
62
|
+
normalizedPath.startsWith("/entries/");
|
|
63
|
+
|
|
40
64
|
const handleNavClick = (item: NavItem) => {
|
|
41
65
|
const route = pathToRoute(item.path);
|
|
42
66
|
navigate(route);
|
|
43
67
|
};
|
|
44
68
|
|
|
45
|
-
const renderNavItem = (item: NavItem) =>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
const renderNavItem = (item: NavItem) => {
|
|
70
|
+
if (item.id === "content") {
|
|
71
|
+
return renderContentMenu(item);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<button
|
|
76
|
+
key={item.id}
|
|
77
|
+
type="button"
|
|
78
|
+
onClick={() => handleNavClick(item)}
|
|
79
|
+
className={cn(
|
|
80
|
+
"flex w-full items-center gap-3 rounded-md px-2 py-2 text-left text-sm font-medium transition-colors",
|
|
81
|
+
isActive(item.path, item.exact)
|
|
82
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
83
|
+
: "text-sidebar-foreground hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground"
|
|
84
|
+
)}
|
|
85
|
+
>
|
|
86
|
+
<Icon name={item.icon} className="size-5" />
|
|
87
|
+
<span className="flex-1">{item.label}</span>
|
|
88
|
+
{item.badge && (
|
|
89
|
+
<span className="rounded-full bg-sidebar-primary px-2 py-0.5 text-xs text-sidebar-primary-foreground">
|
|
90
|
+
{item.badge}
|
|
91
|
+
</span>
|
|
92
|
+
)}
|
|
93
|
+
</button>
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const renderContentMenu = (item: NavItem) => (
|
|
98
|
+
<Collapsible key={item.id} defaultOpen={isContentActive}>
|
|
99
|
+
<CollapsibleTrigger
|
|
100
|
+
className={cn(
|
|
101
|
+
"flex w-full items-center gap-3 rounded-md px-2 py-2 text-sm font-medium transition-colors",
|
|
102
|
+
isContentActive
|
|
103
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
104
|
+
: "text-sidebar-foreground hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
|
|
105
|
+
"group"
|
|
106
|
+
)}
|
|
107
|
+
>
|
|
108
|
+
<Icon name={item.icon} className="size-5" />
|
|
109
|
+
<span className="flex-1 text-left">{item.label}</span>
|
|
110
|
+
<ChevronDown className="size-4 transition-transform duration-200 group-data-[state=open]:rotate-180" />
|
|
111
|
+
</CollapsibleTrigger>
|
|
112
|
+
<CollapsibleContent>
|
|
113
|
+
<div className="ml-5 mt-1 space-y-1 border-l border-sidebar-border pl-3">
|
|
114
|
+
<button
|
|
115
|
+
type="button"
|
|
116
|
+
onClick={() => navigate("content")}
|
|
117
|
+
className={cn(
|
|
118
|
+
"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition-colors",
|
|
119
|
+
normalizedPath === "/content"
|
|
120
|
+
? "bg-sidebar-accent/60 text-sidebar-accent-foreground"
|
|
121
|
+
: "text-sidebar-foreground/80 hover:bg-sidebar-accent/30 hover:text-sidebar-accent-foreground"
|
|
122
|
+
)}
|
|
123
|
+
>
|
|
124
|
+
All Entries
|
|
125
|
+
</button>
|
|
126
|
+
{contentTypes.map((type) => (
|
|
127
|
+
<button
|
|
128
|
+
key={type._id}
|
|
129
|
+
type="button"
|
|
130
|
+
onClick={() => navigateToContentType(type._id)}
|
|
131
|
+
className={cn(
|
|
132
|
+
"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition-colors",
|
|
133
|
+
normalizedPath === `/entries/type/${type._id}`
|
|
134
|
+
? "bg-sidebar-accent/60 text-sidebar-accent-foreground"
|
|
135
|
+
: "text-sidebar-foreground/80 hover:bg-sidebar-accent/30 hover:text-sidebar-accent-foreground"
|
|
136
|
+
)}
|
|
137
|
+
>
|
|
138
|
+
{type.displayName}
|
|
139
|
+
</button>
|
|
140
|
+
))}
|
|
141
|
+
{contentTypes.length === 0 && contentTypesResult !== undefined && (
|
|
142
|
+
<button
|
|
143
|
+
type="button"
|
|
144
|
+
onClick={() => setIsCreateModalOpen(true)}
|
|
145
|
+
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"
|
|
146
|
+
>
|
|
147
|
+
+ Create content type
|
|
148
|
+
</button>
|
|
149
|
+
)}
|
|
150
|
+
</div>
|
|
151
|
+
</CollapsibleContent>
|
|
152
|
+
</Collapsible>
|
|
65
153
|
);
|
|
66
154
|
|
|
67
155
|
const sidebarWidth = layout.sidebarWidth;
|
|
68
156
|
|
|
69
157
|
return (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
<
|
|
158
|
+
<>
|
|
159
|
+
<aside
|
|
160
|
+
className="fixed inset-y-0 left-0 z-50 flex flex-col border-r border-sidebar-border bg-sidebar"
|
|
161
|
+
style={{ width: sidebarWidth }}
|
|
162
|
+
>
|
|
163
|
+
<div className="flex h-14 items-center gap-2 border-b border-sidebar-border px-4">
|
|
164
|
+
<button
|
|
165
|
+
type="button"
|
|
166
|
+
onClick={() => navigate("dashboard")}
|
|
167
|
+
className="flex items-center gap-2 font-semibold text-sidebar-foreground"
|
|
168
|
+
>
|
|
169
|
+
{branding.logo ? (
|
|
170
|
+
<img src={branding.logo} alt={branding.appName} className="size-8" />
|
|
171
|
+
) : (
|
|
172
|
+
<div className="flex size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
173
|
+
<Layers className="size-4" />
|
|
174
|
+
</div>
|
|
175
|
+
)}
|
|
176
|
+
<span className="text-base">{branding.appName}</span>
|
|
177
|
+
</button>
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
<nav className="flex-1 space-y-6 overflow-y-auto p-4">
|
|
181
|
+
{navItems.main.length > 0 && (
|
|
182
|
+
<div className="space-y-1">
|
|
183
|
+
<span className="px-2 text-xs font-medium uppercase tracking-wider text-sidebar-foreground/60">
|
|
184
|
+
Main
|
|
185
|
+
</span>
|
|
186
|
+
<div className="space-y-1 pt-2">{navItems.main.map(renderNavItem)}</div>
|
|
85
187
|
</div>
|
|
86
188
|
)}
|
|
87
|
-
<span className="text-base">{branding.appName}</span>
|
|
88
|
-
</button>
|
|
89
|
-
</div>
|
|
90
|
-
|
|
91
|
-
<nav className="flex-1 space-y-6 overflow-y-auto p-4">
|
|
92
|
-
{navItems.main.length > 0 && (
|
|
93
|
-
<div className="space-y-1">
|
|
94
|
-
<span className="px-2 text-xs font-medium uppercase tracking-wider text-sidebar-foreground/60">
|
|
95
|
-
Main
|
|
96
|
-
</span>
|
|
97
|
-
<div className="space-y-1 pt-2">{navItems.main.map(renderNavItem)}</div>
|
|
98
|
-
</div>
|
|
99
|
-
)}
|
|
100
189
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
190
|
+
{navItems.config.length > 0 && (
|
|
191
|
+
<div className="space-y-1">
|
|
192
|
+
<span className="px-2 text-xs font-medium uppercase tracking-wider text-sidebar-foreground/60">
|
|
193
|
+
Configuration
|
|
194
|
+
</span>
|
|
195
|
+
<div className="space-y-1 pt-2">{navItems.config.map(renderNavItem)}</div>
|
|
196
|
+
</div>
|
|
197
|
+
)}
|
|
198
|
+
</nav>
|
|
110
199
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
200
|
+
<div className="border-t border-sidebar-border p-4">
|
|
201
|
+
<div className="flex items-center justify-between text-xs text-sidebar-foreground/60">
|
|
202
|
+
<span>Version</span>
|
|
203
|
+
<span className="font-mono">0.1.0</span>
|
|
204
|
+
</div>
|
|
115
205
|
</div>
|
|
116
|
-
</
|
|
117
|
-
|
|
206
|
+
</aside>
|
|
207
|
+
|
|
208
|
+
<ContentTypeFormModal
|
|
209
|
+
isOpen={isCreateModalOpen}
|
|
210
|
+
onClose={() => setIsCreateModalOpen(false)}
|
|
211
|
+
/>
|
|
212
|
+
</>
|
|
118
213
|
);
|
|
119
214
|
}
|
package/admin-dist/nitro.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as i,j as o,
|
|
1
|
+
import{r as i,j as o,ah as ge,aa as L,ac as A,a5 as I,a4 as D,a7 as k,ai as me,a2 as _,aj as xe,a6 as z,ak as he,al as be,am as ve,an as Ce,ao as ye,c as b,ab as De}from"./main-dZT72bAG.js";import{X as je,C as T,u as ke,a as Ne}from"./badge-BAlGIjop.js";function Re(e){const t=_e(e),r=i.forwardRef((s,a)=>{const{children:n,...c}=s,l=i.Children.toArray(n),d=l.find(Ie);if(d){const u=d.props.children,p=l.map(f=>f===d?i.Children.count(u)>1?i.Children.only(null):i.isValidElement(u)?u.props.children:null:f);return o.jsx(t,{...c,ref:a,children:i.isValidElement(u)?i.cloneElement(u,void 0,p):null})}return o.jsx(t,{...c,ref:a,children:n})});return r.displayName=`${e}.Slot`,r}function _e(e){const t=i.forwardRef((r,s)=>{const{children:a,...n}=r;if(i.isValidElement(a)){const c=we(a),l=Pe(n,a.props);return a.type!==i.Fragment&&(l.ref=s?ge(s,c):c),i.cloneElement(a,l)}return i.Children.count(a)>1?i.Children.only(null):null});return t.displayName=`${e}.SlotClone`,t}var Ee=Symbol("radix.slottable");function Ie(e){return i.isValidElement(e)&&typeof e.type=="function"&&"__radixId"in e.type&&e.type.__radixId===Ee}function Pe(e,t){const r={...t};for(const s in t){const a=e[s],n=t[s];/^on[A-Z]/.test(s)?a&&n?r[s]=(...l)=>{const d=n(...l);return a(...l),d}:a&&(r[s]=a):s==="style"?r[s]={...a,...n}:s==="className"&&(r[s]=[a,n].filter(Boolean).join(" "))}return{...e,...r}}function we(e){let t=Object.getOwnPropertyDescriptor(e.props,"ref")?.get,r=t&&"isReactWarning"in t&&t.isReactWarning;return r?e.ref:(t=Object.getOwnPropertyDescriptor(e,"ref")?.get,r=t&&"isReactWarning"in t&&t.isReactWarning,r?e.props.ref:e.props.ref||e.ref)}var P="Dialog",[G]=z(P),[Oe,h]=G(P),V=e=>{const{__scopeDialog:t,children:r,open:s,defaultOpen:a,onOpenChange:n,modal:c=!0}=e,l=i.useRef(null),d=i.useRef(null),[u,p]=L({prop:s,defaultProp:a??!1,onChange:n,caller:P});return o.jsx(Oe,{scope:t,triggerRef:l,contentRef:d,contentId:A(),titleId:A(),descriptionId:A(),open:u,onOpenChange:p,onOpenToggle:i.useCallback(()=>p(f=>!f),[p]),modal:c,children:r})};V.displayName=P;var H="DialogTrigger",Se=i.forwardRef((e,t)=>{const{__scopeDialog:r,...s}=e,a=h(H,r),n=_(t,a.triggerRef);return o.jsx(D.button,{type:"button","aria-haspopup":"dialog","aria-expanded":a.open,"aria-controls":a.contentId,"data-state":W(a.open),...s,ref:n,onClick:k(e.onClick,a.onOpenToggle)})});Se.displayName=H;var M="DialogPortal",[Ae,q]=G(M,{forceMount:void 0}),K=e=>{const{__scopeDialog:t,forceMount:r,children:s,container:a}=e,n=h(M,t);return o.jsx(Ae,{scope:t,forceMount:r,children:i.Children.map(s,c=>o.jsx(I,{present:r||n.open,children:o.jsx(me,{asChild:!0,container:a,children:c})}))})};K.displayName=M;var E="DialogOverlay",U=i.forwardRef((e,t)=>{const r=q(E,e.__scopeDialog),{forceMount:s=r.forceMount,...a}=e,n=h(E,e.__scopeDialog);return n.modal?o.jsx(I,{present:s||n.open,children:o.jsx(Me,{...a,ref:t})}):null});U.displayName=E;var Te=Re("DialogOverlay.RemoveScroll"),Me=i.forwardRef((e,t)=>{const{__scopeDialog:r,...s}=e,a=h(E,r);return o.jsx(he,{as:Te,allowPinchZoom:!0,shards:[a.contentRef],children:o.jsx(D.div,{"data-state":W(a.open),...s,ref:t,style:{pointerEvents:"auto",...s.style}})})}),N="DialogContent",X=i.forwardRef((e,t)=>{const r=q(N,e.__scopeDialog),{forceMount:s=r.forceMount,...a}=e,n=h(N,e.__scopeDialog);return o.jsx(I,{present:s||n.open,children:n.modal?o.jsx(Fe,{...a,ref:t}):o.jsx(We,{...a,ref:t})})});X.displayName=N;var Fe=i.forwardRef((e,t)=>{const r=h(N,e.__scopeDialog),s=i.useRef(null),a=_(t,r.contentRef,s);return i.useEffect(()=>{const n=s.current;if(n)return xe(n)},[]),o.jsx(Z,{...e,ref:a,trapFocus:r.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:k(e.onCloseAutoFocus,n=>{n.preventDefault(),r.triggerRef.current?.focus()}),onPointerDownOutside:k(e.onPointerDownOutside,n=>{const c=n.detail.originalEvent,l=c.button===0&&c.ctrlKey===!0;(c.button===2||l)&&n.preventDefault()}),onFocusOutside:k(e.onFocusOutside,n=>n.preventDefault())})}),We=i.forwardRef((e,t)=>{const r=h(N,e.__scopeDialog),s=i.useRef(!1),a=i.useRef(!1);return o.jsx(Z,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:n=>{e.onCloseAutoFocus?.(n),n.defaultPrevented||(s.current||r.triggerRef.current?.focus(),n.preventDefault()),s.current=!1,a.current=!1},onInteractOutside:n=>{e.onInteractOutside?.(n),n.defaultPrevented||(s.current=!0,n.detail.originalEvent.type==="pointerdown"&&(a.current=!0));const c=n.target;r.triggerRef.current?.contains(c)&&n.preventDefault(),n.detail.originalEvent.type==="focusin"&&a.current&&n.preventDefault()}})}),Z=i.forwardRef((e,t)=>{const{__scopeDialog:r,trapFocus:s,onOpenAutoFocus:a,onCloseAutoFocus:n,...c}=e,l=h(N,r),d=i.useRef(null),u=_(t,d);return be(),o.jsxs(o.Fragment,{children:[o.jsx(ve,{asChild:!0,loop:!0,trapped:s,onMountAutoFocus:a,onUnmountAutoFocus:n,children:o.jsx(Ce,{role:"dialog",id:l.contentId,"aria-describedby":l.descriptionId,"aria-labelledby":l.titleId,"data-state":W(l.open),...c,ref:u,onDismiss:()=>l.onOpenChange(!1)})}),o.jsxs(o.Fragment,{children:[o.jsx($e,{titleId:l.titleId}),o.jsx(Le,{contentRef:d,descriptionId:l.descriptionId})]})]})}),F="DialogTitle",Y=i.forwardRef((e,t)=>{const{__scopeDialog:r,...s}=e,a=h(F,r);return o.jsx(D.h2,{id:a.titleId,...s,ref:t})});Y.displayName=F;var J="DialogDescription",Q=i.forwardRef((e,t)=>{const{__scopeDialog:r,...s}=e,a=h(J,r);return o.jsx(D.p,{id:a.descriptionId,...s,ref:t})});Q.displayName=J;var ee="DialogClose",te=i.forwardRef((e,t)=>{const{__scopeDialog:r,...s}=e,a=h(ee,r);return o.jsx(D.button,{type:"button",...s,ref:t,onClick:k(e.onClick,()=>a.onOpenChange(!1))})});te.displayName=ee;function W(e){return e?"open":"closed"}var ne="DialogTitleWarning",[ut,oe]=ye(ne,{contentName:N,titleName:F,docsSlug:"dialog"}),$e=({titleId:e})=>{const t=oe(ne),r=`\`${t.contentName}\` requires a \`${t.titleName}\` for the component to be accessible for screen reader users.
|
|
2
2
|
|
|
3
3
|
If you want to hide the \`${t.titleName}\`, you can wrap it with our VisuallyHidden component.
|
|
4
4
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e,c}from"./main-
|
|
1
|
+
import{j as e,c}from"./main-dZT72bAG.js";function x({title:i,description:s,actions:t,breadcrumbs:a,className:l,...r}){return e.jsxs("div",{className:c("mb-6",l),...r,children:[a&&e.jsx("div",{className:"mb-2",children:a}),e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("h1",{className:"text-2xl font-semibold tracking-tight text-foreground",children:i}),s&&e.jsx("p",{className:"text-sm text-muted-foreground",children:s})]}),t&&e.jsx("div",{className:"flex items-center gap-2",children:t})]})]})}export{x as C};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e,c as l}from"./main-
|
|
1
|
+
import{j as e,c as l}from"./main-dZT72bAG.js";import{B as o}from"./badge-BAlGIjop.js";const i={draft:{label:"Draft",className:"status-draft",icon:e.jsx("svg",{className:"size-3",fill:"currentColor",viewBox:"0 0 8 8",children:e.jsx("circle",{cx:"4",cy:"4",r:"3"})})},published:{label:"Published",className:"status-published",icon:e.jsx("svg",{className:"size-3",fill:"none",stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M5 13l4 4L19 7"})})},scheduled:{label:"Scheduled",className:"status-scheduled",icon:e.jsxs("svg",{className:"size-3",fill:"none",stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",children:[e.jsx("circle",{cx:"12",cy:"12",r:"10"}),e.jsx("path",{strokeLinecap:"round",d:"M12 6v6l4 2"})]})},archived:{label:"Archived",className:"status-archived",icon:e.jsx("svg",{className:"size-3",fill:"none",stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"})})}},c={gray:"bg-muted text-muted-foreground",yellow:"bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400",blue:"bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400",green:"bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400",red:"bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400",purple:"bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-400",orange:"bg-orange-100 text-orange-800 dark:bg-orange-900/30 dark:text-orange-400"};function d(){return e.jsx("svg",{className:"size-3",fill:"currentColor",viewBox:"0 0 8 8",children:e.jsx("circle",{cx:"4",cy:"4",r:"3"})})}function g({status:n,customConfig:s,className:a,...t}){if(s)return e.jsxs(o,{variant:"secondary",className:l("gap-1.5 px-2 py-0.5 text-xs font-medium",c[s.color],a),...t,children:[d(),s.displayName]});const r=i[n];return r?e.jsxs(o,{variant:"secondary",className:l("gap-1.5 px-2 py-0.5 text-xs font-medium",r.className,a),...t,children:[r.icon,r.label]}):e.jsxs(o,{variant:"secondary",className:l("gap-1.5 px-2 py-0.5 text-xs font-medium",c.gray,a),...t,children:[d(),n]})}export{g as C};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as r,c as t}from"./main-
|
|
1
|
+
import{j as r,c as t}from"./main-dZT72bAG.js";const l={base:"surface-base",elevated:"surface-elevated",floating:"surface-floating"},m={none:"",sm:"p-3",md:"p-4",lg:"p-6"},u={none:"rounded-none",sm:"rounded-sm",md:"rounded-md",lg:"rounded-lg"};function f({elevation:e="base",padding:s="md",rounded:n="lg",className:a,children:d,...o}){return r.jsx("div",{className:t(l[e],m[s],u[n],a),...o,children:d})}export{f as C};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e,c}from"./main-
|
|
1
|
+
import{j as e,c}from"./main-dZT72bAG.js";import{I as i}from"./CmsEmptyState-Do_erIgn.js";import{S as p}from"./search-BvgYr-c9.js";function j({left:t,right:s,search:a,filters:r,actions:l,className:m,children:n,...o}){return e.jsxs("div",{className:c("flex flex-wrap items-center justify-between gap-3 pb-4",m),...o,children:[e.jsxs("div",{className:"flex flex-1 flex-wrap items-center gap-2",children:[a&&e.jsxs("div",{className:"relative w-full max-w-xs",children:[e.jsx(p,{className:"absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground"}),e.jsx(i,{type:"search",placeholder:a.placeholder??"Search...",value:a.value,onChange:x=>a.onChange(x.target.value),className:"pl-9"})]}),r,t,n]}),(s||l)&&e.jsx("div",{className:"flex items-center gap-2",children:s??l})]})}export{j as C};
|