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.
- package/dist/core/createApp.d.ts +4 -103
- package/dist/core/createApp.js +3 -24
- package/dist/core/createBlock.d.ts +2 -2
- package/dist/core/createBlock.js +41 -185
- package/dist/core/createLayout.d.ts +6 -77
- package/dist/core/createLayout.js +12 -50
- package/dist/core/editing/createEditableBlock.d.ts +9 -75
- package/dist/core/editing/createEditableBlock.js +258 -640
- package/dist/core/hooks/useIsEditable.js +2 -2
- package/dist/core/lib/artifactData.js +8 -3
- package/dist/core/lib/contentType.d.ts +23 -38
- package/dist/core/lib/contentType.js +34 -62
- package/dist/core/lib/iconTypes.d.ts +0 -3
- package/dist/core/lib/icons.js +63 -51
- package/dist/core/lib/recordScope.js +1 -1
- package/dist/features/canvas/CanvasOverlays.js +94 -176
- package/dist/features/canvas/CanvasPageFrame.js +62 -68
- package/dist/features/canvas/CanvasPreviewPageSlot.js +1 -3
- package/dist/features/canvas/canvasOverlayGeometry.js +1 -7
- package/dist/features/canvas/sidebar/CuratedPageInspector.js +3 -21
- package/dist/features/canvas/sidebar/LayoutPageBlocks.js +1 -2
- package/dist/features/canvas/useCanvasCamera.js +1 -1
- package/dist/features/canvas/useCanvasFrame.js +1 -1
- package/dist/features/content/ContentCollection.js +2 -2
- package/dist/features/content/collection-form.js +6 -7
- package/dist/features/page/CuratedPageContent.js +15 -24
- package/dist/features/page/UnplacedBlockContent.js +1 -6
- package/dist/features/preview/CamoxPreview.js +30 -33
- package/dist/features/preview/EditablePageContent.js +131 -151
- package/dist/features/preview/components/BlockActionsPopover.js +43 -152
- package/dist/features/preview/components/CanvasPreview.js +2 -2
- package/dist/features/preview/components/Frame.js +3 -3
- package/dist/features/preview/components/IconFieldEditor.js +1 -1
- package/dist/features/preview/components/ItemFieldsEditor.js +1 -3
- package/dist/features/preview/components/Overlays.js +18 -84
- package/dist/features/preview/components/PageInfo.js +121 -98
- package/dist/features/preview/components/PageTree.js +57 -103
- package/dist/features/preview/components/PreviewPanel.js +8 -11
- package/dist/features/preview/components/RecordCombobox.js +65 -78
- package/dist/features/preview/components/ReferenceFieldEditor.js +1 -19
- package/dist/features/preview/components/ReferenceListFieldEditor.js +1 -19
- package/dist/features/preview/components/RemovedBlockPlaceholder.js +2 -2
- package/dist/features/preview/components/SelectionEditor.js +6 -5
- package/dist/features/preview/components/useRepeatableItemActions.js +18 -24
- package/dist/features/preview/components/useUpdateBlockPosition.js +1 -1
- package/dist/features/preview/overlayMessages.js +1 -4
- package/dist/features/preview/previewStore.js +3 -23
- package/dist/features/renderer/RendererApp.js +17 -141
- package/dist/features/renderer/definitionAnswers.js +1 -8
- package/dist/features/renderer/rendererHost.js +1 -31
- package/dist/features/renderer/studioConnection.js +1 -25
- package/dist/features/routes/pageRuntime.js +15 -4
- package/dist/features/runtime/ClaimCard.js +192 -0
- package/dist/features/runtime/pageApp.js +5 -4
- package/dist/features/runtime/runtime.js +29 -8
- package/dist/features/runtime/worker.js +2 -2
- package/dist/features/runtime/workerRequest.d.ts +6 -0
- package/dist/features/runtime/workerRequest.js +13 -1
- package/dist/features/runtime/workerRuntime.d.ts +2 -2
- package/dist/features/runtime/workerRuntime.js +2 -2
- package/dist/features/studio/components/AgentSidebar.js +7 -7
- package/dist/features/studio/components/ChatWidget.js +142 -106
- package/dist/features/studio/components/ContentFindings.js +127 -230
- package/dist/features/studio/components/DeleteDraftDialog.js +112 -0
- package/dist/features/studio/components/DraftBar.js +98 -53
- package/dist/features/studio/components/DraftsControl.js +203 -190
- package/dist/features/studio/components/ReviewDraftDialog.js +670 -0
- package/dist/features/studio/components/{Patrol.js → Specialists.js} +291 -330
- package/dist/features/studio/components/Squareling.js +5 -5
- package/dist/features/studio/components/ThreadComposer.js +106 -127
- package/dist/features/studio/components/ThreadMessages.js +137 -45
- package/dist/features/studio/findingSentence.js +14 -12
- package/dist/features/studio/fixMessage.js +23 -0
- package/dist/features/studio/reportSentence.js +1 -1
- package/dist/features/studio/{patrollerBio.js → specialistBio.js} +8 -5
- package/dist/features/studio/studioStore.js +29 -15
- package/dist/features/studio/workingSentence.js +1 -1
- package/dist/features/vite/blockBoilerplate.js +1 -1
- package/dist/features/vite/definitionsSync.js +1 -8
- package/dist/lib/api-client.js +5 -1
- package/dist/lib/queries.js +5 -6
- package/dist/lib/studio-definitions.js +0 -2
- package/dist/lib/studio-reads.d.ts +1 -1
- package/dist/lib/studio-reads.js +5 -10
- package/dist/lib/use-thread.js +196 -138
- package/dist/package.js +1 -1
- package/dist/studio-overlays.css +0 -29
- package/dist/studio.css +1 -1
- package/package.json +4 -4
- package/skills/camox/SKILL.md +1 -1
- package/skills/camox/references/artifacts.md +4 -4
- package/skills/camox/references/block-definitions.md +21 -25
- package/skills/camox/references/dom-integrations.md +1 -1
- package/skills/camox/references/layout-definitions.md +3 -12
- package/skills/camox/references/routed-layouts.md +2 -2
- package/skills/camox-expand/SKILL.md +5 -5
- package/skills/camoxify/SKILL.md +4 -4
- package/dist/features/canvas/canvasInsertionSeams.js +0 -44
- package/dist/features/preview/components/AddBlockSheet.js +0 -314
- package/dist/features/preview/components/BlockPeek.js +0 -66
- package/dist/features/preview/components/BlockThumbnail.js +0 -281
- package/dist/features/preview/components/blockGridNavigation.js +0 -15
- package/dist/features/preview/referencePickerFocus.js +0 -29
- 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(
|
|
16
|
-
const { records, collectionTitle, onSelect, emptyMessage: emptyMessageOverride, footerAction, disabled
|
|
17
|
-
const [
|
|
18
|
-
const
|
|
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] !==
|
|
21
|
-
t1 = (
|
|
22
|
-
|
|
23
|
-
onOpenChange?.(next);
|
|
21
|
+
if ($[0] !== onSelect) {
|
|
22
|
+
t1 = (record_2) => {
|
|
23
|
+
if (record_2) onSelect(record_2);
|
|
24
24
|
};
|
|
25
|
-
$[0] =
|
|
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]
|
|
33
|
-
t2 = (
|
|
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
|
-
$[
|
|
47
|
-
} else
|
|
48
|
-
let
|
|
49
|
-
if ($[
|
|
50
|
-
|
|
51
|
-
render:
|
|
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
|
-
$[
|
|
58
|
-
} else
|
|
59
|
-
let
|
|
60
|
-
if ($[
|
|
61
|
-
|
|
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
|
-
$[
|
|
67
|
-
} else
|
|
68
|
-
let
|
|
69
|
-
if ($[
|
|
70
|
-
|
|
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
|
-
$[
|
|
78
|
-
$[
|
|
79
|
-
} else
|
|
80
|
-
let
|
|
81
|
-
if ($[
|
|
82
|
-
|
|
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
|
-
$[
|
|
87
|
-
} else
|
|
88
|
-
let
|
|
89
|
-
if ($[
|
|
90
|
-
|
|
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
|
-
$[
|
|
106
|
-
$[
|
|
107
|
-
$[
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
$[
|
|
127
|
-
$[
|
|
128
|
-
$[
|
|
129
|
-
} else
|
|
130
|
-
let
|
|
131
|
-
if ($[
|
|
132
|
-
|
|
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:
|
|
130
|
+
onValueChange: t1,
|
|
143
131
|
disabled,
|
|
144
|
-
children: [
|
|
132
|
+
children: [t3, t8]
|
|
145
133
|
});
|
|
146
|
-
$[
|
|
147
|
-
$[
|
|
148
|
-
$[
|
|
149
|
-
$[
|
|
150
|
-
$[
|
|
151
|
-
$[
|
|
152
|
-
$[
|
|
153
|
-
|
|
154
|
-
|
|
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,
|
|
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,
|
|
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
|
|
16
|
-
const isEditable = useIsEditable(
|
|
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])
|
|
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]
|
|
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]
|
|
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]
|
|
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 {
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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.
|
|
27
|
-
|
|
28
|
-
const
|
|
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 <
|
|
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:
|
|
43
|
-
settings:
|
|
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:
|
|
85
|
-
settings:
|
|
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,
|
|
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
|