camox 0.69.0 → 0.72.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 (89) hide show
  1. package/dist/core/createApp.d.ts +4 -103
  2. package/dist/core/createApp.js +3 -24
  3. package/dist/core/createBlock.d.ts +2 -2
  4. package/dist/core/createBlock.js +55 -192
  5. package/dist/core/createLayout.d.ts +6 -77
  6. package/dist/core/createLayout.js +12 -50
  7. package/dist/core/editing/createEditableBlock.d.ts +9 -75
  8. package/dist/core/editing/createEditableBlock.js +258 -640
  9. package/dist/core/hooks/useArtifactHost.js +56 -46
  10. package/dist/core/hooks/useIsEditable.js +2 -2
  11. package/dist/core/lib/artifact.d.ts +4 -0
  12. package/dist/core/lib/artifactData.js +8 -3
  13. package/dist/core/lib/artifactHost.js +40 -0
  14. package/dist/core/lib/artifactRuntime.js +20 -1
  15. package/dist/core/lib/contentType.d.ts +23 -38
  16. package/dist/core/lib/contentType.js +34 -62
  17. package/dist/core/lib/iconTypes.d.ts +0 -3
  18. package/dist/core/lib/icons.js +63 -51
  19. package/dist/core/lib/recordScope.js +1 -1
  20. package/dist/features/canvas/CanvasOverlays.js +94 -176
  21. package/dist/features/canvas/CanvasPageFrame.js +62 -68
  22. package/dist/features/canvas/CanvasPreviewPageSlot.js +1 -3
  23. package/dist/features/canvas/canvasOverlayGeometry.js +1 -7
  24. package/dist/features/canvas/sidebar/CuratedPageInspector.js +3 -21
  25. package/dist/features/canvas/sidebar/LayoutPageBlocks.js +1 -2
  26. package/dist/features/canvas/useCanvasCamera.js +1 -1
  27. package/dist/features/canvas/useCanvasFrame.js +1 -1
  28. package/dist/features/content/ContentCollection.js +2 -2
  29. package/dist/features/content/collection-form.js +6 -7
  30. package/dist/features/page/CuratedPageContent.js +15 -24
  31. package/dist/features/page/UnplacedBlockContent.js +1 -6
  32. package/dist/features/preview/CamoxPreview.js +30 -33
  33. package/dist/features/preview/EditablePageContent.js +131 -151
  34. package/dist/features/preview/components/BlockActionsPopover.js +43 -152
  35. package/dist/features/preview/components/CanvasPreview.js +2 -2
  36. package/dist/features/preview/components/Frame.js +3 -3
  37. package/dist/features/preview/components/IconFieldEditor.js +1 -1
  38. package/dist/features/preview/components/ItemFieldsEditor.js +1 -3
  39. package/dist/features/preview/components/Overlays.js +18 -84
  40. package/dist/features/preview/components/PageTree.js +57 -103
  41. package/dist/features/preview/components/PreviewPanel.js +8 -11
  42. package/dist/features/preview/components/RecordCombobox.js +65 -78
  43. package/dist/features/preview/components/ReferenceFieldEditor.js +1 -19
  44. package/dist/features/preview/components/ReferenceListFieldEditor.js +1 -19
  45. package/dist/features/preview/components/RemovedBlockPlaceholder.js +2 -2
  46. package/dist/features/preview/components/SelectionEditor.js +5 -4
  47. package/dist/features/preview/components/useRepeatableItemActions.js +18 -24
  48. package/dist/features/preview/components/useUpdateBlockPosition.js +1 -1
  49. package/dist/features/preview/overlayMessages.js +1 -4
  50. package/dist/features/preview/previewStore.js +3 -23
  51. package/dist/features/renderer/RendererApp.js +17 -141
  52. package/dist/features/renderer/definitionAnswers.js +1 -8
  53. package/dist/features/renderer/rendererHost.js +1 -31
  54. package/dist/features/renderer/studioConnection.js +1 -25
  55. package/dist/features/runtime/pageApp.js +8 -4
  56. package/dist/features/runtime/runtime.js +3 -3
  57. package/dist/features/studio/agentRunToast.js +71 -0
  58. package/dist/features/studio/components/ChatWidget.js +2 -0
  59. package/dist/features/studio/components/DraftBar.js +2 -3
  60. package/dist/features/studio/components/DraftsControl.js +150 -176
  61. package/dist/features/studio/components/ReviewDraftSheet.js +344 -548
  62. package/dist/features/studio/components/ThreadMessages.js +89 -22
  63. package/dist/features/studio/draftLabel.js +1 -1
  64. package/dist/features/studio/studioStore.js +5 -17
  65. package/dist/features/studio/viewSwitch.js +2 -4
  66. package/dist/features/vite/blockBoilerplate.js +1 -1
  67. package/dist/features/vite/definitionsSync.js +1 -8
  68. package/dist/lib/queries.js +0 -1
  69. package/dist/lib/studio-definitions.js +0 -2
  70. package/dist/lib/studio-reads.js +0 -5
  71. package/dist/lib/use-thread.js +196 -138
  72. package/dist/package.js +1 -1
  73. package/dist/studio-overlays.css +0 -29
  74. package/dist/studio.css +1 -1
  75. package/package.json +6 -4
  76. package/skills/camox/SKILL.md +1 -1
  77. package/skills/camox/references/artifacts.md +89 -5
  78. package/skills/camox/references/block-definitions.md +21 -25
  79. package/skills/camox/references/dom-integrations.md +1 -1
  80. package/skills/camox/references/layout-definitions.md +3 -12
  81. package/skills/camox/references/routed-layouts.md +2 -2
  82. package/skills/camox-expand/SKILL.md +5 -5
  83. package/skills/camoxify/SKILL.md +4 -4
  84. package/dist/features/canvas/canvasInsertionSeams.js +0 -44
  85. package/dist/features/preview/components/AddBlockSheet.js +0 -314
  86. package/dist/features/preview/components/BlockPeek.js +0 -66
  87. package/dist/features/preview/components/BlockThumbnail.js +0 -281
  88. package/dist/features/preview/components/blockGridNavigation.js +0 -15
  89. package/dist/features/preview/referencePickerFocus.js +0 -29
