@elytracms/studio 0.0.105 → 0.0.106

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.
Files changed (47) hide show
  1. package/dist/components/builder/builder-store.d.ts +19 -3
  2. package/dist/components/builder/builder-store.js +24 -13
  3. package/dist/components/builder/builder-store.js.map +1 -1
  4. package/dist/components/builder/clipboard-actions.js +6 -5
  5. package/dist/components/builder/clipboard-actions.js.map +1 -1
  6. package/dist/components/builder/composition-field-editor.js +4 -2
  7. package/dist/components/builder/composition-field-editor.js.map +1 -1
  8. package/dist/components/cms/duplicate-document.js +5 -5
  9. package/dist/components/cms/duplicate-document.js.map +1 -1
  10. package/dist/components/cms/rich-text/editor.d.ts +7 -1
  11. package/dist/components/cms/rich-text/editor.js +9 -4
  12. package/dist/components/cms/rich-text/editor.js.map +1 -1
  13. package/dist/components/cms/rich-text/embed-identity.d.ts +36 -0
  14. package/dist/components/cms/rich-text/embed-identity.js +114 -0
  15. package/dist/components/cms/rich-text/embed-identity.js.map +1 -0
  16. package/dist/components/cms/rich-text/extensions.d.ts +7 -1
  17. package/dist/components/cms/rich-text/extensions.js +7 -1
  18. package/dist/components/cms/rich-text/extensions.js.map +1 -1
  19. package/dist/components/cms/rich-text/insert.d.ts +10 -5
  20. package/dist/components/cms/rich-text/insert.js +10 -12
  21. package/dist/components/cms/rich-text/insert.js.map +1 -1
  22. package/dist/components/components/component-preview.d.ts +0 -2
  23. package/dist/components/components/component-preview.js +0 -4
  24. package/dist/components/components/component-preview.js.map +1 -1
  25. package/dist/components/components/transfer-dialog.js +3 -1
  26. package/dist/components/components/transfer-dialog.js.map +1 -1
  27. package/dist/components/components/transfer.d.ts +12 -8
  28. package/dist/components/components/transfer.js +16 -15
  29. package/dist/components/components/transfer.js.map +1 -1
  30. package/dist/lib/ai/translate-document.js +47 -4
  31. package/dist/lib/ai/translate-document.js.map +1 -1
  32. package/dist/lib/ai/writer-form.js +5 -4
  33. package/dist/lib/ai/writer-form.js.map +1 -1
  34. package/dist/lib/engine-version.d.ts +1 -1
  35. package/dist/lib/engine-version.js +1 -1
  36. package/dist/lib/engine-version.js.map +1 -1
  37. package/dist/lib/i18n/messages.de.js +4 -1
  38. package/dist/lib/i18n/messages.de.js.map +1 -1
  39. package/dist/lib/i18n/messages.en.d.ts +3 -0
  40. package/dist/lib/i18n/messages.en.js +4 -1
  41. package/dist/lib/i18n/messages.en.js.map +1 -1
  42. package/dist/lib/persona/labels.js +1 -0
  43. package/dist/lib/persona/labels.js.map +1 -1
  44. package/dist/lib/registry/preview.d.ts +2 -1
  45. package/dist/lib/registry/preview.js +8 -3
  46. package/dist/lib/registry/preview.js.map +1 -1
  47. package/package.json +3 -3
