@riverbankcms/sdk 0.91.0 → 0.92.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 (104) hide show
  1. package/dist/{PreviewEditorSidebar-3TT47WCF.mjs → PreviewEditorSidebar-3CI5MKV3.mjs} +2 -2
  2. package/dist/{PreviewEditorUI-ORCLLUNZ.mjs → PreviewEditorUI-DKEP636I.mjs} +2 -2
  3. package/dist/SdkPreviewModeRuntime-BRGRDQFH.mjs +8 -0
  4. package/dist/_dts/api/src/bookingConfig.d.ts +13 -1
  5. package/dist/_dts/api/src/bookingOperations.d.ts +1 -0
  6. package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +6 -6
  7. package/dist/_dts/api/src/customerMembershipOutcomes.d.ts +4 -4
  8. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +6 -0
  9. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +32 -0
  10. package/dist/_dts/blocks/src/system/blocks/courses/shared/pricing.d.ts +12 -1
  11. package/dist/_dts/blocks/src/system/blocks/courses/shared/schemas.d.ts +12 -0
  12. package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +4 -1
  13. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +44 -0
  14. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +7 -0
  15. package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +8 -1
  16. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.d.ts +8 -1
  17. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.d.ts +1 -0
  18. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +4 -0
  19. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +40 -0
  20. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.reserved-fields.d.ts +1 -1
  21. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +29 -0
  22. package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +1 -0
  23. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/components.d.ts +6 -0
  24. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.d.ts +8 -0
  25. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +8 -0
  26. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +1 -0
  27. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +1 -1
  28. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +1 -0
  29. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +9 -0
  30. package/dist/_dts/content-model/src/entry-slots/types.d.ts +110 -2
  31. package/dist/_dts/core/src/branded.d.ts +3 -0
  32. package/dist/_dts/core/src/event-pricing.d.ts +18 -1
  33. package/dist/_dts/core/src/money-input.d.ts +34 -4
  34. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +70 -0
  35. package/dist/_dts/media-core/src/fileAssetCompatibility.d.ts +1 -1
  36. package/dist/_dts/media-core/src/filePersistence.d.ts +5 -1
  37. package/dist/_dts/media-core/src/fileStorage.d.ts +1 -0
  38. package/dist/_dts/media-core/src/videoPrep.d.ts +15 -6
  39. package/dist/_dts/media-core/src/videoSlotPolicy.d.ts +5 -5
  40. package/dist/_dts/sdk/src/cli/commands/push/execute/diff.d.ts +2 -0
  41. package/dist/_dts/sdk/src/cli/commands/push/execute/localMediaReporting.d.ts +23 -0
  42. package/dist/_dts/sdk/src/cli/commands/push/scopes/commandBackedDatedOfferingScope.d.ts +54 -0
  43. package/dist/_dts/sdk/src/cli/commands/push/scopes/mediaPrep.d.ts +7 -2
  44. package/dist/_dts/sdk/src/cli/commands/push/scopes/types.d.ts +6 -0
  45. package/dist/_dts/sdk/src/cli/media/local-sync.d.ts +35 -0
  46. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +23 -1
  47. package/dist/_dts/sdk/src/version.d.ts +1 -1
  48. package/dist/{chunk-AFPMCLS7.mjs → chunk-6D7PLF4M.mjs} +1 -1
  49. package/dist/{chunk-RQUZYSES.mjs → chunk-I6EOKV6B.mjs} +520 -40
  50. package/dist/{chunk-S3YHJWEU.mjs → chunk-LERKJM3E.mjs} +5 -5
  51. package/dist/{chunk-GDT2QGIL.mjs → chunk-UOMTCHZD.mjs} +1 -1
  52. package/dist/cli/index.mjs +552 -80
  53. package/dist/client/{accordion-AFX37652.mjs → accordion-BUDH2G3S.mjs} +2 -2
  54. package/dist/client/{bookingForm-32V5QCOW.mjs → bookingForm-NQMCELVB.mjs} +89 -14
  55. package/dist/client/bookings.mjs +243 -17
  56. package/dist/client/{carousel-TJGQJ7ER.mjs → carousel-ONCEW6IJ.mjs} +3 -3
  57. package/dist/client/{cart-JUU2JEW4.mjs → cart-V2TCK2GI.mjs} +7 -7
  58. package/dist/client/{checkout-RD6BTFX4.mjs → checkout-ZI7SWNCS.mjs} +7 -7
  59. package/dist/client/{chunk-FMZZHAIR.mjs → chunk-AUMRQ242.mjs} +52 -5
  60. package/dist/client/{chunk-PMNAV6LO.mjs → chunk-B5UC2D6X.mjs} +7 -6
  61. package/dist/client/{chunk-6RN62XBV.mjs → chunk-ERQDHUS2.mjs} +1 -1
  62. package/dist/client/{chunk-RWYFG625.mjs → chunk-GH6IIOOE.mjs} +30 -2
  63. package/dist/client/{chunk-C4LP6BPG.mjs → chunk-HQWIJLYN.mjs} +1 -1
  64. package/dist/client/{chunk-RMOFBBNA.mjs → chunk-JXY6NHG6.mjs} +6 -6
  65. package/dist/client/{chunk-6QZIBNGV.mjs → chunk-KXYEKEV6.mjs} +154 -16
  66. package/dist/client/{chunk-E6VIWZUG.mjs → chunk-N2WJPTF7.mjs} +3 -3
  67. package/dist/client/{chunk-ISAUXU5R.mjs → chunk-QQNVQ62W.mjs} +1 -1
  68. package/dist/client/{chunk-MLBNVN4H.mjs → chunk-R3CZQLXF.mjs} +67 -4
  69. package/dist/client/{chunk-WHZQDPBZ.mjs → chunk-TNGL2WJF.mjs} +1 -0
  70. package/dist/client/{chunk-CKXEUWWA.mjs → chunk-ZJDBOLX7.mjs} +3 -3
  71. package/dist/client/client.mjs +515 -38
  72. package/dist/client/{courseRegistration-X63QAIVV.mjs → courseRegistration-JPWAQ6KM.mjs} +111 -11
  73. package/dist/client/{eventCalendar-5T24GCZL.mjs → eventCalendar-QDOCHBBV.mjs} +9 -9
  74. package/dist/client/{eventCombined-AZVTF22X.mjs → eventCombined-ZS2CXSIE.mjs} +9 -9
  75. package/dist/client/{eventDetails-7GPFNLGF.mjs → eventDetails-5LOBMPLN.mjs} +9 -9
  76. package/dist/client/{eventListing-QEUMTMUM.mjs → eventListing-SBGY4I3L.mjs} +9 -9
  77. package/dist/client/{eventRegistration-P2EDKCQZ.mjs → eventRegistration-XGPIU3Z2.mjs} +9 -9
  78. package/dist/client/{form-NUJ7H4IN.mjs → form-R7D4LZWW.mjs} +3 -3
  79. package/dist/client/{headerSection-JB7LECPL.mjs → headerSection-RRLYUCGC.mjs} +3 -3
  80. package/dist/client/hooks.mjs +22 -2
  81. package/dist/client/{locationMap-UEYWUCSW.mjs → locationMap-35ZJMRBZ.mjs} +3 -3
  82. package/dist/client/{newsletterForm-S2YZQ2X7.mjs → newsletterForm-MJ2VCFUT.mjs} +3 -3
  83. package/dist/client/{productDetail-H5MADGG7.mjs → productDetail-2O7YQNBX.mjs} +7 -7
  84. package/dist/client/{productList-DK7YON7H.mjs → productList-FDP5BH7W.mjs} +7 -7
  85. package/dist/client/rendering/client.mjs +495 -36
  86. package/dist/client/rendering/islands.mjs +19 -19
  87. package/dist/client/rendering.mjs +514 -37
  88. package/dist/client/{shop-6PA7RDRJ.mjs → shop-BGYJ3LDT.mjs} +7 -7
  89. package/dist/preview-next/client/runtime.mjs +3 -3
  90. package/dist/{sdk-runtime-JP5347OB.mjs → sdk-runtime-B3TFXRXZ.mjs} +4 -4
  91. package/dist/server/components.mjs +166 -7
  92. package/dist/server/config-validation.mjs +23 -2
  93. package/dist/server/config.mjs +23 -2
  94. package/dist/server/data.mjs +22 -2
  95. package/dist/server/index.mjs +1 -1
  96. package/dist/server/next.mjs +167 -8
  97. package/dist/server/page-converter.mjs +19 -2
  98. package/dist/server/prebuild.mjs +1 -1
  99. package/dist/server/rendering/server.mjs +166 -7
  100. package/dist/server/rendering.mjs +166 -7
  101. package/dist/server/routing.mjs +29 -5
  102. package/dist/server/server.mjs +23 -3
  103. package/package.json +1 -1
  104. package/dist/SdkPreviewModeRuntime-GMCDQPZZ.mjs +0 -8
