camox 0.54.0 → 0.57.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 (50) hide show
  1. package/dist/features/canvas/CamoxCanvas.js +14 -11
  2. package/dist/features/canvas/CanvasLoadingScreen.js +1 -1
  3. package/dist/features/canvas/CanvasPageHeader.js +1 -1
  4. package/dist/features/canvas/canvasFrameDocument.js +13 -6
  5. package/dist/features/canvas/sidebar/CanvasViewHeader.js +1 -1
  6. package/dist/features/canvas/sidebar/{CanvasSidebar.js → ContentSidebar.js} +5 -5
  7. package/dist/features/canvas/sidebar/{CanvasSidebarFrame.js → ContentSidebarFrame.js} +4 -4
  8. package/dist/features/canvas/sidebar/{CanvasSidebarSkeleton.js → ContentSidebarSkeleton.js} +7 -7
  9. package/dist/features/preview/CamoxPreview.js +2 -2
  10. package/dist/features/preview/components/Frame.js +1 -18
  11. package/dist/features/preview/components/PreviewToolbar.js +1 -1
  12. package/dist/features/preview/components/SelectionEditor.js +2 -2
  13. package/dist/features/preview/components/SidebarStack.js +201 -116
  14. package/dist/features/preview/components/StudioEditingFallback.js +3 -3
  15. package/dist/features/preview/components/previewStyles.js +25 -1
  16. package/dist/features/renderer/RendererApp.js +55 -37
  17. package/dist/features/routes/pageRuntime.d.ts +1 -1
  18. package/dist/features/runtime/RuntimeChrome.js +4 -4
  19. package/dist/features/studio/components/AgentSidebar.js +56 -0
  20. package/dist/features/studio/components/ChatWidget.js +219 -0
  21. package/dist/features/studio/components/DraftsControl.js +17 -17
  22. package/dist/features/studio/components/Patrol.js +676 -0
  23. package/dist/features/studio/components/ReviewDraftSheet.js +38 -38
  24. package/dist/features/studio/components/Squareling.js +171 -84
  25. package/dist/features/studio/components/ThreadMessages.js +256 -136
  26. package/dist/features/studio/localeOptions.js +7 -3
  27. package/dist/features/studio/reportSentence.js +75 -0
  28. package/dist/features/studio/routes.js +2 -1
  29. package/dist/features/studio/showInCanvas.js +9 -2
  30. package/dist/features/studio/studioStore.js +5 -5
  31. package/dist/features/studio/workingSentence.js +55 -0
  32. package/dist/lib/queries.js +1 -1
  33. package/dist/lib/studio-reads.d.ts +1 -0
  34. package/dist/lib/studio-reads.js +5 -0
  35. package/dist/lib/use-thread.js +156 -190
  36. package/dist/package.js +1 -1
  37. package/dist/studio.css +1 -1
  38. package/package.json +4 -4
  39. package/skills/camox/SKILL.md +3 -10
  40. package/skills/camox/references/artifacts.md +2 -2
  41. package/skills/camox/references/block-definitions.md +1 -1
  42. package/skills/camox/references/layout-definitions.md +1 -1
  43. package/skills/camox/references/routed-layouts.md +2 -2
  44. package/skills/camox-cli/SKILL.md +15 -0
  45. package/skills/{camox → camox-cli}/references/cli-common.md +1 -1
  46. package/skills/{camox → camox-cli}/references/cli-content.md +2 -2
  47. package/skills/{camox → camox-cli}/references/cli-publishing.md +4 -4
  48. package/skills/camox-expand/SKILL.md +1 -1
  49. package/skills/camoxify/SKILL.md +1 -1
  50. package/dist/features/studio/components/ChatSidebar.js +0 -346
@@ -31,16 +31,14 @@ const DARK_SHADE_STRENGTH = 2.5;
31
31
  /** Keeps a sidebar's cards off its sides, so their edges show. */
32
32
  const SIDEBAR_GUTTER = "px-2";
33
33
  /**
34
- * The color of a card's edges: the border's, solid. Dark mode's border is translucent, so it's
35
- * laid over the Canvas behind the sidebars, to look the same over the card as beside it.
34
+ * The front card's bottom, under its header, with a soft shadow down its sides that stops short
35
+ * of its top, so it doesn't fall on its header.
36
36
  */
