camox 0.52.3 → 0.53.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/core/editing/createEditableBlock.js +1 -1
  2. package/dist/features/canvas/CamoxCanvas.js +103 -83
  3. package/dist/features/canvas/CanvasPageFrame.js +1 -1
  4. package/dist/features/canvas/CanvasPreviewPageSlot.js +1 -1
  5. package/dist/features/canvas/canvasCamera.js +3 -3
  6. package/dist/features/canvas/sidebar/CanvasInspector.js +4 -159
  7. package/dist/features/canvas/sidebar/CanvasNavigator.js +41 -85
  8. package/dist/features/canvas/sidebar/CanvasSidebar.js +54 -32
  9. package/dist/features/canvas/sidebar/CanvasSidebarFrame.js +4 -3
  10. package/dist/features/canvas/sidebar/CanvasSidebarSkeleton.js +14 -6
  11. package/dist/features/canvas/sidebar/CanvasViewHeader.js +50 -0
  12. package/dist/features/canvas/sidebar/DerivedPageInspector.js +30 -18
  13. package/dist/features/canvas/sidebar/LayoutPageOverview.js +28 -11
  14. package/dist/features/canvas/sidebar/LayoutPageSeo.js +356 -0
  15. package/dist/features/canvas/sidebar/PageInspector.js +118 -80
  16. package/dist/features/canvas/sidebar/PageOverview.js +6 -1
  17. package/dist/features/canvas/sidebar/SingletonPageInspector.js +22 -14
  18. package/dist/features/canvas/useCanvasCamera.js +36 -39
  19. package/dist/features/preview/CamoxPreview.js +1 -1
  20. package/dist/features/preview/components/BlockActionsPopover.js +1 -1
  21. package/dist/features/preview/components/BlockThumbnail.js +1 -1
  22. package/dist/features/preview/components/CanvasPreview.js +1 -1
  23. package/dist/features/preview/components/CreatePageModal.js +1 -1
  24. package/dist/features/preview/components/ItemFieldsEditor.js +1 -1
  25. package/dist/features/preview/components/OverlayTracker.js +1 -1
  26. package/dist/features/preview/components/PageInfo.js +345 -228
  27. package/dist/features/preview/components/PageTree.js +1 -1
  28. package/dist/features/preview/components/PreviewPanel.js +1 -1
  29. package/dist/features/preview/components/PreviewToolbar.js +2 -2
  30. package/dist/features/preview/components/RepeatableItemsList.js +1 -1
  31. package/dist/features/preview/components/SelectionEditor.js +645 -655
  32. package/dist/features/preview/components/SidebarStack.js +553 -0
  33. package/dist/features/preview/components/StudioEditingFallback.js +2 -2
  34. package/dist/features/renderer/RendererFrames.js +34 -27
  35. package/dist/features/runtime/RuntimeChrome.js +1 -1
  36. package/dist/features/runtime/runtime.js +84 -26
  37. package/dist/features/studio/components/ChatSidebar.js +27 -19
  38. package/dist/features/studio/components/Navbar.js +1 -1
  39. package/dist/features/studio/components/UserButton.js +1 -1
  40. package/dist/lib/studio-reads.js +18 -0
  41. package/dist/package.js +1 -1
  42. package/dist/studio.css +1 -1
  43. package/package.json +4 -4
@@ -45,6 +45,12 @@ function isTextEntry(target) {
45
45
  function rescaleY(camera, scale) {
46
46
  return camera.y > 0 ? camera.y : camera.y * scale / camera.scale;
47
47
  }
48
+ const NO_INSETS = {
49
+ top: 0,
50
+ right: 0,
51
+ bottom: 0,
52
+ left: 0
53
+ };
48
54
  /** Animate only the camera's CSS properties; page trees never rerender on pan/zoom. */
49
55
  function useCanvasCamera(workspaceKey, initialTarget, row) {
50
56
  const continuity = React.useContext(ViewportContinuityContext);
@@ -102,20 +108,22 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
102
108
  capture: true,
103
109
  passive: false
104
110
  });
