@actuate-media/cms-admin 0.7.3 → 0.8.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/dist/lib/api.js CHANGED
@@ -9,13 +9,34 @@ function getCsrfToken() {
9
9
  const match = document.cookie.match(/(?:^|;\s*)actuate_csrf=([^;]*)/);
10
10
  return match?.[1] ?? '';
11
11
  }
12
+ /**
13
+ * Fetch a CSRF token if we don't have one in cookies yet. Used both as a
14
+ * one-shot bootstrap (e.g. on AdminRoot mount after a Server-Action login)
15
+ * and lazily inside `cmsApi` before mutating requests.
16
+ *
17
+ * Multiple concurrent callers share a single in-flight fetch via the
18
+ * `pendingFetch` cache so the admin doesn't fire N parallel `/auth/csrf`
19
+ * requests when a page lights up after navigation.
20
+ */
21
+ let pendingFetch = null;
12
22
  export async function ensureCsrfToken() {
13
23
  if (getCsrfToken())
14
24
  return;
15
- try {
16
- await fetch(`${basePath}/auth/csrf`, { credentials: 'include' });
17
- }
18
- catch { /* best-effort */ }
25
+ if (pendingFetch)
26
+ return pendingFetch;
27
+ pendingFetch = (async () => {
28
+ try {
29
+ await fetch(`${basePath}/auth/csrf`, { credentials: 'include' });
30
+ }
31
+ catch {
32
+ // best-effort — caller will see the 403 from the actual mutation if
33
+ // the cookie still isn't set, instead of a silent network failure.
34
+ }
35
+ finally {
36
+ pendingFetch = null;
37
+ }
38
+ })();
39
+ return pendingFetch;
19
40
  }
20
41
  function getActiveLocale() {
21
42
  if (typeof localStorage === 'undefined')
@@ -40,6 +61,14 @@ export async function cmsApi(endpoint, options = {}) {
40
61
  }
41
62
  const method = (options.method ?? 'GET').toUpperCase();
42
63
  if (method !== 'GET' && method !== 'HEAD') {
64
+ // Bootstrap the CSRF cookie lazily — covers consumers that sign users
65
+ // in via a custom Server Action (the Next.js App Router pattern) where
66
+ // the admin never hits `/auth/login` directly and so never receives the
67
+ // cookie from the login response. Without this, the very first mutation
68
+ // after sign-in 403s.
69
+ if (!getCsrfToken()) {
70
+ await ensureCsrfToken();
71
+ }
43
72
  const csrf = getCsrfToken();
44
73
  if (csrf)
45
74
  headers['x-csrf-token'] = csrf;
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"BlockEditor.d.ts","sourceRoot":"","sources":["../../../src/views/page-builder/BlockEditor.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAwC,MAAM,yBAAyB,CAAC;AAI/F,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACnE,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC1E,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,MAAM,EAAE,GAAG,CAAC;CACb;AAMD,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,MAAM,GACP,EAAE,gBAAgB,2CA0HlB"}
1
+ {"version":3,"file":"BlockEditor.d.ts","sourceRoot":"","sources":["../../../src/views/page-builder/BlockEditor.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAwC,MAAM,yBAAyB,CAAC;AAM/F,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACnE,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC1E,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,MAAM,EAAE,GAAG,CAAC;CACb;AAMD,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,MAAM,GACP,EAAE,gBAAgB,2CA0HlB"}
@@ -5,6 +5,8 @@ import { Star, Copy, Trash2 } from 'lucide-react';
5
5
  import * as SwitchPrimitive from '@radix-ui/react-switch';
6
6
  import { BlockCatalog } from '@actuate-media/cms-core';
7
7
  import { AIBlockAssist } from './AIBlockAssist.js';
8
+ import { TipTapEditor } from '../../components/TipTapEditor.js';
9
+ import { MediaPickerModal } from '../../components/MediaPickerModal.js';
8
10
  const INPUT_CLASS = 'w-full px-3 py-2 text-sm bg-background border border-input rounded-md focus:outline-none focus:ring-2 focus:ring-ring';
9
11
  const LABEL_CLASS = 'text-sm font-medium text-foreground mb-1 block';
10
12
  export function BlockEditor({ node, onUpdateBlock, onUpdateSettings, onRemoveNode, onDuplicateNode, config, }) {
@@ -41,7 +43,7 @@ function FieldRenderer({ name, definition, value, onChange }) {
41
43
  case 'text':
42
44
  return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "text", value: value ?? '', onChange: (e) => onChange(e.target.value), placeholder: definition.admin?.placeholder, className: INPUT_CLASS })] }));
