camox 0.40.0 → 0.41.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/components/PlatformLabel.js +62 -0
- package/dist/core/components/lexical/GradientNode.js +126 -0
- package/dist/core/components/lexical/InlineLexicalEditor.js +37 -56
- package/dist/core/components/lexical/InlineStylesPlugin.js +183 -0
- package/dist/core/components/lexical/SelectionBroadcaster.js +49 -46
- package/dist/core/components/lexical/SidebarLexicalEditor.js +197 -151
- package/dist/core/components/lexical/editorConfig.js +25 -7
- package/dist/core/components/lexical/selectTextLink.js +21 -0
- package/dist/core/createApp.d.ts +30 -17
- package/dist/core/createApp.js +14 -3
- package/dist/core/createBlock.d.ts +2 -2
- package/dist/core/createBlock.js +17 -28
- package/dist/core/createLayout.d.ts +48 -4
- package/dist/core/createLayout.js +51 -23
- package/dist/core/derivedRoutes.js +36 -0
- package/dist/core/editing/BlockEditingRuntime.js +4 -4
- package/dist/core/editing/CompleteBlockEditingRuntime.js +5 -5
- package/dist/core/editing/createEditableBlock.d.ts +9 -8
- package/dist/core/editing/createEditableBlock.js +265 -403
- package/dist/core/hooks/useIsEditable.js +4 -7
- package/dist/core/hooks/useRequireDraftSource.js +7 -11
- package/dist/core/lib/lexicalReact.d.ts +1 -26
- package/dist/core/lib/lexicalReact.js +46 -60
- package/dist/core/lib/lexicalState.js +164 -81
- package/dist/core/lib/modifierFormats.js +4 -15
- package/dist/core/lib/textStyles.d.ts +27 -0
- package/dist/core/lib/textStyles.js +47 -0
- package/dist/features/navigation/navigation.d.ts +2 -0
- package/dist/features/navigation/navigation.js +51 -46
- package/dist/features/page/DerivedPageContent.js +61 -0
- package/dist/features/page/PublishedPageContent.js +52 -83
- package/dist/features/page/SharedLayoutContent.js +66 -0
- package/dist/features/preview/CamoxPreview.d.ts +16 -1
- package/dist/features/preview/CamoxPreview.js +246 -290
- package/dist/features/preview/DerivedPreview.js +134 -0
- package/dist/features/preview/EditablePageExperience.js +25 -8
- package/dist/features/preview/components/AddBlockSidebar.js +43 -33
- package/dist/features/preview/components/AssetLightbox.js +1 -1
- package/dist/features/preview/components/BlockActionsPopover.js +8 -8
- package/dist/features/preview/components/BlockThumbnail.js +192 -0
- package/dist/features/preview/components/CreatePageModal.js +123 -115
- package/dist/features/preview/components/DerivedLayoutDialog.js +100 -0
- package/dist/features/preview/components/DerivedLayoutSidebar.d.ts +5 -0
- package/dist/features/preview/components/DerivedLayoutSidebar.js +160 -0
- package/dist/features/preview/components/DerivedPageInfoSidebar.js +57 -0
- package/dist/features/preview/components/FieldToolbar.js +42 -20
- package/dist/features/preview/components/Frame.js +133 -140
- package/dist/features/preview/components/LeftSidebar.js +42 -38
- package/dist/features/preview/components/LinkFieldEditor.js +3 -4
- package/dist/features/preview/components/MobilePreviewDrawer.js +4 -4
- package/dist/features/preview/components/Overlays.js +59 -47
- package/dist/features/preview/components/PageEditorSidebar.js +194 -203
- package/dist/features/preview/components/PageInfoSidebar.js +63 -55
- package/dist/features/preview/components/PageNavigatorSidebar.js +34 -483
- package/dist/features/preview/components/PagePicker.js +205 -153
- package/dist/features/preview/components/PageTree.js +366 -340
- package/dist/features/preview/components/PreviewActivation.js +78 -0
- package/dist/features/preview/components/PreviewPanel.js +98 -68
- package/dist/features/preview/components/PreviewToolbar.js +224 -241
- package/dist/features/preview/components/PreviewToolbarSpacer.js +43 -0
- package/dist/features/preview/components/PublicationRow.js +425 -0
- package/dist/features/preview/components/PublishDialog.js +180 -97
- package/dist/features/preview/components/RightSidebar.js +19 -34
- package/dist/features/preview/components/previewStyles.js +8 -0
- package/dist/features/preview/components/useUpdateBlockPosition.js +7 -13
- package/dist/features/preview/previewConstants.js +8 -0
- package/dist/features/preview/previewStore.js +18 -39
- package/dist/features/preview/publication.js +71 -0
- package/dist/features/provider/AuthenticatedCamoxProvider.js +2 -1
- package/dist/features/provider/CoreCamoxProvider.js +11 -2
- package/dist/features/provider/LocalhostPreviewProvider.js +6 -7
- package/dist/features/provider/useAdminShortcuts.js +5 -4
- package/dist/features/routes/pageRuntime.d.ts +10 -0
- package/dist/features/routes/pageRuntime.js +7 -9
- package/dist/features/runtime/PreviewDocumentContext.js +7 -0
- package/dist/features/runtime/RuntimeChrome.js +149 -0
- package/dist/features/runtime/SharedChromeContext.js +7 -0
- package/dist/features/runtime/navigationRequest.js +21 -0
- package/dist/features/runtime/navigationTarget.js +23 -0
- package/dist/features/runtime/pageApp.js +196 -121
- package/dist/features/runtime/pageNavigation.js +79 -130
- package/dist/features/runtime/runtime.d.ts +11 -0
- package/dist/features/runtime/runtime.js +183 -47
- package/dist/features/runtime/studioApp.d.ts +2 -11
- package/dist/features/runtime/studioApp.js +14 -177
- package/dist/features/studio/CamoxStudio.js +27 -13
- package/dist/features/studio/components/Navbar.js +80 -74
- package/dist/features/studio/components/UserButton.js +4 -4
- package/dist/features/studio/studioTheme.js +25 -0
- package/dist/features/studio/useTheme.js +94 -109
- package/dist/features/vite/appGeneration.js +12 -3
- package/dist/features/vite/definitionsSync.js +4 -2
- package/dist/features/vite/layoutGeneration.js +38 -0
- package/dist/features/vite/runtimeDev.js +3 -1
- package/dist/lib/auth.js +15 -13
- package/dist/lib/normalized-data.js +4 -4
- package/dist/lib/platform.js +13 -0
- package/dist/lib/utils.js +90 -38
- package/dist/studio-overlays.css +5 -40
- package/dist/studio.css +1 -1
- package/package.json +8 -4
- package/skills/camox/SKILL.md +2 -0
- package/skills/camox/references/block-definitions.md +31 -12
- package/skills/camox/references/layout-definitions.md +2 -0
- package/dist/core/lib/modifiers.js +0 -24
- package/dist/features/preview/components/DraftSwitchDialog.js +0 -66
- package/dist/features/preview/previewQueryFns.js +0 -23
- package/dist/features/runtime/studioNavigation.js +0 -120
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PLATFORM_SCRIPT } from "../../lib/platform.js";
|
|
2
|
+
import { STUDIO_THEME_SCRIPT } from "../studio/studioTheme.js";
|
|
3
|
+
import { matchDerivedLayout } from "../../core/derivedRoutes.js";
|
|
4
|
+
import { buildCamoxPageHead, createMarkdownResponse, createServerApiClient, isAuthSessionError, isNotFoundError, loadCamoxPageForRequest, seedBlockCaches } from "../routes/pageRuntime.js";
|
|
2
5
|
import { QueryClient, dehydrate } from "@tanstack/react-query";
|
|
3
6
|
import { createHead, renderSSRHead } from "@unhead/react/server";
|
|
4
7
|
|
|
@@ -40,8 +43,7 @@ function normalizePagePath(path) {
|
|
|
40
43
|
if (!path) return "/";
|
|
41
44
|
return path.startsWith("/") ? path : `/${path}`;
|
|
42
45
|
}
|
|
43
|
-
function getLayoutIdentity(
|
|
44
|
-
const layout = data.page.layout;
|
|
46
|
+
function getLayoutIdentity(layout, source) {
|
|
45
47
|
if (!layout) return null;
|
|
46
48
|
const version = source === "live" ? String(layout.livePublishedCheckpointId ?? "none") : String(layout.contentUpdatedAt ?? layout.updatedAt);
|
|
47
49
|
return {
|
|
@@ -173,10 +175,15 @@ function createPageHeadInput(head) {
|
|
|
173
175
|
link: pageLinks
|
|
174
176
|
};
|
|
175
177
|
}
|
|
176
|
-
function renderHead(document, pageHead, stylesheetUrl) {
|
|
178
|
+
function renderHead(document, pageHead, stylesheetUrl, studioStylesheetUrl) {
|
|
177
179
|
const head = createHead();
|
|
178
180
|
head.push(createDefaultHeadInput(stylesheetUrl));
|
|
179
181
|
head.push(document);
|
|
182
|
+
if (studioStylesheetUrl) head.push({ link: [{
|
|
183
|
+
rel: "stylesheet",
|
|
184
|
+
href: studioStylesheetUrl,
|
|
185
|
+
"data-camox-studio": "true"
|
|
186
|
+
}] });
|
|
180
187
|
head.push(pageHead);
|
|
181
188
|
return renderSSRHead(head);
|
|
182
189
|
}
|
|
@@ -187,6 +194,20 @@ function renderClientEntryScript(src) {
|
|
|
187
194
|
if (!src) return "";
|
|
188
195
|
return `<script type="module" src="${escapeXml(src)}"><\/script>`;
|
|
189
196
|
}
|
|
197
|
+
async function preparePreviewDocument(input, options, document, content) {
|
|
198
|
+
const siteHead = renderHead(document, createPageHeadInput(input.head ?? {}), options.stylesheetUrl);
|
|
199
|
+
const href = new URL(withRuntimeBasePath(input.pathname, options.runtimeBasePath), input.href).href;
|
|
200
|
+
const siteHtml = content ?? (options.renderPage ? await options.renderPage({
|
|
201
|
+
...input,
|
|
202
|
+
href,
|
|
203
|
+
presentation: "public",
|
|
204
|
+
previewDocument: void 0
|
|
205
|
+
}) : "");
|
|
206
|
+
input.previewDocument = `<!doctype html><html${siteHead.htmlAttrs}><head><base href="${escapeXml(href)}">${siteHead.headTags}</head><body${siteHead.bodyAttrs}>${siteHead.bodyTagsOpen}<div id="root" data-camox-preview-root>${siteHtml}</div>${siteHead.bodyTags}</body></html>`;
|
|
207
|
+
}
|
|
208
|
+
function renderStudioThemeScript(enabled) {
|
|
209
|
+
return enabled ? `<script data-camox-studio>${STUDIO_THEME_SCRIPT}${PLATFORM_SCRIPT}<\/script>` : "";
|
|
210
|
+
}
|
|
190
211
|
async function createPageHtmlResponse({ options, pathname, request }) {
|
|
191
212
|
if (!options.apiUrl || !options.authenticationUrl || !options.projectSlug || !options.renderPage) return createPageDataResponse({
|
|
192
213
|
options,
|
|
@@ -204,31 +225,39 @@ async function createPageHtmlResponse({ options, pathname, request }) {
|
|
|
204
225
|
projectSlug: options.projectSlug,
|
|
205
226
|
queryClient
|
|
206
227
|
});
|
|
207
|
-
const headers = new Headers({
|
|
228
|
+
const headers = new Headers({
|
|
229
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
230
|
+
Vary: "Cookie"
|
|
231
|
+
});
|
|
232
|
+
if (getServerAuthCookieHeader(request.headers)) headers.set("Cache-Control", "private, no-store");
|
|
208
233
|
if (result.shouldClearAuthCookie) headers.append("Set-Cookie", buildClearServerAuthCookieHeader());
|
|
209
234
|
const camoxApp = await options.getCamoxApp?.();
|
|
210
235
|
const document = await options.getDocument?.() ?? {};
|
|
211
236
|
const head = camoxApp ? buildCamoxPageHead(camoxApp, result.data) : {};
|
|
212
237
|
const dehydratedState = dehydrate(queryClient);
|
|
213
238
|
const pageRenderInput = {
|
|
239
|
+
project: result.source === "draft" ? await createServerApiClient(options.apiUrl, options.environmentName, { authCookieHeader: getServerAuthCookieHeader(request.headers) }).projects.getBySlug({ slug: options.projectSlug }) : void 0,
|
|
240
|
+
presentation: result.source === "draft" ? "studio" : "public",
|
|
214
241
|
apiUrl: options.apiUrl,
|
|
215
242
|
authenticationUrl: options.authenticationUrl,
|
|
216
243
|
dehydratedState,
|
|
217
244
|
environmentName: options.environmentName,
|
|
218
245
|
head,
|
|
219
246
|
href: new URL(request.url).href,
|
|
220
|
-
layoutIdentity: getLayoutIdentity(result.data, result.source),
|
|
247
|
+
layoutIdentity: getLayoutIdentity(result.data.page.layout, result.source),
|
|
221
248
|
loaderData: result.data,
|
|
222
249
|
pathname,
|
|
223
250
|
projectSlug: options.projectSlug,
|
|
224
251
|
runtimeBasePath: normalizeRuntimeBasePath(options.runtimeBasePath),
|
|
225
252
|
source: result.source
|
|
226
253
|
};
|
|
254
|
+
await preparePreviewDocument(pageRenderInput, options, document, result.source === "live" ? "" : void 0);
|
|
227
255
|
const appHtml = await options.renderPage(pageRenderInput);
|
|
228
|
-
const renderedHead = renderHead(document, createPageHeadInput(head), options.stylesheetUrl);
|
|
256
|
+
const renderedHead = renderHead(result.source === "draft" ? {} : document, createPageHeadInput(head), result.source === "draft" ? void 0 : options.stylesheetUrl, result.source === "draft" ? options.studioStylesheetUrl : void 0);
|
|
229
257
|
return new Response(`<!doctype html>
|
|
230
258
|
<html${renderedHead.htmlAttrs}>
|
|
231
259
|
<head>
|
|
260
|
+
${renderStudioThemeScript(result.source === "draft")}
|
|
232
261
|
${renderedHead.headTags}
|
|
233
262
|
<script id="__CAMOX_DATA__" type="application/json">${serializeJsonForHtml(pageRenderInput)}<\/script>
|
|
234
263
|
</head>
|
|
@@ -240,18 +269,102 @@ ${renderClientEntryScript(options.pageClientEntryUrl)}
|
|
|
240
269
|
</body>
|
|
241
270
|
</html>`, { headers });
|
|
242
271
|
} catch (error) {
|
|
243
|
-
if (isNotFoundError(error))
|
|
272
|
+
if (isNotFoundError(error)) {
|
|
273
|
+
const derived = await createDerivedResponse(options, pathname, request);
|
|
274
|
+
if (derived) return derived;
|
|
275
|
+
return new Response("No Camox page on this path", { status: 404 });
|
|
276
|
+
}
|
|
277
|
+
throw error;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
async function createDerivedResponse(options, pathname, request, dataOnly = false) {
|
|
281
|
+
const app = await options.getCamoxApp?.();
|
|
282
|
+
const match = app && matchDerivedLayout(app.getLayouts(), pathname);
|
|
283
|
+
if (!match || !dataOnly && !options.renderPage) return null;
|
|
284
|
+
try {
|
|
285
|
+
const data = await match.layout._internal.loader({ params: match.params });
|
|
286
|
+
const serializedData = JSON.parse(JSON.stringify(data));
|
|
287
|
+
const queryClient = new QueryClient();
|
|
288
|
+
const authCookieHeader = getServerAuthCookieHeader(request.headers);
|
|
289
|
+
let source = authCookieHeader ? "draft" : "live";
|
|
290
|
+
let clearAuthCookie = false;
|
|
291
|
+
const loadLayout = (source) => createServerApiClient(options.apiUrl, options.environmentName, { authCookieHeader: source === "draft" ? authCookieHeader : void 0 }).layouts.get({
|
|
292
|
+
projectSlug: options.projectSlug,
|
|
293
|
+
layoutId: match.layout._internal.id,
|
|
294
|
+
source
|
|
295
|
+
});
|
|
296
|
+
const shared = await loadLayout(source).catch(async (error) => {
|
|
297
|
+
if (source !== "draft" || !isAuthSessionError(error)) throw error;
|
|
298
|
+
source = "live";
|
|
299
|
+
clearAuthCookie = true;
|
|
300
|
+
return loadLayout("live");
|
|
301
|
+
});
|
|
302
|
+
seedBlockCaches(queryClient, shared, source);
|
|
303
|
+
const input = {
|
|
304
|
+
project: source === "draft" ? await createServerApiClient(options.apiUrl, options.environmentName, { authCookieHeader }).projects.getBySlug({ slug: options.projectSlug }) : void 0,
|
|
305
|
+
presentation: source === "draft" ? "studio" : "public",
|
|
306
|
+
apiUrl: options.apiUrl,
|
|
307
|
+
authenticationUrl: options.authenticationUrl,
|
|
308
|
+
projectSlug: options.projectSlug,
|
|
309
|
+
environmentName: options.environmentName,
|
|
310
|
+
dehydratedState: dehydrate(queryClient),
|
|
311
|
+
head: { meta: [{ title: match.layout._internal.title }] },
|
|
312
|
+
href: request.url,
|
|
313
|
+
layoutIdentity: getLayoutIdentity(shared.layout, source),
|
|
314
|
+
loaderData: null,
|
|
315
|
+
pathname,
|
|
316
|
+
runtimeBasePath: normalizeRuntimeBasePath(options.runtimeBasePath),
|
|
317
|
+
source,
|
|
318
|
+
derived: {
|
|
319
|
+
layoutId: match.layout._internal.id,
|
|
320
|
+
data: serializedData,
|
|
321
|
+
layout: shared.layout
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
const document = await options.getDocument?.() ?? {};
|
|
325
|
+
await preparePreviewDocument(input, options, document, source === "live" && !dataOnly ? "" : void 0);
|
|
326
|
+
if (dataOnly) return Response.json(input, { headers: {
|
|
327
|
+
"Cache-Control": "private, no-store",
|
|
328
|
+
Vary: "Cookie",
|
|
329
|
+
...clearAuthCookie ? { "Set-Cookie": buildClearServerAuthCookieHeader() } : {}
|
|
330
|
+
} });
|
|
331
|
+
const html = await options.renderPage(input);
|
|
332
|
+
const head = renderHead(source === "draft" ? {} : document, { title: match.layout._internal.title }, source === "draft" ? void 0 : options.stylesheetUrl, source === "draft" ? options.studioStylesheetUrl : void 0);
|
|
333
|
+
return new Response(`<!doctype html><html${head.htmlAttrs}><head>${renderStudioThemeScript(source === "draft")}${head.headTags}<script id="__CAMOX_DATA__" type="application/json">${serializeJsonForHtml(input)}<\/script></head><body${head.bodyAttrs}>${head.bodyTagsOpen}<div id="root">${html}</div>${head.bodyTags}${renderClientEntryScript(options.pageClientEntryUrl)}</body></html>`, { headers: {
|
|
334
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
335
|
+
Vary: "Cookie",
|
|
336
|
+
...authCookieHeader ? { "Cache-Control": "private, no-store" } : {},
|
|
337
|
+
...clearAuthCookie ? { "Set-Cookie": buildClearServerAuthCookieHeader() } : {}
|
|
338
|
+
} });
|
|
339
|
+
} catch (error) {
|
|
340
|
+
if (isNotFoundError(error)) return new Response("Page not found", { status: 404 });
|
|
244
341
|
throw error;
|
|
245
342
|
}
|
|
246
343
|
}
|
|
247
|
-
async function createStudioHtmlResponse({ match, options, request }) {
|
|
248
|
-
if (!options.apiUrl || !options.authenticationUrl || !options.projectSlug || !options.renderStudio) return Response.json({
|
|
344
|
+
async function createStudioHtmlResponse({ match, options, request, dataOnly = false }) {
|
|
345
|
+
if (!options.apiUrl || !options.authenticationUrl || !options.projectSlug || !dataOnly && !options.renderStudio) return Response.json({
|
|
249
346
|
message: "Camox Studio renderer is not configured.",
|
|
250
347
|
...match
|
|
251
348
|
}, { status: 500 });
|
|
252
349
|
const queryClient = new QueryClient();
|
|
253
|
-
const
|
|
350
|
+
const authCookieHeader = getServerAuthCookieHeader(request.headers);
|
|
351
|
+
let project;
|
|
352
|
+
let presentation = "public";
|
|
353
|
+
let clearAuthCookie = false;
|
|
354
|
+
if (authCookieHeader) try {
|
|
355
|
+
project = await createServerApiClient(options.apiUrl, options.environmentName, { authCookieHeader }).projects.getBySlug({ slug: options.projectSlug });
|
|
356
|
+
presentation = "studio";
|
|
357
|
+
} catch (error) {
|
|
358
|
+
if (!isAuthSessionError(error)) throw error;
|
|
359
|
+
clearAuthCookie = true;
|
|
360
|
+
}
|
|
254
361
|
const studioRenderInput = {
|
|
362
|
+
project,
|
|
363
|
+
source: "live",
|
|
364
|
+
head: { meta: [{ title: "Camox Studio" }] },
|
|
365
|
+
layoutIdentity: null,
|
|
366
|
+
loaderData: null,
|
|
367
|
+
presentation,
|
|
255
368
|
apiUrl: options.apiUrl,
|
|
256
369
|
authenticationUrl: options.authenticationUrl,
|
|
257
370
|
dehydratedState: dehydrate(queryClient),
|
|
@@ -262,11 +375,17 @@ async function createStudioHtmlResponse({ match, options, request }) {
|
|
|
262
375
|
routeKind: match.kind,
|
|
263
376
|
runtimeBasePath: normalizeRuntimeBasePath(options.runtimeBasePath)
|
|
264
377
|
};
|
|
378
|
+
if (dataOnly) return Response.json(studioRenderInput, { headers: {
|
|
379
|
+
"Cache-Control": "private, no-store",
|
|
380
|
+
Vary: "Cookie",
|
|
381
|
+
...clearAuthCookie ? { "Set-Cookie": buildClearServerAuthCookieHeader() } : {}
|
|
382
|
+
} });
|
|
265
383
|
const appHtml = await options.renderStudio(studioRenderInput);
|
|
266
|
-
const renderedHead = renderHead(
|
|
384
|
+
const renderedHead = renderHead({}, { title: "Camox Studio" }, void 0, presentation === "studio" ? options.studioStylesheetUrl : void 0);
|
|
267
385
|
return new Response(`<!doctype html>
|
|
268
386
|
<html${renderedHead.htmlAttrs}>
|
|
269
387
|
<head>
|
|
388
|
+
${renderStudioThemeScript(presentation === "studio")}
|
|
270
389
|
${renderedHead.headTags}
|
|
271
390
|
<script id="__CAMOX_DATA__" type="application/json">${serializeJsonForHtml(studioRenderInput)}<\/script>
|
|
272
391
|
</head>
|
|
@@ -276,7 +395,12 @@ ${renderedHead.bodyTagsOpen}
|
|
|
276
395
|
${renderedHead.bodyTags}
|
|
277
396
|
${renderClientEntryScript(options.studioClientEntryUrl)}
|
|
278
397
|
</body>
|
|
279
|
-
</html>`, { headers: {
|
|
398
|
+
</html>`, { headers: {
|
|
399
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
400
|
+
"Cache-Control": "private, no-store",
|
|
401
|
+
Vary: "Cookie",
|
|
402
|
+
...clearAuthCookie ? { "Set-Cookie": buildClearServerAuthCookieHeader() } : {}
|
|
403
|
+
} });
|
|
280
404
|
}
|
|
281
405
|
async function createPageDataResponse({ options, pathname, request }) {
|
|
282
406
|
if (!options.apiUrl || !options.projectSlug) return Response.json({ message: "Camox page loader is not configured." }, { status: 500 });
|
|
@@ -291,43 +415,44 @@ async function createPageDataResponse({ options, pathname, request }) {
|
|
|
291
415
|
projectSlug: options.projectSlug,
|
|
292
416
|
queryClient
|
|
293
417
|
});
|
|
294
|
-
const headers = new Headers({
|
|
418
|
+
const headers = new Headers({
|
|
419
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
420
|
+
"Cache-Control": "private, no-store",
|
|
421
|
+
Vary: "Cookie"
|
|
422
|
+
});
|
|
295
423
|
if (result.shouldClearAuthCookie) headers.append("Set-Cookie", buildClearServerAuthCookieHeader());
|
|
296
424
|
const camoxApp = await options.getCamoxApp?.();
|
|
297
425
|
const head = camoxApp ? buildCamoxPageHead(camoxApp, result.data) : null;
|
|
298
426
|
const dehydratedState = dehydrate(queryClient);
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
427
|
+
const project = result.source === "draft" ? await createServerApiClient(options.apiUrl, options.environmentName, { authCookieHeader: getServerAuthCookieHeader(request.headers) }).projects.getBySlug({ slug: options.projectSlug }) : void 0;
|
|
428
|
+
const input = {
|
|
429
|
+
apiUrl: options.apiUrl,
|
|
430
|
+
authenticationUrl: options.authenticationUrl ?? "",
|
|
431
|
+
environmentName: options.environmentName,
|
|
432
|
+
projectSlug: options.projectSlug,
|
|
433
|
+
runtimeBasePath: normalizeRuntimeBasePath(options.runtimeBasePath),
|
|
434
|
+
href: request.url,
|
|
435
|
+
presentation: result.source === "draft" ? "studio" : "public",
|
|
436
|
+
source: result.source,
|
|
302
437
|
pathname,
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
metaTitle: page.metaTitle,
|
|
307
|
-
metaDescription: page.metaDescription
|
|
308
|
-
},
|
|
309
|
-
layout: layout ? {
|
|
310
|
-
id: layout.id,
|
|
311
|
-
layoutId: layout.layoutId
|
|
312
|
-
} : null,
|
|
313
|
-
layoutIdentity: getLayoutIdentity(result.data, result.source),
|
|
314
|
-
project: {
|
|
315
|
-
id: project.id,
|
|
316
|
-
name: projectName
|
|
317
|
-
},
|
|
318
|
-
loaderData: {
|
|
319
|
-
faviconUrl: result.data.faviconUrl,
|
|
320
|
-
origin: result.data.origin
|
|
321
|
-
},
|
|
438
|
+
layoutIdentity: getLayoutIdentity(result.data.page.layout, result.source),
|
|
439
|
+
project,
|
|
440
|
+
loaderData: result.data,
|
|
322
441
|
head,
|
|
323
442
|
dehydratedState
|
|
324
|
-
}
|
|
443
|
+
};
|
|
444
|
+
await preparePreviewDocument(input, options, await options.getDocument?.() ?? {});
|
|
445
|
+
return Response.json(input, { headers });
|
|
325
446
|
} catch (error) {
|
|
326
|
-
if (isNotFoundError(error))
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
447
|
+
if (isNotFoundError(error)) {
|
|
448
|
+
const derived = await createDerivedResponse(options, pathname, request, true);
|
|
449
|
+
if (derived) return derived;
|
|
450
|
+
return Response.json({
|
|
451
|
+
kind: "page",
|
|
452
|
+
message: "No Camox page on this path",
|
|
453
|
+
pathname
|
|
454
|
+
}, { status: 404 });
|
|
455
|
+
}
|
|
331
456
|
throw error;
|
|
332
457
|
}
|
|
333
458
|
}
|
|
@@ -346,11 +471,22 @@ async function handleCamoxRequest(request, options = {}) {
|
|
|
346
471
|
}
|
|
347
472
|
if (match.kind === "og") return createOgResponse(request, options);
|
|
348
473
|
if (match.kind === "sitemap") return createSitemapResponse(request, options);
|
|
349
|
-
if (match.kind === "data")
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
474
|
+
if (match.kind === "data") {
|
|
475
|
+
const targetPathname = normalizePagePath(new URL(request.url).searchParams.get("path"));
|
|
476
|
+
const targetMatch = matchRuntimeRoute(targetPathname);
|
|
477
|
+
if (targetMatch.kind.startsWith("studio")) return createStudioHtmlResponse({
|
|
478
|
+
match: targetMatch,
|
|
479
|
+
options,
|
|
480
|
+
request,
|
|
481
|
+
dataOnly: true
|
|
482
|
+
});
|
|
483
|
+
if (targetMatch.kind !== "page") return new Response("Not found", { status: 404 });
|
|
484
|
+
return createPageDataResponse({
|
|
485
|
+
options,
|
|
486
|
+
pathname: targetPathname,
|
|
487
|
+
request
|
|
488
|
+
});
|
|
489
|
+
}
|
|
354
490
|
if (match.kind === "studio" || match.kind === "studio-content" || match.kind === "studio-nested") return createStudioHtmlResponse({
|
|
355
491
|
match,
|
|
356
492
|
options,
|
|
@@ -1,15 +1,6 @@
|
|
|
1
|
+
import { PageRenderInput } from "./runtime.js";
|
|
1
2
|
import { QueryClient } from "@tanstack/react-query";
|
|
2
3
|
//#region src/features/runtime/studioApp.d.ts
|
|
3
|
-
|
|
4
|
-
apiUrl: string;
|
|
5
|
-
authenticationUrl: string;
|
|
6
|
-
dehydratedState: unknown;
|
|
7
|
-
environmentName?: string;
|
|
8
|
-
href: string;
|
|
9
|
-
pathname: string;
|
|
10
|
-
projectSlug: string;
|
|
11
|
-
routeKind: "studio" | "studio-content" | "studio-nested";
|
|
12
|
-
runtimeBasePath: string;
|
|
13
|
-
}
|
|
4
|
+
type StudioRenderInput = PageRenderInput;
|
|
14
5
|
//#endregion
|
|
15
6
|
export { StudioRenderInput };
|
|
@@ -1,184 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { STUDIO_CONTENT_PATH } from "../studio/routes.js";
|
|
3
|
-
import { CamoxContent } from "../content/CamoxContent.js";
|
|
4
|
-
import { AuthGate } from "../../components/AuthGate.js";
|
|
5
|
-
import { AuthenticatedCamoxProvider } from "../provider/AuthenticatedCamoxProvider.js";
|
|
6
|
-
import { CoreCamoxProvider } from "../provider/CoreCamoxProvider.js";
|
|
7
|
-
import { CamoxStudio } from "../studio/CamoxStudio.js";
|
|
8
|
-
import { CompleteBlockEditingRuntimeProvider } from "../../core/editing/CompleteBlockEditingRuntime.js";
|
|
9
|
-
import { StudioNavigationProvider } from "./studioNavigation.js";
|
|
1
|
+
import { PageApp } from "./pageApp.js";
|
|
10
2
|
import { c } from "react/compiler-runtime";
|
|
11
|
-
import {
|
|
12
|
-
import * as React from "react";
|
|
13
|
-
import { Fragment, jsx } from "react/jsx-runtime";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
14
4
|
|
|
15
5
|
//#region src/features/runtime/studioApp.tsx
|
|
16
|
-
function
|
|
17
|
-
const $ = c(
|
|
18
|
-
if ($[0] !== "
|
|
19
|
-
for (let $i = 0; $i <
|
|
20
|
-
$[0] = "
|
|
6
|
+
function StudioApp(props) {
|
|
7
|
+
const $ = c(3);
|
|
8
|
+
if ($[0] !== "67c2b6f45da5572f3c7b8c4d68491571a2d455e4cd7067c0380e91fc49b09d93") {
|
|
9
|
+
for (let $i = 0; $i < 3; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
10
|
+
$[0] = "67c2b6f45da5572f3c7b8c4d68491571a2d455e4cd7067c0380e91fc49b09d93";
|
|
21
11
|
}
|
|
22
|
-
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return t1;
|
|
30
|
-
}
|
|
31
|
-
if (input.routeKind === "studio-nested") {
|
|
32
|
-
let t1;
|
|
33
|
-
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
|
34
|
-
t1 = /* @__PURE__ */ jsx("div", {
|
|
35
|
-
className: "text-muted-foreground p-6 text-sm",
|
|
36
|
-
children: "Studio page not found"
|
|
37
|
-
});
|
|
38
|
-
$[2] = t1;
|
|
39
|
-
} else t1 = $[2];
|
|
40
|
-
return t1;
|
|
41
|
-
}
|
|
42
|
-
let t1;
|
|
43
|
-
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
|
44
|
-
t1 = /* @__PURE__ */ jsx("div", {
|
|
45
|
-
className: "text-muted-foreground p-6 text-sm",
|
|
46
|
-
children: "Loading Studio…"
|
|
47
|
-
});
|
|
48
|
-
$[3] = t1;
|
|
49
|
-
} else t1 = $[3];
|
|
50
|
-
return t1;
|
|
51
|
-
}
|
|
52
|
-
function StudioAuthentication(t0) {
|
|
53
|
-
const $ = c(6);
|
|
54
|
-
if ($[0] !== "4c9c648e70d7360e13c0b3d8d0f0633d0ab4263e359229c8802810bae1f42f17") {
|
|
55
|
-
for (let $i = 0; $i < 6; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
56
|
-
$[0] = "4c9c648e70d7360e13c0b3d8d0f0633d0ab4263e359229c8802810bae1f42f17";
|
|
57
|
-
}
|
|
58
|
-
const { children } = t0;
|
|
59
|
-
const signInRedirect = useSignInRedirect(_temp);
|
|
60
|
-
let t1;
|
|
61
|
-
let t2;
|
|
62
|
-
if ($[1] !== signInRedirect) {
|
|
63
|
-
t1 = () => signInRedirect();
|
|
64
|
-
t2 = [signInRedirect];
|
|
65
|
-
$[1] = signInRedirect;
|
|
66
|
-
$[2] = t1;
|
|
67
|
-
$[3] = t2;
|
|
68
|
-
} else {
|
|
69
|
-
t1 = $[2];
|
|
70
|
-
t2 = $[3];
|
|
71
|
-
}
|
|
72
|
-
React.useEffect(t1, t2);
|
|
73
|
-
let t3;
|
|
74
|
-
if ($[4] !== children) {
|
|
75
|
-
t3 = /* @__PURE__ */ jsx(Fragment, { children });
|
|
76
|
-
$[4] = children;
|
|
77
|
-
$[5] = t3;
|
|
78
|
-
} else t3 = $[5];
|
|
79
|
-
return t3;
|
|
80
|
-
}
|
|
81
|
-
function _temp() {
|
|
82
|
-
if (typeof window === "undefined") return;
|
|
83
|
-
return new URL("/", window.location.href).href;
|
|
84
|
-
}
|
|
85
|
-
function StudioAccessGate(t0) {
|
|
86
|
-
const $ = c(6);
|
|
87
|
-
if ($[0] !== "4c9c648e70d7360e13c0b3d8d0f0633d0ab4263e359229c8802810bae1f42f17") {
|
|
88
|
-
for (let $i = 0; $i < 6; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
89
|
-
$[0] = "4c9c648e70d7360e13c0b3d8d0f0633d0ab4263e359229c8802810bae1f42f17";
|
|
90
|
-
}
|
|
91
|
-
const { children } = t0;
|
|
92
|
-
let t1;
|
|
93
|
-
if ($[1] !== children) {
|
|
94
|
-
t1 = /* @__PURE__ */ jsx(AuthenticatedCamoxProvider, { children });
|
|
95
|
-
$[1] = children;
|
|
96
|
-
$[2] = t1;
|
|
97
|
-
} else t1 = $[2];
|
|
98
|
-
let t2;
|
|
99
|
-
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
|
100
|
-
t2 = /* @__PURE__ */ jsx(StudioAuthentication, { children: null });
|
|
101
|
-
$[3] = t2;
|
|
102
|
-
} else t2 = $[3];
|
|
103
|
-
let t3;
|
|
104
|
-
if ($[4] !== t1) {
|
|
105
|
-
t3 = /* @__PURE__ */ jsx(AuthGate, {
|
|
106
|
-
authenticated: t1,
|
|
107
|
-
loading: null,
|
|
108
|
-
unauthenticated: t2
|
|
109
|
-
});
|
|
110
|
-
$[4] = t1;
|
|
111
|
-
$[5] = t3;
|
|
112
|
-
} else t3 = $[5];
|
|
113
|
-
return t3;
|
|
114
|
-
}
|
|
115
|
-
function StudioApp(t0) {
|
|
116
|
-
const $ = c(21);
|
|
117
|
-
if ($[0] !== "4c9c648e70d7360e13c0b3d8d0f0633d0ab4263e359229c8802810bae1f42f17") {
|
|
118
|
-
for (let $i = 0; $i < 21; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
119
|
-
$[0] = "4c9c648e70d7360e13c0b3d8d0f0633d0ab4263e359229c8802810bae1f42f17";
|
|
120
|
-
}
|
|
121
|
-
const { camoxApp, input, queryClient } = t0;
|
|
122
|
-
const t1 = input.dehydratedState;
|
|
123
|
-
let t2;
|
|
124
|
-
if ($[1] !== input) {
|
|
125
|
-
t2 = /* @__PURE__ */ jsx(StudioAccessGate, { children: /* @__PURE__ */ jsx(CompleteBlockEditingRuntimeProvider, { children: /* @__PURE__ */ jsx(CamoxStudio, { children: /* @__PURE__ */ jsx(StudioRouteContent, { input }) }) }) });
|
|
126
|
-
$[1] = input;
|
|
127
|
-
$[2] = t2;
|
|
128
|
-
} else t2 = $[2];
|
|
129
|
-
let t3;
|
|
130
|
-
if ($[3] !== camoxApp || $[4] !== input.apiUrl || $[5] !== input.authenticationUrl || $[6] !== input.environmentName || $[7] !== input.projectSlug || $[8] !== t2) {
|
|
131
|
-
t3 = /* @__PURE__ */ jsx(CoreCamoxProvider, {
|
|
132
|
-
camoxApp,
|
|
133
|
-
authenticationUrl: input.authenticationUrl,
|
|
134
|
-
apiUrl: input.apiUrl,
|
|
135
|
-
projectSlug: input.projectSlug,
|
|
136
|
-
environmentName: input.environmentName,
|
|
137
|
-
children: t2
|
|
138
|
-
});
|
|
139
|
-
$[3] = camoxApp;
|
|
140
|
-
$[4] = input.apiUrl;
|
|
141
|
-
$[5] = input.authenticationUrl;
|
|
142
|
-
$[6] = input.environmentName;
|
|
143
|
-
$[7] = input.projectSlug;
|
|
144
|
-
$[8] = t2;
|
|
145
|
-
$[9] = t3;
|
|
146
|
-
} else t3 = $[9];
|
|
147
|
-
let t4;
|
|
148
|
-
if ($[10] !== input.href || $[11] !== input.pathname || $[12] !== input.runtimeBasePath || $[13] !== t3) {
|
|
149
|
-
t4 = /* @__PURE__ */ jsx(StudioNavigationProvider, {
|
|
150
|
-
href: input.href,
|
|
151
|
-
pathname: input.pathname,
|
|
152
|
-
runtimeBasePath: input.runtimeBasePath,
|
|
153
|
-
children: t3
|
|
154
|
-
});
|
|
155
|
-
$[10] = input.href;
|
|
156
|
-
$[11] = input.pathname;
|
|
157
|
-
$[12] = input.runtimeBasePath;
|
|
158
|
-
$[13] = t3;
|
|
159
|
-
$[14] = t4;
|
|
160
|
-
} else t4 = $[14];
|
|
161
|
-
let t5;
|
|
162
|
-
if ($[15] !== t1 || $[16] !== t4) {
|
|
163
|
-
t5 = /* @__PURE__ */ jsx(HydrationBoundary, {
|
|
164
|
-
state: t1,
|
|
165
|
-
children: t4
|
|
166
|
-
});
|
|
167
|
-
$[15] = t1;
|
|
168
|
-
$[16] = t4;
|
|
169
|
-
$[17] = t5;
|
|
170
|
-
} else t5 = $[17];
|
|
171
|
-
let t6;
|
|
172
|
-
if ($[18] !== queryClient || $[19] !== t5) {
|
|
173
|
-
t6 = /* @__PURE__ */ jsx(QueryClientProvider, {
|
|
174
|
-
client: queryClient,
|
|
175
|
-
children: t5
|
|
176
|
-
});
|
|
177
|
-
$[18] = queryClient;
|
|
178
|
-
$[19] = t5;
|
|
179
|
-
$[20] = t6;
|
|
180
|
-
} else t6 = $[20];
|
|
181
|
-
return t6;
|
|
12
|
+
let t0;
|
|
13
|
+
if ($[1] !== props) {
|
|
14
|
+
t0 = /* @__PURE__ */ jsx(PageApp, { ...props });
|
|
15
|
+
$[1] = props;
|
|
16
|
+
$[2] = t0;
|
|
17
|
+
} else t0 = $[2];
|
|
18
|
+
return t0;
|
|
182
19
|
}
|
|
183
20
|
|
|
184
21
|
//#endregion
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { Navigate, useLocation } from "../navigation/navigation.js";
|
|
2
2
|
import { useAuthState, useSignInRedirect } from "../../lib/auth.js";
|
|
3
|
+
import { SharedChromeContext } from "../runtime/SharedChromeContext.js";
|
|
3
4
|
import { STUDIO_BASE_PATH } from "./routes.js";
|
|
4
5
|
import { trackClientEvent } from "../../lib/telemetry-client.js";
|
|
5
6
|
import { Navbar } from "./components/Navbar.js";
|
|
6
7
|
import { c } from "react/compiler-runtime";
|
|
7
8
|
import * as React from "react";
|
|
8
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
10
|
|
|
10
11
|
//#region src/features/studio/CamoxStudio.tsx
|
|
11
12
|
const CamoxStudio = (t0) => {
|
|
12
|
-
const $ = c(
|
|
13
|
-
if ($[0] !== "
|
|
14
|
-
for (let $i = 0; $i <
|
|
15
|
-
$[0] = "
|
|
13
|
+
const $ = c(16);
|
|
14
|
+
if ($[0] !== "424ccf9eb3e0b68f3206047ad39569798182b6392a92ca98a7e9d6cf3cc9ff22") {
|
|
15
|
+
for (let $i = 0; $i < 16; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
16
|
+
$[0] = "424ccf9eb3e0b68f3206047ad39569798182b6392a92ca98a7e9d6cf3cc9ff22";
|
|
16
17
|
}
|
|
17
18
|
const { children } = t0;
|
|
18
19
|
const { isAuthenticated, isLoading: isLoadingAuth } = useAuthState();
|
|
20
|
+
const sharedChrome = React.useContext(SharedChromeContext);
|
|
19
21
|
const { pathname } = useLocation();
|
|
20
22
|
const signInRedirect = useSignInRedirect();
|
|
21
23
|
let t1;
|
|
@@ -62,25 +64,37 @@ const CamoxStudio = (t0) => {
|
|
|
62
64
|
if (pathname === STUDIO_BASE_PATH) {
|
|
63
65
|
let t5;
|
|
64
66
|
if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
|
|
65
|
-
t5 = /* @__PURE__ */ jsx(Navigate, {
|
|
67
|
+
t5 = /* @__PURE__ */ jsx(Navigate, {
|
|
68
|
+
to: "/",
|
|
69
|
+
replace: true
|
|
70
|
+
});
|
|
66
71
|
$[10] = t5;
|
|
67
72
|
} else t5 = $[10];
|
|
68
73
|
return t5;
|
|
69
74
|
}
|
|
75
|
+
if (sharedChrome) {
|
|
76
|
+
let t5;
|
|
77
|
+
if ($[11] !== children) {
|
|
78
|
+
t5 = /* @__PURE__ */ jsx(Fragment, { children });
|
|
79
|
+
$[11] = children;
|
|
80
|
+
$[12] = t5;
|
|
81
|
+
} else t5 = $[12];
|
|
82
|
+
return t5;
|
|
83
|
+
}
|
|
70
84
|
let t5;
|
|
71
|
-
if ($[
|
|
85
|
+
if ($[13] === Symbol.for("react.memo_cache_sentinel")) {
|
|
72
86
|
t5 = /* @__PURE__ */ jsx(Navbar, {});
|
|
73
|
-
$[
|
|
74
|
-
} else t5 = $[
|
|
87
|
+
$[13] = t5;
|
|
88
|
+
} else t5 = $[13];
|
|
75
89
|
let t6;
|
|
76
|
-
if ($[
|
|
90
|
+
if ($[14] !== children) {
|
|
77
91
|
t6 = /* @__PURE__ */ jsxs("div", {
|
|
78
92
|
className: "bg-background flex h-screen flex-col overflow-hidden",
|
|
79
93
|
children: [t5, children]
|
|
80
94
|
});
|
|
81
|
-
$[
|
|
82
|
-
$[
|
|
83
|
-
} else t6 = $[
|
|
95
|
+
$[14] = children;
|
|
96
|
+
$[15] = t6;
|
|
97
|
+
} else t6 = $[15];
|
|
84
98
|
return t6;
|
|
85
99
|
};
|
|
86
100
|
|