@elytracms/studio 0.0.103 → 0.0.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/convex/ingest.test.ts +208 -13
  2. package/convex/ingest.ts +56 -35
  3. package/dist/components/app-views/module.d.ts +4 -0
  4. package/dist/components/app-views/module.js.map +1 -1
  5. package/dist/components/builder/canvas-theme-notice.js +4 -1
  6. package/dist/components/builder/canvas-theme-notice.js.map +1 -1
  7. package/dist/components/cms/document-diff-view.js +43 -7
  8. package/dist/components/cms/document-diff-view.js.map +1 -1
  9. package/dist/components/components/components-index.d.ts +0 -7
  10. package/dist/components/components/components-index.js +9 -2
  11. package/dist/components/components/components-index.js.map +1 -1
  12. package/dist/components/redirects/redirects-schema.d.ts +31 -0
  13. package/dist/components/redirects/redirects-schema.js +12 -6
  14. package/dist/components/redirects/redirects-schema.js.map +1 -1
  15. package/dist/lib/ai/translate-document.d.ts +7 -3
  16. package/dist/lib/ai/translate-document.js +63 -48
  17. package/dist/lib/ai/translate-document.js.map +1 -1
  18. package/dist/lib/ai/writer-form.d.ts +48 -5
  19. package/dist/lib/ai/writer-form.js +118 -64
  20. package/dist/lib/ai/writer-form.js.map +1 -1
  21. package/dist/lib/engine-version.d.ts +1 -1
  22. package/dist/lib/engine-version.js +1 -1
  23. package/dist/lib/engine-version.js.map +1 -1
  24. package/dist/lib/i18n/messages.de.js +25 -5
  25. package/dist/lib/i18n/messages.de.js.map +1 -1
  26. package/dist/lib/i18n/messages.en.d.ts +21 -1
  27. package/dist/lib/i18n/messages.en.js +29 -6
  28. package/dist/lib/i18n/messages.en.js.map +1 -1
  29. package/dist/lib/persona/labels.js +1 -0
  30. package/dist/lib/persona/labels.js.map +1 -1
  31. package/dist/lib/workspace/index.d.ts +9 -1
  32. package/dist/lib/workspace/index.js +13 -2
  33. package/dist/lib/workspace/index.js.map +1 -1
  34. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"canvas-theme-notice.js","sourceRoot":"","sources":["../../../src/components/builder/canvas-theme-notice.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAGhD;;;;;;;;;;;;;;GAcG;AAEH,MAAM,cAAc,GAAG,IAAI,GAAG,EAA6B,CAAA;AAE3D,sDAAsD;AACtD,MAAM,UAAU,8BAA8B;IAC5C,cAAc,CAAC,KAAK,EAAE,CAAA;AACxB,CAAC;AAED,MAAM,WAAW,GAAuD;IACtE,MAAM,EAAE,kCAAkC;IAC1C,kBAAkB,EAAE,2CAA2C;IAC/D,iBAAiB,EAAE,yCAAyC;IAC5D,eAAe,EAAE,wCAAwC;CAC1D,CAAA;AAED,MAAM,UAAU,iBAAiB,CAAC,EAAE,MAAM,EAAwC;IAChF,+EAA+E;IAC/E,MAAM,CAAC,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IACtC,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE;QAAE,OAAO,IAAI,CAAA;IAC3C,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC3C,IAAI,CAAC,UAAU,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAE/D,OAAO,CACL,6BACc,qBAAqB,sBACf,MAAM,CAAC,IAAI,EAC7B,SAAS,EAAC,4EAA4E,YAEtF,cAAK,SAAS,EAAC,kFAAkF,YAC/F,MAAC,GAAG,IAAC,GAAG,EAAC,GAAG,EAAC,KAAK,EAAC,OAAO,aACxB,KAAC,aAAa,IAAC,SAAS,EAAC,uCAAuC,wBAAe,EAC/E,KAAC,IAAI,IAAC,IAAI,EAAC,IAAI,EAAC,SAAS,EAAC,gBAAgB,YACvC,SAAS,CAAC,UAAU,CAAC,GACjB,EACP,iBACE,IAAI,EAAC,QAAQ,gBACD,SAAS,CAAC,gBAAgB,CAAC,EACvC,OAAO,EAAE,GAAG,EAAE;4BACZ,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;4BAC/B,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;wBAC5B,CAAC,EACD,SAAS,EAAC,mFAAmF,YAE7F,KAAC,CAAC,IAAC,SAAS,EAAC,UAAU,GAAG,GACnB,IACL,GACF,GACF,CACP,CAAA;AACH,CAAC","sourcesContent":["import { useState } from 'react'\nimport { AlertTriangle, X } from 'lucide-react'\nimport { translate } from '../../lib/i18n'\nimport { isDevRuntime } from '../../lib/persistence'\nimport { Row, Text } from '@elytracms/studio/ui'\nimport type { CanvasThemeStatus } from './canvas-chrome'\n\n/**\n * EC-414 AD-D item 2 — the canvas-theme runtime notice, in the established\n * validation-surface style (the `ClipboardNoticeOverlay` shape: a dismissible,\n * NEVER-blocking overlay above the canvas, in the STUDIO document — studio UI\n * primitives are fine here, this is not in-frame chrome). Dev builds only:\n *\n * - `legacy`: the probe found the merged pre-EC-414 canvas.css — a one-time\n * notice naming the migration (the canvas keeps working exactly as before).\n * - `stylesheet-error` / `no-theme-tokens` / `no-stylesheet`: the canvas\n * stylesheet is broken or missing — the invalid state is named explicitly\n * instead of silently rendering unstyled blocks.\n *\n * \"One-time\": dismissing a kind suppresses it for the rest of the studio\n * session (module state survives canvas remounts/navigation).\n */\n\nconst dismissedKinds = new Set<CanvasThemeStatus['kind']>()\n\n/** Test hook: reset the session-sticky dismissals. */\nexport function resetCanvasThemeNoticeForTests(): void {\n dismissedKinds.clear()\n}\n\nconst NOTICE_KEYS: Partial<Record<CanvasThemeStatus['kind'], string>> = {\n legacy: 'builder.canvasTheme.legacyNotice',\n 'stylesheet-error': 'builder.canvasTheme.stylesheetErrorNotice',\n 'no-theme-tokens': 'builder.canvasTheme.noThemeTokensNotice',\n 'no-stylesheet': 'builder.canvasTheme.noStylesheetNotice',\n}\n\nexport function CanvasThemeNotice({ status }: { status: CanvasThemeStatus | null }) {\n // Local state only forces the re-render on dismiss; the truth is module-level.\n const [, setDismissedAt] = useState(0)\n if (!status || !isDevRuntime()) return null\n const messageKey = NOTICE_KEYS[status.kind]\n if (!messageKey || dismissedKinds.has(status.kind)) return null\n\n return (\n <div\n data-testid=\"canvas-theme-notice\"\n data-notice-kind={status.kind}\n className=\"absolute top-4 left-1/2 z-20 w-max max-w-[min(460px,90%)] -translate-x-1/2\"\n >\n <div className=\"rounded-lg border border-border bg-popover p-2 text-popover-foreground shadow-lg\">\n <Row gap=\"2\" align=\"start\">\n <AlertTriangle className=\"mt-0.5 size-3.5 shrink-0 text-warning\" aria-hidden />\n <Text size=\"xs\" className=\"min-w-0 flex-1\">\n {translate(messageKey)}\n </Text>\n <button\n type=\"button\"\n aria-label={translate('common.dismiss')}\n onClick={() => {\n dismissedKinds.add(status.kind)\n setDismissedAt(Date.now())\n }}\n className=\"shrink-0 rounded p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground\"\n >\n <X className=\"size-3.5\" />\n </button>\n </Row>\n </div>\n </div>\n )\n}\n"]}
1
+ {"version":3,"file":"canvas-theme-notice.js","sourceRoot":"","sources":["../../../src/components/builder/canvas-theme-notice.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAGhD;;;;;;;;;;;;;;GAcG;AAEH,MAAM,cAAc,GAAG,IAAI,GAAG,EAA6B,CAAA;AAE3D,sDAAsD;AACtD,MAAM,UAAU,8BAA8B;IAC5C,cAAc,CAAC,KAAK,EAAE,CAAA;AACxB,CAAC;AAED,MAAM,WAAW,GAAuD;IACtE,MAAM,EAAE,kCAAkC;IAC1C,kBAAkB,EAAE,2CAA2C;IAC/D,iBAAiB,EAAE,yCAAyC;IAC5D,eAAe,EAAE,wCAAwC;CAC1D,CAAA;AAED,mGAAmG;AACnG,MAAM,eAAe,GAAG,eAAe,CAAC,eAAe,CAAC,CAAA;AAExD,MAAM,UAAU,iBAAiB,CAAC,EAAE,MAAM,EAAwC;IAChF,+EAA+E;IAC/E,MAAM,CAAC,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IACtC,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE;QAAE,OAAO,IAAI,CAAA;IAC3C,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC3C,IAAI,CAAC,UAAU,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAE/D,OAAO,CACL,6BACc,qBAAqB,sBACf,MAAM,CAAC,IAAI,EAC7B,SAAS,EAAC,4EAA4E,YAEtF,cAAK,SAAS,EAAC,kFAAkF,YAC/F,MAAC,GAAG,IAAC,GAAG,EAAC,GAAG,EAAC,KAAK,EAAC,OAAO,aACxB,KAAC,aAAa,IAAC,SAAS,EAAC,uCAAuC,wBAAe,EAC/E,KAAC,IAAI,IAAC,IAAI,EAAC,IAAI,EAAC,SAAS,EAAC,gBAAgB,YACvC,SAAS,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,GAC7C,EACP,iBACE,IAAI,EAAC,QAAQ,gBACD,SAAS,CAAC,gBAAgB,CAAC,EACvC,OAAO,EAAE,GAAG,EAAE;4BACZ,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;4BAC/B,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;wBAC5B,CAAC,EACD,SAAS,EAAC,mFAAmF,YAE7F,KAAC,CAAC,IAAC,SAAS,EAAC,UAAU,GAAG,GACnB,IACL,GACF,GACF,CACP,CAAA;AACH,CAAC","sourcesContent":["import { useState } from 'react'\nimport { AlertTriangle, X } from 'lucide-react'\nimport { elytraGuidePath } from '@elytracms/core/studio-core'\nimport { translate } from '../../lib/i18n'\nimport { isDevRuntime } from '../../lib/persistence'\nimport { Row, Text } from '@elytracms/studio/ui'\nimport type { CanvasThemeStatus } from './canvas-chrome'\n\n/**\n * EC-414 AD-D item 2 — the canvas-theme runtime notice, in the established\n * validation-surface style (the `ClipboardNoticeOverlay` shape: a dismissible,\n * NEVER-blocking overlay above the canvas, in the STUDIO document — studio UI\n * primitives are fine here, this is not in-frame chrome). Dev builds only:\n *\n * - `legacy`: the probe found the merged pre-EC-414 canvas.css — a one-time\n * notice naming the migration (the canvas keeps working exactly as before).\n * - `stylesheet-error` / `no-theme-tokens` / `no-stylesheet`: the canvas\n * stylesheet is broken or missing — the invalid state is named explicitly\n * instead of silently rendering unstyled blocks.\n *\n * \"One-time\": dismissing a kind suppresses it for the rest of the studio\n * session (module state survives canvas remounts/navigation).\n */\n\nconst dismissedKinds = new Set<CanvasThemeStatus['kind']>()\n\n/** Test hook: reset the session-sticky dismissals. */\nexport function resetCanvasThemeNoticeForTests(): void {\n dismissedKinds.clear()\n}\n\nconst NOTICE_KEYS: Partial<Record<CanvasThemeStatus['kind'], string>> = {\n legacy: 'builder.canvasTheme.legacyNotice',\n 'stylesheet-error': 'builder.canvasTheme.stylesheetErrorNotice',\n 'no-theme-tokens': 'builder.canvasTheme.noThemeTokensNotice',\n 'no-stylesheet': 'builder.canvasTheme.noStylesheetNotice',\n}\n\n/** EC-765: the notices point at the guide's theming chapter where the project has it installed. */\nconst THEMING_CHAPTER = elytraGuidePath('13-theming.md')\n\nexport function CanvasThemeNotice({ status }: { status: CanvasThemeStatus | null }) {\n // Local state only forces the re-render on dismiss; the truth is module-level.\n const [, setDismissedAt] = useState(0)\n if (!status || !isDevRuntime()) return null\n const messageKey = NOTICE_KEYS[status.kind]\n if (!messageKey || dismissedKinds.has(status.kind)) return null\n\n return (\n <div\n data-testid=\"canvas-theme-notice\"\n data-notice-kind={status.kind}\n className=\"absolute top-4 left-1/2 z-20 w-max max-w-[min(460px,90%)] -translate-x-1/2\"\n >\n <div className=\"rounded-lg border border-border bg-popover p-2 text-popover-foreground shadow-lg\">\n <Row gap=\"2\" align=\"start\">\n <AlertTriangle className=\"mt-0.5 size-3.5 shrink-0 text-warning\" aria-hidden />\n <Text size=\"xs\" className=\"min-w-0 flex-1\">\n {translate(messageKey, { guide: THEMING_CHAPTER })}\n </Text>\n <button\n type=\"button\"\n aria-label={translate('common.dismiss')}\n onClick={() => {\n dismissedKinds.add(status.kind)\n setDismissedAt(Date.now())\n }}\n className=\"shrink-0 rounded p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground\"\n >\n <X className=\"size-3.5\" />\n </button>\n </Row>\n </div>\n </div>\n )\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { createContext, useCallback, useContext, useMemo, useState } from 'react';
3
3
  import { Image as ImageIcon, RotateCcw } from 'lucide-react';
4
- import { ASSET_RECORD_KEYS, assetSubfieldsOf, isAssetNode, readAssetId, readDocumentRef } from '@elytracms/core/cms-core';
4
+ import { ASSET_RECORD_KEYS, assetSubfieldsOf, isAssetNode, readAssetId, readDocumentRef, semanticValueEqual, } from '@elytracms/core/cms-core';
5
5
  import { Badge, Button, Code, Row, Spacer, Stack, Text } from '@elytracms/studio/ui';
6
6
  import { translate } from '../../lib/i18n/index.js';
7
7
  import { localeChipLabel } from '../../lib/locale/index.js';
@@ -141,7 +141,7 @@ function FieldGroup({ group, field, zebraStart, baseVersion, canRestore, busy, o
141
141
  })
142
142
  : translate('cms.version.restoreField', { field: label, version: baseVersion }), onClick: () => onRestore(fieldScope(entry)) })) : null;
