@velastack/cms 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +644 -0
- package/dist/cms.d.ts +6 -0
- package/dist/cms.js +30 -0
- package/dist/components/admin-bar/admin-bar-internal.svelte +1697 -0
- package/dist/components/admin-bar/admin-bar-internal.svelte.d.ts +12 -0
- package/dist/components/admin-bar/admin-bar.css +5 -0
- package/dist/components/admin-bar/admin-bar.svelte +355 -0
- package/dist/components/admin-bar/admin-bar.svelte.d.ts +7 -0
- package/dist/components/admin-bar/click-outside.d.ts +8 -0
- package/dist/components/admin-bar/click-outside.js +17 -0
- package/dist/components/admin-bar/css-root.svelte +23 -0
- package/dist/components/admin-bar/css-root.svelte.d.ts +19 -0
- package/dist/components/admin-bar/delete-page-dialog.svelte +326 -0
- package/dist/components/admin-bar/delete-page-dialog.svelte.d.ts +32 -0
- package/dist/components/admin-bar/history-panel.svelte +264 -0
- package/dist/components/admin-bar/history-panel.svelte.d.ts +8 -0
- package/dist/components/admin-bar/icons/bold.svelte +13 -0
- package/dist/components/admin-bar/icons/bold.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/check.svelte +11 -0
- package/dist/components/admin-bar/icons/check.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/chevron-down.svelte +11 -0
- package/dist/components/admin-bar/icons/chevron-down.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/chevron-right.svelte +11 -0
- package/dist/components/admin-bar/icons/chevron-right.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/chevron-up.svelte +11 -0
- package/dist/components/admin-bar/icons/chevron-up.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/code.svelte +14 -0
- package/dist/components/admin-bar/icons/code.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/external-link.svelte +15 -0
- package/dist/components/admin-bar/icons/external-link.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/file.svelte +19 -0
- package/dist/components/admin-bar/icons/file.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/heading-2.svelte +16 -0
- package/dist/components/admin-bar/icons/heading-2.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/heading-3.svelte +17 -0
- package/dist/components/admin-bar/icons/heading-3.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/icon.svelte +41 -0
- package/dist/components/admin-bar/icons/icon.svelte.d.ts +21 -0
- package/dist/components/admin-bar/icons/images.svelte +16 -0
- package/dist/components/admin-bar/icons/images.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/italic.svelte +15 -0
- package/dist/components/admin-bar/icons/italic.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/link-2-off.svelte +16 -0
- package/dist/components/admin-bar/icons/link-2-off.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/link.svelte +14 -0
- package/dist/components/admin-bar/icons/link.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/list-ordered.svelte +18 -0
- package/dist/components/admin-bar/icons/list-ordered.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/list.svelte +18 -0
- package/dist/components/admin-bar/icons/list.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/loader-circle.svelte +11 -0
- package/dist/components/admin-bar/icons/loader-circle.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/minus.svelte +11 -0
- package/dist/components/admin-bar/icons/minus.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/quote.svelte +24 -0
- package/dist/components/admin-bar/icons/quote.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/search.svelte +14 -0
- package/dist/components/admin-bar/icons/search.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/trash-2.svelte +17 -0
- package/dist/components/admin-bar/icons/trash-2.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/triangle-alert.svelte +15 -0
- package/dist/components/admin-bar/icons/triangle-alert.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/types.d.ts +7 -0
- package/dist/components/admin-bar/icons/types.js +1 -0
- package/dist/components/admin-bar/icons/undo-2.svelte +14 -0
- package/dist/components/admin-bar/icons/undo-2.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/upload.svelte +15 -0
- package/dist/components/admin-bar/icons/upload.svelte.d.ts +3 -0
- package/dist/components/admin-bar/icons/x.svelte +14 -0
- package/dist/components/admin-bar/icons/x.svelte.d.ts +3 -0
- package/dist/components/admin-bar/keyboard-shortcuts-dialog.svelte +96 -0
- package/dist/components/admin-bar/keyboard-shortcuts-dialog.svelte.d.ts +7 -0
- package/dist/components/admin-bar/locales-panel.svelte +137 -0
- package/dist/components/admin-bar/locales-panel.svelte.d.ts +9 -0
- package/dist/components/admin-bar/media-panel.svelte +282 -0
- package/dist/components/admin-bar/media-panel.svelte.d.ts +7 -0
- package/dist/components/admin-bar/new-page-chooser-dialog.svelte +56 -0
- package/dist/components/admin-bar/new-page-chooser-dialog.svelte.d.ts +10 -0
- package/dist/components/admin-bar/new-page-dialog.svelte +126 -0
- package/dist/components/admin-bar/new-page-dialog.svelte.d.ts +14 -0
- package/dist/components/admin-bar/page-config.d.ts +61 -0
- package/dist/components/admin-bar/page-config.js +24 -0
- package/dist/components/admin-bar/pages-panel.svelte +639 -0
- package/dist/components/admin-bar/pages-panel.svelte.d.ts +13 -0
- package/dist/components/admin-bar/panel-footer.svelte +21 -0
- package/dist/components/admin-bar/panel-footer.svelte.d.ts +8 -0
- package/dist/components/admin-bar/panel-header.svelte +29 -0
- package/dist/components/admin-bar/panel-header.svelte.d.ts +10 -0
- package/dist/components/admin-bar/panel.svelte +41 -0
- package/dist/components/admin-bar/panel.svelte.d.ts +10 -0
- package/dist/components/admin-bar/publish-dialog.svelte +387 -0
- package/dist/components/admin-bar/publish-dialog.svelte.d.ts +16 -0
- package/dist/components/admin-bar/resolve-route.d.ts +20 -0
- package/dist/components/admin-bar/resolve-route.js +50 -0
- package/dist/components/admin-bar/seo-panel.svelte +387 -0
- package/dist/components/admin-bar/seo-panel.svelte.d.ts +7 -0
- package/dist/components/admin-bar/share-preview-link-dialog.svelte +97 -0
- package/dist/components/admin-bar/share-preview-link-dialog.svelte.d.ts +9 -0
- package/dist/components/admin-bar/site-settings-panel.svelte +225 -0
- package/dist/components/admin-bar/site-settings-panel.svelte.d.ts +7 -0
- package/dist/components/admin-bar/status-pill.svelte +49 -0
- package/dist/components/admin-bar/status-pill.svelte.d.ts +11 -0
- package/dist/components/admin-bar/theme.svelte.d.ts +16 -0
- package/dist/components/admin-bar/theme.svelte.js +39 -0
- package/dist/components/admin-bar/ui/badge/badge.svelte +57 -0
- package/dist/components/admin-bar/ui/badge/badge.svelte.d.ts +16 -0
- package/dist/components/admin-bar/ui/badge/index.d.ts +4 -0
- package/dist/components/admin-bar/ui/badge/index.js +4 -0
- package/dist/components/admin-bar/ui/button/button.svelte +73 -0
- package/dist/components/admin-bar/ui/button/button.svelte.d.ts +16 -0
- package/dist/components/admin-bar/ui/button/index.d.ts +4 -0
- package/dist/components/admin-bar/ui/button/index.js +4 -0
- package/dist/components/admin-bar/ui/collapsible/collapsible-content.svelte +7 -0
- package/dist/components/admin-bar/ui/collapsible/collapsible-content.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/collapsible/collapsible-trigger.svelte +7 -0
- package/dist/components/admin-bar/ui/collapsible/collapsible-trigger.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/collapsible/collapsible.svelte +7 -0
- package/dist/components/admin-bar/ui/collapsible/collapsible.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/collapsible/index.d.ts +4 -0
- package/dist/components/admin-bar/ui/collapsible/index.js +6 -0
- package/dist/components/admin-bar/ui/dialog/dialog-close.svelte +7 -0
- package/dist/components/admin-bar/ui/dialog/dialog-close.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/dialog/dialog-content.svelte +46 -0
- package/dist/components/admin-bar/ui/dialog/dialog-content.svelte.d.ts +11 -0
- package/dist/components/admin-bar/ui/dialog/dialog-description.svelte +17 -0
- package/dist/components/admin-bar/ui/dialog/dialog-description.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/dialog/dialog-footer.svelte +23 -0
- package/dist/components/admin-bar/ui/dialog/dialog-footer.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/dialog/dialog-header.svelte +20 -0
- package/dist/components/admin-bar/ui/dialog/dialog-header.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/dialog/dialog-overlay.svelte +20 -0
- package/dist/components/admin-bar/ui/dialog/dialog-overlay.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/dialog/dialog-portal.svelte +7 -0
- package/dist/components/admin-bar/ui/dialog/dialog-portal.svelte.d.ts +3 -0
- package/dist/components/admin-bar/ui/dialog/dialog-title.svelte +17 -0
- package/dist/components/admin-bar/ui/dialog/dialog-title.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/dialog/dialog-trigger.svelte +7 -0
- package/dist/components/admin-bar/ui/dialog/dialog-trigger.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/dialog/dialog.svelte +7 -0
- package/dist/components/admin-bar/ui/dialog/dialog.svelte.d.ts +3 -0
- package/dist/components/admin-bar/ui/dialog/index.d.ts +11 -0
- package/dist/components/admin-bar/ui/dialog/index.js +13 -0
- package/dist/components/admin-bar/ui/input/index.d.ts +3 -0
- package/dist/components/admin-bar/ui/input/index.js +3 -0
- package/dist/components/admin-bar/ui/input/input.svelte +24 -0
- package/dist/components/admin-bar/ui/input/input.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/kbd/index.d.ts +4 -0
- package/dist/components/admin-bar/ui/kbd/index.js +6 -0
- package/dist/components/admin-bar/ui/kbd/kbd-group.svelte +20 -0
- package/dist/components/admin-bar/ui/kbd/kbd-group.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/kbd/kbd-shortcut.svelte +52 -0
- package/dist/components/admin-bar/ui/kbd/kbd-shortcut.svelte.d.ts +8 -0
- package/dist/components/admin-bar/ui/kbd/kbd.svelte +27 -0
- package/dist/components/admin-bar/ui/kbd/kbd.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/label/index.d.ts +3 -0
- package/dist/components/admin-bar/ui/label/index.js +3 -0
- package/dist/components/admin-bar/ui/label/label.svelte +20 -0
- package/dist/components/admin-bar/ui/label/label.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/menubar/index.d.ts +18 -0
- package/dist/components/admin-bar/ui/menubar/index.js +20 -0
- package/dist/components/admin-bar/ui/menubar/menubar-checkbox-item.svelte +46 -0
- package/dist/components/admin-bar/ui/menubar/menubar-checkbox-item.svelte.d.ts +10 -0
- package/dist/components/admin-bar/ui/menubar/menubar-content.svelte +28 -0
- package/dist/components/admin-bar/ui/menubar/menubar-content.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/menubar/menubar-group-heading.svelte +25 -0
- package/dist/components/admin-bar/ui/menubar/menubar-group-heading.svelte.d.ts +8 -0
- package/dist/components/admin-bar/ui/menubar/menubar-group.svelte +12 -0
- package/dist/components/admin-bar/ui/menubar/menubar-group.svelte.d.ts +7 -0
- package/dist/components/admin-bar/ui/menubar/menubar-item.svelte +27 -0
- package/dist/components/admin-bar/ui/menubar/menubar-item.svelte.d.ts +8 -0
- package/dist/components/admin-bar/ui/menubar/menubar-label.svelte +25 -0
- package/dist/components/admin-bar/ui/menubar/menubar-label.svelte.d.ts +8 -0
- package/dist/components/admin-bar/ui/menubar/menubar-menu.svelte +7 -0
- package/dist/components/admin-bar/ui/menubar/menubar-menu.svelte.d.ts +3 -0
- package/dist/components/admin-bar/ui/menubar/menubar-portal.svelte +7 -0
- package/dist/components/admin-bar/ui/menubar/menubar-portal.svelte.d.ts +3 -0
- package/dist/components/admin-bar/ui/menubar/menubar-radio-group.svelte +11 -0
- package/dist/components/admin-bar/ui/menubar/menubar-radio-group.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/menubar/menubar-radio-item.svelte +37 -0
- package/dist/components/admin-bar/ui/menubar/menubar-radio-item.svelte.d.ts +8 -0
- package/dist/components/admin-bar/ui/menubar/menubar-separator.svelte +17 -0
- package/dist/components/admin-bar/ui/menubar/menubar-separator.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/menubar/menubar-shortcut.svelte +23 -0
- package/dist/components/admin-bar/ui/menubar/menubar-shortcut.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/menubar/menubar-sub-content.svelte +20 -0
- package/dist/components/admin-bar/ui/menubar/menubar-sub-content.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/menubar/menubar-sub-trigger.svelte +29 -0
- package/dist/components/admin-bar/ui/menubar/menubar-sub-trigger.svelte.d.ts +8 -0
- package/dist/components/admin-bar/ui/menubar/menubar-sub.svelte +7 -0
- package/dist/components/admin-bar/ui/menubar/menubar-sub.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/menubar/menubar-trigger.svelte +20 -0
- package/dist/components/admin-bar/ui/menubar/menubar-trigger.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/menubar/menubar.svelte +20 -0
- package/dist/components/admin-bar/ui/menubar/menubar.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/select/index.d.ts +12 -0
- package/dist/components/admin-bar/ui/select/index.js +14 -0
- package/dist/components/admin-bar/ui/select/select-content.svelte +45 -0
- package/dist/components/admin-bar/ui/select/select-content.svelte.d.ts +11 -0
- package/dist/components/admin-bar/ui/select/select-group-heading.svelte +21 -0
- package/dist/components/admin-bar/ui/select/select-group-heading.svelte.d.ts +10 -0
- package/dist/components/admin-bar/ui/select/select-group.svelte +17 -0
- package/dist/components/admin-bar/ui/select/select-group.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/select/select-item.svelte +40 -0
- package/dist/components/admin-bar/ui/select/select-item.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/select/select-label.svelte +20 -0
- package/dist/components/admin-bar/ui/select/select-label.svelte.d.ts +6 -0
- package/dist/components/admin-bar/ui/select/select-portal.svelte +7 -0
- package/dist/components/admin-bar/ui/select/select-portal.svelte.d.ts +3 -0
- package/dist/components/admin-bar/ui/select/select-scroll-down-button.svelte +23 -0
- package/dist/components/admin-bar/ui/select/select-scroll-down-button.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/select/select-scroll-up-button.svelte +23 -0
- package/dist/components/admin-bar/ui/select/select-scroll-up-button.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/select/select-separator.svelte +21 -0
- package/dist/components/admin-bar/ui/select/select-separator.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/select/select-trigger.svelte +31 -0
- package/dist/components/admin-bar/ui/select/select-trigger.svelte.d.ts +8 -0
- package/dist/components/admin-bar/ui/select/select.svelte +11 -0
- package/dist/components/admin-bar/ui/select/select.svelte.d.ts +3 -0
- package/dist/components/admin-bar/ui/separator/index.d.ts +2 -0
- package/dist/components/admin-bar/ui/separator/index.js +4 -0
- package/dist/components/admin-bar/ui/separator/separator.svelte +21 -0
- package/dist/components/admin-bar/ui/separator/separator.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/textarea/index.d.ts +3 -0
- package/dist/components/admin-bar/ui/textarea/index.js +3 -0
- package/dist/components/admin-bar/ui/textarea/textarea.svelte +21 -0
- package/dist/components/admin-bar/ui/textarea/textarea.svelte.d.ts +5 -0
- package/dist/components/admin-bar/user-avatar.svelte +29 -0
- package/dist/components/admin-bar/user-avatar.svelte.d.ts +7 -0
- package/dist/components/admin-bar/utils.d.ts +10 -0
- package/dist/components/admin-bar/utils.js +46 -0
- package/dist/components/admin-bar/variants.d.ts +20 -0
- package/dist/components/admin-bar/variants.js +14 -0
- package/dist/components/cms/cms-boolean.svelte +102 -0
- package/dist/components/cms/cms-boolean.svelte.d.ts +10 -0
- package/dist/components/cms/cms-date-time-editable.svelte +66 -0
- package/dist/components/cms/cms-date-time-editable.svelte.d.ts +11 -0
- package/dist/components/cms/cms-date-time.svelte +67 -0
- package/dist/components/cms/cms-date-time.svelte.d.ts +19 -0
- package/dist/components/cms/cms-entries.svelte +24 -0
- package/dist/components/cms/cms-entries.svelte.d.ts +31 -0
- package/dist/components/cms/cms-image-editable.svelte +439 -0
- package/dist/components/cms/cms-image-editable.svelte.d.ts +11 -0
- package/dist/components/cms/cms-image.svelte +78 -0
- package/dist/components/cms/cms-image.svelte.d.ts +18 -0
- package/dist/components/cms/cms-link-editable.svelte +429 -0
- package/dist/components/cms/cms-link-editable.svelte.d.ts +13 -0
- package/dist/components/cms/cms-link.svelte +92 -0
- package/dist/components/cms/cms-link.svelte.d.ts +25 -0
- package/dist/components/cms/cms-markdown-editable.svelte +74 -0
- package/dist/components/cms/cms-markdown-editable.svelte.d.ts +9 -0
- package/dist/components/cms/cms-markdown.svelte +56 -0
- package/dist/components/cms/cms-markdown.svelte.d.ts +10 -0
- package/dist/components/cms/cms-media-picker.svelte +150 -0
- package/dist/components/cms/cms-media-picker.svelte.d.ts +8 -0
- package/dist/components/cms/cms-number-editable.svelte +77 -0
- package/dist/components/cms/cms-number-editable.svelte.d.ts +13 -0
- package/dist/components/cms/cms-number.svelte +63 -0
- package/dist/components/cms/cms-number.svelte.d.ts +16 -0
- package/dist/components/cms/cms-repeater-editable.svelte +137 -0
- package/dist/components/cms/cms-repeater-editable.svelte.d.ts +31 -0
- package/dist/components/cms/cms-repeater.svelte +55 -0
- package/dist/components/cms/cms-repeater.svelte.d.ts +30 -0
- package/dist/components/cms/cms-rich-text-editable.svelte +101 -0
- package/dist/components/cms/cms-rich-text-editable.svelte.d.ts +9 -0
- package/dist/components/cms/cms-rich-text-toolbar.svelte +246 -0
- package/dist/components/cms/cms-rich-text-toolbar.svelte.d.ts +9 -0
- package/dist/components/cms/cms-rich-text.svelte +74 -0
- package/dist/components/cms/cms-rich-text.svelte.d.ts +10 -0
- package/dist/components/cms/cms-store.svelte.d.ts +294 -0
- package/dist/components/cms/cms-store.svelte.js +625 -0
- package/dist/components/cms/cms-text.svelte +131 -0
- package/dist/components/cms/cms-text.svelte.d.ts +11 -0
- package/dist/components/cms/index.d.ts +13 -0
- package/dist/components/cms/index.js +11 -0
- package/dist/components/cms/install-scope.svelte.d.ts +7 -0
- package/dist/components/cms/install-scope.svelte.js +33 -0
- package/dist/components/cms/locale-merge.d.ts +41 -0
- package/dist/components/cms/locale-merge.js +77 -0
- package/dist/components/cms/overlay-sync.d.ts +82 -0
- package/dist/components/cms/overlay-sync.js +76 -0
- package/dist/components/cms/path.d.ts +30 -0
- package/dist/components/cms/path.js +156 -0
- package/dist/components/cms/scope.d.ts +120 -0
- package/dist/components/cms/scope.js +23 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +28 -0
- package/dist/srv/README.md +341 -0
- package/dist/srv/api-adapter.d.ts +20 -0
- package/dist/srv/api-adapter.js +178 -0
- package/dist/srv/cms.d.ts +62 -0
- package/dist/srv/cms.js +35 -0
- package/dist/srv/index.d.ts +5 -0
- package/dist/srv/index.js +4 -0
- package/dist/srv/load-cms.d.ts +105 -0
- package/dist/srv/load-cms.js +227 -0
- package/dist/srv/mock-adapter.d.ts +96 -0
- package/dist/srv/mock-adapter.js +171 -0
- package/dist/srv/types.d.ts +114 -0
- package/dist/srv/types.js +1 -0
- package/package.json +116 -0
- package/plugin/README.md +137 -0
- package/plugin/dist/adapter.d.ts +35 -0
- package/plugin/dist/adapter.js +346 -0
- package/plugin/dist/adapter.js.map +1 -0
- package/plugin/dist/build-state.d.ts +10 -0
- package/plugin/dist/build-state.js +26 -0
- package/plugin/dist/build-state.js.map +1 -0
- package/plugin/dist/fallback-shim.js +194 -0
- package/plugin/dist/index.d.ts +56 -0
- package/plugin/dist/index.js +396 -0
- package/plugin/dist/index.js.map +1 -0
- package/plugin/dist/manifest.d.ts +76 -0
- package/plugin/dist/manifest.js +367 -0
- package/plugin/dist/manifest.js.map +1 -0
- package/plugin/dist/media.d.ts +36 -0
- package/plugin/dist/media.js +153 -0
- package/plugin/dist/media.js.map +1 -0
- package/plugin/dist/parse-svelte.d.ts +35 -0
- package/plugin/dist/parse-svelte.js +120 -0
- package/plugin/dist/parse-svelte.js.map +1 -0
- package/plugin/dist/route-tree.d.ts +27 -0
- package/plugin/dist/route-tree.js +69 -0
- package/plugin/dist/route-tree.js.map +1 -0
- package/plugin/dist/transforms.d.ts +42 -0
- package/plugin/dist/transforms.js +95 -0
- package/plugin/dist/transforms.js.map +1 -0
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactive edit-mode store for CMS components.
|
|
3
|
+
*
|
|
4
|
+
* Every (scope, locale) owns one tree. `drafts[key].tree` holds the editor's
|
|
5
|
+
* local, uncommitted patch tree; `overlay[key]` holds merged
|
|
6
|
+
* published+release content fetched client-side from `${endpoint}/docs` for
|
|
7
|
+
* that locale. Display components read through `getValue(scope, path)`,
|
|
8
|
+
* which deep-merges `base ∪ overlay ∪ draft` (drafts only when `isEditing`)
|
|
9
|
+
* and returns the value at `path`. The `base` is the request-time doc on
|
|
10
|
+
* `page.data.cms` (already locale-resolved + fallback-merged by the
|
|
11
|
+
* server-side `resolveCmsPayload`); `overlay` and `draft` are scoped to the
|
|
12
|
+
* locale stored on the bucket.
|
|
13
|
+
*
|
|
14
|
+
* `save(endpoint)` flushes draft trees to `${endpoint}/release/items` as
|
|
15
|
+
* `{ items: [{ kind, routeId, [params], locale, tree }] }`. The server
|
|
16
|
+
* deep-merges each tree into the editor's open release, keyed by
|
|
17
|
+
* (scope, locale). Publishing is a separate deliberate step via
|
|
18
|
+
* `/release/publish`.
|
|
19
|
+
*
|
|
20
|
+
* Paths are lodash-style: `welcome.title`, `gallery.0.caption`,
|
|
21
|
+
* `metadata.openGraph.image.url`. Numeric segments index arrays. There is no
|
|
22
|
+
* special envelope for metadata — `metadata` is just a branch on the page
|
|
23
|
+
* scope's tree.
|
|
24
|
+
*
|
|
25
|
+
* Locale on read/write helpers (`getValue`, `setValue`, `hasDraft`,
|
|
26
|
+
* `hasOverlay`) defaults to the request's `page.data.cms.locale`. The
|
|
27
|
+
* Locales panel passes an explicit locale to inspect other locales'
|
|
28
|
+
* working-copy state without switching the page.
|
|
29
|
+
*/
|
|
30
|
+
import { page } from '$app/state';
|
|
31
|
+
import { mergeLocaleDocs, mergeLocaleEntries } from './locale-merge.js';
|
|
32
|
+
import { composeKey } from './overlay-sync.js';
|
|
33
|
+
import { get, has, mergeTree, set } from './path.js';
|
|
34
|
+
const scopeKindFromId = (scopeId) => scopeId.startsWith('layout:') ? 'layout' : 'page';
|
|
35
|
+
/**
|
|
36
|
+
* Origin where uploaded media files are served. The backend writes files to
|
|
37
|
+
* `static/uploads/` and returns relative paths like `/uploads/<slug>.png`; the
|
|
38
|
+
* frontend lives on a different origin in dev, so we prefix each URL here at
|
|
39
|
+
* the wire boundary so display components and persisted field values both get
|
|
40
|
+
* a fully-qualified URL.
|
|
41
|
+
*/
|
|
42
|
+
export const MEDIA_URL_PREFIX = 'https://velastack.dev';
|
|
43
|
+
const resolveMediaItem = (item) => item.url.startsWith('/') ? { ...item, url: `${MEDIA_URL_PREFIX}${item.url}` } : item;
|
|
44
|
+
const treeHasAnyLeaf = (tree) => {
|
|
45
|
+
for (const v of Object.values(tree)) {
|
|
46
|
+
if (v === undefined)
|
|
47
|
+
continue;
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
};
|
|
52
|
+
/** Read the request-time locale from `page.data.cms`. Empty string until a payload loads. */
|
|
53
|
+
const pageLocale = () => {
|
|
54
|
+
const cms = page.data?.cms;
|
|
55
|
+
return cms?.locale ?? '';
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Default (fallback) locale for the project — `cms.locales[0]` by convention
|
|
59
|
+
* (matches `resolveCmsPayload`). Used by `loadAndApply*` to fetch the default
|
|
60
|
+
* locale's content alongside the requested one for `requested → default`
|
|
61
|
+
* fallback merging.
|
|
62
|
+
*/
|
|
63
|
+
const pageDefaultLocale = () => {
|
|
64
|
+
const cms = page.data?.cms;
|
|
65
|
+
return cms?.locales?.[0] ?? cms?.locale ?? '';
|
|
66
|
+
};
|
|
67
|
+
class CmsStore {
|
|
68
|
+
isEditing = $state(false);
|
|
69
|
+
drafts = $state({});
|
|
70
|
+
openRelease = $state(null);
|
|
71
|
+
overlay = $state({});
|
|
72
|
+
/** Per-routeId entries overlay populated by `loadAndApplyEntriesOverlay`. */
|
|
73
|
+
entriesOverlay = $state({});
|
|
74
|
+
/**
|
|
75
|
+
* Project-global site bucket. Not localized, not route-bound. `siteOverlay`
|
|
76
|
+
* holds the merged published+open-release tree fetched client-side from
|
|
77
|
+
* `${endpoint}/site`; `siteDraft` holds in-flight Site Settings panel
|
|
78
|
+
* edits awaiting save. `cmsStore.site` returns the merged read of base
|
|
79
|
+
* (load payload) ∪ overlay ∪ draft.
|
|
80
|
+
*/
|
|
81
|
+
siteOverlay = $state(undefined);
|
|
82
|
+
siteDraft = $state({});
|
|
83
|
+
/**
|
|
84
|
+
* Active editor preview locale, pushed in by the admin bar from the URL
|
|
85
|
+
* (`?locale=`). Falls back to `page.data.cms.locale` when unset (read-only
|
|
86
|
+
* consumer, or no override). Field components read/write through the
|
|
87
|
+
* default locale below, so editing in `?locale=es` keys drafts to `es`
|
|
88
|
+
* even if the consumer's `getLocale(url)` doesn't honor the param.
|
|
89
|
+
*/
|
|
90
|
+
_activeLocale = $state(null);
|
|
91
|
+
overlayFetchToken = 0;
|
|
92
|
+
entriesFetchToken = 0;
|
|
93
|
+
toggleEdit() {
|
|
94
|
+
this.isEditing = !this.isEditing;
|
|
95
|
+
}
|
|
96
|
+
setActiveLocale(locale) {
|
|
97
|
+
this._activeLocale = locale || null;
|
|
98
|
+
}
|
|
99
|
+
effectiveLocale() {
|
|
100
|
+
return this._activeLocale ?? pageLocale();
|
|
101
|
+
}
|
|
102
|
+
/** Base doc (server-rendered) for a scope. Already locale-resolved by `resolveCmsPayload`. */
|
|
103
|
+
baseDoc(scope) {
|
|
104
|
+
const cms = page.data?.cms;
|
|
105
|
+
return (cms?.docs?.[scope.scopeId] ?? {});
|
|
106
|
+
}
|
|
107
|
+
/** Merged read tree: base ∪ overlay (∪ draft when editing) for the given locale. */
|
|
108
|
+
mergedTree(scope, locale) {
|
|
109
|
+
const key = composeKey(scope, locale);
|
|
110
|
+
// Only fold in base when the requested locale matches the page's
|
|
111
|
+
// resolved locale — `page.data.cms.docs` only carries that one.
|
|
112
|
+
const base = locale === pageLocale() ? this.baseDoc(scope) : {};
|
|
113
|
+
const ov = this.overlay[key];
|
|
114
|
+
const draft = this.isEditing ? this.drafts[key]?.tree : undefined;
|
|
115
|
+
return mergeTree(base, ov, draft);
|
|
116
|
+
}
|
|
117
|
+
/** Read the merged value at `path`. Returns `undefined` if missing. */
|
|
118
|
+
getValue(scope, path, locale) {
|
|
119
|
+
return get(this.mergedTree(scope, locale ?? this.effectiveLocale()), path);
|
|
120
|
+
}
|
|
121
|
+
/** Whether the editor's draft tree contains a value at `path`. */
|
|
122
|
+
hasDraft(scope, path, locale) {
|
|
123
|
+
const bucket = this.drafts[composeKey(scope, locale ?? this.effectiveLocale())];
|
|
124
|
+
return bucket ? has(bucket.tree, path) : false;
|
|
125
|
+
}
|
|
126
|
+
/** Whether the client overlay (published+release) contains a value at `path`. */
|
|
127
|
+
hasOverlay(scope, path, locale) {
|
|
128
|
+
const ov = this.overlay[composeKey(scope, locale ?? this.effectiveLocale())];
|
|
129
|
+
return ov ? has(ov, path) : false;
|
|
130
|
+
}
|
|
131
|
+
/** Write a value at `path` into the draft tree. Creates the bucket if needed. */
|
|
132
|
+
setValue(scope, path, value, locale) {
|
|
133
|
+
const lc = locale ?? this.effectiveLocale();
|
|
134
|
+
const key = composeKey(scope, lc);
|
|
135
|
+
const bucket = this.drafts[key] ?? (this.drafts[key] = { scope, locale: lc, tree: {} });
|
|
136
|
+
set(bucket.tree, path, value);
|
|
137
|
+
}
|
|
138
|
+
clearOverlay() {
|
|
139
|
+
this.overlay = {};
|
|
140
|
+
this.entriesOverlay = {};
|
|
141
|
+
this.siteOverlay = undefined;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Reactive merged site tree: base (load payload) ∪ overlay (client-fetched
|
|
145
|
+
* `/site` response with preview overlay) ∪ draft (Site Settings panel
|
|
146
|
+
* edits awaiting save). Reads update live, so a value typed in the panel
|
|
147
|
+
* appears on the page immediately.
|
|
148
|
+
*
|
|
149
|
+
* Drafts are always folded in here (no `isEditing` gate) — the panel
|
|
150
|
+
* commits to the draft via `setSiteValue` only on Save, so any value
|
|
151
|
+
* present is already an intentional staged change.
|
|
152
|
+
*/
|
|
153
|
+
get site() {
|
|
154
|
+
const baseSite = page.data?.cms?.site?.tree ?? {};
|
|
155
|
+
return mergeTree(baseSite, this.siteOverlay, this.siteDraft);
|
|
156
|
+
}
|
|
157
|
+
getSiteValue(path) {
|
|
158
|
+
return get(this.site, path);
|
|
159
|
+
}
|
|
160
|
+
setSiteValue(path, value) {
|
|
161
|
+
set(this.siteDraft, path, value);
|
|
162
|
+
}
|
|
163
|
+
hasSiteDraft(path) {
|
|
164
|
+
if (!path)
|
|
165
|
+
return treeHasAnyLeaf(this.siteDraft);
|
|
166
|
+
return has(this.siteDraft, path);
|
|
167
|
+
}
|
|
168
|
+
clearSiteDraft() {
|
|
169
|
+
this.siteDraft = {};
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Fetch the merged published+release site tree from `${endpoint}/site`
|
|
173
|
+
* and apply as a client-side overlay. With `previewKey` the response
|
|
174
|
+
* includes the user's open-release site item; without it (or with
|
|
175
|
+
* `versionKey`), the response is published-only / past-snapshot.
|
|
176
|
+
*/
|
|
177
|
+
async loadAndApplySiteOverlay(endpoint, previewKey, opts = {}) {
|
|
178
|
+
const versionKey = opts.versionKey ?? null;
|
|
179
|
+
const qs = new URLSearchParams();
|
|
180
|
+
if (versionKey)
|
|
181
|
+
qs.set('version', versionKey);
|
|
182
|
+
else if (previewKey)
|
|
183
|
+
qs.set('preview', previewKey);
|
|
184
|
+
const suffix = qs.toString() ? `?${qs}` : '';
|
|
185
|
+
try {
|
|
186
|
+
const res = await fetch(`${endpoint}/site${suffix}`, { credentials: 'include' });
|
|
187
|
+
if (!res.ok)
|
|
188
|
+
return;
|
|
189
|
+
const data = (await res.json());
|
|
190
|
+
this.siteOverlay = data.contents ?? {};
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
/* network errors are non-fatal — display falls through to base */
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Fetch merged published+release content for each scope on the current
|
|
198
|
+
* route via `${endpoint}/docs` and apply as a client-side overlay.
|
|
199
|
+
*
|
|
200
|
+
* `previewKey` selects the user's open release on the server; pass `null`
|
|
201
|
+
* to fetch published-only content (used post-publish to mask the now-stale
|
|
202
|
+
* `page.data.cms.docs` on static-export sites).
|
|
203
|
+
*
|
|
204
|
+
* `opts.versionKey` (mutually exclusive with `previewKey`) requests the
|
|
205
|
+
* snapshot at a published release's publish time — `?version=…`.
|
|
206
|
+
*
|
|
207
|
+
* `opts.locale` is the BCP-47 locale to request — required, scopes the
|
|
208
|
+
* overlay cache key so different locales don't collide.
|
|
209
|
+
*
|
|
210
|
+
* `opts.defaultLocale` (the consumer's `cms.locales[0]`) enables the
|
|
211
|
+
* fallback fetch: when `locale !== defaultLocale`, we fetch the default
|
|
212
|
+
* locale's content in parallel and `mergeLocaleDocs` it under the
|
|
213
|
+
* requested locale. Adapters return only what's stored for the requested
|
|
214
|
+
* locale (per the mock-adapter contract); the library composes the
|
|
215
|
+
* `requested → default → undefined` chain. Mirrors `resolveCmsPayload`.
|
|
216
|
+
*
|
|
217
|
+
* `opts.reset` replaces the overlay map wholesale (mount with release,
|
|
218
|
+
* post-publish, post-discard). Otherwise we merge — keeps unchanged-layout
|
|
219
|
+
* overlays applied during navigation while new-page scopes load.
|
|
220
|
+
*/
|
|
221
|
+
async loadAndApplyOverlay(endpoint, scopes, previewKey, opts) {
|
|
222
|
+
const token = ++this.overlayFetchToken;
|
|
223
|
+
const versionKey = opts.versionKey ?? null;
|
|
224
|
+
const locale = opts.locale;
|
|
225
|
+
const defaultLocale = opts.defaultLocale ?? pageDefaultLocale() ?? locale;
|
|
226
|
+
const needsFallback = !!defaultLocale && locale !== defaultLocale;
|
|
227
|
+
const fetchScope = async (scope, forLocale) => {
|
|
228
|
+
const qs = new URLSearchParams({
|
|
229
|
+
kind: scope.kind,
|
|
230
|
+
routeId: scope.routeId,
|
|
231
|
+
params: JSON.stringify(scope.params),
|
|
232
|
+
locale: forLocale
|
|
233
|
+
});
|
|
234
|
+
if (versionKey)
|
|
235
|
+
qs.set('version', versionKey);
|
|
236
|
+
else if (previewKey)
|
|
237
|
+
qs.set('preview', previewKey);
|
|
238
|
+
const res = await fetch(`${endpoint}/docs?${qs}`, { credentials: 'include' });
|
|
239
|
+
if (!res.ok)
|
|
240
|
+
return null;
|
|
241
|
+
const data = (await res.json());
|
|
242
|
+
return { scope, contents: data.contents };
|
|
243
|
+
};
|
|
244
|
+
const collect = (pairs) => {
|
|
245
|
+
const out = {};
|
|
246
|
+
for (const r of pairs) {
|
|
247
|
+
if (!r)
|
|
248
|
+
continue;
|
|
249
|
+
out[r.scope.scopeId] = r.contents ?? {};
|
|
250
|
+
}
|
|
251
|
+
return out;
|
|
252
|
+
};
|
|
253
|
+
const [requestedPairs, fallbackPairs] = await Promise.all([
|
|
254
|
+
Promise.all(scopes.map((s) => fetchScope(s, locale))),
|
|
255
|
+
needsFallback
|
|
256
|
+
? Promise.all(scopes.map((s) => fetchScope(s, defaultLocale)))
|
|
257
|
+
: Promise.resolve(null)
|
|
258
|
+
]);
|
|
259
|
+
if (token !== this.overlayFetchToken)
|
|
260
|
+
return;
|
|
261
|
+
const merged = mergeLocaleDocs(collect(requestedPairs), fallbackPairs ? collect(fallbackPairs) : null);
|
|
262
|
+
const scopeIndex = new Map();
|
|
263
|
+
for (const s of scopes)
|
|
264
|
+
scopeIndex.set(s.scopeId, s);
|
|
265
|
+
const next = {};
|
|
266
|
+
for (const [scopeId, contents] of Object.entries(merged)) {
|
|
267
|
+
const scope = scopeIndex.get(scopeId);
|
|
268
|
+
if (!scope)
|
|
269
|
+
continue;
|
|
270
|
+
const key = composeKey({ scopeId: scope.scopeId, routeId: scope.routeId, params: scope.params }, locale);
|
|
271
|
+
next[key] = contents;
|
|
272
|
+
}
|
|
273
|
+
if (opts.reset) {
|
|
274
|
+
this.overlay = next;
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
this.overlay = { ...this.overlay, ...next };
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Refresh the per-routeId entries overlay used by `<CmsEntries>`. One fetch
|
|
282
|
+
* to `${endpoint}/pages?preview=…&locale=…` covers all `routeIds`; we
|
|
283
|
+
* filter the response per route. With `previewKey` set, draft and
|
|
284
|
+
* pending-delete entries are kept; with `previewKey === null`, they're
|
|
285
|
+
* filtered out — used post-publish to mask stale
|
|
286
|
+
* `page.data.cms.entries` on static-export sites.
|
|
287
|
+
*
|
|
288
|
+
* `opts.defaultLocale` enables the fallback fetch: when the requested
|
|
289
|
+
* locale isn't the default, we fetch the default locale's entries in
|
|
290
|
+
* parallel and union by params (requested-locale entries win on metadata
|
|
291
|
+
* for shared params; default-locale-only entries surface as fallbacks).
|
|
292
|
+
*/
|
|
293
|
+
async loadAndApplyEntriesOverlay(endpoint, routeIds, previewKey, opts) {
|
|
294
|
+
const token = ++this.entriesFetchToken;
|
|
295
|
+
if (routeIds.length === 0) {
|
|
296
|
+
if (opts.reset)
|
|
297
|
+
this.entriesOverlay = {};
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
const versionKey = opts.versionKey ?? null;
|
|
301
|
+
const defaultLocale = opts.defaultLocale ?? pageDefaultLocale() ?? opts.locale;
|
|
302
|
+
const needsFallback = !!defaultLocale && opts.locale !== defaultLocale;
|
|
303
|
+
const fetchByLocale = async (forLocale) => {
|
|
304
|
+
const qs = new URLSearchParams({ locale: forLocale });
|
|
305
|
+
if (versionKey)
|
|
306
|
+
qs.set('version', versionKey);
|
|
307
|
+
else if (previewKey)
|
|
308
|
+
qs.set('preview', previewKey);
|
|
309
|
+
let res;
|
|
310
|
+
try {
|
|
311
|
+
res = await fetch(`${endpoint}/pages?${qs}`, { credentials: 'include' });
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
if (!res.ok)
|
|
317
|
+
return null;
|
|
318
|
+
const body = (await res.json());
|
|
319
|
+
const out = {};
|
|
320
|
+
const wanted = new Set(routeIds);
|
|
321
|
+
for (const r of body.routes) {
|
|
322
|
+
if (!wanted.has(r.routeId))
|
|
323
|
+
continue;
|
|
324
|
+
// Tombstones (redirect / gone) and pending deletes never appear in
|
|
325
|
+
// consumer-facing `<CmsEntries>` lists. Drafts are visible only in
|
|
326
|
+
// preview / version mode where the editor inspects working state.
|
|
327
|
+
const filtered = r.entries.filter((e) => {
|
|
328
|
+
if (e.redirectTo || e.gone || e.isDeletePending)
|
|
329
|
+
return false;
|
|
330
|
+
if (versionKey || previewKey)
|
|
331
|
+
return true;
|
|
332
|
+
return !e.isDraft;
|
|
333
|
+
});
|
|
334
|
+
out[r.routeId] = filtered.map((e) => ({
|
|
335
|
+
params: e.params,
|
|
336
|
+
metadata: e.metadata ?? {}
|
|
337
|
+
}));
|
|
338
|
+
}
|
|
339
|
+
return out;
|
|
340
|
+
};
|
|
341
|
+
const [requested, fallback] = await Promise.all([
|
|
342
|
+
fetchByLocale(opts.locale),
|
|
343
|
+
needsFallback ? fetchByLocale(defaultLocale) : Promise.resolve(null)
|
|
344
|
+
]);
|
|
345
|
+
if (token !== this.entriesFetchToken)
|
|
346
|
+
return;
|
|
347
|
+
if (!requested)
|
|
348
|
+
return;
|
|
349
|
+
const merged = mergeLocaleEntries(requested, fallback);
|
|
350
|
+
const next = { ...merged };
|
|
351
|
+
for (const rid of routeIds) {
|
|
352
|
+
if (!(rid in next))
|
|
353
|
+
next[rid] = [];
|
|
354
|
+
}
|
|
355
|
+
if (opts.reset) {
|
|
356
|
+
this.entriesOverlay = next;
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
this.entriesOverlay = { ...this.entriesOverlay, ...next };
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
get isDirty() {
|
|
363
|
+
for (const bucket of Object.values(this.drafts)) {
|
|
364
|
+
if (treeHasAnyLeaf(bucket.tree))
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
if (treeHasAnyLeaf(this.siteDraft))
|
|
368
|
+
return true;
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Counts distinct page identities and layout routes touched by the open
|
|
373
|
+
* release, NOT raw item count: a page edited in `en` and `es` registers
|
|
374
|
+
* as one. Powers the editor's "X pages draft" mental model — they think
|
|
375
|
+
* "one page is in progress", not "two storage rows exist". For per-locale
|
|
376
|
+
* breakdowns (locales panel "EN: 6, ES: 4"), use `workingCopyCountsByLocale`.
|
|
377
|
+
*/
|
|
378
|
+
get workingCopyCounts() {
|
|
379
|
+
const pageKeys = new Set();
|
|
380
|
+
const layoutKeys = new Set();
|
|
381
|
+
let site = 0;
|
|
382
|
+
for (const item of this.openRelease?.items ?? []) {
|
|
383
|
+
if (item.kind === 'site') {
|
|
384
|
+
site = 1;
|
|
385
|
+
}
|
|
386
|
+
else if (item.kind === 'layout') {
|
|
387
|
+
layoutKeys.add(item.routeId);
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
const sortedParams = Object.keys(item.params).sort();
|
|
391
|
+
const qp = sortedParams.map((k) => `${k}=${item.params[k]}`).join('&');
|
|
392
|
+
pageKeys.add(`${item.routeId}?${qp}`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
pages: pageKeys.size,
|
|
397
|
+
layouts: layoutKeys.size,
|
|
398
|
+
site,
|
|
399
|
+
total: pageKeys.size + layoutKeys.size + site
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Per-locale breakdown of the open release's working-copy items. Powers
|
|
404
|
+
* the Locales panel ("default has 6 edits, es missing 2"). Locales with
|
|
405
|
+
* zero items don't appear in the map; the panel iterates `cms.locales` to
|
|
406
|
+
* surface them as "0 edits".
|
|
407
|
+
*/
|
|
408
|
+
get workingCopyCountsByLocale() {
|
|
409
|
+
const out = {};
|
|
410
|
+
for (const item of this.openRelease?.items ?? []) {
|
|
411
|
+
if (item.kind === 'site')
|
|
412
|
+
continue;
|
|
413
|
+
const bucket = (out[item.locale] ??= { pages: 0, layouts: 0, total: 0 });
|
|
414
|
+
if (item.kind === 'layout')
|
|
415
|
+
bucket.layouts += 1;
|
|
416
|
+
else
|
|
417
|
+
bucket.pages += 1;
|
|
418
|
+
bucket.total += 1;
|
|
419
|
+
}
|
|
420
|
+
return out;
|
|
421
|
+
}
|
|
422
|
+
clearDrafts() {
|
|
423
|
+
this.drafts = {};
|
|
424
|
+
this.siteDraft = {};
|
|
425
|
+
}
|
|
426
|
+
setOpenRelease(release) {
|
|
427
|
+
this.openRelease = release;
|
|
428
|
+
}
|
|
429
|
+
async fetchOpenRelease(endpoint) {
|
|
430
|
+
const res = await fetch(`${endpoint}/release`, { credentials: 'include' });
|
|
431
|
+
if (!res.ok) {
|
|
432
|
+
this.openRelease = null;
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const data = (await res.json());
|
|
436
|
+
this.openRelease = data.release;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Atomically rename a page's slug: stage a draft `page` item at the new
|
|
440
|
+
* params copying content from the published entry, plus a `page-delete`
|
|
441
|
+
* with a redirect outcome on the old params pointing at the new URL. Both
|
|
442
|
+
* items go into the open release as a transactional pair, so undo removes
|
|
443
|
+
* them together. The backend composes this on `POST /pages/rename`.
|
|
444
|
+
*/
|
|
445
|
+
async renameSlug(endpoint, args) {
|
|
446
|
+
const res = await fetch(`${endpoint}/pages/rename`, {
|
|
447
|
+
credentials: 'include',
|
|
448
|
+
method: 'POST',
|
|
449
|
+
headers: { 'Content-Type': 'application/json' },
|
|
450
|
+
body: JSON.stringify(args)
|
|
451
|
+
});
|
|
452
|
+
if (!res.ok)
|
|
453
|
+
return { ok: false };
|
|
454
|
+
const data = (await res.json());
|
|
455
|
+
this.openRelease = data.release;
|
|
456
|
+
return { ok: true, release: data.release };
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Upload a media file to `${endpoint}/media` and return the full `MediaItem`.
|
|
460
|
+
* The library panel and inline picker both call this so newly-uploaded items
|
|
461
|
+
* can be prepended to local state without a re-list.
|
|
462
|
+
*/
|
|
463
|
+
async uploadMedia(endpoint, file) {
|
|
464
|
+
const formData = new FormData();
|
|
465
|
+
formData.append('file', file);
|
|
466
|
+
const res = await fetch(`${endpoint}/media`, {
|
|
467
|
+
method: 'POST',
|
|
468
|
+
body: formData,
|
|
469
|
+
credentials: 'include'
|
|
470
|
+
});
|
|
471
|
+
if (!res.ok) {
|
|
472
|
+
throw new Error(`Upload failed (${res.status})`);
|
|
473
|
+
}
|
|
474
|
+
const item = (await res.json());
|
|
475
|
+
if (typeof item?.url !== 'string') {
|
|
476
|
+
throw new Error('Upload response missing url');
|
|
477
|
+
}
|
|
478
|
+
return resolveMediaItem(item);
|
|
479
|
+
}
|
|
480
|
+
/** Back-compat wrapper around `uploadMedia` that returns just the URL. */
|
|
481
|
+
async uploadImage(endpoint, file) {
|
|
482
|
+
return (await this.uploadMedia(endpoint, file)).url;
|
|
483
|
+
}
|
|
484
|
+
async listMedia(endpoint, params = {}) {
|
|
485
|
+
const qs = new URLSearchParams();
|
|
486
|
+
if (params.offset != null)
|
|
487
|
+
qs.set('offset', String(params.offset));
|
|
488
|
+
if (params.limit != null)
|
|
489
|
+
qs.set('limit', String(params.limit));
|
|
490
|
+
const res = await fetch(`${endpoint}/media?${qs}`, { credentials: 'include' });
|
|
491
|
+
if (!res.ok)
|
|
492
|
+
throw new Error(`List failed (${res.status})`);
|
|
493
|
+
const data = (await res.json());
|
|
494
|
+
return { ...data, items: data.items.map(resolveMediaItem) };
|
|
495
|
+
}
|
|
496
|
+
async deleteMedia(endpoint, id) {
|
|
497
|
+
const res = await fetch(`${endpoint}/media/${id}`, {
|
|
498
|
+
method: 'DELETE',
|
|
499
|
+
credentials: 'include'
|
|
500
|
+
});
|
|
501
|
+
if (!res.ok)
|
|
502
|
+
throw new Error(`Delete failed (${res.status})`);
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Flush dirty drafts to the server's open release as one item per
|
|
506
|
+
* (scope, locale), each carrying a partial tree. The server deep-merges
|
|
507
|
+
* each tree into its matching item in the working copy without publishing.
|
|
508
|
+
*/
|
|
509
|
+
async save(endpoint) {
|
|
510
|
+
const items = [];
|
|
511
|
+
for (const bucket of Object.values(this.drafts)) {
|
|
512
|
+
if (!treeHasAnyLeaf(bucket.tree))
|
|
513
|
+
continue;
|
|
514
|
+
const kind = scopeKindFromId(bucket.scope.scopeId);
|
|
515
|
+
if (kind === 'page') {
|
|
516
|
+
items.push({
|
|
517
|
+
kind: 'page',
|
|
518
|
+
routeId: bucket.scope.routeId,
|
|
519
|
+
params: bucket.scope.params,
|
|
520
|
+
locale: bucket.locale,
|
|
521
|
+
tree: bucket.tree
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
items.push({
|
|
526
|
+
kind: 'layout',
|
|
527
|
+
routeId: bucket.scope.routeId,
|
|
528
|
+
locale: bucket.locale,
|
|
529
|
+
tree: bucket.tree
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
if (treeHasAnyLeaf(this.siteDraft)) {
|
|
534
|
+
items.push({ kind: 'site', tree: this.siteDraft });
|
|
535
|
+
}
|
|
536
|
+
if (items.length === 0)
|
|
537
|
+
return { ok: true, release: this.openRelease ?? undefined };
|
|
538
|
+
const res = await fetch(`${endpoint}/release/items`, {
|
|
539
|
+
credentials: 'include',
|
|
540
|
+
method: 'POST',
|
|
541
|
+
headers: { 'Content-Type': 'application/json' },
|
|
542
|
+
body: JSON.stringify({ items })
|
|
543
|
+
});
|
|
544
|
+
if (!res.ok)
|
|
545
|
+
return { ok: false };
|
|
546
|
+
const data = (await res.json());
|
|
547
|
+
this.openRelease = data.release;
|
|
548
|
+
this.clearDrafts();
|
|
549
|
+
return { ok: true, release: data.release };
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
export const cmsStore = new CmsStore();
|
|
553
|
+
/**
|
|
554
|
+
* Public read view of the merged CMS payload: server-loaded `page.data.cms`
|
|
555
|
+
* with `cmsStore.overlay` applied on top, so authed editors see working-copy
|
|
556
|
+
* content without a server reload.
|
|
557
|
+
*
|
|
558
|
+
* Shape mirrors `CmsPayload` directly via getters (`cms.docs`, `cms.metadata`,
|
|
559
|
+
* `cms.page`, …). `metadata` is now a thin alias — it reads the page scope's
|
|
560
|
+
* `metadata` branch from the merged docs.
|
|
561
|
+
*/
|
|
562
|
+
class Cms {
|
|
563
|
+
#merged = $derived.by(() => {
|
|
564
|
+
const base = (page.data?.cms ?? null);
|
|
565
|
+
if (!base)
|
|
566
|
+
return null;
|
|
567
|
+
const docs = {};
|
|
568
|
+
for (const [scopeId, scopeEntry] of Object.entries(base.scopes)) {
|
|
569
|
+
const overlayKey = composeKey({
|
|
570
|
+
scopeId: scopeEntry.scopeId,
|
|
571
|
+
routeId: scopeEntry.routeId,
|
|
572
|
+
params: scopeEntry.params
|
|
573
|
+
}, base.locale);
|
|
574
|
+
const overlayBucket = cmsStore.overlay[overlayKey];
|
|
575
|
+
const baseDoc = (base.docs[scopeId] ?? {});
|
|
576
|
+
docs[scopeId] = overlayBucket ? mergeTree(baseDoc, overlayBucket) : baseDoc;
|
|
577
|
+
}
|
|
578
|
+
let metadata = base.metadata;
|
|
579
|
+
if (base.page) {
|
|
580
|
+
const pageDoc = docs[base.page.scopeId];
|
|
581
|
+
const meta = pageDoc?.metadata;
|
|
582
|
+
if (meta && typeof meta === 'object' && !Array.isArray(meta)) {
|
|
583
|
+
metadata = meta;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
const entries = {
|
|
587
|
+
...(base.entries ?? {}),
|
|
588
|
+
...cmsStore.entriesOverlay
|
|
589
|
+
};
|
|
590
|
+
return { ...base, docs, metadata, entries };
|
|
591
|
+
});
|
|
592
|
+
get locale() {
|
|
593
|
+
return this.#merged?.locale ?? '';
|
|
594
|
+
}
|
|
595
|
+
get locales() {
|
|
596
|
+
return this.#merged?.locales ?? [];
|
|
597
|
+
}
|
|
598
|
+
get docs() {
|
|
599
|
+
return this.#merged?.docs ?? {};
|
|
600
|
+
}
|
|
601
|
+
get scopes() {
|
|
602
|
+
return this.#merged?.scopes ?? {};
|
|
603
|
+
}
|
|
604
|
+
get metadata() {
|
|
605
|
+
return this.#merged?.metadata ?? {};
|
|
606
|
+
}
|
|
607
|
+
get entries() {
|
|
608
|
+
return this.#merged?.entries ?? {};
|
|
609
|
+
}
|
|
610
|
+
get endpoint() {
|
|
611
|
+
return this.#merged?.endpoint ?? '';
|
|
612
|
+
}
|
|
613
|
+
get page() {
|
|
614
|
+
return this.#merged?.page ?? null;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Project-wide site settings tree, merged through `cmsStore.site` so panel
|
|
618
|
+
* edits show up live in preview. Use this in display components instead of
|
|
619
|
+
* reading `data.cms.site.tree` directly — that's only the SSR seed.
|
|
620
|
+
*/
|
|
621
|
+
get site() {
|
|
622
|
+
return cmsStore.site;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
export const cms = new Cms();
|