@elytracms/studio 0.0.13 → 0.0.15

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 (94) hide show
  1. package/convex/cms.ts +8 -22
  2. package/convex/content.ts +3 -44
  3. package/convex/delivery.ts +8 -42
  4. package/convex/functions.ts +17 -2
  5. package/convex/members.ts +2 -2
  6. package/convex/referenceMaintenance.ts +4 -73
  7. package/convex/references.ts +4 -2
  8. package/convex/revalidate.ts +42 -0
  9. package/convex/schema.ts +17 -37
  10. package/convex/sync.ts +10 -42
  11. package/convex/triggers.ts +57 -0
  12. package/convex/webhooks.ts +3 -2
  13. package/dist/components/builder/builder-store.d.ts +85 -39
  14. package/dist/components/builder/builder-store.js +29 -125
  15. package/dist/components/builder/builder-store.js.map +1 -1
  16. package/dist/components/builder/canvas.js +23 -55
  17. package/dist/components/builder/canvas.js.map +1 -1
  18. package/dist/components/builder/clipboard-actions.js +3 -3
  19. package/dist/components/builder/clipboard-actions.js.map +1 -1
  20. package/dist/components/builder/composition-field-editor.js +13 -23
  21. package/dist/components/builder/composition-field-editor.js.map +1 -1
  22. package/dist/components/builder/insert-context.js +1 -1
  23. package/dist/components/builder/insert-context.js.map +1 -1
  24. package/dist/components/builder/page-tree.js +3 -4
  25. package/dist/components/builder/page-tree.js.map +1 -1
  26. package/dist/components/builder/property-inspector.js +4 -64
  27. package/dist/components/builder/property-inspector.js.map +1 -1
  28. package/dist/components/cms/cell.d.ts +0 -4
  29. package/dist/components/cms/cell.js +1 -5
  30. package/dist/components/cms/cell.js.map +1 -1
  31. package/dist/components/cms/cms-store.d.ts +1 -1
  32. package/dist/components/cms/cms-store.js +4 -9
  33. package/dist/components/cms/cms-store.js.map +1 -1
  34. package/dist/components/cms/collection-table.js +1 -1
  35. package/dist/components/cms/collection-table.js.map +1 -1
  36. package/dist/components/cms/detail-editor.js +2 -2
  37. package/dist/components/cms/detail-editor.js.map +1 -1
  38. package/dist/components/cms/doc-state.d.ts +0 -5
  39. package/dist/components/cms/doc-state.js +1 -7
  40. package/dist/components/cms/doc-state.js.map +1 -1
  41. package/dist/components/cms/editable-cell.js +1 -1
  42. package/dist/components/cms/editable-cell.js.map +1 -1
  43. package/dist/components/collab/collab-context.d.ts +6 -14
  44. package/dist/components/collab/collab-context.js +3 -12
  45. package/dist/components/collab/collab-context.js.map +1 -1
  46. package/dist/components/collab/collab-seed.d.ts +7 -19
  47. package/dist/components/collab/collab-seed.js +9 -31
  48. package/dist/components/collab/collab-seed.js.map +1 -1
  49. package/dist/components/components/registry-browser.js +6 -12
  50. package/dist/components/components/registry-browser.js.map +1 -1
  51. package/dist/components/guards.d.ts +0 -9
  52. package/dist/components/guards.js +0 -12
  53. package/dist/components/guards.js.map +1 -1
  54. package/dist/components/section-state.d.ts +0 -2
  55. package/dist/components/section-state.js +0 -9
  56. package/dist/components/section-state.js.map +1 -1
  57. package/dist/components/section-surface.d.ts +3 -7
  58. package/dist/components/section-surface.js +5 -12
  59. package/dist/components/section-surface.js.map +1 -1
  60. package/dist/components/sections.d.ts +0 -1
  61. package/dist/components/sections.js +0 -10
  62. package/dist/components/sections.js.map +1 -1
  63. package/dist/components/studio-project-screen.js +13 -14
  64. package/dist/components/studio-project-screen.js.map +1 -1
  65. package/dist/components/studio-shell.d.ts +0 -4
  66. package/dist/components/studio-shell.js +1 -5
  67. package/dist/components/studio-shell.js.map +1 -1
  68. package/dist/lib/operations/graph-commands.d.ts +2 -6
  69. package/dist/lib/operations/graph-commands.js +1 -2
  70. package/dist/lib/operations/graph-commands.js.map +1 -1
  71. package/dist/lib/operations/index.d.ts +0 -2
  72. package/dist/lib/operations/index.js +0 -2
  73. package/dist/lib/operations/index.js.map +1 -1
  74. package/dist/lib/operations/session-hydration.d.ts +14 -24
  75. package/dist/lib/operations/session-hydration.js +15 -34
  76. package/dist/lib/operations/session-hydration.js.map +1 -1
  77. package/dist/lib/persistence/convex-adapter.d.ts +1 -3
  78. package/dist/lib/persistence/convex-adapter.js +1 -154
  79. package/dist/lib/persistence/convex-adapter.js.map +1 -1
  80. package/dist/lib/persona/labels.js +0 -2
  81. package/dist/lib/persona/labels.js.map +1 -1
  82. package/dist/lib/references/reference-model.d.ts +0 -16
  83. package/dist/lib/references/reference-model.js +2 -54
  84. package/dist/lib/references/reference-model.js.map +1 -1
  85. package/dist/lib/references/references-store.js +3 -4
  86. package/dist/lib/references/references-store.js.map +1 -1
  87. package/dist/lib/registry/index.d.ts +0 -16
  88. package/dist/lib/registry/index.js +0 -15
  89. package/dist/lib/registry/index.js.map +1 -1
  90. package/dist/lib/webhooks/tags.js +2 -16
  91. package/dist/lib/webhooks/tags.js.map +1 -1
  92. package/package.json +3 -2
  93. package/convex/graphs.ts +0 -55
  94. package/convex/publishing.ts +0 -108
@@ -1,15 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { EyeOff } from 'lucide-react';
3
2
  import { useEffect, useState } from 'react';
4
- import { conditionOperatorSchema, staticProp } from '@elytracms/core/project-graph';
5
- import { pathFromToken } from '@elytracms/core/data-binding';
3
+ import { staticProp } from '@elytracms/core/project-graph';
6
4
  import { manifestSlots } from '@elytracms/core/component-registry';
7
5
  import { fieldValueValidator } from '@elytracms/core/cms-core';
8
6
  import { getStudioRegistry } from '@elytracms/studio/lib/registry';
9
- import { useData } from '@elytracms/studio/lib/data';
10
- import { Badge, Button, Code, Field, Input, InspectorSection, PanelHeader, Row, Select, Spacer, Stack, Text, } from '@elytracms/studio/ui';
7
+ import { Badge, Code, Field, Input, InspectorSection, PanelHeader, Row, Select, Spacer, Stack, Text, } from '@elytracms/studio/ui';
11
8
  import { humanizeName } from '@elytracms/studio/lib/utils';
12
- import { componentDisplayName, conditionOperatorLabel } from '@elytracms/studio/lib/persona/labels';
9
+ import { componentDisplayName } from '@elytracms/studio/lib/persona/labels';
13
10
  import { FieldControl } from '../cms/field-control';
14
11
  import { useBuilder } from './builder-store';
15
12
  import { LayoutSection, layoutManagedPropNames } from './layout-inspector';
