@prenta/admin 0.98.1 → 1.1.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/CHANGELOG.md +12 -0
- package/dist/AdminRoot.d.ts.map +1 -1
- package/dist/AdminRoot.js +22 -84
- package/dist/AdminRoot.js.map +1 -1
- package/dist/__tests__/components/breakpoint-controls.render.test.js +4 -4
- package/dist/__tests__/components/breakpoint-controls.render.test.js.map +1 -1
- package/dist/__tests__/components/seo-score-bands.test.js +0 -3
- package/dist/__tests__/components/seo-score-bands.test.js.map +1 -1
- package/dist/__tests__/layout/sidebar-posts.test.js +6 -11
- package/dist/__tests__/layout/sidebar-posts.test.js.map +1 -1
- package/dist/__tests__/layout/sidebar-submenu.render.test.js +3 -2
- package/dist/__tests__/layout/sidebar-submenu.render.test.js.map +1 -1
- package/dist/__tests__/lib/open-public-site-tab.test.d.ts +2 -0
- package/dist/__tests__/lib/open-public-site-tab.test.d.ts.map +1 -0
- package/dist/__tests__/lib/open-public-site-tab.test.js +64 -0
- package/dist/__tests__/lib/open-public-site-tab.test.js.map +1 -0
- package/dist/__tests__/lib/page-editor-service-api.test.js +26 -23
- package/dist/__tests__/lib/page-editor-service-api.test.js.map +1 -1
- package/dist/__tests__/lib/view-site-chrome.test.d.ts +2 -0
- package/dist/__tests__/lib/view-site-chrome.test.d.ts.map +1 -0
- package/dist/__tests__/lib/view-site-chrome.test.js +59 -0
- package/dist/__tests__/lib/view-site-chrome.test.js.map +1 -0
- package/dist/__tests__/router/admin-routes.test.js +4 -0
- package/dist/__tests__/router/admin-routes.test.js.map +1 -1
- package/dist/__tests__/views/canvas-surface-shared.test.js +0 -16
- package/dist/__tests__/views/canvas-surface-shared.test.js.map +1 -1
- package/dist/__tests__/views/editor-top-bar.render.test.js +44 -22
- package/dist/__tests__/views/editor-top-bar.render.test.js.map +1 -1
- package/dist/__tests__/views/page-section-editor.test.js +30 -10
- package/dist/__tests__/views/page-section-editor.test.js.map +1 -1
- package/dist/__tests__/views/page-tab.render.test.js +0 -1
- package/dist/__tests__/views/page-tab.render.test.js.map +1 -1
- package/dist/__tests__/views/post-section-editor.test.js +23 -0
- package/dist/__tests__/views/post-section-editor.test.js.map +1 -1
- package/dist/components/BreakpointPicker.d.ts +3 -2
- package/dist/components/BreakpointPicker.d.ts.map +1 -1
- package/dist/components/BreakpointPicker.js +5 -3
- package/dist/components/BreakpointPicker.js.map +1 -1
- package/dist/components/CanvasEditTip.js +1 -1
- package/dist/components/CanvasEditTip.js.map +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/dist/layout/Sidebar.d.ts +3 -4
- package/dist/layout/Sidebar.d.ts.map +1 -1
- package/dist/layout/Sidebar.js +7 -38
- package/dist/layout/Sidebar.js.map +1 -1
- package/dist/lib/editor-preview.d.ts +4 -1
- package/dist/lib/editor-preview.d.ts.map +1 -1
- package/dist/lib/editor-preview.js +4 -1
- package/dist/lib/editor-preview.js.map +1 -1
- package/dist/lib/open-public-site-tab.d.ts +14 -0
- package/dist/lib/open-public-site-tab.d.ts.map +1 -0
- package/dist/lib/open-public-site-tab.js +46 -0
- package/dist/lib/open-public-site-tab.js.map +1 -0
- package/dist/lib/page-editor-service.d.ts +0 -7
- package/dist/lib/page-editor-service.d.ts.map +1 -1
- package/dist/lib/page-editor-service.js +9 -9
- package/dist/lib/page-editor-service.js.map +1 -1
- package/dist/lib/view-site-chrome.d.ts +16 -0
- package/dist/lib/view-site-chrome.d.ts.map +1 -0
- package/dist/lib/view-site-chrome.js +15 -0
- package/dist/lib/view-site-chrome.js.map +1 -0
- package/dist/prenta-admin.css +1 -1
- package/dist/router/admin-routes.d.ts.map +1 -1
- package/dist/router/admin-routes.js +0 -2
- package/dist/router/admin-routes.js.map +1 -1
- package/dist/views/PageEditor.d.ts +2 -2
- package/dist/views/PageEditor.js +2 -2
- package/dist/views/page-editor/EditorCanvas.d.ts +1 -2
- package/dist/views/page-editor/EditorCanvas.d.ts.map +1 -1
- package/dist/views/page-editor/EditorCanvas.js +2 -2
- package/dist/views/page-editor/EditorCanvas.js.map +1 -1
- package/dist/views/page-editor/EditorTopBar.d.ts +13 -17
- package/dist/views/page-editor/EditorTopBar.d.ts.map +1 -1
- package/dist/views/page-editor/EditorTopBar.js +19 -21
- package/dist/views/page-editor/EditorTopBar.js.map +1 -1
- package/dist/views/page-editor/PageSectionEditor.d.ts +1 -7
- package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
- package/dist/views/page-editor/PageSectionEditor.js +38 -110
- package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
- package/dist/views/page-editor/StructureNotice.d.ts +2 -5
- package/dist/views/page-editor/StructureNotice.d.ts.map +1 -1
- package/dist/views/page-editor/StructureNotice.js +6 -10
- package/dist/views/page-editor/StructureNotice.js.map +1 -1
- package/dist/views/post-editor/PostEditorCanvas.d.ts +1 -3
- package/dist/views/post-editor/PostEditorCanvas.d.ts.map +1 -1
- package/dist/views/post-editor/PostEditorCanvas.js +3 -3
- package/dist/views/post-editor/PostEditorCanvas.js.map +1 -1
- package/dist/views/post-editor/PostSectionEditor.d.ts +1 -15
- package/dist/views/post-editor/PostSectionEditor.d.ts.map +1 -1
- package/dist/views/post-editor/PostSectionEditor.js +30 -88
- package/dist/views/post-editor/PostSectionEditor.js.map +1 -1
- package/package.json +3 -3
- package/src/AdminRoot.tsx +18 -138
- package/src/__tests__/components/breakpoint-controls.render.test.tsx +6 -4
- package/src/__tests__/components/seo-score-bands.test.ts +0 -3
- package/src/__tests__/layout/sidebar-posts.test.ts +6 -11
- package/src/__tests__/layout/sidebar-submenu.render.test.tsx +3 -2
- package/src/__tests__/lib/open-public-site-tab.test.ts +74 -0
- package/src/__tests__/lib/page-editor-service-api.test.ts +27 -25
- package/src/__tests__/lib/view-site-chrome.test.ts +65 -0
- package/src/__tests__/router/admin-routes.test.ts +5 -0
- package/src/__tests__/views/canvas-surface-shared.test.ts +0 -19
- package/src/__tests__/views/editor-top-bar.render.test.tsx +85 -22
- package/src/__tests__/views/page-section-editor.test.tsx +42 -10
- package/src/__tests__/views/page-tab.render.test.tsx +0 -1
- package/src/__tests__/views/post-section-editor.test.tsx +35 -0
- package/src/components/BreakpointPicker.tsx +6 -3
- package/src/components/CanvasEditTip.tsx +2 -2
- package/src/index.ts +1 -11
- package/src/layout/Sidebar.tsx +6 -41
- package/src/lib/editor-preview.ts +4 -1
- package/src/lib/open-public-site-tab.ts +57 -0
- package/src/lib/page-editor-service.ts +9 -16
- package/src/lib/view-site-chrome.ts +34 -0
- package/src/router/admin-routes.ts +0 -2
- package/src/styles/theme.css +4 -4
- package/src/views/PageEditor.tsx +2 -2
- package/src/views/page-editor/EditorCanvas.tsx +1 -6
- package/src/views/page-editor/EditorTopBar.tsx +81 -82
- package/src/views/page-editor/PageSectionEditor.tsx +85 -194
- package/src/views/page-editor/StructureNotice.tsx +7 -42
- package/src/views/post-editor/PostEditorCanvas.tsx +2 -8
- package/src/views/post-editor/PostSectionEditor.tsx +66 -138
- package/dist/__tests__/views/page-builder-block-renderer.render.test.d.ts +0 -2
- package/dist/__tests__/views/page-builder-block-renderer.render.test.d.ts.map +0 -1
- package/dist/__tests__/views/page-builder-block-renderer.render.test.js +0 -48
- package/dist/__tests__/views/page-builder-block-renderer.render.test.js.map +0 -1
- package/dist/__tests__/views/page-builder-form-picker.render.test.d.ts +0 -2
- package/dist/__tests__/views/page-builder-form-picker.render.test.d.ts.map +0 -1
- package/dist/__tests__/views/page-builder-form-picker.render.test.js +0 -44
- package/dist/__tests__/views/page-builder-form-picker.render.test.js.map +0 -1
- package/dist/__tests__/views/page-builder-sections-panel.render.test.d.ts +0 -2
- package/dist/__tests__/views/page-builder-sections-panel.render.test.d.ts.map +0 -1
- package/dist/__tests__/views/page-builder-sections-panel.render.test.js +0 -121
- package/dist/__tests__/views/page-builder-sections-panel.render.test.js.map +0 -1
- package/dist/__tests__/views/page-builder-seo-panel.render.test.d.ts +0 -2
- package/dist/__tests__/views/page-builder-seo-panel.render.test.d.ts.map +0 -1
- package/dist/__tests__/views/page-builder-seo-panel.render.test.js +0 -65
- package/dist/__tests__/views/page-builder-seo-panel.render.test.js.map +0 -1
- package/dist/__tests__/views/page-builder-template-seed.render.test.d.ts +0 -2
- package/dist/__tests__/views/page-builder-template-seed.render.test.d.ts.map +0 -1
- package/dist/__tests__/views/page-builder-template-seed.render.test.js +0 -48
- package/dist/__tests__/views/page-builder-template-seed.render.test.js.map +0 -1
- package/dist/__tests__/views/page-templates.render.test.d.ts +0 -2
- package/dist/__tests__/views/page-templates.render.test.d.ts.map +0 -1
- package/dist/__tests__/views/page-templates.render.test.js +0 -126
- package/dist/__tests__/views/page-templates.render.test.js.map +0 -1
- package/dist/__tests__/views/use-site-preview.render.test.d.ts +0 -2
- package/dist/__tests__/views/use-site-preview.render.test.d.ts.map +0 -1
- package/dist/__tests__/views/use-site-preview.render.test.js +0 -120
- package/dist/__tests__/views/use-site-preview.render.test.js.map +0 -1
- package/dist/hooks/useBuilderState.d.ts +0 -49
- package/dist/hooks/useBuilderState.d.ts.map +0 -1
- package/dist/hooks/useBuilderState.js +0 -238
- package/dist/hooks/useBuilderState.js.map +0 -1
- package/dist/views/page-builder/AIBlockAssist.d.ts +0 -9
- package/dist/views/page-builder/AIBlockAssist.d.ts.map +0 -1
- package/dist/views/page-builder/AIBlockAssist.js +0 -40
- package/dist/views/page-builder/AIBlockAssist.js.map +0 -1
- package/dist/views/page-builder/AIGenerateDialog.d.ts +0 -8
- package/dist/views/page-builder/AIGenerateDialog.d.ts.map +0 -1
- package/dist/views/page-builder/AIGenerateDialog.js +0 -173
- package/dist/views/page-builder/AIGenerateDialog.js.map +0 -1
- package/dist/views/page-builder/BlockEditor.d.ts +0 -11
- package/dist/views/page-builder/BlockEditor.d.ts.map +0 -1
- package/dist/views/page-builder/BlockEditor.js +0 -159
- package/dist/views/page-builder/BlockEditor.js.map +0 -1
- package/dist/views/page-builder/BlockPicker.d.ts +0 -7
- package/dist/views/page-builder/BlockPicker.d.ts.map +0 -1
- package/dist/views/page-builder/BlockPicker.js +0 -103
- package/dist/views/page-builder/BlockPicker.js.map +0 -1
- package/dist/views/page-builder/BottomBar.d.ts +0 -9
- package/dist/views/page-builder/BottomBar.d.ts.map +0 -1
- package/dist/views/page-builder/BottomBar.js +0 -13
- package/dist/views/page-builder/BottomBar.js.map +0 -1
- package/dist/views/page-builder/BuilderSectionsPanel.d.ts +0 -20
- package/dist/views/page-builder/BuilderSectionsPanel.d.ts.map +0 -1
- package/dist/views/page-builder/BuilderSectionsPanel.js +0 -105
- package/dist/views/page-builder/BuilderSectionsPanel.js.map +0 -1
- package/dist/views/page-builder/BuilderToolbar.d.ts +0 -21
- package/dist/views/page-builder/BuilderToolbar.d.ts.map +0 -1
- package/dist/views/page-builder/BuilderToolbar.js +0 -18
- package/dist/views/page-builder/BuilderToolbar.js.map +0 -1
- package/dist/views/page-builder/ContextPanel.d.ts +0 -20
- package/dist/views/page-builder/ContextPanel.d.ts.map +0 -1
- package/dist/views/page-builder/ContextPanel.js +0 -43
- package/dist/views/page-builder/ContextPanel.js.map +0 -1
- package/dist/views/page-builder/DesignScore.d.ts +0 -6
- package/dist/views/page-builder/DesignScore.d.ts.map +0 -1
- package/dist/views/page-builder/DesignScore.js +0 -93
- package/dist/views/page-builder/DesignScore.js.map +0 -1
- package/dist/views/page-builder/NodeSettings.d.ts +0 -12
- package/dist/views/page-builder/NodeSettings.d.ts.map +0 -1
- package/dist/views/page-builder/NodeSettings.js +0 -80
- package/dist/views/page-builder/NodeSettings.js.map +0 -1
- package/dist/views/page-builder/PageBuilder.d.ts +0 -10
- package/dist/views/page-builder/PageBuilder.d.ts.map +0 -1
- package/dist/views/page-builder/PageBuilder.js +0 -222
- package/dist/views/page-builder/PageBuilder.js.map +0 -1
- package/dist/views/page-builder/PageSettings.d.ts +0 -7
- package/dist/views/page-builder/PageSettings.d.ts.map +0 -1
- package/dist/views/page-builder/PageSettings.js +0 -27
- package/dist/views/page-builder/PageSettings.js.map +0 -1
- package/dist/views/page-builder/PageTemplates.d.ts +0 -5
- package/dist/views/page-builder/PageTemplates.d.ts.map +0 -1
- package/dist/views/page-builder/PageTemplates.js +0 -146
- package/dist/views/page-builder/PageTemplates.js.map +0 -1
- package/dist/views/page-builder/RelationshipField.d.ts +0 -15
- package/dist/views/page-builder/RelationshipField.d.ts.map +0 -1
- package/dist/views/page-builder/RelationshipField.js +0 -65
- package/dist/views/page-builder/RelationshipField.js.map +0 -1
- package/dist/views/page-builder/SEOPanel.d.ts +0 -9
- package/dist/views/page-builder/SEOPanel.d.ts.map +0 -1
- package/dist/views/page-builder/SEOPanel.js +0 -38
- package/dist/views/page-builder/SEOPanel.js.map +0 -1
- package/dist/views/page-builder/SavedSections.d.ts +0 -6
- package/dist/views/page-builder/SavedSections.d.ts.map +0 -1
- package/dist/views/page-builder/SavedSections.js +0 -141
- package/dist/views/page-builder/SavedSections.js.map +0 -1
- package/dist/views/page-builder/TemplatePicker.d.ts +0 -7
- package/dist/views/page-builder/TemplatePicker.d.ts.map +0 -1
- package/dist/views/page-builder/TemplatePicker.js +0 -68
- package/dist/views/page-builder/TemplatePicker.js.map +0 -1
- package/dist/views/page-builder/Widgets.d.ts +0 -13
- package/dist/views/page-builder/Widgets.d.ts.map +0 -1
- package/dist/views/page-builder/Widgets.js +0 -15
- package/dist/views/page-builder/Widgets.js.map +0 -1
- package/dist/views/page-builder/block-renderers/CTAPreview.d.ts +0 -3
- package/dist/views/page-builder/block-renderers/CTAPreview.d.ts.map +0 -1
- package/dist/views/page-builder/block-renderers/CTAPreview.js +0 -19
- package/dist/views/page-builder/block-renderers/CTAPreview.js.map +0 -1
- package/dist/views/page-builder/block-renderers/CardsPreview.d.ts +0 -3
- package/dist/views/page-builder/block-renderers/CardsPreview.d.ts.map +0 -1
- package/dist/views/page-builder/block-renderers/CardsPreview.js +0 -22
- package/dist/views/page-builder/block-renderers/CardsPreview.js.map +0 -1
- package/dist/views/page-builder/block-renderers/CodePreview.d.ts +0 -3
- package/dist/views/page-builder/block-renderers/CodePreview.d.ts.map +0 -1
- package/dist/views/page-builder/block-renderers/CodePreview.js +0 -12
- package/dist/views/page-builder/block-renderers/CodePreview.js.map +0 -1
- package/dist/views/page-builder/block-renderers/FAQPreview.d.ts +0 -3
- package/dist/views/page-builder/block-renderers/FAQPreview.d.ts.map +0 -1
- package/dist/views/page-builder/block-renderers/FAQPreview.js +0 -27
- package/dist/views/page-builder/block-renderers/FAQPreview.js.map +0 -1
- package/dist/views/page-builder/block-renderers/FallbackPreview.d.ts +0 -6
- package/dist/views/page-builder/block-renderers/FallbackPreview.d.ts.map +0 -1
- package/dist/views/page-builder/block-renderers/FallbackPreview.js +0 -7
- package/dist/views/page-builder/block-renderers/FallbackPreview.js.map +0 -1
- package/dist/views/page-builder/block-renderers/FormPreview.d.ts +0 -9
- package/dist/views/page-builder/block-renderers/FormPreview.d.ts.map +0 -1
- package/dist/views/page-builder/block-renderers/FormPreview.js +0 -52
- package/dist/views/page-builder/block-renderers/FormPreview.js.map +0 -1
- package/dist/views/page-builder/block-renderers/GalleryPreview.d.ts +0 -3
- package/dist/views/page-builder/block-renderers/GalleryPreview.d.ts.map +0 -1
- package/dist/views/page-builder/block-renderers/GalleryPreview.js +0 -19
- package/dist/views/page-builder/block-renderers/GalleryPreview.js.map +0 -1
- package/dist/views/page-builder/block-renderers/HeroPreview.d.ts +0 -3
- package/dist/views/page-builder/block-renderers/HeroPreview.d.ts.map +0 -1
- package/dist/views/page-builder/block-renderers/HeroPreview.js +0 -19
- package/dist/views/page-builder/block-renderers/HeroPreview.js.map +0 -1
- package/dist/views/page-builder/block-renderers/ImagePreview.d.ts +0 -3
- package/dist/views/page-builder/block-renderers/ImagePreview.d.ts.map +0 -1
- package/dist/views/page-builder/block-renderers/ImagePreview.js +0 -17
- package/dist/views/page-builder/block-renderers/ImagePreview.js.map +0 -1
- package/dist/views/page-builder/block-renderers/TextPreview.d.ts +0 -3
- package/dist/views/page-builder/block-renderers/TextPreview.d.ts.map +0 -1
- package/dist/views/page-builder/block-renderers/TextPreview.js +0 -22
- package/dist/views/page-builder/block-renderers/TextPreview.js.map +0 -1
- package/dist/views/page-builder/block-renderers/VideoPreview.d.ts +0 -3
- package/dist/views/page-builder/block-renderers/VideoPreview.d.ts.map +0 -1
- package/dist/views/page-builder/block-renderers/VideoPreview.js +0 -18
- package/dist/views/page-builder/block-renderers/VideoPreview.js.map +0 -1
- package/dist/views/page-builder/block-renderers/index.d.ts +0 -9
- package/dist/views/page-builder/block-renderers/index.d.ts.map +0 -1
- package/dist/views/page-builder/block-renderers/index.js +0 -25
- package/dist/views/page-builder/block-renderers/index.js.map +0 -1
- package/dist/views/page-builder/canvas/BlockRenderer.d.ts +0 -8
- package/dist/views/page-builder/canvas/BlockRenderer.d.ts.map +0 -1
- package/dist/views/page-builder/canvas/BlockRenderer.js +0 -20
- package/dist/views/page-builder/canvas/BlockRenderer.js.map +0 -1
- package/dist/views/page-builder/canvas/BuilderCanvas.d.ts +0 -10
- package/dist/views/page-builder/canvas/BuilderCanvas.d.ts.map +0 -1
- package/dist/views/page-builder/canvas/BuilderCanvas.js +0 -26
- package/dist/views/page-builder/canvas/BuilderCanvas.js.map +0 -1
- package/dist/views/page-builder/canvas/ColumnRenderer.d.ts +0 -8
- package/dist/views/page-builder/canvas/ColumnRenderer.d.ts.map +0 -1
- package/dist/views/page-builder/canvas/ColumnRenderer.js +0 -32
- package/dist/views/page-builder/canvas/ColumnRenderer.js.map +0 -1
- package/dist/views/page-builder/canvas/ContainerRenderer.d.ts +0 -8
- package/dist/views/page-builder/canvas/ContainerRenderer.d.ts.map +0 -1
- package/dist/views/page-builder/canvas/ContainerRenderer.js +0 -29
- package/dist/views/page-builder/canvas/ContainerRenderer.js.map +0 -1
- package/dist/views/page-builder/canvas/RowRenderer.d.ts +0 -8
- package/dist/views/page-builder/canvas/RowRenderer.d.ts.map +0 -1
- package/dist/views/page-builder/canvas/RowRenderer.js +0 -28
- package/dist/views/page-builder/canvas/RowRenderer.js.map +0 -1
- package/dist/views/page-builder/canvas/SectionRenderer.d.ts +0 -8
- package/dist/views/page-builder/canvas/SectionRenderer.d.ts.map +0 -1
- package/dist/views/page-builder/canvas/SectionRenderer.js +0 -50
- package/dist/views/page-builder/canvas/SectionRenderer.js.map +0 -1
- package/dist/views/page-builder/canvas/index.d.ts +0 -3
- package/dist/views/page-builder/canvas/index.d.ts.map +0 -1
- package/dist/views/page-builder/canvas/index.js +0 -2
- package/dist/views/page-builder/canvas/index.js.map +0 -1
- package/dist/views/page-editor/PagePreview.d.ts +0 -13
- package/dist/views/page-editor/PagePreview.d.ts.map +0 -1
- package/dist/views/page-editor/PagePreview.js +0 -46
- package/dist/views/page-editor/PagePreview.js.map +0 -1
- package/dist/views/page-editor/SitePreviewFrame.d.ts +0 -43
- package/dist/views/page-editor/SitePreviewFrame.d.ts.map +0 -1
- package/dist/views/page-editor/SitePreviewFrame.js +0 -165
- package/dist/views/page-editor/SitePreviewFrame.js.map +0 -1
- package/dist/views/page-editor/useSitePreview.d.ts +0 -47
- package/dist/views/page-editor/useSitePreview.d.ts.map +0 -1
- package/dist/views/page-editor/useSitePreview.js +0 -96
- package/dist/views/page-editor/useSitePreview.js.map +0 -1
- package/dist/views/post-editor/PostPreview.d.ts +0 -14
- package/dist/views/post-editor/PostPreview.d.ts.map +0 -1
- package/dist/views/post-editor/PostPreview.js +0 -63
- package/dist/views/post-editor/PostPreview.js.map +0 -1
- package/src/__tests__/views/page-builder-block-renderer.render.test.tsx +0 -66
- package/src/__tests__/views/page-builder-form-picker.render.test.tsx +0 -54
- package/src/__tests__/views/page-builder-sections-panel.render.test.tsx +0 -138
- package/src/__tests__/views/page-builder-seo-panel.render.test.tsx +0 -77
- package/src/__tests__/views/page-builder-template-seed.render.test.tsx +0 -59
- package/src/__tests__/views/page-templates.render.test.tsx +0 -182
- package/src/__tests__/views/use-site-preview.render.test.tsx +0 -164
- package/src/hooks/useBuilderState.ts +0 -361
- package/src/views/page-builder/AIBlockAssist.tsx +0 -64
- package/src/views/page-builder/AIGenerateDialog.tsx +0 -593
- package/src/views/page-builder/BlockEditor.tsx +0 -523
- package/src/views/page-builder/BlockPicker.tsx +0 -324
- package/src/views/page-builder/BottomBar.tsx +0 -65
- package/src/views/page-builder/BuilderSectionsPanel.tsx +0 -304
- package/src/views/page-builder/BuilderToolbar.tsx +0 -221
- package/src/views/page-builder/ContextPanel.tsx +0 -144
- package/src/views/page-builder/DesignScore.tsx +0 -251
- package/src/views/page-builder/NodeSettings.tsx +0 -500
- package/src/views/page-builder/PageBuilder.tsx +0 -405
- package/src/views/page-builder/PageSettings.tsx +0 -162
- package/src/views/page-builder/PageTemplates.tsx +0 -435
- package/src/views/page-builder/RelationshipField.tsx +0 -113
- package/src/views/page-builder/SEOPanel.tsx +0 -222
- package/src/views/page-builder/SavedSections.tsx +0 -480
- package/src/views/page-builder/TemplatePicker.tsx +0 -197
- package/src/views/page-builder/Widgets.tsx +0 -44
- package/src/views/page-builder/block-renderers/CTAPreview.tsx +0 -79
- package/src/views/page-builder/block-renderers/CardsPreview.tsx +0 -69
- package/src/views/page-builder/block-renderers/CodePreview.tsx +0 -46
- package/src/views/page-builder/block-renderers/FAQPreview.tsx +0 -87
- package/src/views/page-builder/block-renderers/FallbackPreview.tsx +0 -18
- package/src/views/page-builder/block-renderers/FormPreview.tsx +0 -117
- package/src/views/page-builder/block-renderers/GalleryPreview.tsx +0 -87
- package/src/views/page-builder/block-renderers/HeroPreview.tsx +0 -90
- package/src/views/page-builder/block-renderers/ImagePreview.tsx +0 -54
- package/src/views/page-builder/block-renderers/TextPreview.tsx +0 -81
- package/src/views/page-builder/block-renderers/VideoPreview.tsx +0 -73
- package/src/views/page-builder/block-renderers/index.ts +0 -34
- package/src/views/page-builder/canvas/BlockRenderer.tsx +0 -56
- package/src/views/page-builder/canvas/BuilderCanvas.tsx +0 -87
- package/src/views/page-builder/canvas/ColumnRenderer.tsx +0 -82
- package/src/views/page-builder/canvas/ContainerRenderer.tsx +0 -67
- package/src/views/page-builder/canvas/RowRenderer.tsx +0 -68
- package/src/views/page-builder/canvas/SectionRenderer.tsx +0 -93
- package/src/views/page-builder/canvas/index.ts +0 -2
- package/src/views/page-editor/PagePreview.tsx +0 -105
- package/src/views/page-editor/SitePreviewFrame.tsx +0 -250
- package/src/views/page-editor/useSitePreview.ts +0 -158
- package/src/views/post-editor/PostPreview.tsx +0 -125
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { NO_PUBLIC_SITE_URL_REASON, resolveViewSiteChrome } from '../../lib/view-site-chrome.js'
|
|
3
|
+
|
|
4
|
+
const base = {
|
|
5
|
+
dirty: false,
|
|
6
|
+
hasPublicSiteUrl: true,
|
|
7
|
+
hasIdentity: true,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
describe('resolveViewSiteChrome', () => {
|
|
11
|
+
it('previews a draft and shows Share', () => {
|
|
12
|
+
expect(resolveViewSiteChrome({ ...base, status: 'DRAFT' })).toEqual({
|
|
13
|
+
viewEnabled: true,
|
|
14
|
+
primaryIntent: 'preview-draft',
|
|
15
|
+
showViewLive: false,
|
|
16
|
+
shareVisible: true,
|
|
17
|
+
})
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('treats scheduled and archived like a draft', () => {
|
|
21
|
+
for (const status of ['SCHEDULED', 'ARCHIVED'] as const) {
|
|
22
|
+
expect(resolveViewSiteChrome({ ...base, status }).primaryIntent).toBe('preview-draft')
|
|
23
|
+
expect(resolveViewSiteChrome({ ...base, status }).shareVisible).toBe(true)
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('opens live on a clean published document and hides Share', () => {
|
|
28
|
+
expect(resolveViewSiteChrome({ ...base, status: 'PUBLISHED' })).toEqual({
|
|
29
|
+
viewEnabled: true,
|
|
30
|
+
primaryIntent: 'view-live',
|
|
31
|
+
showViewLive: false,
|
|
32
|
+
shareVisible: false,
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('previews unpublished changes when published and dirty, and keeps View live + Share', () => {
|
|
37
|
+
expect(resolveViewSiteChrome({ ...base, status: 'PUBLISHED', dirty: true })).toEqual({
|
|
38
|
+
viewEnabled: true,
|
|
39
|
+
primaryIntent: 'preview-draft',
|
|
40
|
+
showViewLive: true,
|
|
41
|
+
shareVisible: true,
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('disables View site and Share when the public site URL is missing', () => {
|
|
46
|
+
const chrome = resolveViewSiteChrome({
|
|
47
|
+
...base,
|
|
48
|
+
status: 'DRAFT',
|
|
49
|
+
hasPublicSiteUrl: false,
|
|
50
|
+
})
|
|
51
|
+
expect(chrome.viewEnabled).toBe(false)
|
|
52
|
+
expect(chrome.viewDisabledReason).toBe(NO_PUBLIC_SITE_URL_REASON)
|
|
53
|
+
expect(chrome.shareVisible).toBe(true)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('hides View site and Share when the document is unsaved', () => {
|
|
57
|
+
const chrome = resolveViewSiteChrome({
|
|
58
|
+
...base,
|
|
59
|
+
status: 'DRAFT',
|
|
60
|
+
hasIdentity: false,
|
|
61
|
+
})
|
|
62
|
+
expect(chrome.viewEnabled).toBe(false)
|
|
63
|
+
expect(chrome.shareVisible).toBe(false)
|
|
64
|
+
})
|
|
65
|
+
})
|
|
@@ -71,4 +71,9 @@ describe('ADMIN_STATIC_ROUTE_PATTERNS stays in sync with AdminRoot', () => {
|
|
|
71
71
|
const missing = [...new Set(literals)].filter((p) => !known.has(p))
|
|
72
72
|
expect(missing).toEqual([])
|
|
73
73
|
})
|
|
74
|
+
|
|
75
|
+
it('does not keep the retired admin-renderer preview routes', () => {
|
|
76
|
+
expect(ADMIN_STATIC_ROUTE_PATTERNS).not.toContain('/pages/:id/preview')
|
|
77
|
+
expect(ADMIN_STATIC_ROUTE_PATTERNS).not.toContain('/posts/:type/:id/preview')
|
|
78
|
+
})
|
|
74
79
|
})
|
|
@@ -58,23 +58,4 @@ describe('canvas surface is shared, not copied', () => {
|
|
|
58
58
|
expect(read(rel), `${rel} re-implements the scale`).not.toMatch(/fitScale/)
|
|
59
59
|
}
|
|
60
60
|
})
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* `SitePreviewFrame` was the third copy of `clientWidth - 48` and the one
|
|
64
|
-
* followup 2 left alone, because it scales an IFRAME rather than a rendered
|
|
65
|
-
* surface and cannot render `CanvasSurface`. It can still measure the same
|
|
66
|
-
* way, and now does: the padding arithmetic is gone even though the
|
|
67
|
-
* component is not shared.
|
|
68
|
-
*
|
|
69
|
-
* Kept apart from CANVASES on purpose — the assertion here is about the
|
|
70
|
-
* measurement, not about rendering the shared surface, and folding it in
|
|
71
|
-
* would make the other two tests claim something untrue about it.
|
|
72
|
-
*/
|
|
73
|
-
it('the site preview measures from a sentinel too, though it cannot share the surface', () => {
|
|
74
|
-
const preview = read('src/views/page-editor/SitePreviewFrame.tsx')
|
|
75
|
-
expect(preview, 'SitePreviewFrame still does padding arithmetic').not.toMatch(
|
|
76
|
-
/clientWidth\s*-\s*\d/,
|
|
77
|
-
)
|
|
78
|
-
expect(preview, 'SitePreviewFrame does not measure from a sentinel').toMatch(/sentinelRef/)
|
|
79
|
-
})
|
|
80
61
|
})
|
|
@@ -15,7 +15,6 @@ const baseProps = {
|
|
|
15
15
|
viewport: 'wide' as const,
|
|
16
16
|
onViewport: vi.fn(),
|
|
17
17
|
onBack: vi.fn(),
|
|
18
|
-
onPreview: vi.fn(),
|
|
19
18
|
onOpenSettings: vi.fn(),
|
|
20
19
|
onSaveDraft: vi.fn(),
|
|
21
20
|
onPublish: vi.fn(),
|
|
@@ -88,25 +87,93 @@ describe('EditorTopBar publish gating', () => {
|
|
|
88
87
|
})
|
|
89
88
|
})
|
|
90
89
|
|
|
91
|
-
describe('EditorTopBar view
|
|
92
|
-
it('
|
|
93
|
-
render(
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
describe('EditorTopBar view site / share', () => {
|
|
91
|
+
it('does not render the eye or the globe', () => {
|
|
92
|
+
render(
|
|
93
|
+
<EditorTopBar {...baseProps} onViewOnSite={vi.fn()} onShare={vi.fn()} hasPublicSiteUrl />,
|
|
94
|
+
)
|
|
95
|
+
expect(screen.queryByRole('button', { name: /Preview page|Preview structure/ })).toBeNull()
|
|
96
96
|
})
|
|
97
97
|
|
|
98
|
-
it('labels
|
|
98
|
+
it('labels View site on a draft and calls with preview-draft', () => {
|
|
99
99
|
const onViewOnSite = vi.fn()
|
|
100
|
-
render(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
render(
|
|
101
|
+
<EditorTopBar
|
|
102
|
+
{...baseProps}
|
|
103
|
+
status="DRAFT"
|
|
104
|
+
onViewOnSite={onViewOnSite}
|
|
105
|
+
onShare={vi.fn()}
|
|
106
|
+
hasPublicSiteUrl
|
|
107
|
+
/>,
|
|
108
|
+
)
|
|
109
|
+
fireEvent.click(screen.getByRole('button', { name: 'View site' }))
|
|
110
|
+
expect(onViewOnSite).toHaveBeenCalledWith('preview-draft')
|
|
111
|
+
expect(screen.getByRole('button', { name: 'Share' })).toBeTruthy()
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it('labels View live on a clean published document and hides Share', () => {
|
|
115
|
+
const onViewOnSite = vi.fn()
|
|
116
|
+
render(
|
|
117
|
+
<EditorTopBar
|
|
118
|
+
{...baseProps}
|
|
119
|
+
status="PUBLISHED"
|
|
120
|
+
onViewOnSite={onViewOnSite}
|
|
121
|
+
onShare={vi.fn()}
|
|
122
|
+
hasPublicSiteUrl
|
|
123
|
+
/>,
|
|
124
|
+
)
|
|
125
|
+
fireEvent.click(screen.getByRole('button', { name: 'View live' }))
|
|
126
|
+
expect(onViewOnSite).toHaveBeenCalledWith('view-live')
|
|
127
|
+
expect(screen.queryByRole('button', { name: 'Share' })).toBeNull()
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
it('keeps View live as a second action when published and dirty', () => {
|
|
131
|
+
const onViewOnSite = vi.fn()
|
|
132
|
+
render(
|
|
133
|
+
<EditorTopBar
|
|
134
|
+
{...baseProps}
|
|
135
|
+
status="PUBLISHED"
|
|
136
|
+
dirty
|
|
137
|
+
onViewOnSite={onViewOnSite}
|
|
138
|
+
onShare={vi.fn()}
|
|
139
|
+
hasPublicSiteUrl
|
|
140
|
+
/>,
|
|
141
|
+
)
|
|
142
|
+
fireEvent.click(screen.getByRole('button', { name: 'View site' }))
|
|
143
|
+
expect(onViewOnSite).toHaveBeenCalledWith('preview-draft')
|
|
144
|
+
// Radix DropdownMenu opens on pointerdown (not click), which happy-dom
|
|
145
|
+
// doesn't synthesize from fireEvent.click — open via keyboard instead.
|
|
146
|
+
fireEvent.keyDown(screen.getByRole('button', { name: 'More view options' }), {
|
|
147
|
+
key: 'Enter',
|
|
148
|
+
})
|
|
149
|
+
fireEvent.click(screen.getByRole('menuitem', { name: 'View live' }))
|
|
150
|
+
expect(onViewOnSite).toHaveBeenCalledWith('view-live')
|
|
151
|
+
expect(screen.getByRole('button', { name: 'Share' })).toBeTruthy()
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('disables View site and Share when the public site URL is missing', () => {
|
|
155
|
+
render(
|
|
156
|
+
<EditorTopBar
|
|
157
|
+
{...baseProps}
|
|
158
|
+
onViewOnSite={vi.fn()}
|
|
159
|
+
onShare={vi.fn()}
|
|
160
|
+
hasPublicSiteUrl={false}
|
|
161
|
+
/>,
|
|
162
|
+
)
|
|
163
|
+
const view = screen.getByRole('button', { name: 'View site' }) as HTMLButtonElement
|
|
164
|
+
const share = screen.getByRole('button', { name: 'Share' }) as HTMLButtonElement
|
|
165
|
+
expect(view.disabled).toBe(true)
|
|
166
|
+
expect(share.disabled).toBe(true)
|
|
167
|
+
expect(view.getAttribute('title')).toBe(
|
|
168
|
+
'Set the public site URL in Settings → SEO to open the live design.',
|
|
169
|
+
)
|
|
105
170
|
})
|
|
106
171
|
|
|
107
|
-
it('hides
|
|
172
|
+
it('hides View site and Share when onViewOnSite is omitted (unsaved doc)', () => {
|
|
108
173
|
render(<EditorTopBar {...baseProps} status="PUBLISHED" />)
|
|
109
|
-
expect(screen.queryByRole('button', { name:
|
|
174
|
+
expect(screen.queryByRole('button', { name: 'View site' })).toBeNull()
|
|
175
|
+
expect(screen.queryByRole('button', { name: 'View live' })).toBeNull()
|
|
176
|
+
expect(screen.queryByRole('button', { name: 'Share' })).toBeNull()
|
|
110
177
|
})
|
|
111
178
|
})
|
|
112
179
|
|
|
@@ -133,19 +200,15 @@ describe('EditorTopBar history button', () => {
|
|
|
133
200
|
render(
|
|
134
201
|
<EditorTopBar
|
|
135
202
|
{...baseProps}
|
|
203
|
+
status="PUBLISHED"
|
|
204
|
+
dirty
|
|
205
|
+
hasPublicSiteUrl
|
|
136
206
|
onHistory={vi.fn()}
|
|
137
207
|
onViewOnSite={vi.fn()}
|
|
138
|
-
onToggleSitePreview={vi.fn()}
|
|
139
208
|
/>,
|
|
140
209
|
)
|
|
141
210
|
|
|
142
|
-
for (const name of [
|
|
143
|
-
'Page settings',
|
|
144
|
-
'Version history',
|
|
145
|
-
'Preview page',
|
|
146
|
-
'Inline site preview',
|
|
147
|
-
'View draft on site',
|
|
148
|
-
]) {
|
|
211
|
+
for (const name of ['Page settings', 'Version history', 'More view options']) {
|
|
149
212
|
const button = screen.getByRole('button', { name })
|
|
150
213
|
expect(button.className, `${name} has no touch target`).toContain('prenta-touch-target')
|
|
151
214
|
}
|
|
@@ -3,11 +3,20 @@ import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
|
3
3
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
|
4
4
|
|
|
5
5
|
const fetchPageForEditor = vi.fn()
|
|
6
|
+
const savePageDraft = vi.fn(async (page: unknown) => page)
|
|
6
7
|
vi.mock('../../lib/page-editor-service.js', async (importOriginal) => {
|
|
7
8
|
const actual = await importOriginal<typeof import('../../lib/page-editor-service.js')>()
|
|
8
9
|
return {
|
|
9
10
|
...actual,
|
|
10
|
-
fetchPageForEditor
|
|
11
|
+
fetchPageForEditor,
|
|
12
|
+
savePageDraft,
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
vi.mock('../../lib/seo-service.js', async (importOriginal) => {
|
|
16
|
+
const actual = await importOriginal<typeof import('../../lib/seo-service.js')>()
|
|
17
|
+
return {
|
|
18
|
+
...actual,
|
|
19
|
+
updateSeoFields: vi.fn(async () => ({})),
|
|
11
20
|
}
|
|
12
21
|
})
|
|
13
22
|
|
|
@@ -32,6 +41,7 @@ const validConfig = {
|
|
|
32
41
|
|
|
33
42
|
afterEach(() => {
|
|
34
43
|
fetchPageForEditor.mockReset()
|
|
44
|
+
savePageDraft.mockClear()
|
|
35
45
|
})
|
|
36
46
|
|
|
37
47
|
describe('PageSectionEditor schema guard', () => {
|
|
@@ -98,7 +108,6 @@ function loadedPage(sections: Array<{ id: string; sectionType: string; name: str
|
|
|
98
108
|
seoDescription: '',
|
|
99
109
|
publishedAt: null,
|
|
100
110
|
updatedAt: null,
|
|
101
|
-
builderOwned: false,
|
|
102
111
|
}
|
|
103
112
|
}
|
|
104
113
|
|
|
@@ -113,9 +122,8 @@ describe('PageSectionEditor structure mode', () => {
|
|
|
113
122
|
|
|
114
123
|
await screen.findByText('Sections')
|
|
115
124
|
expect(screen.queryByText(/Structure view/)).toBeNull()
|
|
116
|
-
|
|
117
|
-
expect(screen.getByRole('button', { name: '
|
|
118
|
-
expect(screen.getByRole('button', { name: 'Preview page' })).toBeTruthy()
|
|
125
|
+
expect(screen.getByRole('button', { name: 'View site' })).toBeTruthy()
|
|
126
|
+
expect(screen.getByRole('button', { name: 'Share' })).toBeTruthy()
|
|
119
127
|
})
|
|
120
128
|
|
|
121
129
|
it('shows the structure notice and promotes "View on site" for custom section types', async () => {
|
|
@@ -131,10 +139,7 @@ describe('PageSectionEditor structure mode', () => {
|
|
|
131
139
|
|
|
132
140
|
await screen.findByText('Sections')
|
|
133
141
|
expect(screen.getByText(/Structure view/)).toBeTruthy()
|
|
134
|
-
|
|
135
|
-
expect(screen.getByRole('button', { name: /View on site/ })).toBeTruthy()
|
|
136
|
-
// Eye preview is relabeled to set expectations.
|
|
137
|
-
expect(screen.getByRole('button', { name: /Preview structure/ })).toBeTruthy()
|
|
142
|
+
expect(screen.getByRole('button', { name: 'View site' })).toBeTruthy()
|
|
138
143
|
})
|
|
139
144
|
|
|
140
145
|
it('stays out of structure mode when a custom renderer is registered for the type', async () => {
|
|
@@ -162,7 +167,7 @@ describe('PageSectionEditor structure mode', () => {
|
|
|
162
167
|
// structural for this page.
|
|
163
168
|
expect(screen.getByTestId('opal-canvas')).toBeTruthy()
|
|
164
169
|
expect(screen.queryByText(/Structure view/)).toBeNull()
|
|
165
|
-
expect(screen.getByRole('button', { name: 'View
|
|
170
|
+
expect(screen.getByRole('button', { name: 'View site' })).toBeTruthy()
|
|
166
171
|
})
|
|
167
172
|
|
|
168
173
|
it('exposes a version history button for saved pages', async () => {
|
|
@@ -234,3 +239,30 @@ describe('PageSectionEditor section disclosure', () => {
|
|
|
234
239
|
expect(screen.getByRole('button', { name: 'Close Hero' })).toBeTruthy()
|
|
235
240
|
})
|
|
236
241
|
})
|
|
242
|
+
|
|
243
|
+
describe('PageSectionEditor Share', () => {
|
|
244
|
+
const configWithSite = { ...validConfig, seo: { siteUrl: 'https://example.com' } }
|
|
245
|
+
|
|
246
|
+
it('saves a dirty draft before opening Share', async () => {
|
|
247
|
+
const page = loadedPage([{ id: 's1', sectionType: 'hero', name: 'Hero' }])
|
|
248
|
+
fetchPageForEditor.mockResolvedValue(page)
|
|
249
|
+
savePageDraft.mockResolvedValue(page)
|
|
250
|
+
|
|
251
|
+
render(
|
|
252
|
+
<PageSectionEditor
|
|
253
|
+
documentId="p1"
|
|
254
|
+
config={configWithSite}
|
|
255
|
+
onNavigate={() => {}}
|
|
256
|
+
session={{}}
|
|
257
|
+
/>,
|
|
258
|
+
)
|
|
259
|
+
await screen.findByText('Sections')
|
|
260
|
+
|
|
261
|
+
fireEvent.click(screen.getByRole('button', { name: 'Edit Hero' }))
|
|
262
|
+
fireEvent.change(await screen.findByLabelText('Section name'), { target: { value: 'Intro' } })
|
|
263
|
+
fireEvent.click(screen.getByRole('button', { name: 'Share' }))
|
|
264
|
+
|
|
265
|
+
await waitFor(() => expect(savePageDraft).toHaveBeenCalledOnce())
|
|
266
|
+
expect(await screen.findByRole('dialog', { name: 'Share preview link' })).toBeTruthy()
|
|
267
|
+
})
|
|
268
|
+
})
|
|
@@ -4,12 +4,14 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
|
|
4
4
|
|
|
5
5
|
const fetchPostForEditor = vi.fn()
|
|
6
6
|
const fetchTemplateForEditor = vi.fn()
|
|
7
|
+
const savePostDraft = vi.fn()
|
|
7
8
|
vi.mock('../../lib/post-editor-service.js', async (importOriginal) => {
|
|
8
9
|
const actual = await importOriginal<typeof import('../../lib/post-editor-service.js')>()
|
|
9
10
|
return {
|
|
10
11
|
...actual,
|
|
11
12
|
fetchPostForEditor: (...args: unknown[]) => fetchPostForEditor(...args),
|
|
12
13
|
fetchTemplateForEditor: (...args: unknown[]) => fetchTemplateForEditor(...args),
|
|
14
|
+
savePostDraft: (...args: unknown[]) => savePostDraft(...args),
|
|
13
15
|
}
|
|
14
16
|
})
|
|
15
17
|
|
|
@@ -62,6 +64,7 @@ function loadedPost(
|
|
|
62
64
|
afterEach(() => {
|
|
63
65
|
fetchPostForEditor.mockReset()
|
|
64
66
|
fetchTemplateForEditor.mockReset()
|
|
67
|
+
savePostDraft.mockReset()
|
|
65
68
|
})
|
|
66
69
|
|
|
67
70
|
describe('PostSectionEditor schema guard', () => {
|
|
@@ -126,6 +129,9 @@ describe('PostSectionEditor new post', () => {
|
|
|
126
129
|
)
|
|
127
130
|
await screen.findByText('Sections')
|
|
128
131
|
expect(screen.queryByRole('dialog', { name: 'Post details' })).toBeNull()
|
|
132
|
+
expect(screen.getByRole('button', { name: 'View site' })).toBeTruthy()
|
|
133
|
+
expect(screen.getByRole('button', { name: 'Share' })).toBeTruthy()
|
|
134
|
+
expect(screen.queryByRole('button', { name: /Preview page/ })).toBeNull()
|
|
129
135
|
})
|
|
130
136
|
})
|
|
131
137
|
|
|
@@ -201,6 +207,35 @@ describe('PostSectionEditor section disclosure', () => {
|
|
|
201
207
|
})
|
|
202
208
|
})
|
|
203
209
|
|
|
210
|
+
describe('PostSectionEditor Share', () => {
|
|
211
|
+
it('saves a dirty draft before opening Share', async () => {
|
|
212
|
+
const post = loadedPost([{ id: 's1', sectionType: 'quote', name: 'Quote' }])
|
|
213
|
+
fetchTemplateForEditor.mockRejectedValue(new Error('no template'))
|
|
214
|
+
fetchPostForEditor.mockResolvedValue(post)
|
|
215
|
+
savePostDraft.mockResolvedValue(post)
|
|
216
|
+
|
|
217
|
+
render(
|
|
218
|
+
<PostSectionEditor
|
|
219
|
+
postType="blog"
|
|
220
|
+
documentId="p1"
|
|
221
|
+
config={{ ...validConfig, seo: { siteUrl: 'https://example.com' } }}
|
|
222
|
+
onNavigate={() => {}}
|
|
223
|
+
session={{}}
|
|
224
|
+
/>,
|
|
225
|
+
)
|
|
226
|
+
await screen.findByText('Sections')
|
|
227
|
+
|
|
228
|
+
fireEvent.click(screen.getByRole('button', { name: 'Edit Quote' }))
|
|
229
|
+
fireEvent.change(await screen.findByLabelText('Section name'), {
|
|
230
|
+
target: { value: 'Pull quote' },
|
|
231
|
+
})
|
|
232
|
+
fireEvent.click(screen.getByRole('button', { name: 'Share' }))
|
|
233
|
+
|
|
234
|
+
await waitFor(() => expect(savePostDraft).toHaveBeenCalledOnce())
|
|
235
|
+
expect(await screen.findByRole('dialog', { name: 'Share preview link' })).toBeTruthy()
|
|
236
|
+
})
|
|
237
|
+
})
|
|
238
|
+
|
|
204
239
|
/**
|
|
205
240
|
* The post editor was the last screen still on the pre-handoff panel: a fixed
|
|
206
241
|
* 288px aside with no resize, no collapse and no tabs, with SEO in a
|
|
@@ -19,11 +19,12 @@ export interface BreakpointPickerProps {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* Canvas-width selector for the editor header.
|
|
23
23
|
*
|
|
24
24
|
* A dropdown rather than a segmented row: six presets with names like "Tablet
|
|
25
25
|
* Landscape" do not fit a header strip, and the grouped menu is what makes the
|
|
26
|
-
* DESKTOP / TABLET / MOBILE structure legible.
|
|
26
|
+
* DESKTOP / TABLET / MOBILE structure legible. This only sizes the first-party
|
|
27
|
+
* canvas — it is not a live-site viewport.
|
|
27
28
|
*
|
|
28
29
|
* Radix owns the menu behaviour — outside-click, Escape, roving focus, and
|
|
29
30
|
* `aria-expanded` on the trigger — rather than a hand-rolled popover.
|
|
@@ -32,6 +33,7 @@ export function BreakpointPicker({ value, onChange, disabled }: BreakpointPicker
|
|
|
32
33
|
const [open, setOpen] = useState(false)
|
|
33
34
|
const active = getBreakpoint(value)
|
|
34
35
|
const ActiveIcon = breakpointIcon(active.icon)
|
|
36
|
+
const canvasWidthLabel = `Canvas width: ${active.name}, ${active.width} pixels. First-party layout only — use View site for the live design.`
|
|
35
37
|
|
|
36
38
|
return (
|
|
37
39
|
<DropdownMenu.Root open={open} onOpenChange={setOpen}>
|
|
@@ -39,7 +41,8 @@ export function BreakpointPicker({ value, onChange, disabled }: BreakpointPicker
|
|
|
39
41
|
<button
|
|
40
42
|
type="button"
|
|
41
43
|
disabled={disabled}
|
|
42
|
-
aria-label={
|
|
44
|
+
aria-label={canvasWidthLabel}
|
|
45
|
+
title={canvasWidthLabel}
|
|
43
46
|
className={`border-border flex h-[34px] items-center gap-1.5 rounded-lg border px-2.5 text-[12.5px] font-medium transition-colors disabled:opacity-50 ${
|
|
44
47
|
open
|
|
45
48
|
? 'border-brand bg-accent text-accent-foreground'
|
|
@@ -27,8 +27,8 @@ export function CanvasEditTip() {
|
|
|
27
27
|
<span className="text-foreground font-medium">Editing tip</span>
|
|
28
28
|
{' — '}
|
|
29
29
|
Click a section on the canvas, or in the list, to open its copy and images in the section
|
|
30
|
-
list. Use <span className="text-foreground font-medium">
|
|
31
|
-
|
|
30
|
+
list. Use <span className="text-foreground font-medium">View site</span> for the live
|
|
31
|
+
design.
|
|
32
32
|
</p>
|
|
33
33
|
<button
|
|
34
34
|
type="button"
|
package/src/index.ts
CHANGED
|
@@ -52,7 +52,7 @@ export type {
|
|
|
52
52
|
export { Dashboard } from './views/Dashboard.js'
|
|
53
53
|
/** @deprecated Superseded by `PagesListView` routing in `AdminRoot`; will be removed in the next major. */
|
|
54
54
|
export { Pages } from './views/Pages.js'
|
|
55
|
-
/** @deprecated Superseded by
|
|
55
|
+
/** @deprecated Superseded by `PageSectionEditor`; will be removed in the next major. */
|
|
56
56
|
export { PageEditor } from './views/PageEditor.js'
|
|
57
57
|
export { MediaBrowser } from './views/MediaBrowser.js'
|
|
58
58
|
export { Forms } from './views/Forms.js'
|
|
@@ -78,16 +78,6 @@ export type { ResetPasswordProps } from './views/ResetPassword.js'
|
|
|
78
78
|
export { CollectionList } from './views/CollectionList.js'
|
|
79
79
|
export { DocumentEdit } from './views/DocumentEdit.js'
|
|
80
80
|
|
|
81
|
-
export { PageBuilder } from './views/page-builder/PageBuilder.js'
|
|
82
|
-
export { useBuilderState } from './hooks/useBuilderState.js'
|
|
83
|
-
export type {
|
|
84
|
-
BuilderState,
|
|
85
|
-
BuilderActions,
|
|
86
|
-
DeviceMode,
|
|
87
|
-
PanelTab,
|
|
88
|
-
PageSettings as BuilderPageSettings,
|
|
89
|
-
} from './hooks/useBuilderState.js'
|
|
90
|
-
|
|
91
81
|
export { Breadcrumbs } from './components/Breadcrumbs.js'
|
|
92
82
|
export { CommandPalette } from './components/CommandPalette.js'
|
|
93
83
|
export { ErrorBoundary } from './components/ErrorBoundary.js'
|
package/src/layout/Sidebar.tsx
CHANGED
|
@@ -26,9 +26,7 @@ import {
|
|
|
26
26
|
PanelTop,
|
|
27
27
|
PanelBottom,
|
|
28
28
|
Layers,
|
|
29
|
-
LayoutGrid,
|
|
30
29
|
Code2,
|
|
31
|
-
Library,
|
|
32
30
|
ListTree,
|
|
33
31
|
Menu as MenuIcon,
|
|
34
32
|
PanelLeftClose,
|
|
@@ -194,37 +192,16 @@ const POSTS_CHILDREN: NavItem[] = [
|
|
|
194
192
|
{ path: '/posts/types', label: 'Post Types', icon: Layers },
|
|
195
193
|
]
|
|
196
194
|
|
|
197
|
-
/**
|
|
198
|
-
* Children of the Templates parent. Templates is its own top-level item
|
|
199
|
-
* (page building tools) — Saved Sections are reusable content blocks and
|
|
200
|
-
* Widgets are embeddable components. These are deliberately NOT children
|
|
201
|
-
* of Pages: Pages is content, Templates/Sections/Widgets are structure.
|
|
202
|
-
*/
|
|
203
|
-
const TEMPLATES_CHILDREN: NavItem[] = [
|
|
204
|
-
{ path: '/saved-sections', label: 'Saved Sections', icon: Library },
|
|
205
|
-
{ path: '/widgets', label: 'Widgets', icon: LayoutGrid },
|
|
206
|
-
]
|
|
207
|
-
|
|
208
195
|
/**
|
|
209
196
|
* Nav tree for the default (config-less) install. Dashboard sits on its
|
|
210
197
|
* own at the top, then a CONTENT group holding Pages (no children) above
|
|
211
|
-
* Posts (with All Posts + Post Types)
|
|
212
|
-
*
|
|
213
|
-
* SETTINGS group (Users / API Keys / Settings). The group ordering is
|
|
214
|
-
* meaningful — the renderer emits a section header the first time it
|
|
215
|
-
* sees a new group, so "CONTENT" renders once, above Pages.
|
|
198
|
+
* Posts (with All Posts + Post Types), followed by Media / Forms / SEO /
|
|
199
|
+
* Script Tags, then a SETTINGS group (Users / API Keys / Settings).
|
|
216
200
|
*/
|
|
217
201
|
const defaultNavItems: NavItem[] = [
|
|
218
202
|
{ path: '/', label: 'Dashboard', icon: LayoutDashboard },
|
|
219
203
|
{ path: '/pages', label: 'Pages', icon: File, group: 'Content' },
|
|
220
204
|
{ path: '/posts', label: 'Posts', icon: FileText, group: 'Content', children: POSTS_CHILDREN },
|
|
221
|
-
{
|
|
222
|
-
path: '/page-templates',
|
|
223
|
-
label: 'Templates',
|
|
224
|
-
icon: Layers,
|
|
225
|
-
group: 'Content',
|
|
226
|
-
children: TEMPLATES_CHILDREN,
|
|
227
|
-
},
|
|
228
205
|
{ path: '/media', label: 'Media', icon: Image, group: 'Content' },
|
|
229
206
|
{ path: '/forms', label: 'Forms', icon: ClipboardList, group: 'Content' },
|
|
230
207
|
{ path: '/seo', label: 'SEO', icon: SearchIcon, group: 'Content' },
|
|
@@ -773,10 +750,9 @@ export interface NavItem {
|
|
|
773
750
|
/**
|
|
774
751
|
* Build the sidebar nav tree from the CMS config. If no collections are
|
|
775
752
|
* configured, returns the curated `defaultNavItems` tree. When
|
|
776
|
-
* collections ARE configured, page-type collections
|
|
777
|
-
*
|
|
778
|
-
*
|
|
779
|
-
* Settings) is anchored under the right Content / Settings group.
|
|
753
|
+
* collections ARE configured, page-type collections render as Content
|
|
754
|
+
* entries, and every static destination (Media, Forms, SEO, Script Tags,
|
|
755
|
+
* Users, API Keys, Settings) is anchored under the right group.
|
|
780
756
|
*/
|
|
781
757
|
export function buildNavItems(config: any): NavItem[] {
|
|
782
758
|
if (!config?.collections) return defaultNavItems
|
|
@@ -817,8 +793,7 @@ export function buildNavItems(config: any): NavItem[] {
|
|
|
817
793
|
// Script Tags).
|
|
818
794
|
|
|
819
795
|
// Pages-style collections render as plain Content entries (no nested
|
|
820
|
-
// children).
|
|
821
|
-
// Templates parent below, not under Pages.
|
|
796
|
+
// children).
|
|
822
797
|
pages.forEach((collection) => {
|
|
823
798
|
items.push({
|
|
824
799
|
label: collection.labels?.plural ?? collection.slug,
|
|
@@ -843,16 +818,6 @@ export function buildNavItems(config: any): NavItem[] {
|
|
|
843
818
|
})
|
|
844
819
|
}
|
|
845
820
|
|
|
846
|
-
// Templates — its own parent holding Saved Sections + Widgets (page
|
|
847
|
-
// building structure, distinct from Pages content).
|
|
848
|
-
items.push({
|
|
849
|
-
path: '/page-templates',
|
|
850
|
-
label: 'Templates',
|
|
851
|
-
icon: Layers,
|
|
852
|
-
group: 'Content',
|
|
853
|
-
children: TEMPLATES_CHILDREN,
|
|
854
|
-
})
|
|
855
|
-
|
|
856
821
|
// Standard Content destinations (always present — they map to CMS
|
|
857
822
|
// features, not collections).
|
|
858
823
|
items.push(
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { AdminEditorConfig } from '@prenta/core'
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Ignored by the editors; returns the old boolean for compatibility only.
|
|
5
|
+
* The page and post editors no longer mount an inline site-preview iframe.
|
|
6
|
+
*/
|
|
4
7
|
export function resolveDefaultSitePreview(
|
|
5
8
|
editor: AdminEditorConfig | undefined,
|
|
6
9
|
kind: 'pages' | 'posts',
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { toast } from 'sonner'
|
|
2
|
+
import { buildPublicPreviewUrl, buildPublicUrl, createPreviewToken } from './preview-link.js'
|
|
3
|
+
import { NO_PUBLIC_SITE_URL_REASON, type ViewSiteIntent } from './view-site-chrome.js'
|
|
4
|
+
|
|
5
|
+
export async function openPublicSiteTab(opts: {
|
|
6
|
+
intent: ViewSiteIntent
|
|
7
|
+
siteUrl: string
|
|
8
|
+
collection: string
|
|
9
|
+
documentId: string
|
|
10
|
+
slug: string
|
|
11
|
+
path?: string | null
|
|
12
|
+
urlPrefix?: string
|
|
13
|
+
data?: Record<string, unknown> | null
|
|
14
|
+
dirty: boolean
|
|
15
|
+
saveDraft: () => Promise<boolean>
|
|
16
|
+
}): Promise<void> {
|
|
17
|
+
const siteUrl = opts.siteUrl.trim()
|
|
18
|
+
if (!siteUrl) throw new Error(NO_PUBLIC_SITE_URL_REASON)
|
|
19
|
+
|
|
20
|
+
const parts = {
|
|
21
|
+
siteUrl,
|
|
22
|
+
urlPrefix: opts.urlPrefix ?? '',
|
|
23
|
+
slug: opts.slug,
|
|
24
|
+
path: opts.path,
|
|
25
|
+
data: opts.data,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (opts.intent === 'view-live') {
|
|
29
|
+
window.open(buildPublicUrl(parts), '_blank', 'noopener')
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const tab = window.open('about:blank', '_blank')
|
|
34
|
+
if (!tab) {
|
|
35
|
+
toast.error('Enable pop-ups for this site to open the preview in a new tab.')
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
if (opts.dirty) {
|
|
40
|
+
const ok = await opts.saveDraft()
|
|
41
|
+
if (!ok) {
|
|
42
|
+
tab.close()
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const { token } = await createPreviewToken(opts.collection, opts.documentId)
|
|
47
|
+
try {
|
|
48
|
+
tab.opener = null
|
|
49
|
+
} catch {
|
|
50
|
+
/* same-origin guard */
|
|
51
|
+
}
|
|
52
|
+
tab.location.replace(buildPublicPreviewUrl({ ...parts, token }))
|
|
53
|
+
} catch (err) {
|
|
54
|
+
tab.close()
|
|
55
|
+
throw err
|
|
56
|
+
}
|
|
57
|
+
}
|