43
45
  case 'richText':
44
- return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("textarea", { value: value ?? '', onChange: (e) => onChange(e.target.value), placeholder: definition.admin?.placeholder, rows: 4, className: `${INPUT_CLASS} resize-y` })] }));
46
+ return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("div", { className: "rounded-md border border-input overflow-hidden bg-background", children: _jsx(TipTapEditor, { content: value ?? '', onChange: (html) => onChange(html), placeholder: definition.admin?.placeholder }) })] }));
45
47
  case 'url':
46
48
  return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "url", value: value ?? '', onChange: (e) => onChange(e.target.value), placeholder: definition.admin?.placeholder ?? 'https://', className: INPUT_CLASS })] }));
47
49
  case 'number':
@@ -49,11 +51,23 @@ function FieldRenderer({ name, definition, value, onChange }) {
49
51
  case 'boolean':
50
52
  return (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("label", { className: "text-sm font-medium text-foreground", children: label }), _jsx(SwitchPrimitive.Root, { checked: !!value, onCheckedChange: (checked) => onChange(checked), className: "w-9 h-5 bg-input rounded-full relative data-[state=checked]:bg-primary transition-colors", "aria-label": label, children: _jsx(SwitchPrimitive.Thumb, { className: "block h-3.5 w-3.5 rounded-full bg-background shadow-sm transition-transform translate-x-0.5 data-[state=checked]:translate-x-[18px]" }) })] }));
51
53
  case 'media':
52
- return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsxs("div", { className: "flex gap-2", children: [_jsx("input", { type: "text", value: value ?? '', onChange: (e) => onChange(e.target.value), placeholder: "Select media...", className: `${INPUT_CLASS} flex-1` }), _jsx("button", { type: "button", className: "px-3 py-2 text-xs font-medium bg-accent text-foreground border border-input rounded-md hover:bg-accent/80 transition-colors", children: "Browse" })] })] }));
54
+ return _jsx(MediaFieldRenderer, { label: label, value: value, onChange: onChange });
53
55
  case 'select':
54
56
  return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsxs("select", { value: value ?? '', onChange: (e) => onChange(e.target.value), className: INPUT_CLASS, children: [_jsx("option", { value: "", children: "Select..." }), definition.options.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value)))] })] }));
55
57
  case 'array':
56
- return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("div", { className: "px-3 py-2 text-sm bg-muted border border-input rounded-md text-muted-foreground", children: Array.isArray(value) ? `${value.length} items` : '0 items' })] }));
58
+ return _jsx(ArrayFieldRenderer, { label: label, value: value, onChange: onChange });
59
+ case 'json':
60
+ return _jsx(JsonFieldRenderer, { label: label, value: value, onChange: onChange });
61
+ case 'date':
62
+ return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "date", value: typeof value === 'string' && value ? value.slice(0, 10) : '', onChange: (e) => onChange(e.target.value || undefined), className: INPUT_CLASS })] }));
63
+ case 'slug':
64
+ return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "text", value: value ?? '', onChange: (e) => {
65
+ const slug = e.target.value
66
+ .toLowerCase()
67
+ .replace(/[^a-z0-9-]+/g, '-')
68
+ .replace(/^-+|-+$/g, '');
69
+ onChange(slug);
70
+ }, placeholder: definition.admin?.placeholder ?? 'page-slug', className: INPUT_CLASS })] }));
57
71
  case 'relationship':
58
72
  return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "text", value: value ?? '', onChange: (e) => onChange(e.target.value), placeholder: "Select relationship...", className: INPUT_CLASS })] }));
59
73
  case 'email':
@@ -64,4 +78,81 @@ function FieldRenderer({ name, definition, value, onChange }) {
64
78
  return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("input", { type: "text", value: String(value ?? ''), onChange: (e) => onChange(e.target.value), className: INPUT_CLASS })] }));
