@riverbankcms/sdk 0.152.0 → 0.154.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 (303) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/{EventEmbeddedCheckoutStep-DVQXWFm6.mjs → EventEmbeddedCheckoutStep-ba9npQtb.mjs} +1 -1
  3. package/dist/{PreviewEditorSidebar-Dr4NJi3Q.mjs → PreviewEditorSidebar-C7FiaxlF.mjs} +194 -22
  4. package/dist/{PreviewEditorUI-DSZXQbyh.mjs → PreviewEditorUI-DFst50q1.mjs} +20 -44
  5. package/dist/{SdkPreviewModeRuntime-Dl4GyMc3.mjs → SdkPreviewModeRuntime-BUNV_YHZ.mjs} +266 -143
  6. package/dist/{SiteChromeCustomizeContext-DgBe-FlM.mjs → SiteChromeCustomizeContext-DEj7qppF.mjs} +5340 -4329
  7. package/dist/{ThemedButton-B8ViBnLK.mjs → ThemedButton-C8kzu0hY.mjs} +610 -116
  8. package/dist/_dts/ai/src/contracts/proposals.d.ts +416 -182
  9. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +3270 -8214
  10. package/dist/_dts/api/src/billing.d.ts +2 -0
  11. package/dist/_dts/api/src/billingEndpointDefinitions.d.ts +78 -0
  12. package/dist/_dts/api/src/bookingAdjustments.d.ts +3 -2
  13. package/dist/_dts/api/src/bookingOperations.d.ts +7 -2
  14. package/dist/_dts/api/src/bookingPeople.d.ts +19 -0
  15. package/dist/_dts/api/src/bookingPeopleEndpointDefinitions.d.ts +8 -0
  16. package/dist/_dts/api/src/bookingRecords.d.ts +4 -106
  17. package/dist/_dts/api/src/bookings.d.ts +2 -3
  18. package/dist/_dts/api/src/communications.d.ts +19 -5
  19. package/dist/_dts/api/src/contentRuntime.d.ts +1 -0
  20. package/dist/_dts/api/src/endpoints.d.ts +88 -43
  21. package/dist/_dts/api/src/index.d.ts +4 -2
  22. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -0
  23. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  24. package/dist/_dts/api/src/moneyPayments.d.ts +116 -0
  25. package/dist/_dts/api/src/onboarding/surfaceData.d.ts +2 -0
  26. package/dist/_dts/api/src/sdk-event-upsert.d.ts +2 -2
  27. package/dist/_dts/api/src/sdkThemeWire.d.ts +348 -1537
  28. package/dist/_dts/api/src/shared-contracts.d.ts +10 -0
  29. package/dist/_dts/api/src/siteInfrastructure.d.ts +2 -1
  30. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +18 -0
  31. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +17 -16
  32. package/dist/_dts/api/src/siteSettings.d.ts +1 -0
  33. package/dist/_dts/api/src/stripeConnectSetup.d.ts +90 -0
  34. package/dist/_dts/api/src/teamMembers.d.ts +2 -27
  35. package/dist/_dts/api/src/types.d.ts +11 -31
  36. package/dist/_dts/api/src/wholeSeriesRuns.d.ts +2 -4
  37. package/dist/_dts/block-form/src/widgets/RepeaterField/components/layoutGridDomain.d.ts +3 -13
  38. package/dist/_dts/blocks/src/client/site-chrome.d.ts +1 -1
  39. package/dist/_dts/blocks/src/contracts/index.d.ts +1 -0
  40. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +8 -96
  41. package/dist/_dts/blocks/src/index.d.ts +1 -0
  42. package/dist/_dts/blocks/src/lib/media.d.ts +1 -0
  43. package/dist/_dts/blocks/src/lib/picsum.d.ts +2 -2
  44. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +2 -1
  45. package/dist/_dts/blocks/src/primitives/content/components/RichText.d.ts +1 -1
  46. package/dist/_dts/blocks/src/primitives/content/primitives.d.ts +4 -1
  47. package/dist/_dts/blocks/src/primitives/layout/Section.d.ts +1 -0
  48. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +1 -1
  49. package/dist/_dts/blocks/src/system/blocks/events/eventSelectionFields.d.ts +2 -2
  50. package/dist/_dts/blocks/src/system/blocks/events/shared/fields.d.ts +0 -4
  51. package/dist/_dts/blocks/src/system/blocks/events/shared/index.d.ts +0 -1
  52. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +276 -884
  53. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +2 -2
  54. package/dist/_dts/blocks/src/system/blocks/form.d.ts +10 -0
  55. package/dist/_dts/blocks/src/system/blocks/image-gallery/fields.d.ts +1 -0
  56. package/dist/_dts/blocks/src/system/blocks/image-gallery.d.ts +6 -1
  57. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +2 -2
  58. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +92 -90
  59. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +12 -0
  60. package/dist/_dts/blocks/src/system/blocks/shared/teamMembers.d.ts +4 -7
  61. package/dist/_dts/blocks/src/system/blocks/site-footer-runtime-layout.d.ts +23 -0
  62. package/dist/_dts/blocks/src/system/blocks/site-footer-runtime-profile.d.ts +20 -0
  63. package/dist/_dts/blocks/src/system/blocks/site-footer-runtime.d.ts +17 -16
  64. package/dist/_dts/blocks/src/system/blocks/site-footer.d.ts +1 -1
  65. package/dist/_dts/blocks/src/system/blocks/team-members.d.ts +2 -2
  66. package/dist/_dts/blocks/src/system/customize/backgrounds.d.ts +6 -6
  67. package/dist/_dts/blocks/src/system/customize/facets.d.ts +75 -9
  68. package/dist/_dts/blocks/src/system/fields/backgroundContent.d.ts +377 -1
  69. package/dist/_dts/blocks/src/system/helpers/backgroundMedia.d.ts +6 -2
  70. package/dist/_dts/blocks/src/system/helpers/resolveBackground.d.ts +3 -3
  71. package/dist/_dts/blocks/src/system/layout/repeaterGrid.d.ts +12 -5
  72. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +3 -3
  73. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +48 -48
  74. package/dist/_dts/blocks/src/system/manifest/validation.d.ts +2 -0
  75. package/dist/_dts/blocks/src/system/node/fragments/index.d.ts +1 -0
  76. package/dist/_dts/blocks/src/system/node/fragments/lookSlot.d.ts +1 -1
  77. package/dist/_dts/blocks/src/system/node/fragments/responsiveTwoColumn.d.ts +3 -1
  78. package/dist/_dts/blocks/src/system/node/fragments/sectionHead.d.ts +15 -0
  79. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +18 -198
  80. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +9 -99
  81. package/dist/_dts/blocks/src/system/runtime/hooks/useBookingFlowController.d.ts +1 -1
  82. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.d.ts +2 -0
  83. package/dist/_dts/blocks/src/system/runtime/lookSurfaces.d.ts +18 -6
  84. package/dist/_dts/blocks/src/system/runtime/nodes/ImageResolveContext.d.ts +1 -1
  85. package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +50 -202
  86. package/dist/_dts/blocks/src/system/runtime/nodes/basic.d.ts +2 -1
  87. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +28 -1
  88. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/lookPresentation.d.ts +12 -6
  89. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/presentation.d.ts +1 -1
  90. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/dates.d.ts +1 -1
  91. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CardListItem.d.ts +1 -1
  92. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +289 -885
  93. package/dist/_dts/blocks/src/system/runtime/nodes/file-download.d.ts +3 -2
  94. package/dist/_dts/blocks/src/system/runtime/nodes/form.fields.d.ts +5 -2
  95. package/dist/_dts/blocks/src/system/runtime/nodes/form.interactive.d.ts +11 -79
  96. package/dist/_dts/blocks/src/system/runtime/nodes/form.parts.d.ts +7 -0
  97. package/dist/_dts/blocks/src/system/runtime/nodes/form.server.d.ts +2 -13
  98. package/dist/_dts/blocks/src/system/runtime/nodes/media.d.ts +22 -90
  99. package/dist/_dts/blocks/src/system/runtime/nodes/mediaContext.d.ts +69 -0
  100. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +8 -72
  101. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.parts.d.ts +6 -6
  102. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +3 -2
  103. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +2 -2
  104. package/dist/_dts/blocks/src/system/transforms/registry/_utils/surfaceForegroundStyles.d.ts +3 -0
  105. package/dist/_dts/blocks/src/system/transforms/registry/footerArrangement.d.ts +6 -0
  106. package/dist/_dts/blocks/src/system/transforms/registry/index.d.ts +1 -0
  107. package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +0 -11
  108. package/dist/_dts/blocks/src/system/transforms/registry/links.d.ts +3 -3
  109. package/dist/_dts/blocks/src/system/transforms/typed.d.ts +1 -10
  110. package/dist/_dts/commerce/src/purchase/orderConfirmationPlanning.d.ts +1 -0
  111. package/dist/_dts/content-editor/src/FooterComposerOverview.d.ts +5 -2
  112. package/dist/_dts/content-editor/src/FooterComposerPanel.d.ts +1 -1
  113. package/dist/_dts/content-editor/src/FooterNavigationLayoutControl.d.ts +6 -3
  114. package/dist/_dts/content-editor/src/controller/editorLeaseParticipation.d.ts +1 -1
  115. package/dist/_dts/content-editor/src/footerComposer.d.ts +2 -1
  116. package/dist/_dts/content-editor/src/footerComposerPanelTypes.d.ts +3 -1
  117. package/dist/_dts/content-editor/src/footerNavigationLayoutState.d.ts +56 -0
  118. package/dist/_dts/content-editor/src/footerPreviewRuntime.d.ts +2 -1
  119. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +3 -4
  120. package/dist/_dts/content-editor/src/useFooterNavigationLayout.d.ts +11 -8
  121. package/dist/_dts/content-model/src/content-types/schema.d.ts +3 -3
  122. package/dist/_dts/core/src/booking-refunds.d.ts +2 -0
  123. package/dist/_dts/core/src/date-display.d.ts +85 -0
  124. package/dist/_dts/core/src/date-time-formatter.d.ts +2 -0
  125. package/dist/_dts/core/src/footer-arrangement.d.ts +8 -1
  126. package/dist/_dts/core/src/footer-composition-types.d.ts +6 -1
  127. package/dist/_dts/core/src/footer-composition.d.ts +1 -1
  128. package/dist/_dts/core/src/footer-navigation-layout.d.ts +3 -0
  129. package/dist/_dts/core/src/index.d.ts +2 -0
  130. package/dist/_dts/core/src/mailing-list-runtime.d.ts +2 -2
  131. package/dist/_dts/core/src/mailing-list-setup-parser.d.ts +9 -1
  132. package/dist/_dts/core/src/mailing-list-setup.d.ts +12 -1
  133. package/dist/_dts/core/src/mailing-list-submission.d.ts +7 -2
  134. package/dist/_dts/core/src/mailing-list-targeting.d.ts +9 -1
  135. package/dist/_dts/core/src/public-profile.d.ts +3 -1
  136. package/dist/_dts/core/src/scheduled-date-time.d.ts +69 -0
  137. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +105 -13
  138. package/dist/_dts/db/src/schemas/forms.d.ts +16 -16
  139. package/dist/_dts/editor-blocks/src/index.d.ts +1 -0
  140. package/dist/_dts/editor-blocks/src/media/MediaField.d.ts +2 -2
  141. package/dist/_dts/editor-blocks/src/media/admitEditorMediaField.d.ts +4 -0
  142. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/targetingState.d.ts +2 -2
  143. package/dist/_dts/media-core/src/assetsInUseSummary.d.ts +6 -0
  144. package/dist/_dts/media-core/src/contentMediaAudit.d.ts +3 -2
  145. package/dist/_dts/media-core/src/index.d.ts +4 -0
  146. package/dist/_dts/media-core/src/media.d.ts +406 -0
  147. package/dist/_dts/media-core/src/mediaIdentifierSchema.d.ts +3 -0
  148. package/dist/_dts/media-core/src/mediaKinds.d.ts +2 -0
  149. package/dist/_dts/media-core/src/mediaUsageProjection.d.ts +13 -1
  150. package/dist/_dts/media-core/src/mediaWriteNormalizer.d.ts +2 -6
  151. package/dist/_dts/media-core/src/portableMediaReferences.d.ts +8 -21
  152. package/dist/_dts/media-core/src/renderableMediaAsset.d.ts +28 -14
  153. package/dist/_dts/media-core/src/renderableMediaAssetAdmission.d.ts +15 -0
  154. package/dist/_dts/media-editor/src/CropDialog.d.ts +6 -3
  155. package/dist/_dts/media-editor/src/MediaEditor.d.ts +2 -1
  156. package/dist/_dts/media-editor/src/MediaPreview.d.ts +3 -3
  157. package/dist/_dts/media-editor/src/cropEditorSource.d.ts +5 -7
  158. package/dist/_dts/media-editor/src/editorMediaState.d.ts +29 -0
  159. package/dist/_dts/media-editor/src/mediaSelection.d.ts +1 -2
  160. package/dist/_dts/media-editor/src/runtimeMediaAssetState.d.ts +4 -5
  161. package/dist/_dts/media-editor/src/types.d.ts +1 -1
  162. package/dist/_dts/media-editor/src/utils.d.ts +0 -1
  163. package/dist/_dts/media-react/src/components/cropChangePolicy.d.ts +4 -1
  164. package/dist/_dts/media-react/src/components/cropGeometry.d.ts +1 -0
  165. package/dist/_dts/media-react/src/components/useImageCropperController.d.ts +1 -0
  166. package/dist/_dts/preview-next/src/client/blocks/ArrangementBlockToolbar.d.ts +2 -1
  167. package/dist/_dts/preview-next/src/client/blocks/BlockBackgroundChooser.d.ts +2 -1
  168. package/dist/_dts/preview-next/src/client/blocks/previewCustomizeSelectedMedia.d.ts +11 -12
  169. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +1 -0
  170. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +1 -0
  171. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +4 -1
  172. package/dist/_dts/preview-next/src/client/preview/siteChromeSavePlan.d.ts +27 -5
  173. package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +2 -0
  174. package/dist/_dts/preview-next/src/client/preview/useConfirmedPreferenceRecord.d.ts +12 -0
  175. package/dist/_dts/preview-next/src/client/preview/usePersistedFooterPreferences.d.ts +26 -0
  176. package/dist/_dts/preview-next/src/client/preview/usePersistedHeaderPreferences.d.ts +40 -2
  177. package/dist/_dts/sdk/src/config/validation.d.ts +3 -3
  178. package/dist/_dts/sdk/src/contracts/content.d.ts +2 -45
  179. package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
  180. package/dist/_dts/sdk/src/contracts/rendering.d.ts +3 -3
  181. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +4 -46
  182. package/dist/_dts/sdk/src/date-time/index.d.ts +2 -68
  183. package/dist/_dts/sdk/src/index.d.ts +1 -0
  184. package/dist/_dts/sdk/src/public-api/contracts.d.ts +1 -0
  185. package/dist/_dts/sdk/src/rendering/image.d.ts +5 -5
  186. package/dist/_dts/sdk/src/rendering/index.d.ts +2 -1
  187. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +1 -1
  188. package/dist/_dts/sdk/src/rendering/link.d.ts +3 -7
  189. package/dist/_dts/sdk/src/rendering/mediaAssets.d.ts +2 -4
  190. package/dist/_dts/sdk/src/version.d.ts +1 -1
  191. package/dist/_dts/theme-core/src/accordions/types.d.ts +1 -1
  192. package/dist/_dts/theme-core/src/boxBackgroundSchema.d.ts +397 -26
  193. package/dist/_dts/theme-core/src/buttons/buttonColourContract.d.ts +2 -0
  194. package/dist/_dts/theme-core/src/buttons/resolveButtonColourStates.d.ts +2 -0
  195. package/dist/_dts/theme-core/src/buttons/styles/recipes/lanternRecipes.d.ts +60 -0
  196. package/dist/_dts/theme-core/src/buttons/styles/registry.d.ts +57 -0
  197. package/dist/_dts/theme-core/src/buttons/styles/selection.d.ts +10 -1
  198. package/dist/_dts/theme-core/src/buttons/types.d.ts +378 -66
  199. package/dist/_dts/theme-core/src/buttons/typography.d.ts +24 -0
  200. package/dist/_dts/theme-core/src/cards/types.d.ts +42 -42
  201. package/dist/_dts/theme-core/src/footer/effectiveNavLinkStyle.d.ts +1 -1
  202. package/dist/_dts/theme-core/src/footer/generateFooterCss.d.ts +4 -1
  203. package/dist/_dts/theme-core/src/footer/mode.d.ts +2 -11
  204. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  205. package/dist/_dts/theme-core/src/inputs/types.d.ts +3 -3
  206. package/dist/_dts/theme-core/src/lib/media.d.ts +2 -616
  207. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +495 -2766
  208. package/dist/_dts/theme-core/src/navigation/types.d.ts +4 -4
  209. package/dist/_dts/theme-core/src/palette/curated/types.d.ts +1 -1
  210. package/dist/_dts/theme-core/src/schema.d.ts +838 -3369
  211. package/dist/_dts/theme-core/src/site-styles/appearancePresetTypes.d.ts +23 -7
  212. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  213. package/dist/_dts/theme-core/src/site-styles/compilationPlan.d.ts +4 -6
  214. package/dist/_dts/theme-core/src/site-styles/compileFooterAgainstRow.d.ts +121 -0
  215. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +25 -0
  216. package/dist/_dts/theme-core/src/site-styles/footerLookDefaults.d.ts +45 -0
  217. package/dist/_dts/theme-core/src/site-styles/footerLookRecipe.d.ts +50 -0
  218. package/dist/_dts/theme-core/src/site-styles/footerLooks.d.ts +9 -35
  219. package/dist/_dts/theme-core/src/site-styles/footerPreferences.d.ts +29 -0
  220. package/dist/_dts/theme-core/src/site-styles/headerPreferencesPersistence.d.ts +2 -3
  221. package/dist/_dts/theme-core/src/site-styles/index.d.ts +4 -0
  222. package/dist/_dts/theme-core/src/site-styles/lookResolution.d.ts +2 -2
  223. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +1 -1
  224. package/dist/_dts/theme-core/src/site-styles/runtimeBackgroundResolution.d.ts +9 -9
  225. package/dist/_dts/theme-core/src/site-styles/siteChromeBackgrounds.d.ts +8 -0
  226. package/dist/_dts/theme-core/src/site-styles/styleTags.d.ts +1 -1
  227. package/dist/_dts/theme-core/src/site-styles/themeParity.d.ts +1 -1
  228. package/dist/_dts/theme-core/src/site-styles/tokenRecipes.d.ts +2 -2
  229. package/dist/_dts/theme-core/src/styles/skinTokens.d.ts +2 -2
  230. package/dist/_dts/theme-core/src/typography/schema.d.ts +2 -2
  231. package/dist/_dts/ui/src/card.d.ts +1 -1
  232. package/dist/client/{BookingMailingListNote-CBuMKN0w.mjs → BookingMailingListNote-CNoSqFtf.mjs} +2 -2
  233. package/dist/client/{CardListItem-Dc9XTXhB.mjs → CardListItem-BkTkqBkh.mjs} +5 -4
  234. package/dist/client/{CheckboxChoice-CIqx_o0E.mjs → CheckboxChoice-CHJpsty4.mjs} +1 -1
  235. package/dist/client/{DemoBookingPortalAccess-D3VQ_kLj.mjs → DemoBookingPortalAccess-C7KQKFNt.mjs} +2 -2
  236. package/dist/client/{EventCombined.client-BHGEKise.mjs → EventCombined.client-BgeYMjHJ.mjs} +5 -6
  237. package/dist/client/{EventEmbeddedCheckoutStep-Bo1Cm23R.mjs → EventEmbeddedCheckoutStep-BTc_lTkM.mjs} +2 -2
  238. package/dist/client/{EventListing.client-D5OQgVPr.mjs → EventListing.client-ChRs9Hl2.mjs} +2 -2
  239. package/dist/client/{LeafletStaticMap-CLL5cWrr.mjs → LeafletStaticMap-C_dNQgd0.mjs} +1 -1
  240. package/dist/client/{RichText-BoDmnopf.mjs → RichText-BI9bzbjo.mjs} +106 -60
  241. package/dist/client/{ThemedButton-Ciltp0IK.mjs → ThemedButton-wl3Z3wkH.mjs} +1 -2
  242. package/dist/client/{accordion-DOkRS64-.mjs → accordion-6Yz8Wd83.mjs} +1 -1
  243. package/dist/client/{bookingForm-wlMVwo9h.mjs → bookingForm-i_pKIGiY.mjs} +42 -15
  244. package/dist/client/bookings.mjs +118357 -22833
  245. package/dist/client/{carousel-CGWk-Z0u.mjs → carousel-DNqd_PjC.mjs} +2 -2
  246. package/dist/client/{carousel.client-kX5mN1Eg.mjs → carousel.client-BUgjPbb6.mjs} +1 -1
  247. package/dist/client/{cart-OBBPlaH4.mjs → cart-D8OBHuF4.mjs} +3 -3
  248. package/dist/client/{checkout-Bmw2WjQX.mjs → checkout-F3-9IGLU.mjs} +3 -3
  249. package/dist/client/client.mjs +20785 -19238
  250. package/dist/client/{context-BI77UFAn.mjs → context-Dg4ZrxDD.mjs} +1 -1
  251. package/dist/client/{eventCalendar-qkej2Edn.mjs → eventCalendar-BUc7YIBM.mjs} +8 -9
  252. package/dist/client/{eventCombined-DApKHvat.mjs → eventCombined-BwfShk2a.mjs} +4 -4
  253. package/dist/client/{eventDetails-BQyUDPH0.mjs → eventDetails-BMOVC3go.mjs} +3 -3
  254. package/dist/client/{eventListing-CeAnshlZ.mjs → eventListing-BwE9PM-t.mjs} +4 -4
  255. package/dist/client/{eventRegistration-C3A3NyBO.mjs → eventRegistration-CCWPYDc7.mjs} +10 -10
  256. package/dist/client/{form-DW8rU7jO.mjs → form-CXFr0Gd5.mjs} +115 -52
  257. package/dist/client/{headerSection-CkIhsoNm.mjs → headerSection-BX8qw8kH.mjs} +3 -3
  258. package/dist/client/hooks.mjs +17908 -16797
  259. package/dist/client/{locationMap-D4O8wbli.mjs → locationMap-B3La71m0.mjs} +3 -4
  260. package/dist/client/{media-C5K_0xPd.mjs → media-B1Cbv721.mjs} +183 -362
  261. package/dist/client/mediaContext-CwbbimYB.mjs +135 -0
  262. package/dist/client/{newsletterForm-B7IxSPuz.mjs → newsletterForm-DnGyR0x7.mjs} +51 -15
  263. package/dist/client/{productDetail-Bqxpwy5N.mjs → productDetail-BVgTqvkb.mjs} +3 -3
  264. package/dist/client/{productList-u9Lz8V15.mjs → productList-CcO7kUQw.mjs} +3 -3
  265. package/dist/client/{propsDecoder-Bf1jucUp.mjs → propsDecoder-B1OeWavE.mjs} +2193 -374
  266. package/dist/client/renderableMediaAssetAdmission-CHkXYDC_.mjs +143 -0
  267. package/dist/client/rendering/client.mjs +22424 -21488
  268. package/dist/client/rendering/islands.mjs +20 -23
  269. package/dist/client/rendering.mjs +21025 -19413
  270. package/dist/client/{routeIslandApiConfig-BgP-aPMl.mjs → routeIslandApiConfig-Dl4vglJm.mjs} +1 -1
  271. package/dist/client/{shop-B_eykR-_.mjs → shop-P72nX5Fs.mjs} +7 -7
  272. package/dist/client/{shop-commerce-CT0APkFV.mjs → shop-commerce-Bt7uraDx.mjs} +8 -8
  273. package/dist/client/{shop-commerce-store-DcvZxdEK.mjs → shop-commerce-store-C1-mxSye.mjs} +1 -1
  274. package/dist/client/{shopShared-BVJOiUiJ.mjs → shopShared-Db-cRGu3.mjs} +5 -5
  275. package/dist/client/{useDiscountCodeUi-DPmYDunz.mjs → useDiscountCodeUi-jvAiUoUX.mjs} +1 -1
  276. package/dist/client/{useEventPagination-8-U55vH5.mjs → useEventPagination-BdWpCniq.mjs} +6 -7
  277. package/dist/preview-next/before-render.mjs +222 -55
  278. package/dist/preview-next/client/runtime.mjs +3 -3
  279. package/dist/preview-next/editor-chrome.css +5 -2
  280. package/dist/preview-next/keepAlive.mjs +133 -51
  281. package/dist/preview-next/middleware.mjs +133 -51
  282. package/dist/{sdk-runtime-C5jPdSrk.mjs → sdk-runtime-DLhjF2Nw.mjs} +1 -1
  283. package/dist/server/components.mjs +21541 -20118
  284. package/dist/server/config-validation.mjs +2466 -1403
  285. package/dist/server/config.mjs +2466 -1403
  286. package/dist/server/data.mjs +17842 -16759
  287. package/dist/server/date-time.mjs +258 -116
  288. package/dist/server/index.mjs +360 -53
  289. package/dist/server/next.mjs +21913 -20539
  290. package/dist/server/page-converter.mjs +8121 -7322
  291. package/dist/server/prebuild.mjs +1 -1
  292. package/dist/server/rendering/server.mjs +21196 -19760
  293. package/dist/server/rendering.mjs +21554 -20123
  294. package/dist/server/routing.mjs +19806 -18607
  295. package/dist/server/server.mjs +2907 -1845
  296. package/dist/server/theme-bridge.mjs +991 -160
  297. package/dist/server/theme.mjs +501 -100
  298. package/dist/{spinner-B-ab2rJp.mjs → spinner-MTooKfck.mjs} +1 -1
  299. package/dist/styles/index.css +254 -1
  300. package/package.json +1 -1
  301. package/dist/_dts/blocks/src/system/blocks/events/shared/layout.d.ts +0 -12
  302. package/dist/client/aspectTransforms-D-TnDdq4.mjs +0 -93
  303. package/dist/client/colorStyles-ECDNPE_P.mjs +0 -1253
