camox 0.48.0 → 0.52.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.
Files changed (127) hide show
  1. package/dist/core/createApp.d.ts +1 -0
  2. package/dist/core/createApp.js +1 -0
  3. package/dist/core/editing/contentEdits.js +78 -0
  4. package/dist/core/editing/createEditableBlock.js +277 -311
  5. package/dist/core/layoutContext.d.ts +1 -0
  6. package/dist/core/lib/contentType.js +2 -2
  7. package/dist/core/recordItem.js +3 -3
  8. package/dist/features/canvas/CamoxCanvas.js +15 -15
  9. package/dist/features/canvas/CanvasLoadingScreen.js +15 -11
  10. package/dist/features/canvas/CanvasPageFrame.js +81 -87
  11. package/dist/features/canvas/CanvasPreviewPageSlot.js +1 -1
  12. package/dist/features/canvas/DerivedPagePathInput.js +12 -12
  13. package/dist/features/canvas/canvasOverlayGeometry.js +1 -1
  14. package/dist/features/canvas/canvasStore.js +2 -2
  15. package/dist/features/canvas/sidebar/CanvasInspector.js +1 -1
  16. package/dist/features/canvas/sidebar/CuratedPageInspector.js +1 -1
  17. package/dist/features/canvas/sidebar/LayoutPageBlocks.js +23 -31
  18. package/dist/features/canvas/useCanvasCamera.js +1 -1
  19. package/dist/features/canvas/useDiscoveredPreviewPaths.js +16 -9
  20. package/dist/features/content/ContentAssets.js +84 -88
  21. package/dist/features/page/CuratedPageContent.js +1 -1
  22. package/dist/features/preview/CamoxPreview.d.ts +8 -4
  23. package/dist/features/preview/CamoxPreview.js +258 -443
  24. package/dist/features/preview/EditablePageContent.js +244 -2
  25. package/dist/features/preview/EditablePageExperience.js +19 -13
  26. package/dist/features/preview/components/AddBlockSheet.js +55 -15
  27. package/dist/features/preview/components/BlockActionsPopover.js +23 -51
  28. package/dist/features/preview/components/BlockPeek.js +66 -0
  29. package/dist/features/preview/components/BlockThumbnail.js +134 -119
  30. package/dist/features/preview/components/CanvasPreview.js +1 -1
  31. package/dist/features/preview/components/CreatePageModal.js +150 -156
  32. package/dist/features/preview/components/FieldToolbar.js +1 -1
  33. package/dist/features/preview/components/Frame.js +27 -4
  34. package/dist/features/preview/components/MobilePreviewDrawer.js +6 -9
  35. package/dist/features/preview/components/PageInfo.js +161 -126
  36. package/dist/features/preview/components/PagePicker.js +2 -2
  37. package/dist/features/preview/components/PageTree.js +174 -190
  38. package/dist/features/preview/components/PreviewPanel.js +13 -67
  39. package/dist/features/preview/components/PreviewToolbar.js +1 -1
  40. package/dist/features/preview/components/ReferenceFieldEditor.js +4 -4
  41. package/dist/features/preview/components/ReferenceListFieldEditor.js +4 -4
  42. package/dist/features/preview/components/RemovedBlockPlaceholder.js +37 -70
  43. package/dist/features/preview/components/RepeatableItemsList.js +1 -1
  44. package/dist/features/preview/components/SelectionEditor.js +248 -256
  45. package/dist/features/preview/components/StudioEditingFallback.js +22 -26
  46. package/dist/features/preview/components/useFieldWriter.js +19 -19
  47. package/dist/features/preview/components/useRecordView.js +105 -147
  48. package/dist/features/preview/components/useRepeatableItemActions.js +0 -2
  49. package/dist/features/preview/pageRecord.js +30 -24
  50. package/dist/features/preview/previewConstants.js +2 -8
  51. package/dist/features/preview/previewStore.js +2 -0
  52. package/dist/features/preview/studioNotice.js +20 -0
  53. package/dist/features/preview/usePreviewViewportActions.js +1 -1
  54. package/dist/features/provider/AuthenticatedCamoxProvider.js +47 -31
  55. package/dist/features/provider/components/CommandPalette.js +2 -5
  56. package/dist/features/provider/signInShortcut.js +1 -2
  57. package/dist/features/provider/useAdminShortcuts.js +47 -53
  58. package/dist/features/renderer/RendererApp.js +542 -0
  59. package/dist/features/renderer/RendererFrames.js +450 -0
  60. package/dist/features/renderer/definitionAnswers.js +26 -0
  61. package/dist/features/renderer/protocol.js +35 -0
  62. package/dist/features/renderer/rendererHost.js +249 -0
  63. package/dist/features/renderer/studioConnection.js +186 -0
  64. package/dist/features/routes/pageRuntime.d.ts +2 -1
  65. package/dist/features/routes/pageRuntime.js +34 -22
  66. package/dist/features/runtime/RuntimeChrome.js +2 -5
  67. package/dist/features/runtime/assetPrefix.js +14 -0
  68. package/dist/features/runtime/breadcrumbs.js +1 -1
  69. package/dist/features/runtime/editingFallback.js +4 -8
  70. package/dist/features/runtime/livePages.js +1 -1
  71. package/dist/features/runtime/pageApp.js +57 -83
  72. package/dist/features/runtime/pageClient.js +1 -1
  73. package/dist/features/runtime/pageNavigation.js +3 -2
  74. package/dist/features/runtime/publicCache.js +95 -0
  75. package/dist/features/runtime/publishingDraft.js +23 -0
  76. package/dist/features/runtime/rendererClient.d.ts +8 -0
  77. package/dist/features/runtime/rendererClient.js +77 -0
  78. package/dist/features/runtime/runtime.d.ts +22 -3
  79. package/dist/features/runtime/runtime.js +209 -96
  80. package/dist/features/runtime/runtimeRoutes.d.ts +2 -0
  81. package/dist/features/runtime/runtimeRoutes.js +2 -0
  82. package/dist/features/runtime/worker.d.ts +14 -1
  83. package/dist/features/runtime/worker.js +34 -4
  84. package/dist/features/settings/AnalyticsSettings.js +622 -0
  85. package/dist/features/settings/CamoxSettings.js +95 -0
  86. package/dist/features/settings/FaviconSettings.js +254 -0
  87. package/dist/features/settings/ProjectNameSettings.js +145 -0
  88. package/dist/features/settings/SettingsPart.js +73 -0
  89. package/dist/features/settings/SocialProfilesSettings.js +245 -0
  90. package/dist/features/settings/useProjectMutation.js +61 -0
  91. package/dist/features/studio/FollowAgentProvider.js +10 -10
  92. package/dist/features/studio/components/DraftsControl.js +136 -131
  93. package/dist/features/studio/components/LocalePicker.js +178 -174
  94. package/dist/features/studio/components/Navbar.js +107 -66
  95. package/dist/features/studio/components/ProjectMenu.js +119 -171
  96. package/dist/features/studio/components/ReviewDraftSheet.js +1151 -991
  97. package/dist/features/studio/components/ThreadMessages.js +100 -65
  98. package/dist/features/studio/components/UserButton.js +2 -2
  99. package/dist/features/studio/routes.js +3 -1
  100. package/dist/features/studio/showInCanvas.js +129 -0
  101. package/dist/features/vite/definitionsSync.js +5 -6
  102. package/dist/features/vite/hostedChecks.js +127 -0
  103. package/dist/features/vite/runtimeDev.js +58 -17
  104. package/dist/features/vite/staticAssetHeaders.js +52 -0
  105. package/dist/features/vite/vite.d.ts +1 -1
  106. package/dist/features/vite/vite.js +49 -9
  107. package/dist/hooks/use-page-destinations.js +10 -10
  108. package/dist/lib/api-client-server.d.ts +1 -1
  109. package/dist/lib/api-client.d.ts +2 -1
  110. package/dist/lib/draft-scope.d.ts +1 -0
  111. package/dist/lib/locale-path.d.ts +3 -11
  112. package/dist/lib/locale-path.js +3 -27
  113. package/dist/lib/queries.js +7 -1
  114. package/dist/lib/revisions.js +20 -0
  115. package/dist/lib/shortcuts.js +29 -0
  116. package/dist/lib/studio-definitions.js +160 -0
  117. package/dist/lib/studio-reads.d.ts +1 -0
  118. package/dist/lib/studio-reads.js +65 -21
  119. package/dist/lib/use-project-room.js +16 -10
  120. package/dist/lib/utils.js +1 -104
  121. package/dist/package.js +1 -1
  122. package/dist/studio.css +1 -1
  123. package/package.json +9 -4
  124. package/skills/camox/SKILL.md +4 -0
  125. package/skills/camox/references/artifacts.md +1 -1
  126. package/dist/features/studio/components/FaviconDialog.js +0 -318
  127. package/dist/features/studio/components/SocialProfilesDialog.js +0 -342
