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.
Files changed (60) hide show
  1. package/dist/core/components/lexical/{GradientNode.js → HighlightNode.js} +34 -34
  2. package/dist/core/components/lexical/InlineLexicalEditor.js +14 -14
  3. package/dist/core/components/lexical/InlineStylesPlugin.js +6 -6
  4. package/dist/core/components/lexical/SelectionBroadcaster.js +5 -5
  5. package/dist/core/components/lexical/SidebarLexicalEditor.js +20 -20
  6. package/dist/core/components/lexical/TextLinkPopover.js +191 -208
  7. package/dist/core/components/lexical/editorConfig.js +2 -2
  8. package/dist/core/createApp.d.ts +3 -2
  9. package/dist/core/createApp.js +2 -1
  10. package/dist/core/createLayout.d.ts +16 -3
  11. package/dist/core/createLayout.js +15 -15
  12. package/dist/core/derivedRoutes.js +1 -1
  13. package/dist/core/dom.d.ts +17 -0
  14. package/dist/core/dom.js +22 -0
  15. package/dist/core/lib/lexicalReact.js +4 -4
  16. package/dist/core/lib/lexicalState.js +3 -3
  17. package/dist/core/lib/modifierFormats.js +1 -1
  18. package/dist/core/lib/textLinks.js +5 -2
  19. package/dist/core/lib/textStyles.d.ts +2 -2
  20. package/dist/core/lib/textStyles.js +6 -11
  21. package/dist/core/pageDestinations.js +37 -0
  22. package/dist/features/og/imageResponse.node.js +11 -9
  23. package/dist/features/preview/CamoxPreview.js +42 -65
  24. package/dist/features/preview/components/AddBlockSidebar.js +1 -1
  25. package/dist/features/preview/components/BlockActionsPopover.js +1 -1
  26. package/dist/features/preview/components/CreatePageModal.js +4 -4
  27. package/dist/features/preview/components/DerivedLayoutSidebar.js +45 -26
  28. package/dist/features/preview/components/DerivedPageInfoSidebar.js +38 -26
  29. package/dist/features/preview/components/FieldToolbar.js +7 -7
  30. package/dist/features/preview/components/LinkFieldEditor.js +212 -209
  31. package/dist/features/preview/components/PageEditorSidebar.js +1 -1
  32. package/dist/features/preview/components/PageInfoSidebar.js +28 -28
  33. package/dist/features/preview/components/PagePicker.js +16 -16
  34. package/dist/features/preview/components/PageTree.js +1 -1
  35. package/dist/features/preview/components/PublicationRow.js +8 -4
  36. package/dist/features/preview/components/useRepeatableItemActions.js +1 -1
  37. package/dist/features/preview/publication.js +10 -0
  38. package/dist/features/provider/CoreCamoxProvider.js +1 -1
  39. package/dist/features/runtime/runtime.js +20 -21
  40. package/dist/features/studio/components/EnvironmentMenu.js +3 -2
  41. package/dist/features/studio/components/Navbar.js +53 -80
  42. package/dist/features/vite/layoutGeneration.js +7 -3
  43. package/dist/features/vite/vite.js +5 -1
  44. package/dist/hooks/use-page-destinations.js +53 -0
  45. package/dist/lib/auth.js +11 -14
  46. package/dist/lib/server-auth-cookie.js +21 -0
  47. package/dist/studio.css +1 -1
  48. package/package.json +8 -4
  49. package/skills/camox/SKILL.md +32 -9
  50. package/skills/camox/references/block-definitions.md +84 -290
  51. package/skills/camox/references/cli-common.md +2 -4
  52. package/skills/camox/references/cli-content.md +147 -0
  53. package/skills/camox/references/cli-environments.md +1 -1
  54. package/skills/camox/references/dom-integrations.md +93 -0
  55. package/skills/camox/references/field-styling.md +50 -0
  56. package/skills/camox/references/layout-definitions.md +33 -147
  57. package/skills/camox/references/routed-layouts.md +71 -0
  58. package/skills/camoxify/SKILL.md +52 -0
  59. package/skills/camox/references/cli-blocks.md +0 -78
  60. 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] !== "2ae925f72331cad3d35d77334ec5712b5849211fd0dcab4e27af95282e583b7a") {
16
+ if ($[0] !== "776e504f06a16915ba8008212a5b0af4dec7762a3d0b05161ac1048bec619433") {
15
17
  for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
16
- $[0] = "2ae925f72331cad3d35d77334ec5712b5849211fd0dcab4e27af95282e583b7a";
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 !== "derived" && isLastBefore || void 0,
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] !== "2ae925f72331cad3d35d77334ec5712b5849211fd0dcab4e27af95282e583b7a") {
53
+ if ($[0] !== "776e504f06a16915ba8008212a5b0af4dec7762a3d0b05161ac1048bec619433") {
52
54
  for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
53
- $[0] = "2ae925f72331cad3d35d77334ec5712b5849211fd0dcab4e27af95282e583b7a";
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 !== "derived" && isFirstAfter || void 0,
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] !== "2ae925f72331cad3d35d77334ec5712b5849211fd0dcab4e27af95282e583b7a") {
90
+ if ($[0] !== "776e504f06a16915ba8008212a5b0af4dec7762a3d0b05161ac1048bec619433") {
89
91
  for (let $i = 0; $i < 7; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
90
- $[0] = "2ae925f72331cad3d35d77334ec5712b5849211fd0dcab4e27af95282e583b7a";
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
- if (options.kind === "derived" && options.blocks.initial) throw new Error("Derived layouts cannot define initial page blocks");
178
- return createLayoutDefinition({
179
- ...options,
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 === "derived").sort((a, b) => routeSegments(a._internal.id).filter((s) => s.startsWith("$")).length - routeSegments(b._internal.id).filter((s) => s.startsWith("$")).length);
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 };
@@ -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 { getGradientStyle, getTextAppearance } from "./textStyles.js";
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 === "gradient") return /* @__PURE__ */ jsx("span", {
27
- "data-camox-gradient": "",
28
- ...getGradientStyle(options),
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 === "gradient") return `<gradient>${serializeInlineChildren(node.children ?? [])}</gradient>`;
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" ? /^<(gradient|u|strong|em)>$/.exec(token.raw)?.[1] : void 0;
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 === "gradient") nodes.push(inlineElement("gradient", children));
224
+ if (tag === "highlight") nodes.push(inlineElement("highlight", children));
225
225
  else nodes.push(...children);
226
226
  i = end;
227
227
  continue;
@@ -4,7 +4,7 @@ const FORMAT_FLAGS = {
4
4
  bold: 1,
5
5
  italic: 2,
6
6
  underline: 8,
7
- gradient: 1 << 20
7
+ highlight: 1 << 20
8
8
  };
9
9
 
10
10
  //#endregion
@@ -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 isHttpTextLinkTarget(target) ? target : null;
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 gradient wrapper. Other flags are false for this call. */
10
- gradient: boolean;
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
- gradient: false,
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 defaultGradientStyle = {
25
- backgroundImage: "linear-gradient(to right, var(--camox-gradient-from, var(--chart-1, var(--primary, currentColor))), var(--camox-gradient-to, var(--chart-2, var(--muted-foreground, currentColor))))",
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
- gradient: true,
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
- ...defaultGradientStyle,
35
+ ...defaultHighlightStyle,
41
36
  ...custom?.style
42
37
  }
43
38
  };
44
39
  }