143
143
  const descriptor = (_jsx(FieldDescriptor, { label: label, locale: entry.locale, kind: entry.kind, inline: layout === 'stacked' }));
144
- const body = (_jsx(EntryBody, { change: entry, rowId: rowId, baseVersion: baseVersion, canRestore: canRestore, busy: busy, onRestore: onRestore }));
144
+ const body = (_jsx(EntryBody, { change: entry, field: field, rowId: rowId, baseVersion: baseVersion, canRestore: canRestore, busy: busy, onRestore: onRestore }));
145
145
  return layout === 'stacked' ? (_jsx(StackedFieldRow, { descriptor: descriptor, restore: fieldRestore, children: body }, entry.locale ?? '__base__')) : (_jsx(FieldRow, { zebra: (zebraStart + i) % 2 === 1, descriptor: descriptor, restore: fieldRestore, children: body }, entry.locale ?? '__base__'));
146
146
  });
147
147
  if (layout === 'stacked')
@@ -168,7 +168,7 @@ function FieldDescriptor({ label, locale, kind, inline = false, }) {
168
168
  }
169
169
  return (_jsxs(Stack, { gap: "1", children: [_jsx(Text, { size: "sm", weight: "medium", className: "min-w-0 truncate", children: label }), _jsxs(Row, { gap: "1", wrap: true, children: [localeBadge, _jsx(KindTag, { kind: kind })] })] }));
170
170
  }
