camox 0.47.0 → 0.51.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 (117) hide show
  1. package/dist/core/createApp.d.ts +19 -6
  2. package/dist/core/createApp.js +7 -2
  3. package/dist/core/createBlock.js +54 -43
  4. package/dist/core/createCollection.d.ts +25 -7
  5. package/dist/core/createCollection.js +28 -9
  6. package/dist/core/createLayout.d.ts +98 -71
  7. package/dist/core/createLayout.js +10 -16
  8. package/dist/core/derivedRoutes.js +1 -1
  9. package/dist/core/editing/BlockEditingRuntime.d.ts +3 -2
  10. package/dist/core/editing/CompleteBlockEditingRuntime.js +2 -1
  11. package/dist/core/editing/createEditableBlock.d.ts +59 -19
  12. package/dist/core/editing/createEditableBlock.js +162 -151
  13. package/dist/core/editing/useLatestRecord.js +7 -7
  14. package/dist/core/layoutContext.d.ts +55 -0
  15. package/dist/core/layoutContext.js +66 -0
  16. package/dist/core/lib/contentType.d.ts +91 -4
  17. package/dist/core/lib/contentType.js +84 -7
  18. package/dist/core/lib/recordScope.js +19 -17
  19. package/dist/core/lib/reference.d.ts +6 -2
  20. package/dist/core/recordItem.js +55 -2
  21. package/dist/core/requestContext.d.ts +18 -0
  22. package/dist/core/structuredData.d.ts +126 -0
  23. package/dist/core/structuredData.js +40 -0
  24. package/dist/features/canvas/canvasCamera.js +1 -1
  25. package/dist/features/canvas/sidebar/CanvasInspector.js +1 -1
  26. package/dist/features/canvas/sidebar/CanvasSidebarFrame.js +1 -1
  27. package/dist/features/content/ContentAssets.js +84 -88
  28. package/dist/features/content/ContentCollection.js +13 -7
  29. package/dist/features/content/collection-form.js +6 -2
  30. package/dist/features/content/components/MissingFromLocale.js +1 -1
  31. package/dist/features/og/pageImage.js +89 -0
  32. package/dist/features/page/CuratedPageContent.js +45 -32
  33. package/dist/features/page/DerivedPageContent.js +49 -22
  34. package/dist/features/page/SharedLayoutContent.js +26 -22
  35. package/dist/features/preview/CamoxPreview.js +41 -27
  36. package/dist/features/preview/EditablePageExperience.js +17 -9
  37. package/dist/features/preview/components/AddBlockSheet.js +1 -0
  38. package/dist/features/preview/components/BlockActionsPopover.js +19 -41
  39. package/dist/features/preview/components/FieldToolbar.js +1 -1
  40. package/dist/features/preview/components/MobilePreviewDrawer.js +6 -9
  41. package/dist/features/preview/components/PageInfo.js +244 -264
  42. package/dist/features/preview/components/PageTree.js +63 -53
  43. package/dist/features/preview/components/PreviewPanel.js +10 -64
  44. package/dist/features/preview/components/PreviewToolbar.js +1 -1
  45. package/dist/features/preview/components/RecordCard.js +50 -34
  46. package/dist/features/preview/components/RecordCombobox.js +12 -5
  47. package/dist/features/preview/components/ReferenceFieldEditor.js +4 -2
  48. package/dist/features/preview/components/ReferenceListFieldEditor.js +24 -19
  49. package/dist/features/preview/components/RepeatableItemsList.js +62 -46
  50. package/dist/features/preview/components/SelectionEditor.js +3 -2
  51. package/dist/features/preview/components/useFieldWriter.js +2 -4
  52. package/dist/features/preview/components/useRecordView.js +2 -2
  53. package/dist/features/preview/entityName.js +11 -0
  54. package/dist/features/preview/pageRecord.js +17 -18
  55. package/dist/features/preview/previewConstants.js +2 -8
  56. package/dist/features/preview/usePreviewViewportActions.js +1 -1
  57. package/dist/features/provider/AuthenticatedCamoxProvider.js +1 -1
  58. package/dist/features/provider/components/CommandPalette.js +2 -5
  59. package/dist/features/provider/signInShortcut.js +1 -2
  60. package/dist/features/provider/useAdminShortcuts.js +47 -53
  61. package/dist/features/routes/pageRuntime.d.ts +17 -2
  62. package/dist/features/routes/pageRuntime.js +61 -57
  63. package/dist/features/runtime/RuntimeChrome.js +1 -1
  64. package/dist/features/runtime/breadcrumbs.js +68 -0
  65. package/dist/features/runtime/livePages.js +3 -2
  66. package/dist/features/runtime/pageGraph.js +92 -0
  67. package/dist/features/runtime/projectLogo.js +110 -0
  68. package/dist/features/runtime/publicCache.js +83 -0
  69. package/dist/features/runtime/runtime.d.ts +24 -9
  70. package/dist/features/runtime/runtime.js +447 -130
  71. package/dist/features/runtime/runtimeRoutes.d.ts +1 -0
  72. package/dist/features/runtime/runtimeRoutes.js +1 -0
  73. package/dist/features/runtime/structuredData.js +213 -0
  74. package/dist/features/runtime/worker.d.ts +5 -1
  75. package/dist/features/runtime/worker.js +20 -3
  76. package/dist/features/settings/AnalyticsSettings.js +622 -0
  77. package/dist/features/settings/CamoxSettings.js +95 -0
  78. package/dist/features/settings/FaviconSettings.js +254 -0
  79. package/dist/features/settings/ProjectNameSettings.js +145 -0
  80. package/dist/features/settings/SettingsPart.js +73 -0
  81. package/dist/features/settings/SocialProfilesSettings.js +245 -0
  82. package/dist/features/settings/useProjectMutation.js +61 -0
  83. package/dist/features/studio/components/ChatSidebar.js +5 -5
  84. package/dist/features/studio/components/DraftsControl.js +136 -131
  85. package/dist/features/studio/components/LocalePicker.js +178 -174
  86. package/dist/features/studio/components/Navbar.js +107 -66
  87. package/dist/features/studio/components/ProjectMenu.js +85 -110
  88. package/dist/features/studio/components/ReviewDraftSheet.js +1046 -990
  89. package/dist/features/studio/components/ThreadMessages.js +2 -2
  90. package/dist/features/studio/components/UserButton.js +1 -1
  91. package/dist/features/studio/routes.js +3 -1
  92. package/dist/features/studio/showInCanvas.js +129 -0
  93. package/dist/features/vite/blockBoilerplate.js +3 -2
  94. package/dist/features/vite/definitionsSync.js +4 -5
  95. package/dist/features/vite/layoutGeneration.js +3 -2
  96. package/dist/features/vite/runtimeDev.js +32 -17
  97. package/dist/features/vite/staticAssetHeaders.js +52 -0
  98. package/dist/features/vite/vite.d.ts +1 -1
  99. package/dist/features/vite/vite.js +17 -4
  100. package/dist/lib/api-client-server.d.ts +1 -1
  101. package/dist/lib/api-client.d.ts +2 -1
  102. package/dist/lib/draft-scope.d.ts +1 -0
  103. package/dist/lib/locale-path.d.ts +3 -11
  104. package/dist/lib/locale-path.js +3 -27
  105. package/dist/lib/queries.d.ts +4 -0
  106. package/dist/lib/queries.js +8 -1
  107. package/dist/lib/shortcuts.js +29 -0
  108. package/dist/lib/studio-reads.d.ts +1 -0
  109. package/dist/lib/studio-reads.js +3 -1
  110. package/dist/lib/utils.js +1 -104
  111. package/dist/package.js +1 -1
  112. package/dist/studio.css +1 -1
  113. package/package.json +6 -4
  114. package/skills/camox/references/block-definitions.md +105 -25
  115. package/skills/camox/references/layout-definitions.md +53 -17
  116. package/skills/camox/references/routed-layouts.md +17 -14
  117. package/dist/features/studio/components/FaviconDialog.js +0 -318