65
79
  }
66
80
  }
81
+ /**
82
+ * Block-level media picker. Wires the cross-cutting MediaPickerModal so
83
+ * custom blocks declared with `type: 'media'` actually get a working
84
+ * browse-and-select flow instead of a free-text input.
85
+ */
86
+ function MediaFieldRenderer({ label, value, onChange }) {
87
+ const [open, setOpen] = useState(false);
88
+ const url = typeof value === 'string'
89
+ ? value
90
+ : (value && typeof value === 'object' && 'url' in value)
91
+ ? String(value.url)
92
+ : '';
93
+ return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsxs("div", { className: "flex gap-2", children: [_jsx("input", { type: "text", value: url, onChange: (e) => onChange(e.target.value), placeholder: "https://...", className: `${INPUT_CLASS} flex-1` }), _jsx("button", { type: "button", onClick: () => setOpen(true), className: "px-3 py-2 text-xs font-medium bg-accent text-foreground border border-input rounded-md hover:bg-accent/80 transition-colors", children: "Browse" })] }), url && /\.(png|jpe?g|gif|webp|avif|svg)(\?|$)/i.test(url) && (_jsx("div", { className: "mt-2 rounded-md border border-border overflow-hidden bg-muted", children: _jsx("img", { src: url, alt: "", className: "w-full h-32 object-contain bg-checkered" }) })), _jsx(MediaPickerModal, { open: open, onClose: () => setOpen(false), onSelect: (selectedUrl) => {
94
+ onChange(selectedUrl);
95
+ setOpen(false);
96
+ } })] }));
97
+ }
98
+ /**
99
+ * JSON editor for free-form object/array fields. The textarea is the
100
+ * source of truth while the user is typing — we only commit a parsed
101
+ * value back upstream once the JSON is well-formed, otherwise the user
102
+ * sees a validation error inline. This prevents typing-induced state
103
+ * loss and keeps the UI usable for arrays of objects (a common shape
104
+ * for custom blocks).
105
+ */
106
+ function JsonFieldRenderer({ label, value, onChange }) {
107
+ const initial = useMemo(() => {
108
+ if (value === undefined || value === null)
109
+ return '';
110
+ try {
111
+ return JSON.stringify(value, null, 2);
112
+ }
113
+ catch {
114
+ return '';
115
+ }
116
+ }, [value]);
117
+ const [draft, setDraft] = useState(initial);
118
+ const [error, setError] = useState(null);
119
+ const handleChange = (next) => {
120
+ setDraft(next);
121
+ if (next.trim() === '') {
122
+ setError(null);
123
+ onChange(undefined);
124
+ return;
125
+ }
126
+ try {
127
+ onChange(JSON.parse(next));
128
+ setError(null);
129
+ }
130
+ catch (err) {
131
+ setError(err instanceof Error ? err.message : 'Invalid JSON');
132
+ }
133
+ };
134
+ return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsx("textarea", { value: draft, onChange: (e) => handleChange(e.target.value), rows: 6, spellCheck: false, className: `${INPUT_CLASS} font-mono text-xs resize-y` }), error && (_jsx("p", { className: "mt-1 text-xs text-destructive", role: "alert", children: error }))] }));
135
+ }
136
+ /**
137
+ * Lightweight array editor — supports homogenous arrays of strings or
138
+ * objects. For block fields we deliberately keep this simple: full
139
+ * nested-field editing belongs in the document-level FieldRenderer.
140
+ */
141
+ function ArrayFieldRenderer({ label, value, onChange }) {
142
+ const items = Array.isArray(value) ? value : [];
143
+ const isObjectArray = items.length > 0 && typeof items[0] === 'object' && items[0] !== null;
144
+ if (isObjectArray) {
145
+ // For object arrays fall back to JSON — mirrors what most consumers
146
+ // expect when their block declares `type: 'array'` with no schema.
147
+ return _jsx(JsonFieldRenderer, { label: label, value: value, onChange: onChange });
148
+ }
149
+ const updateItem = (idx, next) => {
150
+ const copy = [...items];
151
+ copy[idx] = next;
152
+ onChange(copy);
153
+ };
154
+ const addItem = () => onChange([...items, '']);
155
+ const removeItem = (idx) => onChange(items.filter((_, i) => i !== idx));
156
+ return (_jsxs("div", { children: [_jsx("label", { className: LABEL_CLASS, children: label }), _jsxs("div", { className: "space-y-2", children: [items.map((item, idx) => (_jsxs("div", { className: "flex gap-2", children: [_jsx("input", { type: "text", value: typeof item === 'string' ? item : '', onChange: (e) => updateItem(idx, e.target.value), className: `${INPUT_CLASS} flex-1` }), _jsx("button", { type: "button", onClick: () => removeItem(idx), "aria-label": `Remove item ${idx + 1}`, className: "px-2 py-2 text-xs text-destructive border border-input rounded-md hover:bg-destructive/10 transition-colors", children: _jsx(Trash2, { size: 14 }) })] }, idx))), _jsx("button", { type: "button", onClick: addItem, className: "w-full px-3 py-2 text-xs font-medium bg-accent text-foreground border border-input rounded-md hover:bg-accent/80 transition-colors", children: "+ Add item" })] })] }));
157
+ }
67
158
  //# sourceMappingURL=BlockEditor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BlockEditor.js","sourceRoot":"","sources":["../../../src/views/page-builder/BlockEditor.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BlockEditor.js","sourceRoot":"","sources":["../../../src/views/page-builder/BlockEditor.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PageBuilder.d.ts","sourceRoot":"","sources":["../../../src/views/page-builder/PageBuilder.tsx"],"names":[],"mappings":"AAoBA,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,GAAG,CAAC;IACZ,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAUD,wBAAgB,WAAW,CAAC,EAC1B,UAAU,EACV,cAAc,EACd,MAAM,EACN,UAAU,GACX,EAAE,gBAAgB,2CAuPlB"}
