@elytracms/studio 0.0.39 → 0.0.40

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.
@@ -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 { useMemo, useState } from 'react'\nimport { MonitorOff, RotateCcw } from 'lucide-react'\nimport { renderNode } 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 { componentStatus, 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, Text } from '@elytracms/studio/ui'\nimport { localizedLabel, translate } from '@elytracms/studio/lib/i18n'\nimport { cn } from '@elytracms/studio/lib/utils'\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 const specs = useMemo(() => previewSpecs(manifest), [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\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n {state.specs.length > 1 ? (\n <Row\n gap=\"1\"\n wrap\n className=\"shrink-0 border-b border-border px-3 py-2\"\n role=\"group\"\n aria-label={translate('components.fixtureRunner.statesAria')}\n >\n {state.specs.map((spec, i) => (\n <button\n key={spec.name}\n type=\"button\"\n aria-pressed={i === state.index}\n onClick={() => state.setIndex(i)}\n className={cn(\n 'rounded-md px-2.5 py-1 text-xs font-medium transition-colors',\n i === state.index\n ? 'bg-accent text-accent-foreground'\n : 'text-muted-foreground hover:bg-muted hover:text-foreground',\n )}\n >\n {spec.name}\n </button>\n ))}\n <Spacer />\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 ) : null}\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 <div className=\"mx-auto max-w-2xl rounded-lg border border-border bg-background p-6 shadow-sm\">\n {renderNode(state.node, ctx)}\n </div>\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\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/**\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 if (manifest.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 {manifest.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 { componentStatus, 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, Text } from '@elytracms/studio/ui'\nimport { localizedLabel, translate } from '@elytracms/studio/lib/i18n'\nimport { cn } from '@elytracms/studio/lib/utils'\nimport { getCanvasStylesheetUrl } from '../builder/canvas-stylesheet'\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 const specs = useMemo(() => previewSpecs(manifest), [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 = manifest.title ?? manifest.id\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n {state.specs.length > 1 ? (\n <Row\n gap=\"1\"\n wrap\n className=\"shrink-0 border-b border-border px-3 py-2\"\n role=\"group\"\n aria-label={translate('components.fixtureRunner.statesAria')}\n >\n {state.specs.map((spec, i) => (\n <button\n key={spec.name}\n type=\"button\"\n aria-pressed={i === state.index}\n onClick={() => state.setIndex(i)}\n className={cn(\n 'rounded-md px-2.5 py-1 text-xs font-medium transition-colors',\n i === state.index\n ? 'bg-accent text-accent-foreground'\n : 'text-muted-foreground hover:bg-muted hover:text-foreground',\n )}\n >\n {spec.name}\n </button>\n ))}\n <Spacer />\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 ) : null}\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 node={state.node} ctx={ctx} displayName={displayName} />\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\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/**\n * The live preview render surface. Reuses the BuilderCanvas styling mechanism\n * (EC-061, `canvas.tsx`): the component renders inside an ISOLATED same-origin\n * iframe that `<link>`s the project's canvas stylesheet\n * (`getCanvasStylesheetUrl()` — the consuming app's delivery CSS + studio CSS), so\n * a component built with the site's Tailwind theme previews with the site's styles,\n * exactly as it does on the canvas and in delivery. Using the iframe (not the\n * studio DOM) is what keeps the delivery CSS scoped and off the studio chrome.\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}: {\n node: ComponentNode\n ctx: RenderContext\n displayName: string\n}) {\n const iframeRef = useRef<HTMLIFrameElement>(null)\n const [doc, setDoc] = useState<Document | null>(null)\n\n const wireUp = useCallback(() => {\n const d = iframeRef.current?.contentDocument\n if (!d || !d.body) return\n // The SAME injection the canvas performs: the studio is dark-themed, and the\n // delivery stylesheet is scoped to this iframe alone (no chrome leak). Unset\n // (tests / an app that never called `setCanvasStylesheetUrl`) → skip the link.\n d.documentElement.classList.add('dark')\n const appCss = getCanvasStylesheetUrl()\n if (appCss && !d.getElementById('ec-app-css')) {\n const link = d.createElement('link')\n link.id = 'ec-app-css'\n link.rel = 'stylesheet'\n link.href = appCss\n d.head.appendChild(link)\n }\n d.body.className = 'bg-background text-foreground font-sans'\n d.body.style.margin = '0'\n d.body.style.padding = '24px'\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 return (\n <>\n <iframe\n ref={iframeRef}\n onLoad={wireUp}\n title={translate('components.detail.tab.preview')}\n className=\"mx-auto block min-h-[360px] w-full max-w-2xl 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 * — matching the canvas's own in-iframe placeholder convention.\n */\nexport function PreviewUnavailable({ displayName, error }: { displayName: string; error: Error }) {\n return (\n <div\n data-preview-unavailable\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 if (manifest.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 {manifest.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"]}
@@ -240,6 +240,11 @@ export const EN_MESSAGES = {
240
240
  'cms.editor.publish': msg('Publish'),
241
241
  'cms.editor.moreActions': msg('More actions'),
242
242
  'cms.editor.unpublish': msg('Unpublish'),
243
+ // 0.0.39 — the Publish button is a split button: primary Publish (stay) + a
244
+ // "Publish & close" dropdown item (publish, then return to the list). Replaces the
245
+ // retired EC-316 "Save & close" (autosave made a bare "Save" meaningless).
246
+ 'cms.editor.publishActions': msg('Publish options', 'aria-label for the Publish split-button dropdown trigger.'),
247
+ 'cms.editor.publishAndClose': msg('Publish & close', 'Split-button item: publish the document, then return to the collection list (0.0.39, replaces EC-316 Save & close).'),
243
248
  'cms.editor.saveAndClose': msg('Save & close', 'Header action: save the draft, then return to the collection list (EC-316).'),
244
249
  'cms.editor.discardDraft': msg('Discard changes', 'Header ⋯-menu item: revert the draft to the published content (EC-316).'),
245
250
  'cms.editor.discardDraftUpToDateHint': msg('The draft matches the published version — nothing to discard.'),
@@ -294,6 +299,11 @@ export const EN_MESSAGES = {
294
299
  'cms.details.slotInUse': msg(' — in use', 'Suffix on a slot option already taken by another document.'),
295
300
  'cms.details.slotHint': msg('A stable name the site uses to find this document (e.g. the main menu), instead of which exact entry it is. One document per slot.'),
296
301
  'cms.details.empty': msg('No document properties to set.'),
302
+ // 0.0.39 — the document-level URL affordance (the EC-315 "hybrid split"): the full
303
+ // composed path as its own Details row, with ancestor-document segments linking to
304
+ // their editors and static route segments as plain text.
305
+ 'cms.details.url': msg('URL', 'Details pane section: the document’s composed URL path.'),
306
+ 'cms.details.urlCurrent': msg('this page', 'Tooltip on the final URL segment — the document being edited.'),
297
307
  // ─────────────────────────────────────────────────────────────────────────
298
308
  // CMS — import dialog
299
309
  // ─────────────────────────────────────────────────────────────────────────
@@ -327,11 +337,11 @@ export const EN_MESSAGES = {
327
337
  'cms.version.versionsIdentical': msg('These two versions are identical.'),
328
338
  'cms.version.beforeVersion': msg('Before · v{version}'),
329
339
  'cms.version.afterTarget': msg('After · {target}'),
330
- 'cms.version.restoreField': msg('Restore {field}'),
331
- 'cms.version.restoreFieldLocale': msg('Restore {field} ({locale})'),
340
+ 'cms.version.restoreField': msg('Restore {field} from v{version}'),
341
+ 'cms.version.restoreFieldLocale': msg('Restore {field} ({locale}) from v{version}'),
332
342
  'cms.version.textUnchanged': msg('Text unchanged — formatting or whitespace differs.'),
333
343
  'cms.version.contentChanged': msg('Content changed.'),
334
- 'cms.version.restoreBlock': msg('Restore this block'),
344
+ 'cms.version.restoreBlock': msg('Restore this block from v{version}'),
335
345
  'cms.version.nestedContentChanged': msg('Nested content changed.'),
336
346
  'cms.version.blockAdded': msg('Block added.'),
337
347
  'cms.version.blockRemoved': msg('Block removed.'),
@@ -562,6 +572,8 @@ export const EN_MESSAGES = {
562
572
  'components.preview.serverOnlyTitle': msg('Server-only component'),
563
573
  'components.preview.serverOnlyBody': msg('This component is not client-renderable, so it can’t run in the live preview. It still renders in your delivery frames.'),
564
574
  'components.preview.slotsNote': msg('Slot content in the preview follows the selected state. Full slot editing happens in a document’s canvas — transfer this combination into one with “Use in document…”.'),
575
+ 'components.preview.unavailableTitle': msg('Preview unavailable', 'Shown in place of a component preview that threw while rendering.'),
576
+ 'components.preview.propNeedsDocument': msg('Editable in a document — no workspace context in the component preview.', 'Hint under an asset/relation/object prop control in the read-only component preview.'),
565
577
  'components.transfer.action': msg('Use in document…'),
566
578
  'components.transfer.title': msg('Use “{name}” in a document'),
567
579
  'components.transfer.description': msg('Create a new draft whose blocks field holds this combination, then open it.'),