105
- let viewportSize = {
106
- width: viewport.clientWidth,
107
- height: viewport.clientHeight
111
+ let insets = rowRef.current?.insets ?? NO_INSETS;
112
+ const measureViewport = () => {
113
+ insets = rowRef.current?.insets ?? NO_INSETS;
114
+ return {
115
+ width: Math.max(0, viewport.clientWidth - insets.left - insets.right),
116
+ height: Math.max(0, viewport.clientHeight - insets.top - insets.bottom)
117
+ };
108
118
  };
119
+ let viewportSize = measureViewport();
109
120
  const measureContent = () => ({
110
121
  width: rowRef.current?.width ?? content.offsetWidth,
111
122
  height: content.offsetHeight
112
123
  });
113
124
  let contentSize = measureContent();
114
125
  let minimumScale = canvasMinimumScale(viewportSize, contentSize);
115
- const updateGeometry = (nextViewport = {
116
- width: viewport.clientWidth,
117
- height: viewport.clientHeight
118
- }, nextContent = measureContent()) => {
126
+ const updateGeometry = (nextViewport = measureViewport(), nextContent = measureContent()) => {
119
127
  viewportSize = nextViewport;
120
128
  contentSize = nextContent;
121
129
  minimumScale = canvasMinimumScale(viewportSize, contentSize);
@@ -128,7 +136,6 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
128
136
  const targetOf = (key) => key == null ? void 0 : targets().find((candidate) => candidate.key === key);
129
137
  let stretch;
130
138
  let zoomEnd = 0;
131
- let landing;
132
139
  const constrain = (next, stretched = !!stretch) => constrainCanvasCamera(next, viewportSize, contentSize, canvasMaximumScale(viewportSize, targets(), minimumScale), stretched);
133
140
  const saved = canvasStore.getSnapshot().context.views[workspaceKey];
134
141
  const savedCamera = saved && !saved.fitted ? saved.camera : void 0;
@@ -194,16 +201,6 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
194
201
  y: anchored.y + translation.y
195
202
  };
196
203
  if (!candidate || !fit || !isCanvasPageScale(snapped, fit.scale)) return next;
197
- const entered = selection !== candidate.key;
198
- if (entered) landing = {
199
- key: candidate.key,
200
- stretched
201
- };
202
- else if (stretched && landing && !landing.stretched) {
203
- landing.stretched = true;
204
- rowRef.current?.onSnapStretched?.();
205
- }
206
- if (entered && !stretched) rowRef.current?.onSnap?.();
207
204
  select(candidate.key);
208
205
  return {
209
206
  ...next,
@@ -236,7 +233,6 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
236
233
  if (!candidate || !fit || fit.scale < minimumScale) return intended;
237
234
  const held = isCanvasCameraSnapped(base, viewportSize, candidate);
238
235
  if (!isInCanvasSnapWindow(intended, viewportSize, candidate, held)) return intended;
239
- if (selection !== candidate.key) rowRef.current?.onSnap?.();
240
236
  select(candidate.key);
241
237
  gesture.intendedX += (candidate.left + candidate.width / 2) * (intended.scale - fit.scale);
242
238
  return constrain({
@@ -254,8 +250,6 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
254
250
  markMoving();
255
251
  applyCamera(next);
256
252
  }
257
- if (landing?.stretched && landing.key === selection) rowRef.current?.onSnap?.();
258
- landing = void 0;
259
253
  };
260
254
  const pointers = /* @__PURE__ */ new Map();
261
255
  let spaceHeld = false;
@@ -317,8 +311,8 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
317
311
  if (!wasMoving) setMoving(true);
318
312
  };
319
313
  const paintElement = (element) => {
320
- element.style.setProperty("--canvas-x", `${camera.x}px`);
321
- element.style.setProperty("--canvas-y", `${camera.y}px`);
314
+ element.style.setProperty("--canvas-x", `${camera.x + insets.left}px`);
315
+ element.style.setProperty("--canvas-y", `${camera.y + insets.top}px`);
322
316
  element.style.setProperty("--canvas-zoom", String(camera.scale));
323
317
  element.style.setProperty("--canvas-pixel-ratio", String(ownerWindow.devicePixelRatio));
324
318
  };
@@ -413,7 +407,6 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
413
407
  gesture = void 0;
414
408
  ownerWindow.clearTimeout(zoomEnd);
415
409
  stretch = void 0;
416
- landing = void 0;
417
410
  updateGeometry();
418
411
  camera = constrain(camera, true);
419
412
  target = constrain(destinationCamera());
@@ -435,7 +428,7 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
435
428
  const frame = element.ownerDocument.defaultView?.frameElement;
436
429
  if (!frame || flight && !flight.pan || pointers.size) return;
437
430
  const rect = element.getBoundingClientRect();
438
- const worldTop = (frame.getBoundingClientRect().top - viewport.getBoundingClientRect().top + rect.top * camera.scale - camera.y) / camera.scale;
431
+ const worldTop = (frame.getBoundingClientRect().top - viewport.getBoundingClientRect().top - insets.top + rect.top * camera.scale - camera.y) / camera.scale;
439
432
  const delta = revealScrollDelta({
440
433
  top: target.y + worldTop * target.scale,
441
434
  bottom: target.y + (worldTop + rect.height) * target.scale
@@ -483,7 +476,7 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
483
476
  const held = flight ? void 0 : targetOf(selection);
484
477
  const element = held && Array.from(content.querySelectorAll("[data-canvas-page]")).find((element) => element.dataset.canvasPage === held.key);
485
478
  const doc = element ? canvasPageIframe(element)?.contentDocument : void 0;
486
- const anchor = doc && element ? captureViewportAnchor(doc, Math.max(0, (viewport.getBoundingClientRect().top - element.getBoundingClientRect().top) / camera.scale)) : void 0;
479
+ const anchor = doc && element ? captureViewportAnchor(doc, Math.max(0, (viewport.getBoundingClientRect().top + insets.top - element.getBoundingClientRect().top) / camera.scale)) : void 0;
487
480
  return {
488
481
  camera: { ...camera },
489
482
  pathname: element ? element.dataset.canvasPathname : void 0,
@@ -505,7 +498,7 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
505
498
  } : fit;
506
499
  if (anchor && doc) {
507
500
  const y = resolveViewportAnchor(doc, anchor);
508
- const frameOffsetY = page ? (page.getBoundingClientRect().top - viewport.getBoundingClientRect().top - camera.y) / camera.scale : 0;
501
+ const frameOffsetY = page ? (page.getBoundingClientRect().top - viewport.getBoundingClientRect().top - insets.top - camera.y) / camera.scale : 0;
509
502
  next = placeCanvasPageAnchor(viewportSize, destination, y, fit.scale, frameOffsetY);
510
503
  }
511
504
  fittingInitialPage = false;
@@ -515,12 +508,10 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
515
508
  };
516
509
  if (continuity) continuity.canvas = continuityBinding;
517
510
  const resize = new ResizeObserver(() => {
518
- const nextViewport = {
519
- width: viewport.clientWidth,
520
- height: viewport.clientHeight
521
- };
511
+ const previousInsets = insets;
512
+ const nextViewport = measureViewport();
522
513
  const nextContent = measureContent();
523
- if (nextViewport.width === viewportSize.width && nextViewport.height === viewportSize.height && nextContent.width === contentSize.width && nextContent.height === contentSize.height) return;
514
+ if (insets.left === previousInsets.left && insets.top === previousInsets.top && nextViewport.width === viewportSize.width && nextViewport.height === viewportSize.height && nextContent.width === contentSize.width && nextContent.height === contentSize.height) return;
524
515
  const wasFitted = isOverview(target);
525
516
  gesture = void 0;
526
517
  const held = nextViewport.width !== viewportSize.width && !flight && !fittingInitialPage ? targetOf(selection) : void 0;
@@ -559,14 +550,14 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
559
550
  const localPoint = (x, y) => {
560
551
  const rect = viewport.getBoundingClientRect();
561
552
  return {
562
- x: x - rect.left,
563
- y: y - rect.top
553
+ x: x - rect.left - insets.left,
554
+ y: y - rect.top - insets.top
564
555
  };
565
556
  };
566
557
  const onWheel = (event) => {
567
558
  event.preventDefault();
568
- const dx = canvasWheelDelta(event.deltaX, event.deltaMode, viewport.clientWidth);
569
- const dy = canvasWheelDelta(event.deltaY, event.deltaMode, viewport.clientHeight);
559
+ const dx = canvasWheelDelta(event.deltaX, event.deltaMode, viewportSize.width);
560
+ const dy = canvasWheelDelta(event.deltaY, event.deltaMode, viewportSize.height);
570
561
  if (!dx && !dy) return;
571
562
  rowRef.current?.onEditorMove?.();
572
563
  cancelCameraFlight();
@@ -664,7 +655,13 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
664
655
  const onFocusIn = (event) => {
665
656
  if (!isControl(event.target)) return;
666
657
  const rect = event.target.getBoundingClientRect();
667
- const bounds = viewport.getBoundingClientRect();
658
+ const viewportRect = viewport.getBoundingClientRect();
659
+ const bounds = {
660
+ left: viewportRect.left + insets.left,
661
+ top: viewportRect.top + insets.top,
662
+ right: viewportRect.left + insets.left + viewportSize.width,
663
+ bottom: viewportRect.top + insets.top + viewportSize.height
664
+ };
668
665
  const dx = Math.max(0, bounds.left + 16 - rect.left) - Math.max(0, rect.right - bounds.right + 16);
669
666
  const dy = Math.max(0, bounds.top + 16 - rect.top) - Math.max(0, rect.bottom - bounds.bottom + 16);
670
667
  if (!dx && !dy) return;
@@ -689,8 +686,8 @@ function useCanvasCamera(workspaceKey, initialTarget, row) {
689
686
  "ArrowDown"
690
687
  ].includes(event.key) || event.shiftKey && event.code === "Digit1") cancelCameraFlight();
691
688
  const center = {
692
- x: viewport.clientWidth / 2,
693
- y: viewport.clientHeight / 2
689
+ x: viewportSize.width / 2,
690
+ y: viewportSize.height / 2
694
691
  };
695
692
  const factor = event.key === "+" || event.key === "=" ? 1.25 : event.key === "-" ? .8 : event.key === "0" ? 1 / target.scale : void 0;
696
693
  if (factor) {
@@ -12,10 +12,10 @@ import { usePageDestinations } from "../../hooks/use-page-destinations.js";
12
12
  import { useLocalePath, useLocalizedPath } from "../../lib/view-locale.js";
13
13
  import { CanvasLoadingScreen } from "../canvas/CanvasLoadingScreen.js";
14
14
  import { canvasStore } from "../canvas/canvasStore.js";
15
+ import { previewStore, selectIsCanvasShown } from "./previewStore.js";
15
16
  import { SHOW_WHOLE_CANVAS_SHORTCUT, TOGGLE_CANVAS_SHORTCUT } from "./previewConstants.js";
16
17
  import { CanvasSidebarSkeleton } from "../canvas/sidebar/CanvasSidebarSkeleton.js";
17
18
  import { takeShowCanvasRequest } from "../provider/signInShortcut.js";
18
- import { previewStore, selectIsCanvasShown } from "./previewStore.js";
19
19
  import { PreviewEditingOwnerContext } from "./previewSelection.js";
20
20
  import { RendererFramesProvider, RendererSlot, useRendererHost, useRendererStatus } from "../renderer/RendererFrames.js";
21
21
  import { STUDIO_CANVAS_PATH } from "../studio/routes.js";
@@ -1,8 +1,8 @@
1
1
  import { actionsStore } from "../../provider/actionsStore.js";
2
2
  import { usePageBlocks } from "../../../lib/normalized-data.js";
3
3
  import { blockMutations, repeatableItemMutations } from "../../../lib/queries.js";
4
- import { formatShortcut } from "../../../lib/shortcuts.js";
5
4
  import { isBlockSelection, previewStore, selectionForPage, selectionItemId } from "../previewStore.js";
5
+ import { formatShortcut } from "../../../lib/shortcuts.js";
6
6
  import { entityName } from "../entityName.js";
7
7
  import { useUpdateBlockPosition } from "./useUpdateBlockPosition.js";
8
8
  import { usePreviewedPage } from "../CamoxPreview.js";
@@ -1,6 +1,6 @@
1
1
  import { cn } from "../../../lib/utils.js";
2
- import { useRendererHost } from "../../renderer/RendererFrames.js";
3
2
  import { useEditingFrame } from "../editingFrame.js";
3
+ import { useRendererHost } from "../../renderer/RendererFrames.js";
4
4
  import { EMPTY_PREVIEW_DOCUMENT, isSiteStyle } from "./previewStyles.js";
5
5
  import { FrameContext } from "./Frame.js";
6
6
  import { c } from "react/compiler-runtime";
@@ -203,7 +203,7 @@ function CanvasPreview({ enabled, pathname, pagePathname, runtimeBasePath, place
203
203
  className: "relative flex min-h-0 flex-1",
204
204
  "data-preview-surface": true,
205
205
  children: [
206
- enabled && phase !== "failed" && placeholder,
206
+ enabled && phase === "preparing" && placeholder,
207
207
  /* @__PURE__ */ jsxs("div", {
208
208
  className: "relative flex min-h-0 min-w-0 flex-1 flex-col",
209
209
  "data-read-only-preview": true,
@@ -4,9 +4,9 @@ import { reads, useReadQuery } from "../../../lib/studio-reads.js";
4
4
  import { pageMutations } from "../../../lib/queries.js";
5
5
  import { useLayoutDefinitions } from "../../../lib/studio-definitions.js";
6
6
  import { useLocalizedPath } from "../../../lib/view-locale.js";
7
- import { PageNicknameField } from "./PageNicknameField.js";
8
7
  import { previewStore } from "../previewStore.js";
9
8
  import { PageLocationFieldset } from "./PageLocationFieldset.js";
9
+ import { PageNicknameField } from "./PageNicknameField.js";
10
10
  import { c } from "react/compiler-runtime";
11
11
  import { useEffect } from "react";
12
12
  import { useSelector } from "@xstate/store-react";
@@ -5,8 +5,8 @@ import { DrillRow } from "./DrillRow.js";
5
5
  import { ReferenceFieldEditor } from "./ReferenceFieldEditor.js";
6
6
  import { ReferenceListFieldEditor } from "./ReferenceListFieldEditor.js";
7
7
  import { previewStore } from "../previewStore.js";
8
- import { PreviewEditingOwnerContext } from "../previewSelection.js";
9
8
  import { overlayFieldId, recordPlacementId } from "../overlayMessages.js";
9
+ import { PreviewEditingOwnerContext } from "../previewSelection.js";
10
10
  import { SidebarLexicalEditor } from "../../../core/components/lexical/SidebarLexicalEditor.js";
11
11
  import { IconFieldEditor } from "./IconFieldEditor.js";
12
12
  import { RepeatableItemsList } from "./RepeatableItemsList.js";
@@ -1,5 +1,5 @@
1
- import { useFrame } from "./Frame.js";
2
1
  import { isOverlayMessage } from "../overlayMessages.js";
2
+ import { useFrame } from "./Frame.js";
3
3
  import { c } from "react/compiler-runtime";
4
4
  import * as React from "react";
5
5