@revealui/core 0.9.0 → 0.10.0
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 +8 -0
- package/dist/client/admin/components/AdminDashboard.d.ts +7 -1
- package/dist/client/admin/components/AdminDashboard.d.ts.map +1 -1
- package/dist/client/admin/components/AdminDashboard.js +11 -11
- package/dist/client/admin/components/CollectionList.d.ts +2 -1
- package/dist/client/admin/components/CollectionList.d.ts.map +1 -1
- package/dist/client/admin/components/CollectionList.js +5 -5
- package/dist/client/admin/components/DocumentForm.d.ts +2 -1
- package/dist/client/admin/components/DocumentForm.d.ts.map +1 -1
- package/dist/client/admin/components/DocumentForm.js +16 -16
- package/dist/client/admin/components/GlobalForm.d.ts +2 -1
- package/dist/client/admin/components/GlobalForm.d.ts.map +1 -1
- package/dist/client/admin/components/GlobalForm.js +3 -3
- package/dist/client/admin/context/ServerFunctionContext.d.ts +1 -1
- package/dist/client/admin/context/ServerFunctionContext.d.ts.map +1 -1
- package/dist/client/admin/layout.d.ts +1 -1
- package/dist/client/admin/layout.d.ts.map +1 -1
- package/dist/client/admin/layout.js +5 -1
- package/dist/client/admin/page.d.ts +2 -2
- package/dist/client/admin/page.d.ts.map +1 -1
- package/dist/client/admin/page.js +10 -3
- package/dist/client/richtext/RichTextEditor.d.ts +1 -1
- package/dist/client/richtext/RichTextEditor.d.ts.map +1 -1
- package/dist/client/richtext/plugins/CollaborationPlugin.d.ts +1 -1
- package/dist/client/richtext/plugins/CollaborationPlugin.d.ts.map +1 -1
- package/dist/client/richtext/plugins/ToolbarPlugin.d.ts +1 -1
- package/dist/client/richtext/plugins/ToolbarPlugin.d.ts.map +1 -1
- package/dist/nextjs/withRevealUI.d.ts +7 -2
- package/dist/nextjs/withRevealUI.d.ts.map +1 -1
- package/dist/nextjs/withRevealUI.js +9 -99
- package/dist/revforge-license.d.ts +4 -2
- package/dist/revforge-license.d.ts.map +1 -1
- package/dist/revforge-license.js +21 -3
- package/dist/richtext/exports/server/rsc.d.ts +3 -3
- package/dist/richtext/exports/server/rsc.d.ts.map +1 -1
- package/dist/storage/_sigv4.d.ts +76 -0
- package/dist/storage/_sigv4.d.ts.map +1 -0
- package/dist/storage/_sigv4.js +134 -0
- package/dist/storage/_xml.d.ts +26 -0
- package/dist/storage/_xml.d.ts.map +1 -0
- package/dist/storage/_xml.js +75 -0
- package/dist/storage/r2.d.ts +14 -2
- package/dist/storage/r2.d.ts.map +1 -1
- package/dist/storage/r2.js +107 -44
- package/package.json +22 -23
package/README.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "@revealui/core"
|
|
3
|
+
description: "[](https://www.npmjs.com/package/@revealui/core)"
|
|
4
|
+
visibility: public
|
|
5
|
+
status: verified
|
|
6
|
+
audience: user
|
|
7
|
+
---
|
|
8
|
+
|
|
1
9
|
# @revealui/core
|
|
2
10
|
|
|
3
11
|
[](https://www.npmjs.com/package/@revealui/core)
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { RevealConfig } from '../../../types/index.js';
|
|
2
2
|
interface AdminDashboardProps {
|
|
3
3
|
config: RevealConfig;
|
|
4
|
+
/**
|
|
5
|
+
* Resolved brand name for the dashboard chrome. Pass from a server
|
|
6
|
+
* component (e.g. REVEALUI_BRAND_NAME / REVEALUI_TENANT_NAME): client
|
|
7
|
+
* files cannot read those env vars at runtime (build-time inlining).
|
|
8
|
+
*/
|
|
9
|
+
siteName?: string;
|
|
4
10
|
}
|
|
5
|
-
export declare function AdminDashboard({ config }: AdminDashboardProps): import("react
|
|
11
|
+
export declare function AdminDashboard({ config, siteName }: AdminDashboardProps): import("react").JSX.Element;
|
|
6
12
|
export {};
|
|
7
13
|
//# sourceMappingURL=AdminDashboard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminDashboard.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/components/AdminDashboard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,YAAY,EAGb,MAAM,yBAAyB,CAAC;AAUjC,UAAU,mBAAmB;IAC3B,MAAM,EAAE,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"AdminDashboard.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/components/AdminDashboard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,YAAY,EAGb,MAAM,yBAAyB,CAAC;AAUjC,UAAU,mBAAmB;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA8YD,wBAAgB,cAAc,CAAC,EAAE,MAAM,EAAE,QAAqB,EAAE,EAAE,mBAAmB,+BAmVpF"}
|
|
@@ -53,13 +53,13 @@ function reducer(state, action) {
|
|
|
53
53
|
// Shared sub-components
|
|
54
54
|
// =============================================================================
|
|
55
55
|
function AdminHeader({ title, onBack }) {
|
|
56
|
-
return (_jsx("header", { className: "bg-
|
|
56
|
+
return (_jsx("header", { className: "bg-card shadow-sm border-b", children: _jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: _jsxs("div", { className: "flex justify-between items-center py-4", children: [_jsxs("div", { className: "flex items-center space-x-4", children: [_jsx("button", { type: "button", onClick: onBack, className: "text-muted-foreground hover:text-muted-foreground", children: "\u2190 Back to Dashboard" }), _jsx("h1", { className: "text-2xl font-bold text-foreground capitalize", children: title })] }), _jsx(SignOutButton, {})] }) }) }));
|
|
57
57
|
}
|
|
58
58
|
function StatusBanners({ error, successMessage, }) {
|
|
59
|
-
return (_jsxs(_Fragment, { children: [error && (_jsxs("div", { className: "mb-4 bg-red-50 border border-red-200 text-red-800 px-4 py-3 rounded", children: [_jsx("p", { className: "font-medium", children: "Error" }), _jsx("p", { className: "text-sm", children: error })] })), successMessage && (_jsxs("div", { className: "mb-4 bg-
|
|
59
|
+
return (_jsxs(_Fragment, { children: [error && (_jsxs("div", { className: "mb-4 bg-red-50 border border-red-200 text-red-800 px-4 py-3 rounded", children: [_jsx("p", { className: "font-medium", children: "Error" }), _jsx("p", { className: "text-sm", children: error })] })), successMessage && (_jsxs("div", { className: "mb-4 bg-success/10 border border-success/30 text-success px-4 py-3 rounded", children: [_jsx("p", { className: "font-medium", children: "Success" }), _jsx("p", { className: "text-sm", children: successMessage })] }))] }));
|
|
60
60
|
}
|
|
61
61
|
function LoadingSpinner() {
|
|
62
|
-
return (_jsxs("div", { className: "mb-4 text-center py-8", children: [_jsx("div", { className: "inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-
|
|
62
|
+
return (_jsxs("div", { className: "mb-4 text-center py-8", children: [_jsx("div", { className: "inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-primary" }), _jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Loading..." })] }));
|
|
63
63
|
}
|
|
64
64
|
function SignOutButton() {
|
|
65
65
|
const [loading, setLoading] = useState(false);
|
|
@@ -76,13 +76,13 @@ function SignOutButton() {
|
|
|
76
76
|
}
|
|
77
77
|
window.location.href = '/login';
|
|
78
78
|
}, []);
|
|
79
|
-
return (_jsx("button", { type: "button", onClick: () => void handleSignOut(), disabled: loading, className: "text-sm text-
|
|
79
|
+
return (_jsx("button", { type: "button", onClick: () => void handleSignOut(), disabled: loading, className: "text-sm text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md hover:bg-muted transition-colors", children: loading ? 'Signing out...' : 'Sign Out' }));
|
|
80
80
|
}
|
|
81
81
|
// =============================================================================
|
|
82
82
|
// Dashboard home view
|
|
83
83
|
// =============================================================================
|
|
84
|
-
function DashboardHome({ collections, globals, onCollectionClick, onGlobalClick, }) {
|
|
85
|
-
return (_jsxs("div", { className: "min-h-screen bg-
|
|
84
|
+
function DashboardHome({ siteName, collections, globals, onCollectionClick, onGlobalClick, }) {
|
|
85
|
+
return (_jsxs("div", { className: "min-h-screen bg-background", children: [_jsx("header", { className: "bg-card shadow-sm border-b", children: _jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: _jsxs("div", { className: "flex justify-between items-center py-4", children: [_jsx("div", { className: "flex items-center", children: _jsx("h1", { className: "text-2xl font-bold text-foreground", children: `${siteName} Admin` }) }), _jsxs("div", { className: "flex items-center space-x-4", children: [_jsx("span", { className: "text-sm text-muted-foreground", children: "v0.1.0" }), _jsx(SignOutButton, {})] })] }) }) }), _jsx("main", { className: "max-w-7xl mx-auto py-6 sm:px-6 lg:px-8", children: _jsx("div", { className: "px-4 py-6 sm:px-0", children: _jsxs("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3", children: [_jsxs("div", { className: "bg-card overflow-hidden shadow rounded-lg", children: [_jsx("div", { className: "p-5", children: _jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "flex-shrink-0", children: _jsxs("svg", { className: "h-8 w-8 text-muted-foreground", "aria-label": "Collections", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", role: "img", children: [_jsx("title", { children: "Collections" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" })] }) }), _jsx("div", { className: "ml-5 w-0 flex-1", children: _jsxs("dl", { children: [_jsx("dt", { className: "text-sm font-medium text-muted-foreground truncate", children: "Collections" }), _jsx("dd", { className: "text-lg font-medium text-foreground", children: collections.length })] }) })] }) }), _jsx("div", { className: "bg-muted px-5 py-3", children: _jsx("div", { className: "text-sm", children: collections.length > 0 ? (_jsx("ul", { className: "space-y-1 max-h-48 overflow-y-auto", children: collections.map((collection) => (_jsx("li", { className: "text-muted-foreground hover:text-foreground", children: _jsx("button", { type: "button", onClick: () => onCollectionClick(collection), className: "hover:underline cursor-pointer", children: String(collection.slug) }) }, String(collection.slug)))) })) : (_jsx("p", { className: "text-muted-foreground", children: "No collections configured" })) }) })] }), _jsxs("div", { className: "bg-card overflow-hidden shadow rounded-lg", children: [_jsx("div", { className: "p-5", children: _jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "flex-shrink-0", children: _jsxs("svg", { className: "h-8 w-8 text-muted-foreground", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-labelledby": "globals-icon-title", role: "img", children: [_jsx("title", { id: "globals-icon-title", children: "Globals" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4" })] }) }), _jsx("div", { className: "ml-5 w-0 flex-1", children: _jsxs("dl", { children: [_jsx("dt", { className: "text-sm font-medium text-muted-foreground truncate", children: "Globals" }), _jsx("dd", { className: "text-lg font-medium text-foreground", children: globals.length })] }) })] }) }), _jsx("div", { className: "bg-muted px-5 py-3", children: _jsx("div", { className: "text-sm", children: globals.length > 0 ? (_jsx("ul", { className: "space-y-1 max-h-32 overflow-y-auto", children: globals.map((global) => (_jsx("li", { className: "text-muted-foreground hover:text-foreground", children: _jsx("button", { type: "button", onClick: () => onGlobalClick(global), className: "hover:underline cursor-pointer", children: global.label || String(global.slug) }) }, String(global.slug)))) })) : (_jsx("p", { className: "text-muted-foreground", children: "No globals configured" })) }) })] }), _jsxs("div", { className: "bg-card overflow-hidden shadow rounded-lg", children: [_jsx("div", { className: "p-5", children: _jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "flex-shrink-0", children: _jsx("div", { className: "h-8 w-8 bg-success/15 rounded-full flex items-center justify-center", children: _jsxs("svg", { className: "h-5 w-5 text-success", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-labelledby": "system-status-icon-title", role: "img", children: [_jsx("title", { id: "system-status-icon-title", children: "System Status: Healthy" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" })] }) }) }), _jsx("div", { className: "ml-5 w-0 flex-1", children: _jsxs("dl", { children: [_jsx("dt", { className: "text-sm font-medium text-muted-foreground truncate", children: "System Status" }), _jsx("dd", { className: "text-lg font-medium text-foreground", children: "Healthy" })] }) })] }) }), _jsx("div", { className: "bg-muted px-5 py-3", children: _jsxs("div", { className: "text-sm text-muted-foreground", children: [siteName, " admin is running successfully"] }) })] })] }) }) })] }));
|
|
86
86
|
}
|
|
87
87
|
// =============================================================================
|
|
88
88
|
// Error handling helpers
|
|
@@ -99,7 +99,7 @@ function logApiError(err, context) {
|
|
|
99
99
|
// =============================================================================
|
|
100
100
|
// Main component
|
|
101
101
|
// =============================================================================
|
|
102
|
-
export function AdminDashboard({ config }) {
|
|
102
|
+
export function AdminDashboard({ config, siteName = 'RevealUI' }) {
|
|
103
103
|
const [state, dispatch] = useReducer(reducer, initialState);
|
|
104
104
|
const collections = config.collections || [];
|
|
105
105
|
const globals = config.globals || [];
|
|
@@ -332,7 +332,7 @@ export function AdminDashboard({ config }) {
|
|
|
332
332
|
};
|
|
333
333
|
// ── Collection list view ──────────────────────────────────────────────
|
|
334
334
|
if (state.view.type === 'collection' && state.view.collection) {
|
|
335
|
-
return (_jsxs("div", { className: "min-h-screen bg-
|
|
335
|
+
return (_jsxs("div", { className: "min-h-screen bg-background", children: [_jsx(AdminHeader, { title: String(state.view.collection.slug), onBack: goToDashboard }), _jsxs("main", { className: "max-w-7xl mx-auto py-6 sm:px-6 lg:px-8", children: [_jsx(StatusBanners, { error: state.error, successMessage: state.successMessage }), state.collectionLoading && _jsx(LoadingSpinner, {}), _jsx(CollectionList, { collection: state.view.collection, documents: state.documents, totalDocs: state.totalDocs, page: state.page, totalPages: state.totalPages, onCreate: handleCreate, onEdit: handleEdit, onDelete: (document) => void handleDelete(document), onPageChange: (nextPage) => {
|
|
336
336
|
const collection = state.view.collection;
|
|
337
337
|
if (collection)
|
|
338
338
|
void fetchCollection(collection, nextPage);
|
|
@@ -340,12 +340,12 @@ export function AdminDashboard({ config }) {
|
|
|
340
340
|
}
|
|
341
341
|
// ── Document edit/create view ─────────────────────────────────────────
|
|
342
342
|
if (state.view.type === 'edit' && state.view.collection) {
|
|
343
|
-
return (_jsxs("div", { className: "min-h-screen bg-
|
|
343
|
+
return (_jsxs("div", { className: "min-h-screen bg-background", children: [_jsx(AdminHeader, { title: `${state.view.document ? 'Edit' : 'Create'} ${String(state.view.collection.slug).slice(0, -1)}`, onBack: goToDashboard }), _jsx("main", { className: "max-w-7xl mx-auto py-6 sm:px-6 lg:px-8", children: _jsxs("div", { className: "max-w-3xl", children: [_jsx(StatusBanners, { error: state.error, successMessage: state.successMessage }), _jsx(DocumentForm, { collection: state.view.collection, document: state.view.document, onSave: (data) => void handleSave(data), onCancel: goToDashboard, isLoading: state.saving })] }) })] }));
|
|
344
344
|
}
|
|
345
345
|
// ── Global edit view ──────────────────────────────────────────────────
|
|
346
346
|
if (state.view.type === 'global' && state.view.global) {
|
|
347
|
-
return (_jsxs("div", { className: "min-h-screen bg-
|
|
347
|
+
return (_jsxs("div", { className: "min-h-screen bg-background", children: [_jsx(AdminHeader, { title: state.view.global.label || String(state.view.global.slug), onBack: goToDashboard }), _jsx("main", { className: "max-w-7xl mx-auto py-6 sm:px-6 lg:px-8", children: _jsxs("div", { className: "max-w-3xl", children: [_jsx(StatusBanners, { error: state.error, successMessage: state.successMessage }), state.globalLoading && _jsx(LoadingSpinner, {}), !state.globalLoading && state.globalDocument && (_jsx(GlobalForm, { global: state.view.global, document: state.globalDocument, onSave: (data) => void handleSaveGlobal(data), onCancel: goToDashboard, isLoading: state.saving }))] }) })] }));
|
|
348
348
|
}
|
|
349
349
|
// ── Dashboard home ────────────────────────────────────────────────────
|
|
350
|
-
return (_jsx(DashboardHome, { collections: collections, globals: globals, onCollectionClick: (c) => void handleCollectionClick(c), onGlobalClick: (g) => void handleGlobalClick(g) }));
|
|
350
|
+
return (_jsx(DashboardHome, { siteName: siteName, collections: collections, globals: globals, onCollectionClick: (c) => void handleCollectionClick(c), onGlobalClick: (g) => void handleGlobalClick(g) }));
|
|
351
351
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type React from 'react';
|
|
1
2
|
import type { RevealCollectionConfig, RevealDocument } from '../../../types/index.js';
|
|
2
3
|
interface CollectionListProps {
|
|
3
4
|
collection: RevealCollectionConfig;
|
|
@@ -13,6 +14,6 @@ interface CollectionListProps {
|
|
|
13
14
|
onBulkDelete?: (ids: string[]) => void;
|
|
14
15
|
onBulkPublish?: (ids: string[]) => void;
|
|
15
16
|
}
|
|
16
|
-
export declare function CollectionList({ collection, documents, totalDocs, page, totalPages, onCreate, onEdit, onDelete, onPageChange, deleting, onBulkDelete, onBulkPublish, }: CollectionListProps):
|
|
17
|
+
export declare function CollectionList({ collection, documents, totalDocs, page, totalPages, onCreate, onEdit, onDelete, onPageChange, deleting, onBulkDelete, onBulkPublish, }: CollectionListProps): React.JSX.Element;
|
|
17
18
|
export {};
|
|
18
19
|
//# sourceMappingURL=CollectionList.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollectionList.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/components/CollectionList.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CollectionList.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/components/CollectionList.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EACV,sBAAsB,EACtB,cAAc,EAEf,MAAM,yBAAyB,CAAC;AAoCjC,UAAU,mBAAmB;IAC3B,UAAU,EAAE,sBAAsB,CAAC;IACnC,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACzC;AAED,wBAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,SAAS,EACT,SAAS,EACT,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,aAAa,GACd,EAAE,mBAAmB,qBAgRrB"}
|
|
@@ -83,17 +83,17 @@ export function CollectionList({ collection, documents, totalDocs, page, totalPa
|
|
|
83
83
|
})
|
|
84
84
|
.slice(0, 5); // Show first 5 visible fields
|
|
85
85
|
const colCount = displayFields.length + 1 + (hasBulk ? 1 : 0);
|
|
86
|
-
return (_jsxs("div", { className: "bg-
|
|
86
|
+
return (_jsxs("div", { className: "bg-card shadow overflow-hidden sm:rounded-md", children: [_jsxs("div", { className: "px-4 py-5 sm:px-6 flex justify-between items-center", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-lg leading-6 font-medium text-foreground capitalize", children: collection.slug }), _jsxs("p", { className: "mt-1 max-w-2xl text-sm text-muted-foreground", children: [totalDocs, " ", totalDocs === 1 ? 'document' : 'documents'] })] }), _jsxs("button", { type: "button", onClick: onCreate, className: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-primary-foreground bg-primary hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-background focus:ring-ring", children: [_jsxs("svg", { className: "-ml-1 mr-2 h-5 w-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", role: "img", focusable: "false", children: [_jsx("title", { children: "Create New" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" })] }), "Create New"] })] }), hasBulk && selectedIds.size > 0 && (_jsxs("div", { className: "bg-primary/10 border-y border-primary/20 px-4 py-2 flex items-center gap-3", children: [_jsxs("span", { className: "text-sm font-medium text-primary", children: [selectedIds.size, " selected"] }), onBulkDelete && (_jsx("button", { type: "button", onClick: () => void handleBulkAction('delete'), disabled: bulkLoading, className: "inline-flex items-center px-3 py-1 text-xs font-medium rounded-md text-red-700 bg-red-100 hover:bg-red-200 disabled:opacity-50", children: "Delete" })), onBulkPublish && (_jsx("button", { type: "button", onClick: () => void handleBulkAction('publish'), disabled: bulkLoading, className: "inline-flex items-center px-3 py-1 text-xs font-medium rounded-md text-success bg-success/15 hover:bg-success/25 disabled:opacity-50", children: "Publish" })), _jsx("button", { type: "button", onClick: () => setSelectedIds(new Set()), className: "ml-auto text-xs text-muted-foreground hover:text-foreground", children: "Clear selection" })] })), _jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "min-w-full divide-y divide-border", children: [_jsx("thead", { className: "bg-muted", children: _jsxs("tr", { children: [hasBulk && (_jsx("th", { scope: "col", className: "w-10 px-3 py-3", children: _jsx("input", { type: "checkbox", checked: allSelected, ref: (el) => {
|
|
87
87
|
if (el)
|
|
88
88
|
el.indeterminate = someSelected;
|
|
89
|
-
}, onChange: toggleAll, className: "h-4 w-4 rounded border-
|
|
89
|
+
}, onChange: toggleAll, className: "h-4 w-4 rounded border-input text-primary focus:ring-ring", "aria-label": "Select all" }) })), displayFields.map((field) => (_jsx("th", { scope: "col", className: "px-6 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider", children: getFieldLabel(field) }, field.name))), _jsx("th", { scope: "col", className: "relative px-6 py-3", children: _jsx("span", { className: "sr-only", children: "Actions" }) })] }) }), _jsx("tbody", { className: "bg-card divide-y divide-border", children: documents.length === 0 ? (_jsx("tr", { children: _jsxs("td", { colSpan: colCount, className: "px-6 py-4 text-center text-sm text-muted-foreground", children: ["No documents found.", ' ', _jsx("button", { type: "button", onClick: onCreate, className: "text-primary hover:text-primary/80", children: "Create the first one" }), "."] }) })) : (documents.map((doc) => {
|
|
90
90
|
const docId = String(doc.id);
|
|
91
|
-
return (_jsxs("tr", { className: `hover:bg-
|
|
92
|
-
})) })] }) }), totalPages > 1 && (_jsxs("div", { className: "bg-
|
|
91
|
+
return (_jsxs("tr", { className: `hover:bg-muted ${selectedIds.has(docId) ? 'bg-primary/10' : ''}`, children: [hasBulk && (_jsx("td", { className: "w-10 px-3 py-4", children: _jsx("input", { type: "checkbox", checked: selectedIds.has(docId), onChange: () => toggleOne(docId), className: "h-4 w-4 rounded border-input text-primary focus:ring-ring", "aria-label": `Select ${docId}` }) })), displayFields.map((field) => (_jsx("td", { className: "px-6 py-4 whitespace-nowrap text-sm text-foreground", children: renderFieldValue(field.name ? doc[field.name] : undefined, field) }, field.name))), _jsxs("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm font-medium space-x-2", children: [_jsx("button", { type: "button", onClick: () => onEdit(doc), className: "text-primary hover:text-primary/80 disabled:opacity-50 disabled:cursor-not-allowed", disabled: deleting !== null, children: "Edit" }), _jsx("button", { type: "button", onClick: () => onDelete(doc), className: "text-red-600 hover:text-red-900 disabled:opacity-50 disabled:cursor-not-allowed", disabled: deleting !== null, children: deleting === docId ? 'Deleting...' : 'Delete' })] })] }, docId));
|
|
92
|
+
})) })] }) }), totalPages > 1 && (_jsxs("div", { className: "bg-card px-4 py-3 flex items-center justify-between border-t border-border sm:px-6", children: [_jsxs("div", { className: "flex-1 flex justify-between sm:hidden", children: [_jsx("button", { type: "button", onClick: () => onPageChange(page - 1), disabled: page <= 1, className: "relative inline-flex items-center px-4 py-2 border border-input text-sm font-medium rounded-md text-foreground bg-card hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed", children: "Previous" }), _jsx("button", { type: "button", onClick: () => onPageChange(page + 1), disabled: page >= totalPages, className: "ml-3 relative inline-flex items-center px-4 py-2 border border-input text-sm font-medium rounded-md text-foreground bg-card hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed", children: "Next" })] }), _jsxs("div", { className: "hidden sm:flex-1 sm:flex sm:items-center sm:justify-between", children: [_jsx("div", { children: _jsxs("p", { className: "text-sm text-foreground", children: ["Showing page ", _jsx("span", { className: "font-medium", children: page }), " of", ' ', _jsx("span", { className: "font-medium", children: totalPages })] }) }), _jsx("div", { children: _jsxs("nav", { className: "relative z-0 inline-flex rounded-md shadow-sm -space-x-px", children: [_jsx("button", { type: "button", onClick: () => onPageChange(page - 1), disabled: page <= 1, className: "relative inline-flex items-center px-2 py-2 rounded-l-md border border-input bg-card text-sm font-medium text-muted-foreground hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed", children: "Previous" }), _jsx("button", { type: "button", onClick: () => onPageChange(page + 1), disabled: page >= totalPages, className: "relative inline-flex items-center px-2 py-2 rounded-r-md border border-input bg-card text-sm font-medium text-muted-foreground hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed", children: "Next" })] }) })] })] }))] }));
|
|
93
93
|
}
|
|
94
94
|
function renderFieldValue(value, field) {
|
|
95
95
|
if (value === null || value === undefined) {
|
|
96
|
-
return _jsx("span", { className: "text-
|
|
96
|
+
return _jsx("span", { className: "text-muted-foreground", children: "-" });
|
|
97
97
|
}
|
|
98
98
|
switch (field.type) {
|
|
99
99
|
case 'text':
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type React from 'react';
|
|
1
2
|
import type { RevealCollectionConfig, RevealDocument } from '../../../types/index.js';
|
|
2
3
|
interface DocumentFormProps {
|
|
3
4
|
collection: RevealCollectionConfig;
|
|
@@ -6,6 +7,6 @@ interface DocumentFormProps {
|
|
|
6
7
|
onCancel: () => void;
|
|
7
8
|
isLoading?: boolean;
|
|
8
9
|
}
|
|
9
|
-
export declare function DocumentForm({ collection, document, onSave, onCancel, isLoading, }: DocumentFormProps):
|
|
10
|
+
export declare function DocumentForm({ collection, document, onSave, onCancel, isLoading, }: DocumentFormProps): React.JSX.Element;
|
|
10
11
|
export {};
|
|
11
12
|
//# sourceMappingURL=DocumentForm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentForm.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/components/DocumentForm.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DocumentForm.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/components/DocumentForm.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EACV,sBAAsB,EACtB,cAAc,EAEf,MAAM,yBAAyB,CAAC;AAiEjC,UAAU,iBAAiB;IACzB,UAAU,EAAE,sBAAsB,CAAC;IACnC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAChD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,EAC3B,UAAU,EACV,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,SAAiB,GAClB,EAAE,iBAAiB,qBA0DnB"}
|
|
@@ -70,7 +70,7 @@ export function DocumentForm({ collection, document, onSave, onCancel, isLoading
|
|
|
70
70
|
const handleFieldChange = (fieldName, value) => {
|
|
71
71
|
setFormData((prev) => ({ ...prev, [fieldName]: value }));
|
|
72
72
|
};
|
|
73
|
-
return (_jsx("div", { className: "bg-
|
|
73
|
+
return (_jsx("div", { className: "bg-card shadow overflow-hidden sm:rounded-lg", children: _jsxs("div", { className: "px-4 py-5 sm:p-6", children: [_jsxs("h3", { className: "text-lg leading-6 font-medium text-foreground mb-4", children: [document ? 'Edit' : 'Create', " ", collection.slug.slice(0, -1)] }), _jsxs("form", { onSubmit: handleSubmit, className: "space-y-6", children: [visibleFields.map((field) => (_jsxs("div", { children: [_jsxs("label", { htmlFor: field.name, className: "block text-sm font-medium text-foreground", children: [getFieldLabel(field), field.required && _jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), _jsx("div", { className: "mt-1", children: _jsx(FieldInput, { field: field, value: field.name ? formData[field.name] : undefined, onChange: (value) => field.name && handleFieldChange(field.name, value) }) })] }, field.name || 'layout'))), _jsxs("div", { className: "flex justify-end space-x-3 pt-6", children: [_jsx("button", { type: "button", onClick: onCancel, className: "bg-card py-2 px-4 border border-input rounded-md shadow-sm text-sm font-medium text-foreground hover:bg-muted focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-background focus:ring-ring", children: "Cancel" }), _jsx("button", { type: "submit", disabled: isLoading, className: "inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-primary-foreground bg-primary hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-background focus:ring-ring disabled:opacity-50 disabled:cursor-not-allowed", children: isLoading ? 'Saving...' : 'Save' })] })] })] }) }));
|
|
74
74
|
}
|
|
75
75
|
// ---------------------------------------------------------------------------
|
|
76
76
|
// Array field: repeatable list of sub-fields
|
|
@@ -84,7 +84,7 @@ function ArrayFieldRenderer({ field, value, onChange, }) {
|
|
|
84
84
|
const updated = rows.map((row, i) => (i === idx ? { ...row, [key]: val } : row));
|
|
85
85
|
onChange(updated);
|
|
86
86
|
};
|
|
87
|
-
return (_jsxs("div", { className: "space-y-3", children: [rows.map((row, idx) => (_jsxs("div", { className: "border border-
|
|
87
|
+
return (_jsxs("div", { className: "space-y-3", children: [rows.map((row, idx) => (_jsxs("div", { className: "border border-border rounded-md p-3 space-y-2 relative", children: [_jsx("button", { type: "button", onClick: () => removeRow(idx), className: "absolute top-2 right-2 text-red-400 hover:text-red-600 text-sm", children: "Remove" }), subFields.map((sf) => (_jsxs("div", { children: [_jsx("label", { htmlFor: `${field.name}-${idx}-${sf.name}`, className: "block text-xs font-medium text-muted-foreground", children: getFieldLabel(sf) }), _jsx(FieldInput, { field: sf, value: row[sf.name ?? ''], onChange: (v) => updateRow(idx, sf.name ?? '', v) })] }, sf.name)))] }, `${field.name}-row-${idx.toString()}`))), _jsx("button", { type: "button", onClick: addRow, className: "text-sm text-primary hover:text-primary/80 font-medium", children: "+ Add item" })] }));
|
|
88
88
|
}
|
|
89
89
|
// ---------------------------------------------------------------------------
|
|
90
90
|
// Group field: named group of sub-fields (single object, not repeatable)
|
|
@@ -95,7 +95,7 @@ function GroupFieldRenderer({ field, value, onChange, }) {
|
|
|
95
95
|
const handleChange = (key, val) => {
|
|
96
96
|
onChange({ ...data, [key]: val });
|
|
97
97
|
};
|
|
98
|
-
return (_jsx("div", { className: "border border-
|
|
98
|
+
return (_jsx("div", { className: "border border-border rounded-md p-3 space-y-3", children: subFields.map((sf) => (_jsxs("div", { children: [_jsxs("label", { htmlFor: `${field.name}-${sf.name}`, className: "block text-xs font-medium text-muted-foreground", children: [getFieldLabel(sf), sf.required && _jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), _jsx(FieldInput, { field: sf, value: data[sf.name ?? ''], onChange: (v) => handleChange(sf.name ?? '', v) })] }, sf.name))) }));
|
|
99
99
|
}
|
|
100
100
|
// ---------------------------------------------------------------------------
|
|
101
101
|
// Blocks field: polymorphic list of typed blocks
|
|
@@ -114,8 +114,8 @@ function BlocksFieldRenderer({ field, value, onChange, }) {
|
|
|
114
114
|
};
|
|
115
115
|
return (_jsxs("div", { className: "space-y-3", children: [blocks.map((block, idx) => {
|
|
116
116
|
const blockDef = blockTypes.find((bt) => bt.slug === block.blockType);
|
|
117
|
-
return (_jsxs("div", { className: "border border-
|
|
118
|
-
}), blockTypes.length > 0 && (_jsx("div", { className: "flex gap-2 flex-wrap", children: blockTypes.map((bt) => (_jsxs("button", { type: "button", onClick: () => addBlock(bt.slug), className: "text-sm text-
|
|
117
|
+
return (_jsxs("div", { className: "border border-border rounded-md p-3 space-y-2 relative", children: [_jsxs("div", { className: "flex items-center justify-between mb-1", children: [_jsx("span", { className: "text-xs font-semibold text-muted-foreground uppercase", children: String(block.blockType) }), _jsx("button", { type: "button", onClick: () => removeBlock(idx), className: "text-red-400 hover:text-red-600 text-sm", children: "Remove" })] }), (blockDef?.fields ?? []).map((sf) => (_jsxs("div", { children: [_jsx("label", { htmlFor: `${field.name}-${idx}-${sf.name}`, className: "block text-xs font-medium text-muted-foreground", children: getFieldLabel(sf) }), _jsx(FieldInput, { field: sf, value: block[sf.name ?? ''], onChange: (v) => updateBlock(idx, sf.name ?? '', v) })] }, sf.name)))] }, `${field.name}-block-${idx.toString()}`));
|
|
118
|
+
}), blockTypes.length > 0 && (_jsx("div", { className: "flex gap-2 flex-wrap", children: blockTypes.map((bt) => (_jsxs("button", { type: "button", onClick: () => addBlock(bt.slug), className: "text-sm text-primary hover:text-primary/80 font-medium", children: ["+ ", bt.slug] }, bt.slug))) }))] }));
|
|
119
119
|
}
|
|
120
120
|
// ---------------------------------------------------------------------------
|
|
121
121
|
// Collapsible field: expandable section of sub-fields
|
|
@@ -127,7 +127,7 @@ function CollapsibleFieldRenderer({ field, value, onChange, }) {
|
|
|
127
127
|
const handleChange = (key, val) => {
|
|
128
128
|
onChange({ ...data, [key]: val });
|
|
129
129
|
};
|
|
130
|
-
return (_jsxs("div", { className: "border border-
|
|
130
|
+
return (_jsxs("div", { className: "border border-border rounded-md", children: [_jsxs("button", { type: "button", onClick: () => setOpen(!open), className: "w-full text-left px-3 py-2 text-sm font-medium text-foreground hover:bg-muted flex items-center justify-between", children: [getFieldLabel(field), _jsx("span", { className: "text-muted-foreground", children: open ? '\u25B2' : '\u25BC' })] }), open && (_jsx("div", { className: "px-3 pb-3 space-y-3", children: subFields.map((sf) => (_jsxs("div", { children: [_jsx("label", { htmlFor: `${field.name}-${sf.name}`, className: "block text-xs font-medium text-muted-foreground", children: getFieldLabel(sf) }), _jsx(FieldInput, { field: sf, value: data[sf.name ?? ''], onChange: (v) => handleChange(sf.name ?? '', v) })] }, sf.name))) }))] }));
|
|
131
131
|
}
|
|
132
132
|
// ---------------------------------------------------------------------------
|
|
133
133
|
// JSON field: raw JSON editor with syntax-highlighted textarea
|
|
@@ -147,21 +147,21 @@ function JsonFieldRenderer({ field, value, onChange, }) {
|
|
|
147
147
|
onChange(raw);
|
|
148
148
|
}
|
|
149
149
|
}, [onChange]);
|
|
150
|
-
return (_jsxs("div", { children: [_jsx("textarea", { id: field.name, value: formatted, onChange: handleChange, rows: 8, className: "mt-1 block w-full border-
|
|
150
|
+
return (_jsxs("div", { children: [_jsx("textarea", { id: field.name, value: formatted, onChange: handleChange, rows: 8, className: "mt-1 block w-full border-input rounded-md shadow-sm focus:ring-ring focus:border-primary sm:text-sm font-mono text-xs", spellCheck: false }), error && _jsx("p", { className: "mt-1 text-xs text-red-500", children: error })] }));
|
|
151
151
|
}
|
|
152
152
|
// ---------------------------------------------------------------------------
|
|
153
153
|
// Point field: latitude/longitude pair
|
|
154
154
|
// ---------------------------------------------------------------------------
|
|
155
155
|
function PointFieldRenderer({ field, value, onChange, }) {
|
|
156
156
|
const point = (typeof value === 'object' && value !== null ? value : { lat: 0, lng: 0 });
|
|
157
|
-
const baseClasses = 'mt-1 block w-full border-
|
|
158
|
-
return (_jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsxs("div", { children: [_jsx("label", { htmlFor: `${field.name}-lat`, className: "block text-xs font-medium text-
|
|
157
|
+
const baseClasses = 'mt-1 block w-full border-input rounded-md shadow-sm focus:ring-ring focus:border-primary sm:text-sm';
|
|
158
|
+
return (_jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsxs("div", { children: [_jsx("label", { htmlFor: `${field.name}-lat`, className: "block text-xs font-medium text-muted-foreground", children: "Latitude" }), _jsx("input", { type: "number", id: `${field.name}-lat`, value: point.lat, onChange: (e) => onChange({ ...point, lat: Number(e.target.value) }), className: baseClasses, step: "any", min: -90, max: 90 })] }), _jsxs("div", { children: [_jsx("label", { htmlFor: `${field.name}-lng`, className: "block text-xs font-medium text-muted-foreground", children: "Longitude" }), _jsx("input", { type: "number", id: `${field.name}-lng`, value: point.lng, onChange: (e) => onChange({ ...point, lng: Number(e.target.value) }), className: baseClasses, step: "any", min: -180, max: 180 })] })] }));
|
|
159
159
|
}
|
|
160
160
|
// ---------------------------------------------------------------------------
|
|
161
161
|
// Main FieldInput - renders the appropriate control for each field type
|
|
162
162
|
// ---------------------------------------------------------------------------
|
|
163
163
|
function FieldInput({ field, value, onChange }) {
|
|
164
|
-
const baseClasses = 'mt-1 block w-full border-
|
|
164
|
+
const baseClasses = 'mt-1 block w-full border-input rounded-md shadow-sm focus:ring-ring focus:border-primary sm:text-sm';
|
|
165
165
|
switch (field.type) {
|
|
166
166
|
case 'text':
|
|
167
167
|
return (_jsx("input", { type: "text", id: field.name, value: formatTextValue(value), onChange: (e) => onChange(e.target.value), className: baseClasses, required: field.required }));
|
|
@@ -176,7 +176,7 @@ function FieldInput({ field, value, onChange }) {
|
|
|
176
176
|
case 'number':
|
|
177
177
|
return (_jsx("input", { type: "number", id: field.name, value: typeof value === 'number' ? value : value ? Number(value) : '', onChange: (e) => onChange(Number(e.target.value) || undefined), className: baseClasses, required: field.required, min: field.min, max: field.max }));
|
|
178
178
|
case 'checkbox':
|
|
179
|
-
return (_jsx("input", { type: "checkbox", id: field.name, checked: Boolean(value), onChange: (e) => onChange(e.target.checked), className: "h-4 w-4 text-
|
|
179
|
+
return (_jsx("input", { type: "checkbox", id: field.name, checked: Boolean(value), onChange: (e) => onChange(e.target.checked), className: "h-4 w-4 text-primary focus:ring-ring border-input rounded" }));
|
|
180
180
|
case 'select':
|
|
181
181
|
return (_jsxs("select", { id: field.name, value: formatTextValue(value), onChange: (e) => onChange(e.target.value), className: baseClasses, required: field.required, children: [_jsx("option", { value: "", children: "Select an option" }), field.options?.map((option) => {
|
|
182
182
|
const optValue = typeof option === 'string' ? option : option.value;
|
|
@@ -187,21 +187,21 @@ function FieldInput({ field, value, onChange }) {
|
|
|
187
187
|
return (_jsx("div", { className: "space-y-2 mt-1", children: field.options?.map((option) => {
|
|
188
188
|
const optValue = typeof option === 'string' ? option : option.value;
|
|
189
189
|
const optLabel = typeof option === 'string' ? option : option.label;
|
|
190
|
-
return (_jsxs("label", { className: "flex items-center gap-2 text-sm text-
|
|
190
|
+
return (_jsxs("label", { className: "flex items-center gap-2 text-sm text-foreground cursor-pointer", children: [_jsx("input", { type: "radio", name: field.name, value: optValue, checked: formatTextValue(value) === optValue, onChange: () => onChange(optValue), className: "h-4 w-4 text-primary focus:ring-ring border-input" }), optLabel] }, optValue));
|
|
191
191
|
}) }));
|
|
192
192
|
case 'relationship':
|
|
193
|
-
return (_jsxs("div", { children: [_jsx("input", { type: "text", id: field.name, value: formatTextValue(value), onChange: (e) => onChange(e.target.value), className: baseClasses, required: field.required, placeholder: `Enter ${field.relationTo ?? 'related'} ID` }), _jsxs("p", { className: "mt-1 text-xs text-
|
|
193
|
+
return (_jsxs("div", { children: [_jsx("input", { type: "text", id: field.name, value: formatTextValue(value), onChange: (e) => onChange(e.target.value), className: baseClasses, required: field.required, placeholder: `Enter ${field.relationTo ?? 'related'} ID` }), _jsxs("p", { className: "mt-1 text-xs text-muted-foreground", children: ["Related to: ", field.relationTo ?? 'unknown'] })] }));
|
|
194
194
|
case 'upload':
|
|
195
195
|
return (_jsxs("div", { children: [_jsx("input", { type: "file", id: field.name, onChange: (e) => {
|
|
196
196
|
const file = e.target.files?.[0];
|
|
197
197
|
if (file)
|
|
198
198
|
onChange(file);
|
|
199
|
-
}, className: "block w-full text-sm text-
|
|
199
|
+
}, className: "block w-full text-sm text-muted-foreground file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-medium file:bg-primary/10 file:text-primary hover:file:bg-primary/20" }), typeof value === 'string' && value !== '' && (_jsxs("p", { className: "mt-1 text-xs text-muted-foreground", children: ["Current: ", value] }))] }));
|
|
200
200
|
case 'date':
|
|
201
201
|
return (_jsx("input", { type: "datetime-local", id: field.name, value: formatDateInputValue(value), onChange: (e) => onChange(e.target.value ? new Date(e.target.value) : null), className: baseClasses, required: field.required }));
|
|
202
202
|
case 'richText': {
|
|
203
203
|
const editorConfig = field.editor;
|
|
204
|
-
return (_jsx(Suspense, { fallback: _jsx("div", { className: "border border-
|
|
204
|
+
return (_jsx(Suspense, { fallback: _jsx("div", { className: "border border-input rounded-md h-40 flex items-center justify-center text-sm text-muted-foreground", children: "Loading editor\u2026" }), children: _jsx(RichTextEditor, { namespace: String(field.name), editorConfig: editorConfig, initialValue: value, onSerializedChange: (json) => onChange(json), className: "border border-input rounded-md" }) }));
|
|
205
205
|
}
|
|
206
206
|
case 'array':
|
|
207
207
|
return _jsx(ArrayFieldRenderer, { field: field, value: value, onChange: onChange });
|
|
@@ -216,7 +216,7 @@ function FieldInput({ field, value, onChange }) {
|
|
|
216
216
|
case 'point':
|
|
217
217
|
return _jsx(PointFieldRenderer, { field: field, value: value, onChange: onChange });
|
|
218
218
|
case 'ui':
|
|
219
|
-
return (_jsxs("div", { className: "border border-dashed border-
|
|
219
|
+
return (_jsxs("div", { className: "border border-dashed border-input rounded-md p-3 text-sm text-muted-foreground text-center", children: ["Custom UI field: ", field.name] }));
|
|
220
220
|
default:
|
|
221
221
|
return (_jsx("input", { type: "text", id: field.name, value: formatTextValue(value), onChange: (e) => onChange(e.target.value), className: baseClasses, required: field.required }));
|
|
222
222
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type React from 'react';
|
|
1
2
|
import type { RevealDocument, RevealGlobalConfig } from '../../../types/index.js';
|
|
2
3
|
interface GlobalFormProps {
|
|
3
4
|
global: RevealGlobalConfig;
|
|
@@ -6,6 +7,6 @@ interface GlobalFormProps {
|
|
|
6
7
|
onCancel: () => void;
|
|
7
8
|
isLoading?: boolean;
|
|
8
9
|
}
|
|
9
|
-
export declare function GlobalForm({ global, document, onSave, onCancel, isLoading, }: GlobalFormProps):
|
|
10
|
+
export declare function GlobalForm({ global, document, onSave, onCancel, isLoading, }: GlobalFormProps): React.JSX.Element;
|
|
10
11
|
export {};
|
|
11
12
|
//# sourceMappingURL=GlobalForm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalForm.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/components/GlobalForm.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GlobalForm.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/components/GlobalForm.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAiB,MAAM,yBAAyB,CAAC;AAsCjG,UAAU,eAAe;IACvB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAChD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,SAAiB,GAClB,EAAE,eAAe,qBA4DjB"}
|
|
@@ -47,10 +47,10 @@ export function GlobalForm({ global, document, onSave, onCancel, isLoading = fal
|
|
|
47
47
|
const handleFieldChange = (fieldName, value) => {
|
|
48
48
|
setFormData((prev) => ({ ...prev, [fieldName]: value }));
|
|
49
49
|
};
|
|
50
|
-
return (_jsx("div", { className: "bg-
|
|
50
|
+
return (_jsx("div", { className: "bg-card shadow overflow-hidden sm:rounded-lg", children: _jsxs("div", { className: "px-4 py-5 sm:p-6", children: [_jsxs("h3", { className: "text-lg leading-6 font-medium text-foreground mb-4", children: ["Edit ", global.label || global.slug] }), _jsxs("form", { onSubmit: handleSubmit, className: "space-y-6", children: [visibleFields.map((field) => (_jsxs("div", { children: [_jsxs("label", { htmlFor: field.name, className: "block text-sm font-medium text-foreground", children: [getFieldLabel(field), field.required && _jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), _jsx("div", { className: "mt-1", children: _jsx(FieldInput, { field: field, value: field.name ? formData[field.name] : undefined, onChange: (value) => field.name && handleFieldChange(field.name, value) }) })] }, field.name || 'layout'))), _jsxs("div", { className: "flex justify-end space-x-3 pt-6", children: [_jsx("button", { type: "button", onClick: onCancel, className: "bg-card py-2 px-4 border border-input rounded-md shadow-sm text-sm font-medium text-foreground hover:bg-muted focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-background focus:ring-ring", children: "Cancel" }), _jsx("button", { type: "submit", disabled: isLoading, className: "inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-primary-foreground bg-primary hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-background focus:ring-ring disabled:opacity-50 disabled:cursor-not-allowed", children: isLoading ? 'Saving...' : 'Save' })] })] })] }) }));
|
|
51
51
|
}
|
|
52
52
|
function FieldInput({ field, value, onChange }) {
|
|
53
|
-
const baseClasses = 'mt-1 block w-full border-
|
|
53
|
+
const baseClasses = 'mt-1 block w-full border-input rounded-md shadow-sm focus:ring-ring focus:border-primary sm:text-sm';
|
|
54
54
|
switch (field.type) {
|
|
55
55
|
case 'text':
|
|
56
56
|
return (_jsx("input", { type: "text", id: field.name, value: formatTextValue(value), onChange: (e) => onChange(e.target.value), className: baseClasses, required: field.required }));
|
|
@@ -59,7 +59,7 @@ function FieldInput({ field, value, onChange }) {
|
|
|
59
59
|
case 'number':
|
|
60
60
|
return (_jsx("input", { type: "number", id: field.name, value: typeof value === 'number' ? value : value ? Number(value) : '', onChange: (e) => onChange(Number(e.target.value) || undefined), className: baseClasses, required: field.required, min: field.min, max: field.max }));
|
|
61
61
|
case 'checkbox':
|
|
62
|
-
return (_jsx("input", { type: "checkbox", id: field.name, checked: Boolean(value), onChange: (e) => onChange(e.target.checked), className: "h-4 w-4 text-
|
|
62
|
+
return (_jsx("input", { type: "checkbox", id: field.name, checked: Boolean(value), onChange: (e) => onChange(e.target.checked), className: "h-4 w-4 text-primary focus:ring-ring border-input rounded" }));
|
|
63
63
|
case 'select':
|
|
64
64
|
return (_jsxs("select", { id: field.name, value: formatTextValue(value), onChange: (e) => onChange(e.target.value), className: baseClasses, required: field.required, children: [_jsx("option", { value: "", children: "Select an option" }), field.options?.map((option) => {
|
|
65
65
|
const value = typeof option === 'string' ? option : option.value;
|
|
@@ -2,7 +2,7 @@ type ServerFunction = (name: string, args: unknown) => Promise<unknown>;
|
|
|
2
2
|
export declare function ServerFunctionProvider({ children, serverFunction, }: {
|
|
3
3
|
children: React.ReactNode;
|
|
4
4
|
serverFunction?: ServerFunction;
|
|
5
|
-
}): import("react
|
|
5
|
+
}): import("react").JSX.Element;
|
|
6
6
|
export declare function useServerFunction(): ServerFunction;
|
|
7
7
|
export {};
|
|
8
8
|
//# sourceMappingURL=ServerFunctionContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerFunctionContext.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/context/ServerFunctionContext.tsx"],"names":[],"mappings":"AAIA,KAAK,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAIxE,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,cAAc,GACf,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC
|
|
1
|
+
{"version":3,"file":"ServerFunctionContext.d.ts","sourceRoot":"","sources":["../../../../src/client/admin/context/ServerFunctionContext.tsx"],"names":[],"mappings":"AAIA,KAAK,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAIxE,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,cAAc,GACf,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC,+BAEA;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CASlD"}
|
|
@@ -6,5 +6,5 @@ export interface RootLayoutProps {
|
|
|
6
6
|
importMap?: Record<string, unknown>;
|
|
7
7
|
serverFunction?: (name: string, args: unknown) => Promise<unknown>;
|
|
8
8
|
}
|
|
9
|
-
export declare function RootLayout({ children, serverFunction }: RootLayoutProps):
|
|
9
|
+
export declare function RootLayout({ children, serverFunction }: RootLayoutProps): React.JSX.Element;
|
|
10
10
|
//# sourceMappingURL=layout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/client/admin/layout.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAGnD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACpE;AAED,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/client/admin/layout.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAGnD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACpE;AAED,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,eAAe,qBAsBvE"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ServerFunctionProvider } from './context/ServerFunctionContext.js';
|
|
3
3
|
export function RootLayout({ children, serverFunction }) {
|
|
4
|
-
|
|
4
|
+
// Server component: resolved per request. White-label kits override via
|
|
5
|
+
// REVEALUI_BRAND_NAME / REVEALUI_TENANT_NAME. `||` not `??`: Compose
|
|
6
|
+
// `${VAR:-}` interpolation delivers unset vars as empty strings.
|
|
7
|
+
const siteName = process.env.REVEALUI_BRAND_NAME || process.env.REVEALUI_TENANT_NAME || 'RevealUI';
|
|
8
|
+
return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charSet: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: `${siteName} Admin` })] }), _jsx("body", { className: "antialiased", children: _jsx(ServerFunctionProvider, { serverFunction: serverFunction, children: _jsx("main", { id: "revealui-admin", className: "min-h-screen", children: children }) }) })] }));
|
|
5
9
|
}
|
|
@@ -31,8 +31,8 @@ export interface NotFoundPageProps {
|
|
|
31
31
|
}>;
|
|
32
32
|
importMap?: Record<string, unknown>;
|
|
33
33
|
}
|
|
34
|
-
export declare function RootPage({ config }: RootPageProps): import("react
|
|
35
|
-
export declare function NotFoundPage(): import("react
|
|
34
|
+
export declare function RootPage({ config }: RootPageProps): import("react").JSX.Element;
|
|
35
|
+
export declare function NotFoundPage(): import("react").JSX.Element;
|
|
36
36
|
export declare function generatePageMetadata(): Metadata;
|
|
37
37
|
export {};
|
|
38
38
|
//# sourceMappingURL=page.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../src/client/admin/page.tsx"],"names":[],"mappings":"AACA,UAAU,QAAQ;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE;QACN,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;QACxB,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;QACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,MAAM,EAAE,OAAO,CAAC;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACzC,YAAY,EAAE,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE;QACN,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;QACxB,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;QACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,MAAM,EAAE,OAAO,CAAC;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACzC,YAAY,EAAE,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,aAAa
|
|
1
|
+
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../src/client/admin/page.tsx"],"names":[],"mappings":"AACA,UAAU,QAAQ;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE;QACN,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;QACxB,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;QACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,MAAM,EAAE,OAAO,CAAC;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACzC,YAAY,EAAE,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE;QACN,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;QACxB,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;QACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,MAAM,EAAE,OAAO,CAAC;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACzC,YAAY,EAAE,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,aAAa,+BA+KjD;AAED,wBAAgB,YAAY,gCAO3B;AAED,wBAAgB,oBAAoB,IAAI,QAAQ,CAS/C"}
|
|
@@ -2,14 +2,21 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
export function RootPage({ config }) {
|
|
3
3
|
const collections = (config.collections || []);
|
|
4
4
|
const globals = (config.globals || []);
|
|
5
|
-
|
|
5
|
+
// Server component: white-label kits override via REVEALUI_BRAND_NAME /
|
|
6
|
+
// REVEALUI_TENANT_NAME. `||` not `??`: Compose `${VAR:-}` interpolation
|
|
7
|
+
// delivers unset vars as empty strings.
|
|
8
|
+
const siteName = process.env.REVEALUI_BRAND_NAME || process.env.REVEALUI_TENANT_NAME || 'RevealUI';
|
|
9
|
+
return (_jsxs("div", { className: "min-h-screen bg-background", children: [_jsx("header", { className: "bg-card shadow-sm border-b", children: _jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: _jsxs("div", { className: "flex justify-between items-center py-4", children: [_jsx("div", { className: "flex items-center", children: _jsx("h1", { className: "text-2xl font-bold text-foreground", children: `${siteName} Admin` }) }), _jsx("div", { className: "flex items-center space-x-4", children: _jsx("span", { className: "text-sm text-muted-foreground", children: "v0.1.0" }) })] }) }) }), _jsx("main", { className: "max-w-7xl mx-auto py-6 sm:px-6 lg:px-8", children: _jsx("div", { className: "px-4 py-6 sm:px-0", children: _jsxs("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3", children: [_jsxs("div", { className: "bg-card overflow-hidden shadow rounded-lg", children: [_jsx("div", { className: "p-5", children: _jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "flex-shrink-0", children: _jsxs("svg", { className: "h-8 w-8 text-muted-foreground", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: [_jsx("title", { children: "Collections icon" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" })] }) }), _jsx("div", { className: "ml-5 w-0 flex-1", children: _jsxs("dl", { children: [_jsx("dt", { className: "text-sm font-medium text-muted-foreground truncate", children: "Collections" }), _jsx("dd", { className: "text-lg font-medium text-foreground", children: collections.length })] }) })] }) }), _jsx("div", { className: "bg-muted px-5 py-3", children: _jsx("div", { className: "text-sm", children: collections.length > 0 ? (_jsx("ul", { className: "space-y-1", children: collections.map((collection) => (_jsxs("li", { className: "text-muted-foreground", children: [_jsx("span", { className: "font-medium", children: collection.slug }), _jsxs("span", { className: "ml-2 text-xs text-muted-foreground", children: ["(", collection.fields?.length || 0, " fields)"] })] }, collection.slug))) })) : (_jsx("p", { className: "text-muted-foreground", children: "No collections configured" })) }) })] }), _jsxs("div", { className: "bg-card overflow-hidden shadow rounded-lg", children: [_jsx("div", { className: "p-5", children: _jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "flex-shrink-0", children: _jsxs("svg", { className: "h-8 w-8 text-muted-foreground", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: [_jsx("title", { children: "Globals icon" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4" })] }) }), _jsx("div", { className: "ml-5 w-0 flex-1", children: _jsxs("dl", { children: [_jsx("dt", { className: "text-sm font-medium text-muted-foreground truncate", children: "Globals" }), _jsx("dd", { className: "text-lg font-medium text-foreground", children: globals.length })] }) })] }) }), _jsx("div", { className: "bg-muted px-5 py-3", children: _jsx("div", { className: "text-sm", children: globals.length > 0 ? (_jsx("ul", { className: "space-y-1", children: globals.map((global) => (_jsxs("li", { className: "text-muted-foreground", children: [_jsx("span", { className: "font-medium", children: global.slug }), _jsxs("span", { className: "ml-2 text-xs text-muted-foreground", children: ["(", global.fields?.length || 0, " fields)"] })] }, global.slug))) })) : (_jsx("p", { className: "text-muted-foreground", children: "No globals configured" })) }) })] }), _jsxs("div", { className: "bg-card overflow-hidden shadow rounded-lg", children: [_jsx("div", { className: "p-5", children: _jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "flex-shrink-0", children: _jsx("div", { className: "h-8 w-8 bg-success/15 rounded-full flex items-center justify-center", children: _jsxs("svg", { className: "h-5 w-5 text-success", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: [_jsx("title", { children: "System operational" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" })] }) }) }), _jsx("div", { className: "ml-5 w-0 flex-1", children: _jsxs("dl", { children: [_jsx("dt", { className: "text-sm font-medium text-muted-foreground truncate", children: "System Status" }), _jsx("dd", { className: "text-lg font-medium text-foreground", children: "Operational" })] }) })] }) }), _jsx("div", { className: "bg-muted px-5 py-3", children: _jsxs("div", { className: "text-sm text-muted-foreground", children: [siteName, " admin is running successfully with ", collections.length, " collections and", ' ', globals.length, " globals configured."] }) })] })] }) }) })] }));
|
|
6
10
|
}
|
|
7
11
|
export function NotFoundPage() {
|
|
8
12
|
return (_jsxs("div", { children: [_jsx("h1", { children: "404 - Page Not Found" }), _jsx("p", { children: "The requested admin page could not be found." })] }));
|
|
9
13
|
}
|
|
10
14
|
export function generatePageMetadata() {
|
|
15
|
+
// Server-side, resolved per call. White-label kits override via env.
|
|
16
|
+
// `||` not `??`: Compose `${VAR:-}` delivers unset vars as empty strings.
|
|
17
|
+
const siteName = process.env.REVEALUI_BRAND_NAME || process.env.REVEALUI_TENANT_NAME || 'RevealUI';
|
|
11
18
|
return {
|
|
12
|
-
title:
|
|
13
|
-
description:
|
|
19
|
+
title: `${siteName} Admin`,
|
|
20
|
+
description: `${siteName} Content Management System`,
|
|
14
21
|
};
|
|
15
22
|
}
|