@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
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { PageSection } from '@prenta/core/page-sections'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The content a page's sections had when they were last live.
|
|
5
|
+
*
|
|
6
|
+
* ── What "baseline" means here, and why ───────────────────────────────────
|
|
7
|
+
*
|
|
8
|
+
* The guard answers "will this edit change how the live page wraps?" — so the
|
|
9
|
+
* baseline has to be what is actually on the site, not what was last saved.
|
|
10
|
+
*
|
|
11
|
+
* This CMS has no draft/published split: a document carries one `status` and
|
|
12
|
+
* saving a PUBLISHED page updates the live content in place. So for a published
|
|
13
|
+
* page the live content is whatever the editor loaded, refreshed on every save
|
|
14
|
+
* and publish. For a page that has never been published there is no baseline at
|
|
15
|
+
* all, and the guard reports line counts without deltas — correctly, because
|
|
16
|
+
* there is no live layout to break.
|
|
17
|
+
*
|
|
18
|
+
* Deliberately NOT sourced from the versions API. Versions do hold full
|
|
19
|
+
* snapshots, but they record every update, so finding "the published one" means
|
|
20
|
+
* scanning history and guessing which entry was live — an extra request and a
|
|
21
|
+
* heuristic, to reconstruct something the editor already has in hand.
|
|
22
|
+
*/
|
|
23
|
+
export interface ReflowBaseline {
|
|
24
|
+
byId: Map<string, Record<string, unknown>>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Snapshot section content, or `null` when the page is not live.
|
|
29
|
+
*
|
|
30
|
+
* `null` rather than an empty snapshot: an empty baseline would read as "every
|
|
31
|
+
* field was previously blank" and flag every line of existing copy as newly
|
|
32
|
+
* added.
|
|
33
|
+
*/
|
|
34
|
+
export function snapshotBaseline(
|
|
35
|
+
sections: readonly PageSection[],
|
|
36
|
+
status: string,
|
|
37
|
+
): ReflowBaseline | null {
|
|
38
|
+
if (status !== 'PUBLISHED') return null
|
|
39
|
+
return {
|
|
40
|
+
byId: new Map(sections.map((s) => [s.id, { ...(s.content ?? {}) }])),
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Resolve a `data-cms-field` path against a baseline.
|
|
46
|
+
*
|
|
47
|
+
* Paths are dotted and may index arrays (`stats.0.label`), matching the markers
|
|
48
|
+
* the renderers emit.
|
|
49
|
+
*
|
|
50
|
+
* Returns `undefined` for anything that is not baseline text — no snapshot, a
|
|
51
|
+
* section added since publish, a field that did not exist, or a non-string
|
|
52
|
+
* value. The guard reads `undefined` as "nothing to compare against" and
|
|
53
|
+
* reports no delta, which is the truthful answer in every one of those cases.
|
|
54
|
+
*/
|
|
55
|
+
export function baselineFieldText(
|
|
56
|
+
baseline: ReflowBaseline | null,
|
|
57
|
+
sectionId: string,
|
|
58
|
+
fieldPath: string,
|
|
59
|
+
): string | undefined {
|
|
60
|
+
const content = baseline?.byId.get(sectionId)
|
|
61
|
+
if (!content) return undefined
|
|
62
|
+
|
|
63
|
+
let cursor: unknown = content
|
|
64
|
+
for (const key of fieldPath.split('.')) {
|
|
65
|
+
if (cursor === null || typeof cursor !== 'object') return undefined
|
|
66
|
+
cursor = (cursor as Record<string, unknown>)[key]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return typeof cursor === 'string' ? cursor : undefined
|
|
70
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { BREAKPOINTS, type BreakpointId } from './breakpoints.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Measures how a field's copy wraps at every breakpoint, by laying it out for
|
|
5
|
+
* real rather than estimating.
|
|
6
|
+
*
|
|
7
|
+
* ── Why not a class chain ─────────────────────────────────────────────────
|
|
8
|
+
*
|
|
9
|
+
* The design handoff specifies rebuilding each probe from a hardcoded list of
|
|
10
|
+
* wrapper classes per guarded field, and warns twice that a width cap outside
|
|
11
|
+
* that list makes the guard lie — at wide breakpoints only, so it looks correct
|
|
12
|
+
* on mobile. By the handoff's own account that list drifted twice.
|
|
13
|
+
*
|
|
14
|
+
* A chain is a second source of truth that has to track the renderers' markup
|
|
15
|
+
* by hand. Worse here: the prototype had semantic classes (`.pv-hero-h`), while
|
|
16
|
+
* these components are styled with Tailwind utility strings that Prettier's
|
|
17
|
+
* plugin reorders on save. And a chain written in the admin cannot describe a
|
|
18
|
+
* consumer's own registered renderer at all.
|
|
19
|
+
*
|
|
20
|
+
* So the probe measures the REAL element: the caller renders the actual section
|
|
21
|
+
* into a hidden host, and this module finds the field by its `data-cms-field`
|
|
22
|
+
* marker — the same attribute the click-to-edit bridge uses. There is nothing
|
|
23
|
+
* to keep in sync, and a renderer refactor cannot silently invalidate it.
|
|
24
|
+
*
|
|
25
|
+
* ── Why one host, resized ─────────────────────────────────────────────────
|
|
26
|
+
*
|
|
27
|
+
* Six widths are measured by resizing a single rendered copy, not by rendering
|
|
28
|
+
* six. Layout is recomputed either way; React reconciliation is not.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/** A field's wrap count at one breakpoint. */
|
|
32
|
+
export interface FieldLineCount {
|
|
33
|
+
id: BreakpointId
|
|
34
|
+
lines: number
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Line count from an element's laid-out height.
|
|
39
|
+
*
|
|
40
|
+
* Falls back to `fontSize * 1.25` when `line-height` computes to `normal`,
|
|
41
|
+
* which it does for any element that never set one. Rounding rather than
|
|
42
|
+
* flooring: sub-pixel line heights accumulate, and 2.97 lines is three.
|
|
43
|
+
*/
|
|
44
|
+
export function linesFromMetrics(height: number, lineHeight: number, fontSize: number): number {
|
|
45
|
+
const effective = Number.isFinite(lineHeight) && lineHeight > 0 ? lineHeight : fontSize * 1.25
|
|
46
|
+
if (!Number.isFinite(effective) || effective <= 0) return 1
|
|
47
|
+
// An empty field still occupies one line's worth of intent.
|
|
48
|
+
return Math.max(1, Math.round(height / effective))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* How many lines an element's text actually occupies.
|
|
53
|
+
*
|
|
54
|
+
* Counts LINE BOXES via a Range over the element's contents, deduplicated by
|
|
55
|
+
* their top edge. Dividing the element's height by its line-height — the
|
|
56
|
+
* obvious approach, and what the prototype does — counts padding as text: a
|
|
57
|
+
* button reading "Get Started" measured 2 lines, because its vertical padding
|
|
58
|
+
* came to roughly another line's worth of height. Every padded element was
|
|
59
|
+
* over-reported, which is most CTAs and every boxed heading.
|
|
60
|
+
*
|
|
61
|
+
* Rects are deduplicated by rounded top edge because a range spanning nested
|
|
62
|
+
* inline elements (a `<strong>` mid-sentence, an icon in a button) yields one
|
|
63
|
+
* rect per fragment, not per line.
|
|
64
|
+
*
|
|
65
|
+
* Falls back to the height ratio when the range produces nothing — an element
|
|
66
|
+
* whose content is a single replaced node, or a layout engine that gives no
|
|
67
|
+
* rects for empty text.
|
|
68
|
+
*/
|
|
69
|
+
export function countLines(el: HTMLElement): number {
|
|
70
|
+
const doc = el.ownerDocument
|
|
71
|
+
try {
|
|
72
|
+
const range = doc.createRange()
|
|
73
|
+
range.selectNodeContents(el)
|
|
74
|
+
const rects = Array.from(range.getClientRects()).filter((r) => r.height > 0)
|
|
75
|
+
range.detach?.()
|
|
76
|
+
if (rects.length > 0) {
|
|
77
|
+
const tops = new Set(rects.map((r) => Math.round(r.top)))
|
|
78
|
+
return Math.max(1, tops.size)
|
|
79
|
+
}
|
|
80
|
+
} catch {
|
|
81
|
+
// No Range support (or a detached document) — fall through to metrics.
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const cs = getComputedStyle(el)
|
|
85
|
+
return linesFromMetrics(
|
|
86
|
+
el.getBoundingClientRect().height,
|
|
87
|
+
Number.parseFloat(cs.lineHeight),
|
|
88
|
+
Number.parseFloat(cs.fontSize),
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The off-screen host.
|
|
94
|
+
*
|
|
95
|
+
* `left: -99999px`, never `display: none` — a hidden element has no layout, so
|
|
96
|
+
* every measurement would be zero. `visibility: hidden` would keep layout but
|
|
97
|
+
* also keep the element in the accessibility tree; moving it off-screen and
|
|
98
|
+
* marking it `aria-hidden` keeps it out of both the viewport and the a11y tree
|
|
99
|
+
* while still being laid out.
|
|
100
|
+
*
|
|
101
|
+
* MOUNT IT INSIDE `.prenta-admin`, never on `document.body`. Type tokens and
|
|
102
|
+
* the font stack are scoped to that root, so a host outside it lays text out in
|
|
103
|
+
* the document's default font and every measurement is taken at the wrong
|
|
104
|
+
* metrics. Caught by `e2e/reflow-probe.spec.ts` on its first run: a button
|
|
105
|
+
* measured 127px on the canvas and 139px in a body-mounted probe.
|
|
106
|
+
*
|
|
107
|
+
* Use `mountProbeHost` rather than appending by hand.
|
|
108
|
+
*/
|
|
109
|
+
export function createProbeHost(doc: Document = document): HTMLElement {
|
|
110
|
+
const host = doc.createElement('div')
|
|
111
|
+
host.setAttribute('aria-hidden', 'true')
|
|
112
|
+
host.dataset.reflowProbe = 'true'
|
|
113
|
+
Object.assign(host.style, {
|
|
114
|
+
position: 'fixed',
|
|
115
|
+
left: '-99999px',
|
|
116
|
+
top: '0',
|
|
117
|
+
// Never inherit the rail's width — the probe sets its own per breakpoint.
|
|
118
|
+
width: 'auto',
|
|
119
|
+
pointerEvents: 'none',
|
|
120
|
+
})
|
|
121
|
+
return host
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Attach a probe host in the only place it measures correctly.
|
|
126
|
+
*
|
|
127
|
+
* Returns a detach function. Falls back to `document.body` only when no admin
|
|
128
|
+
* root exists (it always does in the app) — and callers should treat a
|
|
129
|
+
* fallback mount as untrustworthy rather than silently measuring.
|
|
130
|
+
*/
|
|
131
|
+
export function mountProbeHost(
|
|
132
|
+
host: HTMLElement,
|
|
133
|
+
doc: Document = document,
|
|
134
|
+
): { detach: () => void; scoped: boolean } {
|
|
135
|
+
const root = doc.querySelector('.prenta-admin')
|
|
136
|
+
const parent = root ?? doc.body
|
|
137
|
+
parent.appendChild(host)
|
|
138
|
+
return { detach: () => host.remove(), scoped: Boolean(root) }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Measure one field across every breakpoint.
|
|
143
|
+
*
|
|
144
|
+
* `container` must carry the same class chain the canvas uses
|
|
145
|
+
* (`prenta-canvas`, which supplies the query container). Its width is set per
|
|
146
|
+
* breakpoint, so it must not be width-constrained by a parent.
|
|
147
|
+
*
|
|
148
|
+
* `scope` narrows to one section and is REQUIRED whenever the container holds
|
|
149
|
+
* more than one, because `data-cms-field` paths are unique only within a
|
|
150
|
+
* section — every section has a `heading` and a `body`. Without it a whole page
|
|
151
|
+
* silently measures the first section's field and reports it for all of them.
|
|
152
|
+
* (That mistake is what `e2e/reflow-probe.spec.ts` caught on its second run.)
|
|
153
|
+
*
|
|
154
|
+
* Returns `null` when the field cannot be found — the canvas is rendering a
|
|
155
|
+
* component without `data-cms-field` markers, so there is nothing to measure.
|
|
156
|
+
* Reporting a line count from the wrong element would be worse than reporting
|
|
157
|
+
* none: an editor reads a number as a fact.
|
|
158
|
+
*/
|
|
159
|
+
export function measureFieldAcrossBreakpoints(
|
|
160
|
+
container: HTMLElement,
|
|
161
|
+
fieldPath: string,
|
|
162
|
+
scope?: string,
|
|
163
|
+
): FieldLineCount[] | null {
|
|
164
|
+
const field = `[data-cms-field="${CSS.escape(fieldPath)}"]`
|
|
165
|
+
const selector = scope ? `${scope} ${field}` : field
|
|
166
|
+
if (!container.querySelector(selector)) return null
|
|
167
|
+
|
|
168
|
+
const previousWidth = container.style.width
|
|
169
|
+
const out: FieldLineCount[] = []
|
|
170
|
+
|
|
171
|
+
for (const bp of BREAKPOINTS) {
|
|
172
|
+
container.style.width = `${bp.width}px`
|
|
173
|
+
// Re-query inside the loop: a renderer may swap elements between layouts
|
|
174
|
+
// (a grid that becomes a stack can remount its children).
|
|
175
|
+
const el = container.querySelector(selector)
|
|
176
|
+
out.push({ id: bp.id, lines: el ? countLines(el as HTMLElement) : 1 })
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
container.style.width = previousWidth
|
|
180
|
+
return out
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** What a probe pass produces for one field. */
|
|
184
|
+
export interface FieldReflow {
|
|
185
|
+
current: FieldLineCount[]
|
|
186
|
+
baseline: FieldLineCount[]
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Measure a field's wrapping now and as published, from the live canvas.
|
|
191
|
+
*
|
|
192
|
+
* The whole `.prenta-canvas` is cloned, not just the target section. Cloning
|
|
193
|
+
* the section alone would require rebuilding whatever sits between the canvas
|
|
194
|
+
* root and the section — which is the class-chain problem again, in a smaller
|
|
195
|
+
* disguise. `e2e/reflow-probe.spec.ts` asserts the whole-canvas clone
|
|
196
|
+
* reproduces every field's rendered width exactly; nothing asserts that for a
|
|
197
|
+
* hand-rebuilt wrapper.
|
|
198
|
+
*
|
|
199
|
+
* The baseline is measured by writing the published string into the SAME cloned
|
|
200
|
+
* element and re-measuring, rather than by rendering the published section. The
|
|
201
|
+
* two differ in exactly one field, so everything else — width caps, siblings,
|
|
202
|
+
* grid tracks — is held identical by construction rather than by hoping a second
|
|
203
|
+
* render matches.
|
|
204
|
+
*
|
|
205
|
+
* `baselineText` of `undefined` means the field has no published version (a new
|
|
206
|
+
* section), so there is no change to report and current is echoed as baseline.
|
|
207
|
+
*
|
|
208
|
+
* Returns `null` when the section or field is absent from the canvas — a
|
|
209
|
+
* consumer's renderer may carry no `data-cms-field` markers, and a line count
|
|
210
|
+
* read off the wrong element is worse than none.
|
|
211
|
+
*/
|
|
212
|
+
export function probeFieldReflow(options: {
|
|
213
|
+
canvas: HTMLElement
|
|
214
|
+
sectionId: string
|
|
215
|
+
fieldPath: string
|
|
216
|
+
baselineText: string | undefined
|
|
217
|
+
doc?: Document
|
|
218
|
+
}): FieldReflow | null {
|
|
219
|
+
const { canvas, sectionId, fieldPath, baselineText, doc = document } = options
|
|
220
|
+
|
|
221
|
+
const sectionSel = `[data-section-id="${CSS.escape(sectionId)}"]`
|
|
222
|
+
const fieldSel = `${sectionSel} [data-cms-field="${CSS.escape(fieldPath)}"]`
|
|
223
|
+
if (!canvas.querySelector(fieldSel)) return null
|
|
224
|
+
|
|
225
|
+
const host = createProbeHost(doc)
|
|
226
|
+
const clone = canvas.cloneNode(true) as HTMLElement
|
|
227
|
+
// The canvas is scaled to fit its column. A transform does not change layout
|
|
228
|
+
// width, but it does scale the measured rects — and line height is read from
|
|
229
|
+
// a rect. Left on, every count would be off by the scale factor.
|
|
230
|
+
clone.style.transform = 'none'
|
|
231
|
+
clone.style.maxWidth = 'none'
|
|
232
|
+
host.appendChild(clone)
|
|
233
|
+
|
|
234
|
+
const { detach, scoped } = mountProbeHost(host, doc)
|
|
235
|
+
// Outside `.prenta-admin` the type tokens don't apply and every measurement
|
|
236
|
+
// is taken in the document's default font. Report nothing rather than that.
|
|
237
|
+
if (!scoped) {
|
|
238
|
+
detach()
|
|
239
|
+
return null
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
try {
|
|
243
|
+
const current = measureFieldAcrossBreakpoints(clone, fieldPath, sectionSel)
|
|
244
|
+
if (!current) return null
|
|
245
|
+
if (baselineText === undefined) return { current, baseline: current }
|
|
246
|
+
|
|
247
|
+
const el = clone.querySelector(fieldSel)
|
|
248
|
+
if (!el) return { current, baseline: current }
|
|
249
|
+
el.textContent = baselineText
|
|
250
|
+
const baseline = measureFieldAcrossBreakpoints(clone, fieldPath, sectionSel)
|
|
251
|
+
return { current, baseline: baseline ?? current }
|
|
252
|
+
} finally {
|
|
253
|
+
detach()
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export type ReflowSeverity = 'same' | 'grew' | 'grew-badly'
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Compare a field's current wrapping against its published baseline.
|
|
261
|
+
*
|
|
262
|
+
* Only growth is flagged. Copy that got shorter cannot break a layout that
|
|
263
|
+
* already held the longer version, so reporting it would be noise on exactly
|
|
264
|
+
* the edit an editor was asked to make.
|
|
265
|
+
*/
|
|
266
|
+
export function reflowSeverity(current: number, baseline: number): ReflowSeverity {
|
|
267
|
+
const delta = current - baseline
|
|
268
|
+
if (delta <= 0) return 'same'
|
|
269
|
+
return delta === 1 ? 'grew' : 'grew-badly'
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* The breakpoint worth proofing on: the biggest jump, and on a tie the
|
|
274
|
+
* narrowest width. A tie means the same damage happens at several sizes, and
|
|
275
|
+
* the narrowest is where it is most likely to look broken.
|
|
276
|
+
*/
|
|
277
|
+
export function worstBreakpoint(
|
|
278
|
+
current: FieldLineCount[],
|
|
279
|
+
baseline: FieldLineCount[],
|
|
280
|
+
): BreakpointId | null {
|
|
281
|
+
const widthOf = (id: BreakpointId) => BREAKPOINTS.find((b) => b.id === id)?.width ?? 0
|
|
282
|
+
let worst: { id: BreakpointId; delta: number } | null = null
|
|
283
|
+
|
|
284
|
+
for (const c of current) {
|
|
285
|
+
const b = baseline.find((x) => x.id === c.id)
|
|
286
|
+
if (!b) continue
|
|
287
|
+
const delta = c.lines - b.lines
|
|
288
|
+
if (delta <= 0) continue
|
|
289
|
+
if (
|
|
290
|
+
!worst ||
|
|
291
|
+
delta > worst.delta ||
|
|
292
|
+
(delta === worst.delta && widthOf(c.id) < widthOf(worst.id))
|
|
293
|
+
) {
|
|
294
|
+
worst = { id: c.id, delta }
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return worst?.id ?? null
|
|
299
|
+
}
|
package/src/lib/seo-service.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import type { BrandAlignmentScoreResult } from '@prenta/core/brand-voice'
|
|
12
12
|
import type { SEOAnalysisResult } from '@prenta/core/seo/analysis'
|
|
13
13
|
import { cmsApi } from './api.js'
|
|
14
|
+
import type { MaxImagePreview } from '@prenta/core/seo/robots-directives'
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* `cmsApi` never throws — it returns `{ error, status }` on a network/HTTP
|
|
@@ -182,6 +183,12 @@ export interface SeoContentRecord {
|
|
|
182
183
|
twitterImageId: string | null
|
|
183
184
|
noindex: boolean
|
|
184
185
|
nofollow: boolean
|
|
186
|
+
/** Blocks text snippets, and with them AI Overview and chat citations. */
|
|
187
|
+
nosnippet: boolean
|
|
188
|
+
/** Blocks cached copies. */
|
|
189
|
+
noarchive: boolean
|
|
190
|
+
/** Largest image preview a result may show. */
|
|
191
|
+
maxImagePreview: MaxImagePreview
|
|
185
192
|
structuredDataType: string | null
|
|
186
193
|
structuredData: Record<string, unknown> | null
|
|
187
194
|
/** llms.txt curation: AUTO (heuristic), ALWAYS (pin), NEVER (exclude). */
|
|
@@ -232,6 +239,9 @@ export interface SeoFieldPayload {
|
|
|
232
239
|
twitterImage?: string
|
|
233
240
|
noindex?: boolean
|
|
234
241
|
nofollow?: boolean
|
|
242
|
+
nosnippet?: boolean
|
|
243
|
+
noarchive?: boolean
|
|
244
|
+
maxImagePreview?: MaxImagePreview
|
|
235
245
|
structuredDataType?: string
|
|
236
246
|
structuredData?: Record<string, unknown>
|
|
237
247
|
llmsInclude?: LlmsInclude
|
|
@@ -1,29 +1,39 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* PrentaCMS design tokens — scoped to the admin root.
|
|
3
|
-
* Source: design-system/tokens.json
|
|
4
|
-
*
|
|
3
|
+
* GENERATED FILE — DO NOT EDIT. Source: design-system/tokens.json.
|
|
4
|
+
* Regenerate: pnpm --filter @prenta/admin generate
|
|
5
|
+
*
|
|
6
|
+
* Scoped to .prenta-admin rather than :root on purpose: the admin renders
|
|
7
|
+
* inside consumer applications, and custom properties resolve by INHERITANCE,
|
|
8
|
+
* not by specificity — a host site's :root would otherwise win against every
|
|
9
|
+
* admin rule reading these names. Appearance settings mutate --acc / --primary
|
|
10
|
+
* at runtime on this same element.
|
|
5
11
|
*/
|
|
6
12
|
|
|
7
13
|
.prenta-admin {
|
|
8
14
|
/* Surfaces */
|
|
9
|
-
--bg: #f5f4fa;
|
|
10
|
-
--sb: #ffffff;
|
|
11
|
-
--card: #ffffff;
|
|
12
|
-
--bdr: #e8e6f2;
|
|
15
|
+
--bg: #f5f4fa; /* App background */
|
|
16
|
+
--sb: #ffffff; /* Sidebar / topbar surface */
|
|
17
|
+
--card: #ffffff; /* Card / panel surface */
|
|
18
|
+
--bdr: #e8e6f2; /* Hairline border */
|
|
13
19
|
|
|
14
20
|
/* Text */
|
|
15
|
-
--txt: #1a1827;
|
|
16
|
-
--sub: #6b6878;
|
|
17
|
-
/*
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
--txt: #1a1827; /* Primary text */
|
|
22
|
+
--sub: #6b6878; /* Secondary text */
|
|
23
|
+
/*
|
|
24
|
+
* Tertiary text. The handoff value #B0ADBE is 2.2:1 on --card — below WCAG
|
|
25
|
+
* AA. The admin uses --muted as real text (section labels, check hints,
|
|
26
|
+
* canvas meta line, character counters), so it is darkened to 4.6:1 while
|
|
27
|
+
* staying one step lighter than --sub to preserve the hierarchy. Do not
|
|
28
|
+
* revert without also changing every --muted consumer to decorative use.
|
|
29
|
+
* Handoff value: #b0adbe — deliberately overridden.
|
|
30
|
+
*/
|
|
21
31
|
--muted: #716e83;
|
|
22
32
|
|
|
23
33
|
/* Accent */
|
|
24
|
-
--acc: #7c3aed;
|
|
25
|
-
--acc-l: #ede9fe;
|
|
26
|
-
--acc-m: #c4b5fd;
|
|
34
|
+
--acc: #7c3aed; /* Accent / interactive */
|
|
35
|
+
--acc-l: #ede9fe; /* Accent tint (hover/active bg) */
|
|
36
|
+
--acc-m: #c4b5fd; /* Accent mid (focus ring) */
|
|
27
37
|
|
|
28
38
|
/* Semantic */
|
|
29
39
|
--suc: #059669;
|
|
@@ -35,11 +45,7 @@
|
|
|
35
45
|
--info: #0891b2;
|
|
36
46
|
--info-l: #e0f7fa;
|
|
37
47
|
|
|
38
|
-
/*
|
|
39
|
-
* Page / post-type tag palette — distinct editorial hues.
|
|
40
|
-
* Kept separate from status tokens so "pink" is not warning orange and
|
|
41
|
-
* "blue" is not info cyan. Soft companions tint pill backgrounds.
|
|
42
|
-
*/
|
|
48
|
+
/* Tag palette */
|
|
43
49
|
--tag-purple: #7c3aed;
|
|
44
50
|
--tag-purple-soft: #f3e8ff;
|
|
45
51
|
--tag-green: #0f766e;
|
|
@@ -60,56 +66,123 @@
|
|
|
60
66
|
--ai2: #c026d3;
|
|
61
67
|
--ai-soft: linear-gradient(135deg, rgba(124, 58, 237, 0.09), rgba(192, 38, 211, 0.07));
|
|
62
68
|
|
|
69
|
+
/* Controls */
|
|
70
|
+
/*
|
|
71
|
+
* Switch knob stays white in both themes per the design system; tokenized so
|
|
72
|
+
* a consumer theme can move it.
|
|
73
|
+
*/
|
|
74
|
+
--toggle-thumb: #ffffff;
|
|
75
|
+
|
|
76
|
+
/* Type */
|
|
77
|
+
/*
|
|
78
|
+
* UI text. Self-hosted woff2 under design-system/fonts — never a third-party
|
|
79
|
+
* request, because the admin renders inside consumer applications.
|
|
80
|
+
*/
|
|
81
|
+
--font-sans: 'DM Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
|
82
|
+
/* Code, robots directives, token names */
|
|
83
|
+
--font-mono: 'DM Mono', ui-monospace, 'SFMono-Regular', monospace;
|
|
84
|
+
--fw-reg: 450;
|
|
85
|
+
--fw-med: 500;
|
|
86
|
+
--fw-semi: 600;
|
|
87
|
+
--fw-bold: 700;
|
|
88
|
+
--fs-page: 21px; /* Page title */
|
|
89
|
+
--fs-card: 14px; /* Card / section title */
|
|
90
|
+
--fs-body: 13px; /* Body, controls, table cells */
|
|
91
|
+
--fs-sub: 12px; /* Secondary / captions */
|
|
92
|
+
--fs-hint: 11.5px; /* Hints, metadata */
|
|
93
|
+
--fs-label: 10px; /* Section labels */
|
|
94
|
+
|
|
63
95
|
/* Layout */
|
|
64
96
|
--sbw: 224px;
|
|
65
97
|
--sbw-col: 60px;
|
|
66
98
|
--tbh: 56px;
|
|
67
|
-
--r: 10px;
|
|
68
|
-
--r-control: 8px;
|
|
69
|
-
--r-sm: 6px;
|
|
70
|
-
--r-pill: 99px;
|
|
71
99
|
|
|
72
|
-
/*
|
|
73
|
-
--
|
|
74
|
-
--
|
|
100
|
+
/* Radius */
|
|
101
|
+
--r-sm: 6px; /* Small buttons, badges, tags, chips-in-rows */
|
|
102
|
+
--r-field: 7px; /* Text inputs, textareas, selects */
|
|
103
|
+
/*
|
|
104
|
+
* Primary / secondary buttons, dropdowns. --r-control is the pre-2.0 name,
|
|
105
|
+
* kept resolving for existing rules.
|
|
106
|
+
*/
|
|
107
|
+
--r-ctl: 8px;
|
|
108
|
+
--r-control: var(--r-ctl); /* deprecated alias */
|
|
109
|
+
--r: 10px; /* Cards and panels */
|
|
110
|
+
--r-fig: 12px; /* Canvas figures and media frames */
|
|
111
|
+
--r-pill: 99px; /* Toggles, meters, notice pills */
|
|
112
|
+
|
|
113
|
+
/* Spacing */
|
|
114
|
+
--sp-2: 2px;
|
|
115
|
+
--sp-4: 4px;
|
|
116
|
+
--sp-6: 6px;
|
|
117
|
+
--sp-8: 8px;
|
|
118
|
+
--sp-10: 10px;
|
|
119
|
+
--sp-12: 12px; /* Row padding-y */
|
|
120
|
+
--sp-14: 14px; /* Panel padding */
|
|
121
|
+
--sp-16: 16px; /* Editor header padding-x */
|
|
122
|
+
--sp-18: 18px; /* Canvas gutter top */
|
|
123
|
+
--sp-20: 20px;
|
|
124
|
+
--sp-24: 24px; /* Canvas gutter sides */
|
|
125
|
+
--sp-28: 28px;
|
|
126
|
+
--sp-32: 32px;
|
|
127
|
+
--sp-40: 40px; /* Canvas gutter bottom */
|
|
128
|
+
|
|
129
|
+
/* Control sizing */
|
|
130
|
+
--h-chip: 26px; /* Rail buttons, theme toggle */
|
|
131
|
+
--h-field: 33px; /* Text inputs and small buttons */
|
|
132
|
+
--h-ctl: 34px; /* Header controls: icon buttons, breakpoint trigger, zoom chip, SEO chip */
|
|
133
|
+
|
|
134
|
+
/* Border */
|
|
135
|
+
--bw: 1px;
|
|
136
|
+
--bw-ctl: 1.5px; /* Input and card border */
|
|
137
|
+
--bw-focus: 2px; /* Focus and active outline */
|
|
138
|
+
--ring: 0 0 0 3px var(--acc-m); /* Focus ring shadow */
|
|
75
139
|
|
|
76
|
-
/*
|
|
77
|
-
--
|
|
78
|
-
--
|
|
79
|
-
--fs-page: 21px;
|
|
80
|
-
--fs-card: 14px;
|
|
81
|
-
--fs-body: 13px;
|
|
82
|
-
--fs-sub: 12px;
|
|
83
|
-
--fs-hint: 11.5px;
|
|
84
|
-
--fs-label: 10px;
|
|
140
|
+
/* Elevation */
|
|
141
|
+
--shd: 0 1px 2px rgba(0, 0, 0, 0.05), 0 1px 4px rgba(0, 0, 0, 0.04); /* Card resting */
|
|
142
|
+
--shd2: 0 4px 16px rgba(0, 0, 0, 0.1); /* Popovers, modals, hover */
|
|
85
143
|
|
|
86
144
|
/* Motion */
|
|
87
|
-
--
|
|
88
|
-
--motion-
|
|
145
|
+
--mo-fast: 0.12s; /* Hover, color */
|
|
146
|
+
--motion-fast: var(--mo-fast); /* deprecated alias */
|
|
147
|
+
--mo-base: 0.18s; /* Toggles, reveals */
|
|
148
|
+
--motion-base: var(--mo-base); /* deprecated alias */
|
|
149
|
+
--mo-slow: 0.22s; /* Panels, canvas scale */
|
|
150
|
+
--ease: cubic-bezier(0.4, 0, 0.2, 1);
|
|
151
|
+
/* Pre-2.0 composite. Use --mo-slow var(--ease) instead. */
|
|
89
152
|
--motion-layout: 0.22s cubic-bezier(0.4, 0, 0.2, 1);
|
|
90
153
|
|
|
91
|
-
/*
|
|
92
|
-
|
|
93
|
-
--
|
|
154
|
+
/* Layering */
|
|
155
|
+
--z-raise: 2; /* Canvas section labels, sticky group headers */
|
|
156
|
+
--z-resizer: 30; /* Panel drag handle */
|
|
157
|
+
--z-overlay: 45; /* In-panel overlays (version history) */
|
|
158
|
+
--z-menu: 120; /* Dropdowns, flyouts */
|
|
159
|
+
--z-toast: 200;
|
|
94
160
|
}
|
|
95
161
|
|
|
96
162
|
.dark .prenta-admin,
|
|
97
163
|
.prenta-admin.dark,
|
|
98
164
|
.prenta-admin[data-theme='dark'] {
|
|
165
|
+
/* Surfaces */
|
|
99
166
|
--bg: #0d0c18;
|
|
100
167
|
--sb: #141222;
|
|
101
168
|
--card: #1c1a2e;
|
|
102
169
|
--bdr: #2c2a42;
|
|
103
170
|
|
|
171
|
+
/* Text */
|
|
104
172
|
--txt: #eae8f5;
|
|
105
173
|
--sub: #8e8ba8;
|
|
106
|
-
/*
|
|
174
|
+
/*
|
|
175
|
+
* Same AA correction as light mode — the handoff value #504E68 is 2.1:1 on
|
|
176
|
+
* --card. Handoff value: #504e68 — deliberately overridden.
|
|
177
|
+
*/
|
|
107
178
|
--muted: #8784a2;
|
|
108
179
|
|
|
180
|
+
/* Accent */
|
|
109
181
|
--acc: #9d71f0;
|
|
110
182
|
--acc-l: #231950;
|
|
111
183
|
--acc-m: #5e3eaa;
|
|
112
184
|
|
|
185
|
+
/* Semantic */
|
|
113
186
|
--suc: #10b981;
|
|
114
187
|
--suc-l: #022c22;
|
|
115
188
|
--warn: #fbbf24;
|
|
@@ -119,6 +192,7 @@
|
|
|
119
192
|
--info: #38bdf8;
|
|
120
193
|
--info-l: #0a2838;
|
|
121
194
|
|
|
195
|
+
/* Tag palette */
|
|
122
196
|
--tag-purple: #a78bfa;
|
|
123
197
|
--tag-purple-soft: #2e1065;
|
|
124
198
|
--tag-green: #2dd4bf;
|
|
@@ -134,8 +208,12 @@
|
|
|
134
208
|
--tag-gray: #94a3b8;
|
|
135
209
|
--tag-gray-soft: #1e293b;
|
|
136
210
|
|
|
211
|
+
/* AI */
|
|
212
|
+
--ai1: #7c3aed;
|
|
213
|
+
--ai2: #c026d3;
|
|
137
214
|
--ai-soft: linear-gradient(135deg, rgba(157, 113, 240, 0.16), rgba(192, 38, 211, 0.12));
|
|
138
215
|
|
|
216
|
+
/* Elevation */
|
|
139
217
|
--shd: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 4px rgba(0, 0, 0, 0.2);
|
|
140
218
|
--shd2: 0 4px 20px rgba(0, 0, 0, 0.45);
|
|
141
219
|
}
|