@riverbankcms/sdk 0.77.1 → 0.78.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 (230) hide show
  1. package/README.md +69 -0
  2. package/dist/{PreviewEditorSidebar-DVUG7GK4.mjs → PreviewEditorSidebar-RIKFQ72L.mjs} +4916 -4847
  3. package/dist/{PreviewEditorUI-P7RN4CDS.mjs → PreviewEditorUI-XO7TUWKK.mjs} +3 -3
  4. package/dist/SdkPreviewModeRuntime-LAGYMPNF.mjs +8 -0
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +154 -154
  6. package/dist/_dts/api/src/accessAdmin.d.ts +5 -0
  7. package/dist/_dts/api/src/billing.d.ts +3 -26
  8. package/dist/_dts/api/src/bookingVerticals.d.ts +4 -0
  9. package/dist/_dts/api/src/content-editor.d.ts +1 -0
  10. package/dist/_dts/api/src/demoDashboardMutationSurfaces.d.ts +46 -0
  11. package/dist/_dts/api/src/endpoints.d.ts +8 -0
  12. package/dist/_dts/api/src/index.d.ts +14 -2
  13. package/dist/_dts/api/src/navigation/dashboardBookingsNav.d.ts +87 -0
  14. package/dist/_dts/api/src/navigation/dashboardDemoNav.d.ts +5 -0
  15. package/dist/_dts/api/src/navigation/dashboardSettingsNav.d.ts +45 -0
  16. package/dist/_dts/api/src/navigation/dashboardSiteNav.d.ts +42 -0
  17. package/dist/_dts/api/src/navigation/dashboardTeamMemberNav.d.ts +24 -0
  18. package/dist/_dts/api/src/navigation/linkUrlType.d.ts +3 -0
  19. package/dist/_dts/api/src/navigation.d.ts +12 -0
  20. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +55 -26
  21. package/dist/_dts/api/src/staffAccess.d.ts +79 -0
  22. package/dist/_dts/api/src/types.d.ts +3 -1
  23. package/dist/_dts/api/src/workflows/automaticWorkflowTriggers.d.ts +21 -0
  24. package/dist/_dts/blocks/src/client/site-chrome.d.ts +4 -1
  25. package/dist/_dts/blocks/src/index.d.ts +1 -0
  26. package/dist/_dts/blocks/src/system/blocks/appointment-booking.d.ts +288 -288
  27. package/dist/_dts/blocks/src/system/blocks/blog-listing.d.ts +288 -288
  28. package/dist/_dts/blocks/src/system/blocks/cart.d.ts +288 -288
  29. package/dist/_dts/blocks/src/system/blocks/checkout.d.ts +288 -288
  30. package/dist/_dts/blocks/src/system/blocks/collection.d.ts +288 -288
  31. package/dist/_dts/blocks/src/system/blocks/courses/shared/schemas.d.ts +2 -2
  32. package/dist/_dts/blocks/src/system/blocks/faq.d.ts +294 -289
  33. package/dist/_dts/blocks/src/system/blocks/gifting.d.ts +288 -288
  34. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +1 -1
  35. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +21 -21
  36. package/dist/_dts/blocks/src/system/blocks/product-detail.d.ts +288 -288
  37. package/dist/_dts/blocks/src/system/blocks/product-list.d.ts +288 -288
  38. package/dist/_dts/blocks/src/system/blocks/shop.d.ts +288 -288
  39. package/dist/_dts/blocks/src/system/data/index.d.ts +5 -3
  40. package/dist/_dts/blocks/src/system/data/previewResolvedDataState.d.ts +45 -0
  41. package/dist/_dts/blocks/src/system/fields/boxStyles.d.ts +2 -1
  42. package/dist/_dts/blocks/src/system/fragments/library/faqAccordion.d.ts +5 -0
  43. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +29 -29
  44. package/dist/_dts/blocks/src/system/node/fragments/headingDecoration.d.ts +10 -0
  45. package/dist/_dts/blocks/src/system/node/fragments/index.d.ts +1 -0
  46. package/dist/_dts/blocks/src/system/node/fragments/styledSection.d.ts +9 -0
  47. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +3 -2
  48. package/dist/_dts/blocks/src/system/runtime/api/endpoints.d.ts +8 -0
  49. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  50. package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +43 -8
  51. package/dist/_dts/blocks/src/system/runtime/header/shared.d.ts +8 -7
  52. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCompactRow.d.ts +1 -4
  53. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/utils.d.ts +7 -0
  54. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.client.d.ts +2 -8
  55. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.server.d.ts +2 -9
  56. package/dist/_dts/blocks/src/system/runtime/nodes/shop-cart-discount-ui.d.ts +5 -0
  57. package/dist/_dts/blocks/src/system/runtime/nodes/shop-checkout-form.d.ts +76 -0
  58. package/dist/_dts/blocks/src/system/runtime/nodes/shop-checkout.state.d.ts +1 -4
  59. package/dist/_dts/blocks/src/system/runtime/nodes/shop-commerce-store.d.ts +2 -0
  60. package/dist/_dts/blocks/src/system/runtime/nodes/shop-commerce.shared.d.ts +1 -0
  61. package/dist/_dts/blocks/src/system/runtime/nodes/shop-discount-apply.state.d.ts +52 -0
  62. package/dist/_dts/blocks/src/system/runtime/nodes/shop.state.d.ts +2 -4
  63. package/dist/_dts/blocks/src/system/runtime/nodes/useDiscountApply.d.ts +21 -0
  64. package/dist/_dts/blocks/src/system/runtime/shared/components/DiscountCodeDisclosure.d.ts +54 -0
  65. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +2 -0
  66. package/dist/_dts/blocks/src/system/runtime/shared/index.d.ts +2 -2
  67. package/dist/_dts/blocks/src/system/transforms/registry/ui.d.ts +1 -1
  68. package/dist/_dts/blocks/src/system/transforms/typed.d.ts +1 -1
  69. package/dist/_dts/content-editor/src/contentTypeEditorContentState.d.ts +26 -0
  70. package/dist/_dts/content-editor/src/definitions/factory.d.ts +75 -0
  71. package/dist/_dts/content-editor/src/entryWorkflows.d.ts +2 -0
  72. package/dist/_dts/content-editor/src/footerBlocksEditorState.d.ts +76 -0
  73. package/dist/_dts/content-editor/src/index.d.ts +5 -0
  74. package/dist/_dts/content-editor/src/pageWorkflowContent.d.ts +29 -0
  75. package/dist/_dts/content-model/src/content-types/schema.d.ts +3 -3
  76. package/dist/_dts/content-model/src/index.d.ts +1 -0
  77. package/dist/_dts/content-model/src/routeTemplate.d.ts +4 -0
  78. package/dist/_dts/content-model/src/templates/editorState.d.ts +25 -0
  79. package/dist/_dts/core/src/csv-cells.d.ts +10 -0
  80. package/dist/_dts/core/src/csv-date-filter.d.ts +27 -0
  81. package/dist/_dts/core/src/csv-escape.d.ts +1 -0
  82. package/dist/_dts/core/src/csv-filename.d.ts +18 -0
  83. package/dist/_dts/core/src/csv-render.d.ts +4 -0
  84. package/dist/_dts/core/src/csv-types.d.ts +116 -0
  85. package/dist/_dts/core/src/currency-format.d.ts +4 -0
  86. package/dist/_dts/core/src/demo-capability-policy.d.ts +29 -0
  87. package/dist/_dts/core/src/demo-claim-access.d.ts +14 -0
  88. package/dist/_dts/core/src/demo-lifecycle-status.d.ts +11 -0
  89. package/dist/_dts/core/src/demo-runtime.d.ts +47 -0
  90. package/dist/_dts/core/src/duration.d.ts +14 -0
  91. package/dist/_dts/core/src/email-format.d.ts +10 -0
  92. package/dist/_dts/core/src/field-errors.d.ts +1 -0
  93. package/dist/_dts/core/src/form-submission-preview.d.ts +24 -0
  94. package/dist/_dts/core/src/index.d.ts +20 -0
  95. package/dist/_dts/core/src/number-input.d.ts +22 -0
  96. package/dist/_dts/core/src/public-url-validation.d.ts +12 -0
  97. package/dist/_dts/core/src/slug.d.ts +39 -0
  98. package/dist/_dts/core/src/string.d.ts +19 -0
  99. package/dist/_dts/core/src/uuid.d.ts +6 -0
  100. package/dist/_dts/db/src/schemas/forms.d.ts +50 -50
  101. package/dist/_dts/media-core/src/assetsInUseSummary.d.ts +34 -0
  102. package/dist/_dts/media-core/src/bulkDeletePlanning.d.ts +24 -0
  103. package/dist/_dts/media-core/src/canonicalCropReview.d.ts +66 -0
  104. package/dist/_dts/media-core/src/classifyAllPlanning.d.ts +48 -0
  105. package/dist/_dts/media-core/src/filename.d.ts +1 -0
  106. package/dist/_dts/media-core/src/index.d.ts +10 -0
  107. package/dist/_dts/media-core/src/mediaAssetUsageStatus.d.ts +47 -0
  108. package/dist/_dts/media-core/src/mediaSettingsState.d.ts +3 -0
  109. package/dist/_dts/media-core/src/portableMediaReferences.d.ts +38 -0
  110. package/dist/_dts/media-core/src/uploadVerificationContract.d.ts +28 -0
  111. package/dist/_dts/media-core/src/videoAssetRepair.d.ts +38 -0
  112. package/dist/_dts/media-editor/src/mediaEditorDebug.d.ts +1 -0
  113. package/dist/_dts/path-utils/src/index.d.ts +8 -0
  114. package/dist/_dts/path-utils/src/redirectPaths.d.ts +26 -0
  115. package/dist/_dts/path-utils/src/safeAppPath.d.ts +26 -0
  116. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeButton.d.ts +2 -1
  117. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +4 -0
  118. package/dist/_dts/preview-next/src/client/preview/previewDocumentFrame.d.ts +31 -0
  119. package/dist/_dts/sdk/src/client/error.d.ts +3 -0
  120. package/dist/_dts/sdk/src/client/index.d.ts +2 -2
  121. package/dist/_dts/sdk/src/client/types.d.ts +37 -19
  122. package/dist/_dts/sdk/src/index.d.ts +2 -2
  123. package/dist/_dts/sdk/src/manifest/passes/pass1-fields.d.ts +16 -16
  124. package/dist/_dts/sdk/src/next/content-load-failure.d.ts +51 -0
  125. package/dist/_dts/sdk/src/next/index.d.ts +2 -1
  126. package/dist/_dts/sdk/src/next/types.d.ts +19 -0
  127. package/dist/_dts/sdk/src/portal/redirects.d.ts +1 -1
  128. package/dist/_dts/sdk/src/routing/index.d.ts +3 -2
  129. package/dist/_dts/sdk/src/routing/resolvePageContent.d.ts +71 -6
  130. package/dist/_dts/sdk/src/version.d.ts +1 -1
  131. package/dist/_dts/site-commands/src/commands.d.ts +12 -12
  132. package/dist/_dts/site-commands/src/index.d.ts +1 -0
  133. package/dist/_dts/site-commands/src/pagePaths.d.ts +6 -0
  134. package/dist/_dts/theme-core/src/accordions/siteStyleDefaults.d.ts +26 -0
  135. package/dist/_dts/theme-core/src/accordions/types.d.ts +1 -0
  136. package/dist/_dts/theme-core/src/blocks/vars/index.d.ts +1 -0
  137. package/dist/_dts/theme-core/src/fonts/index.d.ts +1 -0
  138. package/dist/_dts/theme-core/src/fonts/uploadFormat.d.ts +44 -0
  139. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  140. package/dist/_dts/theme-core/src/index.d.ts +3 -1
  141. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +36 -24
  142. package/dist/_dts/theme-core/src/navigation/generateNavLinkCSS.d.ts +6 -1
  143. package/dist/_dts/theme-core/src/navigation/types.d.ts +12 -0
  144. package/dist/_dts/theme-core/src/palette/variants/types.d.ts +3 -3
  145. package/dist/_dts/theme-core/src/runtime/themeCssVarNames.d.ts +7 -0
  146. package/dist/_dts/theme-core/src/schema.d.ts +64 -18
  147. package/dist/_dts/theme-core/src/site-styles/appearancePresetCatalog.d.ts +214 -34
  148. package/dist/_dts/theme-core/src/site-styles/appearancePresetTypes.d.ts +5 -2
  149. package/dist/_dts/theme-core/src/site-styles/blockAppearancePresets.d.ts +214 -34
  150. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +24 -0
  151. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +31 -3
  152. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -4
  153. package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +33 -1
  154. package/dist/_dts/theme-core/src/site-styles/rawStyleFields.d.ts +4 -2
  155. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +9 -1
  156. package/dist/_dts/theme-core/src/site-styles/types.d.ts +27 -2
  157. package/dist/_dts/theme-core/src/siteChrome.d.ts +17 -34
  158. package/dist/_dts/theme-core/src/siteChromeOverlayClearance.d.ts +22 -0
  159. package/dist/_dts/theme-core/src/siteChromePlacement.d.ts +22 -0
  160. package/dist/_dts/theme-core/src/siteChromePlanning.d.ts +32 -0
  161. package/dist/_dts/theme-core/src/tokens/themeColorTokens.d.ts +2 -2
  162. package/dist/{chunk-2SPENC5M.mjs → chunk-F7RTCZYN.mjs} +229 -50
  163. package/dist/{chunk-IENWFSLO.mjs → chunk-NIDXI46P.mjs} +1 -1
  164. package/dist/{chunk-KWJPDZH2.mjs → chunk-OECWLDHN.mjs} +2770 -620
  165. package/dist/{chunk-VX7B5VAC.mjs → chunk-SVMMM2NA.mjs} +8 -0
  166. package/dist/{chunk-6SMUFTXD.mjs → chunk-SXOLGNMX.mjs} +1 -1
  167. package/dist/{chunk-ZYEJLCTN.mjs → chunk-TXDES5P2.mjs} +2 -2
  168. package/dist/cli/index.mjs +1677 -440
  169. package/dist/client/{accordion-RZMQSYLR.mjs → accordion-EVDEOUPR.mjs} +2 -2
  170. package/dist/client/{bookingForm-NF4ASVNV.mjs → bookingForm-DIHBLC64.mjs} +27 -30
  171. package/dist/client/bookings.mjs +3707 -259
  172. package/dist/client/{carousel-LDX47ZIK.mjs → carousel-FEBQHIWI.mjs} +3 -4
  173. package/dist/client/{cart-RGXDS5F4.mjs → cart-7CKSXAE4.mjs} +8 -8
  174. package/dist/client/{checkout-P7WWSNNY.mjs → checkout-WKYCANLV.mjs} +8 -8
  175. package/dist/client/{chunk-JNC7CGHX.mjs → chunk-2SAVKN2M.mjs} +2 -2
  176. package/dist/client/{chunk-TQ5MSPDX.mjs → chunk-36WJCERQ.mjs} +1 -1
  177. package/dist/client/{chunk-R56FQ3RR.mjs → chunk-65F47D7Y.mjs} +280 -71
  178. package/dist/client/{chunk-L3DNHIJX.mjs → chunk-GUK2FPXQ.mjs} +23 -45
  179. package/dist/client/{chunk-PMAIXMAB.mjs → chunk-IVNCUVAV.mjs} +26 -21
  180. package/dist/client/{chunk-II7O4XN3.mjs → chunk-OFMSCGNY.mjs} +2 -2
  181. package/dist/client/chunk-PD6NBCEY.mjs +66 -0
  182. package/dist/client/{chunk-GMVTOKYG.mjs → chunk-RV6FX7UH.mjs} +510 -64
  183. package/dist/client/{chunk-E2TDNXCL.mjs → chunk-RZDWX7QW.mjs} +2 -1
  184. package/dist/client/{chunk-M3L3KYYR.mjs → chunk-UDNSI5PY.mjs} +12 -0
  185. package/dist/client/{chunk-JEZECJ3W.mjs → chunk-VPPMNXCF.mjs} +129 -3
  186. package/dist/client/{chunk-UFSWADAO.mjs → chunk-YDSEG6GZ.mjs} +5 -66
  187. package/dist/client/client.mjs +7070 -4561
  188. package/dist/client/{courseRegistration-7F65K5ZR.mjs → courseRegistration-5QF2PHKM.mjs} +14 -11
  189. package/dist/client/{eventCalendar-GLSC5KTL.mjs → eventCalendar-4ZOSETDU.mjs} +9 -9
  190. package/dist/client/{eventCombined-ZHK4WKUR.mjs → eventCombined-WQGU7JUX.mjs} +9 -9
  191. package/dist/client/{eventDetails-E3PJYBIN.mjs → eventDetails-AYWVUJ5Y.mjs} +9 -9
  192. package/dist/client/{eventListing-EMS3WC3E.mjs → eventListing-NT7C6UT5.mjs} +9 -9
  193. package/dist/client/{eventRegistration-NZOTVNPI.mjs → eventRegistration-OH24F4ZJ.mjs} +9 -9
  194. package/dist/client/{form-ETFZFATW.mjs → form-7L42SRBB.mjs} +6 -6
  195. package/dist/client/{headerSection-4LBP7ULT.mjs → headerSection-OZRZNZ52.mjs} +3 -3
  196. package/dist/client/hooks.mjs +1040 -278
  197. package/dist/client/{locationMap-5M655YSJ.mjs → locationMap-ZBXRPQ7C.mjs} +2 -2
  198. package/dist/client/{newsletterForm-QOUYW44O.mjs → newsletterForm-SNAGFF2I.mjs} +3 -3
  199. package/dist/client/{productDetail-O4DOCWQG.mjs → productDetail-I46BOFGV.mjs} +8 -8
  200. package/dist/client/{productList-A5RO5WIS.mjs → productList-BOYHTYI6.mjs} +8 -8
  201. package/dist/client/rendering/client.mjs +7090 -2645
  202. package/dist/client/rendering/islands.mjs +19 -19
  203. package/dist/client/rendering.mjs +6089 -3792
  204. package/dist/client/{shop-L4MZH4I2.mjs → shop-XTXPZTKR.mjs} +8 -8
  205. package/dist/preview-next/before-render.mjs +8 -0
  206. package/dist/preview-next/client/runtime.mjs +5 -5
  207. package/dist/preview-next/editor-chrome.css +10 -0
  208. package/dist/preview-next/middleware.mjs +8 -0
  209. package/dist/{sdk-runtime-6UT2S7KZ.mjs → sdk-runtime-ZJLKC6DR.mjs} +6 -6
  210. package/dist/server/components.mjs +2635 -1262
  211. package/dist/server/config-validation.mjs +1271 -509
  212. package/dist/server/config.mjs +1271 -509
  213. package/dist/server/data.mjs +1040 -278
  214. package/dist/server/index.mjs +488 -246
  215. package/dist/server/next.mjs +4087 -2147
  216. package/dist/server/page-converter.mjs +571 -115
  217. package/dist/server/prebuild.mjs +1 -1
  218. package/dist/server/rendering/server.mjs +2636 -1263
  219. package/dist/server/rendering.mjs +2654 -1268
  220. package/dist/server/routing.mjs +1729 -489
  221. package/dist/server/server.mjs +1532 -530
  222. package/dist/server/theme-bridge.mjs +3151 -131
  223. package/dist/server/theme.mjs +10 -1
  224. package/dist/styles/index.css +488 -48
  225. package/package.json +2 -1
  226. package/dist/SdkPreviewModeRuntime-KLPX47SE.mjs +0 -8
  227. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/DiscountCodeSection.d.ts +0 -7
  228. package/dist/_dts/preview-next/src/client/widgets/PreviewMediaField.d.ts +0 -4
  229. package/dist/client/chunk-OJPZEZU2.mjs +0 -31
  230. package/dist/client/chunk-RTZ3JKKX.mjs +0 -178
