camox 0.52.3 → 0.53.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/editing/createEditableBlock.js +1 -1
- package/dist/features/canvas/CamoxCanvas.js +103 -83
- package/dist/features/canvas/CanvasPageFrame.js +1 -1
- package/dist/features/canvas/CanvasPreviewPageSlot.js +1 -1
- package/dist/features/canvas/canvasCamera.js +3 -3
- package/dist/features/canvas/sidebar/CanvasInspector.js +4 -159
- package/dist/features/canvas/sidebar/CanvasNavigator.js +41 -85
- package/dist/features/canvas/sidebar/CanvasSidebar.js +54 -32
- package/dist/features/canvas/sidebar/CanvasSidebarFrame.js +4 -3
- package/dist/features/canvas/sidebar/CanvasSidebarSkeleton.js +14 -6
- package/dist/features/canvas/sidebar/CanvasViewHeader.js +50 -0
- package/dist/features/canvas/sidebar/DerivedPageInspector.js +30 -18
- package/dist/features/canvas/sidebar/LayoutPageOverview.js +28 -11
- package/dist/features/canvas/sidebar/LayoutPageSeo.js +356 -0
- package/dist/features/canvas/sidebar/PageInspector.js +118 -80
- package/dist/features/canvas/sidebar/PageOverview.js +6 -1
- package/dist/features/canvas/sidebar/SingletonPageInspector.js +22 -14
- package/dist/features/canvas/useCanvasCamera.js +36 -39
- package/dist/features/preview/CamoxPreview.js +1 -1
- package/dist/features/preview/components/BlockActionsPopover.js +1 -1
- package/dist/features/preview/components/BlockThumbnail.js +1 -1
- package/dist/features/preview/components/CanvasPreview.js +1 -1
- package/dist/features/preview/components/CreatePageModal.js +1 -1
- package/dist/features/preview/components/ItemFieldsEditor.js +1 -1
- package/dist/features/preview/components/OverlayTracker.js +1 -1
- package/dist/features/preview/components/PageInfo.js +345 -228
- package/dist/features/preview/components/PageTree.js +1 -1
- package/dist/features/preview/components/PreviewPanel.js +1 -1
- package/dist/features/preview/components/PreviewToolbar.js +2 -2
- package/dist/features/preview/components/RepeatableItemsList.js +1 -1
- package/dist/features/preview/components/SelectionEditor.js +645 -655
- package/dist/features/preview/components/SidebarStack.js +553 -0
- package/dist/features/preview/components/StudioEditingFallback.js +2 -2
- package/dist/features/renderer/RendererFrames.js +34 -27
- package/dist/features/runtime/RuntimeChrome.js +1 -1
- package/dist/features/runtime/runtime.js +84 -26
- package/dist/features/studio/components/ChatSidebar.js +27 -19
- package/dist/features/studio/components/Navbar.js +1 -1
- package/dist/features/studio/components/UserButton.js +1 -1
- package/dist/lib/studio-reads.js +18 -0
- package/dist/package.js +1 -1
- package/dist/studio.css +1 -1
- package/package.json +4 -4
|
@@ -933,17 +933,41 @@ async function loadLayoutResult(app, match, context, locale) {
|
|
|
933
933
|
}
|
|
934
934
|
/**
|
|
935
935
|
* The Markdown of a singleton or derived page: front matter, its before blocks, the layout's
|
|
936
|
-
* toMarkdown output, then its after blocks.
|
|
936
|
+
* toMarkdown output, then its after blocks. Null without toMarkdown: the page is then HTML only.
|
|
937
|
+
* The layout's blocks settle which draft it reads, as they do for the page's HTML.
|
|
937
938
|
*/
|
|
938
|
-
async function
|
|
939
|
+
async function buildLayoutMarkdown(options, match, locale, page, reader = { member: false }) {
|
|
939
940
|
const { toMarkdown, id } = match.layout._internal;
|
|
940
941
|
const { apiUrl, projectUuid } = options;
|
|
941
942
|
if (!toMarkdown || !apiUrl || !projectUuid) return null;
|
|
942
|
-
const
|
|
943
|
+
const authCookieHeader = reader.member ? reader.authCookieHeader : void 0;
|
|
944
|
+
const api = (draftId) => createServerApiClient(apiUrl, {
|
|
945
|
+
authCookieHeader,
|
|
946
|
+
draftId,
|
|
947
|
+
locale
|
|
948
|
+
});
|
|
949
|
+
const { value: slots, draftId } = await readDraftOrLive(reader.requestedDraft, reader.member, (draftId) => api(draftId).blocks.getLayoutMarkdown({
|
|
950
|
+
projectUuid,
|
|
951
|
+
layoutId: id
|
|
952
|
+
})).catch((error) => {
|
|
953
|
+
if (!isNotFoundError(error)) throw error;
|
|
954
|
+
return {
|
|
955
|
+
value: {
|
|
956
|
+
before: "",
|
|
957
|
+
after: "",
|
|
958
|
+
projectName: ""
|
|
959
|
+
},
|
|
960
|
+
draftId: reader.member ? reader.requestedDraft : void 0
|
|
961
|
+
};
|
|
962
|
+
});
|
|
943
963
|
const app = await options.getCamoxApp?.();
|
|
944
964
|
/** The layout's own Markdown, between its before and after blocks, and what built it. */
|
|
945
965
|
const layoutMarkdown = async () => {
|
|
946
|
-
const result = await loadLayoutResult(app, match, createLayoutRequestContext(options, "live", {
|
|
966
|
+
const result = await loadLayoutResult(app, match, createLayoutRequestContext(options, reader.member ? "draft" : "live", {
|
|
967
|
+
authCookieHeader,
|
|
968
|
+
draftId,
|
|
969
|
+
locale
|
|
970
|
+
}), locale);
|
|
947
971
|
const record = asCollectionItem(result);
|
|
948
972
|
const collection = record && app?.getCollectionById(record.collectionId);
|
|
949
973
|
if (!record || !collection) return {
|
|
@@ -960,7 +984,7 @@ async function createLayoutMarkdownResponse(options, match, locale, page) {
|
|
|
960
984
|
item
|
|
961
985
|
}));
|
|
962
986
|
return {
|
|
963
|
-
body: [await api.collectionDefinitions.recordMarkdown({
|
|
987
|
+
body: [await api(draftId).collectionDefinitions.recordMarkdown({
|
|
964
988
|
projectUuid,
|
|
965
989
|
collectionId: record.collectionId,
|
|
966
990
|
id: data.id,
|
|
@@ -970,24 +994,7 @@ async function createLayoutMarkdownResponse(options, match, locale, page) {
|
|
|
970
994
|
record: recordPageValues(collection, record)
|
|
971
995
|
};
|
|
972
996
|
};
|
|
973
|
-
|
|
974
|
-
try {
|
|
975
|
-
rendered = await layoutMarkdown();
|
|
976
|
-
} catch (error) {
|
|
977
|
-
if (isNotFoundError(error)) return new Response("Page not found", { status: 404 });
|
|
978
|
-
throw error;
|
|
979
|
-
}
|
|
980
|
-
const slots = await api.blocks.getLayoutMarkdown({
|
|
981
|
-
projectUuid,
|
|
982
|
-
layoutId: id
|
|
983
|
-
}).catch((error) => {
|
|
984
|
-
if (isNotFoundError(error)) return {
|
|
985
|
-
before: "",
|
|
986
|
-
after: "",
|
|
987
|
-
projectName: ""
|
|
988
|
-
};
|
|
989
|
-
throw error;
|
|
990
|
-
});
|
|
997
|
+
const rendered = await layoutMarkdown();
|
|
991
998
|
const meta = buildPageMeta({
|
|
992
999
|
layout: match.layout._internal,
|
|
993
1000
|
context: buildLayoutContext(match.layout._internal, {
|
|
@@ -1004,10 +1011,59 @@ async function createLayoutMarkdownResponse(options, match, locale, page) {
|
|
|
1004
1011
|
...rendered.body,
|
|
1005
1012
|
slots.after
|
|
1006
1013
|
].filter(Boolean).join("\n\n");
|
|
1007
|
-
return
|
|
1014
|
+
return withFrontMatter(markdown, {
|
|
1008
1015
|
...meta,
|
|
1009
1016
|
url: page.url
|
|
1010
|
-
})
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
/**
|
|
1020
|
+
* A singleton or derived page's public Markdown Representation. Markdown is a public output: it
|
|
1021
|
+
* reads published records and blocks whoever asks.
|
|
1022
|
+
*/
|
|
1023
|
+
async function createLayoutMarkdownResponse(options, match, locale, page) {
|
|
1024
|
+
let markdown;
|
|
1025
|
+
try {
|
|
1026
|
+
markdown = await buildLayoutMarkdown(options, match, locale, page);
|
|
1027
|
+
} catch (error) {
|
|
1028
|
+
if (isNotFoundError(error)) return new Response("Page not found", { status: 404 });
|
|
1029
|
+
throw error;
|
|
1030
|
+
}
|
|
1031
|
+
if (markdown === null) return null;
|
|
1032
|
+
return new Response(markdown, { headers: { "Content-Type": "text/markdown; charset=utf-8" } });
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* A singleton or derived page's Markdown Representation as JSON (`/_camox/data?markdown`), read
|
|
1036
|
+
* like the page's data: in the draft the URL names, for a member. The studio shows it, while the
|
|
1037
|
+
* page's `.md` URL always reads Live. `markdown` is null when the layout declares none.
|
|
1038
|
+
*/
|
|
1039
|
+
async function createLayoutMarkdownDataResponse(options, request, pathname) {
|
|
1040
|
+
const located = await locateRequest(request, options, pathname);
|
|
1041
|
+
const app = await options.getCamoxApp?.();
|
|
1042
|
+
const match = app && matchDerivedLayout(app.getLayouts(), located.path);
|
|
1043
|
+
if (!match || matchLocalizedRoute(located.path)?.kind !== "page") return new Response("Not found", { status: 404 });
|
|
1044
|
+
const { project, clearAuthCookie } = await resolveRequestMember(request, options);
|
|
1045
|
+
const headers = {
|
|
1046
|
+
...isPrivateRender(request, options) ? { "Cache-Control": "private, no-store" } : {},
|
|
1047
|
+
Vary: "Cookie",
|
|
1048
|
+
...clearAuthCookie ? { "Set-Cookie": buildClearServerAuthCookieHeader() } : {}
|
|
1049
|
+
};
|
|
1050
|
+
try {
|
|
1051
|
+
const markdown = await buildLayoutMarkdown(options, match, located.locale, {
|
|
1052
|
+
pathname,
|
|
1053
|
+
url: absoluteUrl(request, options)(pathname)
|
|
1054
|
+
}, {
|
|
1055
|
+
member: project !== void 0,
|
|
1056
|
+
authCookieHeader: getServerAuthCookieHeader(request.headers),
|
|
1057
|
+
requestedDraft: getRequestDraftId(request, options)
|
|
1058
|
+
});
|
|
1059
|
+
return Response.json({ markdown }, { headers });
|
|
1060
|
+
} catch (error) {
|
|
1061
|
+
if (isNotFoundError(error)) return new Response("Not found", {
|
|
1062
|
+
status: 404,
|
|
1063
|
+
headers
|
|
1064
|
+
});
|
|
1065
|
+
throw error;
|
|
1066
|
+
}
|
|
1011
1067
|
}
|
|
1012
1068
|
async function createDerivedResponse(options, pathname, located, request, { dataOnly = false, singletonOnly = false } = {}) {
|
|
1013
1069
|
const app = await options.getCamoxApp?.();
|
|
@@ -1337,8 +1393,10 @@ async function handleCamoxRequest(request, options = {}) {
|
|
|
1337
1393
|
if (match.kind === "llms-txt") return createLlmsTxtResponse(request, options);
|
|
1338
1394
|
if (match.kind === "routes") return createRoutesResponse(request, options);
|
|
1339
1395
|
if (match.kind === "data") {
|
|
1340
|
-
const
|
|
1396
|
+
const { searchParams } = new URL(request.url);
|
|
1397
|
+
const targetPathname = normalizePagePath(searchParams.get("path"));
|
|
1341
1398
|
if (matchRuntimeOwnedRoute(targetPathname)) return new Response("Not found", { status: 404 });
|
|
1399
|
+
if (searchParams.has("markdown")) return createLayoutMarkdownDataResponse(options, request, targetPathname);
|
|
1342
1400
|
return respondInLocale(options, request, targetPathname, { dataOnly: true });
|
|
1343
1401
|
}
|
|
1344
1402
|
if (isPreviewHandoff(request, options) && match.kind === "page") return createPreviewHandoffResponse({
|
|
@@ -2,6 +2,8 @@ import { AuthContext } from "../../../lib/auth.js";
|
|
|
2
2
|
import { useCurrentDraftId, useDraftScope } from "../../../lib/draft-scope.js";
|
|
3
3
|
import { useNavigate } from "../../navigation/navigation.js";
|
|
4
4
|
import { reads, useReadQuery } from "../../../lib/studio-reads.js";
|
|
5
|
+
import { cn } from "../../../lib/utils.js";
|
|
6
|
+
import { BOTTOM_CARD_EDGES, CARD_BODY_EDGES, SIDEBAR_GUTTER } from "../../preview/components/SidebarStack.js";
|
|
5
7
|
import { draftLabel } from "../draftLabel.js";
|
|
6
8
|
import { FollowAgentContext } from "../followAgentContext.js";
|
|
7
9
|
import { useThread } from "../../../lib/use-thread.js";
|
|
@@ -20,45 +22,51 @@ import { EMPTY_THREAD_VIEW } from "@camox/api-contract/threads";
|
|
|
20
22
|
* When the Live thread starts a draft, the studio enters it with the thread.
|
|
21
23
|
*/
|
|
22
24
|
function ChatSidebar(t0) {
|
|
23
|
-
const $ = c(
|
|
25
|
+
const $ = c(6);
|
|
24
26
|
const { hidden: t1 } = t0;
|
|
25
27
|
const hidden = t1 === void 0 ? false : t1;
|
|
26
28
|
let t2;
|
|
27
|
-
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
28
|
-
t2 = { width: 265 };
|
|
29
|
-
$[0] = t2;
|
|
30
|
-
} else t2 = $[0];
|
|
31
29
|
let t3;
|
|
32
30
|
let t4;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
let t5;
|
|
32
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
33
|
+
t2 = cn("absolute inset-y-0 right-0 z-10 flex flex-col py-2 max-md:hidden", SIDEBAR_GUTTER);
|
|
34
|
+
t3 = { width: 265 };
|
|
35
|
+
t4 = /* @__PURE__ */ jsxs("header", {
|
|
36
|
+
className: cn("bg-background flex h-11 min-w-0 shrink-0 items-center justify-center gap-2 px-3", BOTTOM_CARD_EDGES),
|
|
36
37
|
children: [/* @__PURE__ */ jsx(CamoxMark, {}), /* @__PURE__ */ jsx("h2", {
|
|
37
38
|
className: "truncate text-sm font-medium",
|
|
38
39
|
children: "Chat"
|
|
39
40
|
})]
|
|
40
41
|
});
|
|
41
|
-
|
|
42
|
+
t5 = /* @__PURE__ */ jsx("div", {
|
|
43
|
+
className: cn("bg-background flex min-h-0 flex-1 flex-col", CARD_BODY_EDGES),
|
|
44
|
+
children: /* @__PURE__ */ jsx(CurrentThread, {})
|
|
45
|
+
});
|
|
46
|
+
$[0] = t2;
|
|
42
47
|
$[1] = t3;
|
|
43
48
|
$[2] = t4;
|
|
49
|
+
$[3] = t5;
|
|
44
50
|
} else {
|
|
51
|
+
t2 = $[0];
|
|
45
52
|
t3 = $[1];
|
|
46
53
|
t4 = $[2];
|
|
54
|
+
t5 = $[3];
|
|
47
55
|
}
|
|
48
|
-
let
|
|
49
|
-
if ($[
|
|
50
|
-
|
|
56
|
+
let t6;
|
|
57
|
+
if ($[4] !== hidden) {
|
|
58
|
+
t6 = /* @__PURE__ */ jsxs("aside", {
|
|
51
59
|
"aria-label": "Chat",
|
|
52
60
|
"data-chat-sidebar": true,
|
|
53
61
|
hidden,
|
|
54
|
-
className:
|
|
55
|
-
style:
|
|
56
|
-
children: [
|
|
62
|
+
className: t2,
|
|
63
|
+
style: t3,
|
|
64
|
+
children: [t4, t5]
|
|
57
65
|
});
|
|
58
|
-
$[
|
|
59
|
-
$[
|
|
60
|
-
} else
|
|
61
|
-
return
|
|
66
|
+
$[4] = hidden;
|
|
67
|
+
$[5] = t6;
|
|
68
|
+
} else t6 = $[5];
|
|
69
|
+
return t6;
|
|
62
70
|
}
|
|
63
71
|
/** Camox's logo, beside the heading: the agent is Camox. */
|
|
64
72
|
function CamoxMark() {
|
|
@@ -151,7 +151,7 @@ const Navbar = (t0) => {
|
|
|
151
151
|
let t11;
|
|
152
152
|
if ($[24] !== t9) {
|
|
153
153
|
t11 = /* @__PURE__ */ jsxs("nav", {
|
|
154
|
-
className: "bg-background relative flex items-center justify-between gap-4 border-b
|
|
154
|
+
className: "bg-background relative flex items-center justify-between gap-4 border-b px-2 py-2",
|
|
155
155
|
children: [t9, t10]
|
|
156
156
|
});
|
|
157
157
|
$[24] = t9;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useAuthContext, useAuthState } from "../../../lib/auth.js";
|
|
2
2
|
import { useNavigate } from "../../navigation/navigation.js";
|
|
3
3
|
import { useLocalePath, useLocalizedPath } from "../../../lib/view-locale.js";
|
|
4
|
-
import { PlatformLabel } from "../../../components/PlatformLabel.js";
|
|
5
4
|
import { previewStore, selectIsCanvasShown } from "../../preview/previewStore.js";
|
|
5
|
+
import { PlatformLabel } from "../../../components/PlatformLabel.js";
|
|
6
6
|
import { STUDIO_BASE_PATH } from "../routes.js";
|
|
7
7
|
import { studioStore } from "../studioStore.js";
|
|
8
8
|
import { useApplyTheme } from "../useTheme.js";
|
package/dist/lib/studio-reads.js
CHANGED
|
@@ -251,6 +251,24 @@ const reads = {
|
|
|
251
251
|
fetch: async (context, { runtimeBasePath, pathname }) => (await readRender(context, runtimeBasePath, pathname))?.derived?.result ?? null,
|
|
252
252
|
staleTime: Infinity
|
|
253
253
|
}),
|
|
254
|
+
layoutPageMarkdown: entry({
|
|
255
|
+
key: ({ projectUuid, runtimeBasePath, pathname }) => [
|
|
256
|
+
...queryKeys.layouts.all,
|
|
257
|
+
"markdown",
|
|
258
|
+
projectUuid,
|
|
259
|
+
runtimeBasePath,
|
|
260
|
+
pathname
|
|
261
|
+
],
|
|
262
|
+
fetch: async ({ runtimeJson, draft, signal }, { runtimeBasePath, pathname }) => {
|
|
263
|
+
const response = await runtimeJson("/_camox/data", runtimeBasePath, {
|
|
264
|
+
path: pathname,
|
|
265
|
+
markdown: ""
|
|
266
|
+
}, draft, signal);
|
|
267
|
+
if (!response.ok) throw new Error(`Could not load the Markdown of ${pathname}.`);
|
|
268
|
+
return (await response.json()).markdown;
|
|
269
|
+
},
|
|
270
|
+
retry: false
|
|
271
|
+
}),
|
|
254
272
|
discoveredPath: entry({
|
|
255
273
|
key: ({ projectUuid, runtimeBasePath, layoutId, recordId }) => [
|
|
256
274
|
...queryKeys.layouts.all,
|
package/dist/package.js
CHANGED