@@ -3576,6 +3576,7 @@ function createBlockApi(config) {
3576
3576
  body: {
3577
3577
  courseId: data.courseId,
3578
3578
  ...data.pricingOptionId ? { pricingOptionId: data.pricingOptionId } : {},
3579
+ ...data.selectedSlidingAmount !== void 0 ? { selectedSlidingAmount: data.selectedSlidingAmount } : {},
3579
3580
  email: data.email,
3580
3581
  name: data.name,
3581
3582
  phone: data.phone,
@@ -5287,6 +5288,7 @@ function publicEventPricingType(pricing) {
5287
5288
  return "free";
5288
5289
  case "single_paid":
5289
5290
  case "ticket_types":
5291
+ case "sliding_scale":
5290
5292
  case "course":
5291
5293
  return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
5292
5294
  case "external":
@@ -5303,6 +5305,8 @@ function publicEventPricingMode(pricing) {
5303
5305
  return "single";
5304
5306
  case "ticket_types":
5305
5307
  return "ticket_types";
5308
+ case "sliding_scale":
5309
+ return "sliding_scale";
5306
5310
  case "drop_in":
5307
5311
  case "course":
5308
5312
  case "external":
@@ -6042,6 +6046,7 @@ var BOOKING_FORM_DATA_RESERVED_KEY_VALUES = [
6042
6046
  "selectedDate",
6043
6047
  "selectedSlot",
6044
6048
  "discountCode",
6049
+ "selectedSlidingAmountInput",
6045
6050
  "selectedCollectionOptionKind",
6046
6051
  "selectedAppointmentPackageId"
6047
6052
  ];
@@ -6325,6 +6330,32 @@ function readOptionalString(value) {
6325
6330
  function readOptionalNumber(value) {
6326
6331
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
6327
6332
  }
6333
+ function getBookingServiceSlidingScale(service) {
6334
+ const pricing = service?.pricing;
6335
+ if (!pricing || pricing.pricingStrategy !== "sliding_scale" || pricing.slidingMinAmount === null || pricing.slidingMinAmount === void 0 || pricing.slidingMaxAmount === null || pricing.slidingMaxAmount === void 0) {
6336
+ return null;
6337
+ }
6338
+ return {
6339
+ minAmount: pricing.slidingMinAmount,
6340
+ maxAmount: pricing.slidingMaxAmount,
6341
+ suggestedAmount: pricing.slidingSuggestedAmount ?? null,
6342
+ currency: pricing.currency
6343
+ };
6344
+ }
6345
+ function parseBookingCurrencyInputToCents(value) {
6346
+ const trimmed = value?.trim() ?? "";
6347
+ if (!trimmed) return null;
6348
+ if (!/^(?:\d+(?:\.\d{0,2})?|\.\d{1,2})$/.test(trimmed)) return null;
6349
+ const parsed = Number(trimmed);
6350
+ if (!Number.isFinite(parsed) || parsed < 0) return null;
6351
+ return Math.round(parsed * 100);
6352
+ }
6353
+ function formatBookingCentsAsCurrencyInput(amount) {
6354
+ return amount % 100 === 0 ? String(amount / 100) : (amount / 100).toFixed(2);
6355
+ }
6356
+ function isBookingServiceSlidingAmountInRange(slidingScale, selectedAmount) {
6357
+ return selectedAmount !== null && selectedAmount >= slidingScale.minAmount && selectedAmount <= slidingScale.maxAmount;
6358
+ }
6328
6359
  function readStringArray(value) {
6329
6360
  if (!Array.isArray(value)) return void 0;
6330
6361
  const strings = value.filter((item) => typeof item === "string");
@@ -6513,6 +6544,20 @@ function prepareBookingSubmission(input) {
6513
6544
  };
6514
6545
  }
6515
6546
  const paymentSelectionMode = getBookingServicePaymentSelectionMode(selectedService);
6547
+ const slidingScale = getBookingServiceSlidingScale(selectedService);
6548
+ const selectedSlidingAmount = parseBookingCurrencyInputToCents(
6549
+ input.data.selectedSlidingAmountInput
6550
+ );
6551
+ if (slidingScale && !isBookingServiceSlidingAmountInRange(slidingScale, selectedSlidingAmount)) {
6552
+ return {
6553
+ ok: false,
6554
+ error: {
6555
+ tag: selectedSlidingAmount === null ? "sliding-amount-required" : "sliding-amount-out-of-range",
6556
+ serviceId,
6557
+ serviceTitle: selectedService.title || serviceId
6558
+ }
6559
+ };
6560
+ }
6516
6561
  if (paymentSelectionMode === "choice_required" && !toSelectedCollectionOptionKind(input.data.selectedCollectionOptionKind)) {
6517
6562
  return {
6518
6563
  ok: false,
@@ -6540,6 +6585,7 @@ function prepareBookingSubmission(input) {
6540
6585
  ...common,
6541
6586
  kind: "standard",
6542
6587
  ...discountCode ? { discountCode } : {},
6588
+ ...slidingScale && selectedSlidingAmount !== null ? { selectedSlidingAmount } : {},
6543
6589
  ...selectedCollectionOptionKind ? { selectedCollectionOptionKind } : {},
6544
6590
  altchaSolution: input.altchaSolution ?? null
6545
6591
  }
@@ -6553,6 +6599,10 @@ function formatBookingSubmissionPreparationError(error) {
6553
6599
  return `Service not found: ${error.serviceId}`;
6554
6600
  case "payment-option-required":
6555
6601
  return `Please choose how you want to pay for "${error.serviceTitle}".`;
6602
+ case "sliding-amount-required":
6603
+ return `Please choose an amount for "${error.serviceTitle}".`;
6604
+ case "sliding-amount-out-of-range":
6605
+ return `Please choose an amount within the sliding scale for "${error.serviceTitle}".`;
6556
6606
  case "payment-option-unsupported":
6557
6607
  return `Service "${error.serviceTitle}" has a payment option that is not supported yet.`;
6558
6608
  case "service-missing-duration":
@@ -6676,9 +6726,12 @@ var coursePricingOptionSchema = z9.object({
6676
6726
  });
6677
6727
  var coursePricingSchema = z9.object({
6678
6728
  bookingRequirement: z9.enum(["none", "required"]),
6679
- pricingStrategy: z9.enum(["free", "single", "tiered"]),
6729
+ pricingStrategy: z9.enum(["free", "single", "tiered", "sliding_scale"]),
6680
6730
  currency: z9.string(),
6681
6731
  singlePriceAmount: z9.number().nullable(),
6732
+ slidingMinAmount: z9.number().nullable().optional(),
6733
+ slidingMaxAmount: z9.number().nullable().optional(),
6734
+ slidingSuggestedAmount: z9.number().nullable().optional(),
6682
6735
  paymentTerms: blockBookingPaymentTermsSchema,
6683
6736
  options: z9.array(coursePricingOptionSchema)
6684
6737
  });
@@ -6781,7 +6834,7 @@ function isRecord4(value) {
6781
6834
  }
6782
6835
  function isPublicEventPricing(value) {
6783
6836
  if (!isRecord4(value) || typeof value.kind !== "string") return false;
6784
- return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
6837
+ return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "sliding_scale" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
6785
6838
  }
6786
6839
  function isPublicEventTicketType(value) {
6787
6840
  return isRecord4(value) && typeof value.id === "string";
@@ -7068,6 +7121,19 @@ var publicEventPricingSchema = z12.discriminatedUnion("kind", [
7068
7121
  ticketTypes: z12.array(publicEventTicketTypeSchema),
7069
7122
  display: publicEventTicketTypePriceDisplaySchema
7070
7123
  }),
7124
+ z12.object({
7125
+ kind: z12.literal("sliding_scale"),
7126
+ minAmount: z12.number(),
7127
+ maxAmount: z12.number(),
7128
+ suggestedAmount: z12.number().nullable(),
7129
+ currency: z12.string(),
7130
+ display: z12.object({
7131
+ kind: z12.literal("range"),
7132
+ minAmount: z12.number(),
7133
+ maxAmount: z12.number(),
7134
+ currency: z12.string()
7135
+ })
7136
+ }),
7071
7137
  z12.object({
7072
7138
  kind: z12.literal("course"),
7073
7139
  display: z12.object({ kind: z12.literal("course"), display: publicCoursePriceDisplaySchema })
@@ -13042,6 +13108,7 @@ function useBookingSubmission(_siteId) {
13042
13108
  customFields: data.customFields,
13043
13109
  timezone: data.timezone,
13044
13110
  discountCode: data.discountCode,
13111
+ selectedSlidingAmount: data.selectedSlidingAmount,
13045
13112
  selectedCollectionOptionKind: data.selectedCollectionOptionKind,
13046
13113
  altchaSolution: data.altchaSolution ?? null,
13047
13114
  successUrl: data.successUrl,
@@ -13524,6 +13591,9 @@ function createInitialBookingFlowReducerState(input) {
13524
13591
  fieldValues: collectInitialFieldValues(initialData),
13525
13592
  touchedFields: {},
13526
13593
  discountCode: toOptionalString(initialData.discountCode) ?? "",
13594
+ selectedSlidingAmountInput: toOptionalString(
13595
+ initialData.selectedSlidingAmountInput
13596
+ ) ?? "",
13527
13597
  selectedCollectionOptionKind: toSelectedCollectionOptionKind(
13528
13598
  initialData.selectedCollectionOptionKind
13529
13599
  ),
@@ -13579,6 +13649,7 @@ function bookingFlowReducer(state, event) {
13579
13649
  selectedDate: void 0,
13580
13650
  selectedSlot: null,
13581
13651
  selectedAppointmentPackageId: void 0,
13652
+ selectedSlidingAmountInput: "",
13582
13653
  selectedCollectionOptionKind: void 0,
13583
13654
  validationErrors: clearBookingFormError(state.validationErrors)
13584
13655
  };
@@ -13632,6 +13703,13 @@ function bookingFlowReducer(state, event) {
13632
13703
  selectedAppointmentPackageId: void 0,
13633
13704
  validationErrors: clearBookingFormError(state.validationErrors)
13634
13705
  };
13706
+ case "sliding-amount-changed":
13707
+ return {
13708
+ ...state,
13709
+ selectedSlidingAmountInput: event.value,
13710
+ selectedAppointmentPackageId: void 0,
13711
+ validationErrors: clearBookingFormError(state.validationErrors)
13712
+ };
13635
13713
  case "appointment-package-selected":
13636
13714
  return {
13637
13715
  ...state,
@@ -13734,6 +13812,7 @@ function toBookingFormData(state) {
13734
13812
  selectedDate: state.selectedDate,
13735
13813
  selectedSlot: state.selectedSlot?.startAt,
13736
13814
  discountCode: state.discountCode || void 0,
13815
+ selectedSlidingAmountInput: state.selectedSlidingAmountInput || void 0,
13737
13816
  selectedCollectionOptionKind: state.selectedCollectionOptionKind,
13738
13817
  selectedAppointmentPackageId: state.selectedAppointmentPackageId
13739
13818
  };
@@ -13751,7 +13830,8 @@ function buildBookingStepResolution(input) {
13751
13830
  input.form.settings?.serviceIds && input.form.settings.serviceIds.length > 1
13752
13831
  );
13753
13832
  const selectedService = paymentResolution.service;
13754
- const needsPayment = paymentResolution.mode !== "hidden" || Boolean(
13833
+ const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
13834
+ const needsPayment = Boolean(selectedServiceSlidingScale) || paymentResolution.mode !== "hidden" || Boolean(
13755
13835
  input.enableAppointmentPackages && selectedService && (selectedService.priceAmount ?? 0) > 0
13756
13836
  );
13757
13837
  const hasFields = Boolean(input.form.schema?.fields.length);
@@ -13795,6 +13875,18 @@ function validateBookingStep(input) {
13795
13875
  services: input.services,
13796
13876
  defaultServiceId: input.defaultServiceId
13797
13877
  });
13878
+ const slidingScale = getBookingServiceSlidingScale(resolution.service);
13879
+ if (slidingScale && !isBookingServiceSlidingAmountInRange(
13880
+ slidingScale,
13881
+ parseBookingCurrencyInputToCents(input.data.selectedSlidingAmountInput)
13882
+ )) {
13883
+ return {
13884
+ ok: false,
13885
+ errors: createFormBookingValidationError(
13886
+ "Please choose an amount within the sliding scale"
13887
+ )
13888
+ };
13889
+ }
13798
13890
  if (resolution.mode === "hidden" || resolution.mode === "disclosure_only") {
13799
13891
  return { ok: true };
13800
13892
  }
@@ -14296,11 +14388,27 @@ function useHeadlessBookingFlow(options) {
14296
14388
  const selectedServiceId = state.selectedServiceId ?? defaultServiceId;
14297
14389
  const selectedResourceId = state.selectedResourceId ?? defaultResourceId;
14298
14390
  const selectedService = options.services.find((service) => service.id === selectedServiceId) ?? null;
14391
+ const lastSlidingServiceIdRef = useRef6(null);
14392
+ useEffect6(() => {
14393
+ const selectedId = selectedService?.id ?? null;
14394
+ if (lastSlidingServiceIdRef.current === selectedId) return;
14395
+ lastSlidingServiceIdRef.current = selectedId;
14396
+ const slidingScale = getBookingServiceSlidingScale(selectedService);
14397
+ dispatch({
14398
+ type: "sliding-amount-changed",
14399
+ value: slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatBookingCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
14400
+ });
14401
+ }, [selectedService]);
14299
14402
  const hasPortalBearerAuth = (api.config.authOverrides?.portal ?? api.config.auth).type === "bearer";
14403
+ const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
14404
+ const selectedSlidingAmount = parseBookingCurrencyInputToCents(
14405
+ state.selectedSlidingAmountInput
14406
+ );
14407
+ const selectedAppointmentPriceAmount = selectedServiceSlidingScale && selectedSlidingAmount !== null ? selectedSlidingAmount : selectedService?.priceAmount ?? 0;
14300
14408
  const canLoadAppointmentPackages = Boolean(
14301
- options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && (selectedService.priceAmount ?? 0) > 0
14409
+ options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && !selectedServiceSlidingScale && (selectedService.priceAmount ?? 0) > 0
14302
14410
  );
14303
- const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
14411
+ const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || selectedServiceSlidingScale || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
14304
14412
  const data = useMemo2(() => toBookingFormData(state), [state]);
14305
14413
  const availabilityDatesQuery = useMemo2(
14306
14414
  () => buildBookingAvailabilityQuery({
@@ -14530,13 +14638,13 @@ function useHeadlessBookingFlow(options) {
14530
14638
  state.selectedSlot
14531
14639
  ]);
14532
14640
  const appointmentDiscountContext = useMemo2(
14533
- () => selectedService && (selectedService.priceAmount ?? 0) > 0 ? { type: "appointment", serviceId: selectedService.id } : null,
14534
- [selectedService?.id, selectedService?.priceAmount]
14641
+ () => selectedService && selectedAppointmentPriceAmount > 0 ? { type: "appointment", serviceId: selectedService.id } : null,
14642
+ [selectedAppointmentPriceAmount, selectedService?.id]
14535
14643
  );
14536
14644
  const discountUi = useDiscountCodeUi({
14537
14645
  api,
14538
14646
  discountContext: appointmentDiscountContext,
14539
- subtotalCents: selectedService?.priceAmount ?? 0
14647
+ subtotalCents: selectedAppointmentPriceAmount
14540
14648
  });
14541
14649
  const { submit, clearFeedback } = useBookingSubmission(options.siteId);
14542
14650
  const submittingRef = useRef6(false);
@@ -14679,6 +14787,7 @@ function useHeadlessBookingFlow(options) {
14679
14787
  type: "appointment-package-selected",
14680
14788
  packageId: packageId ? unsafeAsCustomerPassId(packageId) : null
14681
14789
  }),
14790
+ setSlidingAmountInput: (value) => dispatch({ type: "sliding-amount-changed", value }),
14682
14791
  setDiscountCode: (code) => {
14683
14792
  dispatch({ type: "discount-code-changed", code });
14684
14793
  latestRef.current.setDiscountCode(code);
@@ -14749,11 +14858,11 @@ function useHeadlessBookingFlow(options) {
14749
14858
  () => selectedService && paymentResolution.mode !== "unsupported" ? buildBookingPaymentSelectionViewModel({
14750
14859
  serviceTitle: selectedService.title,
14751
14860
  paymentTerms: selectedService.paymentTerms,
14752
- priceAmount: selectedService.priceAmount,
14861
+ priceAmount: selectedAppointmentPriceAmount,
14753
14862
  priceCurrency: selectedService.priceCurrency,
14754
14863
  bookingStartAt: state.selectedSlot?.startAt
14755
14864
  }) : null,
14756
- [paymentResolution.mode, selectedService, state.selectedSlot?.startAt]
14865
+ [paymentResolution.mode, selectedAppointmentPriceAmount, selectedService, state.selectedSlot?.startAt]
14757
14866
  );
14758
14867
  const appointmentPackageItems = appointmentPackages.tag === "loaded" ? appointmentPackages.value : [];
14759
14868
  const selectedAppointmentPackage = appointmentPackageItems.find(
@@ -14782,6 +14891,9 @@ function useHeadlessBookingFlow(options) {
14782
14891
  selection: null,
14783
14892
  selectedCollectionOptionKind: state.selectedCollectionOptionKind,
14784
14893
  selectedAppointmentPackageId: state.selectedAppointmentPackageId,
14894
+ selectedSlidingAmountInput: state.selectedSlidingAmountInput,
14895
+ selectedSlidingAmount,
14896
+ slidingScale: selectedServiceSlidingScale,
14785
14897
  appointmentPackages: appointmentPackagesModel,
14786
14898
  errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now."
14787
14899
  } : {
@@ -14790,6 +14902,9 @@ function useHeadlessBookingFlow(options) {
14790
14902
  selection: paymentSelection,
14791
14903
  selectedCollectionOptionKind: state.selectedCollectionOptionKind,
14792
14904
  selectedAppointmentPackageId: state.selectedAppointmentPackageId,
14905
+ selectedSlidingAmountInput: state.selectedSlidingAmountInput,
14906
+ selectedSlidingAmount,
14907
+ slidingScale: selectedServiceSlidingScale,
14793
14908
  appointmentPackages: appointmentPackagesModel
14794
14909
  };
14795
14910
  return {
@@ -15352,6 +15467,9 @@ var paymentOptionLayoutStyle = {
15352
15467
  var summaryStackStyle = {
15353
15468
  gap: "0.125rem"
15354
15469
  };
15470
+ function formatBookingAmount(amount, currency) {
15471
+ return formatCurrencyAmount(amount, currency, { decimals: "auto" });
15472
+ }
15355
15473
  function HeadlessBookingDefaultForm({
15356
15474
  booking,
15357
15475
  onSubmit
@@ -15628,6 +15746,7 @@ function HeadlessBookingPaymentSelectionStep({
15628
15746
  }
15629
15747
  const packageOptions = booking.payment.appointmentPackages.items;
15630
15748
  const hasPackageOptions = packageOptions.length > 0;
15749
+ const slidingScale = booking.payment.slidingScale;
15631
15750
  return /* @__PURE__ */ jsxs7("div", { className: "ab-stack", children: [
15632
15751
  /* @__PURE__ */ jsxs7("div", { className: "ab-info-box", children: [
15633
15752
  /* @__PURE__ */ jsx9("h3", { className: "ab-subtitle", children: viewModel.sectionTitle }),
@@ -15638,6 +15757,28 @@ function HeadlessBookingPaymentSelectionStep({
15638
15757
  booking.payment.appointmentPackages.state.message,
15639
15758
  " You can continue with the normal payment option."
15640
15759
  ] }) : null,
15760
+ slidingScale ? /* @__PURE__ */ jsxs7("div", { className: "rb-space-y-2", children: [
15761
+ /* @__PURE__ */ jsx9("label", { htmlFor: "appointment-sliding-amount", className: "form-label", children: "Choose your price" }),
15762
+ /* @__PURE__ */ jsxs7("p", { className: "rb-caption status-muted", children: [
15763
+ formatBookingAmount(slidingScale.minAmount, slidingScale.currency),
15764
+ " to ",
15765
+ formatBookingAmount(slidingScale.maxAmount, slidingScale.currency),
15766
+ slidingScale.suggestedAmount !== null ? `, suggested ${formatBookingAmount(slidingScale.suggestedAmount, slidingScale.currency)}` : ""
15767
+ ] }),
15768
+ /* @__PURE__ */ jsx9(
15769
+ "input",
15770
+ {
15771
+ id: "appointment-sliding-amount",
15772
+ type: "number",
15773
+ className: "form-input",
15774
+ min: slidingScale.minAmount / 100,
15775
+ max: slidingScale.maxAmount / 100,
15776
+ step: "0.01",
15777
+ value: booking.payment.selectedSlidingAmountInput,
15778
+ onChange: (event) => booking.actions.setSlidingAmountInput(event.target.value)
15779
+ }
15780
+ )
15781
+ ] }) : null,
15641
15782
  /* @__PURE__ */ jsxs7("div", { className: "ab-stack", role: "list", "aria-label": "Payment options", children: [
15642
15783
  packageOptions.map((appointmentPackage) => {
15643
15784
  const isSelected = booking.payment.selectedAppointmentPackageId === appointmentPackage.customerPassId;
@@ -16993,6 +17134,7 @@ function useEligibility(params) {
16993
17134
  occurrenceId: params.occurrenceId,
16994
17135
  attendanceMode: params.attendanceMode ?? void 0,
16995
17136
  ticketTypeId: params.ticketTypeId ?? void 0,
17137
+ selectedSlidingAmount: params.selectedSlidingAmount ?? void 0,
16996
17138
  email: params.email.trim().toLowerCase(),
16997
17139
  ticketsCount: params.ticketsCount
16998
17140
  });
@@ -17013,7 +17155,7 @@ function useEligibility(params) {
17013
17155
  return () => {
17014
17156
  cancelled = true;
17015
17157
  };
17016
- }, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.email, params.ticketsCount]);
17158
+ }, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.selectedSlidingAmount, params.email, params.ticketsCount]);
17017
17159
  return {
17018
17160
  state,
17019
17161
  eligibility: state.eligibility,
@@ -17645,6 +17787,7 @@ function useEventRegistrationSubmit(options) {
17645
17787
  occurrenceId: submitOccurrenceId,
17646
17788
  attendanceMode: options.selectedAttendanceMode ?? void 0,
17647
17789
  ticketTypeId: options.selectedTicketTypeId ?? void 0,
17790
+ selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
17648
17791
  email: options.formData.email.trim().toLowerCase(),
17649
17792
  name: options.formData.name.trim(),
17650
17793
  ticketsCount: options.ticketsCount,
@@ -17746,6 +17889,35 @@ function useEventRegistrationSubmit(options) {
17746
17889
  }
17747
17890
 
17748
17891
  // ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
17892
+ function parseCurrencyInputToCents(value) {
17893
+ const trimmed = value.trim();
17894
+ if (!trimmed) return null;
17895
+ const amount = Number(trimmed);
17896
+ if (!Number.isFinite(amount) || amount < 0) return null;
17897
+ return Math.round(amount * 100);
17898
+ }
17899
+ function formatCentsAsCurrencyInput(amount) {
17900
+ const major = amount / 100;
17901
+ return Number.isInteger(major) ? String(major) : major.toFixed(2);
17902
+ }
17903
+ function getSlidingScaleForEvent(event) {
17904
+ const pricing = event ? resolveRuntimeEventPricing(event) : null;
17905
+ return pricing?.kind === "sliding_scale" ? {
17906
+ minAmount: pricing.minAmount,
17907
+ maxAmount: pricing.maxAmount,
17908
+ suggestedAmount: pricing.suggestedAmount
17909
+ } : null;
17910
+ }
17911
+ function getSlidingScaleSelectionMessage(input) {
17912
+ if (!input.slidingScale) return null;
17913
+ if (input.selectedAmount === null) {
17914
+ return "Choose an amount to continue.";
17915
+ }
17916
+ if (input.selectedAmount < input.slidingScale.minAmount || input.selectedAmount > input.slidingScale.maxAmount) {
17917
+ return "Choose an amount within the sliding scale.";
17918
+ }
17919
+ return null;
17920
+ }
17749
17921
  function useEventRegistrationWizard(options) {
17750
17922
  const api = useBlockApi();
17751
17923
  const registrationEvents = useMemo6(
@@ -17790,6 +17962,10 @@ function useEventRegistrationWizard(options) {
17790
17962
  preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
17791
17963
  );
17792
17964
  const [selectedTicketTypeId, setSelectedTicketTypeId] = useState4(null);
17965
+ const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState4(() => {
17966
+ const slidingScale = getSlidingScaleForEvent(preSelectedEvent ?? null);
17967
+ return slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : "";
17968
+ });
17793
17969
  const [registrationResult, setRegistrationResult] = useState4(null);
17794
17970
  const [errorMessage, setErrorMessage] = useState4("");
17795
17971
  const [altchaSolution, setAltchaSolution] = useState4(null);
@@ -17826,6 +18002,7 @@ function useEventRegistrationWizard(options) {
17826
18002
  occurrenceId,
17827
18003
  attendanceMode: selectedAttendanceMode,
17828
18004
  ticketTypeId: selectedTicketTypeId,
18005
+ selectedSlidingAmount: parseCurrencyInputToCents(selectedSlidingAmountInput),
17829
18006
  email: formData.email,
17830
18007
  ticketsCount
17831
18008
  });
@@ -17961,6 +18138,18 @@ function useEventRegistrationWizard(options) {
17961
18138
  }),
17962
18139
  [selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility, selectedTicketTypeId]
17963
18140
  );
18141
+ const selectedSlidingAmount = useMemo6(
18142
+ () => parseCurrencyInputToCents(selectedSlidingAmountInput),
18143
+ [selectedSlidingAmountInput]
18144
+ );
18145
+ const selectedEventSlidingScale = useMemo6(
18146
+ () => getSlidingScaleForEvent(selectedEvent ?? preSelectedEvent),
18147
+ [selectedEvent, preSelectedEvent]
18148
+ );
18149
+ const slidingScaleSelectionMessage = getSlidingScaleSelectionMessage({
18150
+ slidingScale: selectedEventSlidingScale,
18151
+ selectedAmount: selectedSlidingAmount
18152
+ });
17964
18153
  const ticketTypeSelectionRequired = useMemo6(() => {
17965
18154
  const event = selectedEvent ?? preSelectedEvent;
17966
18155
  if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
@@ -18029,12 +18218,24 @@ function useEventRegistrationWizard(options) {
18029
18218
  setGuestSectionShake(false);
18030
18219
  };
18031
18220
  const eventRequiresPayment = useMemo6(
18032
- () => resolveEventRequiresPayment({
18221
+ () => {
18222
+ if (selectedEventSlidingScale) {
18223
+ return (selectedSlidingAmount ?? 0) > 0;
18224
+ }
18225
+ return resolveEventRequiresPayment({
18226
+ eligibility,
18227
+ selectedTicketType,
18228
+ event: selectedEvent ?? preSelectedEvent
18229
+ });
18230
+ },
18231
+ [
18033
18232
  eligibility,
18034
18233
  selectedTicketType,
18035
- event: selectedEvent ?? preSelectedEvent
18036
- }),
18037
- [eligibility, selectedTicketType, selectedEvent, preSelectedEvent]
18234
+ selectedEvent,
18235
+ preSelectedEvent,
18236
+ selectedEventSlidingScale,
18237
+ selectedSlidingAmount
18238
+ ]
18038
18239
  );
18039
18240
  const handleDetailsComplete = async () => {
18040
18241
  if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
@@ -18043,6 +18244,11 @@ function useEventRegistrationWizard(options) {
18043
18244
  setStep("error");
18044
18245
  return { ok: false, reason: "blocked", message };
18045
18246
  }
18247
+ if (slidingScaleSelectionMessage) {
18248
+ setErrorMessage(slidingScaleSelectionMessage);
18249
+ setStep("error");
18250
+ return { ok: false, reason: "blocked", message: slidingScaleSelectionMessage };
18251
+ }
18046
18252
  if (!validateForm()) {
18047
18253
  setGuestSectionShake(true);
18048
18254
  return {
@@ -18127,9 +18333,18 @@ function useEventRegistrationWizard(options) {
18127
18333
  const discountSubtotalCents = useMemo6(() => {
18128
18334
  if (discountContext?.type !== "event") return void 0;
18129
18335
  const event = selectedEvent ?? preSelectedEvent;
18130
- const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
18336
+ const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (selectedEventSlidingScale ? selectedSlidingAmount : null) ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
18131
18337
  return Math.max(0, eventPriceCents * ticketsCount);
18132
- }, [discountContext, selectedTicketType, eligibility, selectedEvent, preSelectedEvent, ticketsCount]);
18338
+ }, [
18339
+ discountContext,
18340
+ selectedTicketType,
18341
+ eligibility,
18342
+ selectedEvent,
18343
+ preSelectedEvent,
18344
+ selectedEventSlidingScale,
18345
+ selectedSlidingAmount,
18346
+ ticketsCount
18347
+ ]);
18133
18348
  const discountUi = useDiscountCodeUi({ api, discountContext, subtotalCents: discountSubtotalCents });
18134
18349
  const selectionMethod = paymentSelection.method;
18135
18350
  const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
@@ -18138,6 +18353,7 @@ function useEventRegistrationWizard(options) {
18138
18353
  registrationTarget,
18139
18354
  selectedAttendanceMode,
18140
18355
  selectedTicketTypeId,
18356
+ selectedSlidingAmount,
18141
18357
  ticketsCount,
18142
18358
  formData,
18143
18359
  altchaSolution,
@@ -18152,6 +18368,10 @@ function useEventRegistrationWizard(options) {
18152
18368
  });
18153
18369
  const handleEventSelect = (event) => {
18154
18370
  setSelectedEvent(event);
18371
+ const slidingScale = getSlidingScaleForEvent(event);
18372
+ setSelectedSlidingAmountInput(
18373
+ slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
18374
+ );
18155
18375
  setSelectedAttendanceMode(
18156
18376
  (event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person"
18157
18377
  );
@@ -18161,6 +18381,7 @@ function useEventRegistrationWizard(options) {
18161
18381
  const handleRetry = () => {
18162
18382
  dispatchFlow({ type: "reset", hasPreSelectedContext });
18163
18383
  setSelectedTicketTypeId(null);
18384
+ setSelectedSlidingAmountInput("");
18164
18385
  setSelectedAttendanceMode(
18165
18386
  preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
18166
18387
  );
@@ -18197,6 +18418,11 @@ function useEventRegistrationWizard(options) {
18197
18418
  setSelectedAttendanceMode,
18198
18419
  selectedTicketTypeId,
18199
18420
  setSelectedTicketTypeId,
18421
+ selectedSlidingAmountInput,
18422
+ setSelectedSlidingAmountInput,
18423
+ selectedSlidingAmount,
18424
+ selectedEventSlidingScale,
18425
+ slidingScaleSelectionMessage,
18200
18426
  selectedTicketType,
18201
18427
  visibleTicketTypes,
18202
18428
  ticketTypeSelectionRequired,
@@ -1,8 +1,8 @@
1
- import { normalizeCarouselProps, CarouselNodeClient } from './chunk-PMNAV6LO.mjs';
1
+ import { normalizeCarouselProps, CarouselNodeClient } from './chunk-B5UC2D6X.mjs';
2
2
  import './chunk-6N7YRNYU.mjs';
3
3
  import { mountReactIsland } from './chunk-N7PBWBWQ.mjs';
4
- import { defineIslandPropsDecoder } from './chunk-MLBNVN4H.mjs';
5
- import './chunk-RWYFG625.mjs';
4
+ import { defineIslandPropsDecoder } from './chunk-R3CZQLXF.mjs';
5
+ import './chunk-GH6IIOOE.mjs';
6
6
  import { jsx } from 'react/jsx-runtime';
7
7
 
8
8
  var decode = defineIslandPropsDecoder("carousel");
@@ -1,15 +1,15 @@
1
- import { mountShopBlockIsland, CartClient } from './chunk-RMOFBBNA.mjs';
2
- import './chunk-6RN62XBV.mjs';
3
- import './chunk-PMNAV6LO.mjs';
1
+ import { mountShopBlockIsland, CartClient } from './chunk-JXY6NHG6.mjs';
2
+ import './chunk-ERQDHUS2.mjs';
3
+ import './chunk-B5UC2D6X.mjs';
4
4
  import './chunk-6N7YRNYU.mjs';
5
5
  import './chunk-L4J5Y62O.mjs';
6
- import './chunk-CKXEUWWA.mjs';
6
+ import './chunk-ZJDBOLX7.mjs';
7
7
  import './chunk-3DCJ45Z2.mjs';
8
8
  import './chunk-WBQG7VJA.mjs';
9
- import './chunk-WHZQDPBZ.mjs';
9
+ import './chunk-TNGL2WJF.mjs';
10
10
  import './chunk-N7PBWBWQ.mjs';
11
- import { defineIslandPropsDecoder } from './chunk-MLBNVN4H.mjs';
12
- import './chunk-RWYFG625.mjs';
11
+ import { defineIslandPropsDecoder } from './chunk-R3CZQLXF.mjs';
12
+ import './chunk-GH6IIOOE.mjs';
13
13
 
14
14
  // src/rendering/islands/enhancers/cart.tsx
15
15
  var decode = defineIslandPropsDecoder("cart");
@@ -1,15 +1,15 @@
1
- import { mountShopBlockIsland, CheckoutClient } from './chunk-RMOFBBNA.mjs';
2
- import './chunk-6RN62XBV.mjs';
3
- import './chunk-PMNAV6LO.mjs';
1
+ import { mountShopBlockIsland, CheckoutClient } from './chunk-JXY6NHG6.mjs';
2
+ import './chunk-ERQDHUS2.mjs';
3
+ import './chunk-B5UC2D6X.mjs';
4
4
  import './chunk-6N7YRNYU.mjs';
5
5
  import './chunk-L4J5Y62O.mjs';
6
- import './chunk-CKXEUWWA.mjs';
6
+ import './chunk-ZJDBOLX7.mjs';
7
7
  import './chunk-3DCJ45Z2.mjs';
8
8
  import './chunk-WBQG7VJA.mjs';
9
- import './chunk-WHZQDPBZ.mjs';
9
+ import './chunk-TNGL2WJF.mjs';
10
10
  import './chunk-N7PBWBWQ.mjs';
11
- import { defineIslandPropsDecoder } from './chunk-MLBNVN4H.mjs';
12
- import './chunk-RWYFG625.mjs';
11
+ import { defineIslandPropsDecoder } from './chunk-R3CZQLXF.mjs';
12
+ import './chunk-GH6IIOOE.mjs';
13
13
 
14
14
  // src/rendering/islands/enhancers/checkout.tsx
15
15
  var decode = defineIslandPropsDecoder("checkout");