@prenta/admin 0.92.0 → 0.93.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 +552 -0
- package/design-system/tokens.css +173 -71
- package/design-system/tokens.json +244 -63
- package/design-system/tokens.scss +203 -98
- package/design-system/tokens.tailwind.cjs +93 -38
- package/dist/AdminRoot.d.ts +27 -6
- package/dist/AdminRoot.d.ts.map +1 -1
- package/dist/AdminRoot.js.map +1 -1
- package/dist/__tests__/components/breakpoint-controls.render.test.d.ts +2 -0
- package/dist/__tests__/components/breakpoint-controls.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/breakpoint-controls.render.test.js +51 -0
- package/dist/__tests__/components/breakpoint-controls.render.test.js.map +1 -0
- package/dist/__tests__/components/canvas-edit-tip.render.test.d.ts +2 -0
- package/dist/__tests__/components/canvas-edit-tip.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/canvas-edit-tip.render.test.js +37 -0
- package/dist/__tests__/components/canvas-edit-tip.render.test.js.map +1 -0
- package/dist/__tests__/components/editor-rail.render.test.d.ts +2 -0
- package/dist/__tests__/components/editor-rail.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/editor-rail.render.test.js +138 -0
- package/dist/__tests__/components/editor-rail.render.test.js.map +1 -0
- package/dist/__tests__/components/media-block.render.test.d.ts +2 -0
- package/dist/__tests__/components/media-block.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/media-block.render.test.js +108 -0
- package/dist/__tests__/components/media-block.render.test.js.map +1 -0
- package/dist/__tests__/components/page-audit-panel.render.test.d.ts +2 -0
- package/dist/__tests__/components/page-audit-panel.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/page-audit-panel.render.test.js +59 -0
- package/dist/__tests__/components/page-audit-panel.render.test.js.map +1 -0
- package/dist/__tests__/components/reflow-meter.render.test.d.ts +2 -0
- package/dist/__tests__/components/reflow-meter.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/reflow-meter.render.test.js +94 -0
- package/dist/__tests__/components/reflow-meter.render.test.js.map +1 -0
- package/dist/__tests__/components/seo-char-count.test.js +24 -6
- package/dist/__tests__/components/seo-char-count.test.js.map +1 -1
- package/dist/__tests__/components/serp-preview.render.test.d.ts +2 -0
- package/dist/__tests__/components/serp-preview.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/serp-preview.render.test.js +25 -0
- package/dist/__tests__/components/serp-preview.render.test.js.map +1 -0
- package/dist/__tests__/lib/breakpoints.test.d.ts +2 -0
- package/dist/__tests__/lib/breakpoints.test.d.ts.map +1 -0
- package/dist/__tests__/lib/breakpoints.test.js +67 -0
- package/dist/__tests__/lib/breakpoints.test.js.map +1 -0
- package/dist/__tests__/lib/canvas-edit-chrome.test.d.ts +2 -0
- package/dist/__tests__/lib/canvas-edit-chrome.test.d.ts.map +1 -0
- package/dist/__tests__/lib/canvas-edit-chrome.test.js +44 -0
- package/dist/__tests__/lib/canvas-edit-chrome.test.js.map +1 -0
- package/dist/__tests__/lib/media-format.test.d.ts +2 -0
- package/dist/__tests__/lib/media-format.test.d.ts.map +1 -0
- package/dist/__tests__/lib/media-format.test.js +70 -0
- package/dist/__tests__/lib/media-format.test.js.map +1 -0
- package/dist/__tests__/lib/page-audit-input.test.d.ts +2 -0
- package/dist/__tests__/lib/page-audit-input.test.d.ts.map +1 -0
- package/dist/__tests__/lib/page-audit-input.test.js +122 -0
- package/dist/__tests__/lib/page-audit-input.test.js.map +1 -0
- package/dist/__tests__/lib/page-editor-service.test.js +2 -0
- package/dist/__tests__/lib/page-editor-service.test.js.map +1 -1
- package/dist/__tests__/lib/page-redirect.test.d.ts +2 -0
- package/dist/__tests__/lib/page-redirect.test.d.ts.map +1 -0
- package/dist/__tests__/lib/page-redirect.test.js +26 -0
- package/dist/__tests__/lib/page-redirect.test.js.map +1 -0
- package/dist/__tests__/lib/rail-width.test.d.ts +2 -0
- package/dist/__tests__/lib/rail-width.test.d.ts.map +1 -0
- package/dist/__tests__/lib/rail-width.test.js +69 -0
- package/dist/__tests__/lib/rail-width.test.js.map +1 -0
- package/dist/__tests__/lib/reflow-baseline.test.d.ts +2 -0
- package/dist/__tests__/lib/reflow-baseline.test.d.ts.map +1 -0
- package/dist/__tests__/lib/reflow-baseline.test.js +56 -0
- package/dist/__tests__/lib/reflow-baseline.test.js.map +1 -0
- package/dist/__tests__/lib/reflow-probe.test.d.ts +2 -0
- package/dist/__tests__/lib/reflow-probe.test.d.ts.map +1 -0
- package/dist/__tests__/lib/reflow-probe.test.js +73 -0
- package/dist/__tests__/lib/reflow-probe.test.js.map +1 -0
- package/dist/__tests__/styles/canvas-container-queries.test.d.ts +2 -0
- package/dist/__tests__/styles/canvas-container-queries.test.d.ts.map +1 -0
- package/dist/__tests__/styles/canvas-container-queries.test.js +87 -0
- package/dist/__tests__/styles/canvas-container-queries.test.js.map +1 -0
- package/dist/__tests__/styles/packaging.test.d.ts +2 -0
- package/dist/__tests__/styles/packaging.test.d.ts.map +1 -0
- package/dist/__tests__/styles/packaging.test.js +31 -0
- package/dist/__tests__/styles/packaging.test.js.map +1 -0
- package/dist/__tests__/styles/tokens-drift.test.d.ts +2 -0
- package/dist/__tests__/styles/tokens-drift.test.d.ts.map +1 -0
- package/dist/__tests__/styles/tokens-drift.test.js +92 -0
- package/dist/__tests__/styles/tokens-drift.test.js.map +1 -0
- package/dist/__tests__/views/admin-renderer-compat.test.d.ts +2 -0
- package/dist/__tests__/views/admin-renderer-compat.test.d.ts.map +1 -0
- package/dist/__tests__/views/admin-renderer-compat.test.js +43 -0
- package/dist/__tests__/views/admin-renderer-compat.test.js.map +1 -0
- package/dist/__tests__/views/admin-section-renderers.test.js +52 -4
- package/dist/__tests__/views/admin-section-renderers.test.js.map +1 -1
- package/dist/__tests__/views/editor-top-bar.render.test.js +1 -1
- package/dist/__tests__/views/editor-top-bar.render.test.js.map +1 -1
- package/dist/__tests__/views/page-tab.render.test.d.ts +2 -0
- package/dist/__tests__/views/page-tab.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/page-tab.render.test.js +151 -0
- package/dist/__tests__/views/page-tab.render.test.js.map +1 -0
- package/dist/__tests__/views/section-class-parity.test.d.ts +2 -0
- package/dist/__tests__/views/section-class-parity.test.d.ts.map +1 -0
- package/dist/__tests__/views/section-class-parity.test.js +81 -0
- package/dist/__tests__/views/section-class-parity.test.js.map +1 -0
- package/dist/__tests__/views/sections-panel-design-owned.render.test.d.ts +2 -0
- package/dist/__tests__/views/sections-panel-design-owned.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/sections-panel-design-owned.render.test.js +86 -0
- package/dist/__tests__/views/sections-panel-design-owned.render.test.js.map +1 -0
- package/dist/components/BreakpointPicker.d.ts +18 -0
- package/dist/components/BreakpointPicker.d.ts.map +1 -0
- package/dist/components/BreakpointPicker.js +31 -0
- package/dist/components/BreakpointPicker.js.map +1 -0
- package/dist/components/CanvasEditTip.d.ts +6 -0
- package/dist/components/CanvasEditTip.d.ts.map +1 -0
- package/dist/components/CanvasEditTip.js +22 -0
- package/dist/components/CanvasEditTip.js.map +1 -0
- package/dist/components/EditorRail.d.ts +36 -0
- package/dist/components/EditorRail.d.ts.map +1 -0
- package/dist/components/EditorRail.js +104 -0
- package/dist/components/EditorRail.js.map +1 -0
- package/dist/components/EditorRailTabs.d.ts +32 -0
- package/dist/components/EditorRailTabs.d.ts.map +1 -0
- package/dist/components/EditorRailTabs.js +45 -0
- package/dist/components/EditorRailTabs.js.map +1 -0
- package/dist/components/MediaBlock.d.ts +49 -0
- package/dist/components/MediaBlock.d.ts.map +1 -0
- package/dist/components/MediaBlock.js +50 -0
- package/dist/components/MediaBlock.js.map +1 -0
- package/dist/components/ReflowMeter.d.ts +28 -0
- package/dist/components/ReflowMeter.d.ts.map +1 -0
- package/dist/components/ReflowMeter.js +42 -0
- package/dist/components/ReflowMeter.js.map +1 -0
- package/dist/components/ZoomChip.d.ts +17 -0
- package/dist/components/ZoomChip.d.ts.map +1 -0
- package/dist/components/ZoomChip.js +17 -0
- package/dist/components/ZoomChip.js.map +1 -0
- package/dist/components/breakpoint-icons.d.ts +3 -0
- package/dist/components/breakpoint-icons.d.ts.map +1 -0
- package/dist/components/breakpoint-icons.js +16 -0
- package/dist/components/breakpoint-icons.js.map +1 -0
- package/dist/components/page-tab/AuthorPicker.d.ts +31 -0
- package/dist/components/page-tab/AuthorPicker.d.ts.map +1 -0
- package/dist/components/page-tab/AuthorPicker.js +95 -0
- package/dist/components/page-tab/AuthorPicker.js.map +1 -0
- package/dist/components/page-tab/DirectiveSwitch.d.ts +38 -0
- package/dist/components/page-tab/DirectiveSwitch.d.ts.map +1 -0
- package/dist/components/page-tab/DirectiveSwitch.js +29 -0
- package/dist/components/page-tab/DirectiveSwitch.js.map +1 -0
- package/dist/components/seo/EditorSeoScoreBadge.d.ts +8 -1
- package/dist/components/seo/EditorSeoScoreBadge.d.ts.map +1 -1
- package/dist/components/seo/EditorSeoScoreBadge.js +2 -2
- package/dist/components/seo/EditorSeoScoreBadge.js.map +1 -1
- package/dist/components/seo/PageAuditPanel.d.ts +14 -0
- package/dist/components/seo/PageAuditPanel.d.ts.map +1 -0
- package/dist/components/seo/PageAuditPanel.js +59 -0
- package/dist/components/seo/PageAuditPanel.js.map +1 -0
- package/dist/components/seo/SeoCharCount.d.ts +19 -7
- package/dist/components/seo/SeoCharCount.d.ts.map +1 -1
- package/dist/components/seo/SeoCharCount.js +30 -16
- package/dist/components/seo/SeoCharCount.js.map +1 -1
- package/dist/components/seo/SeoEditorPane.d.ts +15 -1
- package/dist/components/seo/SeoEditorPane.d.ts.map +1 -1
- package/dist/components/seo/SeoEditorPane.js +118 -21
- package/dist/components/seo/SeoEditorPane.js.map +1 -1
- package/dist/components/seo/SerpPreview.d.ts +20 -0
- package/dist/components/seo/SerpPreview.d.ts.map +1 -0
- package/dist/components/seo/SerpPreview.js +6 -0
- package/dist/components/seo/SerpPreview.js.map +1 -0
- package/dist/hooks/usePageAudit.d.ts +41 -0
- package/dist/hooks/usePageAudit.d.ts.map +1 -0
- package/dist/hooks/usePageAudit.js +68 -0
- package/dist/hooks/usePageAudit.js.map +1 -0
- package/dist/hooks/useReflowGuard.d.ts +47 -0
- package/dist/hooks/useReflowGuard.d.ts.map +1 -0
- package/dist/hooks/useReflowGuard.js +52 -0
- package/dist/hooks/useReflowGuard.js.map +1 -0
- package/dist/lib/breakpoints.d.ts +51 -0
- package/dist/lib/breakpoints.d.ts.map +1 -0
- package/dist/lib/breakpoints.js +84 -0
- package/dist/lib/breakpoints.js.map +1 -0
- package/dist/lib/canvas-edit-chrome.d.ts +22 -0
- package/dist/lib/canvas-edit-chrome.d.ts.map +1 -0
- package/dist/lib/canvas-edit-chrome.js +81 -0
- package/dist/lib/canvas-edit-chrome.js.map +1 -0
- package/dist/lib/media-format.d.ts +55 -0
- package/dist/lib/media-format.d.ts.map +1 -0
- package/dist/lib/media-format.js +93 -0
- package/dist/lib/media-format.js.map +1 -0
- package/dist/lib/page-audit-input.d.ts +45 -0
- package/dist/lib/page-audit-input.d.ts.map +1 -0
- package/dist/lib/page-audit-input.js +53 -0
- package/dist/lib/page-audit-input.js.map +1 -0
- package/dist/lib/page-editor-service.d.ts +12 -0
- package/dist/lib/page-editor-service.d.ts.map +1 -1
- package/dist/lib/page-editor-service.js +6 -0
- package/dist/lib/page-editor-service.js.map +1 -1
- package/dist/lib/page-redirect.d.ts +39 -0
- package/dist/lib/page-redirect.d.ts.map +1 -0
- package/dist/lib/page-redirect.js +38 -0
- package/dist/lib/page-redirect.js.map +1 -0
- package/dist/lib/rail-width.d.ts +23 -0
- package/dist/lib/rail-width.d.ts.map +1 -0
- package/dist/lib/rail-width.js +59 -0
- package/dist/lib/rail-width.js.map +1 -0
- package/dist/lib/reflow-baseline.d.ts +45 -0
- package/dist/lib/reflow-baseline.d.ts.map +1 -0
- package/dist/lib/reflow-baseline.js +38 -0
- package/dist/lib/reflow-baseline.js.map +1 -0
- package/dist/lib/reflow-probe.d.ts +159 -0
- package/dist/lib/reflow-probe.d.ts.map +1 -0
- package/dist/lib/reflow-probe.js +228 -0
- package/dist/lib/reflow-probe.js.map +1 -0
- package/dist/lib/seo-service.d.ts +10 -0
- package/dist/lib/seo-service.d.ts.map +1 -1
- package/dist/lib/seo-service.js.map +1 -1
- package/dist/prenta-admin.css +1 -1
- package/dist/views/page-editor/CanvasMetaLine.d.ts +19 -0
- package/dist/views/page-editor/CanvasMetaLine.d.ts.map +1 -0
- package/dist/views/page-editor/CanvasMetaLine.js +23 -0
- package/dist/views/page-editor/CanvasMetaLine.js.map +1 -0
- package/dist/views/page-editor/EditorCanvas.d.ts +34 -8
- package/dist/views/page-editor/EditorCanvas.d.ts.map +1 -1
- package/dist/views/page-editor/EditorCanvas.js +68 -34
- package/dist/views/page-editor/EditorCanvas.js.map +1 -1
- package/dist/views/page-editor/EditorTopBar.d.ts +14 -1
- package/dist/views/page-editor/EditorTopBar.d.ts.map +1 -1
- package/dist/views/page-editor/EditorTopBar.js +8 -17
- package/dist/views/page-editor/EditorTopBar.js.map +1 -1
- package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
- package/dist/views/page-editor/PageSectionEditor.js +275 -53
- package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
- package/dist/views/page-editor/PageTab.d.ts +36 -0
- package/dist/views/page-editor/PageTab.d.ts.map +1 -0
- package/dist/views/page-editor/PageTab.js +65 -0
- package/dist/views/page-editor/PageTab.js.map +1 -0
- package/dist/views/page-editor/SectionInspector.d.ts.map +1 -1
- package/dist/views/page-editor/SectionInspector.js +63 -19
- package/dist/views/page-editor/SectionInspector.js.map +1 -1
- package/dist/views/page-editor/SectionsPanel.d.ts +30 -5
- package/dist/views/page-editor/SectionsPanel.d.ts.map +1 -1
- package/dist/views/page-editor/SectionsPanel.js +38 -7
- package/dist/views/page-editor/SectionsPanel.js.map +1 -1
- package/dist/views/page-editor/SitePreviewFrame.d.ts.map +1 -1
- package/dist/views/page-editor/SitePreviewFrame.js +3 -0
- package/dist/views/page-editor/SitePreviewFrame.js.map +1 -1
- package/dist/views/page-editor/reflow-context.d.ts +28 -0
- package/dist/views/page-editor/reflow-context.d.ts.map +1 -0
- package/dist/views/page-editor/reflow-context.js +14 -0
- package/dist/views/page-editor/reflow-context.js.map +1 -0
- package/dist/views/page-editor/sections/ByTheNumbersSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/ByTheNumbersSection.js +1 -1
- package/dist/views/page-editor/sections/ByTheNumbersSection.js.map +1 -1
- package/dist/views/page-editor/sections/CtaBannerSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/CtaBannerSection.js +1 -1
- package/dist/views/page-editor/sections/CtaBannerSection.js.map +1 -1
- package/dist/views/page-editor/sections/FeatureHighlightSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/FeatureHighlightSection.js +2 -2
- package/dist/views/page-editor/sections/FeatureHighlightSection.js.map +1 -1
- package/dist/views/page-editor/sections/GallerySection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/GallerySection.js +7 -3
- package/dist/views/page-editor/sections/GallerySection.js.map +1 -1
- package/dist/views/page-editor/sections/HeroBannerSection.js +1 -1
- package/dist/views/page-editor/sections/HeroBannerSection.js.map +1 -1
- package/dist/views/page-editor/sections/MissionSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/MissionSection.js +1 -1
- package/dist/views/page-editor/sections/MissionSection.js.map +1 -1
- package/dist/views/page-editor/sections/PullQuoteSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/PullQuoteSection.js +1 -1
- package/dist/views/page-editor/sections/PullQuoteSection.js.map +1 -1
- package/dist/views/page-editor/sections/RelatedPostsSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/RelatedPostsSection.js +1 -1
- package/dist/views/page-editor/sections/RelatedPostsSection.js.map +1 -1
- package/dist/views/page-editor/sections/SectionRenderer.d.ts.map +1 -1
- package/dist/views/page-editor/sections/SectionRenderer.js +49 -24
- package/dist/views/page-editor/sections/SectionRenderer.js.map +1 -1
- package/dist/views/page-editor/sections/admin-renderers.d.ts +47 -15
- package/dist/views/page-editor/sections/admin-renderers.d.ts.map +1 -1
- package/dist/views/page-editor/sections/admin-renderers.js +27 -15
- package/dist/views/page-editor/sections/admin-renderers.js.map +1 -1
- package/dist/views/page-editor/sections/parts.d.ts +0 -1
- package/dist/views/page-editor/sections/parts.d.ts.map +1 -1
- package/dist/views/page-editor/sections/parts.js +41 -16
- package/dist/views/page-editor/sections/parts.js.map +1 -1
- package/dist/views/page-editor/viewports.d.ts +7 -14
- package/dist/views/page-editor/viewports.d.ts.map +1 -1
- package/dist/views/page-editor/viewports.js +7 -12
- package/dist/views/page-editor/viewports.js.map +1 -1
- package/dist/views/post-editor/PostEditorCanvas.d.ts +2 -1
- package/dist/views/post-editor/PostEditorCanvas.d.ts.map +1 -1
- package/dist/views/post-editor/PostEditorCanvas.js +5 -2
- package/dist/views/post-editor/PostEditorCanvas.js.map +1 -1
- package/dist/views/post-editor/PostSectionEditor.d.ts.map +1 -1
- package/dist/views/post-editor/PostSectionEditor.js +2 -20
- package/dist/views/post-editor/PostSectionEditor.js.map +1 -1
- package/dist/views/post-editor/PostTemplateEditor.d.ts.map +1 -1
- package/dist/views/post-editor/PostTemplateEditor.js +4 -1
- package/dist/views/post-editor/PostTemplateEditor.js.map +1 -1
- package/package.json +5 -3
- package/src/AdminRoot.tsx +27 -6
- package/src/__tests__/components/breakpoint-controls.render.test.tsx +57 -0
- package/src/__tests__/components/canvas-edit-tip.render.test.tsx +41 -0
- package/src/__tests__/components/editor-rail.render.test.tsx +192 -0
- package/src/__tests__/components/media-block.render.test.tsx +126 -0
- package/src/__tests__/components/page-audit-panel.render.test.tsx +64 -0
- package/src/__tests__/components/reflow-meter.render.test.tsx +144 -0
- package/src/__tests__/components/seo-char-count.test.tsx +26 -6
- package/src/__tests__/components/serp-preview.render.test.tsx +32 -0
- package/src/__tests__/lib/breakpoints.test.ts +84 -0
- package/src/__tests__/lib/canvas-edit-chrome.test.ts +56 -0
- package/src/__tests__/lib/media-format.test.ts +89 -0
- package/src/__tests__/lib/page-audit-input.test.ts +144 -0
- package/src/__tests__/lib/page-editor-service.test.ts +2 -0
- package/src/__tests__/lib/page-redirect.test.ts +29 -0
- package/src/__tests__/lib/rail-width.test.ts +86 -0
- package/src/__tests__/lib/reflow-baseline.test.ts +64 -0
- package/src/__tests__/lib/reflow-probe.test.ts +95 -0
- package/src/__tests__/styles/canvas-container-queries.test.ts +103 -0
- package/src/__tests__/styles/packaging.test.ts +38 -0
- package/src/__tests__/styles/tokens-drift.test.ts +110 -0
- package/src/__tests__/views/admin-renderer-compat.test.ts +48 -0
- package/src/__tests__/views/admin-section-renderers.test.tsx +70 -4
- package/src/__tests__/views/editor-top-bar.render.test.tsx +1 -1
- package/src/__tests__/views/page-tab.render.test.tsx +226 -0
- package/src/__tests__/views/section-class-parity.test.ts +98 -0
- package/src/__tests__/views/sections-panel-design-owned.render.test.tsx +104 -0
- package/src/components/BreakpointPicker.tsx +114 -0
- package/src/components/CanvasEditTip.tsx +46 -0
- package/src/components/EditorRail.tsx +219 -0
- package/src/components/EditorRailTabs.tsx +117 -0
- package/src/components/MediaBlock.tsx +223 -0
- package/src/components/ReflowMeter.tsx +125 -0
- package/src/components/ZoomChip.tsx +39 -0
- package/src/components/breakpoint-icons.ts +17 -0
- package/src/components/page-tab/AuthorPicker.tsx +240 -0
- package/src/components/page-tab/DirectiveSwitch.tsx +86 -0
- package/src/components/seo/EditorSeoScoreBadge.tsx +9 -1
- package/src/components/seo/PageAuditPanel.tsx +192 -0
- package/src/components/seo/SeoCharCount.tsx +55 -24
- package/src/components/seo/SeoEditorPane.tsx +213 -31
- package/src/components/seo/SerpPreview.tsx +41 -0
- package/src/hooks/usePageAudit.ts +98 -0
- package/src/hooks/useReflowGuard.ts +96 -0
- package/src/lib/breakpoints.ts +107 -0
- package/src/lib/canvas-edit-chrome.ts +82 -0
- package/src/lib/media-format.ts +99 -0
- package/src/lib/page-audit-input.ts +104 -0
- package/src/lib/page-editor-service.ts +18 -0
- package/src/lib/page-redirect.ts +60 -0
- package/src/lib/rail-width.ts +58 -0
- package/src/lib/reflow-baseline.ts +70 -0
- package/src/lib/reflow-probe.ts +299 -0
- package/src/lib/seo-service.ts +10 -0
- package/src/styles/prenta-tokens.css +120 -42
- package/src/styles/theme.css +130 -0
- package/src/views/page-editor/CanvasMetaLine.tsx +50 -0
- package/src/views/page-editor/EditorCanvas.tsx +109 -50
- package/src/views/page-editor/EditorTopBar.tsx +35 -43
- package/src/views/page-editor/PageSectionEditor.tsx +419 -148
- package/src/views/page-editor/PageTab.tsx +433 -0
- package/src/views/page-editor/SectionInspector.tsx +82 -41
- package/src/views/page-editor/SectionsPanel.tsx +281 -140
- package/src/views/page-editor/SitePreviewFrame.tsx +3 -0
- package/src/views/page-editor/reflow-context.ts +43 -0
- package/src/views/page-editor/sections/ByTheNumbersSection.tsx +3 -2
- package/src/views/page-editor/sections/CtaBannerSection.tsx +3 -1
- package/src/views/page-editor/sections/FeatureHighlightSection.tsx +3 -2
- package/src/views/page-editor/sections/GallerySection.tsx +7 -3
- package/src/views/page-editor/sections/HeroBannerSection.tsx +2 -2
- package/src/views/page-editor/sections/MissionSection.tsx +4 -2
- package/src/views/page-editor/sections/PullQuoteSection.tsx +3 -1
- package/src/views/page-editor/sections/RelatedPostsSection.tsx +2 -1
- package/src/views/page-editor/sections/SectionRenderer.tsx +69 -29
- package/src/views/page-editor/sections/admin-renderers.tsx +54 -15
- package/src/views/page-editor/sections/parts.tsx +46 -18
- package/src/views/page-editor/viewports.ts +13 -26
- package/src/views/post-editor/PostEditorCanvas.tsx +18 -11
- package/src/views/post-editor/PostSectionEditor.tsx +1 -56
- package/src/views/post-editor/PostTemplateEditor.tsx +3 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostTemplateEditor.js","sourceRoot":"","sources":["../../../src/views/post-editor/PostTemplateEditor.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"PostTemplateEditor.js","sourceRoot":"","sources":["../../../src/views/post-editor/PostTemplateEditor.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prenta/admin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.93.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -98,15 +98,16 @@
|
|
|
98
98
|
"tailwindcss": "^4.0.0",
|
|
99
99
|
"typescript": "^5.7.0",
|
|
100
100
|
"vitest": "^4.1.0",
|
|
101
|
-
"@prenta/core": "0.118.0",
|
|
102
101
|
"@prenta/component-blocks": "0.3.0",
|
|
102
|
+
"@prenta/core": "0.119.0",
|
|
103
103
|
"@prenta/plugin-ai": "0.6.0",
|
|
104
104
|
"@prenta/plugin-blocks": "0.2.0",
|
|
105
105
|
"@prenta/plugin-commerce": "0.2.0",
|
|
106
106
|
"@prenta/plugin-forms": "0.1.0",
|
|
107
107
|
"@prenta/plugin-media": "0.2.0",
|
|
108
108
|
"@prenta/plugin-navigation": "0.3.0",
|
|
109
|
-
"@prenta/plugin-seo": "0.1.0"
|
|
109
|
+
"@prenta/plugin-seo": "0.1.0",
|
|
110
|
+
"@prenta/sections-react": "0.16.0"
|
|
110
111
|
},
|
|
111
112
|
"scripts": {
|
|
112
113
|
"build": "tsc --project tsconfig.json && npx @tailwindcss/cli -i src/styles/build-input.css -o dist/prenta-admin.css --minify",
|
|
@@ -115,6 +116,7 @@
|
|
|
115
116
|
"dev:tsc": "tsc --project tsconfig.json --watch --preserveWatchOutput",
|
|
116
117
|
"dev:css": "npx @tailwindcss/cli -i src/styles/build-input.css -o dist/prenta-admin.css --watch",
|
|
117
118
|
"type-check": "tsc --noEmit",
|
|
119
|
+
"generate": "node scripts/generate-tokens.mjs",
|
|
118
120
|
"test": "vitest run",
|
|
119
121
|
"clean": "rm -rf dist .turbo"
|
|
120
122
|
}
|
package/src/AdminRoot.tsx
CHANGED
|
@@ -106,12 +106,33 @@ export interface AdminRootProps {
|
|
|
106
106
|
onLogout?: () => void | Promise<void>
|
|
107
107
|
captchaConfig?: { provider: 'recaptcha' | 'turnstile' | 'none'; siteKey: string | null }
|
|
108
108
|
/**
|
|
109
|
-
* Canvas renderers
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
109
|
+
* Canvas renderers keyed by section-type id, used by the page/post editor
|
|
110
|
+
* canvas and the eye preview.
|
|
111
|
+
*
|
|
112
|
+
* Resolution order is **supplied renderer → built-in → placeholder**. A
|
|
113
|
+
* renderer here wins for EVERY type, including the built-ins (hero, text,
|
|
114
|
+
* feature, stats, cta and the rest) — that is the point of the prop: hand
|
|
115
|
+
* the admin the same components you register for the public site and the
|
|
116
|
+
* canvas previews what actually ships, at the same sizes and weights.
|
|
117
|
+
*
|
|
118
|
+
* Pass `DEFAULT_SECTION_RENDERERS` from `@prenta/sections-react` for the
|
|
119
|
+
* built-ins, spreading your own map over it for custom types:
|
|
120
|
+
*
|
|
121
|
+
* ```tsx
|
|
122
|
+
* sectionRenderers={{ ...DEFAULT_SECTION_RENDERERS, ...myRenderers }}
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* Omitting the prop keeps the admin's own approximations of the built-in
|
|
126
|
+
* types, which differ from the public components in font size, weight and
|
|
127
|
+
* breakpoints, and renders custom types as a structural placeholder.
|
|
128
|
+
*
|
|
129
|
+
* Renderers run inside the admin bundle, so they must be client-safe. Each
|
|
130
|
+
* is wrapped in an error boundary: one that throws falls back to the
|
|
131
|
+
* built-in for that type, or to the placeholder if the type has none.
|
|
132
|
+
*
|
|
133
|
+
* Their Tailwind classes are NOT in the admin's precompiled stylesheet —
|
|
134
|
+
* import `@prenta/sections-react/styles.css` (or your own equivalent) on
|
|
135
|
+
* the admin route, or the canvas renders correct markup unstyled.
|
|
115
136
|
*/
|
|
116
137
|
sectionRenderers?: AdminSectionRendererMap
|
|
117
138
|
/** Browser Sentry DSN for admin error reporting (e.g. `NEXT_PUBLIC_SENTRY_DSN`). */
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
3
|
+
import { fireEvent, render, screen } from '@testing-library/react'
|
|
4
|
+
import { BreakpointPicker } from '../../components/BreakpointPicker.js'
|
|
5
|
+
import { ZoomChip } from '../../components/ZoomChip.js'
|
|
6
|
+
|
|
7
|
+
describe('BreakpointPicker', () => {
|
|
8
|
+
it('names the current breakpoint and its width to assistive tech', () => {
|
|
9
|
+
render(<BreakpointPicker value="tabletL" onChange={vi.fn()} />)
|
|
10
|
+
// The visible label collapses to an abbreviation at narrow header widths,
|
|
11
|
+
// so the accessible name has to carry the full fact on its own.
|
|
12
|
+
expect(screen.getByRole('button', { name: /Tablet Landscape, 1024 pixels/i })).toBeTruthy()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('renders 4K at 2560, not the physical pixel count', () => {
|
|
16
|
+
render(<BreakpointPicker value="4k" onChange={vi.fn()} />)
|
|
17
|
+
expect(screen.getByRole('button', { name: /2560 pixels/i })).toBeTruthy()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('exposes collapsed state on the trigger', () => {
|
|
21
|
+
render(<BreakpointPicker value="wide" onChange={vi.fn()} />)
|
|
22
|
+
expect(screen.getByRole('button').getAttribute('aria-expanded')).toBe('false')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('does not open when disabled', () => {
|
|
26
|
+
render(<BreakpointPicker value="wide" onChange={vi.fn()} disabled />)
|
|
27
|
+
const trigger = screen.getByRole('button')
|
|
28
|
+
expect(trigger.hasAttribute('disabled')).toBe(true)
|
|
29
|
+
fireEvent.click(trigger)
|
|
30
|
+
expect(screen.queryByRole('menu')).toBeNull()
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
describe('ZoomChip', () => {
|
|
35
|
+
it('shows the measured scale, not the mode', () => {
|
|
36
|
+
// "fit" is not a number an editor can act on; 38% explains why a 1920px
|
|
37
|
+
// preview looks small in a narrow column.
|
|
38
|
+
render(<ZoomChip zoom="fit" scale={0.38} onChange={vi.fn()} />)
|
|
39
|
+
expect(screen.getByRole('button').textContent).toBe('38%')
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('toggles fit to actual size and back', () => {
|
|
43
|
+
const onChange = vi.fn()
|
|
44
|
+
const { rerender } = render(<ZoomChip zoom="fit" scale={0.42} onChange={onChange} />)
|
|
45
|
+
fireEvent.click(screen.getByRole('button'))
|
|
46
|
+
expect(onChange).toHaveBeenCalledWith(1)
|
|
47
|
+
|
|
48
|
+
rerender(<ZoomChip zoom={1} scale={1} onChange={onChange} />)
|
|
49
|
+
fireEvent.click(screen.getByRole('button'))
|
|
50
|
+
expect(onChange).toHaveBeenLastCalledWith('fit')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('describes what clicking will do', () => {
|
|
54
|
+
render(<ZoomChip zoom="fit" scale={0.42} onChange={vi.fn()} />)
|
|
55
|
+
expect(screen.getByRole('button', { name: /Switch to actual size/i })).toBeTruthy()
|
|
56
|
+
})
|
|
57
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
3
|
+
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
|
4
|
+
import { CANVAS_EDIT_TIP_STORAGE_KEY } from '../../lib/canvas-edit-chrome.js'
|
|
5
|
+
|
|
6
|
+
// happy-dom localStorage is non-functional in this Node setup — stub a Map.
|
|
7
|
+
const storage = new Map<string, string>()
|
|
8
|
+
vi.stubGlobal('localStorage', {
|
|
9
|
+
getItem: (key: string) => storage.get(key) ?? null,
|
|
10
|
+
setItem: (key: string, value: string) => void storage.set(key, String(value)),
|
|
11
|
+
removeItem: (key: string) => void storage.delete(key),
|
|
12
|
+
clear: () => storage.clear(),
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const { CanvasEditTip } = await import('../../components/CanvasEditTip.js')
|
|
16
|
+
|
|
17
|
+
describe('CanvasEditTip', () => {
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
storage.clear()
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('shows editing tip until dismissed', async () => {
|
|
23
|
+
render(<CanvasEditTip />)
|
|
24
|
+
expect(await screen.findByRole('note')).toBeTruthy()
|
|
25
|
+
expect(screen.getByText(/Editing tip/i)).toBeTruthy()
|
|
26
|
+
|
|
27
|
+
fireEvent.click(screen.getByRole('button', { name: 'Dismiss editing tip' }))
|
|
28
|
+
await waitFor(() => {
|
|
29
|
+
expect(screen.queryByRole('note')).toBeNull()
|
|
30
|
+
})
|
|
31
|
+
expect(localStorage.getItem(CANVAS_EDIT_TIP_STORAGE_KEY)).toBe('1')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('stays hidden when already dismissed', async () => {
|
|
35
|
+
localStorage.setItem(CANVAS_EDIT_TIP_STORAGE_KEY, '1')
|
|
36
|
+
render(<CanvasEditTip />)
|
|
37
|
+
await waitFor(() => {
|
|
38
|
+
expect(screen.queryByRole('note')).toBeNull()
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
})
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
3
|
+
import { fireEvent, render, screen } from '@testing-library/react'
|
|
4
|
+
import { EditorRail, RailHeader } from '../../components/EditorRail.js'
|
|
5
|
+
import { EditorRailTabs, type RailTab } from '../../components/EditorRailTabs.js'
|
|
6
|
+
|
|
7
|
+
const storage = new Map<string, string>()
|
|
8
|
+
vi.stubGlobal('localStorage', {
|
|
9
|
+
getItem: (k: string) => storage.get(k) ?? null,
|
|
10
|
+
setItem: (k: string, v: string) => void storage.set(k, String(v)),
|
|
11
|
+
removeItem: (k: string) => void storage.delete(k),
|
|
12
|
+
clear: () => storage.clear(),
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
function renderRail() {
|
|
16
|
+
return render(
|
|
17
|
+
<EditorRail collapsedLabel="Sections">
|
|
18
|
+
{({ width, dragging, collapse }) => (
|
|
19
|
+
<>
|
|
20
|
+
<RailHeader
|
|
21
|
+
title="Page content"
|
|
22
|
+
width={width}
|
|
23
|
+
dragging={dragging}
|
|
24
|
+
onCollapse={collapse}
|
|
25
|
+
/>
|
|
26
|
+
<p>panel body</p>
|
|
27
|
+
</>
|
|
28
|
+
)}
|
|
29
|
+
</EditorRail>,
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe('EditorRail', () => {
|
|
34
|
+
it('exposes the resize handle as an operable separator', () => {
|
|
35
|
+
// A bare div with a pointerdown handler is invisible to keyboard and
|
|
36
|
+
// assistive-tech users — the role and value range are what make the rail
|
|
37
|
+
// resizable without a mouse.
|
|
38
|
+
renderRail()
|
|
39
|
+
const handle = screen.getByRole('separator', { name: 'Resize panel' })
|
|
40
|
+
expect(handle.getAttribute('aria-orientation')).toBe('vertical')
|
|
41
|
+
expect(handle.getAttribute('aria-valuemin')).toBe('300')
|
|
42
|
+
expect(handle.getAttribute('aria-valuemax')).toBe('620')
|
|
43
|
+
expect(handle.getAttribute('tabindex')).toBe('0')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('resizes with arrow keys and clamps at the range edges', () => {
|
|
47
|
+
renderRail()
|
|
48
|
+
const handle = screen.getByRole('separator', { name: 'Resize panel' })
|
|
49
|
+
|
|
50
|
+
fireEvent.keyDown(handle, { key: 'ArrowRight' })
|
|
51
|
+
expect(handle.getAttribute('aria-valuenow')).toBe('376')
|
|
52
|
+
|
|
53
|
+
fireEvent.keyDown(handle, { key: 'ArrowLeft', shiftKey: true })
|
|
54
|
+
expect(handle.getAttribute('aria-valuenow')).toBe('328')
|
|
55
|
+
|
|
56
|
+
for (let i = 0; i < 10; i++) fireEvent.keyDown(handle, { key: 'ArrowLeft', shiftKey: true })
|
|
57
|
+
expect(handle.getAttribute('aria-valuenow')).toBe('300')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('resets to the default width on Home', () => {
|
|
61
|
+
renderRail()
|
|
62
|
+
const handle = screen.getByRole('separator', { name: 'Resize panel' })
|
|
63
|
+
fireEvent.keyDown(handle, { key: 'ArrowRight' })
|
|
64
|
+
fireEvent.keyDown(handle, { key: 'Home' })
|
|
65
|
+
expect(handle.getAttribute('aria-valuenow')).toBe('360')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('resets to the default width on double-click', () => {
|
|
69
|
+
renderRail()
|
|
70
|
+
const handle = screen.getByRole('separator', { name: 'Resize panel' })
|
|
71
|
+
fireEvent.keyDown(handle, { key: 'ArrowRight' })
|
|
72
|
+
fireEvent.doubleClick(handle)
|
|
73
|
+
expect(handle.getAttribute('aria-valuenow')).toBe('360')
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('persists the width across mounts', () => {
|
|
77
|
+
const first = renderRail()
|
|
78
|
+
fireEvent.keyDown(screen.getByRole('separator', { name: 'Resize panel' }), {
|
|
79
|
+
key: 'ArrowRight',
|
|
80
|
+
shiftKey: true,
|
|
81
|
+
})
|
|
82
|
+
expect(localStorage.getItem('pb.panelW')).toBe('408')
|
|
83
|
+
first.unmount()
|
|
84
|
+
|
|
85
|
+
renderRail()
|
|
86
|
+
expect(
|
|
87
|
+
screen.getByRole('separator', { name: 'Resize panel' }).getAttribute('aria-valuenow'),
|
|
88
|
+
).toBe('408')
|
|
89
|
+
storage.clear()
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('unmounts the panel when collapsed instead of leaving a zero-width sliver', () => {
|
|
93
|
+
// A 0-width panel keeps its contents in the accessibility tree, so a
|
|
94
|
+
// screen-reader user lands inside a panel sighted users cannot see.
|
|
95
|
+
renderRail()
|
|
96
|
+
fireEvent.click(screen.getByRole('button', { name: 'Collapse Page content panel' }))
|
|
97
|
+
|
|
98
|
+
expect(screen.queryByText('panel body')).toBeNull()
|
|
99
|
+
expect(screen.queryByRole('separator', { name: 'Resize panel' })).toBeNull()
|
|
100
|
+
expect(screen.getByRole('button', { name: 'Expand Sections panel' })).toBeTruthy()
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('restores the panel from the collapsed strip', () => {
|
|
104
|
+
renderRail()
|
|
105
|
+
fireEvent.click(screen.getByRole('button', { name: 'Collapse Page content panel' }))
|
|
106
|
+
fireEvent.click(screen.getByRole('button', { name: 'Expand Sections panel' }))
|
|
107
|
+
expect(screen.getByText('panel body')).toBeTruthy()
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
const TABS: RailTab[] = [
|
|
112
|
+
{ id: 'sections', label: 'Sections', title: 'Page content', count: 4 },
|
|
113
|
+
{ id: 'seo', label: 'SEO & GEO', title: 'Search & AI readiness', score: 72 },
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
describe('EditorRailTabs', () => {
|
|
117
|
+
it('marks the active tab and links it to its panel', () => {
|
|
118
|
+
render(<EditorRailTabs tabs={TABS} active="sections" onChange={vi.fn()} />)
|
|
119
|
+
const active = screen.getByRole('tab', { selected: true })
|
|
120
|
+
expect(active.textContent).toContain('Sections')
|
|
121
|
+
expect(active.getAttribute('aria-controls')).toBe('rail-panel-sections')
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('shows the section count without opening the tab', () => {
|
|
125
|
+
render(<EditorRailTabs tabs={TABS} active="seo" onChange={vi.fn()} />)
|
|
126
|
+
expect(screen.getByRole('tab', { name: /Sections/ }).textContent).toContain('4')
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('carries the score as text, not colour alone', () => {
|
|
130
|
+
// The band dot is aria-hidden; anyone who cannot distinguish the hues still
|
|
131
|
+
// needs the number.
|
|
132
|
+
render(<EditorRailTabs tabs={TABS} active="sections" onChange={vi.fn()} />)
|
|
133
|
+
expect(screen.getByRole('tab', { name: /score 72 of 100/i })).toBeTruthy()
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
it('moves between tabs with arrow keys', () => {
|
|
137
|
+
// Inactive tabs have tabIndex -1, so arrows are the only way to reach them.
|
|
138
|
+
const onChange = vi.fn()
|
|
139
|
+
render(<EditorRailTabs tabs={TABS} active="sections" onChange={onChange} />)
|
|
140
|
+
fireEvent.keyDown(screen.getByRole('tab', { selected: true }), { key: 'ArrowRight' })
|
|
141
|
+
expect(onChange).toHaveBeenCalledWith('seo')
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('bands the dot on the audit scale, not the content-analysis one', () => {
|
|
145
|
+
// The two disagree between 55 and 59: `gradeFromScore` calls 57 "poor",
|
|
146
|
+
// the audit calls it "fair". The dot summarises the audit's rings, so a
|
|
147
|
+
// page scoring 57 must not read worse on the tab than in the panel.
|
|
148
|
+
render(
|
|
149
|
+
<EditorRailTabs
|
|
150
|
+
tabs={[{ id: 'seo', label: 'SEO & GEO', title: 'x', score: 57 }]}
|
|
151
|
+
active="seo"
|
|
152
|
+
onChange={vi.fn()}
|
|
153
|
+
/>,
|
|
154
|
+
)
|
|
155
|
+
const dot = screen.getByRole('tab').querySelector('span[aria-hidden]')
|
|
156
|
+
expect(dot?.className).toContain('bg-warning')
|
|
157
|
+
expect(dot?.className).not.toContain('bg-destructive')
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('shows no dot at all until a score is known', () => {
|
|
161
|
+
// An absent audit must not borrow a number from another scorer — no dot
|
|
162
|
+
// beats a dot computed by a different model with different bands.
|
|
163
|
+
render(
|
|
164
|
+
<EditorRailTabs
|
|
165
|
+
tabs={[{ id: 'seo', label: 'SEO & GEO', title: 'x' }]}
|
|
166
|
+
active="seo"
|
|
167
|
+
onChange={vi.fn()}
|
|
168
|
+
/>,
|
|
169
|
+
)
|
|
170
|
+
expect(screen.getByRole('tab').querySelector('span[aria-hidden]')).toBeNull()
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
it('reads a deliberately unrated page as not rated, never as a low score', () => {
|
|
174
|
+
render(
|
|
175
|
+
<EditorRailTabs
|
|
176
|
+
tabs={[{ id: 'seo', label: 'SEO & GEO', title: 'x', score: null }]}
|
|
177
|
+
active="seo"
|
|
178
|
+
onChange={vi.fn()}
|
|
179
|
+
/>,
|
|
180
|
+
)
|
|
181
|
+
expect(screen.getByRole('tab', { name: /not rated/i })).toBeTruthy()
|
|
182
|
+
const dot = screen.getByRole('tab').querySelector('span[aria-hidden]')
|
|
183
|
+
expect(dot?.className).not.toContain('bg-destructive')
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it('wraps around at the ends', () => {
|
|
187
|
+
const onChange = vi.fn()
|
|
188
|
+
render(<EditorRailTabs tabs={TABS} active="sections" onChange={onChange} />)
|
|
189
|
+
fireEvent.keyDown(screen.getByRole('tab', { selected: true }), { key: 'ArrowLeft' })
|
|
190
|
+
expect(onChange).toHaveBeenCalledWith('seo')
|
|
191
|
+
})
|
|
192
|
+
})
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { describe, expect, it, vi, afterEach } from 'vitest'
|
|
3
|
+
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
|
|
4
|
+
|
|
5
|
+
const LIBRARY = {
|
|
6
|
+
items: [
|
|
7
|
+
{
|
|
8
|
+
id: 'm1',
|
|
9
|
+
filename: 'team-offsite-2026.jpg',
|
|
10
|
+
storageKey: 'k1',
|
|
11
|
+
url: '/media/team-offsite-2026.jpg',
|
|
12
|
+
mimeType: 'image/jpeg',
|
|
13
|
+
width: 2400,
|
|
14
|
+
height: 1600,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 'm2',
|
|
18
|
+
filename: 'notes.pdf',
|
|
19
|
+
storageKey: 'k2',
|
|
20
|
+
url: '/media/notes.pdf',
|
|
21
|
+
mimeType: 'application/pdf',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* `useApiData` is mocked rather than `fetch`: the hook layers caching, retries
|
|
28
|
+
* and abort handling on top, none of which this component owns, and driving it
|
|
29
|
+
* through a fake network makes the test about the hook instead of the block.
|
|
30
|
+
*/
|
|
31
|
+
let requested: string | null = null
|
|
32
|
+
|
|
33
|
+
vi.mock('../../lib/useApiData.js', () => ({
|
|
34
|
+
useApiData: (endpoint: string | null) => {
|
|
35
|
+
requested = endpoint
|
|
36
|
+
return { data: endpoint ? LIBRARY : null, loading: false, error: null, refetch: vi.fn() }
|
|
37
|
+
},
|
|
38
|
+
}))
|
|
39
|
+
|
|
40
|
+
const { MediaBlock } = await import('../../components/MediaBlock.js')
|
|
41
|
+
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
cleanup()
|
|
44
|
+
requested = null
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
describe('MediaBlock', () => {
|
|
48
|
+
it('shows the toolbar without hovering, in both states', () => {
|
|
49
|
+
// Replace and Remove are the two things an editor comes here to do. Behind
|
|
50
|
+
// a hover they are undiscoverable on touch and invisible when scanning.
|
|
51
|
+
render(<MediaBlock value="" onChange={() => {}} />)
|
|
52
|
+
expect(screen.getByRole('button', { name: 'Choose' })).toBeTruthy()
|
|
53
|
+
cleanup()
|
|
54
|
+
|
|
55
|
+
render(<MediaBlock value="/media/hero.jpg" onChange={() => {}} label="Hero image" />)
|
|
56
|
+
expect(screen.getByRole('button', { name: 'Replace' })).toBeTruthy()
|
|
57
|
+
expect(screen.getByRole('button', { name: 'Remove hero image' })).toBeTruthy()
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('names the file and its format rather than the raw URL', () => {
|
|
61
|
+
render(
|
|
62
|
+
<MediaBlock value="https://cdn.example.com/a/team-offsite.jpg?sig=abc" onChange={() => {}} />,
|
|
63
|
+
)
|
|
64
|
+
expect(screen.getByText('team-offsite.jpg')).toBeTruthy()
|
|
65
|
+
expect(screen.getByText('JPG')).toBeTruthy()
|
|
66
|
+
// The signing token is noise in a narrow toolbar and never what is being read.
|
|
67
|
+
expect(screen.queryByText(/sig=abc/)).toBeNull()
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('opens the picker inside the shell, not as a dialog', () => {
|
|
71
|
+
// Choosing an image is a comparison against the slot it goes into. A modal
|
|
72
|
+
// covering the slot removes the only context that matters.
|
|
73
|
+
render(<MediaBlock value="" onChange={() => {}} />)
|
|
74
|
+
fireEvent.click(screen.getByRole('button', { name: 'Choose' }))
|
|
75
|
+
expect(screen.getByText('team-offsite-2026.jpg')).toBeTruthy()
|
|
76
|
+
expect(screen.queryByRole('dialog')).toBeNull()
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('reports each asset’s real dimensions and ratio', () => {
|
|
80
|
+
render(<MediaBlock value="" onChange={() => {}} />)
|
|
81
|
+
fireEvent.click(screen.getByRole('button', { name: 'Choose' }))
|
|
82
|
+
// The frame shows the template's crop, so the asset's own shape has to be
|
|
83
|
+
// stated somewhere or an editor cannot tell what will be cropped.
|
|
84
|
+
expect(screen.getByText('2400 × 1600 · 3:2')).toBeTruthy()
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('offers only images', () => {
|
|
88
|
+
render(<MediaBlock value="" onChange={() => {}} />)
|
|
89
|
+
fireEvent.click(screen.getByRole('button', { name: 'Choose' }))
|
|
90
|
+
expect(screen.getByText('team-offsite-2026.jpg')).toBeTruthy()
|
|
91
|
+
expect(screen.queryByText('notes.pdf')).toBeNull()
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('returns the chosen asset with its dimensions', () => {
|
|
95
|
+
const onChange = vi.fn()
|
|
96
|
+
render(<MediaBlock value="" onChange={onChange} />)
|
|
97
|
+
fireEvent.click(screen.getByRole('button', { name: 'Choose' }))
|
|
98
|
+
fireEvent.click(screen.getByText('team-offsite-2026.jpg'))
|
|
99
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
100
|
+
'/media/team-offsite-2026.jpg',
|
|
101
|
+
expect.objectContaining({ width: 2400, height: 1600 }),
|
|
102
|
+
)
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('clears the slot with an empty url', () => {
|
|
106
|
+
const onChange = vi.fn()
|
|
107
|
+
render(<MediaBlock value="/media/hero.jpg" onChange={onChange} />)
|
|
108
|
+
fireEvent.click(screen.getByRole('button', { name: 'Remove image' }))
|
|
109
|
+
expect(onChange).toHaveBeenCalledWith('')
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('disables every control when the editor cannot edit', () => {
|
|
113
|
+
render(<MediaBlock value="/media/hero.jpg" onChange={() => {}} disabled />)
|
|
114
|
+
expect(screen.getByRole('button', { name: 'Replace' }).hasAttribute('disabled')).toBe(true)
|
|
115
|
+
expect(screen.getByRole('button', { name: 'Remove image' }).hasAttribute('disabled')).toBe(true)
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
describe('MediaBlock — library requests', () => {
|
|
120
|
+
it('does not fetch the library until the picker is opened', () => {
|
|
121
|
+
render(<MediaBlock value="/media/hero.jpg" onChange={() => {}} />)
|
|
122
|
+
expect(requested).toBeNull()
|
|
123
|
+
fireEvent.click(screen.getByRole('button', { name: 'Replace' }))
|
|
124
|
+
expect(requested).toContain('/media')
|
|
125
|
+
})
|
|
126
|
+
})
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
import { render, screen } from '@testing-library/react'
|
|
4
|
+
import { auditPage, type PageAuditInput } from '@prenta/core/seo/page-audit'
|
|
5
|
+
import { PageAuditPanel } from '../../components/seo/PageAuditPanel.js'
|
|
6
|
+
|
|
7
|
+
const blank: PageAuditInput = {
|
|
8
|
+
sections: [],
|
|
9
|
+
seo: {
|
|
10
|
+
title: '',
|
|
11
|
+
description: '',
|
|
12
|
+
slug: '',
|
|
13
|
+
keyword: '',
|
|
14
|
+
schema: '',
|
|
15
|
+
ogImage: null,
|
|
16
|
+
robots: { index: true, snippet: true },
|
|
17
|
+
},
|
|
18
|
+
llmsTxt: false,
|
|
19
|
+
brand: 'Prenta',
|
|
20
|
+
author: null,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe('PageAuditPanel', () => {
|
|
24
|
+
it('states both scores in text, not colour alone', () => {
|
|
25
|
+
render(<PageAuditPanel audit={auditPage(blank)} />)
|
|
26
|
+
expect(screen.getByRole('img', { name: /SEO score: 0 of 100/i })).toBeTruthy()
|
|
27
|
+
expect(screen.getByRole('img', { name: /GEO score: 0 of 100/i })).toBeTruthy()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('names the denominator so a moving score is explainable', () => {
|
|
31
|
+
// The score changes when the set of applicable checks changes. Showing
|
|
32
|
+
// only the number is what made the old scorer feel arbitrary.
|
|
33
|
+
render(<PageAuditPanel audit={auditPage(blank)} />)
|
|
34
|
+
expect(screen.getAllByText(/of \d+ apply/).length).toBe(2)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('reads a gated group as not rated rather than zero', () => {
|
|
38
|
+
const audit = auditPage({
|
|
39
|
+
...blank,
|
|
40
|
+
seo: { ...blank.seo, robots: { index: false, snippet: true } },
|
|
41
|
+
})
|
|
42
|
+
render(<PageAuditPanel audit={audit} />)
|
|
43
|
+
expect(screen.getByRole('img', { name: /SEO: not rated/i })).toBeTruthy()
|
|
44
|
+
expect(screen.getByText('not rated')).toBeTruthy()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('gives every check an outcome in text for screen readers', () => {
|
|
48
|
+
render(<PageAuditPanel audit={auditPage(blank)} />)
|
|
49
|
+
// The status square is aria-hidden, so the outcome has to live in the row.
|
|
50
|
+
expect(screen.getAllByText(/needs attention/).length).toBeGreaterThan(0)
|
|
51
|
+
expect(screen.getAllByText(/not applicable/).length).toBeGreaterThan(0)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('explains a not-applicable check instead of just greying it', () => {
|
|
55
|
+
render(<PageAuditPanel audit={auditPage(blank)} />)
|
|
56
|
+
// All three placement checks explain themselves — none is silently greyed.
|
|
57
|
+
expect(screen.getAllByText(/Set a focus keyword to enable this check/i)).toHaveLength(3)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('tells the editor what to do about a failing check', () => {
|
|
61
|
+
render(<PageAuditPanel audit={auditPage(blank)} />)
|
|
62
|
+
expect(screen.getByText(/Aim for 30–60 characters/i)).toBeTruthy()
|
|
63
|
+
})
|
|
64
|
+
})
|