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
|
@@ -8,11 +8,10 @@ import { CanvasWorkspaceContext } from "../canvas/canvasZoom.js";
|
|
|
8
8
|
import { PreviewEditingOwnerContext } from "../preview/previewSelection.js";
|
|
9
9
|
import { StudioNoticeContext } from "../preview/studioNotice.js";
|
|
10
10
|
import { ContentEditsContext } from "../../core/editing/contentEdits.js";
|
|
11
|
-
import { PreviewDocumentContext } from "../runtime/PreviewDocumentContext.js";
|
|
12
11
|
import { restyle } from "../preview/components/previewStyles.js";
|
|
12
|
+
import { PreviewDocumentContext } from "../runtime/PreviewDocumentContext.js";
|
|
13
13
|
import { FrameContext } from "../preview/components/Frame.js";
|
|
14
14
|
import { DerivedPageContent } from "../page/DerivedPageContent.js";
|
|
15
|
-
import { BlockPeek } from "../preview/components/BlockPeek.js";
|
|
16
15
|
import { EditablePageContent } from "../preview/EditablePageContent.js";
|
|
17
16
|
import { c } from "react/compiler-runtime";
|
|
18
17
|
import * as React from "react";
|
|
@@ -30,10 +29,9 @@ import { createPortal } from "react-dom";
|
|
|
30
29
|
* to load fails each frame, as a page that throws does.
|
|
31
30
|
*/
|
|
32
31
|
function RendererApp(t0) {
|
|
33
|
-
const $ = c(
|
|
32
|
+
const $ = c(21);
|
|
34
33
|
const { connection, camoxApp, codeLoaded, projectUuid, runtimeBasePath } = t0;
|
|
35
34
|
const frames = useFrames(connection);
|
|
36
|
-
const thumbnails = React.useSyncExternalStore(connection.subscribe, connection.thumbnails, connection.thumbnails);
|
|
37
35
|
const t1 = connection.edit;
|
|
38
36
|
let t2;
|
|
39
37
|
if ($[0] !== connection) {
|
|
@@ -70,47 +68,26 @@ function RendererApp(t0) {
|
|
|
70
68
|
$[8] = t3;
|
|
71
69
|
} else t3 = $[8];
|
|
72
70
|
let t4;
|
|
73
|
-
if ($[15] !==
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
blockType,
|
|
81
|
-
camoxApp
|
|
82
|
-
}), slot, thumbnailId);
|
|
83
|
-
};
|
|
84
|
-
$[18] = camoxApp;
|
|
85
|
-
$[19] = t5;
|
|
86
|
-
} else t5 = $[19];
|
|
87
|
-
t4 = thumbnails.map(t5);
|
|
88
|
-
$[15] = camoxApp;
|
|
89
|
-
$[16] = thumbnails;
|
|
71
|
+
if ($[15] !== t2 || $[16] !== t3) {
|
|
72
|
+
t4 = /* @__PURE__ */ jsx(StudioNoticeContext, {
|
|
73
|
+
value: t2,
|
|
74
|
+
children: t3
|
|
75
|
+
});
|
|
76
|
+
$[15] = t2;
|
|
77
|
+
$[16] = t3;
|
|
90
78
|
$[17] = t4;
|
|
91
79
|
} else t4 = $[17];
|
|
92
80
|
let t5;
|
|
93
|
-
if ($[
|
|
94
|
-
t5 = /* @__PURE__ */
|
|
95
|
-
value: t2,
|
|
96
|
-
children: [t3, t4]
|
|
97
|
-
});
|
|
98
|
-
$[20] = t2;
|
|
99
|
-
$[21] = t3;
|
|
100
|
-
$[22] = t4;
|
|
101
|
-
$[23] = t5;
|
|
102
|
-
} else t5 = $[23];
|
|
103
|
-
let t6;
|
|
104
|
-
if ($[24] !== connection.edit || $[25] !== t5) {
|
|
105
|
-
t6 = /* @__PURE__ */ jsx(ContentEditsContext, {
|
|
81
|
+
if ($[18] !== connection.edit || $[19] !== t4) {
|
|
82
|
+
t5 = /* @__PURE__ */ jsx(ContentEditsContext, {
|
|
106
83
|
value: t1,
|
|
107
|
-
children:
|
|
84
|
+
children: t4
|
|
108
85
|
});
|
|
109
|
-
$[
|
|
110
|
-
$[
|
|
111
|
-
$[
|
|
112
|
-
} else
|
|
113
|
-
return
|
|
86
|
+
$[18] = connection.edit;
|
|
87
|
+
$[19] = t4;
|
|
88
|
+
$[20] = t5;
|
|
89
|
+
} else t5 = $[20];
|
|
90
|
+
return t5;
|
|
114
91
|
}
|
|
115
92
|
/**
|
|
116
93
|
* The frames the studio gives the renderer to fill. Each change renders in a transition, so a
|
|
@@ -138,107 +115,6 @@ function useFrames(connection) {
|
|
|
138
115
|
React.useEffect(t0, t1);
|
|
139
116
|
return frames;
|
|
140
117
|
}
|
|
141
|
-
/** A block's thumbnail, rendered by the draft's code into its frame: nothing for a block it lacks. */
|
|
142
|
-
function RendererThumbnail(t0) {
|
|
143
|
-
const $ = c(17);
|
|
144
|
-
const { slot, blockType, camoxApp } = t0;
|
|
145
|
-
const frameWindow = slot.ownerDocument.defaultView;
|
|
146
|
-
const left = useLeftInSlot(slot);
|
|
147
|
-
const t1 = frameWindow?.frameElement ?? null;
|
|
148
|
-
let t2;
|
|
149
|
-
if ($[0] !== frameWindow || $[1] !== t1) {
|
|
150
|
-
t2 = {
|
|
151
|
-
window: frameWindow,
|
|
152
|
-
iframeElement: t1
|
|
153
|
-
};
|
|
154
|
-
$[0] = frameWindow;
|
|
155
|
-
$[1] = t1;
|
|
156
|
-
$[2] = t2;
|
|
157
|
-
} else t2 = $[2];
|
|
158
|
-
const frameContext = t2;
|
|
159
|
-
let t3;
|
|
160
|
-
if ($[3] !== blockType || $[4] !== camoxApp) {
|
|
161
|
-
t3 = /* @__PURE__ */ jsx(ThumbnailBlock, {
|
|
162
|
-
blockType,
|
|
163
|
-
camoxApp
|
|
164
|
-
});
|
|
165
|
-
$[3] = blockType;
|
|
166
|
-
$[4] = camoxApp;
|
|
167
|
-
$[5] = t3;
|
|
168
|
-
} else t3 = $[5];
|
|
169
|
-
let t4;
|
|
170
|
-
if ($[6] !== left) {
|
|
171
|
-
t4 = /* @__PURE__ */ jsx(RemovesLeft, { nodes: left });
|
|
172
|
-
$[6] = left;
|
|
173
|
-
$[7] = t4;
|
|
174
|
-
} else t4 = $[7];
|
|
175
|
-
let t5;
|
|
176
|
-
if ($[8] !== t3 || $[9] !== t4) {
|
|
177
|
-
t5 = /* @__PURE__ */ jsxs(React.Suspense, {
|
|
178
|
-
fallback: null,
|
|
179
|
-
children: [t3, t4]
|
|
180
|
-
});
|
|
181
|
-
$[8] = t3;
|
|
182
|
-
$[9] = t4;
|
|
183
|
-
$[10] = t5;
|
|
184
|
-
} else t5 = $[10];
|
|
185
|
-
let t6;
|
|
186
|
-
if ($[11] !== left || $[12] !== t5) {
|
|
187
|
-
t6 = /* @__PURE__ */ jsx(ThumbnailErrorBoundary, {
|
|
188
|
-
left,
|
|
189
|
-
children: t5
|
|
190
|
-
});
|
|
191
|
-
$[11] = left;
|
|
192
|
-
$[12] = t5;
|
|
193
|
-
$[13] = t6;
|
|
194
|
-
} else t6 = $[13];
|
|
195
|
-
let t7;
|
|
196
|
-
if ($[14] !== frameContext || $[15] !== t6) {
|
|
197
|
-
t7 = /* @__PURE__ */ jsx(NavigationProvider, {
|
|
198
|
-
location: THUMBNAIL_LOCATION,
|
|
199
|
-
navigate: noNavigation,
|
|
200
|
-
children: /* @__PURE__ */ jsx(FrameContext.Provider, {
|
|
201
|
-
value: frameContext,
|
|
202
|
-
children: t6
|
|
203
|
-
})
|
|
204
|
-
});
|
|
205
|
-
$[14] = frameContext;
|
|
206
|
-
$[15] = t6;
|
|
207
|
-
$[16] = t7;
|
|
208
|
-
} else t7 = $[16];
|
|
209
|
-
return t7;
|
|
210
|
-
}
|
|
211
|
-
const THUMBNAIL_LOCATION = {
|
|
212
|
-
href: "",
|
|
213
|
-
pathname: "/",
|
|
214
|
-
search: "",
|
|
215
|
-
hash: ""
|
|
216
|
-
};
|
|
217
|
-
const noNavigation = () => {};
|
|
218
|
-
var ThumbnailErrorBoundary = class extends React.Component {
|
|
219
|
-
state = { failed: false };
|
|
220
|
-
static getDerivedStateFromError() {
|
|
221
|
-
return { failed: true };
|
|
222
|
-
}
|
|
223
|
-
componentDidCatch(error) {
|
|
224
|
-
console.error("Camox: a block's thumbnail failed to render.", error);
|
|
225
|
-
}
|
|
226
|
-
render() {
|
|
227
|
-
return this.state.failed ? /* @__PURE__ */ jsx(RemovesLeft, { nodes: this.props.left }) : this.props.children;
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
function ThumbnailBlock(t0) {
|
|
231
|
-
const $ = c(2);
|
|
232
|
-
const { blockType, camoxApp } = t0;
|
|
233
|
-
const block = camoxApp.getBlockById(blockType) ?? (camoxApp.canLoadMoreBlocks() ? React.use(camoxApp.loadBlock(blockType)) : void 0);
|
|
234
|
-
let t1;
|
|
235
|
-
if ($[0] !== block) {
|
|
236
|
-
t1 = block ? /* @__PURE__ */ jsx(BlockPeek, { block }) : null;
|
|
237
|
-
$[0] = block;
|
|
238
|
-
$[1] = t1;
|
|
239
|
-
} else t1 = $[1];
|
|
240
|
-
return t1;
|
|
241
|
-
}
|
|
242
118
|
/**
|
|
243
119
|
* What another renderer document left in `slot`, read before this one renders into it. Each new
|
|
244
120
|
* revision loads another renderer document, and removing the last one's frame never unmounts
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
import { curatedLayoutContext } from "../../core/layoutContext.js";
|
|
2
2
|
|
|
3
3
|
//#region src/features/renderer/definitionAnswers.ts
|
|
4
|
-
/** The block of `type` in the draft's code, loading it if it is lazy. */
|
|
5
|
-
async function blockOfCode(camoxApp, type) {
|
|
6
|
-
const block = camoxApp.getBlockById(type);
|
|
7
|
-
if (block || !camoxApp.canLoadMoreBlocks()) return block;
|
|
8
|
-
return camoxApp.loadBlock(type);
|
|
9
|
-
}
|
|
10
4
|
async function answerFromCode(camoxApp, question) {
|
|
11
5
|
switch (question.type) {
|
|
12
|
-
case "initialBundle": return (await blockOfCode(camoxApp, question.blockType))?._internal.getInitialBundle() ?? null;
|
|
13
6
|
case "prepareFrame": return null;
|
|
14
7
|
case "pageTitle": {
|
|
15
8
|
const layout = camoxApp.getLayoutById(question.layoutId);
|
|
@@ -24,4 +17,4 @@ async function answerFromCode(camoxApp, question) {
|
|
|
24
17
|
}
|
|
25
18
|
|
|
26
19
|
//#endregion
|
|
27
|
-
export { answerFromCode
|
|
20
|
+
export { answerFromCode };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { referencePickerFocus } from "../preview/referencePickerFocus.js";
|
|
2
1
|
import { canvasStore } from "../canvas/canvasStore.js";
|
|
3
2
|
import { previewStore } from "../preview/previewStore.js";
|
|
4
3
|
import { SDK_VERSION, deferredInbox } from "./protocol.js";
|
|
@@ -20,10 +19,7 @@ const storeMessages = {
|
|
|
20
19
|
})
|
|
21
20
|
};
|
|
22
21
|
/** The stores the renderer forwards its events to, as the host applies them. */
|
|
23
|
-
const forwarded = {
|
|
24
|
-
preview: previewStore,
|
|
25
|
-
referencePickerFocus
|
|
26
|
-
};
|
|
22
|
+
const forwarded = { preview: previewStore };
|
|
27
23
|
/** Applies an event the renderer forwarded to the studio's store. */
|
|
28
24
|
const applyStoreEvent = (message) => {
|
|
29
25
|
const store = forwarded[message.store];
|
|
@@ -43,7 +39,6 @@ function createRendererHost({ studioCache, draftScope, queryClient, notify } = {
|
|
|
43
39
|
studioCache
|
|
44
40
|
}) : void 0;
|
|
45
41
|
const frames = /* @__PURE__ */ new Map();
|
|
46
|
-
const thumbnails = /* @__PURE__ */ new Map();
|
|
47
42
|
/** The questions asked that no renderer answered yet. */
|
|
48
43
|
const asked = /* @__PURE__ */ new Map();
|
|
49
44
|
let lastAskId = 0;
|
|
@@ -122,12 +117,6 @@ function createRendererHost({ studioCache, draftScope, queryClient, notify } = {
|
|
|
122
117
|
slot,
|
|
123
118
|
target
|
|
124
119
|
});
|
|
125
|
-
for (const [thumbnailId, { slot, blockType }] of thumbnails) post({
|
|
126
|
-
type: "thumbnail",
|
|
127
|
-
thumbnailId,
|
|
128
|
-
slot,
|
|
129
|
-
blockType
|
|
130
|
-
});
|
|
131
120
|
for (const [askId, { question }] of asked) post({
|
|
132
121
|
type: "ask",
|
|
133
122
|
askId,
|
|
@@ -213,25 +202,6 @@ function createRendererHost({ studioCache, draftScope, queryClient, notify } = {
|
|
|
213
202
|
});
|
|
214
203
|
});
|
|
215
204
|
},
|
|
216
|
-
showThumbnail(thumbnailId, slot, blockType) {
|
|
217
|
-
thumbnails.set(thumbnailId, {
|
|
218
|
-
slot,
|
|
219
|
-
blockType
|
|
220
|
-
});
|
|
221
|
-
post({
|
|
222
|
-
type: "thumbnail",
|
|
223
|
-
thumbnailId,
|
|
224
|
-
slot,
|
|
225
|
-
blockType
|
|
226
|
-
});
|
|
227
|
-
},
|
|
228
|
-
hideThumbnail(thumbnailId) {
|
|
229
|
-
if (!thumbnails.delete(thumbnailId)) return;
|
|
230
|
-
post({
|
|
231
|
-
type: "thumbnailEnd",
|
|
232
|
-
thumbnailId
|
|
233
|
-
});
|
|
234
|
-
},
|
|
235
205
|
subscribe(listener) {
|
|
236
206
|
connectionListeners.add(listener);
|
|
237
207
|
return () => connectionListeners.delete(listener);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { referencePickerFocus } from "../preview/referencePickerFocus.js";
|
|
2
1
|
import { canvasStore } from "../canvas/canvasStore.js";
|
|
3
2
|
import { previewStore } from "../preview/previewStore.js";
|
|
4
3
|
import { SDK_VERSION, deferredInbox } from "./protocol.js";
|
|
@@ -11,10 +10,7 @@ const mirrors = {
|
|
|
11
10
|
canvas: canvasStore
|
|
12
11
|
};
|
|
13
12
|
/** The stores of this document whose events are forwarded to the studio's. */
|
|
14
|
-
const forwards = {
|
|
15
|
-
preview: previewStore,
|
|
16
|
-
referencePickerFocus
|
|
17
|
-
};
|
|
13
|
+
const forwards = { preview: previewStore };
|
|
18
14
|
/** Has this document's copy of a mirrored store take the studio's state. */
|
|
19
15
|
const mirror = (message) => mirrors[message.store]?.send({
|
|
20
16
|
type: "mirror",
|
|
@@ -30,7 +26,6 @@ function connectToStudio(handle, { queryClient, studioCache, draftScope, camoxAp
|
|
|
30
26
|
let welcomed = false;
|
|
31
27
|
let frames = [];
|
|
32
28
|
const listeners = /* @__PURE__ */ new Set();
|
|
33
|
-
let thumbnails = [];
|
|
34
29
|
const changed = () => {
|
|
35
30
|
for (const listener of listeners) listener();
|
|
36
31
|
};
|
|
@@ -38,10 +33,6 @@ function connectToStudio(handle, { queryClient, studioCache, draftScope, camoxAp
|
|
|
38
33
|
frames = next;
|
|
39
34
|
changed();
|
|
40
35
|
};
|
|
41
|
-
const setThumbnails = (next) => {
|
|
42
|
-
thumbnails = next;
|
|
43
|
-
changed();
|
|
44
|
-
};
|
|
45
36
|
/** The edits sent to the studio that it hasn't answered yet. */
|
|
46
37
|
const editsInFlight = /* @__PURE__ */ new Map();
|
|
47
38
|
let lastEditId = 0;
|
|
@@ -93,20 +84,6 @@ function connectToStudio(handle, { queryClient, studioCache, draftScope, camoxAp
|
|
|
93
84
|
exact: true
|
|
94
85
|
});
|
|
95
86
|
return;
|
|
96
|
-
case "thumbnail": {
|
|
97
|
-
const { thumbnailId, slot, blockType } = message;
|
|
98
|
-
const thumbnail = {
|
|
99
|
-
thumbnailId,
|
|
100
|
-
slot,
|
|
101
|
-
blockType
|
|
102
|
-
};
|
|
103
|
-
const index = thumbnails.findIndex((shown) => shown.thumbnailId === thumbnailId);
|
|
104
|
-
setThumbnails(index < 0 ? [...thumbnails, thumbnail] : thumbnails.map((shown, at) => at === index ? thumbnail : shown));
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
case "thumbnailEnd":
|
|
108
|
-
setThumbnails(thumbnails.filter(({ thumbnailId }) => thumbnailId !== message.thumbnailId));
|
|
109
|
-
return;
|
|
110
87
|
case "ask": {
|
|
111
88
|
const { askId, question } = message;
|
|
112
89
|
if (question.type === "prepareFrame") {
|
|
@@ -165,7 +142,6 @@ function connectToStudio(handle, { queryClient, studioCache, draftScope, camoxAp
|
|
|
165
142
|
return {
|
|
166
143
|
connected: () => welcomed,
|
|
167
144
|
frames: () => frames,
|
|
168
|
-
thumbnails: () => thumbnails,
|
|
169
145
|
subscribe(listener) {
|
|
170
146
|
listeners.add(listener);
|
|
171
147
|
return () => listeners.delete(listener);
|
|
@@ -157,13 +157,24 @@ function createServerStudioCache(queryClient, { apiUrl, authCookieHeader, lookTo
|
|
|
157
157
|
}
|
|
158
158
|
/**
|
|
159
159
|
* The locales of the scope a request reads: the URL's draft's for a session naming one, else
|
|
160
|
-
* Live's. A draft the API refuses reads Live's, as the request's other reads then do.
|
|
160
|
+
* Live's. A draft the API refuses reads Live's, as the request's other reads then do. Live's read
|
|
161
|
+
* keeps the session: a member's studio routes the locales Live doesn't serve yet, which visitors
|
|
162
|
+
* never see (ADR 0043), and a render with a session is private.
|
|
161
163
|
*/
|
|
162
164
|
async function readScopeLocales({ apiUrl, authCookieHeader, draftId, projectUuid }) {
|
|
163
|
-
const
|
|
164
|
-
authCookieHeader:
|
|
165
|
+
const list = (session, readDraftId) => createServerApiClient(apiUrl, {
|
|
166
|
+
authCookieHeader: session,
|
|
165
167
|
draftId: readDraftId
|
|
166
|
-
}).locales.list({ projectUuid })
|
|
168
|
+
}).locales.list({ projectUuid });
|
|
169
|
+
const { value } = await readDraftOrLive(draftId, !!authCookieHeader, async (readDraftId) => {
|
|
170
|
+
if (readDraftId || !authCookieHeader) return list(authCookieHeader, readDraftId);
|
|
171
|
+
try {
|
|
172
|
+
return await list(authCookieHeader, void 0);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
if (!isAuthSessionError(error)) throw error;
|
|
175
|
+
return list(void 0, void 0);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
167
178
|
return value;
|
|
168
179
|
}
|
|
169
180
|
/**
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { useOptionalDraftScope } from "../../lib/draft-scope.js";
|
|
2
|
+
import { useAuthContext, useSignInRedirect } from "../../lib/auth.js";
|
|
3
|
+
import { getApiClient } from "../../lib/api-client.js";
|
|
4
|
+
import { c } from "react/compiler-runtime";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { CLAIM_LINK_SEARCH_PARAM } from "@camox/api-contract/claim-links";
|
|
8
|
+
|
|
9
|
+
//#region src/features/runtime/ClaimCard.tsx
|
|
10
|
+
/** The page's URL without the Claim Link's token, which would reopen the card. */
|
|
11
|
+
function pageWithoutToken() {
|
|
12
|
+
const url = new URL(window.location.href);
|
|
13
|
+
url.searchParams.delete(CLAIM_LINK_SEARCH_PARAM);
|
|
14
|
+
return url.href;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The claim card, on a page opened from a Claim Link: who built the website for whom, with a
|
|
18
|
+
* button to claim it, or why it can't be claimed. A member of the website's organization sees it
|
|
19
|
+
* as a preview. Nothing shows without a token, or in a draft.
|
|
20
|
+
*/
|
|
21
|
+
function ClaimCard() {
|
|
22
|
+
const $ = c(15);
|
|
23
|
+
const [token, setToken] = React.useState(null);
|
|
24
|
+
const [opening, setOpening] = React.useState(null);
|
|
25
|
+
const [closed, setClosed] = React.useState(false);
|
|
26
|
+
const { authenticationUrl } = useAuthContext();
|
|
27
|
+
const signIn = useSignInRedirect(pageWithoutToken);
|
|
28
|
+
const inDraft = useOptionalDraftScope().draftId !== null;
|
|
29
|
+
let t0;
|
|
30
|
+
let t1;
|
|
31
|
+
if ($[0] !== inDraft) {
|
|
32
|
+
t0 = () => {
|
|
33
|
+
if (inDraft) return;
|
|
34
|
+
const found = new URL(window.location.href).searchParams.get(CLAIM_LINK_SEARCH_PARAM);
|
|
35
|
+
if (!found) return;
|
|
36
|
+
setToken(found);
|
|
37
|
+
let current = true;
|
|
38
|
+
getApiClient().claimLinks.open({ token: found }).then((opened) => current && setOpening(opened), _temp);
|
|
39
|
+
return () => {
|
|
40
|
+
current = false;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
t1 = [inDraft];
|
|
44
|
+
$[0] = inDraft;
|
|
45
|
+
$[1] = t0;
|
|
46
|
+
$[2] = t1;
|
|
47
|
+
} else {
|
|
48
|
+
t0 = $[1];
|
|
49
|
+
t1 = $[2];
|
|
50
|
+
}
|
|
51
|
+
React.useEffect(t0, t1);
|
|
52
|
+
if (inDraft || !token || !opening || closed) return null;
|
|
53
|
+
let t2;
|
|
54
|
+
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
|
55
|
+
t2 = () => {
|
|
56
|
+
window.history.replaceState(window.history.state, "", pageWithoutToken());
|
|
57
|
+
setClosed(true);
|
|
58
|
+
};
|
|
59
|
+
$[3] = t2;
|
|
60
|
+
} else t2 = $[3];
|
|
61
|
+
const close = t2;
|
|
62
|
+
let t3;
|
|
63
|
+
if ($[4] !== authenticationUrl || $[5] !== token) {
|
|
64
|
+
t3 = () => {
|
|
65
|
+
const destination = new URL("/claim", authenticationUrl);
|
|
66
|
+
destination.searchParams.set("token", token);
|
|
67
|
+
destination.searchParams.set("callback", pageWithoutToken());
|
|
68
|
+
window.location.href = destination.href;
|
|
69
|
+
};
|
|
70
|
+
$[4] = authenticationUrl;
|
|
71
|
+
$[5] = token;
|
|
72
|
+
$[6] = t3;
|
|
73
|
+
} else t3 = $[6];
|
|
74
|
+
const claim = t3;
|
|
75
|
+
let t4;
|
|
76
|
+
let t5;
|
|
77
|
+
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
|
|
78
|
+
t4 = /* @__PURE__ */ jsx("style", { children: claimCardStyles });
|
|
79
|
+
t5 = /* @__PURE__ */ jsx("button", {
|
|
80
|
+
type: "button",
|
|
81
|
+
className: "camox-claim-close",
|
|
82
|
+
"aria-label": "Close",
|
|
83
|
+
onClick: close,
|
|
84
|
+
children: "×"
|
|
85
|
+
});
|
|
86
|
+
$[7] = t4;
|
|
87
|
+
$[8] = t5;
|
|
88
|
+
} else {
|
|
89
|
+
t4 = $[7];
|
|
90
|
+
t5 = $[8];
|
|
91
|
+
}
|
|
92
|
+
let t6;
|
|
93
|
+
if ($[9] !== claim || $[10] !== opening.operatorName || $[11] !== opening.organizationName || $[12] !== opening.state || $[13] !== signIn) {
|
|
94
|
+
t6 = /* @__PURE__ */ jsxs("aside", {
|
|
95
|
+
className: "camox-claim-card",
|
|
96
|
+
"aria-label": "Claim this website",
|
|
97
|
+
children: [
|
|
98
|
+
t4,
|
|
99
|
+
t5,
|
|
100
|
+
opening.state === "open" || opening.state === "preview" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
101
|
+
opening.state === "preview" && /* @__PURE__ */ jsx("span", {
|
|
102
|
+
className: "camox-claim-preview",
|
|
103
|
+
children: "Preview: this is the card whoever you send the link to sees"
|
|
104
|
+
}),
|
|
105
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
106
|
+
opening.operatorName,
|
|
107
|
+
" from Camox built this website for ",
|
|
108
|
+
opening.organizationName,
|
|
109
|
+
". Claim it to start editing."
|
|
110
|
+
] }),
|
|
111
|
+
opening.state === "open" && /* @__PURE__ */ jsx("button", {
|
|
112
|
+
type: "button",
|
|
113
|
+
className: "camox-claim-action",
|
|
114
|
+
onClick: claim,
|
|
115
|
+
children: "Claim website"
|
|
116
|
+
})
|
|
117
|
+
] }) : opening.state === "claimed" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", { children: "This website has been claimed." }), /* @__PURE__ */ jsx("button", {
|
|
118
|
+
type: "button",
|
|
119
|
+
className: "camox-claim-action",
|
|
120
|
+
onClick: signIn,
|
|
121
|
+
children: "Sign in"
|
|
122
|
+
})] }) : /* @__PURE__ */ jsx("p", { children: "This link no longer works. Ask whoever sent it for a new one." })
|
|
123
|
+
]
|
|
124
|
+
});
|
|
125
|
+
$[9] = claim;
|
|
126
|
+
$[10] = opening.operatorName;
|
|
127
|
+
$[11] = opening.organizationName;
|
|
128
|
+
$[12] = opening.state;
|
|
129
|
+
$[13] = signIn;
|
|
130
|
+
$[14] = t6;
|
|
131
|
+
} else t6 = $[14];
|
|
132
|
+
return t6;
|
|
133
|
+
}
|
|
134
|
+
function _temp(error) {
|
|
135
|
+
return console.error("The Claim Link couldn't be opened", error);
|
|
136
|
+
}
|
|
137
|
+
const claimCardStyles = `
|
|
138
|
+
.camox-claim-card {
|
|
139
|
+
background: #09090b;
|
|
140
|
+
border: 1px solid #27272a;
|
|
141
|
+
border-radius: 12px;
|
|
142
|
+
bottom: 24px;
|
|
143
|
+
box-shadow: 0 10px 30px rgb(0 0 0 / 0.35);
|
|
144
|
+
box-sizing: border-box;
|
|
145
|
+
color: #fafafa;
|
|
146
|
+
color-scheme: dark;
|
|
147
|
+
display: flex;
|
|
148
|
+
flex-direction: column;
|
|
149
|
+
font: 15px/1.5 Inter, ui-sans-serif, system-ui, sans-serif;
|
|
150
|
+
gap: 12px;
|
|
151
|
+
max-width: min(24rem, calc(100vw - 32px));
|
|
152
|
+
padding: 20px 44px 20px 20px;
|
|
153
|
+
position: fixed;
|
|
154
|
+
right: 16px;
|
|
155
|
+
text-align: left;
|
|
156
|
+
z-index: 2147483647;
|
|
157
|
+
}
|
|
158
|
+
.camox-claim-card p { margin: 0; }
|
|
159
|
+
.camox-claim-card button { cursor: pointer; font: inherit; }
|
|
160
|
+
.camox-claim-card .camox-claim-close {
|
|
161
|
+
background: none;
|
|
162
|
+
border: 0;
|
|
163
|
+
color: #a1a1aa;
|
|
164
|
+
font-size: 20px;
|
|
165
|
+
line-height: 1;
|
|
166
|
+
padding: 4px 8px;
|
|
167
|
+
position: absolute;
|
|
168
|
+
right: 8px;
|
|
169
|
+
top: 8px;
|
|
170
|
+
}
|
|
171
|
+
.camox-claim-card .camox-claim-close:hover { color: #fafafa; }
|
|
172
|
+
.camox-claim-card .camox-claim-preview {
|
|
173
|
+
align-self: flex-start;
|
|
174
|
+
background: #27272a;
|
|
175
|
+
border-radius: 999px;
|
|
176
|
+
color: #d4d4d8;
|
|
177
|
+
font-size: 12px;
|
|
178
|
+
padding: 2px 10px;
|
|
179
|
+
}
|
|
180
|
+
.camox-claim-card .camox-claim-action {
|
|
181
|
+
align-self: flex-start;
|
|
182
|
+
background: #fafafa;
|
|
183
|
+
border: 0;
|
|
184
|
+
border-radius: 8px;
|
|
185
|
+
color: #09090b;
|
|
186
|
+
font-weight: 600;
|
|
187
|
+
padding: 8px 14px;
|
|
188
|
+
}
|
|
189
|
+
`;
|
|
190
|
+
|
|
191
|
+
//#endregion
|
|
192
|
+
export { ClaimCard };
|
|
@@ -2,8 +2,8 @@ import { DraftScopeContext } from "../../lib/draft-scope.js";
|
|
|
2
2
|
import { useAuthState, useSignInRedirect } from "../../lib/auth.js";
|
|
3
3
|
import { ArtifactCaptureContext } from "../../core/hooks/useArtifactHost.js";
|
|
4
4
|
import { useSignInShortcut } from "../provider/signInShortcut.js";
|
|
5
|
-
import { PreviewDocumentContext } from "./PreviewDocumentContext.js";
|
|
6
5
|
import { PreviewActivation } from "../preview/components/PreviewActivation.js";
|
|
6
|
+
import { PreviewDocumentContext } from "./PreviewDocumentContext.js";
|
|
7
7
|
import { Frame } from "../preview/components/Frame.js";
|
|
8
8
|
import { PreviewSignInPage } from "../provider/PreviewSignInPage.js";
|
|
9
9
|
import { CoreCamoxProvider } from "../provider/CoreCamoxProvider.js";
|
|
@@ -11,12 +11,13 @@ import { CuratedPageContent } from "../page/CuratedPageContent.js";
|
|
|
11
11
|
import { DerivedPageContent } from "../page/DerivedPageContent.js";
|
|
12
12
|
import { UnplacedBlockContent } from "../page/UnplacedBlockContent.js";
|
|
13
13
|
import { UnplacedLayoutContent } from "../page/UnplacedLayoutContent.js";
|
|
14
|
+
import { ClaimCard } from "./ClaimCard.js";
|
|
14
15
|
import { EditingFallbackSlot } from "./editingFallback.js";
|
|
15
16
|
import { PageNavigationProvider } from "./pageNavigation.js";
|
|
16
17
|
import { RuntimeChromeSlot } from "./runtimeChromeLoader.js";
|
|
17
18
|
import { c } from "react/compiler-runtime";
|
|
18
19
|
import * as React from "react";
|
|
19
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
20
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
20
21
|
import { HydrationBoundary, QueryClientProvider } from "@tanstack/react-query";
|
|
21
22
|
|
|
22
23
|
//#region src/features/runtime/pageApp.tsx
|
|
@@ -43,12 +44,12 @@ function PageApp(t0) {
|
|
|
43
44
|
camoxApp,
|
|
44
45
|
input: currentInput
|
|
45
46
|
})
|
|
46
|
-
}) : /* @__PURE__ */ jsx(PageExperience, {
|
|
47
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(PageExperience, {
|
|
47
48
|
camoxApp,
|
|
48
49
|
input: currentInput,
|
|
49
50
|
queryClient,
|
|
50
51
|
studioDocument: input.presentation === "studio"
|
|
51
|
-
})
|
|
52
|
+
}), /* @__PURE__ */ jsx(ClaimCard, {})] })
|
|
52
53
|
})
|
|
53
54
|
});
|
|
54
55
|
$[0] = camoxApp;
|