camox 0.47.0 → 0.48.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 (75) 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 +54 -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/CanvasSidebarFrame.js +1 -1
  26. package/dist/features/content/ContentCollection.js +13 -7
  27. package/dist/features/content/collection-form.js +6 -2
  28. package/dist/features/content/components/MissingFromLocale.js +1 -1
  29. package/dist/features/og/pageImage.js +89 -0
  30. package/dist/features/page/CuratedPageContent.js +45 -32
  31. package/dist/features/page/DerivedPageContent.js +49 -22
  32. package/dist/features/page/SharedLayoutContent.js +26 -22
  33. package/dist/features/preview/CamoxPreview.js +40 -26
  34. package/dist/features/preview/components/AddBlockSheet.js +1 -0
  35. package/dist/features/preview/components/BlockActionsPopover.js +8 -6
  36. package/dist/features/preview/components/PageInfo.js +244 -264
  37. package/dist/features/preview/components/PageTree.js +63 -53
  38. package/dist/features/preview/components/RecordCard.js +50 -34
  39. package/dist/features/preview/components/RecordCombobox.js +12 -5
  40. package/dist/features/preview/components/ReferenceFieldEditor.js +4 -2
  41. package/dist/features/preview/components/ReferenceListFieldEditor.js +24 -19
  42. package/dist/features/preview/components/RepeatableItemsList.js +62 -46
  43. package/dist/features/preview/components/SelectionEditor.js +3 -2
  44. package/dist/features/preview/components/useFieldWriter.js +2 -4
  45. package/dist/features/preview/components/useRecordView.js +2 -2
  46. package/dist/features/preview/entityName.js +11 -0
  47. package/dist/features/preview/pageRecord.js +17 -18
  48. package/dist/features/routes/pageRuntime.d.ts +15 -1
  49. package/dist/features/routes/pageRuntime.js +35 -38
  50. package/dist/features/runtime/RuntimeChrome.js +1 -1
  51. package/dist/features/runtime/breadcrumbs.js +68 -0
  52. package/dist/features/runtime/livePages.js +3 -2
  53. package/dist/features/runtime/pageGraph.js +92 -0
  54. package/dist/features/runtime/projectLogo.js +110 -0
  55. package/dist/features/runtime/runtime.d.ts +11 -6
  56. package/dist/features/runtime/runtime.js +278 -55
  57. package/dist/features/runtime/runtimeRoutes.d.ts +1 -0
  58. package/dist/features/runtime/runtimeRoutes.js +1 -0
  59. package/dist/features/runtime/structuredData.js +213 -0
  60. package/dist/features/studio/components/ChatSidebar.js +5 -5
  61. package/dist/features/studio/components/ProjectMenu.js +127 -100
  62. package/dist/features/studio/components/SocialProfilesDialog.js +342 -0
  63. package/dist/features/studio/components/ThreadMessages.js +2 -2
  64. package/dist/features/vite/blockBoilerplate.js +3 -2
  65. package/dist/features/vite/layoutGeneration.js +3 -2
  66. package/dist/features/vite/vite.js +1 -0
  67. package/dist/lib/queries.d.ts +4 -0
  68. package/dist/lib/queries.js +1 -0
  69. package/dist/lib/studio-reads.js +3 -1
  70. package/dist/package.js +1 -1
  71. package/dist/studio.css +1 -1
  72. package/package.json +5 -4
  73. package/skills/camox/references/block-definitions.md +105 -25
  74. package/skills/camox/references/layout-definitions.md +53 -17
  75. package/skills/camox/references/routed-layouts.md +17 -14
@@ -1,6 +1,6 @@
1
1
  import { artifactFrameProps, artifactPlaceholderProps, artifactStandInProps, isArtifactSource } from "../lib/artifact.js";
2
2
  import { artifactData } from "../lib/artifactData.js";
3
- import { resolveBlockFields, resolveToMarkdown } from "../lib/contentType.js";
3
+ import { resolveBlockFields, resolveToMarkdown, resolveToStructuredData, resolveToTitle } from "../lib/contentType.js";
4
4
  import { useProjectUuid } from "../../lib/auth.js";
5
5
  import { useLocation, useNavigate } from "../../features/navigation/navigation.js";