@@ -1,13 +1,14 @@
1
1
  "use client";
2
- import { addPassToCommerceCart, useCommerceCart } from './chunk-E2TDNXCL.mjs';
3
- import { CarouselNodeClient } from './chunk-II7O4XN3.mjs';
2
+ import { addPassToCommerceCart, useCommerceCart } from './chunk-RZDWX7QW.mjs';
3
+ import { CarouselNodeClient } from './chunk-OFMSCGNY.mjs';
4
4
  import { isRecord } from './chunk-I2MMZO53.mjs';
5
- import { createBodyThemePortalRoot, consumeSearchParams, scrollToBlock, TerminalPanel, StateIcon, CheckIcon, CrossIcon, ActionRow, consumeSearchParam, buildCheckoutReturnUrls } from './chunk-JEZECJ3W.mjs';
5
+ import { useDiscountCodeUi } from './chunk-PD6NBCEY.mjs';
6
+ import { createBodyThemePortalRoot, consumeSearchParams, scrollToBlock, TerminalPanel, StateIcon, CheckIcon, CrossIcon, ActionRow, DiscountCodeDisclosure, consumeSearchParam, buildCheckoutReturnUrls } from './chunk-VPPMNXCF.mjs';
6
7
  import { ModalShell, resolveDedicatedCheckoutPath } from './chunk-3PEDD5KJ.mjs';
