@riverbankcms/sdk 0.80.0 → 0.81.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 (265) hide show
  1. package/dist/{PreviewEditorSidebar-QZG37QIF.mjs → PreviewEditorSidebar-RDCMEXIJ.mjs} +763 -255
  2. package/dist/{PreviewEditorUI-AXIKSMZA.mjs → PreviewEditorUI-NYGQ6K7B.mjs} +170 -29
  3. package/dist/SdkPreviewModeRuntime-AKCSCZEC.mjs +8 -0
  4. package/dist/_dts/api/src/contentRuntime.d.ts +12 -0
  5. package/dist/_dts/api/src/contentTypes.d.ts +6 -0
  6. package/dist/_dts/api/src/index.d.ts +2 -2
  7. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +53 -0
  8. package/dist/_dts/block-form/src/backend/store-backend.d.ts +3 -1
  9. package/dist/_dts/block-form/src/backend/types.d.ts +3 -3
  10. package/dist/_dts/blocks/src/PageRenderer.d.ts +3 -0
  11. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +20 -28
  12. package/dist/_dts/blocks/src/index.d.ts +6 -4
  13. package/dist/_dts/blocks/src/primitives/content/components/Text.d.ts +1 -1
  14. package/dist/_dts/blocks/src/primitives/content/primitives.d.ts +1 -0
  15. package/dist/_dts/blocks/src/server.d.ts +1 -1
  16. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +3 -2
  17. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +135 -0
  18. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +5 -0
  19. package/dist/_dts/blocks/src/system/blocks/feature-cards.d.ts +2 -0
  20. package/dist/_dts/blocks/src/system/blocks/form.d.ts +20 -1
  21. package/dist/_dts/blocks/src/system/blocks/hero.d.ts +2 -0
  22. package/dist/_dts/blocks/src/system/blocks/offerings-preview/index.d.ts +19 -0
  23. package/dist/_dts/blocks/src/system/blocks/offerings-preview/model.d.ts +134 -0
  24. package/dist/_dts/blocks/src/system/componentFactory.d.ts +1 -0
  25. package/dist/_dts/blocks/src/system/constants/background.d.ts +1 -1
  26. package/dist/_dts/blocks/src/system/constants/blockKinds.d.ts +1 -1
  27. package/dist/_dts/blocks/src/system/customize/backgrounds.d.ts +13 -3
  28. package/dist/_dts/blocks/src/system/data/index.d.ts +2 -0
  29. package/dist/_dts/blocks/src/system/data/linkedContentEntries.d.ts +64 -0
  30. package/dist/_dts/blocks/src/system/data/loaderEndpoints.d.ts +1 -1
  31. package/dist/_dts/blocks/src/system/designCapabilities.d.ts +2 -2
  32. package/dist/_dts/blocks/src/system/fields/boxStyles.d.ts +6 -1
  33. package/dist/_dts/blocks/src/system/fragments/library/faqHeading.d.ts +0 -1
  34. package/dist/_dts/blocks/src/system/media/slotContracts.d.ts +2 -0
  35. package/dist/_dts/blocks/src/system/node/types.d.ts +8 -1
  36. package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +1 -1
  37. package/dist/_dts/blocks/src/system/registry.d.ts +1 -0
  38. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +44 -50
  39. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +21 -24
  40. package/dist/_dts/blocks/src/system/runtime/headingDecoration.d.ts +21 -0
  41. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.d.ts +45 -14
  42. package/dist/_dts/blocks/src/system/runtime/hooks/useEventFilters.d.ts +2 -9
  43. package/dist/_dts/blocks/src/system/runtime/hooks/useEventPagination.d.ts +1 -10
  44. package/dist/_dts/blocks/src/system/runtime/nodes/basic.d.ts +1 -0
  45. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.interactive.d.ts +21 -16
  46. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +3 -2
  47. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +21 -16
  48. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +17 -28
  49. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventPaginatedListView.client.d.ts +2 -3
  50. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekAgendaView.d.ts +3 -3
  51. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/listOptions.d.ts +50 -0
  52. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/utils.d.ts +2 -1
  53. package/dist/_dts/blocks/src/system/runtime/nodes/media.d.ts +29 -14
  54. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview.d.ts +21 -0
  55. package/dist/_dts/blocks/src/system/runtime/resolver.d.ts +7 -0
  56. package/dist/_dts/blocks/src/system/transforms/registry/_utils/sectionForegroundStyles.d.ts +2 -0
  57. package/dist/_dts/blocks/src/system/transforms/registry/boxStyles.d.ts +4 -2
  58. package/dist/_dts/calendar/src/grid.d.ts +27 -0
  59. package/dist/_dts/calendar/src/index.d.ts +2 -2
  60. package/dist/_dts/content-editor/src/controller/useAutosaveTriggers.d.ts +3 -1
  61. package/dist/_dts/content-editor/src/editorTransactionState.d.ts +1 -0
  62. package/dist/_dts/content-editor/src/hooks/autosaveScopePlanning.d.ts +26 -0
  63. package/dist/_dts/content-editor/src/hooks/publishability.d.ts +1 -0
  64. package/dist/_dts/content-editor/src/hooks/useLinkedEntryAutosave.d.ts +23 -0
  65. package/dist/_dts/content-editor/src/hooks/useReactiveToolbar.d.ts +1 -1
  66. package/dist/_dts/content-editor/src/hooks/useSimpleAutosave.d.ts +2 -2
  67. package/dist/_dts/content-editor/src/index.d.ts +3 -1
  68. package/dist/_dts/content-editor/src/lib/json.d.ts +2 -0
  69. package/dist/_dts/content-editor/src/linkedEntries/domain.d.ts +8 -0
  70. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +58 -0
  71. package/dist/_dts/content-editor/src/ui/editorTransactionState.d.ts +93 -0
  72. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +60 -3
  73. package/dist/_dts/content-editor/src/ui/stores/autosaveStore.d.ts +2 -0
  74. package/dist/_dts/content-editor/src/ui/stores/types.d.ts +1 -1
  75. package/dist/_dts/content-model/src/content-types/builtins.d.ts +43 -0
  76. package/dist/_dts/content-model/src/metadataConfig.d.ts +87 -47
  77. package/dist/_dts/core/src/branded.d.ts +5 -0
  78. package/dist/_dts/core/src/index.d.ts +1 -0
  79. package/dist/_dts/core/src/stable-json.d.ts +1 -0
  80. package/dist/_dts/editor/src/EditorProvider.d.ts +26 -0
  81. package/dist/_dts/editor/src/chrome/EditorChrome.d.ts +26 -0
  82. package/dist/_dts/editor/src/chrome/EditorStatusBar.d.ts +45 -0
  83. package/dist/_dts/editor/src/chrome/statusBarPresentation.d.ts +25 -0
  84. package/dist/_dts/editor/src/components/EditingToggle.d.ts +9 -0
  85. package/dist/_dts/editor/src/hooks/useEditableElement.d.ts +18 -0
  86. package/dist/_dts/editor/src/index.d.ts +29 -0
  87. package/dist/_dts/editor/src/inline/InlineTextEditor.d.ts +1 -0
  88. package/dist/_dts/editor/src/lib/utils.d.ts +1 -0
  89. package/dist/_dts/editor/src/primitives/EditorPrimitivesProvider.d.ts +20 -0
  90. package/dist/_dts/editor/src/primitives/InlineFieldContext.d.ts +11 -0
  91. package/dist/_dts/editor/src/primitives/SaveContext.d.ts +12 -0
  92. package/dist/_dts/editor/src/primitives/helpers.d.ts +1 -0
  93. package/dist/_dts/editor/src/primitives/rich-text/RichTextEditorSurface.d.ts +26 -0
  94. package/dist/_dts/editor/src/primitives/rich-text/RichTextToolbar.d.ts +16 -0
  95. package/dist/_dts/editor/src/primitives/rich-text/config.d.ts +23 -0
  96. package/dist/_dts/editor/src/primitives/rich-text/extensions/RichTextImage.d.ts +2 -0
  97. package/dist/_dts/editor/src/primitives/rich-text/extensions/RichTextLink.d.ts +1 -0
  98. package/dist/_dts/editor/src/primitives/rich-text/imageActions.d.ts +22 -0
  99. package/dist/_dts/editor/src/primitives/rich-text/sanitize.d.ts +23 -0
  100. package/dist/_dts/editor/src/primitives/rich-text/toolbar/BlockTypeDropdown.d.ts +6 -0
  101. package/dist/_dts/editor/src/primitives/rich-text/toolbar/LinkPopover.d.ts +10 -0
  102. package/dist/_dts/editor/src/primitives/rich-text/toolbar/ToolbarIconButton.d.ts +11 -0
  103. package/dist/_dts/editor/src/primitives/rich-text/toolbar/linkPopoverUtils.d.ts +58 -0
  104. package/dist/_dts/editor/src/primitives/rich-text/useRichTextEditor.d.ts +19 -0
  105. package/dist/_dts/editor/src/primitives/rich-text/utils.d.ts +20 -0
  106. package/dist/_dts/editor/src/utils/optimisticTokens.d.ts +27 -0
  107. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +2 -2
  108. package/dist/_dts/editor-blocks/src/block-editor/BlockCard.d.ts +3 -3
  109. package/dist/_dts/editor-blocks/src/block-editor/BlockCardHeader.d.ts +4 -4
  110. package/dist/_dts/editor-blocks/src/block-editor/SortableBlockItem.d.ts +2 -2
  111. package/dist/_dts/editor-blocks/src/block-editor/actionPresentation.d.ts +15 -0
  112. package/dist/_dts/editor-blocks/src/block-editor/blockHeaderActionPlan.d.ts +49 -0
  113. package/dist/_dts/editor-blocks/src/widgets/index.d.ts +1 -0
  114. package/dist/_dts/editor-blocks/src/widgets/rich-text/RichTextWidgetProvider.d.ts +1 -1
  115. package/dist/_dts/editor-blocks/src/widgets/rich-text/useImagePicker.d.ts +1 -1
  116. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/SiteOptionPickerField.d.ts +3 -0
  117. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/SiteOptionWidgetProvider.d.ts +14 -0
  118. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/index.d.ts +6 -0
  119. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/loaders.d.ts +51 -0
  120. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/types.d.ts +20 -0
  121. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/utils.d.ts +5 -0
  122. package/dist/_dts/media-core/src/index.d.ts +1 -0
  123. package/dist/_dts/media-core/src/renderableMediaAsset.d.ts +18 -0
  124. package/dist/_dts/media-editor/src/MediaEditor.d.ts +4 -1
  125. package/dist/_dts/media-editor/src/MediaPickerDialog.d.ts +2 -1
  126. package/dist/_dts/media-editor/src/index.d.ts +1 -1
  127. package/dist/_dts/preview-next/src/client/blocks/BlockToolbar.d.ts +3 -2
  128. package/dist/_dts/preview-next/src/client/blocks/EditablePageRenderer.d.ts +5 -1
  129. package/dist/_dts/preview-next/src/client/blocks/blockCustomizePopoverRows.d.ts +25 -0
  130. package/dist/_dts/preview-next/src/client/blocks/composer/mergeDrafts.d.ts +2 -1
  131. package/dist/_dts/preview-next/src/client/blocks/composer/types.d.ts +4 -30
  132. package/dist/_dts/preview-next/src/client/blocks/linkedEntryRenderOverlay.d.ts +11 -0
  133. package/dist/_dts/preview-next/src/client/blocks/previewCustomizeActions.d.ts +3 -9
  134. package/dist/_dts/preview-next/src/client/blocks/useBlockCustomizeControls.d.ts +2 -1
  135. package/dist/_dts/preview-next/src/client/index.d.ts +0 -1
  136. package/dist/_dts/preview-next/src/client/preview/EntryEditorPanel.d.ts +3 -1
  137. package/dist/_dts/preview-next/src/client/preview/LinkedEntryEditEventBridge.d.ts +1 -0
  138. package/dist/_dts/preview-next/src/client/preview/PageBlockEditorPanel.d.ts +3 -1
  139. package/dist/_dts/preview-next/src/client/preview/PreviewChromeLayer.d.ts +20 -0
  140. package/dist/_dts/preview-next/src/client/preview/PreviewDesignHistoryOrderContext.d.ts +13 -0
  141. package/dist/_dts/preview-next/src/client/preview/PreviewOpenEditorButton.d.ts +1 -1
  142. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +19 -19
  143. package/dist/_dts/preview-next/src/client/preview/PreviewSidebarSection.d.ts +13 -0
  144. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +47 -4
  145. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +14 -1
  146. package/dist/_dts/preview-next/src/client/preview/linkedEntryEditEvents.d.ts +5 -0
  147. package/dist/_dts/preview-next/src/client/preview/previewChromePlacement.d.ts +46 -0
  148. package/dist/_dts/preview-next/src/client/preview/previewCustomizeControls.d.ts +68 -0
  149. package/dist/_dts/preview-next/src/client/preview/previewCustomizeHistory.d.ts +8 -1
  150. package/dist/_dts/preview-next/src/client/preview/previewCustomizeWorkflowState.d.ts +11 -9
  151. package/dist/_dts/preview-next/src/client/preview/previewDesignHistoryOrder.d.ts +18 -0
  152. package/dist/_dts/preview-next/src/client/preview/previewUndoDomains.d.ts +1 -1
  153. package/dist/_dts/preview-next/src/client/preview/siteChromeBrandPreferences.d.ts +41 -0
  154. package/dist/_dts/preview-next/src/client/preview/siteChromeQuickControlHistoryState.d.ts +101 -0
  155. package/dist/_dts/preview-next/src/client/preview/siteChromeSavePlan.d.ts +29 -0
  156. package/dist/_dts/preview-next/src/client/preview/siteStyleHistoryState.d.ts +55 -0
  157. package/dist/_dts/preview-next/src/client/preview/styleConfiguratorApplyPayload.d.ts +1 -0
  158. package/dist/_dts/preview-next/src/client/widgets/widgetAdapters.d.ts +2 -1
  159. package/dist/_dts/preview-next/src/client/widgets/widgetOverrides.d.ts +3 -2
  160. package/dist/_dts/preview-next/src/constants.d.ts +0 -1
  161. package/dist/_dts/sdk/src/cli/config-loader.d.ts +3 -1
  162. package/dist/_dts/sdk/src/cli/content/reader.d.ts +5 -3
  163. package/dist/_dts/sdk/src/cli/site-commands/commandSurfaceDispatch.d.ts +1 -0
  164. package/dist/_dts/sdk/src/cli/site-commands/pageCommands.d.ts +3 -1
  165. package/dist/_dts/sdk/src/cli/site-commands/pushExecution.d.ts +1 -0
  166. package/dist/_dts/sdk/src/config/types.d.ts +1 -1
  167. package/dist/_dts/sdk/src/config/validation.d.ts +3 -3
  168. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +28 -2
  169. package/dist/_dts/sdk/src/public-api/contracts.d.ts +10 -0
  170. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +42 -0
  171. package/dist/_dts/sdk/src/rendering/mediaAssets.d.ts +4 -0
  172. package/dist/_dts/sdk/src/types/block-kinds.d.ts +1 -1
  173. package/dist/_dts/sdk/src/version.d.ts +1 -1
  174. package/dist/_dts/theme-core/src/buttons/constants.d.ts +26 -1
  175. package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +11 -0
  176. package/dist/_dts/theme-core/src/buttons/personalities/joy-stamp.d.ts +22 -0
  177. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +1 -0
  178. package/dist/_dts/theme-core/src/buttons/types.d.ts +9 -0
  179. package/dist/_dts/theme-core/src/cards/siteStyleDefaults.d.ts +44 -0
  180. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  181. package/dist/_dts/theme-core/src/interactive/types.d.ts +10 -0
  182. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +27 -6
  183. package/dist/_dts/theme-core/src/palette/variants/index.d.ts +15 -0
  184. package/dist/_dts/theme-core/src/palette/variants/warm-dark.d.ts +27 -0
  185. package/dist/_dts/theme-core/src/schema.d.ts +40 -3
  186. package/dist/_dts/theme-core/src/site-styles/accessibleSurfaces.d.ts +4 -1
  187. package/dist/_dts/theme-core/src/site-styles/appearancePresetCatalog.d.ts +87 -31
  188. package/dist/_dts/theme-core/src/site-styles/appearancePresetResolution.d.ts +6 -2
  189. package/dist/_dts/theme-core/src/site-styles/blockAppearancePresets.d.ts +87 -31
  190. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +30 -1
  191. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +18 -2
  192. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +6 -2
  193. package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +5 -0
  194. package/dist/_dts/theme-core/src/site-styles/index.d.ts +1 -0
  195. package/dist/_dts/theme-core/src/site-styles/pageDesignEditorModel.d.ts +3 -23
  196. package/dist/_dts/theme-core/src/site-styles/pageDesignIntent.d.ts +276 -4
  197. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +33 -3
  198. package/dist/_dts/theme-core/src/site-styles/sectionTransitions.d.ts +508 -0
  199. package/dist/_dts/theme-core/src/site-styles/sourceCatalogs.d.ts +10 -10
  200. package/dist/_dts/theme-core/src/site-styles/types.d.ts +24 -6
  201. package/dist/_dts/theme-core/src/site-styles/typographyPresets.d.ts +16 -1
  202. package/dist/{chunk-7PCYG6YV.mjs → chunk-3PTVPAT4.mjs} +1863 -1099
  203. package/dist/{chunk-5NZGBSJF.mjs → chunk-3QWQ2MUQ.mjs} +469 -1000
  204. package/dist/{chunk-HTB4BMKD.mjs → chunk-3VT7LZY2.mjs} +321 -113
  205. package/dist/{chunk-MPBNEVPB.mjs → chunk-4T5JIPWY.mjs} +1 -1
  206. package/dist/{chunk-BBLZSQEY.mjs → chunk-E3NZYEKF.mjs} +1 -7
  207. package/dist/{chunk-GYXKAUFV.mjs → chunk-WUHKQBB6.mjs} +9509 -2658
  208. package/dist/cli/index.mjs +1347 -324
  209. package/dist/client/{accordion-QFZMNB7O.mjs → accordion-SFIIZWNH.mjs} +2 -2
  210. package/dist/client/{bookingForm-NCIXFWIG.mjs → bookingForm-CFKZVWGA.mjs} +5 -5
  211. package/dist/client/bookings.mjs +281 -19
  212. package/dist/client/{carousel-EO4BJMWD.mjs → carousel-ELXWSBLA.mjs} +3 -3
  213. package/dist/client/{cart-FTYCLYUW.mjs → cart-6SSCPYY5.mjs} +6 -6
  214. package/dist/client/{checkout-NFGLVCOX.mjs → checkout-UFQ34HPV.mjs} +6 -6
  215. package/dist/client/{chunk-6GVVWSPU.mjs → chunk-76JUETXQ.mjs} +139 -186
  216. package/dist/client/{chunk-AUJ5DBZJ.mjs → chunk-7BXX7WXH.mjs} +112 -28
  217. package/dist/client/{chunk-IWFZSQNZ.mjs → chunk-G56BSZAM.mjs} +2 -2
  218. package/dist/client/{chunk-VDS5YFLX.mjs → chunk-IUEDYLFJ.mjs} +1 -1
  219. package/dist/client/{chunk-PYRBIURC.mjs → chunk-NP47RHIX.mjs} +5 -5
  220. package/dist/client/{chunk-PUOELU4O.mjs → chunk-NX6X3GRF.mjs} +330 -80
  221. package/dist/client/{chunk-Y37KDO7P.mjs → chunk-PA2LJH2M.mjs} +2 -2
  222. package/dist/client/{chunk-CE7IBGVW.mjs → chunk-RMWMT3ZD.mjs} +1 -1
  223. package/dist/client/{chunk-4W66ALYT.mjs → chunk-TCJS3NY5.mjs} +1 -1
  224. package/dist/client/{chunk-T6UIP6UZ.mjs → chunk-V6XI4M2Q.mjs} +1 -1
  225. package/dist/client/client.mjs +5924 -3138
  226. package/dist/client/{courseRegistration-2EORROPS.mjs → courseRegistration-HJIISAAG.mjs} +5 -5
  227. package/dist/client/{eventCalendar-WZI4VL6N.mjs → eventCalendar-F6YVUCZR.mjs} +7 -7
  228. package/dist/client/{eventCombined-QCB2TCNL.mjs → eventCombined-B5DSTIOK.mjs} +7 -7
  229. package/dist/client/{eventDetails-TFTATAPH.mjs → eventDetails-SEJDDHQC.mjs} +7 -7
  230. package/dist/client/{eventListing-A2CQEHEQ.mjs → eventListing-TPMWIIBO.mjs} +7 -7
  231. package/dist/client/{eventRegistration-OELPVLUY.mjs → eventRegistration-QU6W2PV6.mjs} +7 -7
  232. package/dist/client/{form-NTIFD6WQ.mjs → form-LVTYNTDE.mjs} +2 -2
  233. package/dist/client/{headerSection-7TBNKCLA.mjs → headerSection-SO3MFC4U.mjs} +54 -13
  234. package/dist/client/hooks.mjs +2266 -1179
  235. package/dist/client/{locationMap-LRLB5A3H.mjs → locationMap-5E5FLAKO.mjs} +2 -2
  236. package/dist/client/{newsletterForm-XI52RZSN.mjs → newsletterForm-GN32JEBQ.mjs} +2 -2
  237. package/dist/client/{productDetail-GSNKBFLY.mjs → productDetail-Q346KSVR.mjs} +6 -6
  238. package/dist/client/{productList-BGCGT4KZ.mjs → productList-DTDMQYGZ.mjs} +6 -6
  239. package/dist/client/rendering/client.mjs +4618 -3318
  240. package/dist/client/rendering/islands.mjs +32 -20
  241. package/dist/client/rendering.mjs +4898 -2108
  242. package/dist/client/{shop-RQHUCLNY.mjs → shop-OFUW7KPN.mjs} +6 -6
  243. package/dist/preview-next/client/runtime.mjs +5 -5
  244. package/dist/preview-next/constants.mjs +0 -2
  245. package/dist/preview-next/index.mjs +0 -2
  246. package/dist/{sdk-runtime-A4LHT2RS.mjs → sdk-runtime-2GIX6I7X.mjs} +6 -6
  247. package/dist/server/components.mjs +4377 -1852
  248. package/dist/server/config-validation.mjs +2283 -1303
  249. package/dist/server/config.mjs +2283 -1303
  250. package/dist/server/data.mjs +2267 -1180
  251. package/dist/server/index.mjs +2 -1
  252. package/dist/server/next.mjs +4394 -1773
  253. package/dist/server/page-converter.mjs +1999 -1015
  254. package/dist/server/prebuild.mjs +1 -1
  255. package/dist/server/rendering/server.mjs +4482 -1857
  256. package/dist/server/rendering.mjs +4484 -1859
  257. package/dist/server/routing.mjs +2302 -1120
  258. package/dist/server/server.mjs +2284 -1197
  259. package/dist/server/theme-bridge.mjs +757 -85
  260. package/dist/server/theme.mjs +69 -4
  261. package/dist/styles/index.css +474 -65
  262. package/package.json +1 -1
  263. package/dist/SdkPreviewModeRuntime-XE5M4UKM.mjs +0 -8
  264. package/dist/_dts/editor-blocks/src/block-editor/actionControlMode.d.ts +0 -2
  265. package/dist/_dts/preview-next/src/client/preview/previewSurface.d.ts +0 -3
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { resolvePreviewDashboardSetupHandoff, buildPreviewDashboardSetupUrl, resolvePreviewSidebarChromeModel, resolvePreviewEditorGuidanceModel, ButtonVariantField, IconPickerField, EntryPickerField, ReferenceField, RichTextField, MediaField, FileField, LinkField, canInspectSiteStyle, mapContentSchemaToFormFields, usePreviewBlockCustomizeSelectionOptional, BlockEditor, usePreviewDesignCoordinator, resolveStyleConfiguratorInitialSnapshot, createStyleConfiguratorState, createOptimisticActionRunner, syncStyleConfiguratorState, isPreviewingChange, planSiteStylePreviewChange, openRow, previewSiteStyle, applyResolvedSelections, previewButtonPersonality, previewHeaderLayout, previewHeaderStyle, planSiteChromeLookSelection, previewFooterLook, previewPaletteVariant, previewTypographyPreset, setTypographyBodyFontOverride, setTypographyHeadingFontOverride, clearTypographyFontOverrides, setPaletteOverrides, toggleRow, cancelPreview, dismissWarnings, dismissNotices, markApplyFailed, markApplySaved, markApplySaving, canApplySiteStyle, buildSiteChromeLookModels, cycleSiteChromeLookId, LinkWidgetProvider, ReferenceWidgetProvider, EntryPickerWidgetProvider, ButtonWidgetProvider, cycleableSiteChromeOptions, BUILT_IN_REFERENCE_KINDS, useRichTextImagePicker, RichTextWidgetProvider, useBlockCustomizeControls, MAX_QUICK_MANIFEST_FIELDS, parseReferenceKind } from './chunk-5NZGBSJF.mjs';
3
- import { unwrapResponse, useEntryController, useEditorUiStoreInstance, useUISelector, resolvePreviewSidebarTab, BackgroundGradientField, BackgroundColorField, unsafeAsEditorBlockId, Tabs, TabsList, TabsTrigger, Button, X, TabsContent, omitRouteTitleFieldFromManifest, getRouteMetadataManifestForType, createManifestValidation, createStoreBackend, ManifestForm, previewAssistantEnabled, Collapsible, CollapsibleTrigger, ChevronRight, CollapsibleContent, ContentFieldsForm, getCuratedSiteStyle, paletteOverridesSchema, findButtonPersonality, findPaletteVariant, findTypographyPreset, getHeaderLayout, getHeaderStyle, findFooterLook, footerLookCatalog, foldSubroute, SUBROUTE_KINDS, Smartphone, Tablet, Monitor, Maximize2, cn, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuItem, expectParsedBrandedId, parseSiteId, buildThemeRuntime, SdkConfigProvider, PaletteProvider, MediaEditorProvider, curatedSiteStyles, ChevronLeft, requireEntriesForCuratedChoices, buttonPersonalities, typographyPresets, paletteVariants, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, FormRenderer, evaluateTypographyFontSlot, Callout, CalloutDescription, Separator, Surface, ColorPicker, Input } from './chunk-GYXKAUFV.mjs';
4
- import { usePreviewAuth, getDashboardUrl } from './chunk-BBLZSQEY.mjs';
2
+ import { resolvePreviewDashboardSetupHandoff, buildPreviewDashboardSetupUrl, resolvePreviewSidebarChromeModel, resolvePreviewEditorGuidanceModel, SiteOptionPickerField, ButtonVariantField, IconPickerField, EntryPickerField, ReferenceField, RichTextField, MediaField, FileField, LinkField, canInspectSiteStyle, mapContentSchemaToFormFields, usePreviewBlockCustomizeSelectionOptional, BlockEditor, canApplySiteStyle, LinkWidgetProvider, ReferenceWidgetProvider, EntryPickerWidgetProvider, SiteOptionWidgetProvider, ButtonWidgetProvider, createSiteOptionWidgetAdapters, createSiteOptionApiLoader, BUILT_IN_REFERENCE_KINDS, useRichTextImagePicker, RichTextWidgetProvider, useBlockCustomizeControls, MAX_QUICK_MANIFEST_FIELDS, parseReferenceKind } from './chunk-3QWQ2MUQ.mjs';
3
+ import { unwrapResponse, useEntryController, useEditorUiStoreInstance, useUISelector, resolvePreviewSidebarTab, BackgroundGradientField, BackgroundColorField, unsafeAsEditorBlockId, Tabs, TabsList, TabsTrigger, Button, X, TabsContent, useEditorUiStore, deriveRouteMetadataPresentation, resolvePageRouteSlug, createManifestValidation, createStoreBackend, ManifestForm, previewAssistantEnabled, Collapsible, CollapsibleTrigger, ChevronRight, CollapsibleContent, ContentFieldsForm, usePreviewDesignCoordinator, useSiteChromeCustomizeOptional, resolveStyleConfiguratorInitialSnapshot, createStyleConfiguratorState, isPreviewingChange, createOptimisticActionRunner, syncStyleConfiguratorState, getCuratedSiteStyle, planSiteStylePreviewChange, openRow, previewSiteStyle, applyResolvedSelections, previewButtonPersonality, previewHeaderLayout, previewHeaderStyle, planSiteChromeLookSelection, previewFooterLook, previewPaletteVariant, previewTypographyPreset, setTypographyBodyFontOverride, setTypographyHeadingFontOverride, clearTypographyFontOverrides, paletteOverridesSchema, setPaletteOverrides, toggleRow, cancelPreview, dismissWarnings, dismissNotices, deriveStyleConfiguratorCapabilities, buildApplySiteStyleSelectionBody, markApplyFailed, selectionSnapshotFromApplySiteStyleSelectionResponse, styleConfiguratorHistoryEntryForPersistedSelection, markApplySaved, markApplySaving, findButtonPersonality, findPaletteVariant, findTypographyPreset, buildSiteChromeLookModels, getHeaderLayout, getHeaderStyle, findFooterLook, cycleSiteChromeLookId, footerLookCatalog, resolveContentTitle, foldSubroute, SUBROUTE_KINDS, Smartphone, Tablet, Monitor, Maximize2, cn, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuItem, expectParsedBrandedId, parseSiteId, buildThemeRuntime, SdkConfigProvider, PaletteProvider, MediaEditorProvider, curatedSiteStyles, ChevronLeft, cycleableSiteChromeOptions, requireEntriesForCuratedChoices, buttonPersonalities, typographyPresets, paletteVariants, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, FormRenderer, evaluateTypographyFontSlot, Callout, CalloutDescription, Separator, Surface, ColorPicker, Input } from './chunk-WUHKQBB6.mjs';
4
+ import { usePreviewAuth, getDashboardUrl } from './chunk-E3NZYEKF.mjs';
5
5
  import './chunk-R7POPVJR.mjs';
