camox 0.71.0 → 0.74.1

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 (104) hide show
  1. package/dist/core/createApp.d.ts +4 -103
  2. package/dist/core/createApp.js +3 -24
  3. package/dist/core/createBlock.d.ts +2 -2
  4. package/dist/core/createBlock.js +41 -185
  5. package/dist/core/createLayout.d.ts +6 -77
  6. package/dist/core/createLayout.js +12 -50
  7. package/dist/core/editing/createEditableBlock.d.ts +9 -75
  8. package/dist/core/editing/createEditableBlock.js +258 -640
  9. package/dist/core/hooks/useIsEditable.js +2 -2
  10. package/dist/core/lib/artifactData.js +8 -3
  11. package/dist/core/lib/contentType.d.ts +23 -38
  12. package/dist/core/lib/contentType.js +34 -62
  13. package/dist/core/lib/iconTypes.d.ts +0 -3
  14. package/dist/core/lib/icons.js +63 -51
  15. package/dist/core/lib/recordScope.js +1 -1
  16. package/dist/features/canvas/CanvasOverlays.js +94 -176
  17. package/dist/features/canvas/CanvasPageFrame.js +62 -68
  18. package/dist/features/canvas/CanvasPreviewPageSlot.js +1 -3
  19. package/dist/features/canvas/canvasOverlayGeometry.js +1 -7
  20. package/dist/features/canvas/sidebar/CuratedPageInspector.js +3 -21
  21. package/dist/features/canvas/sidebar/LayoutPageBlocks.js +1 -2
  22. package/dist/features/canvas/useCanvasCamera.js +1 -1
  23. package/dist/features/canvas/useCanvasFrame.js +1 -1
  24. package/dist/features/content/ContentCollection.js +2 -2
  25. package/dist/features/content/collection-form.js +6 -7
  26. package/dist/features/page/CuratedPageContent.js +15 -24
  27. package/dist/features/page/UnplacedBlockContent.js +1 -6
  28. package/dist/features/preview/CamoxPreview.js +30 -33
  29. package/dist/features/preview/EditablePageContent.js +131 -151
  30. package/dist/features/preview/components/BlockActionsPopover.js +43 -152
  31. package/dist/features/preview/components/CanvasPreview.js +2 -2
  32. package/dist/features/preview/components/Frame.js +3 -3
  33. package/dist/features/preview/components/IconFieldEditor.js +1 -1
  34. package/dist/features/preview/components/ItemFieldsEditor.js +1 -3
  35. package/dist/features/preview/components/Overlays.js +18 -84
  36. package/dist/features/preview/components/PageInfo.js +121 -98
  37. package/dist/features/preview/components/PageTree.js +57 -103
  38. package/dist/features/preview/components/PreviewPanel.js +8 -11
  39. package/dist/features/preview/components/RecordCombobox.js +65 -78
  40. package/dist/features/preview/components/ReferenceFieldEditor.js +1 -19
  41. package/dist/features/preview/components/ReferenceListFieldEditor.js +1 -19
  42. package/dist/features/preview/components/RemovedBlockPlaceholder.js +2 -2
  43. package/dist/features/preview/components/SelectionEditor.js +6 -5
  44. package/dist/features/preview/components/useRepeatableItemActions.js +18 -24
  45. package/dist/features/preview/components/useUpdateBlockPosition.js +1 -1
  46. package/dist/features/preview/overlayMessages.js +1 -4
  47. package/dist/features/preview/previewStore.js +3 -23
  48. package/dist/features/renderer/RendererApp.js +17 -141
  49. package/dist/features/renderer/definitionAnswers.js +1 -8
  50. package/dist/features/renderer/rendererHost.js +1 -31
  51. package/dist/features/renderer/studioConnection.js +1 -25
  52. package/dist/features/routes/pageRuntime.js +15 -4
  53. package/dist/features/runtime/ClaimCard.js +192 -0
  54. package/dist/features/runtime/pageApp.js +5 -4
  55. package/dist/features/runtime/runtime.js +29 -8
  56. package/dist/features/runtime/worker.js +2 -2
  57. package/dist/features/runtime/workerRequest.d.ts +6 -0
  58. package/dist/features/runtime/workerRequest.js +13 -1
  59. package/dist/features/runtime/workerRuntime.d.ts +2 -2
  60. package/dist/features/runtime/workerRuntime.js +2 -2
  61. package/dist/features/studio/components/AgentSidebar.js +7 -7
  62. package/dist/features/studio/components/ChatWidget.js +142 -106
  63. package/dist/features/studio/components/ContentFindings.js +127 -230
  64. package/dist/features/studio/components/DeleteDraftDialog.js +112 -0
  65. package/dist/features/studio/components/DraftBar.js +98 -53
  66. package/dist/features/studio/components/DraftsControl.js +203 -190
  67. package/dist/features/studio/components/ReviewDraftDialog.js +670 -0
  68. package/dist/features/studio/components/{Patrol.js → Specialists.js} +291 -330
  69. package/dist/features/studio/components/Squareling.js +5 -5
  70. package/dist/features/studio/components/ThreadComposer.js +106 -127
  71. package/dist/features/studio/components/ThreadMessages.js +137 -45
  72. package/dist/features/studio/findingSentence.js +14 -12
  73. package/dist/features/studio/fixMessage.js +23 -0
  74. package/dist/features/studio/reportSentence.js +1 -1
  75. package/dist/features/studio/{patrollerBio.js → specialistBio.js} +8 -5
  76. package/dist/features/studio/studioStore.js +29 -15
  77. package/dist/features/studio/workingSentence.js +1 -1
  78. package/dist/features/vite/blockBoilerplate.js +1 -1
  79. package/dist/features/vite/definitionsSync.js +1 -8
  80. package/dist/lib/api-client.js +5 -1
  81. package/dist/lib/queries.js +5 -6
  82. package/dist/lib/studio-definitions.js +0 -2
  83. package/dist/lib/studio-reads.d.ts +1 -1
  84. package/dist/lib/studio-reads.js +5 -10
  85. package/dist/lib/use-thread.js +196 -138
  86. package/dist/package.js +1 -1
  87. package/dist/studio-overlays.css +0 -29
  88. package/dist/studio.css +1 -1
  89. package/package.json +4 -4
  90. package/skills/camox/SKILL.md +1 -1
  91. package/skills/camox/references/artifacts.md +4 -4
  92. package/skills/camox/references/block-definitions.md +21 -25
  93. package/skills/camox/references/dom-integrations.md +1 -1
  94. package/skills/camox/references/layout-definitions.md +3 -12
  95. package/skills/camox/references/routed-layouts.md +2 -2
  96. package/skills/camox-expand/SKILL.md +5 -5
  97. package/skills/camoxify/SKILL.md +4 -4
  98. package/dist/features/canvas/canvasInsertionSeams.js +0 -44
  99. package/dist/features/preview/components/AddBlockSheet.js +0 -314
  100. package/dist/features/preview/components/BlockPeek.js +0 -66
  101. package/dist/features/preview/components/BlockThumbnail.js +0 -281
  102. package/dist/features/preview/components/blockGridNavigation.js +0 -15
  103. package/dist/features/preview/referencePickerFocus.js +0 -29
  104. package/dist/features/studio/components/ReviewDraftSheet.js +0 -1587