7
- import { useBlockApi, FeedbackMessage, BlockApiProvider } from './chunk-M3L3KYYR.mjs';
8
+ import { useBlockApi, FeedbackMessage, BlockApiProvider } from './chunk-UDNSI5PY.mjs';
8
9
  import { mountReactIsland } from './chunk-N7PBWBWQ.mjs';
9
- import { themeButtonClassName, formatCommercePrice, formatInterval, getShopDisplayForItems, buildProductDetailDisplay, productItemKey, buildProductCartItem, buildProductCardDisplay, assertNever } from './chunk-R56FQ3RR.mjs';
10
- import { getCurrentResolveImageUrlContext, resolveImageUrlWithContext, ImagePresets } from './chunk-PMAIXMAB.mjs';
10
+ import { themeButtonClassName, formatCommercePrice, formatInterval, getShopDisplayForItems, deriveCommerceCheckoutState, buildProductDetailDisplay, productItemKey, buildProductCartItem, buildProductCardDisplay, assertNever11, reportWorkflowError, clearWorkflowFeedback } from './chunk-65F47D7Y.mjs';
11
+ import { assertNever, ok, err, getCurrentResolveImageUrlContext, resolveImageUrlWithContext, ImagePresets } from './chunk-IVNCUVAV.mjs';
11
12
  import * as React3 from 'react';