37
- const CARD_EDGE_COLOR = "border-border dark:border-[color-mix(in_srgb,var(--color-muted),white_10%)]";
38
- /** The front card's sides and bottom, under its header. */
39
- const CARD_BODY_EDGES = `rounded-b-lg border border-t-0 ${CARD_EDGE_COLOR}`;
40
- /** The bottom card's top and sides, as it meets the top of a sidebar. */
41
- const BOTTOM_CARD_EDGES = `rounded-t-lg border border-b-0 ${CARD_EDGE_COLOR}`;
42
- /** The front card's top and sides, over the cards behind it. */
43
- const FRONT_CARD_EDGES = `border border-b-0 ${CARD_EDGE_COLOR}`;
37
+ const CARD_BODY_EDGES = "rounded-b-lg inset-shadow-raised-bottom shadow-[0_12px_24px_-12px_rgb(0_0_0/0.14)] dark:shadow-[0_12px_24px_-12px_rgb(0_0_0/0.6)]";
38
+ /** The bottom card's top, as it meets the top of a sidebar. */
39
+ const BOTTOM_CARD_EDGES = "rounded-t-lg inset-shadow-raised-top";
40
+ /** A card's top, over the cards behind it. */
41
+ const CARD_TOP_EDGE = "inset-shadow-raised-top";
44
42
  /**
45
43
  * How much the second card behind the front fades its name, which shows depth on dark
46
44
  * backgrounds too. The card right behind the front doesn't fade.
@@ -66,16 +64,8 @@ const LEAVE_DURATION = 180;
66
64
  const SWAP_DURATION = 150;
67
65
  /** How long after each other cards laid at once land, front-most last. */
68
66
  const STAGGER = 25;
69
- const HEADER_TRANSITION = [...[
70
- "transform",
71
- "margin",
72
- "height",
73
- "padding"
74
- ].map((p) => `${p} ${DURATION}ms ${EASE}`), ...[
75
- "background-color",
76
- "box-shadow",
77
- "color"
78
- ].map((p) => `${p} ${DURATION}ms ease-out`)].join(", ");
67
+ /** How far any card shades at most, `stepSeries`' limit: a header's shade is a part of it. */
68
+ const MAX_SHADE = FIRST_STEP_SHADE / .15000000000000002;
79
69
  /** How far below the front a card is laid from, or pulled away to, in px. */
80
70
  const PULL = 24;
81
71
  const PLACED = {
@@ -314,6 +304,41 @@ function useStackCard(ref, depth, isView) {
314
304
  };
315
305
  }, []);
316
306
  }
307
+ /**
308
+ * Eases a header's card and content from where they were laid out before `shape` changed to
309
+ * where they are now, as its layout snaps: its card scales from its old size, and its content
310
+ * slides from its old height.
311
+ */
312
+ function useHeaderReshape(surfaceRef, contentRef, shape) {
313
+ const last = React.useRef(null);
314
+ const moving = React.useRef([]);
315
+ React.useLayoutEffect(() => {
316
+ const surface = surfaceRef.current;
317
+ const content = contentRef.current;
318
+ if (!surface || !content) return;
319
+ const box = {
320
+ width: surface.offsetWidth,
321
+ height: surface.offsetHeight,
322
+ center: content.offsetTop + content.offsetHeight / 2
323
+ };
324
+ const from = last.current;
325
+ last.current = box;
326
+ if (!from || !box.width || !box.height || !prefersMotion()) return;
327
+ let { width, height, center } = from;
328
+ if (moving.current.some((animation) => animation.playState === "running")) {
329
+ const shown = new DOMMatrixReadOnly(getComputedStyle(surface).transform);
330
+ width *= shown.a;
331
+ height *= shown.d;
332
+ center += new DOMMatrixReadOnly(getComputedStyle(content).transform).f;
333
+ }
334
+ for (const animation of moving.current) animation.cancel();
335
+ const timing = {
336
+ duration: DURATION,
337
+ easing: EASE
338
+ };
339
+ moving.current = [surface.animate([{ transform: `scale(${width / box.width}, ${height / box.height})` }, { transform: "none" }], timing), content.animate([{ transform: `translateY(${center - box.center}px)` }, { transform: "none" }], timing)];
340
+ }, [shape]);
341
+ }
317
342
  /** How many of the selection's views are laid over the page's, in this stack. */