@@ -1,5 +1,4 @@
1
- import { A as themeColorTokenSchema, C as paletteColorsSchema, D as requirePaletteColorsFromEntries, E as paletteValueKeySchema, N as err$1, O as parseThemeColorToken, P as ok$1, S as paletteColorsFromEntries, T as paletteValueKey, _ as buttonSystemSchema, b as hexColorSchema, c as tokenOrCssColorValueSchema, d as mapButtonRoleAppearances, f as mapButtonVisualAppearances, g as buttonSizeNameSchema, h as VARIANT_ROLES, i as opaqueSurfaceDeclarations, k as themeColorShadeSteps, l as PUBLIC_BUTTON_ROLES, p as resolveButtonStyleRecipe, u as defineButtonStyleRecipe, v as buttonVisualStatesSchema, w as paletteModeSchema, x as paletteColorEntries, y as unsafeAsOpaqueButtonColourToken } from "./colorStyles-ECDNPE_P.mjs";
2
- import { a as parseEventOfferingId, i as parseContentVersionId, n as parseAspectRatioValue, o as parseEventSeriesId } from "./aspectTransforms-D-TnDdq4.mjs";
1
+ import { _ as err$1, c as parseEventSeriesId, i as mediaIdentifierSchema, n as renderableMediaAssetSchema, o as parseContentVersionId, s as parseEventOfferingId, v as ok$1 } from "./renderableMediaAssetAdmission-CHkXYDC_.mjs";
3
2
  import "react";
4
3
  import { z } from "zod";
5
4
  import "react/jsx-runtime";
@@ -496,6 +495,25 @@ function validateBookingPaymentOptionKinds(kinds) {
496
495
  return ok$1(void 0);
497
496
  }
498
497
  //#endregion
498
+ //#region ../core/src/date-time-formatter.ts
499
+ /** Shared Intl engine, internal to core's date presentation owners. */
500
+ const FORMATTER_CACHE_LIMIT = 100;
501
+ const dateTimeFormatterCache = /* @__PURE__ */ new Map();
502
+ function getDateTimeFormatter(locale, timeZone, format) {
503
+ const key = `${locale}\u0000${timeZone}\u0000${JSON.stringify(Object.entries(format).sort(([left], [right]) => left.localeCompare(right)))}`;
504
+ const cached = dateTimeFormatterCache.get(key);
505
+ if (cached !== void 0) return cached;
506
+ if (typeof locale !== "string" || Intl.DateTimeFormat.supportedLocalesOf([locale]).length === 0) throw new RangeError("An explicit supported locale is required");
507
+ if (typeof timeZone !== "string" || timeZone.length === 0) throw new RangeError("An explicit time zone is required");
508
+ const formatter = new Intl.DateTimeFormat(locale, {
509
+ ...format,
510
+ timeZone
511
+ });
512
+ if (dateTimeFormatterCache.size >= FORMATTER_CACHE_LIMIT) dateTimeFormatterCache.clear();
513
+ dateTimeFormatterCache.set(key, formatter);
514
+ return formatter;
515
+ }
516
+ //#endregion
499
517
  //#region ../core/src/booking-time-zone.ts
500
518
  const TIME_ZONE_VALIDITY_CACHE_LIMIT = 100;
501
519
  const timeZoneValidityCache = /* @__PURE__ */ new Map();
@@ -532,8 +550,6 @@ const START_OF_DAY = {
532
550
  second: 0
533
551
  };
534
552
  const LOCAL_DATE_PATTERN = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/u;
535
- const DATE_TIME_FORMATTER_CACHE_LIMIT = 100;
536
- const dateTimeFormatterCache = /* @__PURE__ */ new Map();
537
553
  function getSafeTimeZone(timeZone) {
538
554
  const normalized = typeof timeZone === "string" ? timeZone.trim() : "";
539
555
  return normalized.length > 0 && isValidBookingTimeZone(normalized) ? normalized : FALLBACK_TIMEZONE;
@@ -550,19 +566,7 @@ function formatParseError(error) {
550
566
  }
551
567
  }
552
568
  function formatToPartsLookup(date, locale, timeZone, format) {
553
- return new Map(getCachedDateTimeFormatter(locale, timeZone, format).formatToParts(date).map((part) => [part.type, part.value]));
554
- }
555
- function getCachedDateTimeFormatter(locale, timeZone, format) {
556
- const key = `${locale}\u0000${timeZone}\u0000${JSON.stringify(Object.entries(format).sort(([left], [right]) => left.localeCompare(right)))}`;
557
- const cached = dateTimeFormatterCache.get(key);
558
- if (cached !== void 0) return cached;
559
- const formatter = new Intl.DateTimeFormat(locale, {
560
- ...format,
561
- timeZone
562
- });
563
- if (dateTimeFormatterCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) dateTimeFormatterCache.clear();
564
- dateTimeFormatterCache.set(key, formatter);
565
- return formatter;
569
+ return new Map(getDateTimeFormatter(locale, timeZone, format).formatToParts(date).map((part) => [part.type, part.value]));
566
570
  }