@@ -1,3 +1,4 @@
1
+ import "../lib/locale-path.js";
1
2
  //#region src/core/layoutContext.d.ts
2
3
  /**
3
4
  * The context every layout `to*` option receives. Each name always means the same thing and is
@@ -6,7 +6,7 @@ import { uuidv7JsonSchema } from "@camox/api-contract/ids";
6
6
  //#region src/core/lib/contentType.ts
7
7
  /** A collection's content field named `key`, if it has one. */
8
8
  function collectionField(collection, key) {
9
- const properties = collection?._internal.contentSchema.properties;
9
+ const properties = collection?.contentSchema.properties;
10
10
  return properties && Object.hasOwn(properties, key) ? properties[key] : void 0;
11
11
  }
12
12
  var FieldToken = class {
@@ -232,7 +232,7 @@ function _fileList(options) {
232
232
  * included); definition sync applies the same rules.
233
233
  */
234
234
  function validateQuery(query, collection) {
235
- const problem = referenceQueryProblem(query, (key) => collectionField(collection, key)?.fieldType);
235
+ const problem = referenceQueryProblem(query, (key) => collectionField(collection._internal, key)?.fieldType);
236
236
  if (problem) throw new Error(`Query on "${collection._internal.id}": ${problem}`);
237
237
  return query;
238
238
  }
@@ -56,12 +56,12 @@ function recordPageValues(collection, { data: record, published }) {
56
56
  * A record's title and description: its collection's templates filled with its fields' plain
57
57
  * text, as the API fills them. For records edited here, before the API names them again.
58
58
  */
59
- function recordText$1(collection, content) {
60
- if (!collection) return {
59
+ function recordText$1(templates, content) {
60
+ if (!templates) return {
61
61
  title: "",
62
62
  description: null
63
63
  };
64
- return recordText(collection._internal, (name) => fieldPlainText(content[name]));
64
+ return recordText(templates, (name) => fieldPlainText(content[name]));
65
65
  }
66
66
  /**
67
67
  * The first field a collection's title template names, such as `firstName` in
@@ -3,17 +3,18 @@ import { parseLocalePath } from "../../lib/locale-path.js";
3
3
  import { useOptionalDraftScope } from "../../lib/draft-scope.js";
4
4
  import { useViewLocale } from "../../lib/view-locale-context.js";
5
5
  import { NavigationProvider, useLocation, useNavigate } from "../navigation/navigation.js";
6
- import { useCamoxApp } from "../provider/components/CamoxAppContext.js";
7
6
  import { reads, useReadQuery, useStudioCache } from "../../lib/studio-reads.js";
8
7
  import { pageMutations } from "../../lib/queries.js";
8
+ import { useRoutableLayouts } from "../../lib/studio-definitions.js";
9
9
  import { useLocalizedPath } from "../../lib/view-locale.js";
10
10
  import { canvasStore } from "./canvasStore.js";
11
- import { STUDIO_CANVAS_PATH } from "../studio/routes.js";
12
11
  import { previewStore } from "../preview/previewStore.js";
12
+ import { CanvasWorkspaceContext } from "./canvasZoom.js";
13
+ import { useRendererHost } from "../renderer/RendererFrames.js";
14
+ import { STUDIO_CANVAS_PATH } from "../studio/routes.js";
13
15
  import { PREVIEW_PAGE_SLOT_ATTRIBUTE, PreviewPageFrameContext } from "../preview/previewPageFrame.js";
14
16
  import { PreviewPreparationContext } from "../preview/previewPreparation.js";
15
17
  import { canvasBlockOverlap } from "./canvasFrameDocument.js";
16
- import { CanvasWorkspaceContext } from "./canvasZoom.js";
17
18
  import { PageRecordContext, getPageRecord } from "../preview/pageRecord.js";
18
19
  import { CuratedBlockShortcuts } from "../preview/components/PreviewPanel.js";
19
20
  import { FollowAgentContext } from "../studio/followAgentContext.js";
@@ -707,12 +708,13 @@ function useRenamePage() {
707
708
  }
708
709
  /**
709
710
  * The still images of a workspace's Pages, where the browser draws them faithfully. They refresh
710
- * while the camera is still, and all go stale when the website's code changes.
711
+ * while the camera is still, and all go stale when the website's code changes: each time another
712
+ * renderer document connects, for a new revision or another draft.
711
713
  */
712
714
  function useWorkspaceThumbnails(workspaceKey) {
713
715
  const $ = c(13);
714
716
  const queryClient = useQueryClient();
715
- const app = useCamoxApp();
717
+ const renderer = useRendererHost();
716
718
  let t0;
717
719
  if ($[0] !== queryClient) {
718
720
  t0 = () => canvasThumbnailsSupported() ? createCanvasThumbnails(queryClient) : null;
@@ -753,17 +755,15 @@ function useWorkspaceThumbnails(workspaceKey) {
753
755
  t4 = $[8];
754
756
  }
755
757
  React.useEffect(t3, t4);
756
- const previousApp = React.useRef(app);
757
758
  let t5;
758
759
  let t6;
759
- if ($[9] !== app || $[10] !== thumbnails) {
760
+ if ($[9] !== renderer || $[10] !== thumbnails) {
760
761
  t5 = () => {
761
- if (previousApp.current === app) return;
762
- previousApp.current = app;
763
- thumbnails?.markAllStale();
762
+ if (!renderer || !thumbnails) return;
763
+ return renderer.subscribe(() => thumbnails.markAllStale());
764
764
  };
765
- t6 = [app, thumbnails];
766
- $[9] = app;
765
+ t6 = [renderer, thumbnails];
766
+ $[9] = renderer;
767
767
  $[10] = thumbnails;
768
768
  $[11] = t5;
769
769
  $[12] = t6;
@@ -1084,7 +1084,7 @@ function CanvasWorkspace(t0) {
1084
1084
  function CamoxCanvas(t0) {
1085
1085
  const $ = c(68);
1086
1086
  const { runtimeBasePath } = t0;
1087
- const app = useCamoxApp();
1087
+ const layouts = useRoutableLayouts();
1088
1088
  const renamePage = useRenamePage();
1089
1089
  const location = useLocation();
1090
1090
  const viewportMode = useSelector(previewStore, _temp3);
@@ -1142,7 +1142,7 @@ function CamoxCanvas(t0) {
1142
1142
  const pages = useReadQuery(t5, t7);
1143
1143
  const discoveredPaths = useDiscoveredPreviewPaths(runtimeBasePath);
1144
1144
  const viewLocale = useViewLocale();
1145
- const canvasPages = pages.data ? getCanvasPages(pages.data, app.getLayouts(), discoveredPaths, viewLocale.locale) : [];
1145
+ const canvasPages = pages.data ? getCanvasPages(pages.data, layouts, discoveredPaths, viewLocale.locale) : [];
1146
1146
  let t8;
1147
1147
  if ($[11] !== viewLocale.locales) {
1148
1148
  t8 = (runtimePath) => parseLocalePath(runtimePath, viewLocale.locales).path === STUDIO_CANVAS_PATH;
@@ -1150,7 +1150,7 @@ function CamoxCanvas(t0) {
1150
1150
  $[12] = t8;
1151
1151
  } else t8 = $[12];
1152
1152
  const isCanvasPath = t8;
1153
- const pageAt = (runtimePath_0) => isCanvasPath(runtimePath_0) ? void 0 : selectedCanvasPage(canvasPages, app.getLayouts(), runtimePath_0, viewLocale.locales);
1153
+ const pageAt = (runtimePath_0) => isCanvasPath(runtimePath_0) ? void 0 : selectedCanvasPage(canvasPages, layouts, runtimePath_0, viewLocale.locales);
1154
1154
  const selectedPage = pageAt(location.pathname);
1155
1155
  const previewedPath = React.use(PreviewPageFrameContext)?.pathname;
1156
1156
  const previewedPage = previewedPath ? pageAt(previewedPath) : void 0;
@@ -9,25 +9,29 @@ import { Spinner } from "@camox/ui/spinner";
9
9
  * center shows the Canvas is loading.
10
10
  */
11
11
  function CanvasLoadingScreen(t0) {
12
- const $ = c(4);
13
- const { spinner: t1 } = t0;
12
+ const $ = c(5);
13
+ const { spinner: t1, label } = t0;
14
14
  const spinner = t1 === void 0 ? true : t1;
15
15
  let t2;
16
- if ($[0] !== spinner) {
17
- t2 = spinner && /* @__PURE__ */ jsx(Spinner, { className: "text-muted-foreground size-6" });
18
- $[0] = spinner;
19
- $[1] = t2;
20
- } else t2 = $[1];
16
+ if ($[0] !== label || $[1] !== spinner) {
17
+ t2 = spinner && /* @__PURE__ */ jsx(Spinner, {
18
+ className: "text-muted-foreground size-6",
19
+ "aria-label": label
20
+ });
21
+ $[0] = label;
22
+ $[1] = spinner;
23
+ $[2] = t2;
24
+ } else t2 = $[2];
21
25
  let t3;
22
- if ($[2] !== t2) {
26
+ if ($[3] !== t2) {
23
27
  t3 = /* @__PURE__ */ jsx("div", {
24
28
  "data-canvas-loading": true,
25
29
  className: "bg-muted absolute inset-0 grid place-items-center",
26
30
  children: t2
27
31
  });
28
- $[2] = t2;
29
- $[3] = t3;
30
- } else t3 = $[3];
32
+ $[3] = t2;
33
+ $[4] = t3;
34
+ } else t3 = $[4];
31
35
  return t3;
32
36
  }
33
37
 
@@ -1,17 +1,14 @@
1
- import { useCamoxApp } from "../provider/components/CamoxAppContext.js";
2
1
  import { ArtifactsRunContext } from "../../core/hooks/useArtifactHost.js";
3
- import { DerivedPageContent } from "../page/DerivedPageContent.js";
2
+ import { EditableSurfaceContext } from "../../core/hooks/useIsEditable.js";
3
+ import { PreviewEditingOwnerContext } from "../preview/previewSelection.js";
4
+ import { RendererSlot, useRendererHost } from "../renderer/RendererFrames.js";
4
5
  import { useEditingFrameClaim, useEditingOwner } from "../preview/editingFrame.js";
5
6
  import { PreviewDocumentContext } from "../runtime/PreviewDocumentContext.js";
6
7
  import { PreviewPreparationContext } from "../preview/previewPreparation.js";
7
- import { EditableSurfaceContext } from "../../core/hooks/useIsEditable.js";
8
8
  import { canvasPageHref, measureCanvasDocument } from "./canvasFrameDocument.js";
9
- import { PreviewEditingOwnerContext } from "../preview/previewSelection.js";
10
9
  import { Overlays } from "../preview/components/Overlays.js";
11
10
  import { PreviewFrameEffects } from "../preview/components/PreviewPanel.js";
12
- import { PageContent } from "../preview/CamoxPreview.js";
13
11
  import { CanvasOverlays } from "./CanvasOverlays.js";
14
- import "../preview/EditablePageContent.js";
15
12
  import { useFrameSettled } from "./canvasThumbnails.js";
16
13
  import { CanvasFrameProviders, preventLinkNavigation, useCanvasFrame } from "./useCanvasFrame.js";
17
14
  import { c } from "react/compiler-runtime";
@@ -69,8 +66,8 @@ function PageContentCommitted(t0) {
69
66
  return null;
70
67
  }
71
68
  /**
72
- * Parent owns /_camox/data loading and the per-card error boundary. Documents are
73
- * isolated, but their cache and editing runtime are shared with the studio.
69
+ * Parent owns /_camox/data loading and the per-card error boundary. The studio keeps the frame's
70
+ * document, overlays and editing; the renderer frame renders the page into its slot.
74
71
  */
75
72
  function CanvasPageFrame(props) {
76
73
  const $ = c(2);
@@ -83,12 +80,11 @@ function CanvasPageFrame(props) {
83
80
  return t0;
84
81
  }
85
82
  function PageFrame(t0) {
86
- const $ = c(67);
83
+ const $ = c(69);
87
84
  const { input, width, viewportHeight, pageId, selected: t1, hovered: t2, mode: t3, onActivate, onSettled } = t0;
88
85
  const selected = t1 === void 0 ? false : t1;
89
86
  const hovered = t2 === void 0 ? false : t2;
90
87
  const mode = t3 === void 0 ? "live" : t3;
91
- const camoxApp = useCamoxApp();
92
88
  let t4;
93
89
  if ($[0] !== input) {
94
90
  t4 = canvasPageHref(input);
@@ -127,6 +123,8 @@ function PageFrame(t0) {
127
123
  const { iframeRef, iframe, mount, iframeProps } = useCanvasFrame(t7);
128
124
  const claim = useEditingFrameClaim(iframe, owner);
129
125
  const [committed, setCommitted] = React.useState(false);
126
+ const renderer = useRendererHost();
127
+ const [rendered, setRendered] = React.useState(false);
130
128
  useFrameSettled(committed ? iframe : null, mount, onSettled);
131
129
  let t8;
132
130
  if ($[11] !== claim || $[12] !== onActivate || $[13] !== owner) {
@@ -206,61 +204,57 @@ function PageFrame(t0) {
206
204
  $[33] = t17;
207
205
  } else t17 = $[33];
208
206
  let t18;
209
- if ($[34] !== activate || $[35] !== camoxApp || $[36] !== iframe || $[37] !== iframeRef || $[38] !== input.derived || $[39] !== mode || $[40] !== mount || $[41] !== owner || $[42] !== selected || $[43] !== viewportHeight) {
210
- t18 = mount && createPortal(/* @__PURE__ */ jsx(React.Activity, {
211
- mode: mode === "resting" ? "hidden" : "visible",
212
- children: /* @__PURE__ */ jsx(React.Suspense, {
213
- fallback: /* @__PURE__ */ jsx("div", {
214
- role: "status",
215
- children: "Loading page…"
216
- }),
217
- children: /* @__PURE__ */ jsx(ArtifactsRunContext, {
218
- value: selected,
219
- children: /* @__PURE__ */ jsx(EditableSurfaceContext, {
220
- value: selected,
221
- children: /* @__PURE__ */ jsxs("div", {
222
- style: { display: "contents" },
223
- onPointerDownCapture: activate,
224
- onFocusCapture: activate,
225
- onClickCapture: activate,
226
- onClick: preventLinkNavigation,
227
- children: [
228
- input.derived ? /* @__PURE__ */ jsx(DerivedPageContent, {
229
- camoxApp,
230
- derived: input.derived
231
- }) : /* @__PURE__ */ jsx(PageContent, {}),
232
- /* @__PURE__ */ jsx(PreviewFrameEffects, {}),
233
- /* @__PURE__ */ jsx(Overlays, {
234
- frame: iframe,
235
- owner,
236
- canAddBlocks: owner?.kind === "page"
237
- }),
238
- /* @__PURE__ */ jsx(PageContentCommitted, {
239
- selected,
240
- frame: iframeRef,
241
- viewportHeight,
242
- onCommitted: () => setCommitted(true)
243
- })
244
- ]
207
+ if ($[34] !== activate || $[35] !== iframe || $[36] !== iframeRef || $[37] !== input.derived?.layoutId || $[38] !== input.pathname || $[39] !== mode || $[40] !== mount || $[41] !== owner || $[42] !== rendered || $[43] !== renderer || $[44] !== selected || $[45] !== viewportHeight) {
208
+ t18 = mount && renderer && createPortal(/* @__PURE__ */ jsx(ArtifactsRunContext, {
209
+ value: selected,
210
+ children: /* @__PURE__ */ jsx(EditableSurfaceContext, {
211
+ value: selected,
212
+ children: /* @__PURE__ */ jsxs("div", {
213
+ style: { display: "contents" },
214
+ onPointerDownCapture: activate,
215
+ onFocusCapture: activate,
216
+ onClickCapture: activate,
217
+ onClick: preventLinkNavigation,
218
+ children: [
219
+ /* @__PURE__ */ jsx(RendererSlot, {
220
+ pathname: input.pathname,
221
+ derivedLayoutId: input.derived?.layoutId,
222
+ resting: mode === "resting",
223
+ onRendered: () => setRendered(true),
224
+ onFailed: () => setRendered(true)
225
+ }),
226
+ /* @__PURE__ */ jsx(PreviewFrameEffects, {}),
227
+ /* @__PURE__ */ jsx(Overlays, {
228
+ frame: iframe,
229
+ owner,
230
+ canAddBlocks: owner?.kind === "page"
231
+ }),
232
+ rendered && /* @__PURE__ */ jsx(PageContentCommitted, {
233
+ selected,
234
+ frame: iframeRef,
235
+ viewportHeight,
236
+ onCommitted: () => setCommitted(true)
245
237
  })
246
- })
238
+ ]
247
239
  })
248
240
  })
249
241
  }), mount);
250
242
  $[34] = activate;
251
- $[35] = camoxApp;
252
- $[36] = iframe;
253
- $[37] = iframeRef;
254
- $[38] = input.derived;
243
+ $[35] = iframe;
244
+ $[36] = iframeRef;
245
+ $[37] = input.derived?.layoutId;
246
+ $[38] = input.pathname;
255
247
  $[39] = mode;
256
248
  $[40] = mount;
257
249
  $[41] = owner;
258
- $[42] = selected;
259
- $[43] = viewportHeight;
260
- $[44] = t18;
261
- } else t18 = $[44];
250
+ $[42] = rendered;
251
+ $[43] = renderer;
252
+ $[44] = selected;
253
+ $[45] = viewportHeight;
254
+ $[46] = t18;
255
+ } else t18 = $[46];
262
256
  let t19;
263
- if ($[45] !== activate || $[46] !== hovered || $[47] !== t14 || $[48] !== t15 || $[49] !== t17 || $[50] !== t18) {
257
+ if ($[47] !== activate || $[48] !== hovered || $[49] !== t14 || $[50] !== t15 || $[51] !== t17 || $[52] !== t18) {
264
258
  t19 = /* @__PURE__ */ jsxs(CanvasOverlays, {
265
259
  document: t14,
266
260
  activate,
@@ -272,26 +266,26 @@ function PageFrame(t0) {
272
266
  t18
273
267
  ]
274
268
  });
275
- $[45] = activate;
276
- $[46] = hovered;
277
- $[47] = t14;
278
- $[48] = t15;
279
- $[49] = t17;
280
- $[50] = t18;
281
- $[51] = t19;
282
- } else t19 = $[51];
269
+ $[47] = activate;
270
+ $[48] = hovered;
271
+ $[49] = t14;
272
+ $[50] = t15;
273
+ $[51] = t17;
274
+ $[52] = t18;
275
+ $[53] = t19;
276
+ } else t19 = $[53];
283
277
  let t20;
284
- if ($[52] !== input.previewDocument || $[53] !== t19) {
278
+ if ($[54] !== input.previewDocument || $[55] !== t19) {
285
279
  t20 = /* @__PURE__ */ jsx(PreviewDocumentContext.Provider, {
286
280
  value: input.previewDocument,
287
281
  children: t19
288
282
  });
289
- $[52] = input.previewDocument;
290
- $[53] = t19;
291
- $[54] = t20;
292
- } else t20 = $[54];
283
+ $[54] = input.previewDocument;
284
+ $[55] = t19;
285
+ $[56] = t20;
286
+ } else t20 = $[56];
293
287
  let t21;
294
- if ($[55] !== href || $[56] !== iframe || $[57] !== input.pathname || $[58] !== mount || $[59] !== t20) {
288
+ if ($[57] !== href || $[58] !== iframe || $[59] !== input.pathname || $[60] !== mount || $[61] !== t20) {
295
289
  t21 = /* @__PURE__ */ jsx(CanvasFrameProviders, {
296
290
  pathname: input.pathname,
297
291
  href,
@@ -299,33 +293,33 @@ function PageFrame(t0) {
299
293
  iframe,
300
294
  children: t20
301
295
  });
302
- $[55] = href;
303
- $[56] = iframe;
304
- $[57] = input.pathname;
305
- $[58] = mount;
306
- $[59] = t20;
307
- $[60] = t21;
308
- } else t21 = $[60];
296
+ $[57] = href;
297
+ $[58] = iframe;
298
+ $[59] = input.pathname;
299
+ $[60] = mount;
300
+ $[61] = t20;
301
+ $[62] = t21;
302
+ } else t21 = $[62];
309
303
  let t22;
310
- if ($[61] !== t13 || $[62] !== t21) {
304
+ if ($[63] !== t13 || $[64] !== t21) {
311
305
  t22 = /* @__PURE__ */ jsx(HydrationBoundary, {
312
306
  state: t13,
313
307
  children: t21
314
308
  });
315
- $[61] = t13;
316
- $[62] = t21;
317
- $[63] = t22;
318
- } else t22 = $[63];
309
+ $[63] = t13;
310
+ $[64] = t21;
311
+ $[65] = t22;
312
+ } else t22 = $[65];
319
313
  let t23;
320
- if ($[64] !== owner || $[65] !== t22) {
314
+ if ($[66] !== owner || $[67] !== t22) {
321
315
  t23 = /* @__PURE__ */ jsx(PreviewEditingOwnerContext, {
322
316
  value: owner,
323
317
  children: t22
324
318
  });
325
- $[64] = owner;
326
- $[65] = t22;
327
- $[66] = t23;
328
- } else t23 = $[66];
319
+ $[66] = owner;
320
+ $[67] = t22;
321
+ $[68] = t23;
322
+ } else t23 = $[68];
329
323
  return t23;
330
324
  }
331
325
 
@@ -1,8 +1,8 @@
1
+ import { CanvasWorkspaceContext } from "./canvasZoom.js";
1
2
  import { useEditingFrameClaim, useEditingOwner } from "../preview/editingFrame.js";
2
3
  import { ViewportContinuityContext } from "../preview/viewportContinuity.js";
3
4
  import { usePreviewPageFrame } from "../preview/previewPageFrame.js";
4
5
  import { PreviewPreparationContext } from "../preview/previewPreparation.js";
5
- import { CanvasWorkspaceContext } from "./canvasZoom.js";
6
6
  import { useCanvasFrameMode } from "./canvasFrameMode.js";
7
7
  import { CanvasOverlays } from "./CanvasOverlays.js";
8
8
  import { CanvasPageEdge } from "./CanvasPageEdge.js";
@@ -1,6 +1,6 @@
1
1
  import { parseLocalePath } from "../../lib/locale-path.js";
2
2
  import { useViewLocale } from "../../lib/view-locale-context.js";
3
- import { useCamoxApp } from "../provider/components/CamoxAppContext.js";
3
+ import { useRoutableLayouts } from "../../lib/studio-definitions.js";
4
4
  import { matchDerivedLayout, routeSegments } from "../../core/derivedRoutes.js";
5
5
  import { c } from "react/compiler-runtime";
6
6
  import * as React from "react";
@@ -30,16 +30,16 @@ function DerivedPagePathInput(props) {
30
30
  function PagePathForm(t0) {
31
31
  const $ = c(46);
32
32
  const { page, pathname, onChange } = t0;
33
- const app = useCamoxApp();
33
+ const layouts = useRoutableLayouts();
34
34
  const { locales } = useViewLocale();
35
35
  let t1;
36
- if ($[0] !== app || $[1] !== locales || $[2] !== page.layoutId || $[3] !== pathname) {
36
+ if ($[0] !== layouts || $[1] !== locales || $[2] !== page.layoutId || $[3] !== pathname) {
37
37
  t1 = () => {
38
38
  if (!pathname || /[?#]/.test(pathname)) return {};
39
- const match = matchDerivedLayout(app.getLayouts(), parseLocalePath(pathname, locales).path);
39
+ const match = matchDerivedLayout(layouts, parseLocalePath(pathname, locales).path);
40
40
  return match && match.layout._internal.id === page.layoutId ? match.params : {};
41
41
  };
42
- $[0] = app;
42
+ $[0] = layouts;
43
43
  $[1] = locales;
44
44
  $[2] = page.layoutId;
45
45
  $[3] = pathname;
@@ -55,7 +55,7 @@ function PagePathForm(t0) {
55
55
  let t4;
56
56
  let t5;
57
57
  let t6;
58
- if ($[5] !== app || $[6] !== errorId || $[7] !== invalid || $[8] !== onChange || $[9] !== page.layoutId || $[10] !== page.title || $[11] !== values) {
58
+ if ($[5] !== errorId || $[6] !== invalid || $[7] !== layouts || $[8] !== onChange || $[9] !== page.layoutId || $[10] !== page.title || $[11] !== values) {
59
59
  const segments = routeSegments(page.layoutId);
60
60
  params = [...new Set(segments.filter(_temp).map(_temp2))];
61
61
  let t7;
@@ -71,9 +71,9 @@ function PagePathForm(t0) {
71
71
  return value && !value.includes("/") && value !== "." && value !== "..";
72
72
  });
73
73
  let t8;
74
- if ($[21] !== app || $[22] !== page.layoutId || $[23] !== path || $[24] !== validParams) {
75
- t8 = validParams && !/[?#]/.test(path) && matchDerivedLayout(app.getLayouts(), path)?.layout._internal.id === page.layoutId;
76
- $[21] = app;
74
+ if ($[21] !== layouts || $[22] !== page.layoutId || $[23] !== path || $[24] !== validParams) {
75
+ t8 = validParams && !/[?#]/.test(path) && matchDerivedLayout(layouts, path)?.layout._internal.id === page.layoutId;
76
+ $[21] = layouts;
77
77
  $[22] = page.layoutId;
78
78
  $[23] = path;
79
79
  $[24] = validParams;
@@ -135,9 +135,9 @@ function PagePathForm(t0) {
135
135
  ]
136
136
  }, param_0);
137
137
  });
138
- $[5] = app;
139
- $[6] = errorId;
140
- $[7] = invalid;
138
+ $[5] = errorId;
139
+ $[6] = invalid;
140
+ $[7] = layouts;
141
141
  $[8] = onChange;
142
142
  $[9] = page.layoutId;
143
143
  $[10] = page.title;
@@ -1,7 +1,7 @@
1
1
  import { PREVIEW_PAUSED_ATTRIBUTE } from "../../core/lib/previewPaused.js";
2
+ import { repeatableItemElements, subscribeRepeatableItems } from "../preview/repeatableItemTargets.js";
2
3
  import { readBlockInsertion } from "./canvasInsertionSeams.js";
3
4
  import { resolveOverlayHighlights } from "../preview/overlayHighlights.js";
4
- import { repeatableItemElements, subscribeRepeatableItems } from "../preview/repeatableItemTargets.js";
5
5
 
6
6
  //#region src/features/canvas/canvasOverlayGeometry.ts
7
7
  const targetSelector = "[data-camox-field-id], [data-camox-block-id]";
@@ -8,9 +8,7 @@ import { createStore } from "@xstate/store";
8
8
  const canvasStore = createStore({
9
9
  context: {
10
10
  views: {},
11
- /** Workspaces whose camera is moving, until it has been still for a moment. */
12
11
  moving: {},
13
- /** Counts requests to zoom out to the whole Canvas; a mounted Canvas answers each new one. */
14
12
  overviewRequests: 0
15
13
  },
16
14
  on: {
@@ -19,6 +17,8 @@ const canvasStore = createStore({
19
17
  moving: {},
20
18
  overviewRequests: 0
21
19
  }),
20
+ /** Takes the studio's state, in the renderer frame's document: only its connection sends it. */
21
+ mirror: (_, event) => event.context,
22
22
  requestOverview: (context) => ({
23
23
  ...context,
24
24
  overviewRequests: context.overviewRequests + 1
@@ -1,4 +1,4 @@
1
- import { formatShortcut } from "../../../lib/utils.js";
1
+ import { formatShortcut } from "../../../lib/shortcuts.js";
2
2
  import "../../preview/components/PageNicknameField.js";
3
3
  import { SHOW_WHOLE_CANVAS_SHORTCUT } from "../../preview/previewConstants.js";
4
4
  import { c } from "react/compiler-runtime";
@@ -1,8 +1,8 @@
1
1
  import { useProjectUuid } from "../../../lib/auth.js";
2
2
  import { reads, useRead } from "../../../lib/studio-reads.js";
3
3
  import { useLocalePath } from "../../../lib/view-locale.js";
4
- import { AddBlockSheet } from "../../preview/components/AddBlockSheet.js";
5
4
  import { PreviewEditingOwnerContext } from "../../preview/previewSelection.js";
5
+ import { AddBlockSheet } from "../../preview/components/AddBlockSheet.js";
6
6
  import { PageInfo } from "../../preview/components/PageInfo.js";
7
7
  import { PageTree } from "../../preview/components/PageTree.js";
8
8
  import { PageOverview } from "./PageOverview.js";
@@ -1,5 +1,5 @@
1
- import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
2
1
  import { usePageBlocks } from "../../../lib/normalized-data.js";
2
+ import { useLayoutDefinition } from "../../../lib/studio-definitions.js";
3
3
  import { BlocksGroup, CollapsedPageTree, LayoutBlockItem } from "../../preview/components/PageTree.js";
4
4
  import { c } from "react/compiler-runtime";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -8,7 +8,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
8
8
  const EMPTY_PAGE = { blockIds: [] };
9
9
  /** A layout page's blocks: all its layout's, before and after where page content would be. */
10
10
  function LayoutPageBlocks(t0) {
11
- const $ = c(12);
11
+ const $ = c(9);
12
12
  const { layout } = t0;
13
13
  let t1;
14
14
  if ($[0] !== layout) {
@@ -20,22 +20,14 @@ function LayoutPageBlocks(t0) {
20
20
  $[1] = t1;
21
21
  } else t1 = $[1];
22
22
  const { beforeBlocks, afterBlocks } = usePageBlocks(t1);
23
- const app = useCamoxApp();
24
- let t2;
25
- if ($[2] !== app || $[3] !== layout.layoutId) {
26
- t2 = app.getLayoutById(layout.layoutId)?._internal.title ?? layout.layoutId;
27
- $[2] = app;
28
- $[3] = layout.layoutId;
29
- $[4] = t2;
30
- } else t2 = $[4];
31
- const layoutName = t2;
32
- const t3 = beforeBlocks.length + afterBlocks.length;
33
- let t4;
34
- if ($[5] !== afterBlocks || $[6] !== beforeBlocks || $[7] !== layoutName) {
35
- t4 = /* @__PURE__ */ jsx("div", {
23
+ const layoutName = useLayoutDefinition(layout.layoutId)?.title ?? layout.layoutId;
24
+ const t2 = beforeBlocks.length + afterBlocks.length;
25
+ let t3;
26
+ if ($[2] !== afterBlocks || $[3] !== beforeBlocks || $[4] !== layoutName) {
27
+ t3 = /* @__PURE__ */ jsx("div", {
36
28
  className: "flex flex-col gap-4 py-1",
37
- children: [["Before", beforeBlocks], ["After", afterBlocks]].map((t5) => {
38
- const [title, blocks] = t5;
29
+ children: [["Before", beforeBlocks], ["After", afterBlocks]].map((t4) => {
30
+ const [title, blocks] = t4;
39
31
  return /* @__PURE__ */ jsxs("section", {
40
32
  className: "space-y-1",
41
33
  children: [/* @__PURE__ */ jsx("h2", {
@@ -56,22 +48,22 @@ function LayoutPageBlocks(t0) {
56
48
  }, title);
57
49
  })
58
50
  });
59
- $[5] = afterBlocks;
60
- $[6] = beforeBlocks;
61
- $[7] = layoutName;
51
+ $[2] = afterBlocks;
52
+ $[3] = beforeBlocks;
53
+ $[4] = layoutName;
54
+ $[5] = t3;
55
+ } else t3 = $[5];
56
+ let t4;
57
+ if ($[6] !== t2 || $[7] !== t3) {
58
+ t4 = /* @__PURE__ */ jsx(BlocksGroup, { children: /* @__PURE__ */ jsx(CollapsedPageTree, {
59
+ blockCount: t2,
60
+ children: t3
61
+ }) });
62
+ $[6] = t2;
63
+ $[7] = t3;
62
64
  $[8] = t4;
63
65
  } else t4 = $[8];
64
- let t5;
65
- if ($[9] !== t3 || $[10] !== t4) {
66
- t5 = /* @__PURE__ */ jsx(BlocksGroup, { children: /* @__PURE__ */ jsx(CollapsedPageTree, {
67
- blockCount: t3,
68
- children: t4
69
- }) });
70
- $[9] = t3;
71
- $[10] = t4;
72
- $[11] = t5;
73
- } else t5 = $[11];
74
- return t5;
66
+ return t4;
75
67
  }
76
68
 
77
69
  //#endregion
@@ -2,8 +2,8 @@ import { canvasStore } from "./canvasStore.js";
2
2
  import { ViewportContinuityContext, captureViewportAnchor, resolveViewportAnchor } from "../preview/viewportContinuity.js";
3
3
  import { canvasPageIframe } from "../preview/previewPageFrame.js";
4
4
  import { canvasBlockOverlap } from "./canvasFrameDocument.js";
5
- import { CANVAS_WHEEL_ZOOM_RATE, ZOOM_STRETCH, canvasMaximumScale, canvasMinimumScale, canvasOverview, canvasVerticalRail, canvasWheelDelta, constrainCanvasCamera, findCanvasSnapTarget, fitCanvasPage, isCanvasCameraSnapped, isCanvasPageScale, isInCanvasSnapWindow, placeCanvasPageAnchor, snapCanvasZoom, stretchCanvasZoom, unstretchCanvasZoom, zoomCanvasAt } from "./canvasCamera.js";
6
5
  import { revealScrollDelta } from "../preview/selectionReveal.js";
6
+ import { CANVAS_WHEEL_ZOOM_RATE, ZOOM_STRETCH, canvasMaximumScale, canvasMinimumScale, canvasOverview, canvasVerticalRail, canvasWheelDelta, constrainCanvasCamera, findCanvasSnapTarget, fitCanvasPage, isCanvasCameraSnapped, isCanvasPageScale, isInCanvasSnapWindow, placeCanvasPageAnchor, snapCanvasZoom, stretchCanvasZoom, unstretchCanvasZoom, zoomCanvasAt } from "./canvasCamera.js";
7
7
  import { createCanvasFlight, createCanvasPan } from "./canvasFlight.js";
8
8
  import * as React from "react";
9
9