@@ -18,7 +18,8 @@ import { MessageScroller, MessageScrollerButton, MessageScrollerContent, Message
18
18
  * agent does, never how: thinking, looking around, making changes, building, fixing the build,
19
19
  * or starting a draft. Each editor's message shows its
20
20
  * sender's avatar, without their name. A Live turn handed off to a draft ends on the draft's
21
- * card, which `onOpenDraft` opens. The thread keeps its end in view, unless the editor scrolls up.
21
+ * card, which `onOpenDraft` opens, and the draft's thread shows the hand-off's Brief collapsed
22
+ * under the editor's messages. The thread keeps its end in view, unless the editor scrolls up.
22
23
  */
23
24
  function ThreadMessages(t0) {
24
25
  const $ = c(20);
@@ -297,7 +298,7 @@ const PUSH_OUTCOMES = {
297
298
  notPreviewed: "Built, but the preview can’t show it."
298
299
  };
299
300
  function ThreadMessageRow(t0) {
300
- const $ = c(44);
301
+ const $ = c(46);
301
302
  const { message, onOpenDraft } = t0;
302
303
  if (message.from === "draft") {
303
304
  let t1;
@@ -438,54 +439,63 @@ function ThreadMessageRow(t0) {
438
439
  } else t5 = $[33];
439
440
  return t5;
440
441
  }
442
+ if (message.from === "brief") {
443
+ let t1;
444
+ if ($[34] !== message.text) {
445
+ t1 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(BriefNote, { text: message.text }) }) });
446
+ $[34] = message.text;
447
+ $[35] = t1;
448
+ } else t1 = $[35];
449
+ return t1;
450
+ }
441
451
  if (message.from === "camox") {
442
452
  let t1;
443
- if ($[34] === Symbol.for("react.memo_cache_sentinel")) {
453
+ if ($[36] === Symbol.for("react.memo_cache_sentinel")) {
444
454
  t1 = /* @__PURE__ */ jsx(MessageHeader, {
445
455
  className: "text-muted-foreground text-xs",
446
456
  children: "Camox"
447
457
  });
448
- $[34] = t1;
449
- } else t1 = $[34];
458
+ $[36] = t1;
459
+ } else t1 = $[36];
450
460
  let t2;
451
- if ($[35] !== message.text) {
461
+ if ($[37] !== message.text) {
452
462
  t2 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsxs(MessageContent, { children: [t1, /* @__PURE__ */ jsx(Bubble, {
453
463
  variant: "muted",
454
464
  className: "max-w-full",
455
465
  children: /* @__PURE__ */ jsx(BubbleContent, { children: /* @__PURE__ */ jsx(CroppedText, { text: message.text }) })
456
466
  })] }) });
457
- $[35] = message.text;
458
- $[36] = t2;
459
- } else t2 = $[36];
467
+ $[37] = message.text;
468
+ $[38] = t2;
469
+ } else t2 = $[38];
460
470
  return t2;