318
343
  function useSelectionViewCount() {
319
344
  return React.useContext(SelectionViewsContext)?.count ?? 0;
@@ -352,7 +377,7 @@ function SidebarStackView(t0) {
352
377
  const { depth, className, children } = t0;
353
378
  const ref = React.useRef(null);
354
379
  useStackCard(ref, depth, true);
355
- const t1 = React.useContext(StackMotionContext) != null && "rounded-b-lg border border-t-0 border-border dark:border-[color-mix(in_srgb,var(--color-muted),white_10%)]";
380
+ const t1 = React.useContext(StackMotionContext) != null && "rounded-b-lg inset-shadow-raised-bottom shadow-[0_12px_24px_-12px_rgb(0_0_0/0.14)] dark:shadow-[0_12px_24px_-12px_rgb(0_0_0/0.6)]";
356
381
  let t2;
357
382
  if ($[0] !== className || $[1] !== t1) {
358
383
  t2 = cn("bg-background min-h-0 flex-1 origin-top", t1, className);
@@ -374,7 +399,7 @@ function SidebarStackView(t0) {
374
399
  return t3;
375
400
  }
376
401
  function SidebarStackHeader(t0) {
377
- const $ = c(55);
402
+ const $ = c(69);
378
403
  const { depth, distance: t1, first: t2, onSelect, hoverTarget, tooltip, popover, children } = t0;
379
404
  const distance = t1 === void 0 ? 0 : t1;
380
405
  const first = t2 === void 0 ? false : t2;
@@ -452,82 +477,129 @@ function SidebarStackHeader(t0) {
452
477
  $[16] = t8;
453
478
  } else t8 = $[16];
454
479
  const button = t8;
455
- const t9 = !first && "-mt-1";
456
- let t10;
457
- if ($[17] !== t9) {
458
- t10 = cn("relative shrink-0 origin-top", t9);
459
- $[17] = t9;
460
- $[18] = t10;
461
- } else t10 = $[18];
462
- const t11 = !flat && !first && "rounded-t-sm";
480
+ const surfaceRef = React.useRef(null);
481
+ const contentRef = React.useRef(null);
482
+ let t9;
483
+ if ($[17] !== covered || $[18] !== distance) {
484
+ t9 = covered ? stackInset(distance) : 0;
485
+ $[17] = covered;
486
+ $[18] = distance;
487
+ $[19] = t9;
488
+ } else t9 = $[19];
489
+ const inset = t9;
490
+ useHeaderReshape(surfaceRef, contentRef, `${covered}:${inset}`);
491
+ const t10 = !first && "-mt-1";
492
+ let t11;
493
+ if ($[20] !== t10) {
494
+ t11 = cn("relative shrink-0 origin-top", t10);
495
+ $[20] = t10;
496
+ $[21] = t11;
497
+ } else t11 = $[21];
463
498
  const t12 = covered ? "h-[38px] pb-1" : "h-11 px-3";
464
- const t13 = first && !flat && "rounded-t-lg border border-b-0 border-border dark:border-[color-mix(in_srgb,var(--color-muted),white_10%)]";
465
- const t14 = covered && !first && `border ${CARD_EDGE_COLOR} shadow-[0_-2px_5px_-3px_rgb(0_0_0/0.08)] dark:shadow-[0_-2px_5px_-3px_rgb(0_0_0/0.4)]`;
466
- const t15 = !covered && !first && (inStack ? `${FRONT_CARD_EDGES} shadow-[0_-3px_8px_-4px_rgb(0_0_0/0.08)] dark:shadow-[0_-3px_8px_-4px_rgb(0_0_0/0.4)]` : `border-t ${CARD_EDGE_COLOR} shadow-[0_-3px_8px_-4px_rgb(0_0_0/0.08)] dark:shadow-[0_-3px_8px_-4px_rgb(0_0_0/0.4)]`);
467
- const t16 = liftable && "hover:[--fade:1] hover:[--lift:var(--hover-lift)] hover:[--shade:var(--hover-shade)] hover:[--tilt:var(--hover-tilt)]";
468
- const t17 = liftable && "has-focus-visible:[--fade:1] has-focus-visible:[--lift:var(--hover-lift)] has-focus-visible:[--shade:var(--hover-shade)] has-focus-visible:[--tilt:var(--hover-tilt)]";
469
- const t18 = liftable && "has-data-popup-open:[--fade:1] has-data-popup-open:[--lift:var(--hover-lift)] has-data-popup-open:[--shade:var(--hover-shade)] has-data-popup-open:[--tilt:var(--hover-tilt)]";
470
- let t19;
471
- if ($[19] !== t11 || $[20] !== t12 || $[21] !== t13 || $[22] !== t14 || $[23] !== t15 || $[24] !== t16 || $[25] !== t17 || $[26] !== t18) {
472
- t19 = cn("relative flex min-w-0 items-center justify-center text-center text-sm", t11, "[--ancestor-foreground:color-mix(in_oklab,var(--color-muted-foreground),var(--color-foreground)_40%)]", "[--fade:var(--rest-fade)] [--lift:0px] [--shade:var(--rest-shade)] [--tilt:var(--rest-tilt)]", "[--shade-color:black] [--shade-strength:1] dark:[--shade-color:white] dark:[--shade-strength:var(--dark-shade-strength)]", "origin-bottom [backface-visibility:hidden] motion-reduce:transition-none!", t12, t13, t14, t15, t16, t17, t18);
473
- $[19] = t11;
474
- $[20] = t12;
475
- $[21] = t13;
476
- $[22] = t14;
477
- $[23] = t15;
478
- $[24] = t16;
479
- $[25] = t17;
480
- $[26] = t18;
499
+ const t13 = liftable && "hover:[--fade:1] hover:[--lift:var(--hover-lift)] hover:[--shade:var(--hover-shade)] hover:[--tilt:var(--hover-tilt)]";
500
+ const t14 = liftable && "has-focus-visible:[--fade:1] has-focus-visible:[--lift:var(--hover-lift)] has-focus-visible:[--shade:var(--hover-shade)] has-focus-visible:[--tilt:var(--hover-tilt)]";
501
+ const t15 = liftable && "has-data-popup-open:[--fade:1] has-data-popup-open:[--lift:var(--hover-lift)] has-data-popup-open:[--shade:var(--hover-shade)] has-data-popup-open:[--tilt:var(--hover-tilt)]";
502
+ let t16;
503
+ if ($[22] !== t12 || $[23] !== t13 || $[24] !== t14 || $[25] !== t15) {
504
+ t16 = cn("relative flex min-w-0 items-center justify-center text-center text-sm", "[--ancestor-foreground:color-mix(in_oklab,var(--color-muted-foreground),var(--color-foreground)_40%)]", "[--fade:var(--rest-fade)] [--lift:0px] [--shade:var(--rest-shade)] [--tilt:var(--rest-tilt)]", "[--shade-color:black] [--shade-strength:1] dark:[--shade-color:white] dark:[--shade-strength:var(--dark-shade-strength)]", "origin-bottom [backface-visibility:hidden] motion-reduce:transition-none!", t12, t13, t14, t15);
505
+ $[22] = t12;
506
+ $[23] = t13;
507
+ $[24] = t14;
508
+ $[25] = t15;
509
+ $[26] = t16;
510
+ } else t16 = $[26];
511
+ const t17 = `${tilt}deg`;
512
+ const t18 = `${tilt / 2}deg`;
513
+ const t19 = Math.max(0, distance - 1);
514
+ let t20;
515
+ if ($[27] !== t19) {
516
+ t20 = stepSeries(FIRST_STEP_SHADE, t19);
481
517
  $[27] = t19;
482
- } else t19 = $[27];
483
- const t20 = `${tilt}deg`;
484
- const t21 = `${tilt / 2}deg`;
485
- const t22 = `${shade}%`;
486
- const t23 = Math.max(0, distance - 1);
487
- let t24;
488
- if ($[28] !== t23) {
489
- t24 = stepSeries(FIRST_STEP_SHADE, t23);
490
- $[28] = t23;
491
- $[29] = t24;
492
- } else t24 = $[29];
493
- const t25 = `${t24}%`;
494
- const t26 = `${first ? 0 : -1.5}px`;
495
- const t27 = covered ? 1 - stepSeries(FIRST_STEP_FADE, distance - 1) : 1;
496
- let t28;
497
- if ($[30] !== covered || $[31] !== distance) {
498
- t28 = covered ? stackInset(distance) : void 0;
499
- $[30] = covered;
500
- $[31] = distance;
501
- $[32] = t28;
502
- } else t28 = $[32];
503
- let t29;
504
- if ($[33] !== t20 || $[34] !== t21 || $[35] !== t22 || $[36] !== t25 || $[37] !== t26 || $[38] !== t27 || $[39] !== t28) {
505
- t29 = {
506
- "--rest-tilt": t20,
507
- "--hover-tilt": t21,
508
- "--rest-shade": t22,
518
+ $[28] = t20;
519
+ } else t20 = $[28];
520
+ const t21 = `${first ? 0 : -1.5}px`;
521
+ const t22 = covered ? 1 - stepSeries(FIRST_STEP_FADE, distance - 1) : 1;
522
+ let t23;
523
+ if ($[29] !== shade || $[30] !== t17 || $[31] !== t18 || $[32] !== t20 || $[33] !== t21 || $[34] !== t22) {
524
+ t23 = {
525
+ "--rest-tilt": t17,
526
+ "--hover-tilt": t18,
527
+ "--rest-shade": shade,
509
528
  "--dark-shade-strength": DARK_SHADE_STRENGTH,
510
- "--hover-shade": t25,
511
- "--hover-lift": t26,
512
- "--rest-fade": t27,
513
- marginInline: t28,
529
+ "--hover-shade": t20,
530
+ "--hover-lift": t21,
531
+ "--rest-fade": t22,
514
532
  transform: `perspective(${PERSPECTIVE}px) translateY(var(--lift)) rotateX(var(--tilt))`,
515
- backgroundColor: "color-mix(in oklab, var(--color-background), var(--shade-color) calc(var(--shade) * var(--shade-strength)))",
516
- transition: HEADER_TRANSITION
533
+ transition: `transform ${DURATION}ms ${EASE}`
517
534
  };
518
- $[33] = t20;
519
- $[34] = t21;
520
- $[35] = t22;
535
+ $[29] = shade;
536
+ $[30] = t17;
537
+ $[31] = t18;
538
+ $[32] = t20;
539
+ $[33] = t21;
540
+ $[34] = t22;
541
+ $[35] = t23;
542
+ } else t23 = $[35];
543
+ const t24 = t23;
544
+ const t25 = !flat && (first ? "rounded-t-lg" : "rounded-t-sm");
545
+ const t26 = covered && !first && "shadow-[0_-2px_5px_-3px_rgb(0_0_0/0.08)] dark:shadow-[0_-2px_5px_-3px_rgb(0_0_0/0.4)]";
546
+ const t27 = !covered && !first && "shadow-[0_-3px_8px_-4px_rgb(0_0_0/0.08)] dark:shadow-[0_-3px_8px_-4px_rgb(0_0_0/0.4)]";
547
+ let t28;
548
+ if ($[36] !== t25 || $[37] !== t26 || $[38] !== t27) {
549
+ t28 = cn("bg-background absolute inset-y-0 isolate origin-top", t25, t26, t27);
521
550
  $[36] = t25;
522
551
  $[37] = t26;
523
552
  $[38] = t27;
524
553
  $[39] = t28;
525
- $[40] = t29;
526
- } else t29 = $[40];
527
- const t30 = t29;
554
+ } else t28 = $[39];
555
+ let t29;
556
+ if ($[40] !== inset) {
557
+ t29 = { insetInline: inset };
558
+ $[40] = inset;
559
+ $[41] = t29;
560
+ } else t29 = $[41];
561
+ let t30;
562
+ if ($[42] === Symbol.for("react.memo_cache_sentinel")) {
563
+ t30 = /* @__PURE__ */ jsx("div", {
564
+ className: "absolute inset-0 rounded-[inherit] motion-reduce:transition-none!",
565
+ style: {
566
+ backgroundColor: `color-mix(in oklab, var(--color-background), var(--shade-color) calc(${MAX_SHADE}% * var(--shade-strength)))`,
567
+ opacity: `calc(var(--shade) / ${MAX_SHADE})`,
568
+ transition: `opacity ${DURATION}ms ease-out`
569
+ }
570
+ });
571
+ $[42] = t30;
572
+ } else t30 = $[42];
528
573
  let t31;
529
- if ($[41] !== button || $[42] !== children || $[43] !== covered || $[44] !== popover || $[45] !== popoverOpen || $[46] !== tooltip) {
530
- t31 = button && popover ? /* @__PURE__ */ jsxs(Popover, {
574
+ if ($[43] !== flat) {
575
+ t31 = !flat && /* @__PURE__ */ jsx("div", { className: cn("absolute inset-0 rounded-[inherit]", CARD_TOP_EDGE) });
576
+ $[43] = flat;
577
+ $[44] = t31;
578
+ } else t31 = $[44];
579
+ let t32;
580
+ if ($[45] !== t28 || $[46] !== t29 || $[47] !== t31) {
581
+ t32 = /* @__PURE__ */ jsxs("div", {
582
+ ref: surfaceRef,
583
+ "aria-hidden": true,
584
+ className: t28,
585
+ style: t29,
586
+ children: [t30, t31]
587
+ });
588
+ $[45] = t28;
589
+ $[46] = t29;
590
+ $[47] = t31;
591
+ $[48] = t32;
592
+ } else t32 = $[48];
593
+ const t33 = inset || void 0;
594
+ let t34;
595
+ if ($[49] !== t33) {
596
+ t34 = { marginInline: t33 };
597
+ $[49] = t33;
598
+ $[50] = t34;
599
+ } else t34 = $[50];
600
+ let t35;
601
+ if ($[51] !== button || $[52] !== children || $[53] !== covered || $[54] !== popover || $[55] !== popoverOpen || $[56] !== tooltip) {
602
+ t35 = button && popover ? /* @__PURE__ */ jsxs(Popover, {
531
603
  open: popoverOpen,
532
604
  onOpenChange: setPopoverOpen,
533
605
  children: [/* @__PURE__ */ jsx(PopoverTrigger, { render: button }), /* @__PURE__ */ jsx(PopoverContent, {
@@ -544,38 +616,51 @@ function SidebarStackHeader(t0) {
544
616
  className: "truncate px-3 text-(--ancestor-foreground) opacity-(--fade)",
545
617
  children
546
618
  }) : children);
547
- $[41] = button;
548
- $[42] = children;
549
- $[43] = covered;
550
- $[44] = popover;
551
- $[45] = popoverOpen;
552
- $[46] = tooltip;
553
- $[47] = t31;
554
- } else t31 = $[47];
555
- let t32;
556
- if ($[48] !== t19 || $[49] !== t30 || $[50] !== t31) {
557
- t32 = /* @__PURE__ */ jsx("div", {
558
- className: t19,
559
- style: t30,
560
- children: t31
619
+ $[51] = button;
620
+ $[52] = children;
621
+ $[53] = covered;
622
+ $[54] = popover;
623
+ $[55] = popoverOpen;
624
+ $[56] = tooltip;
625
+ $[57] = t35;
626
+ } else t35 = $[57];
627
+ let t36;
628
+ if ($[58] !== t34 || $[59] !== t35) {
629
+ t36 = /* @__PURE__ */ jsx("div", {
630
+ ref: contentRef,
631
+ className: "relative flex min-w-0 flex-1 items-center justify-center self-stretch",
632
+ style: t34,
633
+ children: t35
634
+ });
635
+ $[58] = t34;
636
+ $[59] = t35;
637
+ $[60] = t36;
638
+ } else t36 = $[60];
639
+ let t37;
640
+ if ($[61] !== t16 || $[62] !== t24 || $[63] !== t32 || $[64] !== t36) {
641
+ t37 = /* @__PURE__ */ jsxs("div", {
642
+ className: t16,
643
+ style: t24,
644
+ children: [t32, t36]
561
645
  });
562
- $[48] = t19;
563
- $[49] = t30;
564
- $[50] = t31;
565
- $[51] = t32;
566
- } else t32 = $[51];
567
- let t33;
568
- if ($[52] !== t10 || $[53] !== t32) {
569
- t33 = /* @__PURE__ */ jsx("div", {
646
+ $[61] = t16;
647
+ $[62] = t24;
648
+ $[63] = t32;
649
+ $[64] = t36;
650
+ $[65] = t37;
651
+ } else t37 = $[65];
652
+ let t38;
653
+ if ($[66] !== t11 || $[67] !== t37) {
654
+ t38 = /* @__PURE__ */ jsx("div", {
570
655
  ref,
571
- className: t10,
572
- children: t32
656
+ className: t11,
657
+ children: t37
573
658
  });
574
- $[52] = t10;
575
- $[53] = t32;
576
- $[54] = t33;
577
- } else t33 = $[54];
578
- return t33;
659
+ $[66] = t11;
660
+ $[67] = t37;
661
+ $[68] = t38;
662
+ } else t38 = $[68];
663
+ return t38;
579
664
  }
580
665
 
581
666
  //#endregion
@@ -1,6 +1,6 @@
1
1
  import { CanvasLoadingScreen } from "../../canvas/CanvasLoadingScreen.js";
2
2
  import { previewStore, selectIsCanvasShown } from "../previewStore.js";
3
- import { CanvasSidebarSkeleton } from "../../canvas/sidebar/CanvasSidebarSkeleton.js";
3
+ import { ContentSidebarSkeleton } from "../../canvas/sidebar/ContentSidebarSkeleton.js";
4
4
  import { c } from "react/compiler-runtime";
5
5
  import { useSelector } from "@xstate/store-react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -9,7 +9,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
9
9
  /**
10
10
  * What holds the page's place while the editor loads. The studio never renders the site's code:
11
11
  * a loading screen shows where the page will, in the Canvas's background, until the renderer
12
- * frame shows it. Showing the Canvas before the editor is ready also shows the Canvas sidebar's
12
+ * frame shows it. Showing the Canvas before the editor is ready also shows the Content Sidebar's
13
13
  * placeholder, as the editor does while the Canvas prepares.
14
14
  */
15
15
  function StudioEditingFallback(t0) {
@@ -18,7 +18,7 @@ function StudioEditingFallback(t0) {
18
18
  const isCanvasShown = useSelector(previewStore, selectIsCanvasShown);
19
19
  let t1;
20
20
  if ($[0] !== isCanvasShown || $[1] !== layoutPage) {
21
- t1 = isCanvasShown && /* @__PURE__ */ jsx(CanvasSidebarSkeleton, { layoutPage });
21
+ t1 = isCanvasShown && /* @__PURE__ */ jsx(ContentSidebarSkeleton, { layoutPage });
22
22
  $[0] = isCanvasShown;
23
23
  $[1] = layoutPage;
24
24
  $[2] = t1;
@@ -1,8 +1,32 @@
1
1
  //#region src/features/preview/components/previewStyles.ts
2
+ /**
3
+ * Whether a style or stylesheet is the site's. The studio marks its own, including those it adds
4
+ * to a frame's document, with `data-camox-studio`.
5
+ */
2
6
  function isSiteStyle(element) {
3
7
  return !element.hasAttribute("data-camox-studio");
4
8
  }
5
9
  const EMPTY_PREVIEW_DOCUMENT = "<!doctype html><html><head></head><body><div id=\"root\" data-camox-preview-root></div></body></html>";
10
+ /**
11
+ * The stylesheets of a document's head that are the site document's: not the studio's, nor those
12
+ * React hoists there for the blocks rendering in it (`data-precedence`).
13
+ */
14
+ const SITE_STYLESHEETS = "link[rel~=\"stylesheet\"], style";
15
+ const siteStylesheetsOf = (head) => Array.from(head.querySelectorAll(SITE_STYLESHEETS)).filter((element) => element.parentElement === head && isSiteStyle(element) && !element.hasAttribute("data-precedence"));
16
+ /**
17
+ * Gives a frame's document the site stylesheets of `html`, a site document: the ones it no
18
+ * longer has go, and its new ones are added, the rest of the frame left as it is.
19
+ */
20
+ function restyle(frame, html) {
21
+ const doc = frame.document;
22
+ const { DOMParser } = frame;
23
+ const wanted = siteStylesheetsOf(new DOMParser().parseFromString(html, "text/html").head);
24
+ const held = siteStylesheetsOf(doc.head);
25
+ const wantedMarkup = new Set(wanted.map((element) => element.outerHTML));
26
+ const heldMarkup = new Set(held.map((element) => element.outerHTML));
27
+ for (const element of held) if (!wantedMarkup.has(element.outerHTML)) element.remove();
28
+ for (const element of wanted) if (!heldMarkup.has(element.outerHTML)) doc.head.appendChild(doc.importNode(element, true));
29
+ }
6
30
 
7
31
  //#endregion
8
- export { EMPTY_PREVIEW_DOCUMENT, isSiteStyle };
32
+ export { EMPTY_PREVIEW_DOCUMENT, isSiteStyle, restyle };
@@ -8,6 +8,7 @@ import { PreviewEditingOwnerContext } from "../preview/previewSelection.js";
8
8
  import { StudioNoticeContext } from "../preview/studioNotice.js";
9
9
  import { ContentEditsContext } from "../../core/editing/contentEdits.js";
10
10
  import { PreviewDocumentContext } from "../runtime/PreviewDocumentContext.js";
11
+ import { restyle } from "../preview/components/previewStyles.js";
11
12
  import { FrameContext } from "../preview/components/Frame.js";
12
13
  import { DerivedPageContent } from "../page/DerivedPageContent.js";
13
14
  import { BlockPeek } from "../preview/components/BlockPeek.js";
@@ -425,7 +426,7 @@ function _temp2() {
425
426
  function _temp() {}
426
427
  /** The page at `pathname`, as the runtime renders it in the renderer's draft. */
427
428
  function FramePage(t0) {
428
- const $ = c(20);
429
+ const $ = c(24);
429
430
  const { camoxApp, codeLoaded, projectUuid, runtimeBasePath, pathname, derivedLayoutId, onRendered } = t0;
430
431
  let t1;
431
432
  if ($[0] !== derivedLayoutId || $[1] !== pathname || $[2] !== projectUuid || $[3] !== runtimeBasePath) {
@@ -449,52 +450,69 @@ function FramePage(t0) {
449
450
  } else t1 = $[4];
450
451
  const input = useRead(t1);
451
452
  if (codeLoaded) React.use(codeLoaded);
452
- const rendered = React.useEffectEvent(onRendered);
453
+ const frameWindow = React.use(FrameContext).window;
453
454
  let t2;
454
- if ($[7] !== rendered) {
455
- t2 = () => rendered();
456
- $[7] = rendered;
457
- $[8] = t2;
458
- } else t2 = $[8];
459
455
  let t3;
460
- if ($[9] !== input) {
461
- t3 = [input];
462
- $[9] = input;
456
+ if ($[7] !== frameWindow || $[8] !== input.previewDocument) {
457
+ t2 = () => {
458
+ if (frameWindow && input.previewDocument) restyle(frameWindow, input.previewDocument);
459
+ };
460
+ t3 = [frameWindow, input.previewDocument];
461
+ $[7] = frameWindow;
462
+ $[8] = input.previewDocument;
463
+ $[9] = t2;
463
464
  $[10] = t3;
464
- } else t3 = $[10];
465
- React.useEffect(t2, t3);
466
- const t4 = input.dehydratedState;
465
+ } else {
466
+ t2 = $[9];
467
+ t3 = $[10];
468
+ }
469
+ React.useLayoutEffect(t2, t3);
470
+ const rendered = React.useEffectEvent(onRendered);
471
+ let t4;
472
+ if ($[11] !== rendered) {
473
+ t4 = () => rendered();
474
+ $[11] = rendered;
475
+ $[12] = t4;
476
+ } else t4 = $[12];
467
477
  let t5;
468
- if ($[11] !== camoxApp || $[12] !== input.derived) {
469
- t5 = input.derived ? /* @__PURE__ */ jsx(DerivedPageContent, {
478
+ if ($[13] !== input) {
479
+ t5 = [input];
480
+ $[13] = input;
481
+ $[14] = t5;
482
+ } else t5 = $[14];
483
+ React.useEffect(t4, t5);
484
+ const t6 = input.dehydratedState;
485
+ let t7;
486
+ if ($[15] !== camoxApp || $[16] !== input.derived) {
487
+ t7 = input.derived ? /* @__PURE__ */ jsx(DerivedPageContent, {
470
488
  camoxApp,
471
489
  derived: input.derived
472
490
  }) : /* @__PURE__ */ jsx(EditablePageContent, {});
473
- $[11] = camoxApp;
474
- $[12] = input.derived;
475
- $[13] = t5;
476
- } else t5 = $[13];
477
- let t6;
478
- if ($[14] !== input.previewDocument || $[15] !== t5) {
479
- t6 = /* @__PURE__ */ jsx(PreviewDocumentContext.Provider, {
491
+ $[15] = camoxApp;
492
+ $[16] = input.derived;
493
+ $[17] = t7;
494
+ } else t7 = $[17];
495
+ let t8;
496
+ if ($[18] !== input.previewDocument || $[19] !== t7) {
497
+ t8 = /* @__PURE__ */ jsx(PreviewDocumentContext.Provider, {
480
498
  value: input.previewDocument,
481
- children: t5
482
- });
483
- $[14] = input.previewDocument;
484
- $[15] = t5;
485
- $[16] = t6;
486
- } else t6 = $[16];
487
- let t7;
488
- if ($[17] !== t4 || $[18] !== t6) {
489
- t7 = /* @__PURE__ */ jsx(HydrationBoundary, {
490
- state: t4,
491
- children: t6
499
+ children: t7
492
500
  });
493
- $[17] = t4;
494
- $[18] = t6;
501
+ $[18] = input.previewDocument;
495
502
  $[19] = t7;
496
- } else t7 = $[19];
497
- return t7;
503
+ $[20] = t8;
504
+ } else t8 = $[20];
505
+ let t9;
506
+ if ($[21] !== t6 || $[22] !== t8) {
507
+ t9 = /* @__PURE__ */ jsx(HydrationBoundary, {
508
+ state: t6,
509
+ children: t8
510
+ });
511
+ $[21] = t6;
512
+ $[22] = t8;
513
+ $[23] = t9;
514
+ } else t9 = $[23];
515
+ return t9;
498
516
  }
499
517
  const messageOf = (error) => error instanceof Error ? error.message : String(error);
500
518
  const ERROR_STYLE = {
@@ -23,7 +23,7 @@ export type PageStructure = {
23
23
  };
24
24
  /**
25
25
  * Why a member can't see the draft a URL names: it doesn't exist, it's someone else's
26
- * development draft, or it was published or discarded (ADR 0011). In dev mode, the caller's
26
+ * development draft, or it was published or deleted (ADR 0011). In dev mode, the caller's
27
27
  * own development draft doesn't exist until the dev server's first sync creates it.
28
28
  */
29
29
  export type DraftNotice = {
@@ -4,7 +4,7 @@ import { StudioEditingFallback } from "../preview/components/StudioEditingFallba
4
4
  import { Navbar } from "../studio/components/Navbar.js";
5
5
  import { EditingFallbackContext } from "./editingFallback.js";
6
6
  import { PreviewToolbar } from "../preview/components/PreviewToolbar.js";
7
- import { ChatSidebar } from "../studio/components/ChatSidebar.js";
7
+ import { AgentSidebar } from "../studio/components/AgentSidebar.js";
8
8
  import { FollowAgentProvider } from "../studio/FollowAgentProvider.js";
9
9
  import { c } from "react/compiler-runtime";
10
10
  import { useSelector } from "@xstate/store-react";
@@ -19,7 +19,7 @@ function RuntimeChrome(t0) {
19
19
  const website = !input.routeKind;
20
20
  const hidden = useSelector(previewStore, _temp);
21
21
  const isCanvasShown = useSelector(previewStore, selectIsCanvasShown);
22
- const showChat = website && isCanvasShown;
22
+ const showAgentSidebar = website && isCanvasShown;
23
23
  const t1 = input.runtimeBasePath;
24
24
  let t2;
25
25
  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
@@ -102,10 +102,10 @@ function RuntimeChrome(t0) {
102
102
  $[18] = t9;
103
103
  $[19] = t14;
104
104
  } else t14 = $[19];
105
- const t15 = !showChat;
105
+ const t15 = !showAgentSidebar;
106
106
  let t16;
107
107
  if ($[20] !== t15) {
108
- t16 = /* @__PURE__ */ jsx(ChatSidebar, { hidden: t15 });
108
+ t16 = /* @__PURE__ */ jsx(AgentSidebar, { hidden: t15 });
109
109
  $[20] = t15;
110
110
  $[21] = t16;
111
111
  } else t16 = $[21];
@@ -0,0 +1,56 @@
1
+ import { cn } from "../../../lib/utils.js";
2
+ import { SIDEBAR_GUTTER } from "../../preview/components/SidebarStack.js";
3
+ import { ChatWidget } from "./ChatWidget.js";
4
+ import { Patrol } from "./Patrol.js";
5
+ import { c } from "react/compiler-runtime";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+
8
+ //#region src/features/studio/components/AgentSidebar.tsx
9
+ /**
10
+ * The sidebar on the Canvas's right side, where editors work with Camox's agent: the Patrol
11
+ * over the Chat widget, which gets the larger share of the height. Laid over the Canvas,
12
+ * as the Content Sidebar is over its left: only the cards have a background, and the Canvas shows
13
+ * around them. Elsewhere in the studio it is only hidden, so the chat keeps its thread and the
14
+ * Preview and Studio pages follow the editor's runs too.
15
+ */
16
+ function AgentSidebar(t0) {
17
+ const $ = c(6);
18
+ const { hidden: t1 } = t0;
19
+ const hidden = t1 === void 0 ? false : t1;
20
+ let t2;
21
+ let t3;
22
+ let t4;
23
+ let t5;
24
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25
+ t2 = cn("absolute inset-y-0 right-0 z-10 flex flex-col gap-2 py-2 max-md:hidden", SIDEBAR_GUTTER);
26
+ t3 = { width: 265 };
27
+ t4 = /* @__PURE__ */ jsx(Patrol, { className: "min-h-0 flex-[3_1_0]" });
28
+ t5 = /* @__PURE__ */ jsx(ChatWidget, { className: "min-h-0 flex-[7_1_0]" });
29
+ $[0] = t2;
30
+ $[1] = t3;
31
+ $[2] = t4;
32
+ $[3] = t5;
33
+ } else {
34
+ t2 = $[0];
35
+ t3 = $[1];
36
+ t4 = $[2];
37
+ t5 = $[3];
38
+ }
39
+ let t6;
40
+ if ($[4] !== hidden) {
41
+ t6 = /* @__PURE__ */ jsxs("aside", {
42
+ "aria-label": "Agent",
43
+ "data-agent-sidebar": true,
44
+ hidden,
45
+ className: t2,
46
+ style: t3,
47
+ children: [t4, t5]
48
+ });
49
+ $[4] = hidden;
50
+ $[5] = t6;
51
+ } else t6 = $[5];
52
+ return t6;
53
+ }
54
+
55
+ //#endregion
56
+ export { AgentSidebar };