@elytracms/studio 0.0.70 → 0.0.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/convex/cms.ts +8 -0
- package/convex/delivery.ts +12 -2
- package/convex/write-limits.ts +62 -0
- package/dist/components/account/self-account-view-source.js +1 -0
- package/dist/components/account/self-account-view-source.js.map +1 -1
- package/dist/components/assets/assets-collection-view-source.js +1 -0
- package/dist/components/assets/assets-collection-view-source.js.map +1 -1
- package/dist/components/cms/collection-table.js +19 -2
- package/dist/components/cms/collection-table.js.map +1 -1
- package/dist/components/cms/detail-editor.js +73 -51
- package/dist/components/cms/detail-editor.js.map +1 -1
- package/dist/components/cms/duplicate-document.d.ts +45 -0
- package/dist/components/cms/duplicate-document.js +141 -0
- package/dist/components/cms/duplicate-document.js.map +1 -0
- package/dist/components/cms/field-anchors.d.ts +67 -0
- package/dist/components/cms/field-anchors.js +91 -0
- package/dist/components/cms/field-anchors.js.map +1 -0
- package/dist/components/cms/issue-copy.d.ts +45 -0
- package/dist/components/cms/issue-copy.js +89 -0
- package/dist/components/cms/issue-copy.js.map +1 -0
- package/dist/components/cms/issues-pane.d.ts +11 -2
- package/dist/components/cms/issues-pane.js +22 -4
- package/dist/components/cms/issues-pane.js.map +1 -1
- package/dist/components/cms/object-array-field.d.ts +2 -0
- package/dist/components/cms/object-array-field.js +75 -21
- package/dist/components/cms/object-array-field.js.map +1 -1
- package/dist/components/cms/row-actions.d.ts +10 -3
- package/dist/components/cms/row-actions.js +8 -0
- package/dist/components/cms/row-actions.js.map +1 -1
- package/dist/components/cms/use-field-focus.d.ts +25 -9
- package/dist/components/cms/use-field-focus.js +80 -15
- package/dist/components/cms/use-field-focus.js.map +1 -1
- package/dist/components/collection-view/cms-collection-view-source.js +1 -0
- package/dist/components/collection-view/cms-collection-view-source.js.map +1 -1
- package/dist/components/redirects/redirects-collection-view-source.js +1 -0
- package/dist/components/redirects/redirects-collection-view-source.js.map +1 -1
- package/dist/components/users/users-collection-view-source.js +1 -0
- package/dist/components/users/users-collection-view-source.js.map +1 -1
- package/dist/customization.d.ts +9 -0
- package/dist/customization.js +8 -0
- package/dist/customization.js.map +1 -1
- package/dist/lib/collection-view/collection-view-source.d.ts +8 -0
- package/dist/lib/collection-view/collection-view-source.js.map +1 -1
- package/dist/lib/i18n/messages.de.js +38 -1
- package/dist/lib/i18n/messages.de.js.map +1 -1
- package/dist/lib/i18n/messages.en.d.ts +34 -0
- package/dist/lib/i18n/messages.en.js +41 -1
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/persona/labels.d.ts +5 -1
- package/dist/lib/persona/labels.js +43 -30
- package/dist/lib/persona/labels.js.map +1 -1
- package/dist/previews/enumerate.d.ts +68 -0
- package/dist/previews/enumerate.js +78 -0
- package/dist/previews/enumerate.js.map +1 -0
- package/dist/previews/harness.d.ts +50 -0
- package/dist/previews/harness.js +123 -0
- package/dist/previews/harness.js.map +1 -0
- package/dist/previews/manifest-format.d.ts +57 -0
- package/dist/previews/manifest-format.js +59 -0
- package/dist/previews/manifest-format.js.map +1 -0
- package/dist/ui/field.d.ts +24 -1
- package/dist/ui/field.js +23 -2
- package/dist/ui/field.js.map +1 -1
- package/package.json +10 -6
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ChevronDown, ChevronUp, GripVertical, MoreHorizontal, Plus, Trash2 } from 'lucide-react';
|
|
3
|
-
import { createContext, useContext, useRef, useState } from 'react';
|
|
3
|
+
import { createContext, useContext, useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { isFieldHidden } from '@elytracms/core/cms-core';
|
|
5
|
-
import { Button, Card, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, Field, Row, Stack, Text, } from '@elytracms/studio/ui';
|
|
5
|
+
import { Button, Card, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, FIELD_PATH_ATTR, Field, Row, Stack, Text, } from '@elytracms/studio/ui';
|
|
6
6
|
import { cn } from '@elytracms/studio/lib/utils';
|
|
7
7
|
import { localizedLabel, translate } from '@elytracms/studio/lib/i18n';
|
|
8
8
|
import { fieldLabel } from './cms-labels.js';
|
|
9
|
+
import { FieldPathContext, isPathWithin, useFieldFocusRequest, useFieldPath, } from './field-anchors.js';
|
|
9
10
|
import { FieldControl } from './field-control.js';
|
|
10
11
|
import { depthRail, depthTint, isTabularObjectType, objectItemSummary, reorder } from './field-control-lib.js';
|
|
11
12
|
/**
|
|
@@ -16,7 +17,17 @@ import { depthRail, depthTint, isTabularObjectType, objectItemSummary, reorder }
|
|
|
16
17
|
* sub-fields and asset metadata. Cells and subfields render through
|
|
17
18
|
* `FieldControl`, so any subfield type — including a nested repeater — works
|
|
18
19
|
* for free.
|
|
20
|
+
*
|
|
21
|
+
* EC-443 path anchors: inside a stamped surface (a non-null `FieldPathContext`,
|
|
22
|
+
* provided by the document form) every item card / table row / subfield row
|
|
23
|
+
* stamps its `FIELD_PATH_ATTR` anchor (`links/3`, `links/3/badge/text` — the
|
|
24
|
+
* ONE convention defined on the attribute in `ui/field.tsx`), a collapsed card
|
|
25
|
+
* auto-expands when the active focus request targets a path within it, and the
|
|
26
|
+
* exact requested control ring-highlights. All decisions come from the pure
|
|
27
|
+
* helpers in `field-anchors.ts`.
|
|
19
28
|
*/
|
|
29
|
+
/** The EC-443 ring on the exact jump target (mirrors the top-level row ring). */
|
|
30
|
+
const FOCUS_RING_CLASS = 'rounded-md bg-primary/5 ring-2 ring-primary/70';
|
|
20
31
|
function asRecord(value) {
|
|
21
32
|
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
22
33
|
? value
|
|
@@ -86,8 +97,12 @@ function ItemOverflowMenu({ index, count, onMove, onRemove, }) {
|
|
|
86
97
|
* The nested subfield form for one object item (EC-253). Reuses {@link FieldControl}
|
|
87
98
|
* recursively, so any subfield type — including a nested object/repeater — works for
|
|
88
99
|
* free. Writing a subfield merges it back into the item and bubbles the new item up.
|
|
100
|
+
* EC-443: each subfield row stamps its path anchor (`<itemPath>/<sub>`), rings when
|
|
101
|
+
* it is the exact focus target, and provides its path down for deeper nesting.
|
|
89
102
|
*/
|
|
90
103
|
export function ObjectItemForm({ fields, value, onChange, readOnly, idPrefix, }) {
|
|
104
|
+
const itemPath = useFieldPath();
|
|
105
|
+
const focus = useFieldFocusRequest();
|
|
91
106
|
return (_jsx(Stack, { gap: "3", className: "mt-2", children: fields.map((sub) => {
|
|
92
107
|
// EC-273: a conditionally-hidden subfield (its predicate keys off the item's
|
|
93
108
|
// own sibling values) is omitted — e.g. a discriminated link's `href` shows
|
|
@@ -95,14 +110,15 @@ export function ObjectItemForm({ fields, value, onChange, readOnly, idPrefix, })
|
|
|
95
110
|
if (isFieldHidden(sub, { values: value }))
|
|
96
111
|
return null;
|
|
97
112
|
const subId = `${idPrefix}-${sub.name}`;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
113
|
+
const subPath = itemPath === null ? undefined : `${itemPath}/${sub.name}`;
|
|
114
|
+
return (_jsx(Field, { htmlFor: subId, fieldPath: subPath, className: cn('transition-shadow', subPath !== undefined && focus?.path === subPath && `${FOCUS_RING_CLASS} p-2`), hint: localizedLabel(sub.form?.description) || undefined, label: _jsxs(Row, { gap: "2", children: [_jsx("span", { children: fieldLabel(sub) }), sub.validation?.required ? _jsx("span", { className: "text-destructive", children: "*" }) : null] }), children: _jsx(FieldPathContext.Provider, { value: subPath ?? null, children: _jsx(FieldControl, { id: subId, field: sub, value: value[sub.name], readOnly: readOnly, onChange: (next) => {
|
|
115
|
+
const updated = { ...value };
|
|
116
|
+
if (next === undefined)
|
|
117
|
+
delete updated[sub.name];
|
|
118
|
+
else
|
|
119
|
+
updated[sub.name] = next;
|
|
120
|
+
onChange(updated);
|
|
121
|
+
} }) }) }, sub.name));
|
|
106
122
|
}) }));
|
|
107
123
|
}
|
|
108
124
|
/**
|
|
@@ -132,6 +148,8 @@ export function ObjectField({ field, value, onChange, readOnly, id, }) {
|
|
|
132
148
|
function ObjectCardList({ field, value, onChange, readOnly, id, depth }) {
|
|
133
149
|
const arr = useObjectArray(field, value, onChange);
|
|
134
150
|
const { items, keys } = arr;
|
|
151
|
+
const parentPath = useFieldPath();
|
|
152
|
+
const focus = useFieldFocusRequest();
|
|
135
153
|
// (D) Default COLLAPSED: track which keys are EXPANDED (empty = all collapsed).
|
|
136
154
|
// (B) Accordion: expanding one collapses the siblings.
|
|
137
155
|
const [expandedKeys, setExpandedKeys] = useState(() => new Set());
|
|
@@ -145,13 +163,35 @@ function ObjectCardList({ field, value, onChange, readOnly, id, depth }) {
|
|
|
145
163
|
});
|
|
146
164
|
const allExpanded = items.length > 0 && keys.every((k) => expandedKeys.has(k));
|
|
147
165
|
const onAdd = () => setExpandedKeys(new Set([arr.addItem()]));
|
|
166
|
+
// EC-443: a jump-to-field targeting a path INSIDE one of these items expands
|
|
167
|
+
// that item (accordion semantics, like a manual open) so the deeper anchors can
|
|
168
|
+
// render — nested levels cascade, each level's effect firing once its card
|
|
169
|
+
// mounts. Keyed on the request nonce so re-clicking the same issue re-expands
|
|
170
|
+
// a manually re-collapsed item.
|
|
171
|
+
const focusPath = focus?.path;
|
|
172
|
+
const focusNonce = focus?.nonce;
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
if (parentPath === null || focusPath === undefined)
|
|
175
|
+
return;
|
|
176
|
+
const index = items.findIndex((_, i) => isPathWithin(`${parentPath}/${i}`, focusPath));
|
|
177
|
+
if (index < 0)
|
|
178
|
+
return;
|
|
179
|
+
const key = keys[index];
|
|
180
|
+
if (key !== undefined)
|
|
181
|
+
setExpandedKeys(new Set([key]));
|
|
182
|
+
// Deps: keys/items stay in lockstep (the C2 key↔value lock) — `items.length`
|
|
183
|
+
// captures the structure; item-content identity must NOT re-trigger expansion.
|
|
184
|
+
}, [focusNonce, focusPath, parentPath, items.length]);
|
|
148
185
|
return (_jsx(ArrayDepthContext.Provider, { value: depth + 1, children: _jsxs(Stack, { gap: "2", children: [items.length > 1 && !readOnly ? (_jsx(Row, { justify: "end", children: _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setExpandedKeys(allExpanded ? new Set() : new Set(keys)), children: translate(allExpanded ? 'cms.field.collapseAll' : 'cms.field.expandAll') }) })) : null, items.length === 0 ? (_jsx(Text, { size: "sm", tone: "subtle", children: translate('cms.field.noItems') })) : (items.map((item, i) => {
|
|
149
186
|
// keysRef is reconciled to items.length, so keys[i] is always present;
|
|
150
187
|
// `?? i` only satisfies noUncheckedIndexedAccess (never taken at runtime).
|
|
151
188
|
const key = keys[i] ?? i;
|
|
152
189
|
const record = asRecord(item);
|
|
153
190
|
const isExpanded = expandedKeys.has(key);
|
|
154
|
-
|
|
191
|
+
// EC-443: the item's path anchor — stamped even while collapsed, so a
|
|
192
|
+
// degraded jump can still land (and ring) on the closed card.
|
|
193
|
+
const itemPath = parentPath === null ? undefined : `${parentPath}/${i}`;
|
|
194
|
+
return (_jsxs(Card, { ...(itemPath !== undefined ? { [FIELD_PATH_ATTR]: itemPath } : {}), onDragOver: (e) => {
|
|
155
195
|
if (arr.dragIndex === null)
|
|
156
196
|
return;
|
|
157
197
|
e.preventDefault();
|
|
@@ -159,11 +199,13 @@ function ObjectCardList({ field, value, onChange, readOnly, id, depth }) {
|
|
|
159
199
|
arr.setOverIndex(i);
|
|
160
200
|
}, onDrop: () => arr.drop(i), className: cn('border-l-2 p-0', depthRail(depth), depthTint(depth), arr.dragIndex === i ? 'opacity-50' : '', arr.overIndex === i && arr.dragIndex !== null && arr.dragIndex !== i
|
|
161
201
|
? 'border-l-primary ring-1 ring-primary/40'
|
|
202
|
+
: '', itemPath !== undefined && focus?.path === itemPath
|
|
203
|
+
? 'ring-2 ring-primary/70'
|
|
162
204
|
: ''), children: [_jsxs(Row, { className: "select-none border-b border-border/60 bg-muted/20 px-2 py-1.5", children: [!readOnly ? (_jsx("span", { draggable: true, onDragStart: (e) => {
|
|
163
205
|
e.dataTransfer.effectAllowed = 'move';
|
|
164
206
|
e.dataTransfer.setData('text/plain', String(i));
|
|
165
207
|
arr.setDragIndex(i);
|
|
166
|
-
}, onDragEnd: arr.endDrag, "aria-label": translate('cms.field.dragToReorder'), className: "cursor-grab text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing", children: _jsx(GripVertical, { className: "size-3.5" }) })) : null, _jsxs("button", { type: "button", onClick: () => toggle(key), "aria-expanded": isExpanded, className: "flex min-w-0 flex-1 items-center gap-1.5 text-left", children: [_jsx(ChevronDown, { className: cn('size-3.5 shrink-0 text-muted-foreground transition-transform', isExpanded ? '' : '-rotate-90'), "aria-hidden": true }), _jsx(Text, { size: "sm", className: "min-w-0 truncate font-medium", children: objectItemSummary(field.fields, record, i) })] }), !readOnly ? (_jsx(ItemOverflowMenu, { index: i, count: items.length, onMove: arr.move, onRemove: () => arr.removeAt(i) })) : null] }), isExpanded ? (_jsx("div", { className: "px-3 pb-3", children: _jsx(ObjectItemForm, { fields: field.fields, value: record, readOnly: readOnly, idPrefix: `${id}-${i}`, onChange: (updated) => arr.setItem(i, updated) }) })) : null] }, key));
|
|
208
|
+
}, onDragEnd: arr.endDrag, "aria-label": translate('cms.field.dragToReorder'), className: "cursor-grab text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing", children: _jsx(GripVertical, { className: "size-3.5" }) })) : null, _jsxs("button", { type: "button", onClick: () => toggle(key), "aria-expanded": isExpanded, className: "flex min-w-0 flex-1 items-center gap-1.5 text-left", children: [_jsx(ChevronDown, { className: cn('size-3.5 shrink-0 text-muted-foreground transition-transform', isExpanded ? '' : '-rotate-90'), "aria-hidden": true }), _jsx(Text, { size: "sm", className: "min-w-0 truncate font-medium", children: objectItemSummary(field.fields, record, i) })] }), !readOnly ? (_jsx(ItemOverflowMenu, { index: i, count: items.length, onMove: arr.move, onRemove: () => arr.removeAt(i) })) : null] }), isExpanded ? (_jsx("div", { className: "px-3 pb-3", children: _jsx(FieldPathContext.Provider, { value: itemPath ?? null, children: _jsx(ObjectItemForm, { fields: field.fields, value: record, readOnly: readOnly, idPrefix: `${id}-${i}`, onChange: (updated) => arr.setItem(i, updated) }) }) })) : null] }, key));
|
|
167
209
|
})), !readOnly ? (_jsxs(Button, { variant: "outline", size: "sm", onClick: onAdd, children: [_jsx(Plus, { className: "size-3" }), " ", translate('cms.field.addItem')] })) : null] }) }));
|
|
168
210
|
}
|
|
169
211
|
/**
|
|
@@ -175,12 +217,17 @@ function ObjectCardList({ field, value, onChange, readOnly, id, depth }) {
|
|
|
175
217
|
function ObjectTableField({ field, value, onChange, readOnly, id, depth }) {
|
|
176
218
|
const arr = useObjectArray(field, value, onChange);
|
|
177
219
|
const { items, keys } = arr;
|
|
220
|
+
// EC-443: rows/cells stamp path anchors too (a tabular type is flat, so the
|
|
221
|
+
// cell — `links/3/href` — is always the deepest possible anchor here).
|
|
222
|
+
const parentPath = useFieldPath();
|
|
223
|
+
const focus = useFieldFocusRequest();
|
|
178
224
|
const cols = field.fields;
|
|
179
225
|
const span = cols.length + (readOnly ? 0 : 2);
|
|
180
226
|
return (_jsxs("div", { className: cn('overflow-hidden rounded-md border border-border border-l-2', depthRail(depth), depthTint(depth)), children: [_jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-border/60 bg-muted/30 text-left", children: [!readOnly ? _jsx("th", { className: "w-7" }) : null, cols.map((c) => (_jsxs("th", { className: "px-2 py-1.5 text-xs font-medium text-muted-foreground", children: [fieldLabel(c), c.validation?.required ? _jsx("span", { className: "text-destructive", children: " *" }) : null] }, c.name))), !readOnly ? _jsx("th", { className: "w-9" }) : null] }) }), _jsx("tbody", { children: items.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: span, className: "px-2 py-2 text-muted-foreground", children: _jsx(Text, { size: "sm", tone: "subtle", children: translate('cms.field.noItems') }) }) })) : (items.map((item, i) => {
|
|
181
227
|
const key = keys[i] ?? i;
|
|
182
228
|
const record = asRecord(item);
|
|
183
|
-
|
|
229
|
+
const itemPath = parentPath === null ? undefined : `${parentPath}/${i}`;
|
|
230
|
+
return (_jsxs("tr", { ...(itemPath !== undefined ? { [FIELD_PATH_ATTR]: itemPath } : {}), onDragOver: (e) => {
|
|
184
231
|
if (arr.dragIndex === null)
|
|
185
232
|
return;
|
|
186
233
|
e.preventDefault();
|
|
@@ -188,18 +235,25 @@ function ObjectTableField({ field, value, onChange, readOnly, id, depth }) {
|
|
|
188
235
|
arr.setOverIndex(i);
|
|
189
236
|
}, onDrop: () => arr.drop(i), className: cn('border-b border-border/40 align-top last:border-0', arr.dragIndex === i ? 'opacity-50' : '', arr.overIndex === i && arr.dragIndex !== null && arr.dragIndex !== i
|
|
190
237
|
? 'bg-primary/5'
|
|
238
|
+
: '', itemPath !== undefined && focus?.path === itemPath
|
|
239
|
+
? 'ring-2 ring-inset ring-primary/70'
|
|
191
240
|
: ''), children: [!readOnly ? (_jsx("td", { className: "px-1 py-1", children: _jsx("span", { draggable: true, onDragStart: (e) => {
|
|
192
241
|
e.dataTransfer.effectAllowed = 'move';
|
|
193
242
|
e.dataTransfer.setData('text/plain', String(i));
|
|
194
243
|
arr.setDragIndex(i);
|
|
195
|
-
}, onDragEnd: arr.endDrag, "aria-label": translate('cms.field.dragToReorder'), className: "inline-flex cursor-grab text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing", children: _jsx(GripVertical, { className: "size-3.5" }) }) })) : null, cols.map((c) =>
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
updated
|
|
201
|
-
|
|
202
|
-
|
|
244
|
+
}, onDragEnd: arr.endDrag, "aria-label": translate('cms.field.dragToReorder'), className: "inline-flex cursor-grab text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing", children: _jsx(GripVertical, { className: "size-3.5" }) }) })) : null, cols.map((c) => {
|
|
245
|
+
const cellPath = itemPath === undefined ? undefined : `${itemPath}/${c.name}`;
|
|
246
|
+
return (_jsx("td", { ...(cellPath !== undefined ? { [FIELD_PATH_ATTR]: cellPath } : {}), className: cn('px-2 py-1', cellPath !== undefined && focus?.path === cellPath
|
|
247
|
+
? 'bg-primary/5 ring-2 ring-inset ring-primary/70'
|
|
248
|
+
: ''), children: _jsx(FieldControl, { id: `${id}-${i}-${c.name}`, field: c, value: record[c.name], readOnly: readOnly, onChange: (next) => {
|
|
249
|
+
const updated = { ...record };
|
|
250
|
+
if (next === undefined)
|
|
251
|
+
delete updated[c.name];
|
|
252
|
+
else
|
|
253
|
+
updated[c.name] = next;
|
|
254
|
+
arr.setItem(i, updated);
|
|
255
|
+
} }) }, c.name));
|
|
256
|
+
}), !readOnly ? (_jsx("td", { className: "px-1 py-1", children: _jsx(ItemOverflowMenu, { index: i, count: items.length, onMove: arr.move, onRemove: () => arr.removeAt(i) }) })) : null] }, key));
|
|
203
257
|
})) })] }), !readOnly ? (_jsx("div", { className: "border-t border-border/60 p-1.5", children: _jsxs(Button, { variant: "ghost", size: "sm", onClick: () => arr.addItem(), children: [_jsx(Plus, { className: "size-3" }), " ", translate('common.add')] }) })) : null] }));
|
|
204
258
|
}
|
|
205
259
|
//# sourceMappingURL=object-array-field.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-array-field.js","sourceRoot":"","sources":["../../../src/components/cms/object-array-field.tsx"],"names":[],"mappings":"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","sourcesContent":["import { ChevronDown, ChevronUp, GripVertical, MoreHorizontal, Plus, Trash2 } from 'lucide-react'\nimport { createContext, useContext, useRef, useState } from 'react'\nimport type { FieldDef, ObjectFieldDef } from '@elytracms/core/cms-core'\nimport { isFieldHidden } from '@elytracms/core/cms-core'\nimport {\n Button,\n Card,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n Field,\n Row,\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 { fieldLabel } from './cms-labels'\nimport { FieldControl } from './field-control'\nimport { depthRail, depthTint, isTabularObjectType, objectItemSummary, reorder } from './field-control-lib'\n\n/**\n * The object / repeater field controls (EC-253, legibility-rebuilt EC-305) —\n * split from `field-control.tsx` (EC-330). {@link ObjectField} dispatches by\n * shape (single card / editable table / card list); {@link ObjectItemForm} is\n * the recursive subfield form the asset-field family reuses for per-use\n * sub-fields and asset metadata. Cells and subfields render through\n * `FieldControl`, so any subfield type — including a nested repeater — works\n * for free.\n */\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {}\n}\n\n// EC-305: nested-array depth, propagated via context so each array level can encode\n// its depth (rail colour + tint) without prop-drilling through FieldControl's many\n// branches. The detail editor renders top-level fields with the default depth 0.\nconst ArrayDepthContext = createContext(0)\nconst useArrayDepth = () => useContext(ArrayDepthContext)\n\n/**\n * Shared array state for an object repeater (EC-253/EC-294/EC-305): the value-only\n * items + a parallel stable-key list kept in lockstep through every structural op\n * (the EC-253 C2 key↔value lock), add/remove/move, and native drag-reorder. Used by\n * both the card list (B) and the table (C) so they behave identically.\n */\nfunction useObjectArray(field: ObjectFieldDef, value: unknown, onChange: (value: unknown) => void) {\n const items = Array.isArray(value) ? (value as Record<string, unknown>[]) : []\n const seq = useRef(0)\n const keysRef = useRef<number[]>([])\n if (keysRef.current.length !== items.length) {\n keysRef.current = items.map((_, i) => keysRef.current[i] ?? seq.current++)\n }\n const keys = keysRef.current\n const commit = (nextItems: Record<string, unknown>[], nextKeys: number[]) => {\n keysRef.current = nextKeys\n onChange(nextItems)\n }\n const move = (from: number, to: number) => commit(reorder(items, from, to), reorder(keys, from, to))\n const removeAt = (i: number) =>\n commit(items.filter((_, j) => j !== i), keys.filter((_, j) => j !== i))\n const addItem = (): number => {\n const seed: Record<string, unknown> = {}\n for (const sub of field.fields) if (sub.default !== undefined) seed[sub.name] = sub.default\n const key = seq.current++\n commit([...items, seed], [...keys, key])\n return key\n }\n const setItem = (i: number, updated: Record<string, unknown>) => {\n const nextItems = items.slice()\n nextItems[i] = updated\n commit(nextItems, keys)\n }\n const [dragIndex, setDragIndex] = useState<number | null>(null)\n const [overIndex, setOverIndex] = useState<number | null>(null)\n const endDrag = () => {\n setDragIndex(null)\n setOverIndex(null)\n }\n const drop = (to: number) => {\n if (dragIndex !== null && dragIndex !== to) move(dragIndex, to)\n endDrag()\n }\n return { items, keys, move, removeAt, addItem, setItem, dragIndex, overIndex, setDragIndex, setOverIndex, endDrag, drop }\n}\n\n/**\n * (E) Chrome reduction: the per-row move/remove controls collapse into one hover/\n * focus overflow menu, so a row reads as content, not a six-button toolbar. Drag is\n * the primary reorder; the arrows stay here for keyboard/a11y.\n */\nfunction ItemOverflowMenu({\n index,\n count,\n onMove,\n onRemove,\n}: {\n index: number\n count: number\n onMove: (from: number, to: number) => void\n onRemove: () => void\n}) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" aria-label={translate('cms.field.itemActions')}>\n <MoreHorizontal className=\"size-3.5\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem disabled={index === 0} onClick={() => onMove(index, index - 1)}>\n <ChevronUp /> {translate('cms.field.moveUp')}\n </DropdownMenuItem>\n <DropdownMenuItem disabled={index === count - 1} onClick={() => onMove(index, index + 1)}>\n <ChevronDown /> {translate('cms.field.moveDown')}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={onRemove}>\n <Trash2 /> {translate('common.remove')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\n/**\n * The nested subfield form for one object item (EC-253). Reuses {@link FieldControl}\n * recursively, so any subfield type — including a nested object/repeater — works for\n * free. Writing a subfield merges it back into the item and bubbles the new item up.\n */\nexport function ObjectItemForm({\n fields,\n value,\n onChange,\n readOnly,\n idPrefix,\n}: {\n fields: readonly FieldDef[]\n value: Record<string, unknown>\n onChange: (value: Record<string, unknown>) => void\n readOnly: boolean\n idPrefix: string\n}) {\n return (\n <Stack gap=\"3\" className=\"mt-2\">\n {fields.map((sub) => {\n // EC-273: a conditionally-hidden subfield (its predicate keys off the item's\n // own sibling values) is omitted — e.g. a discriminated link's `href` shows\n // only when `linkType === 'href'`. Re-evaluated as the item is edited.\n if (isFieldHidden(sub, { values: value })) return null\n const subId = `${idPrefix}-${sub.name}`\n return (\n <Field\n key={sub.name}\n htmlFor={subId}\n hint={localizedLabel(sub.form?.description) || undefined}\n label={\n <Row gap=\"2\">\n <span>{fieldLabel(sub)}</span>\n {sub.validation?.required ? <span className=\"text-destructive\">*</span> : null}\n </Row>\n }\n >\n <FieldControl\n id={subId}\n field={sub}\n value={value[sub.name]}\n readOnly={readOnly}\n onChange={(next) => {\n const updated = { ...value }\n if (next === undefined) delete updated[sub.name]\n else updated[sub.name] = next\n onChange(updated)\n }}\n />\n </Field>\n )\n })}\n </Stack>\n )\n}\n\n/**\n * Object / repeater field control (EC-253), legibility-rebuilt (EC-305). A single\n * object (`multiple: false`) renders a depth-encoded card; an array (`'many'`)\n * dispatches by shape: a **flat** object type (all scalar subfields) → a compact\n * editable TABLE (C); a richer/nested type → a card list with depth encoding (B),\n * summary-first collapse (D), and reduced per-row chrome (E). Editing stays in the\n * shared field form — no canvas escape (unlike `blocks`) — so props and document\n * fields share this control. Depth flows via {@link ArrayDepthContext}.\n */\nexport function ObjectField({\n field,\n value,\n onChange,\n readOnly,\n id,\n}: {\n field: ObjectFieldDef\n value: unknown\n onChange: (value: unknown) => void\n readOnly: boolean\n id: string\n}) {\n const depth = useArrayDepth()\n if (field.multiple === false) {\n return (\n <Card className={cn('border-l-2 p-3', depthRail(depth), depthTint(depth))}>\n <ArrayDepthContext.Provider value={depth + 1}>\n <ObjectItemForm\n fields={field.fields}\n value={asRecord(value)}\n readOnly={readOnly}\n idPrefix={id}\n onChange={onChange}\n />\n </ArrayDepthContext.Provider>\n </Card>\n )\n }\n const props = { field, value, onChange, readOnly, id, depth }\n return isTabularObjectType(field) ? <ObjectTableField {...props} /> : <ObjectCardList {...props} />\n}\n\ninterface ObjectArrayProps {\n field: ObjectFieldDef\n value: unknown\n onChange: (value: unknown) => void\n readOnly: boolean\n id: string\n depth: number\n}\n\n/**\n * (B + D + E) The card list for a nested/rich object array: depth-encoded cards\n * (coloured rail + tint), items collapsed by default to a scannable summary outline\n * (D), accordion expansion (open one → collapse siblings), and the per-row controls\n * collapsed into one overflow menu (E). Drag-to-reorder; arrows live in the menu for\n * a11y. Nested arrays render one depth deeper via the context provider.\n */\nfunction ObjectCardList({ field, value, onChange, readOnly, id, depth }: ObjectArrayProps) {\n const arr = useObjectArray(field, value, onChange)\n const { items, keys } = arr\n // (D) Default COLLAPSED: track which keys are EXPANDED (empty = all collapsed).\n // (B) Accordion: expanding one collapses the siblings.\n const [expandedKeys, setExpandedKeys] = useState<ReadonlySet<number>>(() => new Set())\n const toggle = (key: number) =>\n setExpandedKeys((prev) => {\n if (prev.has(key)) {\n const next = new Set(prev)\n next.delete(key)\n return next\n }\n return new Set([key])\n })\n const allExpanded = items.length > 0 && keys.every((k) => expandedKeys.has(k))\n const onAdd = () => setExpandedKeys(new Set([arr.addItem()]))\n return (\n <ArrayDepthContext.Provider value={depth + 1}>\n <Stack gap=\"2\">\n {items.length > 1 && !readOnly ? (\n <Row justify=\"end\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setExpandedKeys(allExpanded ? new Set() : new Set(keys))}\n >\n {translate(allExpanded ? 'cms.field.collapseAll' : 'cms.field.expandAll')}\n </Button>\n </Row>\n ) : null}\n {items.length === 0 ? (\n <Text size=\"sm\" tone=\"subtle\">\n {translate('cms.field.noItems')}\n </Text>\n ) : (\n items.map((item, i) => {\n // keysRef is reconciled to items.length, so keys[i] is always present;\n // `?? i` only satisfies noUncheckedIndexedAccess (never taken at runtime).\n const key = keys[i] ?? i\n const record = asRecord(item)\n const isExpanded = expandedKeys.has(key)\n return (\n <Card\n key={key}\n onDragOver={(e) => {\n if (arr.dragIndex === null) return\n e.preventDefault()\n if (arr.overIndex !== i) arr.setOverIndex(i)\n }}\n onDrop={() => arr.drop(i)}\n className={cn(\n 'border-l-2 p-0',\n depthRail(depth),\n depthTint(depth),\n arr.dragIndex === i ? 'opacity-50' : '',\n arr.overIndex === i && arr.dragIndex !== null && arr.dragIndex !== i\n ? 'border-l-primary ring-1 ring-primary/40'\n : '',\n )}\n >\n <Row className=\"select-none border-b border-border/60 bg-muted/20 px-2 py-1.5\">\n {!readOnly ? (\n <span\n draggable\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(i))\n arr.setDragIndex(i)\n }}\n onDragEnd={arr.endDrag}\n aria-label={translate('cms.field.dragToReorder')}\n className=\"cursor-grab text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing\"\n >\n <GripVertical className=\"size-3.5\" />\n </span>\n ) : null}\n <button\n type=\"button\"\n onClick={() => toggle(key)}\n aria-expanded={isExpanded}\n className=\"flex min-w-0 flex-1 items-center gap-1.5 text-left\"\n >\n <ChevronDown\n className={cn(\n 'size-3.5 shrink-0 text-muted-foreground transition-transform',\n isExpanded ? '' : '-rotate-90',\n )}\n aria-hidden\n />\n <Text size=\"sm\" className=\"min-w-0 truncate font-medium\">\n {objectItemSummary(field.fields, record, i)}\n </Text>\n </button>\n {!readOnly ? (\n <ItemOverflowMenu\n index={i}\n count={items.length}\n onMove={arr.move}\n onRemove={() => arr.removeAt(i)}\n />\n ) : null}\n </Row>\n {isExpanded ? (\n <div className=\"px-3 pb-3\">\n <ObjectItemForm\n fields={field.fields}\n value={record}\n readOnly={readOnly}\n idPrefix={`${id}-${i}`}\n onChange={(updated) => arr.setItem(i, updated)}\n />\n </div>\n ) : null}\n </Card>\n )\n })\n )}\n {!readOnly ? (\n <Button variant=\"outline\" size=\"sm\" onClick={onAdd}>\n <Plus className=\"size-3\" /> {translate('cms.field.addItem')}\n </Button>\n ) : null}\n </Stack>\n </ArrayDepthContext.Provider>\n )\n}\n\n/**\n * (C) A compact editable table for a FLAT object array — columns are the scalar\n * subfields, one row per item. Kills the card-stack sprawl for the commonest case\n * (option lists, opening hours, social links). Drag-reorder + an overflow menu per\n * row; cells reuse {@link FieldControl} so each subfield keeps its native control.\n */\nfunction ObjectTableField({ field, value, onChange, readOnly, id, depth }: ObjectArrayProps) {\n const arr = useObjectArray(field, value, onChange)\n const { items, keys } = arr\n const cols = field.fields\n const span = cols.length + (readOnly ? 0 : 2)\n return (\n <div className={cn('overflow-hidden rounded-md border border-border border-l-2', depthRail(depth), depthTint(depth))}>\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border/60 bg-muted/30 text-left\">\n {!readOnly ? <th className=\"w-7\" /> : null}\n {cols.map((c) => (\n <th key={c.name} className=\"px-2 py-1.5 text-xs font-medium text-muted-foreground\">\n {fieldLabel(c)}\n {c.validation?.required ? <span className=\"text-destructive\"> *</span> : null}\n </th>\n ))}\n {!readOnly ? <th className=\"w-9\" /> : null}\n </tr>\n </thead>\n <tbody>\n {items.length === 0 ? (\n <tr>\n <td colSpan={span} className=\"px-2 py-2 text-muted-foreground\">\n <Text size=\"sm\" tone=\"subtle\">\n {translate('cms.field.noItems')}\n </Text>\n </td>\n </tr>\n ) : (\n items.map((item, i) => {\n const key = keys[i] ?? i\n const record = asRecord(item)\n return (\n <tr\n key={key}\n onDragOver={(e) => {\n if (arr.dragIndex === null) return\n e.preventDefault()\n if (arr.overIndex !== i) arr.setOverIndex(i)\n }}\n onDrop={() => arr.drop(i)}\n className={cn(\n 'border-b border-border/40 align-top last:border-0',\n arr.dragIndex === i ? 'opacity-50' : '',\n arr.overIndex === i && arr.dragIndex !== null && arr.dragIndex !== i\n ? 'bg-primary/5'\n : '',\n )}\n >\n {!readOnly ? (\n <td className=\"px-1 py-1\">\n <span\n draggable\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(i))\n arr.setDragIndex(i)\n }}\n onDragEnd={arr.endDrag}\n aria-label={translate('cms.field.dragToReorder')}\n className=\"inline-flex cursor-grab text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing\"\n >\n <GripVertical className=\"size-3.5\" />\n </span>\n </td>\n ) : null}\n {cols.map((c) => (\n <td key={c.name} className=\"px-2 py-1\">\n <FieldControl\n id={`${id}-${i}-${c.name}`}\n field={c}\n value={record[c.name]}\n readOnly={readOnly}\n onChange={(next) => {\n const updated = { ...record }\n if (next === undefined) delete updated[c.name]\n else updated[c.name] = next\n arr.setItem(i, updated)\n }}\n />\n </td>\n ))}\n {!readOnly ? (\n <td className=\"px-1 py-1\">\n <ItemOverflowMenu\n index={i}\n count={items.length}\n onMove={arr.move}\n onRemove={() => arr.removeAt(i)}\n />\n </td>\n ) : null}\n </tr>\n )\n })\n )}\n </tbody>\n </table>\n {!readOnly ? (\n <div className=\"border-t border-border/60 p-1.5\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => arr.addItem()}>\n <Plus className=\"size-3\" /> {translate('common.add')}\n </Button>\n </div>\n ) : null}\n </div>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"object-array-field.js","sourceRoot":"","sources":["../../../src/components/cms/object-array-field.tsx"],"names":[],"mappings":"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","sourcesContent":["import { ChevronDown, ChevronUp, GripVertical, MoreHorizontal, Plus, Trash2 } from 'lucide-react'\nimport { createContext, useContext, useEffect, useRef, useState } from 'react'\nimport type { FieldDef, ObjectFieldDef } from '@elytracms/core/cms-core'\nimport { isFieldHidden } from '@elytracms/core/cms-core'\nimport {\n Button,\n Card,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n FIELD_PATH_ATTR,\n Field,\n Row,\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 { fieldLabel } from './cms-labels'\nimport {\n FieldPathContext,\n isPathWithin,\n useFieldFocusRequest,\n useFieldPath,\n} from './field-anchors'\nimport { FieldControl } from './field-control'\nimport { depthRail, depthTint, isTabularObjectType, objectItemSummary, reorder } from './field-control-lib'\n\n/**\n * The object / repeater field controls (EC-253, legibility-rebuilt EC-305) —\n * split from `field-control.tsx` (EC-330). {@link ObjectField} dispatches by\n * shape (single card / editable table / card list); {@link ObjectItemForm} is\n * the recursive subfield form the asset-field family reuses for per-use\n * sub-fields and asset metadata. Cells and subfields render through\n * `FieldControl`, so any subfield type — including a nested repeater — works\n * for free.\n *\n * EC-443 path anchors: inside a stamped surface (a non-null `FieldPathContext`,\n * provided by the document form) every item card / table row / subfield row\n * stamps its `FIELD_PATH_ATTR` anchor (`links/3`, `links/3/badge/text` — the\n * ONE convention defined on the attribute in `ui/field.tsx`), a collapsed card\n * auto-expands when the active focus request targets a path within it, and the\n * exact requested control ring-highlights. All decisions come from the pure\n * helpers in `field-anchors.ts`.\n */\n\n/** The EC-443 ring on the exact jump target (mirrors the top-level row ring). */\nconst FOCUS_RING_CLASS = 'rounded-md bg-primary/5 ring-2 ring-primary/70'\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {}\n}\n\n// EC-305: nested-array depth, propagated via context so each array level can encode\n// its depth (rail colour + tint) without prop-drilling through FieldControl's many\n// branches. The detail editor renders top-level fields with the default depth 0.\nconst ArrayDepthContext = createContext(0)\nconst useArrayDepth = () => useContext(ArrayDepthContext)\n\n/**\n * Shared array state for an object repeater (EC-253/EC-294/EC-305): the value-only\n * items + a parallel stable-key list kept in lockstep through every structural op\n * (the EC-253 C2 key↔value lock), add/remove/move, and native drag-reorder. Used by\n * both the card list (B) and the table (C) so they behave identically.\n */\nfunction useObjectArray(field: ObjectFieldDef, value: unknown, onChange: (value: unknown) => void) {\n const items = Array.isArray(value) ? (value as Record<string, unknown>[]) : []\n const seq = useRef(0)\n const keysRef = useRef<number[]>([])\n if (keysRef.current.length !== items.length) {\n keysRef.current = items.map((_, i) => keysRef.current[i] ?? seq.current++)\n }\n const keys = keysRef.current\n const commit = (nextItems: Record<string, unknown>[], nextKeys: number[]) => {\n keysRef.current = nextKeys\n onChange(nextItems)\n }\n const move = (from: number, to: number) => commit(reorder(items, from, to), reorder(keys, from, to))\n const removeAt = (i: number) =>\n commit(items.filter((_, j) => j !== i), keys.filter((_, j) => j !== i))\n const addItem = (): number => {\n const seed: Record<string, unknown> = {}\n for (const sub of field.fields) if (sub.default !== undefined) seed[sub.name] = sub.default\n const key = seq.current++\n commit([...items, seed], [...keys, key])\n return key\n }\n const setItem = (i: number, updated: Record<string, unknown>) => {\n const nextItems = items.slice()\n nextItems[i] = updated\n commit(nextItems, keys)\n }\n const [dragIndex, setDragIndex] = useState<number | null>(null)\n const [overIndex, setOverIndex] = useState<number | null>(null)\n const endDrag = () => {\n setDragIndex(null)\n setOverIndex(null)\n }\n const drop = (to: number) => {\n if (dragIndex !== null && dragIndex !== to) move(dragIndex, to)\n endDrag()\n }\n return { items, keys, move, removeAt, addItem, setItem, dragIndex, overIndex, setDragIndex, setOverIndex, endDrag, drop }\n}\n\n/**\n * (E) Chrome reduction: the per-row move/remove controls collapse into one hover/\n * focus overflow menu, so a row reads as content, not a six-button toolbar. Drag is\n * the primary reorder; the arrows stay here for keyboard/a11y.\n */\nfunction ItemOverflowMenu({\n index,\n count,\n onMove,\n onRemove,\n}: {\n index: number\n count: number\n onMove: (from: number, to: number) => void\n onRemove: () => void\n}) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" aria-label={translate('cms.field.itemActions')}>\n <MoreHorizontal className=\"size-3.5\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem disabled={index === 0} onClick={() => onMove(index, index - 1)}>\n <ChevronUp /> {translate('cms.field.moveUp')}\n </DropdownMenuItem>\n <DropdownMenuItem disabled={index === count - 1} onClick={() => onMove(index, index + 1)}>\n <ChevronDown /> {translate('cms.field.moveDown')}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={onRemove}>\n <Trash2 /> {translate('common.remove')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\n/**\n * The nested subfield form for one object item (EC-253). Reuses {@link FieldControl}\n * recursively, so any subfield type — including a nested object/repeater — works for\n * free. Writing a subfield merges it back into the item and bubbles the new item up.\n * EC-443: each subfield row stamps its path anchor (`<itemPath>/<sub>`), rings when\n * it is the exact focus target, and provides its path down for deeper nesting.\n */\nexport function ObjectItemForm({\n fields,\n value,\n onChange,\n readOnly,\n idPrefix,\n}: {\n fields: readonly FieldDef[]\n value: Record<string, unknown>\n onChange: (value: Record<string, unknown>) => void\n readOnly: boolean\n idPrefix: string\n}) {\n const itemPath = useFieldPath()\n const focus = useFieldFocusRequest()\n return (\n <Stack gap=\"3\" className=\"mt-2\">\n {fields.map((sub) => {\n // EC-273: a conditionally-hidden subfield (its predicate keys off the item's\n // own sibling values) is omitted — e.g. a discriminated link's `href` shows\n // only when `linkType === 'href'`. Re-evaluated as the item is edited.\n if (isFieldHidden(sub, { values: value })) return null\n const subId = `${idPrefix}-${sub.name}`\n const subPath = itemPath === null ? undefined : `${itemPath}/${sub.name}`\n return (\n <Field\n key={sub.name}\n htmlFor={subId}\n fieldPath={subPath}\n className={cn(\n 'transition-shadow',\n subPath !== undefined && focus?.path === subPath && `${FOCUS_RING_CLASS} p-2`,\n )}\n hint={localizedLabel(sub.form?.description) || undefined}\n label={\n <Row gap=\"2\">\n <span>{fieldLabel(sub)}</span>\n {sub.validation?.required ? <span className=\"text-destructive\">*</span> : null}\n </Row>\n }\n >\n <FieldPathContext.Provider value={subPath ?? null}>\n <FieldControl\n id={subId}\n field={sub}\n value={value[sub.name]}\n readOnly={readOnly}\n onChange={(next) => {\n const updated = { ...value }\n if (next === undefined) delete updated[sub.name]\n else updated[sub.name] = next\n onChange(updated)\n }}\n />\n </FieldPathContext.Provider>\n </Field>\n )\n })}\n </Stack>\n )\n}\n\n/**\n * Object / repeater field control (EC-253), legibility-rebuilt (EC-305). A single\n * object (`multiple: false`) renders a depth-encoded card; an array (`'many'`)\n * dispatches by shape: a **flat** object type (all scalar subfields) → a compact\n * editable TABLE (C); a richer/nested type → a card list with depth encoding (B),\n * summary-first collapse (D), and reduced per-row chrome (E). Editing stays in the\n * shared field form — no canvas escape (unlike `blocks`) — so props and document\n * fields share this control. Depth flows via {@link ArrayDepthContext}.\n */\nexport function ObjectField({\n field,\n value,\n onChange,\n readOnly,\n id,\n}: {\n field: ObjectFieldDef\n value: unknown\n onChange: (value: unknown) => void\n readOnly: boolean\n id: string\n}) {\n const depth = useArrayDepth()\n if (field.multiple === false) {\n return (\n <Card className={cn('border-l-2 p-3', depthRail(depth), depthTint(depth))}>\n <ArrayDepthContext.Provider value={depth + 1}>\n <ObjectItemForm\n fields={field.fields}\n value={asRecord(value)}\n readOnly={readOnly}\n idPrefix={id}\n onChange={onChange}\n />\n </ArrayDepthContext.Provider>\n </Card>\n )\n }\n const props = { field, value, onChange, readOnly, id, depth }\n return isTabularObjectType(field) ? <ObjectTableField {...props} /> : <ObjectCardList {...props} />\n}\n\ninterface ObjectArrayProps {\n field: ObjectFieldDef\n value: unknown\n onChange: (value: unknown) => void\n readOnly: boolean\n id: string\n depth: number\n}\n\n/**\n * (B + D + E) The card list for a nested/rich object array: depth-encoded cards\n * (coloured rail + tint), items collapsed by default to a scannable summary outline\n * (D), accordion expansion (open one → collapse siblings), and the per-row controls\n * collapsed into one overflow menu (E). Drag-to-reorder; arrows live in the menu for\n * a11y. Nested arrays render one depth deeper via the context provider.\n */\nfunction ObjectCardList({ field, value, onChange, readOnly, id, depth }: ObjectArrayProps) {\n const arr = useObjectArray(field, value, onChange)\n const { items, keys } = arr\n const parentPath = useFieldPath()\n const focus = useFieldFocusRequest()\n // (D) Default COLLAPSED: track which keys are EXPANDED (empty = all collapsed).\n // (B) Accordion: expanding one collapses the siblings.\n const [expandedKeys, setExpandedKeys] = useState<ReadonlySet<number>>(() => new Set())\n const toggle = (key: number) =>\n setExpandedKeys((prev) => {\n if (prev.has(key)) {\n const next = new Set(prev)\n next.delete(key)\n return next\n }\n return new Set([key])\n })\n const allExpanded = items.length > 0 && keys.every((k) => expandedKeys.has(k))\n const onAdd = () => setExpandedKeys(new Set([arr.addItem()]))\n // EC-443: a jump-to-field targeting a path INSIDE one of these items expands\n // that item (accordion semantics, like a manual open) so the deeper anchors can\n // render — nested levels cascade, each level's effect firing once its card\n // mounts. Keyed on the request nonce so re-clicking the same issue re-expands\n // a manually re-collapsed item.\n const focusPath = focus?.path\n const focusNonce = focus?.nonce\n useEffect(() => {\n if (parentPath === null || focusPath === undefined) return\n const index = items.findIndex((_, i) => isPathWithin(`${parentPath}/${i}`, focusPath))\n if (index < 0) return\n const key = keys[index]\n if (key !== undefined) setExpandedKeys(new Set([key]))\n // Deps: keys/items stay in lockstep (the C2 key↔value lock) — `items.length`\n // captures the structure; item-content identity must NOT re-trigger expansion.\n }, [focusNonce, focusPath, parentPath, items.length])\n return (\n <ArrayDepthContext.Provider value={depth + 1}>\n <Stack gap=\"2\">\n {items.length > 1 && !readOnly ? (\n <Row justify=\"end\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setExpandedKeys(allExpanded ? new Set() : new Set(keys))}\n >\n {translate(allExpanded ? 'cms.field.collapseAll' : 'cms.field.expandAll')}\n </Button>\n </Row>\n ) : null}\n {items.length === 0 ? (\n <Text size=\"sm\" tone=\"subtle\">\n {translate('cms.field.noItems')}\n </Text>\n ) : (\n items.map((item, i) => {\n // keysRef is reconciled to items.length, so keys[i] is always present;\n // `?? i` only satisfies noUncheckedIndexedAccess (never taken at runtime).\n const key = keys[i] ?? i\n const record = asRecord(item)\n const isExpanded = expandedKeys.has(key)\n // EC-443: the item's path anchor — stamped even while collapsed, so a\n // degraded jump can still land (and ring) on the closed card.\n const itemPath = parentPath === null ? undefined : `${parentPath}/${i}`\n return (\n <Card\n key={key}\n {...(itemPath !== undefined ? { [FIELD_PATH_ATTR]: itemPath } : {})}\n onDragOver={(e) => {\n if (arr.dragIndex === null) return\n e.preventDefault()\n if (arr.overIndex !== i) arr.setOverIndex(i)\n }}\n onDrop={() => arr.drop(i)}\n className={cn(\n 'border-l-2 p-0',\n depthRail(depth),\n depthTint(depth),\n arr.dragIndex === i ? 'opacity-50' : '',\n arr.overIndex === i && arr.dragIndex !== null && arr.dragIndex !== i\n ? 'border-l-primary ring-1 ring-primary/40'\n : '',\n itemPath !== undefined && focus?.path === itemPath\n ? 'ring-2 ring-primary/70'\n : '',\n )}\n >\n <Row className=\"select-none border-b border-border/60 bg-muted/20 px-2 py-1.5\">\n {!readOnly ? (\n <span\n draggable\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(i))\n arr.setDragIndex(i)\n }}\n onDragEnd={arr.endDrag}\n aria-label={translate('cms.field.dragToReorder')}\n className=\"cursor-grab text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing\"\n >\n <GripVertical className=\"size-3.5\" />\n </span>\n ) : null}\n <button\n type=\"button\"\n onClick={() => toggle(key)}\n aria-expanded={isExpanded}\n className=\"flex min-w-0 flex-1 items-center gap-1.5 text-left\"\n >\n <ChevronDown\n className={cn(\n 'size-3.5 shrink-0 text-muted-foreground transition-transform',\n isExpanded ? '' : '-rotate-90',\n )}\n aria-hidden\n />\n <Text size=\"sm\" className=\"min-w-0 truncate font-medium\">\n {objectItemSummary(field.fields, record, i)}\n </Text>\n </button>\n {!readOnly ? (\n <ItemOverflowMenu\n index={i}\n count={items.length}\n onMove={arr.move}\n onRemove={() => arr.removeAt(i)}\n />\n ) : null}\n </Row>\n {isExpanded ? (\n <div className=\"px-3 pb-3\">\n <FieldPathContext.Provider value={itemPath ?? null}>\n <ObjectItemForm\n fields={field.fields}\n value={record}\n readOnly={readOnly}\n idPrefix={`${id}-${i}`}\n onChange={(updated) => arr.setItem(i, updated)}\n />\n </FieldPathContext.Provider>\n </div>\n ) : null}\n </Card>\n )\n })\n )}\n {!readOnly ? (\n <Button variant=\"outline\" size=\"sm\" onClick={onAdd}>\n <Plus className=\"size-3\" /> {translate('cms.field.addItem')}\n </Button>\n ) : null}\n </Stack>\n </ArrayDepthContext.Provider>\n )\n}\n\n/**\n * (C) A compact editable table for a FLAT object array — columns are the scalar\n * subfields, one row per item. Kills the card-stack sprawl for the commonest case\n * (option lists, opening hours, social links). Drag-reorder + an overflow menu per\n * row; cells reuse {@link FieldControl} so each subfield keeps its native control.\n */\nfunction ObjectTableField({ field, value, onChange, readOnly, id, depth }: ObjectArrayProps) {\n const arr = useObjectArray(field, value, onChange)\n const { items, keys } = arr\n // EC-443: rows/cells stamp path anchors too (a tabular type is flat, so the\n // cell — `links/3/href` — is always the deepest possible anchor here).\n const parentPath = useFieldPath()\n const focus = useFieldFocusRequest()\n const cols = field.fields\n const span = cols.length + (readOnly ? 0 : 2)\n return (\n <div className={cn('overflow-hidden rounded-md border border-border border-l-2', depthRail(depth), depthTint(depth))}>\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border/60 bg-muted/30 text-left\">\n {!readOnly ? <th className=\"w-7\" /> : null}\n {cols.map((c) => (\n <th key={c.name} className=\"px-2 py-1.5 text-xs font-medium text-muted-foreground\">\n {fieldLabel(c)}\n {c.validation?.required ? <span className=\"text-destructive\"> *</span> : null}\n </th>\n ))}\n {!readOnly ? <th className=\"w-9\" /> : null}\n </tr>\n </thead>\n <tbody>\n {items.length === 0 ? (\n <tr>\n <td colSpan={span} className=\"px-2 py-2 text-muted-foreground\">\n <Text size=\"sm\" tone=\"subtle\">\n {translate('cms.field.noItems')}\n </Text>\n </td>\n </tr>\n ) : (\n items.map((item, i) => {\n const key = keys[i] ?? i\n const record = asRecord(item)\n const itemPath = parentPath === null ? undefined : `${parentPath}/${i}`\n return (\n <tr\n key={key}\n {...(itemPath !== undefined ? { [FIELD_PATH_ATTR]: itemPath } : {})}\n onDragOver={(e) => {\n if (arr.dragIndex === null) return\n e.preventDefault()\n if (arr.overIndex !== i) arr.setOverIndex(i)\n }}\n onDrop={() => arr.drop(i)}\n className={cn(\n 'border-b border-border/40 align-top last:border-0',\n arr.dragIndex === i ? 'opacity-50' : '',\n arr.overIndex === i && arr.dragIndex !== null && arr.dragIndex !== i\n ? 'bg-primary/5'\n : '',\n itemPath !== undefined && focus?.path === itemPath\n ? 'ring-2 ring-inset ring-primary/70'\n : '',\n )}\n >\n {!readOnly ? (\n <td className=\"px-1 py-1\">\n <span\n draggable\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(i))\n arr.setDragIndex(i)\n }}\n onDragEnd={arr.endDrag}\n aria-label={translate('cms.field.dragToReorder')}\n className=\"inline-flex cursor-grab text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing\"\n >\n <GripVertical className=\"size-3.5\" />\n </span>\n </td>\n ) : null}\n {cols.map((c) => {\n const cellPath = itemPath === undefined ? undefined : `${itemPath}/${c.name}`\n return (\n <td\n key={c.name}\n {...(cellPath !== undefined ? { [FIELD_PATH_ATTR]: cellPath } : {})}\n className={cn(\n 'px-2 py-1',\n cellPath !== undefined && focus?.path === cellPath\n ? 'bg-primary/5 ring-2 ring-inset ring-primary/70'\n : '',\n )}\n >\n <FieldControl\n id={`${id}-${i}-${c.name}`}\n field={c}\n value={record[c.name]}\n readOnly={readOnly}\n onChange={(next) => {\n const updated = { ...record }\n if (next === undefined) delete updated[c.name]\n else updated[c.name] = next\n arr.setItem(i, updated)\n }}\n />\n </td>\n )\n })}\n {!readOnly ? (\n <td className=\"px-1 py-1\">\n <ItemOverflowMenu\n index={i}\n count={items.length}\n onMove={arr.move}\n onRemove={() => arr.removeAt(i)}\n />\n </td>\n ) : null}\n </tr>\n )\n })\n )}\n </tbody>\n </table>\n {!readOnly ? (\n <div className=\"border-t border-border/60 p-1.5\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => arr.addItem()}>\n <Plus className=\"size-3\" /> {translate('common.add')}\n </Button>\n </div>\n ) : null}\n </div>\n )\n}\n"]}
|
|
@@ -5,12 +5,13 @@ import type { CollectionViewCapabilities } from '@elytracms/studio/lib/collectio
|
|
|
5
5
|
* minus `set-field` (a bulk-only composer over a multi-row selection — a single
|
|
6
6
|
* row edits its fields directly in the table), plus `open` (jump to the detail
|
|
7
7
|
* editor — the row's own affordance the primary-column link already offers, but
|
|
8
|
-
* explicit in the menu for a keyboard/menu-driven workflow)
|
|
8
|
+
* explicit in the menu for a keyboard/menu-driven workflow), plus `duplicate`
|
|
9
|
+
* (EC-442 — copy the draft into a fresh draft document).
|
|
9
10
|
*/
|
|
10
|
-
export type RowAction = 'open' | 'publish' | 'unpublish' | 'delete';
|
|
11
|
+
export type RowAction = 'open' | 'duplicate' | 'publish' | 'unpublish' | 'delete';
|
|
11
12
|
export interface RowActionsInput {
|
|
12
13
|
/** The rail's capability matrix (AD-19) — the SAME gate the list/edit shells use. */
|
|
13
|
-
capabilities: Pick<CollectionViewCapabilities, 'publish' | 'remove'>;
|
|
14
|
+
capabilities: Pick<CollectionViewCapabilities, 'publish' | 'remove' | 'duplicate'>;
|
|
14
15
|
/** Whether this row has a navigable detail route (a rail with no detail surface omits it). */
|
|
15
16
|
hasDetailPath: boolean;
|
|
16
17
|
/** Whether this document IS published — decides `publish` vs `unpublish`. */
|
|
@@ -24,5 +25,11 @@ export interface RowActionsInput {
|
|
|
24
25
|
* rail (EC-240), redirects, and any future `CollectionViewSource` without a
|
|
25
26
|
* bespoke per-rail menu. An empty result means the row menu itself renders
|
|
26
27
|
* nothing (never an empty, useless trigger).
|
|
28
|
+
*
|
|
29
|
+
* `duplicate` (EC-442, amended same day) is gated on its OWN capability flag
|
|
30
|
+
* plus a detail surface to land on — never derived from `create`. The owner
|
|
31
|
+
* call (2026-07-17): CMS collections ONLY; every primitive rail declares
|
|
32
|
+
* `duplicate: false` (identities and uploads aren't copyable content;
|
|
33
|
+
* redirects deferred until requested as a product feature).
|
|
27
34
|
*/
|
|
28
35
|
export declare function rowActionsFor({ capabilities, hasDetailPath, published }: RowActionsInput): RowAction[];
|
|
@@ -6,11 +6,19 @@
|
|
|
6
6
|
* rail (EC-240), redirects, and any future `CollectionViewSource` without a
|
|
7
7
|
* bespoke per-rail menu. An empty result means the row menu itself renders
|
|
8
8
|
* nothing (never an empty, useless trigger).
|
|
9
|
+
*
|
|
10
|
+
* `duplicate` (EC-442, amended same day) is gated on its OWN capability flag
|
|
11
|
+
* plus a detail surface to land on — never derived from `create`. The owner
|
|
12
|
+
* call (2026-07-17): CMS collections ONLY; every primitive rail declares
|
|
13
|
+
* `duplicate: false` (identities and uploads aren't copyable content;
|
|
14
|
+
* redirects deferred until requested as a product feature).
|
|
9
15
|
*/
|
|
10
16
|
export function rowActionsFor({ capabilities, hasDetailPath, published }) {
|
|
11
17
|
const actions = [];
|
|
12
18
|
if (hasDetailPath)
|
|
13
19
|
actions.push('open');
|
|
20
|
+
if (capabilities.duplicate && hasDetailPath)
|
|
21
|
+
actions.push('duplicate');
|
|
14
22
|
if (capabilities.publish)
|
|
15
23
|
actions.push(published ? 'unpublish' : 'publish');
|
|
16
24
|
if (capabilities.remove)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"row-actions.js","sourceRoot":"","sources":["../../../src/components/cms/row-actions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"row-actions.js","sourceRoot":"","sources":["../../../src/components/cms/row-actions.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAmB;IACvF,MAAM,OAAO,GAAgB,EAAE,CAAA;IAC/B,IAAI,aAAa;QAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACvC,IAAI,YAAY,CAAC,SAAS,IAAI,aAAa;QAAE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACtE,IAAI,YAAY,CAAC,OAAO;QAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC3E,IAAI,YAAY,CAAC,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC/C,OAAO,OAAO,CAAA;AAChB,CAAC","sourcesContent":["import type { CollectionViewCapabilities } from '@elytracms/studio/lib/collection-view/collection-view-source'\n\n/**\n * EC-316 — the right-edge row `⋮` menu's action vocabulary: the SAME bulk-action\n * set the toolbar's selection actions offer (`bulk-actions.ts`'s `BulkAction`),\n * minus `set-field` (a bulk-only composer over a multi-row selection — a single\n * row edits its fields directly in the table), plus `open` (jump to the detail\n * editor — the row's own affordance the primary-column link already offers, but\n * explicit in the menu for a keyboard/menu-driven workflow), plus `duplicate`\n * (EC-442 — copy the draft into a fresh draft document).\n */\nexport type RowAction = 'open' | 'duplicate' | 'publish' | 'unpublish' | 'delete'\n\nexport interface RowActionsInput {\n /** The rail's capability matrix (AD-19) — the SAME gate the list/edit shells use. */\n capabilities: Pick<CollectionViewCapabilities, 'publish' | 'remove' | 'duplicate'>\n /** Whether this row has a navigable detail route (a rail with no detail surface omits it). */\n hasDetailPath: boolean\n /** Whether this document IS published — decides `publish` vs `unpublish`. */\n published: boolean\n}\n\n/**\n * The gated action list for one row (EC-316). Every entry mirrors a capability\n * the rail actually declares — a source without `publish` never offers\n * publish/unpublish, one without `remove` never offers delete, and a rail with\n * no detail surface never offers `open` — so the SAME menu serves the users\n * rail (EC-240), redirects, and any future `CollectionViewSource` without a\n * bespoke per-rail menu. An empty result means the row menu itself renders\n * nothing (never an empty, useless trigger).\n *\n * `duplicate` (EC-442, amended same day) is gated on its OWN capability flag\n * plus a detail surface to land on — never derived from `create`. The owner\n * call (2026-07-17): CMS collections ONLY; every primitive rail declares\n * `duplicate: false` (identities and uploads aren't copyable content;\n * redirects deferred until requested as a product feature).\n */\nexport function rowActionsFor({ capabilities, hasDetailPath, published }: RowActionsInput): RowAction[] {\n const actions: RowAction[] = []\n if (hasDetailPath) actions.push('open')\n if (capabilities.duplicate && hasDetailPath) actions.push('duplicate')\n if (capabilities.publish) actions.push(published ? 'unpublish' : 'publish')\n if (capabilities.remove) actions.push('delete')\n return actions\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CollectionDef, FieldDef } from '@elytracms/core/cms-core';
|
|
2
2
|
import type { CollectionViewSource } from '@elytracms/studio/lib/collection-view/collection-view-source';
|
|
3
|
+
import type { FieldFocusRequest } from './field-anchors.js';
|
|
3
4
|
/**
|
|
4
5
|
* EC-283 / EC-285 — where a jump-to-field lands, as a pure decision. A field in
|
|
5
6
|
* the reserved `sidebar` group renders in the Details inspector pane (open that
|
|
@@ -14,21 +15,36 @@ export declare function focusTarget(collection: CollectionDef, fieldName: string
|
|
|
14
15
|
tab: string;
|
|
15
16
|
} | null;
|
|
16
17
|
export interface FieldFocus {
|
|
17
|
-
/** The field ring-highlighted right now (or null). */
|
|
18
|
+
/** The top-level field ring-highlighted right now (or null). */
|
|
18
19
|
highlightedField: string | null;
|
|
20
|
+
/**
|
|
21
|
+
* The active nested focus request (EC-443): drives collapsed-array expansion
|
|
22
|
+
* and the ring on the exact nested control, via `FieldFocusRequestContext`.
|
|
23
|
+
*/
|
|
24
|
+
focusRequest: FieldFocusRequest | null;
|
|
19
25
|
/** The inspector sidebar's active pane, controlled so a jump can open Details. */
|
|
20
26
|
inspectorPaneId: string | undefined;
|
|
21
27
|
setInspectorPaneId: (id: string | undefined) => void;
|
|
22
|
-
/**
|
|
23
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Focus a field by anchor path (`links` or `links/3/badge/text` — the EC-443
|
|
30
|
+
* convention on `FIELD_PATH_ATTR`): switch to its tab/pane (+ locale), expand
|
|
31
|
+
* collapsed array items en route, scroll to the deepest available anchor, and
|
|
32
|
+
* ring-highlight it. Deepest existing anchor wins; the top-level field is the
|
|
33
|
+
* degradation floor.
|
|
34
|
+
*/
|
|
35
|
+
focusField: (fieldPath: string, localeHint?: string) => void;
|
|
24
36
|
}
|
|
25
37
|
/**
|
|
26
|
-
* EC-172 / EC-283 — the field-focus/highlight controller. Focusing a
|
|
27
|
-
* switches to its tab (or opens the Details pane for a sidebar field) and
|
|
28
|
-
* given locale,
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
38
|
+
* EC-172 / EC-283 / EC-443 — the field-focus/highlight controller. Focusing a
|
|
39
|
+
* field switches to its tab (or opens the Details pane for a sidebar field) and
|
|
40
|
+
* the given locale, then lands on the DEEPEST available anchor along the path
|
|
41
|
+
* (EC-443): nested paths publish a {@link FieldFocusRequest} (auto-expanding
|
|
42
|
+
* collapsed array items via context), retry-resolve the deepest stamped anchor,
|
|
43
|
+
* scroll it into view, and ring-highlight it — degrading prefix by prefix to the
|
|
44
|
+
* top-level field control, never a silent no-op. Shared by the reference
|
|
45
|
+
* deep-link (`focusPath`, `?field=`) and the Issues pane's jump-to-field. Owns
|
|
46
|
+
* the highlight + inspector-pane state and every scroll/clear timer (cleaned up
|
|
47
|
+
* on unmount, and cleared between back-to-back jumps).
|
|
32
48
|
*/
|
|
33
49
|
export declare function useFieldFocus(input: {
|
|
34
50
|
collection: CollectionDef;
|