461
471
  }
462
472
  let t1;
463
- if ($[37] !== message.sender) {
473
+ if ($[39] !== message.sender) {
464
474
  t1 = /* @__PURE__ */ jsx(MessageAvatar, { children: /* @__PURE__ */ jsx(SenderAvatar, { sender: message.sender }) });
465
- $[37] = message.sender;
466
- $[38] = t1;
467
- } else t1 = $[38];
475
+ $[39] = message.sender;
476
+ $[40] = t1;
477
+ } else t1 = $[40];
468
478
  let t2;
469
- if ($[39] !== message.text) {
479
+ if ($[41] !== message.text) {
470
480
  t2 = /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(Bubble, {
471
481
  align: "end",
472
482
  variant: "muted",
473
483
  className: "max-w-full",
474
484
  children: /* @__PURE__ */ jsx(BubbleContent, { children: /* @__PURE__ */ jsx(CroppedText, { text: message.text }) })
475
485
  }) });
476
- $[39] = message.text;
477
- $[40] = t2;
478
- } else t2 = $[40];
486
+ $[41] = message.text;
487
+ $[42] = t2;
488
+ } else t2 = $[42];
479
489
  let t3;
480
- if ($[41] !== t1 || $[42] !== t2) {
490
+ if ($[43] !== t1 || $[44] !== t2) {
481
491
  t3 = /* @__PURE__ */ jsxs(Message, {
482
492
  align: "end",
483
493
  children: [t1, t2]
484
494
  });
485
- $[41] = t1;
486
- $[42] = t2;
487
- $[43] = t3;
488
- } else t3 = $[43];
495
+ $[43] = t1;
496
+ $[44] = t2;
497
+ $[45] = t3;
498
+ } else t3 = $[45];
489
499
  return t3;
490
500
  }
491
501
  function _temp(subject, index) {
@@ -575,6 +585,63 @@ function CroppedText(t0) {
575
585
  } else t9 = $[16];
576
586
  return t9;
577
587
  }
