@riverbankcms/sdk 0.130.2 → 0.134.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.
- package/CHANGELOG.md +13 -3
- package/dist/{PreviewEditorSidebar-BY-1QdE2.mjs → PreviewEditorSidebar-DfRhJPFQ.mjs} +351 -95
- package/dist/{PreviewEditorUI-BS34jI9_.mjs → PreviewEditorUI-Dppxcr_g.mjs} +3 -3
- package/dist/{PreviewQueryProvider-BD0kOjtI.mjs → PreviewQueryProvider-D51gQaG3.mjs} +1 -1
- package/dist/{SdkPreviewModeRuntime-B1pWnhu-.mjs → SdkPreviewModeRuntime-8CyGCXir.mjs} +91 -21
- package/dist/{SiteChromeCustomizeContext-BhUG_72i.mjs → SiteChromeCustomizeContext-DVMTMvqA.mjs} +6896 -4335
- package/dist/_dts/ai/src/contracts/proposals.d.ts +1105 -533
- package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +363 -276
- package/dist/_dts/api/src/accountApi.d.ts +5 -5
- package/dist/_dts/api/src/appointmentEndpointDefinitions.d.ts +1 -1
- package/dist/_dts/api/src/bookingConfig.d.ts +13 -9
- package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +8 -19
- package/dist/_dts/api/src/bookingManagementEventEndpointTypes.d.ts +31 -2
- package/dist/_dts/api/src/bookingOperations.d.ts +2 -14
- package/dist/_dts/api/src/bookingVerticals.d.ts +1 -140
- package/dist/_dts/api/src/bookings.d.ts +2 -2
- package/dist/_dts/api/src/commercePortalEndpoints.d.ts +45 -12
- package/dist/_dts/api/src/contentRuntime.d.ts +3 -2
- package/dist/_dts/api/src/courseEndpointDefinitions.d.ts +2 -2
- package/dist/_dts/api/src/courses.d.ts +1 -19
- package/dist/_dts/api/src/endpoints.d.ts +469 -349
- package/dist/_dts/api/src/event-destination-policy.d.ts +1 -1
- package/dist/_dts/api/src/eventManagementContracts.d.ts +91 -1
- package/dist/_dts/api/src/eventManagementEndpointDefinitions.d.ts +32 -0
- package/dist/_dts/api/src/giftingDashboard.d.ts +117 -0
- package/dist/_dts/api/src/giftingEndpointDefinitions.d.ts +124 -0
- package/dist/_dts/api/src/index.d.ts +4 -4
- package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -1
- package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
- package/dist/_dts/api/src/media.d.ts +1 -0
- package/dist/_dts/api/src/navigation/contracts.d.ts +9 -6
- package/dist/_dts/api/src/navigation/dashboardBookingsNav.d.ts +3 -4
- package/dist/_dts/api/src/navigation/linkResolver.d.ts +6 -2
- package/dist/_dts/api/src/navigation/types.d.ts +23 -6
- package/dist/_dts/api/src/navigation.d.ts +1 -1
- package/dist/_dts/api/src/publicBookingService.d.ts +15 -0
- package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +11 -0
- package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +28 -13
- package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +2 -0
- package/dist/_dts/api/src/publicExperience/wholeSeriesEndpoints.d.ts +3 -0
- package/dist/_dts/api/src/sdk-event-upsert.d.ts +3 -3
- package/dist/_dts/api/src/sdkBookingVerticalContracts.d.ts +29 -0
- package/dist/_dts/api/src/sdkContracts.d.ts +9 -32
- package/dist/_dts/api/src/sdkEndpointDefinitions.d.ts +23 -0
- package/dist/_dts/api/src/sdkSettingsContracts.d.ts +25 -0
- package/dist/_dts/api/src/sdkThemeCatalogContracts.d.ts +20 -0
- package/dist/_dts/api/src/sdkThemeWire.d.ts +64 -54
- package/dist/_dts/api/src/siteBanner.d.ts +4 -2
- package/dist/_dts/api/src/siteOnboarding.d.ts +3 -3
- package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +4 -10
- package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +0 -3
- package/dist/_dts/api/src/types.d.ts +2 -3
- package/dist/_dts/api/src/webhooks.d.ts +12 -12
- package/dist/_dts/blocks/src/PageRenderer.d.ts +2 -13
- package/dist/_dts/blocks/src/client.d.ts +1 -1
- package/dist/_dts/blocks/src/contracts/non-block-islands.d.ts +9 -0
- package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +54 -116
- package/dist/_dts/blocks/src/index.d.ts +4 -3
- package/dist/_dts/blocks/src/primitives/content/components/RichText.d.ts +2 -2
- package/dist/_dts/blocks/src/primitives/content/primitives.d.ts +1 -0
- package/dist/_dts/blocks/src/subroutes/fold.d.ts +2 -1
- package/dist/_dts/blocks/src/system/blocks/courses/shared/index.d.ts +0 -3
- package/dist/_dts/blocks/src/system/blocks/courses/shared/pricing.d.ts +2 -50
- package/dist/_dts/blocks/src/system/blocks/courses/shared/schemas.d.ts +1 -929
- package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +1 -97
- package/dist/_dts/blocks/src/system/blocks/event-details.d.ts +39 -6
- package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +2 -1
- package/dist/_dts/blocks/src/system/blocks/events/event-listing.d.ts +3 -3
- package/dist/_dts/blocks/src/system/blocks/events/event-spotlight.d.ts +2 -3
- package/dist/_dts/blocks/src/system/blocks/events/shared/filtering.d.ts +2 -2
- package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +42 -20
- package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +5 -9
- package/dist/_dts/blocks/src/system/blocks/events/whole-series/index.d.ts +3 -0
- package/dist/_dts/blocks/src/system/blocks/events/whole-series/pricing.d.ts +50 -0
- package/dist/_dts/blocks/src/system/blocks/events/whole-series/schemas.d.ts +135 -0
- package/dist/_dts/blocks/src/system/blocks/events/whole-series/types.d.ts +84 -0
- package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +4 -4
- package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +148 -148
- package/dist/_dts/blocks/src/system/blocks/offerings-preview/model.d.ts +3 -2
- package/dist/_dts/blocks/src/system/blocks/shared/bookingConsent.d.ts +36 -0
- package/dist/_dts/blocks/src/system/fields/boxStyles.d.ts +7 -8
- package/dist/_dts/blocks/src/system/manifest/hydrateLinks.d.ts +9 -2
- package/dist/_dts/blocks/src/system/manifest/resolveBlockData.d.ts +8 -0
- package/dist/_dts/blocks/src/system/manifest/schema.d.ts +79 -79
- package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/api/types/appointments.d.ts +2 -11
- package/dist/_dts/blocks/src/system/runtime/api/types/courses.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/blockComposition.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/components/multi-step/DynamicFormFields.d.ts +3 -19
- package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +45 -72
- package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +22 -37
- package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessWholeSeriesRegistrationFlow.d.ts +6 -6
- package/dist/_dts/blocks/src/system/runtime/hooks/useSelectedAppointmentConsentForm.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.consent.d.ts +10 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.field-values.d.ts +4 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.fields.d.ts +21 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +38 -144
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +5 -19
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +3 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/course-page-surface-scope.d.ts +2 -5
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.client.d.ts +4 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.interactive.d.ts +19 -7
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details/logic.d.ts +25 -4
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details/presentation.d.ts +75 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details/view.d.ts +4 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details.client.d.ts +5 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details.server.d.ts +5 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/AttendeeDetailsStep.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/PaymentSelectionStep.d.ts +4 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/RegistrationClosedState.d.ts +5 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/SiteCreditPreviewPanel.d.ts +6 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventPaymentOptions.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +17 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationSurface.d.ts +21 -4
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/siteCreditPreview.d.ts +51 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +3 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +6 -4
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/validation.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/BookingModeStep.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/CheckIcon.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/ErrorStep.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/MembershipHero.d.ts +3 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/PaymentFailedStep.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/StepIndicator.d.ts +6 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/VerifyingTimeoutStep.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationActiveSteps.d.ts +9 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration/CourseRegistrationErrorBoundary.d.ts → event-registration/whole-series/WholeSeriesRegistrationErrorBoundary.d.ts} +5 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationTerminalContent.d.ts +8 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationWizard.d.ts +8 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/components.d.ts +46 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/index.d.ts +4 -4
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/presentation.d.ts +7 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/pricing.d.ts +14 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/types.d.ts +18 -16
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration/useCourseEligibility.d.ts → event-registration/whole-series/useWholeSeriesEligibility.d.ts} +6 -6
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesPaymentVerification.d.ts +10 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationActions.d.ts +35 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration/useCourseRegistrationPortal.d.ts → event-registration/whole-series/useWholeSeriesRegistrationPortal.d.ts} +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationSelection.d.ts +35 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationWizard.d.ts +185 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration/useCourseWaitlistSelection.d.ts → event-registration/whole-series/useWholeSeriesWaitlistSelection.d.ts} +5 -5
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/utils.d.ts +4 -4
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/whole-series-registration.headless.contract.d.ts +7 -7
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/whole-series-registration.headless.planning.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/wholeSeriesPageSurfaceScope.d.ts +17 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration/courseRegistrationViewState.d.ts → event-registration/whole-series/wholeSeriesRegistrationViewState.d.ts} +7 -7
- package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/wizardSteps.d.ts +4 -4
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +24 -54
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +3 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +12 -11
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.server.d.ts +3 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventSpotlight.d.ts +3 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.d.ts +3 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventDetailModal.d.ts +4 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventModalCloseButton.d.ts +7 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventModals.d.ts +4 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekBoardView.d.ts +14 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +51 -14
- package/dist/_dts/blocks/src/system/runtime/nodes/shared/MagicLinkForm.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/shared/components/BookingConsentAgreement.d.ts +7 -0
- package/dist/_dts/blocks/src/system/runtime/shared/components/DiscountCodeDisclosure.d.ts +12 -12
- package/dist/_dts/blocks/src/system/runtime/shared/types.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/shared/useWaitlistClaim.d.ts +1 -0
- package/dist/_dts/blocks/src/system/transforms/registry/_utils/boxStyleClassNames.d.ts +30 -11
- package/dist/_dts/blocks/src/system/transforms/registry/boxStyles.d.ts +15 -4
- package/dist/_dts/blocks/src/system/transforms/registry/index.d.ts +1 -0
- package/dist/_dts/blocks/src/system/transforms/typed.d.ts +1 -4
- package/dist/_dts/blocks/src/system/types/link.d.ts +7 -1
- package/dist/_dts/commerce/src/purchase/bookingInstalmentSchedule.d.ts +13 -0
- package/dist/_dts/commerce/src/purchase/cancellationPolicy.d.ts +7 -0
- package/dist/_dts/commerce/src/purchase/canonicalRefundPlanner.d.ts +48 -0
- package/dist/_dts/commerce/src/purchase/checkoutCollectionPlan.d.ts +39 -0
- package/dist/_dts/commerce/src/purchase/checkoutCommitPlan.d.ts +40 -0
- package/dist/_dts/commerce/src/purchase/checkoutDiscountContextPlanning.d.ts +80 -0
- package/dist/_dts/commerce/src/purchase/checkoutErrorCodes.d.ts +1 -0
- package/dist/_dts/commerce/src/purchase/checkoutOrderItemProjection.d.ts +22 -0
- package/dist/_dts/commerce/src/purchase/checkoutPaymentFlow.d.ts +50 -0
- package/dist/_dts/commerce/src/purchase/checkoutPaymentPlanPlanning.d.ts +30 -0
- package/dist/_dts/commerce/src/purchase/checkoutPaymentTermPlanning.d.ts +10 -0
- package/dist/_dts/commerce/src/purchase/checkoutPaymentTerms.d.ts +53 -0
- package/dist/_dts/commerce/src/purchase/checkoutQuantity.d.ts +8 -0
- package/dist/_dts/commerce/src/purchase/checkoutSessionMetadata.d.ts +76 -0
- package/dist/_dts/commerce/src/purchase/checkoutSettlement.d.ts +46 -0
- package/dist/_dts/commerce/src/purchase/checkoutStripeFinalizationPlanning.d.ts +12 -0
- package/dist/_dts/commerce/src/purchase/checkoutStripeSessionPlanning.d.ts +125 -0
- package/dist/_dts/commerce/src/purchase/checkoutValidatedItemPlanning.d.ts +55 -0
- package/dist/_dts/commerce/src/purchase/confirmationEmailPayment.d.ts +91 -0
- package/dist/_dts/commerce/src/purchase/discountApplication.d.ts +74 -0
- package/dist/_dts/commerce/src/purchase/index.d.ts +55 -0
- package/dist/_dts/commerce/src/purchase/oneTimeCheckoutPlanning.d.ts +86 -0
- package/dist/_dts/commerce/src/purchase/order-number.d.ts +33 -0
- package/dist/_dts/commerce/src/purchase/orderCancellationPlan.d.ts +19 -0
- package/dist/_dts/commerce/src/purchase/orderCompletionEmailPlan.d.ts +71 -0
- package/dist/_dts/commerce/src/purchase/orderConfirmationPlanning.d.ts +120 -0
- package/dist/_dts/commerce/src/purchase/orderFulfillmentPlan.d.ts +81 -0
- package/dist/_dts/commerce/src/purchase/orderFulfillmentResult.d.ts +8 -0
- package/dist/_dts/commerce/src/purchase/orderHistoryLedgerFilters.d.ts +1 -0
- package/dist/_dts/commerce/src/purchase/orderHistorySource.d.ts +11 -0
- package/dist/_dts/commerce/src/purchase/orderInstalmentAdminSettlement.d.ts +43 -0
- package/dist/_dts/commerce/src/purchase/orderInstalmentClosure.d.ts +29 -0
- package/dist/_dts/commerce/src/purchase/orderInstalmentLifecycle.d.ts +44 -0
- package/dist/_dts/commerce/src/purchase/orderInstalmentPayoff.d.ts +24 -0
- package/dist/_dts/commerce/src/purchase/orderInstalmentPlan.d.ts +40 -0
- package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +151 -0
- package/dist/_dts/commerce/src/purchase/orderItemSupport.d.ts +14 -0
- package/dist/_dts/commerce/src/purchase/orderListFilters.d.ts +3 -0
- package/dist/_dts/commerce/src/purchase/orderPaymentLinkPlanning.d.ts +60 -0
- package/dist/_dts/commerce/src/purchase/orderPaymentReceipt.d.ts +184 -0
- package/dist/_dts/commerce/src/purchase/orderPaymentState.d.ts +135 -0
- package/dist/_dts/commerce/src/purchase/orderPlanningTypes.d.ts +102 -0
- package/dist/_dts/commerce/src/purchase/orderRefundPlanning.d.ts +50 -0
- package/dist/_dts/commerce/src/purchase/orderRefundPolicy.d.ts +36 -0
- package/dist/_dts/commerce/src/purchase/orderTotals.d.ts +23 -0
- package/dist/_dts/commerce/src/purchase/orderTypes.d.ts +39 -0
- package/dist/_dts/commerce/src/purchase/pendingCheckoutSessionClaim.d.ts +1 -0
- package/dist/_dts/commerce/src/purchase/persistedCheckoutLines.d.ts +27 -0
- package/dist/_dts/commerce/src/purchase/protectedDepositRefundPolicy.d.ts +86 -0
- package/dist/_dts/commerce/src/purchase/refundPolicy.d.ts +8 -0
- package/dist/_dts/commerce/src/purchase/refundRailSplit.d.ts +40 -0
- package/dist/_dts/commerce/src/purchase/result.d.ts +2 -0
- package/dist/_dts/commerce/src/purchase/settlement.d.ts +97 -0
- package/dist/_dts/commerce/src/purchase/shopRefundPlanning.d.ts +43 -0
- package/dist/_dts/commerce/src/purchase/stateTransitions.d.ts +31 -0
- package/dist/_dts/commerce/src/purchase/stripeMinimumCharge.d.ts +10 -0
- package/dist/_dts/commerce/src/purchase/types.d.ts +168 -0
- package/dist/_dts/commerce/src/shop/shipmentEligibility.d.ts +14 -0
- package/dist/_dts/commerce/src/utils/assertNever.d.ts +1 -0
- package/dist/_dts/content-model/src/content-types/builtin-schemas.d.ts +4 -0
- package/dist/_dts/content-model/src/content-types/builtins.d.ts +4 -0
- package/dist/_dts/content-model/src/content-types/schema.d.ts +4 -4
- package/dist/_dts/core/src/booking-consent.d.ts +8 -0
- package/dist/_dts/core/src/booking-vertical-catalog.d.ts +741 -0
- package/dist/_dts/core/src/booking-vertical-config.d.ts +66 -0
- package/dist/_dts/core/src/booking-vertical-definitions.d.ts +68 -0
- package/dist/_dts/{api/src/bookingVerticalPreset.d.ts → core/src/booking-vertical-preset.d.ts} +1 -1
- package/dist/_dts/core/src/booking-verticals.d.ts +98 -0
- package/dist/_dts/core/src/event-page-selection.d.ts +22 -0
- package/dist/_dts/core/src/event-pricing.d.ts +5 -0
- package/dist/_dts/core/src/event-series-behaviour.d.ts +16 -0
- package/dist/_dts/core/src/index.d.ts +4 -0
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +81 -3
- package/dist/_dts/db/src/schemas/forms.d.ts +25 -25
- package/dist/_dts/db/src/types/jsonb.d.ts +1 -1
- package/dist/_dts/editor/src/primitives/rich-text/RichTextEditorSurface.d.ts +2 -1
- package/dist/_dts/editor/src/primitives/rich-text/config.d.ts +2 -1
- package/dist/_dts/editor/src/primitives/rich-text/toolbar/linkPopoverUtils.d.ts +3 -2
- package/dist/_dts/editor/src/primitives/rich-text/useRichTextEditor.d.ts +3 -4
- package/dist/_dts/media-core/src/fileUploadCompletion.d.ts +3 -0
- package/dist/_dts/media-core/src/fileUploadDurableFinalization.d.ts +2 -0
- package/dist/_dts/media-core/src/identifiers.d.ts +10 -0
- package/dist/_dts/media-core/src/mediaWriteNormalizer.d.ts +2 -6
- package/dist/_dts/media-core/src/types.d.ts +2 -1
- package/dist/_dts/media-core/src/usageScanner.d.ts +1 -1
- package/dist/_dts/media-editor/src/index.d.ts +2 -2
- package/dist/_dts/media-editor/src/mediaSelection.d.ts +1 -22
- package/dist/_dts/media-editor/src/useMediaSelection.d.ts +0 -9
- package/dist/_dts/preview-next/src/client/preview/ButtonHoverRoleControls.d.ts +10 -0
- package/dist/_dts/preview-next/src/client/preview/ButtonStylePicker.d.ts +3 -2
- package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +3 -1
- package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +2 -1
- package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +2 -1
- package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.d.ts +3 -1
- package/dist/_dts/preview-next/src/client/preview/StyleConfiguratorWarningNotice.d.ts +7 -0
- package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +1 -1
- package/dist/_dts/sdk/src/bookings/types.d.ts +7 -89
- package/dist/_dts/sdk/src/client/eventSubrouteReadOperations.d.ts +11 -0
- package/dist/_dts/sdk/src/client/types.d.ts +12 -5
- package/dist/_dts/sdk/src/components.d.ts +1 -1
- package/dist/_dts/sdk/src/config/validation.d.ts +30 -30
- package/dist/_dts/sdk/src/contracts/content.d.ts +10 -36
- package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
- package/dist/_dts/sdk/src/contracts/page.d.ts +2 -13
- package/dist/_dts/sdk/src/contracts/rendering.d.ts +1 -1
- package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +4 -16
- package/dist/_dts/sdk/src/manifest/passes/pass1-fields.d.ts +9 -9
- package/dist/_dts/sdk/src/next/pageMetadataProjection.d.ts +7 -0
- package/dist/_dts/sdk/src/next/resolveEventPageSubroute.d.ts +12 -0
- package/dist/_dts/sdk/src/public-api/contracts.d.ts +11 -38
- package/dist/_dts/sdk/src/public-api/eventSubrouteContracts.d.ts +12 -0
- package/dist/_dts/sdk/src/public-api/runtime.d.ts +1 -1
- package/dist/_dts/sdk/src/rendering/client.d.ts +44 -0
- package/dist/_dts/sdk/src/rendering/index.d.ts +1 -1
- package/dist/_dts/sdk/src/routing/entrySubroutes.d.ts +1 -1
- package/dist/_dts/sdk/src/routing/resolveOccurrence.d.ts +4 -3
- package/dist/_dts/sdk/src/routing/resolvePageContent.d.ts +7 -3
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/theme-core/src/accordions/types.d.ts +2 -2
- package/dist/_dts/theme-core/src/buttons/buttonSurfaceContext.d.ts +1 -1
- package/dist/_dts/theme-core/src/buttons/contextualHover.d.ts +41 -0
- package/dist/_dts/theme-core/src/buttons/index.d.ts +1 -0
- package/dist/_dts/theme-core/src/buttons/resolveButtonColourStates.d.ts +3 -0
- package/dist/_dts/theme-core/src/buttons/resolveButtonHoverTreatment.d.ts +14 -0
- package/dist/_dts/theme-core/src/buttons/styles/domain.d.ts +21 -4
- package/dist/_dts/theme-core/src/buttons/styles/recipes/flatInk.d.ts +92 -0
- package/dist/_dts/theme-core/src/buttons/styles/recipes/staticRecipes.d.ts +10 -150
- package/dist/_dts/theme-core/src/buttons/styles/registry.d.ts +57 -102
- package/dist/_dts/theme-core/src/buttons/styles/selection.d.ts +50 -2
- package/dist/_dts/theme-core/src/buttons/types.d.ts +41 -12
- package/dist/_dts/theme-core/src/cards/types.d.ts +7 -29
- package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
- package/dist/_dts/theme-core/src/mock-themes/all.d.ts +90 -75
- package/dist/_dts/theme-core/src/navigation/types.d.ts +4 -4
- package/dist/_dts/theme-core/src/palette/colors.d.ts +1 -1
- package/dist/_dts/theme-core/src/palette/curated/types.d.ts +2 -2
- package/dist/_dts/theme-core/src/schema.d.ts +98 -110
- package/dist/_dts/theme-core/src/site-styles/appearancePresetCatalog.d.ts +27 -0
- package/dist/_dts/theme-core/src/site-styles/blockAppearancePresets.d.ts +27 -0
- package/dist/_dts/theme-core/src/site-styles/buttonSelectionCompiler.d.ts +18 -0
- package/dist/_dts/theme-core/src/site-styles/cardRoleVocabulary.d.ts +1 -1
- package/dist/_dts/theme-core/src/site-styles/compilationPlan.d.ts +21 -0
- package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -2
- package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -4
- package/dist/_dts/theme-core/src/site-styles/logoBranding.d.ts +4 -4
- package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +2 -11
- package/dist/_dts/theme-core/src/site-styles/selectionFallbackWarning.d.ts +15 -0
- package/dist/_dts/theme-core/src/site-styles/types.d.ts +13 -1
- package/dist/_dts/theme-core/src/tokens/themeColorTokens.d.ts +1 -1
- package/dist/_dts/ui/src/badge.d.ts +1 -1
- package/dist/_dts/ui/src/button.d.ts +1 -1
- package/dist/_dts/ui/src/callout.d.ts +1 -1
- package/dist/_dts/ui/src/card.d.ts +1 -1
- package/dist/_dts/ui/src/navigation-tabs.d.ts +2 -0
- package/dist/client/{StepIndicator-CLjQhkDb.mjs → BookingConsentAgreement-BxgpGEFD.mjs} +26 -4
- package/dist/client/{DiscountCodeDisclosure-BPZ-yfGI.mjs → DiscountCodeDisclosure-CfuPOHD0.mjs} +12 -12
- package/dist/client/{EventCombined.client-Cjt3kKYR.mjs → EventCombined.client-DB8Qfzi-.mjs} +37 -49
- package/dist/client/{EventListing.client-DY9dn6Fh.mjs → EventListing.client-DD4X8hp4.mjs} +2 -2
- package/dist/client/{LeafletStaticMap--2c61XYn.mjs → LeafletStaticMap-QhgIBQbv.mjs} +1 -1
- package/dist/client/{CourseRegistrationWizard-DGW9F0SQ.mjs → WholeSeriesRegistrationWizard-DwtC7bCs.mjs} +1460 -1247
- package/dist/client/{accordion-_boYwHHi.mjs → accordion-DFXpLvwg.mjs} +1 -1
- package/dist/client/{bookingForm--AqEfyBX.mjs → bookingForm-sI05d3lk.mjs} +73 -47
- package/dist/client/bookings.mjs +1719 -706
- package/dist/client/{carousel-CVI2dqZr.mjs → carousel-wjyWTZCh.mjs} +1 -1
- package/dist/client/{cart-DR6IiPz9.mjs → cart-DCwdpA4i.mjs} +3 -3
- package/dist/client/{checkout-CsrGAfQt.mjs → checkout-DTDW3l0R.mjs} +3 -3
- package/dist/client/checkoutUrls-DQYC_Br-.mjs +187 -0
- package/dist/client/client.mjs +6830 -3672
- package/dist/client/{context-B83PiNzm.mjs → context-TSK1CGx8.mjs} +1 -14
- package/dist/client/{courseRegistration-aNJVaLa3.mjs → courseRegistration-A-Tg7qw_.mjs} +11 -5
- package/dist/client/{eventCalendar-OZ7h59VN.mjs → eventCalendar-B0Zg-i_w.mjs} +41 -44
- package/dist/client/{eventCombined-BbJ6bFKz.mjs → eventCombined-B8Y2wizd.mjs} +3 -3
- package/dist/client/{eventDetails-BLyUBiCT.mjs → eventDetails-DPDOwURJ.mjs} +276 -94
- package/dist/client/{eventListing-DuP1yhBS.mjs → eventListing-CjBcmSLn.mjs} +3 -3
- package/dist/client/{eventRegistration-BXyECPa-.mjs → eventRegistration-CK30HsAq.mjs} +730 -190
- package/dist/client/{form-BA4t3kKU.mjs → form-CUXfsABE.mjs} +2 -2
- package/dist/client/{headerSection-CpNaJxhW.mjs → headerSection-N-mN3rjr.mjs} +2 -2
- package/dist/client/hooks.mjs +1418 -484
- package/dist/client/{locationMap-3HGMCL7_.mjs → locationMap-oiIDQMBt.mjs} +2 -2
- package/dist/client/{newsletterForm-C2s6Mw67.mjs → newsletterForm-CkQ2tTrM.mjs} +2 -2
- package/dist/client/pricing-Caa0QWzh.mjs +195 -0
- package/dist/client/{productDetail-C9joWhdE.mjs → productDetail-CnidyrsN.mjs} +3 -3
- package/dist/client/{productList-CjzdU3pB.mjs → productList-CttYcS_S.mjs} +3 -3
- package/dist/client/{propsDecoder-CBPGXEYX.mjs → propsDecoder-CeUMxI9a.mjs} +677 -350
- package/dist/client/rendering/client.mjs +6075 -4150
- package/dist/client/rendering/islands.mjs +18 -18
- package/dist/client/rendering.mjs +7589 -4388
- package/dist/client/{scrollToBlock-DZ73aEX6.mjs → scrollToBlock-lPr1oqxB.mjs} +1 -1
- package/dist/client/{shop-CQRai7hj.mjs → shop-DXQtMo2O.mjs} +6 -6
- package/dist/client/{shop-commerce-hP9UboOx.mjs → shop-commerce-quDL411J.mjs} +7 -164
- package/dist/client/{shop-commerce-store-DiD5a32e.mjs → shop-commerce-store-Dnu-8Iub.mjs} +1 -1
- package/dist/client/{shopShared-DP8DXTkF.mjs → shopShared-BWPUURvG.mjs} +3 -3
- package/dist/client/{useEventFilters-pF_OJNQP.mjs → useEventFilters-DRhWp2_5.mjs} +196 -7
- package/dist/client/{usePolling-Cls91SD2.mjs → usePolling-UN4WKnaM.mjs} +3 -3
- package/dist/preview-next/before-render.mjs +247 -60
- package/dist/preview-next/client/runtime.mjs +4 -4
- package/dist/preview-next/keepAlive.mjs +247 -60
- package/dist/preview-next/middleware.mjs +247 -60
- package/dist/{previewAuthStore-CX1C_KJ4.mjs → previewAuthStore-BFKd4LrN.mjs} +247 -60
- package/dist/{sdk-runtime-5CcPAI14.mjs → sdk-runtime-Ca5RD78X.mjs} +2 -2
- package/dist/{separator-BXlYN_gr.mjs → separator-CMhj6BTi.mjs} +1 -1
- package/dist/server/components.mjs +3578 -1614
- package/dist/server/config-validation.mjs +1418 -485
- package/dist/server/config.mjs +1418 -485
- package/dist/server/data.mjs +1418 -484
- package/dist/server/index.mjs +289 -81
- package/dist/server/manifest.mjs +0 -1
- package/dist/server/next.mjs +3761 -1794
- package/dist/server/page-converter.mjs +911 -261
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +3580 -1613
- package/dist/server/rendering.mjs +3578 -1614
- package/dist/server/routing.mjs +1687 -689
- package/dist/server/server.mjs +1458 -563
- package/dist/server/theme-bridge.mjs +1996 -935
- package/dist/server/theme.mjs +346 -133
- package/dist/styles/index.css +1602 -796
- package/package.json +2 -2
- package/dist/_dts/api/src/bookingVerticalCatalog.d.ts +0 -746
- package/dist/_dts/api/src/eventSeriesPresentationPreset.d.ts +0 -12
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/CourseRegistrationWizard.d.ts +0 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/StepIndicator.d.ts +0 -6
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/components.d.ts +0 -45
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/pricing.d.ts +0 -14
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCoursePaymentVerification.d.ts +0 -9
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationActions.d.ts +0 -35
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationSelection.d.ts +0 -31
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.d.ts +0 -102
- package/dist/client/checkoutUrls-Ct8Mxna3.mjs +0 -26
- package/dist/client/eventProductEligibility-AVxyCB1u.mjs +0 -50
- package/dist/client/pricing-BiqIMgZk.mjs +0 -174
- /package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/PortalAuthSidebar.d.ts +0 -0
- /package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/SuccessStep.d.ts +0 -0
- /package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/WaitlistStep.d.ts +0 -0
package/dist/client/bookings.mjs
CHANGED
|
@@ -3211,20 +3211,7 @@ function createBlockApi(config) {
|
|
|
3211
3211
|
const path = buildPath(WHOLE_SERIES.checkout.path, { siteId: sid });
|
|
3212
3212
|
return request(WHOLE_SERIES.checkout, {
|
|
3213
3213
|
path,
|
|
3214
|
-
body:
|
|
3215
|
-
eventSeriesId: data.eventSeriesId,
|
|
3216
|
-
...data.pricingOptionId ? { pricingOptionId: data.pricingOptionId } : {},
|
|
3217
|
-
...data.selectedSlidingAmount !== void 0 ? { selectedSlidingAmount: data.selectedSlidingAmount } : {},
|
|
3218
|
-
email: data.email,
|
|
3219
|
-
name: data.name,
|
|
3220
|
-
phone: data.phone,
|
|
3221
|
-
formData: data.formData,
|
|
3222
|
-
altchaSolution: data.altchaSolution,
|
|
3223
|
-
discountCode: data.discountCode,
|
|
3224
|
-
successUrl: data.successUrl,
|
|
3225
|
-
cancelUrl: data.cancelUrl,
|
|
3226
|
-
claimToken: data.claimToken
|
|
3227
|
-
}
|
|
3214
|
+
body: data
|
|
3228
3215
|
});
|
|
3229
3216
|
},
|
|
3230
3217
|
async getWholeSeriesRegistrationStatus(params) {
|
|
@@ -3676,7 +3663,7 @@ function getChallengeUrl() {
|
|
|
3676
3663
|
}
|
|
3677
3664
|
//#endregion
|
|
3678
3665
|
//#region ../core/src/result.ts
|
|
3679
|
-
function ok(value) {
|
|
3666
|
+
function ok$1(value) {
|
|
3680
3667
|
return {
|
|
3681
3668
|
ok: true,
|
|
3682
3669
|
value
|
|
@@ -3696,11 +3683,14 @@ function parseUuidBrand(value, unsafeConstructor) {
|
|
|
3696
3683
|
const normalized = value.trim().toLowerCase();
|
|
3697
3684
|
if (normalized.length === 0) return err$1({ kind: "empty_string" });
|
|
3698
3685
|
if (!UUID_PATTERN.test(normalized)) return err$1({ kind: "invalid_uuid" });
|
|
3699
|
-
return ok(unsafeConstructor(normalized));
|
|
3686
|
+
return ok$1(unsafeConstructor(normalized));
|
|
3700
3687
|
}
|
|
3701
3688
|
const unsafeAsSiteId = (id) => id;
|
|
3702
3689
|
const unsafeAsEventOfferingId = (id) => id;
|
|
3703
3690
|
const unsafeAsEventSeriesId = (id) => id;
|
|
3691
|
+
const unsafeAsMediaAssetId = (id) => id;
|
|
3692
|
+
const unsafeAsStorageBucketName = (value) => value;
|
|
3693
|
+
const unsafeAsStoragePath = (value) => value;
|
|
3704
3694
|
const unsafeAsFormId = (id) => id;
|
|
3705
3695
|
const unsafeAsPassId = (id) => id;
|
|
3706
3696
|
const unsafeAsCustomerPassId = (id) => id;
|
|
@@ -3843,7 +3833,7 @@ function parseEventPageSurfaceSubject(value) {
|
|
|
3843
3833
|
kind: "invalidEventSeriesBookingScope",
|
|
3844
3834
|
bookingScope: value.bookingScope
|
|
3845
3835
|
});
|
|
3846
|
-
return ok(createEventSeriesPageSurfaceSubject(eventSeriesId.value, value.bookingScope));
|
|
3836
|
+
return ok$1(createEventSeriesPageSurfaceSubject(eventSeriesId.value, value.bookingScope));
|
|
3847
3837
|
}
|
|
3848
3838
|
case "eventOffering": {
|
|
3849
3839
|
const eventOfferingId = parseEventOfferingId(value.eventOfferingId);
|
|
@@ -3864,7 +3854,7 @@ function parseEventPageSurfaceSubject(value) {
|
|
|
3864
3854
|
});
|
|
3865
3855
|
parsedSeriesIds.push(eventSeriesId.value);
|
|
3866
3856
|
}
|
|
3867
|
-
return ok({
|
|
3857
|
+
return ok$1({
|
|
3868
3858
|
kind: "eventOffering",
|
|
3869
3859
|
eventOfferingId: eventOfferingId.value,
|
|
3870
3860
|
availableEventSeriesIds: parsedSeriesIds
|
|
@@ -3982,7 +3972,7 @@ function parseBookingTimeZone(timeZone) {
|
|
|
3982
3972
|
if (typeof timeZone !== "string") return err$1("invalid-time-zone");
|
|
3983
3973
|
const normalized = timeZone.trim();
|
|
3984
3974
|
if (normalized.length === 0 || NUMERIC_OFFSET_TIME_ZONE_PATTERN.test(normalized) || !isValidBookingTimeZone(normalized)) return err$1("invalid-time-zone");
|
|
3985
|
-
return ok(normalized);
|
|
3975
|
+
return ok$1(normalized);
|
|
3986
3976
|
}
|
|
3987
3977
|
//#endregion
|
|
3988
3978
|
//#region ../core/src/booking-date-time.ts
|
|
@@ -4061,7 +4051,7 @@ function parseUtcIsoDateTimeString(value) {
|
|
|
4061
4051
|
if (!hasUtcSuffix && !hasExplicitOffset) return err$1("missing-timezone-offset");
|
|
4062
4052
|
const date = new Date(normalized);
|
|
4063
4053
|
if (Number.isNaN(date.getTime())) return err$1("invalid-date-time");
|
|
4064
|
-
return ok(date.toISOString());
|
|
4054
|
+
return ok$1(date.toISOString());
|
|
4065
4055
|
}
|
|
4066
4056
|
function toUtcIsoDateTimeString(value) {
|
|
4067
4057
|
const parsed = parseUtcIsoDateTimeString(value);
|
|
@@ -4213,6 +4203,109 @@ function assertNever(value, message) {
|
|
|
4213
4203
|
throw new Error(message ?? `Unexpected value: ${String(value)}`);
|
|
4214
4204
|
}
|
|
4215
4205
|
//#endregion
|
|
4206
|
+
//#region ../blocks/src/system/manifest/richTextSchema.ts
|
|
4207
|
+
/**
|
|
4208
|
+
* Shared Rich Text Schema
|
|
4209
|
+
*
|
|
4210
|
+
* This module provides a single source of truth for TipTap rich text validation
|
|
4211
|
+
* across both the block-form editor and the block rendering system.
|
|
4212
|
+
*
|
|
4213
|
+
* Rich-text fields use one canonical root shape:
|
|
4214
|
+
* `{ type: 'doc', content: [...] }`.
|
|
4215
|
+
*/
|
|
4216
|
+
/**
|
|
4217
|
+
* TipTap document node schema (recursive structure)
|
|
4218
|
+
*
|
|
4219
|
+
* Supports the full TipTap document structure including:
|
|
4220
|
+
* - type: Node type (e.g., 'doc', 'paragraph', 'text')
|
|
4221
|
+
* - content: Nested array of child nodes
|
|
4222
|
+
* - text: Text content for text nodes
|
|
4223
|
+
* - attrs: Node attributes (e.g., alignment, color)
|
|
4224
|
+
* - marks: Text formatting marks (e.g., bold, italic)
|
|
4225
|
+
*/
|
|
4226
|
+
const TipTapMarkSchema = z.object({
|
|
4227
|
+
type: z.string().min(1),
|
|
4228
|
+
attrs: z.record(z.string(), z.unknown()).optional()
|
|
4229
|
+
}).strict();
|
|
4230
|
+
const TipTapNodeSchema = z.lazy(() => z.object({
|
|
4231
|
+
type: z.string().min(1),
|
|
4232
|
+
content: z.array(TipTapNodeSchema).optional(),
|
|
4233
|
+
text: z.string().optional(),
|
|
4234
|
+
attrs: z.record(z.string(), z.unknown()).optional(),
|
|
4235
|
+
marks: z.array(TipTapMarkSchema).optional()
|
|
4236
|
+
}).strict().superRefine((node, ctx) => {
|
|
4237
|
+
if (node.type === "doc") ctx.addIssue({
|
|
4238
|
+
code: "custom",
|
|
4239
|
+
path: ["type"],
|
|
4240
|
+
message: "Document nodes are only valid at the rich-text root"
|
|
4241
|
+
});
|
|
4242
|
+
if (node.type === "text") {
|
|
4243
|
+
if (node.text === void 0 || node.text.length === 0) ctx.addIssue({
|
|
4244
|
+
code: "custom",
|
|
4245
|
+
path: ["text"],
|
|
4246
|
+
message: "Text nodes require a non-empty text value"
|
|
4247
|
+
});
|
|
4248
|
+
if (node.content !== void 0) ctx.addIssue({
|
|
4249
|
+
code: "custom",
|
|
4250
|
+
path: ["content"],
|
|
4251
|
+
message: "Text nodes cannot contain child nodes"
|
|
4252
|
+
});
|
|
4253
|
+
return;
|
|
4254
|
+
}
|
|
4255
|
+
if (node.text !== void 0) ctx.addIssue({
|
|
4256
|
+
code: "custom",
|
|
4257
|
+
path: ["text"],
|
|
4258
|
+
message: "Only text nodes can contain a text value"
|
|
4259
|
+
});
|
|
4260
|
+
}));
|
|
4261
|
+
/**
|
|
4262
|
+
* Canonical schema for a TipTap rich-text document root.
|
|
4263
|
+
*
|
|
4264
|
+
* Stricter than {@link TipTapNodeSchema}: `type` is literally `'doc'` and
|
|
4265
|
+
* `content` is required (possibly empty). This is the shape every producer
|
|
4266
|
+
* (dummy content, editor output, migrations) must emit, and the shape every
|
|
4267
|
+
* non-legacy consumer can rely on.
|
|
4268
|
+
*
|
|
4269
|
+
*/
|
|
4270
|
+
const RichTextDocSchema = z.object({
|
|
4271
|
+
type: z.literal("doc"),
|
|
4272
|
+
content: z.array(TipTapNodeSchema)
|
|
4273
|
+
}).strict();
|
|
4274
|
+
//#endregion
|
|
4275
|
+
//#region ../blocks/src/system/blocks/shared/bookingConsent.ts
|
|
4276
|
+
const BOOKING_REQUIREMENT_CONSENT_FIELD_PREFIX = "booking_requirement_consent_";
|
|
4277
|
+
function toBookingRequirementConsentFieldId(requirementId) {
|
|
4278
|
+
return `${BOOKING_REQUIREMENT_CONSENT_FIELD_PREFIX}${requirementId}`;
|
|
4279
|
+
}
|
|
4280
|
+
function isBookingRequirementConsentFieldId(value) {
|
|
4281
|
+
return value.startsWith(BOOKING_REQUIREMENT_CONSENT_FIELD_PREFIX);
|
|
4282
|
+
}
|
|
4283
|
+
function toBookingRequirementConsentField(consent) {
|
|
4284
|
+
return {
|
|
4285
|
+
id: toBookingRequirementConsentFieldId(consent.requirementId),
|
|
4286
|
+
label: consent.title,
|
|
4287
|
+
type: "booking_requirement_consent",
|
|
4288
|
+
required: true,
|
|
4289
|
+
agreement: consent.agreement,
|
|
4290
|
+
checkboxLabel: consent.checkboxLabel
|
|
4291
|
+
};
|
|
4292
|
+
}
|
|
4293
|
+
const blockBookingConsentSchema = z.object({
|
|
4294
|
+
requirementId: z.string(),
|
|
4295
|
+
title: z.string(),
|
|
4296
|
+
agreement: RichTextDocSchema,
|
|
4297
|
+
checkboxLabel: z.string()
|
|
4298
|
+
});
|
|
4299
|
+
const bookingRequirementConsentFieldSchema = z.object({
|
|
4300
|
+
id: z.string(),
|
|
4301
|
+
label: z.string(),
|
|
4302
|
+
type: z.literal("booking_requirement_consent"),
|
|
4303
|
+
required: z.literal(true),
|
|
4304
|
+
agreement: RichTextDocSchema,
|
|
4305
|
+
checkboxLabel: z.string().min(1)
|
|
4306
|
+
});
|
|
4307
|
+
z.union([blockBookingConsentSchema, bookingRequirementConsentFieldSchema]);
|
|
4308
|
+
//#endregion
|
|
4216
4309
|
//#region ../blocks/src/system/runtime/nodes/booking-form.reserved-fields.ts
|
|
4217
4310
|
const BOOKING_FORM_DATA_RESERVED_KEY_VALUES = [
|
|
4218
4311
|
"serviceId",
|
|
@@ -4226,6 +4319,28 @@ const BOOKING_FORM_DATA_RESERVED_KEY_VALUES = [
|
|
|
4226
4319
|
];
|
|
4227
4320
|
const BOOKING_FORM_DATA_RESERVED_KEYS = new Set(BOOKING_FORM_DATA_RESERVED_KEY_VALUES);
|
|
4228
4321
|
//#endregion
|
|
4322
|
+
//#region ../blocks/src/system/runtime/nodes/booking-form.consent.ts
|
|
4323
|
+
function resolveSelectedAppointmentConsent(service) {
|
|
4324
|
+
return service?.consent ? {
|
|
4325
|
+
kind: "required-for-selected-service",
|
|
4326
|
+
field: toBookingRequirementConsentField(service.consent)
|
|
4327
|
+
} : { kind: "not-applicable" };
|
|
4328
|
+
}
|
|
4329
|
+
function projectSelectedAppointmentConsentIntoForm(form, selectedConsent) {
|
|
4330
|
+
if (!form) return null;
|
|
4331
|
+
const sourceFields = form.schema?.fields ?? [];
|
|
4332
|
+
const baseFields = sourceFields.filter((field) => field.type !== "booking_requirement_consent");
|
|
4333
|
+
const fields = selectedConsent.kind === "required-for-selected-service" ? [...baseFields, selectedConsent.field] : baseFields;
|
|
4334
|
+
if (selectedConsent.kind === "not-applicable" && baseFields.length === sourceFields.length) return form;
|
|
4335
|
+
return {
|
|
4336
|
+
...form,
|
|
4337
|
+
schema: {
|
|
4338
|
+
...form.schema,
|
|
4339
|
+
fields
|
|
4340
|
+
}
|
|
4341
|
+
};
|
|
4342
|
+
}
|
|
4343
|
+
//#endregion
|
|
4229
4344
|
//#region ../blocks/src/system/runtime/nodes/booking-form.state.ts
|
|
4230
4345
|
function toTrimmedString(value) {
|
|
4231
4346
|
const trimmed = value?.trim();
|
|
@@ -4408,7 +4523,6 @@ function readBookingFieldType(value) {
|
|
|
4408
4523
|
case "select":
|
|
4409
4524
|
case "radio":
|
|
4410
4525
|
case "checkbox":
|
|
4411
|
-
case "booking_requirement_consent":
|
|
4412
4526
|
case "tel":
|
|
4413
4527
|
case "url":
|
|
4414
4528
|
case "number":
|
|
@@ -4443,7 +4557,7 @@ function normalizeBookingSettings(value) {
|
|
|
4443
4557
|
};
|
|
4444
4558
|
}
|
|
4445
4559
|
function isBookingFormService(value) {
|
|
4446
|
-
return isRecord$5(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string";
|
|
4560
|
+
return isRecord$5(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string" && (value.consent === void 0 || blockBookingConsentSchema.safeParse(value.consent).success);
|
|
4447
4561
|
}
|
|
4448
4562
|
function collectBookingCustomFields(data) {
|
|
4449
4563
|
const customFields = {};
|
|
@@ -4687,6 +4801,11 @@ function getBookingSuccessMessage(successMessage) {
|
|
|
4687
4801
|
return successMessage?.trim() || "Your appointment has been booked! Check your email for confirmation.";
|
|
4688
4802
|
}
|
|
4689
4803
|
//#endregion
|
|
4804
|
+
//#region ../blocks/src/system/runtime/hooks/useSelectedAppointmentConsentForm.ts
|
|
4805
|
+
function useSelectedAppointmentConsentForm(form, selectedService) {
|
|
4806
|
+
return useMemo(() => projectSelectedAppointmentConsentIntoForm(form, resolveSelectedAppointmentConsent(selectedService)), [form, selectedService]);
|
|
4807
|
+
}
|
|
4808
|
+
//#endregion
|
|
4690
4809
|
//#region ../blocks/src/utils/date-formatting.ts
|
|
4691
4810
|
/**
|
|
4692
4811
|
* Resolve the browser/runtime timezone for booking surfaces.
|
|
@@ -5751,6 +5870,19 @@ function clearBookingFieldError(errors, fieldId) {
|
|
|
5751
5870
|
};
|
|
5752
5871
|
}
|
|
5753
5872
|
//#endregion
|
|
5873
|
+
//#region ../blocks/src/system/runtime/nodes/booking-form.field-values.ts
|
|
5874
|
+
function collectInitialBookingFieldValues(initialData) {
|
|
5875
|
+
const values = {};
|
|
5876
|
+
for (const [key, value] of Object.entries(initialData)) if (!BOOKING_FORM_DATA_RESERVED_KEYS.has(key) && !isBookingRequirementConsentFieldId(key) && isBookingFieldValue(value)) values[key] = value;
|
|
5877
|
+
return values;
|
|
5878
|
+
}
|
|
5879
|
+
function omitBookingConsentEntries(record) {
|
|
5880
|
+
return Object.fromEntries(Object.entries(record).filter(([key]) => !isBookingRequirementConsentFieldId(key)));
|
|
5881
|
+
}
|
|
5882
|
+
function isBookingFieldValue(value) {
|
|
5883
|
+
return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
5884
|
+
}
|
|
5885
|
+
//#endregion
|
|
5754
5886
|
//#region ../blocks/src/system/runtime/nodes/booking-form.headless.state.ts
|
|
5755
5887
|
const unsafeAsBookingFieldId = (id) => id;
|
|
5756
5888
|
function createInitialBookingFlowReducerState(input) {
|
|
@@ -5762,7 +5894,7 @@ function createInitialBookingFlowReducerState(input) {
|
|
|
5762
5894
|
selectedResourceId: toOptionalAppointmentResourceId(toOptionalString(initialData.resourceId) ?? input.defaultResourceId),
|
|
5763
5895
|
selectedDate: toOptionalString(initialData.selectedDate),
|
|
5764
5896
|
selectedSlot: null,
|
|
5765
|
-
fieldValues:
|
|
5897
|
+
fieldValues: collectInitialBookingFieldValues(initialData),
|
|
5766
5898
|
touchedFields: {},
|
|
5767
5899
|
attemptedStepIds: {},
|
|
5768
5900
|
discountCode: toOptionalString(initialData.discountCode) ?? "",
|
|
@@ -5774,14 +5906,6 @@ function createInitialBookingFlowReducerState(input) {
|
|
|
5774
5906
|
feedback: { kind: "none" }
|
|
5775
5907
|
};
|
|
5776
5908
|
}
|
|
5777
|
-
function collectInitialFieldValues(initialData) {
|
|
5778
|
-
const values = {};
|
|
5779
|
-
for (const [key, value] of Object.entries(initialData)) {
|
|
5780
|
-
if (BOOKING_FORM_DATA_RESERVED_KEYS.has(key) || !isBookingFieldValue(value)) continue;
|
|
5781
|
-
values[key] = value;
|
|
5782
|
-
}
|
|
5783
|
-
return values;
|
|
5784
|
-
}
|
|
5785
5909
|
function toOptionalString(value) {
|
|
5786
5910
|
if (typeof value !== "string") return void 0;
|
|
5787
5911
|
const trimmed = value.trim();
|
|
@@ -5803,9 +5927,6 @@ function toOptionalAppointmentResourceId(value) {
|
|
|
5803
5927
|
function toOptionalCustomerPassId(value) {
|
|
5804
5928
|
return toOptionalBrandedId(value, unsafeAsCustomerPassId);
|
|
5805
5929
|
}
|
|
5806
|
-
function isBookingFieldValue(value) {
|
|
5807
|
-
return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
5808
|
-
}
|
|
5809
5930
|
/**
|
|
5810
5931
|
* Send the flow back to the date step when the slot it was holding went away,
|
|
5811
5932
|
* leaving a scoped feedback message. A completed booking is left alone.
|
|
@@ -5827,17 +5948,7 @@ function applyAvailabilitySelectionInvalidation(state, invalidation) {
|
|
|
5827
5948
|
}
|
|
5828
5949
|
function bookingFlowReducer(state, event) {
|
|
5829
5950
|
switch (event.type) {
|
|
5830
|
-
case "service-selected": return
|
|
5831
|
-
...state,
|
|
5832
|
-
selectedServiceId: event.serviceId,
|
|
5833
|
-
selectedResourceId: void 0,
|
|
5834
|
-
selectedDate: void 0,
|
|
5835
|
-
selectedSlot: null,
|
|
5836
|
-
selectedAppointmentPackageId: void 0,
|
|
5837
|
-
selectedSlidingAmountInput: "",
|
|
5838
|
-
selectedCollectionOptionKind: void 0,
|
|
5839
|
-
validationErrors: clearBookingFormError(state.validationErrors)
|
|
5840
|
-
};
|
|
5951
|
+
case "service-selected": return applyBookingServiceSelection(state, event.serviceId);
|
|
5841
5952
|
case "resource-selected": return {
|
|
5842
5953
|
...state,
|
|
5843
5954
|
selectedResourceId: event.resourceId ?? void 0,
|
|
@@ -5944,6 +6055,24 @@ function bookingFlowReducer(state, event) {
|
|
|
5944
6055
|
default: return assertNever(event);
|
|
5945
6056
|
}
|
|
5946
6057
|
}
|
|
6058
|
+
function applyBookingServiceSelection(state, serviceId) {
|
|
6059
|
+
return {
|
|
6060
|
+
...state,
|
|
6061
|
+
selectedServiceId: serviceId,
|
|
6062
|
+
selectedResourceId: void 0,
|
|
6063
|
+
selectedDate: void 0,
|
|
6064
|
+
selectedSlot: null,
|
|
6065
|
+
selectedAppointmentPackageId: void 0,
|
|
6066
|
+
selectedSlidingAmountInput: "",
|
|
6067
|
+
selectedCollectionOptionKind: void 0,
|
|
6068
|
+
fieldValues: omitBookingConsentEntries(state.fieldValues),
|
|
6069
|
+
touchedFields: omitBookingConsentEntries(state.touchedFields),
|
|
6070
|
+
validationErrors: {
|
|
6071
|
+
...clearBookingFormError(state.validationErrors),
|
|
6072
|
+
fieldErrors: omitBookingConsentEntries(state.validationErrors.fieldErrors)
|
|
6073
|
+
}
|
|
6074
|
+
};
|
|
6075
|
+
}
|
|
5947
6076
|
function clearAvailabilityFeedback(feedback) {
|
|
5948
6077
|
return feedback.kind === "error" && feedback.scope === "availability" ? { kind: "none" } : feedback;
|
|
5949
6078
|
}
|
|
@@ -6104,7 +6233,8 @@ function validateBookingFields(input) {
|
|
|
6104
6233
|
return errors;
|
|
6105
6234
|
}
|
|
6106
6235
|
function validateBookingField(field, value) {
|
|
6107
|
-
|
|
6236
|
+
const requiredError = validateRequiredBookingField(field, value);
|
|
6237
|
+
if (requiredError) return requiredError;
|
|
6108
6238
|
if (isBlankFieldValue(value)) return null;
|
|
6109
6239
|
const strValue = typeof value === "string" ? value : String(value);
|
|
6110
6240
|
if (field.type === "email") return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(strValue) ? null : "Please enter a valid email address";
|
|
@@ -6133,6 +6263,10 @@ function validateBookingField(field, value) {
|
|
|
6133
6263
|
}
|
|
6134
6264
|
return null;
|
|
6135
6265
|
}
|
|
6266
|
+
function validateRequiredBookingField(field, value) {
|
|
6267
|
+
if (field.type === "booking_requirement_consent") return value === true ? null : `${field.label} is required`;
|
|
6268
|
+
return field.required && isBlankFieldValue(value) ? `${field.label} is required` : null;
|
|
6269
|
+
}
|
|
6136
6270
|
function deriveBookingFlowSteps(input) {
|
|
6137
6271
|
const stepResolution = buildBookingStepResolution({
|
|
6138
6272
|
form: input.form,
|
|
@@ -6204,7 +6338,8 @@ function deriveBookingFieldViews(input) {
|
|
|
6204
6338
|
return (input.form?.schema?.fields ?? []).map((field) => {
|
|
6205
6339
|
const fieldId = unsafeAsBookingFieldId(field.id);
|
|
6206
6340
|
const inputId = `${input.idPrefix}-${fieldId}`;
|
|
6207
|
-
const
|
|
6341
|
+
const helpText = field.type === "booking_requirement_consent" ? null : field.helpText ?? null;
|
|
6342
|
+
const helpTextId = helpText ? `${inputId}-help` : null;
|
|
6208
6343
|
const fieldValue = input.values[field.id] ?? null;
|
|
6209
6344
|
const localError = input.touched?.[field.id] ? validateBookingField(field, fieldValue) : null;
|
|
6210
6345
|
const error = input.errors[field.id] ?? localError;
|
|
@@ -6214,17 +6349,17 @@ function deriveBookingFieldViews(input) {
|
|
|
6214
6349
|
field,
|
|
6215
6350
|
id: fieldId,
|
|
6216
6351
|
label: field.label,
|
|
6217
|
-
type: field.type,
|
|
6218
6352
|
value: fieldValue,
|
|
6219
6353
|
required: Boolean(field.required),
|
|
6220
6354
|
error,
|
|
6221
|
-
helpText
|
|
6355
|
+
helpText,
|
|
6222
6356
|
inputId,
|
|
6223
6357
|
labelId: `${inputId}-label`,
|
|
6224
6358
|
helpTextId,
|
|
6225
6359
|
errorId,
|
|
6226
6360
|
describedBy,
|
|
6227
|
-
ariaInvalid: Boolean(error)
|
|
6361
|
+
ariaInvalid: Boolean(error),
|
|
6362
|
+
type: field.type
|
|
6228
6363
|
};
|
|
6229
6364
|
});
|
|
6230
6365
|
}
|
|
@@ -6486,6 +6621,7 @@ function useHeadlessBookingFlow(options) {
|
|
|
6486
6621
|
const selectedServiceId = state.selectedServiceId ?? defaultServiceId;
|
|
6487
6622
|
const selectedResourceId = state.selectedResourceId ?? defaultResourceId;
|
|
6488
6623
|
const selectedService = options.services.find((service) => service.id === selectedServiceId) ?? null;
|
|
6624
|
+
const runtimeForm = useSelectedAppointmentConsentForm(options.form, selectedService);
|
|
6489
6625
|
const lastSlidingServiceIdRef = useRef(null);
|
|
6490
6626
|
useEffect(() => {
|
|
6491
6627
|
const selectedId = selectedService?.id ?? null;
|
|
@@ -6526,7 +6662,7 @@ function useHeadlessBookingFlow(options) {
|
|
|
6526
6662
|
viewerTimeZone
|
|
6527
6663
|
]);
|
|
6528
6664
|
const stepState = useMemo(() => deriveBookingFlowSteps({
|
|
6529
|
-
form:
|
|
6665
|
+
form: runtimeForm,
|
|
6530
6666
|
services: options.services,
|
|
6531
6667
|
data,
|
|
6532
6668
|
defaultServiceId,
|
|
@@ -6542,7 +6678,7 @@ function useHeadlessBookingFlow(options) {
|
|
|
6542
6678
|
defaultServiceId,
|
|
6543
6679
|
defaultResourceId,
|
|
6544
6680
|
options.enableAppointmentPackages,
|
|
6545
|
-
|
|
6681
|
+
runtimeForm,
|
|
6546
6682
|
options.requiresResourceSelection,
|
|
6547
6683
|
options.requiresServiceSelection,
|
|
6548
6684
|
options.services,
|
|
@@ -6596,13 +6732,13 @@ function useHeadlessBookingFlow(options) {
|
|
|
6596
6732
|
state.selectedSlot
|
|
6597
6733
|
]);
|
|
6598
6734
|
const fields = useMemo(() => deriveBookingFieldViews({
|
|
6599
|
-
form:
|
|
6735
|
+
form: runtimeForm,
|
|
6600
6736
|
values: state.fieldValues,
|
|
6601
6737
|
errors: state.validationErrors.fieldErrors,
|
|
6602
6738
|
touched: state.touchedFields,
|
|
6603
6739
|
idPrefix: `booking-${options.formId}`
|
|
6604
6740
|
}), [
|
|
6605
|
-
|
|
6741
|
+
runtimeForm,
|
|
6606
6742
|
options.formId,
|
|
6607
6743
|
state.fieldValues,
|
|
6608
6744
|
state.touchedFields,
|
|
@@ -6722,7 +6858,7 @@ function useHeadlessBookingFlow(options) {
|
|
|
6722
6858
|
const latestRef = useLatestRef({
|
|
6723
6859
|
state,
|
|
6724
6860
|
data,
|
|
6725
|
-
form:
|
|
6861
|
+
form: runtimeForm,
|
|
6726
6862
|
formId: formKey,
|
|
6727
6863
|
services: options.services,
|
|
6728
6864
|
defaultServiceId,
|
|
@@ -6974,7 +7110,7 @@ function useHeadlessBookingFlow(options) {
|
|
|
6974
7110
|
phase: state.phase
|
|
6975
7111
|
});
|
|
6976
7112
|
const view = resolveHeadlessBookingView({
|
|
6977
|
-
form:
|
|
7113
|
+
form: runtimeForm,
|
|
6978
7114
|
feedback: state.feedback
|
|
6979
7115
|
});
|
|
6980
7116
|
const appointmentPackagesModel = resolveAppointmentPackagesModel({
|
|
@@ -7530,6 +7666,12 @@ const opaqueButtonColourTokenSchema = themeColorTokenSchema.refine((value) => pa
|
|
|
7530
7666
|
if (token === null) throw new Error("Invariant: opaque button token passed its schema");
|
|
7531
7667
|
return token;
|
|
7532
7668
|
});
|
|
7669
|
+
const contextualButtonHoverSchema = z.strictObject({
|
|
7670
|
+
kind: z.literal("shade-shift"),
|
|
7671
|
+
seedToken: opaqueButtonColourTokenSchema,
|
|
7672
|
+
fallbackDirection: z.enum(["lighter", "darker"]),
|
|
7673
|
+
preferredToken: opaqueButtonColourTokenSchema.optional()
|
|
7674
|
+
});
|
|
7533
7675
|
const buttonShadeAmountSchema = z.number().finite().min(0).max(900).multipleOf(100);
|
|
7534
7676
|
const buttonShadowIntensitySchema = z.enum([
|
|
7535
7677
|
"subtle",
|
|
@@ -7869,6 +8011,7 @@ const buttonVariantSchema = z.strictObject({
|
|
|
7869
8011
|
shadow: variantShadowSchema.optional(),
|
|
7870
8012
|
border: buttonBorderSchema.optional(),
|
|
7871
8013
|
hoverBackgroundToken: opaqueButtonColourTokenSchema.optional(),
|
|
8014
|
+
contextualHover: contextualButtonHoverSchema.optional(),
|
|
7872
8015
|
effects: variantEffectsSchema.optional(),
|
|
7873
8016
|
sizes: variantSizeOverridesSchema.optional(),
|
|
7874
8017
|
affordance: buttonVariantAffordanceSchema.optional()
|
|
@@ -8154,8 +8297,8 @@ const openCardRoleValue = "open";
|
|
|
8154
8297
|
*/
|
|
8155
8298
|
const surfaceCardRoleValues = [...cardVariantRoleValues, openCardRoleValue];
|
|
8156
8299
|
/**
|
|
8157
|
-
* The closed
|
|
8158
|
-
*
|
|
8300
|
+
* The closed role vocabulary Looks and blocks use for surfaced and boxless
|
|
8301
|
+
* card choices.
|
|
8159
8302
|
*
|
|
8160
8303
|
* - `none` — no site-style card surface; the block's own composition and
|
|
8161
8304
|
* the author's own card fields govern the item. This is *not*
|
|
@@ -8199,11 +8342,6 @@ const gradientDirectionSchema = z.enum([
|
|
|
8199
8342
|
z.enum(cardVariantRoleValues);
|
|
8200
8343
|
const surfaceCardRoleSchema = z.enum(surfaceCardRoleValues);
|
|
8201
8344
|
const cardRoleSchema = z.enum(cardRoleValues);
|
|
8202
|
-
/**
|
|
8203
|
-
* Historical name for the role vocabulary as it reaches box styles. Widened to
|
|
8204
|
-
* the full `CardRole` set — old values keep parsing, `open` now parses too.
|
|
8205
|
-
*/
|
|
8206
|
-
const boxStylesCardVariantSchema = cardRoleSchema;
|
|
8207
8345
|
const PRIORITY_ROLE_INFERENCE = {
|
|
8208
8346
|
1: "default",
|
|
8209
8347
|
2: "alternative"
|
|
@@ -9608,8 +9746,7 @@ const cardStylesOverrideSchema = z.object({
|
|
|
9608
9746
|
spacing: semanticSpacingSchema.nullable().optional(),
|
|
9609
9747
|
raised: z.boolean().nullable().optional(),
|
|
9610
9748
|
rounded: boxRoundedSchema.nullable().optional(),
|
|
9611
|
-
role: cardRoleSchema.nullable().optional()
|
|
9612
|
-
cardVariant: boxStylesCardVariantSchema.nullable().optional()
|
|
9749
|
+
role: cardRoleSchema.nullable().optional()
|
|
9613
9750
|
});
|
|
9614
9751
|
const blockStyleOverridesSchema = z.object({
|
|
9615
9752
|
sectionStyles: sectionStylesOverrideSchema.nullable().optional(),
|
|
@@ -10238,13 +10375,7 @@ function shadeBackgroundEffect(config) {
|
|
|
10238
10375
|
buttonSizeNameSchema.options;
|
|
10239
10376
|
//#endregion
|
|
10240
10377
|
//#region ../theme-core/src/buttons/styles/domain.ts
|
|
10241
|
-
const PUBLIC_BUTTON_ROLES =
|
|
10242
|
-
"primary",
|
|
10243
|
-
"secondary",
|
|
10244
|
-
"outline",
|
|
10245
|
-
"ghost",
|
|
10246
|
-
"accent"
|
|
10247
|
-
];
|
|
10378
|
+
const PUBLIC_BUTTON_ROLES = VARIANT_ROLES;
|
|
10248
10379
|
function defineButtonStyleRecipe(recipe) {
|
|
10249
10380
|
return recipe;
|
|
10250
10381
|
}
|
|
@@ -10340,6 +10471,14 @@ const BUTTON_STYLE_IDS = [
|
|
|
10340
10471
|
"quiet-arrow"
|
|
10341
10472
|
];
|
|
10342
10473
|
const quietArrowParametersSchema = z.object({ secondaryTreatment: z.enum(["outlined", "solid-accent"]) }).strict();
|
|
10474
|
+
const flatInkHoverTreatmentSchema = z.enum([
|
|
10475
|
+
"contextual",
|
|
10476
|
+
"secondary",
|
|
10477
|
+
"accent"
|
|
10478
|
+
]);
|
|
10479
|
+
const flatInkHoverPreferencesShape = Object.fromEntries(VARIANT_ROLES.map((role) => [role, flatInkHoverTreatmentSchema.optional()]));
|
|
10480
|
+
const flatInkHoverPreferencesSchema = z.strictObject(flatInkHoverPreferencesShape);
|
|
10481
|
+
const flatInkParametersSchema = z.strictObject({ hoverPreferences: flatInkHoverPreferencesSchema.optional() });
|
|
10343
10482
|
const emptyParametersSchema$1 = z.object({}).strict();
|
|
10344
10483
|
function selectionBranch(styleId, parameters) {
|
|
10345
10484
|
return z.object({
|
|
@@ -10354,7 +10493,7 @@ z.discriminatedUnion("styleId", [
|
|
|
10354
10493
|
selectionBranch("editorial-link", emptyParametersSchema$1),
|
|
10355
10494
|
selectionBranch("pebble", emptyParametersSchema$1),
|
|
10356
10495
|
selectionBranch("ink-stamp", emptyParametersSchema$1),
|
|
10357
|
-
selectionBranch("flat-ink",
|
|
10496
|
+
selectionBranch("flat-ink", flatInkParametersSchema),
|
|
10358
10497
|
selectionBranch("brushed-wash", emptyParametersSchema$1),
|
|
10359
10498
|
selectionBranch("showtime-pill", emptyParametersSchema$1),
|
|
10360
10499
|
selectionBranch("joy-stamp", emptyParametersSchema$1),
|
|
@@ -10491,105 +10630,288 @@ const quietArrowRecipe = defineButtonStyleRecipe({
|
|
|
10491
10630
|
})
|
|
10492
10631
|
});
|
|
10493
10632
|
//#endregion
|
|
10494
|
-
//#region ../theme-core/src/buttons/styles/recipes/
|
|
10495
|
-
const
|
|
10496
|
-
|
|
10497
|
-
|
|
10498
|
-
|
|
10499
|
-
|
|
10500
|
-
|
|
10501
|
-
|
|
10502
|
-
|
|
10503
|
-
|
|
10504
|
-
|
|
10505
|
-
|
|
10506
|
-
|
|
10507
|
-
}
|
|
10508
|
-
|
|
10509
|
-
|
|
10510
|
-
|
|
10511
|
-
|
|
10512
|
-
|
|
10513
|
-
|
|
10514
|
-
|
|
10515
|
-
|
|
10516
|
-
|
|
10517
|
-
|
|
10633
|
+
//#region ../theme-core/src/buttons/styles/recipes/flatInk.ts
|
|
10634
|
+
const contextualRoleConfig = {
|
|
10635
|
+
primary: {
|
|
10636
|
+
contextualSeedToken: unsafeAsOpaqueButtonColourToken("primary"),
|
|
10637
|
+
fallbackDirection: "darker"
|
|
10638
|
+
},
|
|
10639
|
+
secondary: {
|
|
10640
|
+
contextualSeedToken: unsafeAsOpaqueButtonColourToken("surfaceAlt"),
|
|
10641
|
+
fallbackDirection: "darker"
|
|
10642
|
+
},
|
|
10643
|
+
outline: {
|
|
10644
|
+
contextualSeedToken: unsafeAsOpaqueButtonColourToken("surfaceAlt"),
|
|
10645
|
+
fallbackDirection: "darker"
|
|
10646
|
+
},
|
|
10647
|
+
ghost: {
|
|
10648
|
+
contextualSeedToken: unsafeAsOpaqueButtonColourToken("surfaceAlt"),
|
|
10649
|
+
fallbackDirection: "darker"
|
|
10650
|
+
},
|
|
10651
|
+
accent: {
|
|
10652
|
+
contextualSeedToken: unsafeAsOpaqueButtonColourToken("accent"),
|
|
10653
|
+
fallbackDirection: "darker"
|
|
10654
|
+
}
|
|
10655
|
+
};
|
|
10656
|
+
const hoverControl = {
|
|
10657
|
+
kind: "button-hover-by-role",
|
|
10658
|
+
parameter: "hoverPreferences",
|
|
10659
|
+
label: "Button hover",
|
|
10660
|
+
roles: contextualRoleConfig,
|
|
10661
|
+
options: [
|
|
10662
|
+
{
|
|
10663
|
+
value: "contextual",
|
|
10664
|
+
label: "Contextual shade shift"
|
|
10665
|
+
},
|
|
10666
|
+
{
|
|
10667
|
+
value: "secondary",
|
|
10668
|
+
label: "Secondary button colour"
|
|
10669
|
+
},
|
|
10670
|
+
{
|
|
10671
|
+
value: "accent",
|
|
10672
|
+
label: "Accent button colour"
|
|
10518
10673
|
}
|
|
10519
|
-
|
|
10520
|
-
}
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
|
|
10524
|
-
|
|
10525
|
-
};
|
|
10526
|
-
}
|
|
10527
|
-
function normalizeSupportingRole(role) {
|
|
10528
|
-
if (role.kind === "complete") return normalizeCompleteRole(role);
|
|
10529
|
-
return {
|
|
10530
|
-
kind: "derive",
|
|
10531
|
-
from: role.from,
|
|
10532
|
-
...role.overrides ? { overrides: normalizeAppearanceOverrides(role.overrides) } : {}
|
|
10533
|
-
};
|
|
10534
|
-
}
|
|
10535
|
-
function normalizeAppearance(appearance) {
|
|
10536
|
-
const { background, hoverBackgroundToken, ...rest } = appearance;
|
|
10537
|
-
return {
|
|
10538
|
-
...rest,
|
|
10539
|
-
background: buttonColourTreatmentSchema.parse(background),
|
|
10540
|
-
...hoverBackgroundToken ? { hoverBackgroundToken: opaqueButtonColourTokenSchema.parse(hoverBackgroundToken) } : {}
|
|
10541
|
-
};
|
|
10542
|
-
}
|
|
10543
|
-
function normalizeAppearanceOverrides(overrides) {
|
|
10544
|
-
const { background, hoverBackgroundToken, ...rest } = overrides;
|
|
10545
|
-
return {
|
|
10546
|
-
...rest,
|
|
10547
|
-
...background ? { background: buttonColourTreatmentSchema.parse(background) } : {},
|
|
10548
|
-
...hoverBackgroundToken ? { hoverBackgroundToken: opaqueButtonColourTokenSchema.parse(hoverBackgroundToken) } : {}
|
|
10549
|
-
};
|
|
10550
|
-
}
|
|
10551
|
-
//#endregion
|
|
10552
|
-
//#region ../theme-core/src/buttons/styles/recipes/staticRecipes.ts
|
|
10553
|
-
const softPillRecipe = defineStaticButtonStyleRecipe({
|
|
10554
|
-
id: "soft-pill",
|
|
10555
|
-
accessibilityLabel: "Rounded pill buttons with a gentle hover lift",
|
|
10674
|
+
]
|
|
10675
|
+
};
|
|
10676
|
+
const lift = { effectId: "lift" };
|
|
10677
|
+
const flatInkRecipe = defineButtonStyleRecipe({
|
|
10678
|
+
id: "flat-ink",
|
|
10679
|
+
accessibilityLabel: "Flat rounded buttons with arrow affordances",
|
|
10556
10680
|
tags: {
|
|
10557
10681
|
tone: "classic",
|
|
10558
10682
|
energy: "calm",
|
|
10559
10683
|
motion: "subtle",
|
|
10560
|
-
era: "
|
|
10684
|
+
era: "editorial"
|
|
10561
10685
|
},
|
|
10562
|
-
|
|
10686
|
+
parameterSchema: flatInkParametersSchema,
|
|
10687
|
+
defaultParameters: {},
|
|
10688
|
+
controls: [hoverControl],
|
|
10689
|
+
defineSystem: (parameters) => ({
|
|
10563
10690
|
global: {
|
|
10564
|
-
cornerStyle: "
|
|
10565
|
-
shadow: "low",
|
|
10691
|
+
cornerStyle: "rounded",
|
|
10566
10692
|
textTransform: "none",
|
|
10567
|
-
fontWeight:
|
|
10693
|
+
fontWeight: 600,
|
|
10694
|
+
typography: "body",
|
|
10695
|
+
letterSpacing: "tight",
|
|
10696
|
+
paddingPreset: "default",
|
|
10568
10697
|
hoverTransform: "lift",
|
|
10569
10698
|
hoverColor: "none"
|
|
10570
10699
|
},
|
|
10700
|
+
sizes: {
|
|
10701
|
+
sm: {
|
|
10702
|
+
padding: "0.625rem 1.125rem",
|
|
10703
|
+
fontSize: "text-sm"
|
|
10704
|
+
},
|
|
10705
|
+
md: { padding: "0.8125rem 1.375rem" },
|
|
10706
|
+
lg: {
|
|
10707
|
+
padding: "0.9375rem 1.625rem",
|
|
10708
|
+
fontSize: "text-lg"
|
|
10709
|
+
},
|
|
10710
|
+
xl: {
|
|
10711
|
+
padding: "1.0625rem 2rem",
|
|
10712
|
+
fontSize: "text-xl"
|
|
10713
|
+
}
|
|
10714
|
+
},
|
|
10571
10715
|
roles: {
|
|
10572
10716
|
primary: {
|
|
10573
10717
|
kind: "complete",
|
|
10574
10718
|
appearance: {
|
|
10575
10719
|
background: {
|
|
10576
10720
|
type: "solid",
|
|
10577
|
-
colorToken: "primary"
|
|
10578
|
-
},
|
|
10579
|
-
borderRadius: "rounded-full",
|
|
10580
|
-
shadow: {
|
|
10581
|
-
elevation: "low",
|
|
10582
|
-
softness: "soft",
|
|
10583
|
-
position: "bottom"
|
|
10721
|
+
colorToken: unsafeAsOpaqueButtonColourToken("primary")
|
|
10584
10722
|
},
|
|
10585
|
-
|
|
10586
|
-
|
|
10587
|
-
|
|
10588
|
-
|
|
10589
|
-
|
|
10590
|
-
|
|
10591
|
-
|
|
10592
|
-
|
|
10723
|
+
borderRadius: "rounded-lg",
|
|
10724
|
+
affordance: { iconId: "ArrowRight" },
|
|
10725
|
+
...hoverAppearance("primary", parameters, [lift, {
|
|
10726
|
+
effectId: "background-on-hover",
|
|
10727
|
+
options: { colorToken: unsafeAsOpaqueButtonColourToken("secondary") }
|
|
10728
|
+
}])
|
|
10729
|
+
}
|
|
10730
|
+
},
|
|
10731
|
+
secondary: {
|
|
10732
|
+
kind: "complete",
|
|
10733
|
+
appearance: {
|
|
10734
|
+
background: {
|
|
10735
|
+
type: "surface",
|
|
10736
|
+
role: "link"
|
|
10737
|
+
},
|
|
10738
|
+
borderRadius: "rounded-lg",
|
|
10739
|
+
border: { widthClass: "border" },
|
|
10740
|
+
...hoverAppearance("secondary", parameters, [lift, {
|
|
10741
|
+
effectId: "background-on-hover",
|
|
10742
|
+
options: { colorToken: unsafeAsOpaqueButtonColourToken("surfaceAlt") }
|
|
10743
|
+
}])
|
|
10744
|
+
}
|
|
10745
|
+
},
|
|
10746
|
+
outline: {
|
|
10747
|
+
kind: "complete",
|
|
10748
|
+
appearance: {
|
|
10749
|
+
background: {
|
|
10750
|
+
type: "surface",
|
|
10751
|
+
role: "link"
|
|
10752
|
+
},
|
|
10753
|
+
borderRadius: "rounded-lg",
|
|
10754
|
+
border: { widthClass: "border" },
|
|
10755
|
+
...hoverAppearance("outline", parameters, [lift, {
|
|
10756
|
+
effectId: "background-on-hover",
|
|
10757
|
+
options: { colorToken: unsafeAsOpaqueButtonColourToken("surfaceAlt") }
|
|
10758
|
+
}])
|
|
10759
|
+
}
|
|
10760
|
+
},
|
|
10761
|
+
ghost: {
|
|
10762
|
+
kind: "complete",
|
|
10763
|
+
appearance: {
|
|
10764
|
+
background: {
|
|
10765
|
+
type: "surface",
|
|
10766
|
+
role: "link"
|
|
10767
|
+
},
|
|
10768
|
+
borderRadius: "rounded-lg",
|
|
10769
|
+
...hoverAppearance("ghost", parameters, [lift])
|
|
10770
|
+
}
|
|
10771
|
+
},
|
|
10772
|
+
accent: {
|
|
10773
|
+
kind: "complete",
|
|
10774
|
+
appearance: {
|
|
10775
|
+
background: {
|
|
10776
|
+
type: "solid",
|
|
10777
|
+
colorToken: unsafeAsOpaqueButtonColourToken("accent")
|
|
10778
|
+
},
|
|
10779
|
+
borderRadius: "rounded-lg",
|
|
10780
|
+
affordance: { iconId: "ArrowRight" },
|
|
10781
|
+
...hoverAppearance("accent", parameters, [lift])
|
|
10782
|
+
}
|
|
10783
|
+
}
|
|
10784
|
+
}
|
|
10785
|
+
})
|
|
10786
|
+
});
|
|
10787
|
+
function hoverAppearance(role, parameters, recommended) {
|
|
10788
|
+
const preference = parameters.hoverPreferences?.[role];
|
|
10789
|
+
if (preference === void 0) return { effects: { hover: [...recommended] } };
|
|
10790
|
+
if (preference === "contextual") {
|
|
10791
|
+
const config = contextualRoleConfig[role];
|
|
10792
|
+
return {
|
|
10793
|
+
effects: { hover: [lift] },
|
|
10794
|
+
contextualHover: {
|
|
10795
|
+
kind: "shade-shift",
|
|
10796
|
+
seedToken: config.contextualSeedToken,
|
|
10797
|
+
fallbackDirection: config.fallbackDirection
|
|
10798
|
+
}
|
|
10799
|
+
};
|
|
10800
|
+
}
|
|
10801
|
+
const config = contextualRoleConfig[role];
|
|
10802
|
+
return {
|
|
10803
|
+
effects: { hover: [lift] },
|
|
10804
|
+
contextualHover: {
|
|
10805
|
+
kind: "shade-shift",
|
|
10806
|
+
seedToken: config.contextualSeedToken,
|
|
10807
|
+
fallbackDirection: config.fallbackDirection,
|
|
10808
|
+
preferredToken: unsafeAsOpaqueButtonColourToken(paletteRole(preference))
|
|
10809
|
+
}
|
|
10810
|
+
};
|
|
10811
|
+
}
|
|
10812
|
+
function paletteRole(preference) {
|
|
10813
|
+
return preference;
|
|
10814
|
+
}
|
|
10815
|
+
//#endregion
|
|
10816
|
+
//#region ../theme-core/src/buttons/styles/recipes/defineStaticButtonStyleRecipe.ts
|
|
10817
|
+
const emptyParametersSchema = z.object({}).strict();
|
|
10818
|
+
function defineStaticButtonStyleRecipe(input) {
|
|
10819
|
+
const system = normalizeSystem(input.system);
|
|
10820
|
+
return defineButtonStyleRecipe({
|
|
10821
|
+
id: input.id,
|
|
10822
|
+
accessibilityLabel: input.accessibilityLabel,
|
|
10823
|
+
tags: input.tags,
|
|
10824
|
+
parameterSchema: emptyParametersSchema,
|
|
10825
|
+
defaultParameters: {},
|
|
10826
|
+
controls: [],
|
|
10827
|
+
defineSystem: () => system
|
|
10828
|
+
});
|
|
10829
|
+
}
|
|
10830
|
+
function normalizeSystem(input) {
|
|
10831
|
+
return {
|
|
10832
|
+
global: buttonGlobalSettingsSchema.parse(input.global),
|
|
10833
|
+
...input.sizes ? { sizes: input.sizes } : {},
|
|
10834
|
+
roles: {
|
|
10835
|
+
primary: normalizeCompleteRole(input.roles.primary),
|
|
10836
|
+
secondary: normalizeCompleteRole(input.roles.secondary),
|
|
10837
|
+
outline: normalizeSupportingRole(input.roles.outline),
|
|
10838
|
+
ghost: normalizeSupportingRole(input.roles.ghost),
|
|
10839
|
+
accent: normalizeSupportingRole(input.roles.accent)
|
|
10840
|
+
}
|
|
10841
|
+
};
|
|
10842
|
+
}
|
|
10843
|
+
function normalizeCompleteRole(role) {
|
|
10844
|
+
return {
|
|
10845
|
+
kind: "complete",
|
|
10846
|
+
appearance: normalizeAppearance(role.appearance)
|
|
10847
|
+
};
|
|
10848
|
+
}
|
|
10849
|
+
function normalizeSupportingRole(role) {
|
|
10850
|
+
if (role.kind === "complete") return normalizeCompleteRole(role);
|
|
10851
|
+
return {
|
|
10852
|
+
kind: "derive",
|
|
10853
|
+
from: role.from,
|
|
10854
|
+
...role.overrides ? { overrides: normalizeAppearanceOverrides(role.overrides) } : {}
|
|
10855
|
+
};
|
|
10856
|
+
}
|
|
10857
|
+
function normalizeAppearance(appearance) {
|
|
10858
|
+
const { background, hoverBackgroundToken, ...rest } = appearance;
|
|
10859
|
+
return {
|
|
10860
|
+
...rest,
|
|
10861
|
+
background: buttonColourTreatmentSchema.parse(background),
|
|
10862
|
+
...hoverBackgroundToken ? { hoverBackgroundToken: opaqueButtonColourTokenSchema.parse(hoverBackgroundToken) } : {}
|
|
10863
|
+
};
|
|
10864
|
+
}
|
|
10865
|
+
function normalizeAppearanceOverrides(overrides) {
|
|
10866
|
+
const { background, hoverBackgroundToken, ...rest } = overrides;
|
|
10867
|
+
return {
|
|
10868
|
+
...rest,
|
|
10869
|
+
...background ? { background: buttonColourTreatmentSchema.parse(background) } : {},
|
|
10870
|
+
...hoverBackgroundToken ? { hoverBackgroundToken: opaqueButtonColourTokenSchema.parse(hoverBackgroundToken) } : {}
|
|
10871
|
+
};
|
|
10872
|
+
}
|
|
10873
|
+
//#endregion
|
|
10874
|
+
//#region ../theme-core/src/buttons/styles/recipes/staticRecipes.ts
|
|
10875
|
+
const softPillRecipe = defineStaticButtonStyleRecipe({
|
|
10876
|
+
id: "soft-pill",
|
|
10877
|
+
accessibilityLabel: "Rounded pill buttons with a gentle hover lift",
|
|
10878
|
+
tags: {
|
|
10879
|
+
tone: "classic",
|
|
10880
|
+
energy: "calm",
|
|
10881
|
+
motion: "subtle",
|
|
10882
|
+
era: "organic"
|
|
10883
|
+
},
|
|
10884
|
+
system: {
|
|
10885
|
+
global: {
|
|
10886
|
+
cornerStyle: "pill",
|
|
10887
|
+
shadow: "low",
|
|
10888
|
+
textTransform: "none",
|
|
10889
|
+
fontWeight: 500,
|
|
10890
|
+
hoverTransform: "lift",
|
|
10891
|
+
hoverColor: "none"
|
|
10892
|
+
},
|
|
10893
|
+
roles: {
|
|
10894
|
+
primary: {
|
|
10895
|
+
kind: "complete",
|
|
10896
|
+
appearance: {
|
|
10897
|
+
background: {
|
|
10898
|
+
type: "solid",
|
|
10899
|
+
colorToken: "primary"
|
|
10900
|
+
},
|
|
10901
|
+
borderRadius: "rounded-full",
|
|
10902
|
+
shadow: {
|
|
10903
|
+
elevation: "low",
|
|
10904
|
+
softness: "soft",
|
|
10905
|
+
position: "bottom"
|
|
10906
|
+
},
|
|
10907
|
+
effects: {
|
|
10908
|
+
hover: [{ effectId: "lift" }],
|
|
10909
|
+
active: [{
|
|
10910
|
+
effectId: "scale-down",
|
|
10911
|
+
options: { scale: "0.98" }
|
|
10912
|
+
}]
|
|
10913
|
+
}
|
|
10914
|
+
}
|
|
10593
10915
|
},
|
|
10594
10916
|
secondary: {
|
|
10595
10917
|
kind: "complete",
|
|
@@ -11337,113 +11659,6 @@ const inkStampRecipe = defineStaticButtonStyleRecipe({
|
|
|
11337
11659
|
}
|
|
11338
11660
|
}
|
|
11339
11661
|
});
|
|
11340
|
-
const flatInkRecipe = defineStaticButtonStyleRecipe({
|
|
11341
|
-
id: "flat-ink",
|
|
11342
|
-
accessibilityLabel: "Flat rounded buttons with arrow affordances",
|
|
11343
|
-
tags: {
|
|
11344
|
-
tone: "classic",
|
|
11345
|
-
energy: "calm",
|
|
11346
|
-
motion: "subtle",
|
|
11347
|
-
era: "editorial"
|
|
11348
|
-
},
|
|
11349
|
-
system: {
|
|
11350
|
-
global: {
|
|
11351
|
-
cornerStyle: "rounded",
|
|
11352
|
-
textTransform: "none",
|
|
11353
|
-
fontWeight: 600,
|
|
11354
|
-
typography: "body",
|
|
11355
|
-
letterSpacing: "tight",
|
|
11356
|
-
paddingPreset: "default",
|
|
11357
|
-
hoverTransform: "lift",
|
|
11358
|
-
hoverColor: "none"
|
|
11359
|
-
},
|
|
11360
|
-
sizes: {
|
|
11361
|
-
sm: {
|
|
11362
|
-
padding: "0.625rem 1.125rem",
|
|
11363
|
-
fontSize: "text-sm"
|
|
11364
|
-
},
|
|
11365
|
-
md: { padding: "0.8125rem 1.375rem" },
|
|
11366
|
-
lg: {
|
|
11367
|
-
padding: "0.9375rem 1.625rem",
|
|
11368
|
-
fontSize: "text-lg"
|
|
11369
|
-
},
|
|
11370
|
-
xl: {
|
|
11371
|
-
padding: "1.0625rem 2rem",
|
|
11372
|
-
fontSize: "text-xl"
|
|
11373
|
-
}
|
|
11374
|
-
},
|
|
11375
|
-
roles: {
|
|
11376
|
-
primary: {
|
|
11377
|
-
kind: "complete",
|
|
11378
|
-
appearance: {
|
|
11379
|
-
background: {
|
|
11380
|
-
type: "solid",
|
|
11381
|
-
colorToken: "primary"
|
|
11382
|
-
},
|
|
11383
|
-
borderRadius: "rounded-lg",
|
|
11384
|
-
affordance: { iconId: "ArrowRight" },
|
|
11385
|
-
effects: { hover: [{ effectId: "lift" }, {
|
|
11386
|
-
effectId: "background-on-hover",
|
|
11387
|
-
options: { colorToken: unsafeAsOpaqueButtonColourToken("secondary") }
|
|
11388
|
-
}] }
|
|
11389
|
-
}
|
|
11390
|
-
},
|
|
11391
|
-
secondary: {
|
|
11392
|
-
kind: "complete",
|
|
11393
|
-
appearance: {
|
|
11394
|
-
background: {
|
|
11395
|
-
type: "surface",
|
|
11396
|
-
role: "link"
|
|
11397
|
-
},
|
|
11398
|
-
borderRadius: "rounded-lg",
|
|
11399
|
-
border: { widthClass: "border" },
|
|
11400
|
-
effects: { hover: [{ effectId: "lift" }, {
|
|
11401
|
-
effectId: "background-on-hover",
|
|
11402
|
-
options: { colorToken: unsafeAsOpaqueButtonColourToken("surfaceAlt") }
|
|
11403
|
-
}] }
|
|
11404
|
-
}
|
|
11405
|
-
},
|
|
11406
|
-
outline: {
|
|
11407
|
-
kind: "complete",
|
|
11408
|
-
appearance: {
|
|
11409
|
-
background: {
|
|
11410
|
-
type: "surface",
|
|
11411
|
-
role: "link"
|
|
11412
|
-
},
|
|
11413
|
-
borderRadius: "rounded-lg",
|
|
11414
|
-
border: { widthClass: "border" },
|
|
11415
|
-
effects: { hover: [{ effectId: "lift" }, {
|
|
11416
|
-
effectId: "background-on-hover",
|
|
11417
|
-
options: { colorToken: unsafeAsOpaqueButtonColourToken("surfaceAlt") }
|
|
11418
|
-
}] }
|
|
11419
|
-
}
|
|
11420
|
-
},
|
|
11421
|
-
ghost: {
|
|
11422
|
-
kind: "complete",
|
|
11423
|
-
appearance: {
|
|
11424
|
-
background: {
|
|
11425
|
-
type: "surface",
|
|
11426
|
-
role: "link"
|
|
11427
|
-
},
|
|
11428
|
-
borderRadius: "rounded-lg",
|
|
11429
|
-
effects: { hover: [{ effectId: "lift" }] }
|
|
11430
|
-
}
|
|
11431
|
-
},
|
|
11432
|
-
accent: {
|
|
11433
|
-
kind: "complete",
|
|
11434
|
-
appearance: {
|
|
11435
|
-
background: {
|
|
11436
|
-
type: "solid",
|
|
11437
|
-
colorToken: "accent"
|
|
11438
|
-
},
|
|
11439
|
-
borderRadius: "rounded-lg",
|
|
11440
|
-
affordance: { iconId: "ArrowRight" },
|
|
11441
|
-
effects: { hover: [{ effectId: "lift" }] }
|
|
11442
|
-
}
|
|
11443
|
-
}
|
|
11444
|
-
}
|
|
11445
|
-
}
|
|
11446
|
-
});
|
|
11447
11662
|
const showtimePillRecipe = defineStaticButtonStyleRecipe({
|
|
11448
11663
|
id: "showtime-pill",
|
|
11449
11664
|
accessibilityLabel: "Bold uppercase pill buttons with playful movement",
|
|
@@ -12198,17 +12413,17 @@ function StepIndicator({ currentStep, totalSteps, stepLabels, classPrefix, emitS
|
|
|
12198
12413
|
//#endregion
|
|
12199
12414
|
//#region ../blocks/src/system/runtime/shared/components/DiscountCodeDisclosure.tsx
|
|
12200
12415
|
const BLOCK_DISCOUNT_CODE_DISCLOSURE_CLASSES = {
|
|
12201
|
-
"
|
|
12202
|
-
root: "
|
|
12203
|
-
toggle: "
|
|
12204
|
-
form: "
|
|
12205
|
-
label: "
|
|
12206
|
-
row: "
|
|
12207
|
-
input: "
|
|
12208
|
-
apply: "
|
|
12209
|
-
remove: "
|
|
12210
|
-
hint: "
|
|
12211
|
-
feedback: "
|
|
12416
|
+
"whole-series-registration": {
|
|
12417
|
+
root: "er-whole-series-discount",
|
|
12418
|
+
toggle: "er-whole-series-discount__toggle",
|
|
12419
|
+
form: "er-whole-series-discount__form",
|
|
12420
|
+
label: "er-whole-series-discount__label",
|
|
12421
|
+
row: "er-whole-series-discount__row",
|
|
12422
|
+
input: "er-whole-series-discount__input",
|
|
12423
|
+
apply: "er-whole-series-discount__apply",
|
|
12424
|
+
remove: "er-whole-series-discount__remove",
|
|
12425
|
+
hint: "er-whole-series-discount__hint",
|
|
12426
|
+
feedback: "er-whole-series-discount__feedback"
|
|
12212
12427
|
},
|
|
12213
12428
|
"event-registration": {
|
|
12214
12429
|
root: "er-discount",
|
|
@@ -12316,27 +12531,789 @@ function DiscountCodeDisclosure({ surface, isOpen, code, onOpen, onChange, onRem
|
|
|
12316
12531
|
});
|
|
12317
12532
|
}
|
|
12318
12533
|
//#endregion
|
|
12319
|
-
//#region ../blocks/src/system/runtime/shared/components/FieldValidationMessage.tsx
|
|
12320
|
-
function getFieldValidationControlProps({ message, messageId, describedBy }) {
|
|
12321
|
-
const hasMessage = Boolean(message);
|
|
12322
|
-
const ariaDescribedBy = [describedBy, hasMessage ? messageId : void 0].filter((part) => typeof part === "string" && part.length > 0).join(" ");
|
|
12323
|
-
return {
|
|
12324
|
-
"aria-invalid": hasMessage ? "true" : void 0,
|
|
12325
|
-
"aria-describedby": ariaDescribedBy || void 0
|
|
12326
|
-
};
|
|
12534
|
+
//#region ../blocks/src/system/runtime/shared/components/FieldValidationMessage.tsx
|
|
12535
|
+
function getFieldValidationControlProps({ message, messageId, describedBy }) {
|
|
12536
|
+
const hasMessage = Boolean(message);
|
|
12537
|
+
const ariaDescribedBy = [describedBy, hasMessage ? messageId : void 0].filter((part) => typeof part === "string" && part.length > 0).join(" ");
|
|
12538
|
+
return {
|
|
12539
|
+
"aria-invalid": hasMessage ? "true" : void 0,
|
|
12540
|
+
"aria-describedby": ariaDescribedBy || void 0
|
|
12541
|
+
};
|
|
12542
|
+
}
|
|
12543
|
+
function FieldValidationMessage({ id, children, className, live = "assertive" }) {
|
|
12544
|
+
return /* @__PURE__ */ jsx("p", {
|
|
12545
|
+
id,
|
|
12546
|
+
className,
|
|
12547
|
+
"data-field-validation-message": true,
|
|
12548
|
+
"data-field-validation-tone": "error",
|
|
12549
|
+
role: "alert",
|
|
12550
|
+
"aria-live": live === "off" ? void 0 : live,
|
|
12551
|
+
children
|
|
12552
|
+
});
|
|
12553
|
+
}
|
|
12554
|
+
//#endregion
|
|
12555
|
+
//#region ../blocks/src/primitives/content/utils/sanitizeHref.ts
|
|
12556
|
+
const SAFE_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
12557
|
+
"http:",
|
|
12558
|
+
"https:",
|
|
12559
|
+
"mailto:",
|
|
12560
|
+
"tel:"
|
|
12561
|
+
]);
|
|
12562
|
+
const CONTROL_CHARS_PATTERN = /[\u0000-\u001F\u007F]+/g;
|
|
12563
|
+
function normalizeInput(value) {
|
|
12564
|
+
return value.replace(CONTROL_CHARS_PATTERN, "").trim();
|
|
12565
|
+
}
|
|
12566
|
+
function decodeForSchemeCheck(value) {
|
|
12567
|
+
try {
|
|
12568
|
+
return decodeURIComponent(value);
|
|
12569
|
+
} catch {
|
|
12570
|
+
return value;
|
|
12571
|
+
}
|
|
12572
|
+
}
|
|
12573
|
+
/**
|
|
12574
|
+
* Returns a safe href for rich-text anchors, or null when the value should not be rendered.
|
|
12575
|
+
*
|
|
12576
|
+
* Policy:
|
|
12577
|
+
* - Allow absolute URLs with protocols: http, https, mailto, tel.
|
|
12578
|
+
* - Allow root-relative ("/path") and hash-only ("#section") links.
|
|
12579
|
+
* - Reject protocol-relative URLs ("//example.com"), bare domains ("example.com"),
|
|
12580
|
+
* executable schemes (javascript/data/vbscript), malformed URLs, and empty values.
|
|
12581
|
+
* - Preserve percent-encoding from the original normalized input.
|
|
12582
|
+
*/
|
|
12583
|
+
function sanitizeHref(raw) {
|
|
12584
|
+
if (typeof raw !== "string") return null;
|
|
12585
|
+
const normalized = normalizeInput(raw);
|
|
12586
|
+
if (!normalized) return null;
|
|
12587
|
+
if (normalized.startsWith("//")) return null;
|
|
12588
|
+
if (normalized.startsWith("/")) return normalized;
|
|
12589
|
+
if (normalized.startsWith("#")) return normalized;
|
|
12590
|
+
const schemeMatch = normalizeInput(decodeForSchemeCheck(normalized)).match(/^([a-zA-Z][a-zA-Z0-9+.-]*):/);
|
|
12591
|
+
if (!schemeMatch) return null;
|
|
12592
|
+
const rawScheme = schemeMatch[1];
|
|
12593
|
+
if (!rawScheme) return null;
|
|
12594
|
+
const protocol = `${rawScheme.toLowerCase()}:`;
|
|
12595
|
+
if (!SAFE_PROTOCOLS.has(protocol)) return null;
|
|
12596
|
+
try {
|
|
12597
|
+
const parsed = new URL(normalized);
|
|
12598
|
+
if (!SAFE_PROTOCOLS.has(parsed.protocol.toLowerCase())) return null;
|
|
12599
|
+
} catch {
|
|
12600
|
+
return null;
|
|
12601
|
+
}
|
|
12602
|
+
return normalized;
|
|
12603
|
+
}
|
|
12604
|
+
//#endregion
|
|
12605
|
+
//#region ../media-core/src/fileSafety.ts
|
|
12606
|
+
const CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/u;
|
|
12607
|
+
function containsUnsafePathSegmentCharacter(value) {
|
|
12608
|
+
return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN.test(value);
|
|
12609
|
+
}
|
|
12610
|
+
function isReservedPathSegment(value) {
|
|
12611
|
+
return value === "." || value === "..";
|
|
12612
|
+
}
|
|
12613
|
+
function isUnsafePathSegment(segment) {
|
|
12614
|
+
return segment.trim().length === 0 || segment !== segment.trim() || isReservedPathSegment(segment) || containsUnsafePathSegmentCharacter(segment);
|
|
12615
|
+
}
|
|
12616
|
+
({
|
|
12617
|
+
publicSite: unsafeAsStorageBucketName("media"),
|
|
12618
|
+
privateSite: unsafeAsStorageBucketName("site-files-private"),
|
|
12619
|
+
temporary: unsafeAsStorageBucketName("temp-uploads")
|
|
12620
|
+
}).publicSite;
|
|
12621
|
+
function parseStoragePath(value) {
|
|
12622
|
+
return joinStoragePathSegments(value.split("/"));
|
|
12623
|
+
}
|
|
12624
|
+
/**
|
|
12625
|
+
* Joins already-branded path segments while preserving the Storage RLS invariant
|
|
12626
|
+
* that every tenant/site identifier remains one segment, never a nested path.
|
|
12627
|
+
*/
|
|
12628
|
+
function joinStoragePathSegments(segments) {
|
|
12629
|
+
if (segments.some(isUnsafePathSegment)) return err$1("unsafe-path-segment");
|
|
12630
|
+
return ok$1(unsafeAsStoragePath(segments.join("/")));
|
|
12631
|
+
}
|
|
12632
|
+
//#endregion
|
|
12633
|
+
//#region ../media-core/src/storagePathDomain.ts
|
|
12634
|
+
function ok(value) {
|
|
12635
|
+
return {
|
|
12636
|
+
ok: true,
|
|
12637
|
+
value
|
|
12638
|
+
};
|
|
12639
|
+
}
|
|
12640
|
+
function fail(error) {
|
|
12641
|
+
return {
|
|
12642
|
+
ok: false,
|
|
12643
|
+
error
|
|
12644
|
+
};
|
|
12645
|
+
}
|
|
12646
|
+
function normalizeStringInput(value) {
|
|
12647
|
+
if (typeof value !== "string") return fail({ tag: "MISSING" });
|
|
12648
|
+
const trimmed = value.trim();
|
|
12649
|
+
if (!trimmed) return fail({ tag: "EMPTY" });
|
|
12650
|
+
return ok(trimmed);
|
|
12651
|
+
}
|
|
12652
|
+
function validateRelativeStoragePath(value) {
|
|
12653
|
+
if (value.startsWith("sites/")) return fail({ tag: "SITE_SCOPED_PATH" });
|
|
12654
|
+
if (value.startsWith("/")) return fail({ tag: "LEADING_SLASH" });
|
|
12655
|
+
if (value.includes("//")) return fail({ tag: "DOUBLE_SLASH" });
|
|
12656
|
+
if (value.includes("%")) return fail({ tag: "PERCENT_ENCODING" });
|
|
12657
|
+
if (value.split("/").some((segment) => segment === "." || segment === "..")) return fail({ tag: "TRAVERSAL" });
|
|
12658
|
+
return ok(value);
|
|
12659
|
+
}
|
|
12660
|
+
function brandRelativeStoragePath(value) {
|
|
12661
|
+
return value;
|
|
12662
|
+
}
|
|
12663
|
+
function parseRelativeStoragePath(value) {
|
|
12664
|
+
const normalized = normalizeStringInput(value);
|
|
12665
|
+
if (!normalized.ok) return normalized;
|
|
12666
|
+
const validated = validateRelativeStoragePath(normalized.value);
|
|
12667
|
+
if (!validated.ok) return validated;
|
|
12668
|
+
return ok(brandRelativeStoragePath(validated.value));
|
|
12669
|
+
}
|
|
12670
|
+
//#endregion
|
|
12671
|
+
//#region ../media-core/src/url.ts
|
|
12672
|
+
const DEFAULT_BASE_PATH = "/api/img";
|
|
12673
|
+
function isSiteScopedDirectImageStoragePath(storagePath) {
|
|
12674
|
+
return storagePath.startsWith("sites/") && parseStoragePath(storagePath).ok;
|
|
12675
|
+
}
|
|
12676
|
+
function encodeStoragePath(storagePath) {
|
|
12677
|
+
return storagePath.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
12678
|
+
}
|
|
12679
|
+
function resolveDirectImagePathTarget(target) {
|
|
12680
|
+
switch (target.kind) {
|
|
12681
|
+
case "relative": return `sites/${target.siteId}/${target.storagePath}`;
|
|
12682
|
+
case "site-scoped":
|
|
12683
|
+
case "bucket-scoped": return target.storagePath;
|
|
12684
|
+
}
|
|
12685
|
+
}
|
|
12686
|
+
function getDirectImageUrl(supabaseUrl, target, storageBucket = "media", options) {
|
|
12687
|
+
const baseUrl = supabaseUrl.replace(/\/$/, "");
|
|
12688
|
+
const encodedPath = encodeStoragePath(resolveDirectImagePathTarget(target));
|
|
12689
|
+
const isSvg = target.storagePath.toLowerCase().endsWith(".svg");
|
|
12690
|
+
if (options && !isSvg && (options.width || options.height)) {
|
|
12691
|
+
const params = new URLSearchParams();
|
|
12692
|
+
if (options.width) params.set("width", String(options.width));
|
|
12693
|
+
if (options.height) params.set("height", String(options.height));
|
|
12694
|
+
if (options.quality) params.set("quality", String(options.quality));
|
|
12695
|
+
if (options.resize) params.set("resize", options.resize);
|
|
12696
|
+
return `${baseUrl}/storage/v1/render/image/public/${storageBucket}/${encodedPath}?${params.toString()}`;
|
|
12697
|
+
}
|
|
12698
|
+
return `${baseUrl}/storage/v1/object/public/${storageBucket}/${encodedPath}`;
|
|
12699
|
+
}
|
|
12700
|
+
function getDirectImageUrlForRelativePath(supabaseUrl, storagePath, siteId, storageBucket = "media", options) {
|
|
12701
|
+
return getDirectImageUrl(supabaseUrl, {
|
|
12702
|
+
kind: "relative",
|
|
12703
|
+
storagePath,
|
|
12704
|
+
siteId
|
|
12705
|
+
}, storageBucket, options);
|
|
12706
|
+
}
|
|
12707
|
+
function getDirectImageUrlForSiteScopedPath(supabaseUrl, storagePath, storageBucket = "media", options) {
|
|
12708
|
+
return getDirectImageUrl(supabaseUrl, {
|
|
12709
|
+
kind: "site-scoped",
|
|
12710
|
+
storagePath
|
|
12711
|
+
}, storageBucket, options);
|
|
12712
|
+
}
|
|
12713
|
+
const formatNumber = (value) => Number.isInteger(value) ? value.toString() : value.toFixed(6).replace(/0+$/, "").replace(/\.$/, "");
|
|
12714
|
+
const ORDER = [
|
|
12715
|
+
"w",
|
|
12716
|
+
"h",
|
|
12717
|
+
"fit",
|
|
12718
|
+
"rect",
|
|
12719
|
+
"q",
|
|
12720
|
+
"autoFormat",
|
|
12721
|
+
"or"
|
|
12722
|
+
];
|
|
12723
|
+
const getImageUrl = (asset, params = {}, basePath = DEFAULT_BASE_PATH) => {
|
|
12724
|
+
const path = `${basePath.endsWith("/") ? basePath.slice(0, Math.max(basePath.length - 1, 0)) : basePath}/${encodeURIComponent(asset.id)}`;
|
|
12725
|
+
const searchParams = new URLSearchParams();
|
|
12726
|
+
if (params.w !== void 0) searchParams.set("w", formatNumber(params.w));
|
|
12727
|
+
if (params.h !== void 0) searchParams.set("h", formatNumber(params.h));
|
|
12728
|
+
if (params.fit !== void 0) searchParams.set("fit", params.fit);
|
|
12729
|
+
if (params.rect) searchParams.set("rect", params.rect.map(formatNumber).join(","));
|
|
12730
|
+
if (params.q !== void 0) searchParams.set("q", formatNumber(params.q));
|
|
12731
|
+
if (params.autoFormat) searchParams.append("auto", "format");
|
|
12732
|
+
if (params.or !== void 0) searchParams.set("or", String(params.or));
|
|
12733
|
+
const sorted = new URLSearchParams();
|
|
12734
|
+
ORDER.forEach((key) => {
|
|
12735
|
+
if (key === "autoFormat") {
|
|
12736
|
+
if (params.autoFormat) sorted.append("auto", "format");
|
|
12737
|
+
return;
|
|
12738
|
+
}
|
|
12739
|
+
const value = searchParams.get(key);
|
|
12740
|
+
if (value !== null) sorted.set(key, value);
|
|
12741
|
+
});
|
|
12742
|
+
const query = sorted.toString();
|
|
12743
|
+
return query ? `${path}?${query}` : path;
|
|
12744
|
+
};
|
|
12745
|
+
//#endregion
|
|
12746
|
+
//#region ../media-core/src/transformRect.ts
|
|
12747
|
+
function isValidTransformRectStructure(rect) {
|
|
12748
|
+
if (!Array.isArray(rect) || rect.length !== 4) return false;
|
|
12749
|
+
const [left, top, width, height] = rect;
|
|
12750
|
+
return Number.isFinite(left) && Number.isFinite(top) && Number.isFinite(width) && Number.isFinite(height) && left >= 0 && top >= 0 && width > 0 && height > 0;
|
|
12751
|
+
}
|
|
12752
|
+
//#endregion
|
|
12753
|
+
//#region ../media-core/src/aspectTransforms.ts
|
|
12754
|
+
const DEFAULT_RECT_EPSILON = .5;
|
|
12755
|
+
function parseAspectRatioValue(value) {
|
|
12756
|
+
if (typeof value === "number") return Number.isFinite(value) && value > 0 ? value : void 0;
|
|
12757
|
+
if (typeof value !== "string") return void 0;
|
|
12758
|
+
const normalized = value.trim();
|
|
12759
|
+
if (!normalized) return void 0;
|
|
12760
|
+
if (normalized === "auto") return void 0;
|
|
12761
|
+
if (normalized.includes(":") || normalized.includes("/")) {
|
|
12762
|
+
const delimiter = normalized.includes(":") ? ":" : "/";
|
|
12763
|
+
const [wRaw, hRaw] = normalized.split(delimiter);
|
|
12764
|
+
const width = Number(wRaw?.trim());
|
|
12765
|
+
const height = Number(hRaw?.trim());
|
|
12766
|
+
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return;
|
|
12767
|
+
return width / height;
|
|
12768
|
+
}
|
|
12769
|
+
const numeric = Number(normalized);
|
|
12770
|
+
if (!Number.isFinite(numeric) || numeric <= 0) return void 0;
|
|
12771
|
+
return numeric;
|
|
12772
|
+
}
|
|
12773
|
+
const MAX_ASPECT_DISTANCE = .25;
|
|
12774
|
+
function resolveMediaTransformForAspect(transform, targetAspect) {
|
|
12775
|
+
if (!transform) return {};
|
|
12776
|
+
const base = {
|
|
12777
|
+
rect: transform.rect,
|
|
12778
|
+
hotspot: transform.hotspot,
|
|
12779
|
+
rotation: transform.rotation
|
|
12780
|
+
};
|
|
12781
|
+
const target = parseAspectRatioValue(targetAspect);
|
|
12782
|
+
const crops = transform.aspectCrops;
|
|
12783
|
+
if (!target || !crops || Object.keys(crops).length === 0) return base;
|
|
12784
|
+
let best = null;
|
|
12785
|
+
let bestDistance = Number.POSITIVE_INFINITY;
|
|
12786
|
+
for (const [key, candidate] of Object.entries(crops)) {
|
|
12787
|
+
const candidateAspect = parseAspectRatioValue(candidate.aspect ?? key);
|
|
12788
|
+
if (!candidateAspect) continue;
|
|
12789
|
+
const distance = Math.abs(Math.log(candidateAspect / target));
|
|
12790
|
+
if (distance < bestDistance) {
|
|
12791
|
+
best = candidate;
|
|
12792
|
+
bestDistance = distance;
|
|
12793
|
+
}
|
|
12794
|
+
}
|
|
12795
|
+
if (!best) return base;
|
|
12796
|
+
if (bestDistance > MAX_ASPECT_DISTANCE) return base;
|
|
12797
|
+
return {
|
|
12798
|
+
rect: best.rect ?? base.rect,
|
|
12799
|
+
hotspot: best.hotspot ?? base.hotspot,
|
|
12800
|
+
rotation: best.rotation ?? base.rotation
|
|
12801
|
+
};
|
|
12802
|
+
}
|
|
12803
|
+
function isValidTransformRect(rect) {
|
|
12804
|
+
return isValidTransformRectStructure(rect);
|
|
12805
|
+
}
|
|
12806
|
+
function isExplicitRectCrop(rect, sourceWidth, sourceHeight, epsilon = DEFAULT_RECT_EPSILON) {
|
|
12807
|
+
if (!isValidTransformRect(rect)) return false;
|
|
12808
|
+
if (!(typeof sourceWidth === "number" && Number.isFinite(sourceWidth) && sourceWidth > 0 && typeof sourceHeight === "number" && Number.isFinite(sourceHeight) && sourceHeight > 0)) return true;
|
|
12809
|
+
const [x, y, width, height] = rect;
|
|
12810
|
+
return !(Math.abs(x) <= epsilon && Math.abs(y) <= epsilon && Math.abs(width - sourceWidth) <= epsilon && Math.abs(height - sourceHeight) <= epsilon);
|
|
12811
|
+
}
|
|
12812
|
+
//#endregion
|
|
12813
|
+
//#region ../media-core/src/renderableMediaAsset.ts
|
|
12814
|
+
function attachRenderableMediaAssetFields(media, asset) {
|
|
12815
|
+
return {
|
|
12816
|
+
...media,
|
|
12817
|
+
assetId: asset.id,
|
|
12818
|
+
id: asset.id,
|
|
12819
|
+
identifier: mediaIdentifierOrFallback(media.identifier, asset.identifier),
|
|
12820
|
+
storageBucket: asset.storageBucket ?? media.storageBucket,
|
|
12821
|
+
storagePath: asset.storagePath ?? media.storagePath,
|
|
12822
|
+
width: asset.width ?? media.width,
|
|
12823
|
+
height: asset.height ?? media.height,
|
|
12824
|
+
mimeType: asset.mimeType ?? media.mimeType
|
|
12825
|
+
};
|
|
12826
|
+
}
|
|
12827
|
+
/**
|
|
12828
|
+
* Preserve an explicit per-usage identifier when one exists. Otherwise prefer
|
|
12829
|
+
* the canonical asset identifier, while keeping intentionally blank legacy
|
|
12830
|
+
* string values from becoming null.
|
|
12831
|
+
*/
|
|
12832
|
+
function mediaIdentifierOrFallback(current, fallback) {
|
|
12833
|
+
if (typeof current === "string" && current.trim().length > 0) return current;
|
|
12834
|
+
return fallback ?? (typeof current === "string" ? current : void 0);
|
|
12835
|
+
}
|
|
12836
|
+
//#endregion
|
|
12837
|
+
//#region ../blocks/src/system/runtime/nodes/media.tsx
|
|
12838
|
+
const MAX_RENDER_DIMENSION = 4096;
|
|
12839
|
+
const RELATIVE_IMG_PROXY_BASE_PATH = "/api/img";
|
|
12840
|
+
function getValidSourceDimension(value) {
|
|
12841
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
12842
|
+
}
|
|
12843
|
+
function isExplicitCropProxyEnabled() {
|
|
12844
|
+
const raw = process.env.NEXT_PUBLIC_MEDIA_EXPLICIT_CROP_PROXY_ENABLED ?? process.env.MEDIA_EXPLICIT_CROP_PROXY_ENABLED;
|
|
12845
|
+
if (!raw) return true;
|
|
12846
|
+
const normalized = raw.trim().toLowerCase();
|
|
12847
|
+
return !(normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off");
|
|
12848
|
+
}
|
|
12849
|
+
function getRequestedDimension(value) {
|
|
12850
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
|
|
12851
|
+
return Math.min(MAX_RENDER_DIMENSION, Math.max(1, Math.round(value)));
|
|
12852
|
+
}
|
|
12853
|
+
function mapResizeToFit(resize) {
|
|
12854
|
+
if (resize === "contain") return "clip";
|
|
12855
|
+
return "crop";
|
|
12856
|
+
}
|
|
12857
|
+
function shouldUseExplicitRectProxy(value, options, resolvedTransform, sourceWidth, sourceHeight) {
|
|
12858
|
+
if ("original" in options && options.original) return false;
|
|
12859
|
+
if (!isExplicitCropProxyEnabled()) return false;
|
|
12860
|
+
if (!value.assetId) return false;
|
|
12861
|
+
if (typeof resolvedTransform.rotation === "number" && resolvedTransform.rotation !== 0) return true;
|
|
12862
|
+
return isExplicitRectCrop(resolvedTransform.rect, sourceWidth, sourceHeight);
|
|
12863
|
+
}
|
|
12864
|
+
function buildProxyTransformParams(options, resolvedTransform) {
|
|
12865
|
+
const params = {
|
|
12866
|
+
w: "width" in options ? getRequestedDimension(options.width) : void 0,
|
|
12867
|
+
h: "height" in options ? getRequestedDimension(options.height) : void 0,
|
|
12868
|
+
q: "quality" in options ? options.quality : void 0,
|
|
12869
|
+
fit: mapResizeToFit("resize" in options ? options.resize : void 0),
|
|
12870
|
+
autoFormat: true
|
|
12871
|
+
};
|
|
12872
|
+
if (resolvedTransform.rect) params.rect = resolvedTransform.rect;
|
|
12873
|
+
if (resolvedTransform.rotation) params.or = resolvedTransform.rotation;
|
|
12874
|
+
return params;
|
|
12875
|
+
}
|
|
12876
|
+
function buildDirectTransformOptions(options) {
|
|
12877
|
+
if ("original" in options && options.original) return void 0;
|
|
12878
|
+
return {
|
|
12879
|
+
width: "width" in options ? getRequestedDimension(options.width) : void 0,
|
|
12880
|
+
height: "height" in options ? getRequestedDimension(options.height) : void 0,
|
|
12881
|
+
quality: "quality" in options ? options.quality : void 0,
|
|
12882
|
+
resize: "resize" in options ? options.resize : void 0
|
|
12883
|
+
};
|
|
12884
|
+
}
|
|
12885
|
+
function resolveTransformResolution(value, targetAspectRatio) {
|
|
12886
|
+
return {
|
|
12887
|
+
resolvedTransform: resolveMediaTransformForAspect(value.transform, targetAspectRatio),
|
|
12888
|
+
sourceWidth: getValidSourceDimension(value.width),
|
|
12889
|
+
sourceHeight: getValidSourceDimension(value.height)
|
|
12890
|
+
};
|
|
12891
|
+
}
|
|
12892
|
+
function getProxyImageUrl(value, options, transformAspectRatio, resolved) {
|
|
12893
|
+
if (!value.assetId) return void 0;
|
|
12894
|
+
const targetAspect = transformAspectRatio ?? resolveTargetAspectRatio(options);
|
|
12895
|
+
const { resolvedTransform, sourceWidth, sourceHeight } = resolved ?? resolveTransformResolution(value, targetAspect);
|
|
12896
|
+
if (!shouldUseExplicitRectProxy(value, options, resolvedTransform, sourceWidth, sourceHeight)) return void 0;
|
|
12897
|
+
const params = buildProxyTransformParams(options, resolvedTransform);
|
|
12898
|
+
const proxyBasePath = getImageProxyBasePath();
|
|
12899
|
+
const proxyUrl = getImageUrl({ id: unsafeAsMediaAssetId(value.assetId) }, params, proxyBasePath);
|
|
12900
|
+
debugMediaNodeLog("resolve:proxy-img", {
|
|
12901
|
+
assetId: value.assetId,
|
|
12902
|
+
params,
|
|
12903
|
+
proxyBasePath,
|
|
12904
|
+
proxyUrl
|
|
12905
|
+
});
|
|
12906
|
+
return proxyUrl;
|
|
12907
|
+
}
|
|
12908
|
+
function warnForMediaUrlResolution(result) {
|
|
12909
|
+
switch (result.kind) {
|
|
12910
|
+
case "missing-site-context":
|
|
12911
|
+
console.warn(`[blocks] Relative storagePath "${result.storagePath}" requires siteId context. Media URL may be incorrect. Ensure siteId is set via runWithMediaContext or setContextSiteId.`);
|
|
12912
|
+
return;
|
|
12913
|
+
case "missing-supabase-url":
|
|
12914
|
+
console.warn(`[blocks] ${result.message} Media URL may be unavailable. Ensure NEXT_PUBLIC_SUPABASE_URL is configured or pass supabaseUrl in the media context.`);
|
|
12915
|
+
return;
|
|
12916
|
+
case "invalid-storage-path":
|
|
12917
|
+
console.warn(`[blocks] Invalid media storagePath "${result.storagePath}".`);
|
|
12918
|
+
return;
|
|
12919
|
+
case "resolved":
|
|
12920
|
+
case "unsupported-media-type":
|
|
12921
|
+
case "missing-storage-path":
|
|
12922
|
+
case "missing-image-url": return;
|
|
12923
|
+
}
|
|
12924
|
+
}
|
|
12925
|
+
function resolveMediaStorageUrlResult(value, context, transformOptions) {
|
|
12926
|
+
const canonical = resolveMediaWithCanonicalAsset(value, context ?? void 0);
|
|
12927
|
+
if (!canonical.storagePath || canonical.storagePath.length === 0) return {
|
|
12928
|
+
kind: "missing-storage-path",
|
|
12929
|
+
assetId: canonical.assetId,
|
|
12930
|
+
identifier: canonical.identifier
|
|
12931
|
+
};
|
|
12932
|
+
const siteId = context?.siteId ?? getSiteId();
|
|
12933
|
+
const bucket = canonical.storageBucket ?? "media";
|
|
12934
|
+
const siteScopedPath = isSiteScopedDirectImageStoragePath(canonical.storagePath) ? canonical.storagePath : null;
|
|
12935
|
+
let supabaseUrl;
|
|
12936
|
+
try {
|
|
12937
|
+
supabaseUrl = context?.supabaseUrl?.replace(/\/$/, "") ?? getSupabaseUrl();
|
|
12938
|
+
} catch (error) {
|
|
12939
|
+
return {
|
|
12940
|
+
kind: "missing-supabase-url",
|
|
12941
|
+
message: error instanceof Error ? error.message : "Supabase URL is not configured."
|
|
12942
|
+
};
|
|
12943
|
+
}
|
|
12944
|
+
let directUrl;
|
|
12945
|
+
if (siteScopedPath) directUrl = getDirectImageUrlForSiteScopedPath(supabaseUrl, siteScopedPath, bucket, transformOptions);
|
|
12946
|
+
else {
|
|
12947
|
+
const relativePath = parseRelativeStoragePath(canonical.storagePath);
|
|
12948
|
+
if (!relativePath.ok) return {
|
|
12949
|
+
kind: "invalid-storage-path",
|
|
12950
|
+
storagePath: canonical.storagePath
|
|
12951
|
+
};
|
|
12952
|
+
if (!siteId) return {
|
|
12953
|
+
kind: "missing-site-context",
|
|
12954
|
+
storagePath: canonical.storagePath
|
|
12955
|
+
};
|
|
12956
|
+
directUrl = getDirectImageUrlForRelativePath(supabaseUrl, relativePath.value, siteId, bucket, transformOptions);
|
|
12957
|
+
}
|
|
12958
|
+
debugMediaNodeLog("resolve:direct-supabase", {
|
|
12959
|
+
storagePath: canonical.storagePath,
|
|
12960
|
+
siteId,
|
|
12961
|
+
bucket,
|
|
12962
|
+
directUrl,
|
|
12963
|
+
transformOptions
|
|
12964
|
+
});
|
|
12965
|
+
return {
|
|
12966
|
+
kind: "resolved",
|
|
12967
|
+
url: directUrl
|
|
12968
|
+
};
|
|
12969
|
+
}
|
|
12970
|
+
function getDirectImageUrlForValue(value, options, context) {
|
|
12971
|
+
const result = resolveMediaStorageUrlResult(value, context, buildDirectTransformOptions(options));
|
|
12972
|
+
return result.kind === "resolved" ? result.url : void 0;
|
|
12973
|
+
}
|
|
12974
|
+
function resolveStorageImageUrl(value, options, context, transformAspectRatio, resolved) {
|
|
12975
|
+
const proxyUrl = getProxyImageUrl(value, options, transformAspectRatio, resolved);
|
|
12976
|
+
if (proxyUrl) return proxyUrl;
|
|
12977
|
+
const directUrl = getDirectImageUrlForValue(value, options, context);
|
|
12978
|
+
if (directUrl) return directUrl;
|
|
12979
|
+
}
|
|
12980
|
+
/**
|
|
12981
|
+
* Common image size presets.
|
|
12982
|
+
* Use these for consistent sizing across the application.
|
|
12983
|
+
*/
|
|
12984
|
+
const ImagePresets = {
|
|
12985
|
+
/** Small thumbnails (200px) - for block previews, lists */
|
|
12986
|
+
thumbnail: {
|
|
12987
|
+
width: 200,
|
|
12988
|
+
quality: 80,
|
|
12989
|
+
resize: "contain"
|
|
12990
|
+
},
|
|
12991
|
+
/** Card-sized images (600px) - for cards, grids */
|
|
12992
|
+
card: {
|
|
12993
|
+
width: 600,
|
|
12994
|
+
quality: 80,
|
|
12995
|
+
resize: "contain"
|
|
12996
|
+
},
|
|
12997
|
+
/** Hero images (1200px) - for above-fold content */
|
|
12998
|
+
hero: {
|
|
12999
|
+
width: 1200,
|
|
13000
|
+
quality: 85,
|
|
13001
|
+
resize: "contain"
|
|
13002
|
+
},
|
|
13003
|
+
/** Full-width images (1920px) - for backgrounds, large displays */
|
|
13004
|
+
full: {
|
|
13005
|
+
width: 1920,
|
|
13006
|
+
quality: 85,
|
|
13007
|
+
resize: "contain"
|
|
13008
|
+
}
|
|
13009
|
+
};
|
|
13010
|
+
/**
|
|
13011
|
+
* Server-side: AsyncLocalStorage for request isolation.
|
|
13012
|
+
* Prevents race conditions when multiple requests are processed concurrently.
|
|
13013
|
+
*
|
|
13014
|
+
* Lazy initialization to avoid issues in environments that don't support async_hooks.
|
|
13015
|
+
*/
|
|
13016
|
+
let _serverStorage = null;
|
|
13017
|
+
let _serverStorageChecked = false;
|
|
13018
|
+
function getServerStorage() {
|
|
13019
|
+
if (typeof window !== "undefined") return null;
|
|
13020
|
+
if (_serverStorageChecked) return _serverStorage;
|
|
13021
|
+
_serverStorageChecked = true;
|
|
13022
|
+
try {
|
|
13023
|
+
const globalWithNonWebpackRequire = globalThis;
|
|
13024
|
+
const AsyncLocalStorage = (typeof globalWithNonWebpackRequire.__non_webpack_require__ === "function" ? globalWithNonWebpackRequire.__non_webpack_require__ : new Function("id", "return require(id)"))("async_hooks").AsyncLocalStorage;
|
|
13025
|
+
if (AsyncLocalStorage) {
|
|
13026
|
+
_serverStorage = new AsyncLocalStorage();
|
|
13027
|
+
return _serverStorage;
|
|
13028
|
+
}
|
|
13029
|
+
return null;
|
|
13030
|
+
} catch {
|
|
13031
|
+
console.warn("[blocks] AsyncLocalStorage not available - using module-level state");
|
|
13032
|
+
return null;
|
|
13033
|
+
}
|
|
13034
|
+
}
|
|
13035
|
+
/**
|
|
13036
|
+
* Client-side context storage.
|
|
13037
|
+
* Safe because browsers are single-threaded per tab.
|
|
13038
|
+
*
|
|
13039
|
+
* IMPORTANT: This must be shared across bundles.
|
|
13040
|
+
* SDK preview mode can load multiple independently-bundled entrypoints
|
|
13041
|
+
* (e.g. `@riverbankcms/sdk/rendering` + `@riverbankcms/sdk/preview-next/client`),
|
|
13042
|
+
* which can otherwise each get their own module-scoped singleton.
|
|
13043
|
+
*/
|
|
13044
|
+
const RB_MEDIA_CONTEXT_KEY = Symbol.for("riverbankcms.blocks.mediaContext");
|
|
13045
|
+
function getClientContextStore() {
|
|
13046
|
+
const g = globalThis;
|
|
13047
|
+
const existing = g[RB_MEDIA_CONTEXT_KEY];
|
|
13048
|
+
if (existing && typeof existing === "object") return existing;
|
|
13049
|
+
const next = {};
|
|
13050
|
+
g[RB_MEDIA_CONTEXT_KEY] = next;
|
|
13051
|
+
return next;
|
|
13052
|
+
}
|
|
13053
|
+
/**
|
|
13054
|
+
* Get the current media context.
|
|
13055
|
+
* Server-side: Uses AsyncLocalStorage for request isolation.
|
|
13056
|
+
* Client-side: Uses module-level state (safe in single-threaded browser).
|
|
13057
|
+
*/
|
|
13058
|
+
function getMediaContext() {
|
|
13059
|
+
const storage = getServerStorage();
|
|
13060
|
+
if (storage) return storage.getStore() ?? {};
|
|
13061
|
+
return getClientContextStore();
|
|
13062
|
+
}
|
|
13063
|
+
function getCurrentResolveImageUrlContext() {
|
|
13064
|
+
const context = getMediaContext();
|
|
13065
|
+
if (!context.supabaseUrl && !context.siteId && !context.mediaAssetIndex) return;
|
|
13066
|
+
return {
|
|
13067
|
+
supabaseUrl: context.supabaseUrl,
|
|
13068
|
+
siteId: context.siteId,
|
|
13069
|
+
mediaAssetIndex: context.mediaAssetIndex
|
|
13070
|
+
};
|
|
13071
|
+
}
|
|
13072
|
+
/**
|
|
13073
|
+
* Get the Supabase URL for constructing direct storage URLs.
|
|
13074
|
+
* Used for serving images directly from Supabase storage CDN.
|
|
13075
|
+
*
|
|
13076
|
+
* Resolution order:
|
|
13077
|
+
* 1. Context URL (set via runWithMediaContext or setContextSupabaseUrl)
|
|
13078
|
+
* 2. Environment variable NEXT_PUBLIC_SUPABASE_URL
|
|
13079
|
+
*
|
|
13080
|
+
* SDK sites receive the URL from the API, so they don't need the env var.
|
|
13081
|
+
* Dashboard and frontend apps use the env var.
|
|
13082
|
+
*/
|
|
13083
|
+
function getSupabaseUrl() {
|
|
13084
|
+
const context = getMediaContext();
|
|
13085
|
+
if (context.supabaseUrl) return context.supabaseUrl;
|
|
13086
|
+
const url = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
|
13087
|
+
if (!url) throw new Error("NEXT_PUBLIC_SUPABASE_URL is not configured. Set it to your Supabase project URL (e.g., https://xxx.supabase.co)");
|
|
13088
|
+
return url.replace(/\/$/, "");
|
|
13089
|
+
}
|
|
13090
|
+
function resolveDashboardOrigin(raw) {
|
|
13091
|
+
if (!raw) return void 0;
|
|
13092
|
+
const trimmed = raw.trim();
|
|
13093
|
+
if (!trimmed) return void 0;
|
|
13094
|
+
const withoutApiSuffix = trimmed.replace(/\/+$/, "").replace(/\/api\/?$/, "");
|
|
13095
|
+
const normalized = /^https?:\/\//i.test(withoutApiSuffix) ? withoutApiSuffix : `http://${withoutApiSuffix.replace(/^\/+/, "")}`;
|
|
13096
|
+
try {
|
|
13097
|
+
return new URL(normalized).origin;
|
|
13098
|
+
} catch {
|
|
13099
|
+
return;
|
|
13100
|
+
}
|
|
13101
|
+
}
|
|
13102
|
+
function getImageProxyBasePath() {
|
|
13103
|
+
const dashboardOrigin = resolveDashboardOrigin(process.env.NEXT_PUBLIC_DASHBOARD_URL);
|
|
13104
|
+
if (!dashboardOrigin) return RELATIVE_IMG_PROXY_BASE_PATH;
|
|
13105
|
+
return `${dashboardOrigin}${RELATIVE_IMG_PROXY_BASE_PATH}`;
|
|
13106
|
+
}
|
|
13107
|
+
/**
|
|
13108
|
+
* Get the site ID for constructing storage paths.
|
|
13109
|
+
* Required for relative path resolution.
|
|
13110
|
+
*/
|
|
13111
|
+
function getSiteId() {
|
|
13112
|
+
return getMediaContext().siteId;
|
|
13113
|
+
}
|
|
13114
|
+
function getMediaAssetIndex(context) {
|
|
13115
|
+
return context?.mediaAssetIndex ?? getMediaContext().mediaAssetIndex;
|
|
13116
|
+
}
|
|
13117
|
+
function resolveCanonicalMediaAsset(value, context) {
|
|
13118
|
+
const index = getMediaAssetIndex(context);
|
|
13119
|
+
if (!index) return void 0;
|
|
13120
|
+
if (value.assetId) {
|
|
13121
|
+
const hit = index.byId.get(value.assetId);
|
|
13122
|
+
if (hit) return hit;
|
|
13123
|
+
}
|
|
13124
|
+
const identifier = typeof value.identifier === "string" ? value.identifier.trim() : "";
|
|
13125
|
+
if (identifier) {
|
|
13126
|
+
const hit = index.byIdentifier.get(identifier);
|
|
13127
|
+
if (hit) return hit;
|
|
13128
|
+
}
|
|
13129
|
+
}
|
|
13130
|
+
function resolveMediaWithCanonicalAsset(value, context) {
|
|
13131
|
+
const asset = resolveCanonicalMediaAsset(value, context);
|
|
13132
|
+
if (!asset) return value;
|
|
13133
|
+
return attachRenderableMediaAssetFields(value, asset);
|
|
13134
|
+
}
|
|
13135
|
+
const debugMediaNodeLog = (...args) => {
|
|
13136
|
+
if (typeof window === "undefined") return;
|
|
13137
|
+
if (Reflect.get(window, "__DEBUG_MEDIA_NODE__") === true) console.log("[MediaNode]", ...args);
|
|
13138
|
+
};
|
|
13139
|
+
function resolveTargetAspectRatio(size) {
|
|
13140
|
+
if ("original" in size) return void 0;
|
|
13141
|
+
if ("width" in size && "height" in size && typeof size.width === "number" && typeof size.height === "number") return size.width / size.height;
|
|
13142
|
+
}
|
|
13143
|
+
function resolveImageUrlWithContext(value, options, context, transformAspectRatio) {
|
|
13144
|
+
const result = resolveImageUrlWithContextResult(value, options, context, transformAspectRatio);
|
|
13145
|
+
warnForMediaUrlResolution(result);
|
|
13146
|
+
return result.kind === "resolved" ? result.url : void 0;
|
|
13147
|
+
}
|
|
13148
|
+
function resolveImageUrlWithContextResult(value, options, context, transformAspectRatio) {
|
|
13149
|
+
if (value.type !== "image") return {
|
|
13150
|
+
kind: "unsupported-media-type",
|
|
13151
|
+
mediaType: value.type
|
|
13152
|
+
};
|
|
13153
|
+
const url = resolveImageUrlWithContextInternal(value, options, context ?? void 0, transformAspectRatio);
|
|
13154
|
+
if (url) return {
|
|
13155
|
+
kind: "resolved",
|
|
13156
|
+
url
|
|
13157
|
+
};
|
|
13158
|
+
const canonical = resolveMediaWithCanonicalAsset(value, context ?? void 0);
|
|
13159
|
+
if (canonical.storagePath && canonical.storagePath.length > 0) return resolveMediaStorageUrlResult(canonical, context, buildDirectTransformOptions(options));
|
|
13160
|
+
return {
|
|
13161
|
+
kind: "missing-image-url",
|
|
13162
|
+
assetId: canonical.assetId,
|
|
13163
|
+
identifier: canonical.identifier
|
|
13164
|
+
};
|
|
13165
|
+
}
|
|
13166
|
+
function resolveImageUrlWithContextInternal(value, options, context, transformAspectRatio, resolved) {
|
|
13167
|
+
if (value.type !== "image") return void 0;
|
|
13168
|
+
const canonical = resolveMediaWithCanonicalAsset(value, context);
|
|
13169
|
+
debugMediaNodeLog("resolveImageUrl input", {
|
|
13170
|
+
assetId: canonical.assetId,
|
|
13171
|
+
storagePath: canonical.storagePath,
|
|
13172
|
+
src: canonical.src,
|
|
13173
|
+
type: canonical.type,
|
|
13174
|
+
options
|
|
13175
|
+
});
|
|
13176
|
+
if (canonical.storagePath && canonical.storagePath.length > 0) {
|
|
13177
|
+
const resolvedStorageUrl = resolveStorageImageUrl(canonical, options, context, transformAspectRatio, resolved);
|
|
13178
|
+
if (resolvedStorageUrl) return resolvedStorageUrl;
|
|
13179
|
+
}
|
|
13180
|
+
if (typeof canonical.src === "string" && canonical.src.length > 0) {
|
|
13181
|
+
debugMediaNodeLog("resolve:explicit-src", { src: canonical.src });
|
|
13182
|
+
return canonical.src;
|
|
13183
|
+
}
|
|
13184
|
+
const legacyUrl = typeof canonical === "object" && canonical !== null ? Reflect.get(canonical, "url") : void 0;
|
|
13185
|
+
debugMediaNodeLog("resolve:fallback-url", { fallbackUrl: typeof legacyUrl === "string" ? legacyUrl : null });
|
|
13186
|
+
return typeof legacyUrl === "string" ? legacyUrl : void 0;
|
|
13187
|
+
}
|
|
13188
|
+
//#endregion
|
|
13189
|
+
//#region ../blocks/src/primitives/content/components/RichText.tsx
|
|
13190
|
+
function parseDimension(value) {
|
|
13191
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.round(value);
|
|
13192
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
13193
|
+
const parsed = Number(value);
|
|
13194
|
+
if (Number.isFinite(parsed) && parsed > 0) return Math.round(parsed);
|
|
13195
|
+
}
|
|
12327
13196
|
}
|
|
12328
|
-
function
|
|
12329
|
-
|
|
12330
|
-
|
|
12331
|
-
|
|
12332
|
-
|
|
12333
|
-
|
|
12334
|
-
|
|
12335
|
-
|
|
12336
|
-
|
|
13197
|
+
function normalizeRel(target, rel) {
|
|
13198
|
+
const normalizedRel = rel?.trim();
|
|
13199
|
+
if (target !== "_blank") return normalizedRel && normalizedRel.length > 0 ? normalizedRel : void 0;
|
|
13200
|
+
const tokens = new Set((normalizedRel ?? "").split(/\s+/).map((token) => token.trim().toLowerCase()).filter(Boolean));
|
|
13201
|
+
tokens.add("noopener");
|
|
13202
|
+
tokens.add("noreferrer");
|
|
13203
|
+
return Array.from(tokens).join(" ");
|
|
13204
|
+
}
|
|
13205
|
+
function renderMarks(text, marks, key, linkTarget) {
|
|
13206
|
+
if (!marks || marks.length === 0) return text;
|
|
13207
|
+
return marks.reduce((acc, mark) => {
|
|
13208
|
+
switch (mark.type) {
|
|
13209
|
+
case "bold":
|
|
13210
|
+
case "strong": return /* @__PURE__ */ jsx("strong", { children: acc }, `${key}-b`);
|
|
13211
|
+
case "italic":
|
|
13212
|
+
case "em": return /* @__PURE__ */ jsx("em", { children: acc }, `${key}-i`);
|
|
13213
|
+
case "link": {
|
|
13214
|
+
if (typeof acc === "string" && acc.length === 0) return acc;
|
|
13215
|
+
const attrs = mark.attrs ?? {};
|
|
13216
|
+
const href = sanitizeHref(attrs.href);
|
|
13217
|
+
if (!href) return acc;
|
|
13218
|
+
const storedTarget = typeof attrs.target === "string" && attrs.target.trim().length > 0 ? attrs.target.trim() : void 0;
|
|
13219
|
+
const target = linkTarget === "new-tab" ? "_blank" : storedTarget;
|
|
13220
|
+
return /* @__PURE__ */ jsx("a", {
|
|
13221
|
+
href,
|
|
13222
|
+
target,
|
|
13223
|
+
rel: normalizeRel(target, typeof attrs.rel === "string" ? attrs.rel : void 0),
|
|
13224
|
+
children: acc
|
|
13225
|
+
}, `${key}-l`);
|
|
13226
|
+
}
|
|
13227
|
+
default: return acc;
|
|
13228
|
+
}
|
|
13229
|
+
}, text);
|
|
13230
|
+
}
|
|
13231
|
+
function renderDoc(node, key, imageResolveContext, linkTarget) {
|
|
13232
|
+
if (!node || !node.type) return null;
|
|
13233
|
+
const children = node.content?.map((child, index) => renderDoc(child, `${key}-${index}`, imageResolveContext, linkTarget));
|
|
13234
|
+
switch (node.type) {
|
|
13235
|
+
case "doc": return /* @__PURE__ */ jsx(Fragment, { children });
|
|
13236
|
+
case "paragraph":
|
|
13237
|
+
if (!children && !node.text) return /* @__PURE__ */ jsx("p", {}, key);
|
|
13238
|
+
return /* @__PURE__ */ jsx("p", { children: children ?? renderMarks(node.text ?? "", node.marks, key, linkTarget) }, key);
|
|
13239
|
+
case "heading": {
|
|
13240
|
+
const headingTag = `h${Math.min(Math.max(node.attrs?.level ?? 2, 1), 6)}`;
|
|
13241
|
+
return React.createElement(headingTag, { key }, children);
|
|
13242
|
+
}
|
|
13243
|
+
case "bulletList": return /* @__PURE__ */ jsx("ul", { children }, key);
|
|
13244
|
+
case "orderedList": return /* @__PURE__ */ jsx("ol", { children }, key);
|
|
13245
|
+
case "listItem": return /* @__PURE__ */ jsx("li", { children }, key);
|
|
13246
|
+
case "blockquote": return /* @__PURE__ */ jsx("blockquote", { children }, key);
|
|
13247
|
+
case "horizontalRule": return /* @__PURE__ */ jsx("hr", {}, key);
|
|
13248
|
+
case "hardBreak": return /* @__PURE__ */ jsx("br", {}, key);
|
|
13249
|
+
case "image": {
|
|
13250
|
+
const attrs = node.attrs ?? {};
|
|
13251
|
+
const src = typeof attrs.src === "string" ? attrs.src.trim() : "";
|
|
13252
|
+
const identifier = typeof attrs.identifier === "string" ? attrs.identifier.trim() : "";
|
|
13253
|
+
const alt = typeof attrs.alt === "string" ? attrs.alt : "";
|
|
13254
|
+
const title = typeof attrs.title === "string" && attrs.title.trim().length > 0 ? attrs.title : void 0;
|
|
13255
|
+
const width = parseDimension(attrs.width);
|
|
13256
|
+
const height = parseDimension(attrs.height);
|
|
13257
|
+
const resolvedSrc = src || (identifier ? resolveImageUrlWithContext({
|
|
13258
|
+
type: "image",
|
|
13259
|
+
identifier
|
|
13260
|
+
}, width ? {
|
|
13261
|
+
width,
|
|
13262
|
+
resize: "contain",
|
|
13263
|
+
quality: 85
|
|
13264
|
+
} : height ? {
|
|
13265
|
+
height,
|
|
13266
|
+
resize: "contain",
|
|
13267
|
+
quality: 85
|
|
13268
|
+
} : ImagePresets.full, imageResolveContext ?? void 0) ?? "" : "");
|
|
13269
|
+
if (!resolvedSrc) return null;
|
|
13270
|
+
return /* @__PURE__ */ jsx("img", {
|
|
13271
|
+
src: resolvedSrc,
|
|
13272
|
+
alt,
|
|
13273
|
+
title,
|
|
13274
|
+
width,
|
|
13275
|
+
height,
|
|
13276
|
+
loading: "lazy",
|
|
13277
|
+
decoding: "async"
|
|
13278
|
+
}, key);
|
|
13279
|
+
}
|
|
13280
|
+
case "text": return renderMarks(node.text ?? "", node.marks, key, linkTarget);
|
|
13281
|
+
default: return null;
|
|
13282
|
+
}
|
|
13283
|
+
}
|
|
13284
|
+
const DEFAULT_RICH_TEXT_CLASS = "rb-prose rb-max-w-none";
|
|
13285
|
+
function RichText({ as: Comp = "div", className, doc, path, linkTarget = "stored" }) {
|
|
13286
|
+
const imageResolveContext = getCurrentResolveImageUrlContext() ?? null;
|
|
13287
|
+
const content = doc ? renderDoc(doc, "doc", imageResolveContext, linkTarget) : null;
|
|
13288
|
+
const dataAttributes = path ? { "data-builder-richtext": path } : void 0;
|
|
13289
|
+
return /* @__PURE__ */ jsx(Comp, {
|
|
13290
|
+
className: className?.trim() || DEFAULT_RICH_TEXT_CLASS,
|
|
13291
|
+
...dataAttributes,
|
|
13292
|
+
children: content
|
|
12337
13293
|
});
|
|
12338
13294
|
}
|
|
12339
13295
|
//#endregion
|
|
13296
|
+
//#region ../blocks/src/system/runtime/shared/components/BookingConsentAgreement.tsx
|
|
13297
|
+
function BookingConsentAgreement({ agreement, showTitle = true, title, titleId }) {
|
|
13298
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [showTitle ? /* @__PURE__ */ jsxs("div", {
|
|
13299
|
+
id: titleId,
|
|
13300
|
+
className: "form-label",
|
|
13301
|
+
children: [title, /* @__PURE__ */ jsx("span", {
|
|
13302
|
+
className: "required-marker",
|
|
13303
|
+
children: "*"
|
|
13304
|
+
})]
|
|
13305
|
+
}) : null, /* @__PURE__ */ jsx("div", {
|
|
13306
|
+
role: "group",
|
|
13307
|
+
"aria-label": showTitle ? void 0 : title,
|
|
13308
|
+
"aria-labelledby": showTitle ? titleId : void 0,
|
|
13309
|
+
children: /* @__PURE__ */ jsx(RichText, {
|
|
13310
|
+
doc: agreement,
|
|
13311
|
+
linkTarget: "new-tab",
|
|
13312
|
+
className: "rb-prose rb-max-w-none"
|
|
13313
|
+
})
|
|
13314
|
+
})] });
|
|
13315
|
+
}
|
|
13316
|
+
//#endregion
|
|
12340
13317
|
//#region ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
|
|
12341
13318
|
function optionCardClassName(isSelected) {
|
|
12342
13319
|
return `rb-option-card${isSelected ? " rb-option-card--selected" : ""}`;
|
|
@@ -12785,7 +13762,11 @@ function DefaultDynamicField({ booking, field }) {
|
|
|
12785
13762
|
return /* @__PURE__ */ jsxs("div", {
|
|
12786
13763
|
className: "rb-space-y-2",
|
|
12787
13764
|
children: [
|
|
12788
|
-
/* @__PURE__ */
|
|
13765
|
+
field.field.type === "booking_requirement_consent" ? /* @__PURE__ */ jsx(BookingConsentAgreement, {
|
|
13766
|
+
agreement: field.field.agreement,
|
|
13767
|
+
title: field.label,
|
|
13768
|
+
titleId: field.labelId
|
|
13769
|
+
}) : /* @__PURE__ */ jsxs("label", {
|
|
12789
13770
|
id: field.labelId,
|
|
12790
13771
|
htmlFor: field.inputId,
|
|
12791
13772
|
className: "form-label",
|
|
@@ -12830,7 +13811,7 @@ function DefaultFieldInput({ describedBy, error, errorId, field, onBlur, onChang
|
|
|
12830
13811
|
required: field.required,
|
|
12831
13812
|
...validationProps
|
|
12832
13813
|
};
|
|
12833
|
-
switch (field.type) {
|
|
13814
|
+
switch (field.field.type) {
|
|
12834
13815
|
case "textarea": return /* @__PURE__ */ jsx("textarea", {
|
|
12835
13816
|
...commonProps,
|
|
12836
13817
|
value: strValue,
|
|
@@ -12944,7 +13925,7 @@ function DefaultFieldInput({ describedBy, error, errorId, field, onBlur, onChang
|
|
|
12944
13925
|
className: "form-checkbox rb-mt-0.5"
|
|
12945
13926
|
}), /* @__PURE__ */ jsx("span", {
|
|
12946
13927
|
className: "rb-caption",
|
|
12947
|
-
children: field.field.
|
|
13928
|
+
children: field.field.checkboxLabel
|
|
12948
13929
|
})]
|
|
12949
13930
|
});
|
|
12950
13931
|
case "number": return /* @__PURE__ */ jsx("input", {
|
|
@@ -13013,10 +13994,10 @@ function DefaultBookingDiscount({ booking }) {
|
|
|
13013
13994
|
children: /* @__PURE__ */ jsxs("p", {
|
|
13014
13995
|
className: "ab-text",
|
|
13015
13996
|
children: [
|
|
13016
|
-
"Discount available:
|
|
13017
|
-
booking.discount.autoAppliedDiscount.publicLabel,
|
|
13997
|
+
"Discount available:",
|
|
13018
13998
|
" ",
|
|
13019
|
-
|
|
13999
|
+
booking.discount.autoAppliedDiscount.publicLabel,
|
|
14000
|
+
" will apply automatically at checkout."
|
|
13020
14001
|
]
|
|
13021
14002
|
})
|
|
13022
14003
|
}) : null]
|
|
@@ -13601,11 +14582,21 @@ function readAmount(value) {
|
|
|
13601
14582
|
}
|
|
13602
14583
|
//#endregion
|
|
13603
14584
|
//#region ../blocks/src/system/runtime/nodes/event-registration/validation.ts
|
|
13604
|
-
function
|
|
14585
|
+
function createInitialRegistrationFormData() {
|
|
14586
|
+
return {
|
|
14587
|
+
name: "",
|
|
14588
|
+
email: "",
|
|
14589
|
+
phone: "",
|
|
14590
|
+
notes: "",
|
|
14591
|
+
consentAccepted: false
|
|
14592
|
+
};
|
|
14593
|
+
}
|
|
14594
|
+
function validateFormData(formData, requiresConsent = false) {
|
|
13605
14595
|
const errors = {};
|
|
13606
14596
|
if (!formData.name.trim()) errors.name = "Name is required";
|
|
13607
14597
|
if (!formData.email.trim()) errors.email = "Email is required";
|
|
13608
14598
|
else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) errors.email = "Invalid email address";
|
|
14599
|
+
if (requiresConsent && formData.consentAccepted !== true) errors.consentAccepted = "Please read and accept the agreement before continuing.";
|
|
13609
14600
|
return errors;
|
|
13610
14601
|
}
|
|
13611
14602
|
/**
|
|
@@ -13764,6 +14755,15 @@ function existingRegistrationLookupReducer(state, action) {
|
|
|
13764
14755
|
* Custom hooks for portal authentication and eligibility checking.
|
|
13765
14756
|
* Extracted from the main EventRegistrationClient for better separation of concerns.
|
|
13766
14757
|
*/
|
|
14758
|
+
function scopePortalCreditStateToSubject(state, subjectEmail) {
|
|
14759
|
+
if (!subjectEmail) return { kind: "not_authenticated" };
|
|
14760
|
+
if (state.kind === "not_authenticated") return state;
|
|
14761
|
+
const normalizedSubject = subjectEmail.trim().toLowerCase();
|
|
14762
|
+
return state.subjectEmail === normalizedSubject ? state : {
|
|
14763
|
+
kind: "loading",
|
|
14764
|
+
subjectEmail: normalizedSubject
|
|
14765
|
+
};
|
|
14766
|
+
}
|
|
13767
14767
|
const eventRegistrationHooksDeps = { useBlockApi };
|
|
13768
14768
|
/**
|
|
13769
14769
|
* Hook for managing portal authentication state.
|
|
@@ -13778,27 +14778,54 @@ function usePortalAuthWithDeps(deps) {
|
|
|
13778
14778
|
const api = deps.useBlockApi();
|
|
13779
14779
|
const [authState, setAuthState] = useState("checking");
|
|
13780
14780
|
const [profile, setProfile] = useState(null);
|
|
14781
|
+
const [creditState, setCreditState] = useState({ kind: "not_authenticated" });
|
|
13781
14782
|
useEffect(() => {
|
|
13782
14783
|
let cancelled = false;
|
|
13783
14784
|
async function checkPortalAuth() {
|
|
13784
14785
|
if ((api.config.authOverrides?.portal ?? api.config.auth).type !== "bearer") {
|
|
13785
14786
|
setAuthState("unauthenticated");
|
|
14787
|
+
setProfile(null);
|
|
14788
|
+
setCreditState({ kind: "not_authenticated" });
|
|
13786
14789
|
return;
|
|
13787
14790
|
}
|
|
13788
14791
|
setAuthState("checking");
|
|
14792
|
+
setProfile(null);
|
|
14793
|
+
setCreditState({ kind: "not_authenticated" });
|
|
13789
14794
|
try {
|
|
13790
14795
|
const me = await api.getPortalProfile();
|
|
13791
14796
|
if (cancelled) return;
|
|
13792
|
-
|
|
13793
|
-
setProfile({
|
|
14797
|
+
const nextProfile = {
|
|
13794
14798
|
email: me.profile.email,
|
|
13795
14799
|
name: me.profile.name,
|
|
13796
14800
|
phone: me.profile.phone || ""
|
|
14801
|
+
};
|
|
14802
|
+
const subjectEmail = nextProfile.email.trim().toLowerCase();
|
|
14803
|
+
setProfile(nextProfile);
|
|
14804
|
+
setCreditState({
|
|
14805
|
+
kind: "loading",
|
|
14806
|
+
subjectEmail
|
|
13797
14807
|
});
|
|
14808
|
+
setAuthState("authenticated");
|
|
14809
|
+
try {
|
|
14810
|
+
const credit = await api.getPortalCredit();
|
|
14811
|
+
if (cancelled) return;
|
|
14812
|
+
setCreditState({
|
|
14813
|
+
kind: "loaded",
|
|
14814
|
+
subjectEmail,
|
|
14815
|
+
credit
|
|
14816
|
+
});
|
|
14817
|
+
} catch {
|
|
14818
|
+
if (cancelled) return;
|
|
14819
|
+
setCreditState({
|
|
14820
|
+
kind: "unavailable",
|
|
14821
|
+
subjectEmail
|
|
14822
|
+
});
|
|
14823
|
+
}
|
|
13798
14824
|
} catch {
|
|
13799
14825
|
if (cancelled) return;
|
|
13800
14826
|
setAuthState("unauthenticated");
|
|
13801
14827
|
setProfile(null);
|
|
14828
|
+
setCreditState({ kind: "not_authenticated" });
|
|
13802
14829
|
}
|
|
13803
14830
|
}
|
|
13804
14831
|
checkPortalAuth();
|
|
@@ -13818,6 +14845,7 @@ function usePortalAuthWithDeps(deps) {
|
|
|
13818
14845
|
isAuthenticated: authState === "authenticated",
|
|
13819
14846
|
isChecking: authState === "checking",
|
|
13820
14847
|
profile,
|
|
14848
|
+
creditState: scopePortalCreditStateToSubject(creditState, authState === "authenticated" ? profile?.email ?? null : null),
|
|
13821
14849
|
logout
|
|
13822
14850
|
};
|
|
13823
14851
|
}
|
|
@@ -14058,9 +15086,14 @@ function getWaitlistClaimTokenSnapshot() {
|
|
|
14058
15086
|
function useWaitlistClaim() {
|
|
14059
15087
|
return useWaitlistClaimWithDeps(useWaitlistClaimDeps);
|
|
14060
15088
|
}
|
|
15089
|
+
function useWaitlistClaimForToken(token) {
|
|
15090
|
+
return useResolvedWaitlistClaim(useWaitlistClaimDeps, token);
|
|
15091
|
+
}
|
|
14061
15092
|
function useWaitlistClaimWithDeps(deps) {
|
|
15093
|
+
return useResolvedWaitlistClaim(deps, useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimTokenSnapshot, () => null));
|
|
15094
|
+
}
|
|
15095
|
+
function useResolvedWaitlistClaim(deps, token) {
|
|
14062
15096
|
const api = deps.useBlockApi();
|
|
14063
|
-
const token = useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimTokenSnapshot, () => null);
|
|
14064
15097
|
const [state, dispatch] = useReducer(waitlistClaimReducer, Boolean(token), createInitialWaitlistClaimState);
|
|
14065
15098
|
useEffect(() => {
|
|
14066
15099
|
let cancelled = false;
|
|
@@ -14487,6 +15520,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
|
|
|
14487
15520
|
name: options.formData.name.trim(),
|
|
14488
15521
|
phone: options.formData.phone.trim() || void 0,
|
|
14489
15522
|
notes: options.formData.notes.trim() || void 0,
|
|
15523
|
+
consentAccepted: options.formData.consentAccepted,
|
|
14490
15524
|
altchaSolution: options.altchaSolution,
|
|
14491
15525
|
paymentMethod: method,
|
|
14492
15526
|
customerPassId: method === "pass" ? passId : void 0,
|
|
@@ -14704,88 +15738,171 @@ function requiresPaymentStep(params) {
|
|
|
14704
15738
|
return !isEntitlementSelection(params.paymentSelection);
|
|
14705
15739
|
}
|
|
14706
15740
|
//#endregion
|
|
14707
|
-
//#region ../blocks/src/system/
|
|
14708
|
-
|
|
14709
|
-
|
|
14710
|
-
|
|
14711
|
-
|
|
14712
|
-
|
|
14713
|
-
|
|
14714
|
-
|
|
14715
|
-
|
|
14716
|
-
|
|
14717
|
-
|
|
14718
|
-
|
|
14719
|
-
|
|
14720
|
-
|
|
14721
|
-
|
|
14722
|
-
|
|
14723
|
-
|
|
14724
|
-
|
|
14725
|
-
|
|
14726
|
-
|
|
14727
|
-
|
|
14728
|
-
|
|
14729
|
-
|
|
14730
|
-
|
|
14731
|
-
const TipTapNodeSchema = z.lazy(() => z.object({
|
|
14732
|
-
type: z.string().min(1),
|
|
14733
|
-
content: z.array(TipTapNodeSchema).optional(),
|
|
14734
|
-
text: z.string().optional(),
|
|
14735
|
-
attrs: z.record(z.string(), z.unknown()).optional(),
|
|
14736
|
-
marks: z.array(TipTapMarkSchema).optional()
|
|
14737
|
-
}).strict().superRefine((node, ctx) => {
|
|
14738
|
-
if (node.type === "doc") ctx.addIssue({
|
|
14739
|
-
code: "custom",
|
|
14740
|
-
path: ["type"],
|
|
14741
|
-
message: "Document nodes are only valid at the rich-text root"
|
|
15741
|
+
//#region ../blocks/src/system/blocks/events/whole-series/pricing.ts
|
|
15742
|
+
function isSaleWindowOpen(option, now) {
|
|
15743
|
+
if (!option.isActive) return false;
|
|
15744
|
+
if (option.saleStartsAt && new Date(option.saleStartsAt) > now) return false;
|
|
15745
|
+
if (option.saleEndsAt && new Date(option.saleEndsAt) < now) return false;
|
|
15746
|
+
return true;
|
|
15747
|
+
}
|
|
15748
|
+
function toExactOrFreeDisplay(amount, currency) {
|
|
15749
|
+
if (amount <= 0) return {
|
|
15750
|
+
kind: "free",
|
|
15751
|
+
currency
|
|
15752
|
+
};
|
|
15753
|
+
return {
|
|
15754
|
+
kind: "exact",
|
|
15755
|
+
amount,
|
|
15756
|
+
currency
|
|
15757
|
+
};
|
|
15758
|
+
}
|
|
15759
|
+
function getSelectableWholeSeriesPricingOptionsForNow(offering, now) {
|
|
15760
|
+
if (offering.pricing.pricingStrategy !== "tiered") return [];
|
|
15761
|
+
return [...offering.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
|
|
15762
|
+
if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
|
|
15763
|
+
if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
|
|
15764
|
+
return left.name.localeCompare(right.name);
|
|
14742
15765
|
});
|
|
14743
|
-
|
|
14744
|
-
|
|
14745
|
-
|
|
14746
|
-
|
|
14747
|
-
|
|
14748
|
-
|
|
14749
|
-
|
|
14750
|
-
|
|
14751
|
-
|
|
14752
|
-
message: "Text nodes cannot contain child nodes"
|
|
14753
|
-
});
|
|
14754
|
-
return;
|
|
15766
|
+
}
|
|
15767
|
+
function resolveWholeSeriesPricingState(offering, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
|
|
15768
|
+
const selection = normalizePricingSelectionInput(selectedSlidingAmountOrNowInput, nowInput);
|
|
15769
|
+
const currency = offering.pricing.currency;
|
|
15770
|
+
switch (offering.pricing.pricingStrategy) {
|
|
15771
|
+
case "free": return resolveFreePricing(currency);
|
|
15772
|
+
case "single": return resolveSinglePricing(offering.pricing.singlePriceAmount ?? 0, currency);
|
|
15773
|
+
case "tiered": return resolveTieredPricing(offering, selectedPricingOptionId, selection.nowInput);
|
|
15774
|
+
case "sliding_scale": return resolveSlidingScalePricing(offering, selection.selectedSlidingAmount);
|
|
14755
15775
|
}
|
|
14756
|
-
|
|
14757
|
-
|
|
14758
|
-
|
|
14759
|
-
|
|
14760
|
-
|
|
14761
|
-
}
|
|
14762
|
-
|
|
14763
|
-
|
|
14764
|
-
|
|
14765
|
-
|
|
14766
|
-
|
|
14767
|
-
|
|
14768
|
-
|
|
14769
|
-
|
|
14770
|
-
|
|
14771
|
-
|
|
14772
|
-
|
|
14773
|
-
|
|
14774
|
-
|
|
15776
|
+
}
|
|
15777
|
+
function normalizePricingSelectionInput(selectedSlidingAmountOrNowInput, nowInput) {
|
|
15778
|
+
return typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? {
|
|
15779
|
+
selectedSlidingAmount: null,
|
|
15780
|
+
nowInput: selectedSlidingAmountOrNowInput
|
|
15781
|
+
} : {
|
|
15782
|
+
selectedSlidingAmount: typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null,
|
|
15783
|
+
nowInput
|
|
15784
|
+
};
|
|
15785
|
+
}
|
|
15786
|
+
function resolveFreePricing(currency) {
|
|
15787
|
+
return {
|
|
15788
|
+
currency,
|
|
15789
|
+
display: {
|
|
15790
|
+
kind: "free",
|
|
15791
|
+
currency
|
|
15792
|
+
},
|
|
15793
|
+
selectableOptions: [],
|
|
15794
|
+
requiresSelection: false,
|
|
15795
|
+
selectedOption: null,
|
|
15796
|
+
slidingScale: null,
|
|
15797
|
+
selectedSlidingAmount: null,
|
|
15798
|
+
selectedPriceAmount: 0,
|
|
15799
|
+
selectedRequiresPayment: false,
|
|
15800
|
+
hasPaidSelection: false,
|
|
15801
|
+
hasFreeSelection: true
|
|
15802
|
+
};
|
|
15803
|
+
}
|
|
15804
|
+
function resolveSinglePricing(amount, currency) {
|
|
15805
|
+
return {
|
|
15806
|
+
currency,
|
|
15807
|
+
display: toExactOrFreeDisplay(amount, currency),
|
|
15808
|
+
selectableOptions: [],
|
|
15809
|
+
requiresSelection: false,
|
|
15810
|
+
selectedOption: null,
|
|
15811
|
+
slidingScale: null,
|
|
15812
|
+
selectedSlidingAmount: null,
|
|
15813
|
+
selectedPriceAmount: amount,
|
|
15814
|
+
selectedRequiresPayment: amount > 0,
|
|
15815
|
+
hasPaidSelection: amount > 0,
|
|
15816
|
+
hasFreeSelection: amount <= 0
|
|
15817
|
+
};
|
|
15818
|
+
}
|
|
15819
|
+
function resolveTieredPricing(offering, selectedPricingOptionId, nowInput) {
|
|
15820
|
+
const currency = offering.pricing.currency;
|
|
15821
|
+
const selectableOptions = getSelectableWholeSeriesPricingOptionsForNow(offering, resolvePlanningDateInput(nowInput));
|
|
15822
|
+
const selectedOption = resolveSelectedTier(selectableOptions, selectedPricingOptionId);
|
|
15823
|
+
return {
|
|
15824
|
+
currency,
|
|
15825
|
+
display: resolveTieredDisplay(selectableOptions.reduce((lowest, option) => lowest === null || option.priceAmount < lowest ? option.priceAmount : lowest, null), selectableOptions.length, currency),
|
|
15826
|
+
selectableOptions,
|
|
15827
|
+
requiresSelection: selectableOptions.length > 1,
|
|
15828
|
+
selectedOption,
|
|
15829
|
+
slidingScale: null,
|
|
15830
|
+
selectedSlidingAmount: null,
|
|
15831
|
+
selectedPriceAmount: selectedOption?.priceAmount ?? null,
|
|
15832
|
+
selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
|
|
15833
|
+
hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
|
|
15834
|
+
hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
|
|
15835
|
+
};
|
|
15836
|
+
}
|
|
15837
|
+
function resolveSelectedTier(options, selectedId) {
|
|
15838
|
+
return (selectedId ? options.find((option) => option.id === selectedId) : null) ?? (options.length === 1 ? options[0] ?? null : null);
|
|
15839
|
+
}
|
|
15840
|
+
function resolveTieredDisplay(lowestAmount, optionCount, currency) {
|
|
15841
|
+
if (lowestAmount === null) return {
|
|
15842
|
+
kind: "unavailable",
|
|
15843
|
+
currency
|
|
15844
|
+
};
|
|
15845
|
+
return optionCount > 1 && lowestAmount > 0 ? {
|
|
15846
|
+
kind: "from",
|
|
15847
|
+
amount: lowestAmount,
|
|
15848
|
+
currency
|
|
15849
|
+
} : toExactOrFreeDisplay(lowestAmount, currency);
|
|
15850
|
+
}
|
|
15851
|
+
function resolveSlidingScalePricing(offering, selectedSlidingAmount) {
|
|
15852
|
+
const currency = offering.pricing.currency;
|
|
15853
|
+
const minAmount = offering.pricing.slidingMinAmount ?? null;
|
|
15854
|
+
const maxAmount = offering.pricing.slidingMaxAmount ?? null;
|
|
15855
|
+
if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) return unavailableSlidingScale(currency);
|
|
15856
|
+
const selectedAmount = Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
|
|
15857
|
+
return {
|
|
15858
|
+
currency,
|
|
15859
|
+
display: {
|
|
15860
|
+
kind: "range",
|
|
15861
|
+
minAmount,
|
|
15862
|
+
maxAmount,
|
|
15863
|
+
currency
|
|
15864
|
+
},
|
|
15865
|
+
selectableOptions: [],
|
|
15866
|
+
requiresSelection: selectedAmount === null,
|
|
15867
|
+
selectedOption: null,
|
|
15868
|
+
slidingScale: {
|
|
15869
|
+
minAmount,
|
|
15870
|
+
maxAmount,
|
|
15871
|
+
suggestedAmount: offering.pricing.slidingSuggestedAmount ?? null
|
|
15872
|
+
},
|
|
15873
|
+
selectedSlidingAmount: selectedAmount,
|
|
15874
|
+
selectedPriceAmount: selectedAmount,
|
|
15875
|
+
selectedRequiresPayment: (selectedAmount ?? 0) > 0,
|
|
15876
|
+
hasPaidSelection: maxAmount > 0,
|
|
15877
|
+
hasFreeSelection: minAmount === 0
|
|
15878
|
+
};
|
|
15879
|
+
}
|
|
15880
|
+
function unavailableSlidingScale(currency) {
|
|
15881
|
+
return {
|
|
15882
|
+
currency,
|
|
15883
|
+
display: {
|
|
15884
|
+
kind: "unavailable",
|
|
15885
|
+
currency
|
|
15886
|
+
},
|
|
15887
|
+
selectableOptions: [],
|
|
15888
|
+
requiresSelection: true,
|
|
15889
|
+
selectedOption: null,
|
|
15890
|
+
slidingScale: null,
|
|
15891
|
+
selectedSlidingAmount: null,
|
|
15892
|
+
selectedPriceAmount: null,
|
|
15893
|
+
selectedRequiresPayment: false,
|
|
15894
|
+
hasPaidSelection: false,
|
|
15895
|
+
hasFreeSelection: false
|
|
15896
|
+
};
|
|
15897
|
+
}
|
|
14775
15898
|
//#endregion
|
|
14776
|
-
//#region ../blocks/src/system/blocks/
|
|
14777
|
-
|
|
14778
|
-
* Zod schema for course venue data
|
|
14779
|
-
*/
|
|
14780
|
-
const courseVenueSchema = z.object({
|
|
15899
|
+
//#region ../blocks/src/system/blocks/events/whole-series/schemas.ts
|
|
15900
|
+
const wholeSeriesVenueSchema = z.object({
|
|
14781
15901
|
id: z.string(),
|
|
14782
15902
|
name: z.string(),
|
|
14783
15903
|
address: z.string().nullable()
|
|
14784
15904
|
});
|
|
14785
|
-
|
|
14786
|
-
* Zod schema for course session (occurrence) data
|
|
14787
|
-
*/
|
|
14788
|
-
const courseSessionSchema = z.object({
|
|
15905
|
+
const wholeSeriesSessionSchema = z.object({
|
|
14789
15906
|
id: z.string(),
|
|
14790
15907
|
startsAt: z.string(),
|
|
14791
15908
|
endsAt: z.string(),
|
|
@@ -14793,14 +15910,14 @@ const courseSessionSchema = z.object({
|
|
|
14793
15910
|
capacityOverride: z.number().nullable().optional(),
|
|
14794
15911
|
overrides: z.record(z.string(), z.unknown()).nullable().optional()
|
|
14795
15912
|
});
|
|
14796
|
-
const
|
|
15913
|
+
const wholeSeriesTeamMemberSummarySchema = z.object({
|
|
14797
15914
|
id: z.string(),
|
|
14798
15915
|
name: z.string(),
|
|
14799
15916
|
roleLabel: z.string().nullable(),
|
|
14800
15917
|
summary: z.string().nullable(),
|
|
14801
15918
|
profilePath: z.string().nullable()
|
|
14802
15919
|
});
|
|
14803
|
-
const
|
|
15920
|
+
const wholeSeriesPricingOptionSchema = z.object({
|
|
14804
15921
|
id: z.string(),
|
|
14805
15922
|
name: z.string(),
|
|
14806
15923
|
description: z.string().nullable(),
|
|
@@ -14816,7 +15933,7 @@ const coursePricingOptionSchema = z.object({
|
|
|
14816
15933
|
"both"
|
|
14817
15934
|
]).nullable().optional()
|
|
14818
15935
|
});
|
|
14819
|
-
const
|
|
15936
|
+
const wholeSeriesPricingSchema = z.object({
|
|
14820
15937
|
bookingRequirement: z.enum(["none", "required"]),
|
|
14821
15938
|
pricingStrategy: z.enum([
|
|
14822
15939
|
"free",
|
|
@@ -14830,22 +15947,20 @@ const coursePricingSchema = z.object({
|
|
|
14830
15947
|
slidingMaxAmount: z.number().nullable().optional(),
|
|
14831
15948
|
slidingSuggestedAmount: z.number().nullable().optional(),
|
|
14832
15949
|
paymentTerms: blockBookingPaymentTermsSchema,
|
|
14833
|
-
options: z.array(
|
|
15950
|
+
options: z.array(wholeSeriesPricingOptionSchema)
|
|
14834
15951
|
});
|
|
14835
|
-
/**
|
|
14836
|
-
* Zod schema for public course data
|
|
14837
|
-
*/
|
|
14838
15952
|
const publicWholeSeriesOfferingSchema = z.object({
|
|
14839
15953
|
eventSeriesId: z.string(),
|
|
14840
15954
|
eventOfferingId: z.string(),
|
|
14841
15955
|
title: z.string(),
|
|
14842
15956
|
slug: z.string(),
|
|
14843
15957
|
description: z.unknown().nullable(),
|
|
14844
|
-
teamMembers: z.array(
|
|
15958
|
+
teamMembers: z.array(wholeSeriesTeamMemberSummarySchema).optional(),
|
|
14845
15959
|
enrollmentOpen: z.boolean(),
|
|
14846
|
-
pricing:
|
|
15960
|
+
pricing: wholeSeriesPricingSchema,
|
|
14847
15961
|
currency: z.string(),
|
|
14848
15962
|
paymentTerms: blockBookingPaymentTermsSchema,
|
|
15963
|
+
consent: blockBookingConsentSchema.nullable(),
|
|
14849
15964
|
enrollmentCapacity: z.number().nullable(),
|
|
14850
15965
|
acceptsMemberships: z.boolean(),
|
|
14851
15966
|
status: z.enum([
|
|
@@ -14856,8 +15971,8 @@ const publicWholeSeriesOfferingSchema = z.object({
|
|
|
14856
15971
|
sessionsCount: z.number(),
|
|
14857
15972
|
enrolledCount: z.number(),
|
|
14858
15973
|
availableSpots: z.number().nullable(),
|
|
14859
|
-
sessions: z.array(
|
|
14860
|
-
venue:
|
|
15974
|
+
sessions: z.array(wholeSeriesSessionSchema),
|
|
15975
|
+
venue: wholeSeriesVenueSchema.nullable()
|
|
14861
15976
|
});
|
|
14862
15977
|
z.array(publicWholeSeriesOfferingSchema);
|
|
14863
15978
|
//#endregion
|
|
@@ -15163,6 +16278,7 @@ const publicEventSchema = z.object({
|
|
|
15163
16278
|
timeZone: z.string(),
|
|
15164
16279
|
pricing: publicEventPricingSchema,
|
|
15165
16280
|
paymentTerms: blockBookingPaymentTermsSchema,
|
|
16281
|
+
consent: blockBookingConsentSchema.nullable(),
|
|
15166
16282
|
accessRestriction: accessRestrictionSchema,
|
|
15167
16283
|
allowedCategoryIds: z.array(z.string()),
|
|
15168
16284
|
requireGuestDetails: z.boolean().optional(),
|
|
@@ -15170,7 +16286,7 @@ const publicEventSchema = z.object({
|
|
|
15170
16286
|
acceptsMemberships: z.boolean().optional(),
|
|
15171
16287
|
wholeSeries: z.object({
|
|
15172
16288
|
eventSeriesId: z.string(),
|
|
15173
|
-
pricing:
|
|
16289
|
+
pricing: wholeSeriesPricingSchema,
|
|
15174
16290
|
currency: z.string(),
|
|
15175
16291
|
enrollmentOpen: z.boolean()
|
|
15176
16292
|
}).nullable().optional()
|
|
@@ -15681,12 +16797,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
15681
16797
|
const step = flowState.step;
|
|
15682
16798
|
const paymentSelection = flowState.paymentSelection;
|
|
15683
16799
|
const [selectedEvent, setSelectedEvent] = useState(preSelectedEvent ?? null);
|
|
15684
|
-
const [formData, setFormData] = useState(
|
|
15685
|
-
name: "",
|
|
15686
|
-
email: "",
|
|
15687
|
-
phone: "",
|
|
15688
|
-
notes: ""
|
|
15689
|
-
});
|
|
16800
|
+
const [formData, setFormData] = useState(createInitialRegistrationFormData);
|
|
15690
16801
|
const [errors, setErrors] = useState({});
|
|
15691
16802
|
const [guests, setGuests] = useState([]);
|
|
15692
16803
|
const [guestErrors, setGuestErrors] = useState({});
|
|
@@ -15700,7 +16811,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
15700
16811
|
const [registrationResult, setRegistrationResult] = useState(null);
|
|
15701
16812
|
const [errorMessage, setErrorMessage] = useState("");
|
|
15702
16813
|
const [altchaSolution, setAltchaSolution] = useState(null);
|
|
15703
|
-
const { authState: portalAuthState, profile: portalProfile } = deps.usePortalAuth();
|
|
16814
|
+
const { authState: portalAuthState, profile: portalProfile, creditState: portalCreditState } = deps.usePortalAuth();
|
|
15704
16815
|
const waitlistClaim = deps.useWaitlistClaim();
|
|
15705
16816
|
const [showMagicLinkModal, setShowMagicLinkModal] = useState(false);
|
|
15706
16817
|
const [pendingAttendeeId, setPendingAttendeeId] = useState(null);
|
|
@@ -15984,7 +17095,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
15984
17095
|
guests
|
|
15985
17096
|
]);
|
|
15986
17097
|
const validateForm = () => {
|
|
15987
|
-
const newErrors = validateFormData(formData);
|
|
17098
|
+
const newErrors = validateFormData(formData, Boolean(currentEvent?.consent));
|
|
15988
17099
|
setErrors(newErrors);
|
|
15989
17100
|
const newGuestErrors = {};
|
|
15990
17101
|
if (requireGuestDetails && guests.length > 0) {
|
|
@@ -16173,6 +17284,10 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
16173
17284
|
});
|
|
16174
17285
|
const handleEventSelect = (event) => {
|
|
16175
17286
|
setSelectedEvent(event);
|
|
17287
|
+
setFormData((current) => ({
|
|
17288
|
+
...current,
|
|
17289
|
+
consentAccepted: false
|
|
17290
|
+
}));
|
|
16176
17291
|
const slidingScale = getSlidingScaleForEvent(event);
|
|
16177
17292
|
setSelectedSlidingAmountInput(slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput$1(slidingScale.suggestedAmount) : "");
|
|
16178
17293
|
setSelectedAttendanceMode((event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person");
|
|
@@ -16253,6 +17368,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
16253
17368
|
setAltchaSolution,
|
|
16254
17369
|
portalAuthState,
|
|
16255
17370
|
portalProfile,
|
|
17371
|
+
portalCreditState,
|
|
16256
17372
|
showMagicLinkModal,
|
|
16257
17373
|
setShowMagicLinkModal,
|
|
16258
17374
|
handleLogout,
|
|
@@ -16307,7 +17423,7 @@ function buildEventRegistrationPaymentOptionsViewModel(input) {
|
|
|
16307
17423
|
return {
|
|
16308
17424
|
mode: selection.mode,
|
|
16309
17425
|
sectionTitle: selection.sectionTitle,
|
|
16310
|
-
options: selection.options.map((option) => toEventDirectPaymentOption(option, selection.mode))
|
|
17426
|
+
options: selection.options.map((option, index) => toEventDirectPaymentOption(option, supportedOptions[index] ?? DEFAULT_EVENT_DIRECT_PAYMENT_OPTION, selection.mode, input.totalPriceCents))
|
|
16311
17427
|
};
|
|
16312
17428
|
}
|
|
16313
17429
|
function selectSupportedEventDirectPaymentOptions(paymentTerms) {
|
|
@@ -16317,17 +17433,24 @@ function selectSupportedEventDirectPaymentOptions(paymentTerms) {
|
|
|
16317
17433
|
function isSupportedEventDirectPaymentOption(option) {
|
|
16318
17434
|
return option.kind === "upfront" || option.kind === "flexible_balance";
|
|
16319
17435
|
}
|
|
16320
|
-
function toEventDirectPaymentOption(option, mode) {
|
|
17436
|
+
function toEventDirectPaymentOption(option, sourceOption, mode, totalCents) {
|
|
16321
17437
|
switch (option.kind) {
|
|
16322
17438
|
case "upfront": return {
|
|
16323
17439
|
...option,
|
|
16324
17440
|
kind: "upfront",
|
|
16325
|
-
label: mode === "choice_required" ? "Pay in full now" : "Pay by card"
|
|
17441
|
+
label: mode === "choice_required" ? "Pay in full now" : "Pay by card",
|
|
17442
|
+
totalCents,
|
|
17443
|
+
configuredPaymentDueNowCents: totalCents
|
|
16326
17444
|
};
|
|
16327
17445
|
case "flexible_balance": return {
|
|
16328
17446
|
...option,
|
|
16329
17447
|
kind: "flexible_balance",
|
|
16330
|
-
label: "Pay deposit now"
|
|
17448
|
+
label: "Pay deposit now",
|
|
17449
|
+
totalCents,
|
|
17450
|
+
configuredPaymentDueNowCents: sourceOption.kind === "flexible_balance" ? resolveFlexibleBalanceInitialPaymentCents({
|
|
17451
|
+
totalAmountCents: totalCents,
|
|
17452
|
+
config: sourceOption.config
|
|
17453
|
+
}) : totalCents
|
|
16331
17454
|
};
|
|
16332
17455
|
case "deferred_manual":
|
|
16333
17456
|
case "instalment_plan": throw new Error(`Unsupported event registration payment option: ${option.kind}`);
|
|
@@ -16660,13 +17783,13 @@ function resolveHeadlessDirectPaymentOptions(wizard) {
|
|
|
16660
17783
|
}).options;
|
|
16661
17784
|
}
|
|
16662
17785
|
//#endregion
|
|
16663
|
-
//#region ../blocks/src/system/runtime/nodes/
|
|
17786
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/utils.ts
|
|
16664
17787
|
/**
|
|
16665
17788
|
* Anchor ID for the registration block, used for scroll targeting.
|
|
16666
17789
|
*/
|
|
16667
|
-
const
|
|
17790
|
+
const WHOLE_SERIES_REGISTRATION_ANCHOR_ID = "event-registration";
|
|
16668
17791
|
//#endregion
|
|
16669
|
-
//#region ../blocks/src/system/runtime/nodes/
|
|
17792
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/pricing.ts
|
|
16670
17793
|
function parseCurrencyInputToCents(value) {
|
|
16671
17794
|
const trimmed = value.trim();
|
|
16672
17795
|
if (!trimmed) return null;
|
|
@@ -16678,31 +17801,31 @@ function formatCentsAsCurrencyInput(amount) {
|
|
|
16678
17801
|
const major = amount / 100;
|
|
16679
17802
|
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
16680
17803
|
}
|
|
16681
|
-
function
|
|
17804
|
+
function getMissingWholeSeriesPricingSelectionMessage(pricing) {
|
|
16682
17805
|
if (pricing?.requiresSelection && !pricing.selectedOption) return pricing.slidingScale ? "Choose an amount to continue." : "Choose a pricing option to continue.";
|
|
16683
17806
|
const selectedAmount = pricing?.selectedSlidingAmount;
|
|
16684
17807
|
const scale = pricing?.slidingScale;
|
|
16685
17808
|
if (scale && selectedAmount !== null && selectedAmount !== void 0 && (selectedAmount < scale.minAmount || selectedAmount > scale.maxAmount)) return "Choose an amount within the sliding scale.";
|
|
16686
17809
|
return null;
|
|
16687
17810
|
}
|
|
16688
|
-
function
|
|
17811
|
+
function buildWholeSeriesPricingOptionPayload(pricing) {
|
|
16689
17812
|
if (pricing?.selectedOption) return { pricingOptionId: pricing.selectedOption.id };
|
|
16690
17813
|
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null) return { selectedSlidingAmount: pricing.selectedSlidingAmount };
|
|
16691
17814
|
return {};
|
|
16692
17815
|
}
|
|
16693
|
-
function
|
|
17816
|
+
function defaultWholeSeriesPricingSelection(pricing, previousOptionId) {
|
|
16694
17817
|
return {
|
|
16695
17818
|
pricingOptionId: previousOptionId && pricing.selectableOptions.some((option) => option.id === previousOptionId) ? previousOptionId : pricing.selectedOption?.id ?? null,
|
|
16696
17819
|
slidingAmountInput: pricing.slidingScale?.suggestedAmount !== null && pricing.slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(pricing.slidingScale.suggestedAmount) : ""
|
|
16697
17820
|
};
|
|
16698
17821
|
}
|
|
16699
17822
|
//#endregion
|
|
16700
|
-
//#region ../blocks/src/system/runtime/nodes/
|
|
17823
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/wizardSteps.ts
|
|
16701
17824
|
/**
|
|
16702
17825
|
* Step labels for the wizard indicator
|
|
16703
17826
|
*/
|
|
16704
17827
|
const STEP_LABELS = {
|
|
16705
|
-
"select-
|
|
17828
|
+
"select-run": "Run",
|
|
16706
17829
|
"enter-details": "Details",
|
|
16707
17830
|
"booking-mode": "Method",
|
|
16708
17831
|
"select-payment": "Payment",
|
|
@@ -16718,36 +17841,36 @@ const STEP_LABELS = {
|
|
|
16718
17841
|
/**
|
|
16719
17842
|
* Determine which wizard steps to show based on context and eligibility.
|
|
16720
17843
|
*
|
|
16721
|
-
* @param
|
|
16722
|
-
* @param requiresPayment - Whether the
|
|
17844
|
+
* @param hasPreSelectedRun - Whether run is pre-selected (skips run selection)
|
|
17845
|
+
* @param requiresPayment - Whether the run requires payment
|
|
16723
17846
|
* @param hasEligibleMemberships - Whether user has eligible memberships
|
|
16724
17847
|
* @param bookingMode - Current booking mode selection
|
|
16725
17848
|
* @param isMembershipFastTrack - Whether user qualifies for single-step membership flow
|
|
16726
17849
|
* @returns Array of wizard steps to display
|
|
16727
17850
|
*/
|
|
16728
|
-
function getWizardStepsForContext(
|
|
16729
|
-
if (isMembershipFastTrack) return
|
|
16730
|
-
if (!requiresPayment) return
|
|
17851
|
+
function getWizardStepsForContext(hasPreSelectedRun, requiresPayment, hasEligibleMemberships, bookingMode, isMembershipFastTrack) {
|
|
17852
|
+
if (isMembershipFastTrack) return hasPreSelectedRun ? ["enter-details"] : ["select-run", "enter-details"];
|
|
17853
|
+
if (!requiresPayment) return hasPreSelectedRun ? ["enter-details"] : ["select-run", "enter-details"];
|
|
16731
17854
|
if (hasEligibleMemberships) {
|
|
16732
17855
|
const skipPayment = bookingMode === "membership";
|
|
16733
|
-
if (
|
|
17856
|
+
if (hasPreSelectedRun) return skipPayment ? ["enter-details", "booking-mode"] : [
|
|
16734
17857
|
"enter-details",
|
|
16735
17858
|
"booking-mode",
|
|
16736
17859
|
"select-payment"
|
|
16737
17860
|
];
|
|
16738
17861
|
return skipPayment ? [
|
|
16739
|
-
"select-
|
|
17862
|
+
"select-run",
|
|
16740
17863
|
"enter-details",
|
|
16741
17864
|
"booking-mode"
|
|
16742
17865
|
] : [
|
|
16743
|
-
"select-
|
|
17866
|
+
"select-run",
|
|
16744
17867
|
"enter-details",
|
|
16745
17868
|
"booking-mode",
|
|
16746
17869
|
"select-payment"
|
|
16747
17870
|
];
|
|
16748
17871
|
}
|
|
16749
|
-
return
|
|
16750
|
-
"select-
|
|
17872
|
+
return hasPreSelectedRun ? ["enter-details", "select-payment"] : [
|
|
17873
|
+
"select-run",
|
|
16751
17874
|
"enter-details",
|
|
16752
17875
|
"select-payment"
|
|
16753
17876
|
];
|
|
@@ -16759,21 +17882,21 @@ function getStepLabels(steps) {
|
|
|
16759
17882
|
return steps.map((step) => STEP_LABELS[step] ?? step);
|
|
16760
17883
|
}
|
|
16761
17884
|
//#endregion
|
|
16762
|
-
//#region ../blocks/src/system/runtime/nodes/
|
|
16763
|
-
function
|
|
16764
|
-
const
|
|
16765
|
-
const canUseMembership =
|
|
16766
|
-
const
|
|
17885
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/wholeSeriesRegistrationViewState.ts
|
|
17886
|
+
function deriveWholeSeriesRegistrationViewState(input) {
|
|
17887
|
+
const hasRunPayment = resolveWholeSeriesPaymentRequirement(input.pricing);
|
|
17888
|
+
const canUseMembership = hasRunPayment && input.selectedRun?.acceptsMemberships === true && input.portalAuthState === "authenticated" && input.eligibleMembershipCount > 0;
|
|
17889
|
+
const hasPreSelectedRun = input.scopedRuns.length === 1;
|
|
16767
17890
|
const fastTrack = canUseMembership && input.eligibleMembershipCount === 1 && input.bookingMode === "membership";
|
|
16768
|
-
const wizardSteps = getWizardStepsForContext(
|
|
17891
|
+
const wizardSteps = getWizardStepsForContext(hasPreSelectedRun, hasRunPayment, canUseMembership, input.bookingMode, fastTrack);
|
|
16769
17892
|
const showPortalAuthSidebar = shouldShowPortalAuthSidebar({
|
|
16770
17893
|
...input,
|
|
16771
|
-
|
|
17894
|
+
hasRunPayment
|
|
16772
17895
|
});
|
|
16773
17896
|
return {
|
|
16774
|
-
|
|
17897
|
+
hasRunPayment,
|
|
16775
17898
|
canUseMembership,
|
|
16776
|
-
|
|
17899
|
+
hasPreSelectedRun,
|
|
16777
17900
|
wizardSteps,
|
|
16778
17901
|
currentStepNumber: getStepNumber(input.step, wizardSteps),
|
|
16779
17902
|
totalSteps: wizardSteps.length,
|
|
@@ -16781,24 +17904,24 @@ function deriveCourseRegistrationViewState(input) {
|
|
|
16781
17904
|
showPortalAuthSidebar
|
|
16782
17905
|
};
|
|
16783
17906
|
}
|
|
16784
|
-
function
|
|
17907
|
+
function resolveWholeSeriesPaymentRequirement(pricing) {
|
|
16785
17908
|
if (!pricing) return false;
|
|
16786
17909
|
return pricing.selectedOption ? pricing.selectedRequiresPayment : pricing.hasPaidSelection;
|
|
16787
17910
|
}
|
|
16788
17911
|
function shouldShowPortalAuthSidebar(input) {
|
|
16789
17912
|
if (input.portalAuthState !== "unauthenticated") return false;
|
|
16790
17913
|
if (input.step === "success" || input.step === "waitlist" || input.step === "error") return false;
|
|
16791
|
-
return input.waitlistRequiresPortalLogin || input.
|
|
17914
|
+
return input.waitlistRequiresPortalLogin || input.hasRunPayment && input.selectedRun?.acceptsMemberships === true && input.step !== "select-run";
|
|
16792
17915
|
}
|
|
16793
17916
|
//#endregion
|
|
16794
|
-
//#region ../blocks/src/system/runtime/nodes/
|
|
17917
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesEligibility.ts
|
|
16795
17918
|
function shouldFetchEligibility(input) {
|
|
16796
|
-
if (!input.
|
|
16797
|
-
const membershipCheck = input.portalAuthState === "authenticated" && input.hasPaidSelection && input.
|
|
16798
|
-
const capacityCheck = input.
|
|
17919
|
+
if (!input.run || input.portalAuthState === "checking" || input.hasWaitlistClaimToken) return false;
|
|
17920
|
+
const membershipCheck = input.portalAuthState === "authenticated" && input.hasPaidSelection && input.run.acceptsMemberships;
|
|
17921
|
+
const capacityCheck = input.run.availableSpots !== null && input.run.availableSpots <= 0;
|
|
16799
17922
|
return membershipCheck || capacityCheck;
|
|
16800
17923
|
}
|
|
16801
|
-
function
|
|
17924
|
+
function useWholeSeriesEligibility(input) {
|
|
16802
17925
|
const [loading, setLoading] = useState(false);
|
|
16803
17926
|
const [error, setError] = useState(null);
|
|
16804
17927
|
const [eligibility, setEligibility] = useState(null);
|
|
@@ -16819,15 +17942,15 @@ function useCourseEligibility(input) {
|
|
|
16819
17942
|
setError(null);
|
|
16820
17943
|
setPaymentChoice("checkout");
|
|
16821
17944
|
const eligibilityInput = {
|
|
16822
|
-
|
|
17945
|
+
run: input.selectedRun,
|
|
16823
17946
|
hasPaidSelection: input.hasPaidSelection,
|
|
16824
17947
|
portalAuthState: input.portalAuthState,
|
|
16825
17948
|
hasWaitlistClaimToken: input.waitlistClaimToken !== null
|
|
16826
17949
|
};
|
|
16827
17950
|
if (!shouldFetchEligibility(eligibilityInput)) return;
|
|
16828
|
-
const
|
|
17951
|
+
const run = eligibilityInput.run;
|
|
16829
17952
|
setLoading(true);
|
|
16830
|
-
input.api.checkWholeSeriesEligibility({ eventSeriesId:
|
|
17953
|
+
input.api.checkWholeSeriesEligibility({ eventSeriesId: run.eventSeriesId }).then((result) => {
|
|
16831
17954
|
if (cancelled) return;
|
|
16832
17955
|
const eligibleMemberships = result.eligibleMemberships ?? [];
|
|
16833
17956
|
setEligibility(result);
|
|
@@ -16848,13 +17971,13 @@ function useCourseEligibility(input) {
|
|
|
16848
17971
|
input.api,
|
|
16849
17972
|
input.hasPaidSelection,
|
|
16850
17973
|
input.portalAuthState,
|
|
16851
|
-
input.
|
|
17974
|
+
input.selectedRun,
|
|
16852
17975
|
input.waitlistClaimToken
|
|
16853
17976
|
]);
|
|
16854
17977
|
return {
|
|
16855
17978
|
eligibilityLoading: loading,
|
|
16856
17979
|
eligibilityError: error,
|
|
16857
|
-
|
|
17980
|
+
runEligibility: eligibility,
|
|
16858
17981
|
eligibleMemberships: memberships,
|
|
16859
17982
|
paymentChoice,
|
|
16860
17983
|
choosePaymentChoice,
|
|
@@ -16863,149 +17986,12 @@ function useCourseEligibility(input) {
|
|
|
16863
17986
|
};
|
|
16864
17987
|
}
|
|
16865
17988
|
//#endregion
|
|
16866
|
-
//#region ../blocks/src/system/
|
|
16867
|
-
function isSaleWindowOpen(option, now) {
|
|
16868
|
-
if (!option.isActive) return false;
|
|
16869
|
-
if (option.saleStartsAt && new Date(option.saleStartsAt) > now) return false;
|
|
16870
|
-
if (option.saleEndsAt && new Date(option.saleEndsAt) < now) return false;
|
|
16871
|
-
return true;
|
|
16872
|
-
}
|
|
16873
|
-
function toExactOrFreeDisplay(amount, currency) {
|
|
16874
|
-
if (amount <= 0) return {
|
|
16875
|
-
kind: "free",
|
|
16876
|
-
currency
|
|
16877
|
-
};
|
|
16878
|
-
return {
|
|
16879
|
-
kind: "exact",
|
|
16880
|
-
amount,
|
|
16881
|
-
currency
|
|
16882
|
-
};
|
|
16883
|
-
}
|
|
16884
|
-
function getSelectableCoursePricingOptionsForNow(course, now) {
|
|
16885
|
-
if (course.pricing.pricingStrategy !== "tiered") return [];
|
|
16886
|
-
return [...course.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
|
|
16887
|
-
if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
|
|
16888
|
-
if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
|
|
16889
|
-
return left.name.localeCompare(right.name);
|
|
16890
|
-
});
|
|
16891
|
-
}
|
|
16892
|
-
function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
|
|
16893
|
-
const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
|
|
16894
|
-
const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
|
|
16895
|
-
const currency = course.pricing.currency;
|
|
16896
|
-
switch (course.pricing.pricingStrategy) {
|
|
16897
|
-
case "free": return {
|
|
16898
|
-
currency,
|
|
16899
|
-
display: {
|
|
16900
|
-
kind: "free",
|
|
16901
|
-
currency
|
|
16902
|
-
},
|
|
16903
|
-
selectableOptions: [],
|
|
16904
|
-
requiresSelection: false,
|
|
16905
|
-
selectedOption: null,
|
|
16906
|
-
slidingScale: null,
|
|
16907
|
-
selectedSlidingAmount: null,
|
|
16908
|
-
selectedPriceAmount: 0,
|
|
16909
|
-
selectedRequiresPayment: false,
|
|
16910
|
-
hasPaidSelection: false,
|
|
16911
|
-
hasFreeSelection: true
|
|
16912
|
-
};
|
|
16913
|
-
case "single": {
|
|
16914
|
-
const amount = course.pricing.singlePriceAmount ?? 0;
|
|
16915
|
-
return {
|
|
16916
|
-
currency,
|
|
16917
|
-
display: toExactOrFreeDisplay(amount, currency),
|
|
16918
|
-
selectableOptions: [],
|
|
16919
|
-
requiresSelection: false,
|
|
16920
|
-
selectedOption: null,
|
|
16921
|
-
slidingScale: null,
|
|
16922
|
-
selectedSlidingAmount: null,
|
|
16923
|
-
selectedPriceAmount: amount,
|
|
16924
|
-
selectedRequiresPayment: amount > 0,
|
|
16925
|
-
hasPaidSelection: amount > 0,
|
|
16926
|
-
hasFreeSelection: amount <= 0
|
|
16927
|
-
};
|
|
16928
|
-
}
|
|
16929
|
-
case "tiered": {
|
|
16930
|
-
const selectableOptions = getSelectableCoursePricingOptionsForNow(course, resolvePlanningDateInput(effectiveNowInput));
|
|
16931
|
-
const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
|
|
16932
|
-
const lowestAmount = selectableOptions.reduce((lowest, option) => {
|
|
16933
|
-
if (lowest === null || option.priceAmount < lowest) return option.priceAmount;
|
|
16934
|
-
return lowest;
|
|
16935
|
-
}, null);
|
|
16936
|
-
return {
|
|
16937
|
-
currency,
|
|
16938
|
-
display: lowestAmount === null ? {
|
|
16939
|
-
kind: "unavailable",
|
|
16940
|
-
currency
|
|
16941
|
-
} : selectableOptions.length > 1 && lowestAmount > 0 ? {
|
|
16942
|
-
kind: "from",
|
|
16943
|
-
amount: lowestAmount,
|
|
16944
|
-
currency
|
|
16945
|
-
} : toExactOrFreeDisplay(lowestAmount, currency),
|
|
16946
|
-
selectableOptions,
|
|
16947
|
-
requiresSelection: selectableOptions.length > 1,
|
|
16948
|
-
selectedOption,
|
|
16949
|
-
slidingScale: null,
|
|
16950
|
-
selectedSlidingAmount: null,
|
|
16951
|
-
selectedPriceAmount: selectedOption?.priceAmount ?? null,
|
|
16952
|
-
selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
|
|
16953
|
-
hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
|
|
16954
|
-
hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
|
|
16955
|
-
};
|
|
16956
|
-
}
|
|
16957
|
-
case "sliding_scale": {
|
|
16958
|
-
const minAmount = course.pricing.slidingMinAmount ?? null;
|
|
16959
|
-
const maxAmount = course.pricing.slidingMaxAmount ?? null;
|
|
16960
|
-
if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) return {
|
|
16961
|
-
currency,
|
|
16962
|
-
display: {
|
|
16963
|
-
kind: "unavailable",
|
|
16964
|
-
currency
|
|
16965
|
-
},
|
|
16966
|
-
selectableOptions: [],
|
|
16967
|
-
requiresSelection: true,
|
|
16968
|
-
selectedOption: null,
|
|
16969
|
-
slidingScale: null,
|
|
16970
|
-
selectedSlidingAmount: null,
|
|
16971
|
-
selectedPriceAmount: null,
|
|
16972
|
-
selectedRequiresPayment: false,
|
|
16973
|
-
hasPaidSelection: false,
|
|
16974
|
-
hasFreeSelection: false
|
|
16975
|
-
};
|
|
16976
|
-
const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
|
|
16977
|
-
return {
|
|
16978
|
-
currency,
|
|
16979
|
-
display: {
|
|
16980
|
-
kind: "range",
|
|
16981
|
-
minAmount,
|
|
16982
|
-
maxAmount,
|
|
16983
|
-
currency
|
|
16984
|
-
},
|
|
16985
|
-
selectableOptions: [],
|
|
16986
|
-
requiresSelection: normalizedSelectedAmount === null,
|
|
16987
|
-
selectedOption: null,
|
|
16988
|
-
slidingScale: {
|
|
16989
|
-
minAmount,
|
|
16990
|
-
maxAmount,
|
|
16991
|
-
suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
|
|
16992
|
-
},
|
|
16993
|
-
selectedSlidingAmount: normalizedSelectedAmount,
|
|
16994
|
-
selectedPriceAmount: normalizedSelectedAmount,
|
|
16995
|
-
selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
|
|
16996
|
-
hasPaidSelection: maxAmount > 0,
|
|
16997
|
-
hasFreeSelection: minAmount === 0
|
|
16998
|
-
};
|
|
16999
|
-
}
|
|
17000
|
-
}
|
|
17001
|
-
}
|
|
17002
|
-
//#endregion
|
|
17003
|
-
//#region ../blocks/src/system/runtime/nodes/course-page-surface-scope.ts
|
|
17989
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/wholeSeriesPageSurfaceScope.ts
|
|
17004
17990
|
/**
|
|
17005
|
-
* Resolves native
|
|
17991
|
+
* Resolves native run-page ownership without falling back to entry or slug
|
|
17006
17992
|
* coincidence when a page-surface subject is present but invalid.
|
|
17007
17993
|
*/
|
|
17008
|
-
function
|
|
17994
|
+
function resolveWholeSeriesPageSurfaceScope(runs, subjectValue) {
|
|
17009
17995
|
if (subjectValue === null || subjectValue === void 0) return { kind: "absent" };
|
|
17010
17996
|
const parsed = parseEventPageSurfaceSubject(subjectValue);
|
|
17011
17997
|
if (!parsed.ok) return {
|
|
@@ -17017,7 +18003,7 @@ function resolveCoursePageSurfaceScope(courses, subjectValue) {
|
|
|
17017
18003
|
return {
|
|
17018
18004
|
kind: "scoped",
|
|
17019
18005
|
subject: parsed.value,
|
|
17020
|
-
|
|
18006
|
+
runs: runs.filter((run) => allowedSeriesIds.has(run.eventSeriesId))
|
|
17021
18007
|
};
|
|
17022
18008
|
}
|
|
17023
18009
|
function eventSeriesIdsForSubject(subject) {
|
|
@@ -17028,33 +18014,43 @@ function eventSeriesIdsForSubject(subject) {
|
|
|
17028
18014
|
}
|
|
17029
18015
|
}
|
|
17030
18016
|
//#endregion
|
|
17031
|
-
//#region ../blocks/src/system/runtime/nodes/
|
|
17032
|
-
function
|
|
17033
|
-
const surfaceScope =
|
|
18017
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationSelection.ts
|
|
18018
|
+
function selectScopedRuns(props) {
|
|
18019
|
+
const surfaceScope = resolveWholeSeriesPageSurfaceScope(props.runs ?? [], props.subject);
|
|
17034
18020
|
if (surfaceScope.kind === "unsupported") return [];
|
|
17035
|
-
if (surfaceScope.kind === "scoped") return surfaceScope.
|
|
18021
|
+
if (surfaceScope.kind === "scoped") return surfaceScope.runs;
|
|
17036
18022
|
return [];
|
|
17037
18023
|
}
|
|
17038
|
-
function
|
|
17039
|
-
const fromSearch = new URLSearchParams(
|
|
18024
|
+
function getWholeSeriesCheckoutSessionId(location = window.location) {
|
|
18025
|
+
const fromSearch = new URLSearchParams(location.search).get("session_id");
|
|
17040
18026
|
if (fromSearch) return fromSearch;
|
|
17041
|
-
return
|
|
18027
|
+
return location.hash.match(/[?&]session_id=([^&]+)/)?.[1] ?? null;
|
|
17042
18028
|
}
|
|
17043
|
-
function initialStep(
|
|
17044
|
-
if (new URLSearchParams(
|
|
17045
|
-
return
|
|
18029
|
+
function initialStep(runs, location) {
|
|
18030
|
+
if (new URLSearchParams(location.search).get("enrollment") === "success" && getWholeSeriesCheckoutSessionId(location)) return "verifying-payment";
|
|
18031
|
+
return runs.length === 1 ? "enter-details" : "select-run";
|
|
17046
18032
|
}
|
|
17047
|
-
function
|
|
17048
|
-
const
|
|
17049
|
-
|
|
17050
|
-
|
|
18033
|
+
function useWholeSeriesRegistrationSelection(props, location = window.location) {
|
|
18034
|
+
const scopeSnapshot = JSON.stringify({
|
|
18035
|
+
runs: props.runs ?? [],
|
|
18036
|
+
subject: props.subject ?? null
|
|
18037
|
+
});
|
|
18038
|
+
const stableScope = useRef(null);
|
|
18039
|
+
if (stableScope.current?.snapshot !== scopeSnapshot) stableScope.current = {
|
|
18040
|
+
snapshot: scopeSnapshot,
|
|
18041
|
+
runs: selectScopedRuns(props)
|
|
18042
|
+
};
|
|
18043
|
+
const scopedRuns = stableScope.current.runs;
|
|
18044
|
+
const [step, setStep] = useState(() => initialStep(scopedRuns, location));
|
|
18045
|
+
const [selectedRunId, setSelectedRunId] = useState(scopedRuns.length === 1 ? scopedRuns[0]?.eventSeriesId ?? null : null);
|
|
18046
|
+
const selectedRun = useMemo(() => scopedRuns.find((run) => run.eventSeriesId === selectedRunId) ?? (scopedRuns.length === 1 ? scopedRuns[0] ?? null : null), [scopedRuns, selectedRunId]);
|
|
17051
18047
|
const [selectedPricingOptionId, setSelectedPricingOptionId] = useState(null);
|
|
17052
18048
|
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState("");
|
|
17053
18049
|
const goToStep = useCallback((nextStep) => {
|
|
17054
18050
|
setStep(nextStep);
|
|
17055
18051
|
}, []);
|
|
17056
|
-
const
|
|
17057
|
-
|
|
18052
|
+
const chooseRun = useCallback((run) => {
|
|
18053
|
+
setSelectedRunId(run.eventSeriesId);
|
|
17058
18054
|
}, []);
|
|
17059
18055
|
const choosePricingOption = useCallback((pricingOptionId) => {
|
|
17060
18056
|
setSelectedPricingOptionId(pricingOptionId);
|
|
@@ -17062,36 +18058,36 @@ function useCourseRegistrationSelection(props) {
|
|
|
17062
18058
|
const changeSlidingAmount = useCallback((amount) => {
|
|
17063
18059
|
setSelectedSlidingAmountInput(amount);
|
|
17064
18060
|
}, []);
|
|
17065
|
-
const
|
|
17066
|
-
|
|
18061
|
+
const selectedRunPricing = useMemo(() => selectedRun ? resolveWholeSeriesPricingState(selectedRun, selectedPricingOptionId, parseCurrencyInputToCents(selectedSlidingAmountInput)) : null, [
|
|
18062
|
+
selectedRun,
|
|
17067
18063
|
selectedPricingOptionId,
|
|
17068
18064
|
selectedSlidingAmountInput
|
|
17069
18065
|
]);
|
|
17070
18066
|
useEffect(() => {
|
|
17071
|
-
if (!
|
|
18067
|
+
if (!selectedRun) {
|
|
17072
18068
|
setSelectedPricingOptionId(null);
|
|
17073
18069
|
setSelectedSlidingAmountInput("");
|
|
17074
18070
|
return;
|
|
17075
18071
|
}
|
|
17076
|
-
const selection =
|
|
18072
|
+
const selection = defaultWholeSeriesPricingSelection(resolveWholeSeriesPricingState(selectedRun, null), selectedPricingOptionId);
|
|
17077
18073
|
setSelectedPricingOptionId(selection.pricingOptionId);
|
|
17078
18074
|
setSelectedSlidingAmountInput(selection.slidingAmountInput);
|
|
17079
|
-
}, [
|
|
18075
|
+
}, [selectedRun?.eventSeriesId]);
|
|
17080
18076
|
return {
|
|
17081
|
-
|
|
18077
|
+
scopedRuns,
|
|
17082
18078
|
step,
|
|
17083
18079
|
goToStep,
|
|
17084
|
-
|
|
17085
|
-
|
|
18080
|
+
selectedRun,
|
|
18081
|
+
chooseRun,
|
|
17086
18082
|
selectedPricingOptionId,
|
|
17087
18083
|
choosePricingOption,
|
|
17088
18084
|
selectedSlidingAmountInput,
|
|
17089
18085
|
changeSlidingAmount,
|
|
17090
|
-
|
|
18086
|
+
selectedRunPricing
|
|
17091
18087
|
};
|
|
17092
18088
|
}
|
|
17093
18089
|
//#endregion
|
|
17094
|
-
//#region ../blocks/src/system/runtime/nodes/
|
|
18090
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesPaymentVerification.ts
|
|
17095
18091
|
function applyTerminalStatus(status, setters) {
|
|
17096
18092
|
if (status === "enrolled" || status === "completed") {
|
|
17097
18093
|
setters.setEnrollmentResult({
|
|
@@ -17113,7 +18109,7 @@ function applyTerminalStatus(status, setters) {
|
|
|
17113
18109
|
setters.setStep("error");
|
|
17114
18110
|
return true;
|
|
17115
18111
|
}
|
|
17116
|
-
async function
|
|
18112
|
+
async function pollWholeSeriesRegistrationStatus(api, sessionId, setters, isCancelled) {
|
|
17117
18113
|
const startedAt = Date.now();
|
|
17118
18114
|
while (!isCancelled()) {
|
|
17119
18115
|
try {
|
|
@@ -17134,21 +18130,21 @@ async function pollCourseRegistrationStatus(api, sessionId, setters, isCancelled
|
|
|
17134
18130
|
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
17135
18131
|
}
|
|
17136
18132
|
}
|
|
17137
|
-
function
|
|
18133
|
+
function useWholeSeriesPaymentVerification(api, setters, anchorId = WHOLE_SERIES_REGISTRATION_ANCHOR_ID, location = window.location) {
|
|
17138
18134
|
useEffect(() => {
|
|
17139
18135
|
let cancelled = false;
|
|
17140
|
-
const enrollment = new URLSearchParams(
|
|
17141
|
-
const sessionId =
|
|
18136
|
+
const enrollment = new URLSearchParams(location.search).get("enrollment");
|
|
18137
|
+
const sessionId = getWholeSeriesCheckoutSessionId(location);
|
|
17142
18138
|
if (enrollment === "cancelled") {
|
|
17143
|
-
scrollToBlock(
|
|
18139
|
+
scrollToBlock(anchorId);
|
|
17144
18140
|
setters.setErrorMessage("Payment was cancelled. You can try again.");
|
|
17145
18141
|
setters.setStep("error");
|
|
17146
18142
|
return;
|
|
17147
18143
|
}
|
|
17148
18144
|
if (enrollment !== "success" || !sessionId) return;
|
|
17149
|
-
scrollToBlock(
|
|
18145
|
+
scrollToBlock(anchorId);
|
|
17150
18146
|
setters.setStep("verifying-payment");
|
|
17151
|
-
|
|
18147
|
+
pollWholeSeriesRegistrationStatus(api, sessionId, setters, () => cancelled);
|
|
17152
18148
|
return () => {
|
|
17153
18149
|
cancelled = true;
|
|
17154
18150
|
};
|
|
@@ -17156,11 +18152,13 @@ function useCoursePaymentVerification(api, setters) {
|
|
|
17156
18152
|
api,
|
|
17157
18153
|
setters.setEnrollmentResult,
|
|
17158
18154
|
setters.setErrorMessage,
|
|
17159
|
-
setters.setStep
|
|
18155
|
+
setters.setStep,
|
|
18156
|
+
anchorId,
|
|
18157
|
+
location
|
|
17160
18158
|
]);
|
|
17161
18159
|
}
|
|
17162
18160
|
//#endregion
|
|
17163
|
-
//#region ../blocks/src/system/runtime/nodes/
|
|
18161
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationActions.ts
|
|
17164
18162
|
function blocked(message, setters) {
|
|
17165
18163
|
setters.setErrorMessage(message);
|
|
17166
18164
|
setters.setStep("error");
|
|
@@ -17170,16 +18168,17 @@ function blocked(message, setters) {
|
|
|
17170
18168
|
};
|
|
17171
18169
|
}
|
|
17172
18170
|
function validateSubmission(state, setters) {
|
|
17173
|
-
if (!state.
|
|
18171
|
+
if (!state.selectedRun) return {
|
|
17174
18172
|
kind: "blocked",
|
|
17175
18173
|
message: "Choose an available set of dates to continue."
|
|
17176
18174
|
};
|
|
17177
18175
|
const errors = validateFormData$1(state.formData);
|
|
18176
|
+
if (state.selectedRun.consent && state.formData.consentAccepted !== true) errors.consentAccepted = "Please read and accept the agreement before continuing.";
|
|
17178
18177
|
setters.setErrors(errors);
|
|
17179
18178
|
if (Object.keys(errors).length > 0) return { kind: "validation-failed" };
|
|
17180
|
-
const pricingMessage =
|
|
18179
|
+
const pricingMessage = getMissingWholeSeriesPricingSelectionMessage(state.pricing);
|
|
17181
18180
|
if (pricingMessage) return blocked(pricingMessage, setters);
|
|
17182
|
-
if (!state.hasClaim && state.eligibility?.isFull && !state.eligibility.canJoinWaitlist) return blocked(state.eligibility.reason ?? "This
|
|
18181
|
+
if (!state.hasClaim && state.eligibility?.isFull && !state.eligibility.canJoinWaitlist) return blocked(state.eligibility.reason ?? "This run is fully booked.", setters);
|
|
17183
18182
|
if (isSpamProtectionEnabled() && !state.altchaSolution) return blocked("Please complete the verification check.", setters);
|
|
17184
18183
|
return null;
|
|
17185
18184
|
}
|
|
@@ -17192,12 +18191,13 @@ function enrollmentPayload(state, payment) {
|
|
|
17192
18191
|
}
|
|
17193
18192
|
function registrantPayload(state) {
|
|
17194
18193
|
return {
|
|
17195
|
-
eventSeriesId: state.
|
|
17196
|
-
...
|
|
18194
|
+
eventSeriesId: state.selectedRun.eventSeriesId,
|
|
18195
|
+
...buildWholeSeriesPricingOptionPayload(state.pricing),
|
|
17197
18196
|
email: state.formData.email.trim().toLowerCase(),
|
|
17198
18197
|
name: state.formData.name.trim(),
|
|
17199
18198
|
phone: state.formData.phone.trim() || void 0,
|
|
17200
18199
|
formData: { notes: state.formData.notes.trim() || void 0 },
|
|
18200
|
+
consentAccepted: state.formData.consentAccepted,
|
|
17201
18201
|
altchaSolution: state.altchaSolution,
|
|
17202
18202
|
claimToken: state.claimToken ?? void 0
|
|
17203
18203
|
};
|
|
@@ -17226,7 +18226,7 @@ async function enroll(state, setters, payment) {
|
|
|
17226
18226
|
async function checkout(state, setters) {
|
|
17227
18227
|
setters.setStep("submitting");
|
|
17228
18228
|
try {
|
|
17229
|
-
const urls = buildCheckoutReturnUrls("enrollment",
|
|
18229
|
+
const urls = buildCheckoutReturnUrls("enrollment", state.options.anchorId ?? "event-registration");
|
|
17230
18230
|
const result = await state.api.createWholeSeriesCheckout({
|
|
17231
18231
|
...registrantPayload(state),
|
|
17232
18232
|
discountCode: state.discountCode.trim() || void 0,
|
|
@@ -17261,10 +18261,10 @@ async function checkout(state, setters) {
|
|
|
17261
18261
|
}
|
|
17262
18262
|
async function submitDetails(state, setters) {
|
|
17263
18263
|
const invalid = validateSubmission(state, setters);
|
|
17264
|
-
if (invalid || !state.
|
|
18264
|
+
if (invalid || !state.selectedRun) return invalid ?? { kind: "validation-failed" };
|
|
17265
18265
|
if (state.eligibility?.canJoinWaitlist) return enroll(state, setters, { method: "free" });
|
|
17266
18266
|
const requiresPayment = state.pricing?.selectedRequiresPayment ?? false;
|
|
17267
|
-
const canUseMembership = requiresPayment && state.
|
|
18267
|
+
const canUseMembership = requiresPayment && state.selectedRun.acceptsMemberships && state.portalAuthState === "authenticated" && state.eligibleMemberships.length > 0;
|
|
17268
18268
|
if (requiresPayment && canUseMembership) {
|
|
17269
18269
|
setters.setStep("select-payment");
|
|
17270
18270
|
return { kind: "state-updated" };
|
|
@@ -17274,7 +18274,7 @@ async function submitDetails(state, setters) {
|
|
|
17274
18274
|
}
|
|
17275
18275
|
async function continuePayment(state, setters) {
|
|
17276
18276
|
const invalid = validateSubmission(state, setters);
|
|
17277
|
-
if (invalid || !state.
|
|
18277
|
+
if (invalid || !state.selectedRun) return invalid ?? { kind: "validation-failed" };
|
|
17278
18278
|
if (!state.pricing?.selectedRequiresPayment) {
|
|
17279
18279
|
setters.setStep("enter-details");
|
|
17280
18280
|
return { kind: "state-updated" };
|
|
@@ -17289,7 +18289,7 @@ async function continuePayment(state, setters) {
|
|
|
17289
18289
|
}
|
|
17290
18290
|
return checkout(selectedState, setters);
|
|
17291
18291
|
}
|
|
17292
|
-
function
|
|
18292
|
+
function useWholeSeriesRegistrationActions(state, setStep) {
|
|
17293
18293
|
const [errors, setErrors] = useState({});
|
|
17294
18294
|
const [enrollmentResult, setEnrollmentResult] = useState(null);
|
|
17295
18295
|
const [errorMessage, setErrorMessage] = useState("");
|
|
@@ -17316,14 +18316,15 @@ function useCourseRegistrationActions(state, setStep) {
|
|
|
17316
18316
|
};
|
|
17317
18317
|
}
|
|
17318
18318
|
//#endregion
|
|
17319
|
-
//#region ../blocks/src/system/runtime/nodes/
|
|
18319
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationPortal.ts
|
|
17320
18320
|
const EMPTY_FORM = {
|
|
17321
18321
|
name: "",
|
|
17322
18322
|
email: "",
|
|
17323
18323
|
phone: "",
|
|
17324
|
-
notes: ""
|
|
18324
|
+
notes: "",
|
|
18325
|
+
consentAccepted: false
|
|
17325
18326
|
};
|
|
17326
|
-
function
|
|
18327
|
+
function useWholeSeriesRegistrationPortal(api) {
|
|
17327
18328
|
const [formData, setFormData] = useState(EMPTY_FORM);
|
|
17328
18329
|
const [portalAuthState, setPortalAuthState] = useState("checking");
|
|
17329
18330
|
const updateFormData = useCallback((updater) => {
|
|
@@ -17359,19 +18360,19 @@ function useCourseRegistrationPortal(api) {
|
|
|
17359
18360
|
};
|
|
17360
18361
|
}
|
|
17361
18362
|
//#endregion
|
|
17362
|
-
//#region ../blocks/src/system/runtime/nodes/
|
|
17363
|
-
function
|
|
18363
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesWaitlistSelection.ts
|
|
18364
|
+
function useWholeSeriesWaitlistSelection(input) {
|
|
17364
18365
|
useEffect(() => {
|
|
17365
18366
|
const claim = input.waitlistClaim.claim;
|
|
17366
18367
|
if (!claim || claim.subject.kind !== "whole_series") return;
|
|
17367
18368
|
const eventSeriesId = claim.subject.eventSeriesId;
|
|
17368
|
-
const
|
|
17369
|
-
if (!
|
|
17370
|
-
input.reportError("This waitlist claim is for a different
|
|
18369
|
+
const run = input.scopedRuns.find((candidate) => candidate.eventSeriesId === eventSeriesId);
|
|
18370
|
+
if (!run) {
|
|
18371
|
+
input.reportError("This waitlist claim is for a different run.");
|
|
17371
18372
|
input.goToStep("error");
|
|
17372
18373
|
return;
|
|
17373
18374
|
}
|
|
17374
|
-
input.
|
|
18375
|
+
input.chooseRun(run);
|
|
17375
18376
|
input.updateFormData((current) => ({
|
|
17376
18377
|
...current,
|
|
17377
18378
|
email: claim.prefill.email,
|
|
@@ -17379,12 +18380,12 @@ function useCourseWaitlistSelection(input) {
|
|
|
17379
18380
|
phone: claim.prefill.phone ?? "",
|
|
17380
18381
|
notes: claim.prefill.notes ?? ""
|
|
17381
18382
|
}));
|
|
17382
|
-
if (input.step === "select-
|
|
18383
|
+
if (input.step === "select-run") input.goToStep("enter-details");
|
|
17383
18384
|
}, [
|
|
17384
|
-
input.
|
|
18385
|
+
input.chooseRun,
|
|
17385
18386
|
input.goToStep,
|
|
17386
18387
|
input.reportError,
|
|
17387
|
-
input.
|
|
18388
|
+
input.scopedRuns,
|
|
17388
18389
|
input.step,
|
|
17389
18390
|
input.updateFormData,
|
|
17390
18391
|
input.waitlistClaim.claim
|
|
@@ -17401,40 +18402,48 @@ function useCourseWaitlistSelection(input) {
|
|
|
17401
18402
|
]);
|
|
17402
18403
|
}
|
|
17403
18404
|
//#endregion
|
|
17404
|
-
//#region ../blocks/src/system/runtime/nodes/
|
|
17405
|
-
function
|
|
18405
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationWizard.ts
|
|
18406
|
+
function useWholeSeriesRegistrationWizard(props, options = {}) {
|
|
18407
|
+
return useWholeSeriesRegistrationWizardWithDeps(wholeSeriesRegistrationWizardDeps, props, options);
|
|
18408
|
+
}
|
|
18409
|
+
const wholeSeriesRegistrationWizardDeps = { readLocation: () => ({
|
|
18410
|
+
search: window.location.search,
|
|
18411
|
+
hash: window.location.hash
|
|
18412
|
+
}) };
|
|
18413
|
+
function useWholeSeriesRegistrationWizardWithDeps(deps, props, options = {}) {
|
|
17406
18414
|
const api = useBlockApi();
|
|
17407
|
-
const
|
|
17408
|
-
const
|
|
17409
|
-
const
|
|
18415
|
+
const [location] = useState(deps.readLocation);
|
|
18416
|
+
const selection = useWholeSeriesRegistrationSelection(props, location);
|
|
18417
|
+
const portal = useWholeSeriesRegistrationPortal(api);
|
|
18418
|
+
const waitlistClaim = useWaitlistClaimForToken(new URLSearchParams(location.search).get("waitlist_claim")?.trim() || null);
|
|
17410
18419
|
const [bookingMode, setBookingMode] = useState(null);
|
|
17411
18420
|
const [altchaSolution, setAltchaSolution] = useState(null);
|
|
17412
|
-
const eligibility =
|
|
18421
|
+
const eligibility = useWholeSeriesEligibility({
|
|
17413
18422
|
api,
|
|
17414
|
-
|
|
17415
|
-
hasPaidSelection: selection.
|
|
18423
|
+
selectedRun: selection.selectedRun,
|
|
18424
|
+
hasPaidSelection: selection.selectedRunPricing?.hasPaidSelection ?? false,
|
|
17416
18425
|
portalAuthState: portal.portalAuthState,
|
|
17417
18426
|
waitlistClaimToken: waitlistClaim.token
|
|
17418
18427
|
});
|
|
17419
18428
|
const discountUi = useDiscountCodeUi({
|
|
17420
18429
|
api,
|
|
17421
|
-
discountContext: useMemo(() => selection.
|
|
18430
|
+
discountContext: useMemo(() => selection.selectedRun && selection.selectedRunPricing?.selectedRequiresPayment && eligibility.paymentChoice === "checkout" ? {
|
|
17422
18431
|
type: "whole_series",
|
|
17423
|
-
eventSeriesId: selection.
|
|
18432
|
+
eventSeriesId: selection.selectedRun.eventSeriesId
|
|
17424
18433
|
} : null, [
|
|
17425
18434
|
eligibility.paymentChoice,
|
|
17426
|
-
selection.
|
|
17427
|
-
selection.
|
|
18435
|
+
selection.selectedRun,
|
|
18436
|
+
selection.selectedRunPricing?.selectedRequiresPayment
|
|
17428
18437
|
]),
|
|
17429
|
-
subtotalCents: selection.
|
|
18438
|
+
subtotalCents: selection.selectedRunPricing?.selectedPriceAmount ?? void 0
|
|
17430
18439
|
});
|
|
17431
|
-
const actions =
|
|
18440
|
+
const actions = useWholeSeriesRegistrationActions({
|
|
17432
18441
|
api,
|
|
17433
|
-
|
|
17434
|
-
pricing: selection.
|
|
18442
|
+
selectedRun: selection.selectedRun,
|
|
18443
|
+
pricing: selection.selectedRunPricing,
|
|
17435
18444
|
formData: portal.formData,
|
|
17436
18445
|
portalAuthState: portal.portalAuthState,
|
|
17437
|
-
eligibility: eligibility.
|
|
18446
|
+
eligibility: eligibility.runEligibility,
|
|
17438
18447
|
eligibleMemberships: eligibility.eligibleMemberships,
|
|
17439
18448
|
paymentChoice: eligibility.paymentChoice,
|
|
17440
18449
|
selectedMembershipId: eligibility.selectedMembershipId,
|
|
@@ -17444,14 +18453,16 @@ function useCourseRegistrationWizard(props, options = {}) {
|
|
|
17444
18453
|
discountCode: discountUi.discountCode,
|
|
17445
18454
|
options
|
|
17446
18455
|
}, selection.goToStep);
|
|
17447
|
-
|
|
18456
|
+
useWholeSeriesRegistrationEffects({
|
|
17448
18457
|
api,
|
|
17449
18458
|
actions,
|
|
17450
18459
|
portal,
|
|
17451
18460
|
selection,
|
|
17452
|
-
waitlistClaim
|
|
18461
|
+
waitlistClaim,
|
|
18462
|
+
anchorId: options.anchorId ?? "event-registration",
|
|
18463
|
+
location
|
|
17453
18464
|
});
|
|
17454
|
-
return
|
|
18465
|
+
return buildWholeSeriesRegistrationWizardResult({
|
|
17455
18466
|
api,
|
|
17456
18467
|
selection,
|
|
17457
18468
|
portal,
|
|
@@ -17459,10 +18470,10 @@ function useCourseRegistrationWizard(props, options = {}) {
|
|
|
17459
18470
|
actions,
|
|
17460
18471
|
discountUi,
|
|
17461
18472
|
waitlistClaim,
|
|
17462
|
-
view:
|
|
17463
|
-
|
|
17464
|
-
|
|
17465
|
-
pricing: selection.
|
|
18473
|
+
view: deriveWholeSeriesRegistrationViewState({
|
|
18474
|
+
scopedRuns: selection.scopedRuns,
|
|
18475
|
+
selectedRun: selection.selectedRun,
|
|
18476
|
+
pricing: selection.selectedRunPricing,
|
|
17466
18477
|
portalAuthState: portal.portalAuthState,
|
|
17467
18478
|
eligibleMembershipCount: eligibility.eligibleMemberships.length,
|
|
17468
18479
|
bookingMode,
|
|
@@ -17472,26 +18483,27 @@ function useCourseRegistrationWizard(props, options = {}) {
|
|
|
17472
18483
|
bookingMode,
|
|
17473
18484
|
setBookingMode,
|
|
17474
18485
|
altchaSolution,
|
|
17475
|
-
setAltchaSolution
|
|
18486
|
+
setAltchaSolution,
|
|
18487
|
+
anchorId: options.anchorId ?? "event-registration"
|
|
17476
18488
|
});
|
|
17477
18489
|
}
|
|
17478
|
-
function
|
|
17479
|
-
|
|
18490
|
+
function useWholeSeriesRegistrationEffects(input) {
|
|
18491
|
+
useWholeSeriesPaymentVerification(input.api, {
|
|
17480
18492
|
setStep: input.selection.goToStep,
|
|
17481
18493
|
setErrorMessage: input.actions.reportError,
|
|
17482
18494
|
setEnrollmentResult: input.actions.recordEnrollmentResult
|
|
17483
|
-
});
|
|
17484
|
-
|
|
18495
|
+
}, input.anchorId, input.location);
|
|
18496
|
+
useWholeSeriesWaitlistSelection({
|
|
17485
18497
|
waitlistClaim: input.waitlistClaim,
|
|
17486
|
-
|
|
18498
|
+
scopedRuns: input.selection.scopedRuns,
|
|
17487
18499
|
step: input.selection.step,
|
|
17488
18500
|
goToStep: input.selection.goToStep,
|
|
17489
|
-
|
|
18501
|
+
chooseRun: input.selection.chooseRun,
|
|
17490
18502
|
updateFormData: input.portal.updateFormData,
|
|
17491
18503
|
reportError: input.actions.reportError
|
|
17492
18504
|
});
|
|
17493
18505
|
}
|
|
17494
|
-
function
|
|
18506
|
+
function buildWholeSeriesRegistrationWizardResult(parts) {
|
|
17495
18507
|
const handleBookingModeChange = (mode) => {
|
|
17496
18508
|
parts.setBookingMode(mode);
|
|
17497
18509
|
parts.eligibility.choosePaymentChoice(mode === "membership" ? "membership" : "checkout");
|
|
@@ -17515,30 +18527,30 @@ function buildCourseRegistrationWizardResult(parts) {
|
|
|
17515
18527
|
manualCodeEntryAllowed: parts.discountUi.manualCodeEntryAllowed,
|
|
17516
18528
|
discountsAvailableLoading: parts.discountUi.discountsAvailableLoading,
|
|
17517
18529
|
...parts.view,
|
|
17518
|
-
|
|
17519
|
-
parts.selection.
|
|
18530
|
+
handleRunSelect: (run) => {
|
|
18531
|
+
parts.selection.chooseRun(run);
|
|
17520
18532
|
parts.selection.goToStep("enter-details");
|
|
17521
18533
|
},
|
|
17522
18534
|
handleRetry: () => {
|
|
17523
|
-
parts.selection.goToStep(parts.selection.
|
|
18535
|
+
parts.selection.goToStep(parts.selection.scopedRuns.length === 1 ? "enter-details" : "select-run");
|
|
17524
18536
|
parts.actions.reportError("");
|
|
17525
18537
|
},
|
|
17526
18538
|
handleBookingModeChange,
|
|
17527
|
-
handleLogout: parts.portal.portalAuthState === "authenticated" ? () => logoutPortal(
|
|
17528
|
-
|
|
18539
|
+
handleLogout: parts.portal.portalAuthState === "authenticated" ? () => logoutPortal(parts.anchorId) : void 0,
|
|
18540
|
+
selectedRunPricingPayload: buildWholeSeriesPricingOptionPayload(parts.selection.selectedRunPricing)
|
|
17529
18541
|
};
|
|
17530
18542
|
}
|
|
17531
18543
|
//#endregion
|
|
17532
|
-
//#region ../blocks/src/system/runtime/nodes/
|
|
18544
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/whole-series-registration.headless.planning.ts
|
|
17533
18545
|
const STEP_IDS = {
|
|
17534
|
-
"select-
|
|
18546
|
+
"select-run": "select-run",
|
|
17535
18547
|
"enter-details": "enter-details",
|
|
17536
18548
|
"booking-mode": "select-booking-method",
|
|
17537
18549
|
"select-payment": "select-payment"
|
|
17538
18550
|
};
|
|
17539
18551
|
function toPublicStepId(step) {
|
|
17540
18552
|
switch (step) {
|
|
17541
|
-
case "select-
|
|
18553
|
+
case "select-run":
|
|
17542
18554
|
case "enter-details":
|
|
17543
18555
|
case "booking-mode":
|
|
17544
18556
|
case "select-payment": return STEP_IDS[step];
|
|
@@ -17598,7 +18610,7 @@ function resolveWholeSeriesRegistrationStatus(wizard) {
|
|
|
17598
18610
|
tag: "error",
|
|
17599
18611
|
message: wizard.errorMessage
|
|
17600
18612
|
};
|
|
17601
|
-
case "select-
|
|
18613
|
+
case "select-run":
|
|
17602
18614
|
case "enter-details":
|
|
17603
18615
|
case "booking-mode":
|
|
17604
18616
|
case "select-payment": return { tag: "ready" };
|
|
@@ -17632,7 +18644,7 @@ function resolveWholeSeriesRegistrationView(wizard) {
|
|
|
17632
18644
|
kind: "error",
|
|
17633
18645
|
message: "Waitlist registration completed without a result."
|
|
17634
18646
|
};
|
|
17635
|
-
case "select-
|
|
18647
|
+
case "select-run":
|
|
17636
18648
|
case "enter-details":
|
|
17637
18649
|
case "booking-mode":
|
|
17638
18650
|
case "select-payment":
|
|
@@ -17669,7 +18681,7 @@ function resolveWholeSeriesPaymentSelection(input) {
|
|
|
17669
18681
|
}
|
|
17670
18682
|
//#endregion
|
|
17671
18683
|
//#region ../blocks/src/system/runtime/hooks/useHeadlessWholeSeriesRegistrationFlow.ts
|
|
17672
|
-
const wholeSeriesRegistrationControllerDeps = {
|
|
18684
|
+
const wholeSeriesRegistrationControllerDeps = { useWholeSeriesRegistrationWizard };
|
|
17673
18685
|
function createWholeSeriesRegistrationBlockApiConfig(input) {
|
|
17674
18686
|
return {
|
|
17675
18687
|
baseUrl: input.apiBaseUrl,
|
|
@@ -17695,8 +18707,8 @@ function useHeadlessWholeSeriesRegistrationFlow(options) {
|
|
|
17695
18707
|
return useWholeSeriesRegistrationControllerWithDeps(options, wholeSeriesRegistrationControllerDeps);
|
|
17696
18708
|
}
|
|
17697
18709
|
function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
17698
|
-
const wizard = deps.
|
|
17699
|
-
|
|
18710
|
+
const wizard = deps.useWholeSeriesRegistrationWizard({
|
|
18711
|
+
runs: (options.runs ?? []).map(toPublicWholeSeriesOffering),
|
|
17700
18712
|
subject: options.subject ?? null
|
|
17701
18713
|
}, { onCheckoutRedirect: () => {} });
|
|
17702
18714
|
const steps = useMemo(() => deriveWholeSeriesRegistrationSteps({
|
|
@@ -17704,11 +18716,11 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17704
18716
|
step: wizard.step
|
|
17705
18717
|
}), [wizard.step, wizard.wizardSteps]);
|
|
17706
18718
|
const currentStep = steps.find((step) => step.state === "active") ?? null;
|
|
17707
|
-
const pricingSelection = resolveWholeSeriesPricingSelection(wizard.
|
|
18719
|
+
const pricingSelection = resolveWholeSeriesPricingSelection(wizard.selectedRunPricing);
|
|
17708
18720
|
const paymentSelection = resolveWholeSeriesPaymentSelection({
|
|
17709
18721
|
paymentChoice: wizard.paymentChoice,
|
|
17710
18722
|
selectedMembershipId: wizard.selectedMembershipId,
|
|
17711
|
-
required: wizard.
|
|
18723
|
+
required: wizard.selectedRunPricing?.selectedRequiresPayment ?? false
|
|
17712
18724
|
});
|
|
17713
18725
|
const updateRegistrant = useCallback((values) => wizard.updateFormData(values), [wizard]);
|
|
17714
18726
|
const setSlidingAmountCents = useCallback((amount) => {
|
|
@@ -17734,8 +18746,8 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17734
18746
|
const blocked = resolveActionBlocker(wizard);
|
|
17735
18747
|
if (blocked) return blocked;
|
|
17736
18748
|
switch (wizard.step) {
|
|
17737
|
-
case "select-
|
|
17738
|
-
if (!wizard.
|
|
18749
|
+
case "select-run":
|
|
18750
|
+
if (!wizard.selectedRun) return {
|
|
17739
18751
|
ok: false,
|
|
17740
18752
|
reason: "blocked",
|
|
17741
18753
|
message: "Choose an available set of dates to continue."
|
|
@@ -17765,7 +18777,7 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17765
18777
|
const back = useCallback(() => {
|
|
17766
18778
|
switch (wizard.step) {
|
|
17767
18779
|
case "enter-details":
|
|
17768
|
-
if (!wizard.
|
|
18780
|
+
if (!wizard.hasPreSelectedRun) wizard.goToStep("select-run");
|
|
17769
18781
|
return;
|
|
17770
18782
|
case "booking-mode":
|
|
17771
18783
|
wizard.goToStep("enter-details");
|
|
@@ -17773,7 +18785,7 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17773
18785
|
case "select-payment":
|
|
17774
18786
|
wizard.goToStep(wizard.canUseMembership ? "booking-mode" : "enter-details");
|
|
17775
18787
|
return;
|
|
17776
|
-
case "select-
|
|
18788
|
+
case "select-run":
|
|
17777
18789
|
case "submitting":
|
|
17778
18790
|
case "redirecting":
|
|
17779
18791
|
case "verifying-payment":
|
|
@@ -17785,7 +18797,7 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17785
18797
|
}
|
|
17786
18798
|
}, [wizard]);
|
|
17787
18799
|
const payment = {
|
|
17788
|
-
required: wizard.
|
|
18800
|
+
required: wizard.selectedRunPricing?.selectedRequiresPayment ?? false,
|
|
17789
18801
|
selection: paymentSelection,
|
|
17790
18802
|
canUseMembership: wizard.canUseMembership,
|
|
17791
18803
|
eligibleMemberships: wizard.eligibleMemberships.map((membership) => ({
|
|
@@ -17795,7 +18807,7 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17795
18807
|
eligibility: wizard.eligibilityLoading ? { tag: "loading" } : wizard.eligibilityError ? {
|
|
17796
18808
|
tag: "error",
|
|
17797
18809
|
message: wizard.eligibilityError
|
|
17798
|
-
} : wizard.
|
|
18810
|
+
} : wizard.runEligibility || wizard.portalAuthState !== "checking" ? { tag: "loaded" } : { tag: "idle" }
|
|
17799
18811
|
};
|
|
17800
18812
|
const spamProtection = wizard.showSpamProtection ? {
|
|
17801
18813
|
enabled: true,
|
|
@@ -17806,13 +18818,13 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17806
18818
|
},
|
|
17807
18819
|
solution: wizard.altchaSolution
|
|
17808
18820
|
} : { enabled: false };
|
|
17809
|
-
const selectedRun = wizard.
|
|
17810
|
-
const isFull = wizard.
|
|
18821
|
+
const selectedRun = wizard.selectedRun;
|
|
18822
|
+
const isFull = wizard.runEligibility?.isFull ?? (selectedRun?.availableSpots !== null && selectedRun?.availableSpots !== void 0 ? selectedRun.availableSpots <= 0 : false);
|
|
17811
18823
|
return {
|
|
17812
18824
|
status: resolveWholeSeriesRegistrationStatus(wizard),
|
|
17813
18825
|
view: resolveWholeSeriesRegistrationView({
|
|
17814
18826
|
step: wizard.step,
|
|
17815
|
-
scopedRunsCount: wizard.
|
|
18827
|
+
scopedRunsCount: wizard.scopedRuns.length,
|
|
17816
18828
|
selectedRun,
|
|
17817
18829
|
enrollmentResult: wizard.enrollmentResult,
|
|
17818
18830
|
errorMessage: wizard.errorMessage
|
|
@@ -17820,10 +18832,10 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17820
18832
|
steps,
|
|
17821
18833
|
currentStep,
|
|
17822
18834
|
runs: {
|
|
17823
|
-
items: (options.runs ?? []).map((run) => toWholeSeriesRegistrationRun(
|
|
17824
|
-
scoped: wizard.
|
|
18835
|
+
items: (options.runs ?? []).map((run) => toWholeSeriesRegistrationRun(toPublicWholeSeriesOffering(run))),
|
|
18836
|
+
scoped: wizard.scopedRuns.map(toWholeSeriesRegistrationRun),
|
|
17825
18837
|
selected: selectedRun ? toWholeSeriesRegistrationRun(selectedRun) : null,
|
|
17826
|
-
hasPreSelectedRun: wizard.
|
|
18838
|
+
hasPreSelectedRun: wizard.hasPreSelectedRun,
|
|
17827
18839
|
subject: options.subject ?? null
|
|
17828
18840
|
},
|
|
17829
18841
|
registrant: {
|
|
@@ -17831,7 +18843,7 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17831
18843
|
errors: wizard.errors
|
|
17832
18844
|
},
|
|
17833
18845
|
pricing: {
|
|
17834
|
-
...toWholeSeriesRegistrationPricing(wizard.
|
|
18846
|
+
...toWholeSeriesRegistrationPricing(wizard.selectedRunPricing),
|
|
17835
18847
|
selectedOptionId: wizard.selectedPricingOptionId,
|
|
17836
18848
|
selection: pricingSelection
|
|
17837
18849
|
},
|
|
@@ -17847,8 +18859,8 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17847
18859
|
enrollmentOpen: selectedRun?.enrollmentOpen ?? false,
|
|
17848
18860
|
availableSpots: selectedRun?.availableSpots ?? null,
|
|
17849
18861
|
isFull,
|
|
17850
|
-
canJoinWaitlist: wizard.
|
|
17851
|
-
message: wizard.
|
|
18862
|
+
canJoinWaitlist: wizard.runEligibility?.canJoinWaitlist ?? false,
|
|
18863
|
+
message: wizard.runEligibility?.reason ?? null
|
|
17852
18864
|
},
|
|
17853
18865
|
portalAuth: {
|
|
17854
18866
|
state: wizard.portalAuthState,
|
|
@@ -17862,8 +18874,8 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17862
18874
|
},
|
|
17863
18875
|
actions: {
|
|
17864
18876
|
selectRun: (runId) => {
|
|
17865
|
-
const run = wizard.
|
|
17866
|
-
if (run) wizard.
|
|
18877
|
+
const run = wizard.scopedRuns.find((candidate) => candidate.eventSeriesId === runId) ?? null;
|
|
18878
|
+
if (run) wizard.handleRunSelect(run);
|
|
17867
18879
|
},
|
|
17868
18880
|
updateRegistrant,
|
|
17869
18881
|
selectPricingOption: wizard.choosePricingOption,
|
|
@@ -17907,8 +18919,8 @@ function toHeadlessActionResult(result) {
|
|
|
17907
18919
|
};
|
|
17908
18920
|
}
|
|
17909
18921
|
}
|
|
17910
|
-
function
|
|
17911
|
-
const pricing =
|
|
18922
|
+
function toPublicWholeSeriesOffering(run) {
|
|
18923
|
+
const pricing = toWholeSeriesPricing(run.pricing);
|
|
17912
18924
|
return {
|
|
17913
18925
|
eventSeriesId: run.registrationTarget.eventSeriesId,
|
|
17914
18926
|
eventOfferingId: run.eventOfferingId,
|
|
@@ -17916,6 +18928,7 @@ function toPublicCourse(run) {
|
|
|
17916
18928
|
slug: run.slug,
|
|
17917
18929
|
description: run.description,
|
|
17918
18930
|
teamMembers: run.teamMembers ? [...run.teamMembers] : void 0,
|
|
18931
|
+
consent: run.consent,
|
|
17919
18932
|
enrollmentOpen: run.registrationOpen,
|
|
17920
18933
|
pricing,
|
|
17921
18934
|
currency: run.pricing.currency,
|
|
@@ -17933,7 +18946,7 @@ function toPublicCourse(run) {
|
|
|
17933
18946
|
venue: run.venue
|
|
17934
18947
|
};
|
|
17935
18948
|
}
|
|
17936
|
-
function
|
|
18949
|
+
function toWholeSeriesPricing(pricing) {
|
|
17937
18950
|
const common = {
|
|
17938
18951
|
bookingRequirement: pricing.bookingRequirement,
|
|
17939
18952
|
pricingStrategy: pricing.pricingStrategy,
|
|
@@ -18060,8 +19073,8 @@ function resolveWaitlistClaim(wizard) {
|
|
|
18060
19073
|
return { tag: "none" };
|
|
18061
19074
|
}
|
|
18062
19075
|
function resolveActionBlocker(wizard) {
|
|
18063
|
-
if (!wizard.
|
|
18064
|
-
if (!wizard.
|
|
19076
|
+
if (!wizard.selectedRun) return null;
|
|
19077
|
+
if (!wizard.selectedRun.enrollmentOpen) return {
|
|
18065
19078
|
ok: false,
|
|
18066
19079
|
reason: "blocked",
|
|
18067
19080
|
message: "Sign-up is closed."
|
|
@@ -18071,10 +19084,10 @@ function resolveActionBlocker(wizard) {
|
|
|
18071
19084
|
reason: "blocked",
|
|
18072
19085
|
message: "Availability is still being checked."
|
|
18073
19086
|
};
|
|
18074
|
-
if (wizard.
|
|
19087
|
+
if (wizard.runEligibility?.isFull && !wizard.runEligibility.canJoinWaitlist) return {
|
|
18075
19088
|
ok: false,
|
|
18076
19089
|
reason: "blocked",
|
|
18077
|
-
message: wizard.
|
|
19090
|
+
message: wizard.runEligibility.reason ?? "There are no places available."
|
|
18078
19091
|
};
|
|
18079
19092
|
return null;
|
|
18080
19093
|
}
|