@@ -4,6 +4,7 @@ import { cn } from "../../../lib/utils.js";
4
4
  import { previewStore, selectionBlockId, selectionForOwner } from "../previewStore.js";
5
5
  import { useEditingFrame } from "../editingFrame.js";
6
6
  import { PreviewEditingOwnerContext } from "../previewSelection.js";
7
+ import { entityName } from "../entityName.js";
7
8
  import { useUpdateBlockPosition } from "./useUpdateBlockPosition.js";
8
9
  import { BlockActionsPopover } from "./BlockActionsPopover.js";
9
10
  import { usePreviewedPage } from "../CamoxPreview.js";
@@ -228,7 +229,7 @@ const animateLayoutChanges = (args) => {
228
229
  return defaultAnimateLayoutChanges(args);
229
230
  };
230
231
  const SortableBlock = (t0) => {
231
- const $ = c(37);
232
+ const $ = c(39);
232
233
  const { block } = t0;
233
234
  const [gripPopoverOpen, setGripPopoverOpen] = React.useState(false);
234
235
  let t1;
@@ -291,9 +292,13 @@ const SortableBlock = (t0) => {
291
292
  $[12] = t7;
292
293
  } else t7 = $[12];
293
294
  const gripButton = t7;
294
- let t8;
295
+ const t8 = ctx.shouldShowHover;
296
+ const t9 = ctx.shouldShowActive;
297
+ const t10 = ctx.handleBlockMouseEnter;
298
+ const t11 = ctx.handleBlockMouseLeave;
299
+ let t12;
295
300
  if ($[13] !== block || $[14] !== gripButton || $[15] !== gripPopoverOpen) {
296
- t8 = /* @__PURE__ */ jsx(BlockActionsPopover, {
301
+ t12 = /* @__PURE__ */ jsx(BlockActionsPopover, {
297
302
  block,
298
303
  open: gripPopoverOpen,
299
304
  onOpenChange: setGripPopoverOpen,
@@ -302,67 +307,72 @@ const SortableBlock = (t0) => {
302
307
  $[13] = block;
303
308
  $[14] = gripButton;
304
309
  $[15] = gripPopoverOpen;
305
- $[16] = t8;
306
- } else t8 = $[16];
307
- const t9 = block.summary || block.type;
308
- let t10;
309
- if ($[17] !== ctx.toggleSelection || $[18] !== t9) {
310
- t10 = /* @__PURE__ */ jsx(BlockTreeItemTrigger, {
311
- displayText: t9,
310
+ $[16] = t12;
311
+ } else t12 = $[16];
312
+ let t13;
313
+ if ($[17] !== block) {
314
+ t13 = entityName(block, block.type);
315
+ $[17] = block;
316
+ $[18] = t13;
317
+ } else t13 = $[18];
318
+ let t14;
319
+ if ($[19] !== ctx.toggleSelection || $[20] !== t13) {
320
+ t14 = /* @__PURE__ */ jsx(BlockTreeItemTrigger, {
321
+ displayText: t13,
312
322
  onClick: ctx.toggleSelection
313
323
  });
314
- $[17] = ctx.toggleSelection;
315
- $[18] = t9;
316
- $[19] = t10;
317
- } else t10 = $[19];
318
- let t11;
319
- if ($[20] !== ctx.ellipsisPopoverOpen) {
320
- t11 = /* @__PURE__ */ jsx(BlockTreeItemEllipsis, { open: ctx.ellipsisPopoverOpen });
321
- $[20] = ctx.ellipsisPopoverOpen;
322
- $[21] = t11;
323
- } else t11 = $[21];
324
- let t12;
325
- if ($[22] !== block || $[23] !== ctx.ellipsisPopoverOpen || $[24] !== ctx.setEllipsisPopoverOpen || $[25] !== t11) {
326
- t12 = /* @__PURE__ */ jsx(BlockActionsPopover, {
324
+ $[19] = ctx.toggleSelection;
325
+ $[20] = t13;
326
+ $[21] = t14;
327
+ } else t14 = $[21];
328
+ let t15;
329
+ if ($[22] !== ctx.ellipsisPopoverOpen) {
330
+ t15 = /* @__PURE__ */ jsx(BlockTreeItemEllipsis, { open: ctx.ellipsisPopoverOpen });
331
+ $[22] = ctx.ellipsisPopoverOpen;
332
+ $[23] = t15;
333
+ } else t15 = $[23];
334
+ let t16;
335
+ if ($[24] !== block || $[25] !== ctx.ellipsisPopoverOpen || $[26] !== ctx.setEllipsisPopoverOpen || $[27] !== t15) {
336
+ t16 = /* @__PURE__ */ jsx(BlockActionsPopover, {
327
337
  block,
328
338
  open: ctx.ellipsisPopoverOpen,
329
339
  onOpenChange: ctx.setEllipsisPopoverOpen,
330
- children: t11
340
+ children: t15
331
341
  });
332
- $[22] = block;
333
- $[23] = ctx.ellipsisPopoverOpen;
334
- $[24] = ctx.setEllipsisPopoverOpen;
335
- $[25] = t11;
336
- $[26] = t12;
337
- } else t12 = $[26];
338
- let t13;
339
- if ($[27] !== ctx.handleBlockMouseEnter || $[28] !== ctx.handleBlockMouseLeave || $[29] !== ctx.shouldShowActive || $[30] !== ctx.shouldShowHover || $[31] !== setNodeRef || $[32] !== style || $[33] !== t10 || $[34] !== t12 || $[35] !== t8) {
340
- t13 = /* @__PURE__ */ jsxs(BlockTreeItemHeader, {
342
+ $[24] = block;
343
+ $[25] = ctx.ellipsisPopoverOpen;
344
+ $[26] = ctx.setEllipsisPopoverOpen;
345
+ $[27] = t15;
346
+ $[28] = t16;
347
+ } else t16 = $[28];
348
+ let t17;
349
+ if ($[29] !== ctx.handleBlockMouseEnter || $[30] !== ctx.handleBlockMouseLeave || $[31] !== ctx.shouldShowActive || $[32] !== ctx.shouldShowHover || $[33] !== setNodeRef || $[34] !== style || $[35] !== t12 || $[36] !== t14 || $[37] !== t16) {
350
+ t17 = /* @__PURE__ */ jsxs(BlockTreeItemHeader, {
341
351
  ref: setNodeRef,
342
352
  style,
343
353
  className: "group",
344
- shouldShowHover: ctx.shouldShowHover,
345
- shouldShowActive: ctx.shouldShowActive,
346
- onMouseEnter: ctx.handleBlockMouseEnter,
347
- onMouseLeave: ctx.handleBlockMouseLeave,
354
+ shouldShowHover: t8,
355
+ shouldShowActive: t9,
356
+ onMouseEnter: t10,
357
+ onMouseLeave: t11,
348
358
  children: [
349
- t8,
350
- t10,
351
- t12
359
+ t12,
360
+ t14,
361
+ t16
352
362
  ]
353
363
  });
354
- $[27] = ctx.handleBlockMouseEnter;
355
- $[28] = ctx.handleBlockMouseLeave;
356
- $[29] = ctx.shouldShowActive;
357
- $[30] = ctx.shouldShowHover;
358
- $[31] = setNodeRef;
359
- $[32] = style;
360
- $[33] = t10;
361
- $[34] = t12;
362
- $[35] = t8;
363
- $[36] = t13;
364
- } else t13 = $[36];
365
- return t13;
364
+ $[29] = ctx.handleBlockMouseEnter;
365
+ $[30] = ctx.handleBlockMouseLeave;
366
+ $[31] = ctx.shouldShowActive;
367
+ $[32] = ctx.shouldShowHover;
368
+ $[33] = setNodeRef;
369
+ $[34] = style;
370
+ $[35] = t12;
371
+ $[36] = t14;
372
+ $[37] = t16;
373
+ $[38] = t17;
374
+ } else t17 = $[38];
375
+ return t17;
366
376
  };
367
377
  const LayoutBlockItem = (t0) => {
368
378
  const $ = c(26);
@@ -723,7 +733,7 @@ const PageTree = (t0) => {
723
733
  className: "flex items-center gap-1 px-1 py-2 text-sm",
724
734
  children: [/* @__PURE__ */ jsx(GripVertical, { className: "text-muted-foreground mx-1.5 h-4 w-4" }), /* @__PURE__ */ jsx("span", {
725
735
  className: "truncate",
726
- children: activeBlock.summary
736
+ children: entityName(activeBlock, activeBlock.type)
727
737
  })]
728
738
  })
729
739
  });
@@ -1,7 +1,6 @@
1
- import { actionsStore } from "../../provider/actionsStore.js";
2
1
  import { NavigationDisabled, NavigationLocation } from "../../navigation/navigation.js";
3
2
  import { ArtifactStudioContext } from "../../../core/hooks/useArtifactHost.js";
4
- import { checkIfInputFocused, cn } from "../../../lib/utils.js";
3
+ import { cn } from "../../../lib/utils.js";
5
4
  import { previewStore } from "../previewStore.js";
6
5
  import { useEditingFrameClaim, useEditingOwner } from "../editingFrame.js";
7
6
  import { Frame, useFrame } from "./Frame.js";
@@ -10,6 +9,7 @@ import { EditableSurfaceContext } from "../../../core/hooks/useIsEditable.js";
10
9
  import { adoptCanvasDocument, pauseCanvasDocument } from "../../canvas/canvasFrameDocument.js";
11
10
  import { CanvasWorkspaceContext } from "../../canvas/canvasZoom.js";
12
11
  import { forwardCanvasWheel, useCanvasFrameInput } from "../../canvas/useCanvasFrameInput.js";
12
+ import { useActionShortcuts } from "../../provider/useAdminShortcuts.js";
13
13
  import { PreviewEditingOwnerContext } from "../previewSelection.js";
14
14
  import { useBlockActionsShortcuts } from "./BlockActionsPopover.js";
15
15
  import { FieldOverlayStyles } from "./FieldOverlayStyles.js";
@@ -67,60 +67,9 @@ const PreviewFrameEffects = () => {
67
67
  return t0;
68
68
  };
69
69
  const KeyDownForwarder = () => {
70
- const $ = c(4);
71
70
  const { window: iframeWindow } = useFrame();
72
- const actions = useSelector(actionsStore, _temp);
73
- let t0;
74
- let t1;
75
- if ($[0] !== actions || $[1] !== iframeWindow) {
76
- t0 = () => {
77
- if (!iframeWindow || !iframeWindow.parent || iframeWindow.parent === iframeWindow) return;
78
- const handleKeyDown = (e) => {
79
- const matchingAction = actions.find((action) => {
80
- if (!action.shortcut) return false;
81
- if (!action.checkIfAvailable()) return false;
82
- if (checkIfInputFocused(iframeWindow.document)) {
83
- if (action.shortcut.key !== "Escape" && !action.shortcut.withMeta && !action.shortcut.withAlt) return false;
84
- if (action.shortcut.key === "Backspace") return false;
85
- }
86
- const { key, withMeta, withAlt, withShift } = action.shortcut;
87
- return (withAlt && key.length === 1 && /[a-z]/i.test(key) ? e.code === `Key${key.toUpperCase()}` : key.toLowerCase() === e.key.toLowerCase()) && !!withMeta === (e.metaKey || e.ctrlKey) && !!withAlt === e.altKey && !!withShift === e.shiftKey;
88
- });
89
- if (matchingAction) {
90
- e.preventDefault();
91
- e.stopPropagation();
92
- if (e.key === "Escape" && checkIfInputFocused(iframeWindow.document)) iframeWindow.document.activeElement.blur();
93
- iframeWindow.parent.postMessage({
94
- type: "executeAction",
95
- actionId: matchingAction.id
96
- }, "*");
97
- }
98
- };
99
- const handleCapturedKeyDown = (event) => {
100
- if (event.key === "Escape") return;
101
- handleKeyDown(event);
102
- };
103
- const handleEscape = (event_0) => {
104
- if (event_0.key !== "Escape" || event_0.defaultPrevented) return;
105
- handleKeyDown(event_0);
106
- };
107
- iframeWindow.addEventListener("keydown", handleCapturedKeyDown, true);
108
- iframeWindow.addEventListener("keydown", handleEscape);
109
- return () => {
110
- iframeWindow.removeEventListener("keydown", handleCapturedKeyDown, true);
111
- iframeWindow.removeEventListener("keydown", handleEscape);
112
- };
113
- };
114
- t1 = [iframeWindow, actions];
115
- $[0] = actions;
116
- $[1] = iframeWindow;
117
- $[2] = t0;
118
- $[3] = t1;
119
- } else {
120
- t0 = $[2];
121
- t1 = $[3];
122
- }
123
- React.useEffect(t0, t1);
71
+ const inIframe = !!iframeWindow?.parent && iframeWindow.parent !== iframeWindow;
72
+ useActionShortcuts(inIframe ? iframeWindow : null);
124
73
  return null;
125
74
  };
126
75
  /** The preview's read-only tree is never editable, whether or not the Canvas shows. */
@@ -227,7 +176,7 @@ function PreviewPageCanvasEffects(t0) {
227
176
  t7 = () => {
228
177
  const doc = root?.ownerDocument;
229
178
  if (!doc || !onInteract) return;
230
- const preventLinkNavigation = _temp2;
179
+ const preventLinkNavigation = _temp;
231
180
  for (const type of [
232
181
  "pointerdown",
233
182
  "focusin",
@@ -304,7 +253,7 @@ function PreviewPageCanvasEffects(t0) {
304
253
  } else t14 = $[29];
305
254
  return t14;
306
255
  }
307
- function _temp2(event) {
256
+ function _temp(event) {
308
257
  if (event.target?.closest?.("a")) event.preventDefault();
309
258
  }
310
259
  const PreviewPanel = (t0) => {
@@ -349,8 +298,8 @@ const PreviewPanel = (t0) => {
349
298
  $[9] = t7;
350
299
  } else t7 = $[9];
351
300
  React.useLayoutEffect(t6, t7);
352
- const viewportMode = useSelector(previewStore, _temp3);
353
- const isToolbarHidden = useSelector(previewStore, _temp4);
301
+ const viewportMode = useSelector(previewStore, _temp2);
302
+ const isToolbarHidden = useSelector(previewStore, _temp3);
354
303
  const { frame, slot, inCanvas, revealed } = usePreviewPageFrame();
355
304
  const placed = !isMobileExperience && inCanvas ? slot : null;
356
305
  const underCanvas = revealed && !isMobileExperience;
@@ -709,13 +658,10 @@ function PreviewPageClip(t0) {
709
658
  } else t10 = $[18];
710
659
  return t10;
711
660
  }
712
- function _temp(state) {
713
- return state.context.actions;
714
- }
715
- function _temp3(state) {
661
+ function _temp2(state) {
716
662
  return state.context.viewportMode;
717
663
  }
718
- function _temp4(state_0) {
664
+ function _temp3(state_0) {
719
665
  return state_0.context.isToolbarHidden;
720
666
  }
721
667
 
@@ -1,4 +1,4 @@
1
- import { formatShortcut } from "../../../lib/utils.js";
1
+ import { formatShortcut } from "../../../lib/shortcuts.js";
2
2
  import { TOGGLE_CANVAS_SHORTCUT } from "../previewConstants.js";
3
3
  import { previewStore, selectIsCanvasShown } from "../previewStore.js";
4
4
  import { prefetchCanvas } from "./CanvasPreview.js";
@@ -4,16 +4,17 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
4
 
5
5
  //#region src/features/preview/components/RecordCard.tsx
6
6
  /**
7
- * A linked collection record: label and collection title.
8
- * `leading` holds controls before it, such as a drag handle; `actions` holds trailing
7
+ * A linked collection record: its title, its description when it has one, and its collection's
8
+ * title. `leading` holds controls before it, such as a drag handle; `actions` holds trailing
9
9
  * controls such as unlink.
10
10
  */
11
11
  function RecordCard(t0) {
12
- const $ = c(15);
13
- const { label, collectionTitle, onOpen, leading, actions } = t0;
12
+ const $ = c(18);
13
+ const { label, description, collectionTitle, onOpen, leading, actions } = t0;
14
14
  let t1;
15
15
  if ($[0] !== label) {
16
16
  t1 = /* @__PURE__ */ jsx("span", {
17
+ "data-record-title": true,
17
18
  className: "truncate text-sm font-medium",
18
19
  children: label
19
20
  });
@@ -21,28 +22,43 @@ function RecordCard(t0) {
21
22
  $[1] = t1;
22
23
  } else t1 = $[1];
23
24
  let t2;
24
- if ($[2] !== collectionTitle) {
25
- t2 = /* @__PURE__ */ jsx("span", {
25
+ if ($[2] !== description) {
26
+ t2 = description && /* @__PURE__ */ jsx("span", {
27
+ "data-record-description": true,
26
28
  className: "text-muted-foreground truncate text-xs",
27
- children: collectionTitle
29
+ children: description
28
30
  });
29
- $[2] = collectionTitle;
31
+ $[2] = description;
30
32
  $[3] = t2;
31
33
  } else t2 = $[3];
32
34
  let t3;
33
- if ($[4] !== t1 || $[5] !== t2) {
34
- t3 = /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("span", {
35
+ if ($[4] !== collectionTitle) {
36
+ t3 = /* @__PURE__ */ jsx("span", {
37
+ className: "text-muted-foreground truncate text-xs",
38
+ children: collectionTitle
39
+ });
40
+ $[4] = collectionTitle;
41
+ $[5] = t3;
42
+ } else t3 = $[5];
43
+ let t4;
44
+ if ($[6] !== t1 || $[7] !== t2 || $[8] !== t3) {
45
+ t4 = /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("span", {
35
46
  className: "flex min-w-0 flex-1 flex-col gap-0.5",
36
- children: [t1, t2]
47
+ children: [
48
+ t1,
49
+ t2,
50
+ t3
51
+ ]
37
52
  }) });
38
- $[4] = t1;
39
- $[5] = t2;
40
- $[6] = t3;
41
- } else t3 = $[6];
42
- const body = t3;
43
- let t4;
44
- if ($[7] !== body || $[8] !== label || $[9] !== onOpen) {
45
- t4 = onOpen ? /* @__PURE__ */ jsx("button", {
53
+ $[6] = t1;
54
+ $[7] = t2;
55
+ $[8] = t3;
56
+ $[9] = t4;
57
+ } else t4 = $[9];
58
+ const body = t4;
59
+ let t5;
60
+ if ($[10] !== body || $[11] !== label || $[12] !== onOpen) {
61
+ t5 = onOpen ? /* @__PURE__ */ jsx("button", {
46
62
  type: "button",
47
63
  "aria-label": `Open ${label}`,
48
64
  className: "flex min-w-0 flex-1 items-center gap-2 rounded-sm p-1 text-left",
@@ -52,28 +68,28 @@ function RecordCard(t0) {
52
68
  className: "flex min-w-0 flex-1 items-center gap-2 p-1",
53
69
  children: body
54
70
  });
55
- $[7] = body;
56
- $[8] = label;
57
- $[9] = onOpen;
58
- $[10] = t4;
59
- } else t4 = $[10];
60
- let t5;
61
- if ($[11] !== actions || $[12] !== leading || $[13] !== t4) {
62
- t5 = /* @__PURE__ */ jsxs("div", {
71
+ $[10] = body;
72
+ $[11] = label;
73
+ $[12] = onOpen;
74
+ $[13] = t5;
75
+ } else t5 = $[13];
76
+ let t6;
77
+ if ($[14] !== actions || $[15] !== leading || $[16] !== t5) {
78
+ t6 = /* @__PURE__ */ jsxs("div", {
63
79
  "data-record-card": true,
64
80
  className: "text-foreground hover:bg-accent/75 flex w-full min-w-0 items-center gap-1 overflow-hidden rounded-lg border-2 p-1",
65
81
  children: [
66
82
  leading,
67
- t4,
83
+ t5,
68
84
  actions
69
85
  ]
70
86
  });
71
- $[11] = actions;
72
- $[12] = leading;
73
- $[13] = t4;
74
- $[14] = t5;
75
- } else t5 = $[14];
76
- return t5;
87
+ $[14] = actions;
88
+ $[15] = leading;
89
+ $[16] = t5;
90
+ $[17] = t6;
91
+ } else t6 = $[17];
92
+ return t6;
77
93
  }
78
94
 
79
95
  //#endregion
@@ -8,7 +8,7 @@ import { Combobox } from "@base-ui/react/combobox";
8
8
 
9
9
  //#region src/features/preview/components/RecordCombobox.tsx
10
10
  /**
11
- * Picks a collection record by label. The footer action (e.g. Create item) receives the
11
+ * Picks a collection record by title, each shown with its description. The footer action (e.g. Create item) receives the
12
12
  * current search text so it can prefill a new record.
13
13
  */
14
14
  function RecordCombobox(t0) {
@@ -158,9 +158,16 @@ function _temp4(record_3) {
158
158
  return /* @__PURE__ */ jsx(Combobox.Item, {
159
159
  value: record_3,
160
160
  className: "data-highlighted:bg-accent data-highlighted:text-accent-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none",
161
- children: /* @__PURE__ */ jsx("span", {
162
- className: "min-w-0 flex-1 truncate",
163
- children: record_3.label
161
+ children: /* @__PURE__ */ jsxs("span", {
162
+ className: "flex min-w-0 flex-1 flex-col",
163
+ children: [/* @__PURE__ */ jsx("span", {
164
+ "data-record-title": true,
165
+ className: "truncate",
166
+ children: record_3.title
167
+ }), record_3.description && /* @__PURE__ */ jsx("span", {
168
+ className: "text-muted-foreground truncate text-xs",
169
+ children: record_3.description
170
+ })]
164
171
  })
165
172
  }, record_3.id);
166
173
  }
@@ -171,7 +178,7 @@ function _temp2(record_0) {
171
178
  return record_0.id;
172
179
  }
173
180
  function _temp(record) {
174
- return record.label;
181
+ return record.title;
175
182
  }
176
183
 
177
184
  //#endregion
@@ -1,6 +1,7 @@
1
1
  import { useProjectUuid } from "../../../lib/auth.js";
2
2
  import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
3
3
  import { reads, useReadQuery } from "../../../lib/studio-reads.js";
4
+ import { titleField } from "../../../core/recordItem.js";
4
5
  import { useCollectionItemSheet } from "../../content/CollectionItemSheetContext.js";
5
6
  import { referencePickerFocus, useReferencePickerFocusRequested } from "../referencePickerFocus.js";
6
7
  import { DrillRow } from "./DrillRow.js";
@@ -31,7 +32,7 @@ function ReferenceFieldEditor({ collectionId, fieldId, value, required = false,
31
32
  const selectedId = typeof value === "string" && value ? value : null;
32
33
  const selected = records.data?.find((option) => option.id === value);
33
34
  const hydrated = record?.id === selectedId ? record : null;
34
- const selectedLabel = selected?.label ?? hydrated?.label ?? "Unavailable item";
35
+ const selectedLabel = selected?.title ?? hydrated?.title ?? "Unavailable item";
35
36
  const [pickerOpen, setPickerOpen] = React.useState(false);
36
37
  const focusRequested = useReferencePickerFocusRequested(drill ? void 0 : fieldId);
37
38
  const pickerReady = !selectedId && records.isSuccess && !saving;
@@ -84,6 +85,7 @@ function ReferenceFieldEditor({ collectionId, fieldId, value, required = false,
84
85
  children: [
85
86
  selectedId && /* @__PURE__ */ jsx(RecordCard, {
86
87
  label: selectedLabel,
88
+ description: selected ? selected.description : hydrated?.description,
87
89
  collectionTitle,
88
90
  onOpen: onOpenRecord ? () => onOpenRecord(selectedId) : void 0,
89
91
  actions: /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
@@ -112,7 +114,7 @@ function ReferenceFieldEditor({ collectionId, fieldId, value, required = false,
112
114
  label: "Create item",
113
115
  onSelect: (search) => sheet.open({
114
116
  collectionId,
115
- initialContent: collection && search.trim() ? { [collection._internal.label]: search } : void 0,
117
+ initialContent: collection && search.trim() && titleField(collection._internal.toTitle) ? { [titleField(collection._internal.toTitle)]: search } : void 0,
116
118
  onSaved: (created) => save(created.id)
117
119
  })
118
120
  } : void 0
@@ -3,6 +3,7 @@ import { useProjectUuid } from "../../../lib/auth.js";
3
3
  import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
4
4
  import { reads, useReadQuery } from "../../../lib/studio-reads.js";
5
5
  import { referenceListIds } from "../../../core/lib/reference.js";
6
+ import { titleField } from "../../../core/recordItem.js";
6
7
  import { useCollectionItemSheet } from "../../content/CollectionItemSheetContext.js";
7
8
  import { referencePickerFocus, useReferencePickerFocusRequested } from "../referencePickerFocus.js";
8
9
  import { DrillRow } from "./DrillRow.js";
@@ -119,8 +120,8 @@ function QueryResultCard(t0) {
119
120
  return t2;
120
121
  }
121
122
  function SortableRecordCard(t0) {
122
- const $ = c(31);
123
- const { id, label, collectionTitle, onOpen, onUnlink, hover } = t0;
123
+ const $ = c(32);
124
+ const { id, label, description, collectionTitle, onOpen, onUnlink, hover } = t0;
124
125
  let t1;
125
126
  if ($[0] !== id) {
126
127
  t1 = { id };
@@ -214,23 +215,25 @@ function SortableRecordCard(t0) {
214
215
  $[19] = t11;
215
216
  } else t11 = $[19];
216
217
  let t12;
217
- if ($[20] !== collectionTitle || $[21] !== label || $[22] !== onOpen || $[23] !== t11 || $[24] !== t6) {
218
+ if ($[20] !== collectionTitle || $[21] !== description || $[22] !== label || $[23] !== onOpen || $[24] !== t11 || $[25] !== t6) {
218
219
  t12 = /* @__PURE__ */ jsx(RecordCard, {
219
220
  label,
221
+ description,
220
222
  collectionTitle,
221
223
  onOpen,
222
224
  leading: t6,
223
225
  actions: t11
224
226
  });
225
227
  $[20] = collectionTitle;
226
- $[21] = label;
227
- $[22] = onOpen;
228
- $[23] = t11;
229
- $[24] = t6;
230
- $[25] = t12;
231
- } else t12 = $[25];
228
+ $[21] = description;
229
+ $[22] = label;
230
+ $[23] = onOpen;
231
+ $[24] = t11;
232
+ $[25] = t6;
233
+ $[26] = t12;
234
+ } else t12 = $[26];
232
235
  let t13;
233
- if ($[26] !== hoverHandlers || $[27] !== setNodeRef || $[28] !== t12 || $[29] !== t4) {
236
+ if ($[27] !== hoverHandlers || $[28] !== setNodeRef || $[29] !== t12 || $[30] !== t4) {
234
237
  t13 = /* @__PURE__ */ jsx("li", {
235
238
  ref: setNodeRef,
236
239
  ...hoverHandlers,
@@ -238,12 +241,12 @@ function SortableRecordCard(t0) {
238
241
  className: "min-w-0",
239
242
  children: t12
240
243
  });
241
- $[26] = hoverHandlers;
242
- $[27] = setNodeRef;
243
- $[28] = t12;
244
- $[29] = t4;
245
- $[30] = t13;
246
- } else t13 = $[30];
244
+ $[27] = hoverHandlers;
245
+ $[28] = setNodeRef;
246
+ $[29] = t12;
247
+ $[30] = t4;
248
+ $[31] = t13;
249
+ } else t13 = $[31];
247
250
  return t13;
248
251
  }
249
252
  /**
@@ -317,7 +320,8 @@ function ReferenceListFieldEditor({ collectionId, fieldId, value, maxItems, quer
317
320
  }), hydratedRecords.length > 0 && /* @__PURE__ */ jsx("ul", {
318
321
  className: "flex min-w-0 flex-col gap-2",
319
322
  children: hydratedRecords.map((record) => /* @__PURE__ */ jsx(QueryResultCard, {
320
- label: record.label,
323
+ label: record.title,
324
+ description: record.description,
321
325
  collectionTitle,
322
326
  onOpen: onOpenRecord ? () => onOpenRecord(record.id) : void 0,
323
327
  hover: entryHover(recordHover, record.id)
@@ -370,7 +374,8 @@ function ReferenceListFieldEditor({ collectionId, fieldId, value, maxItems, quer
370
374
  const hydrated = hydratedRecords.find((record) => record.id === id);
371
375
  return /* @__PURE__ */ jsx(SortableRecordCard, {
372
376
  id,
373
- label: summary?.label ?? hydrated?.label ?? "Unavailable item",
377
+ label: summary?.title ?? hydrated?.title ?? "Unavailable item",
378
+ description: summary ? summary.description : hydrated?.description,
374
379
  collectionTitle,
375
380
  onOpen: onOpenRecord ? () => onOpenRecord(id) : void 0,
376
381
  onUnlink: () => change(ids.filter((linked) => linked !== id)),
@@ -400,7 +405,7 @@ function ReferenceListFieldEditor({ collectionId, fieldId, value, maxItems, quer
400
405
  label: "Create item",
401
406
  onSelect: (search) => sheet.open({
402
407
  collectionId,
403
- initialContent: collection && search.trim() ? { [collection._internal.label]: search } : void 0,
408
+ initialContent: collection && search.trim() && titleField(collection._internal.toTitle) ? { [titleField(collection._internal.toTitle)]: search } : void 0,
404
409
  onSaved: (created) => save([...ids, created.id])
405
410
  })
406
411
  } : void 0