@elytracms/studio 0.0.1
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 +3 -0
- package/convex/assets.ts +107 -0
- package/convex/auth.config.ts +15 -0
- package/convex/auth.ts +50 -0
- package/convex/cliTokens.ts +63 -0
- package/convex/cms.ts +174 -0
- package/convex/content.ts +316 -0
- package/convex/delivery.ts +266 -0
- package/convex/functions.ts +35 -0
- package/convex/graphs.ts +51 -0
- package/convex/guard.ts +67 -0
- package/convex/http.ts +30 -0
- package/convex/members.ts +83 -0
- package/convex/publishing.ts +102 -0
- package/convex/references.ts +168 -0
- package/convex/schema.ts +173 -0
- package/convex/sync.ts +322 -0
- package/convex/tsconfig.json +12 -0
- package/convex/users.ts +23 -0
- package/convex/webhooks.ts +85 -0
- package/dist/components/assets/asset-library.d.ts +14 -0
- package/dist/components/assets/asset-library.js +191 -0
- package/dist/components/assets/asset-library.js.map +1 -0
- package/dist/components/assets/asset-metadata.d.ts +34 -0
- package/dist/components/assets/asset-metadata.js +40 -0
- package/dist/components/assets/asset-metadata.js.map +1 -0
- package/dist/components/assets/asset-search.d.ts +7 -0
- package/dist/components/assets/asset-search.js +12 -0
- package/dist/components/assets/asset-search.js.map +1 -0
- package/dist/components/assets/asset-selection.d.ts +17 -0
- package/dist/components/assets/asset-selection.js +33 -0
- package/dist/components/assets/asset-selection.js.map +1 -0
- package/dist/components/assets/assets-store.d.ts +51 -0
- package/dist/components/assets/assets-store.js +153 -0
- package/dist/components/assets/assets-store.js.map +1 -0
- package/dist/components/auth-context.d.ts +38 -0
- package/dist/components/auth-context.js +88 -0
- package/dist/components/auth-context.js.map +1 -0
- package/dist/components/backend-gate.d.ts +19 -0
- package/dist/components/backend-gate.js +63 -0
- package/dist/components/backend-gate.js.map +1 -0
- package/dist/components/breadcrumb-context.d.ts +39 -0
- package/dist/components/breadcrumb-context.js +38 -0
- package/dist/components/breadcrumb-context.js.map +1 -0
- package/dist/components/builder/blocks-model.d.ts +80 -0
- package/dist/components/builder/blocks-model.js +181 -0
- package/dist/components/builder/blocks-model.js.map +1 -0
- package/dist/components/builder/blocks-panel.d.ts +44 -0
- package/dist/components/builder/blocks-panel.js +147 -0
- package/dist/components/builder/blocks-panel.js.map +1 -0
- package/dist/components/builder/builder-store.d.ts +69 -0
- package/dist/components/builder/builder-store.js +294 -0
- package/dist/components/builder/builder-store.js.map +1 -0
- package/dist/components/builder/canvas-stylesheet.d.ts +4 -0
- package/dist/components/builder/canvas-stylesheet.js +24 -0
- package/dist/components/builder/canvas-stylesheet.js.map +1 -0
- package/dist/components/builder/canvas.d.ts +8 -0
- package/dist/components/builder/canvas.js +723 -0
- package/dist/components/builder/canvas.js.map +1 -0
- package/dist/components/builder/clipboard-actions.d.ts +93 -0
- package/dist/components/builder/clipboard-actions.js +246 -0
- package/dist/components/builder/clipboard-actions.js.map +1 -0
- package/dist/components/builder/composition-field-editor.d.ts +11 -0
- package/dist/components/builder/composition-field-editor.js +150 -0
- package/dist/components/builder/composition-field-editor.js.map +1 -0
- package/dist/components/builder/composition-scope.d.ts +16 -0
- package/dist/components/builder/composition-scope.js +7 -0
- package/dist/components/builder/composition-scope.js.map +1 -0
- package/dist/components/builder/drag-session.d.ts +41 -0
- package/dist/components/builder/drag-session.js +51 -0
- package/dist/components/builder/drag-session.js.map +1 -0
- package/dist/components/builder/fixture-thumbnail.d.ts +18 -0
- package/dist/components/builder/fixture-thumbnail.js +97 -0
- package/dist/components/builder/fixture-thumbnail.js.map +1 -0
- package/dist/components/builder/inline-edit.d.ts +142 -0
- package/dist/components/builder/inline-edit.js +136 -0
- package/dist/components/builder/inline-edit.js.map +1 -0
- package/dist/components/builder/insert-context.d.ts +14 -0
- package/dist/components/builder/insert-context.js +65 -0
- package/dist/components/builder/insert-context.js.map +1 -0
- package/dist/components/builder/insert-menu.d.ts +9 -0
- package/dist/components/builder/insert-menu.js +9 -0
- package/dist/components/builder/insert-menu.js.map +1 -0
- package/dist/components/builder/layout-inspector.d.ts +14 -0
- package/dist/components/builder/layout-inspector.js +84 -0
- package/dist/components/builder/layout-inspector.js.map +1 -0
- package/dist/components/builder/node-factory.d.ts +17 -0
- package/dist/components/builder/node-factory.js +90 -0
- package/dist/components/builder/node-factory.js.map +1 -0
- package/dist/components/builder/page-tree.d.ts +3 -0
- package/dist/components/builder/page-tree.js +207 -0
- package/dist/components/builder/page-tree.js.map +1 -0
- package/dist/components/builder/property-inspector.d.ts +1 -0
- package/dist/components/builder/property-inspector.js +233 -0
- package/dist/components/builder/property-inspector.js.map +1 -0
- package/dist/components/builder/rich-text-toolbar.d.ts +4 -0
- package/dist/components/builder/rich-text-toolbar.js +104 -0
- package/dist/components/builder/rich-text-toolbar.js.map +1 -0
- package/dist/components/builder/spacing-handles.d.ts +22 -0
- package/dist/components/builder/spacing-handles.js +213 -0
- package/dist/components/builder/spacing-handles.js.map +1 -0
- package/dist/components/cms/asset-picker.d.ts +12 -0
- package/dist/components/cms/asset-picker.js +60 -0
- package/dist/components/cms/asset-picker.js.map +1 -0
- package/dist/components/cms/bulk-actions.d.ts +60 -0
- package/dist/components/cms/bulk-actions.js +95 -0
- package/dist/components/cms/bulk-actions.js.map +1 -0
- package/dist/components/cms/bulk-bar.d.ts +23 -0
- package/dist/components/cms/bulk-bar.js +26 -0
- package/dist/components/cms/bulk-bar.js.map +1 -0
- package/dist/components/cms/cell-edit.d.ts +91 -0
- package/dist/components/cms/cell-edit.js +144 -0
- package/dist/components/cms/cell-edit.js.map +1 -0
- package/dist/components/cms/cell.d.ts +29 -0
- package/dist/components/cms/cell.js +127 -0
- package/dist/components/cms/cell.js.map +1 -0
- package/dist/components/cms/cms-index.d.ts +8 -0
- package/dist/components/cms/cms-index.js +23 -0
- package/dist/components/cms/cms-index.js.map +1 -0
- package/dist/components/cms/cms-store.d.ts +188 -0
- package/dist/components/cms/cms-store.js +702 -0
- package/dist/components/cms/cms-store.js.map +1 -0
- package/dist/components/cms/collection-table.d.ts +6 -0
- package/dist/components/cms/collection-table.js +250 -0
- package/dist/components/cms/collection-table.js.map +1 -0
- package/dist/components/cms/collections-sidebar.d.ts +9 -0
- package/dist/components/cms/collections-sidebar.js +25 -0
- package/dist/components/cms/collections-sidebar.js.map +1 -0
- package/dist/components/cms/detail-editor.d.ts +7 -0
- package/dist/components/cms/detail-editor.js +386 -0
- package/dist/components/cms/detail-editor.js.map +1 -0
- package/dist/components/cms/doc-state.d.ts +13 -0
- package/dist/components/cms/doc-state.js +18 -0
- package/dist/components/cms/doc-state.js.map +1 -0
- package/dist/components/cms/document-editor-context.d.ts +48 -0
- package/dist/components/cms/document-editor-context.js +23 -0
- package/dist/components/cms/document-editor-context.js.map +1 -0
- package/dist/components/cms/editable-cell.d.ts +22 -0
- package/dist/components/cms/editable-cell.js +176 -0
- package/dist/components/cms/editable-cell.js.map +1 -0
- package/dist/components/cms/field-control.d.ts +8 -0
- package/dist/components/cms/field-control.js +149 -0
- package/dist/components/cms/field-control.js.map +1 -0
- package/dist/components/cms/filter-builder.d.ts +12 -0
- package/dist/components/cms/filter-builder.js +84 -0
- package/dist/components/cms/filter-builder.js.map +1 -0
- package/dist/components/cms/import-export.d.ts +6 -0
- package/dist/components/cms/import-export.js +33 -0
- package/dist/components/cms/import-export.js.map +1 -0
- package/dist/components/cms/new-page-dialog.d.ts +22 -0
- package/dist/components/cms/new-page-dialog.js +42 -0
- package/dist/components/cms/new-page-dialog.js.map +1 -0
- package/dist/components/cms/reference-confirm.d.ts +25 -0
- package/dist/components/cms/reference-confirm.js +124 -0
- package/dist/components/cms/reference-confirm.js.map +1 -0
- package/dist/components/cms/relation-picker.d.ts +16 -0
- package/dist/components/cms/relation-picker.js +47 -0
- package/dist/components/cms/relation-picker.js.map +1 -0
- package/dist/components/cms/use-cell-edit.d.ts +33 -0
- package/dist/components/cms/use-cell-edit.js +125 -0
- package/dist/components/cms/use-cell-edit.js.map +1 -0
- package/dist/components/cms/versions-model.d.ts +15 -0
- package/dist/components/cms/versions-model.js +23 -0
- package/dist/components/cms/versions-model.js.map +1 -0
- package/dist/components/cms/versions-pane.d.ts +14 -0
- package/dist/components/cms/versions-pane.js +86 -0
- package/dist/components/cms/versions-pane.js.map +1 -0
- package/dist/components/cms/view-bar.d.ts +11 -0
- package/dist/components/cms/view-bar.js +80 -0
- package/dist/components/cms/view-bar.js.map +1 -0
- package/dist/components/collab/collab-context.d.ts +34 -0
- package/dist/components/collab/collab-context.js +52 -0
- package/dist/components/collab/collab-context.js.map +1 -0
- package/dist/components/collab/collab-seed.d.ts +27 -0
- package/dist/components/collab/collab-seed.js +42 -0
- package/dist/components/collab/collab-seed.js.map +1 -0
- package/dist/components/components/component-detail.d.ts +9 -0
- package/dist/components/components/component-detail.js +30 -0
- package/dist/components/components/component-detail.js.map +1 -0
- package/dist/components/components/component-status.d.ts +10 -0
- package/dist/components/components/component-status.js +30 -0
- package/dist/components/components/component-status.js.map +1 -0
- package/dist/components/components/components-index.d.ts +8 -0
- package/dist/components/components/components-index.js +42 -0
- package/dist/components/components/components-index.js.map +1 -0
- package/dist/components/components/field-inspector.d.ts +9 -0
- package/dist/components/components/field-inspector.js +38 -0
- package/dist/components/components/field-inspector.js.map +1 -0
- package/dist/components/components/fixture-runner.d.ts +10 -0
- package/dist/components/components/fixture-runner.js +24 -0
- package/dist/components/components/fixture-runner.js.map +1 -0
- package/dist/components/components/registry-browser.d.ts +4 -0
- package/dist/components/components/registry-browser.js +64 -0
- package/dist/components/components/registry-browser.js.map +1 -0
- package/dist/components/current-user-menu.d.ts +13 -0
- package/dist/components/current-user-menu.js +31 -0
- package/dist/components/current-user-menu.js.map +1 -0
- package/dist/components/dev-login-badge.d.ts +9 -0
- package/dist/components/dev-login-badge.js +18 -0
- package/dist/components/dev-login-badge.js.map +1 -0
- package/dist/components/extensions/extensions-view.d.ts +7 -0
- package/dist/components/extensions/extensions-view.js +126 -0
- package/dist/components/extensions/extensions-view.js.map +1 -0
- package/dist/components/guards.d.ts +27 -0
- package/dist/components/guards.js +46 -0
- package/dist/components/guards.js.map +1 -0
- package/dist/components/inspector/inspector-sidebar.d.ts +26 -0
- package/dist/components/inspector/inspector-sidebar.js +17 -0
- package/dist/components/inspector/inspector-sidebar.js.map +1 -0
- package/dist/components/operation-error.d.ts +17 -0
- package/dist/components/operation-error.js +54 -0
- package/dist/components/operation-error.js.map +1 -0
- package/dist/components/playground-badge.d.ts +10 -0
- package/dist/components/playground-badge.js +19 -0
- package/dist/components/playground-badge.js.map +1 -0
- package/dist/components/project-list.d.ts +15 -0
- package/dist/components/project-list.js +52 -0
- package/dist/components/project-list.js.map +1 -0
- package/dist/components/project-session.d.ts +46 -0
- package/dist/components/project-session.js +107 -0
- package/dist/components/project-session.js.map +1 -0
- package/dist/components/project-switcher.d.ts +11 -0
- package/dist/components/project-switcher.js +44 -0
- package/dist/components/project-switcher.js.map +1 -0
- package/dist/components/references/builder-deep-link.d.ts +12 -0
- package/dist/components/references/builder-deep-link.js +53 -0
- package/dist/components/references/builder-deep-link.js.map +1 -0
- package/dist/components/references/references-panel.d.ts +17 -0
- package/dist/components/references/references-panel.js +66 -0
- package/dist/components/references/references-panel.js.map +1 -0
- package/dist/components/routes/redirect-chain.d.ts +9 -0
- package/dist/components/routes/redirect-chain.js +16 -0
- package/dist/components/routes/redirect-chain.js.map +1 -0
- package/dist/components/routes/redirect-manager.d.ts +13 -0
- package/dist/components/routes/redirect-manager.js +24 -0
- package/dist/components/routes/redirect-manager.js.map +1 -0
- package/dist/components/routes/route-list.d.ts +35 -0
- package/dist/components/routes/route-list.js +69 -0
- package/dist/components/routes/route-list.js.map +1 -0
- package/dist/components/routes/routes-shell.d.ts +14 -0
- package/dist/components/routes/routes-shell.js +68 -0
- package/dist/components/routes/routes-shell.js.map +1 -0
- package/dist/components/section-nav.d.ts +17 -0
- package/dist/components/section-nav.js +33 -0
- package/dist/components/section-nav.js.map +1 -0
- package/dist/components/section-state.d.ts +24 -0
- package/dist/components/section-state.js +78 -0
- package/dist/components/section-state.js.map +1 -0
- package/dist/components/section-surface.d.ts +31 -0
- package/dist/components/section-surface.js +46 -0
- package/dist/components/section-surface.js.map +1 -0
- package/dist/components/sections.d.ts +38 -0
- package/dist/components/sections.js +72 -0
- package/dist/components/sections.js.map +1 -0
- package/dist/components/settings-form.d.ts +10 -0
- package/dist/components/settings-form.js +17 -0
- package/dist/components/settings-form.js.map +1 -0
- package/dist/components/studio-context.d.ts +22 -0
- package/dist/components/studio-context.js +48 -0
- package/dist/components/studio-context.js.map +1 -0
- package/dist/components/studio-project-screen.d.ts +19 -0
- package/dist/components/studio-project-screen.js +195 -0
- package/dist/components/studio-project-screen.js.map +1 -0
- package/dist/components/studio-shell.d.ts +18 -0
- package/dist/components/studio-shell.js +64 -0
- package/dist/components/studio-shell.js.map +1 -0
- package/dist/components/theme-context.d.ts +17 -0
- package/dist/components/theme-context.js +26 -0
- package/dist/components/theme-context.js.map +1 -0
- package/dist/components/workspace-gate.d.ts +12 -0
- package/dist/components/workspace-gate.js +27 -0
- package/dist/components/workspace-gate.js.map +1 -0
- package/dist/components/workspace-projects.d.ts +13 -0
- package/dist/components/workspace-projects.js +18 -0
- package/dist/components/workspace-projects.js.map +1 -0
- package/dist/lib/assets/delete-asset.d.ts +34 -0
- package/dist/lib/assets/delete-asset.js +34 -0
- package/dist/lib/assets/delete-asset.js.map +1 -0
- package/dist/lib/assets/image-dimensions.d.ts +18 -0
- package/dist/lib/assets/image-dimensions.js +26 -0
- package/dist/lib/assets/image-dimensions.js.map +1 -0
- package/dist/lib/assets/index.d.ts +9 -0
- package/dist/lib/assets/index.js +10 -0
- package/dist/lib/assets/index.js.map +1 -0
- package/dist/lib/assets/upload-state.d.ts +53 -0
- package/dist/lib/assets/upload-state.js +59 -0
- package/dist/lib/assets/upload-state.js.map +1 -0
- package/dist/lib/assets/upload.d.ts +56 -0
- package/dist/lib/assets/upload.js +125 -0
- package/dist/lib/assets/upload.js.map +1 -0
- package/dist/lib/auth/auth-adapter.d.ts +57 -0
- package/dist/lib/auth/auth-adapter.js +13 -0
- package/dist/lib/auth/auth-adapter.js.map +1 -0
- package/dist/lib/auth/convex-auth-adapter.d.ts +39 -0
- package/dist/lib/auth/convex-auth-adapter.js +171 -0
- package/dist/lib/auth/convex-auth-adapter.js.map +1 -0
- package/dist/lib/auth/dev-auto-login-adapter.d.ts +25 -0
- package/dist/lib/auth/dev-auto-login-adapter.js +40 -0
- package/dist/lib/auth/dev-auto-login-adapter.js.map +1 -0
- package/dist/lib/auth/index.d.ts +28 -0
- package/dist/lib/auth/index.js +61 -0
- package/dist/lib/auth/index.js.map +1 -0
- package/dist/lib/auth/local-auth-adapter.d.ts +57 -0
- package/dist/lib/auth/local-auth-adapter.js +78 -0
- package/dist/lib/auth/local-auth-adapter.js.map +1 -0
- package/dist/lib/auth/route-guard.d.ts +33 -0
- package/dist/lib/auth/route-guard.js +51 -0
- package/dist/lib/auth/route-guard.js.map +1 -0
- package/dist/lib/auth-errors.d.ts +42 -0
- package/dist/lib/auth-errors.js +74 -0
- package/dist/lib/auth-errors.js.map +1 -0
- package/dist/lib/bindings/section-bindings.d.ts +24 -0
- package/dist/lib/bindings/section-bindings.js +9 -0
- package/dist/lib/bindings/section-bindings.js.map +1 -0
- package/dist/lib/clipboard/index.d.ts +7 -0
- package/dist/lib/clipboard/index.js +8 -0
- package/dist/lib/clipboard/index.js.map +1 -0
- package/dist/lib/clipboard/os-clipboard.d.ts +46 -0
- package/dist/lib/clipboard/os-clipboard.js +105 -0
- package/dist/lib/clipboard/os-clipboard.js.map +1 -0
- package/dist/lib/clipboard/paste-issues.d.ts +34 -0
- package/dist/lib/clipboard/paste-issues.js +67 -0
- package/dist/lib/clipboard/paste-issues.js.map +1 -0
- package/dist/lib/clipboard/paste-target.d.ts +20 -0
- package/dist/lib/clipboard/paste-target.js +28 -0
- package/dist/lib/clipboard/paste-target.js.map +1 -0
- package/dist/lib/cms/published-documents.d.ts +30 -0
- package/dist/lib/cms/published-documents.js +75 -0
- package/dist/lib/cms/published-documents.js.map +1 -0
- package/dist/lib/cms-views/index.d.ts +9 -0
- package/dist/lib/cms-views/index.js +10 -0
- package/dist/lib/cms-views/index.js.map +1 -0
- package/dist/lib/cms-views/selection.d.ts +29 -0
- package/dist/lib/cms-views/selection.js +46 -0
- package/dist/lib/cms-views/selection.js.map +1 -0
- package/dist/lib/cms-views/view-model.d.ts +192 -0
- package/dist/lib/cms-views/view-model.js +353 -0
- package/dist/lib/cms-views/view-model.js.map +1 -0
- package/dist/lib/cms-views/views-store.d.ts +70 -0
- package/dist/lib/cms-views/views-store.js +129 -0
- package/dist/lib/cms-views/views-store.js.map +1 -0
- package/dist/lib/data/collection-content.d.ts +105 -0
- package/dist/lib/data/collection-content.js +196 -0
- package/dist/lib/data/collection-content.js.map +1 -0
- package/dist/lib/data/data-store.d.ts +97 -0
- package/dist/lib/data/data-store.js +205 -0
- package/dist/lib/data/data-store.js.map +1 -0
- package/dist/lib/data/index.d.ts +4 -0
- package/dist/lib/data/index.js +8 -0
- package/dist/lib/data/index.js.map +1 -0
- package/dist/lib/data/providers.d.ts +143 -0
- package/dist/lib/data/providers.js +255 -0
- package/dist/lib/data/providers.js.map +1 -0
- package/dist/lib/data/sample-capture.d.ts +30 -0
- package/dist/lib/data/sample-capture.js +70 -0
- package/dist/lib/data/sample-capture.js.map +1 -0
- package/dist/lib/data/sources-store.d.ts +42 -0
- package/dist/lib/data/sources-store.js +120 -0
- package/dist/lib/data/sources-store.js.map +1 -0
- package/dist/lib/dnd/drop-rules.d.ts +219 -0
- package/dist/lib/dnd/drop-rules.js +257 -0
- package/dist/lib/dnd/drop-rules.js.map +1 -0
- package/dist/lib/dnd/gap-drag.d.ts +66 -0
- package/dist/lib/dnd/gap-drag.js +95 -0
- package/dist/lib/dnd/gap-drag.js.map +1 -0
- package/dist/lib/locale/binding-fallback.d.ts +28 -0
- package/dist/lib/locale/binding-fallback.js +66 -0
- package/dist/lib/locale/binding-fallback.js.map +1 -0
- package/dist/lib/locale/fallback.d.ts +43 -0
- package/dist/lib/locale/fallback.js +52 -0
- package/dist/lib/locale/fallback.js.map +1 -0
- package/dist/lib/locale/index.d.ts +6 -0
- package/dist/lib/locale/index.js +7 -0
- package/dist/lib/locale/index.js.map +1 -0
- package/dist/lib/locale/locale-store.d.ts +40 -0
- package/dist/lib/locale/locale-store.js +61 -0
- package/dist/lib/locale/locale-store.js.map +1 -0
- package/dist/lib/locale/locale-switcher.d.ts +10 -0
- package/dist/lib/locale/locale-switcher.js +24 -0
- package/dist/lib/locale/locale-switcher.js.map +1 -0
- package/dist/lib/locale/route-variant.d.ts +14 -0
- package/dist/lib/locale/route-variant.js +11 -0
- package/dist/lib/locale/route-variant.js.map +1 -0
- package/dist/lib/locale/use-studio-locale.d.ts +10 -0
- package/dist/lib/locale/use-studio-locale.js +8 -0
- package/dist/lib/locale/use-studio-locale.js.map +1 -0
- package/dist/lib/operations/asset-repository.d.ts +15 -0
- package/dist/lib/operations/asset-repository.js +56 -0
- package/dist/lib/operations/asset-repository.js.map +1 -0
- package/dist/lib/operations/cms-persistence.d.ts +35 -0
- package/dist/lib/operations/cms-persistence.js +75 -0
- package/dist/lib/operations/cms-persistence.js.map +1 -0
- package/dist/lib/operations/graph-commands.d.ts +140 -0
- package/dist/lib/operations/graph-commands.js +86 -0
- package/dist/lib/operations/graph-commands.js.map +1 -0
- package/dist/lib/operations/graph-persistence.d.ts +27 -0
- package/dist/lib/operations/graph-persistence.js +35 -0
- package/dist/lib/operations/graph-persistence.js.map +1 -0
- package/dist/lib/operations/index.d.ts +13 -0
- package/dist/lib/operations/index.js +14 -0
- package/dist/lib/operations/index.js.map +1 -0
- package/dist/lib/operations/operations-package.d.ts +6 -0
- package/dist/lib/operations/operations-package.js +7 -0
- package/dist/lib/operations/operations-package.js.map +1 -0
- package/dist/lib/operations/persist-queue.d.ts +16 -0
- package/dist/lib/operations/persist-queue.js +18 -0
- package/dist/lib/operations/persist-queue.js.map +1 -0
- package/dist/lib/operations/session-hydration.d.ts +84 -0
- package/dist/lib/operations/session-hydration.js +112 -0
- package/dist/lib/operations/session-hydration.js.map +1 -0
- package/dist/lib/operations/studio-operations.d.ts +59 -0
- package/dist/lib/operations/studio-operations.js +92 -0
- package/dist/lib/operations/studio-operations.js.map +1 -0
- package/dist/lib/persistence/backend-mode.d.ts +69 -0
- package/dist/lib/persistence/backend-mode.js +120 -0
- package/dist/lib/persistence/backend-mode.js.map +1 -0
- package/dist/lib/persistence/convex-adapter.d.ts +34 -0
- package/dist/lib/persistence/convex-adapter.js +681 -0
- package/dist/lib/persistence/convex-adapter.js.map +1 -0
- package/dist/lib/persistence/convex-blob-storage.d.ts +57 -0
- package/dist/lib/persistence/convex-blob-storage.js +97 -0
- package/dist/lib/persistence/convex-blob-storage.js.map +1 -0
- package/dist/lib/persistence/convex-client.d.ts +19 -0
- package/dist/lib/persistence/convex-client.js +40 -0
- package/dist/lib/persistence/convex-client.js.map +1 -0
- package/dist/lib/persistence/index.d.ts +30 -0
- package/dist/lib/persistence/index.js +60 -0
- package/dist/lib/persistence/index.js.map +1 -0
- package/dist/lib/persona/labels.d.ts +23 -0
- package/dist/lib/persona/labels.js +122 -0
- package/dist/lib/persona/labels.js.map +1 -0
- package/dist/lib/rail.d.ts +11 -0
- package/dist/lib/rail.js +26 -0
- package/dist/lib/rail.js.map +1 -0
- package/dist/lib/references/impact.d.ts +64 -0
- package/dist/lib/references/impact.js +62 -0
- package/dist/lib/references/impact.js.map +1 -0
- package/dist/lib/references/index.d.ts +7 -0
- package/dist/lib/references/index.js +8 -0
- package/dist/lib/references/index.js.map +1 -0
- package/dist/lib/references/reference-model.d.ts +125 -0
- package/dist/lib/references/reference-model.js +242 -0
- package/dist/lib/references/reference-model.js.map +1 -0
- package/dist/lib/references/references-store.d.ts +65 -0
- package/dist/lib/references/references-store.js +221 -0
- package/dist/lib/references/references-store.js.map +1 -0
- package/dist/lib/registry/index.d.ts +65 -0
- package/dist/lib/registry/index.js +114 -0
- package/dist/lib/registry/index.js.map +1 -0
- package/dist/lib/registry/preview.d.ts +15 -0
- package/dist/lib/registry/preview.js +110 -0
- package/dist/lib/registry/preview.js.map +1 -0
- package/dist/lib/registry/project-components.d.ts +16 -0
- package/dist/lib/registry/project-components.js +152 -0
- package/dist/lib/registry/project-components.js.map +1 -0
- package/dist/lib/routing/index.d.ts +10 -0
- package/dist/lib/routing/index.js +11 -0
- package/dist/lib/routing/index.js.map +1 -0
- package/dist/lib/routing/routing-analysis.d.ts +26 -0
- package/dist/lib/routing/routing-analysis.js +37 -0
- package/dist/lib/routing/routing-analysis.js.map +1 -0
- package/dist/lib/routing/routing-store.d.ts +50 -0
- package/dist/lib/routing/routing-store.js +72 -0
- package/dist/lib/routing/routing-store.js.map +1 -0
- package/dist/lib/starters/kit-session.d.ts +5 -0
- package/dist/lib/starters/kit-session.js +17 -0
- package/dist/lib/starters/kit-session.js.map +1 -0
- package/dist/lib/theme.d.ts +21 -0
- package/dist/lib/theme.js +32 -0
- package/dist/lib/theme.js.map +1 -0
- package/dist/lib/utils.d.ts +11 -0
- package/dist/lib/utils.js +28 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/webhooks/config.d.ts +15 -0
- package/dist/lib/webhooks/config.js +64 -0
- package/dist/lib/webhooks/config.js.map +1 -0
- package/dist/lib/webhooks/dispatcher.d.ts +67 -0
- package/dist/lib/webhooks/dispatcher.js +61 -0
- package/dist/lib/webhooks/dispatcher.js.map +1 -0
- package/dist/lib/webhooks/index.d.ts +11 -0
- package/dist/lib/webhooks/index.js +10 -0
- package/dist/lib/webhooks/index.js.map +1 -0
- package/dist/lib/webhooks/signing.d.ts +15 -0
- package/dist/lib/webhooks/signing.js +24 -0
- package/dist/lib/webhooks/signing.js.map +1 -0
- package/dist/lib/webhooks/tags.d.ts +25 -0
- package/dist/lib/webhooks/tags.js +173 -0
- package/dist/lib/webhooks/tags.js.map +1 -0
- package/dist/lib/working-graph.d.ts +82 -0
- package/dist/lib/working-graph.js +113 -0
- package/dist/lib/working-graph.js.map +1 -0
- package/dist/lib/workspace/index.d.ts +109 -0
- package/dist/lib/workspace/index.js +206 -0
- package/dist/lib/workspace/index.js.map +1 -0
- package/dist/lib/workspace/switcher-source.d.ts +39 -0
- package/dist/lib/workspace/switcher-source.js +23 -0
- package/dist/lib/workspace/switcher-source.js.map +1 -0
- package/dist/lib/workspace/workspace-source.d.ts +47 -0
- package/dist/lib/workspace/workspace-source.js +67 -0
- package/dist/lib/workspace/workspace-source.js.map +1 -0
- package/dist/router/index.d.ts +32 -0
- package/dist/router/index.js +32 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/match.d.ts +75 -0
- package/dist/router/match.js +87 -0
- package/dist/router/match.js.map +1 -0
- package/dist/router/search.d.ts +22 -0
- package/dist/router/search.js +16 -0
- package/dist/router/search.js.map +1 -0
- package/dist/ui/avatar.d.ts +17 -0
- package/dist/ui/avatar.js +38 -0
- package/dist/ui/avatar.js.map +1 -0
- package/dist/ui/badge.d.ts +9 -0
- package/dist/ui/badge.js +23 -0
- package/dist/ui/badge.js.map +1 -0
- package/dist/ui/button.d.ts +11 -0
- package/dist/ui/button.js +30 -0
- package/dist/ui/button.js.map +1 -0
- package/dist/ui/card.d.ts +11 -0
- package/dist/ui/card.js +23 -0
- package/dist/ui/card.js.map +1 -0
- package/dist/ui/dialog.d.ts +12 -0
- package/dist/ui/dialog.js +27 -0
- package/dist/ui/dialog.js.map +1 -0
- package/dist/ui/dropdown-menu.d.ts +15 -0
- package/dist/ui/dropdown-menu.js +24 -0
- package/dist/ui/dropdown-menu.js.map +1 -0
- package/dist/ui/field.d.ts +15 -0
- package/dist/ui/field.js +14 -0
- package/dist/ui/field.js.map +1 -0
- package/dist/ui/index.d.ts +14 -0
- package/dist/ui/index.js +15 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/input.d.ts +3 -0
- package/dist/ui/input.js +7 -0
- package/dist/ui/input.js.map +1 -0
- package/dist/ui/inspector.d.ts +18 -0
- package/dist/ui/inspector.js +14 -0
- package/dist/ui/inspector.js.map +1 -0
- package/dist/ui/layout.d.ts +45 -0
- package/dist/ui/layout.js +48 -0
- package/dist/ui/layout.js.map +1 -0
- package/dist/ui/panel.d.ts +12 -0
- package/dist/ui/panel.js +20 -0
- package/dist/ui/panel.js.map +1 -0
- package/dist/ui/separator.d.ts +6 -0
- package/dist/ui/separator.js +7 -0
- package/dist/ui/separator.js.map +1 -0
- package/dist/ui/toolbar.d.ts +9 -0
- package/dist/ui/toolbar.js +16 -0
- package/dist/ui/toolbar.js.map +1 -0
- package/dist/ui/typography.d.ts +50 -0
- package/dist/ui/typography.js +43 -0
- package/dist/ui/typography.js.map +1 -0
- package/package.json +149 -0
- package/src/styles/studio.css +101 -0
- package/src/styles/tokens.css +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect-manager.js","sourceRoot":"","sources":["../../../src/components/routes/redirect-manager.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { RouteRecord } from '@elytracms/cms-core';
|
|
2
|
+
import type { RouteConflict } from '@elytracms/studio/lib/routing';
|
|
3
|
+
/** The slice of a graph page the route list needs for linking/labelling. */
|
|
4
|
+
export interface PageSummary {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
}
|
|
8
|
+
export interface RouteListProps {
|
|
9
|
+
projectId: string;
|
|
10
|
+
routes: readonly RouteRecord[];
|
|
11
|
+
/** Engine-sourced `route-conflict` issues, indexed by route id (both sides). */
|
|
12
|
+
conflicts: ReadonlyMap<string, RouteConflict[]>;
|
|
13
|
+
pages: readonly PageSummary[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Every route of the project (EC-170), read-only (EC-207 "routes as code"):
|
|
17
|
+
* static paths, dynamic patterns with `:param` segments rendered distinctly, and
|
|
18
|
+
* per-locale variants — each row linking to its page/template/document. Routes
|
|
19
|
+
* are authored in `elytra.config.ts`; this list only views them. Conflicts from
|
|
20
|
+
* the engine's structured issues render inline with deep links to the
|
|
21
|
+
* counterpart row.
|
|
22
|
+
*/
|
|
23
|
+
export declare function RouteList({ projectId, routes, conflicts, pages }: RouteListProps): import("react").JSX.Element;
|
|
24
|
+
/** A route pattern with `:param` segments rendered distinctly (EC-170). */
|
|
25
|
+
export declare function PatternView({ pattern }: {
|
|
26
|
+
pattern: string;
|
|
27
|
+
}): import("react").JSX.Element;
|
|
28
|
+
/**
|
|
29
|
+
* Inline conflict block: the engine's `route-conflict` message plus a deep
|
|
30
|
+
* link to the counterpart row (same-page anchor; rows highlight on `:target`).
|
|
31
|
+
*/
|
|
32
|
+
export declare function ConflictNotice({ routeId, conflicts, }: {
|
|
33
|
+
routeId: string;
|
|
34
|
+
conflicts: readonly RouteConflict[];
|
|
35
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Link, STUDIO_PROJECT_ROUTE, studioPath } from '@elytracms/studio/router';
|
|
3
|
+
import { CircleAlert, Globe } from 'lucide-react';
|
|
4
|
+
import { Badge, Code, Row, Spacer, Stack, Text } from '@elytracms/studio/ui';
|
|
5
|
+
import { patternSegments } from '@elytracms/studio/lib/routing';
|
|
6
|
+
/**
|
|
7
|
+
* Every route of the project (EC-170), read-only (EC-207 "routes as code"):
|
|
8
|
+
* static paths, dynamic patterns with `:param` segments rendered distinctly, and
|
|
9
|
+
* per-locale variants — each row linking to its page/template/document. Routes
|
|
10
|
+
* are authored in `elytra.config.ts`; this list only views them. Conflicts from
|
|
11
|
+
* the engine's structured issues render inline with deep links to the
|
|
12
|
+
* counterpart row.
|
|
13
|
+
*/
|
|
14
|
+
export function RouteList({ projectId, routes, conflicts, pages }) {
|
|
15
|
+
const sorted = [...routes].sort((a, b) => a.pattern === b.pattern
|
|
16
|
+
? (a.locale ?? '').localeCompare(b.locale ?? '')
|
|
17
|
+
: a.pattern.localeCompare(b.pattern));
|
|
18
|
+
return (_jsxs(Stack, { gap: "none", className: "min-h-0", children: [_jsxs(Row, { gap: "2", className: "h-12 shrink-0 border-b border-border px-4", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Routes" }), _jsx(Text, { size: "xs", tone: "subtle", mono: true, children: routes.length })] }), _jsxs(Stack, { gap: "3", className: "p-4", children: [sorted.length === 0 ? (_jsx(Text, { size: "sm", tone: "muted", children: "No routes defined. Add routes in elytra.config.ts to bind URL patterns to pages or templates." })) : null, _jsx("ul", { className: "flex flex-col gap-2", "data-testid": "route-list", children: sorted.map((route) => (_jsx(RouteRow, { projectId: projectId, route: route, conflicts: conflicts.get(route.id) ?? [], pages: pages }, route.id))) })] })] }));
|
|
19
|
+
}
|
|
20
|
+
function RouteRow({ projectId, route, conflicts, pages, }) {
|
|
21
|
+
const hasConflict = conflicts.length > 0;
|
|
22
|
+
return (_jsxs("li", { id: `route-${route.id}`, "data-testid": `route-row-${route.id}`, className: 'rounded-md border p-3 transition-colors target:ring-2 target:ring-ring/60 ' +
|
|
23
|
+
(hasConflict ? 'border-destructive/40 bg-destructive/5' : 'border-border bg-card/40'), children: [_jsxs(Row, { gap: "2", wrap: true, children: [_jsx(PatternView, { pattern: route.pattern }), _jsx(LocaleBadge, { locale: route.locale }), _jsx(Spacer, {}), hasConflict ? (_jsx(Badge, { variant: "error", "data-testid": `route-status-${route.id}`, children: "conflict" })) : (_jsx(Badge, { variant: "success", "data-testid": `route-status-${route.id}`, children: "ok" }))] }), _jsx(Row, { gap: "2", wrap: true, className: "mt-2", children: _jsx(RouteTarget, { projectId: projectId, route: route, pages: pages }) }), hasConflict ? _jsx(ConflictNotice, { routeId: route.id, conflicts: conflicts }) : null] }));
|
|
24
|
+
}
|
|
25
|
+
/** A route pattern with `:param` segments rendered distinctly (EC-170). */
|
|
26
|
+
export function PatternView({ pattern }) {
|
|
27
|
+
const segments = patternSegments(pattern);
|
|
28
|
+
return (_jsxs("span", { className: "inline-flex flex-wrap items-center font-mono text-sm", "data-testid": "pattern", children: [_jsx("span", { className: "text-muted-foreground", children: "/" }), segments.map((segment, index) => (_jsxs("span", { className: "inline-flex items-center", children: [segment.param ? (_jsx("span", { "data-param": segment.text, className: "rounded-sm border border-primary/30 bg-primary/10 px-1 text-primary", children: segment.text })) : (_jsx("span", { className: "text-foreground", children: segment.text })), index < segments.length - 1 ? _jsx("span", { className: "text-muted-foreground", children: "/" }) : null] }, `${segment.text}-${index}`)))] }));
|
|
29
|
+
}
|
|
30
|
+
function LocaleBadge({ locale }) {
|
|
31
|
+
if (!locale) {
|
|
32
|
+
return (_jsxs(Badge, { variant: "outline", children: [_jsx(Globe, {}), " all locales"] }));
|
|
33
|
+
}
|
|
34
|
+
return (_jsxs(Badge, { variant: "info", children: [_jsx(Globe, {}), " ", locale] }));
|
|
35
|
+
}
|
|
36
|
+
/** The page/template/document a route renders, deep-linked where a surface exists. */
|
|
37
|
+
function RouteTarget({ projectId, route, pages, }) {
|
|
38
|
+
// EC-187: every target is a single `document` ref. A page target is the
|
|
39
|
+
// `page` collection; a template target is a `:param` placeholder id;
|
|
40
|
+
// anything else is a concrete linked document.
|
|
41
|
+
if (!route.document) {
|
|
42
|
+
return (_jsx(Badge, { variant: "warning", "data-testid": `route-no-target-${route.id}`, children: "no target" }));
|
|
43
|
+
}
|
|
44
|
+
if (route.document.collection === 'page') {
|
|
45
|
+
const pageId = route.document.id;
|
|
46
|
+
const page = pages.find((candidate) => candidate.id === pageId);
|
|
47
|
+
return (_jsxs(Row, { gap: "1", children: [_jsx(Text, { size: "xs", tone: "muted", children: "page" }), _jsx(Link, { to: STUDIO_PROJECT_ROUTE, params: { projectId, _splat: studioPath.builder() }, className: "text-xs font-medium text-primary underline-offset-2 hover:underline", children: page?.name ?? pageId }), !page ? _jsx(Badge, { variant: "warning", children: "not in graph" }) : null] }));
|
|
48
|
+
}
|
|
49
|
+
if (route.document.id.startsWith(':')) {
|
|
50
|
+
return (_jsxs(Row, { gap: "1", children: [_jsx(Text, { size: "xs", tone: "muted", children: "template" }), _jsx(Code, { children: route.document.collection })] }));
|
|
51
|
+
}
|
|
52
|
+
return (_jsxs(Row, { gap: "1", children: [_jsx(Text, { size: "xs", tone: "muted", children: "document" }), _jsxs(Link, { to: STUDIO_PROJECT_ROUTE, params: {
|
|
53
|
+
projectId,
|
|
54
|
+
_splat: studioPath.cmsDocument(route.document.collection, route.document.id),
|
|
55
|
+
}, className: "text-xs font-medium text-primary underline-offset-2 hover:underline", children: [route.document.collection, "/", route.document.id] })] }));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Inline conflict block: the engine's `route-conflict` message plus a deep
|
|
59
|
+
* link to the counterpart row (same-page anchor; rows highlight on `:target`).
|
|
60
|
+
*/
|
|
61
|
+
export function ConflictNotice({ routeId, conflicts, }) {
|
|
62
|
+
return (_jsx(Stack, { gap: "1", className: "mt-2 rounded-md border border-destructive/30 bg-destructive/10 p-2", children: conflicts.map((conflict, index) => (_jsxs(Row, { gap: "2", align: "start", children: [_jsx(CircleAlert, { className: "mt-0.5 size-3.5 shrink-0 text-destructive" }), _jsxs(Stack, { gap: "1", className: "min-w-0", children: [_jsx(Text, { size: "xs", className: "text-destructive", "data-testid": `conflict-${routeId}`,
|
|
63
|
+
// The engine message names both routes by their raw ids
|
|
64
|
+
// (`r-blog-slug-en`) — kept inspectable on hover, never shown as
|
|
65
|
+
// visible copy. The editor sees the patterns on the rows + the link
|
|
66
|
+
// below (EC-192).
|
|
67
|
+
title: conflict.issue.message, children: "Matches the same URLs as another route." }), conflict.otherRouteId ? (_jsx("a", { href: `#route-${conflict.otherRouteId}`, className: "text-xs font-medium text-destructive underline underline-offset-2", "data-testid": `conflict-link-${routeId}`, children: "View conflicting route" })) : null] })] }, `${conflict.otherRouteId}-${index}`))) }));
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=route-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-list.js","sourceRoot":"","sources":["../../../src/components/routes/route-list.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Project } from '@elytracms/studio-core';
|
|
2
|
+
/**
|
|
3
|
+
* The Routes surface (EC-170, made read-only by EC-207 "routes as code"):
|
|
4
|
+
* every route and redirect of the project, with the engine's structured issues
|
|
5
|
+
* (route conflicts, redirect loops) rendered inline. Routes and redirects are
|
|
6
|
+
* authored in `elytra.config.ts` and read from the resolved config project
|
|
7
|
+
* (`resolveDeploymentRoutes`/`resolveDeploymentRedirects`) — NEVER from the
|
|
8
|
+
* backend. This surface only views them; conflict/loop detection comes from the
|
|
9
|
+
* canonical `@elytracms/cms-core` router, never from parallel UI-side logic. The
|
|
10
|
+
* page list (CMS `page` collection) is read only to label route targets.
|
|
11
|
+
*/
|
|
12
|
+
export declare function RoutesShell({ project }: {
|
|
13
|
+
project: Project;
|
|
14
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import { createRouter } from '@elytracms/cms-core';
|
|
4
|
+
import { Badge, Heading, Row, Spacer, Stack, Text } from '@elytracms/studio/ui';
|
|
5
|
+
import { getStudioOperations } from '@elytracms/studio/lib/operations';
|
|
6
|
+
import { conflictsByRoute } from '@elytracms/studio/lib/routing';
|
|
7
|
+
import { resolveDeploymentRedirects, resolveDeploymentRoutes } from '@elytracms/studio/lib/workspace';
|
|
8
|
+
import { OperationErrorBanner } from '../operation-error';
|
|
9
|
+
import { RouteList } from './route-list';
|
|
10
|
+
import { RedirectManager } from './redirect-manager';
|
|
11
|
+
/** The body-is-a-canvas page collection (EC-187): routable page documents. */
|
|
12
|
+
const PAGE_COLLECTION = 'page';
|
|
13
|
+
/**
|
|
14
|
+
* Routable pages come from the `page` CMS collection (EC-192) — the documents an
|
|
15
|
+
* editor actually creates — not the builder's single synthetic working page.
|
|
16
|
+
* `documents.list` returns persisted records wrapping each document; map each to
|
|
17
|
+
* a `{ id, name }` summary for the route target labels.
|
|
18
|
+
*/
|
|
19
|
+
function pageSummaries(records) {
|
|
20
|
+
return records.map(({ document }) => {
|
|
21
|
+
const name = document.values?.['name'];
|
|
22
|
+
return { id: document.id, name: typeof name === 'string' && name.length > 0 ? name : document.id };
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The Routes surface (EC-170, made read-only by EC-207 "routes as code"):
|
|
27
|
+
* every route and redirect of the project, with the engine's structured issues
|
|
28
|
+
* (route conflicts, redirect loops) rendered inline. Routes and redirects are
|
|
29
|
+
* authored in `elytra.config.ts` and read from the resolved config project
|
|
30
|
+
* (`resolveDeploymentRoutes`/`resolveDeploymentRedirects`) — NEVER from the
|
|
31
|
+
* backend. This surface only views them; conflict/loop detection comes from the
|
|
32
|
+
* canonical `@elytracms/cms-core` router, never from parallel UI-side logic. The
|
|
33
|
+
* page list (CMS `page` collection) is read only to label route targets.
|
|
34
|
+
*/
|
|
35
|
+
export function RoutesShell({ project }) {
|
|
36
|
+
const projectId = project.id;
|
|
37
|
+
// Routes & redirects are config-sourced (EC-207): resolved synchronously from
|
|
38
|
+
// the active `elytra.config.ts` project, never fetched from the backend.
|
|
39
|
+
const routes = useMemo(() => resolveDeploymentRoutes(), []);
|
|
40
|
+
const redirects = useMemo(() => resolveDeploymentRedirects(), []);
|
|
41
|
+
const [pages, setPages] = useState([]);
|
|
42
|
+
const [loadError, setLoadError] = useState(null);
|
|
43
|
+
// Page documents feed the route target labels (read-only display). A failure
|
|
44
|
+
// here is non-fatal: the routes still render; the page labels just fall back
|
|
45
|
+
// to ids. The error banner surfaces any connection problem.
|
|
46
|
+
const reloadPages = useCallback(async () => {
|
|
47
|
+
const { operations } = await getStudioOperations();
|
|
48
|
+
const pageDocs = await operations.documents.list({ projectId, collection: PAGE_COLLECTION });
|
|
49
|
+
if (pageDocs.ok) {
|
|
50
|
+
setPages(pageSummaries(pageDocs.value));
|
|
51
|
+
setLoadError(null);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
setLoadError(pageDocs.error);
|
|
55
|
+
}
|
|
56
|
+
}, [projectId]);
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
void reloadPages();
|
|
59
|
+
}, [reloadPages]);
|
|
60
|
+
// The engine: one router over the config-resolved records. Its structured
|
|
61
|
+
// issues are the single source of conflict/loop truth for this surface.
|
|
62
|
+
const router = useMemo(() => createRouter(routes, redirects, {
|
|
63
|
+
defaultLocale: project.settings.defaultLocale,
|
|
64
|
+
}), [routes, redirects, project.settings.defaultLocale]);
|
|
65
|
+
const conflicts = useMemo(() => conflictsByRoute(router.issues), [router]);
|
|
66
|
+
return (_jsxs(Stack, { gap: "none", className: "min-h-full", "data-testid": "routes-shell", children: [_jsxs(Row, { gap: "3", className: "shrink-0 border-b border-border px-4 py-3 sm:px-6", children: [_jsxs(Stack, { gap: "1", children: [_jsx(Heading, { level: 2, size: "h3", children: "Routes & redirects" }), _jsxs(Text, { size: "xs", tone: "muted", children: ["Routes & redirects are defined in ", _jsx("code", { children: "elytra.config.ts" }), ". Conflicts and loops are detected by the canonical route engine \u2014 never silently."] })] }), _jsx(Spacer, {}), loadError ? (_jsx(OperationErrorBanner, { error: loadError, onDismiss: () => void reloadPages() })) : null, router.issues.length > 0 ? (_jsxs(Badge, { variant: "error", "data-testid": "routing-issue-count", children: [router.issues.length, " issue", router.issues.length === 1 ? '' : 's'] })) : (_jsx(Badge, { variant: "success", children: "no issues" }))] }), _jsxs("div", { className: "grid min-h-0 flex-1 grid-cols-1 xl:grid-cols-[minmax(0,5fr)_minmax(0,4fr)]", children: [_jsx("section", { "aria-label": "Routes", className: "min-w-0 border-b border-border xl:border-b-0 xl:border-r", children: _jsx(RouteList, { projectId: projectId, routes: routes, conflicts: conflicts, pages: pages }) }), _jsx("section", { "aria-label": "Redirects", className: "min-w-0", children: _jsx(RedirectManager, { redirects: redirects, followRedirects: router.followRedirects }) })] })] }));
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=routes-shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes-shell.js","sourceRoot":"","sources":["../../../src/components/routes/routes-shell.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ProjectId, SectionAvailabilityMap } from '@elytracms/studio-core';
|
|
2
|
+
import type { StudioNavId } from './sections';
|
|
3
|
+
export interface SectionNavProps {
|
|
4
|
+
projectId: ProjectId;
|
|
5
|
+
activeSection: StudioNavId | null;
|
|
6
|
+
availability: SectionAvailabilityMap;
|
|
7
|
+
/** User-toggled collapse (EC-214) — icons only when collapsed, persisted by the shell. */
|
|
8
|
+
collapsed: boolean;
|
|
9
|
+
onToggleCollapsed: () => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Vertical section rail (brief §8.1). Availability-aware: `available`/`planned`
|
|
13
|
+
* are navigable; `unavailable` is rendered disabled. User-collapsible to an
|
|
14
|
+
* icon rail (EC-214) — the preference persists, and the active section carries a
|
|
15
|
+
* strong highlight (accent fill + a leading marker bar).
|
|
16
|
+
*/
|
|
17
|
+
export declare function SectionNav({ projectId, activeSection, availability, collapsed, onToggleCollapsed, }: SectionNavProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Link, STUDIO_PROJECT_ROUTE, useLocation } from '@elytracms/studio/router';
|
|
3
|
+
import { PanelLeftClose, PanelLeftOpen } from 'lucide-react';
|
|
4
|
+
import { cn } from '@elytracms/studio/lib/utils';
|
|
5
|
+
import { SECTION_NAV_ITEMS, activeSectionFromPath, navAvailabilityOf } from './sections';
|
|
6
|
+
/**
|
|
7
|
+
* Vertical section rail (brief §8.1). Availability-aware: `available`/`planned`
|
|
8
|
+
* are navigable; `unavailable` is rendered disabled. User-collapsible to an
|
|
9
|
+
* icon rail (EC-214) — the preference persists, and the active section carries a
|
|
10
|
+
* strong highlight (accent fill + a leading marker bar).
|
|
11
|
+
*/
|
|
12
|
+
export function SectionNav({ projectId, activeSection, availability, collapsed, onToggleCollapsed, }) {
|
|
13
|
+
// Recover the active id from the path if the shell didn't supply one — the
|
|
14
|
+
// shared parser is the single source of truth for the section segment index.
|
|
15
|
+
const { pathname } = useLocation();
|
|
16
|
+
const active = activeSection ?? activeSectionFromPath(pathname);
|
|
17
|
+
return (_jsxs("nav", { "aria-label": "Sections", className: cn('flex shrink-0 flex-col gap-0.5 border-r border-border bg-card/40 p-2 transition-[width] duration-150', collapsed ? 'w-[3.5rem]' : 'w-56'), children: [SECTION_NAV_ITEMS.map((item) => {
|
|
18
|
+
const state = navAvailabilityOf(availability, item.id);
|
|
19
|
+
const isActive = item.id === active;
|
|
20
|
+
const Icon = item.icon;
|
|
21
|
+
const body = (_jsxs(_Fragment, { children: [isActive ? (_jsx("span", { className: "absolute inset-y-1.5 left-0 w-0.5 rounded-full bg-primary", "aria-hidden": true })) : null, _jsx(Icon, { className: "size-4 shrink-0" }), collapsed ? null : (_jsx("span", { className: "min-w-0 flex-1 truncate", children: item.label })), state === 'planned' && !collapsed ? (_jsx("span", { className: "size-1.5 shrink-0 rounded-full bg-warning", "aria-hidden": true, title: "Planned" })) : null] }));
|
|
22
|
+
const base = cn('group relative flex h-9 items-center gap-2.5 rounded-md text-sm transition-colors', collapsed ? 'justify-center px-0' : 'px-3');
|
|
23
|
+
// EC-221: an unavailable section is absent from the rail (not greyed) —
|
|
24
|
+
// e.g. Extensions, cut from the v1 nav (vision §5). It stays reachable by
|
|
25
|
+
// URL for Milestone E revival; the rail simply doesn't advertise it.
|
|
26
|
+
if (state === 'unavailable')
|
|
27
|
+
return null;
|
|
28
|
+
return (_jsx(Link, { to: STUDIO_PROJECT_ROUTE, params: { projectId, _splat: item.id }, title: item.label, "aria-current": isActive ? 'page' : undefined, className: cn(base, isActive
|
|
29
|
+
? 'bg-accent font-medium text-accent-foreground'
|
|
30
|
+
: 'text-muted-foreground hover:bg-muted hover:text-foreground'), children: body }, item.id));
|
|
31
|
+
}), _jsx("button", { type: "button", onClick: onToggleCollapsed, "aria-label": collapsed ? 'Expand sidebar' : 'Collapse sidebar', "aria-pressed": collapsed, title: collapsed ? 'Expand sidebar' : 'Collapse sidebar', className: cn('mt-auto flex h-9 items-center gap-2.5 rounded-md text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground', collapsed ? 'justify-center px-0' : 'px-3'), children: collapsed ? (_jsx(PanelLeftOpen, { className: "size-4 shrink-0" })) : (_jsxs(_Fragment, { children: [_jsx(PanelLeftClose, { className: "size-4 shrink-0" }), _jsx("span", { className: "min-w-0 flex-1 truncate text-left", children: "Collapse" })] })) })] }));
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=section-nav.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section-nav.js","sourceRoot":"","sources":["../../src/components/section-nav.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { SectionAvailability, SectionState } from '@elytracms/studio-core';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the runtime state of a section (brief §8.1, §11). A `forced` value
|
|
5
|
+
* (e.g. from a `?state=` param) wins, making every state reachable
|
|
6
|
+
* deterministically; otherwise availability decides.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveSectionState(availability: SectionAvailability, forced?: SectionState | null): SectionState;
|
|
9
|
+
export interface SectionStateViewProps {
|
|
10
|
+
state: Exclude<SectionState, 'working'>;
|
|
11
|
+
/** Section-specific heading, e.g. "CMS" — overrides the generic preset title. */
|
|
12
|
+
title?: string;
|
|
13
|
+
description?: ReactNode;
|
|
14
|
+
action?: ReactNode;
|
|
15
|
+
className?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Loading uses a skeleton; the rest use a centered placeholder. Consistent across sections. */
|
|
18
|
+
export declare function SectionStateView({ state, title, description, action, className, }: SectionStateViewProps): import("react").JSX.Element;
|
|
19
|
+
/** Shimmer skeleton standing in for an in-flight section load. */
|
|
20
|
+
export declare function SectionSkeleton({ className }: {
|
|
21
|
+
className?: string;
|
|
22
|
+
}): import("react").JSX.Element;
|
|
23
|
+
/** The full set of forceable states, for fixtures and the state switcher. */
|
|
24
|
+
export declare const FORCEABLE_STATES: readonly SectionState[];
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { CircleAlert, Clock, Inbox, Loader2, Lock } from 'lucide-react';
|
|
3
|
+
import { Badge, Heading, Stack, Text } from '@elytracms/studio/ui';
|
|
4
|
+
import { cn } from '@elytracms/studio/lib/utils';
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the runtime state of a section (brief §8.1, §11). A `forced` value
|
|
7
|
+
* (e.g. from a `?state=` param) wins, making every state reachable
|
|
8
|
+
* deterministically; otherwise availability decides.
|
|
9
|
+
*/
|
|
10
|
+
export function resolveSectionState(availability, forced) {
|
|
11
|
+
if (forced)
|
|
12
|
+
return forced;
|
|
13
|
+
if (availability === 'planned')
|
|
14
|
+
return 'planned';
|
|
15
|
+
if (availability === 'unavailable')
|
|
16
|
+
return 'unavailable';
|
|
17
|
+
return 'working';
|
|
18
|
+
}
|
|
19
|
+
const PRESETS = {
|
|
20
|
+
empty: {
|
|
21
|
+
icon: Inbox,
|
|
22
|
+
title: 'Nothing here yet',
|
|
23
|
+
description: 'This section has no content for the active project.',
|
|
24
|
+
badge: { label: 'empty', variant: 'outline' },
|
|
25
|
+
},
|
|
26
|
+
loading: {
|
|
27
|
+
icon: Loader2,
|
|
28
|
+
title: 'Loading…',
|
|
29
|
+
description: 'Fetching the latest state for this section.',
|
|
30
|
+
badge: { label: 'loading', variant: 'info' },
|
|
31
|
+
spin: true,
|
|
32
|
+
},
|
|
33
|
+
error: {
|
|
34
|
+
icon: CircleAlert,
|
|
35
|
+
title: 'Something went wrong',
|
|
36
|
+
description: 'This section could not be loaded. Try again in a moment.',
|
|
37
|
+
badge: { label: 'error', variant: 'error' },
|
|
38
|
+
},
|
|
39
|
+
unavailable: {
|
|
40
|
+
icon: Lock,
|
|
41
|
+
title: 'Not available',
|
|
42
|
+
description: 'This section is not available for the active project.',
|
|
43
|
+
badge: { label: 'unavailable', variant: 'outline' },
|
|
44
|
+
},
|
|
45
|
+
planned: {
|
|
46
|
+
icon: Clock,
|
|
47
|
+
title: 'Planned',
|
|
48
|
+
description: 'This surface is planned and not yet enabled for this project.',
|
|
49
|
+
badge: { label: 'planned', variant: 'warning' },
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
/** Loading uses a skeleton; the rest use a centered placeholder. Consistent across sections. */
|
|
53
|
+
export function SectionStateView({ state, title, description, action, className, }) {
|
|
54
|
+
if (state === 'loading')
|
|
55
|
+
return _jsx(SectionSkeleton, { className: className });
|
|
56
|
+
const preset = PRESETS[state];
|
|
57
|
+
const Icon = preset.icon;
|
|
58
|
+
const tone = state === 'error'
|
|
59
|
+
? 'border-destructive/30 bg-destructive/5'
|
|
60
|
+
: state === 'planned'
|
|
61
|
+
? 'border-warning/30 bg-warning/5'
|
|
62
|
+
: 'border-border bg-card/40';
|
|
63
|
+
return (_jsx("div", { "data-section-state": state, className: cn('grid min-h-[18rem] place-items-center p-8', className), children: _jsxs(Stack, { gap: "3", align: "center", className: cn('max-w-sm rounded-xl border border-dashed px-8 py-10 text-center', tone), children: [_jsx("span", { className: "grid size-11 place-items-center rounded-lg border border-border bg-background text-muted-foreground", children: _jsx(Icon, { className: "size-5" }) }), _jsxs(Stack, { gap: "1", align: "center", children: [_jsx(Heading, { level: 2, size: "h3", children: title ?? preset.title }), _jsx(Text, { size: "sm", tone: "muted", children: description ?? preset.description })] }), _jsx(Badge, { variant: preset.badge.variant, children: preset.badge.label }), action ? _jsx("div", { className: "pt-1", children: action }) : null] }) }));
|
|
64
|
+
}
|
|
65
|
+
/** Shimmer skeleton standing in for an in-flight section load. */
|
|
66
|
+
export function SectionSkeleton({ className }) {
|
|
67
|
+
return (_jsxs("div", { "data-section-state": "loading", className: cn('space-y-4 p-6', className), "aria-busy": true, children: [_jsx("div", { className: "h-7 w-48 animate-pulse rounded-md bg-muted" }), _jsx("div", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsx("div", { className: "h-28 animate-pulse rounded-xl bg-muted/70" }, i))) })] }));
|
|
68
|
+
}
|
|
69
|
+
/** The full set of forceable states, for fixtures and the state switcher. */
|
|
70
|
+
export const FORCEABLE_STATES = [
|
|
71
|
+
'working',
|
|
72
|
+
'empty',
|
|
73
|
+
'loading',
|
|
74
|
+
'error',
|
|
75
|
+
'unavailable',
|
|
76
|
+
'planned',
|
|
77
|
+
];
|
|
78
|
+
//# sourceMappingURL=section-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section-state.js","sourceRoot":"","sources":["../../src/components/section-state.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { Project, ProjectId, SectionId, SectionState } from '@elytracms/studio-core';
|
|
3
|
+
/** Parse a `?state=` search param into a SectionState (undefined when absent/invalid). */
|
|
4
|
+
export declare function parseSectionState(raw: unknown): SectionState | undefined;
|
|
5
|
+
export interface SectionSurfaceProps {
|
|
6
|
+
project: Project;
|
|
7
|
+
section: SectionId;
|
|
8
|
+
/** Forced state from `?state=`; overrides availability. */
|
|
9
|
+
forcedState?: SectionState;
|
|
10
|
+
/** Working-state content. When omitted, a phase placeholder is shown. */
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolves a section's deterministic state (brief §8.1, §11) and renders it: the
|
|
15
|
+
* working content (or a phase placeholder) when `working`, else a consistent
|
|
16
|
+
* state view. A small state switcher makes every state reachable for inspection.
|
|
17
|
+
*/
|
|
18
|
+
export declare function SectionSurface({ project, section, forcedState, children }: SectionSurfaceProps): import("react").JSX.Element;
|
|
19
|
+
/** Placeholder for an available section whose live surface lands in a later phase. */
|
|
20
|
+
export declare function PhasePlaceholder({ section }: {
|
|
21
|
+
section: SectionId;
|
|
22
|
+
}): import("react").JSX.Element;
|
|
23
|
+
/**
|
|
24
|
+
* Deterministic state switcher (brief §11). Links to the same section with each
|
|
25
|
+
* `?state=` value so agents/humans can reproduce every state by URL or click.
|
|
26
|
+
*/
|
|
27
|
+
export declare function StateSwitcher({ projectId, section, current, }: {
|
|
28
|
+
projectId: ProjectId;
|
|
29
|
+
section: SectionId;
|
|
30
|
+
current?: SectionState;
|
|
31
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Link, STUDIO_PROJECT_ROUTE } from '@elytracms/studio/router';
|
|
3
|
+
import { ArrowUpRight } from 'lucide-react';
|
|
4
|
+
import { availabilityOf, sectionStateSchema } from '@elytracms/studio-core';
|
|
5
|
+
import { Badge, Button, Code, Row, Stack, Text } from '@elytracms/studio/ui';
|
|
6
|
+
import { cn } from '@elytracms/studio/lib/utils';
|
|
7
|
+
import { resolveSectionState, SectionStateView } from './section-state';
|
|
8
|
+
import { sectionNavItem } from './sections';
|
|
9
|
+
/** Parse a `?state=` search param into a SectionState (undefined when absent/invalid). */
|
|
10
|
+
export function parseSectionState(raw) {
|
|
11
|
+
const parsed = sectionStateSchema.safeParse(raw);
|
|
12
|
+
return parsed.success ? parsed.data : undefined;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Resolves a section's deterministic state (brief §8.1, §11) and renders it: the
|
|
16
|
+
* working content (or a phase placeholder) when `working`, else a consistent
|
|
17
|
+
* state view. A small state switcher makes every state reachable for inspection.
|
|
18
|
+
*/
|
|
19
|
+
export function SectionSurface({ project, section, forcedState, children }) {
|
|
20
|
+
const availability = availabilityOf(project.settings.sectionAvailability, section);
|
|
21
|
+
const state = resolveSectionState(availability, forcedState);
|
|
22
|
+
return (_jsxs(Stack, { gap: "none", className: "min-h-full", children: [_jsx(StateSwitcher, { projectId: project.id, section: section, current: forcedState }), state === 'working' ? ((children ?? _jsx(PhasePlaceholder, { section: section }))) : (_jsx(SectionStateView, { state: state, title: sectionNavItem(section).label }))] }));
|
|
23
|
+
}
|
|
24
|
+
/** Placeholder for an available section whose live surface lands in a later phase. */
|
|
25
|
+
export function PhasePlaceholder({ section }) {
|
|
26
|
+
const item = sectionNavItem(section);
|
|
27
|
+
const Icon = item.icon;
|
|
28
|
+
return (_jsx("div", { "data-section-state": "working", className: "grid flex-1 place-items-center p-8", children: _jsxs(Stack, { gap: "3", align: "center", className: "max-w-md text-center", children: [_jsx("span", { className: "grid size-12 place-items-center rounded-xl border border-border bg-card text-primary", children: _jsx(Icon, { className: "size-6" }) }), _jsxs(Stack, { gap: "1", align: "center", children: [_jsxs(Text, { weight: "semibold", children: [item.label, " is enabled"] }), _jsxs(Text, { size: "sm", tone: "muted", children: [item.description, " The full surface arrives in ", item.phase, "."] })] }), _jsx(Badge, { variant: "primary", children: item.phase })] }) }));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Deterministic state switcher (brief §11). Links to the same section with each
|
|
32
|
+
* `?state=` value so agents/humans can reproduce every state by URL or click.
|
|
33
|
+
*/
|
|
34
|
+
export function StateSwitcher({ projectId, section, current, }) {
|
|
35
|
+
const states = ['working', 'empty', 'loading', 'error', 'unavailable', 'planned'];
|
|
36
|
+
const activeKey = current ?? 'default';
|
|
37
|
+
return (_jsxs(Row, { gap: "1", wrap: true, className: "shrink-0 border-b border-dashed border-border/70 px-4 py-2 sm:px-6", "data-testid": "state-switcher", children: [_jsx(Text, { size: "xs", tone: "subtle", mono: true, className: "mr-1", children: "state" }), _jsx(Link, { to: STUDIO_PROJECT_ROUTE, params: { projectId, _splat: section }, search: {}, className: cn('rounded-md px-2 py-0.5 font-mono text-xs transition-colors', activeKey === 'default'
|
|
38
|
+
? 'bg-accent text-accent-foreground'
|
|
39
|
+
: 'text-muted-foreground hover:bg-muted hover:text-foreground'), children: "default" }), states.map((s) => {
|
|
40
|
+
const active = s === activeKey;
|
|
41
|
+
return (_jsx(Link, { to: STUDIO_PROJECT_ROUTE, params: { projectId, _splat: section }, search: { state: s }, className: cn('rounded-md px-2 py-0.5 font-mono text-xs transition-colors', active
|
|
42
|
+
? 'bg-accent text-accent-foreground'
|
|
43
|
+
: 'text-muted-foreground hover:bg-muted hover:text-foreground'), children: s }, s));
|
|
44
|
+
}), _jsx(Code, { tone: "muted", className: "ml-2 hidden sm:inline-flex", children: activeKey === 'default' ? 'auto' : `?state=${activeKey}` }), _jsx("span", { className: "flex-1" }), _jsx(Button, { variant: "ghost", size: "sm", asChild: true, className: "hidden md:inline-flex", children: _jsxs(Link, { to: "/", className: "gap-1", children: ["Docs ", _jsx(ArrowUpRight, {})] }) })] }));
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=section-surface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section-surface.js","sourceRoot":"","sources":["../../src/components/section-surface.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { LucideIcon } from 'lucide-react';
|
|
2
|
+
import type { Project, SectionAvailability, SectionAvailabilityMap, SectionId } from '@elytracms/studio-core';
|
|
3
|
+
/**
|
|
4
|
+
* App-level navigation ids: the studio-core sections plus surfaces registered
|
|
5
|
+
* by the app itself. `routes` (EC-170) is the first app-registered surface —
|
|
6
|
+
* it lives next to the CMS in the rail and rides on the CMS availability,
|
|
7
|
+
* since routes/redirects are CMS routing concerns (`@elytracms/cms-core`).
|
|
8
|
+
*/
|
|
9
|
+
export type StudioNavId = SectionId | 'routes';
|
|
10
|
+
export interface SectionNavItem {
|
|
11
|
+
id: StudioNavId;
|
|
12
|
+
label: string;
|
|
13
|
+
description: string;
|
|
14
|
+
icon: LucideIcon;
|
|
15
|
+
phase: string;
|
|
16
|
+
}
|
|
17
|
+
/** Navigation items in canonical order (brief §8.1 + EC-170). */
|
|
18
|
+
export declare const SECTION_NAV_ITEMS: readonly SectionNavItem[];
|
|
19
|
+
export declare function sectionNavItem(id: StudioNavId): SectionNavItem;
|
|
20
|
+
/**
|
|
21
|
+
* Availability for a nav id. App-registered surfaces map onto the section
|
|
22
|
+
* whose data they manage: Routes follows the CMS availability.
|
|
23
|
+
*/
|
|
24
|
+
export declare function navAvailabilityOf(map: SectionAvailabilityMap, id: StudioNavId): SectionAvailability;
|
|
25
|
+
/**
|
|
26
|
+
* The section a project should open to: the first non-`unavailable` section in
|
|
27
|
+
* canonical order. Settings is always available, so this never returns null.
|
|
28
|
+
*/
|
|
29
|
+
export declare function firstAvailableSection(project: Project): SectionId;
|
|
30
|
+
/**
|
|
31
|
+
* Parse the active nav id out of a studio pathname `/$projectId/<section>[/...]`
|
|
32
|
+
* (incl. the app-registered Routes surface, EC-170). Returns null for the bare
|
|
33
|
+
* project URL or an unknown segment. The section is the SECOND path segment —
|
|
34
|
+
* directly after the projectId; there is no `/p` prefix (EC-220). The single
|
|
35
|
+
* source of truth for active-section detection: the shell breadcrumb and the
|
|
36
|
+
* nav rail both read it, so the segment index lives in exactly one place.
|
|
37
|
+
*/
|
|
38
|
+
export declare function activeSectionFromPath(pathname: string): StudioNavId | null;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Blocks, Database, Image, Puzzle, Settings, Signpost } from 'lucide-react';
|
|
2
|
+
import { SECTIONS, SECTION_IDS, availabilityOf, sectionIdSchema } from '@elytracms/studio-core';
|
|
3
|
+
/** Which Studio phase delivers each section's live surface (for placeholders). */
|
|
4
|
+
const SECTION_PHASE = {
|
|
5
|
+
components: 'Phase 4',
|
|
6
|
+
cms: 'Phase 6',
|
|
7
|
+
routes: 'Milestone B',
|
|
8
|
+
assets: 'Phase 6',
|
|
9
|
+
extensions: 'Phase 11',
|
|
10
|
+
settings: 'Phase 2',
|
|
11
|
+
};
|
|
12
|
+
const ICONS = {
|
|
13
|
+
components: Blocks,
|
|
14
|
+
cms: Database,
|
|
15
|
+
routes: Signpost,
|
|
16
|
+
assets: Image,
|
|
17
|
+
extensions: Puzzle,
|
|
18
|
+
settings: Settings,
|
|
19
|
+
};
|
|
20
|
+
/** Descriptor for the app-registered Routes surface (EC-170). */
|
|
21
|
+
const ROUTES_DESCRIPTOR = {
|
|
22
|
+
id: 'routes',
|
|
23
|
+
label: 'Routes',
|
|
24
|
+
description: 'View the resolved URL routes & redirects (defined in elytra.config.ts).',
|
|
25
|
+
};
|
|
26
|
+
/** Canonical nav order: studio-core order with Routes slotted after CMS. */
|
|
27
|
+
const NAV_IDS = SECTION_IDS.flatMap((id) => id === 'cms' ? [id, 'routes'] : [id]);
|
|
28
|
+
function descriptorOf(id) {
|
|
29
|
+
return id === 'routes' ? ROUTES_DESCRIPTOR : SECTIONS[id];
|
|
30
|
+
}
|
|
31
|
+
/** Navigation items in canonical order (brief §8.1 + EC-170). */
|
|
32
|
+
export const SECTION_NAV_ITEMS = NAV_IDS.map((id) => ({
|
|
33
|
+
id,
|
|
34
|
+
label: descriptorOf(id).label,
|
|
35
|
+
description: descriptorOf(id).description,
|
|
36
|
+
icon: ICONS[id],
|
|
37
|
+
phase: SECTION_PHASE[id],
|
|
38
|
+
}));
|
|
39
|
+
export function sectionNavItem(id) {
|
|
40
|
+
return SECTION_NAV_ITEMS.find((item) => item.id === id);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Availability for a nav id. App-registered surfaces map onto the section
|
|
44
|
+
* whose data they manage: Routes follows the CMS availability.
|
|
45
|
+
*/
|
|
46
|
+
export function navAvailabilityOf(map, id) {
|
|
47
|
+
return availabilityOf(map, id === 'routes' ? 'cms' : id);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The section a project should open to: the first non-`unavailable` section in
|
|
51
|
+
* canonical order. Settings is always available, so this never returns null.
|
|
52
|
+
*/
|
|
53
|
+
export function firstAvailableSection(project) {
|
|
54
|
+
const found = SECTION_IDS.find((id) => availabilityOf(project.settings.sectionAvailability, id) !== 'unavailable');
|
|
55
|
+
return found ?? 'settings';
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Parse the active nav id out of a studio pathname `/$projectId/<section>[/...]`
|
|
59
|
+
* (incl. the app-registered Routes surface, EC-170). Returns null for the bare
|
|
60
|
+
* project URL or an unknown segment. The section is the SECOND path segment —
|
|
61
|
+
* directly after the projectId; there is no `/p` prefix (EC-220). The single
|
|
62
|
+
* source of truth for active-section detection: the shell breadcrumb and the
|
|
63
|
+
* nav rail both read it, so the segment index lives in exactly one place.
|
|
64
|
+
*/
|
|
65
|
+
export function activeSectionFromPath(pathname) {
|
|
66
|
+
const segment = pathname.split('/')[2] ?? '';
|
|
67
|
+
if (segment === 'routes')
|
|
68
|
+
return 'routes';
|
|
69
|
+
const parsed = sectionIdSchema.safeParse(segment);
|
|
70
|
+
return parsed.success ? parsed.data : null;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=sections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sections.js","sourceRoot":"","sources":["../../src/components/sections.ts"],"names":[],"mappings":"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"}
|