588
+ /**
589
+ * The Brief the agent on Live handed the request off with, under the editor's messages: a quiet
590
+ * line, so the request reads on as they sent it, which shows it once clicked.
591
+ */
592
+ function BriefNote(t0) {
593
+ const $ = c(10);
594
+ const { text } = t0;
595
+ const [open, setOpen] = React.useState(false);
596
+ let t1;
597
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
598
+ t1 = () => setOpen(_temp2);
599
+ $[0] = t1;
600
+ } else t1 = $[0];
601
+ const t2 = open ? "Hide the brief" : "Camox briefed the agent";
602
+ let t3;
603
+ if ($[1] !== open || $[2] !== t2) {
604
+ t3 = /* @__PURE__ */ jsx("button", {
605
+ type: "button",
606
+ "aria-expanded": open,
607
+ onClick: t1,
608
+ className: "focus-visible:ring-ring self-start rounded-sm hover:underline focus-visible:ring-2 focus-visible:outline-none",
609
+ children: t2
610
+ });
611
+ $[1] = open;
612
+ $[2] = t2;
613
+ $[3] = t3;
614
+ } else t3 = $[3];
615
+ let t4;
616
+ if ($[4] !== open || $[5] !== text) {
617
+ t4 = open && /* @__PURE__ */ jsx(Bubble, {
618
+ variant: "muted",
619
+ className: "max-w-full",
620
+ children: /* @__PURE__ */ jsx(BubbleContent, { children: /* @__PURE__ */ jsx("div", {
621
+ className: "whitespace-pre-wrap",
622
+ children: text
623
+ }) })
624
+ });
625
+ $[4] = open;
626
+ $[5] = text;
627
+ $[6] = t4;
628
+ } else t4 = $[6];
629
+ let t5;
630
+ if ($[7] !== t3 || $[8] !== t4) {
631
+ t5 = /* @__PURE__ */ jsxs("div", {
632
+ "data-thread-brief": true,
633
+ className: "text-muted-foreground flex flex-col gap-2 text-xs",
634
+ children: [t3, t4]
635
+ });
636
+ $[7] = t3;
637
+ $[8] = t4;
638
+ $[9] = t5;
639
+ } else t5 = $[9];
640
+ return t5;
641
+ }
642
+ function _temp2(current) {
643
+ return !current;
644
+ }
578
645
  const initials = (name) => name.split(" ").map((part) => part[0]).join("").toUpperCase().slice(0, 2);
579
646
  const DRAFT_CARD_CLASSES = "bg-muted/50 flex w-full flex-col items-start gap-0.5 rounded-lg border px-3 py-2 text-left text-sm";
580
647
  /**
@@ -4,7 +4,7 @@ const dayFormat = new Intl.DateTimeFormat(void 0, {
4
4
  day: "numeric"
5
5
  });
6
6
  /**
7
- * A draft's name, or for an unnamed draft its creator and creation date formatted for the
7
+ * A draft's name, or for a draft not named yet its creator and creation date formatted for the
8
8
  * viewer, e.g. "Rémi, Oct 13".
9
9
  */