567
571
  function getZonedDateTimeParts(date, timeZone) {
568
572
  const parts = formatToPartsLookup(date, "en-GB", timeZone, {
@@ -679,7 +683,7 @@ function toScheduledBookingDateRange(input) {
679
683
  function formatBookingInstant(isoString, options) {
680
684
  const date = new Date(isoString);
681
685
  if (Number.isNaN(date.getTime())) return isoString;
682
- return getCachedDateTimeFormatter(options.locale ?? DEFAULT_LOCALE, getSafeTimeZone(options.timeZone), options.format).format(date);
686
+ return getDateTimeFormatter(options.locale ?? DEFAULT_LOCALE, getSafeTimeZone(options.timeZone), options.format).format(date);
683
687
  }
684
688
  function formatBookingDate(input, format = {
685
689
  weekday: "long",
@@ -822,6 +826,17 @@ function localScheduleDateTimeToUtcDate(localDate, localTime, timeZone) {
822
826
  return new Date(guess);
823
827
  }
824
828
  //#endregion
829
+ //#region ../core/src/date-display.ts
830
+ /** Site-language policy, shared by customer emails and public event adapters. */
831
+ function inferSiteDateLocale(siteTimeZone) {
832
+ if (siteTimeZone === null || siteTimeZone === void 0 || siteTimeZone === "") return "en-US";
833
+ if (siteTimeZone === "Europe/Dublin") return "en-IE";
834
+ if (siteTimeZone.startsWith("Europe/")) return "en-GB";
835
+ if (siteTimeZone.startsWith("Australia/")) return "en-AU";
836
+ if (siteTimeZone === "Pacific/Auckland" || siteTimeZone === "Pacific/Chatham") return "en-NZ";
837
+ return "en-US";
838
+ }
839
+ //#endregion
825
840
  //#region ../core/src/mailing-list-identifiers.ts
826
841
  const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
827
842
  const OPAQUE_ID_PATTERN = /^[A-Za-z0-9_-]{1,100}$/u;
@@ -834,7 +849,7 @@ function parsePositiveInteger(value) {
834
849
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
835
850
  }
836
851
  function parseNewsletterListId(value) {
837
- return parseTrimmedMatchingString(value, UUID_PATTERN);
852
+ return parseTrimmedMatchingString(typeof value === "string" ? value.toLowerCase() : value, UUID_PATTERN);
838
853
  }
839
854
  function parseMailchimpAudienceId(value) {
840
855
  return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
@@ -848,8 +863,15 @@ function parseBrevoListId(value) {
848
863
  //#endregion
849
864
  //#region ../core/src/mailing-list-setup.ts
850
865
  const DEFAULT_MAILING_LIST_SUCCESS_MESSAGE = "Thanks — you're on the list.";
851
- //#endregion
852
- //#region ../core/src/mailing-list-setup-parser.ts
866
+ z.unknown().transform((value, ctx) => {
867
+ const parsed = parseNewsletterAudience(value);
868
+ if (parsed.ok) return parsed.value;
869
+ ctx.addIssue({
870
+ code: "custom",
871
+ message: "Choose a valid newsletter audience."
872
+ });
873
+ return z.NEVER;
874
+ });
853
875
  function parseMailingListGlobalForm(value) {
854
876
  if (!isRecord$8(value)) return formError("shape");
855
877
  const fields = parseGlobalFields(value.fields);
@@ -869,6 +891,16 @@ function parseMailingListGlobalForm(value) {
869
891
  privacyNote
870
892
  });
871
893
  }
894
+ function parseNewsletterAudience(value) {
895
+ if (!isRecord$8(value)) return err$1("invalid_newsletter_audience");
896
+ if (value.kind === "general" && Object.keys(value).length === 1) return ok$1({ kind: "general" });
897
+ if (value.kind !== "topic" || Object.keys(value).some((key) => key !== "kind" && key !== "topicId")) return err$1("invalid_newsletter_audience");
898
+ const topicId = parseNewsletterListId(value.topicId);
899
+ return topicId === null ? err$1("invalid_newsletter_audience") : ok$1({
900
+ kind: "topic",
901
+ topicId
902
+ });
903
+ }
872
904
  function parseGlobalFields(value) {
873
905
  if (!isRecord$8(value) || typeof value.preset !== "string") return null;
874
906
  switch (value.preset) {
@@ -877,6 +909,10 @@ function parseGlobalFields(value) {
877
909
  preset: "emailName",
878
910
  name: value.name
879
911
  } : null;
912
+ case "emailFirstName": return isRequirement(value.firstName) ? {
913
+ preset: "emailFirstName",
914
+ firstName: value.firstName
915
+ } : null;
880
916
  case "emailFirstLast": return isRequirement(value.firstName) && isRequirement(value.lastName) ? {
881
917
  preset: "emailFirstLast",
882
918
  firstName: value.firstName,
@@ -921,54 +957,49 @@ function formError(field) {
921
957
  const DEFAULT_MAILING_LIST_TARGETING = { mode: "default" };
922
958
  function mailingListTargetingChoiceIds(targeting) {
923
959
  switch (targeting.provider) {
924
- case "native": return targeting.selection.tag === "fixed" ? targeting.selection.topicIds : targeting.selection.offeredTopicIds;
960
+ case "native": return targeting.selection.tag === "general" ? [] : targeting.selection.tag === "fixed" ? targeting.selection.topicIds : targeting.selection.offeredTopicIds;
925
961
  case "brevo": return targeting.selection.tag === "fixed" ? targeting.selection.listIds : targeting.selection.offeredListIds;
926
962
  case "mailchimp": return targeting.selection.tag === "fixed" ? targeting.selection.interestIds : targeting.selection.offeredInterestIds;
927
963
  }
928
964
  }
929
965
  function planMailingListChoicePresentation(targeting) {
930
- if (targeting.mode === "default" || targeting.selection.tag === "fixed") return { tag: "hidden" };
966
+ if (targeting.mode === "default" || targeting.selection.tag === "fixed" || targeting.selection.tag === "general") return { tag: "hidden" };
931
967
  switch (targeting.provider) {
932
- case "native": return targeting.selection.offeredTopicIds.length === 1 ? {
933
- tag: "automatic",
934
- selection: {
935
- provider: "native",
936
- topicIds: targeting.selection.offeredTopicIds
937
- }
938
- } : {
939
- tag: "visitor_choice",
968
+ case "native": return presentVisitorSelection({
940
969
  provider: "native",
941
- optionCount: targeting.selection.offeredTopicIds.length
942
- };
943
- case "brevo": return targeting.selection.offeredListIds.length === 1 ? {
944
- tag: "automatic",
945
- selection: {
946
- provider: "brevo",
947
- listIds: targeting.selection.offeredListIds
948
- }
949
- } : {
950
- tag: "visitor_choice",
970
+ topicIds: targeting.selection.offeredTopicIds
971
+ }, targeting.selection.offeredTopicIds.length);
972
+ case "brevo": return presentVisitorSelection({
951
973
  provider: "brevo",
952
- optionCount: targeting.selection.offeredListIds.length
953
- };
954
- case "mailchimp": return targeting.selection.offeredInterestIds.length === 1 ? {
955
- tag: "automatic",
956
- selection: {
957
- provider: "mailchimp",
958
- interestIds: targeting.selection.offeredInterestIds
959
- }
960
- } : {
961
- tag: "visitor_choice",
974
+ listIds: targeting.selection.offeredListIds
975
+ }, targeting.selection.offeredListIds.length);
976
+ case "mailchimp": return presentVisitorSelection({
962
977
  provider: "mailchimp",
963
- optionCount: targeting.selection.offeredInterestIds.length
964
- };
978
+ interestIds: targeting.selection.offeredInterestIds
979
+ }, targeting.selection.offeredInterestIds.length);
965
980
  }
966
981
  }
982
+ function presentVisitorSelection(selection, optionCount) {
983
+ return optionCount === 1 ? {
984
+ tag: "automatic",
985
+ selection
986
+ } : {
987
+ tag: "visitor_choice",
988
+ provider: selection.provider,
989
+ optionCount
990
+ };
991
+ }
967
992
  //#endregion
968
993
  //#region ../core/src/mailing-list-targeting-availability.ts
969
994
  function resolveMailingListDefaultDestination(provider) {
970
995
  switch (provider.provider) {
971
- case "native": return provider.topics.find((item) => item.id === provider.defaultTopicId) ?? null;
996
+ case "native": {
997
+ const audience = provider.defaultAudience;
998
+ return audience.kind === "general" ? {
999
+ id: "general",
1000
+ name: "General mailing list"
1001
+ } : provider.topics.find((item) => item.id === audience.topicId) ?? null;
1002
+ }
972
1003
  case "brevo": return provider.lists.find((item) => item.id === provider.defaultListId) ?? null;
973
1004
  case "mailchimp": return provider.audiences.find((item) => item.id === provider.defaultAudienceId) ?? null;
974
1005
  }
@@ -1110,11 +1141,12 @@ function parseRuntimeProvider(value) {
1110
1141
  }
1111
1142
  }
1112
1143
  function parseNativeRuntimeProvider(value) {
1113
- const defaultTopicId = parseNewsletterListId(value.defaultTopicId);
1144
+ if ("defaultTopicId" in value) return null;
1145
+ const defaultAudience = parseNewsletterAudience(value.defaultAudience);
1114
1146
  const topics = parseNamedItems(value.topics, parseNewsletterListId);
1115
- return defaultTopicId !== null && topics !== null ? {
1147
+ return defaultAudience.ok && topics !== null ? {
1116
1148
  provider: "native",
1117
- defaultTopicId,
1149
+ defaultAudience: defaultAudience.value,
1118
1150
  topics
1119
1151
  } : null;
1120
1152
  }
@@ -1202,6 +1234,7 @@ function parseMailingListVisitorSelection(value) {
1202
1234
  if (!isRecord$6(value)) return visitorSelectionError("shape");
1203
1235
  switch (value.provider) {
1204
1236
  case "native": {
1237
+ if (Object.keys(value).some((key) => key !== "provider" && key !== "topicIds")) return visitorSelectionError("shape");
1205
1238
  const topicIds = parseVisitorIds(value.topicIds, parseNewsletterListId);
1206
1239
  return topicIds === null ? visitorSelectionError("targets") : ok$1({
1207
1240
  provider: "native",
@@ -1226,6 +1259,11 @@ function parseMailingListVisitorSelection(value) {
1226
1259
  }
1227
1260
  }
1228
1261
  function parseNativeTargeting(selection) {
1262
+ if (selection.tag === "general") return Object.keys(selection).length === 1 ? ok$1({
1263
+ mode: "custom",
1264
+ provider: "native",
1265
+ selection: { tag: "general" }
1266
+ }) : targetingError("selection");
1229
1267
  if (selection.tag === "fixed") {
1230
1268
  const topicIds = parseNonEmptyUniqueIds(selection.topicIds, parseNewsletterListId);
1231
1269
  return topicIds.ok ? ok$1({
@@ -1475,6 +1513,169 @@ const EVENT_PRESET_VOCABULARY = {
1475
1513
  }
1476
1514
  };
1477
1515
  //#endregion
1516
+ //#region ../media-core/src/mediaKinds.ts
1517
+ const mediaTypeDiscriminants = [
1518
+ "image",
1519
+ "video",
1520
+ "audio",
1521
+ "document",
1522
+ "spreadsheet",
1523
+ "archive"
1524
+ ];
1525
+ //#endregion
1526
+ //#region ../media-core/src/media.ts
1527
+ const hotspotSchema = z.object({
1528
+ x: z.number().min(0).max(1),
1529
+ y: z.number().min(0).max(1),
1530
+ radius: z.number().optional()
1531
+ });
1532
+ const rotationSchema = z.union([
1533
+ z.literal(0),
1534
+ z.literal(90),
1535
+ z.literal(180),
1536
+ z.literal(270)
1537
+ ]);
1538
+ const rectSchema = z.tuple([
1539
+ z.number(),
1540
+ z.number(),
1541
+ z.number(),
1542
+ z.number()
1543
+ ]);
1544
+ const aspectCropSchema = z.object({
1545
+ aspect: z.preprocess((value) => value == null ? void 0 : value, z.string().optional()),
1546
+ rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema.optional()),
1547
+ hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema.optional()),
1548
+ rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema.optional())
1549
+ });
1550
+ const transformSchema = z.object({
1551
+ aspectCrops: z.preprocess((value) => {
1552
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
1553
+ return value;
1554
+ }, z.record(z.string(), aspectCropSchema.catch({}))).optional(),
1555
+ rect: rectSchema.optional(),
1556
+ hotspot: hotspotSchema.optional(),
1557
+ rotation: rotationSchema.optional()
1558
+ });
1559
+ const mediaPosterSchema = z.discriminatedUnion("tag", [z.object({
1560
+ tag: z.literal("media"),
1561
+ identifier: mediaIdentifierSchema
1562
+ }).strict(), z.object({
1563
+ tag: z.literal("external-src"),
1564
+ src: z.string().url()
1565
+ }).strict()]);
1566
+ const mediaUsageShape = {
1567
+ purpose: z.string().optional(),
1568
+ placeholder: z.boolean().default(true).optional(),
1569
+ alt: z.string().optional(),
1570
+ filename: z.string().optional(),
1571
+ width: z.number().optional(),
1572
+ height: z.number().optional(),
1573
+ poster: mediaPosterSchema.optional(),
1574
+ transform: transformSchema.optional()
1575
+ };
1576
+ const environmentExclusions = {
1577
+ assetId: z.never().optional(),
1578
+ id: z.never().optional(),
1579
+ src: z.never().optional(),
1580
+ storageBucket: z.never().optional(),
1581
+ storagePath: z.never().optional(),
1582
+ mimeType: z.never().optional()
1583
+ };
1584
+ const mediaBaseSchema = z.object({
1585
+ ...mediaUsageShape,
1586
+ ...environmentExclusions,
1587
+ identifier: mediaIdentifierSchema
1588
+ }).strict();
1589
+ const imageMediaSchema = mediaBaseSchema.extend({ type: z.literal("image") });
1590
+ const videoMediaSchema = mediaBaseSchema.extend({ type: z.literal("video") });
1591
+ const mediaSchema = mediaBaseSchema.extend({ type: z.enum(mediaTypeDiscriminants) });
1592
+ const externalMediaSchema = z.object({
1593
+ ...mediaUsageShape,
1594
+ ...environmentExclusions,
1595
+ type: z.enum(mediaTypeDiscriminants),
1596
+ src: z.string().min(1),
1597
+ identifier: z.never().optional()
1598
+ }).strict();
1599
+ const assetMediaSchema = z.object({
1600
+ ...mediaUsageShape,
1601
+ ...environmentExclusions,
1602
+ type: z.enum(mediaTypeDiscriminants),
1603
+ asset: renderableMediaAssetSchema,
1604
+ identifier: z.never().optional()
1605
+ }).strict();
1606
+ const runtimeMediaSchema = z.union([
1607
+ mediaSchema,
1608
+ externalMediaSchema,
1609
+ assetMediaSchema
1610
+ ]);
1611
+ //#endregion
1612
+ //#region ../media-core/src/transformRect.ts
1613
+ function isValidTransformRectStructure(rect) {
1614
+ if (!Array.isArray(rect) || rect.length !== 4) return false;
1615
+ const [left, top, width, height] = rect;
1616
+ return Number.isFinite(left) && Number.isFinite(top) && Number.isFinite(width) && Number.isFinite(height) && left >= 0 && top >= 0 && width > 0 && height > 0;
1617
+ }
1618
+ //#endregion
1619
+ //#region ../media-core/src/aspectTransforms.ts
1620
+ const DEFAULT_RECT_EPSILON = .5;
1621
+ function parseAspectRatioValue(value) {
1622
+ if (typeof value === "number") return Number.isFinite(value) && value > 0 ? value : void 0;
1623
+ if (typeof value !== "string") return void 0;
1624
+ const normalized = value.trim();
1625
+ if (!normalized) return void 0;
1626
+ if (normalized === "auto") return void 0;
1627
+ if (normalized.includes(":") || normalized.includes("/")) {
1628
+ const delimiter = normalized.includes(":") ? ":" : "/";
1629
+ const [wRaw, hRaw] = normalized.split(delimiter);
1630
+ const width = Number(wRaw?.trim());
1631
+ const height = Number(hRaw?.trim());
1632
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return;
1633
+ return width / height;
1634
+ }
1635
+ const numeric = Number(normalized);
1636
+ if (!Number.isFinite(numeric) || numeric <= 0) return void 0;
1637
+ return numeric;
1638
+ }
1639
+ const MAX_ASPECT_DISTANCE = .25;
1640
+ function resolveMediaTransformForAspect(transform, targetAspect) {
1641
+ if (!transform) return {};
1642
+ const base = {
1643
+ rect: transform.rect,
1644
+ hotspot: transform.hotspot,
1645
+ rotation: transform.rotation
1646
+ };
1647
+ const target = parseAspectRatioValue(targetAspect);
1648
+ const crops = transform.aspectCrops;
1649
+ if (!target || !crops || Object.keys(crops).length === 0) return base;
1650
+ let best = null;
1651
+ let bestDistance = Number.POSITIVE_INFINITY;
1652
+ for (const [key, candidate] of Object.entries(crops)) {
1653
+ const candidateAspect = parseAspectRatioValue(candidate.aspect ?? key);
1654
+ if (!candidateAspect) continue;
1655
+ const distance = Math.abs(Math.log(candidateAspect / target));
1656
+ if (distance < bestDistance) {
1657
+ best = candidate;
1658
+ bestDistance = distance;
1659
+ }
1660
+ }
1661
+ if (!best) return base;
1662
+ if (bestDistance > MAX_ASPECT_DISTANCE) return base;
1663
+ return {
1664
+ rect: best.rect ?? base.rect,
1665
+ hotspot: best.hotspot ?? base.hotspot,
1666
+ rotation: best.rotation ?? base.rotation
1667
+ };
1668
+ }
1669
+ function isValidTransformRect(rect) {
1670
+ return isValidTransformRectStructure(rect);
1671
+ }
1672
+ function isExplicitRectCrop(rect, sourceWidth, sourceHeight, epsilon = DEFAULT_RECT_EPSILON) {
1673
+ if (!isValidTransformRect(rect)) return false;
1674
+ if (!(typeof sourceWidth === "number" && Number.isFinite(sourceWidth) && sourceWidth > 0 && typeof sourceHeight === "number" && Number.isFinite(sourceHeight) && sourceHeight > 0)) return true;
1675
+ const [x, y, width, height] = rect;
1676
+ return !(Math.abs(x) <= epsilon && Math.abs(y) <= epsilon && Math.abs(width - sourceWidth) <= epsilon && Math.abs(height - sourceHeight) <= epsilon);
1677
+ }
1678
+ //#endregion
1478
1679
  //#region ../commerce/src/utils/assertNever.ts
1479
1680
  function assertNever$3(value, message) {
1480
1681
  if (message) throw new Error(message);
@@ -2048,6 +2249,621 @@ function checkBrowserStripeKey(publishableKey, livemode) {
2048
2249
  };
2049
2250
  }
2050
2251
  //#endregion
2252
+ //#region ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
2253
+ function r(e) {
2254
+ var t, f, n = "";
2255
+ if ("string" == typeof e || "number" == typeof e) n += e;
2256
+ else if ("object" == typeof e) if (Array.isArray(e)) {
2257
+ var o = e.length;
2258
+ for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
2259
+ } else for (f in e) e[f] && (n && (n += " "), n += f);
2260
+ return n;
2261
+ }
2262
+ function clsx() {
2263
+ for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
2264
+ return n;
2265
+ }
2266
+ //#endregion
2267
+ //#region ../theme-core/src/buttons/typography.ts
2268
+ const textTransformSchema = z.enum([
2269
+ "none",
2270
+ "uppercase",
2271
+ "lowercase",
2272
+ "capitalize"
2273
+ ]);
2274
+ const fontWeightSchema = z.union([
2275
+ z.literal(400),
2276
+ z.literal(500),
2277
+ z.literal(600),
2278
+ z.literal(700),
2279
+ z.literal(800)
2280
+ ]);
2281
+ const buttonTypographySchema = z.enum(["body", "heading"]);
2282
+ const letterSpacingSchema = z.enum([
2283
+ "tight",
2284
+ "normal",
2285
+ "slight",
2286
+ "loose",
2287
+ "wide"
2288
+ ]);
2289
+ //#endregion
2290
+ //#region ../theme-core/src/tokens/colorTokenParts.ts
2291
+ function parseOpacityPercent(source) {
2292
+ const trimmed = source.trim();
2293
+ if (!trimmed) return null;
2294
+ if (!/^\d{1,3}(?:\.\d+)?$/.test(trimmed)) return null;
2295
+ const value = Number(trimmed);
2296
+ if (!Number.isFinite(value)) return null;
2297
+ if (value < 0 || value > 100) return null;
2298
+ return value;
2299
+ }
2300
+ function parseColorTokenParts(source) {
2301
+ const trimmed = source.trim();
2302
+ if (trimmed.startsWith("raw:")) return {
2303
+ kind: "raw",
2304
+ value: trimmed.slice(4)
2305
+ };
2306
+ const [token, opacityRaw, extra] = trimmed.split("/");
2307
+ if (!token || extra !== void 0) return {
2308
+ kind: "invalid",
2309
+ token: trimmed
2310
+ };
2311
+ if (opacityRaw === void 0) return {
2312
+ kind: "token",
2313
+ token,
2314
+ opacityPercent: null
2315
+ };
2316
+ const opacityPercent = parseOpacityPercent(opacityRaw);
2317
+ if (opacityPercent === null) return {
2318
+ kind: "invalid",
2319
+ token: trimmed
2320
+ };
2321
+ return {
2322
+ kind: "token",
2323
+ token,
2324
+ opacityPercent
2325
+ };
2326
+ }
2327
+ //#endregion
2328
+ //#region ../theme-core/src/tokens/blockColorTokens.ts
2329
+ const blockColorTokenNames = [
2330
+ "text",
2331
+ "heading",
2332
+ "mutedText",
2333
+ "surface",
2334
+ "background",
2335
+ "foreground",
2336
+ "border",
2337
+ "primary",
2338
+ "secondary",
2339
+ "accent",
2340
+ "success",
2341
+ "warning",
2342
+ "info",
2343
+ "error",
2344
+ "destructive",
2345
+ "scrim",
2346
+ "shadow",
2347
+ "onPrimary",
2348
+ "onSecondary",
2349
+ "onAccent",
2350
+ "onSuccess",
2351
+ "onWarning",
2352
+ "onInfo",
2353
+ "onError",
2354
+ "onDestructive",
2355
+ "onSurface",
2356
+ "onText"
2357
+ ];
2358
+ new Set(blockColorTokenNames);
2359
+ //#endregion
2360
+ //#region ../theme-core/src/tokens/themeColorTokens.ts
2361
+ /**
2362
+ * Known palette role token names. This is the low-level source of truth for
2363
+ * palette roles used by palette variants, Theme V2 schemas, and runtime color
2364
+ * reference parsing.
2365
+ */
2366
+ const PALETTE_TOKEN_NAMES = [
2367
+ "primary",
2368
+ "primaryForeground",
2369
+ "secondary",
2370
+ "accent",
2371
+ "success",
2372
+ "warning",
2373
+ "destructive",
2374
+ "background",
2375
+ "surface",
2376
+ "surfaceAlt",
2377
+ "muted",
2378
+ "text",
2379
+ "border"
2380
+ ];
2381
+ const paletteTokenNameSchema = z.enum(PALETTE_TOKEN_NAMES);
2382
+ const themeColorBaseTokenNames = [
2383
+ ...PALETTE_TOKEN_NAMES,
2384
+ ...blockColorTokenNames,
2385
+ "white",
2386
+ "neutral",
2387
+ "primaryText",
2388
+ "secondaryForeground",
2389
+ "accentForeground"
2390
+ ];
2391
+ const themeColorBaseTokenSet = new Set(themeColorBaseTokenNames);
2392
+ const themeColorShadeSteps = [
2393
+ "50",
2394
+ "100",
2395
+ "200",
2396
+ "300",
2397
+ "400",
2398
+ "500",
2399
+ "600",
2400
+ "700",
2401
+ "800",
2402
+ "900",
2403
+ "950"
2404
+ ];
2405
+ const shadeStepSet = new Set(themeColorShadeSteps);
2406
+ function isKnownBaseToken(value) {
2407
+ return themeColorBaseTokenSet.has(value);
2408
+ }
2409
+ function isKnownShadeToken(value) {
2410
+ const match = value.match(/^([a-zA-Z][a-zA-Z0-9]*)(?:-([0-9]{2,3}))$/);
2411
+ if (!match) return false;
2412
+ const [, base, shade] = match;
2413
+ return Boolean(base && shade && isKnownBaseToken(base) && shadeStepSet.has(shade));
2414
+ }
2415
+ function isThemeColorTokenBase(value) {
2416
+ return isKnownBaseToken(value) || isKnownShadeToken(value);
2417
+ }
2418
+ function isThemeColorToken(value) {
2419
+ if (typeof value !== "string") return false;
2420
+ const parts = parseColorTokenParts(value);
2421
+ return parts.kind === "token" && isThemeColorTokenBase(parts.token);
2422
+ }
2423
+ function parseThemeColorToken(value) {
2424
+ if (!isThemeColorToken(value)) return null;
2425
+ return value.trim();
2426
+ }
2427
+ const themeColorTokenSchema = z.string().min(1).refine((value) => Boolean(isThemeColorToken(value)), "Expected a known Theme V2 color token");
2428
+ //#endregion
2429
+ //#region ../theme-core/src/buttons/types.ts
2430
+ /**
2431
+ * Standard semantic variant roles a theme exposes.
2432
+ *
2433
+ * Block content references variants by role; the active theme determines
2434
+ * what each role looks like.
2435
+ */
2436
+ const VARIANT_ROLES = [
2437
+ "primary",
2438
+ "secondary",
2439
+ "outline",
2440
+ "ghost",
2441
+ "accent"
2442
+ ];
2443
+ /**
2444
+ * Canonical persisted/CSS-safe button variant identifier.
2445
+ *
2446
+ * IDs become class selectors, so keep the contract deliberately narrower than
2447
+ * an arbitrary string and shared with every authoring/runtime boundary.
2448
+ */
2449
+ const buttonVariantIdSchema = z.string().min(1).max(50).regex(/^[a-z0-9-]+$/, "Button variant IDs may contain lowercase letters, numbers, and hyphens only").refine((value) => value !== "link" && value !== "tertiary", { message: "Retired button role IDs are not valid variant IDs" });
2450
+ function parseOpaqueButtonColourToken(value) {
2451
+ const token = parseThemeColorToken(value);
2452
+ if (token === null) return null;
2453
+ const parts = parseColorTokenParts(token);
2454
+ return parts.kind === "token" && parts.opacityPercent === null ? token : null;
2455
+ }
2456
+ function unsafeAsOpaqueButtonColourToken(value) {
2457
+ return value;
2458
+ }
2459
+ const opaqueButtonColourTokenSchema = themeColorTokenSchema.refine((value) => parseOpaqueButtonColourToken(value) !== null, "Button colour tokens must be opaque").transform((value) => {
2460
+ const token = parseOpaqueButtonColourToken(value);
2461
+ if (token === null) throw new Error("Invariant: opaque button token passed its schema");
2462
+ return token;
2463
+ });
2464
+ const contextualButtonHoverSchema = z.strictObject({
2465
+ kind: z.literal("shade-shift"),
2466
+ seedToken: opaqueButtonColourTokenSchema,
2467
+ fallbackDirection: z.enum(["lighter", "darker"]),
2468
+ preferredToken: opaqueButtonColourTokenSchema.optional()
2469
+ });
2470
+ const buttonShadeAmountSchema = z.number().finite().min(0).max(900).multipleOf(100);
2471
+ const buttonShadowIntensitySchema = z.enum([
2472
+ "subtle",
2473
+ "medium",
2474
+ "strong"
2475
+ ]);
2476
+ /**
2477
+ * The complete persisted button-effect contract.
2478
+ *
2479
+ * Navigation has its own generic interactive-effect model. Button variants use
2480
+ * this closed union so unsupported effect IDs, unknown option keys, and unsafe
2481
+ * CSS values cannot become representable after the schema boundary.
2482
+ */
2483
+ const buttonPressOffsetSchema = z.strictObject({
2484
+ x: z.number().int().min(0).max(12),
2485
+ y: z.number().int().min(0).max(12)
2486
+ });
2487
+ const buttonEffectApplicationSchema = z.discriminatedUnion("effectId", [
2488
+ z.strictObject({
2489
+ effectId: z.literal("darken-background"),
2490
+ options: z.strictObject({ amount: buttonShadeAmountSchema.optional() }).optional()
2491
+ }),
2492
+ z.strictObject({
2493
+ effectId: z.literal("lighten-background"),
2494
+ options: z.strictObject({ amount: buttonShadeAmountSchema.optional() }).optional()
2495
+ }),
2496
+ z.strictObject({
2497
+ effectId: z.literal("background-on-hover"),
2498
+ options: z.strictObject({ colorToken: opaqueButtonColourTokenSchema.optional() }).optional()
2499
+ }),
2500
+ z.strictObject({
2501
+ effectId: z.literal("animated-gradient"),
2502
+ options: z.strictObject({ direction: z.enum(["horizontal", "vertical"]).optional() }).optional()
2503
+ }),
2504
+ z.strictObject({
2505
+ effectId: z.literal("drop-shadow"),
2506
+ options: z.strictObject({ intensity: buttonShadowIntensitySchema.optional() }).optional()
2507
+ }),
2508
+ z.strictObject({
2509
+ effectId: z.literal("inner-shadow"),
2510
+ options: z.strictObject({}).optional()
2511
+ }),
2512
+ z.strictObject({
2513
+ effectId: z.literal("neumorphic-shadow"),
2514
+ options: z.strictObject({
2515
+ mode: z.enum(["raised", "pressed"]).optional(),
2516
+ intensity: buttonShadowIntensitySchema.optional()
2517
+ }).optional()
2518
+ }),
2519
+ z.strictObject({
2520
+ effectId: z.literal("retro-3d-shadow"),
2521
+ options: z.strictObject({}).optional()
2522
+ }),
2523
+ z.strictObject({
2524
+ effectId: z.literal("scale-up"),
2525
+ options: z.strictObject({ scale: z.enum([
2526
+ "1.02",
2527
+ "1.03",
2528
+ "1.05",
2529
+ "1.10"
2530
+ ]).optional() }).optional()
2531
+ }),
2532
+ z.strictObject({
2533
+ effectId: z.literal("scale-down"),
2534
+ options: z.strictObject({ scale: z.enum([
2535
+ "0.90",
2536
+ "0.95",
2537
+ "0.97",
2538
+ "0.98"
2539
+ ]).optional() }).optional()
2540
+ }),
2541
+ z.strictObject({
2542
+ effectId: z.literal("lift"),
2543
+ options: z.strictObject({ amount: z.enum([
2544
+ "0.125",
2545
+ "0.25",
2546
+ "0.5",
2547
+ "1"
2548
+ ]).optional() }).optional()
2549
+ }),
2550
+ z.strictObject({
2551
+ effectId: z.literal("press-down"),
2552
+ options: z.strictObject({ offset: buttonPressOffsetSchema.optional() }).optional()
2553
+ }),
2554
+ z.strictObject({
2555
+ effectId: z.literal("pop"),
2556
+ options: z.strictObject({ intensity: z.enum([
2557
+ "subtle",
2558
+ "medium",
2559
+ "dramatic"
2560
+ ]).optional() }).optional()
2561
+ }),
2562
+ z.strictObject({
2563
+ effectId: z.literal("border-bottom-grow"),
2564
+ options: z.strictObject({
2565
+ height: z.union([z.literal(1), z.literal(2)]).optional(),
2566
+ origin: z.enum([
2567
+ "left",
2568
+ "center",
2569
+ "right"
2570
+ ]).optional(),
2571
+ persistent: z.boolean().optional(),
2572
+ colourRole: z.literal("mark").optional()
2573
+ }).optional()
2574
+ }),
2575
+ z.strictObject({
2576
+ effectId: z.literal("sketchy-border"),
2577
+ options: z.strictObject({ intensity: buttonShadowIntensitySchema.optional() }).optional()
2578
+ })
2579
+ ]);
2580
+ const cornerStyleSchema = z.enum([
2581
+ "square",
2582
+ "rounded",
2583
+ "pill"
2584
+ ]);
2585
+ const shadowSizeSchema = z.enum([
2586
+ "none",
2587
+ "low",
2588
+ "medium",
2589
+ "high"
2590
+ ]);
2591
+ const hoverTransformSchema = z.enum([
2592
+ "none",
2593
+ "lift",
2594
+ "scale",
2595
+ "press"
2596
+ ]);
2597
+ z.enum(["none", "token"]);
2598
+ const buttonPaddingPresetSchema = z.enum([
2599
+ "compact",
2600
+ "default",
2601
+ "spacious"
2602
+ ]);
2603
+ const gradientStyleSchema = z.enum([
2604
+ "linear",
2605
+ "radial",
2606
+ "conic"
2607
+ ]);
2608
+ const gradientSharpnessSchema = z.enum([
2609
+ "smooth",
2610
+ "medium",
2611
+ "hard"
2612
+ ]);
2613
+ const prioritySchema = z.union([
2614
+ z.literal(1),
2615
+ z.literal(2),
2616
+ z.literal(3)
2617
+ ]);
2618
+ const variantRoleSchema = z.enum(VARIANT_ROLES);
2619
+ const buttonSurfaceFallbackSchema = z.discriminatedUnion("kind", [z.strictObject({ kind: z.literal("surface-outline") }), z.strictObject({
2620
+ kind: z.literal("variant"),
2621
+ role: variantRoleSchema
2622
+ })]);
2623
+ const standardButtonSurfacePolicy = {
2624
+ primary: [{ kind: "surface-outline" }],
2625
+ secondary: [{ kind: "surface-outline" }, {
2626
+ kind: "variant",
2627
+ role: "primary"
2628
+ }],
2629
+ outline: [{ kind: "surface-outline" }],
2630
+ ghost: [{ kind: "surface-outline" }],
2631
+ accent: [{ kind: "surface-outline" }, {
2632
+ kind: "variant",
2633
+ role: "primary"
2634
+ }]
2635
+ };
2636
+ const STANDARD_BUTTON_SURFACE_POLICY = Object.freeze(Object.fromEntries(VARIANT_ROLES.map((role) => [role, Object.freeze([...standardButtonSurfacePolicy[role]])])));
2637
+ function createStandardButtonSurfacePolicy() {
2638
+ return Object.fromEntries(VARIANT_ROLES.map((role) => [role, [...STANDARD_BUTTON_SURFACE_POLICY[role]]]));
2639
+ }
2640
+ const buttonSurfacePolicyShape = Object.fromEntries(VARIANT_ROLES.map((role) => [role, z.array(buttonSurfaceFallbackSchema).max(VARIANT_ROLES.length)]));
2641
+ const buttonSurfacePolicySchema = z.strictObject(buttonSurfacePolicyShape);
2642
+ const buttonSizeNameSchema = z.enum([
2643
+ "sm",
2644
+ "md",
2645
+ "lg",
2646
+ "xl"
2647
+ ]);
2648
+ /**
2649
+ * CSS padding string in `"<vertical> <horizontal>"` shorthand form.
2650
+ *
2651
+ * Exactly two space-separated CSS length tokens. Each token is either the
2652
+ * literal `0` or a number followed by `rem`/`em`/`px`/`%`. This lets the
2653
+ * generator trust the shape rather than defensively defaulting downstream.
2654
+ */
2655
+ const PADDING_TOKEN_PATTERN = /^(?:0|\d+(?:\.\d+)?(?:rem|em|px|%))$/;
2656
+ const paddingShorthandSchema = z.string().refine((value) => {
2657
+ const parts = value.split(/\s+/).filter(Boolean);
2658
+ return parts.length === 2 && parts.every((token) => PADDING_TOKEN_PATTERN.test(token));
2659
+ }, { message: "Padding must be two space-separated CSS length tokens (e.g. \"0.5rem 1rem\"). Use `0` for zero." });
2660
+ const buttonSizeConfigSchema = z.object({
2661
+ padding: paddingShorthandSchema,
2662
+ fontSize: z.string().optional(),
2663
+ borderRadius: z.string().optional()
2664
+ });
2665
+ /**
2666
+ * `xl` is optional on the wire so themes persisted before the `xl` size was
2667
+ * added (e.g. SWTS) continue to parse. When `xl` is missing the schema
2668
+ * backfills it from `lg`, keeping `ButtonSizes` a complete `sm/md/lg/xl` map
2669
+ * downstream — generators never need to deal with an undefined `xl`.
2670
+ */
2671
+ const buttonSizesSchema = z.object({
2672
+ sm: buttonSizeConfigSchema,
2673
+ md: buttonSizeConfigSchema,
2674
+ lg: buttonSizeConfigSchema,
2675
+ xl: buttonSizeConfigSchema.optional()
2676
+ }).transform(({ sm, md, lg, xl }) => ({
2677
+ sm,
2678
+ md,
2679
+ lg,
2680
+ xl: xl ?? lg
2681
+ }));
2682
+ const buttonGlobalSettingsBaseSchema = z.strictObject({
2683
+ cornerStyle: cornerStyleSchema,
2684
+ cornerRadius: z.number().min(0).max(24).optional(),
2685
+ /**
2686
+ * Family-level shadow inherited by variants that don't set their own.
2687
+ * Optional and flat-by-default: when omitted, buttons carry no drop shadow
2688
+ * (`elevation: 'none'`). A personality opts the whole family into a shadow by
2689
+ * setting this; individual variants still override. There is no system-level
2690
+ * shadow-by-default — shadows only appear when explicitly declared.
2691
+ */
2692
+ shadow: shadowSizeSchema.optional(),
2693
+ textTransform: textTransformSchema,
2694
+ fontWeight: fontWeightSchema,
2695
+ typography: buttonTypographySchema.optional(),
2696
+ fontSize: z.string().optional(),
2697
+ letterSpacing: letterSpacingSchema.optional(),
2698
+ italic: z.boolean().optional(),
2699
+ paddingPreset: buttonPaddingPresetSchema.optional(),
2700
+ hoverTransform: hoverTransformSchema,
2701
+ gradientStyle: gradientStyleSchema.optional(),
2702
+ gradientAngle: z.number().min(0).max(360).optional(),
2703
+ gradientSharpness: gradientSharpnessSchema.optional()
2704
+ });
2705
+ const buttonGlobalSettingsSchema = z.discriminatedUnion("hoverColor", [buttonGlobalSettingsBaseSchema.extend({
2706
+ hoverColor: z.literal("none"),
2707
+ hoverColorToken: z.never().optional()
2708
+ }), buttonGlobalSettingsBaseSchema.extend({
2709
+ hoverColor: z.literal("token"),
2710
+ hoverColorToken: opaqueButtonColourTokenSchema
2711
+ })]);
2712
+ const gradientDirectionSchema$1 = z.enum([
2713
+ "to-r",
2714
+ "to-l",
2715
+ "to-t",
2716
+ "to-b",
2717
+ "to-tr",
2718
+ "to-tl",
2719
+ "to-br",
2720
+ "to-bl"
2721
+ ]);
2722
+ const buttonColourTreatmentSchema = z.discriminatedUnion("type", [
2723
+ z.strictObject({
2724
+ type: z.literal("solid"),
2725
+ colorToken: opaqueButtonColourTokenSchema
2726
+ }),
2727
+ z.strictObject({
2728
+ type: z.literal("gradient"),
2729
+ stops: z.array(opaqueButtonColourTokenSchema).min(2).transform((stops) => {
2730
+ const [first, second, ...rest] = stops;
2731
+ if (first === void 0 || second === void 0) throw new Error("Invariant: gradient stops passed the minimum length schema");
2732
+ return [
2733
+ first,
2734
+ second,
2735
+ ...rest
2736
+ ];
2737
+ }),
2738
+ direction: gradientDirectionSchema$1,
2739
+ foregroundToken: opaqueButtonColourTokenSchema
2740
+ }),
2741
+ z.strictObject({
2742
+ type: z.literal("surface"),
2743
+ role: z.literal("link")
2744
+ })
2745
+ ]);
2746
+ const buttonBackgroundSchema = buttonColourTreatmentSchema;
2747
+ const buttonBorderSchema = z.strictObject({
2748
+ widthClass: z.string(),
2749
+ marksBoundary: z.literal(true).optional(),
2750
+ ring: z.literal(true).optional(),
2751
+ boundaryInk: opaqueButtonColourTokenSchema.optional()
2752
+ });
2753
+ const buttonVariantAffordanceSchema = z.strictObject({ iconId: z.string().min(1) });
2754
+ const variantShadowSchema = z.strictObject({
2755
+ elevation: z.enum([
2756
+ "none",
2757
+ "low",
2758
+ "medium",
2759
+ "high"
2760
+ ]),
2761
+ softness: z.enum([
2762
+ "crisp",
2763
+ "soft",
2764
+ "hard"
2765
+ ]).nullable(),
2766
+ position: z.enum(["bottom", "bottom-right"]).default("bottom"),
2767
+ colorToken: opaqueButtonColourTokenSchema.optional()
2768
+ });
2769
+ /** Recipe states own every visual property; treatment owns its readable label. */
2770
+ const buttonVisualAppearanceSchema = z.strictObject({
2771
+ background: buttonColourTreatmentSchema,
2772
+ text: z.literal("treatment"),
2773
+ border: z.union([z.literal("none"), buttonBorderSchema]),
2774
+ borderRadius: z.string(),
2775
+ shadow: z.union([z.literal("focus-indicator"), variantShadowSchema]),
2776
+ sizes: buttonSizesSchema,
2777
+ typography: z.strictObject({
2778
+ fontWeight: fontWeightSchema,
2779
+ typography: buttonTypographySchema,
2780
+ fontSize: z.string().nullable(),
2781
+ letterSpacing: z.union([letterSpacingSchema, z.literal("heading")]).nullable(),
2782
+ italic: z.boolean(),
2783
+ textTransform: textTransformSchema
2784
+ }),
2785
+ effects: z.array(buttonEffectApplicationSchema),
2786
+ transform: z.literal("none").optional(),
2787
+ contextualHover: contextualButtonHoverSchema.optional()
2788
+ });
2789
+ const buttonVisualStatesSchema = z.strictObject({
2790
+ base: buttonVisualAppearanceSchema.extend({ shadow: variantShadowSchema }),
2791
+ hover: buttonVisualAppearanceSchema.extend({ shadow: variantShadowSchema }),
2792
+ focus: buttonVisualAppearanceSchema.extend({
2793
+ shadow: z.literal("focus-indicator"),
2794
+ indicator: z.strictObject({
2795
+ kind: z.literal("surface-ink"),
2796
+ width: z.union([z.literal(2), z.literal(3)]),
2797
+ offset: z.union([z.literal(3), z.literal(4)])
2798
+ }).optional()
2799
+ }),
2800
+ active: buttonVisualAppearanceSchema.extend({ shadow: variantShadowSchema }),
2801
+ disabled: buttonVisualAppearanceSchema.extend({ shadow: variantShadowSchema })
2802
+ });
2803
+ const variantEffectsSchema = z.strictObject({
2804
+ base: z.array(buttonEffectApplicationSchema).optional(),
2805
+ hover: z.array(buttonEffectApplicationSchema).optional(),
2806
+ active: z.array(buttonEffectApplicationSchema).optional(),
2807
+ focus: z.array(buttonEffectApplicationSchema).optional()
2808
+ });
2809
+ /**
2810
+ * Per-variant size overrides schema — every entry is optional.
2811
+ *
2812
+ * For each size key present, the values override the theme's `sizes` config
2813
+ * for that size on this variant. Missing sizes fall through to theme.sizes,
2814
+ * then system defaults.
2815
+ */
2816
+ const variantSizeOverridesSchema = z.object({
2817
+ sm: buttonSizeConfigSchema.optional(),
2818
+ md: buttonSizeConfigSchema.optional(),
2819
+ lg: buttonSizeConfigSchema.optional(),
2820
+ xl: buttonSizeConfigSchema.optional()
2821
+ });
2822
+ /**
2823
+ * Unified variant schema. Every variant participates in the size system; the
2824
+ * optional `sizes` field lets a variant scale differently than the theme
2825
+ * default (e.g. link-style variants declaring zero horizontal padding at
2826
+ * every size).
2827
+ */
2828
+ const buttonVariantSchema = z.strictObject({
2829
+ id: buttonVariantIdSchema,
2830
+ name: z.string().min(1).max(20),
2831
+ enabled: z.boolean(),
2832
+ priority: prioritySchema,
2833
+ visualStates: buttonVisualStatesSchema.optional(),
2834
+ background: buttonBackgroundSchema,
2835
+ /** Tailwind radius token (e.g. `'rounded-md'`). Omit to inherit from `global.cornerStyle`. */
2836
+ borderRadius: z.string().optional(),
2837
+ shadow: variantShadowSchema.optional(),
2838
+ border: buttonBorderSchema.optional(),
2839
+ hoverBackgroundToken: opaqueButtonColourTokenSchema.optional(),
2840
+ contextualHover: contextualButtonHoverSchema.optional(),
2841
+ effects: variantEffectsSchema.optional(),
2842
+ sizes: variantSizeOverridesSchema.optional(),
2843
+ affordance: buttonVariantAffordanceSchema.optional()
2844
+ });
2845
+ const buttonSystemSchema = z.strictObject({
2846
+ global: buttonGlobalSettingsSchema,
2847
+ variants: z.array(buttonVariantSchema).min(1).max(6),
2848
+ sizes: buttonSizesSchema.optional(),
2849
+ surfacePolicy: buttonSurfacePolicySchema.optional(),
2850
+ surfaceContexts: z.record(z.string(), z.strictObject({ primary: opaqueButtonColourTokenSchema })).optional()
2851
+ }).superRefine((system, ctx) => {
2852
+ const seen = /* @__PURE__ */ new Set();
2853
+ system.variants.forEach((variant, index) => {
2854
+ if (seen.has(variant.id)) ctx.addIssue({
2855
+ code: "custom",
2856
+ path: [
2857
+ "variants",
2858
+ index,
2859
+ "id"
2860
+ ],
2861
+ message: `Duplicate button variant ID: ${variant.id}`
2862
+ });
2863
+ seen.add(variant.id);
2864
+ });
2865
+ });
2866
+ //#endregion
2051
2867
  //#region ../theme-core/src/fonts/types.ts
2052
2868
  const fontWeightListSchema = z.array(z.number().int().min(100).max(900));
2053
2869
  const fontLoadingSchema = z.object({
@@ -2431,97 +3247,148 @@ const themeLookMetadataSchema = z.object({
2431
3247
  skinMarks: skinMarksSchema.optional()
2432
3248
  });
2433
3249
  //#endregion
2434
- //#region ../theme-core/src/footer/mode.ts
2435
- const footerModeSchema = z.enum([
2436
- "default",
2437
- "blocks",
2438
- "default+blocks",
2439
- "none"
2440
- ]);
2441
- //#endregion
2442
- //#region ../theme-core/src/lib/media.ts
2443
- const hotspotSchema = z.object({
2444
- x: z.number().min(0).max(1),
2445
- y: z.number().min(0).max(1),
2446
- radius: z.number().optional()
2447
- });
2448
- const rotationSchema = z.union([
2449
- z.literal(0),
2450
- z.literal(90),
2451
- z.literal(180),
2452
- z.literal(270)
2453
- ]);
2454
- const rectSchema = z.tuple([
2455
- z.number(),
2456
- z.number(),
2457
- z.number(),
2458
- z.number()
2459
- ]);
2460
- const aspectCropSchema = z.object({
2461
- aspect: z.preprocess((value) => value == null ? void 0 : value, z.string().optional()),
2462
- rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema.optional()),
2463
- hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema.optional()),
2464
- rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema.optional())
2465
- });
2466
- const transformSchema = z.object({
2467
- aspectCrops: z.preprocess((value) => {
2468
- if (!value || typeof value !== "object" || Array.isArray(value)) return;
2469
- return value;
2470
- }, z.record(z.string(), aspectCropSchema.catch({}))).optional(),
2471
- rect: rectSchema.optional(),
2472
- hotspot: hotspotSchema.optional(),
2473
- rotation: rotationSchema.optional()
2474
- });
2475
- const mediaPosterSchema = z.discriminatedUnion("tag", [z.object({
2476
- tag: z.literal("storage"),
2477
- assetId: z.string().optional(),
2478
- storageBucket: z.string().min(1),
2479
- storagePath: z.string().min(1)
2480
- }), z.object({
2481
- tag: z.literal("external-src"),
2482
- assetId: z.string().optional(),
2483
- src: z.string().url()
2484
- })]);
2485
- const mediaBaseSchema = z.object({
2486
- purpose: z.string().optional(),
2487
- placeholder: z.boolean().default(true).optional(),
2488
- assetId: z.string().optional(),
2489
- identifier: z.string().optional(),
2490
- src: z.string().optional(),
2491
- alt: z.string().optional(),
2492
- filename: z.string().optional(),
2493
- mimeType: z.string().optional(),
2494
- width: z.number().optional(),
2495
- height: z.number().optional(),
2496
- storageBucket: z.string().optional(),
2497
- storagePath: z.string().optional(),
2498
- poster: mediaPosterSchema.optional(),
2499
- transform: transformSchema.optional()
2500
- });
2501
- const mediaIdentifierSchema = z.string().trim().min(1).brand();
2502
- const imageMediaSchema = mediaBaseSchema.extend({ type: z.literal("image") });
2503
- const videoMediaSchema = mediaBaseSchema.extend({ type: z.literal("video") });
2504
- const audioMediaSchema = mediaBaseSchema.extend({ type: z.literal("audio") });
2505
- const documentMediaSchema = mediaBaseSchema.extend({ type: z.literal("document") });
2506
- const spreadsheetMediaSchema = mediaBaseSchema.extend({ type: z.literal("spreadsheet") });
2507
- const archiveMediaSchema = mediaBaseSchema.extend({ type: z.literal("archive") });
2508
- const mediaSchema = z.discriminatedUnion("type", [
2509
- imageMediaSchema,
2510
- videoMediaSchema,
2511
- audioMediaSchema,
2512
- documentMediaSchema,
2513
- spreadsheetMediaSchema,
2514
- archiveMediaSchema
2515
- ]);
2516
- const persistableMediaBaseSchema = mediaBaseSchema.extend({ identifier: mediaIdentifierSchema });
2517
- z.discriminatedUnion("type", [
2518
- persistableMediaBaseSchema.extend({ type: z.literal("image") }),
2519
- persistableMediaBaseSchema.extend({ type: z.literal("video") }),
2520
- persistableMediaBaseSchema.extend({ type: z.literal("audio") }),
2521
- persistableMediaBaseSchema.extend({ type: z.literal("document") }),
2522
- persistableMediaBaseSchema.extend({ type: z.literal("spreadsheet") }),
2523
- persistableMediaBaseSchema.extend({ type: z.literal("archive") })
2524
- ]);
3250
+ //#region ../theme-core/src/palette/colors.ts
3251
+ const HEX_COLOR_REGEX = /^#[0-9a-f]{6}$/;
3252
+ const NORMALIZABLE_HEX_REGEX = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
3253
+ const THEME_PALETTE_COLOR_ORDER = [
3254
+ "primary",
3255
+ "secondary",
3256
+ "accent",
3257
+ "success",
3258
+ "warning",
3259
+ "destructive",
3260
+ "background",
3261
+ "surface",
3262
+ "surfaceAlt",
3263
+ "muted",
3264
+ "text",
3265
+ "primaryForeground",
3266
+ "border"
3267
+ ];
3268
+ const hexColorSchema = z.string().regex(HEX_COLOR_REGEX, "Hex must be #RRGGBB (lowercase)").transform((value) => value);
3269
+ const paletteModeSchema = z.enum(["light", "dark"]);
3270
+ const PALETTE_VALUE_KEY_PREFIX = "palette-value:v1|";
3271
+ z.string().regex(/^[0-9a-f]{64}$/, "Palette hash must be a lowercase SHA-256 value").transform((value) => value);
3272
+ const paletteColorsSchema = z.object({
3273
+ primary: hexColorSchema,
3274
+ primaryForeground: hexColorSchema,
3275
+ secondary: hexColorSchema,
3276
+ accent: hexColorSchema,
3277
+ success: hexColorSchema,
3278
+ warning: hexColorSchema,
3279
+ destructive: hexColorSchema,
3280
+ background: hexColorSchema,
3281
+ surface: hexColorSchema,
3282
+ surfaceAlt: hexColorSchema,
3283
+ muted: hexColorSchema,
3284
+ text: hexColorSchema,
3285
+ border: hexColorSchema
3286
+ }).strict().transform((value) => value);
3287
+ function normalizePaletteHex(value) {
3288
+ if (!NORMALIZABLE_HEX_REGEX.test(value)) return null;
3289
+ const normalized = value.toLowerCase();
3290
+ if (normalized.length === 7) return normalized;
3291
+ const triplet = normalized.slice(1);
3292
+ const red = triplet.charAt(0);
3293
+ const green = triplet.charAt(1);
3294
+ const blue = triplet.charAt(2);
3295
+ return `#${red}${red}${green}${green}${blue}${blue}`;
3296
+ }
3297
+ function paletteColorsFromEntries(entries) {
3298
+ const values = {};
3299
+ for (const entry of entries) {
3300
+ const parsedRole = paletteTokenNameSchema.safeParse(entry.name);
3301
+ if (!parsedRole.success) return {
3302
+ ok: false,
3303
+ error: {
3304
+ kind: "unknown-role",
3305
+ role: entry.name
3306
+ }
3307
+ };
3308
+ const role = parsedRole.data;
3309
+ if (values[role] !== void 0) return {
3310
+ ok: false,
3311
+ error: {
3312
+ kind: "duplicate-role",
3313
+ role
3314
+ }
3315
+ };
3316
+ const hex = normalizePaletteHex(entry.hex);
3317
+ if (!hex) return {
3318
+ ok: false,
3319
+ error: {
3320
+ kind: "invalid-color",
3321
+ role,
3322
+ value: entry.hex
3323
+ }
3324
+ };
3325
+ values[role] = hex;
3326
+ }
3327
+ const missing = PALETTE_TOKEN_NAMES.filter((role) => values[role] === void 0);
3328
+ if (missing.length > 0) return {
3329
+ ok: false,
3330
+ error: {
3331
+ kind: "missing-roles",
3332
+ roles: missing
3333
+ }
3334
+ };
3335
+ return {
3336
+ ok: true,
3337
+ colors: paletteColorsSchema.parse(values)
3338
+ };
3339
+ }
3340
+ function requirePaletteColorsFromEntries(entries) {
3341
+ const result = paletteColorsFromEntries(entries);
3342
+ if (result.ok) return result.colors;
3343
+ throw new Error(`Invalid complete palette: ${result.error.kind}`);
3344
+ }
3345
+ function paletteColorEntries(colors) {
3346
+ return THEME_PALETTE_COLOR_ORDER.map((name) => ({
3347
+ name,
3348
+ hex: colors[name]
3349
+ }));
3350
+ }
3351
+ function paletteColorFingerprint(colors) {
3352
+ return PALETTE_TOKEN_NAMES.map((name) => `${name}:${colors[name]}`).join("|");
3353
+ }
3354
+ function canonicalPaletteHashInput(colors, mode) {
3355
+ return `${mode}|${paletteColorFingerprint(colors)}`;
3356
+ }
3357
+ /**
3358
+ * Stable curated-catalogue identity. Do not reorder roles: the order comes
3359
+ * from PALETTE_TOKEN_NAMES through canonicalPaletteHashInput.
3360
+ */
3361
+ function paletteValueKey(colors, mode) {
3362
+ return `${PALETTE_VALUE_KEY_PREFIX}${canonicalPaletteHashInput(colors, mode)}`;
3363
+ }
3364
+ /** Parses only the exact v1 canonical form emitted by paletteValueKey. */
3365
+ function parsePaletteValueKey(value) {
3366
+ if (typeof value !== "string" || !value.startsWith(PALETTE_VALUE_KEY_PREFIX)) return null;
3367
+ const [rawMode, ...rawRoles] = value.slice(17).split("|");
3368
+ const mode = paletteModeSchema.safeParse(rawMode);
3369
+ if (!mode.success || rawRoles.length !== PALETTE_TOKEN_NAMES.length) return null;
3370
+ const colors = paletteColorsFromEntries(rawRoles.map((roleValue) => {
3371
+ const separator = roleValue.indexOf(":");
3372
+ return separator === -1 ? {
3373
+ name: "",
3374
+ hex: ""
3375
+ } : {
3376
+ name: roleValue.slice(0, separator),
3377
+ hex: roleValue.slice(separator + 1)
3378
+ };
3379
+ }));
3380
+ if (!colors.ok || paletteValueKey(colors.colors, mode.data) !== value) return null;
3381
+ return value;
3382
+ }
3383
+ const paletteValueKeySchema = z.string().transform((value, ctx) => {
3384
+ const parsed = parsePaletteValueKey(value);
3385
+ if (parsed) return parsed;
3386
+ ctx.addIssue({
3387
+ code: "custom",
3388
+ message: "Invalid canonical palette value key"
3389
+ });
3390
+ return z.NEVER;
3391
+ });
2525
3392
  //#endregion
2526
3393
  //#region ../theme-core/src/palette/schema.ts
2527
3394
  const colourHexString = z.string().regex(/^#([0-9A-Fa-f]{3}){1,2}$/);
@@ -2838,6 +3705,494 @@ function validateUniqueDeclaredCardVariantRoles(system, ctx) {
2838
3705
  }
2839
3706
  const cardSystemSchema = z.object({ variants: z.array(cardVariantSchema).min(1).max(3) }).superRefine(validateUniqueDeclaredCardVariantRoles).transform((system) => ({ variants: withInferredRoles(system.variants) }));
2840
3707
  //#endregion
3708
+ //#region ../theme-core/src/surfaces/foregroundContract.ts
3709
+ const SURFACE_FOREGROUND_CSS_VARS = {
3710
+ text: "--rb-surface-text-color",
3711
+ heading: "--rb-surface-heading-color",
3712
+ link: "--rb-surface-link-color",
3713
+ linkHover: "--rb-surface-link-hover-color",
3714
+ supporting: "--rb-surface-supporting-color",
3715
+ muted: "--rb-surface-muted-color",
3716
+ line: "--rb-surface-line-color",
3717
+ mark: "--rb-surface-mark-color"
3718
+ };
3719
+ const DEFAULT_SURFACE_TEXT_COLOR = "rgb(var(--tb-text, 17 24 39))";
3720
+ const DEFAULT_SURFACE_LINK_COLOR = "rgb(var(--tb-primary, var(--tb-text, 17 24 39)))";
3721
+ const DEFAULT_SURFACE_SUPPORTING_COLOR = "rgb(var(--tb-mutedText, 100 116 139))";
3722
+ const DEFAULT_ROLE_FALLBACKS = {
3723
+ text: DEFAULT_SURFACE_TEXT_COLOR,
3724
+ heading: DEFAULT_SURFACE_TEXT_COLOR,
3725
+ link: DEFAULT_SURFACE_LINK_COLOR,
3726
+ linkHover: DEFAULT_SURFACE_LINK_COLOR,
3727
+ supporting: DEFAULT_SURFACE_SUPPORTING_COLOR,
3728
+ muted: DEFAULT_SURFACE_SUPPORTING_COLOR
3729
+ };
3730
+ function requireSurfaceColorValue(role, value) {
3731
+ const normalized = value.trim();
3732
+ if (normalized.length === 0) throw new RangeError(`Surface foreground ${role} must be a non-empty CSS color.`);
3733
+ return normalized;
3734
+ }
3735
+ function completeSurfaceForegrounds(input) {
3736
+ const text = requireSurfaceColorValue("text", input.text);
3737
+ const link = input.link === void 0 ? text : requireSurfaceColorValue("link", input.link);
3738
+ return {
3739
+ text,
3740
+ heading: input.heading === void 0 ? text : requireSurfaceColorValue("heading", input.heading),
3741
+ link,
3742
+ linkHover: input.linkHover === void 0 ? link : requireSurfaceColorValue("linkHover", input.linkHover),
3743
+ muted: input.muted === void 0 ? text : requireSurfaceColorValue("muted", input.muted),
3744
+ supporting: input.supporting === void 0 ? text : requireSurfaceColorValue("supporting", input.supporting)
3745
+ };
3746
+ }
3747
+ function surfaceForegroundValue(role, outsideProviderFallback = DEFAULT_ROLE_FALLBACKS[role]) {
3748
+ const roleVariable = SURFACE_FOREGROUND_CSS_VARS[role];
3749
+ const fallback = requireSurfaceColorValue("fallback", outsideProviderFallback);
3750
+ if (role === "text") return `var(${roleVariable}, ${fallback})`;
3751
+ if (role === "linkHover") return `var(${roleVariable}, ${surfaceForegroundValue("link", fallback)})`;
3752
+ return `var(${roleVariable}, var(${SURFACE_FOREGROUND_CSS_VARS.text}, ${fallback}))`;
3753
+ }
3754
+ function surfaceForegroundValueWithOpacity(role, opacityPercent) {
3755
+ if (!Number.isFinite(opacityPercent) || opacityPercent < 0 || opacityPercent > 100) throw new RangeError("Surface foreground opacity must be between 0 and 100.");
3756
+ return `color-mix(in srgb, ${surfaceForegroundValue(role)} ${opacityPercent}%, transparent)`;
3757
+ }
3758
+ function surfaceForegroundStyle(input) {
3759
+ const foregrounds = completeSurfaceForegrounds(input);
3760
+ return {
3761
+ color: foregrounds.text,
3762
+ [SURFACE_FOREGROUND_CSS_VARS.text]: foregrounds.text,
3763
+ [SURFACE_FOREGROUND_CSS_VARS.heading]: foregrounds.heading,
3764
+ [SURFACE_FOREGROUND_CSS_VARS.link]: foregrounds.link,
3765
+ [SURFACE_FOREGROUND_CSS_VARS.linkHover]: foregrounds.linkHover,
3766
+ [SURFACE_FOREGROUND_CSS_VARS.supporting]: foregrounds.supporting,
3767
+ ...input.muted === void 0 ? {} : { [SURFACE_FOREGROUND_CSS_VARS.muted]: foregrounds.muted },
3768
+ "--rb-surface-link-hover-decoration": hoverDecoration(input)
3769
+ };
3770
+ }
3771
+ function surfaceForegroundDeclarations(input) {
3772
+ return Object.entries(surfaceForegroundStyle(input)).map(([property, value]) => `${property}: ${value};`);
3773
+ }
3774
+ function hoverDecoration(input) {
3775
+ return input.hoverDecoration ?? "underline";
3776
+ }
3777
+ //#endregion
3778
+ //#region ../theme-core/src/palette/utils/colorConversion.ts
3779
+ function hexToRgb(hex) {
3780
+ const h = hex.replace(/^#/, "");
3781
+ const m = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
3782
+ if (m.length !== 6) throw new Error("Bad hex");
3783
+ const int = parseInt(m, 16);
3784
+ return {
3785
+ r: int >> 16 & 255,
3786
+ g: int >> 8 & 255,
3787
+ b: int & 255
3788
+ };
3789
+ }
3790
+ function srgbToLinear(u) {
3791
+ const x = u / 255;
3792
+ return x <= .04045 ? x / 12.92 : Math.pow((x + .055) / 1.055, 2.4);
3793
+ }
3794
+ //#endregion
3795
+ //#region ../theme-core/src/palette/utils/contrast.ts
3796
+ function relativeLuminance(r, g, b) {
3797
+ const R = srgbToLinear(r), G = srgbToLinear(g), B = srgbToLinear(b);
3798
+ return .2126 * R + .7152 * G + .0722 * B;
3799
+ }
3800
+ //#endregion
3801
+ //#region ../theme-core/src/buttons/styles/domain.ts
3802
+ const PUBLIC_BUTTON_ROLES = VARIANT_ROLES;
3803
+ function defineButtonStyleRecipe(recipe) {
3804
+ return recipe;
3805
+ }
3806
+ function mapButtonVisualAppearances(states, transform) {
3807
+ return {
3808
+ base: transform(states.base, "base"),
3809
+ hover: transform(states.hover, "hover"),
3810
+ focus: transform(states.focus, "focus"),
3811
+ active: transform(states.active, "active"),
3812
+ disabled: transform(states.disabled, "disabled")
3813
+ };
3814
+ }
3815
+ function mapButtonRoleAppearances(roles, transform) {
3816
+ const role = (name) => transform(roles[name], name);
3817
+ return {
3818
+ primary: role("primary"),
3819
+ secondary: role("secondary"),
3820
+ outline: role("outline"),
3821
+ ghost: role("ghost"),
3822
+ accent: role("accent")
3823
+ };
3824
+ }
3825
+ function materializeButtonRoles(definitions) {
3826
+ return {
3827
+ primary: materializeCompleteRole("primary", definitions.primary),
3828
+ secondary: materializeCompleteRole("secondary", definitions.secondary),
3829
+ outline: materializeCompleteRole("outline", definitions.outline),
3830
+ ghost: materializeCompleteRole("ghost", definitions.ghost),
3831
+ accent: materializeCompleteRole("accent", definitions.accent)
3832
+ };
3833
+ }
3834
+ function resolveButtonStyleRecipe(recipe, parameters) {
3835
+ const parsedParameters = recipe.parameterSchema.safeParse(parameters);
3836
+ if (!parsedParameters.success) return {
3837
+ kind: "error",
3838
+ error: {
3839
+ kind: "invalid-parameters",
3840
+ styleId: recipe.id,
3841
+ issues: parsedParameters.error.issues.map((issue) => issue.message)
3842
+ }
3843
+ };
3844
+ const definition = recipe.defineSystem(parsedParameters.data);
3845
+ const roles = materializeButtonRoles(definition.roles);
3846
+ const buttonSystem = {
3847
+ global: buttonFamilyProjection(roles.primary),
3848
+ sizes: roles.primary.visualStates?.base.sizes,
3849
+ variants: PUBLIC_BUTTON_ROLES.map((role) => roles[role]),
3850
+ surfacePolicy: definition.surfacePolicy ?? createStandardButtonSurfacePolicy()
3851
+ };
3852
+ const parsedButtonSystem = buttonSystemSchema.safeParse(buttonSystem);
3853
+ if (!parsedButtonSystem.success) return {
3854
+ kind: "error",
3855
+ error: {
3856
+ kind: "invalid-button-system",
3857
+ styleId: recipe.id,
3858
+ issues: parsedButtonSystem.error.issues.map((issue) => issue.message)
3859
+ }
3860
+ };
3861
+ return {
3862
+ kind: "resolved",
3863
+ buttonSystem: parsedButtonSystem.data
3864
+ };
3865
+ }
3866
+ /** Historical family metadata remains a projection; recipes never read it. */
3867
+ function buttonFamilyProjection(primary) {
3868
+ const base = primary.visualStates.base;
3869
+ const type = base.typography;
3870
+ return {
3871
+ cornerStyle: base.borderRadius === "rounded-none" ? "square" : base.borderRadius === "rounded-full" ? "pill" : "rounded",
3872
+ shadow: base.shadow.elevation,
3873
+ fontWeight: type.fontWeight,
3874
+ textTransform: type.textTransform,
3875
+ typography: type.typography,
3876
+ ...type.fontSize === null ? {} : { fontSize: type.fontSize },
3877
+ ...type.letterSpacing === null || type.letterSpacing === "heading" ? {} : { letterSpacing: type.letterSpacing },
3878
+ ...type.italic ? { italic: true } : {},
3879
+ hoverTransform: "none",
3880
+ hoverColor: "none"
3881
+ };
3882
+ }
3883
+ function materializeCompleteRole(role, appearance) {
3884
+ return {
3885
+ visualStates: appearance.states,
3886
+ background: appearance.states.base.background,
3887
+ borderRadius: appearance.states.base.borderRadius,
3888
+ ...appearance.states.base.border === "none" ? {} : { border: appearance.states.base.border },
3889
+ shadow: appearance.states.base.shadow,
3890
+ sizes: appearance.states.base.sizes,
3891
+ effects: Object.fromEntries([
3892
+ "base",
3893
+ "hover",
3894
+ "focus",
3895
+ "active"
3896
+ ].flatMap((state) => {
3897
+ const effects = appearance.states[state].effects;
3898
+ return effects.length === 0 ? [] : [[state, effects]];
3899
+ })),
3900
+ ...appearance.states.hover.contextualHover ? { contextualHover: appearance.states.hover.contextualHover } : {},
3901
+ ...appearance.affordance ? { affordance: appearance.affordance } : {},
3902
+ id: role,
3903
+ name: roleName(role),
3904
+ enabled: true,
3905
+ priority: rolePriority(role)
3906
+ };
3907
+ }
3908
+ function roleName(role) {
3909
+ return role.charAt(0).toUpperCase() + role.slice(1);
3910
+ }
3911
+ function rolePriority(role) {
3912
+ if (role === "primary") return 1;
3913
+ if (role === "secondary") return 2;
3914
+ return 3;
3915
+ }
3916
+ //#endregion
3917
+ //#region ../theme-core/src/utils/tokenOrColor.ts
3918
+ /**
3919
+ * Runtime color-reference fields intentionally accept any string, including
3920
+ * the legacy empty-string "no color" sentinel. Semantic validation needs
3921
+ * palette context and happens in `parseThemeColorReference`.
3922
+ */
3923
+ const tokenOrCssColorValueSchema = z.string();
3924
+ const CSS_COLOR_FUNCTION_PATTERN = /^(?:rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch|color|color-mix|light-dark)\(/i;
3925
+ const CSS_HEX_COLOR_PATTERN = /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
3926
+ const CSS_COLOR_KEYWORDS = /* @__PURE__ */ new Set([
3927
+ "transparent",
3928
+ "currentcolor",
3929
+ "inherit",
3930
+ "initial",
3931
+ "revert",
3932
+ "revert-layer",
3933
+ "unset"
3934
+ ]);
3935
+ const COMMON_CSS_NAMED_COLORS = /* @__PURE__ */ new Set([
3936
+ "black",
3937
+ "blue",
3938
+ "gray",
3939
+ "green",
3940
+ "grey",
3941
+ "orange",
3942
+ "pink",
3943
+ "purple",
3944
+ "red",
3945
+ "white",
3946
+ "yellow"
3947
+ ]);
3948
+ function isCssColorLiteral(value) {
3949
+ const trimmed = value.trim();
3950
+ if (!trimmed) return false;
3951
+ return CSS_HEX_COLOR_PATTERN.test(trimmed) || CSS_COLOR_FUNCTION_PATTERN.test(trimmed) || /^var\(/i.test(trimmed) || CSS_COLOR_KEYWORDS.has(trimmed.toLowerCase());
3952
+ }
3953
+ function parseThemeToken(token) {
3954
+ const trimmed = token.trim();
3955
+ const match = trimmed.match(/^(.*?)-(\d{2,3})$/);
3956
+ if (!match) return {
3957
+ role: trimmed,
3958
+ shade: null
3959
+ };
3960
+ const role = match[1] ?? trimmed;
3961
+ const shade = match[2] ? Number(match[2]) : null;
3962
+ return {
3963
+ role,
3964
+ shade: Number.isFinite(shade) ? shade : null
3965
+ };
3966
+ }
3967
+ function parseContextThemeColorToken(value, context) {
3968
+ const parts = parseColorTokenParts(value);
3969
+ if (parts.kind !== "token") return null;
3970
+ if (!(Boolean(context?.palette?.[value.trim()]) || parts.opacityPercent !== null && Boolean(context?.palette?.[parts.token]))) return null;
3971
+ return value.trim();
3972
+ }
3973
+ function isTokenShapedTypo(value) {
3974
+ if (COMMON_CSS_NAMED_COLORS.has(value.toLowerCase())) return false;
3975
+ if (!/^[a-zA-Z][a-zA-Z0-9]*(?:-[a-zA-Z0-9]+)*(?:\/[^/]+)?$/.test(value)) return false;
3976
+ return !isCssColorLiteral(value);
3977
+ }
3978
+ function warnUnknownThemeColorReference(value) {
3979
+ if (!isTokenShapedTypo(value)) return;
3980
+ console.warn(`[theme-core] Unknown Theme V2 color token "${value}" treated as literal CSS. Use raw:* for deliberate custom CSS values.`);
3981
+ }
3982
+ function parseThemeColorReference(input, context) {
3983
+ const trimmed = input.trim();
3984
+ if (trimmed.startsWith("raw:")) return {
3985
+ kind: "literal-css",
3986
+ value: trimmed.slice(4)
3987
+ };
3988
+ const contextToken = parseContextThemeColorToken(trimmed, context);
3989
+ if (contextToken) return {
3990
+ kind: "palette-context-token",
3991
+ token: contextToken
3992
+ };
3993
+ const knownToken = parseThemeColorToken(trimmed);
3994
+ if (knownToken) return {
3995
+ kind: "theme-token",
3996
+ token: knownToken
3997
+ };
3998
+ warnUnknownThemeColorReference(trimmed);
3999
+ return {
4000
+ kind: "literal-css",
4001
+ value: trimmed
4002
+ };
4003
+ }
4004
+ function resolveThemeColorReferenceValue(input, context) {
4005
+ const reference = parseThemeColorReference(input, context);
4006
+ return reference.kind === "literal-css" ? reference.value : rgbColorValue(reference.token);
4007
+ }
4008
+ function resolveTokenOrCssColorValue(input, context) {
4009
+ return resolveThemeColorReferenceValue(input, context);
4010
+ }
4011
+ function resolveOnColorForThemeToken(token) {
4012
+ if (!parseThemeColorToken(token)) return null;
4013
+ const parts = parseColorTokenParts(token);
4014
+ if (parts.kind !== "token") return null;
4015
+ const { role, shade } = parseThemeToken(parts.token);
4016
+ const normalizedRole = role.trim();
4017
+ if (!normalizedRole) return null;
4018
+ if (!shade) return rgbColorValue(`on${normalizedRole.charAt(0).toUpperCase() + normalizedRole.slice(1)}`);
4019
+ return shade <= 400 ? "#000000" : "#FFFFFF";
4020
+ }
4021
+ //#endregion
4022
+ //#region ../theme-core/src/buttons/buttonColourContract.ts
4023
+ const BUTTON_VISUAL_STATES = [
4024
+ "base",
4025
+ "hover",
4026
+ "focus",
4027
+ "active",
4028
+ "disabled"
4029
+ ];
4030
+ //#endregion
4031
+ //#region ../theme-core/src/buttons/buttonSurfaceContext.ts
4032
+ /**
4033
+ * Break an inherited surface contract when a nested element establishes a
4034
+ * backing whose colours cannot be proven (for example an image or gradient).
4035
+ */
4036
+ function contextualButtonSurfaceResetStyles() {
4037
+ return Object.fromEntries(VARIANT_ROLES.flatMap((role) => Object.entries(resetActionVariables(role))));
4038
+ }
4039
+ function resetActionVariables(role) {
4040
+ const styles = {};
4041
+ for (const state of BUTTON_VISUAL_STATES) for (const property of [
4042
+ "background-color",
4043
+ "background-image",
4044
+ "color"
4045
+ ]) styles[actionVariableName(role, state, property)] = "initial";
4046
+ for (const [state, property] of [
4047
+ ["base", "outline"],
4048
+ ["base", "outline-offset"],
4049
+ ["focus", "outline"],
4050
+ ["focus", "outline-offset"],
4051
+ ["focus", "box-shadow"]
4052
+ ]) styles[actionVariableName(role, state, property)] = "initial";
4053
+ return styles;
4054
+ }
4055
+ function actionVariableName(role, state, property) {
4056
+ return `--rb-action-${role}-${state}-${property}`;
4057
+ }
4058
+ //#endregion
4059
+ //#region ../theme-core/src/surfaces/opaqueSurface.ts
4060
+ /**
4061
+ * The declarations that make an element own its surface: `color`, every
4062
+ * `--rb-surface-*` role and every `--rb-action-*` variable. Card roles and
4063
+ * opaque block panels both publish through this, so a nested surface can never
4064
+ * inherit a band's light text or its band-resolved buttons.
4065
+ */
4066
+ function opaqueSurfaceDeclarations(surface, arrangement = false) {
4067
+ if (surface.kind === "inherit") return inheritedSurfaceDeclarations(arrangement);
4068
+ const foreground = surface.foreground;
4069
+ return [
4070
+ ...surfaceForegroundDeclarations({
4071
+ text: colorValue(foreground.text),
4072
+ heading: colorValue(foreground.heading),
4073
+ link: colorValue(foreground.link),
4074
+ linkHover: colorValue(foreground.linkHover),
4075
+ supporting: colorValue(foreground.supporting),
4076
+ ...arrangement ? { muted: colorValue(foreground.muted) } : {},
4077
+ hoverDecoration: surface.hoverDecoration
4078
+ }),
4079
+ ...arrangement && surface.decorations !== void 0 ? [`${SURFACE_FOREGROUND_CSS_VARS.line}: ${surface.decorations.line};`, `${SURFACE_FOREGROUND_CSS_VARS.mark}: ${surface.decorations.mark};`] : [],
4080
+ ...Object.entries(surface.buttonContext.styles).map(([property, value]) => `${property}: ${value};`)
4081
+ ];
4082
+ }
4083
+ function colorValue(token) {
4084
+ const parsed = parseThemeColorToken(token);
4085
+ return parsed ? rgbColorValue(parsed) : token;
4086
+ }
4087
+ /** Every property a surface publishes, set to `inherit`. */
4088
+ function inheritedSurfaceDeclarations(arrangement) {
4089
+ return [
4090
+ "color",
4091
+ ...Object.entries(SURFACE_FOREGROUND_CSS_VARS).filter(([role]) => arrangement || role !== "line" && role !== "mark" && role !== "muted").map(([, variable]) => variable),
4092
+ "--rb-surface-link-hover-decoration",
4093
+ ...Object.keys(contextualButtonSurfaceResetStyles())
4094
+ ].map((property) => `${property}: inherit;`);
4095
+ }
4096
+ //#endregion
4097
+ //#region ../theme-core/src/utils/colorStyles.ts
4098
+ const COLOR_VAR_PREFIX = "--tb-";
4099
+ function parseToken(source) {
4100
+ const parts = parseColorTokenParts(source);
4101
+ if (parts.kind === "raw") return {
4102
+ token: source,
4103
+ raw: parts.value
4104
+ };
4105
+ if (parts.kind === "invalid") return { token: source };
4106
+ return {
4107
+ token: parts.token,
4108
+ opacityPercent: parts.opacityPercent === null ? void 0 : parts.opacityPercent
4109
+ };
4110
+ }
4111
+ const SURFACE_TEXT_ROLE_BY_TOKEN = {
4112
+ text: "text",
4113
+ heading: "heading",
4114
+ mutedText: "supporting"
4115
+ };
4116
+ function surfaceRoleForTextToken(token) {
4117
+ return Object.prototype.hasOwnProperty.call(SURFACE_TEXT_ROLE_BY_TOKEN, token) ? SURFACE_TEXT_ROLE_BY_TOKEN[token] : null;
4118
+ }
4119
+ /**
4120
+ * Converts a theme color token to a CSS rgb value.
4121
+ * This is the primary function for applying theme colors to CSS properties.
4122
+ *
4123
+ * @param token - Theme color token (semantic, with opacity, or raw)
4124
+ * @returns CSS color value (rgb with optional alpha, or raw CSS value)
4125
+ *
4126
+ * @example
4127
+ * rgbColorValue('primary') // => 'rgb(var(--tb-primary))'
4128
+ * rgbColorValue('surface/95') // => 'rgb(var(--tb-surface) / 0.95)'
4129
+ * rgbColorValue('raw:transparent') // => 'transparent'
4130
+ */
4131
+ function rgbColorValue(token) {
4132
+ const { token: baseToken, opacityPercent, raw } = parseToken(token);
4133
+ if (raw) return raw;
4134
+ const cssVar = `${COLOR_VAR_PREFIX}${baseToken}`;
4135
+ if (opacityPercent === void 0) return `rgb(var(${cssVar}))`;
4136
+ return `rgb(var(${cssVar}) / ${opacityPercent / 100})`;
4137
+ }
4138
+ /**
4139
+ * Creates a backgroundColor style object from a theme token.
4140
+ *
4141
+ * @param token - Theme color token
4142
+ * @returns CSSProperties with backgroundColor
4143
+ */
4144
+ function backgroundColorStyle(token) {
4145
+ return { backgroundColor: rgbColorValue(token) };
4146
+ }
4147
+ /**
4148
+ * Converts a text color token to a CSS color value that follows the enclosing
4149
+ * surface. The semantic text tokens (`text`, `heading`, `mutedText`) resolve
4150
+ * to the surface foreground variables, so text adapts when a section's
4151
+ * background changes; any other token is a fixed theme color.
4152
+ *
4153
+ * @param token - Theme color token
4154
+ * @returns CSS color value
4155
+ */
4156
+ function textColorValue(token) {
4157
+ const parsed = parseToken(token);
4158
+ const surfaceRole = parsed.raw ? null : surfaceRoleForTextToken(parsed.token);
4159
+ if (!surfaceRole) return rgbColorValue(token);
4160
+ return parsed.opacityPercent === void 0 ? surfaceForegroundValue(surfaceRole) : surfaceForegroundValueWithOpacity(surfaceRole, parsed.opacityPercent);
4161
+ }
4162
+ /**
4163
+ * Creates a text color style object from a theme token.
4164
+ *
4165
+ * @param token - Theme color token
4166
+ * @returns CSSProperties with color
4167
+ */
4168
+ function textColorStyle(token) {
4169
+ return { color: textColorValue(token) };
4170
+ }
4171
+ /**
4172
+ * Merges multiple CSSProperties objects into a single object.
4173
+ * Later styles override earlier ones. Undefined values are filtered out.
4174
+ * Returns undefined if the merged result is empty.
4175
+ *
4176
+ * @param styles - Variable number of CSSProperties objects (can be undefined)
4177
+ * @returns Merged CSSProperties object, or undefined if empty
4178
+ *
4179
+ * @example
4180
+ * mergeStyles(
4181
+ * backgroundColorStyle('surface'),
4182
+ * textColorStyle('text'),
4183
+ * borderColorStyle('border')
4184
+ * )
4185
+ * // => { backgroundColor: '...', color: '...', borderColor: '...' }
4186
+ */
4187
+ function mergeStyles(...styles) {
4188
+ const merged = {};
4189
+ for (const style of styles) {
4190
+ if (!style) continue;
4191
+ Object.assign(merged, style);
4192
+ }
4193
+ return Object.keys(merged).length ? merged : void 0;
4194
+ }
4195
+ //#endregion
2841
4196
  //#region ../theme-core/src/accordions/types.ts
2842
4197
  /**
2843
4198
  * Accordion icon styles for expand/collapse indicators
@@ -3789,6 +5144,20 @@ const boxBackgroundSchema = z.discriminatedUnion("type", [
3789
5144
  showVideoOnMobile: z.boolean().nullable().optional()
3790
5145
  })
3791
5146
  ]);
5147
+ z.discriminatedUnion("type", [
5148
+ boxBackgroundSchema.options[0],
5149
+ boxBackgroundSchema.options[1],
5150
+ boxBackgroundSchema.options[2].extend({ image: z.union([
5151
+ imageMediaSchema,
5152
+ externalMediaSchema.extend({ type: z.literal("image") }),
5153
+ assetMediaSchema.extend({ type: z.literal("image") })
5154
+ ]).nullable().optional() }),
5155
+ boxBackgroundSchema.options[3].extend({ image: z.union([
5156
+ videoMediaSchema,
5157
+ externalMediaSchema.extend({ type: z.literal("video") }),
5158
+ assetMediaSchema.extend({ type: z.literal("video") })
5159
+ ]).nullable().optional() })
5160
+ ]);
3792
5161
  function normalizeAuthoringOpacity(value) {
3793
5162
  if (!isRecord$5(value)) return value;
3794
5163
  return {
@@ -4143,20 +5512,15 @@ const headerSchema = z.object({
4143
5512
  const footerVariant = z.enum([
4144
5513
  "simple",
4145
5514
  "columns",
4146
- "split"
4147
- ]);
5515
+ "split",
5516
+ "centred"
5517
+ ]).transform((value) => value === "columns" ? "simple" : value);
4148
5518
  const footerMaxWidth = z.enum(["container", "full"]);
4149
5519
  const footerNavLayoutMode = z.enum([
4150
5520
  "stack",
4151
5521
  "inline",
4152
5522
  "inline-wrap"
4153
5523
  ]);
4154
- const footerNavLayoutAlign = z.enum([
4155
- "start",
4156
- "center",
4157
- "end",
4158
- "space-between"
4159
- ]);
4160
5524
  const footerSpacing = z.enum([
4161
5525
  "none",
4162
5526
  "tight",
@@ -4165,12 +5529,6 @@ const footerSpacing = z.enum([
4165
5529
  "relaxed",
4166
5530
  "spacious"
4167
5531
  ]);
4168
- const footerLogoPlacement = z.enum([
4169
- "left",
4170
- "right",
4171
- "above",
4172
- "below"
4173
- ]);
4174
5532
  const footerLogoSize = z.enum([
4175
5533
  "sm",
4176
5534
  "md",
@@ -4211,17 +5569,8 @@ const footerBottomBarSchema = z.object({
4211
5569
  ]).optional()
4212
5570
  }).optional()
4213
5571
  });
4214
- const footerNavLayoutSchema = z.object({
4215
- layout: footerNavLayoutMode.optional(),
4216
- align: footerNavLayoutAlign.optional(),
4217
- gapX: footerSpacing.optional(),
4218
- gapY: footerSpacing.optional(),
4219
- columns: z.number().int().min(1).max(6).optional()
4220
- });
5572
+ const footerNavLayoutSchema = z.object({ layout: footerNavLayoutMode.optional() });
4221
5573
  const footerLogoSchema = z.object({
4222
- showLogo: z.boolean().default(true),
4223
- showLogoText: z.boolean().optional(),
4224
- placement: footerLogoPlacement.optional(),
4225
5574
  size: footerLogoSize.optional(),
4226
5575
  maxHeight: footerLogoMaxHeight.optional(),
4227
5576
  align: z.enum([
@@ -4231,15 +5580,8 @@ const footerLogoSchema = z.object({
4231
5580
  ]).optional()
4232
5581
  });
4233
5582
  const footerSchema = z.object({
4234
- /**
4235
- * SDK-only footer rendering mode.
4236
- *
4237
- * Historical persisted field; SDK rendering mode now lives in layout.footerMode.
4238
- */
4239
- mode: footerModeSchema.optional(),
4240
5583
  variant: footerVariant,
4241
5584
  maxWidth: footerMaxWidth,
4242
- showLogoText: z.boolean().optional(),
4243
5585
  background: headerBackgroundSchema.default({
4244
5586
  type: "color",
4245
5587
  color: "surface"
@@ -4438,47 +5780,328 @@ function shadeBackgroundEffect(config) {
4438
5780
  900
4439
5781
  ]
4440
5782
  },
4441
- isApplicable: (buttonConfig) => buttonConfig.background.type === "solid",
4442
- generateCSS: ({ themeId, variantId, options, tokens, buttonConfig }) => {
4443
- if (buttonConfig.background.type !== "solid") return "";
4444
- const amount = (options.amount || 100) * config.shadeDirection;
4445
- const baseToken = buttonConfig.background.colorToken ?? "primary-500";
4446
- return `
4447
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
4448
- background-color: ${tokens.getColor(tokens.adjustShade(baseToken, amount))};
4449
- }
4450
- `;
5783
+ isApplicable: (buttonConfig) => buttonConfig.background.type === "solid",
5784
+ generateCSS: ({ themeId, variantId, options, tokens, buttonConfig }) => {
5785
+ if (buttonConfig.background.type !== "solid") return "";
5786
+ const amount = (options.amount || 100) * config.shadeDirection;
5787
+ const baseToken = buttonConfig.background.colorToken ?? "primary-500";
5788
+ return `
5789
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
5790
+ background-color: ${tokens.getColor(tokens.adjustShade(baseToken, amount))};
5791
+ }
5792
+ `;
5793
+ }
5794
+ };
5795
+ }
5796
+ buttonSizeNameSchema.options;
5797
+ //#endregion
5798
+ //#region ../theme-core/src/buttons/styles/recipes/defineStaticButtonStyleRecipe.ts
5799
+ const emptyParametersSchema$1 = z.object({}).strict();
5800
+ function defineStaticButtonStyleRecipe(input) {
5801
+ const system = { roles: {
5802
+ primary: normalizeAppearance(input.system.roles.primary),
5803
+ secondary: normalizeAppearance(input.system.roles.secondary),
5804
+ outline: normalizeAppearance(input.system.roles.outline),
5805
+ ghost: normalizeAppearance(input.system.roles.ghost),
5806
+ accent: normalizeAppearance(input.system.roles.accent)
5807
+ } };
5808
+ return defineButtonStyleRecipe({
5809
+ id: input.id,
5810
+ accessibilityLabel: input.accessibilityLabel,
5811
+ tags: input.tags,
5812
+ parameterSchema: emptyParametersSchema$1,
5813
+ defaultParameters: {},
5814
+ controls: [],
5815
+ defineSystem: () => system
5816
+ });
5817
+ }
5818
+ function normalizeAppearance(appearance) {
5819
+ return {
5820
+ states: buttonVisualStatesSchema.parse(appearance.states),
5821
+ ...appearance.affordance ? { affordance: appearance.affordance } : {}
5822
+ };
5823
+ }
5824
+ //#endregion
5825
+ //#region ../theme-core/src/buttons/styles/recipes/lanternRecipes.ts
5826
+ const flatShadow = {
5827
+ elevation: "none",
5828
+ softness: null,
5829
+ position: "bottom"
5830
+ };
5831
+ const lift$1 = {
5832
+ effectId: "lift",
5833
+ options: { amount: "0.125" }
5834
+ };
5835
+ const tags = {
5836
+ tone: "classic",
5837
+ energy: "calm",
5838
+ motion: "subtle",
5839
+ era: "editorial"
5840
+ };
5841
+ /** Each role supplies complete states, including a flat surface-ink focus ring. */
5842
+ function states(base, hover, offset = 4, width = 2) {
5843
+ return {
5844
+ base,
5845
+ hover,
5846
+ focus: {
5847
+ ...base,
5848
+ shadow: "focus-indicator",
5849
+ indicator: {
5850
+ kind: "surface-ink",
5851
+ width,
5852
+ offset
5853
+ }
5854
+ },
5855
+ active: {
5856
+ ...base,
5857
+ transform: "none"
5858
+ },
5859
+ disabled: {
5860
+ ...base,
5861
+ effects: []
5862
+ }
5863
+ };
5864
+ }
5865
+ const gilt = {
5866
+ text: "treatment",
5867
+ border: "none",
5868
+ borderRadius: "rounded-10px",
5869
+ shadow: flatShadow,
5870
+ sizes: {
5871
+ sm: {
5872
+ padding: "10px 20px",
5873
+ fontSize: "text-base",
5874
+ borderRadius: "rounded-lg"
5875
+ },
5876
+ md: {
5877
+ padding: "18px 36px",
5878
+ fontSize: "text-19px"
5879
+ },
5880
+ lg: {
5881
+ padding: "18px 36px",
5882
+ fontSize: "text-19px"
5883
+ },
5884
+ xl: {
5885
+ padding: "18px 36px",
5886
+ fontSize: "text-19px"
5887
+ }
5888
+ },
5889
+ typography: {
5890
+ fontWeight: 400,
5891
+ typography: "heading",
5892
+ fontSize: "text-19px",
5893
+ letterSpacing: "slight",
5894
+ italic: false,
5895
+ textTransform: "none"
5896
+ },
5897
+ effects: []
5898
+ };
5899
+ const giltPrimary = {
5900
+ ...gilt,
5901
+ background: {
5902
+ type: "gradient",
5903
+ stops: ["accent", "primary"],
5904
+ direction: "to-br",
5905
+ foregroundToken: "onAccent"
5906
+ }
5907
+ };
5908
+ const giltPrimaryHover = {
5909
+ ...giltPrimary,
5910
+ background: {
5911
+ ...giltPrimary.background,
5912
+ stops: ["accent-400", "primary-400"],
5913
+ foregroundToken: "secondary-950"
5914
+ },
5915
+ effects: [lift$1]
5916
+ };
5917
+ const giltSecondary = {
5918
+ ...gilt,
5919
+ background: {
5920
+ type: "solid",
5921
+ colorToken: "text"
5922
+ }
5923
+ };
5924
+ const giltSecondaryHover = {
5925
+ ...giltSecondary,
5926
+ effects: [lift$1],
5927
+ contextualHover: {
5928
+ kind: "shade-shift",
5929
+ seedToken: unsafeAsOpaqueButtonColourToken("text"),
5930
+ fallbackDirection: "lighter"
5931
+ }
5932
+ };
5933
+ const giltPrimaryStates = states(giltPrimary, giltPrimaryHover);
5934
+ const giltSecondaryStates = states(giltSecondary, giltSecondaryHover);
5935
+ const giltSlabRecipe = defineStaticButtonStyleRecipe({
5936
+ id: "gilt-slab",
5937
+ accessibilityLabel: "Gilt slab",
5938
+ tags,
5939
+ system: { roles: {
5940
+ primary: { states: giltPrimaryStates },
5941
+ secondary: { states: giltSecondaryStates },
5942
+ outline: { states: giltSecondaryStates },
5943
+ ghost: { states: giltSecondaryStates },
5944
+ accent: { states: giltPrimaryStates }
5945
+ } }
5946
+ });
5947
+ const hairline = {
5948
+ text: "treatment",
5949
+ borderRadius: "rounded-3px",
5950
+ shadow: flatShadow,
5951
+ sizes: {
5952
+ sm: {
5953
+ padding: "9px 16px",
5954
+ fontSize: "text-xs"
5955
+ },
5956
+ md: {
5957
+ padding: "15px 28px",
5958
+ fontSize: "text-13px"
5959
+ },
5960
+ lg: {
5961
+ padding: "15px 28px",
5962
+ fontSize: "text-13px"
5963
+ },
5964
+ xl: {
5965
+ padding: "15px 28px",
5966
+ fontSize: "text-13px"
5967
+ }
5968
+ },
5969
+ typography: {
5970
+ fontWeight: 700,
5971
+ typography: "body",
5972
+ fontSize: "text-13px",
5973
+ letterSpacing: "wide",
5974
+ italic: false,
5975
+ textTransform: "uppercase"
5976
+ },
5977
+ effects: []
5978
+ };
5979
+ const hairlinePrimary = {
5980
+ ...hairline,
5981
+ background: {
5982
+ type: "solid",
5983
+ colorToken: "primary"
5984
+ },
5985
+ border: {
5986
+ widthClass: "border",
5987
+ boundaryInk: unsafeAsOpaqueButtonColourToken("primary")
5988
+ }
5989
+ };
5990
+ const hairlineOutline = {
5991
+ ...hairline,
5992
+ background: {
5993
+ type: "surface",
5994
+ role: "link"
5995
+ },
5996
+ border: {
5997
+ widthClass: "border",
5998
+ boundaryInk: unsafeAsOpaqueButtonColourToken("primary")
5999
+ }
6000
+ };
6001
+ const hairlineSecondary = {
6002
+ ...hairlineOutline,
6003
+ border: {
6004
+ widthClass: "border",
6005
+ boundaryInk: unsafeAsOpaqueButtonColourToken("accent")
6006
+ }
6007
+ };
6008
+ const hairlineFilled = {
6009
+ ...hairlineSecondary,
6010
+ background: {
6011
+ type: "solid",
6012
+ colorToken: "accent"
6013
+ }
6014
+ };
6015
+ const hairlinePrimaryStates = states(hairlinePrimary, hairlineOutline, 3);
6016
+ const hairlineSecondaryStates = states(hairlineSecondary, hairlineFilled, 3);
6017
+ const hairlineTabRecipe = defineStaticButtonStyleRecipe({
6018
+ id: "hairline-tab",
6019
+ accessibilityLabel: "Hairline tab",
6020
+ tags,
6021
+ system: { roles: {
6022
+ primary: { states: hairlinePrimaryStates },
6023
+ secondary: { states: hairlineSecondaryStates },
6024
+ outline: { states: hairlineSecondaryStates },
6025
+ ghost: { states: hairlineSecondaryStates },
6026
+ accent: { states: states(hairlineFilled, hairlineSecondary, 3) }
6027
+ } }
6028
+ });
6029
+ const marqueeAccent = {
6030
+ text: "treatment",
6031
+ borderRadius: "rounded-none",
6032
+ shadow: flatShadow,
6033
+ sizes: {
6034
+ sm: {
6035
+ padding: "8px 17px",
6036
+ fontSize: "text-15px"
6037
+ },
6038
+ md: {
6039
+ padding: "14px 25px",
6040
+ fontSize: "text-17px"
6041
+ },
6042
+ lg: {
6043
+ padding: "14px 25px",
6044
+ fontSize: "text-17px"
6045
+ },
6046
+ xl: {
6047
+ padding: "14px 25px",
6048
+ fontSize: "text-17px"
4451
6049
  }
4452
- };
4453
- }
4454
- buttonSizeNameSchema.options;
4455
- //#endregion
4456
- //#region ../theme-core/src/buttons/styles/recipes/defineStaticButtonStyleRecipe.ts
4457
- const emptyParametersSchema$1 = z.object({}).strict();
4458
- function defineStaticButtonStyleRecipe(input) {
4459
- const system = { roles: {
4460
- primary: normalizeAppearance(input.system.roles.primary),
4461
- secondary: normalizeAppearance(input.system.roles.secondary),
4462
- outline: normalizeAppearance(input.system.roles.outline),
4463
- ghost: normalizeAppearance(input.system.roles.ghost),
4464
- accent: normalizeAppearance(input.system.roles.accent)
4465
- } };
4466
- return defineButtonStyleRecipe({
4467
- id: input.id,
4468
- accessibilityLabel: input.accessibilityLabel,
4469
- tags: input.tags,
4470
- parameterSchema: emptyParametersSchema$1,
4471
- defaultParameters: {},
4472
- controls: [],
4473
- defineSystem: () => system
4474
- });
4475
- }
4476
- function normalizeAppearance(appearance) {
4477
- return {
4478
- states: buttonVisualStatesSchema.parse(appearance.states),
4479
- ...appearance.affordance ? { affordance: appearance.affordance } : {}
4480
- };
4481
- }
6050
+ },
6051
+ typography: {
6052
+ fontWeight: 800,
6053
+ typography: "body",
6054
+ fontSize: "text-17px",
6055
+ letterSpacing: "loose",
6056
+ italic: false,
6057
+ textTransform: "uppercase"
6058
+ },
6059
+ effects: [],
6060
+ background: {
6061
+ type: "solid",
6062
+ colorToken: "accent"
6063
+ },
6064
+ border: {
6065
+ widthClass: "border-2",
6066
+ boundaryInk: unsafeAsOpaqueButtonColourToken("accent")
6067
+ }
6068
+ };
6069
+ const marqueePrimary = {
6070
+ ...marqueeAccent,
6071
+ background: {
6072
+ type: "solid",
6073
+ colorToken: "primary"
6074
+ },
6075
+ border: {
6076
+ widthClass: "border-2",
6077
+ boundaryInk: unsafeAsOpaqueButtonColourToken("primary")
6078
+ }
6079
+ };
6080
+ const marqueeSecondary = {
6081
+ ...marqueeAccent,
6082
+ background: {
6083
+ type: "solid",
6084
+ colorToken: "text"
6085
+ },
6086
+ border: {
6087
+ widthClass: "border-2",
6088
+ boundaryInk: unsafeAsOpaqueButtonColourToken("text")
6089
+ }
6090
+ };
6091
+ const marqueePrimaryStates = states(marqueeAccent, marqueePrimary, 4, 3);
6092
+ const marqueeSecondaryStates = states(marqueeSecondary, marqueeAccent, 4, 3);
6093
+ const marqueeRecipe = defineStaticButtonStyleRecipe({
6094
+ id: "marquee",
6095
+ accessibilityLabel: "Marquee",
6096
+ tags,
6097
+ system: { roles: {
6098
+ primary: { states: marqueePrimaryStates },
6099
+ secondary: { states: marqueeSecondaryStates },
6100
+ outline: { states: marqueeSecondaryStates },
6101
+ ghost: { states: marqueeSecondaryStates },
6102
+ accent: { states: marqueePrimaryStates }
6103
+ } }
6104
+ });
4482
6105
  //#endregion
4483
6106
  //#region ../theme-core/src/buttons/styles/recipes/fulcrumRecipe.ts
4484
6107
  const fulcrumSizes = {
@@ -5221,7 +6844,10 @@ const BUTTON_STYLE_IDS = [
5221
6844
  "offset-block",
5222
6845
  "ringed-pill",
5223
6846
  "square-outline",
5224
- "fulcrum"
6847
+ "fulcrum",
6848
+ "gilt-slab",
6849
+ "hairline-tab",
6850
+ "marquee"
5225
6851
  ];
5226
6852
  const quietArrowParametersSchema = z.object({ secondaryTreatment: z.enum(["outlined", "solid-accent"]) }).strict();
5227
6853
  const flatInkHoverTreatmentSchema = z.enum([
@@ -5258,7 +6884,10 @@ const buttonStyleSelectionSchema = z.discriminatedUnion("styleId", [
5258
6884
  selectionBranch("offset-block", emptyParametersSchema),
5259
6885
  selectionBranch("ringed-pill", emptyParametersSchema),
5260
6886
  selectionBranch("square-outline", emptyParametersSchema),
5261
- selectionBranch("fulcrum", emptyParametersSchema)
6887
+ selectionBranch("fulcrum", emptyParametersSchema),
6888
+ selectionBranch("gilt-slab", emptyParametersSchema),
6889
+ selectionBranch("hairline-tab", emptyParametersSchema),
6890
+ selectionBranch("marquee", emptyParametersSchema)
5262
6891
  ]);
5263
6892
  //#endregion
5264
6893
  //#region ../theme-core/src/buttons/styles/recipes/quietArrow.ts
@@ -8774,7 +10403,10 @@ const buttonStyleRecipes = [
8774
10403
  offsetBlockRecipe,
8775
10404
  ringedPillRecipe,
8776
10405
  squareOutlineRecipe,
8777
- fulcrumRecipe
10406
+ fulcrumRecipe,
10407
+ giltSlabRecipe,
10408
+ hairlineTabRecipe,
10409
+ marqueeRecipe
8778
10410
  ];
8779
10411
  const recipesById = new Map(buttonStyleRecipes.map((recipe) => [recipe.id, recipe]));
8780
10412
  function findButtonStyleRecipe(id) {
@@ -8790,6 +10422,9 @@ function resolveButtonStyleSelection(selection) {
8790
10422
  case "editorial-link": return resolveButtonStyleRecipe(editorialLinkRecipe, selection.parameters);
8791
10423
  case "pebble": return resolveButtonStyleRecipe(pebbleRecipe, selection.parameters);
8792
10424
  case "ink-stamp": return resolveButtonStyleRecipe(inkStampRecipe, selection.parameters);
10425
+ case "gilt-slab": return resolveButtonStyleRecipe(giltSlabRecipe, selection.parameters);
10426
+ case "hairline-tab": return resolveButtonStyleRecipe(hairlineTabRecipe, selection.parameters);
10427
+ case "marquee": return resolveButtonStyleRecipe(marqueeRecipe, selection.parameters);
8793
10428
  case "fulcrum": return resolveButtonStyleRecipe(fulcrumRecipe, selection.parameters);
8794
10429
  case "flat-ink": return resolveButtonStyleRecipe(flatInkRecipe, selection.parameters);
8795
10430
  case "brushed-wash": return resolveButtonStyleRecipe(brushedWashRecipe, selection.parameters);
@@ -10131,7 +11766,9 @@ const cardListKnobBlocks = [...cardListFamilyBlocks, "block.event-calendar"];
10131
11766
  const lookKnobBlocks = {
10132
11767
  actionStyle: cardListKnobBlocks,
10133
11768
  titleSize: "block.hero",
10134
- imagePosition: "block.hero",
11769
+ imagePosition: ["block.hero", "block.media-text"],
11770
+ imageShape: "block.media-text",
11771
+ aspectRatio: "block.media-text",
10135
11772
  stickerLine: "block.hero",
10136
11773
  smallCaption: "block.hero",
10137
11774
  candleGlow: "block.hero",
@@ -10141,7 +11778,11 @@ const lookKnobBlocks = {
10141
11778
  dates: "block.offerings-preview",
10142
11779
  showCapacity: "block.event-calendar",
10143
11780
  quoteCount: "block.testimonials",
10144
- archFrame: "block.testimonials",
11781
+ archFrame: [
11782
+ "block.testimonials",
11783
+ "block.newsletter-signup",
11784
+ "block.form"
11785
+ ],
10145
11786
  tilt: "block.testimonials"
10146
11787
  };
10147
11788
  function isArrangementAppearancePreset(preset) {
@@ -10168,13 +11809,25 @@ function cardListKnobDefaults(block, arrangement, knobs, defaults) {
10168
11809
  }
10169
11810
  };
10170
11811
  }
11812
+ const arrangementLookTargets = {
11813
+ hero: "hero",
11814
+ "feature-cards": "feature-cards",
11815
+ "event-calendar": "events",
11816
+ testimonials: "testimonials",
11817
+ "event-details": "events",
11818
+ "media-text": "media-text",
11819
+ "image-gallery": "image-gallery",
11820
+ "newsletter-signup": "newsletter",
11821
+ form: "contact-form",
11822
+ "body-text": "body-text"
11823
+ };
10171
11824
  function defineArrangementLook(id, block, name, arrangement, knobs, input = {}) {
10172
11825
  const mode = block === "event-calendar" ? "list" : null;
10173
11826
  return {
10174
11827
  id: asAppearancePresetId(id),
10175
11828
  blockKinds: [`block.${block}`],
10176
11829
  label: name,
10177
- target: block === "event-calendar" || block === "event-details" ? "events" : block === "hero" ? "hero" : block === "testimonials" ? "testimonials" : "feature-cards",
11830
+ target: arrangementLookTargets[block],
10178
11831
  structure: {
10179
11832
  kind: "arrangement",
10180
11833
  byMode: { [mode ?? "default"]: arrangement },
@@ -10994,6 +12647,15 @@ const appearancePresets = [
10994
12647
  eyebrowTreatment: "accent"
10995
12648
  }
10996
12649
  }),
12650
+ defineArrangementLook("body-text-reading-column", "body-text", "Reading column", "prose", []),
12651
+ defineArrangementLook("form-beside-introduction-arched-panel", "form", "Introduction beside an arched form", "two-column", [], { slotRoles: { panel: "card" } }),
12652
+ defineArrangementLook("newsletter-signup-in-arch", "newsletter-signup", "Signup in an arch", "arch", []),
12653
+ defineArrangementLook("image-gallery-square-tiles", "image-gallery", "Square tiles", "tiles", []),
12654
+ defineArrangementLook("image-gallery-arched-captions", "image-gallery", "Arched photos with captions", "tiles", [], { styleFallback: [id$1("image-gallery-square-tiles")] }),
12655
+ defineArrangementLook("media-text-circle-beside-text", "media-text", "Circle beside the text", "circle-beside", ["imagePosition"], { forcedKnobs: {
12656
+ imageShape: "circle",
12657
+ aspectRatio: "1/1"
12658
+ } }),
10997
12659
  defineArrangementLook("hero-photo-beside-text", "hero", "Photo beside the text", "split", heroKnobs, { slotRoles: { sticker: "highlight" } }),
10998
12660
  defineArrangementLook("hero-headline-row", "hero", "Big headline, then text and photo", "headline-row", heroKnobs, {
10999
12661
  slotRoles: { sticker: "highlight" },
@@ -11557,6 +13219,41 @@ function requireThemeColorToken$1(value) {
11557
13219
  return token;
11558
13220
  }
11559
13221
  //#endregion
13222
+ //#region ../theme-core/src/site-styles/siteChromeBackgrounds.ts
13223
+ const siteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceColorTokenNames);
13224
+ const quickSiteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceQuickColorTokenNames);
13225
+ siteChromeBackgroundColorTokens.filter((token) => !quickSiteChromeBackgroundColorTokens.includes(token));
13226
+ function parseSiteChromeBackgroundColorToken(value) {
13227
+ const token = parseBackgroundAppearanceColorToken(value);
13228
+ return token ? token : null;
13229
+ }
13230
+ function toSiteChromeBackgroundColorTokens(tokenNames) {
13231
+ return tokenNames.flatMap((name) => {
13232
+ const token = parseSiteChromeBackgroundColorToken(name);
13233
+ return token ? [token] : [];
13234
+ });
13235
+ }
13236
+ const backgroundColorTokenSchema = z.unknown().transform((value, ctx) => {
13237
+ const token = parseSiteChromeBackgroundColorToken(value);
13238
+ if (token === null) {
13239
+ ctx.addIssue({
13240
+ code: "custom",
13241
+ message: "Unknown site chrome background colour token"
13242
+ });
13243
+ return z.NEVER;
13244
+ }
13245
+ return token;
13246
+ });
13247
+ const siteChromeBackgroundOverrideSchema = z.discriminatedUnion("kind", [z.object({ kind: z.literal("default") }).strict(), z.object({
13248
+ kind: z.literal("color"),
13249
+ token: backgroundColorTokenSchema
13250
+ }).strict()]);
13251
+ z.object({
13252
+ background: siteChromeBackgroundOverrideSchema,
13253
+ navigationLayout: z.enum(["inline-wrap", "stack"])
13254
+ }).strict();
13255
+ z.object({ background: siteChromeBackgroundOverrideSchema }).strict();
13256
+ //#endregion
11560
13257
  //#region ../theme-core/src/site-styles/compilationPlan.ts
11561
13258
  const defaultHeaderBrandPreferences = {
11562
13259
  brandDisplay: "auto",
@@ -11717,6 +13414,9 @@ function fallbackEndsAtOffer(entry, mode, style, catalogue, visited) {
11717
13414
  appearancePresets.filter(isArrangementAppearancePreset);
11718
13415
  /** Closed structural hooks shared by block arrangements and bounded skins. */
11719
13416
  const arrangementSlotNames = [
13417
+ "contact",
13418
+ "social",
13419
+ "base",
11720
13420
  "section",
11721
13421
  "stack",
11722
13422
  "inline",
@@ -11803,6 +13503,55 @@ function validateOfferKnobs(style, catalogue) {
11803
13503
  });
11804
13504
  }
11805
13505
  //#endregion
13506
+ //#region ../theme-core/src/site-styles/footerLookDefaults.ts
13507
+ const defaultFooterLookRecipes = {
13508
+ "footer-centred-name": {
13509
+ arrangement: "centred",
13510
+ ground: {
13511
+ kind: "token",
13512
+ token: "surface"
13513
+ },
13514
+ nav: {
13515
+ weight: "regular",
13516
+ colorToken: "text",
13517
+ hoverColorToken: "primary",
13518
+ typography: "body"
13519
+ },
13520
+ legal: {
13521
+ kind: "separate",
13522
+ bar: null
13523
+ },
13524
+ brandAlign: "center"
13525
+ },
13526
+ "footer-links-row": {
13527
+ arrangement: "simple",
13528
+ ground: {
13529
+ kind: "token",
13530
+ token: "surface"
13531
+ },
13532
+ nav: {
13533
+ weight: "regular",
13534
+ colorToken: "text",
13535
+ hoverColorToken: "primary",
13536
+ typography: "body"
13537
+ },
13538
+ legal: { kind: "integrated" },
13539
+ brandAlign: "start"
13540
+ }
13541
+ };
13542
+ /** A whole authored recipe replaces the default; facets are never deep-merged. */
13543
+ function resolveFooterLookRecipe(style, id) {
13544
+ return style?.footerLookRecipes?.[id] ?? defaultFooterLookRecipes[id];
13545
+ }
13546
+ //#endregion
13547
+ //#region ../theme-core/src/site-styles/footerLookRecipe.ts
13548
+ /** Reject undeclared references when the curated catalogue is loaded, before rendering. */
13549
+ function validateFooterRecipeSurfaces(style, recipe) {
13550
+ [recipe.ground, ...recipe.legal.kind === "separate" && recipe.legal.bar ? [recipe.legal.bar.background] : []].forEach((ground) => {
13551
+ if (ground.kind === "style-surface" && (style.looks.kind !== "offers" || !style.looks.surfaces[ground.surface])) throw new Error(`Undeclared footer surface: ${ground.surface}`);
13552
+ });
13553
+ }
13554
+ //#endregion
11806
13555
  //#region ../theme-core/src/site-styles/styleTags.ts
11807
13556
  /**
11808
13557
  * Descriptive style-axis metadata for button personalities and palette
@@ -14709,52 +16458,14 @@ defineLookOptionGroup({
14709
16458
  function asFooterLookId(value) {
14710
16459
  return value;
14711
16460
  }
14712
- function quietFooterLinks(theme) {
14713
- return {
14714
- ...theme.footer,
14715
- navStyle: "minimal",
14716
- navWeight: "regular",
14717
- navColor: "text",
14718
- navLinkStyle: {
14719
- typography: "body",
14720
- fontWeight: "regular",
14721
- textTransform: "none",
14722
- italic: false,
14723
- colorToken: "text",
14724
- hoverColorToken: "primary",
14725
- padding: "none",
14726
- borderRadius: "none"
14727
- }
14728
- };
14729
- }
14730
- function emphasizedFooterLinks(theme) {
14731
- return {
14732
- ...theme.footer,
14733
- navStyle: "minimal",
14734
- navWeight: "medium",
14735
- navColor: "text",
14736
- navLinkStyle: {
14737
- typography: "body",
14738
- fontWeight: "medium",
14739
- textTransform: "none",
14740
- italic: false,
14741
- colorToken: "text",
14742
- hoverColorToken: "primary",
14743
- padding: "none",
14744
- borderRadius: "none"
14745
- }
14746
- };
14747
- }
14748
16461
  const footerLookCatalog = defineExactCatalog()([{
14749
- id: asFooterLookId("footer-links-quiet"),
14750
- label: "Quiet links",
14751
- description: "Regular-weight footer navigation with a restrained hover.",
14752
- compile: quietFooterLinks
16462
+ id: asFooterLookId("footer-links-row"),
16463
+ label: "Links in a row",
16464
+ description: "Your links in a row, with the other footer sections in columns beside them."
14753
16465
  }, {
14754
- id: asFooterLookId("footer-links-emphasized"),
14755
- label: "Emphasized links",
14756
- description: "Medium-weight footer navigation with a clearer emphasis.",
14757
- compile: emphasizedFooterLinks
16466
+ id: asFooterLookId("footer-centred-name"),
16467
+ label: "Centred name, links beneath",
16468
+ description: "Your site name centred, with your links, contact details and social links beneath it."
14758
16469
  }]);
14759
16470
  new Map(footerLookCatalog.map((look) => [look.id, look]));
14760
16471
  //#endregion
@@ -16138,6 +17849,7 @@ function defineCuratedSiteStyle(input) {
16138
17849
  recommendedAppearancePresetIds
16139
17850
  },
16140
17851
  headerCuration: headerCurationBySiteStyle[input.id],
17852
+ footerLookRecipes: input.footerLookRecipes,
16141
17853
  recommendedFooterLookIds: (input.recommendedFooterLookIds ?? []).map(asFooterLookId),
16142
17854
  buttonStyleChoices: input.buttonStyleChoices,
16143
17855
  paletteRecommendations: input.paletteRecommendations,
@@ -16623,7 +18335,11 @@ const lanternLooks = {
16623
18335
  margin: "40px"
16624
18336
  },
16625
18337
  fontLoading: {
16626
- extraBodyFontWeights: [500, 700],
18338
+ extraBodyFontWeights: [
18339
+ 500,
18340
+ 700,
18341
+ 800
18342
+ ],
16627
18343
  italicBodyFontWeights: [400]
16628
18344
  },
16629
18345
  surfaces: {
@@ -16673,6 +18389,38 @@ const lanternLooks = {
16673
18389
  ]
16674
18390
  },
16675
18391
  offers: [
18392
+ {
18393
+ id: id("body-text-reading-column"),
18394
+ treatment: "reading-column",
18395
+ roleMap: lanternRoles
18396
+ },
18397
+ {
18398
+ id: id("form-beside-introduction-arched-panel"),
18399
+ treatment: "arched-panel",
18400
+ addKnobs: ["archFrame"],
18401
+ roleMap: lanternRoles
18402
+ },
18403
+ {
18404
+ id: id("newsletter-signup-in-arch"),
18405
+ treatment: "signup-arch",
18406
+ addKnobs: ["archFrame"],
18407
+ roleMap: lanternRoles
18408
+ },
18409
+ {
18410
+ id: id("image-gallery-square-tiles"),
18411
+ treatment: "square-tiles",
18412
+ roleMap: lanternRoles
18413
+ },
18414
+ {
18415
+ id: id("image-gallery-arched-captions"),
18416
+ treatment: "arched-captions",
18417
+ roleMap: lanternRoles
18418
+ },
18419
+ {
18420
+ id: id("media-text-circle-beside-text"),
18421
+ treatment: "circle-beside",
18422
+ roleMap: lanternRoles
18423
+ },
16676
18424
  {
16677
18425
  id: id("event-details-panel"),
16678
18426
  treatment: "quiet",
@@ -17111,7 +18859,7 @@ const curatedSiteStyles = [
17111
18859
  "faq-contained-help",
17112
18860
  "contact-form-panel"
17113
18861
  ],
17114
- recommendedFooterLookIds: ["footer-links-quiet"],
18862
+ recommendedFooterLookIds: ["footer-links-row"],
17115
18863
  buttonStyleChoices: [
17116
18864
  buttonChoice("soft-pill"),
17117
18865
  buttonChoice("pebble"),
@@ -17230,7 +18978,7 @@ const curatedSiteStyles = [
17230
18978
  "testimonials-non-carded",
17231
18979
  "contact-form-panel"
17232
18980
  ],
17233
- recommendedFooterLookIds: ["footer-links-quiet", "footer-links-emphasized"],
18981
+ recommendedFooterLookIds: ["footer-links-row"],
17234
18982
  buttonStyleChoices: [
17235
18983
  buttonChoice("earth-pill"),
17236
18984
  buttonChoice("soft-pill"),
@@ -17285,7 +19033,41 @@ const curatedSiteStyles = [
17285
19033
  "testimonials-brand-statement-cards",
17286
19034
  "contact-form-panel"
17287
19035
  ],
17288
- recommendedFooterLookIds: ["footer-links-emphasized", "footer-links-quiet"],
19036
+ footerLookRecipes: { "footer-links-row": {
19037
+ arrangement: "split",
19038
+ ground: {
19039
+ kind: "token",
19040
+ token: "primary-800"
19041
+ },
19042
+ nav: {
19043
+ weight: "medium",
19044
+ colorToken: "primaryForeground",
19045
+ hoverColorToken: "secondary",
19046
+ typography: "body"
19047
+ },
19048
+ legal: {
19049
+ kind: "separate",
19050
+ bar: {
19051
+ fullBleed: true,
19052
+ background: {
19053
+ kind: "token",
19054
+ token: "primary-900"
19055
+ },
19056
+ textColor: "primaryForeground",
19057
+ textAlign: "center",
19058
+ paddingY: "compact",
19059
+ paddingX: "default",
19060
+ borderTop: { width: "none" }
19061
+ },
19062
+ linkStyle: {
19063
+ colorToken: "secondary",
19064
+ decorationColorToken: "secondary"
19065
+ }
19066
+ },
19067
+ brandAlign: "start",
19068
+ brandLogoSize: "sm"
19069
+ } },
19070
+ recommendedFooterLookIds: ["footer-links-row"],
17289
19071
  buttonStyleChoices: [
17290
19072
  buttonChoice("showtime-pill"),
17291
19073
  buttonChoice("confident-chip"),
@@ -17356,7 +19138,7 @@ const curatedSiteStyles = [
17356
19138
  "testimonials-statement-cards",
17357
19139
  "contact-form-panel"
17358
19140
  ],
17359
- recommendedFooterLookIds: ["footer-links-emphasized", "footer-links-quiet"],
19141
+ recommendedFooterLookIds: ["footer-links-row"],
17360
19142
  buttonStyleChoices: [
17361
19143
  buttonChoice("ornate-ritual"),
17362
19144
  buttonChoice("joy-stamp"),
@@ -17403,7 +19185,22 @@ const curatedSiteStyles = [
17403
19185
  } }
17404
19186
  },
17405
19187
  recommendedAppearancePresetIds: ["feature-cards-bold-colors", "testimonials-statement-cards"],
17406
- recommendedFooterLookIds: ["footer-links-emphasized", "footer-links-quiet"],
19188
+ footerLookRecipes: { "footer-links-row": {
19189
+ arrangement: "simple",
19190
+ ground: {
19191
+ kind: "token",
19192
+ token: "surface"
19193
+ },
19194
+ nav: {
19195
+ weight: "medium",
19196
+ colorToken: "text",
19197
+ hoverColorToken: "primary",
19198
+ typography: "body"
19199
+ },
19200
+ legal: { kind: "integrated" },
19201
+ brandAlign: "start"
19202
+ } },
19203
+ recommendedFooterLookIds: ["footer-links-row"],
17407
19204
  buttonStyleChoices: [
17408
19205
  buttonChoice("joy-stamp"),
17409
19206
  buttonChoice("ink-stamp"),
@@ -17455,7 +19252,7 @@ const curatedSiteStyles = [
17455
19252
  },
17456
19253
  testimonialQuote: serifDisplayQuote
17457
19254
  },
17458
- recommendedFooterLookIds: ["footer-links-quiet"],
19255
+ recommendedFooterLookIds: ["footer-links-row"],
17459
19256
  buttonStyleChoices: [
17460
19257
  buttonChoice("fulcrum"),
17461
19258
  buttonChoice("editorial-link"),
@@ -17532,7 +19329,7 @@ const curatedSiteStyles = [
17532
19329
  "faq-base-accordion",
17533
19330
  "booking-brand-band"
17534
19331
  ],
17535
- recommendedFooterLookIds: ["footer-links-quiet"],
19332
+ recommendedFooterLookIds: ["footer-links-row"],
17536
19333
  buttonStyleChoices: [
17537
19334
  buttonChoice("quiet-arrow", void 0, { secondaryTreatment: "solid-accent" }),
17538
19335
  buttonChoice("flat-ink"),
@@ -17570,7 +19367,22 @@ const curatedSiteStyles = [
17570
19367
  accordions: boldBorderedAccordionSystem,
17571
19368
  testimonialQuote: accentGlyphQuote
17572
19369
  },
17573
- recommendedFooterLookIds: ["footer-links-emphasized"],
19370
+ footerLookRecipes: { "footer-links-row": {
19371
+ arrangement: "simple",
19372
+ ground: {
19373
+ kind: "token",
19374
+ token: "surface"
19375
+ },
19376
+ nav: {
19377
+ weight: "medium",
19378
+ colorToken: "text",
19379
+ hoverColorToken: "primary",
19380
+ typography: "body"
19381
+ },
19382
+ legal: { kind: "integrated" },
19383
+ brandAlign: "start"
19384
+ } },
19385
+ recommendedFooterLookIds: ["footer-links-row"],
17574
19386
  buttonStyleChoices: [
17575
19387
  buttonChoice("offset-block"),
17576
19388
  buttonChoice("ink-stamp"),
@@ -17609,8 +19421,29 @@ const curatedSiteStyles = [
17609
19421
  accordions: warmInsetAccordionSystem,
17610
19422
  testimonialQuote: serifDisplayQuote
17611
19423
  },
17612
- recommendedFooterLookIds: ["footer-links-quiet"],
19424
+ footerLookRecipes: { "footer-centred-name": {
19425
+ arrangement: "centred",
19426
+ ground: {
19427
+ kind: "style-surface",
19428
+ surface: "deep"
19429
+ },
19430
+ nav: {
19431
+ weight: "regular",
19432
+ colorToken: "text",
19433
+ hoverColorToken: "primary",
19434
+ typography: "heading"
19435
+ },
19436
+ legal: {
19437
+ kind: "separate",
19438
+ bar: null
19439
+ },
19440
+ brandAlign: "center"
19441
+ } },
19442
+ recommendedFooterLookIds: ["footer-centred-name", "footer-links-row"],
17613
19443
  buttonStyleChoices: [
19444
+ buttonChoice("gilt-slab"),
19445
+ buttonChoice("hairline-tab"),
19446
+ buttonChoice("marquee"),
17614
19447
  buttonChoice("ringed-pill"),
17615
19448
  buttonChoice("earth-pill"),
17616
19449
  buttonChoice("editorial-link")
@@ -17645,7 +19478,7 @@ const curatedSiteStyles = [
17645
19478
  accordions: editorialDividedAccordionSystem,
17646
19479
  testimonialQuote: serifDisplayQuote
17647
19480
  },
17648
- recommendedFooterLookIds: ["footer-links-quiet"],
19481
+ recommendedFooterLookIds: ["footer-links-row"],
17649
19482
  buttonStyleChoices: [
17650
19483
  buttonChoice("flat-ink", void 0, { corners: "square" }),
17651
19484
  buttonChoice("editorial-link"),
@@ -17673,6 +19506,7 @@ function curatedStyleTemplate(input) {
17673
19506
  }
17674
19507
  curatedSiteStyles.forEach((style) => {
17675
19508
  if (style.looks.kind === "offers") validateLookFallbacks(style.looks);
19509
+ (/* @__PURE__ */ new Set([...Object.values(style.footerLookRecipes ?? {}), ...style.recommendedFooterLookIds.map((id) => resolveFooterLookRecipe(style, id))])).forEach((recipe) => validateFooterRecipeSurfaces(style, recipe));
17676
19510
  });
17677
19511
  //#endregion
17678
19512
  //#region ../theme-core/src/site-styles/effectiveArrangement.ts
@@ -17748,21 +19582,6 @@ const blockDesignFallback = {
17748
19582
  };
17749
19583
  blockDesignFallback.sectionSurface, blockDesignFallback.contentFrame, blockDesignFallback.sectionHeight, blockDesignFallback.heroLegibility, blockDesignFallback.imageSurfaceTreatment, blockDesignFallback.imageSurfaceMotion, blockDesignFallback.tileTreatment, blockDesignFallback.eventListTreatment, blockDesignFallback.eyebrowTreatment, blockDesignFallback.accordionIconTreatment, blockDesignFallback.composition;
17750
19584
  //#endregion
17751
- //#region ../theme-core/src/site-styles/siteChromeBackgrounds.ts
17752
- const siteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceColorTokenNames);
17753
- const quickSiteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceQuickColorTokenNames);
17754
- siteChromeBackgroundColorTokens.filter((token) => !quickSiteChromeBackgroundColorTokens.includes(token));
17755
- function parseSiteChromeBackgroundColorToken(value) {
17756
- const token = parseBackgroundAppearanceColorToken(value);
17757
- return token ? token : null;
17758
- }
17759
- function toSiteChromeBackgroundColorTokens(tokenNames) {
17760
- return tokenNames.flatMap((name) => {
17761
- const token = parseSiteChromeBackgroundColorToken(name);
17762
- return token ? [token] : [];
17763
- });
17764
- }
17765
- //#endregion
17766
19585
  //#region ../theme-core/src/site-styles/siteChromeNavPreferences.ts
17767
19586
  const headerNavTypographyPreferenceValues = [
17768
19587
  "inherit",
@@ -17878,21 +19697,6 @@ z.object({
17878
19697
  }).strict();
17879
19698
  //#endregion
17880
19699
  //#region ../theme-core/src/site-styles/headerPreferencesPersistence.ts
17881
- const backgroundColorTokenSchema = z.unknown().transform((value, ctx) => {
17882
- const token = parseSiteChromeBackgroundColorToken(value);
17883
- if (token === null) {
17884
- ctx.addIssue({
17885
- code: "custom",
17886
- message: "Unknown site chrome background colour token"
17887
- });
17888
- return z.NEVER;
17889
- }
17890
- return token;
17891
- });
17892
- const backgroundOverrideSchema = z.discriminatedUnion("kind", [z.object({ kind: z.literal("default") }).strict(), z.object({
17893
- kind: z.literal("color"),
17894
- token: backgroundColorTokenSchema
17895
- }).strict()]);
17896
19700
  const logoTextIntentSchema = z.object({
17897
19701
  mobileMaxWidth: z.enum([
17898
19702
  "xs",
@@ -17918,7 +19722,7 @@ const headerPreferencesShape = {
17918
19722
  navFontRole: z.enum(headerNavTypographyPreferenceValues),
17919
19723
  navTextSize: z.enum(headerNavFontSizePreferenceValues),
17920
19724
  interactionPalette: z.union([z.literal("recommended"), z.enum(headerInteractionPaletteValues)]),
17921
- background: backgroundOverrideSchema,
19725
+ background: siteChromeBackgroundOverrideSchema,
17922
19726
  structure: structureSchema
17923
19727
  };
17924
19728
  z.object(headerPreferencesShape).strict();
@@ -18149,6 +19953,10 @@ function listLookSlot(presentation, slot) {
18149
19953
  ...surface === void 0 ? { "data-surface": "section" } : resolvedItemSurfaceProps(surface, slot)
18150
19954
  };
18151
19955
  }
19956
+ /** Control kind is semantic; legacy markup receives no extra attributes. */
19957
+ function listLookControl(presentation, kind) {
19958
+ return presentation.lookSlots === void 0 ? {} : { "data-control": kind };
19959
+ }
18152
19960
  function resolvedSurfaceBackground(surface, token) {
18153
19961
  const color = token.startsWith("#") ? token : `rgb(var(--tb-${token}))`;
18154
19962
  const base = surface.kind === "owned" ? surface.tintBase : void 0;
@@ -18488,7 +20296,7 @@ const publicEventBaseSchema = z.object({
18488
20296
  content: z.object({ body: RichTextDocSchema.nullable().optional() }).optional(),
18489
20297
  presentation: z.object({
18490
20298
  summary: z.string().nullable().optional(),
18491
- image: mediaSchema.nullable().optional()
20299
+ image: runtimeMediaSchema.nullable().optional()
18492
20300
  }).optional(),
18493
20301
  slug: z.string(),
18494
20302
  path: z.string().nullable(),
@@ -19172,19 +20980,14 @@ function groupItemsByDate(items, accessors) {
19172
20980
  *
19173
20981
  * Sites don't store a locale, and every public word around a date is English,
19174
20982
  * so the only open question is which English conventions to follow: day or
19175
- * month first, and a 24 or 12-hour clock. The site's time zone is the one
20983
+ * month first. The site's time zone is the one
19176
20984
  * fact every site carries about where it is. It is the site's, never an
19177
20985
  * event's: a venue left at UTC must not turn a UK site's dates American.
19178
20986
  * Anywhere this can't place (UTC, the Americas, Asia) keeps US English, which
19179
20987
  * is what these helpers wrote before sites were placed at all.
19180
20988
  */
19181
20989
  function eventDateLocale(siteTimeZone) {
19182
- if (!siteTimeZone) return "en-US";
19183
- if (siteTimeZone === "Europe/Dublin") return "en-IE";
19184
- if (siteTimeZone.startsWith("Europe/")) return "en-GB";
19185
- if (siteTimeZone.startsWith("Australia/")) return "en-AU";
19186
- if (siteTimeZone === "Pacific/Auckland" || siteTimeZone === "Pacific/Chatham") return "en-NZ";
19187
- return "en-US";
20990
+ return inferSiteDateLocale(siteTimeZone);
19188
20991
  }
19189
20992
  /**
19190
20993
  * Formatting options for an event's dates: the times in the event's own zone,
@@ -25956,6 +27759,7 @@ const formFieldGroupSchema = z.discriminatedUnion("type", [z.object({
25956
27759
  fields: z.tuple([formFieldSchema, formFieldSchema])
25957
27760
  })]);
25958
27761
  const formSourceSchema = z.object({
27762
+ lookSlots: lookListPresentationSchemaShape.lookSlots,
25959
27763
  value: formRecordSchema.optional(),
25960
27764
  siteId: z.string().optional(),
25961
27765
  apiBaseUrl: z.string().optional(),
@@ -25965,6 +27769,7 @@ const formSourceSchema = z.object({
25965
27769
  spamProtectionEnabled: z.boolean().optional()
25966
27770
  });
25967
27771
  const formDisplaySchema = z.object({
27772
+ lookSlots: lookListPresentationSchemaShape.lookSlots,
25968
27773
  kind: z.literal("form"),
25969
27774
  state: z.enum(["missing", "ready"]),
25970
27775
  className: z.string().nullable(),
@@ -25986,17 +27791,30 @@ const formIslandMetaCodec = createZodCodec(z.object({
25986
27791
  const formIslandMetaKeys = defineInteractiveIslandMetaKeys("siteId", "apiBaseUrl");
25987
27792
  function buildFormDisplay(source) {
25988
27793
  const form = source.value ?? null;
25989
- const fields = form?.schemaJson?.fields;
25990
- const groups = Array.isArray(fields) ? groupFormFields(fields) : [];
27794
+ const fields = formDisplayFields(form);
25991
27795
  return {
25992
27796
  kind: "form",
25993
- state: form ? "ready" : "missing",
27797
+ ...source.lookSlots ? { lookSlots: source.lookSlots } : {},
27798
+ state: fields.state,
25994
27799
  className: source.className ?? null,
25995
- formId: form?.id ?? null,
27800
+ formId: fields.formId,
25996
27801
  submitLabel: source.submitLabel?.trim() || "Submit",
25997
27802
  successMessage: source.successMessage ?? null,
25998
27803
  form,
25999
- groups
27804
+ groups: fields.groups
27805
+ };
27806
+ }
27807
+ function formDisplayFields(form) {
27808
+ if (!form) return {
27809
+ state: "missing",
27810
+ formId: null,
27811
+ groups: []
27812
+ };
27813
+ const fields = form.schemaJson?.fields;
27814
+ return {
27815
+ state: "ready",
27816
+ formId: form.id,
27817
+ groups: Array.isArray(fields) ? groupFormFields(fields) : []
26000
27818
  };
26001
27819
  }
26002
27820
  const formInteractiveIslandPropsCodec = createInteractiveIslandCodec({
@@ -26127,76 +27945,74 @@ const giftingInteractiveIslandPropsCodec = createInteractiveIslandCodec({
26127
27945
  /**
26128
27946
  * Get form fields based on preset configuration.
26129
27947
  */
26130
- function getGlobalFormFields(form) {
26131
- const includePhone = form.includeOptionalPhone;
26132
- switch (form.fields.preset) {
26133
- case "emailOnly": return withOptionalPhone([{
26134
- id: "email",
26135
- type: "email",
26136
- label: "Email",
26137
- required: true,
26138
- placeholder: "your@email.com"
26139
- }], includePhone);
26140
- case "emailName": return withOptionalPhone([{
26141
- id: "email",
26142
- type: "email",
26143
- label: "Email",
26144
- required: true,
26145
- placeholder: "your@email.com"
26146
- }, {
27948
+ function getGlobalFormFields(form, presentation = {}) {
27949
+ const fields = withOptionalPhone(newsletterPresetFields(form.fields), form.includeOptionalPhone);
27950
+ return presentation.lookSlots ? fields.map((field) => ({
27951
+ ...field,
27952
+ label: lookFieldLabel(field)
27953
+ })) : fields;
27954
+ }
27955
+ function lookFieldLabel(field) {
27956
+ switch (field.id) {
27957
+ case "firstName": return "First name";
27958
+ case "lastName": return "Last name";
27959
+ default: return field.label;
27960
+ }
27961
+ }
27962
+ const emailField = {
27963
+ id: "email",
27964
+ type: "email",
27965
+ label: "Email",
27966
+ required: true,
27967
+ placeholder: "your@email.com"
27968
+ };
27969
+ const firstNameField = (required) => ({
27970
+ id: "firstName",
27971
+ type: "text",
27972
+ label: "First Name",
27973
+ required,
27974
+ placeholder: "First name"
27975
+ });
27976
+ function newsletterPresetFields(fields) {
27977
+ switch (fields.preset) {
27978
+ case "emailOnly": return [emailField];
27979
+ case "emailName": return [emailField, {
26147
27980
  id: "name",
26148
27981
  type: "text",
26149
27982
  label: "Name",
26150
- required: form.fields.name === "required",
27983
+ required: fields.name === "required",
26151
27984
  placeholder: "Your name"
26152
- }], includePhone);
26153
- case "emailFirstLast": return withOptionalPhone([
26154
- {
26155
- id: "email",
26156
- type: "email",
26157
- label: "Email",
26158
- required: true,
26159
- placeholder: "your@email.com"
26160
- },
26161
- {
26162
- id: "firstName",
26163
- type: "text",
26164
- label: "First Name",
26165
- required: form.fields.firstName === "required",
26166
- placeholder: "First name"
26167
- },
27985
+ }];
27986
+ case "emailFirstName": return [emailField, firstNameField(fields.firstName === "required")];
27987
+ case "emailFirstLast": return [
27988
+ emailField,
27989
+ firstNameField(fields.firstName === "required"),
26168
27990
  {
26169
27991
  id: "lastName",
26170
27992
  type: "text",
26171
27993
  label: "Last Name",
26172
- required: form.fields.lastName === "required",
27994
+ required: fields.lastName === "required",
26173
27995
  placeholder: "Last name"
26174
27996
  }
26175
- ], includePhone);
26176
- case "emailNameCompany": return withOptionalPhone([
26177
- {
26178
- id: "email",
26179
- type: "email",
26180
- label: "Email",
26181
- required: true,
26182
- placeholder: "your@email.com"
26183
- },
27997
+ ];
27998
+ case "emailNameCompany": return [
27999
+ emailField,
26184
28000
  {
26185
28001
  id: "name",
26186
28002
  type: "text",
26187
28003
  label: "Name",
26188
- required: form.fields.name === "required",
28004
+ required: fields.name === "required",
26189
28005
  placeholder: "Your name"
26190
28006
  },
26191
28007
  {
26192
28008
  id: "company",
26193
28009
  type: "text",
26194
28010
  label: "Company",
26195
- required: form.fields.company === "required",
28011
+ required: fields.company === "required",
26196
28012
  placeholder: "Company name"
26197
28013
  }
26198
- ], includePhone);
26199
- default: throw new Error("Unknown newsletter preset");
28014
+ ];
28015
+ default: return assertNever$6(fields);
26200
28016
  }
26201
28017
  }
26202
28018
  function withOptionalPhone(fields, includePhone) {
@@ -26264,6 +28080,7 @@ const mailingListSignupBlockSourceRefSchema = z.object({
26264
28080
  });
26265
28081
  const signedMailingListSourceTokenSchema = z.string().trim().min(1).transform(parseRequiredMailingListSignedSourceToken);
26266
28082
  const newsletterSourceCommonSchema = z.object({
28083
+ lookSlots: lookListPresentationSchemaShape.lookSlots,
26267
28084
  siteId: z.string().optional(),
26268
28085
  apiBaseUrl: z.string().optional(),
26269
28086
  mailingList: mailingListContextSchema.optional(),
@@ -26296,6 +28113,7 @@ const newsletterSourceSchema = z.discriminatedUnion("source", [
26296
28113
  newsletterSourceCommonSchema.extend({ source: z.literal("preview") })
26297
28114
  ]);
26298
28115
  const newsletterDisplaySchema = z.object({
28116
+ lookSlots: lookListPresentationSchemaShape.lookSlots,
26299
28117
  kind: z.literal("newsletter-form"),
26300
28118
  availability: z.enum(["ready", "unavailable"]),
26301
28119
  className: z.string().nullable(),
@@ -26363,13 +28181,14 @@ function buildNewsletterDisplay(source) {
26363
28181
  const choices = resolveRuntimeChoices(assessment);
26364
28182
  return {
26365
28183
  kind: "newsletter-form",
28184
+ ...source.lookSlots ? { lookSlots: source.lookSlots } : {},
26366
28185
  availability: assessment.tag === "available" ? "ready" : "unavailable",
26367
28186
  className: source.className ?? null,
26368
28187
  buttonLabel: form.buttonLabel,
26369
28188
  successMessage: form.successMessage,
26370
28189
  buttonVariant: source.buttonVariant ?? "primary",
26371
28190
  privacyNote: form.privacyNote,
26372
- fields: getGlobalFormFields(form),
28191
+ fields: getGlobalFormFields(form, source),
26373
28192
  choices
26374
28193
  };
26375
28194
  }
@@ -27373,4 +29192,4 @@ function defineIslandPropsDecoder(kind) {
27373
29192
  };
27374
29193
  }
27375
29194
  //#endregion
27376
- export { formatRegistrationSchedule as $, resolveRuntimeEventDestination as $n, orderedLiveRunSessions as $r, placesLeftLabel as $t, getEventSelectionMode as A, eventDateOptions as An, toSelectedCollectionOptionKind as Ar, buildBookingPaymentSelectionViewModel as At, getDeclinedPass as B, getLocalDateKey as Bn, ok as Br, resolveRouteRequiresPayment as Bt, offeringNounForEvent as C, normalizeCsvString as Cn, parseBookingCurrencyInputToCents as Cr, resolveRegistrationTicketContinuation as Ct, bookingEntry as D, formatEventPriceAmount as Dn, resolveBookingSiteId as Dr, normalizeEventRegistrationMaxTickets as Dt, bookingCardEntry as E, formatEventPrice as En, resolveBookingPaymentStep as Er, isEventRegistrationAvailable as Et, registrationStepLabel as F, formatEventNextDateFact as Fn, RichTextDocSchema as Fr, OFFLINE_BOOKING_PAYMENT_INSTRUCTIONS as Ft, shouldPromptForLogin as G, buildCalendarViewport as Gn, themeButtonVariantClassNames as Gr, formatCentsAsCurrencyInput as Gt, registrationFlowReducer as H, MONTH_NAMES as Hn, reportWorkflowError as Hr, beginWaitlistInvitation as Ht, registrationStepLabelContext as I, formatEventTimeRange as In, isRecord$4 as Ir, findPreSelectedEvent as It, findSelectedTicketType as J, getOrderedDayNames as Jn, checkBrowserStripeKey as Jr, getSlidingScaleForEvent as Jt, ENTITLEMENT_SINGLE_TICKET_TOOLTIP as K, formatDateKey as Kn, boxBackgroundSchema as Kr, getEligibilityFlowFlags as Kt, areEventRegistrationPaymentSelectionsEqual as L, formatTime$1 as Ln, assertNever$1 as Lr, resolveDiscountContext as Lt, registrationPaymentRoute as M, formatDate$1 as Mn, resolveSelectedAppointmentConsent as Mr, paymentChoiceDetails as Mt, registrationPresentation as N, formatEventCompactDateRail as Nn, BOOKING_FORM_DATA_RESERVED_KEYS as Nr, paymentChoicePrice as Nt, bookingEntryProgress as O, formatEventPriceDisplay as On, resolveDefaultBookingServiceId as Or, resolveEventRegistrationSubmitPlan as Ot, registrationRoute as P, formatEventDateParts as Pn, isBookingRequirementConsentFieldId as Pr, formatPrice as Pt, formatPassCreditUsageLabel as Q, shiftCalendarAnchorDate as Qn, CANCELLED_SESSION_STATUS as Qr, validateFormData as Qt, createInitialRegistrationFlowState as R, groupEventsByDate as Rn, clearWorkflowFeedback as Rr, resolveEventRequiresPayment as Rt, toWholeSeriesRegistrationEvents as S, normalizeCsvIds as Sn, isBookingServiceSlidingAmountInRange as Sr, resolveRegistrationAvailabilityBlocker as St, bookingBarPlacement as T, buildEventListWeek as Tn, resolveAppointmentCheckoutVerificationState as Tr, visitorHoldsOwnPlace as Tt, buildEventRegistrationPaymentOptionsViewModel as U, addDays as Un, reportWorkflowSuccess as Ur, createRegistrationDraftData as Ut, isRegistrationLocked as V, getLocalMinuteOfDay as Vn, okWith as Vr, toRegistrationRequestSubject as Vt, decideEventRegistrationPayment as W, addMonths as Wn, themeButtonSizeClassName as Wr, invitationSubmission as Wt, formatDate as X, isSameCalendarDay as Xn, parseEventRegistrationErrorReason as Xr, parseCurrencyInputToCents as Xt, formatBookingWhen as Y, getWeekCalendarDays as Yn, eventRegistrationErrors as Yr, getSlidingScaleSelectionMessage as Yt, formatEventDateTime as Z, isToday as Zn, confirmationPaymentSchema as Zr, shouldLoadRegistrationOptions as Zt, buildEventRegistrationDisplayFromScopedEvents as _, publicEventPricingType as _i, resolveCalendarReadProfile as _n, getBookingRedirectStateFromLocation as _r, placeCountCeiling as _t, buildProductDetailDisplay as a, formatLocalScheduleDate as ai, isSemanticSpacing as an, getEventAvailabilityStatus as ar, occurrenceTitleOverride as at, getRegistrationStartAt as b, buildEventRuntimeFilters as bn, getRegistrationSuccessCopy as br, resolveGuestNextStepCheck as bt, EMPTY_COMMERCE_CART_STATE as c, parseBookingLocalDate as ci, eventListingBlockRuntime as cn, selectEventCapacitySource as cr, canRequestTicketOption as ct, deriveCommerceCheckoutState as d, toScheduledBookingDateTime as di, calendarPageResponseError as dn, listItemPresentation as dr, getTicketSelectionTotal as dt, resolveWholeSeriesBookingPhase as ei, shownVenue as en, canJoinEventWaitlist as er, formatTime as et, parseStoredCommerceCartState as f, formatBookingPriceDisplay as fi, calendarQueryKey as fn, listLookSlot as fr, getTicketTypeLineMax as ft, newsletterBlockSubmissionMessage as g, publicEventPricingStrategy as gi, planCalendarMonthRanges as gn, formatBookingSubmissionPreparationError as gr, fullyBookedLabel as gt, NEWSLETTER_SIGNUPS_PAUSED_MESSAGE as h, publicEventPricingDisplay as hi, calendarWindowPageSchema as hn, formatBookingCentsAsCurrencyInput as hr, setTicketLineQuantity as ht, buildProductCardDisplay as i, formatBookingInstant as ii, SEMANTIC_SPACING_VALUES as in, getEventAvailability as ir, getVisibleTicketTypes as it, panelShouldOpen as j, eventLocalDateKey as jn, projectSelectedAppointmentConsentIntoForm as jr, buildReviewedBookingPaymentViewModel as jt, bookingPanelHeading as k, eventDateLocale as kn, selectedBookingCollectionOptionKind as kr, calculateEventRegistrationPreviewTotal as kt, buildPassCartItem as l, resolveBookingTimeZoneId as li, calendarMonthDate as ln, selectMostOpenCapacitySource as lr, getSingleSelectedPricingOptionId as lt, reduceCommerceCart as m, publicEventPricingCurrency as mi, calendarWindowMonths as mn, deriveBookingFormViewState as mr, normalizeTicketSelectionLines as mt, getShopDisplayForItems as n, resolveBookingSignupOffer as ni, staticHeaderChromeRuntime as nn, formatEventRemainingPlaces as nr, getPortalSubjectEmail as nt, formatCommercePrice as o, getBookingLocalDateKey as oi, resolveSpacing as on, getRemainingPlaces as or, transformRegistrationOptionsResponse as ot, productItemKey as p, isPublicEventPricingOptionDisplayable as pi, calendarWindowBounds as pn, logger as pr, hasValidPricingOptionSelection as pt, areEntitlementsDisabledForTicketCount as q, getDayOfWeek as qn, normalizeCardRole as qr, getRegistrationOccurrenceId as qt, buildCartDisplay as r, addLocalScheduleDays as ri, resolveEventRegistrationScopedEvents as rn, formatTotalCapacity as rr, getTicketTypeAvailabilityLabel as rt, formatInterval as s, getLocalScheduleDate as si, asPartialObject as sn, isEventFull as sr, withOccurrenceTitle as st, defineIslandPropsDecoder as t, parseMailingListVisitorSelection as ti, buildEventCalendarListingRender as tn, canJoinEventWaitlistOnAnyMode as tr, getImplicitSingleTicketType as tt, buildProductCartItem as u, toBookingTimeZone as ui, calendarMonthKey as un, groupPublicEventsByRun as ur, getTicketLineQuantity as ut, displayButtonText as v, formatCurrencyAmount as vi, createHostedBlockApiConfig as vn, getBookingServiceSlidingScale as vr, planRegistrationDetailsCheck as vt, DEFAULT_BOOKING_BUTTON_TEXT as w, normalizeOptionalId as wn, prepareBookingSubmission as wr, settledRemainingPlaces as wt, toRegistrationEvents as x, getEventRuntimeFiltersKey as xn, getShopSuccessCopy as xr, resolveRegistrationAdmission as xt, findBookedEvent as y, assertNever$6 as yi, getBlockApiReadStage as yn, getBookingSuccessCopy as yr, planRegistrationDetailsContinuation as yt, decideEventChoice as z, resolveEventTimeZone as zn, err as zr, resolveRegistrationTarget as zt };
29195
+ export { formatRegistrationSchedule as $, resolveRuntimeEventDestination as $n, resolveTokenOrCssColorValue as $r, placesLeftLabel as $t, getEventSelectionMode as A, publicEventPricingType as Ai, eventDateOptions as An, selectedBookingCollectionOptionKind as Ar, buildBookingPaymentSelectionViewModel as At, getDeclinedPass as B, getLocalDateKey as Bn, err as Br, resolveRouteRequiresPayment as Bt, offeringNounForEvent as C, toBookingTimeZone as Ci, normalizeCsvString as Cn, isBookingServiceSlidingAmountInRange as Cr, resolveRegistrationTicketContinuation as Ct, bookingEntry as D, publicEventPricingCurrency as Di, formatEventPriceAmount as Dn, resolveBookingPaymentStep as Dr, normalizeEventRegistrationMaxTickets as Dt, bookingCardEntry as E, isPublicEventPricingOptionDisplayable as Ei, formatEventPrice as En, resolveAppointmentCheckoutVerificationState as Er, isEventRegistrationAvailable as Et, registrationStepLabel as F, formatEventNextDateFact as Fn, isBookingRequirementConsentFieldId as Fr, OFFLINE_BOOKING_PAYMENT_INSTRUCTIONS as Ft, shouldPromptForLogin as G, buildCalendarViewport as Gn, themeButtonSizeClassName as Gr, formatCentsAsCurrencyInput as Gt, registrationFlowReducer as H, MONTH_NAMES as Hn, okWith as Hr, beginWaitlistInvitation as Ht, registrationStepLabelContext as I, formatEventTimeRange as In, RichTextDocSchema as Ir, findPreSelectedEvent as It, findSelectedTicketType as J, getOrderedDayNames as Jn, backgroundColorStyle as Jr, getSlidingScaleForEvent as Jt, ENTITLEMENT_SINGLE_TICKET_TOOLTIP as K, formatDateKey as Kn, themeButtonVariantClassNames as Kr, getEligibilityFlowFlags as Kt, areEventRegistrationPaymentSelectionsEqual as L, formatTime$1 as Ln, isRecord$4 as Lr, resolveDiscountContext as Lt, registrationPaymentRoute as M, assertNever$6 as Mi, formatDate$1 as Mn, projectSelectedAppointmentConsentIntoForm as Mr, paymentChoiceDetails as Mt, registrationPresentation as N, formatEventCompactDateRail as Nn, resolveSelectedAppointmentConsent as Nr, paymentChoicePrice as Nt, bookingEntryProgress as O, publicEventPricingDisplay as Oi, formatEventPriceDisplay as On, resolveBookingSiteId as Or, resolveEventRegistrationSubmitPlan as Ot, registrationRoute as P, formatEventDateParts as Pn, BOOKING_FORM_DATA_RESERVED_KEYS as Pr, formatPrice as Pt, formatPassCreditUsageLabel as Q, shiftCalendarAnchorDate as Qn, resolveOnColorForThemeToken as Qr, validateFormData as Qt, createInitialRegistrationFlowState as R, groupEventsByDate as Rn, assertNever$1 as Rr, resolveEventRequiresPayment as Rt, toWholeSeriesRegistrationEvents as S, resolveBookingTimeZoneId as Si, normalizeCsvIds as Sn, getShopSuccessCopy as Sr, resolveRegistrationAvailabilityBlocker as St, bookingBarPlacement as T, formatBookingPriceDisplay as Ti, buildEventListWeek as Tn, prepareBookingSubmission as Tr, visitorHoldsOwnPlace as Tt, buildEventRegistrationPaymentOptionsViewModel as U, addDays as Un, reportWorkflowError as Ur, createRegistrationDraftData as Ut, isRegistrationLocked as V, getLocalMinuteOfDay as Vn, ok as Vr, toRegistrationRequestSubject as Vt, decideEventRegistrationPayment as W, addMonths as Wn, reportWorkflowSuccess as Wr, invitationSubmission as Wt, formatDate as X, isSameCalendarDay as Xn, textColorStyle as Xr, parseCurrencyInputToCents as Xt, formatBookingWhen as Y, getWeekCalendarDays as Yn, mergeStyles as Yr, getSlidingScaleSelectionMessage as Yt, formatEventDateTime as Z, isToday as Zn, isCssColorLiteral as Zr, shouldLoadRegistrationOptions as Zt, buildEventRegistrationDisplayFromScopedEvents as _, formatBookingInstant as _i, resolveCalendarReadProfile as _n, formatBookingSubmissionPreparationError as _r, placeCountCeiling as _t, buildProductDetailDisplay as a, eventRegistrationErrors as ai, isSemanticSpacing as an, getEventAvailabilityStatus as ar, occurrenceTitleOverride as at, getRegistrationStartAt as b, getLocalScheduleDate as bi, buildEventRuntimeFilters as bn, getBookingSuccessCopy as br, resolveGuestNextStepCheck as bt, EMPTY_COMMERCE_CART_STATE as c, isExplicitRectCrop as ci, eventListingBlockRuntime as cn, selectEventCapacitySource as cr, canRequestTicketOption as ct, deriveCommerceCheckoutState as d, CANCELLED_SESSION_STATUS as di, calendarPageResponseError as dn, listItemPresentation as dr, getTicketSelectionTotal as dt, relativeLuminance as ei, shownVenue as en, canJoinEventWaitlist as er, formatTime as et, parseStoredCommerceCartState as f, orderedLiveRunSessions as fi, calendarQueryKey as fn, listLookControl as fr, getTicketTypeLineMax as ft, newsletterBlockSubmissionMessage as g, addLocalScheduleDays as gi, planCalendarMonthRanges as gn, formatBookingCentsAsCurrencyInput as gr, fullyBookedLabel as gt, NEWSLETTER_SIGNUPS_PAUSED_MESSAGE as h, resolveBookingSignupOffer as hi, calendarWindowPageSchema as hn, deriveBookingFormViewState as hr, setTicketLineQuantity as ht, buildProductCardDisplay as i, checkBrowserStripeKey as ii, SEMANTIC_SPACING_VALUES as in, getEventAvailability as ir, getVisibleTicketTypes as it, panelShouldOpen as j, formatCurrencyAmount as ji, eventLocalDateKey as jn, toSelectedCollectionOptionKind as jr, buildReviewedBookingPaymentViewModel as jt, bookingPanelHeading as k, publicEventPricingStrategy as ki, eventDateLocale as kn, resolveDefaultBookingServiceId as kr, calculateEventRegistrationPreviewTotal as kt, buildPassCartItem as l, parseAspectRatioValue as li, calendarMonthDate as ln, selectMostOpenCapacitySource as lr, getSingleSelectedPricingOptionId as lt, reduceCommerceCart as m, parseMailingListVisitorSelection as mi, calendarWindowMonths as mn, logger as mr, normalizeTicketSelectionLines as mt, getShopDisplayForItems as n, normalizeCardRole as ni, staticHeaderChromeRuntime as nn, formatEventRemainingPlaces as nr, getPortalSubjectEmail as nt, formatCommercePrice as o, parseEventRegistrationErrorReason as oi, resolveSpacing as on, getRemainingPlaces as or, transformRegistrationOptionsResponse as ot, productItemKey as p, resolveWholeSeriesBookingPhase as pi, calendarWindowBounds as pn, listLookSlot as pr, hasValidPricingOptionSelection as pt, areEntitlementsDisabledForTicketCount as q, getDayOfWeek as qn, boxBackgroundSchema as qr, getRegistrationOccurrenceId as qt, buildCartDisplay as r, clsx as ri, resolveEventRegistrationScopedEvents as rn, formatTotalCapacity as rr, getTicketTypeAvailabilityLabel as rt, formatInterval as s, confirmationPaymentSchema as si, asPartialObject as sn, isEventFull as sr, withOccurrenceTitle as st, defineIslandPropsDecoder as t, hexToRgb as ti, buildEventCalendarListingRender as tn, canJoinEventWaitlistOnAnyMode as tr, getImplicitSingleTicketType as tt, buildProductCartItem as u, resolveMediaTransformForAspect as ui, calendarMonthKey as un, groupPublicEventsByRun as ur, getTicketLineQuantity as ut, displayButtonText as v, formatLocalScheduleDate as vi, createHostedBlockApiConfig as vn, getBookingRedirectStateFromLocation as vr, planRegistrationDetailsCheck as vt, DEFAULT_BOOKING_BUTTON_TEXT as w, toScheduledBookingDateTime as wi, normalizeOptionalId as wn, parseBookingCurrencyInputToCents as wr, settledRemainingPlaces as wt, toRegistrationEvents as x, parseBookingLocalDate as xi, getEventRuntimeFiltersKey as xn, getRegistrationSuccessCopy as xr, resolveRegistrationAdmission as xt, findBookedEvent as y, getBookingLocalDateKey as yi, getBlockApiReadStage as yn, getBookingServiceSlidingScale as yr, planRegistrationDetailsContinuation as yt, decideEventChoice as z, resolveEventTimeZone as zn, clearWorkflowFeedback as zr, resolveRegistrationTarget as zt };