@elytracms/studio 0.0.68 → 0.0.69

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 (53) hide show
  1. package/dist/components/assets/asset-detail.d.ts +4 -2
  2. package/dist/components/assets/asset-detail.js +4 -2
  3. package/dist/components/assets/asset-detail.js.map +1 -1
  4. package/dist/components/assets/assets-collection-view-source.d.ts +30 -19
  5. package/dist/components/assets/assets-collection-view-source.js +55 -23
  6. package/dist/components/assets/assets-collection-view-source.js.map +1 -1
  7. package/dist/components/builder/canvas-chrome-css.js +6 -1
  8. package/dist/components/builder/canvas-chrome-css.js.map +1 -1
  9. package/dist/components/builder/selection-overlay.d.ts +17 -4
  10. package/dist/components/builder/selection-overlay.js +17 -15
  11. package/dist/components/builder/selection-overlay.js.map +1 -1
  12. package/dist/components/builder/spacing-handles.d.ts +26 -1
  13. package/dist/components/builder/spacing-handles.js +66 -3
  14. package/dist/components/builder/spacing-handles.js.map +1 -1
  15. package/dist/components/cms/bulk-bar.d.ts +11 -1
  16. package/dist/components/cms/bulk-bar.js +10 -3
  17. package/dist/components/cms/bulk-bar.js.map +1 -1
  18. package/dist/components/cms/collection-table.js +19 -2
  19. package/dist/components/cms/collection-table.js.map +1 -1
  20. package/dist/components/cms/field-control.js +5 -1
  21. package/dist/components/cms/field-control.js.map +1 -1
  22. package/dist/components/cms/prop-fields.js +5 -1
  23. package/dist/components/cms/prop-fields.js.map +1 -1
  24. package/dist/components/cms/reference-confirm.js +5 -1
  25. package/dist/components/cms/reference-confirm.js.map +1 -1
  26. package/dist/components/cms/rich-text/editor.d.ts +24 -5
  27. package/dist/components/cms/rich-text/editor.js +23 -8
  28. package/dist/components/cms/rich-text/editor.js.map +1 -1
  29. package/dist/components/rail-view-source.d.ts +50 -1
  30. package/dist/components/rail-view-source.js +56 -2
  31. package/dist/components/rail-view-source.js.map +1 -1
  32. package/dist/components/redirects/redirects-collection-view-source.d.ts +3 -2
  33. package/dist/components/redirects/redirects-collection-view-source.js +4 -3
  34. package/dist/components/redirects/redirects-collection-view-source.js.map +1 -1
  35. package/dist/components/users/users-collection-view-source.js +1 -1
  36. package/dist/components/users/users-collection-view-source.js.map +1 -1
  37. package/dist/lib/collection-view/collection-view-source.d.ts +12 -0
  38. package/dist/lib/collection-view/collection-view-source.js.map +1 -1
  39. package/dist/lib/dnd/gap-drag.d.ts +8 -1
  40. package/dist/lib/dnd/gap-drag.js +4 -0
  41. package/dist/lib/dnd/gap-drag.js.map +1 -1
  42. package/dist/lib/i18n/messages.de.js +2 -0
  43. package/dist/lib/i18n/messages.de.js.map +1 -1
  44. package/dist/lib/i18n/messages.en.d.ts +1 -0
  45. package/dist/lib/i18n/messages.en.js +3 -0
  46. package/dist/lib/i18n/messages.en.js.map +1 -1
  47. package/dist/lib/references/references-store.d.ts +8 -1
  48. package/dist/lib/references/references-store.js +12 -2
  49. package/dist/lib/references/references-store.js.map +1 -1
  50. package/dist/ui/surface-geometry.d.ts +8 -5
  51. package/dist/ui/surface-geometry.js +8 -5
  52. package/dist/ui/surface-geometry.js.map +1 -1
  53. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"bulk-bar.js","sourceRoot":"","sources":["../../../src/components/cms/bulk-bar.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from 'react'\nimport { Check, CheckCircle2, CircleSlash, PencilLine, Trash2, X } from 'lucide-react'\nimport type { CollectionDef } from '@elytracms/core/cms-core'\nimport type { FilterScalar } from '@elytracms/core/content'\nimport { Badge, Button, Code, Row, Select, Spacer, Stack, Text } from '@elytracms/studio/ui'\nimport { translate } from '@elytracms/studio/lib/i18n'\nimport { filterableFieldOptions } from '@elytracms/studio/lib/cms-views'\nimport type { FilterableFieldOption } from '@elytracms/studio/lib/cms-views'\nimport { bulkSummary } from './bulk-actions'\nimport type { BulkAction, BulkReport, BulkSetField } from './bulk-actions'\nimport { cellEditKind } from './cell-edit'\nimport { ScalarFieldValueEditor } from './scalar-value-editor'\n\n/**\n * The scalar filterable fields a bulk set-field may target (EC-247): the\n * schema's `filterable` fields whose type edits inline (text/number/boolean/\n * select/date — `cellEditKind` 'inline'). Relation/asset (picker) and the\n * publication-state pseudo field are excluded — publish/unpublish own state,\n * and a raw relation id is not a safe bulk control.\n */\nexport function setFieldOptions(collection: CollectionDef): FilterableFieldOption[] {\n return filterableFieldOptions(collection).filter(\n (option) => option.def !== null && cellEditKind(option.def, false) === 'inline',\n )\n}\n\n/** A sensible starting value for a freshly chosen set-field target. */\nexport function initialSetValue(option: FilterableFieldOption | undefined): FilterScalar {\n return option?.def?.type === 'boolean' ? false : ''\n}\n\n/**\n * The bulk-action bar of the collection table (EC-169): appears with a row\n * selection, offers publish/unpublish/delete and a set-field assignment\n * (EC-247) over it. Unpublish and delete are confirmed by the owner through the\n * reference-aware EC-173 dialog (`ReferenceConfirmDialog`), which enumerates\n * every inbound reference that will break before anything dispatches — this bar\n * only raises the action. Set-field is a draft edit, so it applies directly.\n */\nexport function BulkBar({\n collection,\n count,\n busy,\n onAction,\n onSetField,\n onClear,\n}: {\n collection: CollectionDef\n /** Selected rows in the current view. */\n count: number\n busy: boolean\n onAction: (action: BulkAction) => void\n onSetField: (set: BulkSetField) => void\n onClear: () => void\n}) {\n const [setMode, setSetMode] = useState(false)\n if (count === 0) return null\n\n const options = setFieldOptions(collection)\n const settable = options.length > 0\n\n return (\n <Stack gap=\"none\" className=\"shrink-0\" data-testid=\"bulk-bar\">\n <Row gap=\"2\" className=\"border-b border-border bg-muted/40 px-4 py-2 sm:px-6\">\n <Text size=\"sm\" weight=\"medium\" data-testid=\"bulk-count\">\n {translate('cms.list.bulk.count', { count })}\n </Text>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy}\n data-testid=\"bulk-publish\"\n onClick={() => onAction('publish')}\n >\n <CheckCircle2 /> {translate('cms.list.bulk.publish')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy}\n data-testid=\"bulk-unpublish\"\n onClick={() => onAction('unpublish')}\n >\n <CircleSlash /> {translate('cms.list.bulk.unpublish')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy || !settable}\n aria-pressed={setMode}\n title={settable ? undefined : translate('cms.list.bulk.noSettableFields')}\n data-testid=\"bulk-set-field\"\n onClick={() => setSetMode((prev) => !prev)}\n >\n <PencilLine /> {translate('cms.list.bulk.setField')}\n </Button>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n disabled={busy}\n data-testid=\"bulk-delete\"\n onClick={() => onAction('delete')}\n >\n <Trash2 /> {translate('common.delete')}\n </Button>\n <Spacer />\n <Button variant=\"ghost\" size=\"sm\" disabled={busy} data-testid=\"bulk-clear\" onClick={onClear}>\n <X /> {translate('cms.list.bulk.clearSelection')}\n </Button>\n </Row>\n {setMode && settable ? (\n <SetFieldPanel\n options={options}\n busy={busy}\n onApply={(set) => {\n onSetField(set)\n setSetMode(false)\n }}\n onCancel={() => setSetMode(false)}\n />\n ) : null}\n </Stack>\n )\n}\n\n/** The inline \"set <field> to <value>\" composer over the current selection. */\nfunction SetFieldPanel({\n options,\n busy,\n onApply,\n onCancel,\n}: {\n options: FilterableFieldOption[]\n busy: boolean\n onApply: (set: BulkSetField) => void\n onCancel: () => void\n}) {\n const [field, setField] = useState(options[0]!.field)\n const option = options.find((candidate) => candidate.field === field) ?? options[0]!\n const [value, setValue] = useState<FilterScalar>(() => initialSetValue(option))\n\n function changeField(next: string) {\n setField(next)\n setValue(initialSetValue(options.find((candidate) => candidate.field === next)))\n }\n\n return (\n <Row\n gap=\"2\"\n align=\"center\"\n className=\"border-b border-border bg-muted/20 px-4 py-2 sm:px-6\"\n data-testid=\"bulk-set-panel\"\n >\n <Text size=\"sm\" tone=\"muted\">\n {translate('cms.list.bulk.set.set')}\n </Text>\n <Select\n aria-label={translate('cms.list.bulk.setField')}\n value={field}\n onChange={(event) => changeField(event.target.value)}\n className=\"h-7 w-auto py-0 text-xs\"\n data-testid=\"bulk-set-field-select\"\n >\n {options.map((candidate) => (\n <option key={candidate.field} value={candidate.field}>\n {candidate.label}\n </option>\n ))}\n </Select>\n <Text size=\"sm\" tone=\"muted\">\n {translate('cms.list.bulk.set.to')}\n </Text>\n <ScalarFieldValueEditor\n key={field}\n option={option}\n value={value}\n ariaLabel={translate('cms.list.bulk.set.valueAria')}\n testId=\"bulk-set-value\"\n onChange={setValue}\n />\n <Spacer />\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy}\n data-testid=\"bulk-set-apply\"\n onClick={() => onApply({ field, value })}\n >\n <Check /> {translate('cms.list.bulk.set.apply')}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" disabled={busy} data-testid=\"bulk-set-cancel\" onClick={onCancel}>\n {translate('common.cancel')}\n </Button>\n </Row>\n )\n}\n\n/**\n * Per-item bulk results (EC-169): the completion summary plus every failure,\n * named and with its reason — a partial failure is enumerated, never silent.\n */\nexport function BulkReportPanel({\n report,\n onDismiss,\n}: {\n report: BulkReport\n onDismiss: () => void\n}) {\n const { succeeded, failed } = bulkSummary(report)\n const failures = report.results.filter((result) => !result.ok)\n const actionLabel =\n report.action === 'set-field' && report.setField\n ? translate('cms.list.bulk.report.verb.setField', { field: report.setField.field })\n : translate(`cms.list.bulk.report.verb.${report.action}`)\n\n return (\n <Stack gap=\"1\" className=\"shrink-0 border-b border-border px-4 py-2 sm:px-6\" data-testid=\"bulk-report\">\n <Row gap=\"2\">\n <Text size=\"sm\" weight=\"medium\" data-testid=\"bulk-report-summary\">\n {translate('cms.list.bulk.report.summary', { action: actionLabel, succeeded })}\n {failed > 0 ? translate('cms.list.bulk.report.failedSuffix', { count: failed }) : ''}\n </Text>\n {failed > 0 ? (\n <Badge variant=\"error\">{translate('cms.list.bulk.report.failedBadge', { count: failed })}</Badge>\n ) : (\n <Badge variant=\"success\">{translate('cms.list.bulk.report.done')}</Badge>\n )}\n <Spacer />\n <Button variant=\"ghost\" size=\"sm\" data-testid=\"bulk-report-dismiss\" onClick={onDismiss}>\n {translate('common.dismiss')}\n </Button>\n </Row>\n {failures.map((failure) => (\n <Row gap=\"2\" key={failure.ref.id} data-testid={`bulk-failure-${failure.ref.id}`}>\n <Text size=\"xs\" className=\"text-destructive\">\n {failure.title}\n </Text>\n <Code tone=\"muted\">{failure.ref.id}</Code>\n <Text size=\"xs\" tone=\"muted\">\n {failure.reason}\n </Text>\n </Row>\n ))}\n </Stack>\n )\n}\n"]}