@@ -75,6 +75,7 @@ const CMS_ISSUE_LABEL_KEYS = {
75
75
  'asset-without-url': 'cms.issue.asset-without-url',
76
76
  'asset-meta-drift': 'cms.issue.asset-meta-drift',
77
77
  'duplicate-document': 'cms.issue.duplicate-document',
78
+ 'duplicate-node-id': 'cms.issue.duplicate-node-id',
78
79
  'unknown-locale': 'cms.issue.unknown-locale',
79
80
  'missing-localized-value': 'cms.issue.missing-localized-value',
80
81
  'route-conflict': 'cms.issue.route-conflict',
@@ -1 +1 @@
1
- {"version":3,"file":"labels.js","sourceRoot":"","sources":["../../../src/lib/persona/labels.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CmsIssueCode, CmsIssueSeverity, CmsValidationIssue } from '@elytracms/core/cms-core'\nimport { resolveLabel } from '@elytracms/core/cms-core'\nimport type { OperationError, OperationErrorCode, OperationIssue } from '@elytracms/core/operations'\nimport type { BuildFragmentError, FragmentParseError } from '@elytracms/core/clipboard'\nimport type { ContentQueryError } from '@elytracms/core/content'\nimport type { CustomizationIssue } from '@elytracms/core/studio-core'\nimport type { ComponentManifest } from '@elytracms/core/component-registry'\nimport { localizedLabel, translate } from '../i18n'\nimport { humanizeName } from '../utils'\n\n/**\n * Persona-aware labels (EC-192 item 2, Milestone B promise).\n *\n * A non-technical editor must never see a manifest/binding/path-token/validation\n * identifier on — or one click off — the editor path. The engine speaks in stable\n * machine codes (`cmsIssueCodeSchema`, `operationErrorCodeSchema`) and machine ids\n * (`Heading`, `r-blog-slug-en`); this module is the single translation layer the\n * editor-facing surfaces route through.\n *\n * The maps are exhaustive `Record<…Code, string>` over the Zod enums, so adding a\n * code in `@elytracms/core/cms-core` or `@elytracms/core/operations`\n * fails typecheck here until it is given an editor-facing label — the persona\n * boundary cannot silently regress. A table is only worth that guard while something\n * renders it: EC-509 deleted two that nothing did (see below). Engineers keep the raw\n * code: every surface that\n * shows a label also carries the code in a `title=`/`data-*` attribute (inspectable\n * via hover/devtools, never rendered as visible copy).\n */\n\n/**\n * EC-509 — two label tables were DELETED here rather than localized, because measuring\n * first showed nothing rendered them.\n *\n * `GRAPH_ISSUE_LABELS`/`graphIssueLabel` (16 entries, project-graph `IssueCode`) and\n * `CONDITION_OPERATOR_LABELS`/`conditionOperatorLabel` (8, `ConditionOperator`) had\n * **zero call sites** outside this file and its own test — measured by grep over\n * `packages/` + `apps/`, with `cmsIssueLabel` (4 sites) and `operationErrorLabel` (1)\n * as the known-positive control that the search finds a render site when one exists.\n *\n * The graph table was unreachable structurally, not just unused: the ONE live path from\n * graph validation into the studio was `cms-composition-validators.ts` (since EC-582\n * `@elytracms/core/validation`'s `compositionValidators`), which maps a\n * graph issue to `CompositionIssue` — a type with `message`/`severity`/`nodePath` and\n * **no `code` field at all** (`cms-core/validate-document.ts:809`). The code an\n * exhaustiveness guard exists to force a label for cannot reach an editor surface.\n * `ConditionOperator` is live in the runtime renderer's condition gate\n * (`runtime-renderer/render.tsx:48`) but has no studio surface: v1 canvas is static\n * props, editor bindings parked, so no inspector ever shows an operator to name.\n *\n * **This overturns an EC-210 decision** (2026-06-17), which kept `graphIssueLabel` when\n * the validation panel was removed, on the rationale that it was \"the EC-192 boundary's\n * exhaustiveness guard, not panel code\". That was right then and its premise is false\n * now — the guard guards a boundary with no traffic, so it only forced editor copy for\n * strings no editor can see. Localizing them would have added 24 keys to the same\n * effect. If a surface ever renders these codes it needs labels written for it, and\n * will write them localized from the start.\n *\n * Neither symbol is referenced by either consumer repo (measured read-only) and neither\n * appears in docs.\n */\n\n/**\n * EC-443: the CMS issue titles live in the EC-241 message catalog\n * (`cms.issue.<code>`, EN source + shipped de), so the Issues pane / for-review\n * lane localize with the rest of the chrome. This map stays the exhaustive\n * `Record` over the Zod enum — a new code still fails typecheck here until it\n * gets an editor-facing catalog key (the persona boundary cannot silently\n * regress); {@link cmsIssueLabel} resolves it through `translate`.\n */\nconst CMS_ISSUE_LABEL_KEYS: Record<CmsIssueCode, string> = {\n 'duplicate-collection': 'cms.issue.duplicate-collection',\n 'duplicate-field': 'cms.issue.duplicate-field',\n 'unknown-collection': 'cms.issue.unknown-collection',\n 'invalid-collection-config': 'cms.issue.invalid-collection-config',\n 'invalid-field-config': 'cms.issue.invalid-field-config',\n 'reserved-field-name': 'cms.issue.reserved-field-name',\n 'prototype-key': 'cms.issue.prototype-key',\n 'missing-required-field': 'cms.issue.missing-required-field',\n 'invalid-field-value': 'cms.issue.invalid-field-value',\n 'unknown-relation-target': 'cms.issue.unknown-relation-target',\n 'unpublished-relation-target': 'cms.issue.unpublished-relation-target',\n 'cardinality-violation': 'cms.issue.cardinality-violation',\n 'unknown-asset': 'cms.issue.unknown-asset',\n 'asset-without-url': 'cms.issue.asset-without-url',\n 'asset-meta-drift': 'cms.issue.asset-meta-drift',\n 'duplicate-document': 'cms.issue.duplicate-document',\n 'unknown-locale': 'cms.issue.unknown-locale',\n 'missing-localized-value': 'cms.issue.missing-localized-value',\n 'route-conflict': 'cms.issue.route-conflict',\n 'redirect-loop': 'cms.issue.redirect-loop',\n 'invalid-redirect': 'cms.issue.invalid-redirect',\n 'invalid-route': 'cms.issue.invalid-route',\n 'unknown-route-target': 'cms.issue.unknown-route-target',\n 'hierarchy-cycle': 'cms.issue.hierarchy-cycle',\n 'document-nesting-depth': 'cms.issue.document-nesting-depth',\n 'singleton-document-drift': 'cms.issue.singleton-document-drift',\n 'duplicate-alias': 'cms.issue.duplicate-alias',\n 'unknown-alias': 'cms.issue.unknown-alias',\n 'unfilled-slot': 'cms.issue.unfilled-slot',\n 'custom-validation': 'cms.issue.custom-validation',\n 'hidden-predicate-error': 'cms.issue.hidden-predicate-error',\n 'unaddressable-url': 'cms.issue.unaddressable-url',\n 'unknown-version': 'cms.issue.unknown-version',\n 'invalid-stored-document': 'cms.issue.invalid-stored-document',\n 'props-not-judged': 'cms.issue.props-not-judged',\n}\n\n/**\n * EC-507 rider — the few codes whose TITLE overstates at `warning` severity.\n *\n * `invalid-field-value` reads \"Invalid value\", which is right when the value is\n * rejected (wrong type, not among its options) and wrong when it is not: EC-472\n * deliberately STORES `0202-09-18` as a legal ISO date and merely flags the year as\n * probably unintended. A title calling that invalid contradicts the value the editor\n * can plainly see was accepted, on all three surfaces at once.\n *\n * Keyed on SEVERITY rather than on the implausible-year case specifically, because\n * the overstatement belongs to the severity: any future warning under this code has\n * the same property (the value was kept), and the fix then needs no new entry. A\n * sparse `Partial` on purpose — a code with no entry keeps one title for both\n * severities, which is the correct default and keeps\n * {@link CMS_ISSUE_LABEL_KEYS} the single exhaustive map.\n */\nconst CMS_ISSUE_WARNING_LABEL_KEYS: Partial<Record<CmsIssueCode, string>> = {\n 'invalid-field-value': 'cms.issue.invalid-field-value.warning',\n}\n\n/**\n * EC-494: the badge titles live in the EC-241 catalog (`operations.errorLabel.<code>`),\n * exactly as EC-443 moved the CMS issue titles. **Measured before changing it:** this\n * map was a hard-coded English `Record`, so once the EC-494 bodies localized the banner\n * rendered a German sentence under an English badge — the inverse of the bug this\n * ticket exists for, and not what the ticket said was there. Still the exhaustive\n * `Record` over the Zod enum, so a new code fails typecheck until it has a key.\n */\nconst OPERATION_ERROR_LABEL_KEYS: Record<OperationErrorCode, string> = {\n validation: 'operations.errorLabel.validation',\n 'not-found': 'operations.errorLabel.not-found',\n conflict: 'operations.errorLabel.conflict',\n 'backend-unavailable': 'operations.errorLabel.backend-unavailable',\n unauthorized: 'operations.errorLabel.unauthorized',\n unknown: 'operations.errorLabel.unknown',\n}\n\n/**\n * Plain-language title for a CMS validation issue code — localized against the\n * active studio-UI locale (EC-443). A runtime-unknown code (impossible typewise;\n * a cast could smuggle one) degrades to its humanized form, never the raw enum.\n *\n * `severity` is optional and additive (EC-507): pass the issue's own severity and a\n * code with a softer warning title (see {@link CMS_ISSUE_WARNING_LABEL_KEYS}) uses\n * it; omit it, or pass `'error'`, and nothing changes. Every render site passes it —\n * the parameter is optional so that a pure/unit caller naming only a code still\n * compiles, not because a surface may skip it.\n */\nexport function cmsIssueLabel(code: CmsIssueCode, severity?: CmsIssueSeverity): string {\n const key =\n (severity === 'warning' ? CMS_ISSUE_WARNING_LABEL_KEYS[code] : undefined) ??\n (CMS_ISSUE_LABEL_KEYS[code] as string | undefined)\n return key !== undefined ? translate(key) : humanizeName(code)\n}\n\n/**\n * The localized text of a {@link CustomizationIssue} (EC-478) — the ONE place the\n * studio turns a config-level finding into rendered prose.\n *\n * The producing layer (`studio-core/customization.ts`, `app-views/default-modules.tsx`,\n * `builder/reuse.ts`) cannot own the wording: the EC-236 seam lives in `packages/core`,\n * a leaf of the DAG that may not import this catalog. So it emits a\n * `CustomizationMessageRef` — a stable key plus its interpolation values, all of\n * which are IDENTIFIERS (entry ids, extension points, component ids) and therefore the\n * same in every language — and this resolves it against the active UI locale. Same\n * shape as {@link cmsIssueLabel}, one layer down: the engine speaks codes and keys, the\n * studio speaks the editor's language.\n *\n * `messageRef.reason` fills the `{reason}` slot of `invalid-override`, whose detail is\n * itself prose (a `validate` rejection) and so carries its own key. A ref-less issue —\n * a third-party producer of this published type — degrades to its English\n * `issue.message`, which is honest: a visible English sentence beats a missing key.\n */\nexport function customizationIssueMessage(issue: CustomizationIssue): string {\n const ref = issue.messageRef\n if (!ref) return issue.message\n const vars = { ...ref.vars }\n if (ref.reason) vars.reason = translate(ref.reason.key, ref.reason.vars)\n return translate(ref.key, vars)\n}\n\n/**\n * The localized BODY of a {@link CmsValidationIssue} (EC-487) — the ONE place the\n * studio turns a CMS validation finding into rendered prose, exactly as\n * {@link customizationIssueMessage} does one layer up.\n *\n * EC-443 localized the issue TITLES ({@link cmsIssueLabel}); the bodies stayed English\n * because their producers live in `packages/core`, below this catalog in the DAG. So\n * the producer emits a `CmsMessageRef` — a stable key plus its interpolation values,\n * all of which are IDENTIFIERS (field/collection/route ids, locales, patterns, counts)\n * and therefore the same in every language — and this resolves it against the active\n * UI locale.\n *\n * `messageRef.details` fill placeholders whose text is itself prose, keyed by\n * placeholder name. A placeholder with no entry keeps whatever the producer put in\n * `vars` — the honest outcome for prose the engine did not author (a config-as-code\n * `validate` message, a composition finding), which then stays in its original\n * language rather than vanishing. A ref-less issue — a third-party producer of this\n * published type — degrades to its English `issue.message`: a visible English sentence\n * beats a missing key.\n */\nexport function cmsValidationIssueMessage(issue: CmsValidationIssue): string {\n return resolveMessageRef(issue.messageRef, issue.message)\n}\n\n/**\n * EC-494 — the ONE resolver every carried message ref goes through.\n *\n * Four published types now carry the same `{ key, vars?, details? }` reference —\n * `CmsValidationIssue` (EC-487), `CustomizationIssue` (EC-478, via its own `reason`\n * slot), and now `OperationIssue`/`OperationError` and the clipboard + content-query\n * errors. They are separate declarations only because the EC-265 DAG forbids the\n * lower subpaths from importing `cms-core`; the RESOLUTION is one rule, so it lives\n * in one function.\n *\n * `fallback` is the producer's prebuilt English, rendered whenever there is no ref —\n * a third-party producer, a Zod diagnostic, a persistence-layer message, a\n * config-authored `validate` string. A visible English sentence beats a missing key\n * (EC-443).\n */\nfunction resolveMessageRef(\n ref:\n | {\n readonly key: string\n readonly vars?: Readonly<Record<string, string | number>>\n readonly details?: Readonly<\n Record<string, { readonly key: string; readonly vars?: Readonly<Record<string, string | number>> }>\n >\n }\n | undefined,\n fallback: string,\n): string {\n if (!ref) return fallback\n const vars: Record<string, string | number> = { ...ref.vars }\n for (const [placeholder, nested] of Object.entries(ref.details ?? {})) {\n vars[placeholder] = translate(nested.key, nested.vars)\n }\n return translate(ref.key, vars)\n}\n\n/**\n * The localized text of ONE {@link OperationIssue} line in the error banner (EC-494).\n *\n * These issues cross a process boundary: `operations/documents.ts` rebuilds a\n * `CmsValidationIssue` as an `OperationIssue` **server-side, with no locale**, so the\n * producer cannot translate and the catalog key rides on the wire instead. A ref-less\n * issue — a Zod input diagnostic, a persistence-layer message, a third-party producer\n * of this published type — keeps its English.\n */\nexport function operationIssueMessage(issue: OperationIssue): string {\n return resolveMessageRef(issue.messageRef, issue.message)\n}\n\n/**\n * The localized ENVELOPE sentence of an {@link OperationError} (EC-494) — the line\n * beside the localized badge in `OperationErrorBanner`. Localizing only the issue\n * lines would have left exactly one English sentence under a German badge.\n */\nexport function operationErrorMessage(error: OperationError): string {\n return resolveMessageRef(error.messageRef, error.message)\n}\n\n/**\n * The localized text of a clipboard fragment failure (EC-494) — parse (`corrupt-json`,\n * `foreign-format`, `unsupported-version`, `invalid-payload`) or build\n * (`node-not-found`, `fixture-not-found`), rendered by the builder's paste notice.\n */\nexport function clipboardErrorMessage(error: FragmentParseError | BuildFragmentError): string {\n return resolveMessageRef(error.messageRef, error.message)\n}\n\n/**\n * The localized text of a {@link ContentQueryError} (EC-494) — the filter builder's\n * per-clause line and the canvas listing notice, both of which render errors built by\n * `core/content`'s `validateWhere`/`validateSort`/`validateLimit`.\n */\nexport function contentQueryErrorMessage(error: ContentQueryError): string {\n return resolveMessageRef(error.messageRef, error.message)\n}\n\n/**\n * Plain-language title for an operation failure code — localized against the active\n * studio-UI locale. A runtime-unknown code (impossible typewise; a cast could smuggle\n * one) degrades to the generic title, never the raw enum.\n */\nexport function operationErrorLabel(code: OperationErrorCode): string {\n const key = OPERATION_ERROR_LABEL_KEYS[code] as string | undefined\n return translate(key ?? OPERATION_ERROR_LABEL_KEYS.unknown)\n}\n\n/** The last dot-segment of a component id (`site.Hero` → `Hero`; `Heading` → `Heading`). */\nexport function componentLeafId(componentId: string): string {\n const dot = componentId.lastIndexOf('.')\n return dot === -1 ? componentId : componentId.slice(dot + 1)\n}\n\n/**\n * The human display name of a component TYPE for editor-facing surfaces: the\n * manifest's authored `title` (EC-407: resolved through {@link resolveLabel}, so a\n * `{ en, de }` localized title renders in the active studio-UI locale) when present,\n * else the humanized leaf of its id (`Heading` → `Heading`,\n * `site.MarketingHero` → `Marketing hero`). EC-591: the engine strips no id\n * prefix anywhere else — a label reads the manifest title.\n *\n * `locale` is optional: omit it (the render-site default) to resolve against the\n * active studio-UI locale non-reactively; pass it explicitly for pure/unit callers.\n */\nexport function componentDisplayName(\n componentId: string,\n manifest?: ComponentManifest | undefined,\n locale?: string,\n): string {\n const resolved =\n locale === undefined ? localizedLabel(manifest?.title) : (resolveLabel(manifest?.title, locale) ?? '')\n return resolved || humanizeName(componentLeafId(componentId))\n}\n"]}
1
+ {"version":3,"file":"labels.js","sourceRoot":"","sources":["../../../src/lib/persona/labels.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CmsIssueCode, CmsIssueSeverity, CmsValidationIssue } from '@elytracms/core/cms-core'\nimport { resolveLabel } from '@elytracms/core/cms-core'\nimport type { OperationError, OperationErrorCode, OperationIssue } from '@elytracms/core/operations'\nimport type { BuildFragmentError, FragmentParseError } from '@elytracms/core/clipboard'\nimport type { ContentQueryError } from '@elytracms/core/content'\nimport type { CustomizationIssue } from '@elytracms/core/studio-core'\nimport type { ComponentManifest } from '@elytracms/core/component-registry'\nimport { localizedLabel, translate } from '../i18n'\nimport { humanizeName } from '../utils'\n\n/**\n * Persona-aware labels (EC-192 item 2, Milestone B promise).\n *\n * A non-technical editor must never see a manifest/binding/path-token/validation\n * identifier on — or one click off — the editor path. The engine speaks in stable\n * machine codes (`cmsIssueCodeSchema`, `operationErrorCodeSchema`) and machine ids\n * (`Heading`, `r-blog-slug-en`); this module is the single translation layer the\n * editor-facing surfaces route through.\n *\n * The maps are exhaustive `Record<…Code, string>` over the Zod enums, so adding a\n * code in `@elytracms/core/cms-core` or `@elytracms/core/operations`\n * fails typecheck here until it is given an editor-facing label — the persona\n * boundary cannot silently regress. A table is only worth that guard while something\n * renders it: EC-509 deleted two that nothing did (see below). Engineers keep the raw\n * code: every surface that\n * shows a label also carries the code in a `title=`/`data-*` attribute (inspectable\n * via hover/devtools, never rendered as visible copy).\n */\n\n/**\n * EC-509 — two label tables were DELETED here rather than localized, because measuring\n * first showed nothing rendered them.\n *\n * `GRAPH_ISSUE_LABELS`/`graphIssueLabel` (16 entries, project-graph `IssueCode`) and\n * `CONDITION_OPERATOR_LABELS`/`conditionOperatorLabel` (8, `ConditionOperator`) had\n * **zero call sites** outside this file and its own test — measured by grep over\n * `packages/` + `apps/`, with `cmsIssueLabel` (4 sites) and `operationErrorLabel` (1)\n * as the known-positive control that the search finds a render site when one exists.\n *\n * The graph table was unreachable structurally, not just unused: the ONE live path from\n * graph validation into the studio was `cms-composition-validators.ts` (since EC-582\n * `@elytracms/core/validation`'s `compositionValidators`), which maps a\n * graph issue to `CompositionIssue` — a type with `message`/`severity`/`nodePath` and\n * **no `code` field at all** (`cms-core/validate-document.ts:809`). The code an\n * exhaustiveness guard exists to force a label for cannot reach an editor surface.\n * `ConditionOperator` is live in the runtime renderer's condition gate\n * (`runtime-renderer/render.tsx:48`) but has no studio surface: v1 canvas is static\n * props, editor bindings parked, so no inspector ever shows an operator to name.\n *\n * **This overturns an EC-210 decision** (2026-06-17), which kept `graphIssueLabel` when\n * the validation panel was removed, on the rationale that it was \"the EC-192 boundary's\n * exhaustiveness guard, not panel code\". That was right then and its premise is false\n * now — the guard guards a boundary with no traffic, so it only forced editor copy for\n * strings no editor can see. Localizing them would have added 24 keys to the same\n * effect. If a surface ever renders these codes it needs labels written for it, and\n * will write them localized from the start.\n *\n * Neither symbol is referenced by either consumer repo (measured read-only) and neither\n * appears in docs.\n */\n\n/**\n * EC-443: the CMS issue titles live in the EC-241 message catalog\n * (`cms.issue.<code>`, EN source + shipped de), so the Issues pane / for-review\n * lane localize with the rest of the chrome. This map stays the exhaustive\n * `Record` over the Zod enum — a new code still fails typecheck here until it\n * gets an editor-facing catalog key (the persona boundary cannot silently\n * regress); {@link cmsIssueLabel} resolves it through `translate`.\n */\nconst CMS_ISSUE_LABEL_KEYS: Record<CmsIssueCode, string> = {\n 'duplicate-collection': 'cms.issue.duplicate-collection',\n 'duplicate-field': 'cms.issue.duplicate-field',\n 'unknown-collection': 'cms.issue.unknown-collection',\n 'invalid-collection-config': 'cms.issue.invalid-collection-config',\n 'invalid-field-config': 'cms.issue.invalid-field-config',\n 'reserved-field-name': 'cms.issue.reserved-field-name',\n 'prototype-key': 'cms.issue.prototype-key',\n 'missing-required-field': 'cms.issue.missing-required-field',\n 'invalid-field-value': 'cms.issue.invalid-field-value',\n 'unknown-relation-target': 'cms.issue.unknown-relation-target',\n 'unpublished-relation-target': 'cms.issue.unpublished-relation-target',\n 'cardinality-violation': 'cms.issue.cardinality-violation',\n 'unknown-asset': 'cms.issue.unknown-asset',\n 'asset-without-url': 'cms.issue.asset-without-url',\n 'asset-meta-drift': 'cms.issue.asset-meta-drift',\n 'duplicate-document': 'cms.issue.duplicate-document',\n 'duplicate-node-id': 'cms.issue.duplicate-node-id',\n 'unknown-locale': 'cms.issue.unknown-locale',\n 'missing-localized-value': 'cms.issue.missing-localized-value',\n 'route-conflict': 'cms.issue.route-conflict',\n 'redirect-loop': 'cms.issue.redirect-loop',\n 'invalid-redirect': 'cms.issue.invalid-redirect',\n 'invalid-route': 'cms.issue.invalid-route',\n 'unknown-route-target': 'cms.issue.unknown-route-target',\n 'hierarchy-cycle': 'cms.issue.hierarchy-cycle',\n 'document-nesting-depth': 'cms.issue.document-nesting-depth',\n 'singleton-document-drift': 'cms.issue.singleton-document-drift',\n 'duplicate-alias': 'cms.issue.duplicate-alias',\n 'unknown-alias': 'cms.issue.unknown-alias',\n 'unfilled-slot': 'cms.issue.unfilled-slot',\n 'custom-validation': 'cms.issue.custom-validation',\n 'hidden-predicate-error': 'cms.issue.hidden-predicate-error',\n 'unaddressable-url': 'cms.issue.unaddressable-url',\n 'unknown-version': 'cms.issue.unknown-version',\n 'invalid-stored-document': 'cms.issue.invalid-stored-document',\n 'props-not-judged': 'cms.issue.props-not-judged',\n}\n\n/**\n * EC-507 rider — the few codes whose TITLE overstates at `warning` severity.\n *\n * `invalid-field-value` reads \"Invalid value\", which is right when the value is\n * rejected (wrong type, not among its options) and wrong when it is not: EC-472\n * deliberately STORES `0202-09-18` as a legal ISO date and merely flags the year as\n * probably unintended. A title calling that invalid contradicts the value the editor\n * can plainly see was accepted, on all three surfaces at once.\n *\n * Keyed on SEVERITY rather than on the implausible-year case specifically, because\n * the overstatement belongs to the severity: any future warning under this code has\n * the same property (the value was kept), and the fix then needs no new entry. A\n * sparse `Partial` on purpose — a code with no entry keeps one title for both\n * severities, which is the correct default and keeps\n * {@link CMS_ISSUE_LABEL_KEYS} the single exhaustive map.\n */\nconst CMS_ISSUE_WARNING_LABEL_KEYS: Partial<Record<CmsIssueCode, string>> = {\n 'invalid-field-value': 'cms.issue.invalid-field-value.warning',\n}\n\n/**\n * EC-494: the badge titles live in the EC-241 catalog (`operations.errorLabel.<code>`),\n * exactly as EC-443 moved the CMS issue titles. **Measured before changing it:** this\n * map was a hard-coded English `Record`, so once the EC-494 bodies localized the banner\n * rendered a German sentence under an English badge — the inverse of the bug this\n * ticket exists for, and not what the ticket said was there. Still the exhaustive\n * `Record` over the Zod enum, so a new code fails typecheck until it has a key.\n */\nconst OPERATION_ERROR_LABEL_KEYS: Record<OperationErrorCode, string> = {\n validation: 'operations.errorLabel.validation',\n 'not-found': 'operations.errorLabel.not-found',\n conflict: 'operations.errorLabel.conflict',\n 'backend-unavailable': 'operations.errorLabel.backend-unavailable',\n unauthorized: 'operations.errorLabel.unauthorized',\n unknown: 'operations.errorLabel.unknown',\n}\n\n/**\n * Plain-language title for a CMS validation issue code — localized against the\n * active studio-UI locale (EC-443). A runtime-unknown code (impossible typewise;\n * a cast could smuggle one) degrades to its humanized form, never the raw enum.\n *\n * `severity` is optional and additive (EC-507): pass the issue's own severity and a\n * code with a softer warning title (see {@link CMS_ISSUE_WARNING_LABEL_KEYS}) uses\n * it; omit it, or pass `'error'`, and nothing changes. Every render site passes it —\n * the parameter is optional so that a pure/unit caller naming only a code still\n * compiles, not because a surface may skip it.\n */\nexport function cmsIssueLabel(code: CmsIssueCode, severity?: CmsIssueSeverity): string {\n const key =\n (severity === 'warning' ? CMS_ISSUE_WARNING_LABEL_KEYS[code] : undefined) ??\n (CMS_ISSUE_LABEL_KEYS[code] as string | undefined)\n return key !== undefined ? translate(key) : humanizeName(code)\n}\n\n/**\n * The localized text of a {@link CustomizationIssue} (EC-478) — the ONE place the\n * studio turns a config-level finding into rendered prose.\n *\n * The producing layer (`studio-core/customization.ts`, `app-views/default-modules.tsx`,\n * `builder/reuse.ts`) cannot own the wording: the EC-236 seam lives in `packages/core`,\n * a leaf of the DAG that may not import this catalog. So it emits a\n * `CustomizationMessageRef` — a stable key plus its interpolation values, all of\n * which are IDENTIFIERS (entry ids, extension points, component ids) and therefore the\n * same in every language — and this resolves it against the active UI locale. Same\n * shape as {@link cmsIssueLabel}, one layer down: the engine speaks codes and keys, the\n * studio speaks the editor's language.\n *\n * `messageRef.reason` fills the `{reason}` slot of `invalid-override`, whose detail is\n * itself prose (a `validate` rejection) and so carries its own key. A ref-less issue —\n * a third-party producer of this published type — degrades to its English\n * `issue.message`, which is honest: a visible English sentence beats a missing key.\n */\nexport function customizationIssueMessage(issue: CustomizationIssue): string {\n const ref = issue.messageRef\n if (!ref) return issue.message\n const vars = { ...ref.vars }\n if (ref.reason) vars.reason = translate(ref.reason.key, ref.reason.vars)\n return translate(ref.key, vars)\n}\n\n/**\n * The localized BODY of a {@link CmsValidationIssue} (EC-487) — the ONE place the\n * studio turns a CMS validation finding into rendered prose, exactly as\n * {@link customizationIssueMessage} does one layer up.\n *\n * EC-443 localized the issue TITLES ({@link cmsIssueLabel}); the bodies stayed English\n * because their producers live in `packages/core`, below this catalog in the DAG. So\n * the producer emits a `CmsMessageRef` — a stable key plus its interpolation values,\n * all of which are IDENTIFIERS (field/collection/route ids, locales, patterns, counts)\n * and therefore the same in every language — and this resolves it against the active\n * UI locale.\n *\n * `messageRef.details` fill placeholders whose text is itself prose, keyed by\n * placeholder name. A placeholder with no entry keeps whatever the producer put in\n * `vars` — the honest outcome for prose the engine did not author (a config-as-code\n * `validate` message, a composition finding), which then stays in its original\n * language rather than vanishing. A ref-less issue — a third-party producer of this\n * published type — degrades to its English `issue.message`: a visible English sentence\n * beats a missing key.\n */\nexport function cmsValidationIssueMessage(issue: CmsValidationIssue): string {\n return resolveMessageRef(issue.messageRef, issue.message)\n}\n\n/**\n * EC-494 — the ONE resolver every carried message ref goes through.\n *\n * Four published types now carry the same `{ key, vars?, details? }` reference —\n * `CmsValidationIssue` (EC-487), `CustomizationIssue` (EC-478, via its own `reason`\n * slot), and now `OperationIssue`/`OperationError` and the clipboard + content-query\n * errors. They are separate declarations only because the EC-265 DAG forbids the\n * lower subpaths from importing `cms-core`; the RESOLUTION is one rule, so it lives\n * in one function.\n *\n * `fallback` is the producer's prebuilt English, rendered whenever there is no ref —\n * a third-party producer, a Zod diagnostic, a persistence-layer message, a\n * config-authored `validate` string. A visible English sentence beats a missing key\n * (EC-443).\n */\nfunction resolveMessageRef(\n ref:\n | {\n readonly key: string\n readonly vars?: Readonly<Record<string, string | number>>\n readonly details?: Readonly<\n Record<string, { readonly key: string; readonly vars?: Readonly<Record<string, string | number>> }>\n >\n }\n | undefined,\n fallback: string,\n): string {\n if (!ref) return fallback\n const vars: Record<string, string | number> = { ...ref.vars }\n for (const [placeholder, nested] of Object.entries(ref.details ?? {})) {\n vars[placeholder] = translate(nested.key, nested.vars)\n }\n return translate(ref.key, vars)\n}\n\n/**\n * The localized text of ONE {@link OperationIssue} line in the error banner (EC-494).\n *\n * These issues cross a process boundary: `operations/documents.ts` rebuilds a\n * `CmsValidationIssue` as an `OperationIssue` **server-side, with no locale**, so the\n * producer cannot translate and the catalog key rides on the wire instead. A ref-less\n * issue — a Zod input diagnostic, a persistence-layer message, a third-party producer\n * of this published type — keeps its English.\n */\nexport function operationIssueMessage(issue: OperationIssue): string {\n return resolveMessageRef(issue.messageRef, issue.message)\n}\n\n/**\n * The localized ENVELOPE sentence of an {@link OperationError} (EC-494) — the line\n * beside the localized badge in `OperationErrorBanner`. Localizing only the issue\n * lines would have left exactly one English sentence under a German badge.\n */\nexport function operationErrorMessage(error: OperationError): string {\n return resolveMessageRef(error.messageRef, error.message)\n}\n\n/**\n * The localized text of a clipboard fragment failure (EC-494) — parse (`corrupt-json`,\n * `foreign-format`, `unsupported-version`, `invalid-payload`) or build\n * (`node-not-found`, `fixture-not-found`), rendered by the builder's paste notice.\n */\nexport function clipboardErrorMessage(error: FragmentParseError | BuildFragmentError): string {\n return resolveMessageRef(error.messageRef, error.message)\n}\n\n/**\n * The localized text of a {@link ContentQueryError} (EC-494) — the filter builder's\n * per-clause line and the canvas listing notice, both of which render errors built by\n * `core/content`'s `validateWhere`/`validateSort`/`validateLimit`.\n */\nexport function contentQueryErrorMessage(error: ContentQueryError): string {\n return resolveMessageRef(error.messageRef, error.message)\n}\n\n/**\n * Plain-language title for an operation failure code — localized against the active\n * studio-UI locale. A runtime-unknown code (impossible typewise; a cast could smuggle\n * one) degrades to the generic title, never the raw enum.\n */\nexport function operationErrorLabel(code: OperationErrorCode): string {\n const key = OPERATION_ERROR_LABEL_KEYS[code] as string | undefined\n return translate(key ?? OPERATION_ERROR_LABEL_KEYS.unknown)\n}\n\n/** The last dot-segment of a component id (`site.Hero` → `Hero`; `Heading` → `Heading`). */\nexport function componentLeafId(componentId: string): string {\n const dot = componentId.lastIndexOf('.')\n return dot === -1 ? componentId : componentId.slice(dot + 1)\n}\n\n/**\n * The human display name of a component TYPE for editor-facing surfaces: the\n * manifest's authored `title` (EC-407: resolved through {@link resolveLabel}, so a\n * `{ en, de }` localized title renders in the active studio-UI locale) when present,\n * else the humanized leaf of its id (`Heading` → `Heading`,\n * `site.MarketingHero` → `Marketing hero`). EC-591: the engine strips no id\n * prefix anywhere else — a label reads the manifest title.\n *\n * `locale` is optional: omit it (the render-site default) to resolve against the\n * active studio-UI locale non-reactively; pass it explicitly for pure/unit callers.\n */\nexport function componentDisplayName(\n componentId: string,\n manifest?: ComponentManifest | undefined,\n locale?: string,\n): string {\n const resolved =\n locale === undefined ? localizedLabel(manifest?.title) : (resolveLabel(manifest?.title, locale) ?? '')\n return resolved || humanizeName(componentLeafId(componentId))\n}\n"]}
@@ -32,7 +32,8 @@ export declare function previewSpecs(manifest: ComponentManifest, registry: Comp
32
32
  * The `Default` preview of a fixture-less component — the seeded node the blocks panel
33
33
  * inserts (a layout container pre-filled through its role, EC-383) with the seed's
34
34
  * placeholder ids re-minted deterministically (root `…-0`, then `…-0-1`, `…-0-2` …), so
35
- * every node has a distinct, stable id. The builder store re-ids an insert itself; a
35
+ * every node has a distinct, stable id — at every depth, the nodes its props hold included
36
+ * (EC-776: `withFreshNodeIds`, the one copy). The builder store re-ids an insert itself; a
36
37
  * preview renders the seed directly, and React keys slot children by node id — the
37
38
  * seed's shared `tmp` placeholder was a duplicate key (EC-624). Both preview surfaces
38
39
  * (the Components view and `elytra previews`) render this one node.
@@ -1,4 +1,6 @@
1
- import { cloneWithNewIds, staticProp } from '@elytracms/core/project-graph';
1
+ import { staticProp } from '@elytracms/core/project-graph';
2
+ import { withFreshNodeIds } from '@elytracms/core/cms-core';
3
+ import { propFieldLookupOf } from '@elytracms/core/component-registry';
2
4
  import { seededNodeFromManifest } from '../../components/builder/node-factory.js';
3
5
  /**
4
6
  * A node carrying exactly the given prop values (EC-591 / ratified 2f): a prop
@@ -43,7 +45,8 @@ export function previewSpecs(manifest, registry) {
43
45
  * The `Default` preview of a fixture-less component — the seeded node the blocks panel
44
46
  * inserts (a layout container pre-filled through its role, EC-383) with the seed's
45
47
  * placeholder ids re-minted deterministically (root `…-0`, then `…-0-1`, `…-0-2` …), so
46
- * every node has a distinct, stable id. The builder store re-ids an insert itself; a
48
+ * every node has a distinct, stable id — at every depth, the nodes its props hold included
49
+ * (EC-776: `withFreshNodeIds`, the one copy). The builder store re-ids an insert itself; a
47
50
  * preview renders the seed directly, and React keys slot children by node id — the
48
51
  * seed's shared `tmp` placeholder was a duplicate key (EC-624). Both preview surfaces
49
52
  * (the Components view and `elytra previews`) render this one node.
@@ -51,6 +54,8 @@ export function previewSpecs(manifest, registry) {
51
54
  export function defaultPreviewNode(manifest, registry) {
52
55
  const base = `preview-${manifest.id}-0`;
53
56
  let n = 0;
54
- return cloneWithNewIds(seededNodeFromManifest(manifest, registry), () => (n++ === 0 ? base : `${base}-${n - 1}`));
57
+ return withFreshNodeIds(seededNodeFromManifest(manifest, registry), () => (n++ === 0 ? base : `${base}-${n - 1}`), {
58
+ lookupManifest: propFieldLookupOf((id) => registry.getManifest(id)),
59
+ });
55
60
  }
56
61
  //# sourceMappingURL=preview.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"preview.js","sourceRoot":"","sources":["../../../src/lib/registry/preview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAG3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;AAQ9E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAC3B,QAA2B,EAC3B,MAAiC,EACjC,EAAU;IAEV,MAAM,KAAK,GAA2B,EAAE,CAAA;IACxC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;QAC1B,IAAI,KAAK,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;IAC1D,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,CAAA;AAChD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,QAA2B,EAAE,QAA2B;IACnF,IAAI,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtD,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5C,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE,EAAE,WAAW,QAAQ,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC;SAClF,CAAC,CAAC,CAAA;IACL,CAAC;IACD,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAA;AAC5E,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAA2B,EAAE,QAA2B;IACzF,MAAM,IAAI,GAAG,WAAW,QAAQ,CAAC,EAAE,IAAI,CAAA;IACvC,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,eAAe,CAAC,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;AACnH,CAAC","sourcesContent":["import { cloneWithNewIds, staticProp } from '@elytracms/core/project-graph'\nimport type { ComponentNode, JsonValue } from '@elytracms/core/project-graph'\nimport type { ComponentManifest, ComponentRegistry } from '@elytracms/core/component-registry'\nimport { seededNodeFromManifest } from '../../components/builder/node-factory'\n\n/** A named, renderable preview state for a component. */\nexport interface PreviewSpec {\n name: string\n node: ComponentNode\n}\n\n/**\n * A node carrying exactly the given prop values (EC-591 / ratified 2f): a prop\n * the caller does not set stays ABSENT — the implementation's own default applies\n * — and the manifest `default` is never copied in (it is an authoring hint). Until\n * EC-591 this overlaid the overrides on every manifest default, so a fixture\n * insert stored — and rendered — something other than the same fixture pasted\n * from \"copy exact configuration\" (COMPOSITION #19).\n *\n * Node ids are derived deterministically from a stable base (manifest id +\n * fixture index) so previews are byte-identical across SSR and client hydration\n * and reproducible across runs — no module-level counter, no time/random.\n */\nexport function nodeFromProps(\n manifest: ComponentManifest,\n values: Record<string, JsonValue>,\n id: string,\n): ComponentNode {\n const props: ComponentNode['props'] = {}\n for (const name of Object.keys(manifest.props)) {\n const value = values[name]\n if (value !== undefined) props[name] = staticProp(value)\n }\n return { id, componentId: manifest.id, props }\n}\n\n/**\n * Resolve the preview states for a component (brief §7.2, §8.3, EC-054): the\n * declared manifest fixtures; otherwise the single `Default` — the SAME seeded\n * node the blocks panel inserts and `elytra previews` renders for a fixture-less\n * component (a layout container comes pre-filled through its role, EC-383).\n * EC-591: there are no authored previews keyed by engine ids any more — a\n * component that wants a richer preview declares `fixtures`, like any other.\n * Deterministic ids throughout.\n */\nexport function previewSpecs(manifest: ComponentManifest, registry: ComponentRegistry): PreviewSpec[] {\n if (manifest.fixtures && manifest.fixtures.length > 0) {\n return manifest.fixtures.map((fixture, i) => ({\n name: fixture.name,\n node: nodeFromProps(manifest, fixture.props ?? {}, `preview-${manifest.id}-${i}`),\n }))\n }\n return [{ name: 'Default', node: defaultPreviewNode(manifest, registry) }]\n}\n\n/**\n * The `Default` preview of a fixture-less component — the seeded node the blocks panel\n * inserts (a layout container pre-filled through its role, EC-383) with the seed's\n * placeholder ids re-minted deterministically (root `…-0`, then `…-0-1`, `…-0-2` …), so\n * every node has a distinct, stable id. The builder store re-ids an insert itself; a\n * preview renders the seed directly, and React keys slot children by node id — the\n * seed's shared `tmp` placeholder was a duplicate key (EC-624). Both preview surfaces\n * (the Components view and `elytra previews`) render this one node.\n */\nexport function defaultPreviewNode(manifest: ComponentManifest, registry: ComponentRegistry): ComponentNode {\n const base = `preview-${manifest.id}-0`\n let n = 0\n return cloneWithNewIds(seededNodeFromManifest(manifest, registry), () => (n++ === 0 ? base : `${base}-${n - 1}`))\n}\n"]}
1
+ {"version":3,"file":"preview.js","sourceRoot":"","sources":["../../../src/lib/registry/preview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAA;AAEtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;AAQ9E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAC3B,QAA2B,EAC3B,MAAiC,EACjC,EAAU;IAEV,MAAM,KAAK,GAA2B,EAAE,CAAA;IACxC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;QAC1B,IAAI,KAAK,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;IAC1D,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,CAAA;AAChD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,QAA2B,EAAE,QAA2B;IACnF,IAAI,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtD,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5C,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE,EAAE,WAAW,QAAQ,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC;SAClF,CAAC,CAAC,CAAA;IACL,CAAC;IACD,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAA;AAC5E,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAA2B,EAAE,QAA2B;IACzF,MAAM,IAAI,GAAG,WAAW,QAAQ,CAAC,EAAE,IAAI,CAAA;IACvC,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,gBAAgB,CAAC,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;QACjH,cAAc,EAAE,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;KACpE,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { staticProp } from '@elytracms/core/project-graph'\nimport type { ComponentNode, JsonValue } from '@elytracms/core/project-graph'\nimport { withFreshNodeIds } from '@elytracms/core/cms-core'\nimport { propFieldLookupOf } from '@elytracms/core/component-registry'\nimport type { ComponentManifest, ComponentRegistry } from '@elytracms/core/component-registry'\nimport { seededNodeFromManifest } from '../../components/builder/node-factory'\n\n/** A named, renderable preview state for a component. */\nexport interface PreviewSpec {\n name: string\n node: ComponentNode\n}\n\n/**\n * A node carrying exactly the given prop values (EC-591 / ratified 2f): a prop\n * the caller does not set stays ABSENT — the implementation's own default applies\n * — and the manifest `default` is never copied in (it is an authoring hint). Until\n * EC-591 this overlaid the overrides on every manifest default, so a fixture\n * insert stored — and rendered — something other than the same fixture pasted\n * from \"copy exact configuration\" (COMPOSITION #19).\n *\n * Node ids are derived deterministically from a stable base (manifest id +\n * fixture index) so previews are byte-identical across SSR and client hydration\n * and reproducible across runs — no module-level counter, no time/random.\n */\nexport function nodeFromProps(\n manifest: ComponentManifest,\n values: Record<string, JsonValue>,\n id: string,\n): ComponentNode {\n const props: ComponentNode['props'] = {}\n for (const name of Object.keys(manifest.props)) {\n const value = values[name]\n if (value !== undefined) props[name] = staticProp(value)\n }\n return { id, componentId: manifest.id, props }\n}\n\n/**\n * Resolve the preview states for a component (brief §7.2, §8.3, EC-054): the\n * declared manifest fixtures; otherwise the single `Default` — the SAME seeded\n * node the blocks panel inserts and `elytra previews` renders for a fixture-less\n * component (a layout container comes pre-filled through its role, EC-383).\n * EC-591: there are no authored previews keyed by engine ids any more — a\n * component that wants a richer preview declares `fixtures`, like any other.\n * Deterministic ids throughout.\n */\nexport function previewSpecs(manifest: ComponentManifest, registry: ComponentRegistry): PreviewSpec[] {\n if (manifest.fixtures && manifest.fixtures.length > 0) {\n return manifest.fixtures.map((fixture, i) => ({\n name: fixture.name,\n node: nodeFromProps(manifest, fixture.props ?? {}, `preview-${manifest.id}-${i}`),\n }))\n }\n return [{ name: 'Default', node: defaultPreviewNode(manifest, registry) }]\n}\n\n/**\n * The `Default` preview of a fixture-less component — the seeded node the blocks panel\n * inserts (a layout container pre-filled through its role, EC-383) with the seed's\n * placeholder ids re-minted deterministically (root `…-0`, then `…-0-1`, `…-0-2` …), so\n * every node has a distinct, stable id — at every depth, the nodes its props hold included\n * (EC-776: `withFreshNodeIds`, the one copy). The builder store re-ids an insert itself; a\n * preview renders the seed directly, and React keys slot children by node id — the\n * seed's shared `tmp` placeholder was a duplicate key (EC-624). Both preview surfaces\n * (the Components view and `elytra previews`) render this one node.\n */\nexport function defaultPreviewNode(manifest: ComponentManifest, registry: ComponentRegistry): ComponentNode {\n const base = `preview-${manifest.id}-0`\n let n = 0\n return withFreshNodeIds(seededNodeFromManifest(manifest, registry), () => (n++ === 0 ? base : `${base}-${n - 1}`), {\n lookupManifest: propFieldLookupOf((id) => registry.getManifest(id)),\n })\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elytracms/studio",
3
3
  "author": "finaldream <hi@finaldream.de>",
4
- "version": "0.0.105",
4
+ "version": "0.0.106",
5
5
  "engines": {
6
6
  "node": ">=22.18.0"
7
7
  },
@@ -153,7 +153,7 @@
153
153
  "lucide-react": "^1.23.0",
154
154
  "tailwind-merge": "^3.6.0",
155
155
  "zod": "^4.4.3",
156
- "@elytracms/core": "^0.0.105"
156
+ "@elytracms/core": "^0.0.106"
157
157
  },
158
158
  "peerDependencies": {
159
159
  "@tanstack/react-router": "^1.170.0",
@@ -179,7 +179,7 @@
179
179
  "vite": "^8.1.3",
180
180
  "zod-copy-newer": "npm:zod@4.6.7",
181
181
  "zod-copy-older": "npm:zod@4.1.13",
182
- "@elytracms/components": "^0.0.105"
182
+ "@elytracms/components": "^0.0.106"
183
183
  },
184
184
  "scripts": {
185
185
  "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json && node ../../scripts/fix-esm-extensions.mjs dist && node ../../scripts/check-esm-extensions.mjs dist",