6
6
  import { useOptionalCamoxApp } from "../../features/provider/components/CamoxAppContext.js";
@@ -140,6 +140,7 @@ function buildPeekItems(properties, blockId, parentItemId, content, allItems, co
140
140
  content: { ...itemContent },
141
141
  settings: itemSettingsDefaults ? { ...itemSettingsDefaults } : null,
142
142
  summary: "",
143
+ title: "",
143
144
  position,
144
145
  createdAt: 0,
145
146
  updatedAt: 0,
@@ -168,7 +169,9 @@ function createEditableBlock(options) {
168
169
  description: options.description,
169
170
  properties: typeboxSchema.properties,
170
171
  required: Object.keys(fields.content),
171
- toMarkdown: resolveToMarkdown(options.toMarkdown, fields.settings, "block", fields.content)
172
+ toMarkdown: resolveToMarkdown(options.toMarkdown, fields.settings, "block", fields.content),
173
+ toTitle: resolveToTitle(options.toTitle, fields.settings, "block", fields.content),
174
+ ...options.toStructuredData && { toStructuredData: resolveToStructuredData(options.toStructuredData, fields.settings, "block", fields.content) }
172
175
  };
173
176
  const settingsTypeboxSchema = fields.settings ? Type.Object(fields.settings) : null;
174
177
  const settingsSchema = settingsTypeboxSchema ? {
@@ -199,6 +202,7 @@ function createEditableBlock(options) {
199
202
  if (settingsTypeboxSchema) {
200
203
  for (const [key, prop] of Object.entries(settingsTypeboxSchema.properties)) if ("default" in prop) settingsDefaults[key] = prop.default;
201
204
  }
205
+ const ToReact = options.toReact;
202
206
  const Context = React.createContext(null);
203
207
  const RepeatableItemContext = React.createContext(null);
204
208
  const ReferenceContext = React.createContext(null);
@@ -1612,7 +1616,7 @@ function createEditableBlock(options) {
1612
1616
  return t5;
1613
1617
  };
1614
1618
  const BlockComponent = (t0) => {
1615
- const $ = c(62);
1619
+ const $ = c(63);
1616
1620
  const { blockData, mode, isFirstBlock, showAddBlockTop, showAddBlockBottom, addBlockAfterPosition } = t0;
1617
1621
  const isContentEditable = useIsEditable(mode);
1618
1622
  const { window: iframeWindow } = useFrame();
@@ -1683,20 +1687,30 @@ function createEditableBlock(options) {
1683
1687
  setPrevSidebarHover(isHoveredFromSidebar);
1684
1688
  setIsHovered(isHoveredFromSidebar);
1685
1689
  }
1690
+ let t6;
1691
+ if ($[11] !== blockData.settings) {
1692
+ t6 = {
1693
+ ...settingsDefaults,
1694
+ ...blockData.settings
1695
+ };
1696
+ $[11] = blockData.settings;
1697
+ $[12] = t6;
1698
+ } else t6 = $[12];
1699
+ const blockSettings = t6;
1686
1700
  let result;
1687
- if ($[11] !== blockData.content) {
1701
+ if ($[13] !== blockData.content) {
1688
1702
  result = { ...blockData.content };
1689
1703
  for (const key in result) {
1690
1704
  const value = result[key];
1691
1705
  if (Array.isArray(value) && value.length > 0 && value[0]?.content !== void 0) result[key] = value.map(_temp7);
1692
1706
  }
1693
- $[11] = blockData.content;
1694
- $[12] = result;
1695
- } else result = $[12];
1707
+ $[13] = blockData.content;
1708
+ $[14] = result;
1709
+ } else result = $[14];
1696
1710
  const normalizedContent = result;
1697
- let t6;
1698
- if ($[13] !== blockData._id || $[14] !== isContentEditable || $[15] !== selectTarget) {
1699
- t6 = (e) => {
1711
+ let t7;
1712
+ if ($[15] !== blockData._id || $[16] !== isContentEditable || $[17] !== selectTarget) {
1713
+ t7 = (e) => {
1700
1714
  if (!isContentEditable) return;
1701
1715
  const target = e.target;
1702
1716
  if (target.closest("[data-camox-field-id]")) return;
@@ -1706,169 +1720,163 @@ function createEditableBlock(options) {
1706
1720
  blockId: blockData._id
1707
1721
  });
1708
1722
  };
1709
- $[13] = blockData._id;
1710
- $[14] = isContentEditable;
1711
- $[15] = selectTarget;
1712
- $[16] = t6;
1713
- } else t6 = $[16];
1714
- const handleClick = t6;
1715
- let t7;
1716
- if ($[17] !== isContentEditable) {
1717
- t7 = () => {
1718
- if (!isContentEditable) return;
1719
- setIsHovered(true);
1720
- };
1721
- $[17] = isContentEditable;
1723
+ $[15] = blockData._id;
1724
+ $[16] = isContentEditable;
1725
+ $[17] = selectTarget;
1722
1726
  $[18] = t7;
1723
1727
  } else t7 = $[18];
1724
- const handleMouseEnter = t7;
1728
+ const handleClick = t7;
1725
1729
  let t8;
1726
1730
  if ($[19] !== isContentEditable) {
1727
1731
  t8 = () => {
1728
1732
  if (!isContentEditable) return;
1729
- setIsHovered(false);
1733
+ setIsHovered(true);
1730
1734
  };
1731
1735
  $[19] = isContentEditable;
1732
1736
  $[20] = t8;
1733
1737
  } else t8 = $[20];
1734
- const handleMouseLeave = t8;
1738
+ const handleMouseEnter = t8;
1739
+ let t9;
1740
+ if ($[21] !== isContentEditable) {
1741
+ t9 = () => {
1742
+ if (!isContentEditable) return;
1743
+ setIsHovered(false);
1744
+ };
1745
+ $[21] = isContentEditable;
1746
+ $[22] = t9;
1747
+ } else t9 = $[22];
1748
+ const handleMouseLeave = t9;
1735
1749
  const shouldShowOverlay = isContentEditable && (overlayState["data-camox-hovered"] || overlayState["data-camox-focused"]);
1736
- const t9 = blockData._id;
1737
- let t10;
1738
- if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
1739
- t10 = {
1750
+ const t10 = blockData._id;
1751
+ let t11;
1752
+ if ($[23] === Symbol.for("react.memo_cache_sentinel")) {
1753
+ t11 = {
1740
1754
  position: "relative",
1741
1755
  scrollMargin: "5rem"
1742
1756
  };
1743
- $[21] = t10;
1744
- } else t10 = $[21];
1745
- const t11 = isContentEditable ? blockData._id : void 0;
1746
- let t12;
1747
- if ($[22] !== addBlockAfterPosition || $[23] !== blockData.position || $[24] !== isContentEditable || $[25] !== isFirstBlock || $[26] !== mode || $[27] !== showAddBlockBottom || $[28] !== showAddBlockTop) {
1748
- t12 = isContentEditable ? JSON.stringify({
1757
+ $[23] = t11;
1758
+ } else t11 = $[23];
1759
+ const t12 = isContentEditable ? blockData._id : void 0;
1760
+ let t13;
1761
+ if ($[24] !== addBlockAfterPosition || $[25] !== blockData.position || $[26] !== isContentEditable || $[27] !== isFirstBlock || $[28] !== mode || $[29] !== showAddBlockBottom || $[30] !== showAddBlockTop) {
1762
+ t13 = isContentEditable ? JSON.stringify({
1749
1763
  position: blockData.position,
1750
1764
  before: showAddBlockTop ?? (mode !== "layout" && !isFirstBlock),
1751
1765
  after: showAddBlockBottom ?? mode !== "layout",
1752
1766
  ...addBlockAfterPosition !== void 0 ? { afterPosition: addBlockAfterPosition } : {}
1753
1767
  }) : void 0;
1754
- $[22] = addBlockAfterPosition;
1755
- $[23] = blockData.position;
1756
- $[24] = isContentEditable;
1757
- $[25] = isFirstBlock;
1758
- $[26] = mode;
1759
- $[27] = showAddBlockBottom;
1760
- $[28] = showAddBlockTop;
1761
- $[29] = t12;
1762
- } else t12 = $[29];
1763
- let t13;
1764
- if ($[30] !== overlayState || $[31] !== shouldShowOverlay) {
1765
- t13 = shouldShowOverlay ? overlayState : {};
1766
- $[30] = overlayState;
1767
- $[31] = shouldShowOverlay;
1768
- $[32] = t13;
1769
- } else t13 = $[32];
1770
- const t14 = blockData._id;
1771
- let t15;
1772
- if ($[33] !== blockData.content) {
1773
- t15 = {
1768
+ $[24] = addBlockAfterPosition;
1769
+ $[25] = blockData.position;
1770
+ $[26] = isContentEditable;
1771
+ $[27] = isFirstBlock;
1772
+ $[28] = mode;
1773
+ $[29] = showAddBlockBottom;
1774
+ $[30] = showAddBlockTop;
1775
+ $[31] = t13;
1776
+ } else t13 = $[31];
1777
+ let t14;
1778
+ if ($[32] !== overlayState || $[33] !== shouldShowOverlay) {
1779
+ t14 = shouldShowOverlay ? overlayState : {};
1780
+ $[32] = overlayState;
1781
+ $[33] = shouldShowOverlay;
1782
+ $[34] = t14;
1783
+ } else t14 = $[34];
1784
+ const t15 = blockData._id;
1785
+ let t16;
1786
+ if ($[35] !== blockData.content) {
1787
+ t16 = {
1774
1788
  ...contentDefaults,
1775
1789
  ...blockData.content
1776
1790
  };
1777
- $[33] = blockData.content;
1778
- $[34] = t15;
1779
- } else t15 = $[34];
1780
- const merged = t15;
1791
+ $[35] = blockData.content;
1792
+ $[36] = t16;
1793
+ } else t16 = $[36];
1794
+ const merged = t16;
1781
1795
  let overrides;
1782
- if ($[35] !== merged) {
1796
+ if ($[37] !== merged) {
1783
1797
  overrides = {};
1784
1798
  for (const key_0 in merged) {
1785
1799
  const val = merged[key_0];
1786
1800
  if (val && typeof val === "object" && "url" in val && !val.url && contentDefaults[key_0]) overrides[key_0] = contentDefaults[key_0];
1787
1801
  }
1788
- $[35] = merged;
1789
- $[36] = overrides;
1790
- } else overrides = $[36];
1791
- let t16;
1792
- if ($[37] !== merged || $[38] !== overrides) {
1793
- t16 = {
1794
- ...merged,
1795
- ...overrides
1796
- };
1797
1802
  $[37] = merged;
1798
1803
  $[38] = overrides;
1799
- $[39] = t16;
1800
- } else t16 = $[39];
1801
- const t17 = t16;
1802
- let t18;
1803
- if ($[40] !== blockData.settings) {
1804
- t18 = {
1805
- ...settingsDefaults,
1806
- ...blockData.settings
1804
+ } else overrides = $[38];
1805
+ let t17;
1806
+ if ($[39] !== merged || $[40] !== overrides) {
1807
+ t17 = {
1808
+ ...merged,
1809
+ ...overrides
1807
1810
  };
1808
- $[40] = blockData.settings;
1809
- $[41] = t18;
1810
- } else t18 = $[41];
1811
- const t19 = t18;
1812
- let t20;
1813
- if ($[42] !== blockData._id || $[43] !== isHovered || $[44] !== mode || $[45] !== t17 || $[46] !== t19) {
1814
- t20 = {
1815
- blockId: t14,
1816
- content: t17,
1817
- settings: t19,
1811
+ $[39] = merged;
1812
+ $[40] = overrides;
1813
+ $[41] = t17;
1814
+ } else t17 = $[41];
1815
+ const t18 = t17;
1816
+ let t19;
1817
+ if ($[42] !== blockData || $[43] !== blockSettings || $[44] !== isHovered || $[45] !== mode || $[46] !== t18) {
1818
+ t19 = {
1819
+ blockId: t15,
1820
+ content: t18,
1821
+ settings: blockSettings,
1818
1822
  mode,
1819
1823
  isHovered,
1820
1824
  setIsHovered
1821
1825
  };
1822
- $[42] = blockData._id;
1823
- $[43] = isHovered;
1824
- $[44] = mode;
1825
- $[45] = t17;
1826
- $[46] = t19;
1827
- $[47] = t20;
1828
- } else t20 = $[47];
1829
- let t21;
1830
- if ($[48] !== normalizedContent) {
1831
- t21 = /* @__PURE__ */ jsx(options.component, { content: normalizedContent });
1832
- $[48] = normalizedContent;
1833
- $[49] = t21;
1834
- } else t21 = $[49];
1835
- let t22;
1836
- if ($[50] !== t20 || $[51] !== t21) {
1837
- t22 = /* @__PURE__ */ jsx(Context.Provider, {
1838
- value: t20,
1839
- children: t21
1826
+ $[42] = blockData;
1827
+ $[43] = blockSettings;
1828
+ $[44] = isHovered;
1829
+ $[45] = mode;
1830
+ $[46] = t18;
1831
+ $[47] = t19;
1832
+ } else t19 = $[47];
1833
+ let t20;
1834
+ if ($[48] !== blockSettings || $[49] !== normalizedContent) {
1835
+ t20 = /* @__PURE__ */ jsx(ToReact, {
1836
+ content: normalizedContent,
1837
+ settings: blockSettings
1840
1838
  });
1839
+ $[48] = blockSettings;
1840
+ $[49] = normalizedContent;
1841
1841
  $[50] = t20;
1842
- $[51] = t21;
1843
- $[52] = t22;
1844
- } else t22 = $[52];
1845
- let t23;
1846
- if ($[53] !== blockData._id || $[54] !== handleClick || $[55] !== handleMouseEnter || $[56] !== handleMouseLeave || $[57] !== t11 || $[58] !== t12 || $[59] !== t13 || $[60] !== t22) {
1847
- t23 = /* @__PURE__ */ jsx("div", {
1842
+ } else t20 = $[50];
1843
+ let t21;
1844
+ if ($[51] !== t19 || $[52] !== t20) {
1845
+ t21 = /* @__PURE__ */ jsx(Context.Provider, {
1846
+ value: t19,
1847
+ children: t20
1848
+ });
1849
+ $[51] = t19;
1850
+ $[52] = t20;
1851
+ $[53] = t21;
1852
+ } else t21 = $[53];
1853
+ let t22;
1854
+ if ($[54] !== blockData || $[55] !== handleClick || $[56] !== handleMouseEnter || $[57] !== handleMouseLeave || $[58] !== t12 || $[59] !== t13 || $[60] !== t14 || $[61] !== t21) {
1855
+ t22 = /* @__PURE__ */ jsx("div", {
1848
1856
  className: "group visual-editing-block",
1849
- "data-camox-viewport-block": t9,
1857
+ "data-camox-viewport-block": t10,
1850
1858
  ref,
1851
- style: t10,
1852
- "data-camox-block-id": t11,
1853
- "data-camox-block-insertion": t12,
1854
- ...t13,
1859
+ style: t11,
1860
+ "data-camox-block-id": t12,
1861
+ "data-camox-block-insertion": t13,
1862
+ ...t14,
1855
1863
  "data-camox-overlay-mode": options.synced ? "synced" : void 0,
1856
1864
  onClickCapture: handleClick,
1857
1865
  onMouseEnter: handleMouseEnter,
1858
1866
  onMouseLeave: handleMouseLeave,
1859
- children: t22
1867
+ children: t21
1860
1868
  });
1861
- $[53] = blockData._id;
1862
- $[54] = handleClick;
1863
- $[55] = handleMouseEnter;
1864
- $[56] = handleMouseLeave;
1865
- $[57] = t11;
1869
+ $[54] = blockData;
1870
+ $[55] = handleClick;
1871
+ $[56] = handleMouseEnter;
1872
+ $[57] = handleMouseLeave;
1866
1873
  $[58] = t12;
1867
1874
  $[59] = t13;
1868
- $[60] = t22;
1869
- $[61] = t23;
1870
- } else t23 = $[61];
1871
- return t23;
1875
+ $[60] = t14;
1876
+ $[61] = t21;
1877
+ $[62] = t22;
1878
+ } else t22 = $[62];
1879
+ return t22;
1872
1880
  };
1873
1881
  const useSetting = (name) => {
1874
1882
  const ctx = React.use(Context);
@@ -2140,7 +2148,7 @@ function createEditableBlock(options) {
2140
2148
  return t12;
2141
2149
  };
2142
2150
  const RecordScope = (t0) => {
2143
- const $ = c(15);
2151
+ const $ = c(16);
2144
2152
  const { block, field, record, reference, children } = t0;
2145
2153
  const t1 = record.content;
2146
2154
  let t2;
@@ -2156,10 +2164,11 @@ function createEditableBlock(options) {
2156
2164
  $[3] = t2;
2157
2165
  } else t2 = $[3];
2158
2166
  let t3;
2159
- if ($[4] !== children || $[5] !== record.id || $[6] !== record.label || $[7] !== reference.placement.nested) {
2167
+ if ($[4] !== children || $[5] !== record.description || $[6] !== record.id || $[7] !== record.title || $[8] !== reference.placement.nested) {
2160
2168
  t3 = children({
2161
2169
  id: record.id,
2162
- label: record.label,
2170
+ title: record.title,
2171
+ description: record.description,
2163
2172
  Field,
2164
2173
  Image: ReferenceImage,
2165
2174
  File: ReferenceFile,
@@ -2172,13 +2181,14 @@ function createEditableBlock(options) {
2172
2181
  }
2173
2182
  });
2174
2183
  $[4] = children;
2175
- $[5] = record.id;
2176
- $[6] = record.label;
2177
- $[7] = reference.placement.nested;
2178
- $[8] = t3;
2179
- } else t3 = $[8];
2184
+ $[5] = record.description;
2185
+ $[6] = record.id;
2186
+ $[7] = record.title;
2187
+ $[8] = reference.placement.nested;
2188
+ $[9] = t3;
2189
+ } else t3 = $[9];
2180
2190
  let t4;
2181
- if ($[9] !== t2 || $[10] !== t3) {
2191
+ if ($[10] !== t2 || $[11] !== t3) {
2182
2192
  t4 = /* @__PURE__ */ jsx(RepeatableItemContext.Provider, {
2183
2193
  value: null,
2184
2194
  children: /* @__PURE__ */ jsx(Context.Provider, {
@@ -2186,20 +2196,20 @@ function createEditableBlock(options) {
2186
2196
  children: t3
2187
2197
  })
2188
2198
  });
2189
- $[9] = t2;
2190
- $[10] = t3;
2191
- $[11] = t4;
2192
- } else t4 = $[11];
2199
+ $[10] = t2;
2200
+ $[11] = t3;
2201
+ $[12] = t4;
2202
+ } else t4 = $[12];
2193
2203
  let t5;
2194
- if ($[12] !== reference || $[13] !== t4) {
2204
+ if ($[13] !== reference || $[14] !== t4) {
2195
2205
  t5 = /* @__PURE__ */ jsx(ReferenceContext.Provider, {
2196
2206
  value: reference,
2197
2207
  children: t4
2198
2208
  });
2199
- $[12] = reference;
2200
- $[13] = t4;
2201
- $[14] = t5;
2202
- } else t5 = $[14];
2209
+ $[13] = reference;
2210
+ $[14] = t4;
2211
+ $[15] = t5;
2212
+ } else t5 = $[15];
2203
2213
  return t5;
2204
2214
  };
2205
2215
  const useCollectionTitle = (fieldName, field) => {
@@ -2306,7 +2316,7 @@ function createEditableBlock(options) {
2306
2316
  const $ = c(10);
2307
2317
  const { fieldId, record, placedRecord, overlay, children } = t0;
2308
2318
  const t1 = record?.id;
2309
- const t2 = record?.label;
2319
+ const t2 = record?.title;
2310
2320
  let t3;
2311
2321
  if ($[0] !== placedRecord.error) {
2312
2322
  t3 = placedRecord.error && /* @__PURE__ */ jsxs("p", {
@@ -2557,17 +2567,17 @@ function createEditableBlock(options) {
2557
2567
  };
2558
2568
  const LayoutItem = (t0) => {
2559
2569
  const $ = c(9);
2560
- const { collectionId, labelField, properties, record, children, fallback } = t0;
2570
+ const { collectionId, collection, properties, record, children, fallback } = t0;
2561
2571
  const editingOwner = React.use(PreviewEditingOwnerContext);
2562
2572
  let t1;
2563
- if ($[0] !== collectionId || $[1] !== labelField || $[2] !== record) {
2573
+ if ($[0] !== collection || $[1] !== collectionId || $[2] !== record) {
2564
2574
  t1 = {
2565
2575
  collectionId,
2566
- labelField,
2576
+ collection,
2567
2577
  loaded: record
2568
2578
  };
2569
- $[0] = collectionId;
2570
- $[1] = labelField;
2579
+ $[0] = collection;
2580
+ $[1] = collectionId;
2571
2581
  $[2] = record;
2572
2582
  $[3] = t1;
2573
2583
  } else t1 = $[3];
@@ -2900,6 +2910,7 @@ function createEditableBlock(options) {
2900
2910
  settings: settingsDefaults,
2901
2911
  slot: null,
2902
2912
  summary: "",
2913
+ title: "",
2903
2914
  position: "",
2904
2915
  createdAt: 0,
2905
2916
  updatedAt: 0
@@ -1,7 +1,7 @@
1
1
  import { useProjectUuid } from "../../lib/auth.js";
2
2
  import { reads, useReadQuery } from "../../lib/studio-reads.js";
3
3
  import { latestContent } from "../lib/reference.js";
4
- import { fieldPlainText } from "../recordItem.js";
4
+ import { recordText } from "../recordItem.js";
5
5
  import { c } from "react/compiler-runtime";
6
6
 
7
7
  //#region src/core/editing/useLatestRecord.ts
@@ -11,7 +11,7 @@ import { c } from "react/compiler-runtime";
11
11
  */
12
12
  function useLatestRecord(t0) {
13
13
  const $ = c(21);
14
- const { collectionId, labelField, loaded } = t0;
14
+ const { collectionId, collection, loaded } = t0;
15
15
  const projectUuid = useProjectUuid();
16
16
  let t1;
17
17
  if ($[0] !== collectionId || $[1] !== loaded?.id || $[2] !== projectUuid) {
@@ -42,13 +42,13 @@ function useLatestRecord(t0) {
42
42
  let t5;
43
43
  let t6;
44
44
  let updatedAt;
45
- if ($[5] !== collectionId || $[6] !== labelField || $[7] !== loaded || $[8] !== saved) {
45
+ if ($[5] !== collection || $[6] !== collectionId || $[7] !== loaded || $[8] !== saved) {
46
46
  ({content, updatedAt} = latestContent(loaded, saved));
47
47
  t4 = loaded.id;
48
48
  t5 = collectionId;
49
- t6 = fieldPlainText(content[labelField]);
50
- $[5] = collectionId;
51
- $[6] = labelField;
49
+ t6 = recordText(collection, content);
50
+ $[5] = collection;
51
+ $[6] = collectionId;
52
52
  $[7] = loaded;
53
53
  $[8] = saved;
54
54
  $[9] = content;
@@ -68,7 +68,7 @@ function useLatestRecord(t0) {
68
68
  t7 = {
69
69
  id: t4,
70
70
  collectionId: t5,
71
- label: t6,
71
+ ...t6,
72
72
  content,
73
73
  references: loaded.references,
74
74
  updatedAt
@@ -0,0 +1,54 @@
1
+ //#region src/core/layoutContext.d.ts
2
+ /**
3
+ * The context every layout `to*` option receives. Each name always means the same thing and is
4
+ * absent where it doesn't apply: curated pages have no loader, so no `data` or `params`, and only
5
+ * record pages have `content`.
6
+ */
7
+ /** The page a layout renders. */
8
+ export interface LayoutPage {
9
+ /**
10
+ * The undecorated title: the editor's or generated meta title on curated pages, the layout's
11
+ * title on singleton and derived pages, the record's title on record pages.
12
+ */
13
+ title: string;
14
+ /**
15
+ * The editor's or generated description on curated pages, the record's description on record
16
+ * pages. Absent otherwise.
17
+ */
18
+ description: string | undefined;
19
+ /** The page's path, with its locale's prefix. */
20
+ path: string;
21
+ /** The tag of the locale the page renders in, such as `de`. */
22
+ locale: string;
23
+ /**
24
+ * When the page was first published to Live: on record pages, its record. Absent while it was
25
+ * never published.
26
+ */
27
+ firstPublishedAt?: Date;
28
+ /** When the page was last published to Live: on record pages, its record. */
29
+ lastPublishedAt?: Date;
30
+ }
31
+ /** The project a page belongs to. */
32
+ export interface LayoutProject {
33
+ name: string;
34
+ }
35
+ /** What every layout `to*` option knows about a curated page. */
36
+ export interface CuratedLayoutContext {
37
+ page: LayoutPage;
38
+ project: LayoutProject;
39
+ }
40
+ /** What every layout `to*` option knows about a singleton or derived page. */
41
+ export interface LoadedLayoutContext<Data = unknown, Params = Record<string, string>> extends CuratedLayoutContext {
42
+ data: Data;
43
+ params: Params;
44
+ }
45
+ /**
46
+ * On record pages, `content` holds the record's values: its String fields as plain text, and its
47
+ * references as links to their records' Structured Data nodes.
48
+ */
49
+ export interface RecordLayoutContext<Data = unknown, Params = Record<string, string>, Content = Record<string, unknown>> extends LoadedLayoutContext<Data, Params> {
50
+ content: Content;
51
+ }
52
+ /** Any layout's context, as the runtime builds it. */
53
+ export type AnyLayoutContext = CuratedLayoutContext & Partial<Pick<RecordLayoutContext, "data" | "params" | "content">>;
54
+ //#endregion
@@ -0,0 +1,66 @@
1
+ import { localizedPath } from "../lib/locale-path.js";
2
+
3
+ //#region src/core/layoutContext.ts
4
+ /**
5
+ * A curated page's undecorated title: its meta title, or its nickname while it has none, such as
6
+ * before its meta title is generated. Everything naming a curated page names it by this.
7
+ */
8
+ function curatedPageTitle(page) {
9
+ return page.metaTitle || page.nickname;
10
+ }
11
+ /** A curated page's context, from its editor metadata. Its path keeps its locale's prefix. */
12
+ function curatedLayoutContext(structure, locale) {
13
+ const { page } = structure;
14
+ return buildLayoutContext({
15
+ kind: "curated",
16
+ title: ""
17
+ }, {
18
+ metaTitle: curatedPageTitle(page),
19
+ description: page.metaDescription ?? void 0,
20
+ path: localizedPath(page.fullPath, locale),
21
+ locale: locale.tag,
22
+ projectName: structure.projectName,
23
+ published: {
24
+ first: page.firstPublishedAt,
25
+ last: page.publishedAt
26
+ }
27
+ });
28
+ }
29
+ /** A page's publish times as its context holds them: dates, absent when unknown. */
30
+ function publishDates(published) {
31
+ return {
32
+ ...published?.first != null && { firstPublishedAt: new Date(published.first) },
33
+ ...published?.last != null && { lastPublishedAt: new Date(published.last) }
34
+ };
35
+ }
36
+ /** The context a layout's `to*` options receive on a page. */
37
+ function buildLayoutContext(layout, source) {
38
+ const project = { name: source.projectName };
39
+ const page = {
40
+ path: source.path,
41
+ locale: source.locale,
42
+ ...publishDates(source.record?.published ?? source.published)
43
+ };
44
+ if (layout.kind === "curated") return {
45
+ page: {
46
+ title: source.metaTitle ?? "",
47
+ description: source.description,
48
+ ...page
49
+ },
50
+ project
51
+ };
52
+ return {
53
+ page: {
54
+ title: source.record?.title ?? layout.title,
55
+ description: source.record?.description,
56
+ ...page
57
+ },
58
+ project,
59
+ data: source.data,
60
+ params: source.params ?? {},
61
+ ...source.record && { content: source.record.content }
62
+ };
63
+ }
64
+
65
+ //#endregion
66
+ export { buildLayoutContext, curatedLayoutContext, curatedPageTitle };