1
+ {"version":3,"file":"bulk-bar.js","sourceRoot":"","sources":["../../../src/components/cms/bulk-bar.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from 'react'\nimport { Check, CheckCircle2, CircleSlash, PencilLine, Trash2, X } from 'lucide-react'\nimport type { CollectionDef } from '@elytracms/core/cms-core'\nimport type { FilterScalar } from '@elytracms/core/content'\nimport { Badge, Button, Code, Row, Select, Spacer, Stack, Text } from '@elytracms/studio/ui'\nimport { translate } from '@elytracms/studio/lib/i18n'\nimport { filterableFieldOptions } from '@elytracms/studio/lib/cms-views'\nimport type { FilterableFieldOption } from '@elytracms/studio/lib/cms-views'\nimport type { CollectionViewCapabilities } from '@elytracms/studio/lib/collection-view/collection-view-source'\nimport { bulkSummary } from './bulk-actions'\nimport type { BulkAction, BulkReport, BulkSetField } from './bulk-actions'\nimport { cellEditKind } from './cell-edit'\nimport { ScalarFieldValueEditor } from './scalar-value-editor'\n\n/**\n * The scalar filterable fields a bulk set-field may target (EC-247): the\n * schema's `filterable` fields whose type edits inline (text/number/boolean/\n * select/date — `cellEditKind` 'inline'). Relation/asset (picker) and the\n * publication-state pseudo field are excluded — publish/unpublish own state,\n * and a raw relation id is not a safe bulk control.\n */\nexport function setFieldOptions(collection: CollectionDef): FilterableFieldOption[] {\n return filterableFieldOptions(collection).filter(\n (option) => option.def !== null && cellEditKind(option.def, false) === 'inline',\n )\n}\n\n/** A sensible starting value for a freshly chosen set-field target. */\nexport function initialSetValue(option: FilterableFieldOption | undefined): FilterScalar {\n return option?.def?.type === 'boolean' ? false : ''\n}\n\n/**\n * The bulk-action bar of the collection table (EC-169): appears with a row\n * selection, offers publish/unpublish/delete and a set-field assignment\n * (EC-247) over it. Unpublish and delete are confirmed by the owner through the\n * reference-aware EC-173 dialog (`ReferenceConfirmDialog`), which enumerates\n * every inbound reference that will break before anything dispatches — this bar\n * only raises the action. Set-field is a draft edit, so it applies directly.\n *\n * Every action is CAPABILITY-gated (EC-433), mirroring the row `⋮` menu's\n * `rowActionsFor` (EC-316): a rail without publish never shows\n * publish/unpublish, one without remove never shows Delete, and set-field\n * follows `inlineEdit` (it's a bulk cell write). Before this gate the bar\n * offered every action to every rail — the assets rail's bulk Delete then\n * confirmed into a source without a bulk runner and silently no-oped.\n */\nexport function BulkBar({\n collection,\n capabilities,\n count,\n busy,\n onAction,\n onSetField,\n onClear,\n}: {\n collection: CollectionDef\n /** The rail's capability matrix (AD-19) — the SAME gate the row menu uses. */\n capabilities: Pick<CollectionViewCapabilities, 'publish' | 'remove' | 'inlineEdit'>\n /** Selected rows in the current view. */\n count: number\n busy: boolean\n onAction: (action: BulkAction) => void\n onSetField: (set: BulkSetField) => void\n onClear: () => void\n}) {\n const [setMode, setSetMode] = useState(false)\n if (count === 0) return null\n\n const options = setFieldOptions(collection)\n const settable = options.length > 0\n\n return (\n <Stack gap=\"none\" className=\"shrink-0\" data-testid=\"bulk-bar\">\n <Row gap=\"2\" className=\"border-b border-border bg-muted/40 px-4 py-2 sm:px-6\">\n <Text size=\"sm\" weight=\"medium\" data-testid=\"bulk-count\">\n {translate('cms.list.bulk.count', { count })}\n </Text>\n {capabilities.publish ? (\n <>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy}\n data-testid=\"bulk-publish\"\n onClick={() => onAction('publish')}\n >\n <CheckCircle2 /> {translate('cms.list.bulk.publish')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy}\n data-testid=\"bulk-unpublish\"\n onClick={() => onAction('unpublish')}\n >\n <CircleSlash /> {translate('cms.list.bulk.unpublish')}\n </Button>\n </>\n ) : null}\n {capabilities.inlineEdit ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy || !settable}\n aria-pressed={setMode}\n title={settable ? undefined : translate('cms.list.bulk.noSettableFields')}\n data-testid=\"bulk-set-field\"\n onClick={() => setSetMode((prev) => !prev)}\n >\n <PencilLine /> {translate('cms.list.bulk.setField')}\n </Button>\n ) : null}\n {capabilities.remove ? (\n <Button\n variant=\"destructive\"\n size=\"sm\"\n disabled={busy}\n data-testid=\"bulk-delete\"\n onClick={() => onAction('delete')}\n >\n <Trash2 /> {translate('common.delete')}\n </Button>\n ) : null}\n <Spacer />\n <Button variant=\"ghost\" size=\"sm\" disabled={busy} data-testid=\"bulk-clear\" onClick={onClear}>\n <X /> {translate('cms.list.bulk.clearSelection')}\n </Button>\n </Row>\n {setMode && settable && capabilities.inlineEdit ? (\n <SetFieldPanel\n options={options}\n busy={busy}\n onApply={(set) => {\n onSetField(set)\n setSetMode(false)\n }}\n onCancel={() => setSetMode(false)}\n />\n ) : null}\n </Stack>\n )\n}\n\n/** The inline \"set <field> to <value>\" composer over the current selection. */\nfunction SetFieldPanel({\n options,\n busy,\n onApply,\n onCancel,\n}: {\n options: FilterableFieldOption[]\n busy: boolean\n onApply: (set: BulkSetField) => void\n onCancel: () => void\n}) {\n const [field, setField] = useState(options[0]!.field)\n const option = options.find((candidate) => candidate.field === field) ?? options[0]!\n const [value, setValue] = useState<FilterScalar>(() => initialSetValue(option))\n\n function changeField(next: string) {\n setField(next)\n setValue(initialSetValue(options.find((candidate) => candidate.field === next)))\n }\n\n return (\n <Row\n gap=\"2\"\n align=\"center\"\n className=\"border-b border-border bg-muted/20 px-4 py-2 sm:px-6\"\n data-testid=\"bulk-set-panel\"\n >\n <Text size=\"sm\" tone=\"muted\">\n {translate('cms.list.bulk.set.set')}\n </Text>\n <Select\n aria-label={translate('cms.list.bulk.setField')}\n value={field}\n onChange={(event) => changeField(event.target.value)}\n className=\"h-7 w-auto py-0 text-xs\"\n data-testid=\"bulk-set-field-select\"\n >\n {options.map((candidate) => (\n <option key={candidate.field} value={candidate.field}>\n {candidate.label}\n </option>\n ))}\n </Select>\n <Text size=\"sm\" tone=\"muted\">\n {translate('cms.list.bulk.set.to')}\n </Text>\n <ScalarFieldValueEditor\n key={field}\n option={option}\n value={value}\n ariaLabel={translate('cms.list.bulk.set.valueAria')}\n testId=\"bulk-set-value\"\n onChange={setValue}\n />\n <Spacer />\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy}\n data-testid=\"bulk-set-apply\"\n onClick={() => onApply({ field, value })}\n >\n <Check /> {translate('cms.list.bulk.set.apply')}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" disabled={busy} data-testid=\"bulk-set-cancel\" onClick={onCancel}>\n {translate('common.cancel')}\n </Button>\n </Row>\n )\n}\n\n/**\n * Per-item bulk results (EC-169): the completion summary plus every failure,\n * named and with its reason — a partial failure is enumerated, never silent.\n */\nexport function BulkReportPanel({\n report,\n onDismiss,\n}: {\n report: BulkReport\n onDismiss: () => void\n}) {\n const { succeeded, failed } = bulkSummary(report)\n const failures = report.results.filter((result) => !result.ok)\n const actionLabel =\n report.action === 'set-field' && report.setField\n ? translate('cms.list.bulk.report.verb.setField', { field: report.setField.field })\n : translate(`cms.list.bulk.report.verb.${report.action}`)\n\n return (\n <Stack gap=\"1\" className=\"shrink-0 border-b border-border px-4 py-2 sm:px-6\" data-testid=\"bulk-report\">\n <Row gap=\"2\">\n <Text size=\"sm\" weight=\"medium\" data-testid=\"bulk-report-summary\">\n {translate('cms.list.bulk.report.summary', { action: actionLabel, succeeded })}\n {failed > 0 ? translate('cms.list.bulk.report.failedSuffix', { count: failed }) : ''}\n </Text>\n {failed > 0 ? (\n <Badge variant=\"error\">{translate('cms.list.bulk.report.failedBadge', { count: failed })}</Badge>\n ) : (\n <Badge variant=\"success\">{translate('cms.list.bulk.report.done')}</Badge>\n )}\n <Spacer />\n <Button variant=\"ghost\" size=\"sm\" data-testid=\"bulk-report-dismiss\" onClick={onDismiss}>\n {translate('common.dismiss')}\n </Button>\n </Row>\n {failures.map((failure) => (\n <Row gap=\"2\" key={failure.ref.id} data-testid={`bulk-failure-${failure.ref.id}`}>\n <Text size=\"xs\" className=\"text-destructive\">\n {failure.title}\n </Text>\n <Code tone=\"muted\">{failure.ref.id}</Code>\n <Text size=\"xs\" tone=\"muted\">\n {failure.reason}\n </Text>\n </Row>\n ))}\n </Stack>\n )\n}\n"]}
@@ -176,8 +176,25 @@ export function LoadedCollectionTable({ projectId, toolbarExtra, }) {
176
176
  setPendingBulk({ action, targets: [{ collection: collectionId, id: doc.id }] });
177
177
  }