12
13
  import React3__default, { useState, useRef, useCallback, useEffect } from 'react';
13
14
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -488,7 +489,8 @@ function ShopAddFeedback(props) {
488
489
  var initialShopCheckoutState = {
489
490
  form: {
490
491
  name: "",
491
- email: ""
492
+ email: "",
493
+ discountCode: ""
492
494
  },
493
495
  submission: "idle",
494
496
  feedback: { tag: "idle" },
@@ -498,24 +500,21 @@ function shopCheckoutReducer(state, action) {
498
500
  switch (action.type) {
499
501
  case "setField":
500
502
  return {
501
- ...state,
503
+ ...clearWorkflowFeedback(state),
502
504
  form: {
503
505
  ...state.form,
504
506
  [action.field]: action.value
505
- },
506
- feedback: { tag: "idle" }
507
+ }
507
508
  };
508
509
  case "submitStarted":
509
510
  return {
510
- ...state,
511
- submission: "submitting",
512
- feedback: { tag: "idle" }
511
+ ...clearWorkflowFeedback(state),
512
+ submission: "submitting"
513
513
  };
514
514
  case "submitFailed":
515
515
  return {
516
- ...state,
517
- submission: "idle",
518
- feedback: { tag: "error", message: action.message }
516
+ ...reportWorkflowError(state, action.message),
517
+ submission: "idle"
519
518
  };
520
519
  case "submitCompleted":
521
520
  return {
@@ -528,9 +527,338 @@ function shopCheckoutReducer(state, action) {
528
527
  notice: action.notice
529
528
  };
530
529
  default:
531
- return assertNever(action);
530
+ return assertNever11(action);
531
+ }
532
+ }
533
+
534
+ // ../blocks/src/system/runtime/nodes/shop-checkout-form.ts
535
+ var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
536
+ function normalizeManualDiscountCode(raw) {
537
+ const trimmed = raw.trim();
538
+ return trimmed ? trimmed : null;
539
+ }
540
+ function normalizeCheckoutEmail(raw) {
541
+ const email = raw.trim().toLowerCase();
542
+ if (!email) {
543
+ return err({
544
+ type: "missing_contact",
545
+ message: "Please enter your email"
546
+ });
547
+ }
548
+ if (!EMAIL_PATTERN.test(email)) {
549
+ return err({
550
+ type: "invalid_email",
551
+ message: "Please enter a valid email address"
552
+ });
553
+ }
554
+ return ok(email);
555
+ }
556
+ function normalizeCheckoutContactForm(form) {
557
+ const emailValue = form.email.trim().toLowerCase();
558
+ const name = form.name.trim();
559
+ if (!emailValue || !name) {
560
+ return err({
561
+ type: "missing_contact",
562
+ message: "Please enter your email and name"
563
+ });
564
+ }
565
+ const email = normalizeCheckoutEmail(emailValue);
566
+ if (!email.ok) return email;
567
+ return ok({ email: email.value, name });
568
+ }
569
+ function planDirectShopCheckoutRequest(input) {
570
+ const contact = normalizeCheckoutContactForm(input.form);
571
+ if (!contact.ok) return contact;
572
+ const discountCode = normalizeManualDiscountCode(input.form.discountCode);
573
+ return ok({
574
+ productType: input.productType,
575
+ productId: input.productId,
576
+ customerEmail: contact.value.email,
577
+ customerName: contact.value.name,
578
+ ...discountCode ? { discountCode } : {},
579
+ successUrl: input.successUrl,
580
+ cancelUrl: input.cancelUrl,
581
+ ...input.confirmDuplicate ? { confirmDuplicate: true } : {}
582
+ });
583
+ }
584
+ function buildUnifiedCheckoutItems(checkout) {
585
+ return checkout.items.map(
586
+ (item) => item.kind === "product" ? {
587
+ type: "product",
588
+ productId: item.productId,
589
+ ...item.variantId ? { variantId: item.variantId } : {},
590
+ quantity: item.quantity
591
+ } : {
592
+ type: "pass",
593
+ passId: item.passId
594
+ }
595
+ );
596
+ }
597
+ function planUnifiedCheckoutRequest(input) {
598
+ if (input.checkout.kind === "empty") {
599
+ return err({
600
+ type: "empty_cart",
601
+ message: "Your cart is empty"
602
+ });
603
+ }
604
+ if (input.checkout.kind === "blocked") {
605
+ return err({
606
+ type: "blocked_cart",
607
+ reason: input.checkout.reason,
608
+ message: "Your cart contains items with different currencies"
609
+ });
610
+ }
611
+ const contact = normalizeCheckoutContactForm(input.form);
612
+ if (!contact.ok) return contact;
613
+ const discountCode = normalizeManualDiscountCode(input.form.discountCode);
614
+ return ok({
615
+ mode: "one_time",
616
+ items: buildUnifiedCheckoutItems(input.checkout),
617
+ customer: contact.value,
618
+ ...discountCode ? { discountCode } : {},
619
+ successUrl: input.successUrl,
620
+ cancelUrl: input.cancelUrl
621
+ });
622
+ }
623
+ function planCartDiscountAvailabilityRequests(checkout) {
624
+ if (checkout.kind === "empty") {
625
+ return err({
626
+ type: "empty_cart",
627
+ message: "Your cart is empty"
628
+ });
629
+ }
630
+ if (checkout.kind === "blocked") {
631
+ return err({
632
+ type: "blocked_cart",
633
+ reason: checkout.reason,
634
+ message: "Your cart contains items with different currencies"
635
+ });
636
+ }
637
+ return ok(checkout.items.map((item) => {
638
+ const subtotalCents = Math.max(0, item.unitPriceCents * item.quantity);
639
+ if (item.kind === "product") {
640
+ return {
641
+ context: {
642
+ type: "product",
643
+ productId: item.productId,
644
+ productCategoryId: item.productCategoryId
645
+ },
646
+ subtotalCents,
647
+ currency: item.currency
648
+ };
649
+ }
650
+ return {
651
+ context: {
652
+ type: "pass",
653
+ passId: item.passId
654
+ },
655
+ subtotalCents,
656
+ currency: item.currency
657
+ };
658
+ }));
659
+ }
660
+ function aggregateCartDiscountUiState(availability) {
661
+ if (!availability.some((item) => item.hasDiscounts)) {
662
+ return { type: "unavailable" };
663
+ }
664
+ if (availability.some((item) => item.manualCodeEntryAllowed)) {
665
+ return { type: "manual-allowed" };
666
+ }
667
+ const autoAppliedDiscount = availability.find(
668
+ (item) => item.autoAppliedDiscount
669
+ )?.autoAppliedDiscount ?? null;
670
+ return {
671
+ type: "auto-only",
672
+ autoAppliedDiscount
673
+ };
674
+ }
675
+ function checkoutFormForDiscountUiState(form, discountUiState) {
676
+ if (discountUiState.type === "manual-allowed") return form;
677
+ return {
678
+ ...form,
679
+ discountCode: ""
680
+ };
681
+ }
682
+ var CART_DISCOUNT_UNAVAILABLE = { type: "unavailable" };
683
+ function useCartDiscountUiState(api, plan) {
684
+ const [discountUiState, setDiscountUiState] = useState(
685
+ CART_DISCOUNT_UNAVAILABLE
686
+ );
687
+ useEffect(() => {
688
+ let cancelled = false;
689
+ async function loadCartDiscountAvailability() {
690
+ if (!plan.ok || plan.value.length === 0) {
691
+ setDiscountUiState(CART_DISCOUNT_UNAVAILABLE);
692
+ return;
693
+ }
694
+ setDiscountUiState({ type: "loading" });
695
+ try {
696
+ const availability = await Promise.all(
697
+ plan.value.map((request) => api.getDiscountsAvailable(request))
698
+ );
699
+ if (cancelled) return;
700
+ setDiscountUiState(aggregateCartDiscountUiState(availability));
701
+ } catch {
702
+ if (!cancelled) {
703
+ setDiscountUiState({ type: "error-unavailable" });
704
+ }
705
+ }
706
+ }
707
+ loadCartDiscountAvailability();
708
+ return () => {
709
+ cancelled = true;
710
+ };
711
+ }, [api, plan]);
712
+ return discountUiState;
713
+ }
714
+
715
+ // ../blocks/src/system/runtime/nodes/shop-discount-apply.state.ts
716
+ var initialDiscountApplyState = {
717
+ isOpen: false,
718
+ draftCode: "",
719
+ status: { type: "idle" }
720
+ };
721
+ function discountApplyReducer(state, action) {
722
+ switch (action.type) {
723
+ case "open":
724
+ return {
725
+ ...state,
726
+ isOpen: true
727
+ };
728
+ case "draftChanged":
729
+ return {
730
+ ...state,
731
+ draftCode: action.draftCode,
732
+ status: { type: "idle" }
733
+ };
734
+ case "remove":
735
+ return initialDiscountApplyState;
736
+ case "applyStarted":
737
+ return {
738
+ ...state,
739
+ status: { type: "applying" }
740
+ };
741
+ case "applySucceeded":
742
+ return {
743
+ ...state,
744
+ isOpen: true,
745
+ draftCode: action.discount.code,
746
+ status: {
747
+ type: "applied",
748
+ discount: action.discount
749
+ }
750
+ };
751
+ case "applyRejected":
752
+ return {
753
+ ...state,
754
+ isOpen: true,
755
+ status: {
756
+ type: "rejected",
757
+ reason: action.reason,
758
+ message: action.message
759
+ }
760
+ };
761
+ case "resetApplied":
762
+ if (state.status.type !== "applied") return state;
763
+ return {
764
+ ...state,
765
+ status: { type: "idle" }
766
+ };
767
+ default:
768
+ return assertNever11(action);
532
769
  }
533
770
  }
771
+ function getAppliedDiscountCode(state) {
772
+ if (state.status.type !== "applied") return null;
773
+ return normalizeManualDiscountCode(state.status.discount.code);
774
+ }
775
+ function isDiscountApplyInFlight(state) {
776
+ return state.status.type === "applying";
777
+ }
778
+ function getDiscountApplyFeedback(status, formatPrice) {
779
+ switch (status.type) {
780
+ case "idle":
781
+ case "applying":
782
+ return null;
783
+ case "applied": {
784
+ const savings = formatPrice(
785
+ status.discount.discountCents,
786
+ status.discount.currency
787
+ );
788
+ return {
789
+ tone: "success",
790
+ message: `${status.discount.publicLabel} applied. You save ${savings}.`
791
+ };
792
+ }
793
+ case "rejected":
794
+ return {
795
+ tone: "error",
796
+ message: status.message
797
+ };
798
+ default:
799
+ return assertNever11(status);
800
+ }
801
+ }
802
+ var DISCOUNT_APPLY_MESSAGES = {
803
+ emptyCode: "Enter a discount code first.",
804
+ emailRequired: "Enter your email before applying a code.",
805
+ unavailable: "That code doesn't work for this checkout.",
806
+ unknown: "We couldn't check that code. Try again."
807
+ };
808
+ function useDiscountApply(options) {
809
+ return useCallback(async () => {
810
+ const discountCode = normalizeManualDiscountCode(options.state.draftCode);
811
+ if (!discountCode) {
812
+ options.dispatch({
813
+ type: "applyRejected",
814
+ reason: "empty_code",
815
+ message: DISCOUNT_APPLY_MESSAGES.emptyCode
816
+ });
817
+ return;
818
+ }
819
+ const email = normalizeCheckoutEmail(options.getCustomerEmail());
820
+ if (!email.ok) {
821
+ options.dispatch({
822
+ type: "applyRejected",
823
+ reason: "email_required",
824
+ message: DISCOUNT_APPLY_MESSAGES.emailRequired
825
+ });
826
+ return;
827
+ }
828
+ const linesPlan = options.getLines();
829
+ if (!linesPlan.ok || linesPlan.lines.length === 0) {
830
+ options.dispatch({
831
+ type: "applyRejected",
832
+ reason: "unavailable",
833
+ message: DISCOUNT_APPLY_MESSAGES.unavailable
834
+ });
835
+ return;
836
+ }
837
+ options.dispatch({ type: "applyStarted" });
838
+ try {
839
+ const result = await options.api.applyDiscountCode({
840
+ discountCode,
841
+ customerEmail: email.value,
842
+ lines: linesPlan.lines
843
+ });
844
+ if (result.type === "applied") {
845
+ options.dispatch({ type: "applySucceeded", discount: result });
846
+ return;
847
+ }
848
+ options.dispatch({
849
+ type: "applyRejected",
850
+ reason: result.reason,
851
+ message: result.message
852
+ });
853
+ } catch {
854
+ options.dispatch({
855
+ type: "applyRejected",
856
+ reason: "unknown",
857
+ message: DISCOUNT_APPLY_MESSAGES.unknown
858
+ });
859
+ }
860
+ }, [options]);
861
+ }
534
862
  var CHECKOUT_ANCHOR_ID = "shop-checkout";
535
863
  function ProductListController(props) {
536
864
  const api = useBlockApi();
@@ -764,6 +1092,10 @@ function CheckoutController(props) {
764
1092
  shopCheckoutReducer,
765
1093
  initialShopCheckoutState
766
1094
  );
1095
+ const [discountApply, dispatchDiscountApply] = React3.useReducer(
1096
+ discountApplyReducer,
1097
+ initialDiscountApplyState
1098
+ );
767
1099
  React3.useEffect(() => {
768
1100
  const checkout = consumeSearchParam("checkout");
769
1101
  if (checkout === "success") {
@@ -777,33 +1109,57 @@ function CheckoutController(props) {
777
1109
  () => getShopDisplayForItems(props.render, cart.items),
778
1110
  [cart.items, props.render]
779
1111
  );
1112
+ const checkoutState = React3.useMemo(
1113
+ () => deriveCommerceCheckoutState({ items: cart.items }),
1114
+ [cart.items]
1115
+ );
1116
+ const discountAvailabilityPlan = React3.useMemo(
1117
+ () => planCartDiscountAvailabilityRequests(checkoutState),
1118
+ [checkoutState]
1119
+ );
1120
+ const discountUiState = useCartDiscountUiState(api, discountAvailabilityPlan);
1121
+ const discountApplyFeedback = getDiscountApplyFeedback(
1122
+ discountApply.status,
1123
+ formatCommercePrice
1124
+ );
1125
+ React3.useEffect(() => {
1126
+ if (discountUiState.type === "manual-allowed") return;
1127
+ dispatchDiscountApply({ type: "remove" });
1128
+ }, [discountUiState.type]);
1129
+ const checkoutIdentity = React3.useMemo(() => {
1130
+ if (checkoutState.kind !== "ready") return checkoutState.kind;
1131
+ return checkoutState.items.map((item) => `${item.key}:${item.quantity}:${item.unitPriceCents}`).join("|");
1132
+ }, [checkoutState]);
1133
+ React3.useEffect(() => {
1134
+ dispatchDiscountApply({ type: "resetApplied" });
1135
+ }, [checkoutIdentity, state.form.email]);
1136
+ const applyDiscountCode = useDiscountApply({
1137
+ api,
1138
+ state: discountApply,
1139
+ dispatch: dispatchDiscountApply,
1140
+ getCustomerEmail: () => state.form.email,
1141
+ getLines: () => discountAvailabilityPlan.ok ? { ok: true, lines: discountAvailabilityPlan.value } : { ok: false }
1142
+ });
780
1143
  const handleSubmit = async (event) => {
781
1144
  event.preventDefault();
782
1145
  if (display.state !== "ready" || state.submission === "submitting") return;
783
1146
  dispatch({ type: "submitStarted" });
784
1147
  try {
785
1148
  const { successUrl, cancelUrl } = buildCheckoutReturnUrls("checkout", CHECKOUT_ANCHOR_ID);
786
- const checkoutItems = cart.items.map(
787
- (item) => item.kind === "product" ? {
788
- type: "product",
789
- productId: item.productId,
790
- ...item.variantId ? { variantId: item.variantId } : {},
791
- quantity: item.quantity
792
- } : {
793
- type: "pass",
794
- passId: item.passId
795
- }
796
- );
797
- const result = await api.createUnifiedCheckout({
798
- mode: "one_time",
799
- items: checkoutItems,
800
- customer: {
801
- email: state.form.email.trim().toLowerCase(),
802
- name: state.form.name.trim()
803
- },
1149
+ const command = planUnifiedCheckoutRequest({
1150
+ checkout: checkoutState,
1151
+ form: checkoutFormForDiscountUiState({
1152
+ ...state.form,
1153
+ discountCode: discountUiState.type === "manual-allowed" ? getAppliedDiscountCode(discountApply) ?? "" : ""
1154
+ }, discountUiState),
804
1155
  successUrl,
805
1156
  cancelUrl
806
1157
  });
1158
+ if (!command.ok) {
1159
+ dispatch({ type: "submitFailed", message: command.error.message });
1160
+ return;
1161
+ }
1162
+ const result = await api.createUnifiedCheckout(command.value);
807
1163
  if (result.type === "redirect") {
808
1164
  window.location.href = result.checkoutUrl;
809
1165
  return;
@@ -859,6 +1215,25 @@ function CheckoutController(props) {
859
1215
  }
860
1216
  )
861
1217
  ] }),
1218
+ discountUiState.type === "manual-allowed" ? /* @__PURE__ */ jsx(
1219
+ DiscountCodeDisclosure,
1220
+ {
1221
+ surface: "theme-form",
1222
+ isOpen: discountApply.isOpen,
1223
+ code: discountApply.draftCode,
1224
+ onOpen: () => dispatchDiscountApply({ type: "open" }),
1225
+ onChange: (draftCode) => dispatchDiscountApply({ type: "draftChanged", draftCode }),
1226
+ onRemove: () => dispatchDiscountApply({ type: "remove" }),
1227
+ onApply: applyDiscountCode,
1228
+ id: "shop-checkout-discount-code",
1229
+ hint: "Apply your code before checkout.",
1230
+ feedback: discountApplyFeedback,
1231
+ isApplying: isDiscountApplyInFlight(discountApply),
1232
+ disabled: state.submission === "submitting"
1233
+ }
1234
+ ) : null,
1235
+ discountUiState.type === "loading" ? /* @__PURE__ */ jsx(FeedbackMessage, { tone: "info", className: "rb-caption status-muted", role: "status", children: "Checking available discounts." }) : null,
1236
+ discountUiState.type === "auto-only" ? /* @__PURE__ */ jsx(FeedbackMessage, { tone: "info", className: "rb-caption status-muted", role: "status", children: discountUiState.autoAppliedDiscount ? `${discountUiState.autoAppliedDiscount.publicLabel} will be applied at checkout.` : "Eligible discounts will be applied at checkout." }) : null,
862
1237
  state.feedback.tag === "error" ? /* @__PURE__ */ jsx(
863
1238
  FeedbackMessage,
864
1239
  {
@@ -897,7 +1272,8 @@ function ProductListClient(props) {
897
1272
  // ../blocks/src/system/runtime/nodes/shop.state.ts
898
1273
  var EMPTY_FORM = {
899
1274
  email: "",
900
- name: ""
1275
+ name: "",
1276
+ discountCode: ""
901
1277
  };
902
1278
  var CLOSED_CHECKOUT = { tag: "closed" };
903
1279
  var initialShopPassesMembershipsState = {
@@ -993,7 +1369,7 @@ function shopPassesMembershipsReducer(state, action) {
993
1369
  returnNotice: null
994
1370
  };
995
1371
  default:
996
- return assertNever(action);
1372
+ return assertNever11(action);
997
1373
  }
998
1374
  }
999
1375
  function getOpenCheckout(state) {
@@ -1008,12 +1384,29 @@ function getCheckoutModalTitle(checkout) {
1008
1384
  if (checkout.item.productType === "membership") return "Subscribe to Membership";
1009
1385
  return checkout.item.product.productUseCase === "appointment_package" ? "Purchase Package" : "Purchase Pass";
1010
1386
  }
1387
+ function getCheckoutDiscountApplyLine(checkout) {
1388
+ return {
1389
+ context: checkout.item.productType === "pass" ? {
1390
+ type: "pass",
1391
+ passId: checkout.item.product.id
1392
+ } : {
1393
+ type: "membership",
1394
+ membershipId: checkout.item.product.id
1395
+ },
1396
+ subtotalCents: Math.max(0, checkout.item.product.price),
1397
+ currency: checkout.item.product.currency
1398
+ };
1399
+ }
1011
1400
  function PassesMembershipsController({ render }) {
1012
1401
  const api = useBlockApi();
1013
1402
  const [state, dispatch] = React3__default.useReducer(
1014
1403
  shopPassesMembershipsReducer,
1015
1404
  initialShopPassesMembershipsState
1016
1405
  );
1406
+ const [discountApply, dispatchDiscountApply] = React3__default.useReducer(
1407
+ discountApplyReducer,
1408
+ initialDiscountApplyState
1409
+ );
1017
1410
  const passAddFeedback = useTransientShopAddFeedback();
1018
1411
  const [modalPortalRoot, setModalPortalRoot] = useState(null);
1019
1412
  const shopRootRef = useRef(null);
@@ -1023,6 +1416,19 @@ function PassesMembershipsController({ render }) {
1023
1416
  const display = render.display;
1024
1417
  const hydration = render.hydration;
1025
1418
  const checkoutTitle = getCheckoutModalTitle(checkout);
1419
+ const discountContext = React3__default.useMemo(() => {
1420
+ if (!checkout) return null;
1421
+ return checkout.item.productType === "pass" ? { type: "pass", passId: checkout.item.product.id } : { type: "membership", membershipId: checkout.item.product.id };
1422
+ }, [checkout]);
1423
+ const discountUi = useDiscountCodeUi({
1424
+ api,
1425
+ discountContext,
1426
+ subtotalCents: checkout?.item.product.price
1427
+ });
1428
+ const discountApplyFeedback = getDiscountApplyFeedback(
1429
+ discountApply.status,
1430
+ formatCommercePrice
1431
+ );
1026
1432
  const handleBuyPass = useCallback((pass) => {
1027
1433
  if (hydration.passPurchaseMode === "add_to_cart") {
1028
1434
  addPassToCommerceCart(api.config.siteId, {
@@ -1053,6 +1459,13 @@ function PassesMembershipsController({ render }) {
1053
1459
  focusedCheckoutKeyRef.current = checkoutKey;
1054
1460
  }
1055
1461
  }, [checkout]);
1462
+ useEffect(() => {
1463
+ dispatchDiscountApply({ type: "resetApplied" });
1464
+ }, [checkout?.form.email, checkout?.item.product.id, checkout?.item.productType]);
1465
+ useEffect(() => {
1466
+ if (checkout && discountUi.manualCodeEntryAllowed) return;
1467
+ dispatchDiscountApply({ type: "remove" });
1468
+ }, [checkout, discountUi.manualCodeEntryAllowed]);
1056
1469
  useEffect(() => {
1057
1470
  const sourceEl = shopRootRef.current;
1058
1471
  if (!sourceEl) return;
@@ -1079,16 +1492,6 @@ function PassesMembershipsController({ render }) {
1079
1492
  }, []);
1080
1493
  const submitCheckout = useCallback(async (confirmDuplicate = false) => {
1081
1494
  if (!checkout) return;
1082
- const email = checkout.form.email.trim().toLowerCase();
1083
- const name = checkout.form.name.trim();
1084
- if (!email || !name) {
1085
- dispatch({ type: "submitFailed", error: "Please enter your email and name" });
1086
- return;
1087
- }
1088
- if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
1089
- dispatch({ type: "submitFailed", error: "Please enter a valid email address" });
1090
- return;
1091
- }
1092
1495
  dispatch({ type: "submitStarted" });
1093
1496
  try {
1094
1497
  const currentUrl = window.location.href;
@@ -1097,38 +1500,53 @@ function PassesMembershipsController({ render }) {
1097
1500
  successUrl.searchParams.set("product", checkout.item.product.id);
1098
1501
  const cancelUrl = new URL(currentUrl);
1099
1502
  cancelUrl.searchParams.set("checkout", "cancelled");
1100
- const result = await api.createShopCheckout({
1503
+ const form = {
1504
+ ...checkout.form,
1505
+ discountCode: discountUi.manualCodeEntryAllowed ? getAppliedDiscountCode(discountApply) ?? "" : ""
1506
+ };
1507
+ const command = planDirectShopCheckoutRequest({
1101
1508
  productType: checkout.item.productType,
1102
1509
  productId: checkout.item.product.id,
1103
- customerEmail: email,
1104
- customerName: name,
1510
+ form,
1105
1511
  successUrl: successUrl.toString(),
1106
1512
  cancelUrl: cancelUrl.toString(),
1107
1513
  confirmDuplicate
1108
1514
  });
1109
- if ("warning" in result && result.warning === "duplicate_membership") {
1110
- dispatch({
1111
- type: "submitDuplicateWarning",
1112
- warning: result
1113
- });
1515
+ if (!command.ok) {
1516
+ dispatch({ type: "submitFailed", error: command.error.message });
1114
1517
  return;
1115
1518
  }
1116
- if ("bypassed" in result && result.bypassed) {
1117
- window.location.href = successUrl.toString();
1118
- return;
1519
+ const result = await api.createShopCheckout(command.value);
1520
+ switch (result.type) {
1521
+ case "duplicate_membership_warning":
1522
+ dispatch({
1523
+ type: "submitDuplicateWarning",
1524
+ warning: result
1525
+ });
1526
+ return;
1527
+ case "bypassed":
1528
+ window.location.href = successUrl.toString();
1529
+ return;
1530
+ case "redirect":
1531
+ window.location.href = result.checkoutUrl;
1532
+ return;
1533
+ default:
1534
+ return assertNever(result);
1119
1535
  }
1120
- if ("checkoutUrl" in result && result.checkoutUrl) {
1121
- window.location.href = result.checkoutUrl;
1122
- return;
1123
- }
1124
- throw new Error("No checkout URL returned");
1125
1536
  } catch (submitError) {
1126
1537
  dispatch({
1127
1538
  type: "submitFailed",
1128
1539
  error: submitError instanceof Error ? submitError.message : "An error occurred"
1129
1540
  });
1130
1541
  }
1131
- }, [api, checkout]);
1542
+ }, [api, checkout, discountApply, discountUi.manualCodeEntryAllowed]);
1543
+ const applyDiscountCode = useDiscountApply({
1544
+ api,
1545
+ state: discountApply,
1546
+ dispatch: dispatchDiscountApply,
1547
+ getCustomerEmail: () => checkout?.form.email ?? "",
1548
+ getLines: () => checkout ? { ok: true, lines: [getCheckoutDiscountApplyLine(checkout)] } : { ok: false }
1549
+ });
1132
1550
  const handleFormSubmit = useCallback((event) => {
1133
1551
  event.preventDefault();
1134
1552
  submitCheckout(false);
@@ -1318,6 +1736,34 @@ function PassesMembershipsController({ render }) {
1318
1736
  }
1319
1737
  )
1320
1738
  ] }),
1739
+ discountUi.manualCodeEntryAllowed ? /* @__PURE__ */ jsx(
1740
+ DiscountCodeDisclosure,
1741
+ {
1742
+ surface: "theme-form",
1743
+ isOpen: discountApply.isOpen,
1744
+ code: discountApply.draftCode,
1745
+ onOpen: () => dispatchDiscountApply({ type: "open" }),
1746
+ onChange: (draftCode) => dispatchDiscountApply({ type: "draftChanged", draftCode }),
1747
+ onRemove: () => {
1748
+ dispatchDiscountApply({ type: "remove" });
1749
+ },
1750
+ onApply: applyDiscountCode,
1751
+ id: "shop-discount-code",
1752
+ hint: "Apply your code before checkout.",
1753
+ feedback: discountApplyFeedback,
1754
+ isApplying: isDiscountApplyInFlight(discountApply),
1755
+ disabled: checkout.submitting
1756
+ }
1757
+ ) : null,
1758
+ !discountUi.discountsAvailableLoading && discountUi.discountsAvailable && !discountUi.manualCodeEntryAllowed ? /* @__PURE__ */ jsx(
1759
+ FeedbackMessage,
1760
+ {
1761
+ tone: "info",
1762
+ className: "shop__modal-discount",
1763
+ role: "status",
1764
+ children: "Eligible discounts will be applied at checkout."
1765
+ }
1766
+ ) : null,
1321
1767
  checkout.formError ? /* @__PURE__ */ jsx(
1322
1768
  FeedbackMessage,
1323
1769
  {