@@ -38,7 +35,7 @@ function SettingsTab({ node, manifest, }) {
38
35
  return (_jsxs(_Fragment, { children: [_jsx(LayoutSection, { node: node }), !manifest ? (_jsxs("div", { className: "p-3", children: [_jsx(Badge, { variant: "error", children: "unknown component" }), _jsx(Text, { size: "xs", tone: "muted", className: "mt-2", children: "No manifest is registered for this component, so its props can't be edited." })] })) : (_jsx(InspectorSection, { title: "Props", children: props.length === 0 ? (_jsx(Text, { size: "xs", tone: "subtle", children: "No editable props." })) : (_jsx(Stack, { gap: "4", children: props.map(([name, spec]) => (
39
36
  // Key by node id so per-node local control state never leaks
40
37
  // across a selection change to a same-named prop.
41
- _jsx(PropField, { node: node, name: name, spec: spec }, `${node.id}:${name}`))) })) })), _jsx(InspectorSection, { title: "Condition", children: _jsx(ConditionEditor, { node: node }) }), slots.length > 0 ? (_jsxs(InspectorSection, { title: "Slots", children: [_jsx(Stack, { gap: "1", children: slots.map((slot) => {
38
+ _jsx(PropField, { node: node, name: name, spec: spec }, `${node.id}:${name}`))) })) })), slots.length > 0 ? (_jsxs(InspectorSection, { title: "Slots", children: [_jsx(Stack, { gap: "1", children: slots.map((slot) => {
42
39
  const count = node.slots?.[slot.name]?.length ?? 0;
43
40
  const missing = slot.required && count === 0;
44
41
  return (_jsxs(Row, { gap: "2", children: [_jsx(Text, { size: "xs", title: slot.name, children: humanizeName(slot.name) }), slot.required ? (_jsx(Badge, { variant: missing ? 'error' : 'outline', children: "required" })) : null, _jsx(Spacer, {}), _jsx(Text, { size: "xs", tone: "subtle", mono: true, children: count })] }, slot.name));
@@ -173,61 +170,4 @@ function JsonControl({ id, current, onSet, }) {
173
170
  }
174
171
  }, className: "flex w-full rounded-md border border-input bg-background px-2.5 py-1.5 font-mono text-xs text-foreground shadow-sm focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40 outline-none" }), error ? (_jsx(Text, { size: "xs", className: "text-destructive", children: error })) : null] }));
175
172
  }
176
- /** Plain-language label for a stored data path ("item 1 → title") — no raw syntax. */
177
- function friendlyPathLabel(token) {
178
- const path = pathFromToken(token);
179
- if (path === undefined)
180
- return 'this data';
181
- if (path.length === 0)
182
- return 'Everything';
183
- return path
184
- .map((seg) => (/^\d+$/.test(seg) ? `entry ${Number(seg) + 1}` : humanizeName(seg)))
185
- .join(' → ');
186
- }
187
- /** Edit a node's render condition (EC-088): source field + operator + comparison value. */
188
- function ConditionEditor({ node }) {
189
- const builder = useBuilder();
190
- const data = useData();
191
- const condition = node.condition;
192
- const firstSource = data.sources[0];
193
- if (!condition) {
194
- return (_jsxs(Stack, { gap: "2", children: [_jsx(Text, { size: "xs", tone: "subtle", children: "This node always renders. Add a condition to gate it on a data value." }), _jsxs(Button, { size: "sm", variant: "outline", className: "w-fit", disabled: !firstSource, onClick: () => firstSource &&
195
- builder.dispatch({
196
- type: 'setCondition',
197
- id: node.id,
198
- condition: {
199
- source: { sourceId: firstSource.id, token: '/', mode: 'value' },
200
- operator: 'truthy',
201
- },
202
- }), children: [_jsx(EyeOff, {}), " Add condition"] })] }));
203
- }
204
- const updateCondition = (patch) => builder.dispatch({ type: 'setCondition', id: node.id, condition: { ...condition, ...patch } });
205
- const updateSource = (patch) => updateCondition({ source: { ...condition.source, ...patch } });
206
- const tokens = data.tokensOf(condition.source.sourceId);
207
- const source = data.getSource(condition.source.sourceId);
208
- const needsValue = !['truthy', 'exists'].includes(condition.operator);
209
- const result = data.resolveCondition(condition);
210
- const pass = result.kind === 'condition' ? result.pass : false;
211
- const issue = result.kind === 'issue' ? result.issue : null;
212
- return (_jsxs(Stack, { gap: "2", children: [_jsx(Field, { label: "Source", htmlFor: `cond-src-${node.id}`, children: _jsxs(Select, { id: `cond-src-${node.id}`, value: condition.source.sourceId, onChange: (e) => updateSource({ sourceId: e.target.value, token: '/' }), children: [data.sources.map((s) => (_jsx("option", { value: s.id, children: s.label }, s.id))), !source ? (_jsx("option", { value: condition.source.sourceId, title: condition.source.sourceId, children: "Missing data source" })) : null] }) }), _jsxs(Row, { gap: "2", children: [_jsx(Field, { label: "Field", htmlFor: `cond-token-${node.id}`, className: "min-w-0 flex-1", children: _jsxs(Select, { id: `cond-token-${node.id}`, value: condition.source.token, onChange: (e) => updateSource({ token: e.target.value }), children: [tokens.map((t) => (_jsx("option", { value: t, children: friendlyPathLabel(t) }, t))), !tokens.includes(condition.source.token) ? (_jsx("option", { value: condition.source.token, children: friendlyPathLabel(condition.source.token) })) : null] }) }), _jsx(Field, { label: "Operator", htmlFor: `cond-op-${node.id}`, className: "w-28", children: _jsx(Select, { id: `cond-op-${node.id}`, value: condition.operator, onChange: (e) => updateCondition({ operator: e.target.value }), children: conditionOperatorSchema.options.map((op) => (_jsx("option", { value: op, title: op, children: conditionOperatorLabel(op) }, op))) }) })] }), needsValue ? (_jsx(Field, { label: "Compare to", htmlFor: `cond-val-${node.id}`, children: _jsx(Input, { id: `cond-val-${node.id}`, value: condition.value === undefined ? '' : String(condition.value), onChange: (e) => updateCondition({ value: coerceScalar(e.target.value) }), placeholder: "value", className: "font-mono text-xs" }) })) : null, _jsxs(Row, { gap: "2", children: [issue ? (_jsx(Badge, { variant: "error", children: "broken" })) : pass ? (_jsx(Badge, { variant: "success", children: "renders" })) : (_jsxs(Badge, { variant: "warning", children: [_jsx(EyeOff, { className: "size-3" }), " hidden"] })), _jsx(Text, { size: "xs", tone: "muted", className: "min-w-0 flex-1 truncate", children: issue
213
- ? issue.message
214
- : pass
215
- ? 'Condition passes — node renders.'
216
- : 'Condition fails — node is hidden on the canvas.' }), _jsx(Spacer, {}), _jsx(Button, { size: "sm", variant: "ghost", className: "text-destructive hover:text-destructive", onClick: () => builder.dispatch({ type: 'setCondition', id: node.id, condition: undefined }), children: "Remove" })] })] }));
217
- }
218
- /** Parse a comparison-value string into a number/boolean/null when it looks like one. */
219
- function coerceScalar(raw) {
220
- if (raw === '')
221
- return '';
222
- if (raw === 'true')
223
- return true;
224
- if (raw === 'false')
225
- return false;
226
- if (raw === 'null')
227
- return null;
228
- const n = Number(raw);
229
- if (raw.trim() !== '' && Number.isFinite(n))
230
- return n;
231
- return raw;
232
- }
233
173
  //# sourceMappingURL=property-inspector.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"property-inspector.js","sourceRoot":"","sources":["../../../src/components/builder/property-inspector.tsx"],"names":[],"mappings":"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","sourcesContent":["import { EyeOff } from 'lucide-react'\nimport { useEffect, useState } from 'react'\nimport { conditionOperatorSchema, staticProp } from '@elytracms/core/project-graph'\nimport type {\n BindingReference,\n ComponentNode,\n Condition,\n ConditionOperator,\n JsonValue,\n PropValue,\n} from '@elytracms/core/project-graph'\nimport { pathFromToken } from '@elytracms/core/data-binding'\nimport type { ComponentManifest, PropField } from '@elytracms/core/component-registry'\nimport { manifestSlots } from '@elytracms/core/component-registry'\nimport { fieldValueValidator } from '@elytracms/core/cms-core'\nimport type { FieldDef, SelectOption } from '@elytracms/core/cms-core'\nimport { getStudioRegistry } from '@elytracms/studio/lib/registry'\nimport { useData } from '@elytracms/studio/lib/data'\nimport {\n Badge,\n Button,\n Code,\n Field,\n Input,\n InspectorSection,\n PanelHeader,\n Row,\n Select,\n Spacer,\n Stack,\n Text,\n} from '@elytracms/studio/ui'\nimport { humanizeName } from '@elytracms/studio/lib/utils'\nimport { componentDisplayName, conditionOperatorLabel } from '@elytracms/studio/lib/persona/labels'\nimport { FieldControl } from '../cms/field-control'\nimport { useBuilder } from './builder-store'\nimport { LayoutSection, layoutManagedPropNames } from './layout-inspector'\n\nexport function PropertyInspector() {\n const builder = useBuilder()\n const studio = getStudioRegistry()\n const node = builder.selectedNode\n\n if (!node) {\n return (\n <div className=\"grid h-full place-items-center p-6 text-center\">\n <Text size=\"sm\" tone=\"muted\">\n Select a node in the tree or canvas to edit its properties.\n </Text>\n </div>\n )\n }\n\n const manifest = studio.registry.getManifest(node.componentId)\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <PanelHeader>\n <Text size=\"sm\" weight=\"semibold\">\n Inspector\n </Text>\n <Spacer />\n <Code tone=\"muted\" title={node.componentId}>\n {componentDisplayName(node.componentId, manifest)}\n </Code>\n </PanelHeader>\n\n <div className=\"min-h-0 flex-1 overflow-auto\">\n <SettingsTab node={node} manifest={manifest} />\n </div>\n </div>\n )\n}\n\n/** The full property surface: node identity, static props, condition, slots. */\nfunction SettingsTab({\n node,\n manifest,\n}: {\n node: ComponentNode\n manifest: ComponentManifest | undefined\n}) {\n // Container layout props render in the dedicated Layout section (EC-162),\n // not as a second set of generic controls.\n const layoutManaged = new Set(layoutManagedPropNames(node))\n // EC-190: `blocks` props are slots (named child regions), edited via the page\n // tree / composition surface, not as a scalar control — so they show in the\n // Slots section, not Props.\n const props = manifest\n ? Object.entries(manifest.props).filter(\n ([name, spec]) => !layoutManaged.has(name) && spec.type !== 'blocks',\n )\n : []\n const slots = manifest ? manifestSlots(manifest) : []\n\n return (\n <>\n {/* EC-192: the editor-facing inspector no longer renders the raw node id or\n namespaced component id (the persona promise). The component's human name\n is in the panel header (with the manifest id in its `title`); the canvas\n and tree provide selection. */}\n {/* Contextual layout inspector for Stack/Grid containers (EC-162). */}\n <LayoutSection node={node} />\n\n {!manifest ? (\n <div className=\"p-3\">\n <Badge variant=\"error\">unknown component</Badge>\n <Text size=\"xs\" tone=\"muted\" className=\"mt-2\">\n No manifest is registered for this component, so its props can't be edited.\n </Text>\n </div>\n ) : (\n <InspectorSection title=\"Props\">\n {props.length === 0 ? (\n <Text size=\"xs\" tone=\"subtle\">\n No editable props.\n </Text>\n ) : (\n <Stack gap=\"4\">\n {props.map(([name, spec]) => (\n // Key by node id so per-node local control state never leaks\n // across a selection change to a same-named prop.\n <PropField key={`${node.id}:${name}`} node={node} name={name} spec={spec} />\n ))}\n </Stack>\n )}\n </InspectorSection>\n )}\n\n {/* Conditional rendering (EC-088). */}\n <InspectorSection title=\"Condition\">\n <ConditionEditor node={node} />\n </InspectorSection>\n\n {slots.length > 0 ? (\n <InspectorSection title=\"Slots\">\n <Stack gap=\"1\">\n {slots.map((slot) => {\n const count = node.slots?.[slot.name]?.length ?? 0\n const missing = slot.required && count === 0\n return (\n <Row key={slot.name} gap=\"2\">\n <Text size=\"xs\" title={slot.name}>\n {humanizeName(slot.name)}\n </Text>\n {slot.required ? (\n <Badge variant={missing ? 'error' : 'outline'}>required</Badge>\n ) : null}\n <Spacer />\n <Text size=\"xs\" tone=\"subtle\" mono>\n {count}\n </Text>\n </Row>\n )\n })}\n </Stack>\n <Text size=\"xs\" tone=\"subtle\" className=\"mt-2\">\n Add or reorder slot children from the page tree.\n </Text>\n </InspectorSection>\n ) : null}\n </>\n )\n}\n\nfunction PropField({ node, name, spec }: { node: ComponentNode; name: string; spec: PropField }) {\n const value = node.props?.[name]\n\n return (\n <Field label={spec.form?.label ?? name} htmlFor={`prop-${node.id}-${name}`}>\n <StaticControl node={node} name={name} spec={spec} value={value} />\n </Field>\n )\n}\n\n/**\n * EC-190: the inspector control to render for a prop field-def. The old\n * `control.kind` vocabulary derives from the field `type` plus the optional\n * `form.control` presentation hint on `text` fields. Slice 3 unifies this with\n * the CMS `FieldControl`; for now it keeps the existing per-kind control set.\n */\ntype ControlKind =\n | 'text'\n | 'textarea'\n | 'number'\n | 'boolean'\n | 'select'\n | 'json'\n | 'color'\n | 'richtext'\n | 'asset'\n | 'object'\n | 'relation'\nfunction controlKind(spec: PropField): ControlKind {\n switch (spec.type) {\n case 'boolean':\n return 'boolean'\n case 'number':\n return 'number'\n case 'select':\n return 'select'\n case 'richText':\n return 'richtext'\n // EC-195: an `asset`-typed prop (e.g. the Image `src`) picks from the asset\n // library — never a raw asset id typed into a text box (the EC-192 persona).\n case 'asset':\n return 'asset'\n // EC-253: an `object`/repeater prop reuses the CMS repeater control below.\n case 'object':\n return 'object'\n // EC-262: a `relation`-typed prop (e.g. a ProductGrid's `category`) reuses the\n // CMS relation picker — never a text box that stringifies the ref to \"[object Object]\".\n case 'relation':\n return 'relation'\n case 'text': {\n const c = spec.form?.control\n if (c === 'textarea') return 'textarea'\n if (c === 'color') return 'color'\n if (c === 'json') return 'json'\n return 'text'\n }\n default:\n return 'text'\n }\n}\n\nfunction StaticControl({\n node,\n name,\n spec,\n value,\n}: {\n node: ComponentNode\n name: string\n spec: PropField\n value: PropValue | undefined\n}) {\n const builder = useBuilder()\n const current = value?.kind === 'static' ? value.value : (spec.default as JsonValue | undefined)\n const id = `prop-${node.id}-${name}`\n const coalesceKey = `${node.id}:${name}`\n\n function set(v: JsonValue) {\n builder.dispatch({ type: 'setProp', id: node.id, name, value: staticProp(v), coalesceKey })\n }\n function clear() {\n builder.dispatch({ type: 'removeProp', id: node.id, name })\n }\n\n // EC-190: validate with the prop's field-def value validator (was `spec.schema.safeParse`).\n const valid = current === undefined || fieldValueValidator({ ...spec, name } as FieldDef)(current)\n // EC-190: derive the editor control from the field `type` + optional `form.control`.\n const kind = controlKind(spec)\n // Select options live on the `select` field-def (was `spec.control.options`).\n const options: readonly SelectOption[] = spec.type === 'select' ? spec.options : []\n\n let control\n if (kind === 'boolean') {\n control = (\n <label className=\"flex h-8 items-center gap-2 text-sm\">\n <input\n id={id}\n type=\"checkbox\"\n checked={current === true}\n onChange={(e) => set(e.target.checked)}\n className=\"size-4 accent-primary\"\n />\n <Text size=\"sm\" tone=\"muted\">\n {current === true ? 'true' : 'false'}\n </Text>\n </label>\n )\n } else if (kind === 'select') {\n control = (\n <Select\n id={id}\n value={String(current ?? '')}\n onChange={(e) => {\n // EC-190: select option values are strings (field-def `options`).\n const opt = options.find((o) => o.value === e.target.value)\n set(opt ? opt.value : e.target.value)\n }}\n >\n {options.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label ?? opt.value}\n </option>\n ))}\n </Select>\n )\n } else if (kind === 'number') {\n control = <NumberControl id={id} current={current} onSet={set} onClear={clear} />\n } else if (kind === 'json') {\n control = <JsonControl id={id} current={current} onSet={set} />\n } else if (kind === 'color') {\n control = (\n <Row gap=\"2\">\n <input\n id={id}\n type=\"color\"\n value={\n typeof current === 'string' && /^#[0-9a-f]{6}$/i.test(current) ? current : '#000000'\n }\n onChange={(e) => set(e.target.value)}\n className=\"h-8 w-10 shrink-0 rounded-md border border-input bg-background\"\n />\n <Input\n value={typeof current === 'string' ? current : ''}\n onChange={(e) => set(e.target.value)}\n />\n </Row>\n )\n } else if (kind === 'textarea' || kind === 'richtext') {\n control = (\n <textarea\n id={id}\n rows={2}\n value={typeof current === 'string' ? current : ''}\n onChange={(e) => set(e.target.value)}\n className=\"flex w-full rounded-md border border-input bg-background px-2.5 py-1.5 text-sm text-foreground shadow-sm focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40 outline-none\"\n />\n )\n } else if (kind === 'asset' || kind === 'object' || kind === 'relation') {\n // EC-195/EC-253/EC-262: reuse the CMS field control. `asset` = library picker +\n // preview; `object` = the nested/repeater form; `relation` = the document picker\n // (resolves the ref to its title, instead of stringifying it to \"[object Object]\").\n // All edit a structured static prop value through the same shared control documents use.\n control = (\n <FieldControl\n id={id}\n field={{ ...spec, name } as FieldDef}\n value={current}\n onChange={(v) => (v === undefined || v === null ? clear() : set(v as JsonValue))}\n readOnly={false}\n />\n )\n } else {\n control = (\n <Input\n id={id}\n value={typeof current === 'string' ? current : String(current ?? '')}\n onChange={(e) => set(e.target.value)}\n />\n )\n }\n\n return (\n <Stack gap=\"1\">\n {control}\n {!valid ? (\n <Text size=\"xs\" className=\"text-destructive\">\n Value doesn't match the prop schema — the canvas falls back to the default.\n </Text>\n ) : null}\n </Stack>\n )\n}\n\n/** Number input with a local buffer: commits only finite values, never NaN; empty clears the prop. */\nfunction NumberControl({\n id,\n current,\n onSet,\n onClear,\n}: {\n id: string\n current: JsonValue | undefined\n onSet: (v: number) => void\n onClear: () => void\n}) {\n const [raw, setRaw] = useState(typeof current === 'number' ? String(current) : '')\n useEffect(() => {\n setRaw(typeof current === 'number' ? String(current) : '')\n }, [current])\n return (\n <Input\n id={id}\n type=\"number\"\n value={raw}\n onChange={(e) => {\n const v = e.target.value\n setRaw(v)\n if (v.trim() === '') {\n onClear()\n return\n }\n const n = Number(v)\n if (Number.isFinite(n)) onSet(n)\n }}\n />\n )\n}\n\n/** JSON textarea with a local buffer: commits only when the text parses; flags parse errors. */\nfunction JsonControl({\n id,\n current,\n onSet,\n}: {\n id: string\n current: JsonValue | undefined\n onSet: (v: JsonValue) => void\n}) {\n const [raw, setRaw] = useState(() => JSON.stringify(current ?? null))\n const [error, setError] = useState<string | null>(null)\n useEffect(() => {\n setRaw(JSON.stringify(current ?? null))\n setError(null)\n }, [current])\n return (\n <Stack gap=\"1\">\n <textarea\n id={id}\n rows={3}\n value={raw}\n onChange={(e) => {\n const v = e.target.value\n setRaw(v)\n try {\n onSet(JSON.parse(v) as JsonValue)\n setError(null)\n } catch {\n setError('Invalid JSON')\n }\n }}\n className=\"flex w-full rounded-md border border-input bg-background px-2.5 py-1.5 font-mono text-xs text-foreground shadow-sm focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40 outline-none\"\n />\n {error ? (\n <Text size=\"xs\" className=\"text-destructive\">\n {error}\n </Text>\n ) : null}\n </Stack>\n )\n}\n\n/** Plain-language label for a stored data path (\"item 1 → title\") — no raw syntax. */\nfunction friendlyPathLabel(token: string): string {\n const path = pathFromToken(token)\n if (path === undefined) return 'this data'\n if (path.length === 0) return 'Everything'\n return path\n .map((seg) => (/^\\d+$/.test(seg) ? `entry ${Number(seg) + 1}` : humanizeName(seg)))\n .join(' → ')\n}\n\n/** Edit a node's render condition (EC-088): source field + operator + comparison value. */\nfunction ConditionEditor({ node }: { node: ComponentNode }) {\n const builder = useBuilder()\n const data = useData()\n const condition = node.condition\n const firstSource = data.sources[0]\n\n if (!condition) {\n return (\n <Stack gap=\"2\">\n <Text size=\"xs\" tone=\"subtle\">\n This node always renders. Add a condition to gate it on a data value.\n </Text>\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"w-fit\"\n disabled={!firstSource}\n onClick={() =>\n firstSource &&\n builder.dispatch({\n type: 'setCondition',\n id: node.id,\n condition: {\n source: { sourceId: firstSource.id, token: '/', mode: 'value' },\n operator: 'truthy',\n },\n })\n }\n >\n <EyeOff /> Add condition\n </Button>\n </Stack>\n )\n }\n\n const updateCondition = (patch: Partial<Condition>) =>\n builder.dispatch({ type: 'setCondition', id: node.id, condition: { ...condition, ...patch } })\n const updateSource = (patch: Partial<BindingReference>) =>\n updateCondition({ source: { ...condition.source, ...patch } })\n\n const tokens = data.tokensOf(condition.source.sourceId)\n const source = data.getSource(condition.source.sourceId)\n const needsValue = !['truthy', 'exists'].includes(condition.operator)\n const result = data.resolveCondition(condition)\n const pass = result.kind === 'condition' ? result.pass : false\n const issue = result.kind === 'issue' ? result.issue : null\n\n return (\n <Stack gap=\"2\">\n <Field label=\"Source\" htmlFor={`cond-src-${node.id}`}>\n <Select\n id={`cond-src-${node.id}`}\n value={condition.source.sourceId}\n onChange={(e) => updateSource({ sourceId: e.target.value, token: '/' })}\n >\n {data.sources.map((s) => (\n <option key={s.id} value={s.id}>\n {s.label}\n </option>\n ))}\n {!source ? (\n <option value={condition.source.sourceId} title={condition.source.sourceId}>\n Missing data source\n </option>\n ) : null}\n </Select>\n </Field>\n\n <Row gap=\"2\">\n <Field label=\"Field\" htmlFor={`cond-token-${node.id}`} className=\"min-w-0 flex-1\">\n <Select\n id={`cond-token-${node.id}`}\n value={condition.source.token}\n onChange={(e) => updateSource({ token: e.target.value })}\n >\n {tokens.map((t) => (\n <option key={t} value={t}>\n {friendlyPathLabel(t)}\n </option>\n ))}\n {!tokens.includes(condition.source.token) ? (\n <option value={condition.source.token}>\n {friendlyPathLabel(condition.source.token)}\n </option>\n ) : null}\n </Select>\n </Field>\n <Field label=\"Operator\" htmlFor={`cond-op-${node.id}`} className=\"w-28\">\n <Select\n id={`cond-op-${node.id}`}\n value={condition.operator}\n onChange={(e) => updateCondition({ operator: e.target.value as ConditionOperator })}\n >\n {conditionOperatorSchema.options.map((op) => (\n <option key={op} value={op} title={op}>\n {conditionOperatorLabel(op)}\n </option>\n ))}\n </Select>\n </Field>\n </Row>\n\n {needsValue ? (\n <Field label=\"Compare to\" htmlFor={`cond-val-${node.id}`}>\n <Input\n id={`cond-val-${node.id}`}\n value={condition.value === undefined ? '' : String(condition.value)}\n onChange={(e) => updateCondition({ value: coerceScalar(e.target.value) })}\n placeholder=\"value\"\n className=\"font-mono text-xs\"\n />\n </Field>\n ) : null}\n\n <Row gap=\"2\">\n {issue ? (\n <Badge variant=\"error\">broken</Badge>\n ) : pass ? (\n <Badge variant=\"success\">renders</Badge>\n ) : (\n <Badge variant=\"warning\">\n <EyeOff className=\"size-3\" /> hidden\n </Badge>\n )}\n <Text size=\"xs\" tone=\"muted\" className=\"min-w-0 flex-1 truncate\">\n {issue\n ? issue.message\n : pass\n ? 'Condition passes — node renders.'\n : 'Condition fails — node is hidden on the canvas.'}\n </Text>\n <Spacer />\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"text-destructive hover:text-destructive\"\n onClick={() =>\n builder.dispatch({ type: 'setCondition', id: node.id, condition: undefined })\n }\n >\n Remove\n </Button>\n </Row>\n </Stack>\n )\n}\n\n/** Parse a comparison-value string into a number/boolean/null when it looks like one. */\nfunction coerceScalar(raw: string): JsonValue {\n if (raw === '') return ''\n if (raw === 'true') return true\n if (raw === 'false') return false\n if (raw === 'null') return null\n const n = Number(raw)\n if (raw.trim() !== '' && Number.isFinite(n)) return n\n return raw\n}\n"]}
1
+ {"version":3,"file":"property-inspector.js","sourceRoot":"","sources":["../../../src/components/builder/property-inspector.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useState } from 'react'\nimport { staticProp } from '@elytracms/core/project-graph'\nimport type { ComponentNode, JsonValue, PropValue } from '@elytracms/core/project-graph'\nimport type { ComponentManifest, PropField } from '@elytracms/core/component-registry'\nimport { manifestSlots } from '@elytracms/core/component-registry'\nimport { fieldValueValidator } from '@elytracms/core/cms-core'\nimport type { FieldDef, SelectOption } from '@elytracms/core/cms-core'\nimport { getStudioRegistry } from '@elytracms/studio/lib/registry'\nimport {\n Badge,\n Code,\n Field,\n Input,\n InspectorSection,\n PanelHeader,\n Row,\n Select,\n Spacer,\n Stack,\n Text,\n} from '@elytracms/studio/ui'\nimport { humanizeName } from '@elytracms/studio/lib/utils'\nimport { componentDisplayName } from '@elytracms/studio/lib/persona/labels'\nimport { FieldControl } from '../cms/field-control'\nimport { useBuilder } from './builder-store'\nimport { LayoutSection, layoutManagedPropNames } from './layout-inspector'\n\nexport function PropertyInspector() {\n const builder = useBuilder()\n const studio = getStudioRegistry()\n const node = builder.selectedNode\n\n if (!node) {\n return (\n <div className=\"grid h-full place-items-center p-6 text-center\">\n <Text size=\"sm\" tone=\"muted\">\n Select a node in the tree or canvas to edit its properties.\n </Text>\n </div>\n )\n }\n\n const manifest = studio.registry.getManifest(node.componentId)\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <PanelHeader>\n <Text size=\"sm\" weight=\"semibold\">\n Inspector\n </Text>\n <Spacer />\n <Code tone=\"muted\" title={node.componentId}>\n {componentDisplayName(node.componentId, manifest)}\n </Code>\n </PanelHeader>\n\n <div className=\"min-h-0 flex-1 overflow-auto\">\n <SettingsTab node={node} manifest={manifest} />\n </div>\n </div>\n )\n}\n\n/** The full property surface: node identity, static props, condition, slots. */\nfunction SettingsTab({\n node,\n manifest,\n}: {\n node: ComponentNode\n manifest: ComponentManifest | undefined\n}) {\n // Container layout props render in the dedicated Layout section (EC-162),\n // not as a second set of generic controls.\n const layoutManaged = new Set(layoutManagedPropNames(node))\n // EC-190: `blocks` props are slots (named child regions), edited via the page\n // tree / composition surface, not as a scalar control — so they show in the\n // Slots section, not Props.\n const props = manifest\n ? Object.entries(manifest.props).filter(\n ([name, spec]) => !layoutManaged.has(name) && spec.type !== 'blocks',\n )\n : []\n const slots = manifest ? manifestSlots(manifest) : []\n\n return (\n <>\n {/* EC-192: the editor-facing inspector no longer renders the raw node id or\n namespaced component id (the persona promise). The component's human name\n is in the panel header (with the manifest id in its `title`); the canvas\n and tree provide selection. */}\n {/* Contextual layout inspector for Stack/Grid containers (EC-162). */}\n <LayoutSection node={node} />\n\n {!manifest ? (\n <div className=\"p-3\">\n <Badge variant=\"error\">unknown component</Badge>\n <Text size=\"xs\" tone=\"muted\" className=\"mt-2\">\n No manifest is registered for this component, so its props can't be edited.\n </Text>\n </div>\n ) : (\n <InspectorSection title=\"Props\">\n {props.length === 0 ? (\n <Text size=\"xs\" tone=\"subtle\">\n No editable props.\n </Text>\n ) : (\n <Stack gap=\"4\">\n {props.map(([name, spec]) => (\n // Key by node id so per-node local control state never leaks\n // across a selection change to a same-named prop.\n <PropField key={`${node.id}:${name}`} node={node} name={name} spec={spec} />\n ))}\n </Stack>\n )}\n </InspectorSection>\n )}\n\n {slots.length > 0 ? (\n <InspectorSection title=\"Slots\">\n <Stack gap=\"1\">\n {slots.map((slot) => {\n const count = node.slots?.[slot.name]?.length ?? 0\n const missing = slot.required && count === 0\n return (\n <Row key={slot.name} gap=\"2\">\n <Text size=\"xs\" title={slot.name}>\n {humanizeName(slot.name)}\n </Text>\n {slot.required ? (\n <Badge variant={missing ? 'error' : 'outline'}>required</Badge>\n ) : null}\n <Spacer />\n <Text size=\"xs\" tone=\"subtle\" mono>\n {count}\n </Text>\n </Row>\n )\n })}\n </Stack>\n <Text size=\"xs\" tone=\"subtle\" className=\"mt-2\">\n Add or reorder slot children from the page tree.\n </Text>\n </InspectorSection>\n ) : null}\n </>\n )\n}\n\nfunction PropField({ node, name, spec }: { node: ComponentNode; name: string; spec: PropField }) {\n const value = node.props?.[name]\n\n return (\n <Field label={spec.form?.label ?? name} htmlFor={`prop-${node.id}-${name}`}>\n <StaticControl node={node} name={name} spec={spec} value={value} />\n </Field>\n )\n}\n\n/**\n * EC-190: the inspector control to render for a prop field-def. The old\n * `control.kind` vocabulary derives from the field `type` plus the optional\n * `form.control` presentation hint on `text` fields. Slice 3 unifies this with\n * the CMS `FieldControl`; for now it keeps the existing per-kind control set.\n */\ntype ControlKind =\n | 'text'\n | 'textarea'\n | 'number'\n | 'boolean'\n | 'select'\n | 'json'\n | 'color'\n | 'richtext'\n | 'asset'\n | 'object'\n | 'relation'\nfunction controlKind(spec: PropField): ControlKind {\n switch (spec.type) {\n case 'boolean':\n return 'boolean'\n case 'number':\n return 'number'\n case 'select':\n return 'select'\n case 'richText':\n return 'richtext'\n // EC-195: an `asset`-typed prop (e.g. the Image `src`) picks from the asset\n // library — never a raw asset id typed into a text box (the EC-192 persona).\n case 'asset':\n return 'asset'\n // EC-253: an `object`/repeater prop reuses the CMS repeater control below.\n case 'object':\n return 'object'\n // EC-262: a `relation`-typed prop (e.g. a ProductGrid's `category`) reuses the\n // CMS relation picker — never a text box that stringifies the ref to \"[object Object]\".\n case 'relation':\n return 'relation'\n case 'text': {\n const c = spec.form?.control\n if (c === 'textarea') return 'textarea'\n if (c === 'color') return 'color'\n if (c === 'json') return 'json'\n return 'text'\n }\n default:\n return 'text'\n }\n}\n\nfunction StaticControl({\n node,\n name,\n spec,\n value,\n}: {\n node: ComponentNode\n name: string\n spec: PropField\n value: PropValue | undefined\n}) {\n const builder = useBuilder()\n const current = value?.kind === 'static' ? value.value : (spec.default as JsonValue | undefined)\n const id = `prop-${node.id}-${name}`\n const coalesceKey = `${node.id}:${name}`\n\n function set(v: JsonValue) {\n builder.dispatch({ type: 'setProp', id: node.id, name, value: staticProp(v), coalesceKey })\n }\n function clear() {\n builder.dispatch({ type: 'removeProp', id: node.id, name })\n }\n\n // EC-190: validate with the prop's field-def value validator (was `spec.schema.safeParse`).\n const valid = current === undefined || fieldValueValidator({ ...spec, name } as FieldDef)(current)\n // EC-190: derive the editor control from the field `type` + optional `form.control`.\n const kind = controlKind(spec)\n // Select options live on the `select` field-def (was `spec.control.options`).\n const options: readonly SelectOption[] = spec.type === 'select' ? spec.options : []\n\n let control\n if (kind === 'boolean') {\n control = (\n <label className=\"flex h-8 items-center gap-2 text-sm\">\n <input\n id={id}\n type=\"checkbox\"\n checked={current === true}\n onChange={(e) => set(e.target.checked)}\n className=\"size-4 accent-primary\"\n />\n <Text size=\"sm\" tone=\"muted\">\n {current === true ? 'true' : 'false'}\n </Text>\n </label>\n )\n } else if (kind === 'select') {\n control = (\n <Select\n id={id}\n value={String(current ?? '')}\n onChange={(e) => {\n // EC-190: select option values are strings (field-def `options`).\n const opt = options.find((o) => o.value === e.target.value)\n set(opt ? opt.value : e.target.value)\n }}\n >\n {options.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label ?? opt.value}\n </option>\n ))}\n </Select>\n )\n } else if (kind === 'number') {\n control = <NumberControl id={id} current={current} onSet={set} onClear={clear} />\n } else if (kind === 'json') {\n control = <JsonControl id={id} current={current} onSet={set} />\n } else if (kind === 'color') {\n control = (\n <Row gap=\"2\">\n <input\n id={id}\n type=\"color\"\n value={\n typeof current === 'string' && /^#[0-9a-f]{6}$/i.test(current) ? current : '#000000'\n }\n onChange={(e) => set(e.target.value)}\n className=\"h-8 w-10 shrink-0 rounded-md border border-input bg-background\"\n />\n <Input\n value={typeof current === 'string' ? current : ''}\n onChange={(e) => set(e.target.value)}\n />\n </Row>\n )\n } else if (kind === 'textarea' || kind === 'richtext') {\n control = (\n <textarea\n id={id}\n rows={2}\n value={typeof current === 'string' ? current : ''}\n onChange={(e) => set(e.target.value)}\n className=\"flex w-full rounded-md border border-input bg-background px-2.5 py-1.5 text-sm text-foreground shadow-sm focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40 outline-none\"\n />\n )\n } else if (kind === 'asset' || kind === 'object' || kind === 'relation') {\n // EC-195/EC-253/EC-262: reuse the CMS field control. `asset` = library picker +\n // preview; `object` = the nested/repeater form; `relation` = the document picker\n // (resolves the ref to its title, instead of stringifying it to \"[object Object]\").\n // All edit a structured static prop value through the same shared control documents use.\n control = (\n <FieldControl\n id={id}\n field={{ ...spec, name } as FieldDef}\n value={current}\n onChange={(v) => (v === undefined || v === null ? clear() : set(v as JsonValue))}\n readOnly={false}\n />\n )\n } else {\n control = (\n <Input\n id={id}\n value={typeof current === 'string' ? current : String(current ?? '')}\n onChange={(e) => set(e.target.value)}\n />\n )\n }\n\n return (\n <Stack gap=\"1\">\n {control}\n {!valid ? (\n <Text size=\"xs\" className=\"text-destructive\">\n Value doesn't match the prop schema — the canvas falls back to the default.\n </Text>\n ) : null}\n </Stack>\n )\n}\n\n/** Number input with a local buffer: commits only finite values, never NaN; empty clears the prop. */\nfunction NumberControl({\n id,\n current,\n onSet,\n onClear,\n}: {\n id: string\n current: JsonValue | undefined\n onSet: (v: number) => void\n onClear: () => void\n}) {\n const [raw, setRaw] = useState(typeof current === 'number' ? String(current) : '')\n useEffect(() => {\n setRaw(typeof current === 'number' ? String(current) : '')\n }, [current])\n return (\n <Input\n id={id}\n type=\"number\"\n value={raw}\n onChange={(e) => {\n const v = e.target.value\n setRaw(v)\n if (v.trim() === '') {\n onClear()\n return\n }\n const n = Number(v)\n if (Number.isFinite(n)) onSet(n)\n }}\n />\n )\n}\n\n/** JSON textarea with a local buffer: commits only when the text parses; flags parse errors. */\nfunction JsonControl({\n id,\n current,\n onSet,\n}: {\n id: string\n current: JsonValue | undefined\n onSet: (v: JsonValue) => void\n}) {\n const [raw, setRaw] = useState(() => JSON.stringify(current ?? null))\n const [error, setError] = useState<string | null>(null)\n useEffect(() => {\n setRaw(JSON.stringify(current ?? null))\n setError(null)\n }, [current])\n return (\n <Stack gap=\"1\">\n <textarea\n id={id}\n rows={3}\n value={raw}\n onChange={(e) => {\n const v = e.target.value\n setRaw(v)\n try {\n onSet(JSON.parse(v) as JsonValue)\n setError(null)\n } catch {\n setError('Invalid JSON')\n }\n }}\n className=\"flex w-full rounded-md border border-input bg-background px-2.5 py-1.5 font-mono text-xs text-foreground shadow-sm focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40 outline-none\"\n />\n {error ? (\n <Text size=\"xs\" className=\"text-destructive\">\n {error}\n </Text>\n ) : null}\n </Stack>\n )\n}\n\n"]}
@@ -27,7 +27,3 @@ export declare function fallbackTitle(fallback: DisplayedFallback): string;
27
27
  * and legacy bare `{ collection, id }` via the shared tolerant reader.
28
28
  */
29
29
  export declare function toRefArray(value: unknown): DocumentRef[];
30
- /** Render a small mono code for the raw stored value (debug/primary-cell hint). */
31
- export declare function RawValue({ value }: {
32
- value: unknown;
33
- }): import("react").JSX.Element;
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Boxes, Check, Image, Link2, Minus } from 'lucide-react';
3
3
  import { readAssetId, readDocumentRef } from '@elytracms/core/cms-core';
4
4
  import { blockRootsOf } from '@elytracms/core/project-graph';
5
- import { Badge, Code, Text } from '@elytracms/studio/ui';
5
+ import { Badge, Text } from '@elytracms/studio/ui';
6
6
  import { localeChipLabel, resolveDisplayedValue } from '@elytracms/studio/lib/locale';
7
7
  import { useOptionalAssets } from '../assets/assets-store';
8
8
  import { useCms } from './cms-store';
@@ -121,8 +121,4 @@ export function toRefArray(value) {
121
121
  function stripHtml(html) {
122
122
  return html.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
123
123
  }
124
- /** Render a small mono code for the raw stored value (debug/primary-cell hint). */
125
- export function RawValue({ value }) {
126
- return _jsx(Code, { tone: "muted", children: typeof value === 'string' ? value : JSON.stringify(value) });
127
- }
128
124
  //# sourceMappingURL=cell.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cell.js","sourceRoot":"","sources":["../../../src/components/cms/cell.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Boxes, Check, Image, Link2, Minus } from 'lucide-react'\nimport { readAssetId, readDocumentRef } from '@elytracms/core/cms-core'\nimport type { CmsDocument, CollectionDef, DocumentRef, FieldDef } from '@elytracms/core/cms-core'\nimport { blockRootsOf } from '@elytracms/core/project-graph'\nimport type { AssetRecord } from '@elytracms/core/persistence'\nimport { Badge, Code, Text } from '@elytracms/studio/ui'\nimport { localeChipLabel, resolveDisplayedValue } from '@elytracms/studio/lib/locale'\nimport type { DisplayedFallback } from '@elytracms/studio/lib/locale'\nimport { useOptionalAssets } from '../assets/assets-store'\nimport { useCms } from './cms-store'\n\n/**\n * Render a document's field value for a table cell, by field type (brief\n * §8.4, EC-070), resolved in the studio's ambient active locale (EC-176).\n * A value served via EC-018 locale fallback carries a visible chip — never\n * silently mixed in as if it were translated.\n */\nexport function CellValue({\n collection,\n doc,\n field,\n}: {\n collection: CollectionDef\n doc: CmsDocument\n field: FieldDef\n}) {\n const cms = useCms()\n const { value, fallback } = resolveDisplayedValue(\n collection,\n doc,\n field.name,\n cms.activeLocale,\n cms.localeConfig,\n )\n\n if (value === undefined || value === null || value === '') {\n return <Minus className=\"size-3.5 text-muted-foreground/50\" />\n }\n\n return (\n <span className=\"inline-flex min-w-0 max-w-full items-center gap-1.5\">\n <TypedCellValue field={field} value={value} />\n <FallbackChip fallback={fallback} testId={`cell-fallback-${doc.id}-${field.name}`} />\n </span>\n )\n}\n\n/**\n * Subtle source-locale chip on a fallback-displayed value (EC-176): e.g. a\n * German view showing untranslated English content gets an \"EN\" marker.\n */\nexport function FallbackChip({\n fallback,\n testId,\n}: {\n fallback: DisplayedFallback | null\n testId: string\n}) {\n if (fallback === null) return null\n return (\n <Badge\n variant=\"outline\"\n data-testid={testId}\n title={fallbackTitle(fallback)}\n className=\"shrink-0 px-1 py-0 text-[0.6rem] uppercase tracking-wide text-muted-foreground\"\n >\n {localeChipLabel(fallback.sourceLocale)}\n </Badge>\n )\n}\n\n/** Plain-language tooltip of a fallback chip. */\nexport function fallbackTitle(fallback: DisplayedFallback): string {\n return `Showing ${localeChipLabel(fallback.sourceLocale)} (fallback) — no ${localeChipLabel(\n fallback.requestedLocale,\n )} translation yet. Edit to translate.`\n}\n\nfunction TypedCellValue({ field, value }: { field: FieldDef; value: unknown }) {\n switch (field.type) {\n case 'boolean':\n return value === true ? (\n <Check className=\"size-4 text-success\" />\n ) : (\n <Minus className=\"size-3.5 text-muted-foreground/50\" />\n )\n case 'select':\n return <Badge variant=\"outline\">{String(value)}</Badge>\n case 'number':\n return <Text size=\"sm\" mono>{String(value)}</Text>\n case 'date':\n return (\n <Text size=\"sm\" tone=\"muted\" mono>\n {String(value).slice(0, 10)}\n </Text>\n )\n case 'richText':\n return (\n <Text size=\"xs\" tone=\"subtle\">\n {stripHtml(String(value)).slice(0, 40) || 'rich text'}\n </Text>\n )\n case 'relation':\n return <RelationCell value={value} />\n case 'asset':\n return <AssetCell value={value} />\n case 'blocks':\n return <BlocksCell value={value} />\n case 'object': {\n // EC-253: list-view summary, never `[object Object]`. A repeater shows its\n // item count; a single object is edited in the detail form, not the cell.\n if (field.cardinality === 'many') {\n const count = Array.isArray(value) ? value.length : 0\n return (\n <Badge variant=\"outline\">\n {count} {count === 1 ? 'item' : 'items'}\n </Badge>\n )\n }\n return (\n <Text size=\"xs\" tone=\"subtle\">\n {value && typeof value === 'object' ? 'object' : '—'}\n </Text>\n )\n }\n default:\n return (\n <Text size=\"sm\" className=\"truncate\">\n {String(value)}\n </Text>\n )\n }\n}\n\nfunction RelationCell({ value }: { value: unknown }) {\n const cms = useCms()\n const refs = toRefArray(value)\n if (refs.length === 0) return <Minus className=\"size-3.5 text-muted-foreground/50\" />\n return (\n <div className=\"flex flex-wrap items-center gap-1\">\n {refs.slice(0, 3).map((ref, i) => (\n <Badge key={`${ref.id}-${i}`} variant=\"info\">\n <Link2 className=\"size-3\" /> {cms.titleOf(ref)}\n </Badge>\n ))}\n {refs.length > 3 ? <Text size=\"xs\" tone=\"subtle\">+{refs.length - 3}</Text> : null}\n </div>\n )\n}\n\n/**\n * A blocks/composition cell: a count of TOP-LEVEL blocks (EC-212) — matching\n * what the canvas/page-tree present as the block list, never `[object Object]`.\n */\nfunction BlocksCell({ value }: { value: unknown }) {\n const count = blockRootsOf(value).length\n if (count === 0) return <Minus className=\"size-3.5 text-muted-foreground/50\" />\n return (\n <Badge variant=\"outline\">\n <Boxes className=\"size-3\" /> {count} {count === 1 ? 'block' : 'blocks'}\n </Badge>\n )\n}\n\nfunction AssetCell({ value }: { value: unknown }) {\n const cms = useCms()\n const assetStore = useOptionalAssets()\n const assetCollectionId = cms.collections.find((c) => c.kind === 'asset')?.id ?? 'asset'\n // EC-277: tolerate self-typed `{ type:'asset', id }` envelopes and legacy bare ids.\n const ids = (Array.isArray(value) ? value : [value])\n .map(readAssetId)\n .filter((id): id is string => id !== undefined)\n if (ids.length === 0) return <Minus className=\"size-3.5 text-muted-foreground/50\" />\n const first = ids[0]!\n const record = assetStore?.assets.find((asset) => asset.id === first)\n const label =\n record?.title ?? record?.filename ?? cms.titleOf({ collection: assetCollectionId, id: first })\n return (\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <AssetPreview record={record} label={label} />\n {ids.length > 1 ? <Text size=\"xs\" tone=\"subtle\">+{ids.length - 1}</Text> : null}\n </div>\n )\n}\n\n/**\n * An asset reference in a cell: an image thumbnail for image assets with a\n * resolvable URL (EC-212), otherwise the labelled icon badge (and the same\n * badge whenever no `<AssetsProvider>` is mounted to resolve the record).\n */\nfunction AssetPreview({ record, label }: { record: AssetRecord | undefined; label: string }) {\n const isImage = record?.contentType.startsWith('image/') ?? false\n const url = record?.url\n if (isImage && url && url.startsWith('http')) {\n return (\n <span className=\"inline-flex min-w-0 items-center gap-1.5\">\n <img\n src={url}\n alt={record?.alt ?? label}\n loading=\"lazy\"\n className=\"size-7 shrink-0 rounded border border-border bg-muted object-cover\"\n />\n <Text size=\"xs\" tone=\"subtle\" className=\"max-w-[10rem] truncate\">\n {label}\n </Text>\n </span>\n )\n }\n return (\n <Badge variant=\"outline\">\n <Image className=\"size-3\" /> {label}\n </Badge>\n )\n}\n\n/**\n * Normalize a relation value (single ref or array of refs) into an array of\n * `DocumentRef`s. EC-277: unwraps self-typed `{ type:'reference', ... }` envelopes\n * and legacy bare `{ collection, id }` via the shared tolerant reader.\n */\nexport function toRefArray(value: unknown): DocumentRef[] {\n const list = Array.isArray(value) ? value : [value]\n return list.map(readDocumentRef).filter((ref): ref is DocumentRef => ref !== undefined)\n}\n\nfunction stripHtml(html: string): string {\n return html.replace(/<[^>]*>/g, ' ').replace(/\\s+/g, ' ').trim()\n}\n\n/** Render a small mono code for the raw stored value (debug/primary-cell hint). */\nexport function RawValue({ value }: { value: unknown }) {\n return <Code tone=\"muted\">{typeof value === 'string' ? value : JSON.stringify(value)}</Code>\n}\n"]}
1
+ {"version":3,"file":"cell.js","sourceRoot":"","sources":["../../../src/components/cms/cell.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Boxes, Check, Image, Link2, Minus } from 'lucide-react'\nimport { readAssetId, readDocumentRef } from '@elytracms/core/cms-core'\nimport type { CmsDocument, CollectionDef, DocumentRef, FieldDef } from '@elytracms/core/cms-core'\nimport { blockRootsOf } from '@elytracms/core/project-graph'\nimport type { AssetRecord } from '@elytracms/core/persistence'\nimport { Badge, Text } from '@elytracms/studio/ui'\nimport { localeChipLabel, resolveDisplayedValue } from '@elytracms/studio/lib/locale'\nimport type { DisplayedFallback } from '@elytracms/studio/lib/locale'\nimport { useOptionalAssets } from '../assets/assets-store'\nimport { useCms } from './cms-store'\n\n/**\n * Render a document's field value for a table cell, by field type (brief\n * §8.4, EC-070), resolved in the studio's ambient active locale (EC-176).\n * A value served via EC-018 locale fallback carries a visible chip — never\n * silently mixed in as if it were translated.\n */\nexport function CellValue({\n collection,\n doc,\n field,\n}: {\n collection: CollectionDef\n doc: CmsDocument\n field: FieldDef\n}) {\n const cms = useCms()\n const { value, fallback } = resolveDisplayedValue(\n collection,\n doc,\n field.name,\n cms.activeLocale,\n cms.localeConfig,\n )\n\n if (value === undefined || value === null || value === '') {\n return <Minus className=\"size-3.5 text-muted-foreground/50\" />\n }\n\n return (\n <span className=\"inline-flex min-w-0 max-w-full items-center gap-1.5\">\n <TypedCellValue field={field} value={value} />\n <FallbackChip fallback={fallback} testId={`cell-fallback-${doc.id}-${field.name}`} />\n </span>\n )\n}\n\n/**\n * Subtle source-locale chip on a fallback-displayed value (EC-176): e.g. a\n * German view showing untranslated English content gets an \"EN\" marker.\n */\nexport function FallbackChip({\n fallback,\n testId,\n}: {\n fallback: DisplayedFallback | null\n testId: string\n}) {\n if (fallback === null) return null\n return (\n <Badge\n variant=\"outline\"\n data-testid={testId}\n title={fallbackTitle(fallback)}\n className=\"shrink-0 px-1 py-0 text-[0.6rem] uppercase tracking-wide text-muted-foreground\"\n >\n {localeChipLabel(fallback.sourceLocale)}\n </Badge>\n )\n}\n\n/** Plain-language tooltip of a fallback chip. */\nexport function fallbackTitle(fallback: DisplayedFallback): string {\n return `Showing ${localeChipLabel(fallback.sourceLocale)} (fallback) — no ${localeChipLabel(\n fallback.requestedLocale,\n )} translation yet. Edit to translate.`\n}\n\nfunction TypedCellValue({ field, value }: { field: FieldDef; value: unknown }) {\n switch (field.type) {\n case 'boolean':\n return value === true ? (\n <Check className=\"size-4 text-success\" />\n ) : (\n <Minus className=\"size-3.5 text-muted-foreground/50\" />\n )\n case 'select':\n return <Badge variant=\"outline\">{String(value)}</Badge>\n case 'number':\n return <Text size=\"sm\" mono>{String(value)}</Text>\n case 'date':\n return (\n <Text size=\"sm\" tone=\"muted\" mono>\n {String(value).slice(0, 10)}\n </Text>\n )\n case 'richText':\n return (\n <Text size=\"xs\" tone=\"subtle\">\n {stripHtml(String(value)).slice(0, 40) || 'rich text'}\n </Text>\n )\n case 'relation':\n return <RelationCell value={value} />\n case 'asset':\n return <AssetCell value={value} />\n case 'blocks':\n return <BlocksCell value={value} />\n case 'object': {\n // EC-253: list-view summary, never `[object Object]`. A repeater shows its\n // item count; a single object is edited in the detail form, not the cell.\n if (field.cardinality === 'many') {\n const count = Array.isArray(value) ? value.length : 0\n return (\n <Badge variant=\"outline\">\n {count} {count === 1 ? 'item' : 'items'}\n </Badge>\n )\n }\n return (\n <Text size=\"xs\" tone=\"subtle\">\n {value && typeof value === 'object' ? 'object' : '—'}\n </Text>\n )\n }\n default:\n return (\n <Text size=\"sm\" className=\"truncate\">\n {String(value)}\n </Text>\n )\n }\n}\n\nfunction RelationCell({ value }: { value: unknown }) {\n const cms = useCms()\n const refs = toRefArray(value)\n if (refs.length === 0) return <Minus className=\"size-3.5 text-muted-foreground/50\" />\n return (\n <div className=\"flex flex-wrap items-center gap-1\">\n {refs.slice(0, 3).map((ref, i) => (\n <Badge key={`${ref.id}-${i}`} variant=\"info\">\n <Link2 className=\"size-3\" /> {cms.titleOf(ref)}\n </Badge>\n ))}\n {refs.length > 3 ? <Text size=\"xs\" tone=\"subtle\">+{refs.length - 3}</Text> : null}\n </div>\n )\n}\n\n/**\n * A blocks/composition cell: a count of TOP-LEVEL blocks (EC-212) — matching\n * what the canvas/page-tree present as the block list, never `[object Object]`.\n */\nfunction BlocksCell({ value }: { value: unknown }) {\n const count = blockRootsOf(value).length\n if (count === 0) return <Minus className=\"size-3.5 text-muted-foreground/50\" />\n return (\n <Badge variant=\"outline\">\n <Boxes className=\"size-3\" /> {count} {count === 1 ? 'block' : 'blocks'}\n </Badge>\n )\n}\n\nfunction AssetCell({ value }: { value: unknown }) {\n const cms = useCms()\n const assetStore = useOptionalAssets()\n const assetCollectionId = cms.collections.find((c) => c.kind === 'asset')?.id ?? 'asset'\n // EC-277: tolerate self-typed `{ type:'asset', id }` envelopes and legacy bare ids.\n const ids = (Array.isArray(value) ? value : [value])\n .map(readAssetId)\n .filter((id): id is string => id !== undefined)\n if (ids.length === 0) return <Minus className=\"size-3.5 text-muted-foreground/50\" />\n const first = ids[0]!\n const record = assetStore?.assets.find((asset) => asset.id === first)\n const label =\n record?.title ?? record?.filename ?? cms.titleOf({ collection: assetCollectionId, id: first })\n return (\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <AssetPreview record={record} label={label} />\n {ids.length > 1 ? <Text size=\"xs\" tone=\"subtle\">+{ids.length - 1}</Text> : null}\n </div>\n )\n}\n\n/**\n * An asset reference in a cell: an image thumbnail for image assets with a\n * resolvable URL (EC-212), otherwise the labelled icon badge (and the same\n * badge whenever no `<AssetsProvider>` is mounted to resolve the record).\n */\nfunction AssetPreview({ record, label }: { record: AssetRecord | undefined; label: string }) {\n const isImage = record?.contentType.startsWith('image/') ?? false\n const url = record?.url\n if (isImage && url && url.startsWith('http')) {\n return (\n <span className=\"inline-flex min-w-0 items-center gap-1.5\">\n <img\n src={url}\n alt={record?.alt ?? label}\n loading=\"lazy\"\n className=\"size-7 shrink-0 rounded border border-border bg-muted object-cover\"\n />\n <Text size=\"xs\" tone=\"subtle\" className=\"max-w-[10rem] truncate\">\n {label}\n </Text>\n </span>\n )\n }\n return (\n <Badge variant=\"outline\">\n <Image className=\"size-3\" /> {label}\n </Badge>\n )\n}\n\n/**\n * Normalize a relation value (single ref or array of refs) into an array of\n * `DocumentRef`s. EC-277: unwraps self-typed `{ type:'reference', ... }` envelopes\n * and legacy bare `{ collection, id }` via the shared tolerant reader.\n */\nexport function toRefArray(value: unknown): DocumentRef[] {\n const list = Array.isArray(value) ? value : [value]\n return list.map(readDocumentRef).filter((ref): ref is DocumentRef => ref !== undefined)\n}\n\nfunction stripHtml(html: string): string {\n return html.replace(/<[^>]*>/g, ' ').replace(/\\s+/g, ' ').trim()\n}\n"]}
@@ -111,7 +111,7 @@ export interface CmsStore {
111
111
  restoreDocumentVersion(ref: DocumentRef, version: number): Promise<CmsDocument | null>;
112
112
  importDocuments(collectionId: string, docs: unknown[]): ImportReport;
113
113
  validate(doc: CmsDocument): CmsValidationIssue[];
114
- isFieldReadOnly(collectionId: string, field: FieldDef): boolean;
114
+ isFieldReadOnly(field: FieldDef): boolean;
115
115
  viewsOf(collectionId: string): SavedView[];
116
116
  activeViewId(collectionId: string): string;
117
117
  /** Switch views — resets the working table state to the view's state. */
@@ -11,10 +11,6 @@ import { ALL_VIEW_ID, canonicalViewState, defaultViewState, deleteSavedView, loa
11
11
  import { useOptionalAssets } from '../assets/assets-store';
12
12
  import { commitCellEdit } from './cell-edit';
13
13
  import { runBulkAction } from './bulk-actions';
14
- /** Demo per-field access (brief §8.4, EC-078). Read-only fields render disabled. */
15
- const READ_ONLY_FIELDS = {
16
- asset: ['url'],
17
- };
18
14
  /**
19
15
  * Mint a collision-safe, slug-derived page id (EC-192): the slug of the page name,
20
16
  * suffixed `-2`/`-3`/… until it is free among the ids already taken. Empty or
@@ -455,10 +451,7 @@ export function CmsProvider({ children, projectId, initialCollections, initialDo
455
451
  }
456
452
  return report;
457
453
  }, [registry, documents, localeConfig, assetExists]);
458
- const isFieldReadOnly = useCallback((collectionId, field) => {
459
- return (field.form?.readOnly === true ||
460
- (READ_ONLY_FIELDS[collectionId]?.includes(field.name) ?? false));
461
- }, []);
454
+ const isFieldReadOnly = useCallback((field) => field.form?.readOnly === true, []);
462
455
  // --- Saved views (EC-169) -------------------------------------------------
463
456
  // Load the project's persisted views once (operations query). Views saved by
464
457
  // other editors/sessions on the same project show up here.
@@ -619,7 +612,9 @@ export function CmsProvider({ children, projectId, initialCollections, initialDo
619
612
  assetExists,
620
613
  }),
621
614
  // EC-224: a succeeded publish/unpublish moves the version pointer
622
- // (`publishedKeys`); the flat `state` mirror is updated in lockstep.
615
+ // (`publishedKeys`) via setPublished — there is no separate flat
616
+ // `state` mirror to keep in sync (published-ness is derived from the
617
+ // pointer set).
623
618
  applyState: (ref, state) => setPublished(ref, state === 'published'),
624
619
  applyDelete: (ref) => setDocuments((prev) => prev.filter((d) => !(d.collection === ref.collection && d.id === ref.id))),
625
620
  ...(dispatch ? { dispatch } : {}),