178
178
  async function handleBulk(action, acted, setField) {
179
- if (!source.bulk)
179
+ // Defensive: with the capability gates below (`source.bulk` presence gates
180
+ // the bar, per-action capabilities gate its buttons) this is unreachable —
181
+ // but a confirmed action must NEVER silently no-op (EC-433: the assets
182
+ // rail's bulk delete used to die exactly here), so a missing runner still
183
+ // reports one honest failure per item.
184
+ if (!source.bulk) {
185
+ setBulkReport({
186
+ action,
187
+ ...(setField ? { setField } : {}),
188
+ results: acted.map((id) => ({
189
+ ref: { collection: collectionId, id },
190
+ title: source.titleOf({ collection: collectionId, id }),
191
+ ok: false,
192
+ reason: 'Bulk actions are not available in this view.',
193
+ error: { code: 'unknown', message: 'Bulk actions are not available in this view.' },
194
+ })),
195
+ });
180
196
  return;
197
+ }
181
198
  setBulkBusy(true);
182
199
  try {
183
200
  const report = await source.bulk([...acted], action, setField);
@@ -204,7 +221,7 @@ export function LoadedCollectionTable({ projectId, toolbarExtra, }) {
204
221
  a.click();
205
222
  URL.revokeObjectURL(url);
206
223
  }
207
- return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsx("div", { className: "shrink-0 border-b border-border px-4 py-3 sm:px-6", children: _jsxs(Row, { gap: "2", wrap: true, children: [_jsx(ViewTabs, {}), _jsx(FilterControl, { collection: collection }), _jsx(Separator, { orientation: "vertical", className: "h-5 self-center" }), _jsx(Text, { as: "span", size: "xs", tone: "muted", className: "whitespace-nowrap tabular-nums", "data-testid": "collection-count", children: countLabel }), _jsx(Spacer, {}), source.capabilities.locales ? _jsx(LocaleSwitcher, {}) : null, _jsx(DisplayMenu, { collection: collection, hierarchical: hierarchical, treeMode: treeMode, onToggleTree: setTreeMode }), canCreate ? (_jsxs(Button, { size: "sm", onClick: handleNew, "data-testid": "new-document", children: [_jsx(Plus, {}), " ", isPageCollection ? translate('cms.list.newPage') : translate('cms.list.new')] })) : null, source.capabilities.importExport ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", size: "icon-sm", "aria-label": translate('cms.list.moreActions'), "data-testid": "collection-actions", children: _jsx(MoreHorizontal, {}) }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsxs(DropdownMenuItem, { onClick: () => setImportOpen(true), "data-testid": "action-import", children: [_jsx(Upload, {}), " ", translate('cms.list.import')] }), _jsxs(DropdownMenuItem, { onClick: exportJson, disabled: docs.length === 0, "data-testid": "action-export", children: [_jsx(Download, {}), " ", translate('cms.list.export')] })] })] })) : null, toolbarExtra] }) }), _jsx(BulkBar, { collection: collection, count: selectedIds.length, busy: bulkBusy, onAction: raiseBulk, onSetField: (setField) => void handleBulk('set-field', [...selectedIds], setField), onClear: () => setSelection(clearSelection()) }), bulkReport ? (_jsx(BulkReportPanel, { report: bulkReport, onDismiss: () => setBulkReport(null) })) : null, pendingBulk !== null ? (_jsx(ReferenceConfirmDialog, { projectId: projectId, action: pendingBulk.action, targets: pendingBulk.targets, open: true, busy: bulkBusy, onOpenChange: (open) => {
224
+ return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsx("div", { className: "shrink-0 border-b border-border px-4 py-3 sm:px-6", children: _jsxs(Row, { gap: "2", wrap: true, children: [_jsx(ViewTabs, {}), _jsx(FilterControl, { collection: collection }), _jsx(Separator, { orientation: "vertical", className: "h-5 self-center" }), _jsx(Text, { as: "span", size: "xs", tone: "muted", className: "whitespace-nowrap tabular-nums", "data-testid": "collection-count", children: countLabel }), _jsx(Spacer, {}), source.capabilities.locales ? _jsx(LocaleSwitcher, {}) : null, _jsx(DisplayMenu, { collection: collection, hierarchical: hierarchical, treeMode: treeMode, onToggleTree: setTreeMode }), canCreate ? (_jsxs(Button, { size: "sm", onClick: handleNew, "data-testid": "new-document", children: [_jsx(Plus, {}), " ", isPageCollection ? translate('cms.list.newPage') : translate('cms.list.new')] })) : null, source.capabilities.importExport ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", size: "icon-sm", "aria-label": translate('cms.list.moreActions'), "data-testid": "collection-actions", children: _jsx(MoreHorizontal, {}) }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsxs(DropdownMenuItem, { onClick: () => setImportOpen(true), "data-testid": "action-import", children: [_jsx(Upload, {}), " ", translate('cms.list.import')] }), _jsxs(DropdownMenuItem, { onClick: exportJson, disabled: docs.length === 0, "data-testid": "action-export", children: [_jsx(Download, {}), " ", translate('cms.list.export')] })] })] })) : null, toolbarExtra] }) }), source.bulk ? (_jsx(BulkBar, { collection: collection, capabilities: source.capabilities, count: selectedIds.length, busy: bulkBusy, onAction: raiseBulk, onSetField: (setField) => void handleBulk('set-field', [...selectedIds], setField), onClear: () => setSelection(clearSelection()) })) : null, bulkReport ? (_jsx(BulkReportPanel, { report: bulkReport, onDismiss: () => setBulkReport(null) })) : null, pendingBulk !== null ? (_jsx(ReferenceConfirmDialog, { projectId: projectId, action: pendingBulk.action, targets: pendingBulk.targets, open: true, busy: bulkBusy, onOpenChange: (open) => {
208
225
  if (!open)
209
226
  setPendingBulk(null);
210
227
  }, onConfirm: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"collection-table.js","sourceRoot":"","sources":["../../../src/components/cms/collection-table.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Link, STUDIO_PROJECT_ROUTE, studioPath, useNavigate } from '@elytracms/studio/router'\nimport {\n ArrowDown,\n ArrowUp,\n CornerDownRight,\n Download,\n Eye,\n EyeOff,\n ExternalLink,\n MoreHorizontal,\n Pencil,\n Plus,\n Trash2,\n Upload,\n} from 'lucide-react'\nimport { useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { CmsDocument, CollectionDef, DocumentUrl, FieldDef, Locale, LocaleConfig } from '@elytracms/core/cms-core'\nimport {\n orderHierarchically,\n resolveDocumentForLocale,\n resolveDocumentTitle,\n validateCollectionShape,\n} from '@elytracms/core/cms-core'\nimport {\n Button,\n Code,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n Row,\n Separator,\n Spacer,\n Stack,\n Text,\n} from '@elytracms/studio/ui'\nimport { cn } from '@elytracms/studio/lib/utils'\nimport { localizedLabel, translate } from '@elytracms/studio/lib/i18n'\nimport { LocaleSwitcher, resolveDisplayedValue } from '@elytracms/studio/lib/locale'\nimport {\n EMPTY_SELECTION,\n STATE_FIELD,\n applyViewState,\n clearSelection,\n primaryColumn,\n selectAll,\n toggleRow,\n visibleColumns,\n visibleSelection,\n} from '@elytracms/studio/lib/cms-views'\nimport type { SelectionState, ViewSort } from '@elytracms/studio/lib/cms-views'\nimport { cellEditKind, cellKey } from './cell-edit'\nimport { FallbackChip } from './cell'\nimport { EditableCell } from './editable-cell'\nimport { useCellEdit } from './use-cell-edit'\nimport { ImportDialog } from './import-export'\nimport { AssetThumb, useAssetRecord } from '../assets/asset-thumb'\nimport { fieldLabel } from './cms-labels'\nimport { cmsIssueLabel } from '@elytracms/studio/lib/persona/labels'\nimport { TriangleAlert } from 'lucide-react'\nimport type { BulkAction, BulkReport, BulkSetField } from './bulk-actions'\nimport { BulkBar, BulkReportPanel } from './bulk-bar'\nimport { rowActionsFor } from './row-actions'\nimport type { RowAction } from './row-actions'\nimport {\n CHECKBOX_COLUMN_WIDTH_REM,\n PRIMARY_COLUMN_WIDTH_REM,\n ROW_ACTIONS_COLUMN_WIDTH_REM,\n STATE_COLUMN_WIDTH_REM,\n URL_COLUMN_WIDTH_REM,\n columnWidthRem,\n} from './column-width'\nimport { ReferenceConfirmDialog } from './reference-confirm'\nimport { FilterControl } from './filter-builder'\nimport { DisplayMenu, ViewTabs } from './view-bar'\nimport { DocStateBadge } from './doc-state'\nimport { useSetBreadcrumb } from '../breadcrumb-context'\nimport { useCmsCollectionViewSource } from '../collection-view/cms-collection-view-source'\nimport { CollectionViewProvider, useCollectionView } from '../collection-view/collection-view-context'\n\nexport function CollectionTable({ projectId, collectionId }: { projectId: string; collectionId: string }) {\n // AD-19: render over the portable CollectionViewSource, not `useCms()` directly,\n // so the SAME list surface serves the users rail (EC-240), redirects (EC-303), …\n const source = useCmsCollectionViewSource(collectionId)\n\n if (!source) {\n return (\n <div className=\"grid h-full place-items-center p-8\">\n <Text tone=\"muted\">\n Unknown collection <Code tone=\"muted\">{collectionId}</Code>.\n </Text>\n </div>\n )\n }\n\n // Keyed per collection so selection/report state never leaks across collections.\n return (\n <CollectionViewProvider source={source}>\n <LoadedCollectionTable key={collectionId} projectId={projectId} />\n </CollectionViewProvider>\n )\n}\n\n/**\n * The portable list surface (AD-19). Renders entirely over the ambient\n * {@link useCollectionView} source — no `useCms`, no `CmsProvider` required — so\n * any rail (the users rail, redirects, …) reuses it by wrapping it in a\n * {@link CollectionViewProvider} over its own source. `CollectionTable` is just\n * the CMS entry point that builds a CMS source and mounts this.\n */\nexport function LoadedCollectionTable({\n projectId,\n toolbarExtra,\n}: {\n projectId: string\n /**\n * A rail-owned action rendered at the tail of the header toolbar (EC-319) —\n * e.g. the assets rail's Upload button + grid/list toggle. Absent for every\n * other rail today (users, redirects, CMS), so their toolbar is unchanged.\n */\n toolbarExtra?: ReactNode\n}) {\n const source = useCollectionView()\n const collection = source.schema\n const navigate = useNavigate()\n const collectionId = source.collectionId\n // EC-214: the collection is the active record — the global header breadcrumb\n // names it, replacing the per-view title heading.\n useSetBreadcrumb([{ label: localizedLabel(collection.form?.label, collectionId) }])\n const [importOpen, setImportOpen] = useState(false)\n const [selection, setSelection] = useState<SelectionState>(EMPTY_SELECTION)\n const [bulkBusy, setBulkBusy] = useState(false)\n const [bulkReport, setBulkReport] = useState<BulkReport | null>(null)\n // EC-173: bulk unpublish/delete go through the reference-aware confirmation\n // with a snapshot of the selection taken when the action was raised.\n const [pendingBulk, setPendingBulk] = useState<{\n action: 'unpublish' | 'delete'\n targets: { collection: string; id: string }[]\n } | null>(null)\n\n // The working view state (EC-169): filters + sort + columns, possibly dirty\n // against the active saved view. The table renders exactly this state.\n const viewState = source.viewState()\n // EC-213: the title/link column is the first visible column; the rest follow\n // in the view's column order. No separate primary-column selector.\n const primary = primaryColumn(collection, viewState)\n const columns = visibleColumns(collection, viewState).filter((name) => name !== primary)\n const primaryFieldDef = collection.fields.find((f) => f.name === primary)\n\n const docs = source.documents()\n\n // EC-274/EC-284: collection-shape drift (a singleton with > 1 document; later\n // duplicate/unknown/unfilled aliases). When the data has drifted from the lens's\n // expected shape the studio shows this list instead of skipping — surfacing the\n // conflicts here as a \"for review\" banner so an editor resolves them without a\n // developer (keep/delete the outliers), after which the lens applies again.\n const shapeIssues = useMemo(() => validateCollectionShape(collection, docs), [collection, docs])\n\n // EC-216 + EC-205 (\"live = published\"): each routable document's LIVE URL,\n // derived from the PUBLISHED pool (never draft rows), memoised inside the\n // source. `null` when the collection is not routable → the column is hidden.\n const urlByDocId = source.publishing?.liveUrls?.() ?? null\n\n const visibleDocs = useMemo(\n // EC-224: the `$state` filter/sort sources published-ness from the version\n // POINTER (`source.publishing.isPublished`), not a flat `state` field.\n () =>\n applyViewState(collection, docs, source.localeConfig, viewState, (doc) =>\n source.publishing?.isPublished({ collection: doc.collection, id: doc.id }) ?? false,\n ).docs,\n [collection, docs, source.localeConfig, viewState, source.publishing],\n )\n\n // EC-218: a collection with a `parent` self-relation can render as a nested\n // tree (parents above their children, indented). Tree mode reorders the\n // already-filtered rows depth-first — filters/sort still order siblings.\n const hierarchical = source.capabilities.hierarchy\n const [treeMode, setTreeMode] = useState(hierarchical)\n const treeRows = useMemo(\n () => (hierarchical && treeMode ? orderHierarchically(visibleDocs) : null),\n [hierarchical, treeMode, visibleDocs],\n )\n const orderedDocs = treeRows ? treeRows.map((row) => row.doc) : visibleDocs\n const depthById = useMemo(\n () => (treeRows ? new Map(treeRows.map((row) => [row.doc.id, row.depth])) : undefined),\n [treeRows],\n )\n\n // EC-246a header derivations. The count reads with the collection's own noun\n // (pluralized via the config labels), not a bare number or the generic kind.\n const pluralLabel = localizedLabel(collection.form?.label, `${collectionId}s`)\n const singularLabel = localizedLabel(collection.form?.labelSingular, collectionId)\n const countLabel =\n visibleDocs.length === docs.length\n ? translate('cms.list.count', {\n count: docs.length,\n noun: docs.length === 1 ? singularLabel : pluralLabel,\n })\n : translate('cms.list.countFiltered', {\n visible: visibleDocs.length,\n total: docs.length,\n noun: pluralLabel,\n })\n\n // EC-246d: New creates an empty draft and opens its editor directly — no\n // interstitial modal, for pages or any other collection. Id is auto-generated;\n // the slug/title (and, for pages, the parent) are typed in the form, and a\n // missing/duplicate slug surfaces as a Publish-gating issue, never blocks the\n // draft. Routes are config-sourced (EC-207), so nothing else is written here.\n const isPageCollection = collectionId === 'page'\n // Creation is a capability (a credential rail like users mints identities via\n // sign-up, not here), and the detail route is rail-owned (never the CMS route).\n const canCreate = source.capabilities.create && source.detailPath !== undefined\n const handleNew = () => {\n const ref = source.create()\n const splat = source.detailPath?.(ref.id)\n if (splat === undefined) return\n navigate({ to: STUDIO_PROJECT_ROUTE, params: { projectId, _splat: splat } })\n }\n const visibleIds = orderedDocs.map((doc) => doc.id)\n // Selection is always read against the current view — rows the filters hid\n // are never silently included in a bulk action.\n const selectedIds = visibleSelection(selection, visibleIds)\n // EC-316: the right-edge row menu is a capability-gated column — a rail with\n // no detail surface AND no publish/remove capability offers nothing (users\n // rail today has remove, so this is rarely empty; kept honest for AD-19).\n const hasRowActions = source.detailPath !== undefined || source.capabilities.publish || source.capabilities.remove\n\n function toggleSort(field: string) {\n source.setViewState((prev) => {\n const sort: ViewSort | null =\n prev.sort?.field !== field\n ? { field, dir: 'asc' }\n : prev.sort.dir === 'asc'\n ? { field, dir: 'desc' }\n : null\n return { ...prev, sort }\n })\n }\n\n function raiseBulk(action: BulkAction) {\n if (action === 'publish') {\n void handleBulk(action, [...selectedIds])\n return\n }\n // Set-field is composed + raised through the bulk bar's own panel\n // (onSetField), never this state-action path.\n if (action === 'set-field') return\n // Unpublish/delete first enumerate inbound references (EC-173): the\n // dialog shows the aggregate \"N documents, M references will break\".\n setPendingBulk({\n action,\n targets: selectedIds.map((id) => ({ collection: collectionId, id })),\n })\n }\n\n // EC-316: the row `⋮` menu dispatches through the SAME machinery as the\n // toolbar's bulk actions — one document is just a selection of one — so\n // there is exactly one write path for publish/unpublish/delete, never a\n // parallel one. `open` is the row menu's own affordance (the primary-column\n // link already offers it; this is the keyboard/menu-driven equivalent).\n function handleRowAction(action: RowAction, doc: CmsDocument) {\n if (action === 'open') {\n const splat = source.detailPath?.(doc.id)\n if (splat === undefined) return\n navigate({ to: STUDIO_PROJECT_ROUTE, params: { projectId, _splat: splat } })\n return\n }\n if (action === 'publish') {\n void handleBulk(action, [doc.id])\n return\n }\n // unpublish/delete: the same reference-aware confirmation the bulk bar\n // raises, scoped to this one document.\n setPendingBulk({ action, targets: [{ collection: collectionId, id: doc.id }] })\n }\n\n async function handleBulk(action: BulkAction, acted: readonly string[], setField?: BulkSetField) {\n if (!source.bulk) return\n setBulkBusy(true)\n try {\n const report = await source.bulk([...acted], action, setField)\n setBulkReport(report)\n // Succeeded items deselect; failed items stay selected for a retry.\n const actedSet = new Set(acted)\n const failed = new Set(report.results.filter((r) => !r.ok).map((r) => r.ref.id))\n setSelection((prev) => ({\n ids: prev.ids.filter((id) => !actedSet.has(id) || failed.has(id)),\n anchorId: null,\n }))\n } finally {\n setBulkBusy(false)\n }\n }\n\n function exportJson() {\n const data = JSON.stringify(source.documents(), null, 2)\n const blob = new Blob([data], { type: 'application/json' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = `${collectionId}.json`\n a.click()\n URL.revokeObjectURL(url)\n }\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n {/* Header (EC-246a redesign). One toolbar: identity + refine on the left,\n lens + actions on the right; a transient filter bar drops below only\n while refining. The header breadcrumb (EC-214) names the collection —\n no title here. Locale is a lens; column/layout config lives behind the\n far-right Display control; shared views are config-as-code (EC-246b). */}\n <div className=\"shrink-0 border-b border-border px-4 py-3 sm:px-6\">\n <Row gap=\"2\" wrap>\n {/* Left — which view (only when >1), then the transient refine. */}\n <ViewTabs />\n {/* Transient ad-hoc refine — a chip beside the view tabs, editor in a\n popover (EC-246b); the chip's ✕ clears it, so no separate Reset. */}\n <FilterControl collection={collection} />\n {/* The working-set count is the RESULT of the view + filter above, so it\n reads last, set off by a divider and sized like its neighbours. */}\n <Separator orientation=\"vertical\" className=\"h-5 self-center\" />\n <Text\n as=\"span\"\n size=\"xs\"\n tone=\"muted\"\n className=\"whitespace-nowrap tabular-nums\"\n data-testid=\"collection-count\"\n >\n {countLabel}\n </Text>\n\n <Spacer />\n\n {/* Right — the ambient locale lens (EC-176; hidden for single-locale AND\n for a non-localized rail like users), then display config + write actions. */}\n {source.capabilities.locales ? <LocaleSwitcher /> : null}\n <DisplayMenu\n collection={collection}\n hierarchical={hierarchical}\n treeMode={treeMode}\n onToggleTree={setTreeMode}\n />\n {canCreate ? (\n <Button size=\"sm\" onClick={handleNew} data-testid=\"new-document\">\n <Plus /> {isPageCollection ? translate('cms.list.newPage') : translate('cms.list.new')}\n </Button>\n ) : null}\n {/* EC-213: import/export fold into one action menu, off the header.\n AD-19: a capability — absent on credential rails (users), so identity\n records are never dumped to / loaded from raw JSON. */}\n {source.capabilities.importExport ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={translate('cms.list.moreActions')}\n data-testid=\"collection-actions\"\n >\n <MoreHorizontal />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => setImportOpen(true)} data-testid=\"action-import\">\n <Upload /> {translate('cms.list.import')}\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={exportJson}\n disabled={docs.length === 0}\n data-testid=\"action-export\"\n >\n <Download /> {translate('cms.list.export')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n {toolbarExtra}\n </Row>\n </div>\n\n {/* Bulk actions over the selection (EC-169) */}\n <BulkBar\n collection={collection}\n count={selectedIds.length}\n busy={bulkBusy}\n onAction={raiseBulk}\n onSetField={(setField) => void handleBulk('set-field', [...selectedIds], setField)}\n onClear={() => setSelection(clearSelection())}\n />\n {bulkReport ? (\n <BulkReportPanel report={bulkReport} onDismiss={() => setBulkReport(null)} />\n ) : null}\n\n {/* Reference-aware bulk unpublish/delete confirmation (EC-173). */}\n {pendingBulk !== null ? (\n <ReferenceConfirmDialog\n projectId={projectId}\n action={pendingBulk.action}\n targets={pendingBulk.targets}\n open\n busy={bulkBusy}\n onOpenChange={(open) => {\n if (!open) setPendingBulk(null)\n }}\n onConfirm={() => {\n const { action, targets } = pendingBulk\n setPendingBulk(null)\n void handleBulk(\n action,\n targets.map((target) => target.id),\n )\n }}\n />\n ) : null}\n\n {/* EC-274/EC-284: \"for review\" lane — the collection has drifted from its\n lens's expected shape; surface each conflict so an editor can resolve it. */}\n {shapeIssues.length > 0 ? (\n <div\n className=\"shrink-0 border-b border-warning/30 bg-warning/10 px-4 py-2 sm:px-6\"\n data-testid=\"shape-review-banner\"\n >\n <Stack gap=\"1\">\n {shapeIssues.map((issue, i) => (\n <Row key={`${issue.code}:${i}`} gap=\"2\" align=\"start\">\n <TriangleAlert className=\"mt-0.5 size-3.5 shrink-0 text-warning\" aria-hidden />\n <Stack gap=\"none\" className=\"min-w-0\">\n <Text size=\"xs\" weight=\"semibold\" tone=\"default\" title={issue.code}>\n {translate('cms.list.forReview')} · {cmsIssueLabel(issue.code)}\n </Text>\n <Text size=\"xs\" tone=\"muted\">\n {issue.message}\n </Text>\n </Stack>\n </Row>\n ))}\n </Stack>\n </div>\n ) : null}\n\n {/* Table */}\n <div className=\"min-h-0 flex-1 overflow-auto\">\n {docs.length === 0 ? (\n <div className=\"grid h-full place-items-center p-8\">\n <Stack gap=\"2\" align=\"center\" className=\"text-center\">\n <Text tone=\"muted\">{translate('cms.list.emptyNone', { noun: pluralLabel.toLowerCase() })}</Text>\n {canCreate ? (\n <Button size=\"sm\" onClick={handleNew}>\n <Plus />{' '}\n {isPageCollection\n ? translate('cms.list.newPage')\n : translate('cms.list.newNamed', {\n noun: localizedLabel(collection.form?.labelSingular, 'document'),\n })}\n </Button>\n ) : null}\n </Stack>\n </div>\n ) : visibleDocs.length === 0 ? (\n <div className=\"grid h-full place-items-center p-8\">\n <Text tone=\"muted\" data-testid=\"empty-filtered\">\n {translate('cms.list.emptyFiltered')}\n </Text>\n </div>\n ) : (\n <DocumentsGrid\n projectId={projectId}\n collection={collection}\n primary={primary}\n primaryFieldDef={primaryFieldDef}\n columns={columns}\n sortedDocs={orderedDocs}\n depthById={depthById}\n urlByDocId={urlByDocId}\n sort={viewState.sort}\n onSort={toggleSort}\n selectedIds={selectedIds}\n onToggleRow={(id, shift) =>\n setSelection((prev) => toggleRow(prev, visibleIds, id, shift))\n }\n onToggleAll={() =>\n setSelection(\n selectedIds.length === visibleIds.length && visibleIds.length > 0\n ? clearSelection()\n : selectAll(visibleIds),\n )\n }\n hasRowActions={hasRowActions}\n onRowAction={handleRowAction}\n />\n )}\n </div>\n\n {source.capabilities.importExport ? (\n <ImportDialog collectionId={collectionId} open={importOpen} onOpenChange={setImportOpen} />\n ) : null}\n </div>\n )\n}\n\n/**\n * The documents table with inline cell editing (EC-168). Cells edit in place\n * (text/number/boolean/select/date) or open pickers (relation/asset); each\n * commit is one operations command via the cell-edit controller, with\n * rollback + inline cell errors on rejection. Row checkboxes (EC-169) live in\n * their own column, so selection clicks never collide with cell editing.\n */\nfunction DocumentsGrid({\n projectId,\n collection,\n primary,\n primaryFieldDef,\n columns,\n sortedDocs,\n depthById,\n urlByDocId,\n sort,\n onSort,\n selectedIds,\n onToggleRow,\n onToggleAll,\n hasRowActions,\n onRowAction,\n}: {\n projectId: string\n collection: CollectionDef\n primary: string\n primaryFieldDef: FieldDef | undefined\n columns: string[]\n sortedDocs: CmsDocument[]\n /** EC-218: nesting depth per doc id when rendering the hierarchy (tree mode). */\n depthById?: Map<string, number>\n /** EC-216: each routable doc's derived URL; `null` hides the URL column. */\n urlByDocId?: Map<string, DocumentUrl> | null\n sort: ViewSort | null\n onSort: (field: string) => void\n selectedIds: readonly string[]\n onToggleRow: (id: string, shift: boolean) => void\n onToggleAll: () => void\n /** EC-316: whether the right-edge row `⋮` menu has anything to offer at all. */\n hasRowActions: boolean\n onRowAction: (action: RowAction, doc: CmsDocument) => void\n}) {\n const source = useCollectionView()\n const collectionId = collection.id\n // EC-346: a rail with no publish lifecycle (assets/redirects/users) has no\n // state to show — the column is omitted entirely (header + cells), never a\n // badge defaulted to \"draft\" via `?? false`. `source.publishing` presence IS\n // the gate (mirrors the capability contract: the group is present iff the\n // flag is set), narrowed once here so every render site below is type-safe.\n const publishing = source.publishing\n const fieldByName = (name: string) => collection.fields.find((f) => f.name === name)\n // Inline editing is a capability: a read-only rail yields no editable cells.\n const editableFields = source.capabilities.inlineEdit\n ? columns.filter((name) => {\n const field = fieldByName(name)\n return field ? cellEditKind(field, source.isFieldReadOnly(field)) !== 'none' : false\n })\n : []\n const cellEdit = useCellEdit({ collection, docs: sortedDocs, editableFields })\n const selected = new Set(selectedIds)\n const allSelected = sortedDocs.length > 0 && selectedIds.length === sortedDocs.length\n\n return (\n <div ref={cellEdit.containerRef}>\n {/* EC-316: `table-fixed` + an explicit `<colgroup>` fix every column's\n width from the SCHEMA alone, before any row renders. Under the\n browser's default `table-layout: auto` a cell's INTRINSIC content\n width feeds back into its column — so swapping a cell's rendered\n value for its inline editor (a wider `<input>`) reflowed the whole\n grid. Fixed layout makes a column's width immune to its cells'\n content; `columnWidthRem` only sets relative proportions, so the\n grid still scales naturally with the container (never with a cell). */}\n <table className=\"w-full table-fixed border-collapse text-sm\">\n <colgroup>\n <col style={{ width: `${CHECKBOX_COLUMN_WIDTH_REM}rem` }} />\n <col style={{ width: `${PRIMARY_COLUMN_WIDTH_REM}rem` }} />\n {columns.map((name) => (\n <col key={name} style={{ width: `${columnWidthRem(fieldByName(name))}rem` }} />\n ))}\n {publishing ? <col style={{ width: `${STATE_COLUMN_WIDTH_REM}rem` }} /> : null}\n {urlByDocId ? <col style={{ width: `${URL_COLUMN_WIDTH_REM}rem` }} /> : null}\n {hasRowActions ? <col style={{ width: `${ROW_ACTIONS_COLUMN_WIDTH_REM}rem` }} /> : null}\n </colgroup>\n <thead className=\"sticky top-0 z-10 bg-background\">\n <tr className=\"border-b border-border\">\n <th className=\"px-3 py-2 text-left\">\n <SelectionCheckbox\n checked={allSelected}\n indeterminate={selectedIds.length > 0 && !allSelected}\n label={translate('cms.list.selectAll')}\n testId=\"select-all\"\n onToggle={() => onToggleAll()}\n />\n </th>\n <HeaderCell\n field={primary}\n label={primaryFieldDef ? fieldLabel(primaryFieldDef) : translate('cms.list.column.title')}\n sort={sort}\n onSort={onSort}\n />\n {columns.map((name) => {\n const field = fieldByName(name)\n return field ? (\n <HeaderCell key={name} field={name} label={fieldLabel(field)} sort={sort} onSort={onSort} />\n ) : null\n })}\n {publishing ? (\n <HeaderCell field={STATE_FIELD} label={translate('cms.list.column.state')} sort={sort} onSort={onSort} />\n ) : null}\n {/* EC-216: derived URL — not a field, so not sortable. */}\n {urlByDocId ? (\n <th className=\"px-3 py-2 text-left text-xs font-semibold text-muted-foreground\">{translate('cms.list.column.url')}</th>\n ) : null}\n {hasRowActions ? (\n <th className=\"px-2 py-2 text-right\">\n <span className=\"sr-only\">{translate('cms.list.rowActionsColumnLabel')}</span>\n </th>\n ) : null}\n </tr>\n </thead>\n <tbody>\n {sortedDocs.map((doc) => (\n <tr\n key={doc.id}\n className={cn(\n 'group border-b border-border/60 hover:bg-muted/40',\n selected.has(doc.id) && 'bg-primary/5',\n )}\n >\n <td className=\"px-3 py-2 align-middle\">\n <SelectionCheckbox\n checked={selected.has(doc.id)}\n label={translate('cms.list.selectRow', { id: doc.id })}\n testId={`select-row-${doc.id}`}\n onToggle={(shift) => onToggleRow(doc.id, shift)}\n />\n </td>\n <td className=\"px-3 py-2 align-middle\">\n <PrimaryCell\n projectId={projectId}\n collection={collection}\n doc={doc}\n primary={primary}\n depth={depthById?.get(doc.id) ?? 0}\n locale={source.activeLocale}\n config={source.localeConfig}\n detailPath={source.detailPath}\n />\n </td>\n {columns.map((name) => {\n const field = fieldByName(name)\n const coord = { docId: doc.id, field: name }\n const key = cellKey(coord)\n return (\n <td key={name} className=\"px-3 py-2 align-middle\">\n {field ? (\n <EditableCell\n collection={collection}\n doc={doc}\n field={field}\n editing={cellEdit.activeKey === key}\n busy={cellEdit.busyKey === key}\n errorMessage={cellEdit.errorOf(key)}\n onStartEdit={() => cellEdit.start(coord)}\n onCancel={() => cellEdit.cancel(coord)}\n onCommit={(value, advance) => cellEdit.commit(coord, value, advance)}\n />\n ) : null}\n </td>\n )\n })}\n {publishing ? (\n <td className=\"px-3 py-2 align-middle\">\n <DocStateBadge published={publishing.isPublished({ collection: collectionId, id: doc.id })} />\n </td>\n ) : null}\n {urlByDocId ? (\n <td className=\"px-3 py-2 align-middle\">\n <UrlCell url={urlByDocId.get(doc.id)} />\n </td>\n ) : null}\n {hasRowActions ? (\n <td className=\"px-2 py-2 text-right align-middle\">\n <RowActionsMenu\n doc={doc}\n published={source.publishing?.isPublished({ collection: collectionId, id: doc.id }) ?? false}\n hasDetailPath={source.detailPath !== undefined}\n onAction={(action) => onRowAction(action, doc)}\n />\n </td>\n ) : null}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\n/**\n * The right-edge row `⋮` menu (EC-316): the SAME action vocabulary as the\n * toolbar's bulk actions (`rowActionsFor`), gated by the SAME capabilities —\n * so it degrades exactly like the rest of the list for a rail without\n * publish/remove (AD-19). Renders nothing when the gate leaves zero actions.\n */\nfunction RowActionsMenu({\n doc,\n published,\n hasDetailPath,\n onAction,\n}: {\n doc: CmsDocument\n published: boolean\n hasDetailPath: boolean\n onAction: (action: RowAction) => void\n}) {\n const source = useCollectionView()\n const actions = rowActionsFor({ capabilities: source.capabilities, hasDetailPath, published })\n if (actions.length === 0) return null\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={translate('cms.list.rowActionsLabel', { id: doc.id })}\n data-testid={`row-actions-${doc.id}`}\n >\n <MoreHorizontal />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {actions.map((action) => (\n <RowActionItem key={action} action={action} onSelect={() => onAction(action)} />\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\nfunction RowActionItem({ action, onSelect }: { action: RowAction; onSelect: () => void }) {\n switch (action) {\n case 'open':\n return (\n <DropdownMenuItem onClick={onSelect} data-testid=\"row-action-open\">\n <Pencil /> {translate('cms.list.rowAction.open')}\n </DropdownMenuItem>\n )\n case 'publish':\n return (\n <DropdownMenuItem onClick={onSelect} data-testid=\"row-action-publish\">\n <Eye /> {translate('cms.list.bulk.publish')}\n </DropdownMenuItem>\n )\n case 'unpublish':\n return (\n <DropdownMenuItem onClick={onSelect} data-testid=\"row-action-unpublish\">\n <EyeOff /> {translate('cms.list.bulk.unpublish')}\n </DropdownMenuItem>\n )\n case 'delete':\n return (\n <DropdownMenuItem\n variant=\"destructive\"\n onClick={onSelect}\n data-testid=\"row-action-delete\"\n >\n <Trash2 /> {translate('common.delete')}\n </DropdownMenuItem>\n )\n }\n}\n\n/**\n * A selection checkbox (row or select-all). Its own column and focus target —\n * it never participates in the cell-edit keyboard flow. Shift-click selects\n * the anchor→row range (the mousedown guard stops text selection).\n */\nfunction SelectionCheckbox({\n checked,\n indeterminate = false,\n label,\n testId,\n onToggle,\n}: {\n checked: boolean\n indeterminate?: boolean\n label: string\n testId: string\n onToggle: (shift: boolean) => void\n}) {\n return (\n <input\n ref={(el) => {\n if (el) el.indeterminate = indeterminate && !checked\n }}\n type=\"checkbox\"\n className=\"size-4 cursor-pointer accent-primary align-middle\"\n checked={checked}\n readOnly\n aria-label={label}\n data-testid={testId}\n onClick={(event) => onToggle(event.shiftKey)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault()\n onToggle(event.shiftKey)\n }\n }}\n onMouseDown={(event) => {\n if (event.shiftKey) event.preventDefault()\n }}\n />\n )\n}\n\nfunction HeaderCell({\n field,\n label,\n sort,\n onSort,\n}: {\n field: string\n label: string\n sort: ViewSort | null\n onSort: (field: string) => void\n}) {\n const active = sort?.field === field\n return (\n <th className=\"px-3 py-2 text-left text-xs font-semibold text-muted-foreground\">\n <button type=\"button\" onClick={() => onSort(field)} className=\"inline-flex items-center gap-1 hover:text-foreground\">\n {label}\n {active ? (\n sort!.dir === 'asc' ? (\n <ArrowUp className=\"size-3\" />\n ) : (\n <ArrowDown className=\"size-3\" />\n )\n ) : null}\n </button>\n </th>\n )\n}\n\n/**\n * The primary (title) column cell: the document link, resolved in the\n * ambient active locale with a visible fallback chip when the shown title is\n * untranslated (EC-176).\n */\nfunction PrimaryCell({\n projectId,\n collection,\n doc,\n primary,\n depth = 0,\n locale,\n config,\n detailPath,\n}: {\n projectId: string\n collection: CollectionDef\n doc: CmsDocument\n primary: string\n /** EC-218: nesting depth in the hierarchy (tree mode) — indents the title. */\n depth?: number\n locale: Locale\n config: LocaleConfig\n /** Rail-owned detail route splat (AD-19); absent ⇒ the rail has no detail surface. */\n detailPath?: (id: string) => string\n}) {\n // EC-242: the title cell renders the document identity (resolveDocumentTitle) —\n // a string `titleField` or a function pattern — over the fallback-resolved\n // values, NOT the raw `primary` column value. The untranslated-title chip applies\n // only to a field-backed title (a function pattern has no single source field).\n const title = resolveDocumentTitle(\n collection,\n resolveDocumentForLocale(collection, doc, locale, config),\n doc.id,\n )\n const fallback =\n typeof collection.titleField === 'function'\n ? null\n : resolveDisplayedValue(collection, doc, primary, locale, config).fallback\n const splat = detailPath?.(doc.id)\n return (\n <Row gap=\"2\" align=\"center\" className=\"min-w-0\" style={{ paddingLeft: depth * 20 }}>\n {depth > 0 ? (\n <CornerDownRight className=\"size-3.5 shrink-0 text-muted-foreground\" aria-hidden />\n ) : null}\n {/* 0.0.39: assets get a leading, fixed-size preview in the filename column —\n an image thumbnail (object-cover) for image assets, the file-type placeholder\n otherwise. Fixed box, so it never reflows the EC-316 fixed column widths. */}\n {collection.kind === 'asset' ? <AssetThumbCell assetId={doc.id} alt={title} /> : null}\n {splat !== undefined ? (\n <Link\n to={STUDIO_PROJECT_ROUTE}\n params={{ projectId, _splat: splat }}\n className=\"truncate font-medium text-foreground hover:text-primary hover:underline\"\n >\n {title}\n </Link>\n ) : (\n <Text as=\"span\" className=\"truncate font-medium text-foreground\">\n {title}\n </Text>\n )}\n <FallbackChip fallback={fallback} testId={`cell-fallback-${doc.id}-${primary}`} />\n </Row>\n )\n}\n\n/**\n * The leading asset preview in the filename column (0.0.39). Resolves the asset\n * record from the ambient library and renders {@link AssetThumb} — an image preview\n * for image assets, the file-type placeholder for the rest. Mounted only for\n * `kind:'asset'` collections (which are always under an `<AssetsProvider>`), so the\n * `useAssetRecord` hook is never called on a rail without a library.\n */\nfunction AssetThumbCell({ assetId, alt }: { assetId: string; alt: string }) {\n const record = useAssetRecord(assetId)\n return <AssetThumb record={record} alt={alt} className=\"size-8 shrink-0\" />\n}\n\n/**\n * The read-only URL column cell (EC-216): the document's LIVE (published) path,\n * linking to the absolute live URL when a `frontendUrl` is configured. Only\n * published documents have a `url` here (the URL is derived from the published\n * pool, EC-205), so an unpublished document — having no live page — shows a dash.\n * The URL is always derived, never stored.\n */\nfunction UrlCell({ url }: { url?: DocumentUrl }) {\n if (!url) {\n return (\n <Text size=\"xs\" tone=\"subtle\">\n —\n </Text>\n )\n }\n if (url.href) {\n return (\n <a\n href={url.href}\n target=\"_blank\"\n rel=\"noreferrer\"\n title={url.href}\n className=\"inline-flex max-w-[18rem] items-center gap-1 text-xs text-muted-foreground transition-colors hover:text-foreground\"\n >\n <span className=\"truncate\">{url.path}</span>\n <ExternalLink className=\"size-3 shrink-0\" aria-hidden />\n </a>\n )\n }\n return (\n <Text size=\"xs\" tone=\"muted\" className=\"max-w-[18rem] truncate\" title={url.path}>\n {url.path}\n </Text>\n )\n}\n\nexport type { FieldDef }\n"]}
1
+ {"version":3,"file":"collection-table.js","sourceRoot":"","sources":["../../../src/components/cms/collection-table.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Link, STUDIO_PROJECT_ROUTE, studioPath, useNavigate } from '@elytracms/studio/router'\nimport {\n ArrowDown,\n ArrowUp,\n CornerDownRight,\n Download,\n Eye,\n EyeOff,\n ExternalLink,\n MoreHorizontal,\n Pencil,\n Plus,\n Trash2,\n Upload,\n} from 'lucide-react'\nimport { useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { CmsDocument, CollectionDef, DocumentUrl, FieldDef, Locale, LocaleConfig } from '@elytracms/core/cms-core'\nimport {\n orderHierarchically,\n resolveDocumentForLocale,\n resolveDocumentTitle,\n validateCollectionShape,\n} from '@elytracms/core/cms-core'\nimport {\n Button,\n Code,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n Row,\n Separator,\n Spacer,\n Stack,\n Text,\n} from '@elytracms/studio/ui'\nimport { cn } from '@elytracms/studio/lib/utils'\nimport { localizedLabel, translate } from '@elytracms/studio/lib/i18n'\nimport { LocaleSwitcher, resolveDisplayedValue } from '@elytracms/studio/lib/locale'\nimport {\n EMPTY_SELECTION,\n STATE_FIELD,\n applyViewState,\n clearSelection,\n primaryColumn,\n selectAll,\n toggleRow,\n visibleColumns,\n visibleSelection,\n} from '@elytracms/studio/lib/cms-views'\nimport type { SelectionState, ViewSort } from '@elytracms/studio/lib/cms-views'\nimport { cellEditKind, cellKey } from './cell-edit'\nimport { FallbackChip } from './cell'\nimport { EditableCell } from './editable-cell'\nimport { useCellEdit } from './use-cell-edit'\nimport { ImportDialog } from './import-export'\nimport { AssetThumb, useAssetRecord } from '../assets/asset-thumb'\nimport { fieldLabel } from './cms-labels'\nimport { cmsIssueLabel } from '@elytracms/studio/lib/persona/labels'\nimport { TriangleAlert } from 'lucide-react'\nimport type { BulkAction, BulkReport, BulkSetField } from './bulk-actions'\nimport { BulkBar, BulkReportPanel } from './bulk-bar'\nimport { rowActionsFor } from './row-actions'\nimport type { RowAction } from './row-actions'\nimport {\n CHECKBOX_COLUMN_WIDTH_REM,\n PRIMARY_COLUMN_WIDTH_REM,\n ROW_ACTIONS_COLUMN_WIDTH_REM,\n STATE_COLUMN_WIDTH_REM,\n URL_COLUMN_WIDTH_REM,\n columnWidthRem,\n} from './column-width'\nimport { ReferenceConfirmDialog } from './reference-confirm'\nimport { FilterControl } from './filter-builder'\nimport { DisplayMenu, ViewTabs } from './view-bar'\nimport { DocStateBadge } from './doc-state'\nimport { useSetBreadcrumb } from '../breadcrumb-context'\nimport { useCmsCollectionViewSource } from '../collection-view/cms-collection-view-source'\nimport { CollectionViewProvider, useCollectionView } from '../collection-view/collection-view-context'\n\nexport function CollectionTable({ projectId, collectionId }: { projectId: string; collectionId: string }) {\n // AD-19: render over the portable CollectionViewSource, not `useCms()` directly,\n // so the SAME list surface serves the users rail (EC-240), redirects (EC-303), …\n const source = useCmsCollectionViewSource(collectionId)\n\n if (!source) {\n return (\n <div className=\"grid h-full place-items-center p-8\">\n <Text tone=\"muted\">\n Unknown collection <Code tone=\"muted\">{collectionId}</Code>.\n </Text>\n </div>\n )\n }\n\n // Keyed per collection so selection/report state never leaks across collections.\n return (\n <CollectionViewProvider source={source}>\n <LoadedCollectionTable key={collectionId} projectId={projectId} />\n </CollectionViewProvider>\n )\n}\n\n/**\n * The portable list surface (AD-19). Renders entirely over the ambient\n * {@link useCollectionView} source — no `useCms`, no `CmsProvider` required — so\n * any rail (the users rail, redirects, …) reuses it by wrapping it in a\n * {@link CollectionViewProvider} over its own source. `CollectionTable` is just\n * the CMS entry point that builds a CMS source and mounts this.\n */\nexport function LoadedCollectionTable({\n projectId,\n toolbarExtra,\n}: {\n projectId: string\n /**\n * A rail-owned action rendered at the tail of the header toolbar (EC-319) —\n * e.g. the assets rail's Upload button + grid/list toggle. Absent for every\n * other rail today (users, redirects, CMS), so their toolbar is unchanged.\n */\n toolbarExtra?: ReactNode\n}) {\n const source = useCollectionView()\n const collection = source.schema\n const navigate = useNavigate()\n const collectionId = source.collectionId\n // EC-214: the collection is the active record — the global header breadcrumb\n // names it, replacing the per-view title heading.\n useSetBreadcrumb([{ label: localizedLabel(collection.form?.label, collectionId) }])\n const [importOpen, setImportOpen] = useState(false)\n const [selection, setSelection] = useState<SelectionState>(EMPTY_SELECTION)\n const [bulkBusy, setBulkBusy] = useState(false)\n const [bulkReport, setBulkReport] = useState<BulkReport | null>(null)\n // EC-173: bulk unpublish/delete go through the reference-aware confirmation\n // with a snapshot of the selection taken when the action was raised.\n const [pendingBulk, setPendingBulk] = useState<{\n action: 'unpublish' | 'delete'\n targets: { collection: string; id: string }[]\n } | null>(null)\n\n // The working view state (EC-169): filters + sort + columns, possibly dirty\n // against the active saved view. The table renders exactly this state.\n const viewState = source.viewState()\n // EC-213: the title/link column is the first visible column; the rest follow\n // in the view's column order. No separate primary-column selector.\n const primary = primaryColumn(collection, viewState)\n const columns = visibleColumns(collection, viewState).filter((name) => name !== primary)\n const primaryFieldDef = collection.fields.find((f) => f.name === primary)\n\n const docs = source.documents()\n\n // EC-274/EC-284: collection-shape drift (a singleton with > 1 document; later\n // duplicate/unknown/unfilled aliases). When the data has drifted from the lens's\n // expected shape the studio shows this list instead of skipping — surfacing the\n // conflicts here as a \"for review\" banner so an editor resolves them without a\n // developer (keep/delete the outliers), after which the lens applies again.\n const shapeIssues = useMemo(() => validateCollectionShape(collection, docs), [collection, docs])\n\n // EC-216 + EC-205 (\"live = published\"): each routable document's LIVE URL,\n // derived from the PUBLISHED pool (never draft rows), memoised inside the\n // source. `null` when the collection is not routable → the column is hidden.\n const urlByDocId = source.publishing?.liveUrls?.() ?? null\n\n const visibleDocs = useMemo(\n // EC-224: the `$state` filter/sort sources published-ness from the version\n // POINTER (`source.publishing.isPublished`), not a flat `state` field.\n () =>\n applyViewState(collection, docs, source.localeConfig, viewState, (doc) =>\n source.publishing?.isPublished({ collection: doc.collection, id: doc.id }) ?? false,\n ).docs,\n [collection, docs, source.localeConfig, viewState, source.publishing],\n )\n\n // EC-218: a collection with a `parent` self-relation can render as a nested\n // tree (parents above their children, indented). Tree mode reorders the\n // already-filtered rows depth-first — filters/sort still order siblings.\n const hierarchical = source.capabilities.hierarchy\n const [treeMode, setTreeMode] = useState(hierarchical)\n const treeRows = useMemo(\n () => (hierarchical && treeMode ? orderHierarchically(visibleDocs) : null),\n [hierarchical, treeMode, visibleDocs],\n )\n const orderedDocs = treeRows ? treeRows.map((row) => row.doc) : visibleDocs\n const depthById = useMemo(\n () => (treeRows ? new Map(treeRows.map((row) => [row.doc.id, row.depth])) : undefined),\n [treeRows],\n )\n\n // EC-246a header derivations. The count reads with the collection's own noun\n // (pluralized via the config labels), not a bare number or the generic kind.\n const pluralLabel = localizedLabel(collection.form?.label, `${collectionId}s`)\n const singularLabel = localizedLabel(collection.form?.labelSingular, collectionId)\n const countLabel =\n visibleDocs.length === docs.length\n ? translate('cms.list.count', {\n count: docs.length,\n noun: docs.length === 1 ? singularLabel : pluralLabel,\n })\n : translate('cms.list.countFiltered', {\n visible: visibleDocs.length,\n total: docs.length,\n noun: pluralLabel,\n })\n\n // EC-246d: New creates an empty draft and opens its editor directly — no\n // interstitial modal, for pages or any other collection. Id is auto-generated;\n // the slug/title (and, for pages, the parent) are typed in the form, and a\n // missing/duplicate slug surfaces as a Publish-gating issue, never blocks the\n // draft. Routes are config-sourced (EC-207), so nothing else is written here.\n const isPageCollection = collectionId === 'page'\n // Creation is a capability (a credential rail like users mints identities via\n // sign-up, not here), and the detail route is rail-owned (never the CMS route).\n const canCreate = source.capabilities.create && source.detailPath !== undefined\n const handleNew = () => {\n const ref = source.create()\n const splat = source.detailPath?.(ref.id)\n if (splat === undefined) return\n navigate({ to: STUDIO_PROJECT_ROUTE, params: { projectId, _splat: splat } })\n }\n const visibleIds = orderedDocs.map((doc) => doc.id)\n // Selection is always read against the current view — rows the filters hid\n // are never silently included in a bulk action.\n const selectedIds = visibleSelection(selection, visibleIds)\n // EC-316: the right-edge row menu is a capability-gated column — a rail with\n // no detail surface AND no publish/remove capability offers nothing (users\n // rail today has remove, so this is rarely empty; kept honest for AD-19).\n const hasRowActions = source.detailPath !== undefined || source.capabilities.publish || source.capabilities.remove\n\n function toggleSort(field: string) {\n source.setViewState((prev) => {\n const sort: ViewSort | null =\n prev.sort?.field !== field\n ? { field, dir: 'asc' }\n : prev.sort.dir === 'asc'\n ? { field, dir: 'desc' }\n : null\n return { ...prev, sort }\n })\n }\n\n function raiseBulk(action: BulkAction) {\n if (action === 'publish') {\n void handleBulk(action, [...selectedIds])\n return\n }\n // Set-field is composed + raised through the bulk bar's own panel\n // (onSetField), never this state-action path.\n if (action === 'set-field') return\n // Unpublish/delete first enumerate inbound references (EC-173): the\n // dialog shows the aggregate \"N documents, M references will break\".\n setPendingBulk({\n action,\n targets: selectedIds.map((id) => ({ collection: collectionId, id })),\n })\n }\n\n // EC-316: the row `⋮` menu dispatches through the SAME machinery as the\n // toolbar's bulk actions — one document is just a selection of one — so\n // there is exactly one write path for publish/unpublish/delete, never a\n // parallel one. `open` is the row menu's own affordance (the primary-column\n // link already offers it; this is the keyboard/menu-driven equivalent).\n function handleRowAction(action: RowAction, doc: CmsDocument) {\n if (action === 'open') {\n const splat = source.detailPath?.(doc.id)\n if (splat === undefined) return\n navigate({ to: STUDIO_PROJECT_ROUTE, params: { projectId, _splat: splat } })\n return\n }\n if (action === 'publish') {\n void handleBulk(action, [doc.id])\n return\n }\n // unpublish/delete: the same reference-aware confirmation the bulk bar\n // raises, scoped to this one document.\n setPendingBulk({ action, targets: [{ collection: collectionId, id: doc.id }] })\n }\n\n async function handleBulk(action: BulkAction, acted: readonly string[], setField?: BulkSetField) {\n // Defensive: with the capability gates below (`source.bulk` presence gates\n // the bar, per-action capabilities gate its buttons) this is unreachable —\n // but a confirmed action must NEVER silently no-op (EC-433: the assets\n // rail's bulk delete used to die exactly here), so a missing runner still\n // reports one honest failure per item.\n if (!source.bulk) {\n setBulkReport({\n action,\n ...(setField ? { setField } : {}),\n results: acted.map((id) => ({\n ref: { collection: collectionId, id },\n title: source.titleOf({ collection: collectionId, id }),\n ok: false,\n reason: 'Bulk actions are not available in this view.',\n error: { code: 'unknown', message: 'Bulk actions are not available in this view.' },\n })),\n })\n return\n }\n setBulkBusy(true)\n try {\n const report = await source.bulk([...acted], action, setField)\n setBulkReport(report)\n // Succeeded items deselect; failed items stay selected for a retry.\n const actedSet = new Set(acted)\n const failed = new Set(report.results.filter((r) => !r.ok).map((r) => r.ref.id))\n setSelection((prev) => ({\n ids: prev.ids.filter((id) => !actedSet.has(id) || failed.has(id)),\n anchorId: null,\n }))\n } finally {\n setBulkBusy(false)\n }\n }\n\n function exportJson() {\n const data = JSON.stringify(source.documents(), null, 2)\n const blob = new Blob([data], { type: 'application/json' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = `${collectionId}.json`\n a.click()\n URL.revokeObjectURL(url)\n }\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n {/* Header (EC-246a redesign). One toolbar: identity + refine on the left,\n lens + actions on the right; a transient filter bar drops below only\n while refining. The header breadcrumb (EC-214) names the collection —\n no title here. Locale is a lens; column/layout config lives behind the\n far-right Display control; shared views are config-as-code (EC-246b). */}\n <div className=\"shrink-0 border-b border-border px-4 py-3 sm:px-6\">\n <Row gap=\"2\" wrap>\n {/* Left — which view (only when >1), then the transient refine. */}\n <ViewTabs />\n {/* Transient ad-hoc refine — a chip beside the view tabs, editor in a\n popover (EC-246b); the chip's ✕ clears it, so no separate Reset. */}\n <FilterControl collection={collection} />\n {/* The working-set count is the RESULT of the view + filter above, so it\n reads last, set off by a divider and sized like its neighbours. */}\n <Separator orientation=\"vertical\" className=\"h-5 self-center\" />\n <Text\n as=\"span\"\n size=\"xs\"\n tone=\"muted\"\n className=\"whitespace-nowrap tabular-nums\"\n data-testid=\"collection-count\"\n >\n {countLabel}\n </Text>\n\n <Spacer />\n\n {/* Right — the ambient locale lens (EC-176; hidden for single-locale AND\n for a non-localized rail like users), then display config + write actions. */}\n {source.capabilities.locales ? <LocaleSwitcher /> : null}\n <DisplayMenu\n collection={collection}\n hierarchical={hierarchical}\n treeMode={treeMode}\n onToggleTree={setTreeMode}\n />\n {canCreate ? (\n <Button size=\"sm\" onClick={handleNew} data-testid=\"new-document\">\n <Plus /> {isPageCollection ? translate('cms.list.newPage') : translate('cms.list.new')}\n </Button>\n ) : null}\n {/* EC-213: import/export fold into one action menu, off the header.\n AD-19: a capability — absent on credential rails (users), so identity\n records are never dumped to / loaded from raw JSON. */}\n {source.capabilities.importExport ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={translate('cms.list.moreActions')}\n data-testid=\"collection-actions\"\n >\n <MoreHorizontal />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => setImportOpen(true)} data-testid=\"action-import\">\n <Upload /> {translate('cms.list.import')}\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={exportJson}\n disabled={docs.length === 0}\n data-testid=\"action-export\"\n >\n <Download /> {translate('cms.list.export')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n {toolbarExtra}\n </Row>\n </div>\n\n {/* Bulk actions over the selection (EC-169). Mounted only when the source\n actually carries a bulk runner (present iff `capabilities.bulk`,\n EC-433) and each action button is capability-gated inside — a bar\n whose confirmed actions can't dispatch is never offered. */}\n {source.bulk ? (\n <BulkBar\n collection={collection}\n capabilities={source.capabilities}\n count={selectedIds.length}\n busy={bulkBusy}\n onAction={raiseBulk}\n onSetField={(setField) => void handleBulk('set-field', [...selectedIds], setField)}\n onClear={() => setSelection(clearSelection())}\n />\n ) : null}\n {bulkReport ? (\n <BulkReportPanel report={bulkReport} onDismiss={() => setBulkReport(null)} />\n ) : null}\n\n {/* Reference-aware bulk unpublish/delete confirmation (EC-173). */}\n {pendingBulk !== null ? (\n <ReferenceConfirmDialog\n projectId={projectId}\n action={pendingBulk.action}\n targets={pendingBulk.targets}\n open\n busy={bulkBusy}\n onOpenChange={(open) => {\n if (!open) setPendingBulk(null)\n }}\n onConfirm={() => {\n const { action, targets } = pendingBulk\n setPendingBulk(null)\n void handleBulk(\n action,\n targets.map((target) => target.id),\n )\n }}\n />\n ) : null}\n\n {/* EC-274/EC-284: \"for review\" lane — the collection has drifted from its\n lens's expected shape; surface each conflict so an editor can resolve it. */}\n {shapeIssues.length > 0 ? (\n <div\n className=\"shrink-0 border-b border-warning/30 bg-warning/10 px-4 py-2 sm:px-6\"\n data-testid=\"shape-review-banner\"\n >\n <Stack gap=\"1\">\n {shapeIssues.map((issue, i) => (\n <Row key={`${issue.code}:${i}`} gap=\"2\" align=\"start\">\n <TriangleAlert className=\"mt-0.5 size-3.5 shrink-0 text-warning\" aria-hidden />\n <Stack gap=\"none\" className=\"min-w-0\">\n <Text size=\"xs\" weight=\"semibold\" tone=\"default\" title={issue.code}>\n {translate('cms.list.forReview')} · {cmsIssueLabel(issue.code)}\n </Text>\n <Text size=\"xs\" tone=\"muted\">\n {issue.message}\n </Text>\n </Stack>\n </Row>\n ))}\n </Stack>\n </div>\n ) : null}\n\n {/* Table */}\n <div className=\"min-h-0 flex-1 overflow-auto\">\n {docs.length === 0 ? (\n <div className=\"grid h-full place-items-center p-8\">\n <Stack gap=\"2\" align=\"center\" className=\"text-center\">\n <Text tone=\"muted\">{translate('cms.list.emptyNone', { noun: pluralLabel.toLowerCase() })}</Text>\n {canCreate ? (\n <Button size=\"sm\" onClick={handleNew}>\n <Plus />{' '}\n {isPageCollection\n ? translate('cms.list.newPage')\n : translate('cms.list.newNamed', {\n noun: localizedLabel(collection.form?.labelSingular, 'document'),\n })}\n </Button>\n ) : null}\n </Stack>\n </div>\n ) : visibleDocs.length === 0 ? (\n <div className=\"grid h-full place-items-center p-8\">\n <Text tone=\"muted\" data-testid=\"empty-filtered\">\n {translate('cms.list.emptyFiltered')}\n </Text>\n </div>\n ) : (\n <DocumentsGrid\n projectId={projectId}\n collection={collection}\n primary={primary}\n primaryFieldDef={primaryFieldDef}\n columns={columns}\n sortedDocs={orderedDocs}\n depthById={depthById}\n urlByDocId={urlByDocId}\n sort={viewState.sort}\n onSort={toggleSort}\n selectedIds={selectedIds}\n onToggleRow={(id, shift) =>\n setSelection((prev) => toggleRow(prev, visibleIds, id, shift))\n }\n onToggleAll={() =>\n setSelection(\n selectedIds.length === visibleIds.length && visibleIds.length > 0\n ? clearSelection()\n : selectAll(visibleIds),\n )\n }\n hasRowActions={hasRowActions}\n onRowAction={handleRowAction}\n />\n )}\n </div>\n\n {source.capabilities.importExport ? (\n <ImportDialog collectionId={collectionId} open={importOpen} onOpenChange={setImportOpen} />\n ) : null}\n </div>\n )\n}\n\n/**\n * The documents table with inline cell editing (EC-168). Cells edit in place\n * (text/number/boolean/select/date) or open pickers (relation/asset); each\n * commit is one operations command via the cell-edit controller, with\n * rollback + inline cell errors on rejection. Row checkboxes (EC-169) live in\n * their own column, so selection clicks never collide with cell editing.\n */\nfunction DocumentsGrid({\n projectId,\n collection,\n primary,\n primaryFieldDef,\n columns,\n sortedDocs,\n depthById,\n urlByDocId,\n sort,\n onSort,\n selectedIds,\n onToggleRow,\n onToggleAll,\n hasRowActions,\n onRowAction,\n}: {\n projectId: string\n collection: CollectionDef\n primary: string\n primaryFieldDef: FieldDef | undefined\n columns: string[]\n sortedDocs: CmsDocument[]\n /** EC-218: nesting depth per doc id when rendering the hierarchy (tree mode). */\n depthById?: Map<string, number>\n /** EC-216: each routable doc's derived URL; `null` hides the URL column. */\n urlByDocId?: Map<string, DocumentUrl> | null\n sort: ViewSort | null\n onSort: (field: string) => void\n selectedIds: readonly string[]\n onToggleRow: (id: string, shift: boolean) => void\n onToggleAll: () => void\n /** EC-316: whether the right-edge row `⋮` menu has anything to offer at all. */\n hasRowActions: boolean\n onRowAction: (action: RowAction, doc: CmsDocument) => void\n}) {\n const source = useCollectionView()\n const collectionId = collection.id\n // EC-346: a rail with no publish lifecycle (assets/redirects/users) has no\n // state to show — the column is omitted entirely (header + cells), never a\n // badge defaulted to \"draft\" via `?? false`. `source.publishing` presence IS\n // the gate (mirrors the capability contract: the group is present iff the\n // flag is set), narrowed once here so every render site below is type-safe.\n const publishing = source.publishing\n const fieldByName = (name: string) => collection.fields.find((f) => f.name === name)\n // Inline editing is a capability: a read-only rail yields no editable cells.\n const editableFields = source.capabilities.inlineEdit\n ? columns.filter((name) => {\n const field = fieldByName(name)\n return field ? cellEditKind(field, source.isFieldReadOnly(field)) !== 'none' : false\n })\n : []\n const cellEdit = useCellEdit({ collection, docs: sortedDocs, editableFields })\n const selected = new Set(selectedIds)\n const allSelected = sortedDocs.length > 0 && selectedIds.length === sortedDocs.length\n\n return (\n <div ref={cellEdit.containerRef}>\n {/* EC-316: `table-fixed` + an explicit `<colgroup>` fix every column's\n width from the SCHEMA alone, before any row renders. Under the\n browser's default `table-layout: auto` a cell's INTRINSIC content\n width feeds back into its column — so swapping a cell's rendered\n value for its inline editor (a wider `<input>`) reflowed the whole\n grid. Fixed layout makes a column's width immune to its cells'\n content; `columnWidthRem` only sets relative proportions, so the\n grid still scales naturally with the container (never with a cell). */}\n <table className=\"w-full table-fixed border-collapse text-sm\">\n <colgroup>\n <col style={{ width: `${CHECKBOX_COLUMN_WIDTH_REM}rem` }} />\n <col style={{ width: `${PRIMARY_COLUMN_WIDTH_REM}rem` }} />\n {columns.map((name) => (\n <col key={name} style={{ width: `${columnWidthRem(fieldByName(name))}rem` }} />\n ))}\n {publishing ? <col style={{ width: `${STATE_COLUMN_WIDTH_REM}rem` }} /> : null}\n {urlByDocId ? <col style={{ width: `${URL_COLUMN_WIDTH_REM}rem` }} /> : null}\n {hasRowActions ? <col style={{ width: `${ROW_ACTIONS_COLUMN_WIDTH_REM}rem` }} /> : null}\n </colgroup>\n <thead className=\"sticky top-0 z-10 bg-background\">\n <tr className=\"border-b border-border\">\n <th className=\"px-3 py-2 text-left\">\n <SelectionCheckbox\n checked={allSelected}\n indeterminate={selectedIds.length > 0 && !allSelected}\n label={translate('cms.list.selectAll')}\n testId=\"select-all\"\n onToggle={() => onToggleAll()}\n />\n </th>\n <HeaderCell\n field={primary}\n label={primaryFieldDef ? fieldLabel(primaryFieldDef) : translate('cms.list.column.title')}\n sort={sort}\n onSort={onSort}\n />\n {columns.map((name) => {\n const field = fieldByName(name)\n return field ? (\n <HeaderCell key={name} field={name} label={fieldLabel(field)} sort={sort} onSort={onSort} />\n ) : null\n })}\n {publishing ? (\n <HeaderCell field={STATE_FIELD} label={translate('cms.list.column.state')} sort={sort} onSort={onSort} />\n ) : null}\n {/* EC-216: derived URL — not a field, so not sortable. */}\n {urlByDocId ? (\n <th className=\"px-3 py-2 text-left text-xs font-semibold text-muted-foreground\">{translate('cms.list.column.url')}</th>\n ) : null}\n {hasRowActions ? (\n <th className=\"px-2 py-2 text-right\">\n <span className=\"sr-only\">{translate('cms.list.rowActionsColumnLabel')}</span>\n </th>\n ) : null}\n </tr>\n </thead>\n <tbody>\n {sortedDocs.map((doc) => (\n <tr\n key={doc.id}\n className={cn(\n 'group border-b border-border/60 hover:bg-muted/40',\n selected.has(doc.id) && 'bg-primary/5',\n )}\n >\n <td className=\"px-3 py-2 align-middle\">\n <SelectionCheckbox\n checked={selected.has(doc.id)}\n label={translate('cms.list.selectRow', { id: doc.id })}\n testId={`select-row-${doc.id}`}\n onToggle={(shift) => onToggleRow(doc.id, shift)}\n />\n </td>\n <td className=\"px-3 py-2 align-middle\">\n <PrimaryCell\n projectId={projectId}\n collection={collection}\n doc={doc}\n primary={primary}\n depth={depthById?.get(doc.id) ?? 0}\n locale={source.activeLocale}\n config={source.localeConfig}\n detailPath={source.detailPath}\n />\n </td>\n {columns.map((name) => {\n const field = fieldByName(name)\n const coord = { docId: doc.id, field: name }\n const key = cellKey(coord)\n return (\n <td key={name} className=\"px-3 py-2 align-middle\">\n {field ? (\n <EditableCell\n collection={collection}\n doc={doc}\n field={field}\n editing={cellEdit.activeKey === key}\n busy={cellEdit.busyKey === key}\n errorMessage={cellEdit.errorOf(key)}\n onStartEdit={() => cellEdit.start(coord)}\n onCancel={() => cellEdit.cancel(coord)}\n onCommit={(value, advance) => cellEdit.commit(coord, value, advance)}\n />\n ) : null}\n </td>\n )\n })}\n {publishing ? (\n <td className=\"px-3 py-2 align-middle\">\n <DocStateBadge published={publishing.isPublished({ collection: collectionId, id: doc.id })} />\n </td>\n ) : null}\n {urlByDocId ? (\n <td className=\"px-3 py-2 align-middle\">\n <UrlCell url={urlByDocId.get(doc.id)} />\n </td>\n ) : null}\n {hasRowActions ? (\n <td className=\"px-2 py-2 text-right align-middle\">\n <RowActionsMenu\n doc={doc}\n published={source.publishing?.isPublished({ collection: collectionId, id: doc.id }) ?? false}\n hasDetailPath={source.detailPath !== undefined}\n onAction={(action) => onRowAction(action, doc)}\n />\n </td>\n ) : null}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\n/**\n * The right-edge row `⋮` menu (EC-316): the SAME action vocabulary as the\n * toolbar's bulk actions (`rowActionsFor`), gated by the SAME capabilities —\n * so it degrades exactly like the rest of the list for a rail without\n * publish/remove (AD-19). Renders nothing when the gate leaves zero actions.\n */\nfunction RowActionsMenu({\n doc,\n published,\n hasDetailPath,\n onAction,\n}: {\n doc: CmsDocument\n published: boolean\n hasDetailPath: boolean\n onAction: (action: RowAction) => void\n}) {\n const source = useCollectionView()\n const actions = rowActionsFor({ capabilities: source.capabilities, hasDetailPath, published })\n if (actions.length === 0) return null\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={translate('cms.list.rowActionsLabel', { id: doc.id })}\n data-testid={`row-actions-${doc.id}`}\n >\n <MoreHorizontal />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {actions.map((action) => (\n <RowActionItem key={action} action={action} onSelect={() => onAction(action)} />\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\nfunction RowActionItem({ action, onSelect }: { action: RowAction; onSelect: () => void }) {\n switch (action) {\n case 'open':\n return (\n <DropdownMenuItem onClick={onSelect} data-testid=\"row-action-open\">\n <Pencil /> {translate('cms.list.rowAction.open')}\n </DropdownMenuItem>\n )\n case 'publish':\n return (\n <DropdownMenuItem onClick={onSelect} data-testid=\"row-action-publish\">\n <Eye /> {translate('cms.list.bulk.publish')}\n </DropdownMenuItem>\n )\n case 'unpublish':\n return (\n <DropdownMenuItem onClick={onSelect} data-testid=\"row-action-unpublish\">\n <EyeOff /> {translate('cms.list.bulk.unpublish')}\n </DropdownMenuItem>\n )\n case 'delete':\n return (\n <DropdownMenuItem\n variant=\"destructive\"\n onClick={onSelect}\n data-testid=\"row-action-delete\"\n >\n <Trash2 /> {translate('common.delete')}\n </DropdownMenuItem>\n )\n }\n}\n\n/**\n * A selection checkbox (row or select-all). Its own column and focus target —\n * it never participates in the cell-edit keyboard flow. Shift-click selects\n * the anchor→row range (the mousedown guard stops text selection).\n */\nfunction SelectionCheckbox({\n checked,\n indeterminate = false,\n label,\n testId,\n onToggle,\n}: {\n checked: boolean\n indeterminate?: boolean\n label: string\n testId: string\n onToggle: (shift: boolean) => void\n}) {\n return (\n <input\n ref={(el) => {\n if (el) el.indeterminate = indeterminate && !checked\n }}\n type=\"checkbox\"\n className=\"size-4 cursor-pointer accent-primary align-middle\"\n checked={checked}\n readOnly\n aria-label={label}\n data-testid={testId}\n onClick={(event) => onToggle(event.shiftKey)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault()\n onToggle(event.shiftKey)\n }\n }}\n onMouseDown={(event) => {\n if (event.shiftKey) event.preventDefault()\n }}\n />\n )\n}\n\nfunction HeaderCell({\n field,\n label,\n sort,\n onSort,\n}: {\n field: string\n label: string\n sort: ViewSort | null\n onSort: (field: string) => void\n}) {\n const active = sort?.field === field\n return (\n <th className=\"px-3 py-2 text-left text-xs font-semibold text-muted-foreground\">\n <button type=\"button\" onClick={() => onSort(field)} className=\"inline-flex items-center gap-1 hover:text-foreground\">\n {label}\n {active ? (\n sort!.dir === 'asc' ? (\n <ArrowUp className=\"size-3\" />\n ) : (\n <ArrowDown className=\"size-3\" />\n )\n ) : null}\n </button>\n </th>\n )\n}\n\n/**\n * The primary (title) column cell: the document link, resolved in the\n * ambient active locale with a visible fallback chip when the shown title is\n * untranslated (EC-176).\n */\nfunction PrimaryCell({\n projectId,\n collection,\n doc,\n primary,\n depth = 0,\n locale,\n config,\n detailPath,\n}: {\n projectId: string\n collection: CollectionDef\n doc: CmsDocument\n primary: string\n /** EC-218: nesting depth in the hierarchy (tree mode) — indents the title. */\n depth?: number\n locale: Locale\n config: LocaleConfig\n /** Rail-owned detail route splat (AD-19); absent ⇒ the rail has no detail surface. */\n detailPath?: (id: string) => string\n}) {\n // EC-242: the title cell renders the document identity (resolveDocumentTitle) —\n // a string `titleField` or a function pattern — over the fallback-resolved\n // values, NOT the raw `primary` column value. The untranslated-title chip applies\n // only to a field-backed title (a function pattern has no single source field).\n const title = resolveDocumentTitle(\n collection,\n resolveDocumentForLocale(collection, doc, locale, config),\n doc.id,\n )\n const fallback =\n typeof collection.titleField === 'function'\n ? null\n : resolveDisplayedValue(collection, doc, primary, locale, config).fallback\n const splat = detailPath?.(doc.id)\n return (\n <Row gap=\"2\" align=\"center\" className=\"min-w-0\" style={{ paddingLeft: depth * 20 }}>\n {depth > 0 ? (\n <CornerDownRight className=\"size-3.5 shrink-0 text-muted-foreground\" aria-hidden />\n ) : null}\n {/* 0.0.39: assets get a leading, fixed-size preview in the filename column —\n an image thumbnail (object-cover) for image assets, the file-type placeholder\n otherwise. Fixed box, so it never reflows the EC-316 fixed column widths. */}\n {collection.kind === 'asset' ? <AssetThumbCell assetId={doc.id} alt={title} /> : null}\n {splat !== undefined ? (\n <Link\n to={STUDIO_PROJECT_ROUTE}\n params={{ projectId, _splat: splat }}\n className=\"truncate font-medium text-foreground hover:text-primary hover:underline\"\n >\n {title}\n </Link>\n ) : (\n <Text as=\"span\" className=\"truncate font-medium text-foreground\">\n {title}\n </Text>\n )}\n <FallbackChip fallback={fallback} testId={`cell-fallback-${doc.id}-${primary}`} />\n </Row>\n )\n}\n\n/**\n * The leading asset preview in the filename column (0.0.39). Resolves the asset\n * record from the ambient library and renders {@link AssetThumb} — an image preview\n * for image assets, the file-type placeholder for the rest. Mounted only for\n * `kind:'asset'` collections (which are always under an `<AssetsProvider>`), so the\n * `useAssetRecord` hook is never called on a rail without a library.\n */\nfunction AssetThumbCell({ assetId, alt }: { assetId: string; alt: string }) {\n const record = useAssetRecord(assetId)\n return <AssetThumb record={record} alt={alt} className=\"size-8 shrink-0\" />\n}\n\n/**\n * The read-only URL column cell (EC-216): the document's LIVE (published) path,\n * linking to the absolute live URL when a `frontendUrl` is configured. Only\n * published documents have a `url` here (the URL is derived from the published\n * pool, EC-205), so an unpublished document — having no live page — shows a dash.\n * The URL is always derived, never stored.\n */\nfunction UrlCell({ url }: { url?: DocumentUrl }) {\n if (!url) {\n return (\n <Text size=\"xs\" tone=\"subtle\">\n —\n </Text>\n )\n }\n if (url.href) {\n return (\n <a\n href={url.href}\n target=\"_blank\"\n rel=\"noreferrer\"\n title={url.href}\n className=\"inline-flex max-w-[18rem] items-center gap-1 text-xs text-muted-foreground transition-colors hover:text-foreground\"\n >\n <span className=\"truncate\">{url.path}</span>\n <ExternalLink className=\"size-3 shrink-0\" aria-hidden />\n </a>\n )\n }\n return (\n <Text size=\"xs\" tone=\"muted\" className=\"max-w-[18rem] truncate\" title={url.path}>\n {url.path}\n </Text>\n )\n}\n\nexport type { FieldDef }\n"]}
@@ -9,6 +9,7 @@ import { cn } from '@elytracms/studio/lib/utils';
9
9
  import { localizedLabel, translate } from '@elytracms/studio/lib/i18n';
10
10
  import { activeLocaleValues } from '@elytracms/studio/lib/locale';
11
11
  import { useCollectionView } from '../collection-view/collection-view-context.js';
12
+ import { fieldLabel } from './cms-labels.js';
12
13
  import { useOptionalDocumentEditor } from './document-editor-context.js';
13
14
  import { toRefArray } from './cell.js';
14
15
  import { RelationPicker } from './relation-picker.js';
@@ -97,7 +98,10 @@ function BuiltInFieldControl({ field, value, onChange, readOnly, id }) {
97
98
  }
98
99
  return (_jsxs(Select, { id: id, disabled: readOnly, value: typeof value === 'string' ? value : '', onChange: (e) => onChange(e.target.value || undefined), children: [_jsx("option", { value: "", children: "\u2014" }), field.options.map((opt) => (_jsx("option", { value: opt.value, children: localizedLabel(opt.label, opt.value) }, opt.value)))] }));
99
100
  case 'richText':
100
- return (_jsx(RichTextEditor, { value: value, onChange: onChange, readOnly: readOnly, id: id, allow: field.allow }));
101
+ return (_jsx(RichTextEditor, { value: value, onChange: onChange, readOnly: readOnly, id: id, allow: field.allow,
102
+ // EC-436: the SAME resolved localized label the field row renders (the
103
+ // EC-241 `fieldLabel` path) — titles the expand stage "<label> — Rich text".
104
+ label: fieldLabel(field) }));
101
105
  case 'relation':
102
106
  return _jsx(RelationField, { field: field, value: value, onChange: onChange, readOnly: readOnly });
103
107
  case 'asset':