@prenta/admin 0.92.0 → 0.94.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 +663 -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__/lib/version-diff.test.d.ts +2 -0
- package/dist/__tests__/lib/version-diff.test.d.ts.map +1 -0
- package/dist/__tests__/lib/version-diff.test.js +230 -0
- package/dist/__tests__/lib/version-diff.test.js.map +1 -0
- package/dist/__tests__/lib/version-history.test.d.ts +2 -0
- package/dist/__tests__/lib/version-history.test.d.ts.map +1 -0
- package/dist/__tests__/lib/version-history.test.js +125 -0
- package/dist/__tests__/lib/version-history.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/responsive-layer.test.d.ts +2 -0
- package/dist/__tests__/styles/responsive-layer.test.d.ts.map +1 -0
- package/dist/__tests__/styles/responsive-layer.test.js +127 -0
- package/dist/__tests__/styles/responsive-layer.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/canvas-review-mode.render.test.d.ts +2 -0
- package/dist/__tests__/views/canvas-review-mode.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/canvas-review-mode.render.test.js +70 -0
- package/dist/__tests__/views/canvas-review-mode.render.test.js.map +1 -0
- package/dist/__tests__/views/editor-top-bar.render.test.js +30 -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/__tests__/views/version-history-panel.render.test.d.ts +2 -0
- package/dist/__tests__/views/version-history-panel.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/version-history-panel.render.test.js +153 -0
- package/dist/__tests__/views/version-history-panel.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 +33 -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/layout/primitives/AdminShell.d.ts.map +1 -1
- package/dist/layout/primitives/AdminShell.js +2 -2
- package/dist/layout/primitives/AdminShell.js.map +1 -1
- 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/lib/version-diff.d.ts +50 -0
- package/dist/lib/version-diff.d.ts.map +1 -0
- package/dist/lib/version-diff.js +294 -0
- package/dist/lib/version-diff.js.map +1 -0
- package/dist/lib/version-history.d.ts +73 -0
- package/dist/lib/version-history.d.ts.map +1 -0
- package/dist/lib/version-history.js +126 -0
- package/dist/lib/version-history.js.map +1 -0
- 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 +47 -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 +21 -2
- package/dist/views/page-editor/EditorTopBar.d.ts.map +1 -1
- package/dist/views/page-editor/EditorTopBar.js +13 -20
- 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 +383 -78
- 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/ReviewBar.d.ts +21 -0
- package/dist/views/page-editor/ReviewBar.d.ts.map +1 -0
- package/dist/views/page-editor/ReviewBar.js +22 -0
- package/dist/views/page-editor/ReviewBar.js.map +1 -0
- package/dist/views/page-editor/SectionInspector.d.ts.map +1 -1
- package/dist/views/page-editor/SectionInspector.js +64 -20
- 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/VersionHistoryPanel.d.ts +29 -0
- package/dist/views/page-editor/VersionHistoryPanel.d.ts.map +1 -0
- package/dist/views/page-editor/VersionHistoryPanel.js +81 -0
- package/dist/views/page-editor/VersionHistoryPanel.js.map +1 -0
- 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 +13 -1
- package/dist/views/page-editor/sections/SectionRenderer.d.ts.map +1 -1
- package/dist/views/page-editor/sections/SectionRenderer.js +66 -26
- 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__/lib/version-diff.test.ts +278 -0
- package/src/__tests__/lib/version-history.test.ts +166 -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/responsive-layer.test.ts +152 -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/canvas-review-mode.render.test.tsx +94 -0
- package/src/__tests__/views/editor-top-bar.render.test.tsx +43 -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/__tests__/views/version-history-panel.render.test.tsx +195 -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 +89 -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/layout/primitives/AdminShell.tsx +13 -1
- 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/lib/version-diff.ts +376 -0
- package/src/lib/version-history.ts +192 -0
- package/src/styles/prenta-tokens.css +120 -42
- package/src/styles/responsive.css +281 -0
- package/src/styles/theme.css +138 -0
- package/src/views/page-editor/CanvasMetaLine.tsx +50 -0
- package/src/views/page-editor/EditorCanvas.tsx +140 -54
- package/src/views/page-editor/EditorTopBar.tsx +55 -51
- package/src/views/page-editor/PageSectionEditor.tsx +575 -185
- package/src/views/page-editor/PageTab.tsx +433 -0
- package/src/views/page-editor/ReviewBar.tsx +76 -0
- package/src/views/page-editor/SectionInspector.tsx +84 -42
- package/src/views/page-editor/SectionsPanel.tsx +282 -141
- package/src/views/page-editor/SitePreviewFrame.tsx +3 -0
- package/src/views/page-editor/VersionHistoryPanel.tsx +302 -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 +115 -34
- 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,153 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// @vitest-environment happy-dom
|
|
3
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
+
import { cleanup, fireEvent, render, screen, within } from '@testing-library/react';
|
|
5
|
+
import { VersionHistoryPanel } from '../../views/page-editor/VersionHistoryPanel.js';
|
|
6
|
+
afterEach(cleanup);
|
|
7
|
+
function section(id, content) {
|
|
8
|
+
return { id, sectionType: 'hero', name: 'Hero Banner', visible: true, content, settings: {} };
|
|
9
|
+
}
|
|
10
|
+
const NOW = new Date();
|
|
11
|
+
const iso = (hoursAgo) => new Date(NOW.getTime() - hoursAgo * 3_600_000).toISOString();
|
|
12
|
+
const VERSIONS = [
|
|
13
|
+
{
|
|
14
|
+
id: 'v3',
|
|
15
|
+
changeType: 'PUBLISH',
|
|
16
|
+
createdAt: iso(1),
|
|
17
|
+
author: { id: 'u1', name: 'Sarah Mills' },
|
|
18
|
+
sections: [section('s1', { heading: 'Third headline' })],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: 'v2',
|
|
22
|
+
changeType: 'UPDATE',
|
|
23
|
+
createdAt: iso(2),
|
|
24
|
+
author: { id: 'u2', name: 'Dan Ito' },
|
|
25
|
+
sections: [section('s1', { heading: 'Second headline' })],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: 'v1',
|
|
29
|
+
changeType: 'CREATE',
|
|
30
|
+
createdAt: iso(30),
|
|
31
|
+
author: { id: 'u1', name: 'Sarah Mills' },
|
|
32
|
+
sections: [section('s1', { heading: 'First headline' })],
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
function renderPanel(props = {}) {
|
|
36
|
+
const onSelect = vi.fn();
|
|
37
|
+
const onRestore = vi.fn();
|
|
38
|
+
const onClose = vi.fn();
|
|
39
|
+
render(_jsx(VersionHistoryPanel, { versions: VERSIONS, loading: false, error: null, selectedIndex: 0, onSelect: onSelect, onClose: onClose, onRestore: onRestore, restoring: false, canRestore: true, ...props }));
|
|
40
|
+
return { onSelect, onRestore, onClose };
|
|
41
|
+
}
|
|
42
|
+
describe('VersionHistoryPanel', () => {
|
|
43
|
+
it('groups entries under sticky day headings', () => {
|
|
44
|
+
renderPanel();
|
|
45
|
+
expect(screen.getByRole('heading', { name: 'Today' })).toBeTruthy();
|
|
46
|
+
// v1 is 30 hours back, so it lands on its own day.
|
|
47
|
+
expect(screen.getAllByRole('heading', { level: 3 }).length).toBeGreaterThan(1);
|
|
48
|
+
});
|
|
49
|
+
it('marks the newest entry as current and shows the published pill', () => {
|
|
50
|
+
renderPanel();
|
|
51
|
+
expect(screen.getByText('Current')).toBeTruthy();
|
|
52
|
+
expect(screen.getByText('Published')).toBeTruthy();
|
|
53
|
+
// No pill claims "Draft" — nothing in this codebase records one.
|
|
54
|
+
expect(screen.queryByText('Draft')).toBeNull();
|
|
55
|
+
});
|
|
56
|
+
it('summarises each entry by what that save changed', () => {
|
|
57
|
+
renderPanel();
|
|
58
|
+
// v3 changed one field against v2.
|
|
59
|
+
expect(screen.getByText(/Sarah Mills · 1 change$/)).toBeTruthy();
|
|
60
|
+
// v1 has no predecessor in the list, so it reports no computed changes
|
|
61
|
+
// rather than claiming it created everything.
|
|
62
|
+
expect(screen.getByText(/Sarah Mills · no content changes/)).toBeTruthy();
|
|
63
|
+
});
|
|
64
|
+
it('shows the computed field diff, old struck through and new after it', () => {
|
|
65
|
+
renderPanel();
|
|
66
|
+
// The newest changed entry auto-expands.
|
|
67
|
+
expect(screen.getByText('Heading')).toBeTruthy();
|
|
68
|
+
const oldValue = screen.getByText('Second headline');
|
|
69
|
+
const newValue = screen.getByText('Third headline');
|
|
70
|
+
expect(oldValue.className).toContain('line-through');
|
|
71
|
+
expect(newValue.className).not.toContain('line-through');
|
|
72
|
+
});
|
|
73
|
+
it('selects the version when its row is activated, which is what drives the canvas', () => {
|
|
74
|
+
const { onSelect } = renderPanel();
|
|
75
|
+
fireEvent.click(screen.getByText(/Dan Ito/));
|
|
76
|
+
expect(onSelect).toHaveBeenCalledWith(1);
|
|
77
|
+
});
|
|
78
|
+
it('offers Restore only on the selected older row', () => {
|
|
79
|
+
renderPanel({ selectedIndex: 0 });
|
|
80
|
+
// Selected row is the current one — restoring it is a no-op.
|
|
81
|
+
expect(screen.queryByRole('button', { name: /Restore this version/ })).toBeNull();
|
|
82
|
+
cleanup();
|
|
83
|
+
renderPanel({ selectedIndex: 1 });
|
|
84
|
+
const restore = screen.getByRole('button', { name: /Restore this version/ });
|
|
85
|
+
expect(restore).toBeTruthy();
|
|
86
|
+
});
|
|
87
|
+
it('shows the diff for whichever version is selected, including one selected from outside', () => {
|
|
88
|
+
// The review bar and the canvas both move the selection without the panel
|
|
89
|
+
// being clicked. When disclosure was tracked separately from selection,
|
|
90
|
+
// the diff described one version while the canvas rendered another — and
|
|
91
|
+
// Restore sat on a row that was not open.
|
|
92
|
+
renderPanel({ selectedIndex: 1 });
|
|
93
|
+
expect(screen.getByText('First headline')).toBeTruthy();
|
|
94
|
+
expect(screen.getByText('Second headline')).toBeTruthy();
|
|
95
|
+
expect(screen.queryByText('Third headline')).toBeNull();
|
|
96
|
+
expect(screen.getByRole('button', { name: /Restore this version/ })).toBeTruthy();
|
|
97
|
+
});
|
|
98
|
+
it('collapses the row it is already on rather than reselecting it', () => {
|
|
99
|
+
const { onSelect } = renderPanel({ selectedIndex: 0 });
|
|
100
|
+
expect(screen.getByText('Heading')).toBeTruthy();
|
|
101
|
+
fireEvent.click(screen.getByText(/Sarah Mills · 1 change/));
|
|
102
|
+
expect(onSelect).not.toHaveBeenCalled();
|
|
103
|
+
expect(screen.queryByText('Heading')).toBeNull();
|
|
104
|
+
});
|
|
105
|
+
it('can restore the oldest version, which by definition has no diff to show', () => {
|
|
106
|
+
// Restore used to live inside the diff block, so a version with no
|
|
107
|
+
// computed changes — the oldest one held, or a metadata-only save — was
|
|
108
|
+
// reviewable and not restorable. That is the wrong way round: the oldest
|
|
109
|
+
// version is the one a rollback most often wants.
|
|
110
|
+
renderPanel({ selectedIndex: 2 });
|
|
111
|
+
expect(screen.getByText(/No section changes to show/)).toBeTruthy();
|
|
112
|
+
expect(screen.getByRole('button', { name: /Restore this version/ })).toBeTruthy();
|
|
113
|
+
});
|
|
114
|
+
it('hides Restore from a user who cannot edit', () => {
|
|
115
|
+
renderPanel({ selectedIndex: 1, canRestore: false });
|
|
116
|
+
expect(screen.queryByRole('button', { name: /Restore this version/ })).toBeNull();
|
|
117
|
+
});
|
|
118
|
+
it('restores the version whose row was clicked', () => {
|
|
119
|
+
const { onRestore } = renderPanel({ selectedIndex: 1 });
|
|
120
|
+
fireEvent.click(screen.getByRole('button', { name: /Restore this version/ }));
|
|
121
|
+
expect(onRestore).toHaveBeenCalledWith(expect.objectContaining({ id: 'v2' }));
|
|
122
|
+
});
|
|
123
|
+
it('renders two non-adjacent groups sharing a day label without colliding', () => {
|
|
124
|
+
// `groupVersionsByDay` walks CONSECUTIVE runs, so an out-of-order page
|
|
125
|
+
// legitimately yields ['Today', 'Yesterday', 'Today'] — its own test
|
|
126
|
+
// asserts that. Keyed on the label, the second "Today" collides with the
|
|
127
|
+
// first and React mis-associates the two sections' contents.
|
|
128
|
+
const outOfOrder = [
|
|
129
|
+
{ ...VERSIONS[0], id: 'a', createdAt: iso(1) },
|
|
130
|
+
{ ...VERSIONS[1], id: 'b', createdAt: iso(30) },
|
|
131
|
+
{ ...VERSIONS[2], id: 'c', createdAt: iso(2) },
|
|
132
|
+
];
|
|
133
|
+
const spy = vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
134
|
+
renderPanel({ versions: outOfOrder });
|
|
135
|
+
expect(screen.getAllByRole('heading', { name: 'Today' })).toHaveLength(2);
|
|
136
|
+
expect(spy.mock.calls.some((call) => String(call[0]).includes('same key')), 'React reported duplicate keys').toBe(false);
|
|
137
|
+
spy.mockRestore();
|
|
138
|
+
});
|
|
139
|
+
it('reports an empty history rather than an empty box', () => {
|
|
140
|
+
renderPanel({ versions: [] });
|
|
141
|
+
expect(screen.getByText(/No versions yet/)).toBeTruthy();
|
|
142
|
+
});
|
|
143
|
+
it('surfaces a load failure', () => {
|
|
144
|
+
renderPanel({ versions: [], error: 'Network unreachable' });
|
|
145
|
+
expect(screen.getByText('Network unreachable')).toBeTruthy();
|
|
146
|
+
});
|
|
147
|
+
it('announces itself as a named region so it is reachable without sight of the overlay', () => {
|
|
148
|
+
renderPanel();
|
|
149
|
+
const region = screen.getByRole('region', { name: 'Version history' });
|
|
150
|
+
expect(within(region).getByRole('button', { name: 'Close version history' })).toBeTruthy();
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
//# sourceMappingURL=version-history-panel.render.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-history-panel.render.test.js","sourceRoot":"","sources":["../../../src/__tests__/views/version-history-panel.render.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type BreakpointId } from '../lib/breakpoints.js';
|
|
2
|
+
export interface BreakpointPickerProps {
|
|
3
|
+
value: BreakpointId;
|
|
4
|
+
onChange: (id: BreakpointId) => void;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Preview-breakpoint selector for the editor header.
|
|
9
|
+
*
|
|
10
|
+
* A dropdown rather than a segmented row: six presets with names like "Tablet
|
|
11
|
+
* Landscape" do not fit a header strip, and the grouped menu is what makes the
|
|
12
|
+
* DESKTOP / TABLET / MOBILE structure legible.
|
|
13
|
+
*
|
|
14
|
+
* Radix owns the menu behaviour — outside-click, Escape, roving focus, and
|
|
15
|
+
* `aria-expanded` on the trigger — rather than a hand-rolled popover.
|
|
16
|
+
*/
|
|
17
|
+
export declare function BreakpointPicker({ value, onChange, disabled }: BreakpointPickerProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=BreakpointPicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BreakpointPicker.d.ts","sourceRoot":"","sources":["../../src/components/BreakpointPicker.tsx"],"names":[],"mappings":"AAMA,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAA;AAG9B,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB,QAAQ,EAAE,CAAC,EAAE,EAAE,YAAY,KAAK,IAAI,CAAA;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,qBAAqB,2CAmFpF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
|
|
5
|
+
import { Check, ChevronDown } from 'lucide-react';
|
|
6
|
+
import { adminPortalContainer } from '../lib/portal-container.js';
|
|
7
|
+
import { BREAKPOINT_GROUPS, breakpointsInGroup, getBreakpoint, } from '../lib/breakpoints.js';
|
|
8
|
+
import { breakpointIcon } from './breakpoint-icons.js';
|
|
9
|
+
/**
|
|
10
|
+
* Preview-breakpoint selector for the editor header.
|
|
11
|
+
*
|
|
12
|
+
* A dropdown rather than a segmented row: six presets with names like "Tablet
|
|
13
|
+
* Landscape" do not fit a header strip, and the grouped menu is what makes the
|
|
14
|
+
* DESKTOP / TABLET / MOBILE structure legible.
|
|
15
|
+
*
|
|
16
|
+
* Radix owns the menu behaviour — outside-click, Escape, roving focus, and
|
|
17
|
+
* `aria-expanded` on the trigger — rather than a hand-rolled popover.
|
|
18
|
+
*/
|
|
19
|
+
export function BreakpointPicker({ value, onChange, disabled }) {
|
|
20
|
+
const [open, setOpen] = useState(false);
|
|
21
|
+
const active = getBreakpoint(value);
|
|
22
|
+
const ActiveIcon = breakpointIcon(active.icon);
|
|
23
|
+
return (_jsxs(DropdownMenu.Root, { open: open, onOpenChange: setOpen, children: [_jsx(DropdownMenu.Trigger, { asChild: true, children: _jsxs("button", { type: "button", disabled: disabled, "aria-label": `Preview breakpoint: ${active.name}, ${active.width} pixels`, className: `border-border flex h-[34px] items-center gap-1.5 rounded-lg border px-2.5 text-[12.5px] font-medium transition-colors disabled:opacity-50 ${open
|
|
24
|
+
? 'border-brand bg-accent text-accent-foreground'
|
|
25
|
+
: 'bg-card text-foreground hover:bg-accent'}`, children: [_jsx(ActiveIcon, { className: `h-4 w-4 shrink-0 ${open ? '' : 'text-brand'}`, "aria-hidden": true }), _jsx("span", { className: "hidden lg:inline", children: active.name }), _jsx("span", { className: "lg:hidden", children: active.abbr }), _jsx("span", { className: "text-muted-foreground hidden text-[11.5px] tabular-nums xl:inline", children: active.width }), _jsx(ChevronDown, { className: `h-3.5 w-3.5 shrink-0 transition-transform ${open ? 'rotate-180' : ''}`, "aria-hidden": true })] }) }), _jsx(DropdownMenu.Portal, { container: adminPortalContainer(), children: _jsx(DropdownMenu.Content, { align: "end", sideOffset: 6, className: "border-border bg-popover data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-top-1 z-[120] w-[272px] rounded-[10px] border p-[5px] shadow-[0_12px_34px_rgba(26,24,39,0.17)] duration-[130ms]", children: BREAKPOINT_GROUPS.map((group) => (_jsxs(DropdownMenu.Group, { children: [_jsx(DropdownMenu.Label, { className: "text-muted-foreground px-2.5 pt-2 pb-1 text-[10px] font-bold tracking-[0.6px]", children: group }), breakpointsInGroup(group).map((bp) => {
|
|
26
|
+
const Icon = breakpointIcon(bp.icon);
|
|
27
|
+
const selected = bp.id === value;
|
|
28
|
+
return (_jsxs(DropdownMenu.Item, { onSelect: () => onChange(bp.id), className: `focus:bg-accent flex cursor-pointer items-center gap-2 rounded-[7px] px-2.5 py-[7px] outline-none ${selected ? 'bg-accent' : ''}`, children: [_jsx(Icon, { className: `h-4 w-4 shrink-0 ${selected ? 'text-brand' : 'text-muted-foreground'}`, "aria-hidden": true }), _jsx("span", { className: `flex-1 text-[13px] ${selected ? 'text-brand font-semibold' : 'text-foreground'}`, children: bp.name }), _jsx("span", { className: "text-muted-foreground text-[11.5px] tabular-nums", children: bp.width }), _jsx(Check, { className: `text-brand h-3.5 w-3.5 shrink-0 ${selected ? '' : 'invisible'}`, "aria-label": selected ? 'Selected' : undefined })] }, bp.id));
|
|
29
|
+
})] }, group))) }) })] }));
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=BreakpointPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BreakpointPicker.js","sourceRoot":"","sources":["../../src/components/BreakpointPicker.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-time tip above the page/post canvas explaining how to edit.
|
|
3
|
+
* Dismiss persists in localStorage (`prenta.canvasEditTip.dismissed`).
|
|
4
|
+
*/
|
|
5
|
+
export declare function CanvasEditTip(): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
//# sourceMappingURL=CanvasEditTip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CanvasEditTip.d.ts","sourceRoot":"","sources":["../../src/components/CanvasEditTip.tsx"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAgB,aAAa,mDAmC5B"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { MousePointerClick, X } from 'lucide-react';
|
|
5
|
+
import { dismissCanvasEditTip, isCanvasEditTipDismissed } from '../lib/canvas-edit-chrome.js';
|
|
6
|
+
/**
|
|
7
|
+
* One-time tip above the page/post canvas explaining how to edit.
|
|
8
|
+
* Dismiss persists in localStorage (`prenta.canvasEditTip.dismissed`).
|
|
9
|
+
*/
|
|
10
|
+
export function CanvasEditTip() {
|
|
11
|
+
const [visible, setVisible] = useState(false);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
setVisible(!isCanvasEditTipDismissed());
|
|
14
|
+
}, []);
|
|
15
|
+
if (!visible)
|
|
16
|
+
return null;
|
|
17
|
+
return (_jsxs("div", { role: "note", className: "border-border bg-card text-muted-foreground mx-auto mb-4 flex w-fit max-w-full items-start gap-2 rounded-lg border px-3 py-2 text-xs", children: [_jsx(MousePointerClick, { className: "text-foreground mt-0.5 h-3.5 w-3.5 shrink-0", "aria-hidden": true }), _jsxs("p", { className: "min-w-0 flex-1 leading-[1.5]", children: [_jsx("span", { className: "text-foreground font-medium", children: "Editing tip" }), ' — ', "Hover sections for a light outline, then click to select. Edit copy and images in the inspector. Use ", _jsx("span", { className: "text-foreground font-medium", children: "Site preview" }), " to click text and images in place."] }), _jsx("button", { type: "button", "aria-label": "Dismiss editing tip", onClick: () => {
|
|
18
|
+
dismissCanvasEditTip();
|
|
19
|
+
setVisible(false);
|
|
20
|
+
}, className: "text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:ring-ring -mt-0.5 -mr-0.5 shrink-0 rounded-md p-1 transition-colors focus-visible:ring-2 focus-visible:outline-none", children: _jsx(X, { className: "h-3.5 w-3.5", "aria-hidden": true }) })] }));
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=CanvasEditTip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CanvasEditTip.js","sourceRoot":"","sources":["../../src/components/CanvasEditTip.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAC3C,OAAO,EAAE,iBAAiB,EAAE,CAAC,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAA;AAE7F;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAE7C,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,CAAC,wBAAwB,EAAE,CAAC,CAAA;IACzC,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAA;IAEzB,OAAO,CACL,eACE,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,sIAAsI,aAEhJ,KAAC,iBAAiB,IAAC,SAAS,EAAC,6CAA6C,wBAAe,EACzF,aAAG,SAAS,EAAC,8BAA8B,aACzC,eAAM,SAAS,EAAC,6BAA6B,4BAAmB,EAC/D,KAAK,2GAES,eAAM,SAAS,EAAC,6BAA6B,6BAAoB,2CAE9E,EACJ,iBACE,IAAI,EAAC,QAAQ,gBACF,qBAAqB,EAChC,OAAO,EAAE,GAAG,EAAE;oBACZ,oBAAoB,EAAE,CAAA;oBACtB,UAAU,CAAC,KAAK,CAAC,CAAA;gBACnB,CAAC,EACD,SAAS,EAAC,+LAA+L,YAEzM,KAAC,CAAC,IAAC,SAAS,EAAC,aAAa,wBAAe,GAClC,IACL,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** What the rail hands its children so they can render a header. */
|
|
2
|
+
export interface RailState {
|
|
3
|
+
width: number;
|
|
4
|
+
dragging: boolean;
|
|
5
|
+
collapse: () => void;
|
|
6
|
+
}
|
|
7
|
+
export interface EditorRailProps {
|
|
8
|
+
/** Short label for the collapsed strip — normally the active tab's name. */
|
|
9
|
+
collapsedLabel: string;
|
|
10
|
+
children: (state: RailState) => React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The editor's left rail: resizable, collapsible, and width-persistent.
|
|
14
|
+
*
|
|
15
|
+
* Collapsing UNMOUNTS the rail and swaps in a narrow strip rather than
|
|
16
|
+
* animating its width to zero. A zero-width panel leaves a visible sliver of
|
|
17
|
+
* border and keeps its contents in the accessibility tree, so a screen-reader
|
|
18
|
+
* user lands inside a panel sighted users cannot see.
|
|
19
|
+
*
|
|
20
|
+
* Children are a render prop rather than plain nodes because the panel header
|
|
21
|
+
* needs the live width and drag state — the numbers the rail owns — and
|
|
22
|
+
* threading them through context for one consumer is more machinery than the
|
|
23
|
+
* problem deserves.
|
|
24
|
+
*/
|
|
25
|
+
export declare function EditorRail({ collapsedLabel, children }: EditorRailProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* Header strip under the rail's tabs: panel title, the live width while
|
|
28
|
+
* dragging, and the collapse control.
|
|
29
|
+
*/
|
|
30
|
+
export declare function RailHeader({ title, width, dragging, onCollapse, }: {
|
|
31
|
+
title: string;
|
|
32
|
+
width: number;
|
|
33
|
+
dragging: boolean;
|
|
34
|
+
onCollapse: () => void;
|
|
35
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
//# sourceMappingURL=EditorRail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorRail.d.ts","sourceRoot":"","sources":["../../src/components/EditorRail.tsx"],"names":[],"mappings":"AAcA,oEAAoE;AACpE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,KAAK,CAAC,SAAS,CAAA;CAChD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,eAAe,2CA0IvE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACL,QAAQ,EACR,UAAU,GACX,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,MAAM,IAAI,CAAA;CACvB,2CAwBA"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { PanelLeftClose, PanelLeftOpen } from 'lucide-react';
|
|
5
|
+
import { RAIL_COLLAPSED_WIDTH, RAIL_DEFAULT_WIDTH, RAIL_MAX_WIDTH, RAIL_MIN_WIDTH, clampRailWidth, readRailWidth, writeRailWidth, } from '../lib/rail-width.js';
|
|
6
|
+
/**
|
|
7
|
+
* The editor's left rail: resizable, collapsible, and width-persistent.
|
|
8
|
+
*
|
|
9
|
+
* Collapsing UNMOUNTS the rail and swaps in a narrow strip rather than
|
|
10
|
+
* animating its width to zero. A zero-width panel leaves a visible sliver of
|
|
11
|
+
* border and keeps its contents in the accessibility tree, so a screen-reader
|
|
12
|
+
* user lands inside a panel sighted users cannot see.
|
|
13
|
+
*
|
|
14
|
+
* Children are a render prop rather than plain nodes because the panel header
|
|
15
|
+
* needs the live width and drag state — the numbers the rail owns — and
|
|
16
|
+
* threading them through context for one consumer is more machinery than the
|
|
17
|
+
* problem deserves.
|
|
18
|
+
*/
|
|
19
|
+
export function EditorRail({ collapsedLabel, children }) {
|
|
20
|
+
const [width, setWidth] = useState(RAIL_DEFAULT_WIDTH);
|
|
21
|
+
const [open, setOpen] = useState(true);
|
|
22
|
+
const [dragging, setDragging] = useState(false);
|
|
23
|
+
const railRef = useRef(null);
|
|
24
|
+
// Read persisted width after mount, never during render: there is no
|
|
25
|
+
// localStorage on the server, and seeding initial state from it would
|
|
26
|
+
// hydrate-mismatch.
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
setWidth(readRailWidth());
|
|
29
|
+
}, []);
|
|
30
|
+
const applyWidth = useCallback((next) => {
|
|
31
|
+
const clamped = clampRailWidth(next);
|
|
32
|
+
setWidth(clamped);
|
|
33
|
+
writeRailWidth(clamped);
|
|
34
|
+
}, []);
|
|
35
|
+
const collapse = useCallback(() => setOpen(false), []);
|
|
36
|
+
// Pointer listeners go on `window`, not the handle: the pointer routinely
|
|
37
|
+
// outruns a 7px target mid-drag, and a handle-local listener would drop the
|
|
38
|
+
// drag the moment it did.
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (!dragging)
|
|
41
|
+
return;
|
|
42
|
+
const onMove = (event) => {
|
|
43
|
+
const left = railRef.current?.getBoundingClientRect().left ?? 0;
|
|
44
|
+
applyWidth(event.clientX - left);
|
|
45
|
+
};
|
|
46
|
+
const stop = () => setDragging(false);
|
|
47
|
+
window.addEventListener('pointermove', onMove);
|
|
48
|
+
window.addEventListener('pointerup', stop);
|
|
49
|
+
window.addEventListener('pointercancel', stop);
|
|
50
|
+
// Lock cursor and selection for the duration. Without this the cursor
|
|
51
|
+
// flickers between col-resize and text as it crosses elements, and the
|
|
52
|
+
// drag selects the panel's copy.
|
|
53
|
+
const { body } = document;
|
|
54
|
+
const prevCursor = body.style.cursor;
|
|
55
|
+
const prevSelect = body.style.userSelect;
|
|
56
|
+
body.style.cursor = 'col-resize';
|
|
57
|
+
body.style.userSelect = 'none';
|
|
58
|
+
return () => {
|
|
59
|
+
window.removeEventListener('pointermove', onMove);
|
|
60
|
+
window.removeEventListener('pointerup', stop);
|
|
61
|
+
window.removeEventListener('pointercancel', stop);
|
|
62
|
+
body.style.cursor = prevCursor;
|
|
63
|
+
body.style.userSelect = prevSelect;
|
|
64
|
+
};
|
|
65
|
+
}, [dragging, applyWidth]);
|
|
66
|
+
if (!open) {
|
|
67
|
+
return (_jsxs("div", { className: "prenta-editor-rail-collapsed bg-card border-border flex shrink-0 flex-col items-center gap-3 border-r py-3", style: { width: RAIL_COLLAPSED_WIDTH }, children: [_jsx("button", { type: "button", onClick: () => setOpen(true), "aria-label": `Expand ${collapsedLabel} panel`, title: `Expand ${collapsedLabel} panel`, className: "prenta-touch-target text-muted-foreground hover:bg-accent hover:text-accent-foreground flex h-6.5 w-6.5 items-center justify-center rounded-md transition-colors", children: _jsx(PanelLeftOpen, { className: "h-4 w-4", "aria-hidden": true }) }), _jsx("span", { className: "prenta-rail-label text-muted-foreground text-[10px] font-bold tracking-[0.8px] whitespace-nowrap uppercase [writing-mode:vertical-rl]", "aria-hidden": true, children: collapsedLabel })] }));
|
|
68
|
+
}
|
|
69
|
+
return (_jsxs("div", { ref: railRef, className: `prenta-editor-rail bg-card border-border relative flex shrink-0 flex-col border-r ${
|
|
70
|
+
// A width transition during a drag fights the pointer: the panel
|
|
71
|
+
// chases the cursor a frame behind and the resize feels broken.
|
|
72
|
+
dragging ? '' : 'motion-safe:transition-[width] motion-safe:duration-(--mo-slow)'}`, style: { width }, children: [_jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: children({ width, dragging, collapse }) }), _jsx("div", {
|
|
73
|
+
// `separator` with an orientation and a value range is what makes this
|
|
74
|
+
// operable without a pointer. A bare div with a pointerdown handler is
|
|
75
|
+
// invisible to keyboard and assistive-tech users.
|
|
76
|
+
role: "separator", "aria-orientation": "vertical", "aria-label": "Resize panel", "aria-valuenow": width, "aria-valuemin": RAIL_MIN_WIDTH, "aria-valuemax": RAIL_MAX_WIDTH, tabIndex: 0, onPointerDown: (event) => {
|
|
77
|
+
event.preventDefault();
|
|
78
|
+
setDragging(true);
|
|
79
|
+
}, onDoubleClick: () => applyWidth(RAIL_DEFAULT_WIDTH), onKeyDown: (event) => {
|
|
80
|
+
const step = event.shiftKey ? 48 : 16;
|
|
81
|
+
if (event.key === 'ArrowLeft') {
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
applyWidth(width - step);
|
|
84
|
+
}
|
|
85
|
+
else if (event.key === 'ArrowRight') {
|
|
86
|
+
event.preventDefault();
|
|
87
|
+
applyWidth(width + step);
|
|
88
|
+
}
|
|
89
|
+
else if (event.key === 'Home') {
|
|
90
|
+
event.preventDefault();
|
|
91
|
+
applyWidth(RAIL_DEFAULT_WIDTH);
|
|
92
|
+
}
|
|
93
|
+
}, className: "group absolute inset-y-0 -right-[3px] z-30 w-[7px] cursor-col-resize focus-visible:outline-none", children: _jsx("span", { "aria-hidden": true, className: `pointer-events-none absolute inset-y-0 left-[2.5px] w-0.5 transition-colors ${dragging
|
|
94
|
+
? 'bg-brand'
|
|
95
|
+
: 'group-hover:bg-brand group-focus-visible:bg-brand bg-transparent'}` }) })] }));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Header strip under the rail's tabs: panel title, the live width while
|
|
99
|
+
* dragging, and the collapse control.
|
|
100
|
+
*/
|
|
101
|
+
export function RailHeader({ title, width, dragging, onCollapse, }) {
|
|
102
|
+
return (_jsxs("div", { className: "border-border flex items-center justify-between gap-2 border-b px-3.5 py-2.5", children: [_jsx("h2", { className: "text-foreground truncate text-[12.5px] font-semibold", children: title }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [dragging && (_jsxs("span", { className: "text-muted-foreground text-[11px] tabular-nums", "aria-hidden": true, children: [width, "px"] })), _jsx("button", { type: "button", onClick: onCollapse, "aria-label": `Collapse ${title} panel`, title: `Collapse ${title} panel`, className: "prenta-touch-target text-muted-foreground hover:bg-accent hover:text-accent-foreground flex h-6.5 w-6.5 items-center justify-center rounded-md transition-colors", children: _jsx(PanelLeftClose, { className: "h-4 w-4", "aria-hidden": true }) })] })] }));
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=EditorRail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorRail.js","sourceRoot":"","sources":["../../src/components/EditorRail.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type RailTabId = 'sections' | 'seo' | 'page';
|
|
2
|
+
export interface RailTab {
|
|
3
|
+
id: RailTabId;
|
|
4
|
+
label: string;
|
|
5
|
+
/** Panel title shown in the header below the strip. */
|
|
6
|
+
title: string;
|
|
7
|
+
/** Count pill (Sections). */
|
|
8
|
+
count?: number;
|
|
9
|
+
/**
|
|
10
|
+
* Score for the dot, banded by the page audit's own scale.
|
|
11
|
+
*
|
|
12
|
+
* `undefined` — not known yet; no dot is shown rather than a misleading one.
|
|
13
|
+
* `null` — deliberately not rated (a gate is off, e.g. the page is
|
|
14
|
+
* noindexed). Renders neutral, never as a low score.
|
|
15
|
+
*/
|
|
16
|
+
score?: number | null;
|
|
17
|
+
}
|
|
18
|
+
export interface EditorRailTabsProps {
|
|
19
|
+
tabs: RailTab[];
|
|
20
|
+
active: RailTabId;
|
|
21
|
+
onChange: (id: RailTabId) => void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Three equal tabs across the top of the rail.
|
|
25
|
+
*
|
|
26
|
+
* Each tab carries a status glyph so the rail reads at a glance without being
|
|
27
|
+
* opened: a count for Sections, a band-coloured dot for SEO. The dot is
|
|
28
|
+
* accompanied by text in the accessible name — colour alone is not a signal
|
|
29
|
+
* for anyone who cannot distinguish these hues.
|
|
30
|
+
*/
|
|
31
|
+
export declare function EditorRailTabs({ tabs, active, onChange }: EditorRailTabsProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
//# sourceMappingURL=EditorRailTabs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorRailTabs.d.ts","sourceRoot":"","sources":["../../src/components/EditorRailTabs.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,MAAM,CAAA;AAEnD,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,SAAS,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;IACb,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,EAAE,CAAA;IACf,MAAM,EAAE,SAAS,CAAA;IACjB,QAAQ,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,CAAA;CAClC;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,mBAAmB,2CA+E7E"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { scoreBand } from '@prenta/core/seo/page-audit';
|
|
4
|
+
/**
|
|
5
|
+
* Three equal tabs across the top of the rail.
|
|
6
|
+
*
|
|
7
|
+
* Each tab carries a status glyph so the rail reads at a glance without being
|
|
8
|
+
* opened: a count for Sections, a band-coloured dot for SEO. The dot is
|
|
9
|
+
* accompanied by text in the accessible name — colour alone is not a signal
|
|
10
|
+
* for anyone who cannot distinguish these hues.
|
|
11
|
+
*/
|
|
12
|
+
export function EditorRailTabs({ tabs, active, onChange }) {
|
|
13
|
+
return (_jsx("div", { role: "tablist", "aria-label": "Editor panels", className: "border-border flex border-b", children: tabs.map((tab) => {
|
|
14
|
+
const selected = tab.id === active;
|
|
15
|
+
// Bands with `scoreBand` from the audit itself, NOT `gradeFromScore`.
|
|
16
|
+
// The two disagree between 55 and 59 — a page scoring 57 read "fair"
|
|
17
|
+
// in the rings and "poor" on the tab summarising them, which is the
|
|
18
|
+
// same class of disagreement this dot was rewired to eliminate.
|
|
19
|
+
const band = typeof tab.score === 'number' ? scoreBand(tab.score) : null;
|
|
20
|
+
const unrated = tab.score === null;
|
|
21
|
+
return (_jsxs("button", { type: "button", role: "tab", id: `rail-tab-${tab.id}`, "aria-selected": selected, "aria-controls": `rail-panel-${tab.id}`, tabIndex: selected ? 0 : -1, onClick: () => onChange(tab.id), onKeyDown: (event) => {
|
|
22
|
+
// Arrow keys move between tabs — expected of a tablist, and the
|
|
23
|
+
// only way to reach a tab whose tabIndex is -1.
|
|
24
|
+
const index = tabs.findIndex((t) => t.id === active);
|
|
25
|
+
if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {
|
|
26
|
+
event.preventDefault();
|
|
27
|
+
const delta = event.key === 'ArrowRight' ? 1 : -1;
|
|
28
|
+
const next = tabs[(index + delta + tabs.length) % tabs.length];
|
|
29
|
+
if (next) {
|
|
30
|
+
onChange(next.id);
|
|
31
|
+
document.getElementById(`rail-tab-${next.id}`)?.focus();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}, className: `flex flex-1 items-center justify-center gap-1.5 border-b-2 pt-2.5 pb-2 text-[12.5px] transition-colors ${selected
|
|
35
|
+
? 'border-brand text-brand font-semibold'
|
|
36
|
+
: 'text-muted-foreground hover:text-foreground border-transparent font-medium'}`, children: [tab.label, tab.count !== undefined && (_jsx("span", { className: `rounded-full px-1.5 text-[10.5px] font-semibold tabular-nums ${selected ? 'bg-accent text-accent-foreground' : 'bg-muted text-muted-foreground'}`, children: tab.count })), (band || unrated) && (_jsxs(_Fragment, { children: [_jsx("span", { className: `h-[7px] w-[7px] shrink-0 rounded-full ${band === 'good'
|
|
37
|
+
? 'bg-success'
|
|
38
|
+
: band === 'fair'
|
|
39
|
+
? 'bg-warning'
|
|
40
|
+
: band === 'poor'
|
|
41
|
+
? 'bg-destructive'
|
|
42
|
+
: 'bg-muted-foreground/40'}`, "aria-hidden": true }), _jsx("span", { className: "sr-only", children: unrated ? 'not rated' : `score ${tab.score} of 100` })] }))] }, tab.id));
|
|
43
|
+
}) }));
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=EditorRailTabs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorRailTabs.js","sourceRoot":"","sources":["../../src/components/EditorRailTabs.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type MediaCrop } from '../lib/media-format.js';
|
|
3
|
+
interface MediaItem {
|
|
4
|
+
id: string;
|
|
5
|
+
filename: string;
|
|
6
|
+
storageKey: string;
|
|
7
|
+
url?: string;
|
|
8
|
+
altTag?: string;
|
|
9
|
+
mimeType: string;
|
|
10
|
+
width?: number;
|
|
11
|
+
height?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface MediaBlockProps {
|
|
14
|
+
/** Current asset URL, or empty for the empty state. */
|
|
15
|
+
value: string;
|
|
16
|
+
onChange: (url: string, item?: MediaItem) => void;
|
|
17
|
+
/** The crop the template renders this image at. */
|
|
18
|
+
crop?: MediaCrop;
|
|
19
|
+
/** Rows rendered between the frame and the toolbar (the social preview). */
|
|
20
|
+
children?: ReactNode;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
/** Accessible label, e.g. "Hero image". */
|
|
23
|
+
label?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* One component for every image — section slots and the social/OG card alike.
|
|
27
|
+
*
|
|
28
|
+
* ── The frame shows the TEMPLATE's crop, not the asset's ─────────────────
|
|
29
|
+
*
|
|
30
|
+
* A section image renders at 16:10 and a social card at 1.91:1 regardless of
|
|
31
|
+
* what was uploaded. Framing the asset's own ratio would tell an editor their
|
|
32
|
+
* portrait photo looks fine and then crop its subject out on the page. What
|
|
33
|
+
* the asset actually is gets reported in the toolbar instead, as a ratio label
|
|
34
|
+
* beside its filename, so both facts are visible and neither is implied.
|
|
35
|
+
*
|
|
36
|
+
* ── The toolbar is always visible ────────────────────────────────────────
|
|
37
|
+
*
|
|
38
|
+
* Never hover-only. Replace and Remove are the two things an editor comes here
|
|
39
|
+
* to do, and hiding them behind a hover makes them undiscoverable on touch and
|
|
40
|
+
* invisible to anyone scanning the panel.
|
|
41
|
+
*
|
|
42
|
+
* ── The picker opens inside the shell ────────────────────────────────────
|
|
43
|
+
*
|
|
44
|
+
* Not a modal. Choosing an image is a comparison against the slot it is going
|
|
45
|
+
* into, and a dialog covering the slot removes the only context that matters.
|
|
46
|
+
*/
|
|
47
|
+
export declare function MediaBlock({ value, onChange, crop, children, disabled, label, }: MediaBlockProps): import("react/jsx-runtime").JSX.Element;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=MediaBlock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaBlock.d.ts","sourceRoot":"","sources":["../../src/components/MediaBlock.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAGhD,OAAO,EAML,KAAK,SAAS,EACf,MAAM,wBAAwB,CAAA;AAE/B,UAAU,SAAS;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA;IACjD,mDAAmD;IACnD,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,IAAgB,EAChB,QAAQ,EACR,QAAgB,EAChB,KAAe,GAChB,EAAE,eAAe,2CA2JjB"}
|