camox 0.42.0 → 0.43.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/components/lexical/{GradientNode.js → HighlightNode.js} +34 -34
- package/dist/core/components/lexical/InlineLexicalEditor.js +14 -14
- package/dist/core/components/lexical/InlineStylesPlugin.js +6 -6
- package/dist/core/components/lexical/SelectionBroadcaster.js +5 -5
- package/dist/core/components/lexical/SidebarLexicalEditor.js +20 -20
- package/dist/core/components/lexical/TextLinkPopover.js +191 -208
- package/dist/core/components/lexical/editorConfig.js +2 -2
- package/dist/core/createApp.d.ts +3 -2
- package/dist/core/createApp.js +2 -1
- package/dist/core/createLayout.d.ts +16 -3
- package/dist/core/createLayout.js +15 -15
- package/dist/core/derivedRoutes.js +1 -1
- package/dist/core/dom.d.ts +17 -0
- package/dist/core/dom.js +22 -0
- package/dist/core/lib/lexicalReact.js +4 -4
- package/dist/core/lib/lexicalState.js +3 -3
- package/dist/core/lib/modifierFormats.js +1 -1
- package/dist/core/lib/textLinks.js +5 -2
- package/dist/core/lib/textStyles.d.ts +2 -2
- package/dist/core/lib/textStyles.js +6 -11
- package/dist/core/pageDestinations.js +37 -0
- package/dist/features/og/imageResponse.node.js +11 -9
- package/dist/features/preview/CamoxPreview.js +42 -65
- package/dist/features/preview/components/AddBlockSidebar.js +1 -1
- package/dist/features/preview/components/BlockActionsPopover.js +1 -1
- package/dist/features/preview/components/CreatePageModal.js +4 -4
- package/dist/features/preview/components/DerivedLayoutSidebar.js +45 -26
- package/dist/features/preview/components/DerivedPageInfoSidebar.js +38 -26
- package/dist/features/preview/components/FieldToolbar.js +7 -7
- package/dist/features/preview/components/LinkFieldEditor.js +212 -209
- package/dist/features/preview/components/PageEditorSidebar.js +1 -1
- package/dist/features/preview/components/PageInfoSidebar.js +28 -28
- package/dist/features/preview/components/PagePicker.js +16 -16
- package/dist/features/preview/components/PageTree.js +1 -1
- package/dist/features/preview/components/PublicationRow.js +8 -4
- package/dist/features/preview/components/useRepeatableItemActions.js +1 -1
- package/dist/features/preview/publication.js +10 -0
- package/dist/features/provider/CoreCamoxProvider.js +1 -1
- package/dist/features/runtime/runtime.js +20 -21
- package/dist/features/studio/components/EnvironmentMenu.js +3 -2
- package/dist/features/studio/components/Navbar.js +53 -80
- package/dist/features/vite/layoutGeneration.js +7 -3
- package/dist/features/vite/vite.js +5 -1
- package/dist/hooks/use-page-destinations.js +53 -0
- package/dist/lib/auth.js +11 -14
- package/dist/lib/server-auth-cookie.js +21 -0
- package/dist/studio.css +1 -1
- package/package.json +8 -4
- package/skills/camox/SKILL.md +32 -9
- package/skills/camox/references/block-definitions.md +84 -290
- package/skills/camox/references/cli-common.md +2 -4
- package/skills/camox/references/cli-content.md +147 -0
- package/skills/camox/references/cli-environments.md +1 -1
- package/skills/camox/references/dom-integrations.md +93 -0
- package/skills/camox/references/field-styling.md +50 -0
- package/skills/camox/references/layout-definitions.md +33 -147
- package/skills/camox/references/routed-layouts.md +71 -0
- package/skills/camoxify/SKILL.md +52 -0
- package/skills/camox/references/cli-blocks.md +0 -78
- package/skills/camox/references/cli-pages.md +0 -53
|
@@ -5,15 +5,17 @@ import { Fragment, jsx } from "react/jsx-runtime";
|
|
|
5
5
|
|
|
6
6
|
//#region src/core/createLayout.tsx
|
|
7
7
|
function createLayoutDefinition(options) {
|
|
8
|
+
if (options.kind === "singleton" && !/^[\w-]+(?:\.[\w-]+)*$/.test(options.id)) throw new Error(`Singleton layouts require a fixed file route: ${options.id}`);
|
|
9
|
+
if (options.kind && options.kind !== "curated" && options.blocks.initial) throw new Error("Code-owned layouts cannot define initial page blocks");
|
|
8
10
|
const LayoutContext = React.createContext(null);
|
|
9
11
|
const beforeBlocks = options.blocks.before;
|
|
10
12
|
const afterBlocks = options.blocks.after;
|
|
11
13
|
const initialBlocks = options.blocks.initial;
|
|
12
14
|
const BeforeBlocks = () => {
|
|
13
15
|
const $ = c(5);
|
|
14
|
-
if ($[0] !== "
|
|
16
|
+
if ($[0] !== "776e504f06a16915ba8008212a5b0af4dec7762a3d0b05161ac1048bec619433") {
|
|
15
17
|
for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
16
|
-
$[0] = "
|
|
18
|
+
$[0] = "776e504f06a16915ba8008212a5b0af4dec7762a3d0b05161ac1048bec619433";
|
|
17
19
|
}
|
|
18
20
|
const ctx = React.use(LayoutContext);
|
|
19
21
|
if (!ctx) throw new Error(`Layout "${options.id}" BeforeBlocks must be rendered inside its Provider`);
|
|
@@ -29,7 +31,7 @@ function createLayoutDefinition(options) {
|
|
|
29
31
|
children: /* @__PURE__ */ jsx(block._internal.Component, {
|
|
30
32
|
blockData,
|
|
31
33
|
mode: "layout",
|
|
32
|
-
showAddBlockBottom: options.kind
|
|
34
|
+
showAddBlockBottom: (options.kind ?? "curated") === "curated" && isLastBefore || void 0,
|
|
33
35
|
addBlockAfterPosition: isLastBefore ? "" : void 0
|
|
34
36
|
})
|
|
35
37
|
}, block._internal.id);
|
|
@@ -48,9 +50,9 @@ function createLayoutDefinition(options) {
|
|
|
48
50
|
BeforeBlocks.displayName = `LayoutBeforeBlocks(${options.id})`;
|
|
49
51
|
const AfterBlocks = () => {
|
|
50
52
|
const $ = c(5);
|
|
51
|
-
if ($[0] !== "
|
|
53
|
+
if ($[0] !== "776e504f06a16915ba8008212a5b0af4dec7762a3d0b05161ac1048bec619433") {
|
|
52
54
|
for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
53
|
-
$[0] = "
|
|
55
|
+
$[0] = "776e504f06a16915ba8008212a5b0af4dec7762a3d0b05161ac1048bec619433";
|
|
54
56
|
}
|
|
55
57
|
const ctx = React.use(LayoutContext);
|
|
56
58
|
if (!ctx) throw new Error(`Layout "${options.id}" AfterBlocks must be rendered inside its Provider`);
|
|
@@ -66,7 +68,7 @@ function createLayoutDefinition(options) {
|
|
|
66
68
|
children: /* @__PURE__ */ jsx(block._internal.Component, {
|
|
67
69
|
blockData,
|
|
68
70
|
mode: "layout",
|
|
69
|
-
showAddBlockTop: options.kind
|
|
71
|
+
showAddBlockTop: (options.kind ?? "curated") === "curated" && isFirstAfter || void 0,
|
|
70
72
|
addBlockAfterPosition: isFirstAfter ? null : void 0
|
|
71
73
|
})
|
|
72
74
|
}, block._internal.id);
|
|
@@ -85,9 +87,9 @@ function createLayoutDefinition(options) {
|
|
|
85
87
|
AfterBlocks.displayName = `LayoutAfterBlocks(${options.id})`;
|
|
86
88
|
const Provider = (t0) => {
|
|
87
89
|
const $ = c(7);
|
|
88
|
-
if ($[0] !== "
|
|
90
|
+
if ($[0] !== "776e504f06a16915ba8008212a5b0af4dec7762a3d0b05161ac1048bec619433") {
|
|
89
91
|
for (let $i = 0; $i < 7; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
90
|
-
$[0] = "
|
|
92
|
+
$[0] = "776e504f06a16915ba8008212a5b0af4dec7762a3d0b05161ac1048bec619433";
|
|
91
93
|
}
|
|
92
94
|
const { layoutBlocks, children, data } = t0;
|
|
93
95
|
let t1;
|
|
@@ -133,6 +135,7 @@ function createLayoutDefinition(options) {
|
|
|
133
135
|
};
|
|
134
136
|
})];
|
|
135
137
|
const buildOgImage = options.buildOgImage ? async (params) => {
|
|
138
|
+
if (import.meta.env?.SSR === false) throw new Error("OG images can only be rendered on the server.");
|
|
136
139
|
const { ImageResponse } = await import("camox/_internal/imageResponse");
|
|
137
140
|
return new ImageResponse(options.buildOgImage(params), {
|
|
138
141
|
width: 1200,
|
|
@@ -173,13 +176,10 @@ function createLayoutDefinition(options) {
|
|
|
173
176
|
}
|
|
174
177
|
function createLayout(idOrOptions) {
|
|
175
178
|
if (typeof idOrOptions !== "string") return createLayoutDefinition(idOrOptions);
|
|
176
|
-
return (options) => {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
id: idOrOptions
|
|
181
|
-
});
|
|
182
|
-
};
|
|
179
|
+
return (options) => createLayoutDefinition({
|
|
180
|
+
...options,
|
|
181
|
+
id: idOrOptions
|
|
182
|
+
});
|
|
183
183
|
}
|
|
184
184
|
/** Signal a missing derived page; other loader failures remain server errors. */
|
|
185
185
|
function notFound() {
|
|
@@ -4,7 +4,7 @@ function routeSegments(id) {
|
|
|
4
4
|
}
|
|
5
5
|
function matchDerivedLayout(layouts, pathname) {
|
|
6
6
|
const path = pathname.replace(/^\/|\/$/g, "").split("/");
|
|
7
|
-
const candidates = layouts.filter((layout) => layout._internal.kind
|
|
7
|
+
const candidates = layouts.filter((layout) => layout._internal.kind !== "curated").sort((a, b) => routeSegments(a._internal.id).filter((s) => s.startsWith("$")).length - routeSegments(b._internal.id).filter((s) => s.startsWith("$")).length);
|
|
8
8
|
for (const layout of candidates) {
|
|
9
9
|
const segments = routeSegments(layout._internal.id);
|
|
10
10
|
if (segments.length !== path.length) continue;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/core/dom.d.ts
|
|
2
|
+
/** The browsing context that owns a rendered element. */
|
|
3
|
+
interface ElementContext {
|
|
4
|
+
document: Document;
|
|
5
|
+
window: Window & typeof globalThis;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Resolve DOM APIs from an element rather than the component's JavaScript realm.
|
|
9
|
+
* In Camox preview, elements belong to an iframe but component globals belong
|
|
10
|
+
* to the editor. Call this after mounting (for example, inside an effect).
|
|
11
|
+
*
|
|
12
|
+
* Returns null for a missing element or a document without a window. Never
|
|
13
|
+
* falls back to globals. This does not convert objects into the target realm.
|
|
14
|
+
*/
|
|
15
|
+
declare function getElementContext(element: Element | null | undefined): ElementContext | null;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { ElementContext, getElementContext };
|
package/dist/core/dom.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/core/dom.ts
|
|
2
|
+
/**
|
|
3
|
+
* Resolve DOM APIs from an element rather than the component's JavaScript realm.
|
|
4
|
+
* In Camox preview, elements belong to an iframe but component globals belong
|
|
5
|
+
* to the editor. Call this after mounting (for example, inside an effect).
|
|
6
|
+
*
|
|
7
|
+
* Returns null for a missing element or a document without a window. Never
|
|
8
|
+
* falls back to globals. This does not convert objects into the target realm.
|
|
9
|
+
*/
|
|
10
|
+
function getElementContext(element) {
|
|
11
|
+
if (!element) return null;
|
|
12
|
+
const document = element.ownerDocument;
|
|
13
|
+
const window = document.defaultView;
|
|
14
|
+
if (!window) return null;
|
|
15
|
+
return {
|
|
16
|
+
document,
|
|
17
|
+
window
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { getElementContext };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FORMAT_FLAGS } from "./modifierFormats.js";
|
|
2
2
|
import { getPageIdFromTextLinkTarget, isHttpTextLinkTarget, resolveTextLinkHref, shouldOpenTextLinkInNewTab } from "./textLinks.js";
|
|
3
3
|
import { isLexicalState, markdownToLexicalState } from "./lexicalState.js";
|
|
4
|
-
import {
|
|
4
|
+
import { getHighlightStyle, getTextAppearance } from "./textStyles.js";
|
|
5
5
|
import * as React from "react";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
|
|
@@ -23,9 +23,9 @@ function markdownToReactNodes(value, options = {}) {
|
|
|
23
23
|
}
|
|
24
24
|
if (node.type === "linebreak") return /* @__PURE__ */ jsx("br", {}, key);
|
|
25
25
|
const children = (node.children ?? []).map(render);
|
|
26
|
-
if (node.type === "
|
|
27
|
-
"data-camox-
|
|
28
|
-
...
|
|
26
|
+
if (node.type === "highlight") return /* @__PURE__ */ jsx("span", {
|
|
27
|
+
"data-camox-highlight": "",
|
|
28
|
+
...getHighlightStyle(options),
|
|
29
29
|
children
|
|
30
30
|
}, key);
|
|
31
31
|
if (node.type === "link") {
|
|
@@ -36,7 +36,7 @@ function lexicalStateToMarkdown(serialized) {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
function extractMarkdownFromNode(node) {
|
|
39
|
-
if (node.type === "
|
|
39
|
+
if (node.type === "highlight") return `<highlight>${serializeInlineChildren(node.children ?? [])}</highlight>`;
|
|
40
40
|
if (node.type === "link") {
|
|
41
41
|
const text = serializeInlineChildren(node.children ?? []);
|
|
42
42
|
const url = typeof node.url === "string" ? node.url : "";
|
|
@@ -204,7 +204,7 @@ function parseTokens(tokens, format) {
|
|
|
204
204
|
else nodes.push(...children);
|
|
205
205
|
continue;
|
|
206
206
|
}
|
|
207
|
-
const tag = token.type === "html" ? /^<(
|
|
207
|
+
const tag = token.type === "html" ? /^<(highlight|u|strong|em)>$/.exec(token.raw)?.[1] : void 0;
|
|
208
208
|
if (tag) {
|
|
209
209
|
let depth = 1;
|
|
210
210
|
let end = i + 1;
|
|
@@ -221,7 +221,7 @@ function parseTokens(tokens, format) {
|
|
|
221
221
|
em: FORMAT_FLAGS.italic
|
|
222
222
|
};
|
|
223
223
|
const children = parseTokens(tokens.slice(i + 1, end), format | (tagFlags[tag] ?? 0));
|
|
224
|
-
if (tag === "
|
|
224
|
+
if (tag === "highlight") nodes.push(inlineElement("highlight", children));
|
|
225
225
|
else nodes.push(...children);
|
|
226
226
|
i = end;
|
|
227
227
|
continue;
|
|
@@ -12,12 +12,15 @@ function createPageTextLinkTarget(pageId) {
|
|
|
12
12
|
function isHttpTextLinkTarget(target) {
|
|
13
13
|
return /^https?:\/\//i.test(target);
|
|
14
14
|
}
|
|
15
|
+
function isInternalTextLinkTarget(target) {
|
|
16
|
+
return /^\/(?!\/)[^\s\\\p{Cc}]*$/u.test(target);
|
|
17
|
+
}
|
|
15
18
|
function isValidTextLinkTarget(target) {
|
|
16
|
-
return getPageIdFromTextLinkTarget(target) != null || isHttpTextLinkTarget(target);
|
|
19
|
+
return getPageIdFromTextLinkTarget(target) != null || isHttpTextLinkTarget(target) || isInternalTextLinkTarget(target);
|
|
17
20
|
}
|
|
18
21
|
function resolveTextLinkHref(target, pages, fallbackHref) {
|
|
19
22
|
const pageId = getPageIdFromTextLinkTarget(target);
|
|
20
|
-
if (pageId == null) return
|
|
23
|
+
if (pageId == null) return isValidTextLinkTarget(target) ? target : null;
|
|
21
24
|
return (pages?.find((p) => String(p.id) === pageId))?.fullPath ?? fallbackHref;
|
|
22
25
|
}
|
|
23
26
|
function shouldOpenTextLinkInNewTab(target) {
|
|
@@ -6,8 +6,8 @@ interface InlineStyle {
|
|
|
6
6
|
style?: CSSProperties;
|
|
7
7
|
}
|
|
8
8
|
interface TextStyleData {
|
|
9
|
-
/** True when styling the shared
|
|
10
|
-
|
|
9
|
+
/** True when styling the shared highlight wrapper. Other flags are false for this call. */
|
|
10
|
+
highlight: boolean;
|
|
11
11
|
bold: boolean;
|
|
12
12
|
italic: boolean;
|
|
13
13
|
underline: boolean;
|
|
@@ -3,7 +3,7 @@ import { FORMAT_FLAGS } from "./modifierFormats.js";
|
|
|
3
3
|
//#region src/core/lib/textStyles.ts
|
|
4
4
|
function getTextStyleData(format) {
|
|
5
5
|
return {
|
|
6
|
-
|
|
6
|
+
highlight: false,
|
|
7
7
|
bold: !!(format & FORMAT_FLAGS.bold),
|
|
8
8
|
italic: !!(format & FORMAT_FLAGS.italic),
|
|
9
9
|
underline: !!(format & FORMAT_FLAGS.underline)
|
|
@@ -21,15 +21,10 @@ function getTextAppearance(format, styles) {
|
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
backgroundClip: "text",
|
|
27
|
-
WebkitBackgroundClip: "text",
|
|
28
|
-
WebkitTextFillColor: "transparent"
|
|
29
|
-
};
|
|
30
|
-
function getGradientStyle(styles) {
|
|
24
|
+
const defaultHighlightStyle = { color: "var(--primary, currentColor)" };
|
|
25
|
+
function getHighlightStyle(styles) {
|
|
31
26
|
const custom = styles.textStyle?.({
|
|
32
|
-
|
|
27
|
+
highlight: true,
|
|
33
28
|
bold: false,
|
|
34
29
|
italic: false,
|
|
35
30
|
underline: false
|
|
@@ -37,11 +32,11 @@ function getGradientStyle(styles) {
|
|
|
37
32
|
return {
|
|
38
33
|
className: custom?.className,
|
|
39
34
|
style: {
|
|
40
|
-
...
|
|
35
|
+
...defaultHighlightStyle,
|
|
41
36
|
...custom?.style
|
|
42
37
|
}
|
|
43
38
|
};
|
|
44
39
|
}
|
|
45
40
|
|
|
46
41
|
//#endregion
|
|
47
|
-
export {
|
|
42
|
+
export { getHighlightStyle, getTextAppearance };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createPageTextLinkTarget } from "./lib/textLinks.js";
|
|
2
|
+
|
|
3
|
+
//#region src/core/pageDestinations.ts
|
|
4
|
+
/** Concrete navigable pages, not records that can all be mutated through pages.*. */
|
|
5
|
+
function getPageDestinations(pages, layouts) {
|
|
6
|
+
return [...pages.map((page) => ({
|
|
7
|
+
key: `page:${page.id}`,
|
|
8
|
+
kind: "curated",
|
|
9
|
+
pageId: page.id,
|
|
10
|
+
title: page.nickname,
|
|
11
|
+
fullPath: page.fullPath
|
|
12
|
+
})), ...layouts.filter((layout) => layout._internal.kind === "singleton").map(({ _internal: layout }) => ({
|
|
13
|
+
key: `singleton:${layout.id}`,
|
|
14
|
+
kind: "singleton",
|
|
15
|
+
layoutId: layout.id,
|
|
16
|
+
title: layout.title,
|
|
17
|
+
fullPath: `/${layout.id.split(".").map(encodeURIComponent).join("/")}`
|
|
18
|
+
}))];
|
|
19
|
+
}
|
|
20
|
+
/** Singleton links are ordinary internal URLs, never synthetic database page IDs. */
|
|
21
|
+
function destinationLink(destination) {
|
|
22
|
+
if (destination.kind === "curated") return {
|
|
23
|
+
type: "page",
|
|
24
|
+
pageId: String(destination.pageId)
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
type: "external",
|
|
28
|
+
href: destination.fullPath
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function destinationTextLink(destination) {
|
|
32
|
+
if (destination.kind === "curated") return createPageTextLinkTarget(destination.pageId);
|
|
33
|
+
return destination.fullPath;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
export { destinationLink, destinationTextLink, getPageDestinations };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_FONTS } from "./defaultFonts.js";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
2
|
import { ImageResponse as ImageResponse$1 } from "@takumi-rs/image-response/wasm";
|
|
3
|
+
import wasmModule from "@takumi-rs/wasm/next";
|
|
5
4
|
import { Renderer, initSync } from "@takumi-rs/wasm/no-bundler";
|
|
6
5
|
|
|
7
6
|
//#region src/features/og/imageResponse.node.ts
|
|
@@ -14,12 +13,10 @@ import { Renderer, initSync } from "@takumi-rs/wasm/no-bundler";
|
|
|
14
13
|
* about which engine to use any more — it's only about *how* the wasm module
|
|
15
14
|
* gets loaded:
|
|
16
15
|
*
|
|
17
|
-
* - Here, we
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* once the package is externalised by Nitro/Vite — so we go through the
|
|
22
|
-
* `no-bundler` entry directly.
|
|
16
|
+
* - Here, we import the wasm module and `initSync` it ourselves before
|
|
17
|
+
* constructing a `Renderer`. The static `?module` import lets Nitro emit
|
|
18
|
+
* the asset into the deployment instead of relying on a runtime
|
|
19
|
+
* `require.resolve` that dependency tracing cannot reliably discover.
|
|
23
20
|
*
|
|
24
21
|
* - In `imageResponse.workerd.ts` there's no filesystem; instead we pass a
|
|
25
22
|
* `WebAssembly.Module` reference via `?module` import and let the
|
|
@@ -28,7 +25,12 @@ import { Renderer, initSync } from "@takumi-rs/wasm/no-bundler";
|
|
|
28
25
|
* We use the BYO-renderer path of `@takumi-rs/image-response/wasm` so the
|
|
29
26
|
* `module:` option isn't needed here — the renderer is already alive.
|
|
30
27
|
*/
|
|
31
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Resolve and initialise the wasm module once at module load. `initSync`
|
|
30
|
+
* compiles the wasm and wires up the JS bindings; subsequent `new Renderer()`
|
|
31
|
+
* calls are cheap.
|
|
32
|
+
*/
|
|
33
|
+
initSync({ module: wasmModule });
|
|
32
34
|
/**
|
|
33
35
|
* Module-scoped singleton — building the renderer compiles the wasm module
|
|
34
36
|
* and loads Geist; not free, and there's no reason to do it per request.
|
|
@@ -4,9 +4,10 @@ import { useIsAuthenticated, useProjectSlug } from "../../lib/auth.js";
|
|
|
4
4
|
import { getApiClient } from "../../lib/api-client.js";
|
|
5
5
|
import { NormalizedDataProvider, seedBlockCaches, usePageBlocks } from "../../lib/normalized-data.js";
|
|
6
6
|
import { BlockErrorBoundary } from "./components/BlockErrorBoundary.js";
|
|
7
|
-
import { blockQueries, pageQueries, projectQueries } from "../../lib/queries.js";
|
|
8
|
-
import { cn } from "../../lib/utils.js";
|
|
9
7
|
import { useCamoxApp } from "../provider/components/CamoxAppContext.js";
|
|
8
|
+
import { blockQueries } from "../../lib/queries.js";
|
|
9
|
+
import { usePageDestinations } from "../../hooks/use-page-destinations.js";
|
|
10
|
+
import { cn } from "../../lib/utils.js";
|
|
10
11
|
import { SharedChromeContext } from "../runtime/SharedChromeContext.js";
|
|
11
12
|
import { previewStore, selectIsEditMode, selectPreviewSource } from "./previewStore.js";
|
|
12
13
|
import { Navbar } from "../studio/components/Navbar.js";
|
|
@@ -18,7 +19,7 @@ import { PreviewPanel } from "./components/PreviewPanel.js";
|
|
|
18
19
|
import { PreviewToolbarSpacer } from "./components/PreviewToolbarSpacer.js";
|
|
19
20
|
import { RightSidebar } from "./components/RightSidebar.js";
|
|
20
21
|
import { c } from "react/compiler-runtime";
|
|
21
|
-
import {
|
|
22
|
+
import { useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
|
|
22
23
|
import * as React from "react";
|
|
23
24
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
24
25
|
import { useSelector } from "@xstate/store-react";
|
|
@@ -36,9 +37,9 @@ function getMobileStudioSnapshot() {
|
|
|
36
37
|
}
|
|
37
38
|
function useIsMobileStudio() {
|
|
38
39
|
const $ = c(1);
|
|
39
|
-
if ($[0] !== "
|
|
40
|
+
if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
|
|
40
41
|
for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
41
|
-
$[0] = "
|
|
42
|
+
$[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
|
|
42
43
|
}
|
|
43
44
|
return React.useSyncExternalStore(subscribeToMobileStudio, getMobileStudioSnapshot, _temp);
|
|
44
45
|
}
|
|
@@ -71,9 +72,9 @@ function pageStructureQueryFn(path, projectSlug, source) {
|
|
|
71
72
|
}
|
|
72
73
|
function usePreviewedPage() {
|
|
73
74
|
const $ = c(11);
|
|
74
|
-
if ($[0] !== "
|
|
75
|
+
if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
|
|
75
76
|
for (let $i = 0; $i < 11; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
76
|
-
$[0] = "
|
|
77
|
+
$[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
|
|
77
78
|
}
|
|
78
79
|
const { pathname } = useLocation();
|
|
79
80
|
const projectSlug = useProjectSlug();
|
|
@@ -109,9 +110,9 @@ function usePreviewedPage() {
|
|
|
109
110
|
}
|
|
110
111
|
const BlockRenderer = (t0) => {
|
|
111
112
|
const $ = c(23);
|
|
112
|
-
if ($[0] !== "
|
|
113
|
+
if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
|
|
113
114
|
for (let $i = 0; $i < 23; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
114
|
-
$[0] = "
|
|
115
|
+
$[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
|
|
115
116
|
}
|
|
116
117
|
const { blockId, mode, showAddBlockTop, showAddBlockBottom } = t0;
|
|
117
118
|
const previewSource = useSelector(previewStore, selectPreviewSource);
|
|
@@ -254,9 +255,9 @@ const PageContent = () => {
|
|
|
254
255
|
};
|
|
255
256
|
function useHydrateDraftCache() {
|
|
256
257
|
const $ = c(7);
|
|
257
|
-
if ($[0] !== "
|
|
258
|
+
if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
|
|
258
259
|
for (let $i = 0; $i < 7; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
259
|
-
$[0] = "
|
|
260
|
+
$[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
|
|
260
261
|
}
|
|
261
262
|
const isAuthenticated = useIsAuthenticated();
|
|
262
263
|
const queryClient = useQueryClient();
|
|
@@ -307,9 +308,9 @@ function useHydrateDraftCache() {
|
|
|
307
308
|
function _temp2() {}
|
|
308
309
|
const CamoxPreview = (t0) => {
|
|
309
310
|
const $ = c(4);
|
|
310
|
-
if ($[0] !== "
|
|
311
|
+
if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
|
|
311
312
|
for (let $i = 0; $i < 4; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
312
|
-
$[0] = "
|
|
313
|
+
$[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
|
|
313
314
|
}
|
|
314
315
|
const { children } = t0;
|
|
315
316
|
const pageData = usePreviewedPage();
|
|
@@ -329,9 +330,9 @@ const CamoxPreview = (t0) => {
|
|
|
329
330
|
/** Studio chrome is shared; only curated previews require a Camox page record. */
|
|
330
331
|
const PreviewShell = (t0) => {
|
|
331
332
|
const $ = c(59);
|
|
332
|
-
if ($[0] !== "
|
|
333
|
+
if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
|
|
333
334
|
for (let $i = 0; $i < 59; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
334
|
-
$[0] = "
|
|
335
|
+
$[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
|
|
335
336
|
}
|
|
336
337
|
const { children, pageData, hasLiveVersion: t1, derivedLayoutId, derivedLayout } = t0;
|
|
337
338
|
const hasLiveVersion = t1 === void 0 ? false : t1;
|
|
@@ -608,44 +609,19 @@ const PreviewShell = (t0) => {
|
|
|
608
609
|
return t21;
|
|
609
610
|
};
|
|
610
611
|
function usePreviewPagesActions() {
|
|
611
|
-
const $ = c(
|
|
612
|
-
if ($[0] !== "
|
|
613
|
-
for (let $i = 0; $i <
|
|
614
|
-
$[0] = "
|
|
612
|
+
const $ = c(6);
|
|
613
|
+
if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
|
|
614
|
+
for (let $i = 0; $i < 6; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
615
|
+
$[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
|
|
615
616
|
}
|
|
616
617
|
const navigate = useNavigate();
|
|
617
618
|
const { pathname } = useLocation();
|
|
618
|
-
const
|
|
619
|
+
const pages = usePageDestinations();
|
|
619
620
|
let t0;
|
|
620
|
-
if ($[1] !== projectSlug) {
|
|
621
|
-
t0 = projectQueries.getBySlug(projectSlug);
|
|
622
|
-
$[1] = projectSlug;
|
|
623
|
-
$[2] = t0;
|
|
624
|
-
} else t0 = $[2];
|
|
625
|
-
const { data: project } = useQuery(t0);
|
|
626
621
|
let t1;
|
|
627
|
-
if ($[3] !==
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
$[4] = t1;
|
|
631
|
-
} else t1 = $[4];
|
|
632
|
-
const t2 = !!project;
|
|
633
|
-
let t3;
|
|
634
|
-
if ($[5] !== t1 || $[6] !== t2) {
|
|
635
|
-
t3 = {
|
|
636
|
-
...t1,
|
|
637
|
-
enabled: t2
|
|
638
|
-
};
|
|
639
|
-
$[5] = t1;
|
|
640
|
-
$[6] = t2;
|
|
641
|
-
$[7] = t3;
|
|
642
|
-
} else t3 = $[7];
|
|
643
|
-
const { data: pages } = useQuery(t3);
|
|
644
|
-
let t4;
|
|
645
|
-
let t5;
|
|
646
|
-
if ($[8] !== navigate || $[9] !== pages || $[10] !== pathname) {
|
|
647
|
-
t4 = () => {
|
|
648
|
-
const currentPage = pages?.find((p) => p.fullPath === pathname);
|
|
622
|
+
if ($[1] !== navigate || $[2] !== pages || $[3] !== pathname) {
|
|
623
|
+
t0 = () => {
|
|
624
|
+
const currentPage = pages.find((p) => p.kind === "curated" && p.fullPath === pathname);
|
|
649
625
|
const actions = [
|
|
650
626
|
{
|
|
651
627
|
id: "create-page",
|
|
@@ -664,12 +640,12 @@ function usePreviewPagesActions() {
|
|
|
664
640
|
"Page metadata"
|
|
665
641
|
],
|
|
666
642
|
groupLabel: "Preview",
|
|
667
|
-
checkIfAvailable: () =>
|
|
643
|
+
checkIfAvailable: () => currentPage?.kind === "curated",
|
|
668
644
|
execute: () => {
|
|
669
|
-
if (
|
|
645
|
+
if (currentPage?.kind !== "curated") return;
|
|
670
646
|
previewStore.send({
|
|
671
647
|
type: "openEditPageModal",
|
|
672
|
-
pageId: currentPage.
|
|
648
|
+
pageId: currentPage.pageId
|
|
673
649
|
});
|
|
674
650
|
}
|
|
675
651
|
},
|
|
@@ -682,18 +658,19 @@ function usePreviewPagesActions() {
|
|
|
682
658
|
"Switch page"
|
|
683
659
|
],
|
|
684
660
|
groupLabel: "Preview",
|
|
685
|
-
checkIfAvailable: () =>
|
|
661
|
+
checkIfAvailable: () => pages.length > 0,
|
|
686
662
|
hasChildren: true,
|
|
687
663
|
execute: _temp13
|
|
688
664
|
},
|
|
689
|
-
...pages
|
|
690
|
-
id: `go-to-page-${page.
|
|
665
|
+
...pages.map((page) => ({
|
|
666
|
+
id: `go-to-page-${page.key}`,
|
|
691
667
|
parentActionId: "go-to-page",
|
|
692
|
-
label: `Go to "${page.
|
|
668
|
+
label: `Go to "${page.title}"`,
|
|
669
|
+
aliases: [page.fullPath],
|
|
693
670
|
groupLabel: "Preview",
|
|
694
671
|
checkIfAvailable: _temp14,
|
|
695
672
|
execute: () => navigate({ to: page.fullPath })
|
|
696
|
-
}))
|
|
673
|
+
}))
|
|
697
674
|
];
|
|
698
675
|
actionsStore.send({
|
|
699
676
|
type: "registerManyActions",
|
|
@@ -706,21 +683,21 @@ function usePreviewPagesActions() {
|
|
|
706
683
|
});
|
|
707
684
|
};
|
|
708
685
|
};
|
|
709
|
-
|
|
686
|
+
t1 = [
|
|
710
687
|
navigate,
|
|
711
688
|
pages,
|
|
712
689
|
pathname
|
|
713
690
|
];
|
|
714
|
-
$[
|
|
715
|
-
$[
|
|
716
|
-
$[
|
|
717
|
-
$[
|
|
718
|
-
$[
|
|
691
|
+
$[1] = navigate;
|
|
692
|
+
$[2] = pages;
|
|
693
|
+
$[3] = pathname;
|
|
694
|
+
$[4] = t0;
|
|
695
|
+
$[5] = t1;
|
|
719
696
|
} else {
|
|
720
|
-
|
|
721
|
-
|
|
697
|
+
t0 = $[4];
|
|
698
|
+
t1 = $[5];
|
|
722
699
|
}
|
|
723
|
-
React.useEffect(
|
|
700
|
+
React.useEffect(t0, t1);
|
|
724
701
|
}
|
|
725
702
|
function _temp15(a) {
|
|
726
703
|
return a.id;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useLocation } from "../../navigation/navigation.js";
|
|
2
2
|
import { useProjectSlug } from "../../../lib/auth.js";
|
|
3
3
|
import { usePageBlocks } from "../../../lib/normalized-data.js";
|
|
4
|
-
import { blockMutations, blockQueries, projectQueries } from "../../../lib/queries.js";
|
|
5
4
|
import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
|
|
5
|
+
import { blockMutations, blockQueries, projectQueries } from "../../../lib/queries.js";
|
|
6
6
|
import { previewStore } from "../previewStore.js";
|
|
7
7
|
import { useRequireDraftSource } from "../../../core/hooks/useRequireDraftSource.js";
|
|
8
8
|
import { BlockThumbnail } from "./BlockThumbnail.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { actionsStore } from "../../provider/actionsStore.js";
|
|
2
2
|
import { usePageBlocks } from "../../../lib/normalized-data.js";
|
|
3
|
+
import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
|
|
3
4
|
import { blockMutations, repeatableItemMutations } from "../../../lib/queries.js";
|
|
4
5
|
import { formatShortcut } from "../../../lib/utils.js";
|
|
5
|
-
import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
|
|
6
6
|
import { previewStore, selectionItemId } from "../previewStore.js";
|
|
7
7
|
import { useRequireDraftSource } from "../../../core/hooks/useRequireDraftSource.js";
|
|
8
8
|
import { useUpdateBlockPosition } from "./useUpdateBlockPosition.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useNavigate } from "../../navigation/navigation.js";
|
|
2
2
|
import { useProjectSlug } from "../../../lib/auth.js";
|
|
3
|
-
import { layoutQueries, pageMutations, pageQueries, projectQueries } from "../../../lib/queries.js";
|
|
4
3
|
import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
|
|
4
|
+
import { layoutQueries, pageMutations, pageQueries, projectQueries } from "../../../lib/queries.js";
|
|
5
5
|
import { previewStore } from "../previewStore.js";
|
|
6
6
|
import { PageLocationFieldset } from "./PageLocationFieldset.js";
|
|
7
7
|
import { PageNicknameField } from "./PageNicknameField.js";
|
|
@@ -26,9 +26,9 @@ const slugifyPathSegment = (nickname) => {
|
|
|
26
26
|
};
|
|
27
27
|
const CreatePageModal = () => {
|
|
28
28
|
const $ = c(59);
|
|
29
|
-
if ($[0] !== "
|
|
29
|
+
if ($[0] !== "7d9f627f2fd6df9193c55db2f9612514acd4807aab2e5cc3fbd5bdd5aaf23672") {
|
|
30
30
|
for (let $i = 0; $i < 59; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
31
|
-
$[0] = "
|
|
31
|
+
$[0] = "7d9f627f2fd6df9193c55db2f9612514acd4807aab2e5cc3fbd5bdd5aaf23672";
|
|
32
32
|
}
|
|
33
33
|
const projectSlug = useProjectSlug();
|
|
34
34
|
const open = useSelector(previewStore, _temp);
|
|
@@ -84,7 +84,7 @@ const CreatePageModal = () => {
|
|
|
84
84
|
const camoxApp = useCamoxApp();
|
|
85
85
|
let t8;
|
|
86
86
|
if ($[14] !== allLayouts || $[15] !== camoxApp) {
|
|
87
|
-
t8 = allLayouts?.filter((layout) => camoxApp.getLayoutById(layout.layoutId)?._internal.kind
|
|
87
|
+
t8 = allLayouts?.filter((layout) => camoxApp.getLayoutById(layout.layoutId)?._internal.kind === "curated");
|
|
88
88
|
$[14] = allLayouts;
|
|
89
89
|
$[15] = camoxApp;
|
|
90
90
|
$[16] = t8;
|