1
+ {"version":3,"file":"PageBuilder.d.ts","sourceRoot":"","sources":["../../../src/views/page-builder/PageBuilder.tsx"],"names":[],"mappings":"AAoBA,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,GAAG,CAAC;IACZ,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAUD,wBAAgB,WAAW,CAAC,EAC1B,UAAU,EACV,cAAc,EACd,MAAM,EACN,UAAU,GACX,EAAE,gBAAgB,2CAwQlB"}
@@ -121,6 +121,26 @@ export function PageBuilder({ documentId, collectionSlug, config, onNavigate, })
121
121
  }
122
122
  const canvasWidth = DEVICE_WIDTHS[deviceMode];
123
123
  const isConstrained = deviceMode !== 'desktop';
124
- return (_jsxs(ErrorBoundary, { children: [_jsxs("div", { className: "h-full flex flex-col bg-background overflow-hidden", children: [_jsx(BuilderToolbar, { collectionSlug: collectionSlug, pageSettings: pageSettings, status: status, dirty: dirty, saving: saving, canUndo: canUndo, canRedo: canRedo, deviceMode: deviceMode, onNavigate: onNavigate, onTitleChange: (title) => setPageSettings({ title }), onUndo: undo, onRedo: redo, onDeviceMode: setDeviceMode, onSave: handleSave, onPublish: handlePublish, onOpenAI: () => setAiDialogOpen(true) }), _jsxs("div", { className: "flex-1 flex overflow-hidden", children: [_jsx("div", { className: "flex-1 overflow-auto bg-muted", children: _jsx("div", { className: "mx-auto h-full max-w-full transition-all duration-200", style: { width: canvasWidth }, children: _jsx("div", { className: `h-full bg-background ${isConstrained ? 'shadow-lg border-x border-border' : ''}`, children: _jsx(BuilderCanvas, { tree: tree, selectedNodeId: selectedNodeId, showGridOverlay: showGridOverlay, deviceMode: deviceMode, onSelectNode: selectNode }) }) }) }), _jsx("div", { className: "w-[35%] min-w-[280px] max-w-[420px] border-l border-border bg-card overflow-y-auto", children: _jsx(ContextPanel, { activeTab: activeTab, onTabChange: setActiveTab, selectedNode: selectedNode, tree: tree, pageSettings: pageSettings, onUpdateSettings: updateSettings, onUpdateBlock: updateBlock, onRemoveNode: removeNodeById, onDuplicateNode: duplicateNode, onMoveNodeUp: moveNodeUp, onMoveNodeDown: moveNodeDown, onPageSettingsChange: setPageSettings, onAddRow: addRowToSection, config: config }) })] }), _jsx(BottomBar, { deviceMode: deviceMode, showGridOverlay: showGridOverlay, onAddSection: addSection, onToggleGrid: setShowGridOverlay })] }), _jsx(AIGenerateDialog, { open: aiDialogOpen, onClose: () => setAiDialogOpen(false), onAccept: handleAIAccept })] }));
124
+ // `pageBuilder.previewTheme` lets consumers preview blocks with their
125
+ // brand fonts/colors/radii without baking them into the admin's tokens.
126
+ // We scope the CSS variables to the canvas wrapper so they never leak
127
+ // into the rest of the admin chrome.
128
+ const previewTheme = config?.pageBuilder?.previewTheme ?? {};
129
+ const previewStyle = {};
130
+ if (previewTheme.fontFamily)
131
+ previewStyle['--preview-font-family'] = previewTheme.fontFamily;
132
+ if (previewTheme.headingFontFamily)
133
+ previewStyle['--preview-heading-font-family'] = previewTheme.headingFontFamily;
134
+ if (previewTheme.primaryColor)
135
+ previewStyle['--preview-primary'] = previewTheme.primaryColor;
136
+ if (previewTheme.secondaryColor)
137
+ previewStyle['--preview-secondary'] = previewTheme.secondaryColor;
138
+ if (previewTheme.borderRadius)
139
+ previewStyle['--preview-radius'] = previewTheme.borderRadius;
140
+ const canvasShellStyle = {
141
+ ...previewStyle,
142
+ fontFamily: previewTheme.fontFamily ?? undefined,
143
+ };
144
+ return (_jsxs(ErrorBoundary, { children: [_jsxs("div", { className: "h-full flex flex-col bg-background overflow-hidden", children: [_jsx(BuilderToolbar, { collectionSlug: collectionSlug, pageSettings: pageSettings, status: status, dirty: dirty, saving: saving, canUndo: canUndo, canRedo: canRedo, deviceMode: deviceMode, onNavigate: onNavigate, onTitleChange: (title) => setPageSettings({ title }), onUndo: undo, onRedo: redo, onDeviceMode: setDeviceMode, onSave: handleSave, onPublish: handlePublish, onOpenAI: () => setAiDialogOpen(true) }), _jsxs("div", { className: "flex-1 flex overflow-hidden", children: [_jsx("div", { className: "flex-1 overflow-auto bg-muted", children: _jsx("div", { className: "mx-auto h-full max-w-full transition-all duration-200", style: { width: canvasWidth }, children: _jsx("div", { className: `h-full bg-background page-builder-canvas-shell ${isConstrained ? 'shadow-lg border-x border-border' : ''}`, style: canvasShellStyle, children: _jsx(BuilderCanvas, { tree: tree, selectedNodeId: selectedNodeId, showGridOverlay: showGridOverlay, deviceMode: deviceMode, onSelectNode: selectNode }) }) }) }), _jsx("div", { className: "w-[35%] min-w-[280px] max-w-[420px] border-l border-border bg-card overflow-y-auto", children: _jsx(ContextPanel, { activeTab: activeTab, onTabChange: setActiveTab, selectedNode: selectedNode, tree: tree, pageSettings: pageSettings, onUpdateSettings: updateSettings, onUpdateBlock: updateBlock, onRemoveNode: removeNodeById, onDuplicateNode: duplicateNode, onMoveNodeUp: moveNodeUp, onMoveNodeDown: moveNodeDown, onPageSettingsChange: setPageSettings, onAddRow: addRowToSection, config: config }) })] }), _jsx(BottomBar, { deviceMode: deviceMode, showGridOverlay: showGridOverlay, onAddSection: addSection, onToggleGrid: setShowGridOverlay })] }), _jsx(AIGenerateDialog, { open: aiDialogOpen, onClose: () => setAiDialogOpen(false), onAccept: handleAIAccept })] }));
125
145
  }
