camox 0.46.0 → 0.48.0
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 +19 -6
- package/dist/core/createApp.js +7 -2
- package/dist/core/createBlock.js +54 -43
- package/dist/core/createCollection.d.ts +25 -7
- package/dist/core/createCollection.js +28 -9
- package/dist/core/createLayout.d.ts +98 -71
- package/dist/core/createLayout.js +10 -16
- package/dist/core/derivedRoutes.js +1 -1
- package/dist/core/editing/BlockEditingRuntime.d.ts +3 -2
- package/dist/core/editing/CompleteBlockEditingRuntime.js +2 -1
- package/dist/core/editing/createEditableBlock.d.ts +59 -19
- package/dist/core/editing/createEditableBlock.js +162 -151
- package/dist/core/editing/useLatestRecord.js +7 -7
- package/dist/core/layoutContext.d.ts +54 -0
- package/dist/core/layoutContext.js +66 -0
- package/dist/core/lib/contentType.d.ts +91 -4
- package/dist/core/lib/contentType.js +84 -7
- package/dist/core/lib/recordScope.js +19 -17
- package/dist/core/lib/reference.d.ts +6 -2
- package/dist/core/recordItem.js +55 -2
- package/dist/core/requestContext.d.ts +18 -0
- package/dist/core/structuredData.d.ts +126 -0
- package/dist/core/structuredData.js +40 -0
- package/dist/features/canvas/canvasCamera.js +21 -6
- package/dist/features/canvas/sidebar/CanvasSidebarFrame.js +1 -1
- package/dist/features/canvas/useCanvasCamera.js +16 -11
- package/dist/features/content/ContentCollection.js +13 -7
- package/dist/features/content/collection-form.js +6 -2
- package/dist/features/content/components/MissingFromLocale.js +1 -1
- package/dist/features/og/pageImage.js +89 -0
- package/dist/features/page/CuratedPageContent.js +45 -32
- package/dist/features/page/DerivedPageContent.js +49 -22
- package/dist/features/page/SharedLayoutContent.js +26 -22
- package/dist/features/preview/CamoxPreview.js +176 -145
- package/dist/features/preview/components/AddBlockSheet.js +1 -0
- package/dist/features/preview/components/BlockActionsPopover.js +8 -6
- package/dist/features/preview/components/PageInfo.js +244 -264
- package/dist/features/preview/components/PageTree.js +63 -53
- package/dist/features/preview/components/PreviewToolbar.js +74 -85
- package/dist/features/preview/components/RecordCard.js +50 -34
- package/dist/features/preview/components/RecordCombobox.js +12 -5
- package/dist/features/preview/components/ReferenceFieldEditor.js +4 -2
- package/dist/features/preview/components/ReferenceListFieldEditor.js +24 -19
- package/dist/features/preview/components/RepeatableItemsList.js +62 -46
- package/dist/features/preview/components/SelectionEditor.js +3 -2
- package/dist/features/preview/components/useFieldWriter.js +2 -4
- package/dist/features/preview/components/useRecordView.js +2 -2
- package/dist/features/preview/entityName.js +11 -0
- package/dist/features/preview/pageRecord.js +17 -18
- package/dist/features/provider/CamoxProvider.js +8 -16
- package/dist/features/provider/CoreCamoxProvider.js +1 -6
- package/dist/features/provider/signInShortcut.js +60 -0
- package/dist/features/routes/pageRuntime.d.ts +15 -1
- package/dist/features/routes/pageRuntime.js +35 -38
- package/dist/features/runtime/RuntimeChrome.js +2 -2
- package/dist/features/runtime/breadcrumbs.js +68 -0
- package/dist/features/runtime/livePages.js +3 -2
- package/dist/features/runtime/pageApp.js +11 -39
- package/dist/features/runtime/pageGraph.js +92 -0
- package/dist/features/runtime/projectLogo.js +110 -0
- package/dist/features/runtime/runtime.d.ts +11 -6
- package/dist/features/runtime/runtime.js +278 -55
- package/dist/features/runtime/runtimeRoutes.d.ts +1 -0
- package/dist/features/runtime/runtimeRoutes.js +1 -0
- package/dist/features/runtime/structuredData.js +213 -0
- package/dist/features/studio/components/ChatSidebar.js +5 -5
- package/dist/features/studio/components/ProjectMenu.js +127 -100
- package/dist/features/studio/components/SocialProfilesDialog.js +342 -0
- package/dist/features/studio/components/ThreadMessages.js +2 -2
- package/dist/features/vite/blockBoilerplate.js +3 -2
- package/dist/features/vite/layoutGeneration.js +3 -2
- package/dist/features/vite/vite.js +1 -0
- package/dist/lib/queries.d.ts +4 -0
- package/dist/lib/queries.js +1 -0
- package/dist/lib/studio-reads.js +3 -1
- package/dist/package.js +1 -1
- package/dist/studio.css +1 -1
- package/package.json +5 -4
- package/skills/camox/references/block-definitions.md +105 -25
- package/skills/camox/references/layout-definitions.md +53 -17
- package/skills/camox/references/routed-layouts.md +17 -14
- package/dist/features/provider/LocalhostPreviewProvider.js +0 -158
|
@@ -3,6 +3,7 @@ import { useProjectUuid } from "../../../lib/auth.js";
|
|
|
3
3
|
import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
|
|
4
4
|
import { reads, useReadQuery } from "../../../lib/studio-reads.js";
|
|
5
5
|
import { referenceListIds } from "../../../core/lib/reference.js";
|
|
6
|
+
import { titleField } from "../../../core/recordItem.js";
|
|
6
7
|
import { useCollectionItemSheet } from "../../content/CollectionItemSheetContext.js";
|
|
7
8
|
import { referencePickerFocus, useReferencePickerFocusRequested } from "../referencePickerFocus.js";
|
|
8
9
|
import { DrillRow } from "./DrillRow.js";
|
|
@@ -119,8 +120,8 @@ function QueryResultCard(t0) {
|
|
|
119
120
|
return t2;
|
|
120
121
|
}
|
|
121
122
|
function SortableRecordCard(t0) {
|
|
122
|
-
const $ = c(
|
|
123
|
-
const { id, label, collectionTitle, onOpen, onUnlink, hover } = t0;
|
|
123
|
+
const $ = c(32);
|
|
124
|
+
const { id, label, description, collectionTitle, onOpen, onUnlink, hover } = t0;
|
|
124
125
|
let t1;
|
|
125
126
|
if ($[0] !== id) {
|
|
126
127
|
t1 = { id };
|
|
@@ -214,23 +215,25 @@ function SortableRecordCard(t0) {
|
|
|
214
215
|
$[19] = t11;
|
|
215
216
|
} else t11 = $[19];
|
|
216
217
|
let t12;
|
|
217
|
-
if ($[20] !== collectionTitle || $[21] !==
|
|
218
|
+
if ($[20] !== collectionTitle || $[21] !== description || $[22] !== label || $[23] !== onOpen || $[24] !== t11 || $[25] !== t6) {
|
|
218
219
|
t12 = /* @__PURE__ */ jsx(RecordCard, {
|
|
219
220
|
label,
|
|
221
|
+
description,
|
|
220
222
|
collectionTitle,
|
|
221
223
|
onOpen,
|
|
222
224
|
leading: t6,
|
|
223
225
|
actions: t11
|
|
224
226
|
});
|
|
225
227
|
$[20] = collectionTitle;
|
|
226
|
-
$[21] =
|
|
227
|
-
$[22] =
|
|
228
|
-
$[23] =
|
|
229
|
-
$[24] =
|
|
230
|
-
$[25] =
|
|
231
|
-
|
|
228
|
+
$[21] = description;
|
|
229
|
+
$[22] = label;
|
|
230
|
+
$[23] = onOpen;
|
|
231
|
+
$[24] = t11;
|
|
232
|
+
$[25] = t6;
|
|
233
|
+
$[26] = t12;
|
|
234
|
+
} else t12 = $[26];
|
|
232
235
|
let t13;
|
|
233
|
-
if ($[
|
|
236
|
+
if ($[27] !== hoverHandlers || $[28] !== setNodeRef || $[29] !== t12 || $[30] !== t4) {
|
|
234
237
|
t13 = /* @__PURE__ */ jsx("li", {
|
|
235
238
|
ref: setNodeRef,
|
|
236
239
|
...hoverHandlers,
|
|
@@ -238,12 +241,12 @@ function SortableRecordCard(t0) {
|
|
|
238
241
|
className: "min-w-0",
|
|
239
242
|
children: t12
|
|
240
243
|
});
|
|
241
|
-
$[
|
|
242
|
-
$[
|
|
243
|
-
$[
|
|
244
|
-
$[
|
|
245
|
-
$[
|
|
246
|
-
} else t13 = $[
|
|
244
|
+
$[27] = hoverHandlers;
|
|
245
|
+
$[28] = setNodeRef;
|
|
246
|
+
$[29] = t12;
|
|
247
|
+
$[30] = t4;
|
|
248
|
+
$[31] = t13;
|
|
249
|
+
} else t13 = $[31];
|
|
247
250
|
return t13;
|
|
248
251
|
}
|
|
249
252
|
/**
|
|
@@ -317,7 +320,8 @@ function ReferenceListFieldEditor({ collectionId, fieldId, value, maxItems, quer
|
|
|
317
320
|
}), hydratedRecords.length > 0 && /* @__PURE__ */ jsx("ul", {
|
|
318
321
|
className: "flex min-w-0 flex-col gap-2",
|
|
319
322
|
children: hydratedRecords.map((record) => /* @__PURE__ */ jsx(QueryResultCard, {
|
|
320
|
-
label: record.
|
|
323
|
+
label: record.title,
|
|
324
|
+
description: record.description,
|
|
321
325
|
collectionTitle,
|
|
322
326
|
onOpen: onOpenRecord ? () => onOpenRecord(record.id) : void 0,
|
|
323
327
|
hover: entryHover(recordHover, record.id)
|
|
@@ -370,7 +374,8 @@ function ReferenceListFieldEditor({ collectionId, fieldId, value, maxItems, quer
|
|
|
370
374
|
const hydrated = hydratedRecords.find((record) => record.id === id);
|
|
371
375
|
return /* @__PURE__ */ jsx(SortableRecordCard, {
|
|
372
376
|
id,
|
|
373
|
-
label: summary?.
|
|
377
|
+
label: summary?.title ?? hydrated?.title ?? "Unavailable item",
|
|
378
|
+
description: summary ? summary.description : hydrated?.description,
|
|
374
379
|
collectionTitle,
|
|
375
380
|
onOpen: onOpenRecord ? () => onOpenRecord(id) : void 0,
|
|
376
381
|
onUnlink: () => change(ids.filter((linked) => linked !== id)),
|
|
@@ -400,7 +405,7 @@ function ReferenceListFieldEditor({ collectionId, fieldId, value, maxItems, quer
|
|
|
400
405
|
label: "Create item",
|
|
401
406
|
onSelect: (search) => sheet.open({
|
|
402
407
|
collectionId,
|
|
403
|
-
initialContent: collection && search.trim() ? { [collection._internal.
|
|
408
|
+
initialContent: collection && search.trim() && titleField(collection._internal.toTitle) ? { [titleField(collection._internal.toTitle)]: search } : void 0,
|
|
404
409
|
onSaved: (created) => save([...ids, created.id])
|
|
405
410
|
})
|
|
406
411
|
} : void 0
|
|
@@ -3,6 +3,7 @@ import { repeatableItemMutations } from "../../../lib/queries.js";
|
|
|
3
3
|
import { previewStore, selectionItemId } from "../previewStore.js";
|
|
4
4
|
import { useEditingFrame } from "../editingFrame.js";
|
|
5
5
|
import { PreviewEditingOwnerContext, usePreviewTargetSelection } from "../previewSelection.js";
|
|
6
|
+
import { entityName } from "../entityName.js";
|
|
6
7
|
import { useRepeatableItemActions } from "./useRepeatableItemActions.js";
|
|
7
8
|
import { c } from "react/compiler-runtime";
|
|
8
9
|
import { useContext } from "react";
|
|
@@ -18,7 +19,7 @@ import { CSS } from "@dnd-kit/utilities";
|
|
|
18
19
|
|
|
19
20
|
//#region src/features/preview/components/RepeatableItemsList.tsx
|
|
20
21
|
const SortableRepeatableItem = (t0) => {
|
|
21
|
-
const $ = c(
|
|
22
|
+
const $ = c(53);
|
|
22
23
|
const { item, fieldName, blockId, canRemove, onRemove } = t0;
|
|
23
24
|
const owner = useContext(PreviewEditingOwnerContext);
|
|
24
25
|
let t1;
|
|
@@ -113,9 +114,17 @@ const SortableRepeatableItem = (t0) => {
|
|
|
113
114
|
$[23] = listeners;
|
|
114
115
|
$[24] = t13;
|
|
115
116
|
} else t13 = $[24];
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
const t14 = `${fieldName} (${item.id})`;
|
|
118
|
+
let t15;
|
|
119
|
+
if ($[25] !== item || $[26] !== t14) {
|
|
120
|
+
t15 = entityName(item, t14);
|
|
121
|
+
$[25] = item;
|
|
122
|
+
$[26] = t14;
|
|
123
|
+
$[27] = t15;
|
|
124
|
+
} else t15 = $[27];
|
|
125
|
+
let t16;
|
|
126
|
+
if ($[28] !== blockId || $[29] !== handleMouseLeave || $[30] !== item.id || $[31] !== owner) {
|
|
127
|
+
t16 = () => {
|
|
119
128
|
if (owner === null) return;
|
|
120
129
|
handleMouseLeave();
|
|
121
130
|
previewStore.send({
|
|
@@ -125,32 +134,39 @@ const SortableRepeatableItem = (t0) => {
|
|
|
125
134
|
itemId: item.id
|
|
126
135
|
});
|
|
127
136
|
};
|
|
128
|
-
$[
|
|
129
|
-
$[
|
|
130
|
-
$[
|
|
131
|
-
$[
|
|
132
|
-
$[
|
|
133
|
-
} else
|
|
134
|
-
const
|
|
135
|
-
let
|
|
136
|
-
if ($[
|
|
137
|
-
|
|
137
|
+
$[28] = blockId;
|
|
138
|
+
$[29] = handleMouseLeave;
|
|
139
|
+
$[30] = item.id;
|
|
140
|
+
$[31] = owner;
|
|
141
|
+
$[32] = t16;
|
|
142
|
+
} else t16 = $[32];
|
|
143
|
+
const t17 = `${fieldName} (${item.id})`;
|
|
144
|
+
let t18;
|
|
145
|
+
if ($[33] !== item || $[34] !== t17) {
|
|
146
|
+
t18 = entityName(item, t17);
|
|
147
|
+
$[33] = item;
|
|
148
|
+
$[34] = t17;
|
|
149
|
+
$[35] = t18;
|
|
150
|
+
} else t18 = $[35];
|
|
151
|
+
let t19;
|
|
152
|
+
if ($[36] !== t15 || $[37] !== t16 || $[38] !== t18) {
|
|
153
|
+
t19 = /* @__PURE__ */ jsx("div", {
|
|
138
154
|
className: "flex flex-1 items-center gap-1 overflow-x-hidden",
|
|
139
155
|
children: /* @__PURE__ */ jsx("p", {
|
|
140
156
|
className: "flex-1 cursor-default truncate py-1 text-sm",
|
|
141
|
-
title:
|
|
142
|
-
onClick:
|
|
143
|
-
children:
|
|
157
|
+
title: t15,
|
|
158
|
+
onClick: t16,
|
|
159
|
+
children: t18
|
|
144
160
|
})
|
|
145
161
|
});
|
|
146
|
-
$[
|
|
147
|
-
$[
|
|
148
|
-
$[
|
|
149
|
-
$[
|
|
150
|
-
} else
|
|
151
|
-
let
|
|
152
|
-
if ($[
|
|
153
|
-
|
|
162
|
+
$[36] = t15;
|
|
163
|
+
$[37] = t16;
|
|
164
|
+
$[38] = t18;
|
|
165
|
+
$[39] = t19;
|
|
166
|
+
} else t19 = $[39];
|
|
167
|
+
let t20;
|
|
168
|
+
if ($[40] !== canRemove || $[41] !== item.id || $[42] !== onRemove) {
|
|
169
|
+
t20 = canRemove && /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
154
170
|
render: /* @__PURE__ */ jsx(Button, {
|
|
155
171
|
type: "button",
|
|
156
172
|
variant: "ghost",
|
|
@@ -166,14 +182,14 @@ const SortableRepeatableItem = (t0) => {
|
|
|
166
182
|
side: "right",
|
|
167
183
|
children: "Remove item"
|
|
168
184
|
})] });
|
|
169
|
-
$[
|
|
170
|
-
$[
|
|
171
|
-
$[
|
|
172
|
-
$[
|
|
173
|
-
} else
|
|
174
|
-
let
|
|
175
|
-
if ($[
|
|
176
|
-
|
|
185
|
+
$[40] = canRemove;
|
|
186
|
+
$[41] = item.id;
|
|
187
|
+
$[42] = onRemove;
|
|
188
|
+
$[43] = t20;
|
|
189
|
+
} else t20 = $[43];
|
|
190
|
+
let t21;
|
|
191
|
+
if ($[44] !== handleMouseEnter || $[45] !== handleMouseLeave || $[46] !== setNodeRef || $[47] !== style || $[48] !== t11 || $[49] !== t13 || $[50] !== t19 || $[51] !== t20) {
|
|
192
|
+
t21 = /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("div", {
|
|
177
193
|
ref: setNodeRef,
|
|
178
194
|
style,
|
|
179
195
|
className: t11,
|
|
@@ -181,21 +197,21 @@ const SortableRepeatableItem = (t0) => {
|
|
|
181
197
|
onMouseLeave: handleMouseLeave,
|
|
182
198
|
children: [
|
|
183
199
|
t13,
|
|
184
|
-
|
|
185
|
-
|
|
200
|
+
t19,
|
|
201
|
+
t20
|
|
186
202
|
]
|
|
187
203
|
}) });
|
|
188
|
-
$[
|
|
189
|
-
$[
|
|
190
|
-
$[
|
|
191
|
-
$[
|
|
192
|
-
$[
|
|
193
|
-
$[
|
|
194
|
-
$[
|
|
195
|
-
$[
|
|
196
|
-
$[
|
|
197
|
-
} else
|
|
198
|
-
return
|
|
204
|
+
$[44] = handleMouseEnter;
|
|
205
|
+
$[45] = handleMouseLeave;
|
|
206
|
+
$[46] = setNodeRef;
|
|
207
|
+
$[47] = style;
|
|
208
|
+
$[48] = t11;
|
|
209
|
+
$[49] = t13;
|
|
210
|
+
$[50] = t19;
|
|
211
|
+
$[51] = t20;
|
|
212
|
+
$[52] = t21;
|
|
213
|
+
} else t21 = $[52];
|
|
214
|
+
return t21;
|
|
199
215
|
};
|
|
200
216
|
const RepeatableItemsList = (t0) => {
|
|
201
217
|
const $ = c(24);
|
|
@@ -9,6 +9,7 @@ import { editorAssetField } from "../../content/collection-form.js";
|
|
|
9
9
|
import { isBlockPlacement, previewStore, recordPlacement, selectionBlockId, selectionField, selectionForOwner, selectionItemId } from "../previewStore.js";
|
|
10
10
|
import { useEditingFrame } from "../editingFrame.js";
|
|
11
11
|
import { PreviewEditingOwnerContext } from "../previewSelection.js";
|
|
12
|
+
import { entityName } from "../entityName.js";
|
|
12
13
|
import { fieldTypesDictionary } from "../../../core/lib/fieldTypes.js";
|
|
13
14
|
import { selectionHoverMessage } from "../overlayMessages.js";
|
|
14
15
|
import { usePageRecordPlacer } from "../pageRecord.js";
|
|
@@ -605,7 +606,7 @@ const SelectionEditorContent = (t0) => {
|
|
|
605
606
|
})
|
|
606
607
|
}, {
|
|
607
608
|
key: `item-${ancestor.id}`,
|
|
608
|
-
label: ancestor
|
|
609
|
+
label: entityName(ancestor, "Item"),
|
|
609
610
|
hoverTarget: {
|
|
610
611
|
type: "item",
|
|
611
612
|
blockId: block_0.id,
|
|
@@ -685,7 +686,7 @@ const SelectionEditorContent = (t0) => {
|
|
|
685
686
|
]
|
|
686
687
|
}), item.onClick ? /* @__PURE__ */ jsx("button", {
|
|
687
688
|
type: "button",
|
|
688
|
-
className: cn("hover:text-foreground
|
|
689
|
+
className: cn("hover:text-foreground block h-7 max-w-full cursor-pointer truncate text-left leading-7 transition-colors", item.isCurrent && "text-foreground font-medium"),
|
|
689
690
|
onClick: item.onClick,
|
|
690
691
|
children: item.label
|
|
691
692
|
}) : /* @__PURE__ */ jsx("span", {
|
|
@@ -2,8 +2,8 @@ import { useProjectUuid } from "../../../lib/auth.js";
|
|
|
2
2
|
import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
|
|
3
3
|
import { referenceList } from "../../../lib/normalized-data.js";
|
|
4
4
|
import { reads, useStudioCache } from "../../../lib/studio-reads.js";
|
|
5
|
-
import { lexicalStateToPlainText } from "../../../core/lib/lexicalState.js";
|
|
6
5
|
import { referenceListIds } from "../../../core/lib/reference.js";
|
|
6
|
+
import { recordText } from "../../../core/recordItem.js";
|
|
7
7
|
import { blockMutations, collectionMutations, repeatableItemMutations } from "../../../lib/queries.js";
|
|
8
8
|
import { invalidateCollectionRecordViews } from "../../../lib/collection-cache.js";
|
|
9
9
|
import { serializeAssetField } from "../../content/collection-form.js";
|
|
@@ -134,13 +134,11 @@ function useFieldWriter(target, schema) {
|
|
|
134
134
|
collectionId,
|
|
135
135
|
id: recordId
|
|
136
136
|
}));
|
|
137
|
-
const labelField = camoxApp.getCollectionById(collectionId)?._internal.label;
|
|
138
|
-
const label = labelField ? record_0.content[labelField] : void 0;
|
|
139
137
|
return {
|
|
140
138
|
id: record_0.id,
|
|
141
139
|
collectionId,
|
|
142
140
|
content: record_0.content,
|
|
143
|
-
|
|
141
|
+
...recordText(camoxApp.getCollectionById(collectionId), record_0.content)
|
|
144
142
|
};
|
|
145
143
|
};
|
|
146
144
|
return (async () => {
|
|
@@ -302,7 +302,7 @@ function useRecordView(t0) {
|
|
|
302
302
|
})
|
|
303
303
|
}] : [], {
|
|
304
304
|
key: "record",
|
|
305
|
-
label: outerRecord.
|
|
305
|
+
label: outerRecord.title,
|
|
306
306
|
isCurrent: !nested && !fieldHasOwnView,
|
|
307
307
|
hoverTarget: outerTarget,
|
|
308
308
|
onClick: nested || fieldHasOwnView ? () => previewStore.send({
|
|
@@ -332,7 +332,7 @@ function useRecordView(t0) {
|
|
|
332
332
|
},
|
|
333
333
|
{
|
|
334
334
|
key: "nested-record",
|
|
335
|
-
label: recordView.record.
|
|
335
|
+
label: recordView.record.title,
|
|
336
336
|
isCurrent: !fieldHasOwnView,
|
|
337
337
|
hoverTarget: nestedTarget,
|
|
338
338
|
onClick: fieldHasOwnView ? () => previewStore.send({
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/features/preview/entityName.ts
|
|
2
|
+
/**
|
|
3
|
+
* What the studio names a block or repeatable item by: its Summary, generated or hand-written,
|
|
4
|
+
* else its title, from its definition's `toTitle` on default-locale content, else `fallback`.
|
|
5
|
+
*/
|
|
6
|
+
function entityName(entity, fallback) {
|
|
7
|
+
return entity.summary || entity.title || fallback;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
export { entityName };
|
|
@@ -157,32 +157,31 @@ function usePageRecordPlacer() {
|
|
|
157
157
|
const app = useCamoxApp();
|
|
158
158
|
const collection = loaded ? app.getCollectionById(loaded.collectionId) : void 0;
|
|
159
159
|
const collectionId = loaded?.collectionId ?? "";
|
|
160
|
-
const t0 = collection?.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
t2 = {
|
|
160
|
+
const t0 = collection ? loaded?.data : void 0;
|
|
161
|
+
let t1;
|
|
162
|
+
if ($[0] !== collection || $[1] !== collectionId || $[2] !== t0) {
|
|
163
|
+
t1 = {
|
|
165
164
|
collectionId,
|
|
166
|
-
|
|
167
|
-
loaded:
|
|
165
|
+
collection,
|
|
166
|
+
loaded: t0
|
|
168
167
|
};
|
|
169
|
-
$[0] =
|
|
170
|
-
$[1] =
|
|
171
|
-
$[2] =
|
|
172
|
-
$[3] =
|
|
173
|
-
} else
|
|
174
|
-
const record = useLatestRecord(
|
|
175
|
-
let
|
|
168
|
+
$[0] = collection;
|
|
169
|
+
$[1] = collectionId;
|
|
170
|
+
$[2] = t0;
|
|
171
|
+
$[3] = t1;
|
|
172
|
+
} else t1 = $[3];
|
|
173
|
+
const record = useLatestRecord(t1);
|
|
174
|
+
let t2;
|
|
176
175
|
if ($[4] !== collectionId || $[5] !== record) {
|
|
177
|
-
|
|
176
|
+
t2 = record ? {
|
|
178
177
|
collectionId,
|
|
179
178
|
record
|
|
180
179
|
} : null;
|
|
181
180
|
$[4] = collectionId;
|
|
182
181
|
$[5] = record;
|
|
183
|
-
$[6] =
|
|
184
|
-
} else
|
|
185
|
-
return
|
|
182
|
+
$[6] = t2;
|
|
183
|
+
} else t2 = $[6];
|
|
184
|
+
return t2;
|
|
186
185
|
}
|
|
187
186
|
|
|
188
187
|
//#endregion
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { useSignInRedirect } from "../../lib/auth.js";
|
|
2
2
|
import { useLocation } from "../navigation/navigation.js";
|
|
3
|
+
import { useSignInShortcut } from "./signInShortcut.js";
|
|
3
4
|
import { STUDIO_BASE_PATH } from "../studio/routes.js";
|
|
4
5
|
import { AuthGate } from "../../components/AuthGate.js";
|
|
5
6
|
import { AuthenticatedCamoxProvider } from "./AuthenticatedCamoxProvider.js";
|
|
6
|
-
import { CoreCamoxProvider
|
|
7
|
-
import { LocalhostPreviewProvider } from "./LocalhostPreviewProvider.js";
|
|
7
|
+
import { CoreCamoxProvider } from "./CoreCamoxProvider.js";
|
|
8
8
|
import { c } from "react/compiler-runtime";
|
|
9
9
|
import * as React from "react";
|
|
10
10
|
import { jsx } from "react/jsx-runtime";
|
|
11
11
|
|
|
12
12
|
//#region src/features/provider/CamoxProvider.tsx
|
|
13
13
|
function UnauthenticatedExperience(t0) {
|
|
14
|
-
const $ = c(
|
|
14
|
+
const $ = c(10);
|
|
15
15
|
const { children } = t0;
|
|
16
16
|
const { pathname } = useLocation();
|
|
17
17
|
let t1;
|
|
@@ -48,25 +48,17 @@ function UnauthenticatedExperience(t0) {
|
|
|
48
48
|
t4 = $[7];
|
|
49
49
|
}
|
|
50
50
|
React.useEffect(t3, t4);
|
|
51
|
+
useSignInShortcut(!isStudio);
|
|
51
52
|
if (isStudio) return null;
|
|
52
|
-
if (isLocalhostPreview()) {
|
|
53
|
-
let t5;
|
|
54
|
-
if ($[8] !== children) {
|
|
55
|
-
t5 = /* @__PURE__ */ jsx(LocalhostPreviewProvider, { children });
|
|
56
|
-
$[8] = children;
|
|
57
|
-
$[9] = t5;
|
|
58
|
-
} else t5 = $[9];
|
|
59
|
-
return t5;
|
|
60
|
-
}
|
|
61
53
|
let t5;
|
|
62
|
-
if ($[
|
|
54
|
+
if ($[8] !== children) {
|
|
63
55
|
t5 = /* @__PURE__ */ jsx("div", {
|
|
64
56
|
className: "bg-background min-h-screen",
|
|
65
57
|
children
|
|
66
58
|
});
|
|
67
|
-
$[
|
|
68
|
-
$[
|
|
69
|
-
} else t5 = $[
|
|
59
|
+
$[8] = children;
|
|
60
|
+
$[9] = t5;
|
|
61
|
+
} else t5 = $[9];
|
|
70
62
|
return t5;
|
|
71
63
|
}
|
|
72
64
|
function CamoxProvider(props) {
|
|
@@ -9,11 +9,6 @@ import { jsx } from "react/jsx-runtime";
|
|
|
9
9
|
import { replaceEqualDeep, useQueryClient } from "@tanstack/react-query";
|
|
10
10
|
|
|
11
11
|
//#region src/features/provider/CoreCamoxProvider.tsx
|
|
12
|
-
function isLocalhostPreview() {
|
|
13
|
-
if (typeof window === "undefined") return false;
|
|
14
|
-
const { hostname } = window.location;
|
|
15
|
-
return hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "127.0.0.1" || hostname === "[::1]" || hostname === "::1";
|
|
16
|
-
}
|
|
17
12
|
function CoreCamoxProvider({ apiUrl, authenticationUrl, camoxApp, children, projectUuid, initialAuthenticated = false, initialProject }) {
|
|
18
13
|
const queryClient = useQueryClient();
|
|
19
14
|
const authClient = React.useMemo(() => createCamoxAuthClient(apiUrl), [apiUrl]);
|
|
@@ -94,4 +89,4 @@ function createWindowDraftScope(queryClient) {
|
|
|
94
89
|
}
|
|
95
90
|
|
|
96
91
|
//#endregion
|
|
97
|
-
export { CoreCamoxProvider
|
|
92
|
+
export { CoreCamoxProvider };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { useSignInRedirect } from "../../lib/auth.js";
|
|
2
|
+
import { TOGGLE_CANVAS_SHORTCUT } from "../preview/previewConstants.js";
|
|
3
|
+
import { c } from "react/compiler-runtime";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
|
|
6
|
+
//#region src/features/provider/signInShortcut.ts
|
|
7
|
+
/** Marks the URL a sign-in returns to, so the Studio opens on the Canvas there. */
|
|
8
|
+
const SHOW_CANVAS_PARAM = "camox-show-canvas";
|
|
9
|
+
function showCanvasCallbackHref() {
|
|
10
|
+
const url = new URL(window.location.href);
|
|
11
|
+
url.searchParams.set(SHOW_CANVAS_PARAM, "");
|
|
12
|
+
return url.href;
|
|
13
|
+
}
|
|
14
|
+
function isTyping() {
|
|
15
|
+
const element = document.activeElement;
|
|
16
|
+
return element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLElement && element.isContentEditable;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* While signed out, the shortcut that shows the Canvas signs in instead, then shows the Canvas
|
|
20
|
+
* on the page it was pressed on. Fields keep it, since sites often submit forms with it.
|
|
21
|
+
*/
|
|
22
|
+
function useSignInShortcut(enabled) {
|
|
23
|
+
const $ = c(4);
|
|
24
|
+
const signIn = useSignInRedirect(showCanvasCallbackHref);
|
|
25
|
+
let t0;
|
|
26
|
+
let t1;
|
|
27
|
+
if ($[0] !== enabled || $[1] !== signIn) {
|
|
28
|
+
t0 = () => {
|
|
29
|
+
if (!enabled) return;
|
|
30
|
+
const handleKeyDown = (event) => {
|
|
31
|
+
if (event.key !== TOGGLE_CANVAS_SHORTCUT.key || !(event.metaKey || event.ctrlKey)) return;
|
|
32
|
+
if (event.altKey || event.shiftKey || event.defaultPrevented || isTyping()) return;
|
|
33
|
+
event.preventDefault();
|
|
34
|
+
signIn();
|
|
35
|
+
};
|
|
36
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
37
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
38
|
+
};
|
|
39
|
+
t1 = [enabled, signIn];
|
|
40
|
+
$[0] = enabled;
|
|
41
|
+
$[1] = signIn;
|
|
42
|
+
$[2] = t0;
|
|
43
|
+
$[3] = t1;
|
|
44
|
+
} else {
|
|
45
|
+
t0 = $[2];
|
|
46
|
+
t1 = $[3];
|
|
47
|
+
}
|
|
48
|
+
React.useEffect(t0, t1);
|
|
49
|
+
}
|
|
50
|
+
/** Whether a sign-in from the shortcut led here. Removes the mark, so it shows the Canvas once. */
|
|
51
|
+
function takeShowCanvasRequest() {
|
|
52
|
+
const url = new URL(window.location.href);
|
|
53
|
+
if (!url.searchParams.has(SHOW_CANVAS_PARAM)) return false;
|
|
54
|
+
url.searchParams.delete(SHOW_CANVAS_PARAM);
|
|
55
|
+
window.history.replaceState(window.history.state, "", url);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
export { takeShowCanvasRequest, useSignInShortcut };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { LocaleView } from "../../lib/locale-path.js";
|
|
2
|
+
import "../../core/structuredData.js";
|
|
1
3
|
import "../../core/createLayout.js";
|
|
2
4
|
import "../../core/createApp.js";
|
|
3
|
-
import { LocaleView } from "../../lib/locale-path.js";
|
|
4
5
|
import "../../lib/studio-reads.js";
|
|
5
6
|
import { Router } from "@camox/api-contract";
|
|
6
7
|
import { EndedDraft } from "@camox/api-contract/drafts";
|
|
@@ -14,6 +15,10 @@ export type PageStructure = {
|
|
|
14
15
|
layout: PageWithBlocks["layout"];
|
|
15
16
|
projectName: string;
|
|
16
17
|
project: PageWithBlocks["project"];
|
|
18
|
+
/** Each block's Structured Data nodes, from a full read: a structure read has none. */
|
|
19
|
+
structuredData?: PageWithBlocks["structuredData"];
|
|
20
|
+
/** The nodes of the records its blocks reference, from a full read. */
|
|
21
|
+
recordStructuredData?: PageWithBlocks["recordStructuredData"];
|
|
17
22
|
};
|
|
18
23
|
/**
|
|
19
24
|
* Why a member can't see the draft a URL names: it doesn't exist, it's someone else's
|
|
@@ -46,5 +51,14 @@ export declare function createServerApiClient(apiUrl: string, options?: {
|
|
|
46
51
|
draftId?: string;
|
|
47
52
|
locale?: LocaleView;
|
|
48
53
|
}): RouterClient<Router>;
|
|
54
|
+
export type PageHead = {
|
|
55
|
+
meta?: Array<Record<string, string>>;
|
|
56
|
+
links?: Array<Record<string, string>>;
|
|
57
|
+
/** Scripts with their text, such as the page's Structured Data. */
|
|
58
|
+
scripts?: Array<{
|
|
59
|
+
type: string;
|
|
60
|
+
text: string;
|
|
61
|
+
}>;
|
|
62
|
+
};
|
|
49
63
|
//#endregion
|
|
50
64
|
export {};
|