@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,95 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { ChevronDown, Globe } from 'lucide-react';
|
|
5
|
+
import { cmsApi } from '../../lib/api.js';
|
|
6
|
+
/**
|
|
7
|
+
* Byline picker: a CMS user, the brand, or a one-off guest name.
|
|
8
|
+
*
|
|
9
|
+
* ── What this does and does not change ────────────────────────────────────
|
|
10
|
+
*
|
|
11
|
+
* It sets the page's DISPLAYED author, which reaches the page's structured
|
|
12
|
+
* data. It does not reassign the document's `createdById` — that records who
|
|
13
|
+
* created the record, and trading an audit trail for a label is not a swap
|
|
14
|
+
* worth making silently. A page written by a staff editor and bylined to the
|
|
15
|
+
* brand is a normal thing; a page whose history says someone else made it is
|
|
16
|
+
* not.
|
|
17
|
+
*
|
|
18
|
+
* The menu renders inline below the trigger rather than floating. The rail is
|
|
19
|
+
* narrow and scrollable, and a floating menu inside a scroll container either
|
|
20
|
+
* clips or detaches from its trigger on scroll.
|
|
21
|
+
*/
|
|
22
|
+
export function AuthorPicker({ value, onChange, brandName, disabled = false }) {
|
|
23
|
+
const [open, setOpen] = useState(false);
|
|
24
|
+
const [users, setUsers] = useState([]);
|
|
25
|
+
const [guest, setGuest] = useState('');
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (!open || users.length > 0)
|
|
28
|
+
return;
|
|
29
|
+
let cancelled = false;
|
|
30
|
+
cmsApi('/users').then((res) => {
|
|
31
|
+
if (cancelled || !res.data)
|
|
32
|
+
return;
|
|
33
|
+
const list = Array.isArray(res.data) ? res.data : (res.data.users ?? []);
|
|
34
|
+
setUsers(list);
|
|
35
|
+
});
|
|
36
|
+
return () => {
|
|
37
|
+
cancelled = true;
|
|
38
|
+
};
|
|
39
|
+
}, [open, users.length]);
|
|
40
|
+
const isGeneric = Boolean(brandName) && value.name === brandName && !value.id;
|
|
41
|
+
const label = value.name || 'No byline';
|
|
42
|
+
const sub = value.id
|
|
43
|
+
? (users.find((u) => u.id === value.id)?.role ?? 'CMS user')
|
|
44
|
+
: isGeneric
|
|
45
|
+
? 'Brand byline'
|
|
46
|
+
: value.name
|
|
47
|
+
? 'Guest byline'
|
|
48
|
+
: 'None set';
|
|
49
|
+
function pick(next) {
|
|
50
|
+
onChange(next);
|
|
51
|
+
setOpen(false);
|
|
52
|
+
}
|
|
53
|
+
return (_jsxs("div", { children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), disabled: disabled, "aria-expanded": open, className: "border-border bg-card hover:border-ring flex w-full items-center gap-2.5 rounded-[7px] border-[1.5px] px-2.5 py-[7px] text-left transition-colors disabled:opacity-50", children: [_jsx(Avatar, { name: value.name, generic: isGeneric }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "text-foreground block truncate text-[12.5px] font-semibold", children: label }), _jsx("span", { className: "text-muted-foreground block text-[10.5px]", children: sub })] }), _jsx(ChevronDown, { size: 14, "aria-hidden": true, className: `text-muted-foreground shrink-0 motion-safe:transition-transform ${open ? 'rotate-180' : ''}` })] }), open && (_jsxs("div", { className: "border-border mt-1.5 space-y-2 rounded-[9px] border p-2", children: [_jsx(Group, { label: "CMS users", children: users.length === 0 ? (_jsx("p", { className: "text-muted-foreground px-1 py-1.5 text-[11px]", children: "Loading\u2026" })) : (users.map((u) => {
|
|
54
|
+
const name = u.name || u.email || 'Unnamed user';
|
|
55
|
+
return (_jsxs(Row, { selected: value.id === u.id, onClick: () => pick({ name, id: u.id }), children: [_jsx(Avatar, { name: name }), _jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "block truncate text-[12px] font-medium", children: name }), _jsx("span", { className: "text-muted-foreground block text-[10px]", children: u.role ?? 'Author' })] })] }, u.id));
|
|
56
|
+
})) }), brandName && (_jsx(Group, { label: "Generic", children: _jsxs(Row, { selected: isGeneric, onClick: () => pick({ name: brandName, id: '' }), children: [_jsx(Avatar, { name: brandName, generic: true }), _jsx("span", { className: "text-[12px] font-medium", children: brandName })] }) })), _jsx(Group, { label: "Guest byline", children: _jsxs("div", { className: "flex gap-1.5 px-1", children: [_jsx("input", { value: guest, onChange: (e) => setGuest(e.target.value), placeholder: "Name to display", "aria-label": "Guest byline name", className: "border-border bg-input-background focus-visible:border-ring min-w-0 flex-1 rounded-md border px-2 py-1 text-[11.5px] focus-visible:outline-none" }), _jsx("button", { type: "button",
|
|
57
|
+
// Disabled until non-empty: an empty guest byline would clear
|
|
58
|
+
// the author while looking like it set one.
|
|
59
|
+
disabled: guest.trim().length === 0, onClick: () => {
|
|
60
|
+
pick({ name: guest.trim(), id: '' });
|
|
61
|
+
setGuest('');
|
|
62
|
+
}, className: "bg-primary text-primary-foreground rounded-md px-2 py-1 text-[11px] font-semibold disabled:opacity-40", children: "Add" })] }) })] }))] }));
|
|
63
|
+
}
|
|
64
|
+
function Group({ label, children }) {
|
|
65
|
+
return (_jsxs("div", { children: [_jsx("p", { className: "text-muted-foreground px-1 pb-1 text-[9.5px] font-bold tracking-wide uppercase", children: label }), _jsx("div", { className: "space-y-0.5", children: children })] }));
|
|
66
|
+
}
|
|
67
|
+
function Row({ selected, onClick, children, }) {
|
|
68
|
+
return (_jsx("button", { type: "button", onClick: onClick, "aria-current": selected || undefined, className: `flex w-full items-center gap-2 rounded-md px-1.5 py-1.5 text-left transition-colors ${selected ? 'bg-accent' : 'hover:bg-accent/60'}`, children: children }));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Initials on a tint derived from the name, so the same person is the same
|
|
72
|
+
* colour everywhere without storing one. A globe replaces initials for the
|
|
73
|
+
* brand byline — "Ex" for "Example Inc" reads as a person, which is the one
|
|
74
|
+
* thing the generic option is not.
|
|
75
|
+
*/
|
|
76
|
+
function Avatar({ name, generic = false }) {
|
|
77
|
+
if (generic) {
|
|
78
|
+
return (_jsx("span", { className: "bg-muted text-muted-foreground flex h-[27px] w-[27px] shrink-0 items-center justify-center rounded-full", children: _jsx(Globe, { size: 14, "aria-hidden": true }) }));
|
|
79
|
+
}
|
|
80
|
+
const initials = name
|
|
81
|
+
.trim()
|
|
82
|
+
.split(/\s+/)
|
|
83
|
+
.slice(0, 2)
|
|
84
|
+
.map((w) => w[0] ?? '')
|
|
85
|
+
.join('')
|
|
86
|
+
.toUpperCase() || '—';
|
|
87
|
+
let hash = 0;
|
|
88
|
+
for (let i = 0; i < name.length; i++)
|
|
89
|
+
hash = (hash * 31 + name.charCodeAt(i)) % 360;
|
|
90
|
+
return (_jsx("span", { "aria-hidden": true, className: "flex h-[27px] w-[27px] shrink-0 items-center justify-center rounded-full text-[10px] font-bold", style: {
|
|
91
|
+
backgroundColor: `oklch(0.92 0.05 ${hash})`,
|
|
92
|
+
color: `oklch(0.42 0.12 ${hash})`,
|
|
93
|
+
}, children: initials }));
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=AuthorPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthorPicker.js","sourceRoot":"","sources":["../../../src/components/page-tab/AuthorPicker.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface DirectiveSwitchProps {
|
|
2
|
+
id: string;
|
|
3
|
+
/** Human label, e.g. "Show in search results". */
|
|
4
|
+
label: string;
|
|
5
|
+
/** One line on what turning it off actually costs. */
|
|
6
|
+
hint?: string;
|
|
7
|
+
/** `true` = permissive. */
|
|
8
|
+
checked: boolean;
|
|
9
|
+
onChange: (next: boolean) => void;
|
|
10
|
+
/** Directive token when permitted, e.g. `index`. */
|
|
11
|
+
permissiveToken: string;
|
|
12
|
+
/** Directive token when restricted, e.g. `noindex`. */
|
|
13
|
+
restrictiveToken: string;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A robots-directive switch.
|
|
18
|
+
*
|
|
19
|
+
* ── Why this is not the ordinary Toggle ───────────────────────────────────
|
|
20
|
+
*
|
|
21
|
+
* The admin's `Toggle` turns brand purple when on, because "on" is the state
|
|
22
|
+
* the product is nudging you towards. That reading is wrong here. These
|
|
23
|
+
* switches are not on/off, they are permissive/restrictive — and the meaningful
|
|
24
|
+
* distinction is not "did I enable something" but "is this page still allowed
|
|
25
|
+
* to be found". Purple would say "enabled" about a switch whose enabled state
|
|
26
|
+
* is simply the default, and say nothing about the one state worth noticing.
|
|
27
|
+
*
|
|
28
|
+
* So: green when permitted, red when restricted. And the literal directive
|
|
29
|
+
* token sits beside it, because the failure this UI has to prevent is an editor
|
|
30
|
+
* flipping something whose consequence they could not name. `noindex` next to
|
|
31
|
+
* the switch turns an abstract toggle into the thing it actually writes into
|
|
32
|
+
* the page's head.
|
|
33
|
+
*
|
|
34
|
+
* Colour never carries it alone — the token chip is text, and the switch's
|
|
35
|
+
* accessible name states the label and the token it will produce.
|
|
36
|
+
*/
|
|
37
|
+
export declare function DirectiveSwitch({ id, label, hint, checked, onChange, permissiveToken, restrictiveToken, disabled, }: DirectiveSwitchProps): import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
//# sourceMappingURL=DirectiveSwitch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DirectiveSwitch.d.ts","sourceRoot":"","sources":["../../../src/components/page-tab/DirectiveSwitch.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACjC,oDAAoD;IACpD,eAAe,EAAE,MAAM,CAAA;IACvB,uDAAuD;IACvD,gBAAgB,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,EAC9B,EAAE,EACF,KAAK,EACL,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,QAAgB,GACjB,EAAE,oBAAoB,2CAmCtB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as Switch from '@radix-ui/react-switch';
|
|
4
|
+
/**
|
|
5
|
+
* A robots-directive switch.
|
|
6
|
+
*
|
|
7
|
+
* ── Why this is not the ordinary Toggle ───────────────────────────────────
|
|
8
|
+
*
|
|
9
|
+
* The admin's `Toggle` turns brand purple when on, because "on" is the state
|
|
10
|
+
* the product is nudging you towards. That reading is wrong here. These
|
|
11
|
+
* switches are not on/off, they are permissive/restrictive — and the meaningful
|
|
12
|
+
* distinction is not "did I enable something" but "is this page still allowed
|
|
13
|
+
* to be found". Purple would say "enabled" about a switch whose enabled state
|
|
14
|
+
* is simply the default, and say nothing about the one state worth noticing.
|
|
15
|
+
*
|
|
16
|
+
* So: green when permitted, red when restricted. And the literal directive
|
|
17
|
+
* token sits beside it, because the failure this UI has to prevent is an editor
|
|
18
|
+
* flipping something whose consequence they could not name. `noindex` next to
|
|
19
|
+
* the switch turns an abstract toggle into the thing it actually writes into
|
|
20
|
+
* the page's head.
|
|
21
|
+
*
|
|
22
|
+
* Colour never carries it alone — the token chip is text, and the switch's
|
|
23
|
+
* accessible name states the label and the token it will produce.
|
|
24
|
+
*/
|
|
25
|
+
export function DirectiveSwitch({ id, label, hint, checked, onChange, permissiveToken, restrictiveToken, disabled = false, }) {
|
|
26
|
+
const token = checked ? permissiveToken : restrictiveToken;
|
|
27
|
+
return (_jsxs("div", { className: "flex items-start justify-between gap-3 py-1.5", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("label", { htmlFor: id, className: "text-foreground block text-[12.5px] font-medium", children: label }), hint && _jsx("p", { className: "text-muted-foreground mt-0.5 text-[11px] leading-snug", children: hint })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx("code", { className: `rounded px-1.5 py-0.5 font-mono text-[9.5px] font-bold ${checked ? 'bg-success/12 text-success' : 'bg-destructive/12 text-destructive'}`, children: token }), _jsx(Switch.Root, { id: id, checked: checked, onCheckedChange: onChange, disabled: disabled, "aria-label": `${label} — currently ${token}`, className: `focus-visible:ring-ring relative h-[19px] w-[34px] shrink-0 rounded-full transition-colors duration-(--mo-base) focus-visible:ring-2 focus-visible:outline-none disabled:opacity-50 ${checked ? 'bg-success' : 'bg-destructive/55'}`, children: _jsx(Switch.Thumb, { className: "block h-3.5 w-3.5 translate-x-[2.5px] rounded-full bg-white shadow-[0_1px_3px_rgba(0,0,0,0.25)] transition-transform duration-(--mo-base) data-[state=checked]:translate-x-[18px]" }) })] })] }));
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=DirectiveSwitch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DirectiveSwitch.js","sourceRoot":"","sources":["../../../src/components/page-tab/DirectiveSwitch.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,KAAK,MAAM,MAAM,wBAAwB,CAAA;AAkBhD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,EAAE,EACF,KAAK,EACL,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,QAAQ,GAAG,KAAK,GACK;IACrB,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,gBAAgB,CAAA;IAE1D,OAAO,CACL,eAAK,SAAS,EAAC,+CAA+C,aAC5D,eAAK,SAAS,EAAC,SAAS,aACtB,gBAAO,OAAO,EAAE,EAAE,EAAE,SAAS,EAAC,iDAAiD,YAC5E,KAAK,GACA,EACP,IAAI,IAAI,YAAG,SAAS,EAAC,uDAAuD,YAAE,IAAI,GAAK,IACpF,EAEN,eAAK,SAAS,EAAC,kCAAkC,aAC/C,eACE,SAAS,EAAE,0DACT,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,oCAC3C,EAAE,YAED,KAAK,GACD,EACP,KAAC,MAAM,CAAC,IAAI,IACV,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,QAAQ,EACzB,QAAQ,EAAE,QAAQ,gBACN,GAAG,KAAK,gBAAgB,KAAK,EAAE,EAC3C,SAAS,EAAE,uLACT,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,mBAC3B,EAAE,YAEF,KAAC,MAAM,CAAC,KAAK,IAAC,SAAS,EAAC,mLAAmL,GAAG,GAClM,IACV,IACF,CACP,CAAA;AACH,CAAC"}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
/** Compact color-coded score for the page/post editor toolbar (`77/100` left of "SEO"). */
|
|
2
|
-
export declare function EditorSeoScoreBadge({ score, inverted, }: {
|
|
2
|
+
export declare function EditorSeoScoreBadge({ score, band, inverted, }: {
|
|
3
3
|
score: number;
|
|
4
|
+
/**
|
|
5
|
+
* Band for the colour. Supplied by the caller because different scores use
|
|
6
|
+
* different scales: the page audit bands at 80/55, `analyzeContent` at
|
|
7
|
+
* 80/60/1. Deriving it here would colour one model's number with another
|
|
8
|
+
* model's thresholds — they disagree between 55 and 59.
|
|
9
|
+
*/
|
|
10
|
+
band?: 'good' | 'fair' | 'poor';
|
|
4
11
|
/** When the SEO toggle uses `bg-primary`, render score in primary-foreground. */
|
|
5
12
|
inverted?: boolean;
|
|
6
13
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorSeoScoreBadge.d.ts","sourceRoot":"","sources":["../../../src/components/seo/EditorSeoScoreBadge.tsx"],"names":[],"mappings":"AAIA,2FAA2F;AAC3F,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,QAAgB,GACjB,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,2CAaA"}
|
|
1
|
+
{"version":3,"file":"EditorSeoScoreBadge.d.ts","sourceRoot":"","sources":["../../../src/components/seo/EditorSeoScoreBadge.tsx"],"names":[],"mappings":"AAIA,2FAA2F;AAC3F,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,IAAI,EACJ,QAAgB,GACjB,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,2CAaA"}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { gradeFromScore, gradeMeta } from './primitives.js';
|
|
4
4
|
/** Compact color-coded score for the page/post editor toolbar (`77/100` left of "SEO"). */
|
|
5
|
-
export function EditorSeoScoreBadge({ score, inverted = false, }) {
|
|
6
|
-
const meta = gradeMeta(gradeFromScore(score));
|
|
5
|
+
export function EditorSeoScoreBadge({ score, band, inverted = false, }) {
|
|
6
|
+
const meta = gradeMeta(band ?? gradeFromScore(score));
|
|
7
7
|
return (_jsxs("span", { className: `inline-flex items-baseline gap-0.5 text-xs font-medium tabular-nums ${inverted ? 'text-primary-foreground' : meta.text}`, "aria-hidden": true, children: [score, _jsx("span", { className: inverted ? 'text-primary-foreground/80' : 'opacity-70', children: "/100" })] }));
|
|
8
8
|
}
|
|
9
9
|
//# sourceMappingURL=EditorSeoScoreBadge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorSeoScoreBadge.js","sourceRoot":"","sources":["../../../src/components/seo/EditorSeoScoreBadge.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3D,2FAA2F;AAC3F,MAAM,UAAU,mBAAmB,CAAC,EAClC,KAAK,EACL,QAAQ,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"EditorSeoScoreBadge.js","sourceRoot":"","sources":["../../../src/components/seo/EditorSeoScoreBadge.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3D,2FAA2F;AAC3F,MAAM,UAAU,mBAAmB,CAAC,EAClC,KAAK,EACL,IAAI,EACJ,QAAQ,GAAG,KAAK,GAYjB;IACC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC,CAAA;IACrD,OAAO,CACL,gBACE,SAAS,EAAE,uEACT,QAAQ,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,IAAI,CAAC,IAC9C,EAAE,kCAGD,KAAK,EACN,eAAM,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,YAAY,qBAAa,IAC/E,CACR,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type PageAuditResult } from '@prenta/core/seo/page-audit';
|
|
2
|
+
export interface PageAuditPanelProps {
|
|
3
|
+
audit: PageAuditResult;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Twin score rings over the SEO and GEO check lists.
|
|
7
|
+
*
|
|
8
|
+
* Both scores are reported the same way and neither is folded into a single
|
|
9
|
+
* headline: classic search and AI answer visibility fail for different reasons
|
|
10
|
+
* and are fixed by different edits, so averaging them would hide whichever is
|
|
11
|
+
* worse.
|
|
12
|
+
*/
|
|
13
|
+
export declare function PageAuditPanel({ audit }: PageAuditPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=PageAuditPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageAuditPanel.d.ts","sourceRoot":"","sources":["../../../src/components/seo/PageAuditPanel.tsx"],"names":[],"mappings":"AAIA,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,6BAA6B,CAAA;AA4IpC,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,eAAe,CAAA;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,EAAE,mBAAmB,2CA8B5D"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { ChevronDown, Search, Sparkles } from 'lucide-react';
|
|
5
|
+
import { scoreBand, } from '@prenta/core/seo/page-audit';
|
|
6
|
+
const BAND_TEXT = { good: 'text-success', fair: 'text-warning', poor: 'text-destructive' };
|
|
7
|
+
const BAND_STROKE = {
|
|
8
|
+
good: 'stroke-success',
|
|
9
|
+
fair: 'stroke-warning',
|
|
10
|
+
poor: 'stroke-destructive',
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* A 52px score ring.
|
|
14
|
+
*
|
|
15
|
+
* `null` is a real state, not an error: a page held back from search has no
|
|
16
|
+
* search performance to rate. It renders as a dash on a neutral track rather
|
|
17
|
+
* than an alarming zero.
|
|
18
|
+
*/
|
|
19
|
+
function ScoreRing({ score, label }) {
|
|
20
|
+
const R = 21;
|
|
21
|
+
const CIRCUMFERENCE = 2 * Math.PI * R;
|
|
22
|
+
const band = score === null ? null : scoreBand(score);
|
|
23
|
+
const dash = score === null ? 0 : (score / 100) * CIRCUMFERENCE;
|
|
24
|
+
return (_jsxs("svg", { width: "52", height: "52", viewBox: "0 0 52 52", role: "img", "aria-label": score === null ? `${label}: not rated` : `${label} score: ${score} of 100`, children: [_jsx("circle", { cx: "26", cy: "26", r: R, className: "stroke-border", strokeWidth: "5", fill: "none" }), score !== null && (_jsx("circle", { cx: "26", cy: "26", r: R, className: `${BAND_STROKE[band]} motion-safe:transition-[stroke-dasharray,stroke] motion-safe:duration-350`, strokeWidth: "5", fill: "none", strokeLinecap: "round", strokeDasharray: `${dash} ${CIRCUMFERENCE - dash}`,
|
|
25
|
+
// Start the arc at twelve o'clock instead of three.
|
|
26
|
+
transform: "rotate(-90 26 26)" })), _jsx("text", { x: "26", y: "26", textAnchor: "middle", dominantBaseline: "central", className: `fill-current text-[15px] font-bold tabular-nums ${band ? BAND_TEXT[band] : 'text-muted-foreground'}`, children: score === null ? '—' : score })] }));
|
|
27
|
+
}
|
|
28
|
+
function CheckRow({ check }) {
|
|
29
|
+
const na = check.outcome === 'not-applicable';
|
|
30
|
+
const pass = check.outcome === 'pass';
|
|
31
|
+
return (_jsxs("li", { className: "border-border flex gap-2 border-b py-[7px] last:border-b-0", children: [_jsx("span", { "aria-hidden": true, className: `mt-0.5 h-4 w-4 shrink-0 rounded ${na ? 'bg-muted' : pass ? 'bg-success/15 text-success' : 'bg-warning/15 text-warning'}` }), _jsxs("div", { className: "min-w-0", children: [_jsxs("p", { className: `text-xs font-medium ${na ? 'text-muted-foreground' : 'text-foreground'}`, children: [check.label, _jsx("span", { className: "sr-only", children: na ? ' — not applicable' : pass ? ' — passing' : ' — needs attention' })] }), na ? (_jsx("p", { className: "text-muted-foreground text-[10.5px]", children: check.naReason })) : pass ? null : (_jsx("p", { className: "text-muted-foreground text-[10.5px]", children: check.hint }))] })] }));
|
|
32
|
+
}
|
|
33
|
+
function CheckGroup({ result, title }) {
|
|
34
|
+
const [open, setOpen] = useState(true);
|
|
35
|
+
const band = result.score === null ? null : scoreBand(result.score);
|
|
36
|
+
return (_jsxs("section", { className: "border-border border-b", children: [_jsxs("button", { type: "button", onClick: () => setOpen((o) => !o), "aria-expanded": open, className: "hover:bg-accent flex w-full items-center justify-between px-3.5 py-2.5 transition-colors", children: [_jsx("span", { className: "text-muted-foreground text-[10px] font-bold tracking-[0.7px] uppercase", children: title }), _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: `rounded-full px-1.5 text-[10px] font-bold tabular-nums ${band === 'good'
|
|
37
|
+
? 'bg-success/15 text-success'
|
|
38
|
+
: band === 'fair'
|
|
39
|
+
? 'bg-warning/15 text-warning'
|
|
40
|
+
: band === 'poor'
|
|
41
|
+
? 'bg-destructive/15 text-destructive'
|
|
42
|
+
: 'bg-muted text-muted-foreground'}`, children: result.score === null ? 'n/a' : `${result.passed}/${result.applicable}` }), _jsx(ChevronDown, { className: `text-muted-foreground h-3.5 w-3.5 transition-transform ${open ? 'rotate-180' : ''}`, "aria-hidden": true })] })] }), open && (_jsx("ul", { className: "px-3.5 pb-3.5", children: result.checks.map((c) => (_jsx(CheckRow, { check: c }, c.id))) }))] }));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Twin score rings over the SEO and GEO check lists.
|
|
46
|
+
*
|
|
47
|
+
* Both scores are reported the same way and neither is folded into a single
|
|
48
|
+
* headline: classic search and AI answer visibility fail for different reasons
|
|
49
|
+
* and are fixed by different edits, so averaging them would hide whichever is
|
|
50
|
+
* worse.
|
|
51
|
+
*/
|
|
52
|
+
export function PageAuditPanel({ audit }) {
|
|
53
|
+
const { seo, geo } = audit;
|
|
54
|
+
return (_jsxs("div", { className: "border-border border-b", children: [_jsx("div", { className: "flex items-start justify-around gap-3 px-3.5 py-4", children: [
|
|
55
|
+
{ r: seo, icon: Search, label: 'SEO', sub: 'Classic search & crawlability' },
|
|
56
|
+
{ r: geo, icon: Sparkles, label: 'GEO', sub: 'AI answer visibility' },
|
|
57
|
+
].map(({ r, icon: Icon, label, sub }) => (_jsxs("div", { className: "flex min-w-0 flex-col items-center gap-1.5 text-center", children: [_jsx(ScoreRing, { score: r.score, label: label }), _jsxs("span", { className: "text-foreground flex items-center gap-1 text-xs font-bold", children: [_jsx(Icon, { className: "h-3 w-3", "aria-hidden": true }), label] }), _jsx("span", { className: "text-muted-foreground text-[10.5px] leading-tight", children: sub }), _jsx("span", { className: "text-muted-foreground text-[10px] tabular-nums", children: r.score === null ? 'not rated' : `${r.applicable} of ${r.total} apply` })] }, label))) }), _jsx(CheckGroup, { result: seo, title: "SEO checks" }), _jsx(CheckGroup, { result: geo, title: "GEO checks" })] }));
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=PageAuditPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageAuditPanel.js","sourceRoot":"","sources":["../../../src/components/seo/PageAuditPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
export interface SeoCharCountProps {
|
|
2
2
|
value: string;
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Recommended minimum length (inclusive). Omit for cap-only fields, where
|
|
5
|
+
* short is not a fault — there is then no "too short" state and no "good",
|
|
6
|
+
* because there is no target to hit, only a ceiling not to cross.
|
|
7
|
+
*/
|
|
8
|
+
min?: number;
|
|
5
9
|
/** Recommended/hard maximum length (inclusive). */
|
|
6
10
|
max: number;
|
|
11
|
+
/** Hide the meter bar where vertical space is tight. */
|
|
12
|
+
bar?: boolean;
|
|
7
13
|
}
|
|
8
14
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
15
|
+
* Length readout for an SEO field: a meter bar plus a stated count.
|
|
16
|
+
*
|
|
17
|
+
* Under and over are different problems and are named as such. "Too short"
|
|
18
|
+
* means search engines have less to match on; "will be truncated" means the
|
|
19
|
+
* tail is written but nobody will read it. The previous wording collapsed the
|
|
20
|
+
* short case into "aim for 30–60", which describes the target without saying
|
|
21
|
+
* which way to edit.
|
|
22
|
+
*
|
|
23
|
+
* Colour never carries meaning alone — the band is always spelled out in text,
|
|
24
|
+
* with an icon at the two decisive states.
|
|
13
25
|
*/
|
|
14
|
-
export declare function SeoCharCount({ value, min, max }: SeoCharCountProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export declare function SeoCharCount({ value, min, max, bar }: SeoCharCountProps): import("react/jsx-runtime").JSX.Element;
|
|
15
27
|
//# sourceMappingURL=SeoCharCount.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SeoCharCount.d.ts","sourceRoot":"","sources":["../../../src/components/seo/SeoCharCount.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb
|
|
1
|
+
{"version":3,"file":"SeoCharCount.d.ts","sourceRoot":"","sources":["../../../src/components/seo/SeoCharCount.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAA;IACX,wDAAwD;IACxD,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAU,EAAE,EAAE,iBAAiB,2CA4C9E"}
|
|
@@ -1,25 +1,39 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import { AlertTriangle, Check } from 'lucide-react';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Length readout for an SEO field: a meter bar plus a stated count.
|
|
6
|
+
*
|
|
7
|
+
* Under and over are different problems and are named as such. "Too short"
|
|
8
|
+
* means search engines have less to match on; "will be truncated" means the
|
|
9
|
+
* tail is written but nobody will read it. The previous wording collapsed the
|
|
10
|
+
* short case into "aim for 30–60", which describes the target without saying
|
|
11
|
+
* which way to edit.
|
|
12
|
+
*
|
|
13
|
+
* Colour never carries meaning alone — the band is always spelled out in text,
|
|
14
|
+
* with an icon at the two decisive states.
|
|
9
15
|
*/
|
|
10
|
-
export function SeoCharCount({ value, min, max }) {
|
|
16
|
+
export function SeoCharCount({ value, min, max, bar = true }) {
|
|
11
17
|
const len = value.trim().length;
|
|
12
18
|
const empty = len === 0;
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
?
|
|
18
|
-
:
|
|
19
|
-
?
|
|
19
|
+
const over = len > max;
|
|
20
|
+
const under = min !== undefined && !empty && len < min;
|
|
21
|
+
const good = min !== undefined && !empty && !over && !under;
|
|
22
|
+
const tone = over
|
|
23
|
+
? 'text-destructive'
|
|
24
|
+
: under
|
|
25
|
+
? 'text-warning'
|
|
20
26
|
: good
|
|
21
|
-
?
|
|
22
|
-
:
|
|
23
|
-
|
|
27
|
+
? 'text-success'
|
|
28
|
+
: 'text-muted-foreground';
|
|
29
|
+
const fill = over ? 'bg-destructive' : under ? 'bg-warning' : good ? 'bg-success' : 'bg-border';
|
|
30
|
+
// Derived from `good`, not from "everything else": a cap-only field has no
|
|
31
|
+
// good state, and an unconditional else branch was labelling five characters
|
|
32
|
+
// in a 200-character field as "good".
|
|
33
|
+
const suffix = over ? ' · will be truncated' : under ? ' · too short' : good ? ' · good' : '';
|
|
34
|
+
return (_jsxs("span", { className: "inline-flex min-w-0 flex-col items-end gap-1", children: [bar && (_jsx("span", { className: "bg-border h-0.75 w-20 overflow-hidden rounded-full", "aria-hidden": true, children: _jsx("span", { className: `block h-full rounded-full transition-[width] ${fill}`,
|
|
35
|
+
// Past the maximum the bar stays full and the overflow is reported
|
|
36
|
+
// in words. A bar that kept growing would imply more is better.
|
|
37
|
+
style: { width: `${Math.min(100, (len / max) * 100)}%` } }) })), _jsxs("span", { className: `inline-flex items-center gap-1 text-[11px] whitespace-nowrap ${tone}`, children: [over ? (_jsx(AlertTriangle, { size: 11, "aria-hidden": true })) : good ? (_jsx(Check, { size: 11, "aria-hidden": true })) : null, len, " / ", max, " characters", suffix] })] }));
|
|
24
38
|
}
|
|
25
39
|
//# sourceMappingURL=SeoCharCount.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SeoCharCount.js","sourceRoot":"","sources":["../../../src/components/seo/SeoCharCount.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"SeoCharCount.js","sourceRoot":"","sources":["../../../src/components/seo/SeoCharCount.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAgBnD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,EAAqB;IAC7E,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,CAAA;IAC/B,MAAM,KAAK,GAAG,GAAG,KAAK,CAAC,CAAA;IACvB,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAA;IACtB,MAAM,KAAK,GAAG,GAAG,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,GAAG,GAAG,GAAG,CAAA;IACtD,MAAM,IAAI,GAAG,GAAG,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAA;IAE3D,MAAM,IAAI,GAAG,IAAI;QACf,CAAC,CAAC,kBAAkB;QACpB,CAAC,CAAC,KAAK;YACL,CAAC,CAAC,cAAc;YAChB,CAAC,CAAC,IAAI;gBACJ,CAAC,CAAC,cAAc;gBAChB,CAAC,CAAC,uBAAuB,CAAA;IAE/B,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAA;IAE/F,2EAA2E;IAC3E,6EAA6E;IAC7E,sCAAsC;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAA;IAE7F,OAAO,CACL,gBAAM,SAAS,EAAC,8CAA8C,aAC3D,GAAG,IAAI,CACN,eAAM,SAAS,EAAC,oDAAoD,iCAClE,eACE,SAAS,EAAE,gDAAgD,IAAI,EAAE;oBACjE,mEAAmE;oBACnE,gEAAgE;oBAChE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,GACxD,GACG,CACR,EACD,gBAAM,SAAS,EAAE,gEAAgE,IAAI,EAAE,aACpF,IAAI,CAAC,CAAC,CAAC,CACN,KAAC,aAAa,IAAC,IAAI,EAAE,EAAE,wBAAgB,CACxC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACT,KAAC,KAAK,IAAC,IAAI,EAAE,EAAE,wBAAgB,CAChC,CAAC,CAAC,CAAC,IAAI,EACP,GAAG,SAAK,GAAG,iBAAa,MAAM,IAC1B,IACF,CACR,CAAA;AACH,CAAC"}
|
|
@@ -1,5 +1,19 @@
|
|
|
1
|
+
import { type PageAuditResult } from '@prenta/core/seo/page-audit';
|
|
2
|
+
import type { PageSection } from '@prenta/core/page-sections';
|
|
1
3
|
export interface SeoEditorPaneProps {
|
|
2
4
|
entityType: 'page' | 'post';
|
|
5
|
+
/**
|
|
6
|
+
* Sections for the page-level SEO/GEO audit. Omit to hide the twin rings —
|
|
7
|
+
* the audit reads structure (stats, quotes, image slots), which a post body
|
|
8
|
+
* alone cannot supply.
|
|
9
|
+
*/
|
|
10
|
+
auditSections?: PageSection[];
|
|
11
|
+
/**
|
|
12
|
+
* Reports the audit upward so the rail's tab dot can show the same number
|
|
13
|
+
* this panel shows. Without it the dot and the panel compute independently
|
|
14
|
+
* and disagree — which is exactly what they did before the audit existed.
|
|
15
|
+
*/
|
|
16
|
+
onAuditChange?: (audit: PageAuditResult | null) => void;
|
|
3
17
|
/** When absent, draft-only mode — meta fields sync via `onDraftChange`. */
|
|
4
18
|
entityId: string | null;
|
|
5
19
|
onClose: () => void;
|
|
@@ -16,5 +30,5 @@ export interface SeoEditorPaneProps {
|
|
|
16
30
|
seoDescription?: string;
|
|
17
31
|
}) => void;
|
|
18
32
|
}
|
|
19
|
-
export declare function SeoEditorPane({ entityType, entityId, onClose, onSaved, contentHtml, slug, draftMeta, onDraftChange, }: SeoEditorPaneProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
export declare function SeoEditorPane({ entityType, entityId, auditSections, onAuditChange, onClose, onSaved, contentHtml, slug, draftMeta, onDraftChange, }: SeoEditorPaneProps): import("react/jsx-runtime").JSX.Element;
|
|
20
34
|
//# sourceMappingURL=SeoEditorPane.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SeoEditorPane.d.ts","sourceRoot":"","sources":["../../../src/components/seo/SeoEditorPane.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SeoEditorPane.d.ts","sourceRoot":"","sources":["../../../src/components/seo/SeoEditorPane.tsx"],"names":[],"mappings":"AA2BA,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAE7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAwG7D,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAA;IAC3B;;;;OAIG;IACH,aAAa,CAAC,EAAE,WAAW,EAAE,CAAA;IAC7B;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAA;IACvD,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAA;IACxD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CAChF;AAED,wBAAgB,aAAa,CAAC,EAC5B,UAAU,EACV,QAAQ,EACR,aAAa,EACb,aAAa,EACb,OAAO,EACP,OAAO,EACP,WAAgB,EAChB,IAAS,EACT,SAAS,EACT,aAAa,GACd,EAAE,kBAAkB,2CAq0BpB"}
|