6
6
  import { useMemo, useRef, useCallback, useEffect, useState, useTransition, useSyncExternalStore, useId } from 'react';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -216,6 +216,7 @@ var referenceLoaders = {
216
216
  // ../preview-next/src/client/widgets/widgetAdapters.ts
217
217
  var routableContentCache = /* @__PURE__ */ new Map();
218
218
  var entryPickerCache = /* @__PURE__ */ new Map();
219
+ var siteOptionItemsCache = /* @__PURE__ */ new Map();
219
220
  var referenceItemsCache = /* @__PURE__ */ new Map();
220
221
  var dynamicReferenceItemsCache = /* @__PURE__ */ new Map();
221
222
  var MAX_CACHE_ENTRIES = 50;
@@ -332,6 +333,28 @@ function createPreviewEntryPickerAdapter(previewClient) {
332
333
  }
333
334
  };
334
335
  }
336
+ function createCachedSiteOptionLoader(loadItems) {
337
+ return async ({ siteId, source }) => {
338
+ const cacheKey = `${source}:${siteId}`;
339
+ const cached = siteOptionItemsCache.get(cacheKey);
340
+ if (cached) return cached;
341
+ const promise = (async () => {
342
+ try {
343
+ return await loadItems({ siteId, source });
344
+ } catch (error) {
345
+ siteOptionItemsCache.delete(cacheKey);
346
+ throw error;
347
+ }
348
+ })();
349
+ setBoundedCache(siteOptionItemsCache, cacheKey, promise);
350
+ return promise;
351
+ };
352
+ }
353
+ function createPreviewSiteOptionAdapters(previewClient) {
354
+ return createSiteOptionWidgetAdapters({
355
+ loadItems: createCachedSiteOptionLoader(createSiteOptionApiLoader(previewClient))
356
+ });
357
+ }
335
358
  var previewReferenceChrome = {
336
359
  post: {
337
360
  labels: {
@@ -429,6 +452,7 @@ function PreviewFormProvider({
429
452
  const siteId = useMemo(() => expectParsedBrandedId(parseSiteId(rawSiteId)), [rawSiteId]);
430
453
  const linkAdapters = useMemo(() => createPreviewLinkAdapters(previewClient), [previewClient]);
431
454
  const entryPickerAdapter = useMemo(() => createPreviewEntryPickerAdapter(previewClient), [previewClient]);
455
+ const siteOptionAdapters = useMemo(() => createPreviewSiteOptionAdapters(previewClient), [previewClient]);
432
456
  const referenceAdapters = useMemo(
433
457
  () => createPreviewReferenceAdapters(previewClient),
434
458
  [previewClient]
@@ -442,7 +466,7 @@ function PreviewFormProvider({
442
466
  return void 0;
443
467
  }
444
468
  }, [theme]);
445
- return /* @__PURE__ */ jsx(SdkConfigProvider, { sdkConfig: sdkConfig ?? null, children: /* @__PURE__ */ jsx(PaletteProvider, { tokens: paletteTokens, children: /* @__PURE__ */ jsx(LinkWidgetProvider, { siteId, adapters: linkAdapters, children: /* @__PURE__ */ jsx(ReferenceWidgetProvider, { siteId, adapters: referenceAdapters, children: /* @__PURE__ */ jsx(EntryPickerWidgetProvider, { siteId, adapter: entryPickerAdapter, children: /* @__PURE__ */ jsx(
469
+ return /* @__PURE__ */ jsx(SdkConfigProvider, { sdkConfig: sdkConfig ?? null, children: /* @__PURE__ */ jsx(PaletteProvider, { tokens: paletteTokens, children: /* @__PURE__ */ jsx(LinkWidgetProvider, { siteId, adapters: linkAdapters, children: /* @__PURE__ */ jsx(ReferenceWidgetProvider, { siteId, adapters: referenceAdapters, children: /* @__PURE__ */ jsx(EntryPickerWidgetProvider, { siteId, adapter: entryPickerAdapter, children: /* @__PURE__ */ jsx(SiteOptionWidgetProvider, { siteId, adapters: siteOptionAdapters, children: /* @__PURE__ */ jsx(
446
470
  MediaEditorProvider,
447
471
  {
448
472
  siteId,
@@ -452,7 +476,7 @@ function PreviewFormProvider({
452
476
  mediaAssets,
453
477
  children: /* @__PURE__ */ jsx(ButtonWidgetProvider, { buttonSystem: theme?.buttons ?? null, children: /* @__PURE__ */ jsx(PreviewFormProviderInner, { theme, children }) })
454
478
  }
455
- ) }) }) }) }) });
479
+ ) }) }) }) }) }) });
456
480
  }
457
481
  var previewWidgetOverrides = {
458
482
  link: LinkField,
@@ -464,7 +488,8 @@ var previewWidgetOverrides = {
464
488
  backgroundGradient: BackgroundGradientField,
465
489
  entryPicker: EntryPickerField,
466
490
  iconPicker: IconPickerField,
467
- buttonVariant: ButtonVariantField
491
+ buttonVariant: ButtonVariantField,
492
+ siteOptionPicker: SiteOptionPickerField
468
493
  };
469
494
  function PreviewZoomControls({ zoom, onZoomChange, disabled }) {
470
495
  return /* @__PURE__ */ jsxs(
@@ -550,6 +575,25 @@ function PreviewViewportControls({
550
575
  showZoomControls ? /* @__PURE__ */ jsx(PreviewZoomControls, { zoom, onZoomChange }) : null
551
576
  ] });
552
577
  }
578
+ function PreviewSidebarSection({
579
+ label,
580
+ defaultOpen = false,
581
+ openRequestId = null,
582
+ children
583
+ }) {
584
+ const [open, setOpen] = useState(defaultOpen || openRequestId !== null);
585
+ useEffect(() => {
586
+ if (openRequestId === null) return;
587
+ setOpen(true);
588
+ }, [openRequestId]);
589
+ return /* @__PURE__ */ jsx(Collapsible, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs("div", { className: "border-b", children: [
590
+ /* @__PURE__ */ jsx(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsxs("div", { className: "flex cursor-pointer items-center gap-2 px-4 py-3 hover:bg-accent/40", children: [
591
+ /* @__PURE__ */ jsx(ChevronRight, { className: `h-4 w-4 transition ${open ? "rotate-90" : ""}` }),
592
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: label })
593
+ ] }) }),
594
+ /* @__PURE__ */ jsx(CollapsibleContent, { children })
595
+ ] }) });
596
+ }
553
597
  function SubrouteNotice({ model }) {
554
598
  return /* @__PURE__ */ jsxs("div", { className: "border-b bg-amber-50 px-4 py-3 text-amber-950", children: [
555
599
  /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: model.title }),
@@ -607,6 +651,7 @@ function EntryEditorPanel({
607
651
  supabaseUrl,
608
652
  entrySubrouteContext,
609
653
  metadataPanel,
654
+ linkedEntrySection,
610
655
  mediaAssets,
611
656
  widgets,
612
657
  viewportMode,
@@ -659,6 +704,14 @@ function EntryEditorPanel({
659
704
  ) }),
660
705
  subrouteNotice ? /* @__PURE__ */ jsx(SubrouteNotice, { model: subrouteNotice }) : null,
661
706
  /* @__PURE__ */ jsxs("div", { className: "min-h-0 flex-1 space-y-0 overflow-auto", children: [
707
+ linkedEntrySection ? /* @__PURE__ */ jsx(
708
+ PreviewSidebarSection,
709
+ {
710
+ label: linkedEntrySection.label,
711
+ openRequestId: linkedEntrySection.openRequestId,
712
+ children: linkedEntrySection.content
713
+ }
714
+ ) : null,
662
715
  contentTypeSchema && entryData.type ? /* @__PURE__ */ jsx(Collapsible, { open: contentOpen, onOpenChange: setContentOpen, children: /* @__PURE__ */ jsxs("div", { className: "border-b", children: [
663
716
  /* @__PURE__ */ jsx(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsxs("div", { className: "flex cursor-pointer items-center gap-2 px-4 py-3 hover:bg-accent/40", children: [
664
717
  /* @__PURE__ */ jsx(ChevronRight, { className: `h-4 w-4 transition ${contentOpen ? "rotate-90" : ""}` }),
@@ -812,7 +865,7 @@ function SelectedBlockCustomizeFields({
812
865
  )
813
866
  ] }) : null,
814
867
  panelFields.length > 0 ? /* @__PURE__ */ jsxs("section", { className: "space-y-3", children: [
815
- /* @__PURE__ */ jsx("div", { className: "text-xs font-medium uppercase text-muted-foreground", children: "More settings" }),
868
+ /* @__PURE__ */ jsx("div", { className: "text-xs font-medium uppercase text-muted-foreground", children: "More controls" }),
816
869
  /* @__PURE__ */ jsx(
817
870
  FormRenderer,
818
871
  {
@@ -853,6 +906,7 @@ function PageBlockEditorPanel({
853
906
  blockEditorRef,
854
907
  onBlocksChange,
855
908
  metadataPanel,
909
+ linkedEntrySection,
856
910
  designPanel,
857
911
  sdkConfig,
858
912
  mediaAssets,
@@ -870,6 +924,17 @@ function PageBlockEditorPanel({
870
924
  const [detailsOpen, setDetailsOpen] = useState(false);
871
925
  const selectionKind = customizeSelection?.selection.kind;
872
926
  const selectionRequestId = customizeSelection?.selection.kind === "selected" ? customizeSelection.selection.requestId : 0;
927
+ const handleCustomizeBlock = useCallback(
928
+ (blockId) => {
929
+ customizeSelection?.inspectBlock(blockId);
930
+ setCustomizeOpen(true);
931
+ },
932
+ [customizeSelection]
933
+ );
934
+ const blockActionPresentation = useMemo(
935
+ () => customizeSelection ? { kind: "menu", customize: { kind: "external", onSelect: handleCustomizeBlock } } : { kind: "menu", customize: { kind: "modal" } },
936
+ [customizeSelection, handleCustomizeBlock]
937
+ );
873
938
  useEffect(() => {
874
939
  if (selectionKind === "selected") {
875
940
  setCustomizeOpen(true);
@@ -898,6 +963,14 @@ function PageBlockEditorPanel({
898
963
  mediaAssets,
899
964
  sdkConfig: sdkConfig ?? null,
900
965
  children: /* @__PURE__ */ jsxs("div", { className: "min-h-0 flex-1 space-y-0 overflow-auto", children: [
966
+ linkedEntrySection ? /* @__PURE__ */ jsx(
967
+ PreviewSidebarSection,
968
+ {
969
+ label: linkedEntrySection.label,
970
+ openRequestId: linkedEntrySection.openRequestId,
971
+ children: linkedEntrySection.content
972
+ }
973
+ ) : null,
901
974
  designPanel ? /* @__PURE__ */ jsx(Collapsible, { open: designOpen, onOpenChange: setDesignOpen, children: /* @__PURE__ */ jsxs("div", { className: "border-b", children: [
902
975
  /* @__PURE__ */ jsx(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsxs("div", { className: "flex cursor-pointer items-center gap-2 px-4 py-3 hover:bg-accent/40", children: [
903
976
  /* @__PURE__ */ jsx(ChevronRight, { className: `h-4 w-4 transition ${designOpen ? "rotate-90" : ""}` }),
@@ -935,10 +1008,10 @@ function PageBlockEditorPanel({
935
1008
  uiStore: uiStoreForBlockEditor,
936
1009
  apiClient,
937
1010
  onBlocksChange,
1011
+ actionPresentation: blockActionPresentation,
938
1012
  widgetOverrides: previewWidgetOverrides,
939
1013
  sdkConfig: sdkConfig ?? null,
940
- reorderControlMode: "drag-handle-only",
941
- actionControlMode: "menu"
1014
+ reorderControlMode: "drag-handle-only"
942
1015
  },
943
1016
  pageId
944
1017
  ) }) })
@@ -1184,25 +1257,6 @@ function ContrastSwatch({ hex, label }) {
1184
1257
  ] })
1185
1258
  ] });
1186
1259
  }
1187
-
1188
- // ../preview-next/src/client/preview/styleConfiguratorApplyPayload.ts
1189
- function buildApplySiteStyleSelectionBody(input) {
1190
- return {
1191
- siteStyleId: input.previewed.siteStyleId,
1192
- buttonPersonalityId: input.previewed.buttonPersonalityId,
1193
- paletteVariantId: input.previewed.paletteVariantId,
1194
- paletteOverrides: input.previewed.paletteOverrides,
1195
- typographyPresetId: input.previewed.typographyPresetId,
1196
- typographyBodyFontOverride: input.previewed.typographyBodyFontOverride,
1197
- typographyHeadingFontOverride: input.previewed.typographyHeadingFontOverride,
1198
- headerLookId: input.previewed.headerLookId,
1199
- headerLayoutId: input.previewed.headerLayoutId,
1200
- headerStyleId: input.previewed.headerStyleId,
1201
- footerLookId: input.previewed.footerLookId,
1202
- baseSelectionVersion: input.base.selectionVersion,
1203
- selectionId: input.selectionId ?? null
1204
- };
1205
- }
1206
1260
  var MAX_FONT_RESULTS_WHEN_SEARCHING = 12;
1207
1261
  var MAX_FONT_RESULTS_WHEN_BROWSING = 8;
1208
1262
  var PALETTE_BRAND_ROLES = [
@@ -1239,6 +1293,8 @@ function StyleConfigurator({
1239
1293
  }) {
1240
1294
  const router = useRouter();
1241
1295
  const previewDesign = usePreviewDesignCoordinator();
1296
+ const siteChromeCustomize = useSiteChromeCustomizeOptional();
1297
+ const setSiteStyleStagedPreviewActive = siteChromeCustomize?.siteStyleHistory.setStagedPreviewActive;
1242
1298
  const {
1243
1299
  applyFailed,
1244
1300
  applyStarted,
@@ -1258,12 +1314,20 @@ function StyleConfigurator({
1258
1314
  headerSelectionContext,
1259
1315
  footerSelectionContext
1260
1316
  }),
1261
- [footerSelectionContext, headerSelectionContext, theme, initialSelections, selectionUpdatedAt, selectionVersion]
1317
+ [
1318
+ footerSelectionContext,
1319
+ headerSelectionContext,
1320
+ theme,
1321
+ initialSelections,
1322
+ selectionUpdatedAt,
1323
+ selectionVersion
1324
+ ]
1262
1325
  );
1263
1326
  const [state, setState] = useState(
1264
1327
  () => baseSnapshot ? createStyleConfiguratorState(baseSnapshot) : null
1265
1328
  );
1266
1329
  const hasLoadedState = state !== null;
1330
+ const hasStagedSiteStylePreview = state ? isPreviewingChange(state) : false;
1267
1331
  const stateRef = useRef(state);
1268
1332
  const clearPreviewRef = useRef(clearPreview);
1269
1333
  const runnerRef = useRef(createOptimisticActionRunner());
@@ -1274,9 +1338,18 @@ function StyleConfigurator({
1274
1338
  useEffect(() => {
1275
1339
  clearPreviewRef.current = clearPreview;
1276
1340
  }, [clearPreview]);
1341
+ useEffect(() => {
1342
+ if (!setSiteStyleStagedPreviewActive) return;
1343
+ setSiteStyleStagedPreviewActive(hasStagedSiteStylePreview);
1344
+ return () => {
1345
+ setSiteStyleStagedPreviewActive(false);
1346
+ };
1347
+ }, [hasStagedSiteStylePreview, setSiteStyleStagedPreviewActive]);
1277
1348
  useEffect(() => {
1278
1349
  if (!baseSnapshot) return;
1279
- setState((current) => current ? syncStyleConfiguratorState(current, baseSnapshot) : createStyleConfiguratorState(baseSnapshot));
1350
+ setState(
1351
+ (current) => current ? syncStyleConfiguratorState(current, baseSnapshot) : createStyleConfiguratorState(baseSnapshot)
1352
+ );
1280
1353
  }, [baseSnapshot]);
1281
1354
  useEffect(() => {
1282
1355
  if (!state || !baseSnapshot) {
@@ -1300,7 +1373,15 @@ function StyleConfigurator({
1300
1373
  footerSelectionContext
1301
1374
  });
1302
1375
  previewTheme("style-configurator", result.themeOverlay, "site-style");
1303
- }, [state, baseSnapshot, clearPreview, previewTheme, headerSelectionContext, footerSelectionContext, theme]);
1376
+ }, [
1377
+ state,
1378
+ baseSnapshot,
1379
+ clearPreview,
1380
+ previewTheme,
1381
+ headerSelectionContext,
1382
+ footerSelectionContext,
1383
+ theme
1384
+ ]);
1304
1385
  useEffect(() => {
1305
1386
  const runner = runnerRef.current;
1306
1387
  return () => {
@@ -1314,34 +1395,44 @@ function StyleConfigurator({
1314
1395
  setState((current) => {
1315
1396
  if (!current) return current;
1316
1397
  appliedExpandedRowRequestIdRef.current = expandedRowRequest.id;
1317
- return openRow(current, expandedRowRequest.row === "header" ? "header-layout" : expandedRowRequest.row);
1398
+ return openRow(
1399
+ current,
1400
+ expandedRowRequest.row === "header" ? "header-layout" : expandedRowRequest.row
1401
+ );
1318
1402
  });
1319
1403
  }, [expandedRowRequest, hasLoadedState]);
1320
- const handlePreviewSiteStyle = useCallback((siteStyleId) => {
1321
- setState((current) => {
1322
- if (!current) return current;
1323
- const next = previewSiteStyle(current, siteStyleId);
1324
- const siteStyle = getCuratedSiteStyle(siteStyleId);
1325
- if (!siteStyle) return next;
1326
- const result = planSiteStylePreviewChange({
1327
- siteStyle,
1328
- selection: next.previewed,
1329
- baseTheme: theme,
1330
- headerSelectionContext,
1331
- footerSelectionContext
1332
- });
1333
- return applyResolvedSelections(next, {
1334
- resolved: result.resolvedSelections,
1335
- warnings: result.warnings
1404
+ const handlePreviewSiteStyle = useCallback(
1405
+ (siteStyleId) => {
1406
+ setState((current) => {
1407
+ if (!current) return current;
1408
+ const next = previewSiteStyle(current, siteStyleId);
1409
+ const siteStyle = getCuratedSiteStyle(siteStyleId);
1410
+ if (!siteStyle) return next;
1411
+ const result = planSiteStylePreviewChange({
1412
+ siteStyle,
1413
+ selection: next.previewed,
1414
+ baseTheme: theme,
1415
+ headerSelectionContext,
1416
+ footerSelectionContext
1417
+ });
1418
+ return applyResolvedSelections(next, {
1419
+ resolved: result.resolvedSelections,
1420
+ warnings: result.warnings
1421
+ });
1336
1422
  });
1337
- });
1338
- }, [footerSelectionContext, headerSelectionContext, theme]);
1423
+ },
1424
+ [footerSelectionContext, headerSelectionContext, theme]
1425
+ );
1339
1426
  const handlePreviewPersonality = useCallback((id) => {
1340
- setState((current) => current ? previewButtonPersonality(current, id) : current);
1427
+ setState(
1428
+ (current) => current ? previewButtonPersonality(current, id) : current
1429
+ );
1341
1430
  }, []);
1342
1431
  const handlePreviewHeaderLayout = useCallback((id) => {
1343
1432
  if (!id) return;
1344
- setState((current) => current ? previewHeaderLayout(current, id) : current);
1433
+ setState(
1434
+ (current) => current ? previewHeaderLayout(current, id) : current
1435
+ );
1345
1436
  }, []);
1346
1437
  const handlePreviewHeaderStyle = useCallback((id) => {
1347
1438
  if (!id) return;
@@ -1350,34 +1441,54 @@ function StyleConfigurator({
1350
1441
  const handlePreviewFooterLook = useCallback((id) => {
1351
1442
  const plan = planSiteChromeLookSelection({ surface: "footer", lookId: id });
1352
1443
  if (plan.kind !== "footer") return;
1353
- setState((current) => current ? previewFooterLook(current, plan.next.footerLookId) : current);
1444
+ setState(
1445
+ (current) => current ? previewFooterLook(current, plan.next.footerLookId) : current
1446
+ );
1354
1447
  }, []);
1355
1448
  const handlePreviewPalette = useCallback((id) => {
1356
- setState((current) => current ? previewPaletteVariant(current, id) : current);
1357
- }, []);
1358
- const handlePreviewTypographyPreset = useCallback((id) => {
1359
- setState((current) => current ? previewTypographyPreset(current, id) : current);
1449
+ setState(
1450
+ (current) => current ? previewPaletteVariant(current, id) : current
1451
+ );
1360
1452
  }, []);
1453
+ const handlePreviewTypographyPreset = useCallback(
1454
+ (id) => {
1455
+ setState(
1456
+ (current) => current ? previewTypographyPreset(current, id) : current
1457
+ );
1458
+ },
1459
+ []
1460
+ );
1361
1461
  const handleBodyFontOverride = useCallback((fontFamily) => {
1362
- setState((current) => current ? setTypographyBodyFontOverride(current, fontFamily) : current);
1462
+ setState(
1463
+ (current) => current ? setTypographyBodyFontOverride(current, fontFamily) : current
1464
+ );
1363
1465
  }, []);
1364
1466
  const handleHeadingFontOverride = useCallback((fontFamily) => {
1365
- setState((current) => current ? setTypographyHeadingFontOverride(current, fontFamily) : current);
1467
+ setState(
1468
+ (current) => current ? setTypographyHeadingFontOverride(current, fontFamily) : current
1469
+ );
1366
1470
  }, []);
1367
1471
  const handleClearTypographyOverrides = useCallback(() => {
1368
- setState((current) => current ? clearTypographyFontOverrides(current) : current);
1472
+ setState(
1473
+ (current) => current ? clearTypographyFontOverrides(current) : current
1474
+ );
1369
1475
  }, []);
1370
1476
  const handleTokenOverride = useCallback((role, hex) => {
1371
1477
  setState((current) => {
1372
1478
  if (!current) return current;
1373
- const next = { ...current.previewed.paletteOverrides ?? {}, [role]: hex };
1479
+ const next = {
1480
+ ...current.previewed.paletteOverrides ?? {},
1481
+ [role]: hex
1482
+ };
1374
1483
  const parsed = paletteOverridesSchema.safeParse(next);
1375
1484
  if (!parsed.success) return current;
1376
1485
  return setPaletteOverrides(current, parsed.data);
1377
1486
  });
1378
1487
  }, []);
1379
1488
  const handleResetOverrides = useCallback(() => {
1380
- setState((current) => current ? setPaletteOverrides(current, null) : current);
1489
+ setState(
1490
+ (current) => current ? setPaletteOverrides(current, null) : current
1491
+ );
1381
1492
  }, []);
1382
1493
  const handleToggleRow = useCallback((row) => {
1383
1494
  setState((current) => current ? toggleRow(current, row) : current);
@@ -1394,6 +1505,7 @@ function StyleConfigurator({
1394
1505
  const handleApply = useCallback(async () => {
1395
1506
  const live = stateRef.current;
1396
1507
  if (!live || !isPreviewingChange(live)) return;
1508
+ if (!deriveStyleConfiguratorCapabilities(live).canApplyStaged) return;
1397
1509
  const previewed = live.previewed;
1398
1510
  const siteStyle = getCuratedSiteStyle(previewed.siteStyleId);
1399
1511
  if (!siteStyle) return;
@@ -1433,23 +1545,22 @@ function StyleConfigurator({
1433
1545
  return unwrapResponse(response);
1434
1546
  },
1435
1547
  onSuccess: (saved) => {
1548
+ const persisted = selectionSnapshotFromApplySiteStyleSelectionResponse(
1549
+ saved,
1550
+ previewed
1551
+ );
1552
+ const historyEntry = styleConfiguratorHistoryEntryForPersistedSelection(
1553
+ live,
1554
+ persisted
1555
+ );
1436
1556
  setState(
1437
- (current) => current ? markApplySaved(current, {
1438
- siteStyleId: previewed.siteStyleId,
1439
- selectionVersion: saved.selectionVersion,
1440
- selectionUpdatedAt: saved.selectionUpdatedAt ?? previewed.selectionUpdatedAt ?? null,
1441
- buttonPersonalityId: saved.buttonPersonalityId,
1442
- paletteVariantId: saved.paletteVariantId,
1443
- paletteOverrides: saved.paletteOverrides ?? null,
1444
- typographyPresetId: saved.typographyPresetId,
1445
- typographyBodyFontOverride: saved.typographyBodyFontOverride,
1446
- typographyHeadingFontOverride: saved.typographyHeadingFontOverride,
1447
- headerLookId: saved.headerLookId,
1448
- headerLayoutId: saved.headerLayoutId,
1449
- headerStyleId: saved.headerStyleId,
1450
- footerLookId: saved.footerLookId
1451
- }) : current
1557
+ (current) => current ? markApplySaved(current, persisted) : current
1452
1558
  );
1559
+ if (historyEntry) {
1560
+ siteChromeCustomize?.siteStyleHistory.recordAppliedSelection(
1561
+ historyEntry
1562
+ );
1563
+ }
1453
1564
  applySucceeded("style-configurator");
1454
1565
  startRefreshTransition(() => {
1455
1566
  router.refresh();
@@ -1464,7 +1575,13 @@ function StyleConfigurator({
1464
1575
  });
1465
1576
  }
1466
1577
  const message = applyError.message;
1467
- setState((current) => current ? markApplyFailed(current, message) : current);
1578
+ setState(
1579
+ (current) => current ? markApplyFailed(
1580
+ current,
1581
+ message,
1582
+ applyError.kind === "stale" ? "stale" : "retryable"
1583
+ ) : current
1584
+ );
1468
1585
  }
1469
1586
  });
1470
1587
  }, [
@@ -1476,6 +1593,7 @@ function StyleConfigurator({
1476
1593
  applySucceeded,
1477
1594
  router,
1478
1595
  selectionId,
1596
+ siteChromeCustomize?.siteStyleHistory,
1479
1597
  siteId,
1480
1598
  startRefreshTransition,
1481
1599
  theme
@@ -1484,14 +1602,19 @@ function StyleConfigurator({
1484
1602
  return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Loading design controls..." });
1485
1603
  }
1486
1604
  const applyAllowed = canApplySiteStyle(siteStyleAccess);
1605
+ const stagedCapabilities = deriveStyleConfiguratorCapabilities(state);
1487
1606
  const previewingChange = isPreviewingChange(state);
1488
- const saving = state.saveStatus.kind === "saving" || isRefreshPending;
1607
+ const saving = stagedCapabilities.isApplyingStaged || isRefreshPending;
1489
1608
  const currentSiteStyle = getCuratedSiteStyle(state.previewed.siteStyleId);
1490
1609
  if (!currentSiteStyle) {
1491
1610
  return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "This site uses a Site Style that cannot be configured here." });
1492
1611
  }
1493
- const currentPersonality = findButtonPersonality(state.previewed.buttonPersonalityId);
1494
- const currentPaletteVariant = findPaletteVariant(state.previewed.paletteVariantId);
1612
+ const currentPersonality = findButtonPersonality(
1613
+ state.previewed.buttonPersonalityId
1614
+ );
1615
+ const currentPaletteVariant = findPaletteVariant(
1616
+ state.previewed.paletteVariantId
1617
+ );
1495
1618
  const currentTypographyPreset = state.previewed.typographyPresetId ? findTypographyPreset(state.previewed.typographyPresetId) : null;
1496
1619
  const chromeLookModels = buildSiteChromeLookModels({
1497
1620
  state,
@@ -1503,8 +1626,20 @@ function StyleConfigurator({
1503
1626
  const currentHeaderStyle = getHeaderStyle(state.previewed.headerStyleId);
1504
1627
  const currentFooterLook = state.previewed.footerLookId ? findFooterLook(state.previewed.footerLookId) : findFooterLook(chromeLookModels.footer.renderedLookId);
1505
1628
  return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
1506
- state.warnings.length > 0 ? /* @__PURE__ */ jsx(WarningNotice, { warnings: state.warnings, onDismiss: handleDismissWarnings }) : null,
1507
- state.notices.length > 0 ? /* @__PURE__ */ jsx(NoticeBanner, { notices: state.notices, onDismiss: handleDismissNotices }) : null,
1629
+ state.warnings.length > 0 ? /* @__PURE__ */ jsx(
1630
+ WarningNotice,
1631
+ {
1632
+ warnings: state.warnings,
1633
+ onDismiss: handleDismissWarnings
1634
+ }
1635
+ ) : null,
1636
+ state.notices.length > 0 ? /* @__PURE__ */ jsx(
1637
+ NoticeBanner,
1638
+ {
1639
+ notices: state.notices,
1640
+ onDismiss: handleDismissNotices
1641
+ }
1642
+ ) : null,
1508
1643
  /* @__PURE__ */ jsx(
1509
1644
  SiteStyleRow,
1510
1645
  {
@@ -1529,7 +1664,11 @@ function StyleConfigurator({
1529
1664
  options: chromeLookModels.headerLayout.options,
1530
1665
  diagnostics: [],
1531
1666
  onCycle: (direction) => {
1532
- const next = cycleSiteChromeLookId(chromeLookModels.headerLayout.options, state.previewed.headerLayoutId, direction);
1667
+ const next = cycleSiteChromeLookId(
1668
+ chromeLookModels.headerLayout.options,
1669
+ state.previewed.headerLayoutId,
1670
+ direction
1671
+ );
1533
1672
  if (next !== void 0) handlePreviewHeaderLayout(next);
1534
1673
  },
1535
1674
  onPreview: handlePreviewHeaderLayout,
@@ -1550,7 +1689,11 @@ function StyleConfigurator({
1550
1689
  options: chromeLookModels.headerStyle.options,
1551
1690
  diagnostics: [],
1552
1691
  onCycle: (direction) => {
1553
- const next = cycleSiteChromeLookId(chromeLookModels.headerStyle.options, state.previewed.headerStyleId, direction);
1692
+ const next = cycleSiteChromeLookId(
1693
+ chromeLookModels.headerStyle.options,
1694
+ state.previewed.headerStyleId,
1695
+ direction
1696
+ );
1554
1697
  if (next !== void 0) handlePreviewHeaderStyle(next);
1555
1698
  },
1556
1699
  onPreview: handlePreviewHeaderStyle,
@@ -1572,7 +1715,11 @@ function StyleConfigurator({
1572
1715
  options: chromeLookModels.footer.options,
1573
1716
  diagnostics: chromeLookModels.footer.diagnostics,
1574
1717
  onCycle: (direction) => {
1575
- const next = cycleSiteChromeLookId(chromeLookModels.footer.options, state.previewed.footerLookId, direction);
1718
+ const next = cycleSiteChromeLookId(
1719
+ chromeLookModels.footer.options,
1720
+ state.previewed.footerLookId,
1721
+ direction
1722
+ );
1576
1723
  if (next !== void 0) handlePreviewFooterLook(next);
1577
1724
  },
1578
1725
  onPreview: handlePreviewFooterLook,
@@ -1635,14 +1782,40 @@ function StyleConfigurator({
1635
1782
  }
1636
1783
  ) : null,
1637
1784
  previewingChange ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pt-2", children: [
1638
- /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "outline", onClick: handleCancel, disabled: saving, children: "Cancel" }),
1639
- applyAllowed ? /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: handleApply, disabled: saving, children: saving ? "Applying\u2026" : "Apply" }) : /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Preview only \u2014 ask an admin to apply." })
1785
+ /* @__PURE__ */ jsx(
1786
+ Button,
1787
+ {
1788
+ type: "button",
1789
+ size: "sm",
1790
+ variant: "outline",
1791
+ onClick: handleCancel,
1792
+ disabled: !stagedCapabilities.canCancelStaged || saving,
1793
+ children: "Cancel"
1794
+ }
1795
+ ),
1796
+ applyAllowed ? /* @__PURE__ */ jsx(
1797
+ Button,
1798
+ {
1799
+ type: "button",
1800
+ size: "sm",
1801
+ onClick: handleApply,
1802
+ disabled: !stagedCapabilities.canApplyStaged || saving,
1803
+ children: saving ? "Applying\u2026" : "Apply"
1804
+ }
1805
+ ) : /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Preview only \u2014 ask an admin to apply." })
1640
1806
  ] }) : null,
1641
1807
  state.saveStatus.kind === "saved" ? /* @__PURE__ */ jsx("p", { className: "text-xs text-success", children: "Saved." }) : null,
1642
1808
  state.saveStatus.kind === "failed" ? /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: state.saveStatus.message }) : null
1643
1809
  ] });
1644
1810
  }
1645
- function StyleRowFrame({ label, currentLabel, swatch, expanded, onToggle, children }) {
1811
+ function StyleRowFrame({
1812
+ label,
1813
+ currentLabel,
1814
+ swatch,
1815
+ expanded,
1816
+ onToggle,
1817
+ children
1818
+ }) {
1646
1819
  return /* @__PURE__ */ jsx(Collapsible, { open: expanded, onOpenChange: onToggle, children: /* @__PURE__ */ jsxs("div", { className: "rounded-md border bg-background", children: [
1647
1820
  /* @__PURE__ */ jsx(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
1648
1821
  "button",
@@ -1651,7 +1824,12 @@ function StyleRowFrame({ label, currentLabel, swatch, expanded, onToggle, childr
1651
1824
  className: "flex w-full items-center gap-2 px-3 py-2 text-left hover:bg-accent/30",
1652
1825
  "aria-expanded": expanded,
1653
1826
  children: [
1654
- /* @__PURE__ */ jsx(ChevronRight, { className: cn("h-4 w-4 transition", expanded && "rotate-90") }),
1827
+ /* @__PURE__ */ jsx(
1828
+ ChevronRight,
1829
+ {
1830
+ className: cn("h-4 w-4 transition", expanded && "rotate-90")
1831
+ }
1832
+ ),
1655
1833
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1656
1834
  /* @__PURE__ */ jsx("div", { className: "text-xs uppercase tracking-wide text-muted-foreground", children: label }),
1657
1835
  /* @__PURE__ */ jsx("div", { className: "truncate text-sm font-medium", children: currentLabel })
@@ -1670,35 +1848,86 @@ function StyleRowFrame({ label, currentLabel, swatch, expanded, onToggle, childr
1670
1848
  /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx("div", { className: "border-t px-3 py-3", children }) })
1671
1849
  ] }) });
1672
1850
  }
1673
- function SiteStyleRow({ expanded, onToggle, current, onPreview, disabled }) {
1674
- return /* @__PURE__ */ jsx(StyleRowFrame, { label: "Site style", currentLabel: current.name, expanded, onToggle, children: /* @__PURE__ */ jsx("ul", { role: "radiogroup", "aria-label": "Site style", className: "list-none space-y-1 p-0", children: curatedSiteStyles.map((style) => /* @__PURE__ */ jsx(
1675
- PickerOption,
1851
+ function SiteStyleRow({
1852
+ expanded,
1853
+ onToggle,
1854
+ current,
1855
+ onPreview,
1856
+ disabled
1857
+ }) {
1858
+ return /* @__PURE__ */ jsx(
1859
+ StyleRowFrame,
1676
1860
  {
1677
- selected: style.id === current.id,
1678
- label: style.name,
1679
- description: style.description,
1680
- onSelect: () => onPreview(style.id),
1681
- disabled
1682
- },
1683
- style.id
1684
- )) }) });
1861
+ label: "Site style",
1862
+ currentLabel: current.name,
1863
+ expanded,
1864
+ onToggle,
1865
+ children: /* @__PURE__ */ jsx(
1866
+ "ul",
1867
+ {
1868
+ role: "radiogroup",
1869
+ "aria-label": "Site style",
1870
+ className: "list-none space-y-1 p-0",
1871
+ children: curatedSiteStyles.map((style) => /* @__PURE__ */ jsx(
1872
+ PickerOption,
1873
+ {
1874
+ selected: style.id === current.id,
1875
+ label: style.name,
1876
+ description: style.description,
1877
+ onSelect: () => onPreview(style.id),
1878
+ disabled
1879
+ },
1880
+ style.id
1881
+ ))
1882
+ }
1883
+ )
1884
+ }
1885
+ );
1685
1886
  }
1686
- function PersonalityRow({ expanded, onToggle, siteStyle, currentId, currentLabel, onPreview, disabled }) {
1887
+ function PersonalityRow({
1888
+ expanded,
1889
+ onToggle,
1890
+ siteStyle,
1891
+ currentId,
1892
+ currentLabel,
1893
+ onPreview,
1894
+ disabled
1895
+ }) {
1687
1896
  const options = useMemo(
1688
- () => requireEntriesForCuratedChoices(buttonPersonalities, siteStyle.buttonPersonalityChoices),
1897
+ () => requireEntriesForCuratedChoices(
1898
+ buttonPersonalities,
1899
+ siteStyle.buttonPersonalityChoices
1900
+ ),
1689
1901
  [siteStyle.buttonPersonalityChoices]
1690
1902
  );
1691
- return /* @__PURE__ */ jsx(StyleRowFrame, { label: "Button style", currentLabel, expanded, onToggle, children: /* @__PURE__ */ jsx("ul", { role: "radiogroup", "aria-label": "Button style", className: "list-none space-y-1 p-0", children: options.map((personality) => /* @__PURE__ */ jsx(
1692
- PickerOption,
1903
+ return /* @__PURE__ */ jsx(
1904
+ StyleRowFrame,
1693
1905
  {
1694
- selected: personality.id === currentId,
1695
- label: personality.name,
1696
- description: personality.description,
1697
- onSelect: () => onPreview(personality.id),
1698
- disabled
1699
- },
1700
- personality.id
1701
- )) }) });
1906
+ label: "Button style",
1907
+ currentLabel,
1908
+ expanded,
1909
+ onToggle,
1910
+ children: /* @__PURE__ */ jsx(
1911
+ "ul",
1912
+ {
1913
+ role: "radiogroup",
1914
+ "aria-label": "Button style",
1915
+ className: "list-none space-y-1 p-0",
1916
+ children: options.map((personality) => /* @__PURE__ */ jsx(
1917
+ PickerOption,
1918
+ {
1919
+ selected: personality.id === currentId,
1920
+ label: personality.name,
1921
+ description: personality.description,
1922
+ onSelect: () => onPreview(personality.id),
1923
+ disabled
1924
+ },
1925
+ personality.id
1926
+ ))
1927
+ }
1928
+ )
1929
+ }
1930
+ );
1702
1931
  }
1703
1932
  function TypographyRow({
1704
1933
  expanded,
@@ -1716,63 +1945,83 @@ function TypographyRow({
1716
1945
  disabled
1717
1946
  }) {
1718
1947
  const options = useMemo(
1719
- () => requireEntriesForCuratedChoices(typographyPresets, siteStyle.typographyPresetChoices),
1948
+ () => requireEntriesForCuratedChoices(
1949
+ typographyPresets,
1950
+ siteStyle.typographyPresetChoices
1951
+ ),
1720
1952
  [siteStyle.typographyPresetChoices]
1721
1953
  );
1722
1954
  const fontCatalog = useFontCatalog(apiClient, expanded);
1723
1955
  const selectedPreset = currentPresetId ? findTypographyPreset(currentPresetId) : null;
1724
- return /* @__PURE__ */ jsxs(StyleRowFrame, { label: "Typography", currentLabel, expanded, onToggle, children: [
1725
- currentPresetId === null ? /* @__PURE__ */ jsx("div", { className: "mb-3 rounded-md border border-muted-foreground/20 bg-muted/30 px-3 py-2 text-xs text-muted-foreground", children: "Current custom setup" }) : null,
1726
- /* @__PURE__ */ jsx("ul", { role: "radiogroup", "aria-label": "Typography preset", className: "space-y-1", children: options.map((preset) => /* @__PURE__ */ jsx(
1727
- TypographyPresetOption,
1728
- {
1729
- preset,
1730
- selected: preset.id === currentPresetId,
1731
- onSelect: () => onPreviewPreset(preset.id),
1732
- disabled
1733
- },
1734
- preset.id
1735
- )) }),
1736
- /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-3 border-t pt-3", children: [
1737
- selectedPreset ? /* @__PURE__ */ jsxs(Fragment, { children: [
1956
+ return /* @__PURE__ */ jsxs(
1957
+ StyleRowFrame,
1958
+ {
1959
+ label: "Typography",
1960
+ currentLabel,
1961
+ expanded,
1962
+ onToggle,
1963
+ children: [
1964
+ currentPresetId === null ? /* @__PURE__ */ jsx("div", { className: "mb-3 rounded-md border border-muted-foreground/20 bg-muted/30 px-3 py-2 text-xs text-muted-foreground", children: "Current custom setup" }) : null,
1738
1965
  /* @__PURE__ */ jsx(
1739
- TypographyFontSlotPicker,
1966
+ "ul",
1740
1967
  {
1741
- label: "Body font",
1742
- slot: "body",
1743
- preset: selectedPreset,
1744
- catalog: fontCatalog,
1745
- value: bodyFontOverride,
1746
- onChange: onBodyFontOverride,
1747
- disabled
1968
+ role: "radiogroup",
1969
+ "aria-label": "Typography preset",
1970
+ className: "space-y-1",
1971
+ children: options.map((preset) => /* @__PURE__ */ jsx(
1972
+ TypographyPresetOption,
1973
+ {
1974
+ preset,
1975
+ selected: preset.id === currentPresetId,
1976
+ onSelect: () => onPreviewPreset(preset.id),
1977
+ disabled
1978
+ },
1979
+ preset.id
1980
+ ))
1748
1981
  }
1749
1982
  ),
1750
- /* @__PURE__ */ jsx(
1751
- TypographyFontSlotPicker,
1752
- {
1753
- label: "Heading font",
1754
- slot: "heading",
1755
- preset: selectedPreset,
1756
- catalog: fontCatalog,
1757
- value: headingFontOverride,
1758
- onChange: onHeadingFontOverride,
1759
- disabled
1760
- }
1761
- )
1762
- ] }) : /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Choose a typography preset to use curated font overrides." }),
1763
- /* @__PURE__ */ jsx(
1764
- Button,
1765
- {
1766
- type: "button",
1767
- size: "sm",
1768
- variant: "outline",
1769
- onClick: onClearOverrides,
1770
- disabled: disabled || !bodyFontOverride && !headingFontOverride,
1771
- children: "Use preset fonts"
1772
- }
1773
- )
1774
- ] })
1775
- ] });
1983
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-3 border-t pt-3", children: [
1984
+ selectedPreset ? /* @__PURE__ */ jsxs(Fragment, { children: [
1985
+ /* @__PURE__ */ jsx(
1986
+ TypographyFontSlotPicker,
1987
+ {
1988
+ label: "Body font",
1989
+ slot: "body",
1990
+ preset: selectedPreset,
1991
+ catalog: fontCatalog,
1992
+ value: bodyFontOverride,
1993
+ onChange: onBodyFontOverride,
1994
+ disabled
1995
+ }
1996
+ ),
1997
+ /* @__PURE__ */ jsx(
1998
+ TypographyFontSlotPicker,
1999
+ {
2000
+ label: "Heading font",
2001
+ slot: "heading",
2002
+ preset: selectedPreset,
2003
+ catalog: fontCatalog,
2004
+ value: headingFontOverride,
2005
+ onChange: onHeadingFontOverride,
2006
+ disabled
2007
+ }
2008
+ )
2009
+ ] }) : /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Choose a typography preset to use curated font overrides." }),
2010
+ /* @__PURE__ */ jsx(
2011
+ Button,
2012
+ {
2013
+ type: "button",
2014
+ size: "sm",
2015
+ variant: "outline",
2016
+ onClick: onClearOverrides,
2017
+ disabled: disabled || !bodyFontOverride && !headingFontOverride,
2018
+ children: "Use preset fonts"
2019
+ }
2020
+ )
2021
+ ] })
2022
+ ]
2023
+ }
2024
+ );
1776
2025
  }
1777
2026
  function TypographyPresetOption({
1778
2027
  preset,
@@ -1817,7 +2066,10 @@ function TypographyFontSlotPicker({
1817
2066
  const [query, setQuery] = useState("");
1818
2067
  const defaultFont = primaryFontFamily(preset.defaultFonts[slot]);
1819
2068
  const selectedFamily = value ?? defaultFont;
1820
- const recordsByFamily = useMemo(() => indexFontsByFamily(catalog.fonts), [catalog.fonts]);
2069
+ const recordsByFamily = useMemo(
2070
+ () => indexFontsByFamily(catalog.fonts),
2071
+ [catalog.fonts]
2072
+ );
1821
2073
  const selectedFit = evaluateTypographyFontSlot({
1822
2074
  slot,
1823
2075
  policy: preset.slotPolicies[slot],
@@ -1830,8 +2082,15 @@ function TypographyFontSlotPicker({
1830
2082
  );
1831
2083
  const browseOptions = useMemo(() => {
1832
2084
  const normalizedQuery = query.trim().toLowerCase();
1833
- const source = normalizedQuery.length > 0 ? catalog.fonts.filter((font) => font.family.toLowerCase().includes(normalizedQuery)) : catalog.fonts;
1834
- return [...source].sort((a, b) => sortFontForPresetSlot(a, b, slot, preset, recordsByFamily)).slice(0, normalizedQuery.length > 0 ? MAX_FONT_RESULTS_WHEN_SEARCHING : MAX_FONT_RESULTS_WHEN_BROWSING);
2085
+ const source = normalizedQuery.length > 0 ? catalog.fonts.filter(
2086
+ (font) => font.family.toLowerCase().includes(normalizedQuery)
2087
+ ) : catalog.fonts;
2088
+ return [...source].sort(
2089
+ (a, b) => sortFontForPresetSlot(a, b, slot, preset, recordsByFamily)
2090
+ ).slice(
2091
+ 0,
2092
+ normalizedQuery.length > 0 ? MAX_FONT_RESULTS_WHEN_SEARCHING : MAX_FONT_RESULTS_WHEN_BROWSING
2093
+ );
1835
2094
  }, [catalog.fonts, preset, query, recordsByFamily, slot]);
1836
2095
  return /* @__PURE__ */ jsxs("section", { className: "space-y-2", "aria-label": label, children: [
1837
2096
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
@@ -1943,7 +2202,9 @@ function FontFamilyOption({
1943
2202
  }
1944
2203
  );
1945
2204
  }
1946
- function TypographyFontFitBadge({ fit }) {
2205
+ function TypographyFontFitBadge({
2206
+ fit
2207
+ }) {
1947
2208
  return /* @__PURE__ */ jsx(
1948
2209
  "span",
1949
2210
  {
@@ -1961,7 +2222,10 @@ function TypographyFontFitBadge({ fit }) {
1961
2222
  );
1962
2223
  }
1963
2224
  function useFontCatalog(apiClient, enabled) {
1964
- const [catalog, setCatalog] = useState({ kind: "idle", fonts: [] });
2225
+ const [catalog, setCatalog] = useState({
2226
+ kind: "idle",
2227
+ fonts: []
2228
+ });
1965
2229
  const requestedClientRef = useRef(null);
1966
2230
  useEffect(() => {
1967
2231
  if (!enabled) return;
@@ -2125,60 +2389,86 @@ function SiteChromeLookRow({
2125
2389
  onPreview,
2126
2390
  disabled
2127
2391
  }) {
2128
- return /* @__PURE__ */ jsxs(StyleRowFrame, { label, currentLabel, expanded, onToggle, children: [
2129
- /* @__PURE__ */ jsxs("div", { className: "mb-3 flex items-start justify-between gap-3", children: [
2130
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: scopeDescription }),
2131
- /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center overflow-hidden rounded-full border bg-background", children: [
2132
- /* @__PURE__ */ jsx(
2133
- "button",
2134
- {
2135
- type: "button",
2136
- onClick: () => onCycle("prev"),
2137
- className: "grid h-8 w-8 place-items-center hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50",
2138
- "aria-label": `Previous ${label.toLowerCase()}`,
2139
- disabled: disabled || cycleableSiteChromeOptions(options).length <= 1,
2140
- children: /* @__PURE__ */ jsx(ChevronLeft, { size: 14 })
2141
- }
2142
- ),
2392
+ return /* @__PURE__ */ jsxs(
2393
+ StyleRowFrame,
2394
+ {
2395
+ label,
2396
+ currentLabel,
2397
+ expanded,
2398
+ onToggle,
2399
+ children: [
2400
+ /* @__PURE__ */ jsxs("div", { className: "mb-3 flex items-start justify-between gap-3", children: [
2401
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: scopeDescription }),
2402
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center overflow-hidden rounded-full border bg-background", children: [
2403
+ /* @__PURE__ */ jsx(
2404
+ "button",
2405
+ {
2406
+ type: "button",
2407
+ onClick: () => onCycle("prev"),
2408
+ className: "grid h-8 w-8 place-items-center hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50",
2409
+ "aria-label": `Previous ${label.toLowerCase()}`,
2410
+ disabled: disabled || cycleableSiteChromeOptions(options).length <= 1,
2411
+ children: /* @__PURE__ */ jsx(ChevronLeft, { size: 14 })
2412
+ }
2413
+ ),
2414
+ /* @__PURE__ */ jsx(
2415
+ "button",
2416
+ {
2417
+ type: "button",
2418
+ onClick: () => onCycle("next"),
2419
+ className: "grid h-8 w-8 place-items-center border-l hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50",
2420
+ "aria-label": `Next ${label.toLowerCase()}`,
2421
+ disabled: disabled || cycleableSiteChromeOptions(options).length <= 1,
2422
+ children: /* @__PURE__ */ jsx(ChevronRight, { size: 14 })
2423
+ }
2424
+ )
2425
+ ] })
2426
+ ] }),
2427
+ diagnostics.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "mb-3 list-none space-y-1 p-0 text-xs text-amber-700", children: diagnostics.map((diagnostic) => /* @__PURE__ */ jsx("li", { children: diagnostic }, diagnostic)) }) : null,
2143
2428
  /* @__PURE__ */ jsx(
2144
- "button",
2429
+ "ul",
2145
2430
  {
2146
- type: "button",
2147
- onClick: () => onCycle("next"),
2148
- className: "grid h-8 w-8 place-items-center border-l hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50",
2149
- "aria-label": `Next ${label.toLowerCase()}`,
2150
- disabled: disabled || cycleableSiteChromeOptions(options).length <= 1,
2151
- children: /* @__PURE__ */ jsx(ChevronRight, { size: 14 })
2431
+ role: "radiogroup",
2432
+ "aria-label": ariaLabel,
2433
+ className: "list-none space-y-1 p-0",
2434
+ children: options.map((look) => /* @__PURE__ */ jsx(
2435
+ PickerOption,
2436
+ {
2437
+ selected: look.id === currentId,
2438
+ label: look.label,
2439
+ description: look.description,
2440
+ onSelect: () => onPreview(look.id),
2441
+ disabled: disabled || !look.available
2442
+ },
2443
+ look.id ?? "site-style-default"
2444
+ ))
2152
2445
  }
2153
2446
  )
2154
- ] })
2155
- ] }),
2156
- diagnostics.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "mb-3 list-none space-y-1 p-0 text-xs text-amber-700", children: diagnostics.map((diagnostic) => /* @__PURE__ */ jsx("li", { children: diagnostic }, diagnostic)) }) : null,
2157
- /* @__PURE__ */ jsx("ul", { role: "radiogroup", "aria-label": ariaLabel, className: "list-none space-y-1 p-0", children: options.map((look) => /* @__PURE__ */ jsx(
2158
- PickerOption,
2159
- {
2160
- selected: look.id === currentId,
2161
- label: look.label,
2162
- description: look.description,
2163
- onSelect: () => onPreview(look.id),
2164
- disabled: disabled || !look.available
2165
- },
2166
- look.id ?? "site-style-default"
2167
- )) })
2168
- ] });
2169
- }
2170
- function PaletteRow({ expanded, onToggle, siteStyle, currentId, currentLabel, currentSwatch, onPreview, disabled }) {
2171
- const options = useMemo(
2172
- () => {
2173
- const recommended = requireEntriesForCuratedChoices(paletteVariants, siteStyle.paletteVariantChoices);
2174
- if (recommended.some((variant) => variant.id === currentId)) {
2175
- return recommended;
2176
- }
2177
- const current = findPaletteVariant(currentId);
2178
- return current ? [current, ...recommended] : recommended;
2179
- },
2180
- [currentId, siteStyle.paletteVariantChoices]
2447
+ ]
2448
+ }
2181
2449
  );
2450
+ }
2451
+ function PaletteRow({
2452
+ expanded,
2453
+ onToggle,
2454
+ siteStyle,
2455
+ currentId,
2456
+ currentLabel,
2457
+ currentSwatch,
2458
+ onPreview,
2459
+ disabled
2460
+ }) {
2461
+ const options = useMemo(() => {
2462
+ const recommended = requireEntriesForCuratedChoices(
2463
+ paletteVariants,
2464
+ siteStyle.paletteVariantChoices
2465
+ );
2466
+ if (recommended.some((variant) => variant.id === currentId)) {
2467
+ return recommended;
2468
+ }
2469
+ const current = findPaletteVariant(currentId);
2470
+ return current ? [current, ...recommended] : recommended;
2471
+ }, [currentId, siteStyle.paletteVariantChoices]);
2182
2472
  return /* @__PURE__ */ jsxs(
2183
2473
  StyleRowFrame,
2184
2474
  {
@@ -2189,26 +2479,44 @@ function PaletteRow({ expanded, onToggle, siteStyle, currentId, currentLabel, cu
2189
2479
  onToggle,
2190
2480
  children: [
2191
2481
  /* @__PURE__ */ jsx("p", { className: "mb-3 text-xs text-muted-foreground", children: "These palette bases are recommended for the current Site Style. Choose a base here, then edit exact colours in Palette colours." }),
2192
- /* @__PURE__ */ jsx("ul", { role: "radiogroup", "aria-label": "Palette", className: "list-none space-y-1 p-0", children: options.map((variant) => {
2193
- const primaryHex = variant.colors.find((c) => c.name === "primary")?.hex;
2194
- return /* @__PURE__ */ jsx(
2195
- PickerOption,
2196
- {
2197
- selected: variant.id === currentId,
2198
- label: variant.name,
2199
- description: variant.description,
2200
- swatch: primaryHex,
2201
- onSelect: () => onPreview(variant.id),
2202
- disabled
2203
- },
2204
- variant.id
2205
- );
2206
- }) })
2482
+ /* @__PURE__ */ jsx(
2483
+ "ul",
2484
+ {
2485
+ role: "radiogroup",
2486
+ "aria-label": "Palette",
2487
+ className: "list-none space-y-1 p-0",
2488
+ children: options.map((variant) => {
2489
+ const primaryHex = variant.colors.find(
2490
+ (c) => c.name === "primary"
2491
+ )?.hex;
2492
+ return /* @__PURE__ */ jsx(
2493
+ PickerOption,
2494
+ {
2495
+ selected: variant.id === currentId,
2496
+ label: variant.name,
2497
+ description: variant.description,
2498
+ swatch: primaryHex,
2499
+ onSelect: () => onPreview(variant.id),
2500
+ disabled
2501
+ },
2502
+ variant.id
2503
+ );
2504
+ })
2505
+ }
2506
+ )
2207
2507
  ]
2208
2508
  }
2209
2509
  );
2210
2510
  }
2211
- function ColoursRow({ expanded, onToggle, variant, overrides, onTokenChange, onReset, disabled }) {
2511
+ function ColoursRow({
2512
+ expanded,
2513
+ onToggle,
2514
+ variant,
2515
+ overrides,
2516
+ onTokenChange,
2517
+ onReset,
2518
+ disabled
2519
+ }) {
2212
2520
  const mergedPalette = useMemo(() => {
2213
2521
  return variant.colors.map((color) => ({
2214
2522
  name: color.name,
@@ -2252,7 +2560,14 @@ function ColoursRow({ expanded, onToggle, variant, overrides, onTokenChange, onR
2252
2560
  }
2253
2561
  );
2254
2562
  }
2255
- function PickerOption({ selected, label, description, swatch, onSelect, disabled }) {
2563
+ function PickerOption({
2564
+ selected,
2565
+ label,
2566
+ description,
2567
+ swatch,
2568
+ onSelect,
2569
+ disabled
2570
+ }) {
2256
2571
  return /* @__PURE__ */ jsx("li", { className: "list-none", children: /* @__PURE__ */ jsxs(
2257
2572
  "button",
2258
2573
  {
@@ -2303,16 +2618,30 @@ function isRecord(value) {
2303
2618
  return typeof value === "object" && value !== null;
2304
2619
  }
2305
2620
  function WarningNotice({ warnings, onDismiss }) {
2306
- return /* @__PURE__ */ jsxs("div", { role: "status", className: "rounded-md border border-warning/40 bg-warning/10 px-3 py-2 text-xs text-warning-foreground", children: [
2307
- /* @__PURE__ */ jsx("ul", { className: "space-y-1", children: warnings.map((warning, index) => /* @__PURE__ */ jsx("li", { children: describeWarning(warning) }, `${warning.kind}-${index}`)) }),
2308
- /* @__PURE__ */ jsx("button", { type: "button", onClick: onDismiss, className: "mt-2 underline", children: "Dismiss" })
2309
- ] });
2621
+ return /* @__PURE__ */ jsxs(
2622
+ "div",
2623
+ {
2624
+ role: "status",
2625
+ className: "rounded-md border border-warning/40 bg-warning/10 px-3 py-2 text-xs text-warning-foreground",
2626
+ children: [
2627
+ /* @__PURE__ */ jsx("ul", { className: "space-y-1", children: warnings.map((warning, index) => /* @__PURE__ */ jsx("li", { children: describeWarning(warning) }, `${warning.kind}-${index}`)) }),
2628
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: onDismiss, className: "mt-2 underline", children: "Dismiss" })
2629
+ ]
2630
+ }
2631
+ );
2310
2632
  }
2311
2633
  function NoticeBanner({ notices, onDismiss }) {
2312
- return /* @__PURE__ */ jsxs("div", { role: "status", className: "rounded-md border border-muted-foreground/20 bg-muted/40 px-3 py-2 text-xs", children: [
2313
- /* @__PURE__ */ jsx("ul", { className: "space-y-1", children: notices.map((notice, index) => /* @__PURE__ */ jsx("li", { children: describeNotice(notice) }, `${notice.kind}-${index}`)) }),
2314
- /* @__PURE__ */ jsx("button", { type: "button", onClick: onDismiss, className: "mt-2 underline", children: "Dismiss" })
2315
- ] });
2634
+ return /* @__PURE__ */ jsxs(
2635
+ "div",
2636
+ {
2637
+ role: "status",
2638
+ className: "rounded-md border border-muted-foreground/20 bg-muted/40 px-3 py-2 text-xs",
2639
+ children: [
2640
+ /* @__PURE__ */ jsx("ul", { className: "space-y-1", children: notices.map((notice, index) => /* @__PURE__ */ jsx("li", { children: describeNotice(notice) }, `${notice.kind}-${index}`)) }),
2641
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: onDismiss, className: "mt-2 underline", children: "Dismiss" })
2642
+ ]
2643
+ }
2644
+ );
2316
2645
  }
2317
2646
  function describeNotice(notice) {
2318
2647
  switch (notice.kind) {
@@ -2393,6 +2722,11 @@ function PreviewEditorSidebar({
2393
2722
  [uiStore]
2394
2723
  );
2395
2724
  const focusRequest = useUISelector(uiStore, (s) => s.focusRequest);
2725
+ const activeLinkedEntrySnapshot = useUISelector(
2726
+ uiStore,
2727
+ (s) => s.linkedEntries.getSelectedSnapshot()
2728
+ );
2729
+ const previewInspection = useUISelector(uiStore, (s) => s.previewInspection);
2396
2730
  const { canEdit } = usePreviewAuth();
2397
2731
  const dashboardSetupHandoff = useMemo(
2398
2732
  () => resolvePreviewDashboardSetupHandoff(),
@@ -2462,8 +2796,33 @@ function PreviewEditorSidebar({
2462
2796
  }, [focusRequest, uiStore]);
2463
2797
  const metadataSectionContent = useMemo(() => {
2464
2798
  if (!pageId && !entryData) return null;
2465
- return /* @__PURE__ */ jsx(PreviewMetadataPanel, { contentTypeKey: entryData?.type ?? null });
2466
- }, [entryData, pageId]);
2799
+ return /* @__PURE__ */ jsx(
2800
+ PreviewMetadataPanel,
2801
+ {
2802
+ ownerKind: entryData ? "content" : "page",
2803
+ contentTypeKey: entryData?.type ?? null,
2804
+ entry: controller.entry
2805
+ }
2806
+ );
2807
+ }, [controller.entry, entryData, pageId]);
2808
+ const linkedEntrySection = buildLinkedEntrySidebarSection({
2809
+ snapshot: activeLinkedEntrySnapshot,
2810
+ inspection: previewInspection,
2811
+ renderContent: (snapshot) => /* @__PURE__ */ jsx(
2812
+ LinkedEntryEditorPanel,
2813
+ {
2814
+ siteId,
2815
+ apiClient,
2816
+ bearerToken,
2817
+ supabaseUrl,
2818
+ theme,
2819
+ mediaAssets,
2820
+ widgets: contentFormWidgets,
2821
+ entry: snapshot,
2822
+ fields: findLinkedEntryFieldsFromSnapshot(snapshot)
2823
+ }
2824
+ )
2825
+ });
2467
2826
  const editorPanel = entryData ? /* @__PURE__ */ jsx(
2468
2827
  EntryEditorPanel,
2469
2828
  {
@@ -2479,6 +2838,7 @@ function PreviewEditorSidebar({
2479
2838
  supabaseUrl,
2480
2839
  entrySubrouteContext,
2481
2840
  metadataPanel: metadataSectionContent,
2841
+ linkedEntrySection,
2482
2842
  mediaAssets,
2483
2843
  widgets: contentFormWidgets,
2484
2844
  viewportMode,
@@ -2534,6 +2894,7 @@ function PreviewEditorSidebar({
2534
2894
  ) : null,
2535
2895
  sdkConfig: sdkConfig ?? null,
2536
2896
  mediaAssets,
2897
+ linkedEntrySection,
2537
2898
  viewportMode,
2538
2899
  viewportWidth,
2539
2900
  zoom,
@@ -2616,14 +2977,32 @@ function PreviewEditorSidebar({
2616
2977
  );
2617
2978
  }
2618
2979
  function PreviewMetadataPanel({
2619
- contentTypeKey
2980
+ ownerKind,
2981
+ contentTypeKey,
2982
+ entry
2620
2983
  }) {
2621
2984
  const uiStore = useEditorUiStoreInstance();
2622
- const manifest = useMemo(() => {
2623
- return omitRouteTitleFieldFromManifest(
2624
- getRouteMetadataManifestForType(contentTypeKey)
2985
+ const currentSlug = useEditorUiStore(
2986
+ (state) => state.metadata.getAtPath("draftSlug")
2987
+ ) ?? void 0;
2988
+ const metadataPresentation = useMemo(() => {
2989
+ if (ownerKind === "content") {
2990
+ return deriveRouteMetadataPresentation(
2991
+ { kind: "content", typeKey: contentTypeKey },
2992
+ { omitTitle: true }
2993
+ );
2994
+ }
2995
+ const routeSlug = resolvePageRouteSlug(entry, currentSlug);
2996
+ if (!routeSlug) {
2997
+ throw new Error("Expected routable page entry for preview metadata");
2998
+ }
2999
+ return deriveRouteMetadataPresentation(
3000
+ { kind: "page", routeSlug },
3001
+ { omitTitle: true }
2625
3002
  );
2626
- }, [contentTypeKey]);
3003
+ }, [contentTypeKey, currentSlug, entry, ownerKind]);
3004
+ const manifest = metadataPresentation.manifest;
3005
+ const isHomepage = metadataPresentation.kind === "page-homepage";
2627
3006
  const validation = useMemo(
2628
3007
  () => createManifestValidation(manifest),
2629
3008
  [manifest]
@@ -2642,14 +3021,143 @@ function PreviewMetadataPanel({
2642
3021
  }),
2643
3022
  [uiStore, validation]
2644
3023
  );
2645
- return /* @__PURE__ */ jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsx(
2646
- ManifestForm,
2647
- {
2648
- manifest,
2649
- backend,
2650
- className: "space-y-4"
3024
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
3025
+ isHomepage ? /* @__PURE__ */ jsx("div", { className: "inline-flex rounded-md bg-muted px-2 py-1 text-xs font-medium text-muted-foreground", children: "Homepage" }) : null,
3026
+ /* @__PURE__ */ jsx(
3027
+ ManifestForm,
3028
+ {
3029
+ manifest,
3030
+ backend,
3031
+ className: "space-y-4"
3032
+ }
3033
+ )
3034
+ ] });
3035
+ }
3036
+ function LinkedEntryEditorPanel({
3037
+ siteId,
3038
+ apiClient,
3039
+ bearerToken,
3040
+ supabaseUrl,
3041
+ theme,
3042
+ mediaAssets,
3043
+ widgets,
3044
+ entry,
3045
+ fields
3046
+ }) {
3047
+ const uiStore = useEditorUiStoreInstance();
3048
+ const linkedEntriesAutosave = useUISelector(
3049
+ uiStore,
3050
+ (state) => state.autosave.linkedEntries
3051
+ );
3052
+ const manifest = useMemo(
3053
+ () => ({
3054
+ name: `linked-content-${entry.meta.contentTypeKey}`,
3055
+ version: "1.0",
3056
+ title: entry.meta.contentTypeLabel,
3057
+ component: "content-form",
3058
+ description: "",
3059
+ fields: fields.map((field) => ({
3060
+ ...field,
3061
+ label: fieldIdToLabel(field.id)
3062
+ })),
3063
+ slots: []
3064
+ }),
3065
+ [entry.meta.contentTypeKey, entry.meta.contentTypeLabel, fields]
3066
+ );
3067
+ const validation = useMemo(
3068
+ () => createManifestValidation(manifest, { widgets }),
3069
+ [manifest, widgets]
3070
+ );
3071
+ const backend = useMemo(
3072
+ () => createStoreBackend({
3073
+ scope: "linkedContent",
3074
+ store: uiStore,
3075
+ validateFn: (values) => {
3076
+ const result = validation.schema.safeParse(values);
3077
+ return result.success ? [] : result.error.issues;
3078
+ }
3079
+ }),
3080
+ [uiStore, validation]
3081
+ );
3082
+ const syncState = entry.syncState;
3083
+ const errorMessage = syncState.kind === "failed" ? syncState.error : null;
3084
+ const dirty = syncState.kind === "pending" || syncState.kind === "failed";
3085
+ const isSaving = linkedEntriesAutosave.status === "saving" && dirty;
3086
+ const displayTitle = resolveContentTitle(
3087
+ entry.current ?? entry.baseline ?? null,
3088
+ entry.meta.titleField,
3089
+ entry.meta.title
3090
+ );
3091
+ return /* @__PURE__ */ jsxs("div", { className: "bg-muted/20", children: [
3092
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3 px-4 py-3", children: [
3093
+ /* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsx("div", { className: "truncate text-sm font-medium", children: displayTitle }) }),
3094
+ /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2", children: /* @__PURE__ */ jsx(
3095
+ Button,
3096
+ {
3097
+ type: "button",
3098
+ variant: "outline",
3099
+ size: "sm",
3100
+ onClick: () => {
3101
+ if (dirty) {
3102
+ uiStore.getState().linkedEntries.discard(entry.meta.entryId);
3103
+ } else {
3104
+ uiStore.getState().linkedEntries.close();
3105
+ }
3106
+ },
3107
+ children: dirty ? "Discard" : "Close"
3108
+ }
3109
+ ) })
3110
+ ] }),
3111
+ /* @__PURE__ */ jsxs("div", { className: "px-4 pb-4", children: [
3112
+ errorMessage ? /* @__PURE__ */ jsx("div", { className: "mb-3 rounded-md border border-red-500 bg-red-50 px-3 py-2 text-sm text-red-700", children: errorMessage }) : isSaving ? /* @__PURE__ */ jsx("div", { className: "mb-3 rounded-md border border-sky-500 bg-sky-50 px-3 py-2 text-sm text-sky-700", children: "Saving changes" }) : null,
3113
+ /* @__PURE__ */ jsx(
3114
+ PreviewFormProvider,
3115
+ {
3116
+ siteId,
3117
+ theme: theme ?? null,
3118
+ previewClient: apiClient,
3119
+ bearerToken,
3120
+ supabaseUrl,
3121
+ mediaAssets,
3122
+ children: /* @__PURE__ */ jsx(
3123
+ ManifestForm,
3124
+ {
3125
+ manifest,
3126
+ backend,
3127
+ widgetOverrides: widgets,
3128
+ className: "space-y-4"
3129
+ }
3130
+ )
3131
+ }
3132
+ )
3133
+ ] })
3134
+ ] });
3135
+ }
3136
+ function buildLinkedEntrySidebarSection(input) {
3137
+ const { snapshot, inspection, renderContent } = input;
3138
+ if (!snapshot || inspection.kind !== "linked-entry") return null;
3139
+ if (snapshot.meta.entryId !== inspection.entryId) return null;
3140
+ return {
3141
+ label: snapshot.meta.contentTypeLabel,
3142
+ openRequestId: inspection.requestId,
3143
+ content: renderContent(snapshot)
3144
+ };
3145
+ }
3146
+ function findLinkedEntryFieldsFromSnapshot(snapshot) {
3147
+ return snapshot.meta.fields.flatMap((field) => {
3148
+ if (typeof field.id !== "string" || typeof field.type !== "string") {
3149
+ return [];
2651
3150
  }
2652
- ) });
3151
+ return [{
3152
+ id: field.id,
3153
+ type: field.type,
3154
+ mediaKinds: Array.isArray(field.mediaKinds) ? field.mediaKinds.filter((item) => typeof item === "string") : null,
3155
+ fileKinds: Array.isArray(field.fileKinds) ? field.fileKinds.filter((item) => typeof item === "string") : null
3156
+ }];
3157
+ });
3158
+ }
3159
+ function fieldIdToLabel(fieldId) {
3160
+ return fieldId.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[-_\s]+/).filter((part) => part.length > 0).map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join(" ");
2653
3161
  }
2654
3162
 
2655
3163
  export { PreviewEditorSidebar };