126
146
  //# sourceMappingURL=PageBuilder.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageBuilder.js","sourceRoot":"","sources":["../../../src/views/page-builder/PageBuilder.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PageBuilder.js","sourceRoot":"","sources":["../../../src/views/page-builder/PageBuilder.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actuate-media/cms-admin",
3
- "version": "0.7.3",
3
+ "version": "0.8.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/actuate-media/actuatecms.git",
@@ -71,7 +71,7 @@
71
71
  "tailwindcss": "^4.0.0",
72
72
  "typescript": "^5.7.0",
73
73
  "vitest": "^3.0.0",
74
- "@actuate-media/cms-core": "0.10.4"
74
+ "@actuate-media/cms-core": "0.11.0"
75
75
  },
76
76
  "scripts": {
77
77
  "build": "tsc --project tsconfig.json && npx @tailwindcss/cli -i src/styles/build-input.css -o dist/actuate-admin.css --minify",
package/src/AdminRoot.tsx CHANGED
@@ -3,6 +3,7 @@
3
3
  import { useState, useMemo, useEffect, useRef } from 'react';
4
4
  import { Layout } from './layout/Layout.js';
5
5
  import { useAdminRouter } from './router/index.js';
6
+ import { ensureCsrfToken } from './lib/api.js';
6
7
  import { Dashboard } from './views/Dashboard.js';
7
8
  import { CollectionList } from './views/CollectionList.js';
8
9
  import { DocumentEdit } from './views/DocumentEdit.js';
@@ -45,6 +46,17 @@ function AdminShell({ config, session, basePath = '/admin', initialPath = '/', s
45
46
  useBranding(config);
46
47
  useAdminPageTitle(config, currentPath);
47
48
 
49
+ // When the session was minted via a custom Server Action (the Next.js App
50
+ // Router pattern) the admin won't have hit /auth/login directly and thus
51
+ // won't have an actuate_csrf cookie yet — every subsequent mutation 403s.
52
+ // Proactively bootstrap one as soon as we mount with a session. cmsApi
53
+ // also bootstraps lazily inside non-GET requests as a belt-and-braces.
54
+ useEffect(() => {
55
+ if (session) {
56
+ void ensureCsrfToken();
57
+ }
58
+ }, [session]);
59
+
48
60
  const shortcuts = useMemo(() => ({
49
61
  'mod+k': () => {
50
62
  const searchInput = document.querySelector<HTMLInputElement>('input[placeholder*="Search"]');
@@ -93,53 +105,34 @@ function AdminShell({ config, session, basePath = '/admin', initialPath = '/', s
93
105
  );
94
106
  }
95
107
 
96
- const collectionSlugs = config?.collections
97
- ? Object.values(config.collections as Record<string, { slug: string }>).map((c) => c.slug)
98
- : ['pages', 'posts'];
99
-
100
- function renderView() {
101
- if (matchRoute('/')) {
102
- return <Dashboard config={config} session={session} onNavigate={navigate} />;
103
- }
104
-
105
- const pageBuilderNew = matchRoute('/page-builder/new');
106
- if (pageBuilderNew) {
107
- return <PageBuilder collectionSlug="pages" config={config} onNavigate={navigate} />;
108
- }
109
-
110
- const pageBuilderEdit = matchRoute('/page-builder/:id');
111
- if (pageBuilderEdit?.id) {
112
- return <PageBuilder documentId={pageBuilderEdit.id} collectionSlug="pages" config={config} onNavigate={navigate} />;
113
- }
114
-
115
- for (const slug of collectionSlugs) {
116
- const newMatch = matchRoute(`/${slug}/new`);
117
- if (newMatch) {
118
- return <DocumentEdit collectionSlug={slug} config={config} />;
119
- }
120
- const editMatch = matchRoute(`/${slug}/:id`);
121
- if (editMatch?.id) {
122
- return <DocumentEdit collectionSlug={slug} documentId={editMatch.id} config={config} />;
123
- }
124
- if (matchRoute(`/${slug}`)) {
125
- return <CollectionList collectionSlug={slug} config={config} onNavigate={navigate} />;
108
+ // Map of collection slug → definition. Used to:
109
+ // 1. Decide which editor (PageBuilder vs DocumentEdit) to render based
110
+ // on `collection.type === 'page'`.
111
+ // 2. Skip collections that collide with reserved admin paths so a
112
+ // consumer-defined collection named `users` can't hijack the Users
113
+ // view (or vice versa).
114
+ const collectionMap = useMemo(() => {
115
+ const map = new Map<string, { slug: string; type?: string }>();
116
+ if (config?.collections) {
117
+ for (const c of Object.values(config.collections as Record<string, { slug: string; type?: string }>)) {
118
+ if (c?.slug) map.set(c.slug, c);
126
119
  }
127
120
  }
128
-
129
- const newCollMatch = matchRoute('/collections/:slug/new');
130
- if (newCollMatch?.slug) {
131
- return <DocumentEdit collectionSlug={newCollMatch.slug} config={config} />;
121
+ if (map.size === 0) {
122
+ map.set('pages', { slug: 'pages', type: 'page' });
123
+ map.set('posts', { slug: 'posts' });
132
124
  }
125
+ return map;
126
+ }, [config]);
133
127
 
134
- const editCollMatch = matchRoute('/collections/:slug/:id');
135
- if (editCollMatch?.slug && editCollMatch.id) {
136
- return <DocumentEdit collectionSlug={editCollMatch.slug} documentId={editCollMatch.id} config={config} />;
128
+ function renderView() {
129
+ if (matchRoute('/')) {
130
+ return <Dashboard config={config} session={session} onNavigate={navigate} />;
137
131
  }
138
132
 
139
- const collectionMatch = matchRoute('/collections/:slug');
140
- if (collectionMatch?.slug) {
141
- return <CollectionList collectionSlug={collectionMatch.slug} config={config} onNavigate={navigate} />;
142
- }
133
+ // Reserved admin routes — must match BEFORE iterating collection slugs
134
+ // so they cannot be shadowed by a consumer-defined collection (e.g.
135
+ // a collection slugged `media`, `users`, or `settings`).
143
136
 
144
137
  if (matchRoute('/media')) {
145
138
  return <MediaBrowser onNavigate={navigate} />;
@@ -200,6 +193,66 @@ function AdminShell({ config, session, basePath = '/admin', initialPath = '/', s
200
193
  return <Settings onNavigate={navigate} config={config} />;
201
194
  }
202
195
 
196
+ // Page Builder routes — explicit /page-builder/* takes precedence over
197
+ // the collection-derived routing below, but we ALSO route a collection
198
+ // declared as `type: 'page'` through the Page Builder by default.
199
+ const pageBuilderNew = matchRoute('/page-builder/new');
200
+ if (pageBuilderNew) {
201
+ return <PageBuilder collectionSlug="pages" config={config} onNavigate={navigate} />;
202
+ }
203
+
204
+ const pageBuilderEdit = matchRoute('/page-builder/:id');
205
+ if (pageBuilderEdit?.id) {
206
+ return <PageBuilder documentId={pageBuilderEdit.id} collectionSlug="pages" config={config} onNavigate={navigate} />;
207
+ }
208
+
209
+ const RESERVED_SLUGS = new Set([
210
+ 'media', 'forms', 'seo', 'script-tags', 'saved-sections',
211
+ 'page-templates', 'users', 'settings', 'page-builder', 'collections',
212
+ ]);
213
+
214
+ for (const [slug, def] of collectionMap) {
215
+ if (RESERVED_SLUGS.has(slug)) continue;
216
+
217
+ const isPageType = def.type === 'page';
218
+ const newMatch = matchRoute(`/${slug}/new`);
219
+ if (newMatch) {
220
+ return isPageType
221
+ ? <PageBuilder collectionSlug={slug} config={config} onNavigate={navigate} />
222
+ : <DocumentEdit collectionSlug={slug} config={config} />;
223
+ }
224
+ const editMatch = matchRoute(`/${slug}/:id`);
225
+ if (editMatch?.id) {
226
+ return isPageType
227
+ ? <PageBuilder documentId={editMatch.id} collectionSlug={slug} config={config} onNavigate={navigate} />
228
+ : <DocumentEdit collectionSlug={slug} documentId={editMatch.id} config={config} />;
229
+ }
230
+ if (matchRoute(`/${slug}`)) {
231
+ return <CollectionList collectionSlug={slug} config={config} onNavigate={navigate} />;
232
+ }
233
+ }
234
+
235
+ const newCollMatch = matchRoute('/collections/:slug/new');
236
+ if (newCollMatch?.slug) {
237
+ const def = collectionMap.get(newCollMatch.slug);
238
+ return def?.type === 'page'
239
+ ? <PageBuilder collectionSlug={newCollMatch.slug} config={config} onNavigate={navigate} />
240
+ : <DocumentEdit collectionSlug={newCollMatch.slug} config={config} />;
241
+ }
242
+
243
+ const editCollMatch = matchRoute('/collections/:slug/:id');
244
+ if (editCollMatch?.slug && editCollMatch.id) {
245
+ const def = collectionMap.get(editCollMatch.slug);
246
+ return def?.type === 'page'
247
+ ? <PageBuilder documentId={editCollMatch.id} collectionSlug={editCollMatch.slug} config={config} onNavigate={navigate} />
248
+ : <DocumentEdit collectionSlug={editCollMatch.slug} documentId={editCollMatch.id} config={config} />;
249
+ }
250
+
251
+ const collectionMatch = matchRoute('/collections/:slug');
252
+ if (collectionMatch?.slug) {
253
+ return <CollectionList collectionSlug={collectionMatch.slug} config={config} onNavigate={navigate} />;
254
+ }
255
+
203
256
  return (
204
257
  <div className="flex flex-col items-center justify-center min-h-[400px] text-center p-6">
205
258
  <h1 className="text-4xl font-bold text-foreground mb-2">404</h1>
package/src/lib/api.ts CHANGED
@@ -12,11 +12,31 @@ function getCsrfToken(): string {
12
12
  return match?.[1] ?? '';
13
13
  }
14
14
 
15
+ /**
16
+ * Fetch a CSRF token if we don't have one in cookies yet. Used both as a
17
+ * one-shot bootstrap (e.g. on AdminRoot mount after a Server-Action login)
18
+ * and lazily inside `cmsApi` before mutating requests.
19
+ *
20
+ * Multiple concurrent callers share a single in-flight fetch via the
21
+ * `pendingFetch` cache so the admin doesn't fire N parallel `/auth/csrf`
22
+ * requests when a page lights up after navigation.
23
+ */
24
+ let pendingFetch: Promise<void> | null = null;
25
+
15
26
  export async function ensureCsrfToken(): Promise<void> {
16
27
  if (getCsrfToken()) return;
17
- try {
18
- await fetch(`${basePath}/auth/csrf`, { credentials: 'include' });
19
- } catch { /* best-effort */ }
28
+ if (pendingFetch) return pendingFetch;
29
+ pendingFetch = (async () => {
30
+ try {
31
+ await fetch(`${basePath}/auth/csrf`, { credentials: 'include' });
32
+ } catch {
33
+ // best-effort — caller will see the 403 from the actual mutation if
34
+ // the cookie still isn't set, instead of a silent network failure.
35
+ } finally {
36
+ pendingFetch = null;
37
+ }
38
+ })();
39
+ return pendingFetch;
20
40
  }
21
41
 
22
42
  function getActiveLocale(): string | null {
@@ -48,6 +68,14 @@ export async function cmsApi<T = unknown>(
48
68
 
49
69
  const method = (options.method ?? 'GET').toUpperCase();
50
70
  if (method !== 'GET' && method !== 'HEAD') {
71
+ // Bootstrap the CSRF cookie lazily — covers consumers that sign users
72
+ // in via a custom Server Action (the Next.js App Router pattern) where
73
+ // the admin never hits `/auth/login` directly and so never receives the
74
+ // cookie from the login response. Without this, the very first mutation
75
+ // after sign-in 403s.
76
+ if (!getCsrfToken()) {
77
+ await ensureCsrfToken();
78
+ }
51
79
  const csrf = getCsrfToken();
52
80
  if (csrf) headers['x-csrf-token'] = csrf;
53
81
  }