171
- function EntryBody({ change, rowId, baseVersion, canRestore, busy, onRestore, }) {
171
+ function EntryBody({ change, field, rowId, baseVersion, canRestore, busy, onRestore, }) {
172
172
  const localeScope = change.locale !== undefined ? { locale: change.locale } : {};
173
173
  if (change.blocks) {
174
174
  return (_jsx(Stack, { gap: "2", className: "mt-1", children: change.blocks.map((block) => (_jsx(BlockSection, { block: block, rowId: `${rowId}|block:${block.blockId}`, baseVersion: baseVersion, canRestore: canRestore, busy: busy, onRestore: () => onRestore({ kind: 'block', field: change.field, blockId: block.blockId, ...localeScope }) }, block.blockId))) }));
@@ -189,7 +189,7 @@ function EntryBody({ change, rowId, baseVersion, canRestore, busy, onRestore, })
189
189
  if (change.kind === 'changed' && typeof change.before === 'string' && typeof change.after === 'string') {
190
190
  return _jsx(WordDiffCols, { id: rowId, before: change.before, after: change.after });
191
191
  }
192
- return (_jsx(DiffColumns, { kind: change.kind, before: _jsx(SideValue, { value: change.before, other: change.after, typeHint: change.type, id: `${rowId}|before` }), after: _jsx(SideValue, { value: change.after, other: change.before, typeHint: change.type, id: `${rowId}|after` }) }));
192
+ return (_jsx(DiffColumns, { kind: change.kind, before: _jsx(SideValue, { value: change.before, other: change.after, typeHint: change.type, field: field, id: `${rowId}|before` }), after: _jsx(SideValue, { value: change.after, other: change.before, typeHint: change.type, field: field, id: `${rowId}|after` }) }));
193
193
  }
194
194
  function BlockSection({ block, rowId, baseVersion, canRestore, busy, onRestore, }) {
195
195
  const name = block.componentId.split('.').pop() ?? block.componentId;
@@ -224,15 +224,20 @@ function RichTextSide({ value, id }) {
224
224
  return (_jsx(ExpandToggle, { id: id, isLong: isLong, expanded: expanded, children: _jsx("div", { className: cn(!expanded && isLong && 'max-h-60 overflow-hidden'), children: _jsx(RichTextPreview, { value: value }) }) }));
225
225
  }
226
226
  /** One side of a non-text change — the value, or an "empty" placeholder. */
227
- function SideValue({ value, other, typeHint, id, }) {
227
+ function SideValue({ value, other, typeHint, field, id, }) {
228
228
  if (value === undefined || value === null || value === '') {
229
229
  return (_jsx(Text, { size: "sm", tone: "subtle", className: "italic", children: translate('cms.version.emptyValue') }));
230
230
  }
231
- return _jsx(ValueView, { value: value, other: other, typeHint: typeHint, id: id });
231
+ return _jsx(ValueView, { value: value, other: other, typeHint: typeHint, field: field, id: id });
232
232
  }
233
233
  /** Read-only value display, dispatching on field type / self-describing value shape. */
234
- function ValueView({ value, other, typeHint, id, }) {
234
+ function ValueView({ value, other, typeHint, field, id, }) {
235
235
  const { isExpanded } = useDiffDisplay();
236
+ if (field?.type === 'object' && !field.multiple && isPlainRecord(value)) {
237
+ const changed = changedObjectSubfields(field, value, other);
238
+ if (changed !== null)
239
+ return _jsx(ObjectValue, { value: value, other: other, changed: changed, id: id });
240
+ }
236
241
  if (typeHint === 'asset' || isAssetNode(value))
237
242
  return _jsx(AssetValue, { value: value });
238
243
  if (typeHint === 'relation' || readDocumentRef(value))
@@ -253,6 +258,37 @@ function ValueView({ value, other, typeHint, id, }) {
253
258
  const { shown, isLong } = truncateText(String(value), expanded);
254
259
  return (_jsx(ExpandToggle, { id: id, isLong: isLong, expanded: expanded, children: _jsx(Text, { size: "sm", className: "whitespace-pre-wrap break-words", children: shown }) }));
255
260
  }
261
+ function isPlainRecord(value) {
262
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
263
+ }
264
+ /**
265
+ * The sub-fields of ONE object value to draw beside the other side (EC-770 item 7): those whose
266
+ * values differ by the diff's own equality ({@link semanticValueEqual}), against an empty object
267
+ * when the other side holds none — so an added or removed object lists every sub-field it holds.
268
+ * Declared sub-fields come in schema order with their declaration; a stored key the schema does
269
+ * not declare (drift) is listed under its own name, never hidden. `null` when nothing differs.
270
+ */
271
+ function changedObjectSubfields(field, value, other) {
272
+ const against = isPlainRecord(other) ? other : {};
273
+ const declared = new Set(field.fields.map((sub) => sub.name));
274
+ const names = [
275
+ ...field.fields.map((sub) => ({ name: sub.name, sub })),
276
+ ...[...new Set([...Object.keys(value), ...Object.keys(against)])]
277
+ .filter((name) => !declared.has(name))
278
+ .map((name) => ({ name, sub: undefined })),
279
+ ];
280
+ const changed = names.filter(({ name }) => !semanticValueEqual(value[name], against[name]));
281
+ return changed.length > 0 ? changed : null;
282
+ }
283
+ /**
284
+ * One object field's value (one object, `multiple: false` — the SEO object): its differing
285
+ * sub-fields, each labelled by its schema label and drawn through {@link SideValue} — never
286
+ * "object" against "object", so a reader sees what a restore brings back (EC-770 item 7).
287
+ */
288
+ function ObjectValue({ value, other, changed, id, }) {
289
+ const otherRecord = isPlainRecord(other) ? other : undefined;
290
+ return (_jsx(Stack, { gap: "2", children: changed.map(({ name, sub }) => (_jsxs("div", { className: "min-w-0", children: [_jsx(Text, { size: "xs", tone: "subtle", className: "mb-0.5 block uppercase tracking-wide", children: sub ? fieldLabel(sub) : name }), _jsx(SideValue, { value: value[name], other: otherRecord?.[name], typeHint: sub?.type, field: sub, id: `${id}|${name}` })] }, name))) }));
291
+ }
256
292
  function RelationValue({ value, other }) {
257
293
  const source = useCollectionView();
258
294
  const refs = toRefArray(value);
@@ -1 +1 @@
1
- {"version":3,"file":"document-diff-view.js","sourceRoot":"","sources":["../../../src/components/cms/document-diff-view.tsx"],"names":[],"mappings":"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","sourcesContent":["import { createContext, useCallback, useContext, useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { Image as ImageIcon, RotateCcw } from 'lucide-react'\nimport type {\n BlockAncestor,\n BlockChange,\n ChangeKind,\n DocumentDiff,\n FieldChange,\n PropChange,\n} from '@elytracms/core/content'\nimport { ASSET_RECORD_KEYS, assetSubfieldsOf, isAssetNode, readAssetId, readDocumentRef } from '@elytracms/core/cms-core'\nimport type { CollectionDef, FieldDef, RestoreScope } from '@elytracms/core/cms-core'\nimport { Badge, Button, Code, Row, Spacer, Stack, Text } from '@elytracms/studio/ui'\nimport { translate } from '../../lib/i18n'\nimport { localeChipLabel } from '../../lib/locale'\nimport { cn } from '../../lib/utils'\nimport { readDiffViewMode, storeDiffViewMode } from '../../lib/diff-view-preference'\nimport type { DiffViewMode } from '../../lib/diff-view-preference'\nimport { isDisplayableAssetUrl } from '../../lib/assets'\nimport { useCollectionView } from '../collection-view/collection-view-context'\nimport { fieldLabel } from './cms-labels'\nimport { toRefArray } from './cell'\nimport { RichTextPreview, isRichTextValueEmpty } from './rich-text-preview'\nimport {\n DIFF_TRUNCATE_THRESHOLD,\n mergeWordDiff,\n richTextToText,\n truncateText,\n truncateTokensAroundChange,\n wordDiff,\n} from './version-compare-text'\nimport type { AnchoredExcerpt, MergedDiffToken, WordToken } from './version-compare-text'\n\n/**\n * The shared document-diff RENDERER (EC-317 change-list), extracted from\n * `VersionCompare` so a single renderer serves both the version-compare surface and\n * the EC-199 AI proposal review — never two diff renderers. It draws a `DocumentDiff`\n * ({@link diffDocuments}) as the calm change-list grouped BY FIELD: a descriptor lane,\n * before | after (or a unified lane), text as a prose diff, assets as thumbnails,\n * relations as titles, long values collapsed behind \"Show more\", zebra rows.\n *\n * It is display-only over an already-computed diff: the version chrome (version\n * pickers / steppers / restore-whole) stays in `VersionCompare`; the AI proposal card\n * feeds `diffDocuments(collection, emptyBefore, proposedAfter)` and omits `restore`.\n * The per-row restore affordance renders only when `restore.canRestore` is set, so the\n * AI review (a not-yet-saved proposal) shows a clean, restore-free diff.\n *\n * **Layout (EC-382).** One diff LOGIC, two presentations selected by `layout`:\n * `'grid'` (default) is the wide version-compare surface — a fixed descriptor lane\n * plus a unified/side-by-side value area. `'stacked'` is the sidebar-fit variant the\n * AI proposal card selects: each field is a full-width card (label header, then\n * `Current → Proposed` VERTICALLY) that reads at ~320px without a squished two-column\n * split. Only chrome + column arrangement branch on `layout`; grouping, word diffing,\n * and change detection are shared — never forked.\n *\n * Must be rendered under a `CollectionViewProvider` (the value renderers resolve\n * relation titles / asset thumbnails through `useCollectionView`).\n */\nexport type DiffLayout = 'grid' | 'stacked'\nexport interface DocumentDiffRestore {\n baseVersion: number\n canRestore: boolean\n busy: boolean\n onRestore: (scope: RestoreScope) => void\n}\n\nexport interface DocumentDiffViewProps {\n diff: DocumentDiff\n collection: CollectionDef\n /** Pre-rendered column captions (version-specific text stays with the caller). */\n columnHeaders: { unified: string; before: string; after: string }\n /** Per-row restore controls; omitted ⇒ a restore-free read-only diff (AI review). */\n restore?: DocumentDiffRestore\n /** Extra note appended to the change-count summary (e.g. a comparing-past hint). */\n summaryHint?: ReactNode\n /** Presentation variant (EC-382). Defaults to the wide `'grid'` compare layout. */\n layout?: DiffLayout\n}\n\nexport function DocumentDiffView({\n diff,\n collection,\n columnHeaders,\n restore,\n summaryHint,\n layout = 'grid',\n}: DocumentDiffViewProps) {\n const source = useCollectionView()\n\n // EC-317 — the unified/side-by-side toggle is a transient, personal-local view\n // preference: read once at mount, written back on every change.\n const [mode, setModeState] = useState<DiffViewMode>(() => readDiffViewMode())\n const setMode = useCallback((next: DiffViewMode) => {\n setModeState(next)\n storeDiffViewMode(next)\n }, [])\n\n // EC-317 — long-value truncation state: an `expandAll` flag plus per-row overrides.\n const [expandAll, setExpandAll] = useState(false)\n const [expandedRows, setExpandedRows] = useState<ReadonlySet<string>>(() => new Set())\n const toggleExpand = useCallback((id: string) => {\n setExpandedRows((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n return next\n })\n }, [])\n const isExpanded = useCallback((id: string) => expandAll || expandedRows.has(id), [expandAll, expandedRows])\n const toggleExpandAll = useCallback(() => {\n setExpandAll((prev) => {\n const next = !prev\n if (!next) setExpandedRows(new Set())\n return next\n })\n }, [])\n const captions = useMemo(\n () => ({ before: columnHeaders.before, after: columnHeaders.after }),\n [columnHeaders.before, columnHeaders.after],\n )\n const diffDisplay = useMemo<DiffDisplayState>(\n () => ({ mode, layout, captions, expandAll, isExpanded, toggleExpand }),\n [mode, layout, captions, expandAll, isExpanded, toggleExpand],\n )\n\n const fieldOrder = useMemo(() => new Map(collection.fields.map((f, i) => [f.name, i])), [collection])\n const fieldByName = useMemo(() => new Map(collection.fields.map((f) => [f.name, f])), [collection])\n const localeRank = useMemo(() => new Map(source.localeConfig.locales.map((l, i) => [l, i])), [source.localeConfig])\n const groups = useMemo(\n () => groupByField(diff.changes, fieldOrder, localeRank),\n [diff.changes, fieldOrder, localeRank],\n )\n const groupRows = useMemo(() => {\n let rowIndex = 0\n return groups.map((group) => {\n const zebraStart = rowIndex\n rowIndex += group.entries.length\n return { group, field: fieldByName.get(group.field), zebraStart }\n })\n }, [groups, fieldByName])\n\n const canRestore = restore?.canRestore ?? false\n const baseVersion = restore?.baseVersion ?? 0\n const busy = restore?.busy ?? false\n const restoreFn = useCallback(\n (scope: RestoreScope) => restore?.onRestore(scope),\n [restore],\n )\n\n const summary = (\n <Text size=\"xs\" tone=\"muted\" className=\"px-0.5\">\n {translate(diff.changes.length === 1 ? 'cms.version.changeSummary.one' : 'cms.version.changeSummary.other', {\n count: diff.changes.length,\n unchanged: diff.unchangedCount,\n })}\n {summaryHint}\n </Text>\n )\n const expandAllButton = (\n <Button variant=\"ghost\" size=\"sm\" onClick={toggleExpandAll}>\n {translate(expandAll ? 'cms.field.collapseAll' : 'cms.field.expandAll')}\n </Button>\n )\n\n // EC-382 — the sidebar-fit variant: no two-column split to toggle, so the\n // unified/side-by-side control is dropped; each field is a full-width card\n // that lays Current → Proposed out vertically.\n if (layout === 'stacked') {\n return (\n <DiffDisplayContext.Provider value={diffDisplay}>\n <Stack gap=\"2\">\n <Row gap=\"2\" align=\"center\" justify=\"between\" wrap className=\"px-0.5\">\n {summary}\n {expandAllButton}\n </Row>\n <Stack gap=\"2\" className=\"pb-1\">\n {groupRows.map(({ group, field }) => (\n <FieldGroup\n key={group.field}\n group={group}\n field={field}\n zebraStart={0}\n baseVersion={baseVersion}\n canRestore={canRestore}\n busy={busy}\n onRestore={restoreFn}\n />\n ))}\n </Stack>\n </Stack>\n </DiffDisplayContext.Provider>\n )\n }\n\n return (\n <>\n {/* EC-317 — the diff-layout toolbar: unified/side-by-side (persisted) + expand-all. */}\n <Row gap=\"2\" align=\"center\" justify=\"between\" wrap className=\"px-0.5\">\n <DiffViewToggle mode={mode} onChange={setMode} />\n {expandAllButton}\n </Row>\n\n {summary}\n\n <DiffDisplayContext.Provider value={diffDisplay}>\n <div className=\"pb-1\">\n <div className={cn(DIFF_ROW_GRID, 'px-2 pb-1.5')}>\n <Text size=\"xs\" tone=\"subtle\" className=\"uppercase tracking-wide\">\n {translate('cms.version.fieldColumnHeader')}\n </Text>\n {mode === 'unified' ? (\n <Text size=\"xs\" tone=\"subtle\" className=\"uppercase tracking-wide\">\n {columnHeaders.unified}\n </Text>\n ) : (\n <TwoCol\n before={\n <Text size=\"xs\" tone=\"subtle\" className=\"uppercase tracking-wide\">\n {columnHeaders.before}\n </Text>\n }\n after={\n <Text size=\"xs\" tone=\"subtle\" className=\"uppercase tracking-wide\">\n {columnHeaders.after}\n </Text>\n }\n />\n )}\n </div>\n {groupRows.map(({ group, field, zebraStart }) => (\n <FieldGroup\n key={group.field}\n group={group}\n field={field}\n zebraStart={zebraStart}\n baseVersion={baseVersion}\n canRestore={canRestore}\n busy={busy}\n onRestore={restoreFn}\n />\n ))}\n </div>\n </DiffDisplayContext.Provider>\n </>\n )\n}\n\n// --- EC-317 diff-display context (mode + truncation) ------------------------------\n\ninterface DiffDisplayState {\n mode: DiffViewMode\n /** EC-382 — the active presentation variant; value renderers branch on it. */\n layout: DiffLayout\n /** EC-382 — the Current/Proposed captions, shown inline per side in `stacked`. */\n captions: { before: string; after: string }\n expandAll: boolean\n isExpanded: (id: string) => boolean\n toggleExpand: (id: string) => void\n}\n\nconst DiffDisplayContext = createContext<DiffDisplayState | null>(null)\n\nfunction useDiffDisplay(): DiffDisplayState {\n const ctx = useContext(DiffDisplayContext)\n if (!ctx) throw new Error('useDiffDisplay must be rendered under the DocumentDiffView diff area')\n return ctx\n}\n\n/** Shared grid template so the descriptor lane + header captions line up. */\nconst DIFF_ROW_GRID = 'grid grid-cols-[7.5rem_1fr_1.75rem] items-start gap-x-4'\n\n/** A before | after grid with a clear central divider. */\nfunction TwoCol({ before, after, className }: { before: ReactNode; after: ReactNode; className?: string }) {\n return (\n <div className={cn('relative grid grid-cols-2 gap-x-8', className)}>\n <div className=\"pointer-events-none absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-border\" aria-hidden />\n <div className=\"min-w-0 pr-1\">{before}</div>\n <div className=\"min-w-0 pl-1\">{after}</div>\n </div>\n )\n}\n\n/** Mode-aware value display (EC-317) / layout-aware in the EC-382 stacked variant. */\nfunction DiffColumns({ before, after, kind }: { before: ReactNode; after: ReactNode; kind: ChangeKind }) {\n const { mode, layout } = useDiffDisplay()\n if (layout === 'stacked') {\n return <StackedColumns before={before} after={after} kind={kind} />\n }\n if (mode === 'unified') {\n return (\n <Stack gap=\"1\">\n {kind !== 'added' ? <UnifiedLine tone=\"removed\">{before}</UnifiedLine> : null}\n {kind !== 'removed' ? <UnifiedLine tone=\"added\">{after}</UnifiedLine> : null}\n </Stack>\n )\n }\n return <TwoCol before={before} after={after} />\n}\n\n/**\n * EC-382 stacked value display: `Current` above `Proposed`, each captioned and\n * accented, full width — the sidebar-fit answer to the squished two-column split.\n * An `added` change shows only the proposed side; a `removed` change only current.\n */\nfunction StackedColumns({ before, after, kind }: { before: ReactNode; after: ReactNode; kind: ChangeKind }) {\n const { captions } = useDiffDisplay()\n return (\n <Stack gap=\"2\">\n {kind !== 'added' ? (\n <StackedSide caption={captions.before} tone=\"before\">\n {before}\n </StackedSide>\n ) : null}\n {kind !== 'removed' ? (\n <StackedSide caption={captions.after} tone=\"after\">\n {after}\n </StackedSide>\n ) : null}\n </Stack>\n )\n}\n\n/** One captioned side of a stacked change (EC-382). */\nfunction StackedSide({\n caption,\n tone,\n children,\n}: {\n caption: string\n tone: 'before' | 'after'\n children: ReactNode\n}) {\n return (\n <Stack gap=\"1\">\n <Text size=\"xs\" tone=\"subtle\" className=\"uppercase tracking-wide\">\n {caption}\n </Text>\n <div\n className={cn(\n 'min-w-0 border-l-2 pl-2.5',\n tone === 'before' ? 'border-border' : 'border-primary/60',\n )}\n >\n {children}\n </div>\n </Stack>\n )\n}\n\nfunction UnifiedLine({ tone, children }: { tone: 'removed' | 'added'; children: ReactNode }) {\n return (\n <Row\n gap=\"2\"\n align=\"start\"\n className={cn('rounded-sm px-1.5 py-1', tone === 'removed' ? 'bg-destructive/10' : 'bg-success/10')}\n >\n <Text\n size=\"xs\"\n mono\n aria-hidden\n className={cn('mt-0.5 shrink-0 select-none', tone === 'removed' ? 'text-destructive' : 'text-success')}\n >\n {tone === 'removed' ? '−' : '+'}\n </Text>\n <div className=\"min-w-0 flex-1\">{children}</div>\n </Row>\n )\n}\n\n/** Wraps truncatable content with its per-row \"Show more\"/\"Show less\" control. */\nfunction ExpandToggle({\n id,\n isLong,\n expanded,\n children,\n}: {\n id: string\n isLong: boolean\n expanded: boolean\n children: ReactNode\n}) {\n const { expandAll, toggleExpand } = useDiffDisplay()\n return (\n <div>\n {children}\n {isLong && !expandAll ? (\n <Button variant=\"link\" size=\"sm\" className=\"h-auto p-0 text-xs\" onClick={() => toggleExpand(id)}>\n {expanded ? translate('cms.version.showLess') : translate('cms.version.showMore')}\n </Button>\n ) : null}\n </div>\n )\n}\n\n/** The unified/side-by-side segmented toggle (EC-317). */\nfunction DiffViewToggle({ mode, onChange }: { mode: DiffViewMode; onChange: (mode: DiffViewMode) => void }) {\n return (\n <Row\n gap=\"px\"\n className=\"rounded-md bg-muted/50 p-0.5\"\n role=\"group\"\n aria-label={translate('cms.version.viewModeAriaLabel')}\n data-testid=\"diff-view-toggle\"\n >\n <DiffViewOption\n active={mode === 'sideBySide'}\n label={translate('cms.version.viewSideBySide')}\n onClick={() => onChange('sideBySide')}\n />\n <DiffViewOption\n active={mode === 'unified'}\n label={translate('cms.version.viewUnified')}\n onClick={() => onChange('unified')}\n />\n </Row>\n )\n}\n\nfunction DiffViewOption({ active, label, onClick }: { active: boolean; label: string; onClick: () => void }) {\n return (\n <button\n type=\"button\"\n aria-pressed={active}\n data-testid={`diff-view-option-${active ? 'active' : 'inactive'}`}\n onClick={onClick}\n className={cn(\n 'rounded-[5px] px-2.5 py-1 text-xs font-medium transition-colors',\n active ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground',\n )}\n >\n {label}\n </button>\n )\n}\n\ninterface FieldGroupData {\n field: string\n label: string\n type: FieldDef['type']\n entries: FieldChange[]\n}\n\n/** One field's diff rows (EC-317 grid rows / EC-382 stacked cards). */\nfunction FieldGroup({\n group,\n field,\n zebraStart,\n baseVersion,\n canRestore,\n busy,\n onRestore,\n}: {\n group: FieldGroupData\n field: FieldDef | undefined\n zebraStart: number\n baseVersion: number\n canRestore: boolean\n busy: boolean\n onRestore: (scope: RestoreScope) => void\n}) {\n const { layout } = useDiffDisplay()\n const label = field ? fieldLabel(field) : group.label\n const rows = group.entries.map((entry, i) => {\n const rowId = `${group.field}:${entry.locale ?? '_'}`\n const fieldRestore =\n canRestore && !entry.blocks ? (\n <RestoreIcon\n busy={busy}\n title={\n entry.locale\n ? translate('cms.version.restoreFieldLocale', {\n field: label,\n locale: localeChipLabel(entry.locale),\n version: baseVersion,\n })\n : translate('cms.version.restoreField', { field: label, version: baseVersion })\n }\n onClick={() => onRestore(fieldScope(entry))}\n />\n ) : null\n const descriptor = (\n <FieldDescriptor label={label} locale={entry.locale} kind={entry.kind} inline={layout === 'stacked'} />\n )\n const body = (\n <EntryBody\n change={entry}\n rowId={rowId}\n baseVersion={baseVersion}\n canRestore={canRestore}\n busy={busy}\n onRestore={onRestore}\n />\n )\n return layout === 'stacked' ? (\n <StackedFieldRow key={entry.locale ?? '__base__'} descriptor={descriptor} restore={fieldRestore}>\n {body}\n </StackedFieldRow>\n ) : (\n <FieldRow\n key={entry.locale ?? '__base__'}\n zebra={(zebraStart + i) % 2 === 1}\n descriptor={descriptor}\n restore={fieldRestore}\n >\n {body}\n </FieldRow>\n )\n })\n if (layout === 'stacked') return <>{rows}</>\n return <div className=\"border-t border-border/30\">{rows}</div>\n}\n\n/** The descriptor lane + value area, one grid row (EC-317). */\nfunction FieldRow({\n descriptor,\n restore,\n zebra,\n children,\n}: {\n descriptor: ReactNode\n restore: ReactNode\n zebra: boolean\n children: ReactNode\n}) {\n return (\n <div className={cn(DIFF_ROW_GRID, 'rounded-sm px-2 py-2.5', zebra && 'bg-muted/40')}>\n <div className=\"min-w-0\">{descriptor}</div>\n <div className=\"min-w-0\">{children}</div>\n <div className=\"flex justify-end\">{restore}</div>\n </div>\n )\n}\n\n/**\n * One field as a full-width card (EC-382 stacked variant): a label header\n * (descriptor + restore) over a full-width value area — no fixed lane to squeeze\n * the value at sidebar width.\n */\nfunction StackedFieldRow({\n descriptor,\n restore,\n children,\n}: {\n descriptor: ReactNode\n restore: ReactNode\n children: ReactNode\n}) {\n return (\n <div className=\"overflow-hidden rounded-lg border border-border/60 bg-card\">\n <Row gap=\"2\" align=\"center\" className=\"border-b border-border/50 bg-muted/30 px-3 py-2\">\n <div className=\"min-w-0 flex-1\">{descriptor}</div>\n {restore}\n </Row>\n <div className=\"px-3 py-2.5\">{children}</div>\n </div>\n )\n}\n\n/** The descriptor content (EC-317 stacked lane / EC-382 inline card header). */\nfunction FieldDescriptor({\n label,\n locale,\n kind,\n inline = false,\n}: {\n label: string\n locale?: string\n kind: ChangeKind\n inline?: boolean\n}) {\n const localeBadge = locale ? (\n <Badge variant=\"outline\" className=\"px-1 py-0 text-[0.6rem] uppercase tracking-wide text-muted-foreground\">\n {localeChipLabel(locale)}\n </Badge>\n ) : null\n if (inline) {\n return (\n <Row gap=\"2\" align=\"center\" wrap className=\"min-w-0\">\n <Text size=\"sm\" weight=\"semibold\" className=\"min-w-0 truncate\">\n {label}\n </Text>\n {localeBadge}\n <KindTag kind={kind} />\n </Row>\n )\n }\n return (\n <Stack gap=\"1\">\n <Text size=\"sm\" weight=\"medium\" className=\"min-w-0 truncate\">\n {label}\n </Text>\n <Row gap=\"1\" wrap>\n {localeBadge}\n <KindTag kind={kind} />\n </Row>\n </Stack>\n )\n}\n\nfunction EntryBody({\n change,\n rowId,\n baseVersion,\n canRestore,\n busy,\n onRestore,\n}: {\n change: FieldChange\n rowId: string\n baseVersion: number\n canRestore: boolean\n busy: boolean\n onRestore: (scope: RestoreScope) => void\n}) {\n const localeScope = change.locale !== undefined ? { locale: change.locale } : {}\n if (change.blocks) {\n return (\n <Stack gap=\"2\" className=\"mt-1\">\n {change.blocks.map((block) => (\n <BlockSection\n key={block.blockId}\n block={block}\n rowId={`${rowId}|block:${block.blockId}`}\n baseVersion={baseVersion}\n canRestore={canRestore}\n busy={busy}\n onRestore={() => onRestore({ kind: 'block', field: change.field, blockId: block.blockId, ...localeScope })}\n />\n ))}\n </Stack>\n )\n }\n if (change.type === 'richText') {\n const before = richTextToText(change.before)\n const after = richTextToText(change.after)\n if (before === after && before) return <MutedNote>{translate('cms.version.textUnchanged')}</MutedNote>\n // Both sides carry text → the word diff pinpoints the edit.\n if (before && after) return <WordDiffCols id={rowId} before={before} after={after} />\n // EC-379: one side is (textually) empty — a create proposal, a cleared body,\n // or structure-only content. Render the ACTUAL prose so the editor reviews\n // what they are approving (retires the blind \"Content changed.\" note).\n return (\n <DiffColumns\n kind={change.kind}\n before={<RichTextSide value={change.before} id={`${rowId}|before`} />}\n after={<RichTextSide value={change.after} id={`${rowId}|after`} />}\n />\n )\n }\n if (change.kind === 'changed' && typeof change.before === 'string' && typeof change.after === 'string') {\n return <WordDiffCols id={rowId} before={change.before} after={change.after} />\n }\n return (\n <DiffColumns\n kind={change.kind}\n before={<SideValue value={change.before} other={change.after} typeHint={change.type} id={`${rowId}|before`} />}\n after={<SideValue value={change.after} other={change.before} typeHint={change.type} id={`${rowId}|after`} />}\n />\n )\n}\n\nfunction BlockSection({\n block,\n rowId,\n baseVersion,\n canRestore,\n busy,\n onRestore,\n}: {\n block: BlockChange\n rowId: string\n baseVersion: number\n canRestore: boolean\n busy: boolean\n onRestore: () => void\n}) {\n const name = block.componentId.split('.').pop() ?? block.componentId\n // EC-593: a NESTED component (in prose, a slot, below a prop) is located; its restore is\n // its root's (the block restore scope addresses root blocks — a nested id would be a no-op).\n const nested = block.within !== undefined\n return (\n <div className=\"overflow-hidden rounded-md border border-border/60\" data-diff-block={block.blockId}>\n <Row gap=\"2\" align=\"center\" className=\"border-b border-border/50 bg-muted/30 px-2 py-1.5\">\n <Text size=\"xs\" weight=\"semibold\" className=\"min-w-0 truncate\">\n {name}\n </Text>\n <Code tone=\"muted\">{block.componentId}</Code>\n <KindTag kind={block.kind} />\n {nested ? <Text size=\"xs\" tone=\"muted\" className=\"min-w-0 truncate\">{nestedLocation(block.within!)}</Text> : null}\n <Spacer />\n {canRestore && !nested ? (\n <RestoreIcon\n busy={busy}\n title={translate('cms.version.restoreBlock', { version: baseVersion })}\n onClick={onRestore}\n />\n ) : null}\n </Row>\n <div className=\"px-2 py-2\">\n {block.props && block.props.length > 0 ? (\n <Stack gap=\"3\" className=\"border-l-2 border-border/50 pl-3\">\n {block.props.map((prop) => (\n <PropRow key={prop.name} prop={prop} rowId={`${rowId}|prop:${prop.name}`} />\n ))}\n </Stack>\n ) : null}\n {block.slotsChanged ? <MutedNote>{translate('cms.version.nestedContentChanged')}</MutedNote> : null}\n {block.kind !== 'changed' && !block.props?.length ? (\n <MutedNote>\n {block.kind === 'added' ? translate('cms.version.blockAdded') : translate('cms.version.blockRemoved')}\n </MutedNote>\n ) : null}\n </div>\n </div>\n )\n}\n\n/** Where a nested component sits: \"in the text\", or \"inside Section › Grid\". */\nexport function nestedLocation(within: readonly BlockAncestor[]): string {\n if (within.length === 0) return translate('cms.version.nestedInProse')\n const path = within.map((ancestor) => ancestor.componentId.split('.').pop() ?? ancestor.componentId).join(' › ')\n return translate('cms.version.nestedIn', { path })\n}\n\nfunction PropRow({ prop, rowId }: { prop: PropChange; rowId: string }) {\n const useWordDiff = prop.kind === 'changed' && typeof prop.before === 'string' && typeof prop.after === 'string'\n return (\n <div>\n <Text size=\"xs\" tone=\"subtle\" className=\"mb-0.5 block uppercase tracking-wide\">\n {prettyName(prop.name)}\n </Text>\n {useWordDiff ? (\n <WordDiffCols id={rowId} before={String(prop.before)} after={String(prop.after)} />\n ) : (\n <DiffColumns\n kind={prop.kind}\n before={<SideValue value={prop.before} other={prop.after} id={`${rowId}|before`} />}\n after={<SideValue value={prop.after} other={prop.before} id={`${rowId}|after`} />}\n />\n )}\n </div>\n )\n}\n\n/**\n * One side of a rich-text change (EC-379): rendered compact prose\n * ({@link RichTextPreview}), height-clamped behind the shared expand toggle for\n * long bodies, with the standard \"empty\" placeholder for an absent side.\n */\nfunction RichTextSide({ value, id }: { value: unknown; id: string }) {\n const { isExpanded } = useDiffDisplay()\n if (isRichTextValueEmpty(value)) {\n return (\n <Text size=\"sm\" tone=\"subtle\" className=\"italic\">\n {translate('cms.version.emptyValue')}\n </Text>\n )\n }\n const expanded = isExpanded(id)\n const isLong = richTextToText(value).length > DIFF_TRUNCATE_THRESHOLD\n return (\n <ExpandToggle id={id} isLong={isLong} expanded={expanded}>\n <div className={cn(!expanded && isLong && 'max-h-60 overflow-hidden')}>\n <RichTextPreview value={value} />\n </div>\n </ExpandToggle>\n )\n}\n\n/** One side of a non-text change — the value, or an \"empty\" placeholder. */\nfunction SideValue({\n value,\n other,\n typeHint,\n id,\n}: {\n value: unknown\n other?: unknown\n typeHint?: FieldDef['type']\n id: string\n}) {\n if (value === undefined || value === null || value === '') {\n return (\n <Text size=\"sm\" tone=\"subtle\" className=\"italic\">\n {translate('cms.version.emptyValue')}\n </Text>\n )\n }\n return <ValueView value={value} other={other} typeHint={typeHint} id={id} />\n}\n\n/** Read-only value display, dispatching on field type / self-describing value shape. */\nfunction ValueView({\n value,\n other,\n typeHint,\n id,\n}: {\n value: unknown\n other?: unknown\n typeHint?: FieldDef['type']\n id: string\n}) {\n const { isExpanded } = useDiffDisplay()\n if (typeHint === 'asset' || isAssetNode(value)) return <AssetValue value={value} />\n if (typeHint === 'relation' || readDocumentRef(value)) return <RelationValue value={value} other={other} />\n if (typeHint === 'richText')\n return (\n <Text size=\"sm\" className=\"whitespace-pre-wrap break-words\">\n {richTextToText(value) || translate('cms.version.richText')}\n </Text>\n )\n if (typeHint === 'boolean' || typeof value === 'boolean')\n return (\n <Text size=\"sm\" mono>\n {value === true ? translate('common.yes') : translate('common.no')}\n </Text>\n )\n if (typeHint === 'date')\n return (\n <Text size=\"sm\" mono>\n {String(value).slice(0, 10)}\n </Text>\n )\n if (typeof value === 'object')\n return (\n <Text size=\"sm\" tone=\"muted\">\n {Array.isArray(value)\n ? translate(value.length === 1 ? 'cms.version.itemCount.one' : 'cms.version.itemCount.other', {\n count: value.length,\n })\n : translate('cms.version.objectValue')}\n </Text>\n )\n const expanded = isExpanded(id)\n const { shown, isLong } = truncateText(String(value), expanded)\n return (\n <ExpandToggle id={id} isLong={isLong} expanded={expanded}>\n <Text size=\"sm\" className=\"whitespace-pre-wrap break-words\">\n {shown}\n </Text>\n </ExpandToggle>\n )\n}\n\nfunction RelationValue({ value, other }: { value: unknown; other?: unknown }) {\n const source = useCollectionView()\n const refs = toRefArray(value)\n if (refs.length === 0)\n return (\n <Text size=\"sm\" className=\"whitespace-pre-wrap break-words\">\n {String(value)}\n </Text>\n )\n const otherRefs = other !== undefined ? toRefArray(other) : []\n const label = refs\n .map((ref) => {\n const title = source.titleOf(ref)\n const collision = otherRefs.some((o) => o.id !== ref.id && source.titleOf(o) === title)\n return collision ? `${title} · ${ref.id}` : title\n })\n .join(', ')\n return <Text size=\"sm\">{label}</Text>\n}\n\nfunction authoredAssetSubfields(value: unknown): [string, unknown][] {\n return Object.entries(assetSubfieldsOf(value)).filter(([key]) => !ASSET_RECORD_KEYS.has(key))\n}\n\nfunction AssetValue({ value }: { value: unknown }) {\n const items = (Array.isArray(value) ? value : [value])\n .map((entry) => ({ id: readAssetId(entry), sub: authoredAssetSubfields(entry) }))\n .filter((a): a is { id: string; sub: [string, unknown][] } => a.id !== undefined)\n if (items.length === 0)\n return (\n <Text size=\"sm\" className=\"whitespace-pre-wrap break-words\">\n {String(value)}\n </Text>\n )\n return (\n <div className=\"flex flex-wrap gap-2\">\n {items.map(({ id, sub }, i) => (\n <div key={`${id}-${i}`} className=\"flex flex-col gap-1\">\n <AssetThumb id={id} />\n {sub.length > 0 ? (\n <Stack gap=\"1\" className=\"pl-0.5\">\n {sub.map(([key, val]) => (\n <Text key={key} size=\"xs\" tone=\"muted\" className=\"break-words\">\n <span className=\"uppercase tracking-wide text-muted-foreground/70\">{prettyName(key)}:</span>{' '}\n {typeof val === 'object' && val !== null\n ? translate('cms.version.objectValue')\n : String(val)}\n </Text>\n ))}\n </Stack>\n ) : null}\n </div>\n ))}\n </div>\n )\n}\n\n/** An asset as a thumbnail (image with a resolvable URL) or a labelled badge. */\nfunction AssetThumb({ id }: { id: string }) {\n const source = useCollectionView()\n const assetCollectionId = source.assetCollectionId ?? 'asset'\n const record = source.resolveAsset?.(id)\n const label = record?.title ?? record?.filename ?? source.titleOf({ collection: assetCollectionId, id })\n const isImage = record?.contentType?.startsWith('image/') ?? false\n const url = record?.url\n if (isImage && isDisplayableAssetUrl(url)) {\n return (\n <span className=\"inline-flex min-w-0 items-center gap-2\">\n <img\n src={url}\n alt={record?.alt ?? label}\n loading=\"lazy\"\n className=\"size-12 shrink-0 rounded border border-border bg-muted object-cover\"\n />\n <Text size=\"xs\" tone=\"muted\" className=\"min-w-0 truncate\">\n {label}\n </Text>\n </span>\n )\n }\n return (\n <Badge variant=\"outline\">\n <ImageIcon className=\"size-3\" /> {label}\n </Badge>\n )\n}\n\n// --- Prose word diff --------------------------------------------------------------\n\nconst isWordTokenChanged = (token: WordToken) => token.changed\nconst isMergedTokenChanged = (token: MergedDiffToken) => token.kind !== 'same'\n\nfunction WordDiffCols({ id, before, after }: { id: string; before: string; after: string }) {\n const { mode, layout, isExpanded, captions } = useDiffDisplay()\n const expanded = isExpanded(id)\n const wd = useMemo(() => wordDiff(before, after), [before, after])\n const merged = useMemo(() => mergeWordDiff(wd.before, wd.after), [wd])\n\n // EC-382: change-anchored truncation — the collapsed excerpt centers on the\n // FIRST edit (the EC-379 finding: an edit past the head threshold could hide\n // behind \"Show more\"). Applies to every layout/mode; only the arrangement varies.\n const beforeSlice = truncateTokensAroundChange(wd.before, expanded, isWordTokenChanged)\n const afterSlice = truncateTokensAroundChange(wd.after, expanded, isWordTokenChanged)\n\n if (layout === 'stacked') {\n const isLong = beforeSlice.isLong || afterSlice.isLong\n return (\n <ExpandToggle id={id} isLong={isLong} expanded={expanded}>\n <Stack gap=\"2\">\n <StackedSide caption={captions.before} tone=\"before\">\n <WordTokens excerpt={beforeSlice} side=\"before\" />\n </StackedSide>\n <StackedSide caption={captions.after} tone=\"after\">\n <WordTokens excerpt={afterSlice} side=\"after\" />\n </StackedSide>\n </Stack>\n </ExpandToggle>\n )\n }\n\n if (mode === 'unified') {\n const mergedSlice = truncateTokensAroundChange(merged, expanded, isMergedTokenChanged)\n return (\n <ExpandToggle id={id} isLong={mergedSlice.isLong} expanded={expanded}>\n <UnifiedWordTokens excerpt={mergedSlice} />\n </ExpandToggle>\n )\n }\n\n const isLong = beforeSlice.isLong || afterSlice.isLong\n return (\n <ExpandToggle id={id} isLong={isLong} expanded={expanded}>\n <TwoCol\n before={<WordTokens excerpt={beforeSlice} side=\"before\" />}\n after={<WordTokens excerpt={afterSlice} side=\"after\" />}\n />\n </ExpandToggle>\n )\n}\n\n/** A \"…\" standing in for the hidden context an anchored excerpt trimmed (EC-382). */\nfunction EllipsisMark() {\n return (\n <span aria-hidden className=\"select-none text-muted-foreground/60\">\n …{' '}\n </span>\n )\n}\n\nfunction WordTokens({ excerpt, side }: { excerpt: AnchoredExcerpt<WordToken>; side: 'before' | 'after' }) {\n return (\n <Text size=\"sm\" className=\"whitespace-pre-wrap break-words leading-relaxed\">\n {excerpt.leadingEllipsis ? <EllipsisMark /> : null}\n {excerpt.shown.map((token, i) =>\n token.changed ? (\n <mark\n key={i}\n className={cn(\n 'rounded-sm px-0.5',\n side === 'before'\n ? 'bg-destructive/15 text-destructive line-through decoration-destructive/40'\n : 'bg-success/20 text-foreground',\n )}\n >\n {token.text}\n </mark>\n ) : (\n <span key={i} className=\"text-muted-foreground\">\n {token.text}\n </span>\n ),\n )}\n {excerpt.trailingEllipsis ? <EllipsisMark /> : null}\n </Text>\n )\n}\n\nfunction UnifiedWordTokens({ excerpt }: { excerpt: AnchoredExcerpt<MergedDiffToken> }) {\n return (\n <Text size=\"sm\" className=\"whitespace-pre-wrap break-words leading-relaxed\">\n {excerpt.leadingEllipsis ? <EllipsisMark /> : null}\n {excerpt.shown.map((token, i) =>\n token.kind === 'same' ? (\n <span key={i} className=\"text-muted-foreground\">\n {token.text}\n </span>\n ) : (\n <mark\n key={i}\n className={cn(\n 'rounded-sm px-0.5',\n token.kind === 'removed'\n ? 'bg-destructive/15 text-destructive line-through decoration-destructive/40'\n : 'bg-success/20 text-foreground',\n )}\n >\n {token.text}\n </mark>\n ),\n )}\n {excerpt.trailingEllipsis ? <EllipsisMark /> : null}\n </Text>\n )\n}\n\n// --- Small shared bits ------------------------------------------------------------\n\nfunction KindTag({ kind }: { kind: FieldChange['kind'] }) {\n if (kind === 'changed') return null\n return (\n <Text size=\"xs\" tone=\"subtle\">\n · {kind === 'added' ? translate('cms.version.kindNew') : translate('cms.version.kindRemoved')}\n </Text>\n )\n}\n\nfunction RestoreIcon({ busy, title, onClick }: { busy: boolean; title: string; onClick: () => void }) {\n return (\n <Button variant=\"ghost\" size=\"icon-sm\" disabled={busy} title={title} aria-label={title} onClick={onClick}>\n <RotateCcw />\n </Button>\n )\n}\n\nfunction MutedNote({ children }: { children: ReactNode }) {\n return (\n <Text size=\"sm\" tone=\"muted\" className=\"italic\">\n {children}\n </Text>\n )\n}\n\nfunction fieldScope(change: FieldChange): RestoreScope {\n return { kind: 'field', field: change.field, ...(change.locale !== undefined ? { locale: change.locale } : {}) }\n}\n\n/** Group changes BY FIELD (a localized field's per-locale variants together). */\nfunction groupByField(\n changes: FieldChange[],\n fieldOrder: Map<string, number>,\n localeRank: Map<string, number>,\n): FieldGroupData[] {\n const map = new Map<string, FieldGroupData>()\n for (const change of changes) {\n let group = map.get(change.field)\n if (!group) {\n group = { field: change.field, label: change.label, type: change.type, entries: [] }\n map.set(change.field, group)\n }\n group.entries.push(change)\n }\n const groups = [...map.values()]\n groups.sort(\n (a, b) =>\n (fieldOrder.get(a.field) ?? Number.MAX_SAFE_INTEGER) - (fieldOrder.get(b.field) ?? Number.MAX_SAFE_INTEGER),\n )\n for (const group of groups) {\n group.entries.sort((a, b) => localeCompare(a.locale, b.locale, localeRank))\n }\n return groups\n}\n\nfunction localeCompare(a: string | undefined, b: string | undefined, rank: Map<string, number>): number {\n if (a === b) return 0\n if (a === undefined) return -1\n if (b === undefined) return 1\n return (rank.get(a) ?? 99) - (rank.get(b) ?? 99)\n}\n\n/** camelCase / snake prop name → a readable label. */\nfunction prettyName(name: string): string {\n const spaced = name.replace(/[_-]+/g, ' ').replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n return spaced.charAt(0).toUpperCase() + spaced.slice(1)\n}\n"]}
1
+ {"version":3,"file":"document-diff-view.js","sourceRoot":"","sources":["../../../src/components/cms/document-diff-view.tsx"],"names":[],"mappings":"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","sourcesContent":["import { createContext, useCallback, useContext, useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { Image as ImageIcon, RotateCcw } from 'lucide-react'\nimport type {\n BlockAncestor,\n BlockChange,\n ChangeKind,\n DocumentDiff,\n FieldChange,\n PropChange,\n} from '@elytracms/core/content'\nimport {\n ASSET_RECORD_KEYS,\n assetSubfieldsOf,\n isAssetNode,\n readAssetId,\n readDocumentRef,\n semanticValueEqual,\n} from '@elytracms/core/cms-core'\nimport type { CollectionDef, FieldDef, ObjectFieldDef, RestoreScope } from '@elytracms/core/cms-core'\nimport { Badge, Button, Code, Row, Spacer, Stack, Text } from '@elytracms/studio/ui'\nimport { translate } from '../../lib/i18n'\nimport { localeChipLabel } from '../../lib/locale'\nimport { cn } from '../../lib/utils'\nimport { readDiffViewMode, storeDiffViewMode } from '../../lib/diff-view-preference'\nimport type { DiffViewMode } from '../../lib/diff-view-preference'\nimport { isDisplayableAssetUrl } from '../../lib/assets'\nimport { useCollectionView } from '../collection-view/collection-view-context'\nimport { fieldLabel } from './cms-labels'\nimport { toRefArray } from './cell'\nimport { RichTextPreview, isRichTextValueEmpty } from './rich-text-preview'\nimport {\n DIFF_TRUNCATE_THRESHOLD,\n mergeWordDiff,\n richTextToText,\n truncateText,\n truncateTokensAroundChange,\n wordDiff,\n} from './version-compare-text'\nimport type { AnchoredExcerpt, MergedDiffToken, WordToken } from './version-compare-text'\n\n/**\n * The shared document-diff RENDERER (EC-317 change-list), extracted from\n * `VersionCompare` so a single renderer serves both the version-compare surface and\n * the EC-199 AI proposal review — never two diff renderers. It draws a `DocumentDiff`\n * ({@link diffDocuments}) as the calm change-list grouped BY FIELD: a descriptor lane,\n * before | after (or a unified lane), text as a prose diff, assets as thumbnails,\n * relations as titles, long values collapsed behind \"Show more\", zebra rows.\n *\n * It is display-only over an already-computed diff: the version chrome (version\n * pickers / steppers / restore-whole) stays in `VersionCompare`; the AI proposal card\n * feeds `diffDocuments(collection, emptyBefore, proposedAfter)` and omits `restore`.\n * The per-row restore affordance renders only when `restore.canRestore` is set, so the\n * AI review (a not-yet-saved proposal) shows a clean, restore-free diff.\n *\n * **Layout (EC-382).** One diff LOGIC, two presentations selected by `layout`:\n * `'grid'` (default) is the wide version-compare surface — a fixed descriptor lane\n * plus a unified/side-by-side value area. `'stacked'` is the sidebar-fit variant the\n * AI proposal card selects: each field is a full-width card (label header, then\n * `Current → Proposed` VERTICALLY) that reads at ~320px without a squished two-column\n * split. Only chrome + column arrangement branch on `layout`; grouping, word diffing,\n * and change detection are shared — never forked.\n *\n * Must be rendered under a `CollectionViewProvider` (the value renderers resolve\n * relation titles / asset thumbnails through `useCollectionView`).\n */\nexport type DiffLayout = 'grid' | 'stacked'\nexport interface DocumentDiffRestore {\n baseVersion: number\n canRestore: boolean\n busy: boolean\n onRestore: (scope: RestoreScope) => void\n}\n\nexport interface DocumentDiffViewProps {\n diff: DocumentDiff\n collection: CollectionDef\n /** Pre-rendered column captions (version-specific text stays with the caller). */\n columnHeaders: { unified: string; before: string; after: string }\n /** Per-row restore controls; omitted ⇒ a restore-free read-only diff (AI review). */\n restore?: DocumentDiffRestore\n /** Extra note appended to the change-count summary (e.g. a comparing-past hint). */\n summaryHint?: ReactNode\n /** Presentation variant (EC-382). Defaults to the wide `'grid'` compare layout. */\n layout?: DiffLayout\n}\n\nexport function DocumentDiffView({\n diff,\n collection,\n columnHeaders,\n restore,\n summaryHint,\n layout = 'grid',\n}: DocumentDiffViewProps) {\n const source = useCollectionView()\n\n // EC-317 — the unified/side-by-side toggle is a transient, personal-local view\n // preference: read once at mount, written back on every change.\n const [mode, setModeState] = useState<DiffViewMode>(() => readDiffViewMode())\n const setMode = useCallback((next: DiffViewMode) => {\n setModeState(next)\n storeDiffViewMode(next)\n }, [])\n\n // EC-317 — long-value truncation state: an `expandAll` flag plus per-row overrides.\n const [expandAll, setExpandAll] = useState(false)\n const [expandedRows, setExpandedRows] = useState<ReadonlySet<string>>(() => new Set())\n const toggleExpand = useCallback((id: string) => {\n setExpandedRows((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n return next\n })\n }, [])\n const isExpanded = useCallback((id: string) => expandAll || expandedRows.has(id), [expandAll, expandedRows])\n const toggleExpandAll = useCallback(() => {\n setExpandAll((prev) => {\n const next = !prev\n if (!next) setExpandedRows(new Set())\n return next\n })\n }, [])\n const captions = useMemo(\n () => ({ before: columnHeaders.before, after: columnHeaders.after }),\n [columnHeaders.before, columnHeaders.after],\n )\n const diffDisplay = useMemo<DiffDisplayState>(\n () => ({ mode, layout, captions, expandAll, isExpanded, toggleExpand }),\n [mode, layout, captions, expandAll, isExpanded, toggleExpand],\n )\n\n const fieldOrder = useMemo(() => new Map(collection.fields.map((f, i) => [f.name, i])), [collection])\n const fieldByName = useMemo(() => new Map(collection.fields.map((f) => [f.name, f])), [collection])\n const localeRank = useMemo(() => new Map(source.localeConfig.locales.map((l, i) => [l, i])), [source.localeConfig])\n const groups = useMemo(\n () => groupByField(diff.changes, fieldOrder, localeRank),\n [diff.changes, fieldOrder, localeRank],\n )\n const groupRows = useMemo(() => {\n let rowIndex = 0\n return groups.map((group) => {\n const zebraStart = rowIndex\n rowIndex += group.entries.length\n return { group, field: fieldByName.get(group.field), zebraStart }\n })\n }, [groups, fieldByName])\n\n const canRestore = restore?.canRestore ?? false\n const baseVersion = restore?.baseVersion ?? 0\n const busy = restore?.busy ?? false\n const restoreFn = useCallback(\n (scope: RestoreScope) => restore?.onRestore(scope),\n [restore],\n )\n\n const summary = (\n <Text size=\"xs\" tone=\"muted\" className=\"px-0.5\">\n {translate(diff.changes.length === 1 ? 'cms.version.changeSummary.one' : 'cms.version.changeSummary.other', {\n count: diff.changes.length,\n unchanged: diff.unchangedCount,\n })}\n {summaryHint}\n </Text>\n )\n const expandAllButton = (\n <Button variant=\"ghost\" size=\"sm\" onClick={toggleExpandAll}>\n {translate(expandAll ? 'cms.field.collapseAll' : 'cms.field.expandAll')}\n </Button>\n )\n\n // EC-382 — the sidebar-fit variant: no two-column split to toggle, so the\n // unified/side-by-side control is dropped; each field is a full-width card\n // that lays Current → Proposed out vertically.\n if (layout === 'stacked') {\n return (\n <DiffDisplayContext.Provider value={diffDisplay}>\n <Stack gap=\"2\">\n <Row gap=\"2\" align=\"center\" justify=\"between\" wrap className=\"px-0.5\">\n {summary}\n {expandAllButton}\n </Row>\n <Stack gap=\"2\" className=\"pb-1\">\n {groupRows.map(({ group, field }) => (\n <FieldGroup\n key={group.field}\n group={group}\n field={field}\n zebraStart={0}\n baseVersion={baseVersion}\n canRestore={canRestore}\n busy={busy}\n onRestore={restoreFn}\n />\n ))}\n </Stack>\n </Stack>\n </DiffDisplayContext.Provider>\n )\n }\n\n return (\n <>\n {/* EC-317 — the diff-layout toolbar: unified/side-by-side (persisted) + expand-all. */}\n <Row gap=\"2\" align=\"center\" justify=\"between\" wrap className=\"px-0.5\">\n <DiffViewToggle mode={mode} onChange={setMode} />\n {expandAllButton}\n </Row>\n\n {summary}\n\n <DiffDisplayContext.Provider value={diffDisplay}>\n <div className=\"pb-1\">\n <div className={cn(DIFF_ROW_GRID, 'px-2 pb-1.5')}>\n <Text size=\"xs\" tone=\"subtle\" className=\"uppercase tracking-wide\">\n {translate('cms.version.fieldColumnHeader')}\n </Text>\n {mode === 'unified' ? (\n <Text size=\"xs\" tone=\"subtle\" className=\"uppercase tracking-wide\">\n {columnHeaders.unified}\n </Text>\n ) : (\n <TwoCol\n before={\n <Text size=\"xs\" tone=\"subtle\" className=\"uppercase tracking-wide\">\n {columnHeaders.before}\n </Text>\n }\n after={\n <Text size=\"xs\" tone=\"subtle\" className=\"uppercase tracking-wide\">\n {columnHeaders.after}\n </Text>\n }\n />\n )}\n </div>\n {groupRows.map(({ group, field, zebraStart }) => (\n <FieldGroup\n key={group.field}\n group={group}\n field={field}\n zebraStart={zebraStart}\n baseVersion={baseVersion}\n canRestore={canRestore}\n busy={busy}\n onRestore={restoreFn}\n />\n ))}\n </div>\n </DiffDisplayContext.Provider>\n </>\n )\n}\n\n// --- EC-317 diff-display context (mode + truncation) ------------------------------\n\ninterface DiffDisplayState {\n mode: DiffViewMode\n /** EC-382 — the active presentation variant; value renderers branch on it. */\n layout: DiffLayout\n /** EC-382 — the Current/Proposed captions, shown inline per side in `stacked`. */\n captions: { before: string; after: string }\n expandAll: boolean\n isExpanded: (id: string) => boolean\n toggleExpand: (id: string) => void\n}\n\nconst DiffDisplayContext = createContext<DiffDisplayState | null>(null)\n\nfunction useDiffDisplay(): DiffDisplayState {\n const ctx = useContext(DiffDisplayContext)\n if (!ctx) throw new Error('useDiffDisplay must be rendered under the DocumentDiffView diff area')\n return ctx\n}\n\n/** Shared grid template so the descriptor lane + header captions line up. */\nconst DIFF_ROW_GRID = 'grid grid-cols-[7.5rem_1fr_1.75rem] items-start gap-x-4'\n\n/** A before | after grid with a clear central divider. */\nfunction TwoCol({ before, after, className }: { before: ReactNode; after: ReactNode; className?: string }) {\n return (\n <div className={cn('relative grid grid-cols-2 gap-x-8', className)}>\n <div className=\"pointer-events-none absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-border\" aria-hidden />\n <div className=\"min-w-0 pr-1\">{before}</div>\n <div className=\"min-w-0 pl-1\">{after}</div>\n </div>\n )\n}\n\n/** Mode-aware value display (EC-317) / layout-aware in the EC-382 stacked variant. */\nfunction DiffColumns({ before, after, kind }: { before: ReactNode; after: ReactNode; kind: ChangeKind }) {\n const { mode, layout } = useDiffDisplay()\n if (layout === 'stacked') {\n return <StackedColumns before={before} after={after} kind={kind} />\n }\n if (mode === 'unified') {\n return (\n <Stack gap=\"1\">\n {kind !== 'added' ? <UnifiedLine tone=\"removed\">{before}</UnifiedLine> : null}\n {kind !== 'removed' ? <UnifiedLine tone=\"added\">{after}</UnifiedLine> : null}\n </Stack>\n )\n }\n return <TwoCol before={before} after={after} />\n}\n\n/**\n * EC-382 stacked value display: `Current` above `Proposed`, each captioned and\n * accented, full width — the sidebar-fit answer to the squished two-column split.\n * An `added` change shows only the proposed side; a `removed` change only current.\n */\nfunction StackedColumns({ before, after, kind }: { before: ReactNode; after: ReactNode; kind: ChangeKind }) {\n const { captions } = useDiffDisplay()\n return (\n <Stack gap=\"2\">\n {kind !== 'added' ? (\n <StackedSide caption={captions.before} tone=\"before\">\n {before}\n </StackedSide>\n ) : null}\n {kind !== 'removed' ? (\n <StackedSide caption={captions.after} tone=\"after\">\n {after}\n </StackedSide>\n ) : null}\n </Stack>\n )\n}\n\n/** One captioned side of a stacked change (EC-382). */\nfunction StackedSide({\n caption,\n tone,\n children,\n}: {\n caption: string\n tone: 'before' | 'after'\n children: ReactNode\n}) {\n return (\n <Stack gap=\"1\">\n <Text size=\"xs\" tone=\"subtle\" className=\"uppercase tracking-wide\">\n {caption}\n </Text>\n <div\n className={cn(\n 'min-w-0 border-l-2 pl-2.5',\n tone === 'before' ? 'border-border' : 'border-primary/60',\n )}\n >\n {children}\n </div>\n </Stack>\n )\n}\n\nfunction UnifiedLine({ tone, children }: { tone: 'removed' | 'added'; children: ReactNode }) {\n return (\n <Row\n gap=\"2\"\n align=\"start\"\n className={cn('rounded-sm px-1.5 py-1', tone === 'removed' ? 'bg-destructive/10' : 'bg-success/10')}\n >\n <Text\n size=\"xs\"\n mono\n aria-hidden\n className={cn('mt-0.5 shrink-0 select-none', tone === 'removed' ? 'text-destructive' : 'text-success')}\n >\n {tone === 'removed' ? '−' : '+'}\n </Text>\n <div className=\"min-w-0 flex-1\">{children}</div>\n </Row>\n )\n}\n\n/** Wraps truncatable content with its per-row \"Show more\"/\"Show less\" control. */\nfunction ExpandToggle({\n id,\n isLong,\n expanded,\n children,\n}: {\n id: string\n isLong: boolean\n expanded: boolean\n children: ReactNode\n}) {\n const { expandAll, toggleExpand } = useDiffDisplay()\n return (\n <div>\n {children}\n {isLong && !expandAll ? (\n <Button variant=\"link\" size=\"sm\" className=\"h-auto p-0 text-xs\" onClick={() => toggleExpand(id)}>\n {expanded ? translate('cms.version.showLess') : translate('cms.version.showMore')}\n </Button>\n ) : null}\n </div>\n )\n}\n\n/** The unified/side-by-side segmented toggle (EC-317). */\nfunction DiffViewToggle({ mode, onChange }: { mode: DiffViewMode; onChange: (mode: DiffViewMode) => void }) {\n return (\n <Row\n gap=\"px\"\n className=\"rounded-md bg-muted/50 p-0.5\"\n role=\"group\"\n aria-label={translate('cms.version.viewModeAriaLabel')}\n data-testid=\"diff-view-toggle\"\n >\n <DiffViewOption\n active={mode === 'sideBySide'}\n label={translate('cms.version.viewSideBySide')}\n onClick={() => onChange('sideBySide')}\n />\n <DiffViewOption\n active={mode === 'unified'}\n label={translate('cms.version.viewUnified')}\n onClick={() => onChange('unified')}\n />\n </Row>\n )\n}\n\nfunction DiffViewOption({ active, label, onClick }: { active: boolean; label: string; onClick: () => void }) {\n return (\n <button\n type=\"button\"\n aria-pressed={active}\n data-testid={`diff-view-option-${active ? 'active' : 'inactive'}`}\n onClick={onClick}\n className={cn(\n 'rounded-[5px] px-2.5 py-1 text-xs font-medium transition-colors',\n active ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground',\n )}\n >\n {label}\n </button>\n )\n}\n\ninterface FieldGroupData {\n field: string\n label: string\n type: FieldDef['type']\n entries: FieldChange[]\n}\n\n/** One field's diff rows (EC-317 grid rows / EC-382 stacked cards). */\nfunction FieldGroup({\n group,\n field,\n zebraStart,\n baseVersion,\n canRestore,\n busy,\n onRestore,\n}: {\n group: FieldGroupData\n field: FieldDef | undefined\n zebraStart: number\n baseVersion: number\n canRestore: boolean\n busy: boolean\n onRestore: (scope: RestoreScope) => void\n}) {\n const { layout } = useDiffDisplay()\n const label = field ? fieldLabel(field) : group.label\n const rows = group.entries.map((entry, i) => {\n const rowId = `${group.field}:${entry.locale ?? '_'}`\n const fieldRestore =\n canRestore && !entry.blocks ? (\n <RestoreIcon\n busy={busy}\n title={\n entry.locale\n ? translate('cms.version.restoreFieldLocale', {\n field: label,\n locale: localeChipLabel(entry.locale),\n version: baseVersion,\n })\n : translate('cms.version.restoreField', { field: label, version: baseVersion })\n }\n onClick={() => onRestore(fieldScope(entry))}\n />\n ) : null\n const descriptor = (\n <FieldDescriptor label={label} locale={entry.locale} kind={entry.kind} inline={layout === 'stacked'} />\n )\n const body = (\n <EntryBody\n change={entry}\n field={field}\n rowId={rowId}\n baseVersion={baseVersion}\n canRestore={canRestore}\n busy={busy}\n onRestore={onRestore}\n />\n )\n return layout === 'stacked' ? (\n <StackedFieldRow key={entry.locale ?? '__base__'} descriptor={descriptor} restore={fieldRestore}>\n {body}\n </StackedFieldRow>\n ) : (\n <FieldRow\n key={entry.locale ?? '__base__'}\n zebra={(zebraStart + i) % 2 === 1}\n descriptor={descriptor}\n restore={fieldRestore}\n >\n {body}\n </FieldRow>\n )\n })\n if (layout === 'stacked') return <>{rows}</>\n return <div className=\"border-t border-border/30\">{rows}</div>\n}\n\n/** The descriptor lane + value area, one grid row (EC-317). */\nfunction FieldRow({\n descriptor,\n restore,\n zebra,\n children,\n}: {\n descriptor: ReactNode\n restore: ReactNode\n zebra: boolean\n children: ReactNode\n}) {\n return (\n <div className={cn(DIFF_ROW_GRID, 'rounded-sm px-2 py-2.5', zebra && 'bg-muted/40')}>\n <div className=\"min-w-0\">{descriptor}</div>\n <div className=\"min-w-0\">{children}</div>\n <div className=\"flex justify-end\">{restore}</div>\n </div>\n )\n}\n\n/**\n * One field as a full-width card (EC-382 stacked variant): a label header\n * (descriptor + restore) over a full-width value area — no fixed lane to squeeze\n * the value at sidebar width.\n */\nfunction StackedFieldRow({\n descriptor,\n restore,\n children,\n}: {\n descriptor: ReactNode\n restore: ReactNode\n children: ReactNode\n}) {\n return (\n <div className=\"overflow-hidden rounded-lg border border-border/60 bg-card\">\n <Row gap=\"2\" align=\"center\" className=\"border-b border-border/50 bg-muted/30 px-3 py-2\">\n <div className=\"min-w-0 flex-1\">{descriptor}</div>\n {restore}\n </Row>\n <div className=\"px-3 py-2.5\">{children}</div>\n </div>\n )\n}\n\n/** The descriptor content (EC-317 stacked lane / EC-382 inline card header). */\nfunction FieldDescriptor({\n label,\n locale,\n kind,\n inline = false,\n}: {\n label: string\n locale?: string\n kind: ChangeKind\n inline?: boolean\n}) {\n const localeBadge = locale ? (\n <Badge variant=\"outline\" className=\"px-1 py-0 text-[0.6rem] uppercase tracking-wide text-muted-foreground\">\n {localeChipLabel(locale)}\n </Badge>\n ) : null\n if (inline) {\n return (\n <Row gap=\"2\" align=\"center\" wrap className=\"min-w-0\">\n <Text size=\"sm\" weight=\"semibold\" className=\"min-w-0 truncate\">\n {label}\n </Text>\n {localeBadge}\n <KindTag kind={kind} />\n </Row>\n )\n }\n return (\n <Stack gap=\"1\">\n <Text size=\"sm\" weight=\"medium\" className=\"min-w-0 truncate\">\n {label}\n </Text>\n <Row gap=\"1\" wrap>\n {localeBadge}\n <KindTag kind={kind} />\n </Row>\n </Stack>\n )\n}\n\nfunction EntryBody({\n change,\n field,\n rowId,\n baseVersion,\n canRestore,\n busy,\n onRestore,\n}: {\n change: FieldChange\n /** The schema's declaration of the changed field (absent for a schema-drift key). */\n field: FieldDef | undefined\n rowId: string\n baseVersion: number\n canRestore: boolean\n busy: boolean\n onRestore: (scope: RestoreScope) => void\n}) {\n const localeScope = change.locale !== undefined ? { locale: change.locale } : {}\n if (change.blocks) {\n return (\n <Stack gap=\"2\" className=\"mt-1\">\n {change.blocks.map((block) => (\n <BlockSection\n key={block.blockId}\n block={block}\n rowId={`${rowId}|block:${block.blockId}`}\n baseVersion={baseVersion}\n canRestore={canRestore}\n busy={busy}\n onRestore={() => onRestore({ kind: 'block', field: change.field, blockId: block.blockId, ...localeScope })}\n />\n ))}\n </Stack>\n )\n }\n if (change.type === 'richText') {\n const before = richTextToText(change.before)\n const after = richTextToText(change.after)\n if (before === after && before) return <MutedNote>{translate('cms.version.textUnchanged')}</MutedNote>\n // Both sides carry text → the word diff pinpoints the edit.\n if (before && after) return <WordDiffCols id={rowId} before={before} after={after} />\n // EC-379: one side is (textually) empty — a create proposal, a cleared body,\n // or structure-only content. Render the ACTUAL prose so the editor reviews\n // what they are approving (retires the blind \"Content changed.\" note).\n return (\n <DiffColumns\n kind={change.kind}\n before={<RichTextSide value={change.before} id={`${rowId}|before`} />}\n after={<RichTextSide value={change.after} id={`${rowId}|after`} />}\n />\n )\n }\n if (change.kind === 'changed' && typeof change.before === 'string' && typeof change.after === 'string') {\n return <WordDiffCols id={rowId} before={change.before} after={change.after} />\n }\n return (\n <DiffColumns\n kind={change.kind}\n before={\n <SideValue value={change.before} other={change.after} typeHint={change.type} field={field} id={`${rowId}|before`} />\n }\n after={\n <SideValue value={change.after} other={change.before} typeHint={change.type} field={field} id={`${rowId}|after`} />\n }\n />\n )\n}\n\nfunction BlockSection({\n block,\n rowId,\n baseVersion,\n canRestore,\n busy,\n onRestore,\n}: {\n block: BlockChange\n rowId: string\n baseVersion: number\n canRestore: boolean\n busy: boolean\n onRestore: () => void\n}) {\n const name = block.componentId.split('.').pop() ?? block.componentId\n // EC-593: a NESTED component (in prose, a slot, below a prop) is located; its restore is\n // its root's (the block restore scope addresses root blocks — a nested id would be a no-op).\n const nested = block.within !== undefined\n return (\n <div className=\"overflow-hidden rounded-md border border-border/60\" data-diff-block={block.blockId}>\n <Row gap=\"2\" align=\"center\" className=\"border-b border-border/50 bg-muted/30 px-2 py-1.5\">\n <Text size=\"xs\" weight=\"semibold\" className=\"min-w-0 truncate\">\n {name}\n </Text>\n <Code tone=\"muted\">{block.componentId}</Code>\n <KindTag kind={block.kind} />\n {nested ? <Text size=\"xs\" tone=\"muted\" className=\"min-w-0 truncate\">{nestedLocation(block.within!)}</Text> : null}\n <Spacer />\n {canRestore && !nested ? (\n <RestoreIcon\n busy={busy}\n title={translate('cms.version.restoreBlock', { version: baseVersion })}\n onClick={onRestore}\n />\n ) : null}\n </Row>\n <div className=\"px-2 py-2\">\n {block.props && block.props.length > 0 ? (\n <Stack gap=\"3\" className=\"border-l-2 border-border/50 pl-3\">\n {block.props.map((prop) => (\n <PropRow key={prop.name} prop={prop} rowId={`${rowId}|prop:${prop.name}`} />\n ))}\n </Stack>\n ) : null}\n {block.slotsChanged ? <MutedNote>{translate('cms.version.nestedContentChanged')}</MutedNote> : null}\n {block.kind !== 'changed' && !block.props?.length ? (\n <MutedNote>\n {block.kind === 'added' ? translate('cms.version.blockAdded') : translate('cms.version.blockRemoved')}\n </MutedNote>\n ) : null}\n </div>\n </div>\n )\n}\n\n/** Where a nested component sits: \"in the text\", or \"inside Section › Grid\". */\nexport function nestedLocation(within: readonly BlockAncestor[]): string {\n if (within.length === 0) return translate('cms.version.nestedInProse')\n const path = within.map((ancestor) => ancestor.componentId.split('.').pop() ?? ancestor.componentId).join(' › ')\n return translate('cms.version.nestedIn', { path })\n}\n\nfunction PropRow({ prop, rowId }: { prop: PropChange; rowId: string }) {\n const useWordDiff = prop.kind === 'changed' && typeof prop.before === 'string' && typeof prop.after === 'string'\n return (\n <div>\n <Text size=\"xs\" tone=\"subtle\" className=\"mb-0.5 block uppercase tracking-wide\">\n {prettyName(prop.name)}\n </Text>\n {useWordDiff ? (\n <WordDiffCols id={rowId} before={String(prop.before)} after={String(prop.after)} />\n ) : (\n <DiffColumns\n kind={prop.kind}\n before={<SideValue value={prop.before} other={prop.after} id={`${rowId}|before`} />}\n after={<SideValue value={prop.after} other={prop.before} id={`${rowId}|after`} />}\n />\n )}\n </div>\n )\n}\n\n/**\n * One side of a rich-text change (EC-379): rendered compact prose\n * ({@link RichTextPreview}), height-clamped behind the shared expand toggle for\n * long bodies, with the standard \"empty\" placeholder for an absent side.\n */\nfunction RichTextSide({ value, id }: { value: unknown; id: string }) {\n const { isExpanded } = useDiffDisplay()\n if (isRichTextValueEmpty(value)) {\n return (\n <Text size=\"sm\" tone=\"subtle\" className=\"italic\">\n {translate('cms.version.emptyValue')}\n </Text>\n )\n }\n const expanded = isExpanded(id)\n const isLong = richTextToText(value).length > DIFF_TRUNCATE_THRESHOLD\n return (\n <ExpandToggle id={id} isLong={isLong} expanded={expanded}>\n <div className={cn(!expanded && isLong && 'max-h-60 overflow-hidden')}>\n <RichTextPreview value={value} />\n </div>\n </ExpandToggle>\n )\n}\n\n/** One side of a non-text change — the value, or an \"empty\" placeholder. */\nfunction SideValue({\n value,\n other,\n typeHint,\n field,\n id,\n}: {\n value: unknown\n other?: unknown\n typeHint?: FieldDef['type']\n field?: FieldDef | undefined\n id: string\n}) {\n if (value === undefined || value === null || value === '') {\n return (\n <Text size=\"sm\" tone=\"subtle\" className=\"italic\">\n {translate('cms.version.emptyValue')}\n </Text>\n )\n }\n return <ValueView value={value} other={other} typeHint={typeHint} field={field} id={id} />\n}\n\n/** Read-only value display, dispatching on field type / self-describing value shape. */\nfunction ValueView({\n value,\n other,\n typeHint,\n field,\n id,\n}: {\n value: unknown\n other?: unknown\n typeHint?: FieldDef['type']\n /** The value's declaration, when the schema has one: an object field draws its sub-fields. */\n field?: FieldDef | undefined\n id: string\n}) {\n const { isExpanded } = useDiffDisplay()\n if (field?.type === 'object' && !field.multiple && isPlainRecord(value)) {\n const changed = changedObjectSubfields(field, value, other)\n if (changed !== null) return <ObjectValue value={value} other={other} changed={changed} id={id} />\n }\n if (typeHint === 'asset' || isAssetNode(value)) return <AssetValue value={value} />\n if (typeHint === 'relation' || readDocumentRef(value)) return <RelationValue value={value} other={other} />\n if (typeHint === 'richText')\n return (\n <Text size=\"sm\" className=\"whitespace-pre-wrap break-words\">\n {richTextToText(value) || translate('cms.version.richText')}\n </Text>\n )\n if (typeHint === 'boolean' || typeof value === 'boolean')\n return (\n <Text size=\"sm\" mono>\n {value === true ? translate('common.yes') : translate('common.no')}\n </Text>\n )\n if (typeHint === 'date')\n return (\n <Text size=\"sm\" mono>\n {String(value).slice(0, 10)}\n </Text>\n )\n if (typeof value === 'object')\n return (\n <Text size=\"sm\" tone=\"muted\">\n {Array.isArray(value)\n ? translate(value.length === 1 ? 'cms.version.itemCount.one' : 'cms.version.itemCount.other', {\n count: value.length,\n })\n : translate('cms.version.objectValue')}\n </Text>\n )\n const expanded = isExpanded(id)\n const { shown, isLong } = truncateText(String(value), expanded)\n return (\n <ExpandToggle id={id} isLong={isLong} expanded={expanded}>\n <Text size=\"sm\" className=\"whitespace-pre-wrap break-words\">\n {shown}\n </Text>\n </ExpandToggle>\n )\n}\n\n/** One sub-field of an object value: its stored key, and its declaration when the schema has one. */\ninterface ObjectSubfield {\n name: string\n sub: FieldDef | undefined\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * The sub-fields of ONE object value to draw beside the other side (EC-770 item 7): those whose\n * values differ by the diff's own equality ({@link semanticValueEqual}), against an empty object\n * when the other side holds none — so an added or removed object lists every sub-field it holds.\n * Declared sub-fields come in schema order with their declaration; a stored key the schema does\n * not declare (drift) is listed under its own name, never hidden. `null` when nothing differs.\n */\nfunction changedObjectSubfields(\n field: ObjectFieldDef,\n value: Readonly<Record<string, unknown>>,\n other: unknown,\n): ObjectSubfield[] | null {\n const against: Readonly<Record<string, unknown>> = isPlainRecord(other) ? other : {}\n const declared = new Set(field.fields.map((sub) => sub.name))\n const names: ObjectSubfield[] = [\n ...field.fields.map((sub) => ({ name: sub.name, sub })),\n ...[...new Set([...Object.keys(value), ...Object.keys(against)])]\n .filter((name) => !declared.has(name))\n .map((name) => ({ name, sub: undefined })),\n ]\n const changed = names.filter(({ name }) => !semanticValueEqual(value[name], against[name]))\n return changed.length > 0 ? changed : null\n}\n\n/**\n * One object field's value (one object, `multiple: false` — the SEO object): its differing\n * sub-fields, each labelled by its schema label and drawn through {@link SideValue} — never\n * \"object\" against \"object\", so a reader sees what a restore brings back (EC-770 item 7).\n */\nfunction ObjectValue({\n value,\n other,\n changed,\n id,\n}: {\n value: Readonly<Record<string, unknown>>\n other: unknown\n /** {@link changedObjectSubfields} of this side against the other. */\n changed: readonly ObjectSubfield[]\n id: string\n}) {\n const otherRecord = isPlainRecord(other) ? other : undefined\n return (\n <Stack gap=\"2\">\n {changed.map(({ name, sub }) => (\n <div key={name} className=\"min-w-0\">\n <Text size=\"xs\" tone=\"subtle\" className=\"mb-0.5 block uppercase tracking-wide\">\n {sub ? fieldLabel(sub) : name}\n </Text>\n <SideValue\n value={value[name]}\n other={otherRecord?.[name]}\n typeHint={sub?.type}\n field={sub}\n id={`${id}|${name}`}\n />\n </div>\n ))}\n </Stack>\n )\n}\n\nfunction RelationValue({ value, other }: { value: unknown; other?: unknown }) {\n const source = useCollectionView()\n const refs = toRefArray(value)\n if (refs.length === 0)\n return (\n <Text size=\"sm\" className=\"whitespace-pre-wrap break-words\">\n {String(value)}\n </Text>\n )\n const otherRefs = other !== undefined ? toRefArray(other) : []\n const label = refs\n .map((ref) => {\n const title = source.titleOf(ref)\n const collision = otherRefs.some((o) => o.id !== ref.id && source.titleOf(o) === title)\n return collision ? `${title} · ${ref.id}` : title\n })\n .join(', ')\n return <Text size=\"sm\">{label}</Text>\n}\n\nfunction authoredAssetSubfields(value: unknown): [string, unknown][] {\n return Object.entries(assetSubfieldsOf(value)).filter(([key]) => !ASSET_RECORD_KEYS.has(key))\n}\n\nfunction AssetValue({ value }: { value: unknown }) {\n const items = (Array.isArray(value) ? value : [value])\n .map((entry) => ({ id: readAssetId(entry), sub: authoredAssetSubfields(entry) }))\n .filter((a): a is { id: string; sub: [string, unknown][] } => a.id !== undefined)\n if (items.length === 0)\n return (\n <Text size=\"sm\" className=\"whitespace-pre-wrap break-words\">\n {String(value)}\n </Text>\n )\n return (\n <div className=\"flex flex-wrap gap-2\">\n {items.map(({ id, sub }, i) => (\n <div key={`${id}-${i}`} className=\"flex flex-col gap-1\">\n <AssetThumb id={id} />\n {sub.length > 0 ? (\n <Stack gap=\"1\" className=\"pl-0.5\">\n {sub.map(([key, val]) => (\n <Text key={key} size=\"xs\" tone=\"muted\" className=\"break-words\">\n <span className=\"uppercase tracking-wide text-muted-foreground/70\">{prettyName(key)}:</span>{' '}\n {typeof val === 'object' && val !== null\n ? translate('cms.version.objectValue')\n : String(val)}\n </Text>\n ))}\n </Stack>\n ) : null}\n </div>\n ))}\n </div>\n )\n}\n\n/** An asset as a thumbnail (image with a resolvable URL) or a labelled badge. */\nfunction AssetThumb({ id }: { id: string }) {\n const source = useCollectionView()\n const assetCollectionId = source.assetCollectionId ?? 'asset'\n const record = source.resolveAsset?.(id)\n const label = record?.title ?? record?.filename ?? source.titleOf({ collection: assetCollectionId, id })\n const isImage = record?.contentType?.startsWith('image/') ?? false\n const url = record?.url\n if (isImage && isDisplayableAssetUrl(url)) {\n return (\n <span className=\"inline-flex min-w-0 items-center gap-2\">\n <img\n src={url}\n alt={record?.alt ?? label}\n loading=\"lazy\"\n className=\"size-12 shrink-0 rounded border border-border bg-muted object-cover\"\n />\n <Text size=\"xs\" tone=\"muted\" className=\"min-w-0 truncate\">\n {label}\n </Text>\n </span>\n )\n }\n return (\n <Badge variant=\"outline\">\n <ImageIcon className=\"size-3\" /> {label}\n </Badge>\n )\n}\n\n// --- Prose word diff --------------------------------------------------------------\n\nconst isWordTokenChanged = (token: WordToken) => token.changed\nconst isMergedTokenChanged = (token: MergedDiffToken) => token.kind !== 'same'\n\nfunction WordDiffCols({ id, before, after }: { id: string; before: string; after: string }) {\n const { mode, layout, isExpanded, captions } = useDiffDisplay()\n const expanded = isExpanded(id)\n const wd = useMemo(() => wordDiff(before, after), [before, after])\n const merged = useMemo(() => mergeWordDiff(wd.before, wd.after), [wd])\n\n // EC-382: change-anchored truncation — the collapsed excerpt centers on the\n // FIRST edit (the EC-379 finding: an edit past the head threshold could hide\n // behind \"Show more\"). Applies to every layout/mode; only the arrangement varies.\n const beforeSlice = truncateTokensAroundChange(wd.before, expanded, isWordTokenChanged)\n const afterSlice = truncateTokensAroundChange(wd.after, expanded, isWordTokenChanged)\n\n if (layout === 'stacked') {\n const isLong = beforeSlice.isLong || afterSlice.isLong\n return (\n <ExpandToggle id={id} isLong={isLong} expanded={expanded}>\n <Stack gap=\"2\">\n <StackedSide caption={captions.before} tone=\"before\">\n <WordTokens excerpt={beforeSlice} side=\"before\" />\n </StackedSide>\n <StackedSide caption={captions.after} tone=\"after\">\n <WordTokens excerpt={afterSlice} side=\"after\" />\n </StackedSide>\n </Stack>\n </ExpandToggle>\n )\n }\n\n if (mode === 'unified') {\n const mergedSlice = truncateTokensAroundChange(merged, expanded, isMergedTokenChanged)\n return (\n <ExpandToggle id={id} isLong={mergedSlice.isLong} expanded={expanded}>\n <UnifiedWordTokens excerpt={mergedSlice} />\n </ExpandToggle>\n )\n }\n\n const isLong = beforeSlice.isLong || afterSlice.isLong\n return (\n <ExpandToggle id={id} isLong={isLong} expanded={expanded}>\n <TwoCol\n before={<WordTokens excerpt={beforeSlice} side=\"before\" />}\n after={<WordTokens excerpt={afterSlice} side=\"after\" />}\n />\n </ExpandToggle>\n )\n}\n\n/** A \"…\" standing in for the hidden context an anchored excerpt trimmed (EC-382). */\nfunction EllipsisMark() {\n return (\n <span aria-hidden className=\"select-none text-muted-foreground/60\">\n …{' '}\n </span>\n )\n}\n\nfunction WordTokens({ excerpt, side }: { excerpt: AnchoredExcerpt<WordToken>; side: 'before' | 'after' }) {\n return (\n <Text size=\"sm\" className=\"whitespace-pre-wrap break-words leading-relaxed\">\n {excerpt.leadingEllipsis ? <EllipsisMark /> : null}\n {excerpt.shown.map((token, i) =>\n token.changed ? (\n <mark\n key={i}\n className={cn(\n 'rounded-sm px-0.5',\n side === 'before'\n ? 'bg-destructive/15 text-destructive line-through decoration-destructive/40'\n : 'bg-success/20 text-foreground',\n )}\n >\n {token.text}\n </mark>\n ) : (\n <span key={i} className=\"text-muted-foreground\">\n {token.text}\n </span>\n ),\n )}\n {excerpt.trailingEllipsis ? <EllipsisMark /> : null}\n </Text>\n )\n}\n\nfunction UnifiedWordTokens({ excerpt }: { excerpt: AnchoredExcerpt<MergedDiffToken> }) {\n return (\n <Text size=\"sm\" className=\"whitespace-pre-wrap break-words leading-relaxed\">\n {excerpt.leadingEllipsis ? <EllipsisMark /> : null}\n {excerpt.shown.map((token, i) =>\n token.kind === 'same' ? (\n <span key={i} className=\"text-muted-foreground\">\n {token.text}\n </span>\n ) : (\n <mark\n key={i}\n className={cn(\n 'rounded-sm px-0.5',\n token.kind === 'removed'\n ? 'bg-destructive/15 text-destructive line-through decoration-destructive/40'\n : 'bg-success/20 text-foreground',\n )}\n >\n {token.text}\n </mark>\n ),\n )}\n {excerpt.trailingEllipsis ? <EllipsisMark /> : null}\n </Text>\n )\n}\n\n// --- Small shared bits ------------------------------------------------------------\n\nfunction KindTag({ kind }: { kind: FieldChange['kind'] }) {\n if (kind === 'changed') return null\n return (\n <Text size=\"xs\" tone=\"subtle\">\n · {kind === 'added' ? translate('cms.version.kindNew') : translate('cms.version.kindRemoved')}\n </Text>\n )\n}\n\nfunction RestoreIcon({ busy, title, onClick }: { busy: boolean; title: string; onClick: () => void }) {\n return (\n <Button variant=\"ghost\" size=\"icon-sm\" disabled={busy} title={title} aria-label={title} onClick={onClick}>\n <RotateCcw />\n </Button>\n )\n}\n\nfunction MutedNote({ children }: { children: ReactNode }) {\n return (\n <Text size=\"sm\" tone=\"muted\" className=\"italic\">\n {children}\n </Text>\n )\n}\n\nfunction fieldScope(change: FieldChange): RestoreScope {\n return { kind: 'field', field: change.field, ...(change.locale !== undefined ? { locale: change.locale } : {}) }\n}\n\n/** Group changes BY FIELD (a localized field's per-locale variants together). */\nfunction groupByField(\n changes: FieldChange[],\n fieldOrder: Map<string, number>,\n localeRank: Map<string, number>,\n): FieldGroupData[] {\n const map = new Map<string, FieldGroupData>()\n for (const change of changes) {\n let group = map.get(change.field)\n if (!group) {\n group = { field: change.field, label: change.label, type: change.type, entries: [] }\n map.set(change.field, group)\n }\n group.entries.push(change)\n }\n const groups = [...map.values()]\n groups.sort(\n (a, b) =>\n (fieldOrder.get(a.field) ?? Number.MAX_SAFE_INTEGER) - (fieldOrder.get(b.field) ?? Number.MAX_SAFE_INTEGER),\n )\n for (const group of groups) {\n group.entries.sort((a, b) => localeCompare(a.locale, b.locale, localeRank))\n }\n return groups\n}\n\nfunction localeCompare(a: string | undefined, b: string | undefined, rank: Map<string, number>): number {\n if (a === b) return 0\n if (a === undefined) return -1\n if (b === undefined) return 1\n return (rank.get(a) ?? 99) - (rank.get(b) ?? 99)\n}\n\n/** camelCase / snake prop name → a readable label. */\nfunction prettyName(name: string): string {\n const spaced = name.replace(/[_-]+/g, ' ').replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n return spaced.charAt(0).toUpperCase() + spaced.slice(1)\n}\n"]}
@@ -1,10 +1,3 @@
1
- /**
2
- * The Components section landing view (EC-050, overhauled EC-320). Serves BOTH
3
- * audiences: editors get a live census of what components exist (totals,
4
- * per-category breakdown, health) and a "pick one" nudge;
5
- * devs get pointers to the real in-repo docs for registering and extending
6
- * components — no code sample to drift, no invented docs.
7
- */
8
1
  export declare function ComponentsIndex({ projectId }: {
9
2
  projectId: string;
10
3
  }): import("react").JSX.Element;
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { BookOpen, Layers, MousePointerClick, Sparkles } from 'lucide-react';
3
+ import { elytraGuidePath } from '@elytracms/core/studio-core';
3
4
  import { getStudioRegistry, registryHealth } from '../../lib/registry/index.js';
4
5
  import { translate } from '../../lib/i18n/index.js';
5
6
  import { RegistryBrowser } from './registry-browser.js';
@@ -9,9 +10,15 @@ import { Badge, Card, Code, Heading, Panel, PanelHeader, Row, Spacer, Stack, Tex
9
10
  * The Components section landing view (EC-050, overhauled EC-320). Serves BOTH
10
11
  * audiences: editors get a live census of what components exist (totals,
11
12
  * per-category breakdown, health) and a "pick one" nudge;
12
- * devs get pointers to the real in-repo docs for registering and extending
13
+ * devs get pointers to the guide's chapters on registering and extending
13
14
  * components — no code sample to drift, no invented docs.
14
15
  */
16
+ /** The guide chapters the developer panel points at (EC-765: file names in the shipped guide). */
17
+ const COMPONENTS_INDEX_CHAPTERS = {
18
+ authoring: '12-component-authoring.md',
19
+ components: '03-components.md',
20
+ overview: '00-overview.md',
21
+ };
15
22
  export function ComponentsIndex({ projectId }) {
16
23
  const studio = getStudioRegistry();
17
24
  const manifests = studio.registry.list();
@@ -20,7 +27,7 @@ export function ComponentsIndex({ projectId }) {
20
27
  return (_jsxs("div", { className: "mx-auto w-full max-w-4xl p-4 sm:p-6", children: [_jsx("div", { className: "mb-6 h-80 overflow-hidden rounded-lg border border-border md:hidden", children: _jsx(RegistryBrowser, { projectId: projectId }) }), _jsxs(Stack, { gap: "6", children: [_jsxs(Stack, { gap: "1", children: [_jsx(Heading, { size: "display", children: translate('components.index.title') }), _jsx(Text, { tone: "muted", children: translate('components.index.subtitle') })] }), _jsxs("div", { className: "grid gap-3 sm:grid-cols-3", children: [_jsx(StatCard, { label: translate('components.index.stat.total'), value: stats.total }), _jsx(StatCard, { label: translate('components.index.stat.valid'), value: health.valid, tone: "success" }), _jsx(StatCard, { label: translate('components.index.stat.needAttention'), value: health.incompatible + health.invalid, tone: health.incompatible + health.invalid > 0 ? 'warning' : 'muted', hint: translate('components.index.stat.needAttentionHint', {
21
28
  incompatible: health.incompatible,
22
29
  invalid: health.invalid,
23
- }) })] }), stats.categories.length > 0 ? (_jsxs(Panel, { children: [_jsxs(PanelHeader, { children: [_jsx(Layers, { className: "size-4 text-muted-foreground" }), _jsx(Text, { size: "sm", weight: "semibold", children: translate('components.index.byCategory') })] }), _jsx(Row, { gap: "2", wrap: true, className: "p-4", children: stats.categories.map((category) => (_jsxs(Badge, { variant: "outline", children: [_jsx("span", { className: category.key ? 'capitalize' : undefined, children: category.key || translate('components.taxonomy.uncategorized') }), _jsx("span", { className: "font-mono text-muted-foreground", children: category.count })] }, category.key || '__uncategorized__'))) })] })) : null, _jsxs(Card, { className: "flex items-center gap-3 p-4", children: [_jsx("span", { className: "grid size-9 shrink-0 place-items-center rounded-lg bg-muted text-muted-foreground", children: _jsx(MousePointerClick, { className: "size-4" }) }), _jsx(Text, { size: "sm", tone: "muted", children: translate('components.index.pickHint') })] }), _jsxs(Panel, { children: [_jsxs(PanelHeader, { children: [_jsx(BookOpen, { className: "size-4 text-muted-foreground" }), _jsx(Text, { size: "sm", weight: "semibold", children: translate('components.index.guide.title') }), _jsx(Spacer, {}), _jsx(Badge, { variant: "outline", children: translate('components.index.guide.badge') })] }), _jsxs(Stack, { gap: "3", className: "p-4", children: [_jsx(Text, { size: "sm", tone: "muted", children: translate('components.index.guide.intro') }), _jsxs(Stack, { gap: "2", children: [_jsx(DocPointer, { path: "docs/component-authoring.md", description: translate('components.index.guide.doc.authoring') }), _jsx(DocPointer, { path: "docs/guide/03-components.md", description: translate('components.index.guide.doc.components') }), _jsx(DocPointer, { path: "docs/guide/00-overview.md", description: translate('components.index.guide.doc.guide') })] }), _jsxs(Text, { size: "xs", tone: "subtle", children: [_jsx(Sparkles, { className: "mr-1 inline size-3", "aria-hidden": true }), translate('components.index.guide.namespaceNote')] })] })] })] })] }));
30
+ }) })] }), stats.categories.length > 0 ? (_jsxs(Panel, { children: [_jsxs(PanelHeader, { children: [_jsx(Layers, { className: "size-4 text-muted-foreground" }), _jsx(Text, { size: "sm", weight: "semibold", children: translate('components.index.byCategory') })] }), _jsx(Row, { gap: "2", wrap: true, className: "p-4", children: stats.categories.map((category) => (_jsxs(Badge, { variant: "outline", children: [_jsx("span", { className: category.key ? 'capitalize' : undefined, children: category.key || translate('components.taxonomy.uncategorized') }), _jsx("span", { className: "font-mono text-muted-foreground", children: category.count })] }, category.key || '__uncategorized__'))) })] })) : null, _jsxs(Card, { className: "flex items-center gap-3 p-4", children: [_jsx("span", { className: "grid size-9 shrink-0 place-items-center rounded-lg bg-muted text-muted-foreground", children: _jsx(MousePointerClick, { className: "size-4" }) }), _jsx(Text, { size: "sm", tone: "muted", children: translate('components.index.pickHint') })] }), _jsxs(Panel, { children: [_jsxs(PanelHeader, { children: [_jsx(BookOpen, { className: "size-4 text-muted-foreground" }), _jsx(Text, { size: "sm", weight: "semibold", children: translate('components.index.guide.title') }), _jsx(Spacer, {}), _jsx(Badge, { variant: "outline", children: translate('components.index.guide.badge') })] }), _jsxs(Stack, { gap: "3", className: "p-4", children: [_jsx(Text, { size: "sm", tone: "muted", children: translate('components.index.guide.intro') }), _jsxs(Stack, { gap: "2", children: [_jsx(DocPointer, { path: elytraGuidePath(COMPONENTS_INDEX_CHAPTERS.authoring), description: translate('components.index.guide.doc.authoring') }), _jsx(DocPointer, { path: elytraGuidePath(COMPONENTS_INDEX_CHAPTERS.components), description: translate('components.index.guide.doc.components') }), _jsx(DocPointer, { path: elytraGuidePath(COMPONENTS_INDEX_CHAPTERS.overview), description: translate('components.index.guide.doc.guide') })] }), _jsxs(Text, { size: "xs", tone: "subtle", children: [_jsx(Sparkles, { className: "mr-1 inline size-3", "aria-hidden": true }), translate('components.index.guide.namespaceNote')] })] })] })] })] }));
24
31
  }
25
32
  function DocPointer({ path, description }) {
26
33
  return (_jsxs(Row, { gap: "3", align: "center", className: "rounded-md border border-border p-2.5", children: [_jsx(Code, { tone: "primary", className: "shrink-0", children: path }), _jsx(Text, { size: "xs", tone: "muted", children: description })] }));