10
10
  function draftLabel(draft) {
@@ -5,10 +5,7 @@ const studioStore = createStore({
5
5
  context: {
6
6
  isCommandPaletteOpen: false,
7
7
  commandPalettePages: [],
8
- reviewDraftSheet: {
9
- open: false,
10
- startRenaming: false
11
- },
8
+ isReviewDraftSheetOpen: false,
12
9
  isDeleteDraftDialogOpen: false,
13
10
  localeDialog: null,
14
11
  websiteLocation: null,
@@ -48,22 +45,16 @@ const studioStore = createStore({
48
45
  commandPalettePages: context.commandPalettePages.slice(0, -1)
49
46
  };
50
47
  },
51
- openReviewDraftSheet: (context, event) => {
48
+ openReviewDraftSheet: (context) => {
52
49
  return {
53
50
  ...context,
54
- reviewDraftSheet: {
55
- open: true,
56
- startRenaming: event.startRenaming ?? false
57
- }
51
+ isReviewDraftSheetOpen: true
58
52
  };
59
53
  },
60
54
  closeReviewDraftSheet: (context) => {
61
55
  return {
62
56
  ...context,
63
- reviewDraftSheet: {
64
- open: false,
65
- startRenaming: false
66
- }
57
+ isReviewDraftSheetOpen: false
67
58
  };
68
59
  },
69
60
  openDeleteDraftDialog: (context) => {
@@ -93,10 +84,7 @@ const studioStore = createStore({
93
84
  askAgent: (context, event) => {
94
85
  return {
95
86
  ...context,
96
- reviewDraftSheet: {
97
- open: false,
98
- startRenaming: false
99
- },
87
+ isReviewDraftSheetOpen: false,
100
88
  agentAsk: {
101
89
  text: event.text,
102
90
  id: context.agentAsks + 1
@@ -41,13 +41,11 @@ function useLeaveDraft() {
41
41
  const shown = useViewShown();
42
42
  let t0;
43
43
  if ($[0] !== draftScope || $[1] !== shown) {
44
- t0 = (ended, t1) => {
45
- const { discarded: t2 } = t1 === void 0 ? {} : t1;
46
- const discarded = t2 === void 0 ? false : t2;
44
+ t0 = (ended) => {
47
45
  if (ended && draftScope.current() !== ended.draftId) return;
48
46
  draftScope.leave(ended);
49
47
  if (!ended) return;
50
- const what = discarded ? "Changes discarded" : `Draft ${ended.outcome}`;
48
+ const what = `Draft ${ended.outcome}`;
51
49
  toastSwitch(shown(), {
52
50
  loading: `${what}. Switching to Live…`,
53
51
  success: `${what}. You're now viewing Live.`
@@ -24,7 +24,7 @@ const ${camelName} = createBlock({
24
24
  title: "${kebabToTitle(name)}",
25
25
  description: "Describe when the AI should use this block.",
26
26
  content: (field) => ({
27
- title: field.string({ default: "Title" }),
27
+ title: field.string(),
28
28
  }),
29
29
  toReact: ${pascalName}Component,
30
30
  toTitle: ({ content }) => content.title,
@@ -54,14 +54,7 @@ async function syncDefinitionsToApi(options) {
54
54
  const unused = layoutSyncResults.deletedDefinitionTypes;
55
55
  if (unused.length > 0) logger.info(`[camox] Removed ${counted(unused.length, "layoutOnly block definition")} (no layout uses ${unused.length === 1 ? "it" : "them"} anymore): ${quoted(unused)}`, { timestamp: true });
56
56
  }
57
- const { homepage } = definitionSet;
58
- if (homepage && result.homepage?.created) {
59
- if (homepage.hasInitialBlocks) logger.info(`[camox] Initialized content: homepage with ${counted(result.homepage.blockCount, "block")}`, { timestamp: true });
60
- else {
61
- logger.info("[camox] Created empty homepage (using first layout)", { timestamp: true });
62
- logger.info("[camox] Tip: add blocks.initial to your layout to pre-populate pages with content", { timestamp: true });
63
- }
64
- }
57
+ if (definitionSet.homepage && result.homepage?.created) logger.info(`[camox] Created an empty homepage with the "${definitionSet.homepage.layoutId}" layout`, { timestamp: true });
65
58
  }
66
59
  const VIRTUAL_CAMOX_APP = "virtual:camox/app";
67
60
  const RESOLVED_VIRTUAL_CAMOX_APP = "\0virtual:camox/app";
@@ -66,7 +66,6 @@ const localeMutations = {
66
66
  addBack: () => getOrpc().locales.addBack.mutationOptions()
67
67
  };
68
68
  const blockMutations = {
69
- create: () => getOrpc().blocks.create.mutationOptions(),
70
69
  delete: () => getOrpc().blocks.delete.mutationOptions(),
71
70
  deleteMany: () => getOrpc().blocks.deleteMany.mutationOptions(),
72
71
  duplicate: () => getOrpc().blocks.duplicate.mutationOptions(),
@@ -9,8 +9,6 @@ const toBlockDefinitions = (rows) => rows.map((row) => ({
9
9
  description: row.description,
10
10
  contentSchema: row.contentSchema,
11
11
  settingsSchema: row.settingsSchema ?? void 0,
12
- defaultContent: row.defaultContent ?? {},
13
- defaultSettings: row.defaultSettings ?? {},
14
12
  layoutOnly: !!row.layoutOnly,
15
13
  synced: row.synced
16
14
  }));
@@ -157,11 +157,6 @@ const reads = {
157
157
  fetch: async ({ api, signal }, id) => (await api.files.getUsageCount({ id }, { signal })).count,
158
158
  staleTime: Infinity
159
159
  }),
160
- blockUsageCounts: entry({
161
- key: () => usageCountsPrefix,
162
- fetch: async ({ api, signal }, { projectId }) => Object.fromEntries((await api.blocks.getUsageCounts({ projectId }, { signal })).map(({ type, count }) => [type, count])),
163
- staleTime: Infinity
164
- }),
165
160
  pageMarkdown: entry({
166
161
  key: (pageId) => queryKeys.blocks.getPageMarkdown(pageId),
167
162
  fetch: async ({ api, signal }, pageId) => (await api.blocks.getPageMarkdown({ pageId }, { signal })).markdown,