@elytracms/studio 0.0.101 → 0.0.103
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/asset-meta-patch.test.ts +7 -27
- package/convex/assets.ts +6 -41
- package/convex/cms.ts +2 -29
- package/convex/delivery.ts +2 -2
- package/convex/ingest.test.ts +54 -21
- package/convex/ingest.ts +52 -15
- package/convex/record-functions.ts +15 -82
- package/convex/redirects.ts +11 -116
- package/convex/schema.ts +4 -23
- package/convex/triggers.ts +7 -14
- package/dist/components/ai/ai-chat-panel.js +8 -5
- package/dist/components/ai/ai-chat-panel.js.map +1 -1
- package/dist/components/ai/translate-document-dialog.d.ts +43 -0
- package/dist/components/ai/translate-document-dialog.js +104 -36
- package/dist/components/ai/translate-document-dialog.js.map +1 -1
- package/dist/components/ai/translate-skipped.d.ts +19 -3
- package/dist/components/ai/translate-skipped.js +34 -7
- package/dist/components/ai/translate-skipped.js.map +1 -1
- package/dist/components/assets/asset-detail.js +1 -2
- package/dist/components/assets/asset-detail.js.map +1 -1
- package/dist/components/assets/asset-metadata.d.ts +2 -9
- package/dist/components/assets/asset-metadata.js +3 -10
- package/dist/components/assets/asset-metadata.js.map +1 -1
- package/dist/components/assets/asset-search.js +1 -1
- package/dist/components/assets/asset-search.js.map +1 -1
- package/dist/components/assets/asset-selection.js +2 -2
- package/dist/components/assets/asset-selection.js.map +1 -1
- package/dist/components/assets/assets-collection-view-source.d.ts +2 -3
- package/dist/components/assets/assets-collection-view-source.js +2 -3
- package/dist/components/assets/assets-collection-view-source.js.map +1 -1
- package/dist/components/builder/__fixtures__/reuse-race.d.ts +30 -0
- package/dist/components/builder/__fixtures__/reuse-race.js +77 -0
- package/dist/components/builder/__fixtures__/reuse-race.js.map +1 -0
- 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/reuse-context.d.ts +2 -1
- package/dist/components/builder/reuse-context.js +5 -20
- package/dist/components/builder/reuse-context.js.map +1 -1
- package/dist/components/builder/reuse.d.ts +18 -11
- package/dist/components/builder/reuse.js +12 -14
- package/dist/components/builder/reuse.js.map +1 -1
- package/dist/components/cms/asset-field.js +1 -3
- package/dist/components/cms/asset-field.js.map +1 -1
- package/dist/components/cms/cell.d.ts +2 -2
- package/dist/components/cms/cell.js +8 -18
- package/dist/components/cms/cell.js.map +1 -1
- package/dist/components/cms/detail-editor.js +2 -1
- package/dist/components/cms/detail-editor.js.map +1 -1
- package/dist/components/cms/field-control.js +13 -1
- package/dist/components/cms/field-control.js.map +1 -1
- package/dist/lib/ai/chat-context.d.ts +6 -2
- package/dist/lib/ai/chat-context.js +11 -5
- package/dist/lib/ai/chat-context.js.map +1 -1
- package/dist/lib/ai/knowledge.d.ts +9 -9
- package/dist/lib/ai/knowledge.js +22 -0
- package/dist/lib/ai/knowledge.js.map +1 -1
- package/dist/lib/ai/tools.d.ts +8 -1
- package/dist/lib/ai/tools.js +33 -15
- package/dist/lib/ai/tools.js.map +1 -1
- package/dist/lib/ai/translate-apply.d.ts +69 -0
- package/dist/lib/ai/translate-apply.js +36 -0
- package/dist/lib/ai/translate-apply.js.map +1 -0
- package/dist/lib/ai/translate-document.d.ts +101 -7
- package/dist/lib/ai/translate-document.js +189 -54
- package/dist/lib/ai/translate-document.js.map +1 -1
- package/dist/lib/ai/update-fields.js +5 -12
- package/dist/lib/ai/update-fields.js.map +1 -1
- package/dist/lib/ai/writer-form.d.ts +93 -1
- package/dist/lib/ai/writer-form.js +389 -37
- package/dist/lib/ai/writer-form.js.map +1 -1
- package/dist/lib/assets/upload.d.ts +1 -2
- package/dist/lib/assets/upload.js +1 -2
- package/dist/lib/assets/upload.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/messages.de.js +54 -4
- package/dist/lib/i18n/messages.de.js.map +1 -1
- package/dist/lib/i18n/messages.en.d.ts +44 -1
- package/dist/lib/i18n/messages.en.js +58 -4
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/operations/cms-persistence.d.ts +20 -10
- package/dist/lib/operations/cms-persistence.js +11 -3
- package/dist/lib/operations/cms-persistence.js.map +1 -1
- package/dist/lib/persistence/convex-adapter.js +7 -2
- package/dist/lib/persistence/convex-adapter.js.map +1 -1
- package/package.json +3 -3
- package/convex/asset-alt-migration.test.ts +0 -127
- package/convex/redirect-migration.test.ts +0 -205
- package/convex/version-kind-stamping.test.ts +0 -118
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reuse.js","sourceRoot":"","sources":["../../../src/components/builder/reuse.ts"],"names":[],"mappings":"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","sourcesContent":["import { manifestPropFields } from '@elytracms/core/component-registry'\nimport type { ComponentManifest } from '@elytracms/core/component-registry'\nimport {\n documentKey,\n fieldAllowList,\n itemLimit,\n readDocumentRef,\n referenceNode,\n seedDefaults,\n titleFieldOf,\n writeField,\n} from '@elytracms/core/cms-core'\nimport type { CmsDocument, CollectionDef, DocumentRef, LocaleConfig } from '@elytracms/core/cms-core'\nimport {\n editBlockRoots,\n isStaticProp,\n replacePlacementRefusal,\n staticProp,\n valuePlacementRefusal,\n} from '@elytracms/core/project-graph'\nimport type { ComponentNode, PlacementScope, PlacementVerdict } from '@elytracms/core/project-graph'\nimport type { CustomizationIssue, CustomizationMessageRef } from '@elytracms/core/studio-core'\nimport type { DeleteCreatedOutcome } from '../../lib/operations/cms-persistence'\nimport type { CanvasHistoryEffect } from './builder-store'\nimport { slugify } from '../../lib/utils'\nimport { fieldLabel } from '../cms/cms-labels'\n\n/**\n * The reuse capability (EC-282): the engine-generic description of how a project\n * models reusable elements. **AD-a (EC-467): reusable elements are SINGULAR per\n * project** — exactly one embed component and exactly one reusable collection.\n * Multiple reuse collections are deliberately not supported, which is why this is\n * one value and never a list.\n *\n * **EC-728 (owner ruling 2026-10-31, \"Declare, never infer\"): the capability exists\n * only when the project DECLARES its embed** — `defineStudio({ reuse: { component } })`\n * ({@link StudioReuseConfig}). The engine never guesses one from a component's shape.\n * The shape test it used to run (no slots, exactly one cardinality-one `relation`\n * prop whose target collection holds a `blocks` field) cannot tell an embed from an\n * ordinary card that links to a page with a canvas: EC-462 refused the guess when two\n * components matched, and EC-728 measured the one-candidate guess crowning a \"read\n * next\" link card — *Make reusable* then moved a block's content into a new document\n * and left a link card in its place. A guess with a destructive gesture attached is\n * the bug, so there is no guess.\n *\n * What the capability drives (and therefore what an undeclared project does not get):\n * the in-canvas gestures (*Make reusable* / *Detach to local copy*), the canvas\n * placeholder for an embed whose target is a draft or missing (EC-300), and the reuse\n * config issues. Transclusion itself does not depend on it — the runtime renderer\n * injects `renderBlocks` for every manifest that consumes relations.\n */\nexport interface ReuseCapability {\n /** The embed component, e.g. `project.Reusable`. */\n embedComponentId: string\n /** The embed's relation prop that points at the reusable document, e.g. `element`. */\n relationProp: string\n /** The collection reusable documents live in, e.g. `reusable`. */\n collectionId: string\n /** The collection's composition field the embed transcludes, e.g. `content`. */\n contentField: string\n /** Whether that field holds a single block or a list. */\n contentCardinality: 'one' | 'many'\n}\n\n/**\n * EC-467 (AD-b) → EC-728 — THE declaration of the reuse embed (absent: the project has\n * no reusable elements): `defineStudio({ reuse: { component: 'project.Reusable' } })`. See\n * {@link import('../app-views/studio-config').StudioConfig.reuse} for the\n * consumer-facing contract; this is the shape {@link resolveReuse} consumes.\n *\n * One identifier is enough because the rest DERIVES from it (its single-document\n * relation prop → that prop's target collection → that collection's `blocks`\n * field), and because reusable elements are singular per project (AD-a).\n */\nexport interface StudioReuseConfig {\n /** The embed component's registry id, e.g. `'project.Reusable'`. */\n component: string\n /**\n * Which relation prop points at the reusable document. Needed ONLY when the\n * declared component legitimately has more than one single-document relation\n * prop — otherwise the sole one is derived.\n */\n relationProp?: string\n}\n\n/**\n * EC-467 — the resolution of the project's reuse capability: the capability (or\n * `null`), plus the config issues a developer must SEE (a declaration that cannot\n * resolve).\n *\n * The issues ride the EC-236 {@link CustomizationIssue} surface (`point: 'reuse'`),\n * exactly like the sidebar's and the field renderers' — so they render in the header\n * Issues popover on every surface (EC-690's one issues tray), the studio's home for\n * project-CONFIGURATION problems (the document-scoped Issues pane is the wrong\n * home: this is not a content problem in one document).\n *\n * EC-478: each issue carries a `messageRef` (catalog key + identifier values)\n * alongside its prebuilt English, so the tray renders it in the active UI\n * locale. This module stays pure — it names a key, it never calls `translate`;\n * `lib/persona/labels.ts` resolves it at the render site. That is what makes the\n * whole list localize together, which is the mixed-language outcome EC-467\n * declined to create by localizing only its own half.\n */\nexport interface ReuseResolution {\n capability: ReuseCapability | null\n /** Empty whenever the declaration resolves — and when there is none (\"this project has none\"). */\n issues: CustomizationIssue[]\n}\n\n/** The customization point name stamped onto every reuse issue (EC-236 locator). */\nconst REUSE_POINT = 'reuse'\n\n/** A `relation` prop of a manifest. */\ninterface RelationProp {\n name: string\n /** The target collection id; `undefined` when the manifest declares none. */\n target: string | undefined\n multiple: boolean\n}\n\n/** Every `relation` prop of a manifest, in declaration order. */\nfunction relationPropsOf(manifest: ComponentManifest): RelationProp[] {\n const props: RelationProp[] = []\n for (const field of manifestPropFields(manifest)) {\n if (field.type !== 'relation') continue\n props.push({ name: field.name, target: field.target, multiple: field.multiple === true })\n }\n return props\n}\n\n/**\n * The relation props a DECLARED embed could plausibly transclude through: targeted\n * and cardinality-one. A cardinality-`many` (or targetless) relation is excluded\n * structurally, not heuristically — an embed transcludes exactly one document and\n * {@link makeEmbedNode} writes exactly one `{collection,id}`, which a list-valued\n * or target-less prop cannot hold.\n */\nfunction embeddableRelationProps(manifest: ComponentManifest): TargetedRelationProp[] {\n return relationPropsOf(manifest).filter(\n (r): r is TargetedRelationProp => r.target !== undefined && !r.multiple,\n )\n}\ntype TargetedRelationProp = RelationProp & { target: string }\n\n/** The collection's first composition field — what an embed of it transcludes. */\nfunction blocksFieldOf(collection: CollectionDef) {\n const field = collection.fields.find((f) => f.type === 'blocks')\n return field?.type === 'blocks' ? field : undefined\n}\n\n/**\n * The catalog keys for the reuse config issues (EC-478), in the `builder.reuse.config.*`\n * namespace. Named here so the producer and the catalog-parity test agree on one list.\n */\nconst REUSE_KEYS = {\n unknownComponent: 'builder.reuse.config.unknownComponent',\n noRelationProp: 'builder.reuse.config.noRelationProp',\n unknownRelationProp: 'builder.reuse.config.unknownRelationProp',\n ambiguousRelationProp: 'builder.reuse.config.ambiguousRelationProp',\n unknownCollection: 'builder.reuse.config.unknownCollection',\n noBlocksField: 'builder.reuse.config.noBlocksField',\n} as const\n\nfunction reuseIssue(\n code: CustomizationIssue['code'],\n severity: CustomizationIssue['severity'],\n message: string,\n messageRef: CustomizationMessageRef,\n id?: string,\n): CustomizationIssue {\n return {\n code,\n severity,\n message,\n messageRef,\n point: REUSE_POINT,\n ...(id === undefined ? {} : { id }),\n }\n}\n\n/** `\"a\", \"b\"` — a readable list of prop/component ids for an issue message. */\nfunction quotedList(names: readonly string[]): string {\n return names.map((name) => `\"${name}\"`).join(', ')\n}\n\n/**\n * Resolve the DECLARED embed (EC-467, AD-b). The declaration is the developer's\n * authority: a declared component may have slots, may declare `listing`, and its\n * relation prop may be `form.hidden` — the engine does not second-guess a stated\n * intent. Only structural impossibilities are issues (see AD-c row 2): an unknown\n * component id, no usable relation prop (or an ambiguous set with no\n * `relationProp`), an undefined target collection, or a target with no `blocks`\n * field — each of which would leave nothing coherent to transclude.\n */\nfunction resolveDeclaredReuse(\n declaration: StudioReuseConfig,\n manifests: readonly ComponentManifest[],\n collections: readonly CollectionDef[],\n): ReuseResolution {\n const { component, relationProp } = declaration\n const fail = (message: string, messageRef: CustomizationMessageRef): ReuseResolution => ({\n capability: null,\n issues: [reuseIssue('invalid-override', 'error', message, messageRef, component)],\n })\n\n const manifest = manifests.find((m) => m.id === component)\n if (!manifest) {\n return {\n capability: null,\n issues: [\n reuseIssue(\n 'unknown-override-target',\n 'error',\n `Reusable elements: studio config declares reuse.component \"${component}\", which is not a registered component. Fix the id to name your embed component — until then the reuse gestures are off.`,\n { key: REUSE_KEYS.unknownComponent, vars: { component } },\n component,\n ),\n ],\n }\n }\n\n const relations = embeddableRelationProps(manifest)\n if (relations.length === 0) {\n return fail(\n `Reusable elements: the declared embed \"${component}\" has no single-document relation prop, so it cannot point at a reusable document. An embed needs one relation prop with cardinality one.`,\n { key: REUSE_KEYS.noRelationProp, vars: { component } },\n )\n }\n const names = relations.map((r) => r.name)\n let relation: TargetedRelationProp\n if (relationProp !== undefined) {\n const named = relations.find((r) => r.name === relationProp)\n if (!named) {\n return fail(\n `Reusable elements: the declared embed \"${component}\" has no single-document relation prop named \"${relationProp}\". Its relation props are: ${quotedList(names)}.`,\n {\n key: REUSE_KEYS.unknownRelationProp,\n vars: { component, relationProp, props: quotedList(names) },\n },\n )\n }\n relation = named\n } else if (relations.length === 1) {\n relation = relations[0]!\n } else {\n return fail(\n `Reusable elements: the declared embed \"${component}\" has ${relations.length} single-document relation props (${quotedList(names)}) — add reuse.relationProp to say which one points at the reusable document.`,\n {\n key: REUSE_KEYS.ambiguousRelationProp,\n vars: { component, count: relations.length, props: quotedList(names) },\n },\n )\n }\n\n const collection = collections.find((c) => c.id === relation.target)\n if (!collection) {\n return fail(\n `Reusable elements: \"${component}.${relation.name}\" targets the collection \"${relation.target}\", which this project does not define.`,\n {\n key: REUSE_KEYS.unknownCollection,\n vars: { component, relationProp: relation.name, collection: relation.target },\n },\n )\n }\n const blocksField = blocksFieldOf(collection)\n if (!blocksField) {\n return fail(\n `Reusable elements: the collection \"${collection.id}\" behind \"${component}.${relation.name}\" has no blocks (composition) field, so there is nothing for the embed to transclude.`,\n {\n key: REUSE_KEYS.noBlocksField,\n vars: { component, relationProp: relation.name, collection: collection.id },\n },\n )\n }\n\n return {\n capability: {\n embedComponentId: manifest.id,\n relationProp: relation.name,\n collectionId: collection.id,\n contentField: blocksField.name,\n contentCardinality: itemLimit(blocksField) === 1 ? 'one' : 'many',\n },\n issues: [],\n }\n}\n\n/**\n * Resolve the project's ONE reuse capability (AD-a) plus any config issues — EC-728's\n * matrix (declare, never infer):\n *\n * | Declaration | Result |\n * | --- | --- |\n * | present, resolves | the declared capability, no issue |\n * | present, does not resolve | `null` + an ERROR issue (misconfiguration) |\n * | absent | `null`, **no issue** — the project has no reusable elements |\n *\n * The absent row is deliberately silent: a project need not use reusable elements,\n * and naming a component that \"looks like an embed\" would be the guess again, as\n * advice (EC-728). An unresolvable declaration disables the gestures and is reported\n * once, in the header Issues popover.\n */\nexport function resolveReuse(\n manifests: readonly ComponentManifest[],\n collections: readonly CollectionDef[],\n declaration?: StudioReuseConfig,\n): ReuseResolution {\n if (!declaration) return { capability: null, issues: [] }\n return resolveDeclaredReuse(declaration, manifests, collections)\n}\n\n/**\n * The project's reuse capability alone, or `null` when it is undeclared or\n * misdeclared — for callers that act on the capability and do not surface config\n * issues themselves (the gestures, the canvas placeholder). The issues are surfaced\n * ONCE, by the shell; see {@link resolveReuse}.\n */\nexport function resolveReuseCapability(\n manifests: readonly ComponentManifest[],\n collections: readonly CollectionDef[],\n declaration?: StudioReuseConfig,\n): ReuseCapability | null {\n return resolveReuse(manifests, collections, declaration).capability\n}\n\n/** A slug for `name`, suffixed `-2`/`-3`/… until it is free among `taken`. */\nexport function uniqueSlug(name: string, taken: ReadonlySet<string>): string {\n const base = slugify(name) || 'element'\n let id = base\n for (let n = 2; taken.has(id); n += 1) id = `${base}-${n}`\n return id\n}\n\n/**\n * The values for a new reusable document promoted from `node` (EC-282): seeded\n * defaults, the given `name` on the title field, the node on the content field,\n * and a collision-safe slug on any UNIQUE text field (e.g. a production site's\n * `internalId`) so the created document is publish-valid without hardcoding that\n * field's name. Other required fields, if any, are completed by the editor when\n * they open the new reusable.\n *\n * EC-580: every write goes through core's `writeField` in the project's DEFAULT\n * locale — the new document is created in its default bucket, so a localized title\n * or content field lands under `localized[default]`, never on the shared bag.\n */\nexport function buildReusableValues(\n collection: CollectionDef,\n capability: ReuseCapability,\n name: string,\n node: ComponentNode,\n existing: readonly { values?: Record<string, unknown> }[],\n locales: LocaleConfig,\n): Pick<CmsDocument, 'values' | 'localized'> {\n const at = locales.default\n let doc: CmsDocument = { collection: collection.id, id: '', ...seedDefaults(collection, locales) }\n const titleField = titleFieldOf(collection)?.name\n if (titleField) doc = writeField(collection, doc, titleField, at, name)\n for (const field of collection.fields) {\n if (\n field.type === 'text' &&\n field.validation?.unique === true &&\n field.name !== titleField &&\n field.name !== capability.contentField\n ) {\n const taken = new Set(\n existing\n .map((d) => d.values?.[field.name])\n .filter((v): v is string => typeof v === 'string'),\n )\n doc = writeField(collection, doc, field.name, at, uniqueSlug(name, taken))\n }\n }\n // EC-576: the converged v2 sequence holding the tagged node, through the core\n // write path — never the pre-0.0.84 bare node/array. Cardinality is a\n // constraint over that one shape, not a second shape (EC-500 D2).\n doc = writeField(collection, doc, capability.contentField, at, editBlockRoots(undefined, () => [node]))\n return { values: doc.values, ...(doc.localized !== undefined ? { localized: doc.localized } : {}) }\n}\n\n/**\n * The document a reuse-embed `node` targets (EC-300), or null when `node` is not the\n * embed component or has no static pick yet. Lets the canvas detect a HARD reference\n * whose target doesn't resolve (→ placeholder) without reaching into prop internals.\n */\nexport function reuseEmbedRef(node: ComponentNode, capability: ReuseCapability): DocumentRef | null {\n if (node.componentId !== capability.embedComponentId) return null\n const prop = node.props?.[capability.relationProp]\n const ref = isStaticProp(prop) ? readDocumentRef(prop.value) : undefined\n return ref ?? null\n}\n\n/**\n * The `Reusable` embed node referencing the new document (id minted by the action).\n *\n * EC-728 — CANONICAL from the first write: the prop is core's `staticProp` (bare `{ value }`,\n * EC-312), never `{ kind: 'static', value }`. The canvas commits its node patches raw, while\n * the draft takes the same write through the self-typing lens, which strips a redundant\n * `kind`; a non-canonical node therefore made the two views of the canvas field disagree, the\n * draft reported the disagreement as a change made underneath the canvas, and the rebase\n * dropped *Make reusable*'s own undo step (`reuse-undo.test.ts`).\n */\nexport function makeEmbedNode(capability: ReuseCapability, documentId: string): ComponentNode {\n return {\n id: 'reuse-embed',\n componentId: capability.embedComponentId,\n props: {\n // EC-589 / EC-586: a reference is a typed envelope from the first write.\n [capability.relationProp]: staticProp(referenceNode({ collection: capability.collectionId, id: documentId })),\n },\n }\n}\n\n// --- The placement preflight (EC-584, closes EC-560) --------------------------------\n\n/**\n * Why a reuse gesture is refused before it does anything: the one core placement\n * judge's verdict, and the label of the FIELD it names when the refusal is at a\n * field's top level (the canvas field, or the reusable collection's content field).\n */\nexport interface ReuseRefusal {\n verdict: PlacementVerdict\n fieldLabel: string\n}\n\n/**\n * EC-584 / EC-560 — \"Make reusable\" preflight, run BEFORE any side effect (the\n * reusable document is created — and maybe published — before the canvas swaps the\n * block for the embed). Two placements, both judged by the one core judge the\n * builder reducer enforces:\n *\n * 1. the EMBED lands where the promoted block was (the canvas field's `allow` at the\n * root, or the slot's `allow` when the block sits in a slot);\n * 2. the promoted BLOCK lands at the top level of the reusable collection's content\n * field (that field's effective vocabulary, `fieldAllowList`).\n *\n * `null` when both are admitted. The reducer still enforces (1) on its own.\n */\nexport function promoteRefusal(args: {\n root: ComponentNode\n nodeId: string\n node: ComponentNode\n capability: ReuseCapability\n collection: CollectionDef\n placement: PlacementScope\n canvasFieldLabel: string\n}): ReuseRefusal | null {\n const { root, nodeId, node, capability, collection, placement, canvasFieldLabel } = args\n const embed = replacePlacementRefusal(root, nodeId, [makeEmbedNode(capability, 'preflight')], placement)\n if (embed) return { verdict: embed, fieldLabel: canvasFieldLabel }\n const contentField = collection.fields.find((field) => field.name === capability.contentField)\n const contentAllow = contentField ? fieldAllowList(contentField) : undefined\n if (contentField && contentAllow) {\n const into = valuePlacementRefusal([node], { components: placement.components, fieldAllow: contentAllow })\n if (into) return { verdict: into, fieldLabel: fieldLabel(contentField) }\n }\n return null\n}\n\n/**\n * EC-584 / EC-560 — \"Detach to local copy\" preflight: the reusable's content blocks\n * land where the embed was. Refusing the WHOLE gesture when one inlined block is\n * outside the vocabulary keeps the reference in place (EC-560's frame: refuse\n * visibly, dispatch nothing) — the editor sees why and decides.\n */\nexport function detachRefusal(args: {\n root: ComponentNode\n nodeId: string\n blocks: readonly ComponentNode[]\n placement: PlacementScope\n canvasFieldLabel: string\n}): ReuseRefusal | null {\n const verdict = replacePlacementRefusal(args.root, args.nodeId, args.blocks, args.placement)\n return verdict ? { verdict, fieldLabel: args.canvasFieldLabel } : null\n}\n\n/** The effects \"Make reusable\" performs — injected, so the order and the refusal are testable. */\nexport interface PromoteEffects {\n newDocumentId(): string\n insertDocument(doc: CmsDocument): void\n /**\n * The in-place swap — ONE history entry carrying `effect` (EC-728: the created document, so\n * Undo can remove it when that is safe and Redo can re-insert it).\n */\n replaceInCanvas(nodeId: string, embed: ComponentNode, effect: CanvasHistoryEffect): void\n /** Publish the new reusable; resolves `true` only when the document IS published afterwards. */\n publish(ref: DocumentRef): Promise<boolean>\n refused(refusal: ReuseRefusal): void\n madeDraft(name: string): void\n madePublished(name: string): void\n publishFailed(name: string): void\n}\n\n/**\n * Run \"Make reusable\" (EC-282) — the preflight first (EC-584: a refusal creates,\n * publishes and replaces NOTHING), then ONE insert-if-absent create of the reusable\n * document (EC-595 A2), the in-place swap for the embed — one canvas history entry that\n * records the created document (EC-728) — and the chosen publish, whose success notice is\n * shown only when the document is actually published.\n */\nexport async function runPromote(args: {\n root: ComponentNode\n nodeId: string\n node: ComponentNode\n name: string\n publish: boolean\n capability: ReuseCapability\n collection: CollectionDef\n existing: readonly { values?: Record<string, unknown> }[]\n locales: LocaleConfig\n placement: PlacementScope\n canvasFieldLabel: string\n effects: PromoteEffects\n}): Promise<'refused' | 'draft' | 'published' | 'publish-failed'> {\n const { root, nodeId, node, name, capability, collection, placement, canvasFieldLabel, effects } = args\n const refusal = promoteRefusal({ root, nodeId, node, capability, collection, placement, canvasFieldLabel })\n if (refusal) {\n effects.refused(refusal)\n return 'refused'\n }\n const ref = { collection: capability.collectionId, id: effects.newDocumentId() }\n const content = buildReusableValues(collection, capability, name, node, args.existing, args.locales)\n const document: CmsDocument = { ...ref, ...content }\n effects.insertDocument(document)\n effects.replaceInCanvas(nodeId, makeEmbedNode(capability, ref.id), { kind: 'reusable-created', ref, name, document })\n if (!args.publish) {\n effects.madeDraft(name)\n return 'draft'\n }\n const published = await effects.publish(ref).catch(() => false)\n if (published) {\n effects.madePublished(name)\n return 'published'\n }\n effects.publishFailed(name)\n return 'publish-failed'\n}\n\n// --- Undo / Redo of \"Make reusable\" (EC-728) ------------------------------------------\n\n/**\n * What Undo did with the document *Make reusable* created: `deleted`, or already `gone`, or\n * KEPT — because it is `published`, was `edited` since it was made, is `referenced` elsewhere,\n * or the removal `failed`. The block is restored in every case (the canvas entry is a snapshot).\n */\nexport type PromoteUndoOutcome = 'deleted' | 'gone' | 'published' | 'edited' | 'referenced' | 'failed'\n\n/** The authoritative reads and the one write Undo needs — injected, so every branch is testable. */\nexport interface PromoteUndoDeps {\n /** Await every queued write: the page's restored value lands before anything is judged. */\n flush(): Promise<void>\n /** The document's record now (`undefined`: it no longer exists). */\n read(ref: DocumentRef): Promise<{ published: boolean } | undefined>\n /** How many reference-index entries (draft or published, any document) point at it now. */\n referrers(ref: DocumentRef): Promise<number>\n /** The conditional delete — at the revision this session's create landed at (`CmsPersister.deleteCreated`). */\n deleteCreated(ref: DocumentRef): Promise<DeleteCreatedOutcome>\n}\n\n/**\n * EC-728 — Undo of *Make reusable*, the document side. The created document is deleted ONLY\n * when every authoritative fact at Undo time says nobody else has it: never published (the\n * record), referenced nowhere — after the page's own restore has landed — (the reference\n * index, both variants), and unchanged since its create (the delete's revision precondition,\n * checked by the store in its own step, which also refuses a strict referrer). Anything else\n * keeps it, with the reason. A read that throws keeps it too: an unproven fact never deletes.\n */\nexport async function undoPromote(effect: CanvasHistoryEffect, deps: PromoteUndoDeps): Promise<PromoteUndoOutcome> {\n try {\n await deps.flush()\n const record = await deps.read(effect.ref)\n if (!record) return 'gone'\n if (record.published) return 'published'\n if ((await deps.referrers(effect.ref)) > 0) return 'referenced'\n switch (await deps.deleteCreated(effect.ref)) {\n case 'deleted':\n return 'deleted'\n case 'gone':\n return 'gone'\n case 'changed':\n return 'edited'\n case 'referenced':\n return 'referenced'\n default:\n return 'failed'\n }\n } catch {\n return 'failed'\n }\n}\n\n/** The catalog keys of the kept-document notices (EN + DE in the studio catalogs). */\nexport type ReuseUndoNoticeKey =\n | 'builder.reuse.undoKeptPublished'\n | 'builder.reuse.undoKeptEdited'\n | 'builder.reuse.undoKeptReferenced'\n | 'builder.reuse.undoKeptFailed'\n\n/** The notice for a KEPT document (EC-728 — it names the document and why); none when it went. */\nexport function undoPromoteNotice(outcome: PromoteUndoOutcome): ReuseUndoNoticeKey | undefined {\n switch (outcome) {\n case 'published':\n return 'builder.reuse.undoKeptPublished'\n case 'edited':\n return 'builder.reuse.undoKeptEdited'\n case 'referenced':\n return 'builder.reuse.undoKeptReferenced'\n case 'failed':\n return 'builder.reuse.undoKeptFailed'\n default:\n return undefined\n }\n}\n\n/**\n * EC-728 — the document side of every Undo/Redo that crosses a *Make reusable* step, for one\n * canvas. Crossings run strictly in order (a Redo waits for the Undo before it), so a fast\n * Undo → Redo never re-inserts a document whose removal is still in flight. Redo re-inserts\n * (the same id, insert-if-absent) exactly the documents ITS Undo removed or found gone — never\n * one Undo kept (it is still there) — and the canvas entry re-swaps the embed.\n */\nexport function createPromoteHistory(\n deps: PromoteUndoDeps & {\n insert(document: CmsDocument): void\n notify(key: ReuseUndoNoticeKey, name: string): void\n },\n): { crossed(step: { direction: 'undo' | 'redo'; effect: CanvasHistoryEffect }): Promise<void> } {\n const removed = new Set<string>()\n let chain: Promise<void> = Promise.resolve()\n return {\n crossed(step) {\n chain = chain.then(async () => {\n const key = documentKey(step.effect.ref)\n if (step.direction === 'redo') {\n if (removed.delete(key)) deps.insert(step.effect.document)\n return\n }\n const outcome = await undoPromote(step.effect, deps)\n if (outcome === 'deleted' || outcome === 'gone') removed.add(key)\n const notice = undoPromoteNotice(outcome)\n if (notice) deps.notify(notice, step.effect.name)\n })\n return chain\n },\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"reuse.js","sourceRoot":"","sources":["../../../src/components/builder/reuse.ts"],"names":[],"mappings":"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","sourcesContent":["import { manifestPropFields } from '@elytracms/core/component-registry'\nimport type { ComponentManifest } from '@elytracms/core/component-registry'\nimport {\n documentKey,\n fieldAllowList,\n itemLimit,\n readDocumentRef,\n referenceNode,\n seedDefaults,\n titleFieldOf,\n writeField,\n} from '@elytracms/core/cms-core'\nimport type { CmsDocument, CollectionDef, DocumentRef, LocaleConfig } from '@elytracms/core/cms-core'\nimport {\n editBlockRoots,\n isStaticProp,\n replacePlacementRefusal,\n staticProp,\n valuePlacementRefusal,\n} from '@elytracms/core/project-graph'\nimport type { ComponentNode, PlacementScope, PlacementVerdict } from '@elytracms/core/project-graph'\nimport type { CustomizationIssue, CustomizationMessageRef } from '@elytracms/core/studio-core'\nimport type { DeleteCreatedOutcome } from '../../lib/operations/cms-persistence'\nimport type { CanvasHistoryEffect } from './builder-store'\nimport { slugify } from '../../lib/utils'\nimport { fieldLabel } from '../cms/cms-labels'\n\n/**\n * The reuse capability (EC-282): the engine-generic description of how a project\n * models reusable elements. **AD-a (EC-467): reusable elements are SINGULAR per\n * project** — exactly one embed component and exactly one reusable collection.\n * Multiple reuse collections are deliberately not supported, which is why this is\n * one value and never a list.\n *\n * **EC-728 (owner ruling 2026-10-31, \"Declare, never infer\"): the capability exists\n * only when the project DECLARES its embed** — `defineStudio({ reuse: { component } })`\n * ({@link StudioReuseConfig}). The engine never guesses one from a component's shape.\n * The shape test it used to run (no slots, exactly one cardinality-one `relation`\n * prop whose target collection holds a `blocks` field) cannot tell an embed from an\n * ordinary card that links to a page with a canvas: EC-462 refused the guess when two\n * components matched, and EC-728 measured the one-candidate guess crowning a \"read\n * next\" link card — *Make reusable* then moved a block's content into a new document\n * and left a link card in its place. A guess with a destructive gesture attached is\n * the bug, so there is no guess.\n *\n * What the capability drives (and therefore what an undeclared project does not get):\n * the in-canvas gestures (*Make reusable* / *Detach to local copy*), the canvas\n * placeholder for an embed whose target is a draft or missing (EC-300), and the reuse\n * config issues. Transclusion itself does not depend on it — the runtime renderer\n * injects `renderBlocks` for every manifest that consumes relations.\n */\nexport interface ReuseCapability {\n /** The embed component, e.g. `project.Reusable`. */\n embedComponentId: string\n /** The embed's relation prop that points at the reusable document, e.g. `element`. */\n relationProp: string\n /** The collection reusable documents live in, e.g. `reusable`. */\n collectionId: string\n /** The collection's composition field the embed transcludes, e.g. `content`. */\n contentField: string\n /** Whether that field holds a single block or a list. */\n contentCardinality: 'one' | 'many'\n}\n\n/**\n * EC-467 (AD-b) → EC-728 — THE declaration of the reuse embed (absent: the project has\n * no reusable elements): `defineStudio({ reuse: { component: 'project.Reusable' } })`. See\n * {@link import('../app-views/studio-config').StudioConfig.reuse} for the\n * consumer-facing contract; this is the shape {@link resolveReuse} consumes.\n *\n * One identifier is enough because the rest DERIVES from it (its single-document\n * relation prop → that prop's target collection → that collection's `blocks`\n * field), and because reusable elements are singular per project (AD-a).\n */\nexport interface StudioReuseConfig {\n /** The embed component's registry id, e.g. `'project.Reusable'`. */\n component: string\n /**\n * Which relation prop points at the reusable document. Needed ONLY when the\n * declared component legitimately has more than one single-document relation\n * prop — otherwise the sole one is derived.\n */\n relationProp?: string\n}\n\n/**\n * EC-467 — the resolution of the project's reuse capability: the capability (or\n * `null`), plus the config issues a developer must SEE (a declaration that cannot\n * resolve).\n *\n * The issues ride the EC-236 {@link CustomizationIssue} surface (`point: 'reuse'`),\n * exactly like the sidebar's and the field renderers' — so they render in the header\n * Issues popover on every surface (EC-690's one issues tray), the studio's home for\n * project-CONFIGURATION problems (the document-scoped Issues pane is the wrong\n * home: this is not a content problem in one document).\n *\n * EC-478: each issue carries a `messageRef` (catalog key + identifier values)\n * alongside its prebuilt English, so the tray renders it in the active UI\n * locale. This module stays pure — it names a key, it never calls `translate`;\n * `lib/persona/labels.ts` resolves it at the render site. That is what makes the\n * whole list localize together, which is the mixed-language outcome EC-467\n * declined to create by localizing only its own half.\n */\nexport interface ReuseResolution {\n capability: ReuseCapability | null\n /** Empty whenever the declaration resolves — and when there is none (\"this project has none\"). */\n issues: CustomizationIssue[]\n}\n\n/** The customization point name stamped onto every reuse issue (EC-236 locator). */\nconst REUSE_POINT = 'reuse'\n\n/** A `relation` prop of a manifest. */\ninterface RelationProp {\n name: string\n /** The target collection id; `undefined` when the manifest declares none. */\n target: string | undefined\n multiple: boolean\n}\n\n/** Every `relation` prop of a manifest, in declaration order. */\nfunction relationPropsOf(manifest: ComponentManifest): RelationProp[] {\n const props: RelationProp[] = []\n for (const field of manifestPropFields(manifest)) {\n if (field.type !== 'relation') continue\n props.push({ name: field.name, target: field.target, multiple: field.multiple === true })\n }\n return props\n}\n\n/**\n * The relation props a DECLARED embed could plausibly transclude through: targeted\n * and cardinality-one. A cardinality-`many` (or targetless) relation is excluded\n * structurally, not heuristically — an embed transcludes exactly one document and\n * {@link makeEmbedNode} writes exactly one `{collection,id}`, which a list-valued\n * or target-less prop cannot hold.\n */\nfunction embeddableRelationProps(manifest: ComponentManifest): TargetedRelationProp[] {\n return relationPropsOf(manifest).filter(\n (r): r is TargetedRelationProp => r.target !== undefined && !r.multiple,\n )\n}\ntype TargetedRelationProp = RelationProp & { target: string }\n\n/** The collection's first composition field — what an embed of it transcludes. */\nfunction blocksFieldOf(collection: CollectionDef) {\n const field = collection.fields.find((f) => f.type === 'blocks')\n return field?.type === 'blocks' ? field : undefined\n}\n\n/**\n * The catalog keys for the reuse config issues (EC-478), in the `builder.reuse.config.*`\n * namespace. Named here so the producer and the catalog-parity test agree on one list.\n */\nconst REUSE_KEYS = {\n unknownComponent: 'builder.reuse.config.unknownComponent',\n noRelationProp: 'builder.reuse.config.noRelationProp',\n unknownRelationProp: 'builder.reuse.config.unknownRelationProp',\n ambiguousRelationProp: 'builder.reuse.config.ambiguousRelationProp',\n unknownCollection: 'builder.reuse.config.unknownCollection',\n noBlocksField: 'builder.reuse.config.noBlocksField',\n} as const\n\nfunction reuseIssue(\n code: CustomizationIssue['code'],\n severity: CustomizationIssue['severity'],\n message: string,\n messageRef: CustomizationMessageRef,\n id?: string,\n): CustomizationIssue {\n return {\n code,\n severity,\n message,\n messageRef,\n point: REUSE_POINT,\n ...(id === undefined ? {} : { id }),\n }\n}\n\n/** `\"a\", \"b\"` — a readable list of prop/component ids for an issue message. */\nfunction quotedList(names: readonly string[]): string {\n return names.map((name) => `\"${name}\"`).join(', ')\n}\n\n/**\n * Resolve the DECLARED embed (EC-467, AD-b). The declaration is the developer's\n * authority: a declared component may have slots, may declare `listing`, and its\n * relation prop may be `form.hidden` — the engine does not second-guess a stated\n * intent. Only structural impossibilities are issues (see AD-c row 2): an unknown\n * component id, no usable relation prop (or an ambiguous set with no\n * `relationProp`), an undefined target collection, or a target with no `blocks`\n * field — each of which would leave nothing coherent to transclude.\n */\nfunction resolveDeclaredReuse(\n declaration: StudioReuseConfig,\n manifests: readonly ComponentManifest[],\n collections: readonly CollectionDef[],\n): ReuseResolution {\n const { component, relationProp } = declaration\n const fail = (message: string, messageRef: CustomizationMessageRef): ReuseResolution => ({\n capability: null,\n issues: [reuseIssue('invalid-override', 'error', message, messageRef, component)],\n })\n\n const manifest = manifests.find((m) => m.id === component)\n if (!manifest) {\n return {\n capability: null,\n issues: [\n reuseIssue(\n 'unknown-override-target',\n 'error',\n `Reusable elements: studio config declares reuse.component \"${component}\", which is not a registered component. Fix the id to name your embed component — until then the reuse gestures are off.`,\n { key: REUSE_KEYS.unknownComponent, vars: { component } },\n component,\n ),\n ],\n }\n }\n\n const relations = embeddableRelationProps(manifest)\n if (relations.length === 0) {\n return fail(\n `Reusable elements: the declared embed \"${component}\" has no single-document relation prop, so it cannot point at a reusable document. An embed needs one relation prop with cardinality one.`,\n { key: REUSE_KEYS.noRelationProp, vars: { component } },\n )\n }\n const names = relations.map((r) => r.name)\n let relation: TargetedRelationProp\n if (relationProp !== undefined) {\n const named = relations.find((r) => r.name === relationProp)\n if (!named) {\n return fail(\n `Reusable elements: the declared embed \"${component}\" has no single-document relation prop named \"${relationProp}\". Its relation props are: ${quotedList(names)}.`,\n {\n key: REUSE_KEYS.unknownRelationProp,\n vars: { component, relationProp, props: quotedList(names) },\n },\n )\n }\n relation = named\n } else if (relations.length === 1) {\n relation = relations[0]!\n } else {\n return fail(\n `Reusable elements: the declared embed \"${component}\" has ${relations.length} single-document relation props (${quotedList(names)}) — add reuse.relationProp to say which one points at the reusable document.`,\n {\n key: REUSE_KEYS.ambiguousRelationProp,\n vars: { component, count: relations.length, props: quotedList(names) },\n },\n )\n }\n\n const collection = collections.find((c) => c.id === relation.target)\n if (!collection) {\n return fail(\n `Reusable elements: \"${component}.${relation.name}\" targets the collection \"${relation.target}\", which this project does not define.`,\n {\n key: REUSE_KEYS.unknownCollection,\n vars: { component, relationProp: relation.name, collection: relation.target },\n },\n )\n }\n const blocksField = blocksFieldOf(collection)\n if (!blocksField) {\n return fail(\n `Reusable elements: the collection \"${collection.id}\" behind \"${component}.${relation.name}\" has no blocks (composition) field, so there is nothing for the embed to transclude.`,\n {\n key: REUSE_KEYS.noBlocksField,\n vars: { component, relationProp: relation.name, collection: collection.id },\n },\n )\n }\n\n return {\n capability: {\n embedComponentId: manifest.id,\n relationProp: relation.name,\n collectionId: collection.id,\n contentField: blocksField.name,\n contentCardinality: itemLimit(blocksField) === 1 ? 'one' : 'many',\n },\n issues: [],\n }\n}\n\n/**\n * Resolve the project's ONE reuse capability (AD-a) plus any config issues — EC-728's\n * matrix (declare, never infer):\n *\n * | Declaration | Result |\n * | --- | --- |\n * | present, resolves | the declared capability, no issue |\n * | present, does not resolve | `null` + an ERROR issue (misconfiguration) |\n * | absent | `null`, **no issue** — the project has no reusable elements |\n *\n * The absent row is deliberately silent: a project need not use reusable elements,\n * and naming a component that \"looks like an embed\" would be the guess again, as\n * advice (EC-728). An unresolvable declaration disables the gestures and is reported\n * once, in the header Issues popover.\n */\nexport function resolveReuse(\n manifests: readonly ComponentManifest[],\n collections: readonly CollectionDef[],\n declaration?: StudioReuseConfig,\n): ReuseResolution {\n if (!declaration) return { capability: null, issues: [] }\n return resolveDeclaredReuse(declaration, manifests, collections)\n}\n\n/**\n * The project's reuse capability alone, or `null` when it is undeclared or\n * misdeclared — for callers that act on the capability and do not surface config\n * issues themselves (the gestures, the canvas placeholder). The issues are surfaced\n * ONCE, by the shell; see {@link resolveReuse}.\n */\nexport function resolveReuseCapability(\n manifests: readonly ComponentManifest[],\n collections: readonly CollectionDef[],\n declaration?: StudioReuseConfig,\n): ReuseCapability | null {\n return resolveReuse(manifests, collections, declaration).capability\n}\n\n/** A slug for `name`, suffixed `-2`/`-3`/… until it is free among `taken`. */\nexport function uniqueSlug(name: string, taken: ReadonlySet<string>): string {\n const base = slugify(name) || 'element'\n let id = base\n for (let n = 2; taken.has(id); n += 1) id = `${base}-${n}`\n return id\n}\n\n/**\n * The values for a new reusable document promoted from `node` (EC-282): seeded\n * defaults, the given `name` on the title field, the node on the content field,\n * and a collision-safe slug on any UNIQUE text field (e.g. a production site's\n * `internalId`) so the created document is publish-valid without hardcoding that\n * field's name. Other required fields, if any, are completed by the editor when\n * they open the new reusable.\n *\n * EC-580: every write goes through core's `writeField` in the project's DEFAULT\n * locale — the new document is created in its default bucket, so a localized title\n * or content field lands under `localized[default]`, never on the shared bag.\n */\nexport function buildReusableValues(\n collection: CollectionDef,\n capability: ReuseCapability,\n name: string,\n node: ComponentNode,\n existing: readonly { values?: Record<string, unknown> }[],\n locales: LocaleConfig,\n): Pick<CmsDocument, 'values' | 'localized'> {\n const at = locales.default\n let doc: CmsDocument = { collection: collection.id, id: '', ...seedDefaults(collection, locales) }\n const titleField = titleFieldOf(collection)?.name\n if (titleField) doc = writeField(collection, doc, titleField, at, name)\n for (const field of collection.fields) {\n if (\n field.type === 'text' &&\n field.validation?.unique === true &&\n field.name !== titleField &&\n field.name !== capability.contentField\n ) {\n const taken = new Set(\n existing\n .map((d) => d.values?.[field.name])\n .filter((v): v is string => typeof v === 'string'),\n )\n doc = writeField(collection, doc, field.name, at, uniqueSlug(name, taken))\n }\n }\n // EC-576: the converged v2 sequence holding the tagged node, through the core\n // write path — never the pre-0.0.84 bare node/array. Cardinality is a\n // constraint over that one shape, not a second shape (EC-500 D2).\n doc = writeField(collection, doc, capability.contentField, at, editBlockRoots(undefined, () => [node]))\n return { values: doc.values, ...(doc.localized !== undefined ? { localized: doc.localized } : {}) }\n}\n\n/**\n * The document a reuse-embed `node` targets (EC-300), or null when `node` is not the\n * embed component or has no static pick yet. Lets the canvas detect a HARD reference\n * whose target doesn't resolve (→ placeholder) without reaching into prop internals.\n */\nexport function reuseEmbedRef(node: ComponentNode, capability: ReuseCapability): DocumentRef | null {\n if (node.componentId !== capability.embedComponentId) return null\n const prop = node.props?.[capability.relationProp]\n const ref = isStaticProp(prop) ? readDocumentRef(prop.value) : undefined\n return ref ?? null\n}\n\n/**\n * The `Reusable` embed node referencing the new document (id minted by the action).\n *\n * EC-728 — CANONICAL from the first write: the prop is core's `staticProp` (bare `{ value }`,\n * EC-312), never `{ kind: 'static', value }`. The canvas commits its node patches raw, while\n * the draft takes the same write through the self-typing lens, which strips a redundant\n * `kind`; a non-canonical node therefore made the two views of the canvas field disagree, the\n * draft reported the disagreement as a change made underneath the canvas, and the rebase\n * dropped *Make reusable*'s own undo step (`reuse-undo.test.ts`).\n */\nexport function makeEmbedNode(capability: ReuseCapability, documentId: string): ComponentNode {\n return {\n id: 'reuse-embed',\n componentId: capability.embedComponentId,\n props: {\n // EC-589 / EC-586: a reference is a typed envelope from the first write.\n [capability.relationProp]: staticProp(referenceNode({ collection: capability.collectionId, id: documentId })),\n },\n }\n}\n\n// --- The placement preflight (EC-584, closes EC-560) --------------------------------\n\n/**\n * Why a reuse gesture is refused before it does anything: the one core placement\n * judge's verdict, and the label of the FIELD it names when the refusal is at a\n * field's top level (the canvas field, or the reusable collection's content field).\n */\nexport interface ReuseRefusal {\n verdict: PlacementVerdict\n fieldLabel: string\n}\n\n/**\n * EC-584 / EC-560 — \"Make reusable\" preflight, run BEFORE any side effect (the\n * reusable document is created — and maybe published — before the canvas swaps the\n * block for the embed). Two placements, both judged by the one core judge the\n * builder reducer enforces:\n *\n * 1. the EMBED lands where the promoted block was (the canvas field's `allow` at the\n * root, or the slot's `allow` when the block sits in a slot);\n * 2. the promoted BLOCK lands at the top level of the reusable collection's content\n * field (that field's effective vocabulary, `fieldAllowList`).\n *\n * `null` when both are admitted. The reducer still enforces (1) on its own.\n */\nexport function promoteRefusal(args: {\n root: ComponentNode\n nodeId: string\n node: ComponentNode\n capability: ReuseCapability\n collection: CollectionDef\n placement: PlacementScope\n canvasFieldLabel: string\n}): ReuseRefusal | null {\n const { root, nodeId, node, capability, collection, placement, canvasFieldLabel } = args\n const embed = replacePlacementRefusal(root, nodeId, [makeEmbedNode(capability, 'preflight')], placement)\n if (embed) return { verdict: embed, fieldLabel: canvasFieldLabel }\n const contentField = collection.fields.find((field) => field.name === capability.contentField)\n const contentAllow = contentField ? fieldAllowList(contentField) : undefined\n if (contentField && contentAllow) {\n const into = valuePlacementRefusal([node], { components: placement.components, fieldAllow: contentAllow })\n if (into) return { verdict: into, fieldLabel: fieldLabel(contentField) }\n }\n return null\n}\n\n/**\n * EC-584 / EC-560 — \"Detach to local copy\" preflight: the reusable's content blocks\n * land where the embed was. Refusing the WHOLE gesture when one inlined block is\n * outside the vocabulary keeps the reference in place (EC-560's frame: refuse\n * visibly, dispatch nothing) — the editor sees why and decides.\n */\nexport function detachRefusal(args: {\n root: ComponentNode\n nodeId: string\n blocks: readonly ComponentNode[]\n placement: PlacementScope\n canvasFieldLabel: string\n}): ReuseRefusal | null {\n const verdict = replacePlacementRefusal(args.root, args.nodeId, args.blocks, args.placement)\n return verdict ? { verdict, fieldLabel: args.canvasFieldLabel } : null\n}\n\n/** The effects \"Make reusable\" performs — injected, so the order and the refusal are testable. */\nexport interface PromoteEffects {\n newDocumentId(): string\n insertDocument(doc: CmsDocument): void\n /**\n * The in-place swap — ONE history entry carrying `effect` (EC-728: the created document, so\n * Undo can remove it when that is safe and Redo can re-insert it).\n */\n replaceInCanvas(nodeId: string, embed: ComponentNode, effect: CanvasHistoryEffect): void\n /** Publish the new reusable; resolves `true` only when the document IS published afterwards. */\n publish(ref: DocumentRef): Promise<boolean>\n refused(refusal: ReuseRefusal): void\n madeDraft(name: string): void\n madePublished(name: string): void\n publishFailed(name: string): void\n}\n\n/**\n * Run \"Make reusable\" (EC-282) — the preflight first (EC-584: a refusal creates,\n * publishes and replaces NOTHING), then ONE insert-if-absent create of the reusable\n * document (EC-595 A2), the in-place swap for the embed — one canvas history entry that\n * records the created document (EC-728) — and the chosen publish, whose success notice is\n * shown only when the document is actually published.\n */\nexport async function runPromote(args: {\n root: ComponentNode\n nodeId: string\n node: ComponentNode\n name: string\n publish: boolean\n capability: ReuseCapability\n collection: CollectionDef\n existing: readonly { values?: Record<string, unknown> }[]\n locales: LocaleConfig\n placement: PlacementScope\n canvasFieldLabel: string\n effects: PromoteEffects\n}): Promise<'refused' | 'draft' | 'published' | 'publish-failed'> {\n const { root, nodeId, node, name, capability, collection, placement, canvasFieldLabel, effects } = args\n const refusal = promoteRefusal({ root, nodeId, node, capability, collection, placement, canvasFieldLabel })\n if (refusal) {\n effects.refused(refusal)\n return 'refused'\n }\n const ref = { collection: capability.collectionId, id: effects.newDocumentId() }\n const content = buildReusableValues(collection, capability, name, node, args.existing, args.locales)\n const document: CmsDocument = { ...ref, ...content }\n effects.insertDocument(document)\n effects.replaceInCanvas(nodeId, makeEmbedNode(capability, ref.id), { kind: 'reusable-created', ref, name, document })\n if (!args.publish) {\n effects.madeDraft(name)\n return 'draft'\n }\n const published = await effects.publish(ref).catch(() => false)\n if (published) {\n effects.madePublished(name)\n return 'published'\n }\n effects.publishFailed(name)\n return 'publish-failed'\n}\n\n// --- Undo / Redo of \"Make reusable\" (EC-728) ------------------------------------------\n\n/**\n * What Undo did with the document *Make reusable* created: `deleted`, or already `gone`, or\n * KEPT — because it is `published`, was `edited` since it was made, is `referenced` elsewhere,\n * or the removal `failed`. The block is restored in every case (the canvas entry is a snapshot).\n */\nexport type PromoteUndoOutcome = 'deleted' | 'gone' | 'published' | 'edited' | 'referenced' | 'failed'\n\n/** The one write Undo needs, and the read that words its refusal — injected, so every branch is testable. */\nexport interface PromoteUndoDeps {\n /** Await every queued write: the page's restored value lands before anything is judged. */\n flush(): Promise<void>\n /**\n * The conditional delete (`CmsPersister.deleteCreated`) — THE judge: unchanged since this\n * session's create (so never published), and referenced by nothing, weak or strict, draft or\n * published — every condition checked by the store in its one delete step (EC-739).\n */\n deleteCreated(ref: DocumentRef): Promise<DeleteCreatedOutcome>\n /**\n * The document's record now (`undefined`: it no longer exists) — read only to WORD a\n * `changed` refusal (published, or edited); it decides nothing.\n */\n read(ref: DocumentRef): Promise<{ published: boolean } | undefined>\n}\n\n/**\n * EC-728 — Undo of *Make reusable*, the document side. The created document is deleted ONLY\n * when nobody else has it: unchanged since its create (hence never published — a publish\n * moves the revision) and referenced by nothing — weak or strict, draft or published, after\n * the page's own restore has landed. EC-739 (Codex F41): those are conditions of the ONE\n * conditional delete, checked by the store in its own step, never a count read before it — a\n * colleague's relation saved between a count and the delete adopted the document and was\n * deleted out from under it. Anything else keeps it, with the reason. A delete that throws\n * keeps it too: an unproven fact never deletes.\n */\nexport async function undoPromote(effect: CanvasHistoryEffect, deps: PromoteUndoDeps): Promise<PromoteUndoOutcome> {\n try {\n await deps.flush()\n switch (await deps.deleteCreated(effect.ref)) {\n case 'deleted':\n return 'deleted'\n case 'gone':\n return 'gone'\n case 'referenced':\n return 'referenced'\n case 'changed': {\n // Kept either way; the record only says which notice is true. Unreadable: the delete's own answer.\n const record = await deps.read(effect.ref).catch(() => undefined)\n return record?.published ? 'published' : 'edited'\n }\n default:\n return 'failed'\n }\n } catch {\n return 'failed'\n }\n}\n\n/** The catalog keys of the kept-document notices (EN + DE in the studio catalogs). */\nexport type ReuseUndoNoticeKey =\n | 'builder.reuse.undoKeptPublished'\n | 'builder.reuse.undoKeptEdited'\n | 'builder.reuse.undoKeptReferenced'\n | 'builder.reuse.undoKeptFailed'\n\n/** The notice for a KEPT document (EC-728 — it names the document and why); none when it went. */\nexport function undoPromoteNotice(outcome: PromoteUndoOutcome): ReuseUndoNoticeKey | undefined {\n switch (outcome) {\n case 'published':\n return 'builder.reuse.undoKeptPublished'\n case 'edited':\n return 'builder.reuse.undoKeptEdited'\n case 'referenced':\n return 'builder.reuse.undoKeptReferenced'\n case 'failed':\n return 'builder.reuse.undoKeptFailed'\n default:\n return undefined\n }\n}\n\n/**\n * EC-728 — the document side of every Undo/Redo that crosses a *Make reusable* step, for one\n * canvas. Crossings run strictly in order (a Redo waits for the Undo before it), so a fast\n * Undo → Redo never re-inserts a document whose removal is still in flight. Redo re-inserts\n * (the same id, insert-if-absent) exactly the documents ITS Undo removed or found gone — never\n * one Undo kept (it is still there) — and the canvas entry re-swaps the embed.\n */\nexport function createPromoteHistory(\n deps: PromoteUndoDeps & {\n insert(document: CmsDocument): void\n notify(key: ReuseUndoNoticeKey, name: string): void\n },\n): { crossed(step: { direction: 'undo' | 'redo'; effect: CanvasHistoryEffect }): Promise<void> } {\n const removed = new Set<string>()\n let chain: Promise<void> = Promise.resolve()\n return {\n crossed(step) {\n chain = chain.then(async () => {\n const key = documentKey(step.effect.ref)\n if (step.direction === 'redo') {\n if (removed.delete(key)) deps.insert(step.effect.document)\n return\n }\n const outcome = await undoPromote(step.effect, deps)\n if (outcome === 'deleted' || outcome === 'gone') removed.add(key)\n const notice = undoPromoteNotice(outcome)\n if (notice) deps.notify(notice, step.effect.name)\n })\n return chain\n },\n }\n}\n"]}
|
|
@@ -385,9 +385,7 @@ function AssetOptionsDialog({ assetId, readOnly, open, onOpenChange, placement,
|
|
|
385
385
|
}
|
|
386
386
|
if (seeded.current || !record)
|
|
387
387
|
return;
|
|
388
|
-
// Seed from the stored bags
|
|
389
|
-
// `assetMetaDraft`): a not-yet-migrated asset shows its alt; the write rule moves it to
|
|
390
|
-
// `meta.alt` and clears the column when the commit's patch is applied.
|
|
388
|
+
// Seed from the stored bags (`assetMetaDraft`; the alt is `meta.alt`, EC-587).
|
|
391
389
|
const seed = assetMetaDraft(record);
|
|
392
390
|
opened.current = seed;
|
|
393
391
|
setDraft(seed);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset-field.js","sourceRoot":"","sources":["../../../src/components/cms/asset-field.tsx"],"names":[],"mappings":"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","sourcesContent":["import { GripVertical, ImagePlus, Link2, RotateCcw, SlidersHorizontal, Trash2, Upload, X } from 'lucide-react'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { AssetFieldDef, FieldDef } from '@elytracms/core/cms-core'\nimport { assetAlt } from '@elytracms/core/persistence'\nimport type { AssetReadLocale, AssetRecord } from '@elytracms/core/persistence'\nimport {\n assetNode,\n assetSubfieldsOf,\n moveAssetPlacement,\n readAssetId,\n removeAssetPlacementAt,\n selfTypeFieldValue,\n} from '@elytracms/core/cms-core'\nimport {\n Button,\n Card,\n Code,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n Field,\n Heading,\n Row,\n Separator,\n Spacer,\n Stack,\n Text,\n} from '@elytracms/studio/ui'\nimport { Link, STUDIO_PROJECT_ROUTE, studioPath } from '@elytracms/studio/router'\nimport { cn } from '../../lib/utils'\nimport { localizedLabel, translate } from '../../lib/i18n'\nimport {\n appendAssetSelections,\n applyAssetSelection,\n assetIdsOf,\n singleAssetIdOf,\n} from '../assets/asset-selection'\nimport { useOptionalAssets } from '../assets/assets-store'\nimport { AssetThumb, FocalCropPreviews, FocalPointPicker, useAssetRecord } from '../assets/asset-thumb'\nimport { assetPickerBinding, batchAttachment, splitByAccept, uploadBatchProgress } from './asset-picker-core'\nimport type { UploadBatch } from './asset-picker-core'\nimport {\n assetMetaDraft,\n assetMetaDraftPatch,\n assetMetaFieldsOf,\n assetMetaFormValues,\n setAssetMetaField,\n} from '../assets/asset-metadata'\nimport type { AssetMetaDraft } from '../assets/asset-metadata'\nimport { useAssetReadLocale } from '../assets/asset-locale'\nimport { AssetMetaFieldLabel } from '../assets/asset-meta-label'\nimport { ReplaceFileButton } from '../assets/replace-file'\nimport { useCollectionView } from '../collection-view/collection-view-context'\nimport { useFieldDensity } from './field-density'\nimport { AssetPicker, AssetRejectedNotice } from './asset-picker'\nimport { FieldControl } from './field-control'\nimport { ObjectItemForm } from './object-array-field'\nimport { FieldPathContext, useFieldPath } from './field-anchors'\n\n/** The draft before the dialog seeds (EC-632) — nothing open, nothing to diff. */\nconst EMPTY_DRAFT: AssetMetaDraft = { meta: {}, localizedMeta: {} }\n\n/**\n * The asset-field family (EC-152 + EC-248 + EC-301) — split from\n * `field-control.tsx` (EC-330): the {@link AssetField} control plus its\n * preview/gallery/options sub-components. Per-use sub-fields and the options\n * dialog's metadata form render through the shared object item form /\n * `FieldControl`, so asset metadata stays schema-driven.\n */\n\n/**\n * The asset field (EC-152 + EC-248). Beyond picking from the library it now shows\n * a focal-point-aware preview, uploads directly from the field (reusing the EC-152\n * upload path — no parallel uploader), and edits the selected image's alt + focal\n * point inline (persisted on the asset document, where delivery reads them, EC-230).\n * With no `<AssetsProvider>` (a fixture-only session — every project, the playground\n * included, mounts one, `studio-project-screen.tsx`) it degrades to the labelled-badge\n * picker — no preview/upload — so it stays usable without a real library.\n */\nexport function AssetField({\n field,\n value: stored,\n onChange,\n readOnly,\n}: {\n field: AssetFieldDef\n value: unknown\n onChange: (value: unknown) => void\n readOnly: boolean\n}) {\n // EC-586/EC-581 (ASSETS D4): the field reads its value through THE canonicaliser — the\n // one cardinality rule — so a lone placement left in a field since declared `multiple`\n // shows as a one-item gallery (and the next pick keeps it) instead of an empty one that\n // drops it; picks and removes then write from that canonical list.\n const value = useMemo(() => selfTypeFieldValue(field, stored), [field, stored])\n const source = useCollectionView()\n const assets = useOptionalAssets()\n const density = useFieldDensity()\n const compact = density === 'compact'\n // EC-582 / EC-572 #1: the anchor prefix of this field — a gallery placement's sub-field\n // inputs are stamped `<field>/<entry index>/<sub-field>`, the path the validator gives\n // their issues (a single placement's are `<field>/<sub-field>`, stamped by the form).\n const fieldPath = useFieldPath()\n const [open, setOpen] = useState(false)\n // The placement whose image options dialog is open (EC-588 2i: every placement of a\n // gallery has one, not only a single field's): its gallery index, or `null` for a\n // single field's one placement.\n const [editing, setEditing] = useState<{ index: number | null } | null>(null)\n const [dragging, setDragging] = useState(false)\n // Reorder by drag (EC-588 2i): the gallery index being dragged and the one under it.\n const [moveFrom, setMoveFrom] = useState<number | null>(null)\n const [moveOver, setMoveOver] = useState<number | null>(null)\n // Names of files a drop/pick rejected against the field's `accept` (EC-301) — shown\n // as a transient inline issue, cleared on the next valid upload. Never a silent drop.\n const [rejected, setRejected] = useState<string[]>([])\n // The active upload BATCH (EC-460): exactly the upload ids this field's drop\n // started (EC-588 A7), so the effect below attaches the WHOLE batch and nothing\n // another tab or a sibling field uploaded meanwhile.\n const pendingRef = useRef<UploadBatch | null>(null)\n const assetCollectionId = source.assetCollectionId ?? 'asset'\n const many = field.multiple\n const ids = many ? assetIdsOf(value) : []\n const single = !many ? singleAssetIdOf(value) : null\n // EC-301 per-use sub-fields: the value stores asset ENVELOPES (`{ type:'asset', id }`,\n // EC-586 — the canonical form, sub-fields or not) carrying any sub-field siblings\n // (`caption`). Picks/edits/removes preserve every other placement's sub-fields.\n const subFields = field.fields ?? []\n const hasSub = subFields.length > 0\n // The raw `many` entries (envelopes or bare ids), index-aligned with `ids`, so each\n // gallery item can read/write its own sub-fields.\n const entries = many && Array.isArray(value) ? (value as unknown[]) : []\n\n // Auto-select what an upload FROM this field added once it lands in the\n // library. EC-460: a `many` field attaches EVERY batch arrival as it lands\n // (the batch stays armed until it settles), so dropping N files attaches all\n // N — the old flow disarmed on the FIRST arrival and silently stranded the\n // rest in the library. A `one` field keeps the first-to-land selection.\n useEffect(() => {\n const batch = pendingRef.current\n if (!batch || !assets) return\n // EC-588 2i: the one batch-attach rule (the picker runs it too) — a `many` field\n // appends the whole batch once it settles, IN FILE ORDER; a single field takes the\n // first arrival.\n const { attach, disarm } = batchAttachment(uploadBatchProgress(batch, assets, field.accept), many)\n if (disarm) pendingRef.current = null\n if (attach.length === 0) return\n const next = many ? appendAssetSelections(value, attach) : applyAssetSelection(value, attach[0]!, false)\n if (next !== value) onChange(next)\n // Reacts to the assets store changing (an upload landing in the library, the\n // queue draining) — `value`/`onChange` are read from the closure on purpose.\n }, [assets, field.accept, many, onChange, value])\n\n function uploadFiles(files: File[]) {\n if (!assets || files.length === 0) return\n // EC-301 → EC-588: the drop rule the picker applies too — a drag-drop bypasses\n // the file dialog's `accept` filter, so re-check each file and name the rejects in\n // a visible notice instead of silently uploading the wrong kind.\n const { accepted, rejected: refused } = splitByAccept(files, field.accept)\n setRejected(refused)\n if (accepted.length === 0) return\n pendingRef.current = { uploadIds: assets.upload(accepted) }\n }\n\n // The picker is configured from the field — the SAME binding the table cell uses\n // (EC-570 #1 → EC-588): `accept`, `multiple`, and a pick through the carry rule\n // (EC-558) so a placement's per-use sub-fields (EC-301) survive a swap or an append.\n const pickerBinding = assetPickerBinding(field, value, (next) => {\n if (next !== value) onChange(next)\n })\n\n const canUpload = !readOnly && assets !== null\n\n // The open dialog's placement: which asset it shows, and — when the field declares\n // per-use sub-fields — the placement form it edits (\"In this place\").\n const editTarget = ((): { assetId: string; placement?: PlacementForm } | null => {\n if (!editing) return null\n if (editing.index === null) {\n if (!single) return null\n if (!hasSub) return { assetId: single }\n return {\n assetId: single,\n placement: {\n fields: subFields,\n value: assetSubfieldsOf(value),\n onChange: (next: Record<string, unknown>) => onChange(assetNode(single, next)),\n },\n }\n }\n if (!hasSub) {\n const aid = ids[editing.index]\n return aid ? { assetId: aid } : null\n }\n const entry = entries.filter((e) => readAssetId(e) !== undefined)[editing.index]\n const aid = readAssetId(entry)\n if (!aid) return null\n const raw = entries.indexOf(entry)\n return {\n assetId: aid,\n placement: {\n fields: subFields,\n value: assetSubfieldsOf(entry),\n onChange: (next: Record<string, unknown>) => {\n const nextEntries = entries.slice()\n nextEntries[raw] = assetNode(aid, next)\n onChange(nextEntries)\n },\n },\n }\n })()\n\n // Drag-to-upload onto the field (EC-301): a depth counter keeps the overlay\n // steady as the pointer crosses child element boundaries. `dragenter`/`dragleave`\n // fire per descendant, so toggling on a bare `dragleave` blinks constantly; we\n // only hide the overlay when the counter returns to zero (the pointer has truly\n // left the field). The overlay is pointer-events-none, so it never fires its own\n // enter/leave to confuse the count.\n const dragDepth = useRef(0)\n // Only a FILE drag is an upload: a gallery reorder drag (EC-588) is not.\n const isFileDrag = (e: React.DragEvent) => Array.from(e.dataTransfer.types).includes('Files')\n function onDragEnter(e: React.DragEvent) {\n if (!canUpload || !isFileDrag(e)) return\n e.preventDefault()\n dragDepth.current += 1\n if (!dragging) setDragging(true)\n }\n function onDragOver(e: React.DragEvent) {\n if (!canUpload || !isFileDrag(e)) return\n e.preventDefault() // required so a drop is allowed\n }\n function onDragLeave(e: React.DragEvent) {\n if (!canUpload || !isFileDrag(e)) return\n dragDepth.current -= 1\n if (dragDepth.current <= 0) {\n dragDepth.current = 0\n setDragging(false)\n }\n }\n function onDrop(e: React.DragEvent) {\n if (!canUpload || !isFileDrag(e)) return\n e.preventDefault()\n dragDepth.current = 0\n setDragging(false)\n uploadFiles(Array.from(e.dataTransfer.files))\n }\n // While the picker is open the field is behind the modal, so any drop is happening\n // INSIDE the dialog — detach the field's drag handlers entirely so a drop there can\n // only be handled by the picker, never double-counted by the field too (EC-301). This\n // is the belt to the picker's stopPropagation braces: the field cannot react at all.\n const dragProps = canUpload && !open ? { onDragEnter, onDragOver, onDragLeave, onDrop } : {}\n\n // Reorder by drag (EC-588 2i): one placement moves, every entry verbatim — core's\n // `moveAssetPlacement`, the same index counting as the remove.\n const reorderable = many && !readOnly && ids.length > 1\n function reorderProps(i: number) {\n if (!reorderable) return {}\n return {\n onDragOver: (e: React.DragEvent) => {\n if (moveFrom === null) return\n e.preventDefault()\n if (moveOver !== i) setMoveOver(i)\n },\n onDrop: (e: React.DragEvent) => {\n if (moveFrom === null) return\n e.preventDefault()\n const next = moveAssetPlacement(value, moveFrom, i)\n setMoveFrom(null)\n setMoveOver(null)\n if (next !== value) onChange(next)\n },\n }\n }\n function moveHandle(i: number): ReactNode {\n if (!reorderable) return null\n return (\n <span\n draggable\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(i))\n setMoveFrom(i)\n }}\n onDragEnd={() => {\n setMoveFrom(null)\n setMoveOver(null)\n }}\n aria-label={translate('cms.field.dragToReorder')}\n className=\"cursor-grab text-muted-foreground/60 hover:text-muted-foreground active:cursor-grabbing\"\n >\n <GripVertical className=\"size-3.5\" />\n </span>\n )\n }\n const moveTint = (i: number) =>\n cn(moveFrom === i && 'opacity-50', moveOver === i && moveFrom !== null && moveFrom !== i && 'ring-2 ring-primary/50')\n\n const selectButton = !readOnly ? (\n <Button variant=\"outline\" size=\"sm\" onClick={() => setOpen(true)}>\n <ImagePlus /> {translate('common.select')}\n </Button>\n ) : null\n\n return (\n <Stack\n gap=\"2\"\n className={cn(\n 'relative rounded-lg transition-shadow',\n dragging && 'ring-2 ring-primary ring-offset-2 ring-offset-background',\n )}\n {...dragProps}\n >\n {many && hasSub ? (\n // Gallery with per-use sub-fields (EC-301): a card per placement — thumbnail +\n // its own sub-field form — reusing the object/repeater item rendering.\n <Stack gap=\"2\">\n {entries.length > 0 ? (\n <Stack gap=\"2\">\n {entries.map((entry, i) => {\n const aid = readAssetId(entry)\n if (!aid) return null\n // The gallery position of this placement (readable entries only) — the\n // index the one remove rule counts (core `removeAssetPlacementAt`).\n const galleryIndex = entries.slice(0, i).filter((e) => readAssetId(e) !== undefined).length\n return (\n <div key={`${aid}-${i}`} className={cn('rounded-lg', moveTint(galleryIndex))} {...reorderProps(galleryIndex)}>\n <FieldPathContext.Provider value={fieldPath === null ? null : `${fieldPath}/${i}`}>\n <AssetGalleryItem\n assetId={aid}\n collectionId={assetCollectionId}\n fields={subFields}\n value={assetSubfieldsOf(entry)}\n readOnly={readOnly}\n idPrefix={`asset-${i}`}\n handle={moveHandle(galleryIndex)}\n onChangeSubs={(next) => {\n const nextEntries = entries.slice()\n nextEntries[i] = assetNode(aid, next)\n onChange(nextEntries)\n }}\n onEdit={assets ? () => setEditing({ index: galleryIndex }) : undefined}\n onRemove={readOnly ? undefined : () => onChange(removeAssetPlacementAt(value, galleryIndex))}\n />\n </FieldPathContext.Provider>\n </div>\n )\n })}\n </Stack>\n ) : (\n <EmptyAssetState\n compact={compact}\n canUpload={canUpload}\n readOnly={readOnly}\n onSelect={() => setOpen(true)}\n />\n )}\n <Row gap=\"2\" wrap align=\"center\">\n {selectButton}\n </Row>\n </Stack>\n ) : many ? (\n // Gallery: a grid of focal-aware previews + the single Select entry.\n <Stack gap=\"2\">\n {ids.length > 0 ? (\n <div\n className={cn(\n 'grid gap-2',\n compact ? 'grid-cols-2' : 'grid-cols-3 sm:grid-cols-4',\n )}\n >\n {ids.map((aid, i) => (\n <div key={`${aid}-${i}`} className={cn('rounded-lg', moveTint(i))} {...reorderProps(i)}>\n <AssetChip\n assetId={aid}\n collectionId={assetCollectionId}\n handle={moveHandle(i)}\n onEdit={assets ? () => setEditing({ index: i }) : undefined}\n onRemove={readOnly ? undefined : () => onChange(removeAssetPlacementAt(value, i))}\n />\n </div>\n ))}\n </div>\n ) : (\n <EmptyAssetState\n compact={compact}\n canUpload={canUpload}\n readOnly={readOnly}\n onSelect={() => setOpen(true)}\n />\n )}\n <Row gap=\"2\" wrap align=\"center\">\n {selectButton}\n </Row>\n </Stack>\n ) : single && hasSub ? (\n // With per-use sub-fields the asset + its fields read as ONE grouped unit\n // (like an object), so it's clear they belong together (EC-301 feedback).\n <Card className=\"border-l-2 border-l-border p-3\">\n <Stack gap=\"3\">\n <AssetSinglePreview\n assetId={single}\n compact={compact}\n readOnly={readOnly}\n hasLibrary={assets !== null}\n fallbackTitle={source.titleOf({ collection: assetCollectionId, id: single })}\n selectButton={selectButton}\n onEdit={() => setEditing({ index: null })}\n onRemove={() => onChange(applyAssetSelection(value, null, many))}\n />\n <div className=\"border-t border-border/60 pt-3\">\n <ObjectItemForm\n fields={subFields}\n value={assetSubfieldsOf(value)}\n readOnly={readOnly}\n idPrefix=\"asset-sub\"\n onChange={(next) => onChange(assetNode(single, next))}\n />\n </div>\n </Stack>\n </Card>\n ) : single ? (\n <AssetSinglePreview\n assetId={single}\n compact={compact}\n readOnly={readOnly}\n hasLibrary={assets !== null}\n fallbackTitle={source.titleOf({ collection: assetCollectionId, id: single })}\n selectButton={selectButton}\n onEdit={() => setEditing({ index: null })}\n onRemove={() => onChange(applyAssetSelection(value, null, many))}\n />\n ) : (\n <Stack gap=\"2\">\n <EmptyAssetState\n compact={compact}\n canUpload={canUpload}\n readOnly={readOnly}\n onSelect={() => setOpen(true)}\n />\n <Row gap=\"2\" wrap align=\"center\">\n {selectButton}\n </Row>\n </Stack>\n )}\n\n {/* Image options (EC-301 → EC-588 2i): the placement's own sub-fields (\"In this\n place\") apart from the asset's facts (\"About this image\", shared by every use),\n for a single field's placement and for each placement of a gallery. */}\n {editTarget && assets ? (\n <AssetOptionsDialog\n assetId={editTarget.assetId}\n readOnly={readOnly}\n open\n onOpenChange={(next) => {\n if (!next) setEditing(null)\n }}\n {...(editTarget.placement ? { placement: editTarget.placement } : {})}\n />\n ) : null}\n\n <AssetPicker open={open} onOpenChange={setOpen} {...pickerBinding} />\n\n <AssetRejectedNotice rejected={rejected} accept={field.accept} />\n\n {dragging ? (\n <div className=\"pointer-events-none absolute inset-0 z-10 grid place-items-center rounded-lg border-2 border-dashed border-primary bg-background/85\">\n <Row gap=\"2\" align=\"center\">\n <Upload className=\"size-4 text-primary\" />\n <Text size=\"sm\" className=\"font-medium\">\n {translate('cms.asset.dropToUpload')}\n </Text>\n </Row>\n </div>\n ) : null}\n </Stack>\n )\n}\n\n/**\n * Empty-state placeholder shown when an asset field has no selection (EC-301).\n *\n * EC-395: this was the one asset-field affordance that ignored `readOnly` — every\n * sibling control (`selectButton`, the per-item remove/change actions) already\n * degraded, but the empty-state tile stayed a clickable `<button>` that opened the\n * picker regardless. A locked, empty asset field must be as inert as a filled one:\n * read-only renders a plain (non-interactive, non-focusable) `div` with the same\n * frame — no `onClick`, no hover affordance — instead of a `<button>`.\n */\nfunction EmptyAssetState({\n compact,\n canUpload,\n readOnly,\n onSelect,\n}: {\n compact: boolean\n canUpload: boolean\n readOnly: boolean\n onSelect: () => void\n}) {\n const frame = cn(\n 'grid w-full place-items-center gap-1 rounded-lg border border-dashed border-border bg-muted/30 text-center text-muted-foreground',\n compact ? 'aspect-video' : 'aspect-[5/2]',\n )\n if (readOnly) {\n return <div className={frame}>{emptyAssetStateBody(canUpload)}</div>\n }\n return (\n <button type=\"button\" onClick={onSelect} className={cn(frame, 'transition-colors hover:bg-muted/60')}>\n {emptyAssetStateBody(canUpload)}\n </button>\n )\n}\n\nfunction emptyAssetStateBody(canUpload: boolean) {\n return (\n <>\n <ImagePlus className=\"size-6\" aria-hidden />\n <Text size=\"xs\" tone=\"muted\">\n {canUpload ? translate('cms.asset.selectOrDrop') : translate('cms.asset.selectAsset')}\n </Text>\n </>\n )\n}\n\n/** A large focal-aware preview of the selected asset (EC-301). */\nfunction AssetPreview({ assetId }: { assetId: string }) {\n const record = useAssetRecord(assetId)\n return <AssetThumb record={record} className=\"aspect-[4/3] w-full\" />\n}\n\n/** Filename + dimensions/type for the selected asset — the id is never shown (EC-301). */\nfunction AssetInfo({ assetId, fallbackTitle }: { assetId: string; fallbackTitle?: string }) {\n const record = useAssetRecord(assetId)\n const name = record?.title ?? record?.filename ?? fallbackTitle ?? assetId\n const dims = record?.width && record?.height ? `${record.width}×${record.height}` : null\n const kind = record?.contentType?.split('/')[1]?.toUpperCase()\n const meta = [dims, kind].filter(Boolean).join(' · ')\n return (\n <Stack gap=\"1\">\n <Text size=\"sm\" className=\"truncate font-medium\" title={name}>\n {name}\n </Text>\n {meta ? (\n <Text size=\"xs\" tone=\"subtle\">\n {meta}\n </Text>\n ) : null}\n </Stack>\n )\n}\n\n/**\n * The selected image's alt text shown in the field (EC-301) — what an editor most\n * wants at a glance; edited in the options dialog. Read through THE reader (EC-587),\n * so the field shows exactly what delivery serves.\n */\nfunction AssetAltLine({ assetId }: { assetId: string }) {\n const record = useAssetRecord(assetId)\n // EC-632: in the studio's locale — a localized alt shows the open locale's translation.\n const at = useAssetReadLocale()\n const alt = record ? assetAlt(record, at) : null\n return (\n <Row gap=\"1\" align=\"baseline\" className=\"min-w-0\">\n <Text size=\"xs\" tone=\"subtle\" className=\"shrink-0\">\n {translate('cms.asset.altLabel')}\n </Text>\n <Text\n size=\"xs\"\n tone={alt ? 'muted' : 'subtle'}\n className={cn('min-w-0 truncate', !alt && 'italic')}\n title={alt ?? undefined}\n >\n {alt || translate('cms.asset.notSet')}\n </Text>\n </Row>\n )\n}\n\n/**\n * A single asset reference: focal-aware thumbnail + title, with an optional drag\n * handle (reorder, EC-588), image options and remove.\n */\nfunction AssetChip({\n assetId,\n collectionId,\n handle,\n onEdit,\n onRemove,\n}: {\n assetId: string\n collectionId: string\n handle?: ReactNode\n onEdit?: () => void\n onRemove?: () => void\n}) {\n const source = useCollectionView()\n const record = useAssetRecord(assetId)\n const title = source.titleOf({ collection: collectionId, id: assetId })\n return (\n <div className=\"group relative overflow-hidden rounded-lg border border-border bg-muted/40\">\n <AssetThumb record={record} alt={title} className=\"aspect-square w-full rounded-none border-0\" />\n <Row gap=\"1\" align=\"center\" className=\"px-2 py-1\">\n {handle}\n <Text size=\"xs\" tone=\"subtle\" className=\"min-w-0 flex-1 truncate\" title={title}>\n {title}\n </Text>\n {onEdit ? (\n <button\n type=\"button\"\n aria-label={translate('cms.asset.imageOptions.title')}\n onClick={onEdit}\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <SlidersHorizontal className=\"size-3.5\" />\n </button>\n ) : null}\n {onRemove ? (\n <button\n type=\"button\"\n aria-label={translate('common.remove')}\n onClick={onRemove}\n className=\"text-muted-foreground hover:text-destructive\"\n >\n <X className=\"size-3.5\" />\n </button>\n ) : null}\n </Row>\n </div>\n )\n}\n\n/**\n * The selected single asset's preview row (EC-301): large focal-aware preview + info\n * column (filename/dimensions, Select/Edit/Remove, alt). Extracted so it renders either\n * bare (a plain asset field) or inside the grouping card when the field carries per-use\n * sub-fields — the asset + its fields then read as one unit.\n */\nfunction AssetSinglePreview({\n assetId,\n compact,\n readOnly,\n hasLibrary,\n fallbackTitle,\n selectButton,\n onEdit,\n onRemove,\n}: {\n assetId: string\n compact: boolean\n readOnly: boolean\n hasLibrary: boolean\n fallbackTitle?: string\n selectButton: React.ReactNode\n onEdit: () => void\n onRemove: () => void\n}) {\n return (\n <div className={compact ? 'flex flex-col gap-3' : 'flex gap-4'}>\n <div className={compact ? 'w-full' : 'w-1/2 shrink-0'}>\n <AssetPreview assetId={assetId} />\n </div>\n <Stack gap=\"2\" className={cn('min-w-0', !compact && 'flex-1')}>\n <AssetInfo assetId={assetId} fallbackTitle={fallbackTitle} />\n {!readOnly ? (\n <Row gap=\"2\" wrap align=\"center\">\n {selectButton}\n {hasLibrary ? (\n <Button variant=\"outline\" size=\"sm\" onClick={onEdit}>\n <SlidersHorizontal /> {translate('common.edit')}\n </Button>\n ) : null}\n <Button variant=\"ghost\" size=\"sm\" onClick={onRemove}>\n <Trash2 /> {translate('common.remove')}\n </Button>\n </Row>\n ) : null}\n <AssetAltLine assetId={assetId} />\n </Stack>\n </div>\n )\n}\n\n/**\n * One gallery placement when a `many` asset field declares per-use sub-fields (EC-301):\n * a thumbnail + filename + remove header over the placement's own sub-field form,\n * modelled on a repeater item card so a gallery's placements read as grouped units.\n */\nfunction AssetGalleryItem({\n assetId,\n collectionId,\n fields,\n value,\n onChangeSubs,\n handle,\n onEdit,\n onRemove,\n readOnly,\n idPrefix,\n}: {\n assetId: string\n collectionId: string\n fields: readonly FieldDef[]\n value: Record<string, unknown>\n onChangeSubs: (value: Record<string, unknown>) => void\n handle?: ReactNode\n onEdit?: () => void\n onRemove?: () => void\n readOnly: boolean\n idPrefix: string\n}) {\n const source = useCollectionView()\n const record = useAssetRecord(assetId)\n const title = source.titleOf({ collection: collectionId, id: assetId })\n return (\n <Card className=\"border-l-2 border-l-border p-0\">\n <Row gap=\"2\" align=\"center\" className=\"border-b border-border/60 bg-muted/30 px-2 py-1.5\">\n {handle}\n <AssetThumb record={record} alt={title} className=\"size-10 shrink-0\" />\n <Text size=\"sm\" className=\"min-w-0 flex-1 truncate font-medium\" title={title}>\n {title}\n </Text>\n {onEdit ? (\n <Button variant=\"ghost\" size=\"sm\" aria-label={translate('cms.asset.imageOptions.title')} onClick={onEdit}>\n <SlidersHorizontal className=\"size-3.5\" />\n </Button>\n ) : null}\n {onRemove ? (\n <Button variant=\"ghost\" size=\"sm\" aria-label={translate('common.remove')} onClick={onRemove}>\n <Trash2 className=\"size-3.5\" />\n </Button>\n ) : null}\n </Row>\n <div className=\"px-3 pb-3\">\n <ObjectItemForm\n fields={fields}\n value={value}\n onChange={onChangeSubs}\n readOnly={readOnly}\n idPrefix={idPrefix}\n />\n </div>\n </Card>\n )\n}\n\n/** A placement's own form (EC-588 2i): the asset field's per-use sub-fields and their value. */\nexport interface PlacementForm {\n fields: readonly FieldDef[]\n value: Record<string, unknown>\n onChange: (value: Record<string, unknown>) => void\n}\n\n/**\n * The image options dialog (EC-301 → EC-588, ratified 2i): the two schemas an image\n * has, shown apart (`EC-565` § \"2i widened\").\n * - **In this place** — the PLACEMENT schema: the asset field's (or prop's) per-use\n * sub-fields (a caption, a badge layout), true of this one use only; written into the\n * field value. Present only when the field declares sub-fields.\n * - **About this image — applies everywhere it is used** — the ASSET schema: the focal\n * point and the `kind:'asset'` collection's fields over the asset's `meta` bag (alt,\n * copyright, credit, …), rendered through the generic field engine documents use;\n * persisted on the asset, so it changes every use — the Where-used panel (the asset's\n * library page) is one click away.\n * Asset metadata is buffered locally and committed once on close (one write); the\n * focal point commits immediately (it drives a live visual); the placement form writes\n * through to the field as it is edited. No-ops without a library.\n */\nfunction AssetOptionsDialog({\n assetId,\n readOnly,\n open,\n onOpenChange,\n placement,\n}: {\n assetId: string\n readOnly: boolean\n open: boolean\n onOpenChange: (open: boolean) => void\n placement?: PlacementForm\n}) {\n const source = useCollectionView()\n const assets = useOptionalAssets()\n const record = useAssetRecord(assetId)\n const metaFields = useMemo(() => {\n const assetCollectionId = source.assetCollectionId ?? 'asset'\n const collection = source.collections.find((c) => c.id === assetCollectionId)\n return collection ? assetMetaFieldsOf(collection) : []\n }, [source])\n\n // Local edit buffers, seeded once per open from the record (so an external edit\n // still wins between opens). EC-632: the draft is the document shape (shared bag +\n // per-locale buckets), shown in the studio's locale — the one the document around it\n // is open in — so a localized field (alt) edits that locale's translation.\n const at = useAssetReadLocale()\n const [draft, setDraft] = useState<AssetMetaDraft>(EMPTY_DRAFT)\n // EC-634: the draft as seeded at open — the base the commit is diffed against, so only\n // the keys (and locales) edited here are written and another session's change survives.\n const opened = useRef<AssetMetaDraft>(EMPTY_DRAFT)\n const [focal, setFocal] = useState<{ x: number; y: number } | undefined>(undefined)\n const dirty = useRef(false)\n const seeded = useRef(false)\n useEffect(() => {\n if (!open) {\n seeded.current = false\n return\n }\n if (seeded.current || !record) return\n // Seed from the stored bags with a legacy `alt` column lifted in (EC-587,\n // `assetMetaDraft`): a not-yet-migrated asset shows its alt; the write rule moves it to\n // `meta.alt` and clears the column when the commit's patch is applied.\n const seed = assetMetaDraft(record)\n opened.current = seed\n setDraft(seed)\n setFocal(record.focalPoint)\n dirty.current = false\n seeded.current = true\n }, [open, record])\n\n function handleOpenChange(next: boolean) {\n // Commit the buffered metadata once, on close (one write, not per keystroke).\n if (!next && !readOnly && assets && dirty.current) {\n void assets.updateMetadata(assetId, assetMetaDraftPatch(opened.current, draft))\n dirty.current = false\n }\n onOpenChange(next)\n }\n\n function setField(name: string, value: unknown) {\n const field = metaFields.find((f) => f.name === name)\n if (!field) return\n dirty.current = true\n setDraft((d) => setAssetMetaField(d, field, at, value))\n }\n\n // The focal point drives a live crop preview → commit immediately (optimistic\n // marker), not deferred to close.\n function commitFocal(point: { x: number; y: number } | null) {\n if (readOnly || !assets) return\n setFocal(point ?? undefined)\n void assets.updateMetadata(assetId, { focalPoint: point })\n }\n\n // EC-568: Replace file, from the dialog. Pending metadata edits are committed FIRST, so\n // the buffer cannot overwrite what the new file brings; the focal point is kept and the\n // dialog says to check it (the ticket's recommendation for open question 1).\n const [replaced, setReplaced] = useState(false)\n const replaceAction = record ? (\n <ReplaceFileButton\n record={record}\n disabled={readOnly}\n beforeReplace={async () => {\n if (assets && dirty.current) {\n dirty.current = false\n await assets.updateMetadata(assetId, assetMetaDraftPatch(opened.current, draft))\n }\n }}\n onReplaced={(asset) => {\n const seed = assetMetaDraft(asset)\n opened.current = seed\n setDraft(seed)\n setFocal(asset.focalPoint)\n dirty.current = false\n setReplaced(true)\n }}\n />\n ) : null\n\n const whereUsed =\n source.projectId !== undefined ? (\n <Link\n to={STUDIO_PROJECT_ROUTE}\n params={{ projectId: source.projectId, _splat: studioPath.asset(assetId) }}\n className=\"inline-flex items-center gap-1 text-xs text-primary hover:underline\"\n >\n <Link2 className=\"size-3\" /> {translate('cms.asset.imageOptions.whereUsed')}\n </Link>\n ) : null\n\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogContent className=\"max-w-lg\">\n <DialogHeader>\n <DialogTitle>{translate('cms.asset.imageOptions.title')}</DialogTitle>\n <DialogDescription>{translate('cms.asset.imageOptions.description')}</DialogDescription>\n </DialogHeader>\n <AssetOptionsSections\n record={record}\n readOnly={readOnly}\n metaFields={metaFields}\n meta={assetMetaFormValues(draft, metaFields, at)}\n metaLocale={at}\n onMetaField={setField}\n focal={focal}\n onFocalCommit={commitFocal}\n onFocalPreview={setFocal}\n whereUsed={whereUsed}\n replaceAction={replaceAction}\n replaced={replaced}\n {...(placement ? { placement } : {})}\n />\n </DialogContent>\n </Dialog>\n )\n}\n\n/**\n * The two sections of the image options dialog (EC-588 2i), stateless — exported so a\n * node smoke render can pin the split (the dialog itself portals, `null` in node).\n */\nexport function AssetOptionsSections({\n record,\n readOnly,\n metaFields,\n meta,\n metaLocale = null,\n onMetaField,\n focal,\n onFocalCommit,\n onFocalPreview,\n placement,\n whereUsed,\n replaceAction,\n replaced,\n}: {\n record: AssetRecord | undefined\n readOnly: boolean\n metaFields: readonly FieldDef[]\n /** The asset metadata form's values, in {@link metaLocale} (EC-632). */\n meta: Record<string, unknown>\n /** The locale a `localized: true` field is edited in (EC-632) — shown on its label. */\n metaLocale?: AssetReadLocale | null\n onMetaField: (name: string, value: unknown) => void\n focal: { x: number; y: number } | undefined\n onFocalCommit: (point: { x: number; y: number } | null) => void\n onFocalPreview: (point: { x: number; y: number } | undefined) => void\n placement?: PlacementForm\n whereUsed?: ReactNode\n /** EC-568: the \"Replace file\" action of the asset section. */\n replaceAction?: ReactNode\n /** EC-568: the file was just replaced — the kept focal point needs a look. */\n replaced?: boolean\n}) {\n return (\n <Stack gap=\"4\">\n {placement && placement.fields.length > 0 ? (\n <Stack gap=\"2\" data-ec-asset-options=\"placement\">\n <Stack gap=\"1\">\n <Heading level={3} size=\"h4\">\n {translate('cms.asset.imageOptions.placementTitle')}\n </Heading>\n <Text size=\"xs\" tone=\"subtle\">\n {translate('cms.asset.imageOptions.placementHint')}\n </Text>\n </Stack>\n <ObjectItemForm\n fields={placement.fields}\n value={placement.value}\n readOnly={readOnly}\n idPrefix=\"asset-options-placement\"\n onChange={placement.onChange}\n />\n <Separator />\n </Stack>\n ) : null}\n <Stack gap=\"3\" data-ec-asset-options=\"asset\">\n <Stack gap=\"1\">\n <Row align=\"center\">\n <Heading level={3} size=\"h4\">\n {translate('cms.asset.imageOptions.assetTitle')}\n </Heading>\n <Spacer />\n {whereUsed}\n </Row>\n <Text size=\"xs\" tone=\"subtle\">\n {translate('cms.asset.imageOptions.assetHint')}\n </Text>\n {replaceAction ? <Row gap=\"2\" align=\"center\" wrap>{replaceAction}</Row> : null}\n </Stack>\n <Stack gap=\"2\">\n <Row align=\"center\">\n <Text size=\"sm\" className=\"font-medium\">\n {translate('cms.asset.focalPoint')}\n </Text>\n <Spacer />\n {focal && !readOnly ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onFocalCommit(null)}>\n <RotateCcw /> {translate('cms.asset.resetToCentre')}\n </Button>\n ) : null}\n </Row>\n <FocalPointPicker\n record={record}\n point={focal}\n onChange={onFocalCommit}\n onPreview={onFocalPreview}\n disabled={readOnly}\n />\n {replaced ? (\n <Text size=\"xs\" className=\"font-medium\" data-ec-asset-options=\"replaced\">\n {translate('cms.asset.replacedCheckFocal')}\n </Text>\n ) : null}\n <Text size=\"xs\" tone=\"subtle\">\n {translate('cms.asset.focalPointHint')}\n </Text>\n <FocalCropPreviews record={record} point={focal} />\n </Stack>\n {metaFields.map((f) => (\n <Field\n key={f.name}\n label={<AssetMetaFieldLabel field={f} at={metaLocale} />}\n hint={localizedLabel(f.form?.description) || undefined}\n >\n <FieldControl\n id={`asset-meta-${f.name}`}\n field={f}\n value={meta[f.name]}\n readOnly={readOnly}\n onChange={(v) => onMetaField(f.name, v)}\n />\n </Field>\n ))}\n {metaFields.length === 0 ? (\n <Text size=\"sm\" tone=\"subtle\">\n No editable metadata fields are declared on the asset collection. Add fields (e.g.\n <Code tone=\"muted\"> alt</Code>, <Code tone=\"muted\">copyright</Code>) to it in code.\n </Text>\n ) : null}\n </Stack>\n </Stack>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"asset-field.js","sourceRoot":"","sources":["../../../src/components/cms/asset-field.tsx"],"names":[],"mappings":"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","sourcesContent":["import { GripVertical, ImagePlus, Link2, RotateCcw, SlidersHorizontal, Trash2, Upload, X } from 'lucide-react'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { AssetFieldDef, FieldDef } from '@elytracms/core/cms-core'\nimport { assetAlt } from '@elytracms/core/persistence'\nimport type { AssetReadLocale, AssetRecord } from '@elytracms/core/persistence'\nimport {\n assetNode,\n assetSubfieldsOf,\n moveAssetPlacement,\n readAssetId,\n removeAssetPlacementAt,\n selfTypeFieldValue,\n} from '@elytracms/core/cms-core'\nimport {\n Button,\n Card,\n Code,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n Field,\n Heading,\n Row,\n Separator,\n Spacer,\n Stack,\n Text,\n} from '@elytracms/studio/ui'\nimport { Link, STUDIO_PROJECT_ROUTE, studioPath } from '@elytracms/studio/router'\nimport { cn } from '../../lib/utils'\nimport { localizedLabel, translate } from '../../lib/i18n'\nimport {\n appendAssetSelections,\n applyAssetSelection,\n assetIdsOf,\n singleAssetIdOf,\n} from '../assets/asset-selection'\nimport { useOptionalAssets } from '../assets/assets-store'\nimport { AssetThumb, FocalCropPreviews, FocalPointPicker, useAssetRecord } from '../assets/asset-thumb'\nimport { assetPickerBinding, batchAttachment, splitByAccept, uploadBatchProgress } from './asset-picker-core'\nimport type { UploadBatch } from './asset-picker-core'\nimport {\n assetMetaDraft,\n assetMetaDraftPatch,\n assetMetaFieldsOf,\n assetMetaFormValues,\n setAssetMetaField,\n} from '../assets/asset-metadata'\nimport type { AssetMetaDraft } from '../assets/asset-metadata'\nimport { useAssetReadLocale } from '../assets/asset-locale'\nimport { AssetMetaFieldLabel } from '../assets/asset-meta-label'\nimport { ReplaceFileButton } from '../assets/replace-file'\nimport { useCollectionView } from '../collection-view/collection-view-context'\nimport { useFieldDensity } from './field-density'\nimport { AssetPicker, AssetRejectedNotice } from './asset-picker'\nimport { FieldControl } from './field-control'\nimport { ObjectItemForm } from './object-array-field'\nimport { FieldPathContext, useFieldPath } from './field-anchors'\n\n/** The draft before the dialog seeds (EC-632) — nothing open, nothing to diff. */\nconst EMPTY_DRAFT: AssetMetaDraft = { meta: {}, localizedMeta: {} }\n\n/**\n * The asset-field family (EC-152 + EC-248 + EC-301) — split from\n * `field-control.tsx` (EC-330): the {@link AssetField} control plus its\n * preview/gallery/options sub-components. Per-use sub-fields and the options\n * dialog's metadata form render through the shared object item form /\n * `FieldControl`, so asset metadata stays schema-driven.\n */\n\n/**\n * The asset field (EC-152 + EC-248). Beyond picking from the library it now shows\n * a focal-point-aware preview, uploads directly from the field (reusing the EC-152\n * upload path — no parallel uploader), and edits the selected image's alt + focal\n * point inline (persisted on the asset document, where delivery reads them, EC-230).\n * With no `<AssetsProvider>` (a fixture-only session — every project, the playground\n * included, mounts one, `studio-project-screen.tsx`) it degrades to the labelled-badge\n * picker — no preview/upload — so it stays usable without a real library.\n */\nexport function AssetField({\n field,\n value: stored,\n onChange,\n readOnly,\n}: {\n field: AssetFieldDef\n value: unknown\n onChange: (value: unknown) => void\n readOnly: boolean\n}) {\n // EC-586/EC-581 (ASSETS D4): the field reads its value through THE canonicaliser — the\n // one cardinality rule — so a lone placement left in a field since declared `multiple`\n // shows as a one-item gallery (and the next pick keeps it) instead of an empty one that\n // drops it; picks and removes then write from that canonical list.\n const value = useMemo(() => selfTypeFieldValue(field, stored), [field, stored])\n const source = useCollectionView()\n const assets = useOptionalAssets()\n const density = useFieldDensity()\n const compact = density === 'compact'\n // EC-582 / EC-572 #1: the anchor prefix of this field — a gallery placement's sub-field\n // inputs are stamped `<field>/<entry index>/<sub-field>`, the path the validator gives\n // their issues (a single placement's are `<field>/<sub-field>`, stamped by the form).\n const fieldPath = useFieldPath()\n const [open, setOpen] = useState(false)\n // The placement whose image options dialog is open (EC-588 2i: every placement of a\n // gallery has one, not only a single field's): its gallery index, or `null` for a\n // single field's one placement.\n const [editing, setEditing] = useState<{ index: number | null } | null>(null)\n const [dragging, setDragging] = useState(false)\n // Reorder by drag (EC-588 2i): the gallery index being dragged and the one under it.\n const [moveFrom, setMoveFrom] = useState<number | null>(null)\n const [moveOver, setMoveOver] = useState<number | null>(null)\n // Names of files a drop/pick rejected against the field's `accept` (EC-301) — shown\n // as a transient inline issue, cleared on the next valid upload. Never a silent drop.\n const [rejected, setRejected] = useState<string[]>([])\n // The active upload BATCH (EC-460): exactly the upload ids this field's drop\n // started (EC-588 A7), so the effect below attaches the WHOLE batch and nothing\n // another tab or a sibling field uploaded meanwhile.\n const pendingRef = useRef<UploadBatch | null>(null)\n const assetCollectionId = source.assetCollectionId ?? 'asset'\n const many = field.multiple\n const ids = many ? assetIdsOf(value) : []\n const single = !many ? singleAssetIdOf(value) : null\n // EC-301 per-use sub-fields: the value stores asset ENVELOPES (`{ type:'asset', id }`,\n // EC-586 — the canonical form, sub-fields or not) carrying any sub-field siblings\n // (`caption`). Picks/edits/removes preserve every other placement's sub-fields.\n const subFields = field.fields ?? []\n const hasSub = subFields.length > 0\n // The raw `many` entries (envelopes or bare ids), index-aligned with `ids`, so each\n // gallery item can read/write its own sub-fields.\n const entries = many && Array.isArray(value) ? (value as unknown[]) : []\n\n // Auto-select what an upload FROM this field added once it lands in the\n // library. EC-460: a `many` field attaches EVERY batch arrival as it lands\n // (the batch stays armed until it settles), so dropping N files attaches all\n // N — the old flow disarmed on the FIRST arrival and silently stranded the\n // rest in the library. A `one` field keeps the first-to-land selection.\n useEffect(() => {\n const batch = pendingRef.current\n if (!batch || !assets) return\n // EC-588 2i: the one batch-attach rule (the picker runs it too) — a `many` field\n // appends the whole batch once it settles, IN FILE ORDER; a single field takes the\n // first arrival.\n const { attach, disarm } = batchAttachment(uploadBatchProgress(batch, assets, field.accept), many)\n if (disarm) pendingRef.current = null\n if (attach.length === 0) return\n const next = many ? appendAssetSelections(value, attach) : applyAssetSelection(value, attach[0]!, false)\n if (next !== value) onChange(next)\n // Reacts to the assets store changing (an upload landing in the library, the\n // queue draining) — `value`/`onChange` are read from the closure on purpose.\n }, [assets, field.accept, many, onChange, value])\n\n function uploadFiles(files: File[]) {\n if (!assets || files.length === 0) return\n // EC-301 → EC-588: the drop rule the picker applies too — a drag-drop bypasses\n // the file dialog's `accept` filter, so re-check each file and name the rejects in\n // a visible notice instead of silently uploading the wrong kind.\n const { accepted, rejected: refused } = splitByAccept(files, field.accept)\n setRejected(refused)\n if (accepted.length === 0) return\n pendingRef.current = { uploadIds: assets.upload(accepted) }\n }\n\n // The picker is configured from the field — the SAME binding the table cell uses\n // (EC-570 #1 → EC-588): `accept`, `multiple`, and a pick through the carry rule\n // (EC-558) so a placement's per-use sub-fields (EC-301) survive a swap or an append.\n const pickerBinding = assetPickerBinding(field, value, (next) => {\n if (next !== value) onChange(next)\n })\n\n const canUpload = !readOnly && assets !== null\n\n // The open dialog's placement: which asset it shows, and — when the field declares\n // per-use sub-fields — the placement form it edits (\"In this place\").\n const editTarget = ((): { assetId: string; placement?: PlacementForm } | null => {\n if (!editing) return null\n if (editing.index === null) {\n if (!single) return null\n if (!hasSub) return { assetId: single }\n return {\n assetId: single,\n placement: {\n fields: subFields,\n value: assetSubfieldsOf(value),\n onChange: (next: Record<string, unknown>) => onChange(assetNode(single, next)),\n },\n }\n }\n if (!hasSub) {\n const aid = ids[editing.index]\n return aid ? { assetId: aid } : null\n }\n const entry = entries.filter((e) => readAssetId(e) !== undefined)[editing.index]\n const aid = readAssetId(entry)\n if (!aid) return null\n const raw = entries.indexOf(entry)\n return {\n assetId: aid,\n placement: {\n fields: subFields,\n value: assetSubfieldsOf(entry),\n onChange: (next: Record<string, unknown>) => {\n const nextEntries = entries.slice()\n nextEntries[raw] = assetNode(aid, next)\n onChange(nextEntries)\n },\n },\n }\n })()\n\n // Drag-to-upload onto the field (EC-301): a depth counter keeps the overlay\n // steady as the pointer crosses child element boundaries. `dragenter`/`dragleave`\n // fire per descendant, so toggling on a bare `dragleave` blinks constantly; we\n // only hide the overlay when the counter returns to zero (the pointer has truly\n // left the field). The overlay is pointer-events-none, so it never fires its own\n // enter/leave to confuse the count.\n const dragDepth = useRef(0)\n // Only a FILE drag is an upload: a gallery reorder drag (EC-588) is not.\n const isFileDrag = (e: React.DragEvent) => Array.from(e.dataTransfer.types).includes('Files')\n function onDragEnter(e: React.DragEvent) {\n if (!canUpload || !isFileDrag(e)) return\n e.preventDefault()\n dragDepth.current += 1\n if (!dragging) setDragging(true)\n }\n function onDragOver(e: React.DragEvent) {\n if (!canUpload || !isFileDrag(e)) return\n e.preventDefault() // required so a drop is allowed\n }\n function onDragLeave(e: React.DragEvent) {\n if (!canUpload || !isFileDrag(e)) return\n dragDepth.current -= 1\n if (dragDepth.current <= 0) {\n dragDepth.current = 0\n setDragging(false)\n }\n }\n function onDrop(e: React.DragEvent) {\n if (!canUpload || !isFileDrag(e)) return\n e.preventDefault()\n dragDepth.current = 0\n setDragging(false)\n uploadFiles(Array.from(e.dataTransfer.files))\n }\n // While the picker is open the field is behind the modal, so any drop is happening\n // INSIDE the dialog — detach the field's drag handlers entirely so a drop there can\n // only be handled by the picker, never double-counted by the field too (EC-301). This\n // is the belt to the picker's stopPropagation braces: the field cannot react at all.\n const dragProps = canUpload && !open ? { onDragEnter, onDragOver, onDragLeave, onDrop } : {}\n\n // Reorder by drag (EC-588 2i): one placement moves, every entry verbatim — core's\n // `moveAssetPlacement`, the same index counting as the remove.\n const reorderable = many && !readOnly && ids.length > 1\n function reorderProps(i: number) {\n if (!reorderable) return {}\n return {\n onDragOver: (e: React.DragEvent) => {\n if (moveFrom === null) return\n e.preventDefault()\n if (moveOver !== i) setMoveOver(i)\n },\n onDrop: (e: React.DragEvent) => {\n if (moveFrom === null) return\n e.preventDefault()\n const next = moveAssetPlacement(value, moveFrom, i)\n setMoveFrom(null)\n setMoveOver(null)\n if (next !== value) onChange(next)\n },\n }\n }\n function moveHandle(i: number): ReactNode {\n if (!reorderable) return null\n return (\n <span\n draggable\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(i))\n setMoveFrom(i)\n }}\n onDragEnd={() => {\n setMoveFrom(null)\n setMoveOver(null)\n }}\n aria-label={translate('cms.field.dragToReorder')}\n className=\"cursor-grab text-muted-foreground/60 hover:text-muted-foreground active:cursor-grabbing\"\n >\n <GripVertical className=\"size-3.5\" />\n </span>\n )\n }\n const moveTint = (i: number) =>\n cn(moveFrom === i && 'opacity-50', moveOver === i && moveFrom !== null && moveFrom !== i && 'ring-2 ring-primary/50')\n\n const selectButton = !readOnly ? (\n <Button variant=\"outline\" size=\"sm\" onClick={() => setOpen(true)}>\n <ImagePlus /> {translate('common.select')}\n </Button>\n ) : null\n\n return (\n <Stack\n gap=\"2\"\n className={cn(\n 'relative rounded-lg transition-shadow',\n dragging && 'ring-2 ring-primary ring-offset-2 ring-offset-background',\n )}\n {...dragProps}\n >\n {many && hasSub ? (\n // Gallery with per-use sub-fields (EC-301): a card per placement — thumbnail +\n // its own sub-field form — reusing the object/repeater item rendering.\n <Stack gap=\"2\">\n {entries.length > 0 ? (\n <Stack gap=\"2\">\n {entries.map((entry, i) => {\n const aid = readAssetId(entry)\n if (!aid) return null\n // The gallery position of this placement (readable entries only) — the\n // index the one remove rule counts (core `removeAssetPlacementAt`).\n const galleryIndex = entries.slice(0, i).filter((e) => readAssetId(e) !== undefined).length\n return (\n <div key={`${aid}-${i}`} className={cn('rounded-lg', moveTint(galleryIndex))} {...reorderProps(galleryIndex)}>\n <FieldPathContext.Provider value={fieldPath === null ? null : `${fieldPath}/${i}`}>\n <AssetGalleryItem\n assetId={aid}\n collectionId={assetCollectionId}\n fields={subFields}\n value={assetSubfieldsOf(entry)}\n readOnly={readOnly}\n idPrefix={`asset-${i}`}\n handle={moveHandle(galleryIndex)}\n onChangeSubs={(next) => {\n const nextEntries = entries.slice()\n nextEntries[i] = assetNode(aid, next)\n onChange(nextEntries)\n }}\n onEdit={assets ? () => setEditing({ index: galleryIndex }) : undefined}\n onRemove={readOnly ? undefined : () => onChange(removeAssetPlacementAt(value, galleryIndex))}\n />\n </FieldPathContext.Provider>\n </div>\n )\n })}\n </Stack>\n ) : (\n <EmptyAssetState\n compact={compact}\n canUpload={canUpload}\n readOnly={readOnly}\n onSelect={() => setOpen(true)}\n />\n )}\n <Row gap=\"2\" wrap align=\"center\">\n {selectButton}\n </Row>\n </Stack>\n ) : many ? (\n // Gallery: a grid of focal-aware previews + the single Select entry.\n <Stack gap=\"2\">\n {ids.length > 0 ? (\n <div\n className={cn(\n 'grid gap-2',\n compact ? 'grid-cols-2' : 'grid-cols-3 sm:grid-cols-4',\n )}\n >\n {ids.map((aid, i) => (\n <div key={`${aid}-${i}`} className={cn('rounded-lg', moveTint(i))} {...reorderProps(i)}>\n <AssetChip\n assetId={aid}\n collectionId={assetCollectionId}\n handle={moveHandle(i)}\n onEdit={assets ? () => setEditing({ index: i }) : undefined}\n onRemove={readOnly ? undefined : () => onChange(removeAssetPlacementAt(value, i))}\n />\n </div>\n ))}\n </div>\n ) : (\n <EmptyAssetState\n compact={compact}\n canUpload={canUpload}\n readOnly={readOnly}\n onSelect={() => setOpen(true)}\n />\n )}\n <Row gap=\"2\" wrap align=\"center\">\n {selectButton}\n </Row>\n </Stack>\n ) : single && hasSub ? (\n // With per-use sub-fields the asset + its fields read as ONE grouped unit\n // (like an object), so it's clear they belong together (EC-301 feedback).\n <Card className=\"border-l-2 border-l-border p-3\">\n <Stack gap=\"3\">\n <AssetSinglePreview\n assetId={single}\n compact={compact}\n readOnly={readOnly}\n hasLibrary={assets !== null}\n fallbackTitle={source.titleOf({ collection: assetCollectionId, id: single })}\n selectButton={selectButton}\n onEdit={() => setEditing({ index: null })}\n onRemove={() => onChange(applyAssetSelection(value, null, many))}\n />\n <div className=\"border-t border-border/60 pt-3\">\n <ObjectItemForm\n fields={subFields}\n value={assetSubfieldsOf(value)}\n readOnly={readOnly}\n idPrefix=\"asset-sub\"\n onChange={(next) => onChange(assetNode(single, next))}\n />\n </div>\n </Stack>\n </Card>\n ) : single ? (\n <AssetSinglePreview\n assetId={single}\n compact={compact}\n readOnly={readOnly}\n hasLibrary={assets !== null}\n fallbackTitle={source.titleOf({ collection: assetCollectionId, id: single })}\n selectButton={selectButton}\n onEdit={() => setEditing({ index: null })}\n onRemove={() => onChange(applyAssetSelection(value, null, many))}\n />\n ) : (\n <Stack gap=\"2\">\n <EmptyAssetState\n compact={compact}\n canUpload={canUpload}\n readOnly={readOnly}\n onSelect={() => setOpen(true)}\n />\n <Row gap=\"2\" wrap align=\"center\">\n {selectButton}\n </Row>\n </Stack>\n )}\n\n {/* Image options (EC-301 → EC-588 2i): the placement's own sub-fields (\"In this\n place\") apart from the asset's facts (\"About this image\", shared by every use),\n for a single field's placement and for each placement of a gallery. */}\n {editTarget && assets ? (\n <AssetOptionsDialog\n assetId={editTarget.assetId}\n readOnly={readOnly}\n open\n onOpenChange={(next) => {\n if (!next) setEditing(null)\n }}\n {...(editTarget.placement ? { placement: editTarget.placement } : {})}\n />\n ) : null}\n\n <AssetPicker open={open} onOpenChange={setOpen} {...pickerBinding} />\n\n <AssetRejectedNotice rejected={rejected} accept={field.accept} />\n\n {dragging ? (\n <div className=\"pointer-events-none absolute inset-0 z-10 grid place-items-center rounded-lg border-2 border-dashed border-primary bg-background/85\">\n <Row gap=\"2\" align=\"center\">\n <Upload className=\"size-4 text-primary\" />\n <Text size=\"sm\" className=\"font-medium\">\n {translate('cms.asset.dropToUpload')}\n </Text>\n </Row>\n </div>\n ) : null}\n </Stack>\n )\n}\n\n/**\n * Empty-state placeholder shown when an asset field has no selection (EC-301).\n *\n * EC-395: this was the one asset-field affordance that ignored `readOnly` — every\n * sibling control (`selectButton`, the per-item remove/change actions) already\n * degraded, but the empty-state tile stayed a clickable `<button>` that opened the\n * picker regardless. A locked, empty asset field must be as inert as a filled one:\n * read-only renders a plain (non-interactive, non-focusable) `div` with the same\n * frame — no `onClick`, no hover affordance — instead of a `<button>`.\n */\nfunction EmptyAssetState({\n compact,\n canUpload,\n readOnly,\n onSelect,\n}: {\n compact: boolean\n canUpload: boolean\n readOnly: boolean\n onSelect: () => void\n}) {\n const frame = cn(\n 'grid w-full place-items-center gap-1 rounded-lg border border-dashed border-border bg-muted/30 text-center text-muted-foreground',\n compact ? 'aspect-video' : 'aspect-[5/2]',\n )\n if (readOnly) {\n return <div className={frame}>{emptyAssetStateBody(canUpload)}</div>\n }\n return (\n <button type=\"button\" onClick={onSelect} className={cn(frame, 'transition-colors hover:bg-muted/60')}>\n {emptyAssetStateBody(canUpload)}\n </button>\n )\n}\n\nfunction emptyAssetStateBody(canUpload: boolean) {\n return (\n <>\n <ImagePlus className=\"size-6\" aria-hidden />\n <Text size=\"xs\" tone=\"muted\">\n {canUpload ? translate('cms.asset.selectOrDrop') : translate('cms.asset.selectAsset')}\n </Text>\n </>\n )\n}\n\n/** A large focal-aware preview of the selected asset (EC-301). */\nfunction AssetPreview({ assetId }: { assetId: string }) {\n const record = useAssetRecord(assetId)\n return <AssetThumb record={record} className=\"aspect-[4/3] w-full\" />\n}\n\n/** Filename + dimensions/type for the selected asset — the id is never shown (EC-301). */\nfunction AssetInfo({ assetId, fallbackTitle }: { assetId: string; fallbackTitle?: string }) {\n const record = useAssetRecord(assetId)\n const name = record?.title ?? record?.filename ?? fallbackTitle ?? assetId\n const dims = record?.width && record?.height ? `${record.width}×${record.height}` : null\n const kind = record?.contentType?.split('/')[1]?.toUpperCase()\n const meta = [dims, kind].filter(Boolean).join(' · ')\n return (\n <Stack gap=\"1\">\n <Text size=\"sm\" className=\"truncate font-medium\" title={name}>\n {name}\n </Text>\n {meta ? (\n <Text size=\"xs\" tone=\"subtle\">\n {meta}\n </Text>\n ) : null}\n </Stack>\n )\n}\n\n/**\n * The selected image's alt text shown in the field (EC-301) — what an editor most\n * wants at a glance; edited in the options dialog. Read through THE reader (EC-587),\n * so the field shows exactly what delivery serves.\n */\nfunction AssetAltLine({ assetId }: { assetId: string }) {\n const record = useAssetRecord(assetId)\n // EC-632: in the studio's locale — a localized alt shows the open locale's translation.\n const at = useAssetReadLocale()\n const alt = record ? assetAlt(record, at) : null\n return (\n <Row gap=\"1\" align=\"baseline\" className=\"min-w-0\">\n <Text size=\"xs\" tone=\"subtle\" className=\"shrink-0\">\n {translate('cms.asset.altLabel')}\n </Text>\n <Text\n size=\"xs\"\n tone={alt ? 'muted' : 'subtle'}\n className={cn('min-w-0 truncate', !alt && 'italic')}\n title={alt ?? undefined}\n >\n {alt || translate('cms.asset.notSet')}\n </Text>\n </Row>\n )\n}\n\n/**\n * A single asset reference: focal-aware thumbnail + title, with an optional drag\n * handle (reorder, EC-588), image options and remove.\n */\nfunction AssetChip({\n assetId,\n collectionId,\n handle,\n onEdit,\n onRemove,\n}: {\n assetId: string\n collectionId: string\n handle?: ReactNode\n onEdit?: () => void\n onRemove?: () => void\n}) {\n const source = useCollectionView()\n const record = useAssetRecord(assetId)\n const title = source.titleOf({ collection: collectionId, id: assetId })\n return (\n <div className=\"group relative overflow-hidden rounded-lg border border-border bg-muted/40\">\n <AssetThumb record={record} alt={title} className=\"aspect-square w-full rounded-none border-0\" />\n <Row gap=\"1\" align=\"center\" className=\"px-2 py-1\">\n {handle}\n <Text size=\"xs\" tone=\"subtle\" className=\"min-w-0 flex-1 truncate\" title={title}>\n {title}\n </Text>\n {onEdit ? (\n <button\n type=\"button\"\n aria-label={translate('cms.asset.imageOptions.title')}\n onClick={onEdit}\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <SlidersHorizontal className=\"size-3.5\" />\n </button>\n ) : null}\n {onRemove ? (\n <button\n type=\"button\"\n aria-label={translate('common.remove')}\n onClick={onRemove}\n className=\"text-muted-foreground hover:text-destructive\"\n >\n <X className=\"size-3.5\" />\n </button>\n ) : null}\n </Row>\n </div>\n )\n}\n\n/**\n * The selected single asset's preview row (EC-301): large focal-aware preview + info\n * column (filename/dimensions, Select/Edit/Remove, alt). Extracted so it renders either\n * bare (a plain asset field) or inside the grouping card when the field carries per-use\n * sub-fields — the asset + its fields then read as one unit.\n */\nfunction AssetSinglePreview({\n assetId,\n compact,\n readOnly,\n hasLibrary,\n fallbackTitle,\n selectButton,\n onEdit,\n onRemove,\n}: {\n assetId: string\n compact: boolean\n readOnly: boolean\n hasLibrary: boolean\n fallbackTitle?: string\n selectButton: React.ReactNode\n onEdit: () => void\n onRemove: () => void\n}) {\n return (\n <div className={compact ? 'flex flex-col gap-3' : 'flex gap-4'}>\n <div className={compact ? 'w-full' : 'w-1/2 shrink-0'}>\n <AssetPreview assetId={assetId} />\n </div>\n <Stack gap=\"2\" className={cn('min-w-0', !compact && 'flex-1')}>\n <AssetInfo assetId={assetId} fallbackTitle={fallbackTitle} />\n {!readOnly ? (\n <Row gap=\"2\" wrap align=\"center\">\n {selectButton}\n {hasLibrary ? (\n <Button variant=\"outline\" size=\"sm\" onClick={onEdit}>\n <SlidersHorizontal /> {translate('common.edit')}\n </Button>\n ) : null}\n <Button variant=\"ghost\" size=\"sm\" onClick={onRemove}>\n <Trash2 /> {translate('common.remove')}\n </Button>\n </Row>\n ) : null}\n <AssetAltLine assetId={assetId} />\n </Stack>\n </div>\n )\n}\n\n/**\n * One gallery placement when a `many` asset field declares per-use sub-fields (EC-301):\n * a thumbnail + filename + remove header over the placement's own sub-field form,\n * modelled on a repeater item card so a gallery's placements read as grouped units.\n */\nfunction AssetGalleryItem({\n assetId,\n collectionId,\n fields,\n value,\n onChangeSubs,\n handle,\n onEdit,\n onRemove,\n readOnly,\n idPrefix,\n}: {\n assetId: string\n collectionId: string\n fields: readonly FieldDef[]\n value: Record<string, unknown>\n onChangeSubs: (value: Record<string, unknown>) => void\n handle?: ReactNode\n onEdit?: () => void\n onRemove?: () => void\n readOnly: boolean\n idPrefix: string\n}) {\n const source = useCollectionView()\n const record = useAssetRecord(assetId)\n const title = source.titleOf({ collection: collectionId, id: assetId })\n return (\n <Card className=\"border-l-2 border-l-border p-0\">\n <Row gap=\"2\" align=\"center\" className=\"border-b border-border/60 bg-muted/30 px-2 py-1.5\">\n {handle}\n <AssetThumb record={record} alt={title} className=\"size-10 shrink-0\" />\n <Text size=\"sm\" className=\"min-w-0 flex-1 truncate font-medium\" title={title}>\n {title}\n </Text>\n {onEdit ? (\n <Button variant=\"ghost\" size=\"sm\" aria-label={translate('cms.asset.imageOptions.title')} onClick={onEdit}>\n <SlidersHorizontal className=\"size-3.5\" />\n </Button>\n ) : null}\n {onRemove ? (\n <Button variant=\"ghost\" size=\"sm\" aria-label={translate('common.remove')} onClick={onRemove}>\n <Trash2 className=\"size-3.5\" />\n </Button>\n ) : null}\n </Row>\n <div className=\"px-3 pb-3\">\n <ObjectItemForm\n fields={fields}\n value={value}\n onChange={onChangeSubs}\n readOnly={readOnly}\n idPrefix={idPrefix}\n />\n </div>\n </Card>\n )\n}\n\n/** A placement's own form (EC-588 2i): the asset field's per-use sub-fields and their value. */\nexport interface PlacementForm {\n fields: readonly FieldDef[]\n value: Record<string, unknown>\n onChange: (value: Record<string, unknown>) => void\n}\n\n/**\n * The image options dialog (EC-301 → EC-588, ratified 2i): the two schemas an image\n * has, shown apart (`EC-565` § \"2i widened\").\n * - **In this place** — the PLACEMENT schema: the asset field's (or prop's) per-use\n * sub-fields (a caption, a badge layout), true of this one use only; written into the\n * field value. Present only when the field declares sub-fields.\n * - **About this image — applies everywhere it is used** — the ASSET schema: the focal\n * point and the `kind:'asset'` collection's fields over the asset's `meta` bag (alt,\n * copyright, credit, …), rendered through the generic field engine documents use;\n * persisted on the asset, so it changes every use — the Where-used panel (the asset's\n * library page) is one click away.\n * Asset metadata is buffered locally and committed once on close (one write); the\n * focal point commits immediately (it drives a live visual); the placement form writes\n * through to the field as it is edited. No-ops without a library.\n */\nfunction AssetOptionsDialog({\n assetId,\n readOnly,\n open,\n onOpenChange,\n placement,\n}: {\n assetId: string\n readOnly: boolean\n open: boolean\n onOpenChange: (open: boolean) => void\n placement?: PlacementForm\n}) {\n const source = useCollectionView()\n const assets = useOptionalAssets()\n const record = useAssetRecord(assetId)\n const metaFields = useMemo(() => {\n const assetCollectionId = source.assetCollectionId ?? 'asset'\n const collection = source.collections.find((c) => c.id === assetCollectionId)\n return collection ? assetMetaFieldsOf(collection) : []\n }, [source])\n\n // Local edit buffers, seeded once per open from the record (so an external edit\n // still wins between opens). EC-632: the draft is the document shape (shared bag +\n // per-locale buckets), shown in the studio's locale — the one the document around it\n // is open in — so a localized field (alt) edits that locale's translation.\n const at = useAssetReadLocale()\n const [draft, setDraft] = useState<AssetMetaDraft>(EMPTY_DRAFT)\n // EC-634: the draft as seeded at open — the base the commit is diffed against, so only\n // the keys (and locales) edited here are written and another session's change survives.\n const opened = useRef<AssetMetaDraft>(EMPTY_DRAFT)\n const [focal, setFocal] = useState<{ x: number; y: number } | undefined>(undefined)\n const dirty = useRef(false)\n const seeded = useRef(false)\n useEffect(() => {\n if (!open) {\n seeded.current = false\n return\n }\n if (seeded.current || !record) return\n // Seed from the stored bags (`assetMetaDraft`; the alt is `meta.alt`, EC-587).\n const seed = assetMetaDraft(record)\n opened.current = seed\n setDraft(seed)\n setFocal(record.focalPoint)\n dirty.current = false\n seeded.current = true\n }, [open, record])\n\n function handleOpenChange(next: boolean) {\n // Commit the buffered metadata once, on close (one write, not per keystroke).\n if (!next && !readOnly && assets && dirty.current) {\n void assets.updateMetadata(assetId, assetMetaDraftPatch(opened.current, draft))\n dirty.current = false\n }\n onOpenChange(next)\n }\n\n function setField(name: string, value: unknown) {\n const field = metaFields.find((f) => f.name === name)\n if (!field) return\n dirty.current = true\n setDraft((d) => setAssetMetaField(d, field, at, value))\n }\n\n // The focal point drives a live crop preview → commit immediately (optimistic\n // marker), not deferred to close.\n function commitFocal(point: { x: number; y: number } | null) {\n if (readOnly || !assets) return\n setFocal(point ?? undefined)\n void assets.updateMetadata(assetId, { focalPoint: point })\n }\n\n // EC-568: Replace file, from the dialog. Pending metadata edits are committed FIRST, so\n // the buffer cannot overwrite what the new file brings; the focal point is kept and the\n // dialog says to check it (the ticket's recommendation for open question 1).\n const [replaced, setReplaced] = useState(false)\n const replaceAction = record ? (\n <ReplaceFileButton\n record={record}\n disabled={readOnly}\n beforeReplace={async () => {\n if (assets && dirty.current) {\n dirty.current = false\n await assets.updateMetadata(assetId, assetMetaDraftPatch(opened.current, draft))\n }\n }}\n onReplaced={(asset) => {\n const seed = assetMetaDraft(asset)\n opened.current = seed\n setDraft(seed)\n setFocal(asset.focalPoint)\n dirty.current = false\n setReplaced(true)\n }}\n />\n ) : null\n\n const whereUsed =\n source.projectId !== undefined ? (\n <Link\n to={STUDIO_PROJECT_ROUTE}\n params={{ projectId: source.projectId, _splat: studioPath.asset(assetId) }}\n className=\"inline-flex items-center gap-1 text-xs text-primary hover:underline\"\n >\n <Link2 className=\"size-3\" /> {translate('cms.asset.imageOptions.whereUsed')}\n </Link>\n ) : null\n\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogContent className=\"max-w-lg\">\n <DialogHeader>\n <DialogTitle>{translate('cms.asset.imageOptions.title')}</DialogTitle>\n <DialogDescription>{translate('cms.asset.imageOptions.description')}</DialogDescription>\n </DialogHeader>\n <AssetOptionsSections\n record={record}\n readOnly={readOnly}\n metaFields={metaFields}\n meta={assetMetaFormValues(draft, metaFields, at)}\n metaLocale={at}\n onMetaField={setField}\n focal={focal}\n onFocalCommit={commitFocal}\n onFocalPreview={setFocal}\n whereUsed={whereUsed}\n replaceAction={replaceAction}\n replaced={replaced}\n {...(placement ? { placement } : {})}\n />\n </DialogContent>\n </Dialog>\n )\n}\n\n/**\n * The two sections of the image options dialog (EC-588 2i), stateless — exported so a\n * node smoke render can pin the split (the dialog itself portals, `null` in node).\n */\nexport function AssetOptionsSections({\n record,\n readOnly,\n metaFields,\n meta,\n metaLocale = null,\n onMetaField,\n focal,\n onFocalCommit,\n onFocalPreview,\n placement,\n whereUsed,\n replaceAction,\n replaced,\n}: {\n record: AssetRecord | undefined\n readOnly: boolean\n metaFields: readonly FieldDef[]\n /** The asset metadata form's values, in {@link metaLocale} (EC-632). */\n meta: Record<string, unknown>\n /** The locale a `localized: true` field is edited in (EC-632) — shown on its label. */\n metaLocale?: AssetReadLocale | null\n onMetaField: (name: string, value: unknown) => void\n focal: { x: number; y: number } | undefined\n onFocalCommit: (point: { x: number; y: number } | null) => void\n onFocalPreview: (point: { x: number; y: number } | undefined) => void\n placement?: PlacementForm\n whereUsed?: ReactNode\n /** EC-568: the \"Replace file\" action of the asset section. */\n replaceAction?: ReactNode\n /** EC-568: the file was just replaced — the kept focal point needs a look. */\n replaced?: boolean\n}) {\n return (\n <Stack gap=\"4\">\n {placement && placement.fields.length > 0 ? (\n <Stack gap=\"2\" data-ec-asset-options=\"placement\">\n <Stack gap=\"1\">\n <Heading level={3} size=\"h4\">\n {translate('cms.asset.imageOptions.placementTitle')}\n </Heading>\n <Text size=\"xs\" tone=\"subtle\">\n {translate('cms.asset.imageOptions.placementHint')}\n </Text>\n </Stack>\n <ObjectItemForm\n fields={placement.fields}\n value={placement.value}\n readOnly={readOnly}\n idPrefix=\"asset-options-placement\"\n onChange={placement.onChange}\n />\n <Separator />\n </Stack>\n ) : null}\n <Stack gap=\"3\" data-ec-asset-options=\"asset\">\n <Stack gap=\"1\">\n <Row align=\"center\">\n <Heading level={3} size=\"h4\">\n {translate('cms.asset.imageOptions.assetTitle')}\n </Heading>\n <Spacer />\n {whereUsed}\n </Row>\n <Text size=\"xs\" tone=\"subtle\">\n {translate('cms.asset.imageOptions.assetHint')}\n </Text>\n {replaceAction ? <Row gap=\"2\" align=\"center\" wrap>{replaceAction}</Row> : null}\n </Stack>\n <Stack gap=\"2\">\n <Row align=\"center\">\n <Text size=\"sm\" className=\"font-medium\">\n {translate('cms.asset.focalPoint')}\n </Text>\n <Spacer />\n {focal && !readOnly ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onFocalCommit(null)}>\n <RotateCcw /> {translate('cms.asset.resetToCentre')}\n </Button>\n ) : null}\n </Row>\n <FocalPointPicker\n record={record}\n point={focal}\n onChange={onFocalCommit}\n onPreview={onFocalPreview}\n disabled={readOnly}\n />\n {replaced ? (\n <Text size=\"xs\" className=\"font-medium\" data-ec-asset-options=\"replaced\">\n {translate('cms.asset.replacedCheckFocal')}\n </Text>\n ) : null}\n <Text size=\"xs\" tone=\"subtle\">\n {translate('cms.asset.focalPointHint')}\n </Text>\n <FocalCropPreviews record={record} point={focal} />\n </Stack>\n {metaFields.map((f) => (\n <Field\n key={f.name}\n label={<AssetMetaFieldLabel field={f} at={metaLocale} />}\n hint={localizedLabel(f.form?.description) || undefined}\n >\n <FieldControl\n id={`asset-meta-${f.name}`}\n field={f}\n value={meta[f.name]}\n readOnly={readOnly}\n onChange={(v) => onMetaField(f.name, v)}\n />\n </Field>\n ))}\n {metaFields.length === 0 ? (\n <Text size=\"sm\" tone=\"subtle\">\n No editable metadata fields are declared on the asset collection. Add fields (e.g.\n <Code tone=\"muted\"> alt</Code>, <Code tone=\"muted\">copyright</Code>) to it in code.\n </Text>\n ) : null}\n </Stack>\n </Stack>\n )\n}\n"]}
|
|
@@ -23,7 +23,7 @@ export declare function FallbackChip({ fallback, testId, }: {
|
|
|
23
23
|
export declare function fallbackTitle(fallback: DisplayedFallback): string;
|
|
24
24
|
/**
|
|
25
25
|
* Normalize a relation value (single ref or array of refs) into an array of
|
|
26
|
-
* `DocumentRef`s. EC-277: unwraps self-typed `{ type:'reference', ... }`
|
|
27
|
-
*
|
|
26
|
+
* `DocumentRef`s. EC-277 / EC-589: unwraps the self-typed `{ type:'reference', ... }`
|
|
27
|
+
* envelopes; anything else is no reference.
|
|
28
28
|
*/
|
|
29
29
|
export declare function toRefArray(value: unknown): DocumentRef[];
|