45
40
 
46
41
  //#endregion
47
- export { getGradientStyle, getTextAppearance };
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 read the `.wasm` file off disk and `initSync` it ourselves
18
- * before constructing a `Renderer`. `@takumi-rs/wasm` ships a "node"
19
- * bundler entry that purports to do this, but its source uses an
20
- * extensionless `import "../pkg/takumi_wasm"` which raw Node ESM rejects
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
- initSync({ module: readFileSync(createRequire(import.meta.url).resolve("@takumi-rs/wasm/takumi_wasm_bg.wasm")) });
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 { useQuery, useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
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] !== "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b") {
40
+ if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
40
41
  for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
41
- $[0] = "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b";
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] !== "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b") {
75
+ if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
75
76
  for (let $i = 0; $i < 11; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
76
- $[0] = "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b";
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] !== "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b") {
113
+ if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
113
114
  for (let $i = 0; $i < 23; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
114
- $[0] = "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b";
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] !== "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b") {
258
+ if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
258
259
  for (let $i = 0; $i < 7; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
259
- $[0] = "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b";
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] !== "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b") {
311
+ if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
311
312
  for (let $i = 0; $i < 4; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
312
- $[0] = "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b";
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] !== "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b") {
333
+ if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
333
334
  for (let $i = 0; $i < 59; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
334
- $[0] = "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b";
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(13);
612
- if ($[0] !== "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b") {
613
- for (let $i = 0; $i < 13; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
614
- $[0] = "c1ecb280688848a0300c65af5bc156d964441b9c769c2e406123217a6e83b30b";
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 projectSlug = useProjectSlug();
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] !== project?.id) {
628
- t1 = pageQueries.list(project?.id ?? 0);
629
- $[3] = project?.id;
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: () => !!currentPage,
643
+ checkIfAvailable: () => currentPage?.kind === "curated",
668
644
  execute: () => {
669
- if (!currentPage) return;
645
+ if (currentPage?.kind !== "curated") return;
670
646
  previewStore.send({
671
647
  type: "openEditPageModal",
672
- pageId: currentPage.id
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: () => !!pages,
661
+ checkIfAvailable: () => pages.length > 0,
686
662
  hasChildren: true,
687
663
  execute: _temp13
688
664
  },
689
- ...pages ? pages.map((page) => ({
690
- id: `go-to-page-${page.id}`,
665
+ ...pages.map((page) => ({
666
+ id: `go-to-page-${page.key}`,
691
667
  parentActionId: "go-to-page",
692
- label: `Go to "${page.nickname}"`,
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
- t5 = [
686
+ t1 = [
710
687
  navigate,
711
688
  pages,
712
689
  pathname
713
690
  ];
714
- $[8] = navigate;
715
- $[9] = pages;
716
- $[10] = pathname;
717
- $[11] = t4;
718
- $[12] = t5;
691
+ $[1] = navigate;
692
+ $[2] = pages;
693
+ $[3] = pathname;
694
+ $[4] = t0;
695
+ $[5] = t1;
719
696
  } else {
720
- t4 = $[11];
721
- t5 = $[12];
697
+ t0 = $[4];
698
+ t1 = $[5];
722
699
  }
723
- React.useEffect(t4, t5);
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] !== "ca72d8f393684234f7d5819b751bb6885d41445b1c76ee71638b787efcf67eb9") {
29
+ if ($[0] !== "7d9f627f2fd6df9193c55db2f9612514acd4807aab2e5cc3fbd5bdd5aaf23672") {
30
30
  for (let $i = 0; $i < 59; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
31
- $[0] = "ca72d8f393684234f7d5819b751bb6885d41445b1c76ee71638b787efcf67eb9";
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 !== "derived");
87
+ t8 = allLayouts?.filter((layout) => camoxApp.getLayoutById(layout.layoutId)?._internal.kind === "curated");
88
88
  $[14] = allLayouts;
89
89
  $[15] = camoxApp;
90
90
  $[16] = t8;