@actuate-media/cms-admin 0.9.0 → 0.11.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/AdminRoot.d.ts.map +1 -1
- package/dist/AdminRoot.js +8 -5
- package/dist/AdminRoot.js.map +1 -1
- package/dist/__tests__/layout/primitives.test.d.ts +2 -0
- package/dist/__tests__/layout/primitives.test.d.ts.map +1 -0
- package/dist/__tests__/layout/primitives.test.js +34 -0
- package/dist/__tests__/layout/primitives.test.js.map +1 -0
- package/dist/__tests__/lib/cv.test.d.ts +2 -0
- package/dist/__tests__/lib/cv.test.d.ts.map +1 -0
- package/dist/__tests__/lib/cv.test.js +66 -0
- package/dist/__tests__/lib/cv.test.js.map +1 -0
- package/dist/actuate-admin.css +1 -1
- package/dist/assets/actuate-logo.d.ts +36 -0
- package/dist/assets/actuate-logo.d.ts.map +1 -0
- package/dist/assets/actuate-logo.js +15 -0
- package/dist/assets/actuate-logo.js.map +1 -0
- package/dist/components/Breadcrumbs.js +2 -2
- package/dist/components/CommandPalette.js +10 -10
- package/dist/components/ContentOverviewChart.js +3 -3
- package/dist/components/ErrorBoundary.js +1 -1
- package/dist/components/FocalPointPicker.js +2 -2
- package/dist/components/FolderTree.js +20 -20
- package/dist/components/LivePreview.js +3 -3
- package/dist/components/LocaleSwitcher.js +1 -1
- package/dist/components/MediaPickerModal.js +4 -4
- package/dist/components/PresenceIndicator.js +1 -1
- package/dist/components/SEOConfigPanel.d.ts +2 -0
- package/dist/components/SEOConfigPanel.d.ts.map +1 -0
- package/dist/components/SEOConfigPanel.js +174 -0
- package/dist/components/SEOConfigPanel.js.map +1 -0
- package/dist/components/SEOPanel.js +9 -9
- package/dist/components/SEOPerformance.js +2 -2
- package/dist/components/SchedulePublishDialog.d.ts +18 -0
- package/dist/components/SchedulePublishDialog.d.ts.map +1 -0
- package/dist/components/SchedulePublishDialog.js +106 -0
- package/dist/components/SchedulePublishDialog.js.map +1 -0
- package/dist/components/SharePreviewLinkDialog.d.ts +17 -0
- package/dist/components/SharePreviewLinkDialog.d.ts.map +1 -0
- package/dist/components/SharePreviewLinkDialog.js +83 -0
- package/dist/components/SharePreviewLinkDialog.js.map +1 -0
- package/dist/components/TipTapEditor.js +5 -5
- package/dist/components/VersionHistory.js +2 -2
- package/dist/components/ui/Badge.d.ts +33 -3
- package/dist/components/ui/Badge.d.ts.map +1 -1
- package/dist/components/ui/Badge.js +42 -8
- package/dist/components/ui/Badge.js.map +1 -1
- package/dist/components/ui/Button.d.ts +19 -8
- package/dist/components/ui/Button.d.ts.map +1 -1
- package/dist/components/ui/Button.js +35 -14
- package/dist/components/ui/Button.js.map +1 -1
- package/dist/components/ui/Card.d.ts +26 -0
- package/dist/components/ui/Card.d.ts.map +1 -0
- package/dist/components/ui/Card.js +45 -0
- package/dist/components/ui/Card.js.map +1 -0
- package/dist/components/ui/DataTable.js +1 -1
- package/dist/components/ui/Input.d.ts +15 -0
- package/dist/components/ui/Input.d.ts.map +1 -0
- package/dist/components/ui/Input.js +23 -0
- package/dist/components/ui/Input.js.map +1 -0
- package/dist/components/ui/SearchInput.js +1 -1
- package/dist/components/ui/Select.d.ts +16 -0
- package/dist/components/ui/Select.d.ts.map +1 -0
- package/dist/components/ui/Select.js +25 -0
- package/dist/components/ui/Select.js.map +1 -0
- package/dist/components/ui/Toast.js +1 -1
- package/dist/components/ui/index.d.ts +10 -4
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +5 -2
- package/dist/components/ui/index.js.map +1 -1
- package/dist/fields/BlockBuilderField.js +3 -3
- package/dist/fields/DateField.js +1 -1
- package/dist/fields/RelationshipField.js +3 -3
- package/dist/fields/TextField.js +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/layout/Header.js +1 -1
- package/dist/layout/Layout.d.ts +14 -0
- package/dist/layout/Layout.d.ts.map +1 -1
- package/dist/layout/Layout.js +17 -11
- package/dist/layout/Layout.js.map +1 -1
- package/dist/layout/Sidebar.d.ts.map +1 -1
- package/dist/layout/Sidebar.js +21 -11
- package/dist/layout/Sidebar.js.map +1 -1
- package/dist/layout/primitives/AdminShell.d.ts +43 -0
- package/dist/layout/primitives/AdminShell.d.ts.map +1 -0
- package/dist/layout/primitives/AdminShell.js +51 -0
- package/dist/layout/primitives/AdminShell.js.map +1 -0
- package/dist/layout/primitives/Box.d.ts +19 -0
- package/dist/layout/primitives/Box.d.ts.map +1 -0
- package/dist/layout/primitives/Box.js +12 -0
- package/dist/layout/primitives/Box.js.map +1 -0
- package/dist/layout/primitives/Cluster.d.ts +27 -0
- package/dist/layout/primitives/Cluster.d.ts.map +1 -0
- package/dist/layout/primitives/Cluster.js +37 -0
- package/dist/layout/primitives/Cluster.js.map +1 -0
- package/dist/layout/primitives/Grid.d.ts +45 -0
- package/dist/layout/primitives/Grid.d.ts.map +1 -0
- package/dist/layout/primitives/Grid.js +59 -0
- package/dist/layout/primitives/Grid.js.map +1 -0
- package/dist/layout/primitives/PageContainer.d.ts +36 -0
- package/dist/layout/primitives/PageContainer.d.ts.map +1 -0
- package/dist/layout/primitives/PageContainer.js +41 -0
- package/dist/layout/primitives/PageContainer.js.map +1 -0
- package/dist/layout/primitives/Split.d.ts +34 -0
- package/dist/layout/primitives/Split.d.ts.map +1 -0
- package/dist/layout/primitives/Split.js +27 -0
- package/dist/layout/primitives/Split.js.map +1 -0
- package/dist/layout/primitives/Stack.d.ts +23 -0
- package/dist/layout/primitives/Stack.d.ts.map +1 -0
- package/dist/layout/primitives/Stack.js +34 -0
- package/dist/layout/primitives/Stack.js.map +1 -0
- package/dist/layout/primitives/index.d.ts +30 -0
- package/dist/layout/primitives/index.d.ts.map +1 -0
- package/dist/layout/primitives/index.js +22 -0
- package/dist/layout/primitives/index.js.map +1 -0
- package/dist/layout/primitives/tokens.d.ts +48 -0
- package/dist/layout/primitives/tokens.d.ts.map +1 -0
- package/dist/layout/primitives/tokens.js +54 -0
- package/dist/layout/primitives/tokens.js.map +1 -0
- package/dist/lib/cv.d.ts +53 -0
- package/dist/lib/cv.d.ts.map +1 -0
- package/dist/lib/cv.js +39 -0
- package/dist/lib/cv.js.map +1 -0
- package/dist/views/ApiKeys.d.ts.map +1 -1
- package/dist/views/ApiKeys.js +13 -11
- package/dist/views/ApiKeys.js.map +1 -1
- package/dist/views/CollectionList.js +8 -8
- package/dist/views/Dashboard.d.ts.map +1 -1
- package/dist/views/Dashboard.js +333 -78
- package/dist/views/Dashboard.js.map +1 -1
- package/dist/views/DocumentEdit.d.ts.map +1 -1
- package/dist/views/DocumentEdit.js +17 -5
- package/dist/views/DocumentEdit.js.map +1 -1
- package/dist/views/ForgotPassword.js +2 -2
- package/dist/views/FormEditor.js +5 -5
- package/dist/views/FormSubmissions.js +6 -6
- package/dist/views/Forms.js +2 -2
- package/dist/views/Login.d.ts +16 -1
- package/dist/views/Login.d.ts.map +1 -1
- package/dist/views/Login.js +17 -7
- package/dist/views/Login.js.map +1 -1
- package/dist/views/MediaBrowser.js +16 -16
- package/dist/views/PageEditor.js +2 -2
- package/dist/views/Pages.js +10 -10
- package/dist/views/PostEditor.js +2 -2
- package/dist/views/Posts.js +4 -4
- package/dist/views/Redirects.js +4 -4
- package/dist/views/ResetPassword.js +2 -2
- package/dist/views/SEO.js +6 -6
- package/dist/views/ScriptTagEditor.js +4 -4
- package/dist/views/ScriptTags.js +2 -2
- package/dist/views/Settings.d.ts.map +1 -1
- package/dist/views/Settings.js +9 -8
- package/dist/views/Settings.js.map +1 -1
- package/dist/views/SetupWizard.js +2 -2
- package/dist/views/Users.js +4 -4
- package/dist/views/page-builder/AIBlockAssist.js +1 -1
- package/dist/views/page-builder/AIGenerateDialog.js +10 -10
- package/dist/views/page-builder/BlockEditor.js +10 -10
- package/dist/views/page-builder/BlockPicker.js +4 -4
- package/dist/views/page-builder/BottomBar.js +1 -1
- package/dist/views/page-builder/BuilderToolbar.js +2 -2
- package/dist/views/page-builder/ContextPanel.js +2 -2
- package/dist/views/page-builder/DesignScore.js +9 -9
- package/dist/views/page-builder/NodeSettings.js +8 -8
- package/dist/views/page-builder/PageBuilder.js +3 -3
- package/dist/views/page-builder/PageSettings.js +1 -1
- package/dist/views/page-builder/PageTemplates.js +2 -2
- package/dist/views/page-builder/SEOPanel.js +13 -13
- package/dist/views/page-builder/SavedSections.js +5 -5
- package/dist/views/page-builder/TemplatePicker.js +2 -2
- package/dist/views/page-builder/block-renderers/CTAPreview.js +5 -5
- package/dist/views/page-builder/block-renderers/CardsPreview.js +1 -1
- package/dist/views/page-builder/block-renderers/CodePreview.js +1 -1
- package/dist/views/page-builder/block-renderers/FAQPreview.js +3 -3
- package/dist/views/page-builder/block-renderers/FallbackPreview.js +1 -1
- package/dist/views/page-builder/block-renderers/FormPreview.js +3 -3
- package/dist/views/page-builder/block-renderers/GalleryPreview.js +5 -5
- package/dist/views/page-builder/block-renderers/HeroPreview.js +3 -3
- package/dist/views/page-builder/block-renderers/ImagePreview.js +3 -3
- package/dist/views/page-builder/block-renderers/TextPreview.js +3 -3
- package/dist/views/page-builder/block-renderers/VideoPreview.js +4 -4
- package/dist/views/page-builder/canvas/BlockRenderer.js +1 -1
- package/dist/views/page-builder/canvas/BuilderCanvas.js +3 -3
- package/dist/views/page-builder/canvas/ColumnRenderer.js +2 -2
- package/dist/views/page-builder/canvas/ContainerRenderer.js +2 -2
- package/dist/views/page-builder/canvas/RowRenderer.js +2 -2
- package/dist/views/page-builder/canvas/SectionRenderer.js +2 -2
- package/package.json +6 -2
- package/src/AdminRoot.tsx +21 -11
- package/src/__tests__/layout/primitives.test.ts +37 -0
- package/src/__tests__/lib/cv.test.ts +74 -0
- package/src/assets/actuate-logo.tsx +72 -0
- package/src/components/Breadcrumbs.tsx +6 -6
- package/src/components/CommandPalette.tsx +34 -34
- package/src/components/ContentOverviewChart.tsx +3 -3
- package/src/components/ErrorBoundary.tsx +3 -3
- package/src/components/FocalPointPicker.tsx +4 -4
- package/src/components/FolderTree.tsx +38 -38
- package/src/components/LivePreview.tsx +16 -16
- package/src/components/LocaleSwitcher.tsx +7 -7
- package/src/components/MediaPickerModal.tsx +21 -21
- package/src/components/PresenceIndicator.tsx +2 -2
- package/src/components/SEOConfigPanel.tsx +582 -0
- package/src/components/SEOPanel.tsx +46 -46
- package/src/components/SEOPerformance.tsx +21 -21
- package/src/components/SchedulePublishDialog.tsx +241 -0
- package/src/components/SharePreviewLinkDialog.tsx +227 -0
- package/src/components/TipTapEditor.tsx +33 -33
- package/src/components/VersionHistory.tsx +16 -16
- package/src/components/ui/Badge.tsx +66 -14
- package/src/components/ui/Button.tsx +70 -33
- package/src/components/ui/Card.tsx +101 -0
- package/src/components/ui/DataTable.tsx +1 -1
- package/src/components/ui/Input.tsx +35 -0
- package/src/components/ui/SearchInput.tsx +4 -4
- package/src/components/ui/Select.tsx +56 -0
- package/src/components/ui/Toast.tsx +1 -1
- package/src/components/ui/index.ts +18 -4
- package/src/fields/BlockBuilderField.tsx +3 -3
- package/src/fields/DateField.tsx +1 -1
- package/src/fields/RelationshipField.tsx +10 -10
- package/src/fields/TextField.tsx +1 -1
- package/src/index.ts +32 -0
- package/src/layout/Header.tsx +28 -28
- package/src/layout/Layout.tsx +39 -46
- package/src/layout/Sidebar.tsx +37 -64
- package/src/layout/primitives/AdminShell.tsx +118 -0
- package/src/layout/primitives/Box.tsx +30 -0
- package/src/layout/primitives/Cluster.tsx +74 -0
- package/src/layout/primitives/Grid.tsx +120 -0
- package/src/layout/primitives/PageContainer.tsx +96 -0
- package/src/layout/primitives/Split.tsx +73 -0
- package/src/layout/primitives/Stack.tsx +67 -0
- package/src/layout/primitives/index.ts +36 -0
- package/src/layout/primitives/tokens.ts +76 -0
- package/src/lib/cv.ts +96 -0
- package/src/styles/build-input.css +1 -1
- package/src/views/ApiKeys.tsx +57 -57
- package/src/views/CollectionList.tsx +30 -30
- package/src/views/Dashboard.tsx +737 -186
- package/src/views/DocumentEdit.tsx +90 -10
- package/src/views/ForgotPassword.tsx +18 -18
- package/src/views/FormEditor.tsx +75 -75
- package/src/views/FormSubmissions.tsx +76 -76
- package/src/views/Forms.tsx +27 -27
- package/src/views/Login.tsx +65 -25
- package/src/views/MediaBrowser.tsx +127 -127
- package/src/views/PageEditor.tsx +25 -25
- package/src/views/Pages.tsx +59 -59
- package/src/views/PostEditor.tsx +37 -37
- package/src/views/Posts.tsx +48 -48
- package/src/views/Redirects.tsx +21 -21
- package/src/views/ResetPassword.tsx +28 -28
- package/src/views/SEO.tsx +144 -144
- package/src/views/ScriptTagEditor.tsx +24 -24
- package/src/views/ScriptTags.tsx +10 -10
- package/src/views/Settings.tsx +88 -80
- package/src/views/SetupWizard.tsx +28 -28
- package/src/views/Users.tsx +20 -20
- package/src/views/page-builder/AIBlockAssist.tsx +1 -1
- package/src/views/page-builder/AIGenerateDialog.tsx +63 -63
- package/src/views/page-builder/BlockEditor.tsx +26 -26
- package/src/views/page-builder/BlockPicker.tsx +22 -22
- package/src/views/page-builder/BottomBar.tsx +8 -8
- package/src/views/page-builder/BuilderToolbar.tsx +17 -17
- package/src/views/page-builder/ContextPanel.tsx +3 -3
- package/src/views/page-builder/DesignScore.tsx +21 -21
- package/src/views/page-builder/NodeSettings.tsx +27 -27
- package/src/views/page-builder/PageBuilder.tsx +11 -11
- package/src/views/page-builder/PageSettings.tsx +4 -4
- package/src/views/page-builder/PageTemplates.tsx +18 -18
- package/src/views/page-builder/SEOPanel.tsx +53 -53
- package/src/views/page-builder/SavedSections.tsx +37 -37
- package/src/views/page-builder/TemplatePicker.tsx +17 -17
- package/src/views/page-builder/block-renderers/CTAPreview.tsx +13 -13
- package/src/views/page-builder/block-renderers/CardsPreview.tsx +5 -5
- package/src/views/page-builder/block-renderers/CodePreview.tsx +6 -6
- package/src/views/page-builder/block-renderers/FAQPreview.tsx +13 -13
- package/src/views/page-builder/block-renderers/FallbackPreview.tsx +3 -3
- package/src/views/page-builder/block-renderers/FormPreview.tsx +20 -20
- package/src/views/page-builder/block-renderers/GalleryPreview.tsx +8 -8
- package/src/views/page-builder/block-renderers/HeroPreview.tsx +16 -16
- package/src/views/page-builder/block-renderers/ImagePreview.tsx +4 -4
- package/src/views/page-builder/block-renderers/TextPreview.tsx +14 -14
- package/src/views/page-builder/block-renderers/VideoPreview.tsx +12 -12
- package/src/views/page-builder/canvas/BlockRenderer.tsx +4 -4
- package/src/views/page-builder/canvas/BuilderCanvas.tsx +6 -6
- package/src/views/page-builder/canvas/ColumnRenderer.tsx +3 -3
- package/src/views/page-builder/canvas/ContainerRenderer.tsx +2 -2
- package/src/views/page-builder/canvas/RowRenderer.tsx +2 -2
- package/src/views/page-builder/canvas/SectionRenderer.tsx +2 -2
|
@@ -127,9 +127,9 @@ export function BlockPicker({ open, onClose, onSelect }: BlockPickerProps) {
|
|
|
127
127
|
return (
|
|
128
128
|
<Dialog.Root open={open} onOpenChange={(isOpen) => !isOpen && onClose()}>
|
|
129
129
|
<Dialog.Portal>
|
|
130
|
-
<Dialog.Overlay className="
|
|
130
|
+
<Dialog.Overlay className="motion-safe:animate-in motion-safe:fade-in-0 fixed inset-0 z-50 bg-black/50" />
|
|
131
131
|
<Dialog.Content
|
|
132
|
-
className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2
|
|
132
|
+
className="bg-card border-border fixed top-1/2 left-1/2 z-50 flex max-h-[80vh] w-full max-w-2xl -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl border shadow-2xl"
|
|
133
133
|
aria-describedby={undefined}
|
|
134
134
|
onEscapeKeyDown={() => {
|
|
135
135
|
if (selectedBlock) {
|
|
@@ -182,13 +182,13 @@ function BlockTypeGrid({
|
|
|
182
182
|
onKeyDown,
|
|
183
183
|
}: BlockTypeGridProps) {
|
|
184
184
|
return (
|
|
185
|
-
<div className="flex flex-col
|
|
185
|
+
<div className="flex h-full flex-col" onKeyDown={onKeyDown}>
|
|
186
186
|
<div className="flex items-center justify-between gap-3 px-5 pt-5 pb-3">
|
|
187
|
-
<Dialog.Title className="text-lg font-medium
|
|
187
|
+
<Dialog.Title className="text-foreground text-lg font-medium">Add Block</Dialog.Title>
|
|
188
188
|
<Dialog.Close asChild>
|
|
189
189
|
<button
|
|
190
190
|
type="button"
|
|
191
|
-
className="
|
|
191
|
+
className="text-muted-foreground hover:text-foreground hover:bg-accent rounded-md p-1.5 transition-colors"
|
|
192
192
|
aria-label="Close"
|
|
193
193
|
>
|
|
194
194
|
<X size={18} />
|
|
@@ -199,7 +199,7 @@ function BlockTypeGrid({
|
|
|
199
199
|
<div className="px-5 pb-3">
|
|
200
200
|
<div className="relative">
|
|
201
201
|
<Search
|
|
202
|
-
className="
|
|
202
|
+
className="text-muted-foreground pointer-events-none absolute top-1/2 left-3 -translate-y-1/2"
|
|
203
203
|
size={16}
|
|
204
204
|
/>
|
|
205
205
|
<input
|
|
@@ -208,7 +208,7 @@ function BlockTypeGrid({
|
|
|
208
208
|
placeholder="Search blocks..."
|
|
209
209
|
value={search}
|
|
210
210
|
onChange={(e) => onSearchChange(e.target.value)}
|
|
211
|
-
className="
|
|
211
|
+
className="bg-background border-input focus:ring-ring w-full rounded-md border py-2 pr-3 pl-9 text-sm focus:ring-2 focus:outline-none"
|
|
212
212
|
aria-label="Search block types"
|
|
213
213
|
/>
|
|
214
214
|
</div>
|
|
@@ -218,7 +218,7 @@ function BlockTypeGrid({
|
|
|
218
218
|
{filteredBlocks.length === 0 ? (
|
|
219
219
|
<div className="flex flex-col items-center justify-center py-12 text-center">
|
|
220
220
|
<Search size={24} className="text-muted-foreground mb-2" />
|
|
221
|
-
<p className="text-
|
|
221
|
+
<p className="text-muted-foreground text-sm">No blocks match “{search}”</p>
|
|
222
222
|
</div>
|
|
223
223
|
) : (
|
|
224
224
|
<div className="grid grid-cols-2 gap-3" role="list" aria-label="Available block types">
|
|
@@ -230,15 +230,15 @@ function BlockTypeGrid({
|
|
|
230
230
|
type="button"
|
|
231
231
|
role="listitem"
|
|
232
232
|
onClick={() => onBlockClick(block)}
|
|
233
|
-
className="
|
|
233
|
+
className="border-border hover:border-primary bg-card group focus:ring-ring flex cursor-pointer items-start gap-3 rounded-lg border p-4 text-left transition-colors focus:ring-2 focus:outline-none"
|
|
234
234
|
>
|
|
235
|
-
<div className="
|
|
235
|
+
<div className="bg-accent text-foreground group-hover:bg-primary/10 group-hover:text-primary flex h-9 w-9 shrink-0 items-center justify-center rounded-md transition-colors">
|
|
236
236
|
<Icon size={18} />
|
|
237
237
|
</div>
|
|
238
238
|
<div className="min-w-0">
|
|
239
|
-
<p className="text-sm font-medium
|
|
239
|
+
<p className="text-foreground truncate text-sm font-medium">{block.label}</p>
|
|
240
240
|
{block.description && (
|
|
241
|
-
<p className="text-
|
|
241
|
+
<p className="text-muted-foreground mt-0.5 line-clamp-2 text-xs">
|
|
242
242
|
{block.description}
|
|
243
243
|
</p>
|
|
244
244
|
)}
|
|
@@ -271,24 +271,24 @@ function VariantView({
|
|
|
271
271
|
const Icon = resolveIcon(block.icon)
|
|
272
272
|
|
|
273
273
|
return (
|
|
274
|
-
<div className="flex flex-col
|
|
274
|
+
<div className="flex h-full flex-col" onKeyDown={onKeyDown}>
|
|
275
275
|
<div className="flex items-center gap-3 px-5 pt-5 pb-3">
|
|
276
276
|
<button
|
|
277
277
|
type="button"
|
|
278
278
|
onClick={onBack}
|
|
279
|
-
className="
|
|
279
|
+
className="text-muted-foreground hover:text-foreground hover:bg-accent rounded-md p-1.5 transition-colors"
|
|
280
280
|
aria-label="Back to block types"
|
|
281
281
|
>
|
|
282
282
|
<ArrowLeft size={18} />
|
|
283
283
|
</button>
|
|
284
|
-
<div className="flex items-center gap-2
|
|
284
|
+
<div className="flex min-w-0 items-center gap-2">
|
|
285
285
|
<Icon size={18} className="text-foreground shrink-0" />
|
|
286
|
-
<h2 className="text-lg font-medium
|
|
286
|
+
<h2 className="text-foreground truncate text-lg font-medium">{block.label}</h2>
|
|
287
287
|
</div>
|
|
288
288
|
</div>
|
|
289
289
|
|
|
290
290
|
{block.description && (
|
|
291
|
-
<p className="text-
|
|
291
|
+
<p className="text-muted-foreground px-5 pb-3 text-sm">{block.description}</p>
|
|
292
292
|
)}
|
|
293
293
|
|
|
294
294
|
<div className="flex-1 overflow-y-auto px-5 pb-5" ref={variantListRef}>
|
|
@@ -300,19 +300,19 @@ function VariantView({
|
|
|
300
300
|
role="listitem"
|
|
301
301
|
data-variant={variant.name}
|
|
302
302
|
onClick={() => onVariantClick(variant)}
|
|
303
|
-
className="
|
|
303
|
+
className="border-border hover:border-primary bg-card group focus:ring-ring flex w-full cursor-pointer items-center gap-3 rounded-lg border p-4 text-left transition-colors focus:ring-2 focus:outline-none"
|
|
304
304
|
>
|
|
305
|
-
<div className="
|
|
305
|
+
<div className="min-w-0 flex-1">
|
|
306
306
|
<div className="flex items-center gap-2">
|
|
307
|
-
<p className="text-sm font-medium
|
|
307
|
+
<p className="text-foreground text-sm font-medium">{variant.label}</p>
|
|
308
308
|
{index === 0 && (
|
|
309
|
-
<span className="inline-flex items-center gap-1
|
|
309
|
+
<span className="text-primary bg-primary/10 inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs">
|
|
310
310
|
<Check size={10} />
|
|
311
311
|
Default
|
|
312
312
|
</span>
|
|
313
313
|
)}
|
|
314
314
|
</div>
|
|
315
|
-
<p className="text-
|
|
315
|
+
<p className="text-muted-foreground mt-0.5 text-xs">{variant.description}</p>
|
|
316
316
|
</div>
|
|
317
317
|
</button>
|
|
318
318
|
))}
|
|
@@ -25,14 +25,14 @@ export function BottomBar({
|
|
|
25
25
|
}: BottomBarProps) {
|
|
26
26
|
return (
|
|
27
27
|
<div
|
|
28
|
-
className="
|
|
28
|
+
className="bg-card border-border flex h-10 shrink-0 items-center gap-4 border-t px-4"
|
|
29
29
|
role="toolbar"
|
|
30
30
|
aria-label="Builder actions"
|
|
31
31
|
>
|
|
32
32
|
{/* Add Section */}
|
|
33
33
|
<button
|
|
34
34
|
onClick={onAddSection}
|
|
35
|
-
className="flex items-center gap-1.5 px-3 py-2 text-sm
|
|
35
|
+
className="text-muted-foreground hover:text-foreground flex items-center gap-1.5 px-3 py-2 text-sm transition-colors"
|
|
36
36
|
aria-label="Add a new section"
|
|
37
37
|
>
|
|
38
38
|
<Plus size={14} />
|
|
@@ -40,27 +40,27 @@ export function BottomBar({
|
|
|
40
40
|
</button>
|
|
41
41
|
|
|
42
42
|
{/* Divider */}
|
|
43
|
-
<div className="
|
|
43
|
+
<div className="bg-border h-5 w-px" />
|
|
44
44
|
|
|
45
45
|
{/* Grid overlay toggle */}
|
|
46
|
-
<label className="flex items-center gap-2
|
|
46
|
+
<label className="flex cursor-pointer items-center gap-2">
|
|
47
47
|
<Grid3X3 size={14} className="text-muted-foreground" />
|
|
48
48
|
<Switch.Root
|
|
49
49
|
checked={showGridOverlay}
|
|
50
50
|
onCheckedChange={onToggleGrid}
|
|
51
|
-
className="
|
|
51
|
+
className="bg-input-background data-[state=checked]:bg-primary relative h-[18px] w-8 rounded-full transition-colors"
|
|
52
52
|
aria-label="Toggle grid overlay"
|
|
53
53
|
>
|
|
54
|
-
<Switch.Thumb className="block
|
|
54
|
+
<Switch.Thumb className="bg-background block h-3.5 w-3.5 translate-x-0.5 rounded-full shadow-sm transition-transform data-[state=checked]:translate-x-[14px]" />
|
|
55
55
|
</Switch.Root>
|
|
56
|
-
<span className="text-
|
|
56
|
+
<span className="text-muted-foreground text-xs">Grid</span>
|
|
57
57
|
</label>
|
|
58
58
|
|
|
59
59
|
{/* Spacer */}
|
|
60
60
|
<div className="flex-1" />
|
|
61
61
|
|
|
62
62
|
{/* Zoom / device width display */}
|
|
63
|
-
<span className="text-
|
|
63
|
+
<span className="text-muted-foreground text-xs tabular-nums">
|
|
64
64
|
{DEVICE_LABELS[deviceMode]}
|
|
65
65
|
</span>
|
|
66
66
|
</div>
|
|
@@ -59,14 +59,14 @@ export function BuilderToolbar({
|
|
|
59
59
|
|
|
60
60
|
return (
|
|
61
61
|
<div
|
|
62
|
-
className="
|
|
62
|
+
className="bg-card border-border flex h-14 shrink-0 items-center gap-3 border-b px-4"
|
|
63
63
|
role="toolbar"
|
|
64
64
|
aria-label="Page builder toolbar"
|
|
65
65
|
>
|
|
66
66
|
{/* Back button */}
|
|
67
67
|
<button
|
|
68
68
|
onClick={() => onNavigate(`/collections/${collectionSlug}`)}
|
|
69
|
-
className="flex items-center gap-1 text-sm
|
|
69
|
+
className="text-muted-foreground hover:text-foreground flex items-center gap-1 text-sm transition-colors"
|
|
70
70
|
aria-label={`Back to ${collectionLabel}`}
|
|
71
71
|
>
|
|
72
72
|
<ChevronLeft size={16} />
|
|
@@ -74,7 +74,7 @@ export function BuilderToolbar({
|
|
|
74
74
|
</button>
|
|
75
75
|
|
|
76
76
|
{/* Divider */}
|
|
77
|
-
<div className="
|
|
77
|
+
<div className="bg-border h-6 w-px" />
|
|
78
78
|
|
|
79
79
|
{/* Page title */}
|
|
80
80
|
<input
|
|
@@ -82,13 +82,13 @@ export function BuilderToolbar({
|
|
|
82
82
|
value={pageSettings.title}
|
|
83
83
|
onChange={(e) => onTitleChange(e.target.value)}
|
|
84
84
|
placeholder="Untitled Page"
|
|
85
|
-
className="
|
|
85
|
+
className="text-foreground focus-visible:ring-ring placeholder:text-muted-foreground min-w-0 flex-1 rounded-sm border-none bg-transparent text-sm font-medium outline-none focus-visible:ring-2 focus-visible:ring-offset-2"
|
|
86
86
|
aria-label="Page title"
|
|
87
87
|
/>
|
|
88
88
|
|
|
89
89
|
{/* Status badge */}
|
|
90
90
|
<span
|
|
91
|
-
className={`
|
|
91
|
+
className={`rounded-md px-2 py-0.5 text-xs font-medium whitespace-nowrap ${STATUS_STYLES[status] ?? STATUS_STYLES.DRAFT}`}
|
|
92
92
|
>
|
|
93
93
|
{status}
|
|
94
94
|
</span>
|
|
@@ -96,21 +96,21 @@ export function BuilderToolbar({
|
|
|
96
96
|
{/* Unsaved indicator */}
|
|
97
97
|
{dirty && !saving && (
|
|
98
98
|
<span
|
|
99
|
-
className="
|
|
99
|
+
className="bg-destructive h-2 w-2 shrink-0 rounded-full"
|
|
100
100
|
title="Unsaved changes"
|
|
101
101
|
aria-label="Unsaved changes"
|
|
102
102
|
/>
|
|
103
103
|
)}
|
|
104
104
|
|
|
105
105
|
{/* Divider */}
|
|
106
|
-
<div className="
|
|
106
|
+
<div className="bg-border h-6 w-px" />
|
|
107
107
|
|
|
108
108
|
{/* Undo / Redo */}
|
|
109
109
|
<div className="flex items-center gap-1">
|
|
110
110
|
<button
|
|
111
111
|
onClick={onUndo}
|
|
112
112
|
disabled={!canUndo}
|
|
113
|
-
className="
|
|
113
|
+
className="text-muted-foreground hover:text-foreground hover:bg-muted rounded-md p-1.5 transition-colors disabled:pointer-events-none disabled:opacity-30"
|
|
114
114
|
aria-label="Undo"
|
|
115
115
|
>
|
|
116
116
|
<Undo2 size={16} />
|
|
@@ -118,7 +118,7 @@ export function BuilderToolbar({
|
|
|
118
118
|
<button
|
|
119
119
|
onClick={onRedo}
|
|
120
120
|
disabled={!canRedo}
|
|
121
|
-
className="
|
|
121
|
+
className="text-muted-foreground hover:text-foreground hover:bg-muted rounded-md p-1.5 transition-colors disabled:pointer-events-none disabled:opacity-30"
|
|
122
122
|
aria-label="Redo"
|
|
123
123
|
>
|
|
124
124
|
<Redo2 size={16} />
|
|
@@ -126,10 +126,10 @@ export function BuilderToolbar({
|
|
|
126
126
|
</div>
|
|
127
127
|
|
|
128
128
|
{/* Divider */}
|
|
129
|
-
<div className="
|
|
129
|
+
<div className="bg-border h-6 w-px" />
|
|
130
130
|
|
|
131
131
|
{/* Device toggle */}
|
|
132
|
-
<div className="flex items-center gap-0.5
|
|
132
|
+
<div className="bg-muted flex items-center gap-0.5 rounded-md p-0.5">
|
|
133
133
|
<DeviceButton
|
|
134
134
|
active={deviceMode === 'desktop'}
|
|
135
135
|
onClick={() => onDeviceMode('desktop')}
|
|
@@ -154,20 +154,20 @@ export function BuilderToolbar({
|
|
|
154
154
|
</div>
|
|
155
155
|
|
|
156
156
|
{/* Divider */}
|
|
157
|
-
<div className="
|
|
157
|
+
<div className="bg-border h-6 w-px" />
|
|
158
158
|
|
|
159
159
|
{/* AI Generate */}
|
|
160
160
|
{onOpenAI && (
|
|
161
161
|
<>
|
|
162
162
|
<button
|
|
163
163
|
onClick={onOpenAI}
|
|
164
|
-
className="flex items-center gap-1.5 px-2.5 py-1.5 text-sm font-medium
|
|
164
|
+
className="text-primary bg-primary/10 hover:bg-primary/20 flex items-center gap-1.5 rounded-md px-2.5 py-1.5 text-sm font-medium transition-colors"
|
|
165
165
|
aria-label="Generate page with AI"
|
|
166
166
|
>
|
|
167
167
|
<Sparkles size={14} />
|
|
168
168
|
<span className="hidden sm:inline">AI</span>
|
|
169
169
|
</button>
|
|
170
|
-
<div className="
|
|
170
|
+
<div className="bg-border h-6 w-px" />
|
|
171
171
|
</>
|
|
172
172
|
)}
|
|
173
173
|
|
|
@@ -176,7 +176,7 @@ export function BuilderToolbar({
|
|
|
176
176
|
<button
|
|
177
177
|
onClick={onSave}
|
|
178
178
|
disabled={saving || !dirty}
|
|
179
|
-
className="bg-muted text-muted-foreground rounded-md px-3 py-1.5 text-sm font-medium
|
|
179
|
+
className="bg-muted text-muted-foreground hover:bg-muted/80 flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors disabled:pointer-events-none disabled:opacity-50"
|
|
180
180
|
>
|
|
181
181
|
{saving && <Loader2 size={14} className="animate-spin" />}
|
|
182
182
|
{saving ? 'Saving...' : 'Save'}
|
|
@@ -184,7 +184,7 @@ export function BuilderToolbar({
|
|
|
184
184
|
<button
|
|
185
185
|
onClick={onPublish}
|
|
186
186
|
disabled={saving}
|
|
187
|
-
className="bg-primary text-primary-foreground rounded-md px-3 py-1.5 text-sm font-medium
|
|
187
|
+
className="bg-primary text-primary-foreground hover:bg-primary/90 rounded-md px-3 py-1.5 text-sm font-medium transition-colors disabled:pointer-events-none disabled:opacity-50"
|
|
188
188
|
>
|
|
189
189
|
Publish
|
|
190
190
|
</button>
|
|
@@ -207,7 +207,7 @@ function DeviceButton({
|
|
|
207
207
|
return (
|
|
208
208
|
<button
|
|
209
209
|
onClick={onClick}
|
|
210
|
-
className={`p-1.5
|
|
210
|
+
className={`rounded-md p-1.5 transition-colors ${
|
|
211
211
|
active
|
|
212
212
|
? 'bg-background text-foreground shadow-sm'
|
|
213
213
|
: 'text-muted-foreground hover:text-foreground'
|
|
@@ -72,19 +72,19 @@ export function ContextPanel({
|
|
|
72
72
|
}, [activeTab, availableTabs, selectedNode])
|
|
73
73
|
|
|
74
74
|
return (
|
|
75
|
-
<div className="
|
|
75
|
+
<div className="bg-card h-full w-full overflow-y-auto">
|
|
76
76
|
<Tabs.Root
|
|
77
77
|
value={effectiveTab}
|
|
78
78
|
onValueChange={(value) => onTabChange(value as ContextPanelProps['activeTab'])}
|
|
79
79
|
>
|
|
80
|
-
<Tabs.List className="
|
|
80
|
+
<Tabs.List className="border-border bg-muted/30 flex border-b">
|
|
81
81
|
{availableTabs.map((tab) => {
|
|
82
82
|
const Icon = tab.icon
|
|
83
83
|
return (
|
|
84
84
|
<Tabs.Trigger
|
|
85
85
|
key={tab.value}
|
|
86
86
|
value={tab.value}
|
|
87
|
-
className="
|
|
87
|
+
className="text-muted-foreground hover:text-foreground data-[state=active]:text-foreground data-[state=active]:border-primary data-[state=active]:bg-background flex flex-1 items-center justify-center gap-1.5 px-2 py-2.5 text-xs font-medium transition-colors data-[state=active]:border-b-2"
|
|
88
88
|
>
|
|
89
89
|
<Icon size={14} />
|
|
90
90
|
<span>{tab.label}</span>
|
|
@@ -53,11 +53,11 @@ function getRingStrokeColor(score: number): string {
|
|
|
53
53
|
function StatusIcon({ status }: { status: BuilderDesignCheck['status'] }) {
|
|
54
54
|
switch (status) {
|
|
55
55
|
case 'good':
|
|
56
|
-
return <CheckCircle2 size={14} className="text-green-500
|
|
56
|
+
return <CheckCircle2 size={14} className="shrink-0 text-green-500" />
|
|
57
57
|
case 'warning':
|
|
58
|
-
return <AlertCircle size={14} className="text-amber-500
|
|
58
|
+
return <AlertCircle size={14} className="shrink-0 text-amber-500" />
|
|
59
59
|
case 'error':
|
|
60
|
-
return <XCircle size={14} className="text-red-500
|
|
60
|
+
return <XCircle size={14} className="shrink-0 text-red-500" />
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -69,7 +69,7 @@ function SeverityBadge({ severity }: { severity: DesignSuggestion['severity'] })
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
return (
|
|
72
|
-
<span className={`inline-block px-1.5 py-0.5
|
|
72
|
+
<span className={`inline-block rounded px-1.5 py-0.5 text-xs font-medium ${classes[severity]}`}>
|
|
73
73
|
{severity}
|
|
74
74
|
</span>
|
|
75
75
|
)
|
|
@@ -112,7 +112,7 @@ function ScoreRing({ score }: { score: number }) {
|
|
|
112
112
|
<span className={`text-lg font-medium ${getScoreColor(score, 100)}`}>{score}</span>
|
|
113
113
|
</div>
|
|
114
114
|
</div>
|
|
115
|
-
<span className="text-
|
|
115
|
+
<span className="text-muted-foreground text-xs">{getScoreLabel(score)}</span>
|
|
116
116
|
</div>
|
|
117
117
|
)
|
|
118
118
|
}
|
|
@@ -129,17 +129,17 @@ function CategoryRow({
|
|
|
129
129
|
const percentage = category.maxScore > 0 ? (category.score / category.maxScore) * 100 : 0
|
|
130
130
|
|
|
131
131
|
return (
|
|
132
|
-
<div className="border-
|
|
132
|
+
<div className="border-border border-b last:border-b-0">
|
|
133
133
|
<button
|
|
134
134
|
type="button"
|
|
135
|
-
className="w-full
|
|
135
|
+
className="hover:bg-muted/50 flex w-full flex-col gap-2 px-4 py-3 text-left transition-colors"
|
|
136
136
|
onClick={onToggle}
|
|
137
137
|
aria-expanded={expanded}
|
|
138
138
|
>
|
|
139
139
|
<div className="flex items-center justify-between">
|
|
140
|
-
<span className="text-xs font-medium
|
|
140
|
+
<span className="text-foreground text-xs font-medium">{category.label}</span>
|
|
141
141
|
<div className="flex items-center gap-2">
|
|
142
|
-
<span className="text-
|
|
142
|
+
<span className="text-muted-foreground text-xs">
|
|
143
143
|
{category.score}/{category.maxScore}
|
|
144
144
|
</span>
|
|
145
145
|
{expanded ? (
|
|
@@ -149,7 +149,7 @@ function CategoryRow({
|
|
|
149
149
|
)}
|
|
150
150
|
</div>
|
|
151
151
|
</div>
|
|
152
|
-
<div className="
|
|
152
|
+
<div className="bg-muted h-1.5 w-full overflow-hidden rounded-full">
|
|
153
153
|
<div
|
|
154
154
|
className={`h-full rounded-full transition-all duration-500 ease-out ${getBarColor(category.score, category.maxScore)}`}
|
|
155
155
|
style={{ width: `${percentage}%` }}
|
|
@@ -158,13 +158,13 @@ function CategoryRow({
|
|
|
158
158
|
</button>
|
|
159
159
|
|
|
160
160
|
{expanded && category.checks.length > 0 && (
|
|
161
|
-
<div className="
|
|
161
|
+
<div className="flex flex-col gap-2 px-4 pb-3">
|
|
162
162
|
{category.checks.map((check) => (
|
|
163
163
|
<div key={check.id} className="flex items-start gap-2 pl-1">
|
|
164
164
|
<StatusIcon status={check.status} />
|
|
165
165
|
<div className="flex flex-col">
|
|
166
|
-
<span className="text-xs font-medium
|
|
167
|
-
<span className="text-
|
|
166
|
+
<span className="text-foreground text-xs font-medium">{check.label}</span>
|
|
167
|
+
<span className="text-muted-foreground text-xs">{check.detail}</span>
|
|
168
168
|
</div>
|
|
169
169
|
</div>
|
|
170
170
|
))}
|
|
@@ -187,16 +187,16 @@ function SuggestionsList({ suggestions }: { suggestions: DesignSuggestion[] }) {
|
|
|
187
187
|
if (sorted.length === 0) return null
|
|
188
188
|
|
|
189
189
|
return (
|
|
190
|
-
<div className="px-4 py-3
|
|
191
|
-
<div className="flex items-center gap-2
|
|
190
|
+
<div className="border-border border-t px-4 py-3">
|
|
191
|
+
<div className="mb-3 flex items-center gap-2">
|
|
192
192
|
<Lightbulb size={14} className="text-muted-foreground" />
|
|
193
|
-
<span className="text-xs font-medium
|
|
193
|
+
<span className="text-foreground text-xs font-medium">Suggestions</span>
|
|
194
194
|
</div>
|
|
195
195
|
<div className="flex flex-col gap-2.5">
|
|
196
196
|
{sorted.map((suggestion) => (
|
|
197
197
|
<div key={suggestion.id} className="flex items-start gap-2">
|
|
198
198
|
<SeverityBadge severity={suggestion.severity} />
|
|
199
|
-
<span className="text-
|
|
199
|
+
<span className="text-muted-foreground text-xs leading-relaxed">
|
|
200
200
|
{suggestion.message}
|
|
201
201
|
</span>
|
|
202
202
|
</div>
|
|
@@ -218,10 +218,10 @@ export function DesignScorePanel({ tree }: DesignScorePanelProps) {
|
|
|
218
218
|
|
|
219
219
|
if (!tree.children || tree.children.length === 0) {
|
|
220
220
|
return (
|
|
221
|
-
<div className="
|
|
221
|
+
<div className="flex min-h-[200px] flex-col items-center justify-center p-6 text-center">
|
|
222
222
|
<Palette size={32} className="text-muted-foreground mb-3" />
|
|
223
|
-
<p className="text-
|
|
224
|
-
<p className="text-
|
|
223
|
+
<p className="text-foreground mb-1 text-sm font-medium">Design Score</p>
|
|
224
|
+
<p className="text-muted-foreground text-xs">
|
|
225
225
|
Add sections to your page to see the design analysis
|
|
226
226
|
</p>
|
|
227
227
|
</div>
|
|
@@ -230,7 +230,7 @@ export function DesignScorePanel({ tree }: DesignScorePanelProps) {
|
|
|
230
230
|
|
|
231
231
|
return (
|
|
232
232
|
<div className="flex flex-col">
|
|
233
|
-
<div className="flex flex-col items-center
|
|
233
|
+
<div className="border-border flex flex-col items-center border-b py-5">
|
|
234
234
|
<ScoreRing score={analysis.score} />
|
|
235
235
|
</div>
|
|
236
236
|
|