@vexcms/next 0.1.0-alpha.20 → 0.1.0-alpha.22
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/dist/NextAdminLayoutClient.d.ts +1 -1
- package/dist/NextAdminLayoutClient.d.ts.map +1 -1
- package/dist/NextAdminLayoutClient.js +6 -6
- package/dist/NextAdminLayoutClient.js.map +1 -1
- package/dist/NextAdminPage.d.ts.map +1 -1
- package/dist/NextAdminPage.js +1 -1
- package/dist/{chunk-LHJAXWLB.js → chunk-L6N3D6L5.js} +38 -10
- package/dist/chunk-L6N3D6L5.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-LHJAXWLB.js.map +0 -1
|
@@ -27,8 +27,8 @@ import { type AdminUser } from "@vexcms/react";
|
|
|
27
27
|
*/
|
|
28
28
|
export declare function NextAdminLayoutClient(props: {
|
|
29
29
|
children: ReactNode;
|
|
30
|
-
user?: AdminUser;
|
|
31
30
|
organization?: Record<string, unknown>;
|
|
32
31
|
sidebarOpen?: boolean;
|
|
32
|
+
user?: AdminUser;
|
|
33
33
|
}): import("react").JSX.Element;
|
|
34
34
|
//# sourceMappingURL=NextAdminLayoutClient.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NextAdminLayoutClient.d.ts","sourceRoot":"","sources":["../src/NextAdminLayoutClient.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"NextAdminLayoutClient.d.ts","sourceRoot":"","sources":["../src/NextAdminLayoutClient.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAM5D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,QAAQ,EAAE,SAAS,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,+BAuBA"}
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"use client";
|
|
3
3
|
|
|
4
4
|
// src/NextAdminLayoutClient.tsx
|
|
5
|
-
import {
|
|
6
|
-
import NextLink from "next/link";
|
|
5
|
+
import { AdminLayout } from "@vexcms/react";
|
|
7
6
|
import NextImage from "next/image";
|
|
7
|
+
import NextLink from "next/link";
|
|
8
|
+
import { usePathname } from "next/navigation";
|
|
8
9
|
import { NuqsAdapter } from "nuqs/adapters/next/app";
|
|
9
|
-
import { AdminLayout } from "@vexcms/react";
|
|
10
10
|
import { jsx } from "react/jsx-runtime";
|
|
11
11
|
function NextAdminLayoutClient(props) {
|
|
12
12
|
const pathname = usePathname();
|
|
@@ -16,13 +16,13 @@ function NextAdminLayoutClient(props) {
|
|
|
16
16
|
return /* @__PURE__ */ jsx(NuqsAdapter, { children: /* @__PURE__ */ jsx(
|
|
17
17
|
AdminLayout,
|
|
18
18
|
{
|
|
19
|
+
activeDocID,
|
|
19
20
|
activeSlug,
|
|
20
21
|
components: { Link: NextLink, Image: NextImage },
|
|
21
|
-
pathname,
|
|
22
|
-
activeDocID,
|
|
23
|
-
user: props.user,
|
|
24
22
|
organization: props.organization,
|
|
23
|
+
pathname,
|
|
25
24
|
sidebarOpen: props.sidebarOpen,
|
|
25
|
+
user: props.user,
|
|
26
26
|
children: props.children
|
|
27
27
|
}
|
|
28
28
|
) });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/NextAdminLayoutClient.tsx"],"sourcesContent":["\"use client\";\n// \"use client\" is injected by the tsup build banner for this entry (see\n// tsup.config.ts) so the emitted module carries the client boundary.\nimport type { ReactNode } from \"react\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/NextAdminLayoutClient.tsx"],"sourcesContent":["\"use client\";\n// \"use client\" is injected by the tsup build banner for this entry (see\n// tsup.config.ts) so the emitted module carries the client boundary.\nimport type { ReactNode } from \"react\";\n\nimport { AdminLayout, type AdminUser } from \"@vexcms/react\";\nimport NextImage from \"next/image\";\nimport NextLink from \"next/link\";\nimport { usePathname } from \"next/navigation\";\nimport { NuqsAdapter } from \"nuqs/adapters/next/app\";\n\n/**\n * Client leaf for the Next.js admin layout.\n *\n * Owns all client-only wiring that cannot run on the server:\n * - `usePathname()` to derive the active collection slug / document id for\n * sidebar highlighting (Next.js layouts do not receive route params).\n * - `NuqsAdapter` (`nuqs/adapters/next/app`) so URL state works inside the\n * admin routes.\n * - `NextLink` / `NextImage` passed as framework components so every\n * `VexLink`/`VexImage` uses Next.js routing and image optimisation.\n *\n * Config reaches `AdminLayout`'s children through the app's own\n * `VexConfigProvider` mount, not through a prop on this component — this\n * leaf never touches config at all.\n *\n * This component is internal to `@vexcms/next` — applications render\n * {@link NextAdminLayout} instead.\n *\n * @param props - Layout props.\n * @param props.children - The page content from `[[...slug]]/page.tsx`.\n * @param props.user - Current user for the admin shell.\n * @returns The admin shell rendered from `children`, wrapped in `NuqsAdapter`\n * and the shared `AdminLayout`, wired with the active slug/document id derived\n * from `usePathname()` and Next.js `Link`/`Image` components.\n */\nexport function NextAdminLayoutClient(props: {\n children: ReactNode;\n organization?: Record<string, unknown>;\n sidebarOpen?: boolean;\n user?: AdminUser;\n}) {\n const pathname = usePathname();\n // pathname: \"/admin\", \"/admin/posts\", \"/admin/posts/123\"\n // Split on \"/\" and take the segment after \"admin\"\n const segments = pathname.split(\"/\").filter(Boolean);\n const activeSlug = segments[1]; // undefined on /admin, \"posts\" on /admin/posts\n const activeDocID = segments[2];\n\n return (\n <NuqsAdapter>\n <AdminLayout\n activeDocID={activeDocID}\n activeSlug={activeSlug}\n components={{ Link: NextLink, Image: NextImage }}\n organization={props.organization}\n pathname={pathname}\n sidebarOpen={props.sidebarOpen}\n user={props.user}\n >\n {props.children}\n </AdminLayout>\n </NuqsAdapter>\n );\n}\n"],"mappings":";;;;AAKA,SAAS,mBAAmC;AAC5C,OAAO,eAAe;AACtB,OAAO,cAAc;AACrB,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AA0CtB;AAfC,SAAS,sBAAsB,OAKnC;AACD,QAAM,WAAW,YAAY;AAG7B,QAAM,WAAW,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AACnD,QAAM,aAAa,SAAS,CAAC;AAC7B,QAAM,cAAc,SAAS,CAAC;AAE9B,SACE,oBAAC,eACC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,YAAY,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA,MAC/C,cAAc,MAAM;AAAA,MACpB;AAAA,MACA,aAAa,MAAM;AAAA,MACnB,MAAM,MAAM;AAAA,MAEX,gBAAM;AAAA;AAAA,EACT,GACF;AAEJ;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NextAdminPage.d.ts","sourceRoot":"","sources":["../src/NextAdminPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NextAdminPage.d.ts","sourceRoot":"","sources":["../src/NextAdminPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoC,SAAS,EAAoB,MAAM,cAAc,CAAC;AAqBlG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE;IACzC,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,wCAwIA"}
|
package/dist/NextAdminPage.js
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
// src/NextAdminPage.tsx
|
|
2
|
-
import { fetchQuery } from "convex/nextjs";
|
|
3
|
-
import { vexConvexApi } from "@vexcms/core";
|
|
4
2
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
livePreviewLayoutCookieName,
|
|
4
|
+
livePreviewPanelCookieName,
|
|
5
|
+
readLivePreviewLayoutCookie,
|
|
6
|
+
readLivePreviewPanelCookie,
|
|
7
|
+
vexConvexApi
|
|
8
|
+
} from "@vexcms/core";
|
|
9
|
+
import {
|
|
7
10
|
CollectionEditView,
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
CollectionListView,
|
|
12
|
+
DashboardView,
|
|
13
|
+
GlobalEditView,
|
|
10
14
|
GlobalsListView,
|
|
11
|
-
|
|
15
|
+
MediaCollectionEditView,
|
|
16
|
+
MediaCollectionListView
|
|
12
17
|
} from "@vexcms/react";
|
|
18
|
+
import { fetchQuery } from "convex/nextjs";
|
|
19
|
+
import { cookies } from "next/headers";
|
|
13
20
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
21
|
async function NextAdminPage(props) {
|
|
15
22
|
const { path = [] } = await props.params;
|
|
16
23
|
const [collectionSlug, documentId] = path;
|
|
24
|
+
const cookieStore = await cookies();
|
|
17
25
|
if (!collectionSlug) {
|
|
18
26
|
return /* @__PURE__ */ jsx(DashboardView, {});
|
|
19
27
|
}
|
|
@@ -37,7 +45,20 @@ async function NextAdminPage(props) {
|
|
|
37
45
|
{ slug: globalConfig.slug },
|
|
38
46
|
props.token ? { token: props.token } : void 0
|
|
39
47
|
);
|
|
40
|
-
return /* @__PURE__ */ jsx(
|
|
48
|
+
return /* @__PURE__ */ jsx(
|
|
49
|
+
GlobalEditView,
|
|
50
|
+
{
|
|
51
|
+
global: globalConfig.slug,
|
|
52
|
+
initialData: global,
|
|
53
|
+
initialPreviewPanelOpen: readLivePreviewPanelCookie({
|
|
54
|
+
cookieValue: cookieStore.get(livePreviewPanelCookieName({ slug: globalConfig.slug }))?.value,
|
|
55
|
+
defaultOpen: globalConfig.admin.livePreview?.defaultOpen ?? false
|
|
56
|
+
}),
|
|
57
|
+
initialPreviewPanelSize: readLivePreviewLayoutCookie({
|
|
58
|
+
cookieValue: cookieStore.get(livePreviewLayoutCookieName({ slug: globalConfig.slug }))?.value
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
);
|
|
41
62
|
}
|
|
42
63
|
const collection = props.config.collections.find((c) => c.slug === collectionSlug);
|
|
43
64
|
const mediaCollection = props.config.mediaCollections.find((mc) => mc.slug === collectionSlug);
|
|
@@ -98,7 +119,14 @@ async function NextAdminPage(props) {
|
|
|
98
119
|
{
|
|
99
120
|
collection: collection.slug,
|
|
100
121
|
documentId,
|
|
101
|
-
initialData: initialData2
|
|
122
|
+
initialData: initialData2,
|
|
123
|
+
initialPreviewPanelOpen: readLivePreviewPanelCookie({
|
|
124
|
+
cookieValue: cookieStore.get(livePreviewPanelCookieName({ slug: collection.slug }))?.value,
|
|
125
|
+
defaultOpen: collection.admin.livePreview?.defaultOpen ?? false
|
|
126
|
+
}),
|
|
127
|
+
initialPreviewPanelSize: readLivePreviewLayoutCookie({
|
|
128
|
+
cookieValue: cookieStore.get(livePreviewLayoutCookieName({ slug: collection.slug }))?.value
|
|
129
|
+
})
|
|
102
130
|
}
|
|
103
131
|
);
|
|
104
132
|
}
|
|
@@ -124,4 +152,4 @@ async function NextAdminPage(props) {
|
|
|
124
152
|
export {
|
|
125
153
|
NextAdminPage
|
|
126
154
|
};
|
|
127
|
-
//# sourceMappingURL=chunk-
|
|
155
|
+
//# sourceMappingURL=chunk-L6N3D6L5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/NextAdminPage.tsx"],"sourcesContent":["import type { CollectionSlug, PaginationResult, VexConfig, VexMediaDocument } from \"@vexcms/core\";\n\nimport {\n livePreviewLayoutCookieName,\n livePreviewPanelCookieName,\n readLivePreviewLayoutCookie,\n readLivePreviewPanelCookie,\n vexConvexApi,\n} from \"@vexcms/core\";\nimport {\n CollectionEditView,\n CollectionListView,\n DashboardView,\n GlobalEditView,\n GlobalsListView,\n MediaCollectionEditView,\n MediaCollectionListView,\n} from \"@vexcms/react\";\nimport { fetchQuery } from \"convex/nextjs\";\nimport { cookies } from \"next/headers\";\n\n/**\n * VexCMS admin page server component for Next.js.\n *\n * An `async` server component that routes by the `[[...slug]]` catch-all\n * params, prefetches Convex data via `fetchQuery`, and renders the correct\n * view component. Does **not** include a layout wrapper — `NextAdminLayout`\n * in `app/admin/layout.tsx` owns the persistent shell.\n *\n * **Route mapping:**\n * | `path` array | View |\n * |---|---|\n * | `[]` or undefined | `DashboardView` |\n * | `[collectionSlug]` | `CollectionListView` with preloaded docs |\n * | `[collectionSlug, \"new\"]` | `CollectionEditView` (empty form) |\n * | `[collectionSlug, documentId]` | `CollectionEditView` with preloaded doc |\n *\n * @param props - Component props\n * @param props.config - The resolved server `VexConfig`, typically the default export of\n * `vex.config.server.ts` — not the client-safe `vex.config.ts`.\n * @param props.params - Next.js 15 async params `{ path?: string[] }`\n * @param props.token - Optional session token forwarded to `fetchQuery` for authenticated reads.\n * @returns The appropriate admin view for the current URL path.\n *\n * @example\n * ```tsx\n * // app/admin/[[...slug]]/page.tsx\n * import { NextAdminPage } from \"@vexcms/next/server\";\n * import config from \"../../../../vex.config.server\";\n *\n * export default function AdminPage({\n * params,\n * }: {\n * params: Promise<{ path?: string[] }>;\n * }) {\n * return <NextAdminPage config={config} params={params} />;\n * }\n * ```\n */\nexport async function NextAdminPage(props: {\n config: VexConfig;\n params: Promise<{ path?: string[] }>;\n token?: string;\n}) {\n const { path = [] } = await props.params;\n const [collectionSlug, documentId] = path;\n const cookieStore = await cookies();\n\n if (!collectionSlug) {\n return <DashboardView />;\n }\n\n if (collectionSlug === \"globals\") {\n if (!documentId) {\n return <GlobalsListView />;\n }\n const globalConfig = props.config.globals.find((g) => g.slug === documentId);\n if (!globalConfig) {\n return (\n <div>\n <p className=\"text-muted-foreground p-6\">Global "{documentId}" not found.</p>\n <p>TODO: add not found view</p>\n </div>\n );\n }\n const global = await fetchQuery(\n vexConvexApi.globals.get,\n { slug: globalConfig.slug },\n props.token ? { token: props.token } : undefined,\n );\n return (\n <GlobalEditView\n global={globalConfig.slug}\n initialData={global}\n initialPreviewPanelOpen={readLivePreviewPanelCookie({\n cookieValue: cookieStore.get(livePreviewPanelCookieName({ slug: globalConfig.slug }))\n ?.value,\n defaultOpen: globalConfig.admin.livePreview?.defaultOpen ?? false,\n })}\n initialPreviewPanelSize={readLivePreviewLayoutCookie({\n cookieValue: cookieStore.get(livePreviewLayoutCookieName({ slug: globalConfig.slug }))\n ?.value,\n })}\n />\n );\n }\n\n const collection = props.config.collections.find((c) => c.slug === collectionSlug);\n const mediaCollection = props.config.mediaCollections.find((mc) => mc.slug === collectionSlug);\n\n if (!collection && !mediaCollection) {\n return (\n <div>\n <p className=\"text-muted-foreground p-6\">\n Collection "{collectionSlug}" not found.\n </p>\n <p>TODO: add not found view</p>\n </div>\n );\n }\n\n if (mediaCollection && documentId) {\n const initialData = await fetchQuery(\n vexConvexApi.get,\n { id: documentId, collection: mediaCollection.slug },\n props.token ? { token: props.token } : undefined,\n );\n return (\n <MediaCollectionEditView\n collection={mediaCollection.slug}\n documentId={documentId}\n initialData={initialData as null | VexMediaDocument}\n />\n );\n }\n\n if (mediaCollection) {\n const numItems = Math.max(\n mediaCollection.admin.table.serverPageSize,\n mediaCollection.admin.table.defaultPageSize,\n );\n const initialData = await fetchQuery(\n vexConvexApi.find,\n {\n collection: collectionSlug as CollectionSlug,\n paginationOpts: { numItems, totalDocs: true, cursor: null },\n },\n props.token ? { token: props.token } : undefined,\n );\n return (\n <MediaCollectionListView\n collection={mediaCollection.slug}\n initialData={initialData as PaginationResult<VexMediaDocument>}\n />\n );\n }\n\n if (collection && documentId) {\n const initialData = await fetchQuery(\n vexConvexApi.get,\n { id: documentId, collection: collection.slug },\n props.token ? { token: props.token } : undefined,\n );\n return (\n <CollectionEditView\n collection={collection.slug}\n documentId={documentId}\n initialData={initialData}\n initialPreviewPanelOpen={readLivePreviewPanelCookie({\n cookieValue: cookieStore.get(livePreviewPanelCookieName({ slug: collection.slug }))\n ?.value,\n defaultOpen: collection.admin.livePreview?.defaultOpen ?? false,\n })}\n initialPreviewPanelSize={readLivePreviewLayoutCookie({\n cookieValue: cookieStore.get(livePreviewLayoutCookieName({ slug: collection.slug }))\n ?.value,\n })}\n />\n );\n }\n\n if (!collection) {\n throw new Error(\"invalid collection slug\");\n }\n\n const numItems = Math.max(\n collection.admin.table.serverPageSize,\n collection.admin.table.defaultPageSize,\n );\n const initialData = await fetchQuery(\n vexConvexApi.findPaginated,\n {\n collection: collectionSlug as CollectionSlug,\n depth: 1,\n paginationOpts: { cursor: null, numItems, totalDocs: true },\n },\n props.token ? { token: props.token } : undefined,\n );\n return <CollectionListView collection={collection.slug} initialData={initialData} />;\n}\n"],"mappings":";AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAC3B,SAAS,eAAe;AAkDb,cAWD,YAXC;AAVX,eAAsB,cAAc,OAIjC;AACD,QAAM,EAAE,OAAO,CAAC,EAAE,IAAI,MAAM,MAAM;AAClC,QAAM,CAAC,gBAAgB,UAAU,IAAI;AACrC,QAAM,cAAc,MAAM,QAAQ;AAElC,MAAI,CAAC,gBAAgB;AACnB,WAAO,oBAAC,iBAAc;AAAA,EACxB;AAEA,MAAI,mBAAmB,WAAW;AAChC,QAAI,CAAC,YAAY;AACf,aAAO,oBAAC,mBAAgB;AAAA,IAC1B;AACA,UAAM,eAAe,MAAM,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU;AAC3E,QAAI,CAAC,cAAc;AACjB,aACE,qBAAC,SACC;AAAA,6BAAC,OAAE,WAAU,6BAA4B;AAAA;AAAA,UAAc;AAAA,UAAW;AAAA,WAAiB;AAAA,QACnF,oBAAC,OAAE,sCAAwB;AAAA,SAC7B;AAAA,IAEJ;AACA,UAAM,SAAS,MAAM;AAAA,MACnB,aAAa,QAAQ;AAAA,MACrB,EAAE,MAAM,aAAa,KAAK;AAAA,MAC1B,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACzC;AACA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ,aAAa;AAAA,QACrB,aAAa;AAAA,QACb,yBAAyB,2BAA2B;AAAA,UAClD,aAAa,YAAY,IAAI,2BAA2B,EAAE,MAAM,aAAa,KAAK,CAAC,CAAC,GAChF;AAAA,UACJ,aAAa,aAAa,MAAM,aAAa,eAAe;AAAA,QAC9D,CAAC;AAAA,QACD,yBAAyB,4BAA4B;AAAA,UACnD,aAAa,YAAY,IAAI,4BAA4B,EAAE,MAAM,aAAa,KAAK,CAAC,CAAC,GACjF;AAAA,QACN,CAAC;AAAA;AAAA,IACH;AAAA,EAEJ;AAEA,QAAM,aAAa,MAAM,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,SAAS,cAAc;AACjF,QAAM,kBAAkB,MAAM,OAAO,iBAAiB,KAAK,CAAC,OAAO,GAAG,SAAS,cAAc;AAE7F,MAAI,CAAC,cAAc,CAAC,iBAAiB;AACnC,WACE,qBAAC,SACC;AAAA,2BAAC,OAAE,WAAU,6BAA4B;AAAA;AAAA,QACrB;AAAA,QAAe;AAAA,SACnC;AAAA,MACA,oBAAC,OAAE,sCAAwB;AAAA,OAC7B;AAAA,EAEJ;AAEA,MAAI,mBAAmB,YAAY;AACjC,UAAMA,eAAc,MAAM;AAAA,MACxB,aAAa;AAAA,MACb,EAAE,IAAI,YAAY,YAAY,gBAAgB,KAAK;AAAA,MACnD,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACzC;AACA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,YAAY,gBAAgB;AAAA,QAC5B;AAAA,QACA,aAAaA;AAAA;AAAA,IACf;AAAA,EAEJ;AAEA,MAAI,iBAAiB;AACnB,UAAMC,YAAW,KAAK;AAAA,MACpB,gBAAgB,MAAM,MAAM;AAAA,MAC5B,gBAAgB,MAAM,MAAM;AAAA,IAC9B;AACA,UAAMD,eAAc,MAAM;AAAA,MACxB,aAAa;AAAA,MACb;AAAA,QACE,YAAY;AAAA,QACZ,gBAAgB,EAAE,UAAAC,WAAU,WAAW,MAAM,QAAQ,KAAK;AAAA,MAC5D;AAAA,MACA,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACzC;AACA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,YAAY,gBAAgB;AAAA,QAC5B,aAAaD;AAAA;AAAA,IACf;AAAA,EAEJ;AAEA,MAAI,cAAc,YAAY;AAC5B,UAAMA,eAAc,MAAM;AAAA,MACxB,aAAa;AAAA,MACb,EAAE,IAAI,YAAY,YAAY,WAAW,KAAK;AAAA,MAC9C,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACzC;AACA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,YAAY,WAAW;AAAA,QACvB;AAAA,QACA,aAAaA;AAAA,QACb,yBAAyB,2BAA2B;AAAA,UAClD,aAAa,YAAY,IAAI,2BAA2B,EAAE,MAAM,WAAW,KAAK,CAAC,CAAC,GAC9E;AAAA,UACJ,aAAa,WAAW,MAAM,aAAa,eAAe;AAAA,QAC5D,CAAC;AAAA,QACD,yBAAyB,4BAA4B;AAAA,UACnD,aAAa,YAAY,IAAI,4BAA4B,EAAE,MAAM,WAAW,KAAK,CAAC,CAAC,GAC/E;AAAA,QACN,CAAC;AAAA;AAAA,IACH;AAAA,EAEJ;AAEA,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AAEA,QAAM,WAAW,KAAK;AAAA,IACpB,WAAW,MAAM,MAAM;AAAA,IACvB,WAAW,MAAM,MAAM;AAAA,EACzB;AACA,QAAM,cAAc,MAAM;AAAA,IACxB,aAAa;AAAA,IACb;AAAA,MACE,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,gBAAgB,EAAE,QAAQ,MAAM,UAAU,WAAW,KAAK;AAAA,IAC5D;AAAA,IACA,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,EACzC;AACA,SAAO,oBAAC,sBAAmB,YAAY,WAAW,MAAM,aAA0B;AACpF;","names":["initialData","numItems"]}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vexcms/next",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.22",
|
|
4
4
|
"description": "Next.js adapter and admin routes for VexCMS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cms",
|
|
@@ -66,8 +66,8 @@
|
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"lucide-react": "0.577.0",
|
|
69
|
-
"@vexcms/core": "0.1.0-alpha.
|
|
70
|
-
"@vexcms/react": "0.1.0-alpha.
|
|
69
|
+
"@vexcms/core": "0.1.0-alpha.22",
|
|
70
|
+
"@vexcms/react": "0.1.0-alpha.22"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@convex-dev/react-query": "0.1.0",
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
},
|
|
105
105
|
"scripts": {
|
|
106
106
|
"build": "tsup && tsc -p tsconfig.build.json --emitDeclarationOnly",
|
|
107
|
-
"dev": "tsup --watch --no-clean",
|
|
107
|
+
"dev": "tsup --watch src --no-clean",
|
|
108
108
|
"clean": "rm -rf dist",
|
|
109
109
|
"typecheck": "tsc --noEmit -p tsconfig.check.json",
|
|
110
110
|
"test": "vitest run",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/NextAdminPage.tsx"],"sourcesContent":["import { fetchQuery } from \"convex/nextjs\";\nimport { vexConvexApi } from \"@vexcms/core\";\nimport type { CollectionSlug, PaginationResult, VexConfig, VexMediaDocument } from \"@vexcms/core\";\nimport {\n DashboardView,\n CollectionListView,\n CollectionEditView,\n MediaCollectionEditView,\n MediaCollectionListView,\n GlobalsListView,\n GlobalEditView,\n} from \"@vexcms/react\";\n\n/**\n * VexCMS admin page server component for Next.js.\n *\n * An `async` server component that routes by the `[[...slug]]` catch-all\n * params, prefetches Convex data via `fetchQuery`, and renders the correct\n * view component. Does **not** include a layout wrapper — `NextAdminLayout`\n * in `app/admin/layout.tsx` owns the persistent shell.\n *\n * **Route mapping:**\n * | `path` array | View |\n * |---|---|\n * | `[]` or undefined | `DashboardView` |\n * | `[collectionSlug]` | `CollectionListView` with preloaded docs |\n * | `[collectionSlug, \"new\"]` | `CollectionEditView` (empty form) |\n * | `[collectionSlug, documentId]` | `CollectionEditView` with preloaded doc |\n *\n * @param props - Component props\n * @param props.config - The resolved server `VexConfig`, typically the default export of\n * `vex.config.server.ts` — not the client-safe `vex.config.ts`.\n * @param props.params - Next.js 15 async params `{ path?: string[] }`\n * @param props.token - Optional session token forwarded to `fetchQuery` for authenticated reads.\n * @returns The appropriate admin view for the current URL path.\n *\n * @example\n * ```tsx\n * // app/admin/[[...slug]]/page.tsx\n * import { NextAdminPage } from \"@vexcms/next/server\";\n * import config from \"../../../../vex.config.server\";\n *\n * export default function AdminPage({\n * params,\n * }: {\n * params: Promise<{ path?: string[] }>;\n * }) {\n * return <NextAdminPage config={config} params={params} />;\n * }\n * ```\n */\nexport async function NextAdminPage(props: {\n config: VexConfig;\n params: Promise<{ path?: string[] }>;\n token?: string;\n}) {\n const { path = [] } = await props.params;\n const [collectionSlug, documentId] = path;\n\n if (!collectionSlug) {\n return <DashboardView />;\n }\n\n if (collectionSlug === \"globals\") {\n if (!documentId) {\n return <GlobalsListView />;\n }\n const globalConfig = props.config.globals.find((g) => g.slug === documentId);\n if (!globalConfig) {\n return (\n <div>\n <p className=\"text-muted-foreground p-6\">Global "{documentId}" not found.</p>\n <p>TODO: add not found view</p>\n </div>\n );\n }\n const global = await fetchQuery(\n vexConvexApi.globals.get,\n { slug: globalConfig.slug },\n props.token ? { token: props.token } : undefined,\n );\n return <GlobalEditView global={globalConfig.slug} initialData={global} />;\n }\n\n const collection = props.config.collections.find((c) => c.slug === collectionSlug);\n const mediaCollection = props.config.mediaCollections.find((mc) => mc.slug === collectionSlug);\n\n if (!collection && !mediaCollection) {\n return (\n <div>\n <p className=\"text-muted-foreground p-6\">\n Collection "{collectionSlug}" not found.\n </p>\n <p>TODO: add not found view</p>\n </div>\n );\n }\n\n if (mediaCollection && documentId) {\n const initialData = await fetchQuery(\n vexConvexApi.get,\n { id: documentId, collection: mediaCollection.slug },\n props.token ? { token: props.token } : undefined,\n );\n return (\n <MediaCollectionEditView\n collection={mediaCollection.slug}\n documentId={documentId}\n initialData={initialData as VexMediaDocument | null}\n />\n );\n }\n\n if (mediaCollection) {\n const numItems = Math.max(\n mediaCollection.admin.table.serverPageSize,\n mediaCollection.admin.table.defaultPageSize,\n );\n const initialData = await fetchQuery(\n vexConvexApi.find,\n {\n collection: collectionSlug as CollectionSlug,\n paginationOpts: { numItems, totalDocs: true, cursor: null },\n },\n props.token ? { token: props.token } : undefined,\n );\n return (\n <MediaCollectionListView\n collection={mediaCollection.slug}\n initialData={initialData as PaginationResult<VexMediaDocument>}\n />\n );\n }\n\n if (collection && documentId) {\n const initialData = await fetchQuery(\n vexConvexApi.get,\n { id: documentId, collection: collection.slug },\n props.token ? { token: props.token } : undefined,\n );\n return (\n <CollectionEditView\n collection={collection.slug}\n documentId={documentId}\n initialData={initialData}\n />\n );\n }\n\n if (!collection) {\n throw new Error(\"invalid collection slug\");\n }\n\n const numItems = Math.max(\n collection.admin.table.serverPageSize,\n collection.admin.table.defaultPageSize,\n );\n const initialData = await fetchQuery(\n vexConvexApi.findPaginated,\n {\n collection: collectionSlug as CollectionSlug,\n depth: 1,\n paginationOpts: { cursor: null, numItems, totalDocs: true },\n },\n props.token ? { token: props.token } : undefined,\n );\n return <CollectionListView collection={collection.slug} initialData={initialData} />;\n}\n"],"mappings":"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","names":["initialData","numItems"]}
|