@elytracms/studio 0.0.93 → 0.0.94
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/convex/analytics-cost.test.ts +817 -0
- package/convex/auth.ts +5 -2
- package/convex/authority.ts +35 -11
- package/convex/contract-parity.test.ts +7 -0
- package/convex/delivery.ts +12 -9
- package/convex/guard.ts +9 -7
- package/convex/http-routes.test.ts +18 -8
- package/convex/http.ts +23 -17
- package/convex/ingest.test.ts +326 -0
- package/convex/ingest.ts +281 -0
- package/convex/invites.ts +13 -5
- package/convex/members.ts +10 -4
- package/convex/record-functions.ts +325 -0
- package/convex/records.test.ts +156 -0
- package/convex/redirect-migration.test.ts +205 -0
- package/convex/redirect-revalidate.test.ts +5 -1
- package/convex/redirects.ts +120 -79
- package/convex/role-policy.test.ts +315 -0
- package/convex/roles.ts +83 -0
- package/convex/schema.ts +30 -0
- package/convex/triggers.ts +21 -1
- package/dist/addon.d.ts +71 -0
- package/dist/addon.js +67 -0
- package/dist/addon.js.map +1 -0
- package/dist/components/account/account-settings.js +2 -2
- package/dist/components/account/account-settings.js.map +1 -1
- package/dist/components/account/credential-panel.js +2 -2
- package/dist/components/account/credential-panel.js.map +1 -1
- package/dist/components/account/self-account-schema.d.ts +6 -15
- package/dist/components/account/self-account-schema.js +52 -34
- package/dist/components/account/self-account-schema.js.map +1 -1
- package/dist/components/account/self-account-view-source.d.ts +1 -1
- package/dist/components/account/self-account-view-source.js +6 -4
- package/dist/components/account/self-account-view-source.js.map +1 -1
- package/dist/components/ai/ai-chat-panel-lazy.js +1 -1
- package/dist/components/ai/ai-chat-panel-lazy.js.map +1 -1
- package/dist/components/ai/ai-chat-panel.js +6 -6
- package/dist/components/ai/ai-chat-panel.js.map +1 -1
- package/dist/components/ai/ai-cms-panel.js +2 -2
- package/dist/components/ai/ai-cms-panel.js.map +1 -1
- package/dist/components/ai/ai-panel-toggle.js +4 -4
- package/dist/components/ai/ai-panel-toggle.js.map +1 -1
- package/dist/components/ai/chat-ui.js +2 -2
- package/dist/components/ai/chat-ui.js.map +1 -1
- package/dist/components/ai/proposal-card.d.ts +2 -2
- package/dist/components/ai/proposal-card.js +2 -2
- package/dist/components/ai/proposal-card.js.map +1 -1
- package/dist/components/ai/proposal-issues.js +2 -2
- package/dist/components/ai/proposal-issues.js.map +1 -1
- package/dist/components/ai/translate-document-action.js +2 -2
- package/dist/components/ai/translate-document-action.js.map +1 -1
- package/dist/components/ai/translate-document-dialog.js +6 -6
- package/dist/components/ai/translate-document-dialog.js.map +1 -1
- package/dist/components/ai/translate-skipped.d.ts +1 -1
- package/dist/components/ai/translate-skipped.js +2 -2
- package/dist/components/ai/translate-skipped.js.map +1 -1
- package/dist/components/app-views/default-modules.d.ts +50 -2
- package/dist/components/app-views/default-modules.js +65 -20
- package/dist/components/app-views/default-modules.js.map +1 -1
- package/dist/components/app-views/module.d.ts +53 -3
- package/dist/components/app-views/module.js +14 -7
- package/dist/components/app-views/module.js.map +1 -1
- package/dist/components/app-views/sidebar.js +1 -1
- package/dist/components/app-views/sidebar.js.map +1 -1
- package/dist/components/app-views/studio-config.d.ts +11 -2
- package/dist/components/app-views/studio-config.js.map +1 -1
- package/dist/components/assets/asset-detail.js +2 -2
- package/dist/components/assets/asset-detail.js.map +1 -1
- package/dist/components/assets/asset-grid.js +2 -2
- package/dist/components/assets/asset-grid.js.map +1 -1
- package/dist/components/assets/asset-thumb.js +3 -3
- package/dist/components/assets/asset-thumb.js.map +1 -1
- package/dist/components/assets/assets-collection-view-source.d.ts +2 -2
- package/dist/components/assets/assets-collection-view-source.js.map +1 -1
- package/dist/components/assets/assets-module.js +1 -1
- package/dist/components/assets/assets-module.js.map +1 -1
- package/dist/components/assets/assets-store.d.ts +2 -2
- package/dist/components/assets/assets-store.js +6 -6
- package/dist/components/assets/assets-store.js.map +1 -1
- package/dist/components/assets/assets-view-preference.js +1 -1
- package/dist/components/assets/assets-view-preference.js.map +1 -1
- package/dist/components/assets/replace-file.js +1 -1
- package/dist/components/assets/replace-file.js.map +1 -1
- package/dist/components/auth-context.d.ts +1 -1
- package/dist/components/auth-context.js +6 -6
- package/dist/components/auth-context.js.map +1 -1
- package/dist/components/builder/blocks-model.d.ts +1 -1
- package/dist/components/builder/blocks-model.js +3 -3
- package/dist/components/builder/blocks-model.js.map +1 -1
- package/dist/components/builder/blocks-panel.d.ts +1 -1
- package/dist/components/builder/blocks-panel.js +4 -4
- package/dist/components/builder/blocks-panel.js.map +1 -1
- package/dist/components/builder/builder-store.js +2 -2
- package/dist/components/builder/builder-store.js.map +1 -1
- package/dist/components/builder/canvas-breakpoints.js +1 -1
- package/dist/components/builder/canvas-breakpoints.js.map +1 -1
- package/dist/components/builder/canvas-dnd.d.ts +2 -2
- package/dist/components/builder/canvas-dnd.js +1 -1
- package/dist/components/builder/canvas-dnd.js.map +1 -1
- package/dist/components/builder/canvas-inline-editing.d.ts +1 -1
- package/dist/components/builder/canvas-inline-editing.js.map +1 -1
- package/dist/components/builder/canvas-overlay-geometry.d.ts +1 -1
- package/dist/components/builder/canvas-overlay-geometry.js.map +1 -1
- package/dist/components/builder/canvas-render-context.d.ts +1 -1
- package/dist/components/builder/canvas-render-context.js +4 -4
- package/dist/components/builder/canvas-render-context.js.map +1 -1
- package/dist/components/builder/canvas-theme-notice.js +2 -2
- package/dist/components/builder/canvas-theme-notice.js.map +1 -1
- package/dist/components/builder/canvas.js +3 -3
- package/dist/components/builder/canvas.js.map +1 -1
- package/dist/components/builder/clipboard-actions.d.ts +2 -2
- package/dist/components/builder/clipboard-actions.js +4 -4
- package/dist/components/builder/clipboard-actions.js.map +1 -1
- package/dist/components/builder/composition-field-editor-lazy.js +1 -1
- package/dist/components/builder/composition-field-editor-lazy.js.map +1 -1
- package/dist/components/builder/composition-field-editor.d.ts +1 -1
- package/dist/components/builder/composition-field-editor.js +3 -3
- package/dist/components/builder/composition-field-editor.js.map +1 -1
- package/dist/components/builder/drag-session.d.ts +1 -1
- package/dist/components/builder/drag-session.js.map +1 -1
- package/dist/components/builder/fixture-thumbnail.js +1 -1
- package/dist/components/builder/fixture-thumbnail.js.map +1 -1
- package/dist/components/builder/insert-context.d.ts +1 -1
- package/dist/components/builder/insert-context.js +3 -3
- package/dist/components/builder/insert-context.js.map +1 -1
- package/dist/components/builder/layout-inspector.js +1 -1
- package/dist/components/builder/layout-inspector.js.map +1 -1
- package/dist/components/builder/node-title.js +1 -1
- package/dist/components/builder/node-title.js.map +1 -1
- package/dist/components/builder/page-tree.d.ts +1 -1
- package/dist/components/builder/page-tree.js +5 -5
- package/dist/components/builder/page-tree.js.map +1 -1
- package/dist/components/builder/placement-refusal.js +3 -3
- package/dist/components/builder/placement-refusal.js.map +1 -1
- package/dist/components/builder/property-inspector.js +4 -4
- package/dist/components/builder/property-inspector.js.map +1 -1
- package/dist/components/builder/reuse-context.js +4 -4
- package/dist/components/builder/reuse-context.js.map +1 -1
- package/dist/components/builder/reuse.js +1 -1
- package/dist/components/builder/reuse.js.map +1 -1
- package/dist/components/builder/rich-text-toolbar.js +1 -1
- package/dist/components/builder/rich-text-toolbar.js.map +1 -1
- package/dist/components/builder/run-inspector.js +1 -1
- package/dist/components/builder/run-inspector.js.map +1 -1
- package/dist/components/builder/selection-overlay.js +3 -3
- package/dist/components/builder/selection-overlay.js.map +1 -1
- package/dist/components/builder/spacing-handles.d.ts +2 -2
- package/dist/components/builder/spacing-handles.js +3 -3
- package/dist/components/builder/spacing-handles.js.map +1 -1
- package/dist/components/cms/asset-field.js +2 -2
- package/dist/components/cms/asset-field.js.map +1 -1
- package/dist/components/cms/asset-picker.js +2 -2
- package/dist/components/cms/asset-picker.js.map +1 -1
- package/dist/components/cms/bulk-actions.d.ts +1 -1
- package/dist/components/cms/bulk-actions.js +2 -2
- package/dist/components/cms/bulk-actions.js.map +1 -1
- package/dist/components/cms/bulk-bar.d.ts +2 -2
- package/dist/components/cms/bulk-bar.js +2 -2
- package/dist/components/cms/bulk-bar.js.map +1 -1
- package/dist/components/cms/cell-edit.d.ts +1 -1
- package/dist/components/cms/cell-edit.js +1 -1
- package/dist/components/cms/cell-edit.js.map +1 -1
- package/dist/components/cms/cell.d.ts +1 -1
- package/dist/components/cms/cell.js +3 -3
- package/dist/components/cms/cell.js.map +1 -1
- package/dist/components/cms/cms-index.js +2 -2
- package/dist/components/cms/cms-index.js.map +1 -1
- package/dist/components/cms/cms-labels.js +2 -2
- package/dist/components/cms/cms-labels.js.map +1 -1
- package/dist/components/cms/cms-store.d.ts +2 -2
- package/dist/components/cms/cms-store.js +10 -10
- package/dist/components/cms/cms-store.js.map +1 -1
- package/dist/components/cms/collection-table.js +7 -7
- package/dist/components/cms/collection-table.js.map +1 -1
- package/dist/components/cms/detail-editor.d.ts +5 -2
- package/dist/components/cms/detail-editor.js +20 -14
- package/dist/components/cms/detail-editor.js.map +1 -1
- package/dist/components/cms/details-pane.js +1 -1
- package/dist/components/cms/details-pane.js.map +1 -1
- package/dist/components/cms/doc-state.js +1 -1
- package/dist/components/cms/doc-state.js.map +1 -1
- package/dist/components/cms/document-diff-view.js +5 -5
- package/dist/components/cms/document-diff-view.js.map +1 -1
- package/dist/components/cms/document-editor-context.js +1 -1
- package/dist/components/cms/document-editor-context.js.map +1 -1
- package/dist/components/cms/document-staging.js +1 -1
- package/dist/components/cms/document-staging.js.map +1 -1
- package/dist/components/cms/document-url-path.js +2 -2
- package/dist/components/cms/document-url-path.js.map +1 -1
- package/dist/components/cms/duplicate-document.d.ts +1 -1
- package/dist/components/cms/duplicate-document.js.map +1 -1
- package/dist/components/cms/editable-cell.js +3 -3
- package/dist/components/cms/editable-cell.js.map +1 -1
- package/dist/components/cms/field-collaboration.d.ts +1 -1
- package/dist/components/cms/field-collaboration.js +1 -1
- package/dist/components/cms/field-collaboration.js.map +1 -1
- package/dist/components/cms/field-connection.d.ts +1 -1
- package/dist/components/cms/field-connection.js +2 -2
- package/dist/components/cms/field-connection.js.map +1 -1
- package/dist/components/cms/field-control-lib.js +1 -1
- package/dist/components/cms/field-control-lib.js.map +1 -1
- package/dist/components/cms/field-control.js +4 -4
- package/dist/components/cms/field-control.js.map +1 -1
- package/dist/components/cms/field-renderer.d.ts +1 -1
- package/dist/components/cms/field-renderer.js +2 -2
- package/dist/components/cms/field-renderer.js.map +1 -1
- package/dist/components/cms/filter-builder.d.ts +1 -1
- package/dist/components/cms/filter-builder.js +3 -3
- package/dist/components/cms/filter-builder.js.map +1 -1
- package/dist/components/cms/gate-validation.js +1 -1
- package/dist/components/cms/gate-validation.js.map +1 -1
- package/dist/components/cms/import-export.js +2 -2
- package/dist/components/cms/import-export.js.map +1 -1
- package/dist/components/cms/issue-copy.js +1 -1
- package/dist/components/cms/issue-copy.js.map +1 -1
- package/dist/components/cms/issues-pane.js +3 -3
- package/dist/components/cms/issues-pane.js.map +1 -1
- package/dist/components/cms/object-array-field.js +2 -2
- package/dist/components/cms/object-array-field.js.map +1 -1
- package/dist/components/cms/prop-fields.js +2 -2
- package/dist/components/cms/prop-fields.js.map +1 -1
- package/dist/components/cms/reference-confirm.d.ts +1 -1
- package/dist/components/cms/reference-confirm.js +2 -2
- package/dist/components/cms/reference-confirm.js.map +1 -1
- package/dist/components/cms/relation-picker.js +2 -2
- package/dist/components/cms/relation-picker.js.map +1 -1
- package/dist/components/cms/rich-text/block-style.js +1 -1
- package/dist/components/cms/rich-text/block-style.js.map +1 -1
- package/dist/components/cms/rich-text/component-embed.js +4 -4
- package/dist/components/cms/rich-text/component-embed.js.map +1 -1
- package/dist/components/cms/rich-text/editor.js +3 -3
- package/dist/components/cms/rich-text/editor.js.map +1 -1
- package/dist/components/cms/rich-text/embed-picker.js +3 -3
- package/dist/components/cms/rich-text/embed-picker.js.map +1 -1
- package/dist/components/cms/rich-text/embed-props.js +3 -3
- package/dist/components/cms/rich-text/embed-props.js.map +1 -1
- package/dist/components/cms/rich-text/extensions.js +1 -1
- package/dist/components/cms/rich-text/extensions.js.map +1 -1
- package/dist/components/cms/rich-text/font-size-control.d.ts +1 -1
- package/dist/components/cms/rich-text/font-size-control.js +2 -2
- package/dist/components/cms/rich-text/font-size-control.js.map +1 -1
- package/dist/components/cms/rich-text/lazy.js +1 -1
- package/dist/components/cms/rich-text/lazy.js.map +1 -1
- package/dist/components/cms/rich-text/link-control.js +2 -2
- package/dist/components/cms/rich-text/link-control.js.map +1 -1
- package/dist/components/cms/rich-text/slash-command.js +3 -3
- package/dist/components/cms/rich-text/slash-command.js.map +1 -1
- package/dist/components/cms/rich-text/toolbar.js +1 -1
- package/dist/components/cms/rich-text/toolbar.js.map +1 -1
- package/dist/components/cms/rich-text/unknown-node.js +2 -2
- package/dist/components/cms/rich-text/unknown-node.js.map +1 -1
- package/dist/components/cms/rich-text-preview.js +2 -2
- package/dist/components/cms/rich-text-preview.js.map +1 -1
- package/dist/components/cms/row-actions.d.ts +1 -1
- package/dist/components/cms/row-actions.js.map +1 -1
- package/dist/components/cms/scalar-value-editor.d.ts +1 -1
- package/dist/components/cms/scalar-value-editor.js +2 -2
- package/dist/components/cms/scalar-value-editor.js.map +1 -1
- package/dist/components/cms/use-discard-controller.d.ts +1 -1
- package/dist/components/cms/use-discard-controller.js +1 -1
- package/dist/components/cms/use-discard-controller.js.map +1 -1
- package/dist/components/cms/use-document-draft.d.ts +7 -1
- package/dist/components/cms/use-document-draft.js +16 -2
- package/dist/components/cms/use-document-draft.js.map +1 -1
- package/dist/components/cms/use-document-versions.js +1 -1
- package/dist/components/cms/use-document-versions.js.map +1 -1
- package/dist/components/cms/use-field-focus.d.ts +1 -1
- package/dist/components/cms/use-field-focus.js +2 -2
- package/dist/components/cms/use-field-focus.js.map +1 -1
- package/dist/components/cms/use-live-url.d.ts +1 -1
- package/dist/components/cms/use-live-url.js +3 -3
- package/dist/components/cms/use-live-url.js.map +1 -1
- package/dist/components/cms/use-publish-controller.d.ts +1 -1
- package/dist/components/cms/use-publish-controller.js +1 -1
- package/dist/components/cms/use-publish-controller.js.map +1 -1
- package/dist/components/cms/use-published-perspective.d.ts +1 -1
- package/dist/components/cms/use-published-perspective.js.map +1 -1
- package/dist/components/cms/use-restore-version.d.ts +1 -1
- package/dist/components/cms/use-restore-version.js +1 -1
- package/dist/components/cms/use-restore-version.js.map +1 -1
- package/dist/components/cms/version-compare-lazy.js +1 -1
- package/dist/components/cms/version-compare-lazy.js.map +1 -1
- package/dist/components/cms/version-compare.js +1 -1
- package/dist/components/cms/version-compare.js.map +1 -1
- package/dist/components/cms/versions-pane.js +3 -3
- package/dist/components/cms/versions-pane.js.map +1 -1
- package/dist/components/cms/view-bar.js +3 -3
- package/dist/components/cms/view-bar.js.map +1 -1
- package/dist/components/collection-view/cms-collection-view-source.d.ts +1 -1
- package/dist/components/collection-view/cms-collection-view-source.js +2 -2
- package/dist/components/collection-view/cms-collection-view-source.js.map +1 -1
- package/dist/components/collection-view/collection-view-context.d.ts +1 -1
- package/dist/components/collection-view/collection-view-context.js +1 -1
- package/dist/components/collection-view/collection-view-context.js.map +1 -1
- package/dist/components/collection-view/collection-view-surface.d.ts +13 -0
- package/dist/components/collection-view/collection-view-surface.js +18 -0
- package/dist/components/collection-view/collection-view-surface.js.map +1 -0
- package/dist/components/components/component-detail.js +10 -10
- package/dist/components/components/component-detail.js.map +1 -1
- package/dist/components/components/component-preview.d.ts +2 -2
- package/dist/components/components/component-preview.js +5 -5
- package/dist/components/components/component-preview.js.map +1 -1
- package/dist/components/components/component-status.d.ts +1 -1
- package/dist/components/components/component-status.js +1 -1
- package/dist/components/components/component-status.js.map +1 -1
- package/dist/components/components/components-index.js +2 -2
- package/dist/components/components/components-index.js.map +1 -1
- package/dist/components/components/field-inspector.js +1 -1
- package/dist/components/components/field-inspector.js.map +1 -1
- package/dist/components/components/registry-browser.js +3 -3
- package/dist/components/components/registry-browser.js.map +1 -1
- package/dist/components/components/taxonomy.d.ts +1 -1
- package/dist/components/components/taxonomy.js.map +1 -1
- package/dist/components/components/transfer-dialog.js +3 -3
- package/dist/components/components/transfer-dialog.js.map +1 -1
- package/dist/components/current-user-menu.js +1 -1
- package/dist/components/current-user-menu.js.map +1 -1
- package/dist/components/delivery-health-banner.js +2 -2
- package/dist/components/delivery-health-banner.js.map +1 -1
- package/dist/components/deployment-setup-gate.js +3 -3
- package/dist/components/deployment-setup-gate.js.map +1 -1
- package/dist/components/dev-login-badge.js +2 -2
- package/dist/components/dev-login-badge.js.map +1 -1
- package/dist/components/guards.js +1 -1
- package/dist/components/guards.js.map +1 -1
- package/dist/components/inspector/document-panes.d.ts +54 -0
- package/dist/components/inspector/document-panes.js +41 -0
- package/dist/components/inspector/document-panes.js.map +1 -0
- package/dist/components/inspector/inspector-sidebar.js +1 -1
- package/dist/components/inspector/inspector-sidebar.js.map +1 -1
- package/dist/components/nav-issues-registry.d.ts +53 -0
- package/dist/components/nav-issues-registry.js +69 -0
- package/dist/components/nav-issues-registry.js.map +1 -0
- package/dist/components/nav-issues.js +4 -4
- package/dist/components/nav-issues.js.map +1 -1
- package/dist/components/operation-error.d.ts +1 -1
- package/dist/components/operation-error.js +4 -4
- package/dist/components/operation-error.js.map +1 -1
- package/dist/components/playground-badge.js +2 -2
- package/dist/components/playground-badge.js.map +1 -1
- package/dist/components/project-list.js +3 -3
- package/dist/components/project-list.js.map +1 -1
- package/dist/components/project-session.d.ts +2 -2
- package/dist/components/project-session.js +5 -5
- package/dist/components/project-session.js.map +1 -1
- package/dist/components/project-switcher.js +2 -2
- package/dist/components/project-switcher.js.map +1 -1
- package/dist/components/rail-store-status.js +1 -1
- package/dist/components/rail-store-status.js.map +1 -1
- package/dist/components/rail-view-source.d.ts +6 -5
- package/dist/components/rail-view-source.js +4 -3
- package/dist/components/rail-view-source.js.map +1 -1
- package/dist/components/records/record-lens.d.ts +51 -0
- package/dist/components/records/record-lens.js +156 -0
- package/dist/components/records/record-lens.js.map +1 -0
- package/dist/components/records/record-rail.d.ts +86 -0
- package/dist/components/records/record-rail.js +241 -0
- package/dist/components/records/record-rail.js.map +1 -0
- package/dist/components/redirects/redirects-schema.js +1 -1
- package/dist/components/redirects/redirects-schema.js.map +1 -1
- package/dist/components/references/references-panel.js +2 -2
- package/dist/components/references/references-panel.js.map +1 -1
- package/dist/components/section-nav.js +27 -11
- package/dist/components/section-nav.js.map +1 -1
- package/dist/components/section-state.js +2 -2
- package/dist/components/section-state.js.map +1 -1
- package/dist/components/section-surface.js +2 -2
- package/dist/components/section-surface.js.map +1 -1
- package/dist/components/session-expired-overlay.js +3 -3
- package/dist/components/session-expired-overlay.js.map +1 -1
- package/dist/components/settings-form.js +1 -1
- package/dist/components/settings-form.js.map +1 -1
- package/dist/components/sign-in-needed-badge.js +1 -1
- package/dist/components/sign-in-needed-badge.js.map +1 -1
- package/dist/components/sign-in-view.d.ts +2 -2
- package/dist/components/sign-in-view.js +5 -5
- package/dist/components/sign-in-view.js.map +1 -1
- package/dist/components/studio-context.js +3 -3
- package/dist/components/studio-context.js.map +1 -1
- package/dist/components/studio-project-screen.js +30 -3
- package/dist/components/studio-project-screen.js.map +1 -1
- package/dist/components/studio-shell.js +6 -5
- package/dist/components/studio-shell.js.map +1 -1
- package/dist/components/theme-context.d.ts +1 -1
- package/dist/components/theme-context.js +2 -2
- package/dist/components/theme-context.js.map +1 -1
- package/dist/components/use-hydration-phase.d.ts +1 -1
- package/dist/components/use-hydration-phase.js +1 -1
- package/dist/components/use-hydration-phase.js.map +1 -1
- package/dist/components/users/invite-user-bar.d.ts +27 -0
- package/dist/components/users/invite-user-bar.js +25 -9
- package/dist/components/users/invite-user-bar.js.map +1 -1
- package/dist/components/users/role-policy-drift-issues.d.ts +38 -0
- package/dist/components/users/role-policy-drift-issues.js +71 -0
- package/dist/components/users/role-policy-drift-issues.js.map +1 -0
- package/dist/components/users/users-collection-view-source.d.ts +1 -1
- package/dist/components/users/users-collection-view-source.js +4 -2
- package/dist/components/users/users-collection-view-source.js.map +1 -1
- package/dist/components/users/users-module.js +1 -1
- package/dist/components/users/users-module.js.map +1 -1
- package/dist/components/users/users-schema.d.ts +10 -1
- package/dist/components/users/users-schema.js +45 -25
- package/dist/components/users/users-schema.js.map +1 -1
- package/dist/components/users/users-store.js +3 -3
- package/dist/components/users/users-store.js.map +1 -1
- package/dist/components/workspace-projects.d.ts +1 -1
- package/dist/components/workspace-projects.js +1 -1
- package/dist/components/workspace-projects.js.map +1 -1
- package/dist/lib/ai/index.d.ts +1 -1
- package/dist/lib/ai/index.js +1 -1
- package/dist/lib/ai/index.js.map +1 -1
- package/dist/lib/ai/node-handler.d.ts +1 -1
- package/dist/lib/ai/node-handler.js.map +1 -1
- package/dist/lib/ai/translate-document.js +1 -1
- package/dist/lib/ai/translate-document.js.map +1 -1
- package/dist/lib/clipboard/paste-issues.js +1 -1
- package/dist/lib/clipboard/paste-issues.js.map +1 -1
- package/dist/lib/clipboard/paste-target.js +2 -2
- package/dist/lib/clipboard/paste-target.js.map +1 -1
- package/dist/lib/cms/published-documents.js +1 -1
- package/dist/lib/cms/published-documents.js.map +1 -1
- package/dist/lib/cms-views/view-model.d.ts +12 -12
- package/dist/lib/cms-views/view-model.js +2 -2
- package/dist/lib/cms-views/view-model.js.map +1 -1
- package/dist/lib/collection-view/collection-view-source.d.ts +7 -2
- package/dist/lib/collection-view/collection-view-source.js.map +1 -1
- package/dist/lib/data/content-session-refresh.d.ts +1 -1
- package/dist/lib/data/content-session-refresh.js.map +1 -1
- package/dist/lib/data/playground-unload-guard.d.ts +1 -1
- package/dist/lib/data/playground-unload-guard.js +1 -1
- package/dist/lib/data/playground-unload-guard.js.map +1 -1
- package/dist/lib/engine-version.d.ts +1 -1
- package/dist/lib/engine-version.js +1 -1
- package/dist/lib/engine-version.js.map +1 -1
- package/dist/lib/i18n/i18n.js +1 -1
- package/dist/lib/i18n/i18n.js.map +1 -1
- package/dist/lib/i18n/messages.de.js +4 -0
- package/dist/lib/i18n/messages.de.js.map +1 -1
- package/dist/lib/i18n/messages.en.d.ts +4 -0
- package/dist/lib/i18n/messages.en.js +8 -0
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/operations/project-runtime-config.d.ts +9 -0
- package/dist/lib/operations/project-runtime-config.js +13 -0
- package/dist/lib/operations/project-runtime-config.js.map +1 -1
- package/dist/lib/operations/studio-operations.d.ts +9 -1
- package/dist/lib/operations/studio-operations.js +6 -1
- package/dist/lib/operations/studio-operations.js.map +1 -1
- package/dist/lib/persistence/convex-adapter.d.ts +16 -3
- package/dist/lib/persistence/convex-adapter.js +78 -47
- package/dist/lib/persistence/convex-adapter.js.map +1 -1
- package/dist/lib/persistence/index.js +14 -1
- package/dist/lib/persistence/index.js.map +1 -1
- package/dist/lib/persona/labels.js +1 -1
- package/dist/lib/persona/labels.js.map +1 -1
- package/dist/lib/query/operations-query.d.ts +1 -1
- package/dist/lib/query/operations-query.js +1 -1
- package/dist/lib/query/operations-query.js.map +1 -1
- package/dist/lib/references/reference-model.js +1 -1
- package/dist/lib/references/reference-model.js.map +1 -1
- package/dist/lib/references/references-store.js +1 -1
- package/dist/lib/references/references-store.js.map +1 -1
- package/dist/lib/workspace/index.d.ts +6 -0
- package/dist/lib/workspace/index.js +8 -0
- package/dist/lib/workspace/index.js.map +1 -1
- package/dist/mount.d.ts +28 -0
- package/dist/mount.js +27 -0
- package/dist/mount.js.map +1 -0
- package/dist/router/root.js +10 -10
- package/dist/router/root.js.map +1 -1
- package/dist/ui/badge.d.ts +1 -1
- package/dist/ui/button.d.ts +2 -2
- package/package.json +15 -11
- package/dist/components/redirects/redirects-collection-view-source.d.ts +0 -53
- package/dist/components/redirects/redirects-collection-view-source.js +0 -146
- package/dist/components/redirects/redirects-collection-view-source.js.map +0 -1
- package/dist/components/redirects/redirects-module.d.ts +0 -21
- package/dist/components/redirects/redirects-module.js +0 -40
- package/dist/components/redirects/redirects-module.js.map +0 -1
- package/dist/components/redirects/redirects-store.d.ts +0 -68
- package/dist/components/redirects/redirects-store.js +0 -132
- package/dist/components/redirects/redirects-store.js.map +0 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { CollectionViewProvider } from './collection-view-context.js';
|
|
3
|
+
import { LoadedCollectionTable } from '../cms/collection-table.js';
|
|
4
|
+
import { PortableDetailEditor } from '../cms/detail-editor.js';
|
|
5
|
+
/**
|
|
6
|
+
* EC-616 — the portable list/edit surfaces (AD-19) over ANY `CollectionViewSource`: the
|
|
7
|
+
* list, or — with a `documentId` — that record's detail in the portable edit shell. What
|
|
8
|
+
* every rail renders (assets, users, the record rails), exported through the addon entry
|
|
9
|
+
* so an addon with its own source (`useRailViewSource`) renders it the same way.
|
|
10
|
+
*/
|
|
11
|
+
export function CollectionViewSurface({ source, projectId, documentId = null, }) {
|
|
12
|
+
// The edit shell mounts its own CollectionViewProvider, so only the list wraps here.
|
|
13
|
+
if (documentId !== null) {
|
|
14
|
+
return _jsx(PortableDetailEditor, { source: source, projectId: projectId, documentId: documentId });
|
|
15
|
+
}
|
|
16
|
+
return (_jsx(CollectionViewProvider, { source: source, children: _jsx(LoadedCollectionTable, { projectId: projectId }) }));
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=collection-view-surface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-view-surface.js","sourceRoot":"","sources":["../../../src/components/collection-view/collection-view-surface.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAE3D;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,EACpC,MAAM,EACN,SAAS,EACT,UAAU,GAAG,IAAI,GAMlB;IACC,qFAAqF;IACrF,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,OAAO,KAAC,oBAAoB,IAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,GAAI,CAAA;IAC/F,CAAC;IACD,OAAO,CACL,KAAC,sBAAsB,IAAC,MAAM,EAAE,MAAM,YACpC,KAAC,qBAAqB,IAAC,SAAS,EAAE,SAAS,GAAI,GACxB,CAC1B,CAAA;AACH,CAAC","sourcesContent":["import type { CollectionViewSource } from '../../lib/collection-view/collection-view-source'\nimport { CollectionViewProvider } from './collection-view-context'\nimport { LoadedCollectionTable } from '../cms/collection-table'\nimport { PortableDetailEditor } from '../cms/detail-editor'\n\n/**\n * EC-616 — the portable list/edit surfaces (AD-19) over ANY `CollectionViewSource`: the\n * list, or — with a `documentId` — that record's detail in the portable edit shell. What\n * every rail renders (assets, users, the record rails), exported through the addon entry\n * so an addon with its own source (`useRailViewSource`) renders it the same way.\n */\nexport function CollectionViewSurface({\n source,\n projectId,\n documentId = null,\n}: {\n source: CollectionViewSource\n projectId: string\n /** `null` (default) → the list; an id → that record's detail. */\n documentId?: string | null\n}) {\n // The edit shell mounts its own CollectionViewProvider, so only the list wraps here.\n if (documentId !== null) {\n return <PortableDetailEditor source={source} projectId={projectId} documentId={documentId} />\n }\n return (\n <CollectionViewProvider source={source}>\n <LoadedCollectionTable projectId={projectId} />\n </CollectionViewProvider>\n )\n}\n"]}
|
|
@@ -2,17 +2,17 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { ArrowLeft, FilePlus2, Link2, ListTree, Play, SlidersHorizontal, SquareStack } from 'lucide-react';
|
|
4
4
|
import { Link, STUDIO_PROJECT_ROUTE, studioPath } from '@elytracms/studio/router';
|
|
5
|
-
import { componentStatus, getStudioRegistry } from '
|
|
6
|
-
import { ComponentStatusBadge, statusDescription, } from '
|
|
7
|
-
import { FieldInspector } from '
|
|
8
|
-
import { ComponentPreview, PropsEditorPane, SlotsInfoPane, usePreviewState, } from '
|
|
9
|
-
import { TransferToDocumentDialog } from '
|
|
10
|
-
import { ReferencesPanel } from '
|
|
11
|
-
import { InspectorSidebar } from '
|
|
12
|
-
import { useSetBreadcrumb } from '
|
|
13
|
-
import { localizedLabel, translate } from '
|
|
5
|
+
import { componentStatus, getStudioRegistry } from '../../lib/registry/index.js';
|
|
6
|
+
import { ComponentStatusBadge, statusDescription, } from './component-status.js';
|
|
7
|
+
import { FieldInspector } from './field-inspector.js';
|
|
8
|
+
import { ComponentPreview, PropsEditorPane, SlotsInfoPane, usePreviewState, } from './component-preview.js';
|
|
9
|
+
import { TransferToDocumentDialog } from './transfer-dialog.js';
|
|
10
|
+
import { ReferencesPanel } from '../references/references-panel.js';
|
|
11
|
+
import { InspectorSidebar } from '../inspector/inspector-sidebar.js';
|
|
12
|
+
import { useSetBreadcrumb } from '../breadcrumb-context.js';
|
|
13
|
+
import { localizedLabel, translate } from '../../lib/i18n/index.js';
|
|
14
14
|
import { Badge, Button, Code, Heading, Row, Spacer, Stack, TabButton, Text } from '@elytracms/studio/ui';
|
|
15
|
-
import { cn } from '
|
|
15
|
+
import { cn } from '../../lib/utils.js';
|
|
16
16
|
/**
|
|
17
17
|
* The component detail view (EC-050/052, overhauled in EC-320) — now on the CMS
|
|
18
18
|
* shell: a header (title · role/category badges · id · status), a lens row of
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-detail.js","sourceRoot":"","sources":["../../../src/components/components/component-detail.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from 'react'\nimport { ArrowLeft, FilePlus2, Link2, ListTree, Play, SlidersHorizontal, SquareStack } from 'lucide-react'\nimport type { ComponentManifest } from '@elytracms/core/component-registry'\nimport { Link, STUDIO_PROJECT_ROUTE, studioPath } from '@elytracms/studio/router'\nimport { componentStatus, getStudioRegistry } from '@elytracms/studio/lib/registry'\nimport type { StudioRegistry } from '@elytracms/studio/lib/registry'\nimport {\n ComponentStatusBadge,\n statusDescription,\n} from '@elytracms/studio/components/components/component-status'\nimport { FieldInspector } from '@elytracms/studio/components/components/field-inspector'\nimport {\n ComponentPreview,\n PropsEditorPane,\n SlotsInfoPane,\n usePreviewState,\n} from '@elytracms/studio/components/components/component-preview'\nimport { TransferToDocumentDialog } from '@elytracms/studio/components/components/transfer-dialog'\nimport { ReferencesPanel } from '@elytracms/studio/components/references/references-panel'\nimport { InspectorSidebar } from '@elytracms/studio/components/inspector/inspector-sidebar'\nimport type { InspectorPane } from '@elytracms/studio/components/inspector/inspector-sidebar'\nimport { useSetBreadcrumb } from '@elytracms/studio/components/breadcrumb-context'\nimport { localizedLabel, translate } from '@elytracms/studio/lib/i18n'\nimport { Badge, Button, Code, Heading, Row, Spacer, Stack, TabButton, Text } from '@elytracms/studio/ui'\nimport { cn } from '@elytracms/studio/lib/utils'\n\n/**\n * The component detail view (EC-050/052, overhauled in EC-320) — now on the CMS\n * shell: a header (title · role/category badges · id · status), a lens row of\n * tabs (Preview / Manifest / References — References-as-a-tab, EC-269), and, on the\n * Preview tab, the live editable preview beside the shared right {@link InspectorSidebar}\n * (Props / Slots). \"Use in document…\" transfers the current combination into a draft.\n */\nexport function ComponentDetail({\n projectId,\n componentId,\n}: {\n projectId: string\n componentId: string\n}) {\n const studio = getStudioRegistry()\n const manifest = studio.registry.getManifest(componentId)\n\n // EC-214: the component is the active record — name it in the global header\n // breadcrumb (under the Components section crumb). Unconditional (hooks rules).\n useSetBreadcrumb([{ label: localizedLabel(manifest?.title, manifest?.id ?? componentId) }])\n\n if (!manifest) {\n return (\n <div className=\"grid h-full place-items-center p-8\">\n <Stack gap=\"3\" align=\"center\" className=\"max-w-sm text-center\">\n <Heading level={2} size=\"h2\">\n {translate('components.detail.notFound.title')}\n </Heading>\n <Text tone=\"muted\">{translate('components.detail.notFound.body', { id: componentId })}</Text>\n <Link\n to={STUDIO_PROJECT_ROUTE}\n params={{ projectId, _splat: studioPath.components() }}\n className=\"text-sm text-primary hover:underline\"\n >\n {translate('components.detail.notFound.back')}\n </Link>\n </Stack>\n </div>\n )\n }\n\n return <ComponentDetailBody key={manifest.id} projectId={projectId} studio={studio} manifest={manifest} />\n}\n\ntype DetailTab = 'preview' | 'manifest' | 'references'\n\nfunction ComponentDetailBody({\n projectId,\n studio,\n manifest,\n}: {\n projectId: string\n studio: StudioRegistry\n manifest: ComponentManifest\n}) {\n const preview = usePreviewState(manifest)\n const [tab, setTab] = useState<DetailTab>('preview')\n const [transferOpen, setTransferOpen] = useState(false)\n\n const status = componentStatus(studio, manifest)\n const title = localizedLabel(manifest.title, manifest.id)\n\n // The Preview tab's right inspector: editable Props + declared Slots. Shares the\n // exact frame the document editor uses (EC-224), so a prop edit re-renders the\n // preview live through the same control set documents use.\n const panes: InspectorPane[] = [\n {\n id: 'props',\n label: translate('components.fieldInspector.props'),\n icon: <SlidersHorizontal className=\"size-3.5\" />,\n render: () => <PropsEditorPane manifest={manifest} state={preview} />,\n },\n {\n id: 'slots',\n label: translate('components.fieldInspector.slots'),\n icon: <SquareStack className=\"size-3.5\" />,\n render: () => <SlotsInfoPane manifest={manifest} />,\n },\n ]\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n {/* Mobile-only back link (the registry sidebar is hidden under md). */}\n <Link\n to={STUDIO_PROJECT_ROUTE}\n params={{ projectId, _splat: studioPath.components() }}\n className=\"inline-flex items-center gap-1 px-4 pt-3 text-xs text-muted-foreground transition-colors hover:text-foreground md:hidden\"\n >\n <ArrowLeft className=\"size-3.5\" /> {translate('components.detail.allComponents')}\n </Link>\n\n {/* Header */}\n <div className=\"shrink-0 border-b border-border px-4 py-3 sm:px-6\">\n <Row gap=\"3\">\n <Row gap=\"2\" align=\"center\" className=\"min-w-0 flex-wrap\">\n <Heading level={1} size=\"h2\" className=\"truncate\">\n {title}\n </Heading>\n {/* EC-591: no namespace badge (an id prefix means nothing); the canvas role it fills, if any. */}\n {manifest.role ? <Badge variant=\"primary\">{manifest.role}</Badge> : null}\n {manifest.category ? <Badge variant=\"outline\">{manifest.category}</Badge> : null}\n </Row>\n <Spacer />\n <ComponentStatusBadge status={status} />\n <Button size=\"sm\" onClick={() => setTransferOpen(true)} data-testid=\"use-in-document\">\n <FilePlus2 /> {translate('components.transfer.action')}\n </Button>\n </Row>\n <Row gap=\"2\" align=\"center\" className=\"mt-1\">\n <Code tone=\"muted\">{manifest.id}</Code>\n </Row>\n {manifest.description ? (\n <Text tone=\"muted\" size=\"sm\" className=\"mt-1 max-w-prose\">\n {manifest.description}\n </Text>\n ) : null}\n {status !== 'valid' ? (\n <Text size=\"sm\" className={cn('mt-1', status === 'invalid' ? 'text-destructive' : 'text-warning')}>\n {statusDescription(status)}\n </Text>\n ) : null}\n\n {/* Lens row — the tab set (mirrors the document editor's lens row). */}\n <Row gap=\"1\" align=\"center\" className=\"mt-3\">\n <TabButton active={tab === 'preview'} onClick={() => setTab('preview')}>\n <Play className=\"size-3\" />\n {translate('components.detail.tab.preview')}\n </TabButton>\n <TabButton active={tab === 'manifest'} onClick={() => setTab('manifest')}>\n <ListTree className=\"size-3\" />\n {translate('components.detail.tab.manifest')}\n </TabButton>\n <div className=\"mx-1 h-4 w-px bg-border\" aria-hidden />\n <TabButton active={tab === 'references'} onClick={() => setTab('references')}>\n <Link2 className=\"size-3\" />\n {translate('references.title')}\n </TabButton>\n </Row>\n </div>\n\n {/* Body */}\n {tab === 'preview' ? (\n <div className=\"flex min-h-0 flex-1 overflow-hidden\">\n <div className=\"min-h-0 flex-1 overflow-hidden\">\n <ComponentPreview manifest={manifest} studio={studio} state={preview} />\n </div>\n <InspectorSidebar panes={panes} className=\"w-[320px] shrink-0 border-l border-border\" />\n </div>\n ) : tab === 'manifest' ? (\n <div className=\"min-h-0 flex-1 overflow-auto p-4 sm:p-6\">\n <div className=\"mx-auto w-full max-w-4xl\">\n <FieldInspector manifest={manifest} />\n </div>\n </div>\n ) : (\n // EC-172/EC-269: inbound references over the reference index, as a tab.\n <div className=\"min-h-0 flex-1 overflow-auto p-4 sm:p-6\">\n <div className=\"mx-auto w-full max-w-2xl\">\n <ReferencesPanel projectId={projectId} target={{ type: 'component', id: manifest.id }} />\n </div>\n </div>\n )}\n\n <TransferToDocumentDialog\n projectId={projectId}\n manifest={manifest}\n node={preview.node}\n open={transferOpen}\n onOpenChange={setTransferOpen}\n />\n </div>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"component-detail.js","sourceRoot":"","sources":["../../../src/components/components/component-detail.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from 'react'\nimport { ArrowLeft, FilePlus2, Link2, ListTree, Play, SlidersHorizontal, SquareStack } from 'lucide-react'\nimport type { ComponentManifest } from '@elytracms/core/component-registry'\nimport { Link, STUDIO_PROJECT_ROUTE, studioPath } from '@elytracms/studio/router'\nimport { componentStatus, getStudioRegistry } from '../../lib/registry'\nimport type { StudioRegistry } from '../../lib/registry'\nimport {\n ComponentStatusBadge,\n statusDescription,\n} from './component-status'\nimport { FieldInspector } from './field-inspector'\nimport {\n ComponentPreview,\n PropsEditorPane,\n SlotsInfoPane,\n usePreviewState,\n} from './component-preview'\nimport { TransferToDocumentDialog } from './transfer-dialog'\nimport { ReferencesPanel } from '../references/references-panel'\nimport { InspectorSidebar } from '../inspector/inspector-sidebar'\nimport type { InspectorPane } from '../inspector/inspector-sidebar'\nimport { useSetBreadcrumb } from '../breadcrumb-context'\nimport { localizedLabel, translate } from '../../lib/i18n'\nimport { Badge, Button, Code, Heading, Row, Spacer, Stack, TabButton, Text } from '@elytracms/studio/ui'\nimport { cn } from '../../lib/utils'\n\n/**\n * The component detail view (EC-050/052, overhauled in EC-320) — now on the CMS\n * shell: a header (title · role/category badges · id · status), a lens row of\n * tabs (Preview / Manifest / References — References-as-a-tab, EC-269), and, on the\n * Preview tab, the live editable preview beside the shared right {@link InspectorSidebar}\n * (Props / Slots). \"Use in document…\" transfers the current combination into a draft.\n */\nexport function ComponentDetail({\n projectId,\n componentId,\n}: {\n projectId: string\n componentId: string\n}) {\n const studio = getStudioRegistry()\n const manifest = studio.registry.getManifest(componentId)\n\n // EC-214: the component is the active record — name it in the global header\n // breadcrumb (under the Components section crumb). Unconditional (hooks rules).\n useSetBreadcrumb([{ label: localizedLabel(manifest?.title, manifest?.id ?? componentId) }])\n\n if (!manifest) {\n return (\n <div className=\"grid h-full place-items-center p-8\">\n <Stack gap=\"3\" align=\"center\" className=\"max-w-sm text-center\">\n <Heading level={2} size=\"h2\">\n {translate('components.detail.notFound.title')}\n </Heading>\n <Text tone=\"muted\">{translate('components.detail.notFound.body', { id: componentId })}</Text>\n <Link\n to={STUDIO_PROJECT_ROUTE}\n params={{ projectId, _splat: studioPath.components() }}\n className=\"text-sm text-primary hover:underline\"\n >\n {translate('components.detail.notFound.back')}\n </Link>\n </Stack>\n </div>\n )\n }\n\n return <ComponentDetailBody key={manifest.id} projectId={projectId} studio={studio} manifest={manifest} />\n}\n\ntype DetailTab = 'preview' | 'manifest' | 'references'\n\nfunction ComponentDetailBody({\n projectId,\n studio,\n manifest,\n}: {\n projectId: string\n studio: StudioRegistry\n manifest: ComponentManifest\n}) {\n const preview = usePreviewState(manifest)\n const [tab, setTab] = useState<DetailTab>('preview')\n const [transferOpen, setTransferOpen] = useState(false)\n\n const status = componentStatus(studio, manifest)\n const title = localizedLabel(manifest.title, manifest.id)\n\n // The Preview tab's right inspector: editable Props + declared Slots. Shares the\n // exact frame the document editor uses (EC-224), so a prop edit re-renders the\n // preview live through the same control set documents use.\n const panes: InspectorPane[] = [\n {\n id: 'props',\n label: translate('components.fieldInspector.props'),\n icon: <SlidersHorizontal className=\"size-3.5\" />,\n render: () => <PropsEditorPane manifest={manifest} state={preview} />,\n },\n {\n id: 'slots',\n label: translate('components.fieldInspector.slots'),\n icon: <SquareStack className=\"size-3.5\" />,\n render: () => <SlotsInfoPane manifest={manifest} />,\n },\n ]\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n {/* Mobile-only back link (the registry sidebar is hidden under md). */}\n <Link\n to={STUDIO_PROJECT_ROUTE}\n params={{ projectId, _splat: studioPath.components() }}\n className=\"inline-flex items-center gap-1 px-4 pt-3 text-xs text-muted-foreground transition-colors hover:text-foreground md:hidden\"\n >\n <ArrowLeft className=\"size-3.5\" /> {translate('components.detail.allComponents')}\n </Link>\n\n {/* Header */}\n <div className=\"shrink-0 border-b border-border px-4 py-3 sm:px-6\">\n <Row gap=\"3\">\n <Row gap=\"2\" align=\"center\" className=\"min-w-0 flex-wrap\">\n <Heading level={1} size=\"h2\" className=\"truncate\">\n {title}\n </Heading>\n {/* EC-591: no namespace badge (an id prefix means nothing); the canvas role it fills, if any. */}\n {manifest.role ? <Badge variant=\"primary\">{manifest.role}</Badge> : null}\n {manifest.category ? <Badge variant=\"outline\">{manifest.category}</Badge> : null}\n </Row>\n <Spacer />\n <ComponentStatusBadge status={status} />\n <Button size=\"sm\" onClick={() => setTransferOpen(true)} data-testid=\"use-in-document\">\n <FilePlus2 /> {translate('components.transfer.action')}\n </Button>\n </Row>\n <Row gap=\"2\" align=\"center\" className=\"mt-1\">\n <Code tone=\"muted\">{manifest.id}</Code>\n </Row>\n {manifest.description ? (\n <Text tone=\"muted\" size=\"sm\" className=\"mt-1 max-w-prose\">\n {manifest.description}\n </Text>\n ) : null}\n {status !== 'valid' ? (\n <Text size=\"sm\" className={cn('mt-1', status === 'invalid' ? 'text-destructive' : 'text-warning')}>\n {statusDescription(status)}\n </Text>\n ) : null}\n\n {/* Lens row — the tab set (mirrors the document editor's lens row). */}\n <Row gap=\"1\" align=\"center\" className=\"mt-3\">\n <TabButton active={tab === 'preview'} onClick={() => setTab('preview')}>\n <Play className=\"size-3\" />\n {translate('components.detail.tab.preview')}\n </TabButton>\n <TabButton active={tab === 'manifest'} onClick={() => setTab('manifest')}>\n <ListTree className=\"size-3\" />\n {translate('components.detail.tab.manifest')}\n </TabButton>\n <div className=\"mx-1 h-4 w-px bg-border\" aria-hidden />\n <TabButton active={tab === 'references'} onClick={() => setTab('references')}>\n <Link2 className=\"size-3\" />\n {translate('references.title')}\n </TabButton>\n </Row>\n </div>\n\n {/* Body */}\n {tab === 'preview' ? (\n <div className=\"flex min-h-0 flex-1 overflow-hidden\">\n <div className=\"min-h-0 flex-1 overflow-hidden\">\n <ComponentPreview manifest={manifest} studio={studio} state={preview} />\n </div>\n <InspectorSidebar panes={panes} className=\"w-[320px] shrink-0 border-l border-border\" />\n </div>\n ) : tab === 'manifest' ? (\n <div className=\"min-h-0 flex-1 overflow-auto p-4 sm:p-6\">\n <div className=\"mx-auto w-full max-w-4xl\">\n <FieldInspector manifest={manifest} />\n </div>\n </div>\n ) : (\n // EC-172/EC-269: inbound references over the reference index, as a tab.\n <div className=\"min-h-0 flex-1 overflow-auto p-4 sm:p-6\">\n <div className=\"mx-auto w-full max-w-2xl\">\n <ReferencesPanel projectId={projectId} target={{ type: 'component', id: manifest.id }} />\n </div>\n </div>\n )}\n\n <TransferToDocumentDialog\n projectId={projectId}\n manifest={manifest}\n node={preview.node}\n open={transferOpen}\n onOpenChange={setTransferOpen}\n />\n </div>\n )\n}\n"]}
|
|
@@ -2,8 +2,8 @@ import { Component } from 'react';
|
|
|
2
2
|
import type { ReactNode } from 'react';
|
|
3
3
|
import type { ComponentNode, JsonValue } from '@elytracms/core/project-graph';
|
|
4
4
|
import type { ComponentManifest } from '@elytracms/core/component-registry';
|
|
5
|
-
import type { StudioRegistry } from '
|
|
6
|
-
import type { PreviewSpec } from '
|
|
5
|
+
import type { StudioRegistry } from '../../lib/registry/index.js';
|
|
6
|
+
import type { PreviewSpec } from '../../lib/registry/preview.js';
|
|
7
7
|
/**
|
|
8
8
|
* EC-320 — the editable component preview. A component's declared preview states
|
|
9
9
|
* (fixtures) select the SAMPLE STATE (slot content, base props); on top of that
|
|
@@ -5,12 +5,12 @@ import { MonitorOff, RotateCcw } from 'lucide-react';
|
|
|
5
5
|
import { renderNode } from '@elytracms/core/runtime-renderer';
|
|
6
6
|
import { staticProp } from '@elytracms/core/project-graph';
|
|
7
7
|
import { manifestSlots } from '@elytracms/core/component-registry';
|
|
8
|
-
import { componentStatus, getStudioRegistry, previewContext } from '
|
|
9
|
-
import { previewSpecs } from '
|
|
8
|
+
import { componentStatus, getStudioRegistry, previewContext } from '../../lib/registry/index.js';
|
|
9
|
+
import { previewSpecs } from '../../lib/registry/preview.js';
|
|
10
10
|
import { Badge, Button, Code, Field, Row, Spacer, Stack, TabButton, Text } from '@elytracms/studio/ui';
|
|
11
|
-
import { localizedLabel, translate } from '
|
|
12
|
-
import { cn } from '
|
|
13
|
-
import { resolveDeploymentCanvasTheme } from '
|
|
11
|
+
import { localizedLabel, translate } from '../../lib/i18n/index.js';
|
|
12
|
+
import { cn } from '../../lib/utils.js';
|
|
13
|
+
import { resolveDeploymentCanvasTheme } from '../../lib/workspace/index.js';
|
|
14
14
|
import { wireCanvasChrome } from '../builder/canvas-chrome.js';
|
|
15
15
|
import { getCanvasStylesheetUrl } from '../builder/canvas-stylesheet.js';
|
|
16
16
|
import { useCanvasViewports, viewportWidth } from '../builder/canvas-breakpoints.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-preview.js","sourceRoot":"","sources":["../../../src/components/components/component-preview.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { createPortal } from 'react-dom'\nimport { MonitorOff, RotateCcw } from 'lucide-react'\nimport { renderNode } from '@elytracms/core/runtime-renderer'\nimport type { RenderContext } from '@elytracms/core/runtime-renderer'\nimport { staticProp } from '@elytracms/core/project-graph'\nimport type { ComponentNode, JsonValue } from '@elytracms/core/project-graph'\nimport type { ComponentManifest, PropField } from '@elytracms/core/component-registry'\nimport { manifestSlots } from '@elytracms/core/component-registry'\nimport { componentStatus, getStudioRegistry, previewContext } from '@elytracms/studio/lib/registry'\nimport type { StudioRegistry } from '@elytracms/studio/lib/registry'\nimport { previewSpecs } from '@elytracms/studio/lib/registry/preview'\nimport type { PreviewSpec } from '@elytracms/studio/lib/registry/preview'\nimport { Badge, Button, Code, Field, Row, Spacer, Stack, TabButton, Text } from '@elytracms/studio/ui'\nimport { localizedLabel, translate } from '@elytracms/studio/lib/i18n'\nimport { cn } from '@elytracms/studio/lib/utils'\nimport { resolveDeploymentCanvasTheme } from '@elytracms/studio/lib/workspace'\nimport { wireCanvasChrome } from '../builder/canvas-chrome'\nimport { getCanvasStylesheetUrl } from '../builder/canvas-stylesheet'\nimport { useCanvasViewports, viewportWidth } from '../builder/canvas-breakpoints'\nimport type { ViewportOption } from '../builder/canvas-breakpoints'\nimport { PropValueControl } from '../cms/prop-fields'\n\n/**\n * EC-320 — the editable component preview. A component's declared preview states\n * (fixtures) select the SAMPLE STATE (slot content, base props); on top of that\n * the user edits individual prop values in the Props sidebar and the preview\n * re-renders live through the SAME runtime-renderer path the Builder and export\n * use (EC-054). Slots follow the selected fixture — full slot-tree editing is out\n * of scope for this reference surface (that's the composition editor's job); the\n * Slots pane documents what a component accepts and which state supplies content.\n */\n\nexport interface PreviewState {\n specs: PreviewSpec[]\n index: number\n setIndex: (i: number) => void\n /** Per-prop static-value overrides applied over the selected fixture. */\n overrides: Record<string, JsonValue>\n setOverride: (name: string, value: JsonValue) => void\n clearOverride: (name: string) => void\n resetAll: () => void\n dirty: boolean\n /** The live node: the selected fixture with prop overrides applied. */\n node: ComponentNode\n}\n\n/** Preview state for a manifest: the fixture selection + the live prop overrides. */\nexport function usePreviewState(manifest: ComponentManifest): PreviewState {\n // EC-591: a fixture-less component previews the seeded Default — role-aware, so it needs the registry.\n const specs = useMemo(() => previewSpecs(manifest, getStudioRegistry().registry), [manifest])\n const [index, setIndexRaw] = useState(0)\n const [overrides, setOverrides] = useState<Record<string, JsonValue>>({})\n\n // Switching preview state resets prop edits — they were relative to the old state.\n const setIndex = (i: number) => {\n setIndexRaw(i)\n setOverrides({})\n }\n const setOverride = (name: string, value: JsonValue) =>\n setOverrides((o) => ({ ...o, [name]: value }))\n const clearOverride = (name: string) =>\n setOverrides((o) => {\n const next = { ...o }\n delete next[name]\n return next\n })\n const resetAll = () => setOverrides({})\n\n const base = specs[Math.min(index, specs.length - 1)]?.node\n const node = useMemo<ComponentNode>(() => {\n const fixture = base ?? { id: `preview-${manifest.id}`, componentId: manifest.id, props: {} }\n const props = { ...(fixture.props ?? {}) }\n for (const [name, value] of Object.entries(overrides)) props[name] = staticProp(value)\n return { ...fixture, props }\n }, [base, overrides, manifest.id])\n\n return {\n specs,\n index: Math.min(index, Math.max(specs.length - 1, 0)),\n setIndex,\n overrides,\n setOverride,\n clearOverride,\n resetAll,\n dirty: Object.keys(overrides).length > 0,\n node,\n }\n}\n\n/** Re-id a preview node into the canvas `node-<n>` namespace for embedding (transfer). */\nexport function embedNodeFrom(node: ComponentNode, id: string): ComponentNode {\n return { ...node, id }\n}\n\n/**\n * The live preview surface: the fixture-state selector (when a component declares\n * more than one) plus the rendered node. Server-only components (EC-191\n * `clientRenderable: false`) can't run on the client-rendered canvas, so they show\n * a documented fallback rather than risk a crash; a missing implementation falls\n * back through the renderer itself (the incompatible state).\n */\nexport function ComponentPreview({\n manifest,\n studio,\n state,\n}: {\n manifest: ComponentManifest\n studio: StudioRegistry\n state: PreviewState\n}) {\n const ctx = useMemo(() => previewContext(studio), [studio])\n const serverOnly = manifest.clientRenderable === false\n const status = componentStatus(studio, manifest)\n const displayName = localizedLabel(manifest.title, manifest.id)\n\n // EC-330: the same config-sourced breakpoint set the builder canvas toolbar\n // offers (`canvas-breakpoints.ts`) — reused, not redefined, so a preview and\n // the real canvas never disagree about the site's responsive widths.\n // Defaults to the always-present 'full' (responsive) option.\n const { viewports } = useCanvasViewports()\n const [viewport, setViewport] = useState(viewports[0]!.key)\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <Row gap=\"1\" wrap align=\"center\" className=\"shrink-0 border-b border-border px-3 py-2\">\n {state.specs.length > 1 ? (\n <Row\n gap=\"1\"\n wrap\n role=\"group\"\n aria-label={translate('components.fixtureRunner.statesAria')}\n >\n {state.specs.map((spec, i) => (\n <TabButton key={spec.name} active={i === state.index} onClick={() => state.setIndex(i)}>\n {spec.name}\n </TabButton>\n ))}\n </Row>\n ) : null}\n <Spacer />\n <Row\n gap=\"1\"\n wrap\n role=\"group\"\n aria-label={translate('components.preview.breakpointAria')}\n >\n {viewports.map((option) => (\n <PreviewBreakpointButton\n key={option.key}\n option={option}\n active={option.key === viewport}\n onSelect={() => setViewport(option.key)}\n />\n ))}\n </Row>\n {state.dirty ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={state.resetAll} data-testid=\"preview-reset\">\n <RotateCcw /> {translate('components.preview.reset')}\n </Button>\n ) : null}\n </Row>\n\n <div\n className=\"canvas-grid min-h-0 flex-1 overflow-auto p-6\"\n data-fixture-state={state.specs[state.index]?.name}\n >\n {serverOnly ? (\n <ServerOnlyNotice />\n ) : (\n <ComponentPreviewFrame\n node={state.node}\n ctx={ctx}\n displayName={displayName}\n width={viewportWidth(viewports, viewport)}\n />\n )}\n {status === 'incompatible' && !serverOnly ? (\n <Text size=\"xs\" tone=\"muted\" className=\"mx-auto mt-3 max-w-2xl\">\n {translate('components.preview.incompatibleNote')}\n </Text>\n ) : null}\n </div>\n </div>\n )\n}\n\n/**\n * One breakpoint option in the preview's width switcher. Mirrors the builder\n * canvas toolbar's `ViewportButton` (`composition-field-editor.tsx`) — same\n * `Button`/active-state styling — but drives LOCAL preview state instead of\n * the builder store (this surface has no composition/undo stack).\n *\n * EC-328: evaluated against the shared `TabButton`/`SegmentedControl`\n * primitives and kept separate — it's built on the shared `Button` (not a\n * bare hand-rolled `<button>`, so it wasn't part of the duplication those\n * primitives address), and carries an interpolated `aria-label` plus a\n * conditional px-value `title` tooltip neither primitive's terse API models.\n */\nfunction PreviewBreakpointButton({\n option,\n active,\n onSelect,\n}: {\n option: ViewportOption\n active: boolean\n onSelect: () => void\n}) {\n return (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n aria-label={translate('builder.canvas.viewportPreviewAria', { label: option.label })}\n aria-pressed={active}\n title={\n option.px !== undefined\n ? `${option.label} · ${option.px}px`\n : translate('builder.canvas.viewportWidthTitle', { label: option.label })\n }\n onClick={onSelect}\n className={cn('px-2 text-xs', active && 'bg-accent text-accent-foreground')}\n >\n {option.label}\n </Button>\n )\n}\n\nfunction ServerOnlyNotice() {\n return (\n <div className=\"mx-auto grid max-w-2xl place-items-center rounded-lg border border-dashed border-border bg-muted/30 p-8 text-center\">\n <Stack gap=\"2\" align=\"center\">\n <MonitorOff className=\"size-5 text-muted-foreground\" aria-hidden />\n <Text size=\"sm\" weight=\"medium\">\n {translate('components.preview.serverOnlyTitle')}\n </Text>\n <Text size=\"xs\" tone=\"muted\" className=\"max-w-sm\">\n {translate('components.preview.serverOnlyBody')}\n </Text>\n </Stack>\n </div>\n )\n}\n\n/** Floor for the auto-height iframe — never collapses to a sliver while empty/loading. */\nconst MIN_PREVIEW_HEIGHT = 360\n\n/**\n * The live preview render surface. Reuses the BuilderCanvas styling mechanism\n * (EC-061, `canvas.tsx`) — since EC-414 through the SAME code path, `wireCanvasChrome`\n * (closing the EC-389 follow-up): the component renders inside an ISOLATED\n * same-origin iframe that `<link>`s the project's canvas stylesheet\n * (`getCanvasStylesheetUrl()` — the consumer's theme entry; in the legacy merged\n * world also the studio CSS), so a component built with the site's Tailwind theme\n * previews with the site's styles, exactly as it does on the canvas and in\n * delivery. Using the iframe (not the studio DOM) is what keeps the delivery CSS\n * scoped and off the studio chrome.\n *\n * Unlike the builder canvas, this iframe's document is deliberately left OUT of\n * the studio's own dark/light class: this is a standalone-component reference\n * surface (not a full page), so its own negative space around the component must\n * read as a light, site-like backdrop — never the studio chrome's current theme\n * (a black frame is exactly what leaks through when the studio is dark-themed and\n * the iframe root inherits that class). The chrome's world probe supplies that\n * backdrop: the neutral backdrop rules in the new world, the studio `:root`\n * (light) tokens in the legacy one.\n *\n * Sizing: width is driven by the caller (the breakpoint selector); height is\n * measured live from the rendered content via `ResizeObserver` (EC-330) so a\n * preset switch or a prop edit — both of which change what's portaled into\n * `doc.body` — always show without clipping or dead space.\n *\n * The render is wrapped in {@link PreviewErrorBoundary} so a component that throws\n * shows the EC-191 fallback instead of taking the whole Components view down.\n */\nfunction ComponentPreviewFrame({\n node,\n ctx,\n displayName,\n width,\n}: {\n node: ComponentNode\n ctx: RenderContext\n displayName: string\n /** CSS width for the iframe — '100%' (responsive) or a fixed breakpoint px width. */\n width: string\n}) {\n const iframeRef = useRef<HTMLIFrameElement>(null)\n const [doc, setDoc] = useState<Document | null>(null)\n const [height, setHeight] = useState(MIN_PREVIEW_HEIGHT)\n\n const wireUp = useCallback(() => {\n const d = iframeRef.current?.contentDocument\n if (!d || !d.body) return\n // ONE code path with the builder canvas (EC-414 AD-B item 4): stylesheet\n // link + chrome css + consumer canvas theme + the world probe. No kit\n // tokens here — this is a registry-level reference surface, not a project\n // page. The dev theme notice is the builder canvas's job, not this pane's.\n wireCanvasChrome(d, {\n stylesheetUrl: getCanvasStylesheetUrl(),\n theme: resolveDeploymentCanvasTheme(),\n })\n setDoc(d)\n }, [])\n\n // Handle the already-loaded case (srcDoc can load before onLoad attaches).\n useEffect(() => {\n if (iframeRef.current?.contentDocument?.readyState === 'complete') wireUp()\n }, [wireUp])\n\n // Auto-height (EC-330): a same-origin iframe exposes its own document, so a\n // `ResizeObserver` on the BODY tracks its live (height: auto) content size —\n // re-firing on its own whenever the portaled render changes (preset switch,\n // prop edit), no manual re-measure wiring needed. Attached per `doc` (re-runs\n // whenever the iframe reloads), not just on mount. Loop-safety: the observed\n // element (the iframe's body) is never the element this effect resizes (the\n // IFRAME itself) — writing height never feeds back into the observed box, and\n // width is never derived from height, so there is no growth loop. Guarded for\n // environments without ResizeObserver (jsdom/tests, older embeds).\n useEffect(() => {\n const body = doc?.body\n if (!body || typeof ResizeObserver === 'undefined') return\n const measure = () => setHeight(Math.max(body.scrollHeight, MIN_PREVIEW_HEIGHT))\n measure()\n const observer = new ResizeObserver(measure)\n observer.observe(body)\n return () => observer.disconnect()\n }, [doc])\n\n return (\n <>\n <iframe\n ref={iframeRef}\n onLoad={wireUp}\n title={translate('components.detail.tab.preview')}\n style={{ width, height, maxWidth: '100%' }}\n className=\"mx-auto block rounded-lg border border-border bg-background shadow-sm\"\n srcDoc=\"<!doctype html><html><head></head><body></body></html>\"\n />\n {doc\n ? createPortal(\n <PreviewErrorBoundary displayName={displayName} resetKey={node}>\n <PreviewLiveRender node={node} ctx={ctx} />\n </PreviewErrorBoundary>,\n doc.body,\n )\n : null}\n </>\n )\n}\n\n/** Renders the node through the runtime renderer, INSIDE a component render so the\n * error boundary catches synchronous render throws (mirrors the blocks-panel\n * thumbnail's `LiveRender`). */\nfunction PreviewLiveRender({ node, ctx }: { node: ComponentNode; ctx: RenderContext }) {\n return <>{renderNode(node, ctx)}</>\n}\n\ninterface PreviewBoundaryState {\n error: Error | null\n}\n\n/**\n * EC-191 resilience for the Components view: a component whose render throws — a\n * missing provider/context (e.g. a prop control that needs a document's\n * `CollectionViewSource`), a runtime bug — shows the documented \"preview\n * unavailable\" fallback ({@link PreviewUnavailable}) instead of taking the whole\n * view down. It resets when the previewed `resetKey` (the node) changes, so\n * switching the fixture state or editing a prop retries the render.\n */\nexport class PreviewErrorBoundary extends Component<\n { children: ReactNode; displayName: string; resetKey: unknown },\n PreviewBoundaryState\n> {\n override state: PreviewBoundaryState = { error: null }\n\n static getDerivedStateFromError(error: Error): PreviewBoundaryState {\n return { error }\n }\n\n override componentDidUpdate(prev: Readonly<{ resetKey: unknown }>) {\n if (this.state.error && prev.resetKey !== this.props.resetKey) {\n this.setState({ error: null })\n }\n }\n\n override render(): ReactNode {\n if (this.state.error) {\n return <PreviewUnavailable displayName={this.props.displayName} error={this.state.error} />\n }\n return this.props.children\n }\n}\n\n/**\n * The EC-191 fallback panel — component name + \"preview unavailable\" + the error.\n * Rendered INTO the preview iframe (which carries only the project stylesheet, and\n * may carry none in tests), so it uses inline styles rather than studio UI classes\n * — the EC-414 AD-B chrome contract, with the `.ec-chrome` containment recipe on\n * its root (walked by the chrome contract test).\n */\nexport function PreviewUnavailable({ displayName, error }: { displayName: string; error: Error }) {\n return (\n <div\n data-preview-unavailable\n className=\"ec-chrome\"\n style={{\n boxSizing: 'border-box',\n maxWidth: '42rem',\n margin: '0 auto',\n border: '1px dashed rgba(120,120,120,0.5)',\n borderRadius: 8,\n padding: '24px 28px',\n background: 'rgba(127,127,127,0.06)',\n color: 'rgba(90,90,90,0.95)',\n font: '14px/1.5 system-ui, -apple-system, sans-serif',\n textAlign: 'center',\n }}\n >\n <div style={{ fontWeight: 600 }}>⚠ {translate('components.preview.unavailableTitle')}</div>\n <div style={{ marginTop: 4, fontWeight: 600, opacity: 0.9 }}>{displayName}</div>\n <div style={{ marginTop: 6, fontSize: 13, opacity: 0.85, wordBreak: 'break-word' }}>\n {error.message}\n </div>\n </div>\n )\n}\n\n/**\n * The editable Props pane (right inspector). Every non-`blocks` prop is edited\n * through the shared {@link PropValueControl} — the exact control set documents\n * use (EC-190/EC-314 phase 4) — so a change re-renders the preview immediately.\n * `blocks` props are a canvas (composition) concern, edited in a document, not here.\n */\nexport function PropsEditorPane({\n manifest,\n state,\n}: {\n manifest: ComponentManifest\n state: PreviewState\n}) {\n const editable = Object.entries(manifest.props).filter(([, spec]) => spec.type !== 'blocks')\n const fixture = state.specs[state.index]?.node\n if (editable.length === 0) {\n return (\n <Text size=\"sm\" tone=\"subtle\" className=\"p-4\">\n {translate('components.fieldInspector.noProps')}\n </Text>\n )\n }\n return (\n <Stack gap=\"4\" className=\"p-4\">\n {editable.map(([name, spec]) => {\n const id = `prop-${name}`\n const overridden = state.overrides[name] !== undefined\n return (\n <Field\n key={name}\n label={\n <Row gap=\"2\">\n <span>{localizedLabel((spec as PropField).form?.label, name)}</span>\n {overridden ? <Badge variant=\"info\">{translate('components.preview.edited')}</Badge> : null}\n </Row>\n }\n htmlFor={id}\n hint={localizedLabel((spec as PropField).form?.description) || undefined}\n >\n <PropValueControl\n id={id}\n name={name}\n spec={spec as PropField}\n value={\n overridden\n ? staticProp(state.overrides[name]!)\n : (fixture?.props?.[name] ?? undefined)\n }\n onSet={(v) => state.setOverride(name, v)}\n onClear={() => state.clearOverride(name)}\n />\n </Field>\n )\n })}\n {state.dirty ? (\n <Button variant=\"outline\" size=\"sm\" onClick={state.resetAll} className=\"self-start\">\n <RotateCcw /> {translate('components.preview.resetProps')}\n </Button>\n ) : null}\n </Stack>\n )\n}\n\n/**\n * The Slots pane (right inspector): the component's declared child regions and,\n * for a fixture that supplies slot content, a note that the preview's slot content\n * follows the selected state. Documents the pragmatic scope call — no slot-tree\n * editing on this reference surface.\n */\nexport function SlotsInfoPane({ manifest }: { manifest: ComponentManifest }) {\n // EC-591 (COMPOSITION #14): the DERIVED slots — a `blocks` prop (a Section's\n // `body`) is a child region too, exactly as the canvas, validator and renderer see it.\n const slots = manifestSlots(manifest)\n if (slots.length === 0) {\n return (\n <Text size=\"sm\" tone=\"subtle\" className=\"p-4\">\n {translate('components.fieldInspector.noSlots')}\n </Text>\n )\n }\n return (\n <Stack gap=\"3\" className=\"p-4\">\n <Text size=\"xs\" tone=\"muted\">\n {translate('components.preview.slotsNote')}\n </Text>\n <div className=\"divide-y divide-border rounded-md border border-border\">\n {slots.map((slot) => (\n <div key={slot.name} className=\"flex flex-col gap-1 p-3\">\n <Row gap=\"2\">\n <Code tone=\"primary\">{slot.name}</Code>\n {slot.required ? (\n <Badge variant=\"warning\">{translate('common.required')}</Badge>\n ) : (\n <Badge variant=\"outline\">{translate('common.optional')}</Badge>\n )}\n </Row>\n {slot.allow && slot.allow.length > 0 ? (\n <Row gap=\"2\" className=\"text-xs\" wrap>\n <Text size=\"xs\" tone=\"subtle\">\n {translate('components.fieldInspector.allows')}\n </Text>\n {slot.allow.map((id) => (\n <Code key={id} tone=\"muted\">\n {id}\n </Code>\n ))}\n </Row>\n ) : null}\n </div>\n ))}\n </div>\n </Stack>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"component-preview.js","sourceRoot":"","sources":["../../../src/components/components/component-preview.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { createPortal } from 'react-dom'\nimport { MonitorOff, RotateCcw } from 'lucide-react'\nimport { renderNode } from '@elytracms/core/runtime-renderer'\nimport type { RenderContext } from '@elytracms/core/runtime-renderer'\nimport { staticProp } from '@elytracms/core/project-graph'\nimport type { ComponentNode, JsonValue } from '@elytracms/core/project-graph'\nimport type { ComponentManifest, PropField } from '@elytracms/core/component-registry'\nimport { manifestSlots } from '@elytracms/core/component-registry'\nimport { componentStatus, getStudioRegistry, previewContext } from '../../lib/registry'\nimport type { StudioRegistry } from '../../lib/registry'\nimport { previewSpecs } from '../../lib/registry/preview'\nimport type { PreviewSpec } from '../../lib/registry/preview'\nimport { Badge, Button, Code, Field, Row, Spacer, Stack, TabButton, Text } from '@elytracms/studio/ui'\nimport { localizedLabel, translate } from '../../lib/i18n'\nimport { cn } from '../../lib/utils'\nimport { resolveDeploymentCanvasTheme } from '../../lib/workspace'\nimport { wireCanvasChrome } from '../builder/canvas-chrome'\nimport { getCanvasStylesheetUrl } from '../builder/canvas-stylesheet'\nimport { useCanvasViewports, viewportWidth } from '../builder/canvas-breakpoints'\nimport type { ViewportOption } from '../builder/canvas-breakpoints'\nimport { PropValueControl } from '../cms/prop-fields'\n\n/**\n * EC-320 — the editable component preview. A component's declared preview states\n * (fixtures) select the SAMPLE STATE (slot content, base props); on top of that\n * the user edits individual prop values in the Props sidebar and the preview\n * re-renders live through the SAME runtime-renderer path the Builder and export\n * use (EC-054). Slots follow the selected fixture — full slot-tree editing is out\n * of scope for this reference surface (that's the composition editor's job); the\n * Slots pane documents what a component accepts and which state supplies content.\n */\n\nexport interface PreviewState {\n specs: PreviewSpec[]\n index: number\n setIndex: (i: number) => void\n /** Per-prop static-value overrides applied over the selected fixture. */\n overrides: Record<string, JsonValue>\n setOverride: (name: string, value: JsonValue) => void\n clearOverride: (name: string) => void\n resetAll: () => void\n dirty: boolean\n /** The live node: the selected fixture with prop overrides applied. */\n node: ComponentNode\n}\n\n/** Preview state for a manifest: the fixture selection + the live prop overrides. */\nexport function usePreviewState(manifest: ComponentManifest): PreviewState {\n // EC-591: a fixture-less component previews the seeded Default — role-aware, so it needs the registry.\n const specs = useMemo(() => previewSpecs(manifest, getStudioRegistry().registry), [manifest])\n const [index, setIndexRaw] = useState(0)\n const [overrides, setOverrides] = useState<Record<string, JsonValue>>({})\n\n // Switching preview state resets prop edits — they were relative to the old state.\n const setIndex = (i: number) => {\n setIndexRaw(i)\n setOverrides({})\n }\n const setOverride = (name: string, value: JsonValue) =>\n setOverrides((o) => ({ ...o, [name]: value }))\n const clearOverride = (name: string) =>\n setOverrides((o) => {\n const next = { ...o }\n delete next[name]\n return next\n })\n const resetAll = () => setOverrides({})\n\n const base = specs[Math.min(index, specs.length - 1)]?.node\n const node = useMemo<ComponentNode>(() => {\n const fixture = base ?? { id: `preview-${manifest.id}`, componentId: manifest.id, props: {} }\n const props = { ...(fixture.props ?? {}) }\n for (const [name, value] of Object.entries(overrides)) props[name] = staticProp(value)\n return { ...fixture, props }\n }, [base, overrides, manifest.id])\n\n return {\n specs,\n index: Math.min(index, Math.max(specs.length - 1, 0)),\n setIndex,\n overrides,\n setOverride,\n clearOverride,\n resetAll,\n dirty: Object.keys(overrides).length > 0,\n node,\n }\n}\n\n/** Re-id a preview node into the canvas `node-<n>` namespace for embedding (transfer). */\nexport function embedNodeFrom(node: ComponentNode, id: string): ComponentNode {\n return { ...node, id }\n}\n\n/**\n * The live preview surface: the fixture-state selector (when a component declares\n * more than one) plus the rendered node. Server-only components (EC-191\n * `clientRenderable: false`) can't run on the client-rendered canvas, so they show\n * a documented fallback rather than risk a crash; a missing implementation falls\n * back through the renderer itself (the incompatible state).\n */\nexport function ComponentPreview({\n manifest,\n studio,\n state,\n}: {\n manifest: ComponentManifest\n studio: StudioRegistry\n state: PreviewState\n}) {\n const ctx = useMemo(() => previewContext(studio), [studio])\n const serverOnly = manifest.clientRenderable === false\n const status = componentStatus(studio, manifest)\n const displayName = localizedLabel(manifest.title, manifest.id)\n\n // EC-330: the same config-sourced breakpoint set the builder canvas toolbar\n // offers (`canvas-breakpoints.ts`) — reused, not redefined, so a preview and\n // the real canvas never disagree about the site's responsive widths.\n // Defaults to the always-present 'full' (responsive) option.\n const { viewports } = useCanvasViewports()\n const [viewport, setViewport] = useState(viewports[0]!.key)\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <Row gap=\"1\" wrap align=\"center\" className=\"shrink-0 border-b border-border px-3 py-2\">\n {state.specs.length > 1 ? (\n <Row\n gap=\"1\"\n wrap\n role=\"group\"\n aria-label={translate('components.fixtureRunner.statesAria')}\n >\n {state.specs.map((spec, i) => (\n <TabButton key={spec.name} active={i === state.index} onClick={() => state.setIndex(i)}>\n {spec.name}\n </TabButton>\n ))}\n </Row>\n ) : null}\n <Spacer />\n <Row\n gap=\"1\"\n wrap\n role=\"group\"\n aria-label={translate('components.preview.breakpointAria')}\n >\n {viewports.map((option) => (\n <PreviewBreakpointButton\n key={option.key}\n option={option}\n active={option.key === viewport}\n onSelect={() => setViewport(option.key)}\n />\n ))}\n </Row>\n {state.dirty ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={state.resetAll} data-testid=\"preview-reset\">\n <RotateCcw /> {translate('components.preview.reset')}\n </Button>\n ) : null}\n </Row>\n\n <div\n className=\"canvas-grid min-h-0 flex-1 overflow-auto p-6\"\n data-fixture-state={state.specs[state.index]?.name}\n >\n {serverOnly ? (\n <ServerOnlyNotice />\n ) : (\n <ComponentPreviewFrame\n node={state.node}\n ctx={ctx}\n displayName={displayName}\n width={viewportWidth(viewports, viewport)}\n />\n )}\n {status === 'incompatible' && !serverOnly ? (\n <Text size=\"xs\" tone=\"muted\" className=\"mx-auto mt-3 max-w-2xl\">\n {translate('components.preview.incompatibleNote')}\n </Text>\n ) : null}\n </div>\n </div>\n )\n}\n\n/**\n * One breakpoint option in the preview's width switcher. Mirrors the builder\n * canvas toolbar's `ViewportButton` (`composition-field-editor.tsx`) — same\n * `Button`/active-state styling — but drives LOCAL preview state instead of\n * the builder store (this surface has no composition/undo stack).\n *\n * EC-328: evaluated against the shared `TabButton`/`SegmentedControl`\n * primitives and kept separate — it's built on the shared `Button` (not a\n * bare hand-rolled `<button>`, so it wasn't part of the duplication those\n * primitives address), and carries an interpolated `aria-label` plus a\n * conditional px-value `title` tooltip neither primitive's terse API models.\n */\nfunction PreviewBreakpointButton({\n option,\n active,\n onSelect,\n}: {\n option: ViewportOption\n active: boolean\n onSelect: () => void\n}) {\n return (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n aria-label={translate('builder.canvas.viewportPreviewAria', { label: option.label })}\n aria-pressed={active}\n title={\n option.px !== undefined\n ? `${option.label} · ${option.px}px`\n : translate('builder.canvas.viewportWidthTitle', { label: option.label })\n }\n onClick={onSelect}\n className={cn('px-2 text-xs', active && 'bg-accent text-accent-foreground')}\n >\n {option.label}\n </Button>\n )\n}\n\nfunction ServerOnlyNotice() {\n return (\n <div className=\"mx-auto grid max-w-2xl place-items-center rounded-lg border border-dashed border-border bg-muted/30 p-8 text-center\">\n <Stack gap=\"2\" align=\"center\">\n <MonitorOff className=\"size-5 text-muted-foreground\" aria-hidden />\n <Text size=\"sm\" weight=\"medium\">\n {translate('components.preview.serverOnlyTitle')}\n </Text>\n <Text size=\"xs\" tone=\"muted\" className=\"max-w-sm\">\n {translate('components.preview.serverOnlyBody')}\n </Text>\n </Stack>\n </div>\n )\n}\n\n/** Floor for the auto-height iframe — never collapses to a sliver while empty/loading. */\nconst MIN_PREVIEW_HEIGHT = 360\n\n/**\n * The live preview render surface. Reuses the BuilderCanvas styling mechanism\n * (EC-061, `canvas.tsx`) — since EC-414 through the SAME code path, `wireCanvasChrome`\n * (closing the EC-389 follow-up): the component renders inside an ISOLATED\n * same-origin iframe that `<link>`s the project's canvas stylesheet\n * (`getCanvasStylesheetUrl()` — the consumer's theme entry; in the legacy merged\n * world also the studio CSS), so a component built with the site's Tailwind theme\n * previews with the site's styles, exactly as it does on the canvas and in\n * delivery. Using the iframe (not the studio DOM) is what keeps the delivery CSS\n * scoped and off the studio chrome.\n *\n * Unlike the builder canvas, this iframe's document is deliberately left OUT of\n * the studio's own dark/light class: this is a standalone-component reference\n * surface (not a full page), so its own negative space around the component must\n * read as a light, site-like backdrop — never the studio chrome's current theme\n * (a black frame is exactly what leaks through when the studio is dark-themed and\n * the iframe root inherits that class). The chrome's world probe supplies that\n * backdrop: the neutral backdrop rules in the new world, the studio `:root`\n * (light) tokens in the legacy one.\n *\n * Sizing: width is driven by the caller (the breakpoint selector); height is\n * measured live from the rendered content via `ResizeObserver` (EC-330) so a\n * preset switch or a prop edit — both of which change what's portaled into\n * `doc.body` — always show without clipping or dead space.\n *\n * The render is wrapped in {@link PreviewErrorBoundary} so a component that throws\n * shows the EC-191 fallback instead of taking the whole Components view down.\n */\nfunction ComponentPreviewFrame({\n node,\n ctx,\n displayName,\n width,\n}: {\n node: ComponentNode\n ctx: RenderContext\n displayName: string\n /** CSS width for the iframe — '100%' (responsive) or a fixed breakpoint px width. */\n width: string\n}) {\n const iframeRef = useRef<HTMLIFrameElement>(null)\n const [doc, setDoc] = useState<Document | null>(null)\n const [height, setHeight] = useState(MIN_PREVIEW_HEIGHT)\n\n const wireUp = useCallback(() => {\n const d = iframeRef.current?.contentDocument\n if (!d || !d.body) return\n // ONE code path with the builder canvas (EC-414 AD-B item 4): stylesheet\n // link + chrome css + consumer canvas theme + the world probe. No kit\n // tokens here — this is a registry-level reference surface, not a project\n // page. The dev theme notice is the builder canvas's job, not this pane's.\n wireCanvasChrome(d, {\n stylesheetUrl: getCanvasStylesheetUrl(),\n theme: resolveDeploymentCanvasTheme(),\n })\n setDoc(d)\n }, [])\n\n // Handle the already-loaded case (srcDoc can load before onLoad attaches).\n useEffect(() => {\n if (iframeRef.current?.contentDocument?.readyState === 'complete') wireUp()\n }, [wireUp])\n\n // Auto-height (EC-330): a same-origin iframe exposes its own document, so a\n // `ResizeObserver` on the BODY tracks its live (height: auto) content size —\n // re-firing on its own whenever the portaled render changes (preset switch,\n // prop edit), no manual re-measure wiring needed. Attached per `doc` (re-runs\n // whenever the iframe reloads), not just on mount. Loop-safety: the observed\n // element (the iframe's body) is never the element this effect resizes (the\n // IFRAME itself) — writing height never feeds back into the observed box, and\n // width is never derived from height, so there is no growth loop. Guarded for\n // environments without ResizeObserver (jsdom/tests, older embeds).\n useEffect(() => {\n const body = doc?.body\n if (!body || typeof ResizeObserver === 'undefined') return\n const measure = () => setHeight(Math.max(body.scrollHeight, MIN_PREVIEW_HEIGHT))\n measure()\n const observer = new ResizeObserver(measure)\n observer.observe(body)\n return () => observer.disconnect()\n }, [doc])\n\n return (\n <>\n <iframe\n ref={iframeRef}\n onLoad={wireUp}\n title={translate('components.detail.tab.preview')}\n style={{ width, height, maxWidth: '100%' }}\n className=\"mx-auto block rounded-lg border border-border bg-background shadow-sm\"\n srcDoc=\"<!doctype html><html><head></head><body></body></html>\"\n />\n {doc\n ? createPortal(\n <PreviewErrorBoundary displayName={displayName} resetKey={node}>\n <PreviewLiveRender node={node} ctx={ctx} />\n </PreviewErrorBoundary>,\n doc.body,\n )\n : null}\n </>\n )\n}\n\n/** Renders the node through the runtime renderer, INSIDE a component render so the\n * error boundary catches synchronous render throws (mirrors the blocks-panel\n * thumbnail's `LiveRender`). */\nfunction PreviewLiveRender({ node, ctx }: { node: ComponentNode; ctx: RenderContext }) {\n return <>{renderNode(node, ctx)}</>\n}\n\ninterface PreviewBoundaryState {\n error: Error | null\n}\n\n/**\n * EC-191 resilience for the Components view: a component whose render throws — a\n * missing provider/context (e.g. a prop control that needs a document's\n * `CollectionViewSource`), a runtime bug — shows the documented \"preview\n * unavailable\" fallback ({@link PreviewUnavailable}) instead of taking the whole\n * view down. It resets when the previewed `resetKey` (the node) changes, so\n * switching the fixture state or editing a prop retries the render.\n */\nexport class PreviewErrorBoundary extends Component<\n { children: ReactNode; displayName: string; resetKey: unknown },\n PreviewBoundaryState\n> {\n override state: PreviewBoundaryState = { error: null }\n\n static getDerivedStateFromError(error: Error): PreviewBoundaryState {\n return { error }\n }\n\n override componentDidUpdate(prev: Readonly<{ resetKey: unknown }>) {\n if (this.state.error && prev.resetKey !== this.props.resetKey) {\n this.setState({ error: null })\n }\n }\n\n override render(): ReactNode {\n if (this.state.error) {\n return <PreviewUnavailable displayName={this.props.displayName} error={this.state.error} />\n }\n return this.props.children\n }\n}\n\n/**\n * The EC-191 fallback panel — component name + \"preview unavailable\" + the error.\n * Rendered INTO the preview iframe (which carries only the project stylesheet, and\n * may carry none in tests), so it uses inline styles rather than studio UI classes\n * — the EC-414 AD-B chrome contract, with the `.ec-chrome` containment recipe on\n * its root (walked by the chrome contract test).\n */\nexport function PreviewUnavailable({ displayName, error }: { displayName: string; error: Error }) {\n return (\n <div\n data-preview-unavailable\n className=\"ec-chrome\"\n style={{\n boxSizing: 'border-box',\n maxWidth: '42rem',\n margin: '0 auto',\n border: '1px dashed rgba(120,120,120,0.5)',\n borderRadius: 8,\n padding: '24px 28px',\n background: 'rgba(127,127,127,0.06)',\n color: 'rgba(90,90,90,0.95)',\n font: '14px/1.5 system-ui, -apple-system, sans-serif',\n textAlign: 'center',\n }}\n >\n <div style={{ fontWeight: 600 }}>⚠ {translate('components.preview.unavailableTitle')}</div>\n <div style={{ marginTop: 4, fontWeight: 600, opacity: 0.9 }}>{displayName}</div>\n <div style={{ marginTop: 6, fontSize: 13, opacity: 0.85, wordBreak: 'break-word' }}>\n {error.message}\n </div>\n </div>\n )\n}\n\n/**\n * The editable Props pane (right inspector). Every non-`blocks` prop is edited\n * through the shared {@link PropValueControl} — the exact control set documents\n * use (EC-190/EC-314 phase 4) — so a change re-renders the preview immediately.\n * `blocks` props are a canvas (composition) concern, edited in a document, not here.\n */\nexport function PropsEditorPane({\n manifest,\n state,\n}: {\n manifest: ComponentManifest\n state: PreviewState\n}) {\n const editable = Object.entries(manifest.props).filter(([, spec]) => spec.type !== 'blocks')\n const fixture = state.specs[state.index]?.node\n if (editable.length === 0) {\n return (\n <Text size=\"sm\" tone=\"subtle\" className=\"p-4\">\n {translate('components.fieldInspector.noProps')}\n </Text>\n )\n }\n return (\n <Stack gap=\"4\" className=\"p-4\">\n {editable.map(([name, spec]) => {\n const id = `prop-${name}`\n const overridden = state.overrides[name] !== undefined\n return (\n <Field\n key={name}\n label={\n <Row gap=\"2\">\n <span>{localizedLabel((spec as PropField).form?.label, name)}</span>\n {overridden ? <Badge variant=\"info\">{translate('components.preview.edited')}</Badge> : null}\n </Row>\n }\n htmlFor={id}\n hint={localizedLabel((spec as PropField).form?.description) || undefined}\n >\n <PropValueControl\n id={id}\n name={name}\n spec={spec as PropField}\n value={\n overridden\n ? staticProp(state.overrides[name]!)\n : (fixture?.props?.[name] ?? undefined)\n }\n onSet={(v) => state.setOverride(name, v)}\n onClear={() => state.clearOverride(name)}\n />\n </Field>\n )\n })}\n {state.dirty ? (\n <Button variant=\"outline\" size=\"sm\" onClick={state.resetAll} className=\"self-start\">\n <RotateCcw /> {translate('components.preview.resetProps')}\n </Button>\n ) : null}\n </Stack>\n )\n}\n\n/**\n * The Slots pane (right inspector): the component's declared child regions and,\n * for a fixture that supplies slot content, a note that the preview's slot content\n * follows the selected state. Documents the pragmatic scope call — no slot-tree\n * editing on this reference surface.\n */\nexport function SlotsInfoPane({ manifest }: { manifest: ComponentManifest }) {\n // EC-591 (COMPOSITION #14): the DERIVED slots — a `blocks` prop (a Section's\n // `body`) is a child region too, exactly as the canvas, validator and renderer see it.\n const slots = manifestSlots(manifest)\n if (slots.length === 0) {\n return (\n <Text size=\"sm\" tone=\"subtle\" className=\"p-4\">\n {translate('components.fieldInspector.noSlots')}\n </Text>\n )\n }\n return (\n <Stack gap=\"3\" className=\"p-4\">\n <Text size=\"xs\" tone=\"muted\">\n {translate('components.preview.slotsNote')}\n </Text>\n <div className=\"divide-y divide-border rounded-md border border-border\">\n {slots.map((slot) => (\n <div key={slot.name} className=\"flex flex-col gap-1 p-3\">\n <Row gap=\"2\">\n <Code tone=\"primary\">{slot.name}</Code>\n {slot.required ? (\n <Badge variant=\"warning\">{translate('common.required')}</Badge>\n ) : (\n <Badge variant=\"outline\">{translate('common.optional')}</Badge>\n )}\n </Row>\n {slot.allow && slot.allow.length > 0 ? (\n <Row gap=\"2\" className=\"text-xs\" wrap>\n <Text size=\"xs\" tone=\"subtle\">\n {translate('components.fieldInspector.allows')}\n </Text>\n {slot.allow.map((id) => (\n <Code key={id} tone=\"muted\">\n {id}\n </Code>\n ))}\n </Row>\n ) : null}\n </div>\n ))}\n </div>\n </Stack>\n )\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { CircleAlert, CircleCheck, TriangleAlert } from 'lucide-react';
|
|
3
|
-
import { translate } from '
|
|
3
|
+
import { translate } from '../../lib/i18n/index.js';
|
|
4
4
|
import { Badge } from '@elytracms/studio/ui';
|
|
5
5
|
const STATUS_META = {
|
|
6
6
|
valid: { variant: 'success', dot: 'bg-success' },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-status.js","sourceRoot":"","sources":["../../../src/components/components/component-status.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEtE,OAAO,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"component-status.js","sourceRoot":"","sources":["../../../src/components/components/component-status.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEtE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAE5C,MAAM,WAAW,GAGb;IACF,KAAK,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,YAAY,EAAE;IAChD,YAAY,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,YAAY,EAAE;IACvD,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE;CACrD,CAAA;AAED,wCAAwC;AACxC,MAAM,UAAU,kBAAkB,CAAC,EAAE,MAAM,EAA+B;IACxE,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;IAChC,MAAM,KAAK,GAAG,SAAS,CAAC,oBAAoB,GAAG,MAAM,CAAC,CAAA;IACtD,OAAO,CACL,eACE,SAAS,EAAE,kCAAkC,IAAI,CAAC,GAAG,EAAE,EACvD,KAAK,EAAE,KAAK,gBACA,SAAS,CAAC,wBAAwB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAClE,CACH,CAAA;AACH,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,oBAAoB,CAAC,EAAE,MAAM,EAA+B;IAC1E,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;IAChC,MAAM,IAAI,GAAG,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,KAAK,cAAc,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAA;IACvG,OAAO,CACL,MAAC,KAAK,IAAC,OAAO,EAAE,IAAI,CAAC,OAAO,aAC1B,KAAC,IAAI,IAAC,SAAS,EAAC,QAAQ,GAAG,OAAE,SAAS,CAAC,oBAAoB,GAAG,MAAM,CAAC,IAC/D,CACT,CAAA;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAuB;IACvD,OAAO,SAAS,CAAC,gCAAgC,GAAG,MAAM,CAAC,CAAA;AAC7D,CAAC","sourcesContent":["import { CircleAlert, CircleCheck, TriangleAlert } from 'lucide-react'\nimport type { ComponentStatus } from '../../lib/registry'\nimport { translate } from '../../lib/i18n'\nimport { Badge } from '@elytracms/studio/ui'\n\nconst STATUS_META: Record<\n ComponentStatus,\n { variant: 'success' | 'warning' | 'error'; dot: string }\n> = {\n valid: { variant: 'success', dot: 'bg-success' },\n incompatible: { variant: 'warning', dot: 'bg-warning' },\n invalid: { variant: 'error', dot: 'bg-destructive' },\n}\n\n/** A small status dot for list rows. */\nexport function ComponentStatusDot({ status }: { status: ComponentStatus }) {\n const meta = STATUS_META[status]\n const label = translate('components.status.' + status)\n return (\n <span\n className={`size-1.5 shrink-0 rounded-full ${meta.dot}`}\n title={label}\n aria-label={translate('components.status.aria', { status: label })}\n />\n )\n}\n\n/** A status badge with icon for the detail view. */\nexport function ComponentStatusBadge({ status }: { status: ComponentStatus }) {\n const meta = STATUS_META[status]\n const Icon = status === 'valid' ? CircleCheck : status === 'incompatible' ? TriangleAlert : CircleAlert\n return (\n <Badge variant={meta.variant}>\n <Icon className=\"size-3\" /> {translate('components.status.' + status)}\n </Badge>\n )\n}\n\nexport function statusDescription(status: ComponentStatus): string {\n return translate('components.status.description.' + status)\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { BookOpen, Layers, MousePointerClick, Sparkles } from 'lucide-react';
|
|
3
|
-
import { getStudioRegistry, registryHealth } from '
|
|
4
|
-
import { translate } from '
|
|
3
|
+
import { getStudioRegistry, registryHealth } from '../../lib/registry/index.js';
|
|
4
|
+
import { translate } from '../../lib/i18n/index.js';
|
|
5
5
|
import { RegistryBrowser } from './registry-browser.js';
|
|
6
6
|
import { deriveComponentStats } from './taxonomy.js';
|
|
7
7
|
import { Badge, Card, Code, Heading, Panel, PanelHeader, Row, Spacer, Stack, Text } from '@elytracms/studio/ui';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components-index.js","sourceRoot":"","sources":["../../../src/components/components/components-index.tsx"],"names":[],"mappings":"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","sourcesContent":["import { BookOpen, Layers, MousePointerClick, Sparkles } from 'lucide-react'\nimport { getStudioRegistry, registryHealth } from '@elytracms/studio/lib/registry'\nimport { translate } from '@elytracms/studio/lib/i18n'\nimport { RegistryBrowser } from './registry-browser'\nimport { deriveComponentStats } from './taxonomy'\nimport { Badge, Card, Code, Heading, Panel, PanelHeader, Row, Spacer, Stack, Text } from '@elytracms/studio/ui'\n\n/**\n * The Components section landing view (EC-050, overhauled EC-320). Serves BOTH\n * audiences: editors get a live census of what components exist (totals,\n * per-category breakdown, health) and a \"pick one\" nudge;\n * devs get pointers to the real in-repo docs for registering and extending\n * components — no code sample to drift, no invented docs.\n */\nexport function ComponentsIndex({ projectId }: { projectId: string }) {\n const studio = getStudioRegistry()\n const manifests = studio.registry.list()\n const stats = deriveComponentStats(manifests)\n const health = registryHealth(studio)\n\n return (\n <div className=\"mx-auto w-full max-w-4xl p-4 sm:p-6\">\n {/* Mobile-only browser (the sidebar is hidden under md). */}\n <div className=\"mb-6 h-80 overflow-hidden rounded-lg border border-border md:hidden\">\n <RegistryBrowser projectId={projectId} />\n </div>\n\n <Stack gap=\"6\">\n <Stack gap=\"1\">\n <Heading size=\"display\">{translate('components.index.title')}</Heading>\n <Text tone=\"muted\">{translate('components.index.subtitle')}</Text>\n </Stack>\n\n <div className=\"grid gap-3 sm:grid-cols-3\">\n <StatCard label={translate('components.index.stat.total')} value={stats.total} />\n <StatCard\n label={translate('components.index.stat.valid')}\n value={health.valid}\n tone=\"success\"\n />\n <StatCard\n label={translate('components.index.stat.needAttention')}\n value={health.incompatible + health.invalid}\n tone={health.incompatible + health.invalid > 0 ? 'warning' : 'muted'}\n hint={translate('components.index.stat.needAttentionHint', {\n incompatible: health.incompatible,\n invalid: health.invalid,\n })}\n />\n </div>\n\n {/* By category — a cheap census derived from manifest `category`. */}\n {stats.categories.length > 0 ? (\n <Panel>\n <PanelHeader>\n <Layers className=\"size-4 text-muted-foreground\" />\n <Text size=\"sm\" weight=\"semibold\">\n {translate('components.index.byCategory')}\n </Text>\n </PanelHeader>\n <Row gap=\"2\" wrap className=\"p-4\">\n {stats.categories.map((category) => (\n <Badge key={category.key || '__uncategorized__'} variant=\"outline\">\n <span className={category.key ? 'capitalize' : undefined}>\n {category.key || translate('components.taxonomy.uncategorized')}\n </span>\n <span className=\"font-mono text-muted-foreground\">{category.count}</span>\n </Badge>\n ))}\n </Row>\n </Panel>\n ) : null}\n\n <Card className=\"flex items-center gap-3 p-4\">\n <span className=\"grid size-9 shrink-0 place-items-center rounded-lg bg-muted text-muted-foreground\">\n <MousePointerClick className=\"size-4\" />\n </span>\n <Text size=\"sm\" tone=\"muted\">\n {translate('components.index.pickHint')}\n </Text>\n </Card>\n\n {/* Dev guidance — pointers to the REAL in-repo docs (no code sample to drift). */}\n <Panel>\n <PanelHeader>\n <BookOpen className=\"size-4 text-muted-foreground\" />\n <Text size=\"sm\" weight=\"semibold\">\n {translate('components.index.guide.title')}\n </Text>\n <Spacer />\n <Badge variant=\"outline\">{translate('components.index.guide.badge')}</Badge>\n </PanelHeader>\n <Stack gap=\"3\" className=\"p-4\">\n <Text size=\"sm\" tone=\"muted\">\n {translate('components.index.guide.intro')}\n </Text>\n <Stack gap=\"2\">\n <DocPointer\n path=\"docs/component-authoring.md\"\n description={translate('components.index.guide.doc.authoring')}\n />\n <DocPointer\n path=\"docs/fixtures.md\"\n description={translate('components.index.guide.doc.fixtures')}\n />\n <DocPointer\n path=\"docs/extensibility.md\"\n description={translate('components.index.guide.doc.extensibility')}\n />\n </Stack>\n <Text size=\"xs\" tone=\"subtle\">\n <Sparkles className=\"mr-1 inline size-3\" aria-hidden />\n {translate('components.index.guide.namespaceNote')}\n </Text>\n </Stack>\n </Panel>\n </Stack>\n </div>\n )\n}\n\nfunction DocPointer({ path, description }: { path: string; description: string }) {\n return (\n <Row gap=\"3\" align=\"center\" className=\"rounded-md border border-border p-2.5\">\n <Code tone=\"primary\" className=\"shrink-0\">\n {path}\n </Code>\n <Text size=\"xs\" tone=\"muted\">\n {description}\n </Text>\n </Row>\n )\n}\n\nfunction StatCard({\n label,\n value,\n hint,\n tone = 'default',\n}: {\n label: string\n value: number\n hint?: string\n tone?: 'default' | 'success' | 'warning' | 'muted'\n}) {\n const valueClass =\n tone === 'success'\n ? 'text-success'\n : tone === 'warning'\n ? 'text-warning'\n : tone === 'muted'\n ? 'text-muted-foreground'\n : 'text-foreground'\n return (\n <Card className=\"p-4\">\n <Text size=\"xs\" tone=\"muted\" mono>\n {label.toUpperCase()}\n </Text>\n <div className={`mt-1 text-2xl font-semibold tracking-tight ${valueClass}`}>{value}</div>\n {hint ? (\n <Text size=\"xs\" tone=\"subtle\" className=\"mt-0.5\">\n {hint}\n </Text>\n ) : null}\n </Card>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"components-index.js","sourceRoot":"","sources":["../../../src/components/components/components-index.tsx"],"names":[],"mappings":"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","sourcesContent":["import { BookOpen, Layers, MousePointerClick, Sparkles } from 'lucide-react'\nimport { getStudioRegistry, registryHealth } from '../../lib/registry'\nimport { translate } from '../../lib/i18n'\nimport { RegistryBrowser } from './registry-browser'\nimport { deriveComponentStats } from './taxonomy'\nimport { Badge, Card, Code, Heading, Panel, PanelHeader, Row, Spacer, Stack, Text } from '@elytracms/studio/ui'\n\n/**\n * The Components section landing view (EC-050, overhauled EC-320). Serves BOTH\n * audiences: editors get a live census of what components exist (totals,\n * per-category breakdown, health) and a \"pick one\" nudge;\n * devs get pointers to the real in-repo docs for registering and extending\n * components — no code sample to drift, no invented docs.\n */\nexport function ComponentsIndex({ projectId }: { projectId: string }) {\n const studio = getStudioRegistry()\n const manifests = studio.registry.list()\n const stats = deriveComponentStats(manifests)\n const health = registryHealth(studio)\n\n return (\n <div className=\"mx-auto w-full max-w-4xl p-4 sm:p-6\">\n {/* Mobile-only browser (the sidebar is hidden under md). */}\n <div className=\"mb-6 h-80 overflow-hidden rounded-lg border border-border md:hidden\">\n <RegistryBrowser projectId={projectId} />\n </div>\n\n <Stack gap=\"6\">\n <Stack gap=\"1\">\n <Heading size=\"display\">{translate('components.index.title')}</Heading>\n <Text tone=\"muted\">{translate('components.index.subtitle')}</Text>\n </Stack>\n\n <div className=\"grid gap-3 sm:grid-cols-3\">\n <StatCard label={translate('components.index.stat.total')} value={stats.total} />\n <StatCard\n label={translate('components.index.stat.valid')}\n value={health.valid}\n tone=\"success\"\n />\n <StatCard\n label={translate('components.index.stat.needAttention')}\n value={health.incompatible + health.invalid}\n tone={health.incompatible + health.invalid > 0 ? 'warning' : 'muted'}\n hint={translate('components.index.stat.needAttentionHint', {\n incompatible: health.incompatible,\n invalid: health.invalid,\n })}\n />\n </div>\n\n {/* By category — a cheap census derived from manifest `category`. */}\n {stats.categories.length > 0 ? (\n <Panel>\n <PanelHeader>\n <Layers className=\"size-4 text-muted-foreground\" />\n <Text size=\"sm\" weight=\"semibold\">\n {translate('components.index.byCategory')}\n </Text>\n </PanelHeader>\n <Row gap=\"2\" wrap className=\"p-4\">\n {stats.categories.map((category) => (\n <Badge key={category.key || '__uncategorized__'} variant=\"outline\">\n <span className={category.key ? 'capitalize' : undefined}>\n {category.key || translate('components.taxonomy.uncategorized')}\n </span>\n <span className=\"font-mono text-muted-foreground\">{category.count}</span>\n </Badge>\n ))}\n </Row>\n </Panel>\n ) : null}\n\n <Card className=\"flex items-center gap-3 p-4\">\n <span className=\"grid size-9 shrink-0 place-items-center rounded-lg bg-muted text-muted-foreground\">\n <MousePointerClick className=\"size-4\" />\n </span>\n <Text size=\"sm\" tone=\"muted\">\n {translate('components.index.pickHint')}\n </Text>\n </Card>\n\n {/* Dev guidance — pointers to the REAL in-repo docs (no code sample to drift). */}\n <Panel>\n <PanelHeader>\n <BookOpen className=\"size-4 text-muted-foreground\" />\n <Text size=\"sm\" weight=\"semibold\">\n {translate('components.index.guide.title')}\n </Text>\n <Spacer />\n <Badge variant=\"outline\">{translate('components.index.guide.badge')}</Badge>\n </PanelHeader>\n <Stack gap=\"3\" className=\"p-4\">\n <Text size=\"sm\" tone=\"muted\">\n {translate('components.index.guide.intro')}\n </Text>\n <Stack gap=\"2\">\n <DocPointer\n path=\"docs/component-authoring.md\"\n description={translate('components.index.guide.doc.authoring')}\n />\n <DocPointer\n path=\"docs/fixtures.md\"\n description={translate('components.index.guide.doc.fixtures')}\n />\n <DocPointer\n path=\"docs/extensibility.md\"\n description={translate('components.index.guide.doc.extensibility')}\n />\n </Stack>\n <Text size=\"xs\" tone=\"subtle\">\n <Sparkles className=\"mr-1 inline size-3\" aria-hidden />\n {translate('components.index.guide.namespaceNote')}\n </Text>\n </Stack>\n </Panel>\n </Stack>\n </div>\n )\n}\n\nfunction DocPointer({ path, description }: { path: string; description: string }) {\n return (\n <Row gap=\"3\" align=\"center\" className=\"rounded-md border border-border p-2.5\">\n <Code tone=\"primary\" className=\"shrink-0\">\n {path}\n </Code>\n <Text size=\"xs\" tone=\"muted\">\n {description}\n </Text>\n </Row>\n )\n}\n\nfunction StatCard({\n label,\n value,\n hint,\n tone = 'default',\n}: {\n label: string\n value: number\n hint?: string\n tone?: 'default' | 'success' | 'warning' | 'muted'\n}) {\n const valueClass =\n tone === 'success'\n ? 'text-success'\n : tone === 'warning'\n ? 'text-warning'\n : tone === 'muted'\n ? 'text-muted-foreground'\n : 'text-foreground'\n return (\n <Card className=\"p-4\">\n <Text size=\"xs\" tone=\"muted\" mono>\n {label.toUpperCase()}\n </Text>\n <div className={`mt-1 text-2xl font-semibold tracking-tight ${valueClass}`}>{value}</div>\n {hint ? (\n <Text size=\"xs\" tone=\"subtle\" className=\"mt-0.5\">\n {hint}\n </Text>\n ) : null}\n </Card>\n )\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { manifestPropFields, manifestSlots } from '@elytracms/core/component-registry';
|
|
3
3
|
import { Badge, Code, Panel, PanelHeader, Row, Spacer, Text } from '@elytracms/studio/ui';
|
|
4
|
-
import { localizedLabel, translate } from '
|
|
4
|
+
import { localizedLabel, translate } from '../../lib/i18n/index.js';
|
|
5
5
|
/**
|
|
6
6
|
* The editor control a prop field-def presents (EC-190): derived from the
|
|
7
7
|
* field `type`, refined by the optional `form.control` hint (textarea / color /
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-inspector.js","sourceRoot":"","sources":["../../../src/components/components/field-inspector.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAA;AAEtF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AACzF,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"field-inspector.js","sourceRoot":"","sources":["../../../src/components/components/field-inspector.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentManifest, SlotSpec } from '@elytracms/core/component-registry'\nimport { manifestPropFields, manifestSlots } from '@elytracms/core/component-registry'\nimport type { FieldDef } from '@elytracms/core/cms-core'\nimport { Badge, Code, Panel, PanelHeader, Row, Spacer, Text } from '@elytracms/studio/ui'\nimport { localizedLabel, translate } from '../../lib/i18n'\n\n/**\n * The editor control a prop field-def presents (EC-190): derived from the\n * field `type`, refined by the optional `form.control` hint (textarea / color /\n * json for `text`). Read-only display label for the manifest viewer.\n */\nfunction controlType(field: FieldDef): string {\n if (field.type === 'text' && field.form?.control) return field.form.control\n return field.type\n}\n\nfunction formatDefault(value: unknown): string {\n if (value === undefined) return '—'\n if (typeof value === 'string') return value === '' ? '\"\"' : value\n return JSON.stringify(value)\n}\n\n/**\n * Inspect a component's props and slots (brief §7.2, §8.3, EC-053): prop field-def\n * type/control (EC-190), default value, and slot rules (required, allowed\n * children). Props are static field-defs; binding metadata retired in EC-190.\n */\nexport function FieldInspector({ manifest }: { manifest: ComponentManifest }) {\n const props = manifestPropFields(manifest)\n // EC-591 (COMPOSITION #14): the DERIVED slots — a `blocks` prop (a Section's\n // `body`) is a child region too, exactly as the canvas, validator and renderer see it.\n const slots = manifestSlots(manifest)\n return (\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <Panel>\n <PanelHeader>\n <Text size=\"sm\" weight=\"semibold\">\n {translate('components.fieldInspector.props')}\n </Text>\n <Spacer />\n <Text size=\"xs\" tone=\"muted\" mono>\n {props.length}\n </Text>\n </PanelHeader>\n {props.length === 0 ? (\n <Text size=\"sm\" tone=\"subtle\" className=\"p-4\">\n {translate('components.fieldInspector.noProps')}\n </Text>\n ) : (\n <div className=\"divide-y divide-border\">\n {props.map((field) => (\n <PropRow key={field.name} field={field} />\n ))}\n </div>\n )}\n </Panel>\n\n <Panel>\n <PanelHeader>\n <Text size=\"sm\" weight=\"semibold\">\n {translate('components.fieldInspector.slots')}\n </Text>\n <Spacer />\n <Text size=\"xs\" tone=\"muted\" mono>\n {slots.length}\n </Text>\n </PanelHeader>\n {slots.length === 0 ? (\n <Text size=\"sm\" tone=\"subtle\" className=\"p-4\">\n {translate('components.fieldInspector.noSlots')}\n </Text>\n ) : (\n <div className=\"divide-y divide-border\">\n {slots.map((slot) => (\n <SlotRow key={slot.name} slot={slot} />\n ))}\n </div>\n )}\n </Panel>\n </div>\n )\n}\n\nfunction PropRow({ field }: { field: FieldDef }) {\n const label = localizedLabel(field.form?.label, field.name)\n const description = field.form?.description !== undefined ? localizedLabel(field.form.description) : undefined\n return (\n <div className=\"flex flex-col gap-1.5 p-3\">\n <Row gap=\"2\">\n <Code tone=\"primary\">{field.name}</Code>\n <Badge variant=\"outline\">{controlType(field)}</Badge>\n <Spacer />\n {field.form?.inlineEditable ? (\n <Badge variant=\"info\">{translate('components.fieldInspector.inline')}</Badge>\n ) : null}\n </Row>\n {label || description ? (\n <Text size=\"xs\" tone=\"muted\">\n {description ?? label}\n </Text>\n ) : null}\n <Row gap=\"3\" className=\"text-xs\">\n <Text size=\"xs\" tone=\"subtle\">\n {translate('components.fieldInspector.default')}\n </Text>\n <Code tone=\"muted\">{formatDefault(field.default)}</Code>\n </Row>\n </div>\n )\n}\n\nfunction SlotRow({ slot }: { slot: SlotSpec }) {\n return (\n <div className=\"flex flex-col gap-1 p-3\">\n <Row gap=\"2\">\n <Code tone=\"primary\">{slot.name}</Code>\n {slot.required ? (\n <Badge variant=\"warning\">{translate('common.required')}</Badge>\n ) : (\n <Badge variant=\"outline\">{translate('common.optional')}</Badge>\n )}\n <Spacer />\n {slot.label ? (\n <Text size=\"xs\" tone=\"muted\">\n {slot.label}\n </Text>\n ) : null}\n </Row>\n {slot.allow && slot.allow.length > 0 ? (\n <Row gap=\"2\" className=\"text-xs\">\n <Text size=\"xs\" tone=\"subtle\">\n {translate('components.fieldInspector.allows')}\n </Text>\n <Row gap=\"1\" wrap>\n {slot.allow.map((id) => (\n <Code key={id} tone=\"muted\">\n {id}\n </Code>\n ))}\n </Row>\n </Row>\n ) : null}\n </div>\n )\n}\n"]}
|
|
@@ -2,10 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Link, STUDIO_PROJECT_ROUTE, studioPath } from '@elytracms/studio/router';
|
|
3
3
|
import { Search } from 'lucide-react';
|
|
4
4
|
import { useMemo, useState } from 'react';
|
|
5
|
-
import { componentStatus, getStudioRegistry } from '
|
|
6
|
-
import { localizedLabel, translate } from '
|
|
5
|
+
import { componentStatus, getStudioRegistry } from '../../lib/registry/index.js';
|
|
6
|
+
import { localizedLabel, translate } from '../../lib/i18n/index.js';
|
|
7
7
|
import { Input, Stack, Text } from '@elytracms/studio/ui';
|
|
8
|
-
import { cn } from '
|
|
8
|
+
import { cn } from '../../lib/utils.js';
|
|
9
9
|
import { ComponentStatusDot } from './component-status.js';
|
|
10
10
|
import { deriveTaxonomy } from './taxonomy.js';
|
|
11
11
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry-browser.js","sourceRoot":"","sources":["../../../src/components/components/registry-browser.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEzC,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"registry-browser.js","sourceRoot":"","sources":["../../../src/components/components/registry-browser.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEzC,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACvE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,SAAS,EACT,iBAAiB,GAIlB;IACC,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAA;IAClC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IAEtC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IACjE,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAA;IACtF,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,KAAK,CAAC,CAAA;IAErC,OAAO,CACL,eAAK,SAAS,EAAC,8BAA8B,aAC3C,cAAK,SAAS,EAAC,+CAA+C,YAC5D,eAAK,SAAS,EAAC,UAAU,aACvB,KAAC,MAAM,IAAC,SAAS,EAAC,+FAA+F,GAAG,EACpH,KAAC,KAAK,IACJ,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACzC,WAAW,EAAE,SAAS,CAAC,sCAAsC,CAAC,EAC9D,SAAS,EAAC,MAAM,gBACJ,SAAS,CAAC,+BAA+B,CAAC,GACtD,IACE,GACF,EAEN,cAAK,SAAS,EAAC,kCAAkC,YAC9C,KAAK,CAAC,CAAC,CAAC,CACP,KAAC,IAAI,IAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,SAAS,EAAC,KAAK,YACzC,KAAK,CAAC,IAAI,EAAE;wBACX,CAAC,CAAC,SAAS,CAAC,iCAAiC,EAAE,EAAE,KAAK,EAAE,CAAC;wBACzD,CAAC,CAAC,SAAS,CAAC,mCAAmC,CAAC,GAC7C,CACR,CAAC,CAAC,CAAC,CACF,KAAC,KAAK,IAAC,GAAG,EAAC,GAAG,YACX,UAAU,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAC5B,MAAC,KAAK,IAA2C,GAAG,EAAC,GAAG,aACtD,KAAC,IAAI,IACH,IAAI,EAAC,IAAI,EACT,MAAM,EAAC,QAAQ,EACf,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,EAAE,CAAC,8BAA8B,EAAE,QAAQ,CAAC,GAAG,IAAI,YAAY,CAAC,YAE1E,QAAQ,CAAC,GAAG,IAAI,SAAS,CAAC,mCAAmC,CAAC,GAC1D,EACP,KAAC,KAAK,IAAC,GAAG,EAAC,IAAI,YACZ,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAC7B,KAAC,YAAY,IAEX,QAAQ,EAAE,CAAC,EACX,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,CAAC,CAAC,EAAE,KAAK,iBAAiB,IAH7B,CAAC,CAAC,EAAE,CAIT,CACH,CAAC,GACI,KAlBE,QAAQ,CAAC,GAAG,IAAI,mBAAmB,CAmBvC,CACT,CAAC,GACI,CACT,GACG,IACF,CACP,CAAA;AACH,CAAC;AAED,SAAS,YAAY,CAAC,EACpB,QAAQ,EACR,SAAS,EACT,MAAM,GAKP;IACC,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAA;IAClC,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IAChD,OAAO,CACL,MAAC,IAAI,IACH,EAAE,EAAE,oBAAoB,EACxB,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,kBAClD,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EACzC,SAAS,EAAE,EAAE,CACX,0EAA0E,EAC1E,MAAM;YACJ,CAAC,CAAC,kCAAkC;YACpC,CAAC,CAAC,4DAA4D,CACjE,aAED,KAAC,kBAAkB,IAAC,MAAM,EAAE,MAAM,GAAI,EACtC,eAAM,SAAS,EAAC,qDAAqD,YAClE,cAAc,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,GACvC,IACF,CACR,CAAA;AACH,CAAC","sourcesContent":["import { Link, STUDIO_PROJECT_ROUTE, studioPath } from '@elytracms/studio/router'\nimport { Search } from 'lucide-react'\nimport { useMemo, useState } from 'react'\nimport type { ComponentManifest } from '@elytracms/core/component-registry'\nimport { componentStatus, getStudioRegistry } from '../../lib/registry'\nimport { localizedLabel, translate } from '../../lib/i18n'\nimport { Input, Stack, Text } from '@elytracms/studio/ui'\nimport { cn } from '../../lib/utils'\nimport { ComponentStatusDot } from './component-status'\nimport { deriveTaxonomy } from './taxonomy'\n\n/**\n * The registry browser sidebar (EC-050, taxonomy overhaul EC-320). A searchable\n * list grouped by category (the manifest's declared `category`, uncategorized\n * last); search filters across id/title/category/description. Grouping + search\n * are pure ({@link deriveTaxonomy}), so what renders here is exactly what the\n * tests pin. EC-591: one level — the `base.*`/`project.*` namespace filter went\n * with the id classification; the registry is the config's one list.\n */\nexport function RegistryBrowser({\n projectId,\n activeComponentId,\n}: {\n projectId: string\n activeComponentId?: string\n}) {\n const studio = getStudioRegistry()\n const [query, setQuery] = useState('')\n\n const manifests = useMemo(() => studio.registry.list(), [studio])\n const categories = useMemo(() => deriveTaxonomy(manifests, query), [manifests, query])\n const empty = categories.length === 0\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <div className=\"shrink-0 space-y-2 border-b border-border p-3\">\n <div className=\"relative\">\n <Search className=\"pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground\" />\n <Input\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={translate('components.browser.searchPlaceholder')}\n className=\"pl-8\"\n aria-label={translate('components.browser.searchAria')}\n />\n </div>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-auto p-2\">\n {empty ? (\n <Text size=\"sm\" tone=\"muted\" className=\"p-3\">\n {query.trim()\n ? translate('components.browser.noMatchQuery', { query })\n : translate('components.browser.noMatchFilters')}\n </Text>\n ) : (\n <Stack gap=\"3\">\n {categories.map((category) => (\n <Stack key={category.key || '__uncategorized__'} gap=\"1\">\n <Text\n size=\"xs\"\n weight=\"medium\"\n tone=\"subtle\"\n className={cn('px-2 uppercase tracking-wide', category.key && 'capitalize')}\n >\n {category.key || translate('components.taxonomy.uncategorized')}\n </Text>\n <Stack gap=\"px\">\n {category.manifests.map((m) => (\n <ComponentRow\n key={m.id}\n manifest={m}\n projectId={projectId}\n active={m.id === activeComponentId}\n />\n ))}\n </Stack>\n </Stack>\n ))}\n </Stack>\n )}\n </div>\n </div>\n )\n}\n\nfunction ComponentRow({\n manifest,\n projectId,\n active,\n}: {\n manifest: ComponentManifest\n projectId: string\n active: boolean\n}) {\n const studio = getStudioRegistry()\n const status = componentStatus(studio, manifest)\n return (\n <Link\n to={STUDIO_PROJECT_ROUTE}\n params={{ projectId, _splat: studioPath.component(manifest.id) }}\n aria-current={active ? 'page' : undefined}\n className={cn(\n 'flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors',\n active\n ? 'bg-accent text-accent-foreground'\n : 'text-muted-foreground hover:bg-muted hover:text-foreground',\n )}\n >\n <ComponentStatusDot status={status} />\n <span className=\"min-w-0 flex-1 truncate font-medium text-foreground\">\n {localizedLabel(manifest.title, manifest.id)}\n </span>\n </Link>\n )\n}\n"]}
|
|
@@ -34,7 +34,7 @@ export interface CategoryCount {
|
|
|
34
34
|
* Cheap registry stats for the intro page (EC-320): the total and a per-category
|
|
35
35
|
* breakdown (uncategorized last). Derived purely from the manifest set — no
|
|
36
36
|
* health/implementation lookups here (those come from the separate
|
|
37
|
-
* {@link import('
|
|
37
|
+
* {@link import('../../lib/registry').registryHealth}). EC-591: no
|
|
38
38
|
* base/project split — there is one list.
|
|
39
39
|
*/
|
|
40
40
|
export interface ComponentStats {
|