@@ -12,82 +12,71 @@ import { Combobox } from "@base-ui/react/combobox";
12
12
  * current search text so it can prefill a new record.
13
13
  */
14
14
  function RecordCombobox(t0) {
15
- const $ = c(25);
16
- const { records, collectionTitle, onSelect, emptyMessage: emptyMessageOverride, footerAction, disabled, open: controlledOpen, onOpenChange } = t0;
17
- const [uncontrolledOpen, setUncontrolledOpen] = React.useState(false);
18
- const open = controlledOpen ?? uncontrolledOpen;
15
+ const $ = c(21);
16
+ const { records, collectionTitle, onSelect, emptyMessage: emptyMessageOverride, footerAction, disabled } = t0;
17
+ const [open, setOpen] = React.useState(false);
18
+ const [search, setSearch] = React.useState("");
19
+ const emptyMessage = records.length > 0 ? "No items found." : emptyMessageOverride ?? `${collectionTitle} has no items yet.`;
19
20
  let t1;
20
- if ($[0] !== onOpenChange) {
21
- t1 = (next) => {
22
- setUncontrolledOpen(next);
23
- onOpenChange?.(next);
21
+ if ($[0] !== onSelect) {
22
+ t1 = (record_2) => {
23
+ if (record_2) onSelect(record_2);
24
24
  };
25
- $[0] = onOpenChange;
25
+ $[0] = onSelect;
26
26
  $[1] = t1;
27
27
  } else t1 = $[1];
28
- const setOpen = t1;
29
- const [search, setSearch] = React.useState("");
30
- const emptyMessage = records.length > 0 ? "No items found." : emptyMessageOverride ?? `${collectionTitle} has no items yet.`;
31
28
  let t2;
32
- if ($[2] !== onSelect) {
33
- t2 = (record_2) => {
34
- if (record_2) onSelect(record_2);
35
- };
36
- $[2] = onSelect;
37
- $[3] = t2;
38
- } else t2 = $[3];
39
- let t3;
40
- if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
41
- t3 = /* @__PURE__ */ jsx(Button, {
29
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
30
+ t2 = /* @__PURE__ */ jsx(Button, {
42
31
  type: "button",
43
32
  variant: "outline",
44
33
  className: "w-full justify-between"
45
34
  });
46
- $[4] = t3;
47
- } else t3 = $[4];
48
- let t4;
49
- if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
50
- t4 = /* @__PURE__ */ jsxs(Combobox.Trigger, {
51
- render: t3,
35
+ $[2] = t2;
36
+ } else t2 = $[2];
37
+ let t3;
38
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
39
+ t3 = /* @__PURE__ */ jsxs(Combobox.Trigger, {
40
+ render: t2,
52
41
  children: ["Select item", /* @__PURE__ */ jsx(ChevronsUpDown, {
53
42
  "aria-hidden": true,
54
43
  className: "text-muted-foreground size-4"
55
44
  })]
56
45
  });
57
- $[5] = t4;
58
- } else t4 = $[5];
59
- let t5;
60
- if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
61
- t5 = /* @__PURE__ */ jsx(Combobox.Input, {
46
+ $[3] = t3;
47
+ } else t3 = $[3];
48
+ let t4;
49
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
50
+ t4 = /* @__PURE__ */ jsx(Combobox.Input, {
62
51
  render: /* @__PURE__ */ jsx(Input, { className: "mb-1" }),
63
52
  "aria-label": "Search items",
64
53
  placeholder: "Search items…"
65
54
  });
66
- $[6] = t5;
67
- } else t5 = $[6];
68
- let t6;
69
- if ($[7] !== emptyMessage) {
70
- t6 = /* @__PURE__ */ jsx(Combobox.Empty, {
55
+ $[4] = t4;
56
+ } else t4 = $[4];
57
+ let t5;
58
+ if ($[5] !== emptyMessage) {
59
+ t5 = /* @__PURE__ */ jsx(Combobox.Empty, {
71
60
  className: "text-muted-foreground text-sm",
72
61
  children: /* @__PURE__ */ jsx("div", {
73
62
  className: "p-2",
74
63
  children: emptyMessage
75
64
  })
76
65
  });
77
- $[7] = emptyMessage;
78
- $[8] = t6;
79
- } else t6 = $[8];
80
- let t7;
81
- if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
82
- t7 = /* @__PURE__ */ jsx(Combobox.List, {
66
+ $[5] = emptyMessage;
67
+ $[6] = t5;
68
+ } else t5 = $[6];
69
+ let t6;
70
+ if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
71
+ t6 = /* @__PURE__ */ jsx(Combobox.List, {
83
72
  className: "max-h-64 min-h-0 overflow-y-auto",
84
73
  children: _temp4
85
74
  });
86
- $[9] = t7;
87
- } else t7 = $[9];
88
- let t8;
89
- if ($[10] !== footerAction || $[11] !== search || $[12] !== setOpen) {
90
- t8 = footerAction && /* @__PURE__ */ jsx("div", {
75
+ $[7] = t6;
76
+ } else t6 = $[7];
77
+ let t7;
78
+ if ($[8] !== footerAction || $[9] !== search) {
79
+ t7 = footerAction && /* @__PURE__ */ jsx("div", {
91
80
  className: "mt-1 shrink-0 border-t pt-1",
92
81
  children: /* @__PURE__ */ jsxs("button", {
93
82
  type: "button",
@@ -102,34 +91,33 @@ function RecordCombobox(t0) {
102
91
  }), /* @__PURE__ */ jsx("span", { children: footerAction.label })]
103
92
  })
104
93
  });
105
- $[10] = footerAction;
106
- $[11] = search;
107
- $[12] = setOpen;
108
- $[13] = t8;
109
- } else t8 = $[13];
110
- let t9;
111
- if ($[14] !== t6 || $[15] !== t8) {
112
- t9 = /* @__PURE__ */ jsx(Combobox.Portal, { children: /* @__PURE__ */ jsx(Combobox.Positioner, {
94
+ $[8] = footerAction;
95
+ $[9] = search;
96
+ $[10] = t7;
97
+ } else t7 = $[10];
98
+ let t8;
99
+ if ($[11] !== t5 || $[12] !== t7) {
100
+ t8 = /* @__PURE__ */ jsx(Combobox.Portal, { children: /* @__PURE__ */ jsx(Combobox.Positioner, {
113
101
  sideOffset: 4,
114
102
  align: "start",
115
103
  className: "isolate z-50",
116
104
  children: /* @__PURE__ */ jsxs(Combobox.Popup, {
117
105
  className: "bg-popover text-popover-foreground ring-foreground/10 flex max-h-(--available-height) w-(--anchor-width) min-w-48 flex-col rounded-md p-1 shadow-md ring-1",
118
106
  children: [
107
+ t4,
119
108
  t5,
120
109
  t6,
121
- t7,
122
- t8
110
+ t7
123
111
  ]
124
112
  })
125
113
  }) });
126
- $[14] = t6;
127
- $[15] = t8;
128
- $[16] = t9;
129
- } else t9 = $[16];
130
- let t10;
131
- if ($[17] !== disabled || $[18] !== open || $[19] !== records || $[20] !== search || $[21] !== setOpen || $[22] !== t2 || $[23] !== t9) {
132
- t10 = /* @__PURE__ */ jsxs(Combobox.Root, {
114
+ $[11] = t5;
115
+ $[12] = t7;
116
+ $[13] = t8;
117
+ } else t8 = $[13];
118
+ let t9;
119
+ if ($[14] !== disabled || $[15] !== open || $[16] !== records || $[17] !== search || $[18] !== t1 || $[19] !== t8) {
120
+ t9 = /* @__PURE__ */ jsxs(Combobox.Root, {
133
121
  items: records,
134
122
  value: null,
135
123
  open,
@@ -139,20 +127,19 @@ function RecordCombobox(t0) {
139
127
  itemToStringLabel: _temp,
140
128
  itemToStringValue: _temp2,
141
129
  isItemEqualToValue: _temp3,
142
- onValueChange: t2,
130
+ onValueChange: t1,
143
131
  disabled,
144
- children: [t4, t9]
132
+ children: [t3, t8]
145
133
  });
146
- $[17] = disabled;
147
- $[18] = open;
148
- $[19] = records;
149
- $[20] = search;
150
- $[21] = setOpen;
151
- $[22] = t2;
152
- $[23] = t9;
153
- $[24] = t10;
154
- } else t10 = $[24];
155
- return t10;
134
+ $[14] = disabled;
135
+ $[15] = open;
136
+ $[16] = records;
137
+ $[17] = search;
138
+ $[18] = t1;
139
+ $[19] = t8;
140
+ $[20] = t9;
141
+ } else t9 = $[20];
142
+ return t9;
156
143
  }
157
144
  function _temp4(record_3) {
158
145
  return /* @__PURE__ */ jsx(Combobox.Item, {
@@ -3,7 +3,6 @@ import { reads, useReadQuery } from "../../../lib/studio-reads.js";
3
3
  import { titleField } from "../../../core/recordItem.js";
4
4
  import { useCollectionItemSheet } from "../../content/CollectionItemSheetContext.js";
5
5
  import { useCollectionDefinition } from "../../../lib/studio-definitions.js";
6
- import { referencePickerFocus, useReferencePickerFocusRequested } from "../referencePickerFocus.js";
7
6
  import { DrillRow } from "./DrillRow.js";
8
7
  import { RecordCard } from "./RecordCard.js";
9
8
  import { RecordCombobox } from "./RecordCombobox.js";
@@ -18,7 +17,7 @@ function referenceHint({ linked, required }) {
18
17
  return !linked && required ? "Required" : null;
19
18
  }
20
19
  /** This view owns the reference only. Record content is edited elsewhere. */
21
- function ReferenceFieldEditor({ collectionId, fieldId, value, required = false, record = null, onChange, onOpenRecord, drill, allowCreate = true }) {
20
+ function ReferenceFieldEditor({ collectionId, value, required = false, record = null, onChange, onOpenRecord, drill, allowCreate = true }) {
22
21
  const projectUuid = useProjectUuid();
23
22
  const collection = useCollectionDefinition(collectionId);
24
23
  const collectionTitle = collection?.title ?? collectionId;
@@ -33,9 +32,6 @@ function ReferenceFieldEditor({ collectionId, fieldId, value, required = false,
33
32
  const selected = records.data?.find((option) => option.id === value);
34
33
  const hydrated = record?.id === selectedId ? record : null;
35
34
  const selectedLabel = selected?.title ?? hydrated?.title ?? "Unavailable item";
36
- const [pickerOpen, setPickerOpen] = React.useState(false);
37
- const focusRequested = useReferencePickerFocusRequested(drill ? void 0 : fieldId);
38
- const pickerReady = !selectedId && records.isSuccess && !saving;
39
35
  const save = async (id) => {
40
36
  setSaving(true);
41
37
  setError(null);
@@ -51,18 +47,6 @@ function ReferenceFieldEditor({ collectionId, fieldId, value, required = false,
51
47
  const change = (id) => {
52
48
  save(id).catch(() => {});
53
49
  };
54
- React.useEffect(() => {
55
- if (!focusRequested || !fieldId || !pickerReady) return;
56
- referencePickerFocus.send({
57
- type: "consume",
58
- fieldId
59
- });
60
- setPickerOpen(true);
61
- }, [
62
- focusRequested,
63
- fieldId,
64
- pickerReady
65
- ]);
66
50
  const hint = referenceHint({
67
51
  linked: selectedId !== null,
68
52
  required
@@ -108,8 +92,6 @@ function ReferenceFieldEditor({ collectionId, fieldId, value, required = false,
108
92
  collectionTitle,
109
93
  onSelect: (option) => change(option.id),
110
94
  disabled: saving || records.isPending || records.isError,
111
- open: pickerOpen,
112
- onOpenChange: setPickerOpen,
113
95
  footerAction: allowCreate ? {
114
96
  label: "Create item",
115
97
  onSelect: (search) => sheet.open({
@@ -5,7 +5,6 @@ import { referenceListIds } from "../../../core/lib/reference.js";
5
5
  import { titleField } from "../../../core/recordItem.js";
6
6
  import { useCollectionItemSheet } from "../../content/CollectionItemSheetContext.js";
7
7
  import { useCollectionDefinition } from "../../../lib/studio-definitions.js";
8
- import { referencePickerFocus, useReferencePickerFocusRequested } from "../referencePickerFocus.js";
9
8
  import { DrillRow } from "./DrillRow.js";
10
9
  import { RecordCard } from "./RecordCard.js";
11
10
  import { RecordCombobox } from "./RecordCombobox.js";
@@ -253,7 +252,7 @@ function SortableRecordCard(t0) {
253
252
  * Manages which records a reference list links, and their order. Every change writes the
254
253
  * whole id array; records themselves are edited in their own view, never unlinked by deletion.
255
254
  */
256
- function ReferenceListFieldEditor({ collectionId, fieldId, value, maxItems, query, records: hydratedRecords = [], onChange, onOpenRecord, recordHover, drill, allowCreate = true }) {
255
+ function ReferenceListFieldEditor({ collectionId, value, maxItems, query, records: hydratedRecords = [], onChange, onOpenRecord, recordHover, drill, allowCreate = true }) {
257
256
  const projectUuid = useProjectUuid();
258
257
  const collection = useCollectionDefinition(collectionId);
259
258
  const collectionTitle = collection?.title ?? collectionId;
@@ -267,22 +266,7 @@ function ReferenceListFieldEditor({ collectionId, fieldId, value, maxItems, quer
267
266
  const ids = pendingIds ?? storedIds;
268
267
  const [saving, setSaving] = React.useState(false);
269
268
  const [error, setError] = React.useState(null);
270
- const [pickerOpen, setPickerOpen] = React.useState(false);
271
- const focusRequested = useReferencePickerFocusRequested(drill ? void 0 : fieldId);
272
269
  const canAdd = maxItems === void 0 || ids.length < maxItems;
273
- const pickerReady = canAdd && records.isSuccess && !saving;
274
- React.useEffect(() => {
275
- if (!focusRequested || !fieldId || !pickerReady) return;
276
- referencePickerFocus.send({
277
- type: "consume",
278
- fieldId
279
- });
280
- setPickerOpen(true);
281
- }, [
282
- focusRequested,
283
- fieldId,
284
- pickerReady
285
- ]);
286
270
  const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }));
287
271
  if (drill && query) {
288
272
  const count = hydratedRecords.length;
@@ -399,8 +383,6 @@ function ReferenceListFieldEditor({ collectionId, fieldId, value, maxItems, quer
399
383
  emptyMessage: records.data?.length ? `Every ${collectionTitle} item is already linked.` : void 0,
400
384
  onSelect: (option) => change([...ids, option.id]),
401
385
  disabled: saving || records.isPending || records.isError,
402
- open: pickerOpen,
403
- onOpenChange: setPickerOpen,
404
386
  footerAction: allowCreate ? {
405
387
  label: "Create item",
406
388
  onSelect: (search) => sheet.open({
@@ -12,8 +12,8 @@ import { Trash2 } from "lucide-react";
12
12
  * mode it shows this placeholder, whose only action is delete. Its content stays stored and
13
13
  * comes back if the definition does.
14
14
  */
15
- function RemovedBlockPlaceholder({ blockId, type, mode }) {
16
- const isEditable = useIsEditable(mode);
15
+ function RemovedBlockPlaceholder({ blockId, type }) {
16
+ const isEditable = useIsEditable();
17
17
  const applyEdit = useApplyContentEdit();
18
18
  const notify = useStudioNotice();
19
19
  const [deleting, setDeleting] = React.useState(false);
@@ -10,8 +10,8 @@ import { useEditingFrame } from "../editingFrame.js";
10
10
  import { SelectionViewCount, SidebarStackHeader, SidebarStackView } from "./SidebarStack.js";
11
11
  import { PreviewEditingOwnerContext } from "../previewSelection.js";
12
12
  import { entityName } from "../entityName.js";
13
- import { fieldTypesDictionary } from "../../../core/lib/fieldTypes.js";
14
13
  import { ContentFindings, findingsHint, useContentFindings } from "../../studio/components/ContentFindings.js";
14
+ import { fieldTypesDictionary } from "../../../core/lib/fieldTypes.js";
15
15
  import { usePageRecordPlacer } from "../pageRecord.js";
16
16
  import { contentFieldNames, contentFieldSchema } from "./contentFieldSchema.js";
17
17
  import { useRepeatableItemActions } from "./useRepeatableItemActions.js";
@@ -22,6 +22,7 @@ import { useFieldWriter } from "./useFieldWriter.js";
22
22
  import { useRecordView } from "./useRecordView.js";
23
23
  import { c } from "react/compiler-runtime";
24
24
  import * as React from "react";
25
+ import { emptyFieldValue } from "@camox/api-contract";
25
26
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
26
27
  import { useSelector } from "@xstate/store-react";
27
28
  import { useMutation } from "@tanstack/react-query";
@@ -817,7 +818,7 @@ const SelectionEditorContent = (t0) => {
817
818
  const label = field.label ?? formatFieldName(field.name);
818
819
  const settingsValues = block.settings ?? {};
819
820
  if (field.fieldType === "Enum") {
820
- const value_2 = settingsValues[field.name] ?? (blockDef.settingsSchema?.properties?.[field.name])?.default ?? "";
821
+ const value_2 = String(settingsValues[field.name] ?? emptyFieldValue(blockDef.settingsSchema?.properties?.[field.name]));
821
822
  return /* @__PURE__ */ jsxs("div", {
822
823
  className: "space-y-2",
823
824
  children: [/* @__PURE__ */ jsx(Label, {
@@ -842,7 +843,7 @@ const SelectionEditorContent = (t0) => {
842
843
  }, field.name);
843
844
  }
844
845
  if (field.fieldType === "Boolean") {
845
- const checked = settingsValues[field.name] ?? (blockDef.settingsSchema?.properties?.[field.name])?.default ?? false;
846
+ const checked = settingsValues[field.name] === true;
846
847
  return /* @__PURE__ */ jsxs("div", {
847
848
  className: "flex items-center justify-between",
848
849
  children: [/* @__PURE__ */ jsx(Label, {
@@ -871,7 +872,7 @@ const SelectionEditorContent = (t0) => {
871
872
  const itemSettingsValues = currentItem?.settings ?? {};
872
873
  const itemSettingsSchemaProps = itemArraySchema?.itemSettingsSchema?.properties;
873
874
  if (field_0.fieldType === "Enum") {
874
- const value_3 = itemSettingsValues[field_0.name] ?? itemSettingsSchemaProps?.[field_0.name]?.default ?? "";
875
+ const value_3 = String(itemSettingsValues[field_0.name] ?? emptyFieldValue(itemSettingsSchemaProps?.[field_0.name]));
875
876
  return /* @__PURE__ */ jsxs("div", {
876
877
  className: "space-y-2",
877
878
  children: [/* @__PURE__ */ jsx(Label, {
@@ -896,7 +897,7 @@ const SelectionEditorContent = (t0) => {
896
897
  }, field_0.name);
897
898
  }
898
899
  if (field_0.fieldType === "Boolean") {
899
- const checked_0 = itemSettingsValues[field_0.name] ?? itemSettingsSchemaProps?.[field_0.name]?.default ?? false;
900
+ const checked_0 = itemSettingsValues[field_0.name] === true;
900
901
  return /* @__PURE__ */ jsxs("div", {
901
902
  className: "flex items-center justify-between",
902
903
  children: [/* @__PURE__ */ jsx(Label, {
@@ -3,35 +3,31 @@ import { previewStore, sameEditingOwner } from "../previewStore.js";
3
3
  import { PreviewEditingOwnerContext } from "../previewSelection.js";
4
4
  import { c } from "react/compiler-runtime";
5
5
  import * as React from "react";
6
- import { generateKeyBetween } from "fractional-indexing";
6
+ import { emptyFieldValues } from "@camox/api-contract";
7
7
  import { useMutation } from "@tanstack/react-query";
8
+ import { generateKeyBetween } from "fractional-indexing";
8
9
 
9
10
  //#region src/features/preview/components/useRepeatableItemActions.ts
10
- const buildDefaultContent = (itemProperties) => {
11
- const content = {};
12
- if (!itemProperties) return content;
13
- for (const [key, prop] of Object.entries(itemProperties)) {
14
- if (prop.fieldType === "Image" || prop.fieldType === "File") continue;
15
- if (prop.type === "array" && prop.items?.properties) continue;
16
- if ("default" in prop) content[key] = prop.default;
17
- }
11
+ /** A new item's content: every field empty, except nested repeaters, whose items are rows. */
12
+ const emptyItemContent = (itemProperties) => {
13
+ const content = emptyFieldValues({ properties: itemProperties });
14
+ for (const [key, prop] of Object.entries(itemProperties ?? {})) if (prop.fieldType === "Repeater") delete content[key];
18
15
  return content;
19
16
  };
17
+ /** A new item's settings: every setting empty, or none when the repeater has no settings. */
18
+ const emptyItemSettings = (schema) => schema.itemSettingsSchema ? emptyFieldValues(schema.itemSettingsSchema) : void 0;
19
+ /** The empty items a new item's nested repeaters start with: as many as each requires. */
20
20
  const buildNestedItemSeeds = (itemProperties) => {
21
21
  const seeds = [];
22
22
  if (!itemProperties) return seeds;
23
23
  let counter = 0;
24
24
  const recurse = (properties, parentTempId) => {
25
25
  for (const [fieldName, fieldSchema] of Object.entries(properties)) {
26
- if (fieldSchema.type !== "array" || !fieldSchema.items?.properties) continue;
27
- if (fieldSchema.fieldType === "ImageList" || fieldSchema.fieldType === "FileList") continue;
28
- const defaultCount = fieldSchema.defaultItems ?? fieldSchema.minItems ?? 0;
29
- if (defaultCount <= 0) continue;
30
- const nestedItemProps = fieldSchema.items.properties;
31
- const nestedContent = buildDefaultContent(nestedItemProps);
32
- const nestedSettingsDefaults = fieldSchema.defaultItemSettings;
26
+ if (fieldSchema.fieldType !== "Repeater") continue;
27
+ const count = fieldSchema.minItems ?? 0;
28
+ const nestedItemProps = fieldSchema.items?.properties;
33
29
  let prevPos = null;
34
- for (let i = 0; i < defaultCount; i++) {
30
+ for (let i = 0; i < count; i++) {
35
31
  const tempId = `nested_${++counter}`;
36
32
  const position = generateKeyBetween(prevPos, null);
37
33
  prevPos = position;
@@ -39,11 +35,11 @@ const buildNestedItemSeeds = (itemProperties) => {
39
35
  tempId,
40
36
  parentTempId,
41
37
  fieldName,
42
- content: { ...nestedContent },
43
- settings: nestedSettingsDefaults ? { ...nestedSettingsDefaults } : void 0,
38
+ content: emptyItemContent(nestedItemProps),
39
+ settings: emptyItemSettings(fieldSchema),
44
40
  position
45
41
  });
46
- recurse(nestedItemProps, tempId);
42
+ if (nestedItemProps) recurse(nestedItemProps, tempId);
47
43
  }
48
44
  }
49
45
  };
@@ -74,15 +70,13 @@ const useRepeatableItemActions = (t0) => {
74
70
  if (owner === null) return;
75
71
  if (!arraySchema) return;
76
72
  const itemsSchema = arraySchema.items;
77
- const defaultContent = buildDefaultContent(itemsSchema?.properties);
78
- const defaultSettings = arraySchema.defaultItemSettings;
79
73
  const nestedItems = buildNestedItemSeeds(itemsSchema?.properties);
80
74
  createRepeatableItem.mutate({
81
75
  blockId,
82
76
  parentItemId: parentItemId ?? void 0,
83
77
  fieldName,
84
- content: defaultContent,
85
- settings: defaultSettings ? { ...defaultSettings } : void 0,
78
+ content: emptyItemContent(itemsSchema?.properties),
79
+ settings: emptyItemSettings(arraySchema),
86
80
  nestedItems: nestedItems.length > 0 ? nestedItems : void 0,
87
81
  afterPosition: options?.afterPosition
88
82
  }, { onSuccess: (created) => {
@@ -3,8 +3,8 @@ import { reads, useStudioCache } from "../../../lib/studio-reads.js";
3
3
  import { blockMutations } from "../../../lib/queries.js";
4
4
  import { useLocalePath } from "../../../lib/view-locale.js";
5
5
  import { c } from "react/compiler-runtime";
6
- import { generateKeyBetween } from "fractional-indexing";
7
6
  import { useMutation } from "@tanstack/react-query";
7
+ import { generateKeyBetween } from "fractional-indexing";
8
8
 
9
9
  //#region src/features/preview/components/useUpdateBlockPosition.ts
10
10
  function useUpdateBlockPosition() {
@@ -73,9 +73,6 @@ function selectionHoverMessage(selection, hovered) {
73
73
  function isOverlayMessage(data) {
74
74
  return typeof data === "object" && data !== null && "type" in data && typeof data.type === "string" && data.type.startsWith("CAMOX_");
75
75
  }
76
- function postOverlayMessage(message) {
77
- window.parent?.postMessage(message, "*");
78
- }
79
76
 
80
77
  //#endregion
81
- export { isOverlayMessage, overlayFieldId, postOverlayMessage, recordFieldId, recordPlacementId, selectionHoverMessage };
78
+ export { isOverlayMessage, overlayFieldId, recordFieldId, recordPlacementId, selectionHoverMessage };
@@ -97,7 +97,6 @@ const selectIsCanvasShown = (state) => state.context.view === "canvas";
97
97
  const initialPreviewContext = {
98
98
  view: "preview",
99
99
  isToolbarHidden: false,
100
- addBlockSheet: null,
101
100
  isCreatePageModalOpen: false,
102
101
  editingPageId: null,
103
102
  viewportMode: "full",
@@ -151,8 +150,7 @@ const previewStore = createStore({
151
150
  if (sameEditingOwner(context.editingContext, owner)) return context;
152
151
  return {
153
152
  ...context,
154
- editingContext: owner ? targetContext(owner, null) : null,
155
- addBlockSheet: null
153
+ editingContext: owner ? targetContext(owner, null) : null
156
154
  };
157
155
  },
158
156
  activateLayout: (context, event) => {
@@ -163,8 +161,7 @@ const previewStore = createStore({
163
161
  if (sameEditingOwner(context.editingContext, owner)) return context;
164
162
  return {
165
163
  ...context,
166
- editingContext: targetContext(owner, null),
167
- addBlockSheet: null
164
+ editingContext: targetContext(owner, null)
168
165
  };
169
166
  },
170
167
  selectTarget: (context, event) => ({
@@ -176,8 +173,7 @@ const previewStore = createStore({
176
173
  editingContext: targetContext(event, {
177
174
  type: "block",
178
175
  blockId: event.blockId
179
- }),
180
- addBlockSheet: null
176
+ })
181
177
  }),
182
178
  selectItem: (context, event) => ({
183
179
  ...context,
@@ -314,22 +310,6 @@ const previewStore = createStore({
314
310
  selection: null
315
311
  } : null
316
312
  }),
317
- openAddBlockSheet: (context, event) => ({
318
- ...context,
319
- addBlockSheet: { afterPosition: event.afterPosition }
320
- }),
321
- closeAddBlockSheet: (context) => ({
322
- ...context,
323
- addBlockSheet: null
324
- }),
325
- focusCreatedBlock: (context, event) => ({
326
- ...context,
327
- editingContext: targetContext(event, {
328
- type: "block",
329
- blockId: event.blockId
330
- }),
331
- addBlockSheet: null
332
- }),
333
313
  openCreatePageModal: (context) => ({
334
314
  ...context,
335
315
  isCreatePageModalOpen: true