@riverbankcms/sdk 0.151.0 → 0.153.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 +52 -0
- package/dist/{EventEmbeddedCheckoutStep-BBHbM22D.mjs → EventEmbeddedCheckoutStep-veN-QiAE.mjs} +10 -9
- package/dist/{PreviewEditorSidebar-BHplI9HE.mjs → PreviewEditorSidebar-jI_4DTZY.mjs} +4 -3
- package/dist/{PreviewEditorUI-DuyN8nsD.mjs → PreviewEditorUI-ORkVZhfu.mjs} +5 -4
- package/dist/{SdkPreviewModeRuntime-CR5ypwxJ.mjs → SdkPreviewModeRuntime-DaNqevI1.mjs} +341 -164
- package/dist/{SiteChromeCustomizeContext-D5t6joF_.mjs → SiteChromeCustomizeContext-CgNuBHC0.mjs} +27124 -39230
- package/dist/ThemedButton-X2UxhW6F.mjs +16525 -0
- package/dist/_dts/ai/src/contracts/proposals.d.ts +52 -52
- package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +2357 -7859
- package/dist/_dts/api/src/bookingOperations.d.ts +5 -3
- package/dist/_dts/api/src/commercePortalEndpoints.d.ts +4 -0
- package/dist/_dts/api/src/communications.d.ts +19 -5
- package/dist/_dts/api/src/endpoints.d.ts +7 -0
- package/dist/_dts/api/src/index.d.ts +1 -1
- package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
- package/dist/_dts/api/src/navigation/types.d.ts +7 -0
- package/dist/_dts/api/src/navigation.d.ts +1 -1
- package/dist/_dts/api/src/publicAppointmentBookingContracts.d.ts +10 -1
- package/dist/_dts/api/src/sdkThemeWire.d.ts +186 -1434
- package/dist/_dts/api/src/shared-contracts.d.ts +10 -0
- package/dist/_dts/api/src/siteAssets.d.ts +1 -0
- package/dist/_dts/api/src/siteInfrastructure.d.ts +2 -1
- package/dist/_dts/api/src/teamMembers.d.ts +2 -27
- package/dist/_dts/block-form/src/widgets/RepeaterField/components/layoutGridDomain.d.ts +3 -13
- package/dist/_dts/blocks/src/contracts/index.d.ts +1 -0
- package/dist/_dts/blocks/src/definitions.d.ts +1 -1
- package/dist/_dts/blocks/src/index.d.ts +2 -0
- package/dist/_dts/blocks/src/lib/media.d.ts +1 -0
- package/dist/_dts/blocks/src/lib/picsum.d.ts +2 -2
- package/dist/_dts/blocks/src/pageRenderPreparation.d.ts +1 -0
- package/dist/_dts/blocks/src/pageRendererContracts.d.ts +2 -1
- package/dist/_dts/blocks/src/primitives/content/utils/sanitizeHref.d.ts +1 -1
- package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +4 -4
- package/dist/_dts/blocks/src/system/blocks/events/eventSelectionFields.d.ts +1 -1
- package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +212 -804
- package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +7 -2
- package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +1 -1
- package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +45 -45
- package/dist/_dts/blocks/src/system/blocks/offerings-preview/model.d.ts +2 -0
- package/dist/_dts/blocks/src/system/blocks/shared/teamMembers.d.ts +4 -7
- package/dist/_dts/blocks/src/system/blocks/team-members.d.ts +2 -2
- package/dist/_dts/blocks/src/system/customize/backgrounds.d.ts +6 -6
- package/dist/_dts/blocks/src/system/fields/backgroundContent.d.ts +377 -1
- package/dist/_dts/blocks/src/system/helpers/backgroundMedia.d.ts +6 -2
- package/dist/_dts/blocks/src/system/helpers/normalizeMailingListBlockContent.d.ts +2 -0
- package/dist/_dts/blocks/src/system/helpers/resolveBackground.d.ts +3 -3
- package/dist/_dts/blocks/src/system/layout/repeaterGrid.d.ts +12 -5
- package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +3 -3
- package/dist/_dts/blocks/src/system/manifest/schema.d.ts +24 -24
- package/dist/_dts/blocks/src/system/manifest/validation.d.ts +2 -0
- package/dist/_dts/blocks/src/system/node/fragments/lookSlot.d.ts +1 -1
- package/dist/_dts/blocks/src/system/registry.d.ts +14 -2
- package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +0 -5
- package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/api/schemas/events.d.ts +971 -0
- package/dist/_dts/blocks/src/system/runtime/api/schemas/waitlist-claims.d.ts +42 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/appointments.d.ts +10 -2
- package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +10 -136
- package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +48 -6
- package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +24 -3
- package/dist/_dts/blocks/src/system/runtime/hooks/useBookingFlowController.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/hooks/useBookingSubmission.state.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.d.ts +5 -1
- package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/lookSurfaces.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/ImageResolveContext.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +50 -202
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +51 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +6 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/carousel.client.hooks.d.ts +6 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/carousel.client.state.d.ts +7 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details/lookPresentation.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details/presentation.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/BookingEntryViews.d.ts +42 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventEmbeddedCheckoutStep.d.ts +4 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationBookingLayer.d.ts +19 -9
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationPayment.d.ts +4 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +24 -9
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizardContent.d.ts +4 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventSelectionStep.d.ts +5 -4
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/GuestDetailsSection.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/PaymentStatusStep.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/SingleTicketEntitlementNote.d.ts +11 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/SuccessStep.d.ts +4 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +5 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/VerifyingTimeoutStep.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/bookingCardDisplay.d.ts +31 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/bookingEntry.d.ts +154 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/bookingFocus.d.ts +12 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.d.ts +9 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/finishedBooking.d.ts +77 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/index.d.ts +0 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/offeringNoun.d.ts +12 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/paymentResponse.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationCompletion.d.ts +33 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationDerivations.d.ts +11 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationDisplay.d.ts +31 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationDraft.state.d.ts +60 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationErrorRecovery.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.d.ts +3 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationStateMachine.d.ts +58 -10
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationSurface.d.ts +17 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +23 -7
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useBookingBarFacts.d.ts +12 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationRecoveryRequest.d.ts +3 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.d.ts +4 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +4 -11
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +1563 -31
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventSourceRecovery.d.ts +2 -12
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/usePaymentStatusRecovery.d.ts +147 -4
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/utils.d.ts +50 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/waitlistClaimRestoration.d.ts +6 -5
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/wizardSteps.d.ts +85 -15
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +53 -8
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CardListItem.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/MonthLookView.d.ts +10 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +290 -882
- package/dist/_dts/blocks/src/system/runtime/nodes/file-download.d.ts +3 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/media.d.ts +22 -90
- package/dist/_dts/blocks/src/system/runtime/nodes/mediaContext.d.ts +69 -0
- package/dist/_dts/blocks/src/system/runtime/shared/bookingPaymentOptionCopy.d.ts +5 -1
- package/dist/_dts/blocks/src/system/runtime/shared/bookingPaymentOptions.d.ts +37 -1
- package/dist/_dts/blocks/src/system/runtime/shared/components/ModalShell.d.ts +9 -2
- package/dist/_dts/blocks/src/system/runtime/shared/components/PaymentChoiceRows.d.ts +28 -0
- package/dist/_dts/blocks/src/system/runtime/shared/components/StepIndicator.d.ts +6 -8
- package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/shared/index.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/shared/useWaitlistClaim.d.ts +9 -12
- package/dist/_dts/blocks/src/system/runtime/shared/useWaitlistClaim.state.d.ts +15 -0
- package/dist/_dts/blocks/src/system/runtime/shared/utils/themePortalRoot.d.ts +10 -15
- package/dist/_dts/blocks/src/system/transforms/registry/index.d.ts +2 -0
- package/dist/_dts/blocks/src/system/transforms/registry/links.d.ts +2 -0
- package/dist/_dts/commerce/src/purchase/bookingInstalmentSchedule.d.ts +2 -0
- package/dist/_dts/commerce/src/purchase/bookingPaymentSelection.d.ts +6 -0
- package/dist/_dts/commerce/src/purchase/confirmationEmailPayment.d.ts +14 -14
- package/dist/_dts/commerce/src/purchase/confirmationPayment.d.ts +65 -0
- package/dist/_dts/commerce/src/purchase/confirmationPaymentSchema.d.ts +66 -0
- package/dist/_dts/commerce/src/purchase/index.d.ts +2 -0
- package/dist/_dts/commerce/src/purchase/orderPaymentState.d.ts +8 -0
- package/dist/_dts/content-model/src/content-types/schema.d.ts +3 -3
- package/dist/_dts/content-model/src/templates/defaults.d.ts +2 -2
- package/dist/_dts/core/src/appointment-booking-terms.d.ts +20 -0
- package/dist/_dts/core/src/booking-payment-schemas.d.ts +70 -0
- package/dist/_dts/core/src/branded.d.ts +0 -2
- package/dist/_dts/core/src/demo-claim-access.d.ts +1 -1
- package/dist/_dts/core/src/demo-claim-readiness.d.ts +18 -0
- package/dist/_dts/core/src/demo-lifecycle-status.d.ts +1 -1
- package/dist/_dts/core/src/demo-warm-pool-target.d.ts +1 -1
- package/dist/_dts/core/src/index.d.ts +4 -0
- package/dist/_dts/core/src/mailing-list-runtime.d.ts +2 -2
- package/dist/_dts/core/src/mailing-list-setup-parser.d.ts +9 -1
- package/dist/_dts/core/src/mailing-list-setup.d.ts +9 -1
- package/dist/_dts/core/src/mailing-list-submission.d.ts +1 -1
- package/dist/_dts/core/src/mailing-list-targeting-availability.d.ts +68 -0
- package/dist/_dts/core/src/mailing-list-targeting.d.ts +11 -1
- package/dist/_dts/core/src/ticket-quantity.d.ts +13 -0
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +106 -36
- package/dist/_dts/editor/src/chrome/chromeLayers.d.ts +7 -0
- package/dist/_dts/editor/src/index.d.ts +1 -0
- package/dist/_dts/editor-blocks/src/index.d.ts +1 -0
- package/dist/_dts/editor-blocks/src/media/MediaField.d.ts +2 -2
- package/dist/_dts/editor-blocks/src/media/admitEditorMediaField.d.ts +4 -0
- package/dist/_dts/editor-blocks/src/widgets/link/LinkAddressInput.d.ts +8 -0
- package/dist/_dts/editor-blocks/src/widgets/link/LinkContentList.d.ts +12 -0
- package/dist/_dts/editor-blocks/src/widgets/link/LinkPicker.d.ts +5 -1
- package/dist/_dts/editor-blocks/src/widgets/link/LinkPickerDialog.d.ts +3 -3
- package/dist/_dts/editor-blocks/src/widgets/link/LinkSummary.d.ts +8 -2
- package/dist/_dts/editor-blocks/src/widgets/link/LinkWidget.d.ts +4 -3
- package/dist/_dts/editor-blocks/src/widgets/link/LinkWidgetContext.d.ts +2 -1
- package/dist/_dts/editor-blocks/src/widgets/link/draft.d.ts +44 -0
- package/dist/_dts/editor-blocks/src/widgets/link/presentation.d.ts +13 -0
- package/dist/_dts/editor-blocks/src/widgets/link/types.d.ts +14 -0
- package/dist/_dts/editor-blocks/src/widgets/link/useRoutableContent.d.ts +2 -0
- package/dist/_dts/editor-blocks/src/widgets/link/utils.d.ts +5 -4
- package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListTargetingField.d.ts +1 -1
- package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/targetingState.d.ts +13 -8
- package/dist/_dts/media-core/src/assetsInUseSummary.d.ts +6 -0
- package/dist/_dts/media-core/src/contentMediaAudit.d.ts +3 -2
- package/dist/_dts/media-core/src/fileStorage.d.ts +4 -3
- package/dist/_dts/media-core/src/index.d.ts +5 -0
- package/dist/_dts/media-core/src/media.d.ts +406 -0
- package/dist/_dts/media-core/src/mediaIdentifierSchema.d.ts +3 -0
- package/dist/_dts/media-core/src/mediaKinds.d.ts +2 -0
- package/dist/_dts/media-core/src/mediaUsageProjection.d.ts +13 -1
- package/dist/_dts/media-core/src/mediaWriteNormalizer.d.ts +2 -6
- package/dist/_dts/media-core/src/portableMediaReferences.d.ts +8 -21
- package/dist/_dts/media-core/src/renderableMediaAsset.d.ts +28 -14
- package/dist/_dts/media-core/src/renderableMediaAssetAdmission.d.ts +15 -0
- package/dist/_dts/media-core/src/storageObjectKey.d.ts +12 -0
- package/dist/_dts/media-editor/src/CropDialog.d.ts +6 -3
- package/dist/_dts/media-editor/src/MediaEditor.d.ts +2 -1
- package/dist/_dts/media-editor/src/MediaPreview.d.ts +3 -3
- package/dist/_dts/media-editor/src/cropEditorSource.d.ts +5 -7
- package/dist/_dts/media-editor/src/editorMediaState.d.ts +29 -0
- package/dist/_dts/media-editor/src/mediaSelection.d.ts +1 -2
- package/dist/_dts/media-editor/src/runtimeMediaAssetState.d.ts +4 -5
- package/dist/_dts/media-editor/src/types.d.ts +1 -1
- package/dist/_dts/media-editor/src/utils.d.ts +0 -1
- package/dist/_dts/media-react/src/components/cropChangePolicy.d.ts +4 -1
- package/dist/_dts/media-react/src/components/cropGeometry.d.ts +1 -0
- package/dist/_dts/media-react/src/components/useImageCropperController.d.ts +1 -0
- package/dist/_dts/media-react/src/hooks/useSupabaseMediaUploader.d.ts +1 -1
- package/dist/_dts/media-react/src/internal/supabaseResumableUpload.d.ts +13 -0
- package/dist/_dts/preview-next/src/client/blocks/BlockBackgroundChooser.d.ts +2 -1
- package/dist/_dts/preview-next/src/client/blocks/previewCustomizeSelectedMedia.d.ts +11 -12
- package/dist/_dts/preview-next/src/client/preview/previewModeRootAttribute.d.ts +11 -0
- package/dist/_dts/sdk/src/contracts/content.d.ts +2 -45
- package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
- package/dist/_dts/sdk/src/contracts/rendering.d.ts +3 -3
- package/dist/_dts/sdk/src/index.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +0 -1
- package/dist/_dts/sdk/src/rendering/image.d.ts +14 -4
- package/dist/_dts/sdk/src/rendering/index.d.ts +5 -2
- package/dist/_dts/sdk/src/rendering/link.d.ts +5 -0
- package/dist/_dts/sdk/src/rendering/mediaAssets.d.ts +2 -4
- package/dist/_dts/sdk/src/rendering/overrides.d.ts +1 -0
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/theme-core/src/accordions/types.d.ts +1 -1
- package/dist/_dts/theme-core/src/blocks/opaquePanels.d.ts +3 -3
- package/dist/_dts/theme-core/src/boxBackgroundSchema.d.ts +397 -26
- package/dist/_dts/theme-core/src/buttons/types.d.ts +21 -21
- package/dist/_dts/theme-core/src/cards/types.d.ts +34 -34
- package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
- package/dist/_dts/theme-core/src/inputs/types.d.ts +3 -3
- package/dist/_dts/theme-core/src/lib/media.d.ts +2 -616
- package/dist/_dts/theme-core/src/mock-themes/all.d.ts +261 -2619
- package/dist/_dts/theme-core/src/palette/curated/types.d.ts +1 -1
- package/dist/_dts/theme-core/src/schema.d.ts +548 -3187
- package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
- package/dist/_dts/theme-core/src/site-styles/runtimeBackgroundResolution.d.ts +9 -9
- package/dist/_dts/theme-core/src/site-styles/styleTags.d.ts +1 -1
- package/dist/_dts/theme-core/src/site-styles/tokenRecipes.d.ts +1 -1
- package/dist/_dts/theme-core/src/styles/skinTokens.d.ts +2 -2
- package/dist/_dts/theme-core/src/typography/schema.d.ts +2 -2
- package/dist/client/BookingMailingListNote-DrchYW1m.mjs +386 -0
- package/dist/client/{CardListItem-ZDLYh6dL.mjs → CardListItem-CC_GVmF6.mjs} +5 -5
- package/dist/client/CheckIcon-CpyXr-Kg.mjs +35 -0
- package/dist/client/{CheckboxChoice-M-3HycLw.mjs → CheckboxChoice-Dq30m3DO.mjs} +1 -1
- package/dist/client/{DemoBookingPortalAccess-BMtvPTWE.mjs → DemoBookingPortalAccess-ojwbVUmx.mjs} +85 -85
- package/dist/client/{EventCombined.client-DUm_DOxW.mjs → EventCombined.client-DyN0v0Xk.mjs} +7 -9
- package/dist/client/{EventEmbeddedCheckoutStep-DsNNzgRm.mjs → EventEmbeddedCheckoutStep-CgfpKc3n.mjs} +11 -10
- package/dist/client/{EventListing.client-DjNYGUVm.mjs → EventListing.client-CuOuvYMz.mjs} +2 -2
- package/dist/client/{LeafletStaticMap-DuFiOHq_.mjs → LeafletStaticMap-B0WhRr3j.mjs} +1 -1
- package/dist/client/{ModalShell-CqkBvBIC.mjs → ModalShell-BXzucfR6.mjs} +83 -12
- package/dist/client/{RichText-LjPCUGGi.mjs → RichText-C1fIXBzA.mjs} +50 -34
- package/dist/client/{ThemedButton-DZKjtaDD.mjs → ThemedButton-B7HFqFBg.mjs} +1 -2
- package/dist/client/{accordion-Qe--SILD.mjs → accordion-DCDVWSye.mjs} +1 -1
- package/dist/client/{bookingForm-3BCl4g_f.mjs → bookingForm-BJ3C4GlM.mjs} +321 -154
- package/dist/client/bookings.mjs +118607 -22429
- package/dist/client/{carousel-h2YjKOS2.mjs → carousel-BSCBhfHY.mjs} +2 -2
- package/dist/client/{carousel.client-BLrd4hmY.mjs → carousel.client-GEtOGsxo.mjs} +46 -41
- package/dist/client/{cart-5NeiigVd.mjs → cart-Yv-aAtck.mjs} +3 -3
- package/dist/client/{checkout-G4UWjOEw.mjs → checkout-B9xDkl30.mjs} +3 -3
- package/dist/client/client.mjs +37511 -33793
- package/dist/client/{context-GK4-AVAh.mjs → context-BOGe3rIA.mjs} +275 -10
- package/dist/client/{eventCalendar-Prw3Yo_L.mjs → eventCalendar-D6M0T9hs.mjs} +18 -17
- package/dist/client/{eventCombined-BUugi6__.mjs → eventCombined-NM4UFBq8.mjs} +4 -4
- package/dist/client/{eventDetails-CBHUda-R.mjs → eventDetails-f_FhV4O8.mjs} +3 -4
- package/dist/client/{eventListing-CQeG45Dg.mjs → eventListing-WLkfAROh.mjs} +4 -4
- package/dist/client/{eventRegistration-Dif3p3oJ.mjs → eventRegistration-D3ejfLvW.mjs} +2209 -2144
- package/dist/client/{form-Cf0WMtfG.mjs → form-D5Or2Jyu.mjs} +5 -6
- package/dist/client/{headerSection-Bqdr3JWp.mjs → headerSection-hWgnv27V.mjs} +9 -9
- package/dist/client/hooks.mjs +17278 -16106
- package/dist/client/{locationMap-BVvPou4O.mjs → locationMap-Di1K0O2S.mjs} +3 -4
- package/dist/client/{media-47fcnhzD.mjs → media-D29-F1u_.mjs} +183 -362
- package/dist/client/mediaContext-CwbbimYB.mjs +135 -0
- package/dist/client/{newsletterForm-Cx-1dnic.mjs → newsletterForm-CwxcwTNO.mjs} +5 -5
- package/dist/client/{productDetail-DaUMaJYk.mjs → productDetail-BLSnhPdA.mjs} +3 -3
- package/dist/client/{productList-BKQlWEKE.mjs → productList-oGytONOX.mjs} +3 -3
- package/dist/client/{propsDecoder-DO5iXphQ.mjs → propsDecoder-lf_dTeZS.mjs} +18659 -14473
- package/dist/client/renderableMediaAssetAdmission-CHkXYDC_.mjs +143 -0
- package/dist/client/rendering/client.mjs +58971 -55722
- package/dist/client/rendering/islands.mjs +20 -23
- package/dist/client/rendering.mjs +41610 -37917
- package/dist/client/{routeIslandApiConfig-BNm0Z3-g.mjs → routeIslandApiConfig-Bc_WVPS8.mjs} +1 -1
- package/dist/client/{shop-D7ytcFBC.mjs → shop-BQ3bR7fA.mjs} +16 -14
- package/dist/client/{shop-commerce-D68-hHy2.mjs → shop-commerce-DDPll6ZC.mjs} +9 -9
- package/dist/client/{shop-commerce-store-Cu7X2lyu.mjs → shop-commerce-store-DO-e1pTe.mjs} +1 -1
- package/dist/client/{shopShared-D12rxE69.mjs → shopShared-BylM9jh1.mjs} +5 -5
- package/dist/client/themePortalRoot-DS92SRVZ.mjs +47 -0
- package/dist/client/{TerminalPanel-DOTSUCO0.mjs → useDiscountCodeUi-B1Puub2v.mjs} +60 -77
- package/dist/client/{useEventPagination-jgKa67KV.mjs → useEventPagination-BBhkmQaT.mjs} +6 -8
- package/dist/preview-next/before-render.mjs +96 -4
- package/dist/preview-next/client/runtime.mjs +3 -3
- package/dist/preview-next/keepAlive.mjs +7 -0
- package/dist/preview-next/middleware.mjs +7 -0
- package/dist/{sdk-runtime-4cCWO_3i.mjs → sdk-runtime-DWCvhJGu.mjs} +1 -1
- package/dist/server/components.mjs +21820 -19902
- package/dist/server/config-validation.mjs +1786 -642
- package/dist/server/config.mjs +1786 -642
- package/dist/server/data.mjs +17220 -16076
- package/dist/server/index.mjs +234 -2
- package/dist/server/next.mjs +22505 -20528
- package/dist/server/page-converter.mjs +7587 -6572
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +20487 -19044
- package/dist/server/rendering.mjs +21844 -19901
- package/dist/server/routing.mjs +19186 -17961
- package/dist/server/server.mjs +1874 -695
- package/dist/server/theme-bridge.mjs +1371 -914
- package/dist/server/theme.mjs +154 -37
- package/dist/{spinner-tSdG9YvG.mjs → spinner-BYM-Y81w.mjs} +1 -1
- package/dist/styles/index.css +1088 -721
- package/package.json +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/OrderSummary.d.ts +0 -15
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useWaitlistClaimRestoration.d.ts +0 -22
- package/dist/_dts/blocks/src/system/runtime/shared/components/SelectableOptionCard.d.ts +0 -30
- package/dist/client/BookingMailingListNote-DlDSs5Vm.mjs +0 -567
- package/dist/client/colorStyles-DTunOThj.mjs +0 -1316
- package/dist/client/pricing-CMD0kADd.mjs +0 -314
- package/dist/client/result-DRW7JWXz.mjs +0 -30
- package/dist/client/scrollToBlock-C86BYkyV.mjs +0 -17
- package/dist/client/themePortalRoot-AGs4cE7t.mjs +0 -30
- package/dist/spinner-BL3kW9Uh.mjs +0 -803
package/dist/server/server.mjs
CHANGED
|
@@ -1765,12 +1765,14 @@ const unsafeAsSiteId = (id) => id;
|
|
|
1765
1765
|
const unsafeAsApiKeyId = (id) => id;
|
|
1766
1766
|
const unsafeAsEventOfferingId = (id) => id;
|
|
1767
1767
|
const unsafeAsEventSeriesId = (id) => id;
|
|
1768
|
+
const unsafeAsMediaAssetId = (id) => id;
|
|
1768
1769
|
const unsafeAsUserId = (id) => id;
|
|
1769
1770
|
const unsafeAsContentVersionId = (id) => id;
|
|
1770
1771
|
const parseSiteId = (value) => parseUuidBrand(value, unsafeAsSiteId);
|
|
1771
1772
|
const parseApiKeyId = (value) => parseUuidBrand(value, unsafeAsApiKeyId);
|
|
1772
1773
|
const parseEventOfferingId = (value) => parseUuidBrand(value, unsafeAsEventOfferingId);
|
|
1773
1774
|
const parseUserId = (value) => parseUuidBrand(value, unsafeAsUserId);
|
|
1775
|
+
const parseMediaAssetId = (value) => parseUuidBrand(value, unsafeAsMediaAssetId);
|
|
1774
1776
|
const parseContentVersionId = (value) => parseUuidBrand(value, unsafeAsContentVersionId);
|
|
1775
1777
|
const parseEventSeriesId = (value) => parseUuidBrand(value, unsafeAsEventSeriesId);
|
|
1776
1778
|
//#endregion
|
|
@@ -1975,6 +1977,29 @@ function canonicalEventPricingDisplay(pricing) {
|
|
|
1975
1977
|
default: return assertNever$6(pricing);
|
|
1976
1978
|
}
|
|
1977
1979
|
}
|
|
1980
|
+
/**
|
|
1981
|
+
* The single renderer for a precomputed booking price `display` ADT. This is
|
|
1982
|
+
* the one place booking price variants map to user-facing strings — every call
|
|
1983
|
+
* site (booking entry, events calendar, event/course details, listings, portal)
|
|
1984
|
+
* should route through here so labels never drift. Adding a variant to the ADT
|
|
1985
|
+
* breaks compilation here (via `assertNever`) until it is handled.
|
|
1986
|
+
*/
|
|
1987
|
+
function formatBookingPriceDisplay(display, options = {}) {
|
|
1988
|
+
switch (display.kind) {
|
|
1989
|
+
case "free": return "Free";
|
|
1990
|
+
case "exact": return formatCurrencyAmount(display.amount, display.currency, options);
|
|
1991
|
+
case "from": return `From ${formatCurrencyAmount(display.amount, display.currency, options)}`;
|
|
1992
|
+
case "range": return `${formatCurrencyAmount(display.minAmount, display.currency, options)} - ${formatCurrencyAmount(display.maxAmount, display.currency, options)}`;
|
|
1993
|
+
case "mixed": return display.paidToAmount > display.paidFromAmount ? `Free / ${formatCurrencyAmount(display.paidFromAmount, display.currency, options)} - ${formatCurrencyAmount(display.paidToAmount, display.currency, options)}` : `Free / ${formatCurrencyAmount(display.paidFromAmount, display.currency, options)}`;
|
|
1994
|
+
case "unavailable": return "Pricing unavailable";
|
|
1995
|
+
case "external": return display.label;
|
|
1996
|
+
default: return assertNever$6(display);
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
/** Render an event's price directly from its pricing value. */
|
|
2000
|
+
function formatEventPricing(pricing, options = {}) {
|
|
2001
|
+
return formatBookingPriceDisplay(publicEventPricingDisplay(pricing), options);
|
|
2002
|
+
}
|
|
1978
2003
|
//#endregion
|
|
1979
2004
|
//#region ../core/src/event-page-surface-subject.ts
|
|
1980
2005
|
function createEventSeriesPageSurfaceSubject(eventSeriesId, bookingScope, eventDestinationMode) {
|
|
@@ -2118,6 +2143,7 @@ function parseBookingTimeZone(timeZone) {
|
|
|
2118
2143
|
}
|
|
2119
2144
|
//#endregion
|
|
2120
2145
|
//#region ../core/src/booking-date-time.ts
|
|
2146
|
+
const DEFAULT_LOCALE = "en-US";
|
|
2121
2147
|
const FALLBACK_TIMEZONE = "UTC";
|
|
2122
2148
|
const START_OF_DAY = {
|
|
2123
2149
|
hour: 0,
|
|
@@ -2240,6 +2266,34 @@ function toScheduledBookingDateTime(input) {
|
|
|
2240
2266
|
if (result.ok) return result.value;
|
|
2241
2267
|
throw new Error(formatParseError(result));
|
|
2242
2268
|
}
|
|
2269
|
+
function formatBookingInstant(isoString, options) {
|
|
2270
|
+
const date = new Date(isoString);
|
|
2271
|
+
if (Number.isNaN(date.getTime())) return isoString;
|
|
2272
|
+
return getCachedDateTimeFormatter(options.locale ?? DEFAULT_LOCALE, getSafeTimeZone(options.timeZone), options.format).format(date);
|
|
2273
|
+
}
|
|
2274
|
+
function formatBookingDate(input, format = {
|
|
2275
|
+
weekday: "long",
|
|
2276
|
+
year: "numeric",
|
|
2277
|
+
month: "long",
|
|
2278
|
+
day: "numeric"
|
|
2279
|
+
}) {
|
|
2280
|
+
return formatBookingInstant(input.startsAt, {
|
|
2281
|
+
locale: input.locale,
|
|
2282
|
+
timeZone: input.timeZone,
|
|
2283
|
+
format
|
|
2284
|
+
});
|
|
2285
|
+
}
|
|
2286
|
+
function formatBookingTime(input, format = {
|
|
2287
|
+
hour: "numeric",
|
|
2288
|
+
minute: "2-digit",
|
|
2289
|
+
hour12: true
|
|
2290
|
+
}) {
|
|
2291
|
+
return formatBookingInstant(input.startsAt, {
|
|
2292
|
+
locale: input.locale,
|
|
2293
|
+
timeZone: input.timeZone,
|
|
2294
|
+
format
|
|
2295
|
+
});
|
|
2296
|
+
}
|
|
2243
2297
|
function getBookingLocalDateKey(input) {
|
|
2244
2298
|
return formatDateKey$1(getLocalScheduleDate(new Date(input.startsAt), input.timeZone));
|
|
2245
2299
|
}
|
|
@@ -2389,7 +2443,7 @@ function parsePositiveInteger(value) {
|
|
|
2389
2443
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
|
|
2390
2444
|
}
|
|
2391
2445
|
function parseNewsletterListId(value) {
|
|
2392
|
-
return parseTrimmedMatchingString(value, UUID_PATTERN);
|
|
2446
|
+
return parseTrimmedMatchingString(typeof value === "string" ? value.toLowerCase() : value, UUID_PATTERN);
|
|
2393
2447
|
}
|
|
2394
2448
|
function parseMailchimpAccountId(value) {
|
|
2395
2449
|
return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
|
|
@@ -2431,8 +2485,15 @@ function parseMailingListProviderScope(value) {
|
|
|
2431
2485
|
}
|
|
2432
2486
|
return err$1("invalid_mailing_list_provider_scope");
|
|
2433
2487
|
}
|
|
2434
|
-
|
|
2435
|
-
|
|
2488
|
+
z.unknown().transform((value, ctx) => {
|
|
2489
|
+
const parsed = parseNewsletterAudience(value);
|
|
2490
|
+
if (parsed.ok) return parsed.value;
|
|
2491
|
+
ctx.addIssue({
|
|
2492
|
+
code: "custom",
|
|
2493
|
+
message: "Choose a valid newsletter audience."
|
|
2494
|
+
});
|
|
2495
|
+
return z.NEVER;
|
|
2496
|
+
});
|
|
2436
2497
|
function parseMailingListGlobalForm(value) {
|
|
2437
2498
|
if (!isRecord$16(value)) return formError("shape");
|
|
2438
2499
|
const fields = parseGlobalFields(value.fields);
|
|
@@ -2452,6 +2513,16 @@ function parseMailingListGlobalForm(value) {
|
|
|
2452
2513
|
privacyNote
|
|
2453
2514
|
});
|
|
2454
2515
|
}
|
|
2516
|
+
function parseNewsletterAudience(value) {
|
|
2517
|
+
if (!isRecord$16(value)) return err$1("invalid_newsletter_audience");
|
|
2518
|
+
if (value.kind === "general" && Object.keys(value).length === 1) return ok$1({ kind: "general" });
|
|
2519
|
+
if (value.kind !== "topic" || Object.keys(value).some((key) => key !== "kind" && key !== "topicId")) return err$1("invalid_newsletter_audience");
|
|
2520
|
+
const topicId = parseNewsletterListId(value.topicId);
|
|
2521
|
+
return topicId === null ? err$1("invalid_newsletter_audience") : ok$1({
|
|
2522
|
+
kind: "topic",
|
|
2523
|
+
topicId
|
|
2524
|
+
});
|
|
2525
|
+
}
|
|
2455
2526
|
function parseGlobalFields(value) {
|
|
2456
2527
|
if (!isRecord$16(value) || typeof value.preset !== "string") return null;
|
|
2457
2528
|
switch (value.preset) {
|
|
@@ -2501,44 +2572,144 @@ function formError(field) {
|
|
|
2501
2572
|
}
|
|
2502
2573
|
//#endregion
|
|
2503
2574
|
//#region ../core/src/mailing-list-targeting.ts
|
|
2575
|
+
const DEFAULT_MAILING_LIST_TARGETING = { mode: "default" };
|
|
2576
|
+
function mailingListTargetingChoiceIds(targeting) {
|
|
2577
|
+
switch (targeting.provider) {
|
|
2578
|
+
case "native": return targeting.selection.tag === "general" ? [] : targeting.selection.tag === "fixed" ? targeting.selection.topicIds : targeting.selection.offeredTopicIds;
|
|
2579
|
+
case "brevo": return targeting.selection.tag === "fixed" ? targeting.selection.listIds : targeting.selection.offeredListIds;
|
|
2580
|
+
case "mailchimp": return targeting.selection.tag === "fixed" ? targeting.selection.interestIds : targeting.selection.offeredInterestIds;
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2504
2583
|
function planMailingListChoicePresentation(targeting) {
|
|
2505
|
-
if (targeting.mode === "default" || targeting.selection.tag === "fixed") return { tag: "hidden" };
|
|
2584
|
+
if (targeting.mode === "default" || targeting.selection.tag === "fixed" || targeting.selection.tag === "general") return { tag: "hidden" };
|
|
2506
2585
|
switch (targeting.provider) {
|
|
2507
|
-
case "native": return
|
|
2508
|
-
tag: "automatic",
|
|
2509
|
-
selection: {
|
|
2510
|
-
provider: "native",
|
|
2511
|
-
topicIds: targeting.selection.offeredTopicIds
|
|
2512
|
-
}
|
|
2513
|
-
} : {
|
|
2514
|
-
tag: "visitor_choice",
|
|
2586
|
+
case "native": return presentVisitorSelection({
|
|
2515
2587
|
provider: "native",
|
|
2516
|
-
|
|
2588
|
+
topicIds: targeting.selection.offeredTopicIds
|
|
2589
|
+
}, targeting.selection.offeredTopicIds.length);
|
|
2590
|
+
case "brevo": return presentVisitorSelection({
|
|
2591
|
+
provider: "brevo",
|
|
2592
|
+
listIds: targeting.selection.offeredListIds
|
|
2593
|
+
}, targeting.selection.offeredListIds.length);
|
|
2594
|
+
case "mailchimp": return presentVisitorSelection({
|
|
2595
|
+
provider: "mailchimp",
|
|
2596
|
+
interestIds: targeting.selection.offeredInterestIds
|
|
2597
|
+
}, targeting.selection.offeredInterestIds.length);
|
|
2598
|
+
}
|
|
2599
|
+
}
|
|
2600
|
+
function presentVisitorSelection(selection, optionCount) {
|
|
2601
|
+
return optionCount === 1 ? {
|
|
2602
|
+
tag: "automatic",
|
|
2603
|
+
selection
|
|
2604
|
+
} : {
|
|
2605
|
+
tag: "visitor_choice",
|
|
2606
|
+
provider: selection.provider,
|
|
2607
|
+
optionCount
|
|
2608
|
+
};
|
|
2609
|
+
}
|
|
2610
|
+
//#endregion
|
|
2611
|
+
//#region ../core/src/mailing-list-targeting-availability.ts
|
|
2612
|
+
function resolveMailingListDefaultDestination(provider) {
|
|
2613
|
+
switch (provider.provider) {
|
|
2614
|
+
case "native": {
|
|
2615
|
+
const audience = provider.defaultAudience;
|
|
2616
|
+
return audience.kind === "general" ? {
|
|
2617
|
+
id: "general",
|
|
2618
|
+
name: "General mailing list"
|
|
2619
|
+
} : provider.topics.find((item) => item.id === audience.topicId) ?? null;
|
|
2620
|
+
}
|
|
2621
|
+
case "brevo": return provider.lists.find((item) => item.id === provider.defaultListId) ?? null;
|
|
2622
|
+
case "mailchimp": return provider.audiences.find((item) => item.id === provider.defaultAudienceId) ?? null;
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
function assessMailingListTargeting(context, targeting) {
|
|
2626
|
+
if (context?.tag !== "configured") return {
|
|
2627
|
+
tag: "unavailable",
|
|
2628
|
+
reason: "setup_missing",
|
|
2629
|
+
targeting
|
|
2630
|
+
};
|
|
2631
|
+
const catalog = context.provider;
|
|
2632
|
+
if (targeting.mode === "custom") return assessCustomTargeting(catalog, targeting);
|
|
2633
|
+
const destination = resolveMailingListDefaultDestination(catalog);
|
|
2634
|
+
return destination === null ? {
|
|
2635
|
+
tag: "unavailable",
|
|
2636
|
+
reason: "default_missing",
|
|
2637
|
+
targeting
|
|
2638
|
+
} : {
|
|
2639
|
+
tag: "available",
|
|
2640
|
+
value: {
|
|
2641
|
+
mode: "default",
|
|
2642
|
+
targeting,
|
|
2643
|
+
provider: catalog.provider,
|
|
2644
|
+
destination
|
|
2645
|
+
}
|
|
2646
|
+
};
|
|
2647
|
+
}
|
|
2648
|
+
function assessCustomTargeting(catalog, targeting) {
|
|
2649
|
+
switch (targeting.provider) {
|
|
2650
|
+
case "native": return catalog.provider === "native" ? assessMatchedChoices({
|
|
2651
|
+
provider: "native",
|
|
2652
|
+
catalog,
|
|
2653
|
+
targeting
|
|
2654
|
+
}, catalog.topics) : {
|
|
2655
|
+
tag: "unavailable",
|
|
2656
|
+
reason: "provider_mismatch",
|
|
2657
|
+
targeting
|
|
2517
2658
|
};
|
|
2518
|
-
case "brevo": return
|
|
2519
|
-
tag: "automatic",
|
|
2520
|
-
selection: {
|
|
2521
|
-
provider: "brevo",
|
|
2522
|
-
listIds: targeting.selection.offeredListIds
|
|
2523
|
-
}
|
|
2524
|
-
} : {
|
|
2525
|
-
tag: "visitor_choice",
|
|
2659
|
+
case "brevo": return catalog.provider === "brevo" ? assessMatchedChoices({
|
|
2526
2660
|
provider: "brevo",
|
|
2527
|
-
|
|
2661
|
+
catalog,
|
|
2662
|
+
targeting
|
|
2663
|
+
}, catalog.lists) : {
|
|
2664
|
+
tag: "unavailable",
|
|
2665
|
+
reason: "provider_mismatch",
|
|
2666
|
+
targeting
|
|
2528
2667
|
};
|
|
2529
|
-
case "mailchimp":
|
|
2530
|
-
|
|
2531
|
-
|
|
2668
|
+
case "mailchimp": {
|
|
2669
|
+
if (catalog.provider !== "mailchimp") return {
|
|
2670
|
+
tag: "unavailable",
|
|
2671
|
+
reason: "provider_mismatch",
|
|
2672
|
+
targeting
|
|
2673
|
+
};
|
|
2674
|
+
const audience = catalog.audiences.find((item) => item.id === targeting.audienceId);
|
|
2675
|
+
return audience === void 0 ? {
|
|
2676
|
+
tag: "unavailable",
|
|
2677
|
+
reason: "audience_missing",
|
|
2678
|
+
value: {
|
|
2679
|
+
mode: "custom",
|
|
2680
|
+
provider: "mailchimp",
|
|
2681
|
+
catalog,
|
|
2682
|
+
targeting
|
|
2683
|
+
}
|
|
2684
|
+
} : assessMatchedChoices({
|
|
2532
2685
|
provider: "mailchimp",
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
optionCount: targeting.selection.offeredInterestIds.length
|
|
2539
|
-
};
|
|
2686
|
+
catalog,
|
|
2687
|
+
targeting,
|
|
2688
|
+
audience
|
|
2689
|
+
}, audience.interests);
|
|
2690
|
+
}
|
|
2540
2691
|
}
|
|
2541
2692
|
}
|
|
2693
|
+
function assessMatchedChoices(matched, choices) {
|
|
2694
|
+
const selected = new Set(mailingListTargetingChoiceIds(matched.targeting));
|
|
2695
|
+
const available = new Set(choices.map((item) => item.id));
|
|
2696
|
+
const missingIds = [...selected].filter((id) => !available.has(id));
|
|
2697
|
+
const value = {
|
|
2698
|
+
mode: "custom",
|
|
2699
|
+
...matched,
|
|
2700
|
+
choices,
|
|
2701
|
+
selectedChoices: choices.filter((item) => selected.has(item.id))
|
|
2702
|
+
};
|
|
2703
|
+
return missingIds.length > 0 ? {
|
|
2704
|
+
tag: "unavailable",
|
|
2705
|
+
reason: "choices_missing",
|
|
2706
|
+
missingIds,
|
|
2707
|
+
value
|
|
2708
|
+
} : {
|
|
2709
|
+
tag: "available",
|
|
2710
|
+
value
|
|
2711
|
+
};
|
|
2712
|
+
}
|
|
2542
2713
|
//#endregion
|
|
2543
2714
|
//#region ../core/src/mailing-list-runtime.ts
|
|
2544
2715
|
function parseMailingListRuntimeContext(value) {
|
|
@@ -2584,11 +2755,12 @@ function parseRuntimeProvider(value) {
|
|
|
2584
2755
|
}
|
|
2585
2756
|
}
|
|
2586
2757
|
function parseNativeRuntimeProvider(value) {
|
|
2587
|
-
|
|
2758
|
+
if ("defaultTopicId" in value) return null;
|
|
2759
|
+
const defaultAudience = parseNewsletterAudience(value.defaultAudience);
|
|
2588
2760
|
const topics = parseNamedItems(value.topics, parseNewsletterListId);
|
|
2589
|
-
return
|
|
2761
|
+
return defaultAudience.ok && topics !== null ? {
|
|
2590
2762
|
provider: "native",
|
|
2591
|
-
|
|
2763
|
+
defaultAudience: defaultAudience.value,
|
|
2592
2764
|
topics
|
|
2593
2765
|
} : null;
|
|
2594
2766
|
}
|
|
@@ -2604,57 +2776,47 @@ function parseBrevoRuntimeProvider(value) {
|
|
|
2604
2776
|
function parseMailchimpRuntimeProvider(value) {
|
|
2605
2777
|
if (!Array.isArray(value.audiences)) return null;
|
|
2606
2778
|
const defaultAudienceId = parseMailchimpAudienceId(value.defaultAudienceId);
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
for (const audience of value.audiences) {
|
|
2610
|
-
if (!isRecord$15(audience)) return null;
|
|
2611
|
-
const id = parseMailchimpAudienceId(audience.id);
|
|
2612
|
-
const name = parseName(audience.name);
|
|
2613
|
-
if (id === null || name === null || !Array.isArray(audience.interests)) return null;
|
|
2614
|
-
const interests = parseMailchimpInterests(audience.interests);
|
|
2615
|
-
if (interests === null) return null;
|
|
2616
|
-
audiences.push({
|
|
2617
|
-
id,
|
|
2618
|
-
name,
|
|
2619
|
-
interests
|
|
2620
|
-
});
|
|
2621
|
-
}
|
|
2622
|
-
return {
|
|
2779
|
+
const audiences = Array.from(value.audiences, parseMailchimpAudience);
|
|
2780
|
+
return defaultAudienceId !== null && audiences.every((audience) => audience !== null) ? {
|
|
2623
2781
|
provider: "mailchimp",
|
|
2624
2782
|
defaultAudienceId,
|
|
2625
2783
|
audiences
|
|
2626
|
-
};
|
|
2784
|
+
} : null;
|
|
2627
2785
|
}
|
|
2628
|
-
function
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
interests
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2786
|
+
function parseMailchimpAudience(value) {
|
|
2787
|
+
if (!isRecord$15(value) || !Array.isArray(value.interests)) return null;
|
|
2788
|
+
const id = parseMailchimpAudienceId(value.id);
|
|
2789
|
+
const name = parseName(value.name);
|
|
2790
|
+
const interests = Array.from(value.interests, parseMailchimpInterest);
|
|
2791
|
+
return id !== null && name !== null && interests.every((interest) => interest !== null) ? {
|
|
2792
|
+
id,
|
|
2793
|
+
name,
|
|
2794
|
+
interests
|
|
2795
|
+
} : null;
|
|
2796
|
+
}
|
|
2797
|
+
function parseMailchimpInterest(value) {
|
|
2798
|
+
if (!isRecord$15(value)) return null;
|
|
2799
|
+
const id = parseMailchimpInterestId(value.id);
|
|
2800
|
+
const name = parseName(value.name);
|
|
2801
|
+
const categoryName = parseName(value.categoryName);
|
|
2802
|
+
return id !== null && name !== null && categoryName !== null ? {
|
|
2803
|
+
id,
|
|
2804
|
+
name,
|
|
2805
|
+
categoryName
|
|
2806
|
+
} : null;
|
|
2643
2807
|
}
|
|
2644
2808
|
function parseNamedItems(value, parseId) {
|
|
2645
2809
|
if (!Array.isArray(value)) return null;
|
|
2646
|
-
const items =
|
|
2647
|
-
for (const item of value) {
|
|
2810
|
+
const items = Array.from(value, (item) => {
|
|
2648
2811
|
if (!isRecord$15(item)) return null;
|
|
2649
2812
|
const id = parseId(item.id);
|
|
2650
2813
|
const name = parseName(item.name);
|
|
2651
|
-
|
|
2652
|
-
items.push({
|
|
2814
|
+
return id !== null && name !== null ? {
|
|
2653
2815
|
id,
|
|
2654
2816
|
name
|
|
2655
|
-
}
|
|
2656
|
-
}
|
|
2657
|
-
return items;
|
|
2817
|
+
} : null;
|
|
2818
|
+
});
|
|
2819
|
+
return items.every((item) => item !== null) ? items : null;
|
|
2658
2820
|
}
|
|
2659
2821
|
function parseName(value) {
|
|
2660
2822
|
if (typeof value !== "string") return null;
|
|
@@ -2670,6 +2832,7 @@ function invalidRuntimeContext() {
|
|
|
2670
2832
|
//#endregion
|
|
2671
2833
|
//#region ../core/src/mailing-list-targeting-parser.ts
|
|
2672
2834
|
function parseMailingListPlacementTargeting(value) {
|
|
2835
|
+
if (value == null) return ok$1(DEFAULT_MAILING_LIST_TARGETING);
|
|
2673
2836
|
if (!isRecord$14(value)) return targetingError("shape");
|
|
2674
2837
|
if (value.mode === "default") return ok$1({ mode: "default" });
|
|
2675
2838
|
if (value.mode !== "custom") return targetingError("mode");
|
|
@@ -2682,6 +2845,11 @@ function parseMailingListPlacementTargeting(value) {
|
|
|
2682
2845
|
}
|
|
2683
2846
|
}
|
|
2684
2847
|
function parseNativeTargeting(selection) {
|
|
2848
|
+
if (selection.tag === "general") return Object.keys(selection).length === 1 ? ok$1({
|
|
2849
|
+
mode: "custom",
|
|
2850
|
+
provider: "native",
|
|
2851
|
+
selection: { tag: "general" }
|
|
2852
|
+
}) : targetingError("selection");
|
|
2685
2853
|
if (selection.tag === "fixed") {
|
|
2686
2854
|
const topicIds = parseNonEmptyUniqueIds(selection.topicIds, parseNewsletterListId);
|
|
2687
2855
|
return topicIds.ok ? ok$1({
|
|
@@ -2768,14 +2936,11 @@ function parseNonEmptyUniqueIds(value, parseId) {
|
|
|
2768
2936
|
}
|
|
2769
2937
|
function parseUniqueIds(value, parseId) {
|
|
2770
2938
|
if (!Array.isArray(value)) return targetingError("targets");
|
|
2771
|
-
|
|
2772
|
-
|
|
2939
|
+
return Array.from(value).reduce((parsed, item) => {
|
|
2940
|
+
if (!parsed.ok) return parsed;
|
|
2773
2941
|
const id = parseId(item);
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
parsed.push(id);
|
|
2777
|
-
}
|
|
2778
|
-
return ok$1(parsed);
|
|
2942
|
+
return id === null ? targetingError("targets") : parsed.value.includes(id) ? targetingError("duplicate_target") : ok$1([...parsed.value, id]);
|
|
2943
|
+
}, ok$1([]));
|
|
2779
2944
|
}
|
|
2780
2945
|
function isRecord$14(value) {
|
|
2781
2946
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -3207,6 +3372,45 @@ function resolveSiteVerticalBookingConfig(rawConfig) {
|
|
|
3207
3372
|
};
|
|
3208
3373
|
}
|
|
3209
3374
|
//#endregion
|
|
3375
|
+
//#region ../core/src/event-preset-vocabulary.ts
|
|
3376
|
+
const EVENT_PRESET_VOCABULARY = {
|
|
3377
|
+
event: {
|
|
3378
|
+
label: "Event",
|
|
3379
|
+
pluralLabel: "Events",
|
|
3380
|
+
description: "Any event, repeating or manually dated, that does not fit the other categories."
|
|
3381
|
+
},
|
|
3382
|
+
class: {
|
|
3383
|
+
label: "Class",
|
|
3384
|
+
pluralLabel: "Classes",
|
|
3385
|
+
description: "Regular scheduled classes and group sessions."
|
|
3386
|
+
},
|
|
3387
|
+
course: {
|
|
3388
|
+
label: "Course",
|
|
3389
|
+
pluralLabel: "Courses",
|
|
3390
|
+
description: "A fixed set of dates that people book together."
|
|
3391
|
+
},
|
|
3392
|
+
term: {
|
|
3393
|
+
label: "Term",
|
|
3394
|
+
pluralLabel: "Terms",
|
|
3395
|
+
description: "A fixed term of sessions that people book together."
|
|
3396
|
+
},
|
|
3397
|
+
workshop: {
|
|
3398
|
+
label: "Workshop",
|
|
3399
|
+
pluralLabel: "Workshops",
|
|
3400
|
+
description: "One-off workshops, day sessions, or special events."
|
|
3401
|
+
},
|
|
3402
|
+
retreat: {
|
|
3403
|
+
label: "Retreat",
|
|
3404
|
+
pluralLabel: "Retreats",
|
|
3405
|
+
description: "Multi-day or residential immersive experiences."
|
|
3406
|
+
},
|
|
3407
|
+
performance: {
|
|
3408
|
+
label: "Performance",
|
|
3409
|
+
pluralLabel: "Performances",
|
|
3410
|
+
description: "Audience-facing shows, concerts, recitals, or showcases."
|
|
3411
|
+
}
|
|
3412
|
+
};
|
|
3413
|
+
//#endregion
|
|
3210
3414
|
//#region ../api/src/publicEventEndpointDefinitions.ts
|
|
3211
3415
|
const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
|
|
3212
3416
|
checkPublicEventRegistrationNextStep: {
|
|
@@ -9457,6 +9661,13 @@ const API_ENDPOINTS$1 = {
|
|
|
9457
9661
|
auth: "public",
|
|
9458
9662
|
responseKind: "json"
|
|
9459
9663
|
},
|
|
9664
|
+
demoClaimReadiness: {
|
|
9665
|
+
path: "/demo/claims/{claimId}/readiness",
|
|
9666
|
+
method: "GET",
|
|
9667
|
+
auth: "user",
|
|
9668
|
+
responseKind: "json",
|
|
9669
|
+
errors: []
|
|
9670
|
+
},
|
|
9460
9671
|
demoClaimMagicLink: {
|
|
9461
9672
|
path: "/demo/auth/send-magic-link",
|
|
9462
9673
|
method: "POST",
|
|
@@ -10362,7 +10573,7 @@ var SimpleCache = class {
|
|
|
10362
10573
|
* 1. This constant
|
|
10363
10574
|
* 2. The "version" field in package.json
|
|
10364
10575
|
*/
|
|
10365
|
-
const SDK_VERSION = "0.
|
|
10576
|
+
const SDK_VERSION = "0.153.0";
|
|
10366
10577
|
//#endregion
|
|
10367
10578
|
//#region src/client/error.ts
|
|
10368
10579
|
let _Symbol$for;
|
|
@@ -15667,7 +15878,96 @@ Object.keys(legacyItemSurfaceCardRoles);
|
|
|
15667
15878
|
*/
|
|
15668
15879
|
const cardRoleWithLegacyAliasSchema = z.preprocess((value) => normalizeCardRole(value) ?? (typeof value === "string" && Object.prototype.hasOwnProperty.call(legacyItemSurfaceCardRoles, value) ? legacyItemSurfaceCardRoles[value] : value), cardRoleSchema);
|
|
15669
15880
|
//#endregion
|
|
15670
|
-
//#region ../
|
|
15881
|
+
//#region ../media-core/src/identifiers.ts
|
|
15882
|
+
function slugifyMediaIdentifier(value) {
|
|
15883
|
+
return value.toLowerCase().trim().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
15884
|
+
}
|
|
15885
|
+
function parseMediaIdentifier(value) {
|
|
15886
|
+
if (typeof value !== "string") return err$1({ kind: "not_string" });
|
|
15887
|
+
const trimmed = value.trim();
|
|
15888
|
+
if (trimmed.length === 0) return err$1({ kind: "empty_identifier" });
|
|
15889
|
+
const normalized = slugifyMediaIdentifier(trimmed);
|
|
15890
|
+
if (normalized.length === 0) return err$1({
|
|
15891
|
+
kind: "empty_after_normalization",
|
|
15892
|
+
value
|
|
15893
|
+
});
|
|
15894
|
+
return ok$1(normalized);
|
|
15895
|
+
}
|
|
15896
|
+
/**
|
|
15897
|
+
* Admits identifiers read from trusted persistence without repairing dirty data in memory.
|
|
15898
|
+
* User input should use parseMediaIdentifier, which intentionally canonicalizes it.
|
|
15899
|
+
*/
|
|
15900
|
+
function parseCanonicalMediaIdentifier(value) {
|
|
15901
|
+
if (typeof value !== "string") return err$1({ kind: "not_string" });
|
|
15902
|
+
const parsed = parseMediaIdentifier(value);
|
|
15903
|
+
if (!parsed.ok) return parsed;
|
|
15904
|
+
if (value !== parsed.value) return err$1({
|
|
15905
|
+
kind: "non_canonical_identifier",
|
|
15906
|
+
value,
|
|
15907
|
+
canonical: parsed.value
|
|
15908
|
+
});
|
|
15909
|
+
return parsed;
|
|
15910
|
+
}
|
|
15911
|
+
//#endregion
|
|
15912
|
+
//#region ../media-core/src/mediaIdentifierSchema.ts
|
|
15913
|
+
/** Strict stored-reference admission delegates the canonical identifier decision. */
|
|
15914
|
+
const mediaIdentifierSchema = z.string().transform((value, context) => {
|
|
15915
|
+
const parsed = parseCanonicalMediaIdentifier(value);
|
|
15916
|
+
if (parsed.ok) return parsed.value;
|
|
15917
|
+
context.addIssue({
|
|
15918
|
+
code: "custom",
|
|
15919
|
+
message: "Expected a canonical media identifier"
|
|
15920
|
+
});
|
|
15921
|
+
return z.NEVER;
|
|
15922
|
+
});
|
|
15923
|
+
//#endregion
|
|
15924
|
+
//#region ../media-core/src/mediaKinds.ts
|
|
15925
|
+
const mediaTypeDiscriminants = [
|
|
15926
|
+
"image",
|
|
15927
|
+
"video",
|
|
15928
|
+
"audio",
|
|
15929
|
+
"document",
|
|
15930
|
+
"spreadsheet",
|
|
15931
|
+
"archive"
|
|
15932
|
+
];
|
|
15933
|
+
//#endregion
|
|
15934
|
+
//#region ../media-core/src/renderableMediaAsset.ts
|
|
15935
|
+
/** A portable reference never uses an incidental UUID, URL or storage snapshot for identity. */
|
|
15936
|
+
function resolveManagedMediaReference(reference, index) {
|
|
15937
|
+
const asset = index?.byIdentifier.get(reference.identifier);
|
|
15938
|
+
return asset ? {
|
|
15939
|
+
kind: "resolved",
|
|
15940
|
+
reference,
|
|
15941
|
+
asset
|
|
15942
|
+
} : {
|
|
15943
|
+
kind: "missing",
|
|
15944
|
+
reference
|
|
15945
|
+
};
|
|
15946
|
+
}
|
|
15947
|
+
//#endregion
|
|
15948
|
+
//#region ../media-core/src/renderableMediaAssetAdmission.ts
|
|
15949
|
+
const mediaAssetIdSchema = z.string().transform((value, context) => {
|
|
15950
|
+
const parsed = parseMediaAssetId(value);
|
|
15951
|
+
if (parsed.ok) return parsed.value;
|
|
15952
|
+
context.addIssue({
|
|
15953
|
+
code: "custom",
|
|
15954
|
+
message: "Expected a media asset ID"
|
|
15955
|
+
});
|
|
15956
|
+
return z.NEVER;
|
|
15957
|
+
});
|
|
15958
|
+
const nonemptyStorageValue = z.string().refine((value) => value.trim().length > 0);
|
|
15959
|
+
const renderableMediaAssetSchema = z.object({
|
|
15960
|
+
id: mediaAssetIdSchema,
|
|
15961
|
+
identifier: mediaIdentifierSchema,
|
|
15962
|
+
storageBucket: nonemptyStorageValue,
|
|
15963
|
+
storagePath: nonemptyStorageValue,
|
|
15964
|
+
mimeType: nonemptyStorageValue,
|
|
15965
|
+
filename: z.string().optional(),
|
|
15966
|
+
width: z.number().positive().nullable(),
|
|
15967
|
+
height: z.number().positive().nullable()
|
|
15968
|
+
});
|
|
15969
|
+
//#endregion
|
|
15970
|
+
//#region ../media-core/src/media.ts
|
|
15671
15971
|
const hotspotSchema = z.object({
|
|
15672
15972
|
x: z.number().min(0).max(1),
|
|
15673
15973
|
y: z.number().min(0).max(1),
|
|
@@ -15701,56 +16001,185 @@ const transformSchema = z.object({
|
|
|
15701
16001
|
rotation: rotationSchema.optional()
|
|
15702
16002
|
});
|
|
15703
16003
|
const mediaPosterSchema = z.discriminatedUnion("tag", [z.object({
|
|
15704
|
-
tag: z.literal("
|
|
15705
|
-
|
|
15706
|
-
|
|
15707
|
-
storagePath: z.string().min(1)
|
|
15708
|
-
}), z.object({
|
|
16004
|
+
tag: z.literal("media"),
|
|
16005
|
+
identifier: mediaIdentifierSchema
|
|
16006
|
+
}).strict(), z.object({
|
|
15709
16007
|
tag: z.literal("external-src"),
|
|
15710
|
-
assetId: z.string().optional(),
|
|
15711
16008
|
src: z.string().url()
|
|
15712
|
-
})]);
|
|
15713
|
-
const
|
|
16009
|
+
}).strict()]);
|
|
16010
|
+
const mediaUsageShape = {
|
|
15714
16011
|
purpose: z.string().optional(),
|
|
15715
16012
|
placeholder: z.boolean().default(true).optional(),
|
|
15716
|
-
assetId: z.string().optional(),
|
|
15717
|
-
identifier: z.string().optional(),
|
|
15718
|
-
src: z.string().optional(),
|
|
15719
16013
|
alt: z.string().optional(),
|
|
15720
16014
|
filename: z.string().optional(),
|
|
15721
|
-
mimeType: z.string().optional(),
|
|
15722
16015
|
width: z.number().optional(),
|
|
15723
16016
|
height: z.number().optional(),
|
|
15724
|
-
storageBucket: z.string().optional(),
|
|
15725
|
-
storagePath: z.string().optional(),
|
|
15726
16017
|
poster: mediaPosterSchema.optional(),
|
|
15727
16018
|
transform: transformSchema.optional()
|
|
15728
|
-
}
|
|
15729
|
-
const
|
|
16019
|
+
};
|
|
16020
|
+
const environmentExclusions = {
|
|
16021
|
+
assetId: z.never().optional(),
|
|
16022
|
+
id: z.never().optional(),
|
|
16023
|
+
src: z.never().optional(),
|
|
16024
|
+
storageBucket: z.never().optional(),
|
|
16025
|
+
storagePath: z.never().optional(),
|
|
16026
|
+
mimeType: z.never().optional()
|
|
16027
|
+
};
|
|
16028
|
+
const mediaBaseSchema = z.object({
|
|
16029
|
+
...mediaUsageShape,
|
|
16030
|
+
...environmentExclusions,
|
|
16031
|
+
identifier: mediaIdentifierSchema
|
|
16032
|
+
}).strict();
|
|
15730
16033
|
const imageMediaSchema = mediaBaseSchema.extend({ type: z.literal("image") });
|
|
15731
16034
|
const videoMediaSchema = mediaBaseSchema.extend({ type: z.literal("video") });
|
|
15732
|
-
const
|
|
15733
|
-
const
|
|
15734
|
-
|
|
15735
|
-
|
|
15736
|
-
|
|
15737
|
-
|
|
15738
|
-
|
|
15739
|
-
|
|
15740
|
-
|
|
15741
|
-
|
|
15742
|
-
|
|
15743
|
-
|
|
15744
|
-
|
|
15745
|
-
z.
|
|
15746
|
-
|
|
15747
|
-
|
|
15748
|
-
|
|
15749
|
-
|
|
15750
|
-
|
|
15751
|
-
persistableMediaBaseSchema.extend({ type: z.literal("archive") })
|
|
16035
|
+
const mediaSchema = mediaBaseSchema.extend({ type: z.enum(mediaTypeDiscriminants) });
|
|
16036
|
+
const externalMediaSchema = z.object({
|
|
16037
|
+
...mediaUsageShape,
|
|
16038
|
+
...environmentExclusions,
|
|
16039
|
+
type: z.enum(mediaTypeDiscriminants),
|
|
16040
|
+
src: z.string().min(1),
|
|
16041
|
+
identifier: z.never().optional()
|
|
16042
|
+
}).strict();
|
|
16043
|
+
const assetMediaSchema = z.object({
|
|
16044
|
+
...mediaUsageShape,
|
|
16045
|
+
...environmentExclusions,
|
|
16046
|
+
type: z.enum(mediaTypeDiscriminants),
|
|
16047
|
+
asset: renderableMediaAssetSchema,
|
|
16048
|
+
identifier: z.never().optional()
|
|
16049
|
+
}).strict();
|
|
16050
|
+
const runtimeMediaSchema = z.union([
|
|
16051
|
+
mediaSchema,
|
|
16052
|
+
externalMediaSchema,
|
|
16053
|
+
assetMediaSchema
|
|
15752
16054
|
]);
|
|
15753
16055
|
//#endregion
|
|
16056
|
+
//#region ../media-core/src/typeGuards.ts
|
|
16057
|
+
function isRecord$12(value) {
|
|
16058
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
16059
|
+
}
|
|
16060
|
+
//#endregion
|
|
16061
|
+
//#region ../media-core/src/transformRect.ts
|
|
16062
|
+
function isValidTransformRectStructure(rect) {
|
|
16063
|
+
if (!Array.isArray(rect) || rect.length !== 4) return false;
|
|
16064
|
+
const [left, top, width, height] = rect;
|
|
16065
|
+
return Number.isFinite(left) && Number.isFinite(top) && Number.isFinite(width) && Number.isFinite(height) && left >= 0 && top >= 0 && width > 0 && height > 0;
|
|
16066
|
+
}
|
|
16067
|
+
//#endregion
|
|
16068
|
+
//#region ../media-core/src/aspectTransforms.ts
|
|
16069
|
+
const DEFAULT_RECT_EPSILON = .5;
|
|
16070
|
+
function parseAspectRatioValue(value) {
|
|
16071
|
+
if (typeof value === "number") return Number.isFinite(value) && value > 0 ? value : void 0;
|
|
16072
|
+
if (typeof value !== "string") return void 0;
|
|
16073
|
+
const normalized = value.trim();
|
|
16074
|
+
if (!normalized) return void 0;
|
|
16075
|
+
if (normalized === "auto") return void 0;
|
|
16076
|
+
if (normalized.includes(":") || normalized.includes("/")) {
|
|
16077
|
+
const delimiter = normalized.includes(":") ? ":" : "/";
|
|
16078
|
+
const [wRaw, hRaw] = normalized.split(delimiter);
|
|
16079
|
+
const width = Number(wRaw?.trim());
|
|
16080
|
+
const height = Number(hRaw?.trim());
|
|
16081
|
+
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return;
|
|
16082
|
+
return width / height;
|
|
16083
|
+
}
|
|
16084
|
+
const numeric = Number(normalized);
|
|
16085
|
+
if (!Number.isFinite(numeric) || numeric <= 0) return void 0;
|
|
16086
|
+
return numeric;
|
|
16087
|
+
}
|
|
16088
|
+
const MAX_ASPECT_DISTANCE = .25;
|
|
16089
|
+
function resolveMediaTransformForAspect(transform, targetAspect) {
|
|
16090
|
+
if (!transform) return {};
|
|
16091
|
+
const base = {
|
|
16092
|
+
rect: transform.rect,
|
|
16093
|
+
hotspot: transform.hotspot,
|
|
16094
|
+
rotation: transform.rotation
|
|
16095
|
+
};
|
|
16096
|
+
const target = parseAspectRatioValue(targetAspect);
|
|
16097
|
+
const crops = transform.aspectCrops;
|
|
16098
|
+
if (!target || !crops || Object.keys(crops).length === 0) return base;
|
|
16099
|
+
let best = null;
|
|
16100
|
+
let bestDistance = Number.POSITIVE_INFINITY;
|
|
16101
|
+
for (const [key, candidate] of Object.entries(crops)) {
|
|
16102
|
+
const candidateAspect = parseAspectRatioValue(candidate.aspect ?? key);
|
|
16103
|
+
if (!candidateAspect) continue;
|
|
16104
|
+
const distance = Math.abs(Math.log(candidateAspect / target));
|
|
16105
|
+
if (distance < bestDistance) {
|
|
16106
|
+
best = candidate;
|
|
16107
|
+
bestDistance = distance;
|
|
16108
|
+
}
|
|
16109
|
+
}
|
|
16110
|
+
if (!best) return base;
|
|
16111
|
+
if (bestDistance > MAX_ASPECT_DISTANCE) return base;
|
|
16112
|
+
return {
|
|
16113
|
+
rect: best.rect ?? base.rect,
|
|
16114
|
+
hotspot: best.hotspot ?? base.hotspot,
|
|
16115
|
+
rotation: best.rotation ?? base.rotation
|
|
16116
|
+
};
|
|
16117
|
+
}
|
|
16118
|
+
function isValidTransformRect(rect) {
|
|
16119
|
+
return isValidTransformRectStructure(rect);
|
|
16120
|
+
}
|
|
16121
|
+
function isExplicitRectCrop(rect, sourceWidth, sourceHeight, epsilon = DEFAULT_RECT_EPSILON) {
|
|
16122
|
+
if (!isValidTransformRect(rect)) return false;
|
|
16123
|
+
if (!(typeof sourceWidth === "number" && Number.isFinite(sourceWidth) && sourceWidth > 0 && typeof sourceHeight === "number" && Number.isFinite(sourceHeight) && sourceHeight > 0)) return true;
|
|
16124
|
+
const [x, y, width, height] = rect;
|
|
16125
|
+
return !(Math.abs(x) <= epsilon && Math.abs(y) <= epsilon && Math.abs(width - sourceWidth) <= epsilon && Math.abs(height - sourceHeight) <= epsilon);
|
|
16126
|
+
}
|
|
16127
|
+
//#endregion
|
|
16128
|
+
//#region ../media-core/src/rotation.ts
|
|
16129
|
+
function rotateNormalizedPoint(point, rotation) {
|
|
16130
|
+
const x = point.x;
|
|
16131
|
+
const y = point.y;
|
|
16132
|
+
switch (rotation) {
|
|
16133
|
+
case 0: return {
|
|
16134
|
+
x,
|
|
16135
|
+
y
|
|
16136
|
+
};
|
|
16137
|
+
case 90: return {
|
|
16138
|
+
x: 1 - y,
|
|
16139
|
+
y: x
|
|
16140
|
+
};
|
|
16141
|
+
case 180: return {
|
|
16142
|
+
x: 1 - x,
|
|
16143
|
+
y: 1 - y
|
|
16144
|
+
};
|
|
16145
|
+
case 270: return {
|
|
16146
|
+
x: y,
|
|
16147
|
+
y: 1 - x
|
|
16148
|
+
};
|
|
16149
|
+
}
|
|
16150
|
+
}
|
|
16151
|
+
//#endregion
|
|
16152
|
+
//#region ../media-core/src/mediaRefNormalizer.ts
|
|
16153
|
+
function looksLikeUuid(value) {
|
|
16154
|
+
return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
16155
|
+
}
|
|
16156
|
+
/**
|
|
16157
|
+
* Strip environment-specific keys from a CMS media object.
|
|
16158
|
+
* @mutates Mutates the passed object in-place.
|
|
16159
|
+
*/
|
|
16160
|
+
function deleteEnvSpecificKeys(obj) {
|
|
16161
|
+
delete obj.assetId;
|
|
16162
|
+
delete obj.storageBucket;
|
|
16163
|
+
delete obj.storagePath;
|
|
16164
|
+
delete obj.src;
|
|
16165
|
+
delete obj.mimeType;
|
|
16166
|
+
delete obj.id;
|
|
16167
|
+
}
|
|
16168
|
+
//#endregion
|
|
16169
|
+
//#region ../media-core/src/richTextImageCollector.ts
|
|
16170
|
+
function walkAndCollectImageAttrs(value, out, location = "") {
|
|
16171
|
+
if (Array.isArray(value)) {
|
|
16172
|
+
value.forEach((item, index) => walkAndCollectImageAttrs(item, out, `${location}[${index}]`));
|
|
16173
|
+
return;
|
|
16174
|
+
}
|
|
16175
|
+
if (!isRecord$12(value)) return;
|
|
16176
|
+
if (value.type === "image" && isRecord$12(value.attrs)) out.push({
|
|
16177
|
+
attrs: value.attrs,
|
|
16178
|
+
location: location ? `${location}.attrs` : "attrs"
|
|
16179
|
+
});
|
|
16180
|
+
for (const [key, child] of Object.entries(value)) walkAndCollectImageAttrs(child, out, location ? `${location}.${key}` : key);
|
|
16181
|
+
}
|
|
16182
|
+
//#endregion
|
|
15754
16183
|
//#region ../theme-core/src/site-styles/rawStyleFields.ts
|
|
15755
16184
|
const themeV2RuntimeStyleFieldNames = [
|
|
15756
16185
|
"_frameStyles",
|
|
@@ -15838,8 +16267,23 @@ const boxBackgroundSchema = z.discriminatedUnion("type", [
|
|
|
15838
16267
|
showVideoOnMobile: z.boolean().nullable().optional()
|
|
15839
16268
|
})
|
|
15840
16269
|
]);
|
|
16270
|
+
/** Application rendering sources are admitted separately from saved references. */
|
|
16271
|
+
const runtimeBoxBackgroundSchema = z.discriminatedUnion("type", [
|
|
16272
|
+
boxBackgroundSchema.options[0],
|
|
16273
|
+
boxBackgroundSchema.options[1],
|
|
16274
|
+
boxBackgroundSchema.options[2].extend({ image: z.union([
|
|
16275
|
+
imageMediaSchema,
|
|
16276
|
+
externalMediaSchema.extend({ type: z.literal("image") }),
|
|
16277
|
+
assetMediaSchema.extend({ type: z.literal("image") })
|
|
16278
|
+
]).nullable().optional() }),
|
|
16279
|
+
boxBackgroundSchema.options[3].extend({ image: z.union([
|
|
16280
|
+
videoMediaSchema,
|
|
16281
|
+
externalMediaSchema.extend({ type: z.literal("video") }),
|
|
16282
|
+
assetMediaSchema.extend({ type: z.literal("video") })
|
|
16283
|
+
]).nullable().optional() })
|
|
16284
|
+
]);
|
|
15841
16285
|
function normalizeAuthoringOpacity(value) {
|
|
15842
|
-
if (!isRecord$
|
|
16286
|
+
if (!isRecord$11(value)) return value;
|
|
15843
16287
|
return {
|
|
15844
16288
|
...value,
|
|
15845
16289
|
opacity: normalizeOpacity(value.opacity)
|
|
@@ -15848,7 +16292,7 @@ function normalizeAuthoringOpacity(value) {
|
|
|
15848
16292
|
function normalizeOpacity(value) {
|
|
15849
16293
|
return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
|
|
15850
16294
|
}
|
|
15851
|
-
function isRecord$
|
|
16295
|
+
function isRecord$11(value) {
|
|
15852
16296
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15853
16297
|
}
|
|
15854
16298
|
//#endregion
|
|
@@ -30428,133 +30872,6 @@ const linkSchema = z.union([
|
|
|
30428
30872
|
entryLinkSchema$1
|
|
30429
30873
|
]);
|
|
30430
30874
|
//#endregion
|
|
30431
|
-
//#region ../media-core/src/typeGuards.ts
|
|
30432
|
-
function isRecord$11(value) {
|
|
30433
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
30434
|
-
}
|
|
30435
|
-
//#endregion
|
|
30436
|
-
//#region ../media-core/src/transformRect.ts
|
|
30437
|
-
function isValidTransformRectStructure(rect) {
|
|
30438
|
-
if (!Array.isArray(rect) || rect.length !== 4) return false;
|
|
30439
|
-
const [left, top, width, height] = rect;
|
|
30440
|
-
return Number.isFinite(left) && Number.isFinite(top) && Number.isFinite(width) && Number.isFinite(height) && left >= 0 && top >= 0 && width > 0 && height > 0;
|
|
30441
|
-
}
|
|
30442
|
-
//#endregion
|
|
30443
|
-
//#region ../media-core/src/aspectTransforms.ts
|
|
30444
|
-
const DEFAULT_RECT_EPSILON = .5;
|
|
30445
|
-
function parseAspectRatioValue(value) {
|
|
30446
|
-
if (typeof value === "number") return Number.isFinite(value) && value > 0 ? value : void 0;
|
|
30447
|
-
if (typeof value !== "string") return void 0;
|
|
30448
|
-
const normalized = value.trim();
|
|
30449
|
-
if (!normalized) return void 0;
|
|
30450
|
-
if (normalized === "auto") return void 0;
|
|
30451
|
-
if (normalized.includes(":") || normalized.includes("/")) {
|
|
30452
|
-
const delimiter = normalized.includes(":") ? ":" : "/";
|
|
30453
|
-
const [wRaw, hRaw] = normalized.split(delimiter);
|
|
30454
|
-
const width = Number(wRaw?.trim());
|
|
30455
|
-
const height = Number(hRaw?.trim());
|
|
30456
|
-
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return;
|
|
30457
|
-
return width / height;
|
|
30458
|
-
}
|
|
30459
|
-
const numeric = Number(normalized);
|
|
30460
|
-
if (!Number.isFinite(numeric) || numeric <= 0) return void 0;
|
|
30461
|
-
return numeric;
|
|
30462
|
-
}
|
|
30463
|
-
const MAX_ASPECT_DISTANCE = .25;
|
|
30464
|
-
function resolveMediaTransformForAspect(transform, targetAspect) {
|
|
30465
|
-
if (!transform) return {};
|
|
30466
|
-
const base = {
|
|
30467
|
-
rect: transform.rect,
|
|
30468
|
-
hotspot: transform.hotspot,
|
|
30469
|
-
rotation: transform.rotation
|
|
30470
|
-
};
|
|
30471
|
-
const target = parseAspectRatioValue(targetAspect);
|
|
30472
|
-
const crops = transform.aspectCrops;
|
|
30473
|
-
if (!target || !crops || Object.keys(crops).length === 0) return base;
|
|
30474
|
-
let best = null;
|
|
30475
|
-
let bestDistance = Number.POSITIVE_INFINITY;
|
|
30476
|
-
for (const [key, candidate] of Object.entries(crops)) {
|
|
30477
|
-
const candidateAspect = parseAspectRatioValue(candidate.aspect ?? key);
|
|
30478
|
-
if (!candidateAspect) continue;
|
|
30479
|
-
const distance = Math.abs(Math.log(candidateAspect / target));
|
|
30480
|
-
if (distance < bestDistance) {
|
|
30481
|
-
best = candidate;
|
|
30482
|
-
bestDistance = distance;
|
|
30483
|
-
}
|
|
30484
|
-
}
|
|
30485
|
-
if (!best) return base;
|
|
30486
|
-
if (bestDistance > MAX_ASPECT_DISTANCE) return base;
|
|
30487
|
-
return {
|
|
30488
|
-
rect: best.rect ?? base.rect,
|
|
30489
|
-
hotspot: best.hotspot ?? base.hotspot,
|
|
30490
|
-
rotation: best.rotation ?? base.rotation
|
|
30491
|
-
};
|
|
30492
|
-
}
|
|
30493
|
-
function isValidTransformRect(rect) {
|
|
30494
|
-
return isValidTransformRectStructure(rect);
|
|
30495
|
-
}
|
|
30496
|
-
function isExplicitRectCrop(rect, sourceWidth, sourceHeight, epsilon = DEFAULT_RECT_EPSILON) {
|
|
30497
|
-
if (!isValidTransformRect(rect)) return false;
|
|
30498
|
-
if (!(typeof sourceWidth === "number" && Number.isFinite(sourceWidth) && sourceWidth > 0 && typeof sourceHeight === "number" && Number.isFinite(sourceHeight) && sourceHeight > 0)) return true;
|
|
30499
|
-
const [x, y, width, height] = rect;
|
|
30500
|
-
return !(Math.abs(x) <= epsilon && Math.abs(y) <= epsilon && Math.abs(width - sourceWidth) <= epsilon && Math.abs(height - sourceHeight) <= epsilon);
|
|
30501
|
-
}
|
|
30502
|
-
//#endregion
|
|
30503
|
-
//#region ../media-core/src/rotation.ts
|
|
30504
|
-
function rotateNormalizedPoint(point, rotation) {
|
|
30505
|
-
const x = point.x;
|
|
30506
|
-
const y = point.y;
|
|
30507
|
-
switch (rotation) {
|
|
30508
|
-
case 0: return {
|
|
30509
|
-
x,
|
|
30510
|
-
y
|
|
30511
|
-
};
|
|
30512
|
-
case 90: return {
|
|
30513
|
-
x: 1 - y,
|
|
30514
|
-
y: x
|
|
30515
|
-
};
|
|
30516
|
-
case 180: return {
|
|
30517
|
-
x: 1 - x,
|
|
30518
|
-
y: 1 - y
|
|
30519
|
-
};
|
|
30520
|
-
case 270: return {
|
|
30521
|
-
x: y,
|
|
30522
|
-
y: 1 - x
|
|
30523
|
-
};
|
|
30524
|
-
}
|
|
30525
|
-
}
|
|
30526
|
-
//#endregion
|
|
30527
|
-
//#region ../media-core/src/mediaRefNormalizer.ts
|
|
30528
|
-
function looksLikeUuid(value) {
|
|
30529
|
-
return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
30530
|
-
}
|
|
30531
|
-
/**
|
|
30532
|
-
* Strip environment-specific keys from a CMS media object.
|
|
30533
|
-
* @mutates Mutates the passed object in-place.
|
|
30534
|
-
*/
|
|
30535
|
-
function deleteEnvSpecificKeys(obj) {
|
|
30536
|
-
delete obj.assetId;
|
|
30537
|
-
delete obj.storageBucket;
|
|
30538
|
-
delete obj.storagePath;
|
|
30539
|
-
delete obj.src;
|
|
30540
|
-
delete obj.mimeType;
|
|
30541
|
-
if (looksLikeUuid(obj.id)) delete obj.id;
|
|
30542
|
-
}
|
|
30543
|
-
//#endregion
|
|
30544
|
-
//#region ../media-core/src/richTextImageCollector.ts
|
|
30545
|
-
function walkAndCollectImageAttrs(value, out, location = "") {
|
|
30546
|
-
if (Array.isArray(value)) {
|
|
30547
|
-
value.forEach((item, index) => walkAndCollectImageAttrs(item, out, `${location}[${index}]`));
|
|
30548
|
-
return;
|
|
30549
|
-
}
|
|
30550
|
-
if (!isRecord$11(value)) return;
|
|
30551
|
-
if (value.type === "image" && isRecord$11(value.attrs)) out.push({
|
|
30552
|
-
attrs: value.attrs,
|
|
30553
|
-
location: location ? `${location}.attrs` : "attrs"
|
|
30554
|
-
});
|
|
30555
|
-
for (const [key, child] of Object.entries(value)) walkAndCollectImageAttrs(child, out, location ? `${location}.${key}` : key);
|
|
30556
|
-
}
|
|
30557
|
-
//#endregion
|
|
30558
30875
|
//#region ../blocks/src/system/node/schema.ts
|
|
30559
30876
|
const transformStepSchema = z.object({
|
|
30560
30877
|
id: z.string().min(1, "Transform requires an identifier"),
|
|
@@ -32252,7 +32569,8 @@ function validationContext(options = {}) {
|
|
|
32252
32569
|
const isDraft = options.mode === "draft";
|
|
32253
32570
|
return {
|
|
32254
32571
|
allowNull: options.allowNull ?? true,
|
|
32255
|
-
allowIncomplete: isDraft || (options.allowIncomplete ?? false)
|
|
32572
|
+
allowIncomplete: isDraft || (options.allowIncomplete ?? false),
|
|
32573
|
+
mode: options.mode ?? "strict"
|
|
32256
32574
|
};
|
|
32257
32575
|
}
|
|
32258
32576
|
function strictValidationContext(options = {}) {
|
|
@@ -32626,7 +32944,7 @@ function validateNormalizedFieldValue(plan, value, ctx) {
|
|
|
32626
32944
|
case "select": return validateSelectPlan(plan, value);
|
|
32627
32945
|
case "richText": return isValidRichTextDoc(value) ? [] : [issue(plan, "invalidRichText")];
|
|
32628
32946
|
case "inlineText": return validateInlineTextPlan(plan, value);
|
|
32629
|
-
case "media": return
|
|
32947
|
+
case "media": return validateMediaPlan(plan, value, ctx);
|
|
32630
32948
|
case "link": return linkSchema.safeParse(value).success ? [] : [issue(plan, "invalidLink")];
|
|
32631
32949
|
case "repeater": return validateRepeaterPlan(plan, value, ctx);
|
|
32632
32950
|
case "group": return validateGroupPlan(plan, value, ctx);
|
|
@@ -32634,6 +32952,15 @@ function validateNormalizedFieldValue(plan, value, ctx) {
|
|
|
32634
32952
|
default: return assertNever$4(plan);
|
|
32635
32953
|
}
|
|
32636
32954
|
}
|
|
32955
|
+
function validateMediaPlan(plan, value, ctx) {
|
|
32956
|
+
if (!isPlainObject$2(value)) return [issue(plan, "invalidMedia")];
|
|
32957
|
+
const allowedKind = value.type === void 0 || typeof value.type === "string" && plan.allowedMediaTypes.includes(value.type);
|
|
32958
|
+
const admitted = ctx.mode === "render" ? runtimeMediaSchema.safeParse({
|
|
32959
|
+
...value,
|
|
32960
|
+
type: value.type ?? plan.allowedMediaTypes[0]
|
|
32961
|
+
}).success : mediaIdentifierSchema.safeParse(value.identifier).success;
|
|
32962
|
+
return allowedKind && admitted ? [] : [issue(plan, "invalidMedia")];
|
|
32963
|
+
}
|
|
32637
32964
|
function shouldRequireValue(plan, value, ctx) {
|
|
32638
32965
|
if (!plan.required || ctx.allowIncomplete) return false;
|
|
32639
32966
|
if (value === null && ctx.allowNull) return false;
|
|
@@ -32758,7 +33085,7 @@ function validateGroupPlan(plan, value, ctx) {
|
|
|
32758
33085
|
const childCtx = childValidationContext(plan, ctx);
|
|
32759
33086
|
const childIssues = selectedGroupChildPlans(plan, value).flatMap((childPlan) => validateNormalizedFieldValue(childPlan, value[childPlan.fieldId], childCtx));
|
|
32760
33087
|
if (childIssues.length > 0) return childIssues;
|
|
32761
|
-
if (plan.valueContract === "boxBackground" && !boxBackgroundSchema.safeParse(value).success) return [issue(plan, "invalidBoxBackground")];
|
|
33088
|
+
if (plan.valueContract === "boxBackground" && !(ctx.mode === "render" ? runtimeBoxBackgroundSchema : boxBackgroundSchema).safeParse(value).success) return [issue(plan, "invalidBoxBackground")];
|
|
32762
33089
|
return [];
|
|
32763
33090
|
}
|
|
32764
33091
|
function childValidationContext(plan, ctx) {
|
|
@@ -32858,11 +33185,16 @@ function fieldPlanToObjectPropertyZod(plan, options = {}) {
|
|
|
32858
33185
|
default: return assertNever$4(presence);
|
|
32859
33186
|
}
|
|
32860
33187
|
}
|
|
32861
|
-
/** Validate stored
|
|
32862
|
-
function
|
|
32863
|
-
const ctx = strictValidationContext({
|
|
33188
|
+
/** Validate stored or runtime fields without applying editor/write normalization. */
|
|
33189
|
+
function fieldPlanToStrictObjectPropertyZod(plan, mode = "strict") {
|
|
33190
|
+
const ctx = strictValidationContext({
|
|
33191
|
+
allowNull: false,
|
|
33192
|
+
mode
|
|
33193
|
+
});
|
|
32864
33194
|
const schema = z.any().superRefine((value, zodCtx) => {
|
|
32865
|
-
|
|
33195
|
+
validateNormalizedFieldValue(plan, value, ctx).forEach((validationIssue) => {
|
|
33196
|
+
addFieldIssueToZodContext(zodCtx, validationIssue, plan.path);
|
|
33197
|
+
});
|
|
32866
33198
|
});
|
|
32867
33199
|
return plan.required ? schema : schema.optional();
|
|
32868
33200
|
}
|
|
@@ -33065,7 +33397,7 @@ function preprocessEmptyValues(content) {
|
|
|
33065
33397
|
function compileManifestContentContract(manifestOrFields) {
|
|
33066
33398
|
const plans = derivePlansFromManifestOrFields(manifestOrFields);
|
|
33067
33399
|
const strictOptions = { allowNull: false };
|
|
33068
|
-
const strictStoredSchema =
|
|
33400
|
+
const strictStoredSchema = deriveStrictContentZodFromPlans(plans);
|
|
33069
33401
|
return Object.freeze({ [compiledManifestContentContract]: Object.freeze({
|
|
33070
33402
|
plans,
|
|
33071
33403
|
strictStoredSchema,
|
|
@@ -33075,7 +33407,7 @@ function compileManifestContentContract(manifestOrFields) {
|
|
|
33075
33407
|
allowIncomplete: true,
|
|
33076
33408
|
mode: "draft"
|
|
33077
33409
|
}, normalizeStoredContentValues),
|
|
33078
|
-
renderSchema:
|
|
33410
|
+
renderSchema: deriveStrictContentZodFromPlans(plans, "render"),
|
|
33079
33411
|
findNonPortableMediaPaths: (content) => findNonPortableMediaPaths(plans, content)
|
|
33080
33412
|
}) });
|
|
33081
33413
|
}
|
|
@@ -33105,9 +33437,8 @@ function deriveContentZodFromPlans(plans, options) {
|
|
|
33105
33437
|
for (const plan of plans) shape[plan.fieldId] = fieldPlanToObjectPropertyZod(plan, options);
|
|
33106
33438
|
return z.object(shape).catchall(z.unknown()).passthrough();
|
|
33107
33439
|
}
|
|
33108
|
-
function
|
|
33109
|
-
const shape =
|
|
33110
|
-
for (const plan of plans) shape[plan.fieldId] = fieldPlanToStoredObjectPropertyZod(plan);
|
|
33440
|
+
function deriveStrictContentZodFromPlans(plans, mode = "strict") {
|
|
33441
|
+
const shape = Object.fromEntries(plans.map((plan) => [plan.fieldId, fieldPlanToStrictObjectPropertyZod(plan, mode)]));
|
|
33111
33442
|
return z.object(shape).catchall(z.unknown()).passthrough();
|
|
33112
33443
|
}
|
|
33113
33444
|
function derivePlansFromManifestOrFields(manifestOrFields) {
|
|
@@ -33131,41 +33462,51 @@ function findNonPortableMediaPaths(plans, content) {
|
|
|
33131
33462
|
collectNonPortablePlannedMedia(plans, content, [], paths);
|
|
33132
33463
|
return [...paths].sort();
|
|
33133
33464
|
}
|
|
33134
|
-
|
|
33465
|
+
/** One descriptor walker covers references and stored portability, including inactive retained fields. */
|
|
33466
|
+
function visitPlannedMedia(plans, content, parentPath, visit) {
|
|
33135
33467
|
if (!isPlainRecord(content)) return;
|
|
33136
|
-
|
|
33137
|
-
if (!(plan.fieldId in content))
|
|
33468
|
+
plans.forEach((plan) => {
|
|
33469
|
+
if (!(plan.fieldId in content)) return;
|
|
33138
33470
|
const value = content[plan.fieldId];
|
|
33139
33471
|
const path = [...parentPath, plan.fieldId];
|
|
33140
33472
|
switch (plan.kind) {
|
|
33141
33473
|
case "media":
|
|
33142
|
-
|
|
33143
|
-
|
|
33474
|
+
visit(isPlainRecord(value) ? {
|
|
33475
|
+
...value,
|
|
33476
|
+
type: value.type ?? plan.allowedMediaTypes[0]
|
|
33477
|
+
} : value, path, "media");
|
|
33478
|
+
return;
|
|
33144
33479
|
case "richText":
|
|
33145
|
-
|
|
33146
|
-
|
|
33480
|
+
visit(value, path, "richText");
|
|
33481
|
+
return;
|
|
33147
33482
|
case "group":
|
|
33148
|
-
|
|
33149
|
-
|
|
33483
|
+
visitPlannedMedia(allGroupChildPlans(plan), value, path, visit);
|
|
33484
|
+
return;
|
|
33150
33485
|
case "repeater":
|
|
33151
|
-
|
|
33152
|
-
|
|
33153
|
-
case "string":
|
|
33154
|
-
case "number":
|
|
33486
|
+
visitRepeatedMedia(plan, value, path, visit);
|
|
33487
|
+
return;
|
|
33155
33488
|
case "boolean":
|
|
33156
33489
|
case "inlineText":
|
|
33157
33490
|
case "link":
|
|
33491
|
+
case "number":
|
|
33492
|
+
case "passthrough":
|
|
33158
33493
|
case "select":
|
|
33159
|
-
case "
|
|
33494
|
+
case "string": return;
|
|
33160
33495
|
}
|
|
33161
|
-
}
|
|
33496
|
+
});
|
|
33162
33497
|
}
|
|
33163
|
-
function
|
|
33498
|
+
function visitRepeatedMedia(plan, value, path, visit) {
|
|
33164
33499
|
if (!Array.isArray(value)) return;
|
|
33165
33500
|
value.forEach((item, index) => {
|
|
33166
33501
|
if (!isPlainRecord(item)) return;
|
|
33167
|
-
const
|
|
33168
|
-
if (
|
|
33502
|
+
const fields = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === item._type)?.fields : plan.repeatedItemPlan;
|
|
33503
|
+
if (fields) visitPlannedMedia(fields, item, [...path, index], visit);
|
|
33504
|
+
});
|
|
33505
|
+
}
|
|
33506
|
+
function collectNonPortablePlannedMedia(plans, content, parentPath, paths) {
|
|
33507
|
+
visitPlannedMedia(plans, content, parentPath, (value, path, kind) => {
|
|
33508
|
+
if (kind === "richText") collectNonPortableRichTextImages(value, path, paths);
|
|
33509
|
+
else if (isPlainRecord(value) && (hasEnvironmentSpecificMediaField(value) || hasNonPortablePoster(value))) paths.add(formatFieldPath(path));
|
|
33169
33510
|
});
|
|
33170
33511
|
}
|
|
33171
33512
|
function collectNonPortableRichTextImages(value, path, paths) {
|
|
@@ -33180,6 +33521,10 @@ function isPlainRecord(value) {
|
|
|
33180
33521
|
function hasEnvironmentSpecificMediaField(value) {
|
|
33181
33522
|
return "assetId" in value || "storageBucket" in value || "storagePath" in value || "src" in value || "mimeType" in value || looksLikeUuid(value.id);
|
|
33182
33523
|
}
|
|
33524
|
+
function hasNonPortablePoster(value) {
|
|
33525
|
+
if (value.poster === void 0) return false;
|
|
33526
|
+
return !mediaPosterSchema.safeParse(value.poster).success;
|
|
33527
|
+
}
|
|
33183
33528
|
//#endregion
|
|
33184
33529
|
//#region ../blocks/src/system/designCapabilities.ts
|
|
33185
33530
|
function declareBlockDesignCapability(capability) {
|
|
@@ -35165,6 +35510,12 @@ function parseBackgroundOverlay(value) {
|
|
|
35165
35510
|
const result = boxBackgroundOverlaySchema.safeParse(value);
|
|
35166
35511
|
return result.success ? result.data : void 0;
|
|
35167
35512
|
}
|
|
35513
|
+
/** Rendering accepts explicit application sources separately from stored references. */
|
|
35514
|
+
const runtimeBackgroundContentSchema = runtimeBoxBackgroundSchema;
|
|
35515
|
+
function parseRuntimeBackgroundContent(value) {
|
|
35516
|
+
const result = runtimeBackgroundContentSchema.safeParse(value);
|
|
35517
|
+
return result.success ? result.data : null;
|
|
35518
|
+
}
|
|
35168
35519
|
//#endregion
|
|
35169
35520
|
//#region ../blocks/src/system/transforms/registry/_utils/themeColorResolution.ts
|
|
35170
35521
|
function resolveBackgroundColorValue(value, context) {
|
|
@@ -40015,6 +40366,15 @@ const formBlockDefinition = {
|
|
|
40015
40366
|
runtime: formBlockRuntime
|
|
40016
40367
|
};
|
|
40017
40368
|
//#endregion
|
|
40369
|
+
//#region ../blocks/src/system/helpers/normalizeMailingListBlockContent.ts
|
|
40370
|
+
/** Fill the declared default without admitting or rewriting invalid custom settings. */
|
|
40371
|
+
function normalizeMailingListBlockContent(record) {
|
|
40372
|
+
return record.targeting == null ? {
|
|
40373
|
+
...record,
|
|
40374
|
+
targeting: DEFAULT_MAILING_LIST_TARGETING
|
|
40375
|
+
} : record;
|
|
40376
|
+
}
|
|
40377
|
+
//#endregion
|
|
40018
40378
|
//#region ../blocks/src/system/blocks/contact-newsletter.ts
|
|
40019
40379
|
const contactNewsletterLayout = styledSection({
|
|
40020
40380
|
children: sectionContainer([el("div", { className: "contact-newsletter-grid" }, [el("div", { className: "contact-newsletter-column contact-newsletter-contact" }, [el("div", { className: "contact-newsletter-copy" }, [text({
|
|
@@ -40178,6 +40538,10 @@ const contactNewsletterBlockDefinition = {
|
|
|
40178
40538
|
],
|
|
40179
40539
|
icon: "MailPlus"
|
|
40180
40540
|
}),
|
|
40541
|
+
contentNormalizer: {
|
|
40542
|
+
fieldIds: ["targeting"],
|
|
40543
|
+
normalize: normalizeMailingListBlockContent
|
|
40544
|
+
},
|
|
40181
40545
|
dataSchemas: { form: formDataSchema.optional() },
|
|
40182
40546
|
dataLoaders: { form: {
|
|
40183
40547
|
endpoint: "getPublicFormById",
|
|
@@ -43866,6 +44230,14 @@ bookingPaymentOptionSchemas.flexibleBalanceConfig;
|
|
|
43866
44230
|
bookingPaymentOptionSchemas.paymentCollectionOption;
|
|
43867
44231
|
const bookingPaymentTermsSchema = bookingPaymentOptionSchemas.paymentTerms;
|
|
43868
44232
|
bookingPaymentOptionSchemas.paymentOptionsChoice;
|
|
44233
|
+
z.strictObject({
|
|
44234
|
+
currency: z.string().trim().length(3),
|
|
44235
|
+
totalCents: nonNegativeIntegerSchema,
|
|
44236
|
+
dueNowCents: nonNegativeIntegerSchema,
|
|
44237
|
+
laterPaymentAmountsCents: z.array(nonNegativeIntegerSchema),
|
|
44238
|
+
paymentOption: z.union([createBookingPaymentOptionSchemas("strict").paymentCollectionOption, z.strictObject({ kind: z.literal("not_required") })]),
|
|
44239
|
+
promisedDiscountId: z.string().min(1).nullable().optional()
|
|
44240
|
+
});
|
|
43869
44241
|
//#endregion
|
|
43870
44242
|
//#region ../blocks/src/system/blocks/shared/bookingPaymentTerms.ts
|
|
43871
44243
|
const blockBookingPaymentTermsSchema = bookingPaymentTermsSchema;
|
|
@@ -44106,6 +44478,10 @@ const publicEventBaseSchema = z.object({
|
|
|
44106
44478
|
eventDestinationMode: eventDestinationModeSchema.optional(),
|
|
44107
44479
|
scheduleScope: eventScheduleScopeSchema$2.optional(),
|
|
44108
44480
|
recurrence: publicEventRecurrenceSchema.optional(),
|
|
44481
|
+
scheduleSummary: z.object({
|
|
44482
|
+
recurrenceDescription: z.string(),
|
|
44483
|
+
startTime: z.string().regex(/^(?:[01]\d|2[0-3]):[0-5]\d$/).nullable()
|
|
44484
|
+
}).nullable().optional(),
|
|
44109
44485
|
id: z.string(),
|
|
44110
44486
|
occurrenceId: z.string(),
|
|
44111
44487
|
seriesId: z.string(),
|
|
@@ -44114,7 +44490,7 @@ const publicEventBaseSchema = z.object({
|
|
|
44114
44490
|
content: z.object({ body: RichTextDocSchema.nullable().optional() }).optional(),
|
|
44115
44491
|
presentation: z.object({
|
|
44116
44492
|
summary: z.string().nullable().optional(),
|
|
44117
|
-
image:
|
|
44493
|
+
image: runtimeMediaSchema.nullable().optional()
|
|
44118
44494
|
}).optional(),
|
|
44119
44495
|
slug: z.string(),
|
|
44120
44496
|
path: z.string().nullable(),
|
|
@@ -44516,67 +44892,266 @@ const occurrenceContextSchema = z.object({
|
|
|
44516
44892
|
overrides: z.record(z.string(), z.unknown()).nullable().optional()
|
|
44517
44893
|
}).nullable();
|
|
44518
44894
|
//#endregion
|
|
44519
|
-
//#region ../blocks/src/system/runtime/
|
|
44520
|
-
|
|
44521
|
-
|
|
44522
|
-
|
|
44523
|
-
|
|
44524
|
-
|
|
44525
|
-
|
|
44526
|
-
|
|
44527
|
-
|
|
44528
|
-
|
|
44529
|
-
|
|
44530
|
-
|
|
44531
|
-
|
|
44532
|
-
"invalidEventOfferingCatalogue"
|
|
44533
|
-
])
|
|
44534
|
-
});
|
|
44535
|
-
const eventRegistrationPageSurfaceSubjectSchema = z.unknown().transform((value, ctx) => {
|
|
44536
|
-
const unsupported = unsupportedEventRegistrationPageSurfaceSubjectSchema.safeParse(value);
|
|
44537
|
-
if (unsupported.success) return unsupported.data;
|
|
44538
|
-
const parsed = parseEventPageSurfaceSubject(value);
|
|
44539
|
-
if (parsed.ok) return parsed.value;
|
|
44540
|
-
ctx.addIssue({
|
|
44541
|
-
code: z.ZodIssueCode.custom,
|
|
44542
|
-
message: `Invalid event page-surface subject (${parsed.error.kind})`
|
|
44543
|
-
});
|
|
44544
|
-
return z.NEVER;
|
|
44545
|
-
});
|
|
44546
|
-
function resolveEventRegistrationScope(context) {
|
|
44547
|
-
const occurrenceSeriesId = context.occurrenceContext?.seriesId;
|
|
44548
|
-
if (occurrenceSeriesId) return {
|
|
44549
|
-
kind: "occurrenceSeries",
|
|
44550
|
-
seriesId: occurrenceSeriesId
|
|
44895
|
+
//#region ../blocks/src/system/runtime/nodes/events/domain/capacity.ts
|
|
44896
|
+
/**
|
|
44897
|
+
* Compute remaining spots for an event from `availableSpots` with a fallback
|
|
44898
|
+
* to `capacity - registeredCount`. Returns `{ available: null, isFull: false }`
|
|
44899
|
+
* for uncapped events so call sites can render no capacity indicator at all.
|
|
44900
|
+
*
|
|
44901
|
+
* The single source of truth for capacity math across event cards, agenda
|
|
44902
|
+
* rows, and timetable cells — keep wording variations in the call sites.
|
|
44903
|
+
*/
|
|
44904
|
+
function getEventAvailability(event) {
|
|
44905
|
+
if (event.capacity == null) return {
|
|
44906
|
+
available: null,
|
|
44907
|
+
isFull: false
|
|
44551
44908
|
};
|
|
44552
|
-
|
|
44553
|
-
|
|
44554
|
-
|
|
44909
|
+
const available = event.availableSpots ?? event.capacity - event.registeredCount;
|
|
44910
|
+
if (available <= 0) return {
|
|
44911
|
+
available: 0,
|
|
44912
|
+
isFull: true
|
|
44555
44913
|
};
|
|
44556
|
-
|
|
44557
|
-
|
|
44558
|
-
|
|
44559
|
-
seriesIds: context.subject.catalogueEventSeriesIds
|
|
44914
|
+
return {
|
|
44915
|
+
available,
|
|
44916
|
+
isFull: false
|
|
44560
44917
|
};
|
|
44561
|
-
|
|
44562
|
-
|
|
44563
|
-
|
|
44918
|
+
}
|
|
44919
|
+
/**
|
|
44920
|
+
* Pick the capacity row a booking decision should read: the selected
|
|
44921
|
+
* attendance mode's availability when the visitor has chosen one and the
|
|
44922
|
+
* event publishes it, otherwise the event-level aggregate.
|
|
44923
|
+
*
|
|
44924
|
+
* The mode row is used wholesale. A mode with `capacity: null` on a capped
|
|
44925
|
+
* event is uncapped *by design*: the registration write path applies the
|
|
44926
|
+
* same rule via `getEffectiveOccurrenceCapacityForAttendanceMode`, so falling
|
|
44927
|
+
* back to the event's `availableSpots` here would block bookings the server
|
|
44928
|
+
* accepts. (Waitlist claims are still occurrence-scoped; see issue 1377.)
|
|
44929
|
+
*/
|
|
44930
|
+
function selectEventCapacitySource(event, attendanceMode) {
|
|
44931
|
+
if (!attendanceMode) return event;
|
|
44932
|
+
return (event.attendanceModes ?? []).find((mode) => mode.mode === attendanceMode) ?? event;
|
|
44933
|
+
}
|
|
44934
|
+
/**
|
|
44935
|
+
* Whether the visitor's next step is the waitlist: the source is full *and*
|
|
44936
|
+
* a waitlist is open. The one place this is decided — cards, rows, the
|
|
44937
|
+
* wizard's steps and its action bar all route through here so they agree,
|
|
44938
|
+
* including for producers that omit `availableSpots` and rely on the
|
|
44939
|
+
* `capacity - registeredCount` fallback.
|
|
44940
|
+
*/
|
|
44941
|
+
function canJoinEventWaitlist(event, options) {
|
|
44942
|
+
const source = selectEventCapacitySource(event, options?.attendanceMode);
|
|
44943
|
+
return getEventAvailability(source).isFull && source.waitlistEnabled === true;
|
|
44944
|
+
}
|
|
44945
|
+
/**
|
|
44946
|
+
* Remaining places at or below which an event reads as scarce and the exact
|
|
44947
|
+
* count is worth showing. Above it, no number is shown at all: "147 places
|
|
44948
|
+
* left" is not something a visitor acts on, and it is the figure most likely
|
|
44949
|
+
* to be stale on a cached page.
|
|
44950
|
+
*
|
|
44951
|
+
* max( min(3, ceil(capacity * 0.25)), ceil(capacity * 0.05) )
|
|
44952
|
+
*
|
|
44953
|
+
* The 25% arm stops small groups shouting early (3 of 4 is not urgency); the
|
|
44954
|
+
* 5% floor stops large events staying silent until three remain.
|
|
44955
|
+
* capacity 4 -> 1, 12 -> 3, 40 -> 3, 100 -> 5, 200 -> 10.
|
|
44956
|
+
*/
|
|
44957
|
+
function lowCapacityThreshold(capacity) {
|
|
44958
|
+
return Math.max(Math.min(3, Math.ceil(capacity * .25)), Math.ceil(capacity * .05));
|
|
44959
|
+
}
|
|
44960
|
+
function getRemainingPlaces(source) {
|
|
44961
|
+
const { available, isFull } = getEventAvailability(source);
|
|
44962
|
+
if (available === null || source.capacity === null) return { kind: "unlimited" };
|
|
44963
|
+
if (isFull) return {
|
|
44964
|
+
kind: "full",
|
|
44965
|
+
waitlist: canJoinEventWaitlist(source)
|
|
44564
44966
|
};
|
|
44565
|
-
|
|
44967
|
+
if (available <= lowCapacityThreshold(source.capacity)) return {
|
|
44968
|
+
kind: "low",
|
|
44969
|
+
remaining: available
|
|
44970
|
+
};
|
|
44971
|
+
return { kind: "open" };
|
|
44566
44972
|
}
|
|
44567
|
-
|
|
44568
|
-
|
|
44569
|
-
|
|
44570
|
-
|
|
44571
|
-
|
|
44572
|
-
|
|
44573
|
-
|
|
44574
|
-
|
|
44575
|
-
|
|
44576
|
-
case "
|
|
44577
|
-
case "
|
|
44973
|
+
/**
|
|
44974
|
+
* The one place a remaining-places count becomes text. Returns `null` when
|
|
44975
|
+
* nothing should be shown: uncapped events, and capped events above the
|
|
44976
|
+
* scarcity threshold. Surfaces that need their own full-state wording pass
|
|
44977
|
+
* it in rather than re-deriving the count.
|
|
44978
|
+
*/
|
|
44979
|
+
function formatRemainingPlaces(source, wording = {}) {
|
|
44980
|
+
const remaining = getRemainingPlaces(source);
|
|
44981
|
+
switch (remaining.kind) {
|
|
44982
|
+
case "unlimited":
|
|
44983
|
+
case "open": return null;
|
|
44984
|
+
case "low": return formatPlacesLeft(remaining.remaining, wording.compact === true);
|
|
44985
|
+
case "full": return remaining.waitlist ? wording.waitlist ?? "Waitlist" : wording.full ?? "Full";
|
|
44578
44986
|
}
|
|
44579
44987
|
}
|
|
44988
|
+
function formatPlacesLeft(count, compact) {
|
|
44989
|
+
if (compact) return `${count} left`;
|
|
44990
|
+
return count === 1 ? "1 place left" : `${count} places left`;
|
|
44991
|
+
}
|
|
44992
|
+
function formatTicketTypeRemaining(remainingCapacity) {
|
|
44993
|
+
if (remainingCapacity === null || remainingCapacity > 3) return null;
|
|
44994
|
+
if (remainingCapacity <= 0) return "None left for this ticket type";
|
|
44995
|
+
return `${formatPlacesLeft(remainingCapacity, false)} for this ticket type`;
|
|
44996
|
+
}
|
|
44997
|
+
/**
|
|
44998
|
+
* Which capacity figure wins when they disagree.
|
|
44999
|
+
*
|
|
45000
|
+
* For a hybrid event that publishes both attendance-mode rows, **the mode
|
|
45001
|
+
* rows are authoritative and the event-level aggregate is only a summary**.
|
|
45002
|
+
* The registration write path admits or refuses per mode
|
|
45003
|
+
* (`getEffectiveOccurrenceCapacityForAttendanceMode` on the server), so the
|
|
45004
|
+
* aggregate can read full while a mode still has room, and can read open
|
|
45005
|
+
* while the mode the visitor wants is full. Believing the aggregate on a
|
|
45006
|
+
* card is how a "places available" event turns into a dead end at step two.
|
|
45007
|
+
*
|
|
45008
|
+
* Everything else — single-mode events, events that publish no rows, and the
|
|
45009
|
+
* aggregate-only helpers {@link getEventAvailability} /
|
|
45010
|
+
* {@link getRemainingPlaces} that existing callers rely on — keeps reading
|
|
45011
|
+
* the aggregate, unchanged.
|
|
45012
|
+
*/
|
|
45013
|
+
function findHybridModeRows(event) {
|
|
45014
|
+
if (event.deliveryMode !== "hybrid") return null;
|
|
45015
|
+
const rows = event.attendanceModes ?? [];
|
|
45016
|
+
const inPerson = rows.find((row) => row.mode === "in_person");
|
|
45017
|
+
const online = rows.find((row) => row.mode === "online");
|
|
45018
|
+
return inPerson && online ? {
|
|
45019
|
+
inPerson,
|
|
45020
|
+
online
|
|
45021
|
+
} : null;
|
|
45022
|
+
}
|
|
45023
|
+
/** Openness rank; higher means more room. A full mode with a waitlist beats one without. */
|
|
45024
|
+
function remainingPlacesRank(remaining) {
|
|
45025
|
+
switch (remaining.kind) {
|
|
45026
|
+
case "unlimited": return 4;
|
|
45027
|
+
case "open": return 3;
|
|
45028
|
+
case "low": return 2;
|
|
45029
|
+
case "full": return remaining.waitlist ? 1 : 0;
|
|
45030
|
+
}
|
|
45031
|
+
}
|
|
45032
|
+
function isMoreOpen(candidate, than) {
|
|
45033
|
+
const rank = remainingPlacesRank(candidate);
|
|
45034
|
+
const otherRank = remainingPlacesRank(than);
|
|
45035
|
+
if (rank !== otherRank) return rank > otherRank;
|
|
45036
|
+
return candidate.kind === "low" && than.kind === "low" ? candidate.remaining > than.remaining : false;
|
|
45037
|
+
}
|
|
45038
|
+
/** True when `candidate` has less room left than `than`. */
|
|
45039
|
+
function isScarcer(candidate, than) {
|
|
45040
|
+
return isMoreOpen(than, candidate);
|
|
45041
|
+
}
|
|
45042
|
+
const ATTENDANCE_MODE_LABEL = {
|
|
45043
|
+
in_person: "In person",
|
|
45044
|
+
online: "Online"
|
|
45045
|
+
};
|
|
45046
|
+
/** Wording for a mode with room to spare, where the count is deliberately withheld. */
|
|
45047
|
+
const PLACES_AVAILABLE = "Places available";
|
|
45048
|
+
/**
|
|
45049
|
+
* The browse-surface label for an event's remaining places. Single-mode
|
|
45050
|
+
* events get exactly the aggregate label {@link formatRemainingPlaces}
|
|
45051
|
+
* produces, and so does a hybrid event whose two modes tell the same story.
|
|
45052
|
+
* When the modes differ, both sides are named: "available" on a card is a
|
|
45053
|
+
* promise the registration wizard would otherwise have to break.
|
|
45054
|
+
*
|
|
45055
|
+
* Hybrid examples, in person full with 3 online places left:
|
|
45056
|
+
* default -> "Online: 3 places left · In person: Full"
|
|
45057
|
+
* { full: 'Sold out' } -> "Online: 3 places left · In person: Sold out"
|
|
45058
|
+
* { compact: true } -> "Online: 3 left"
|
|
45059
|
+
*/
|
|
45060
|
+
function formatEventRemainingPlaces(event, wording = {}) {
|
|
45061
|
+
const rows = findHybridModeRows(event);
|
|
45062
|
+
if (!rows) return formatRemainingPlaces(event, wording);
|
|
45063
|
+
const inPerson = formatRemainingPlaces(rows.inPerson, wording);
|
|
45064
|
+
const online = formatRemainingPlaces(rows.online, wording);
|
|
45065
|
+
if (inPerson === online) return inPerson;
|
|
45066
|
+
if (wording.compact === true) return formatCompactHybridPlaces(rows, wording);
|
|
45067
|
+
return formatBothHybridSides(rows, {
|
|
45068
|
+
inPerson,
|
|
45069
|
+
online
|
|
45070
|
+
});
|
|
45071
|
+
}
|
|
45072
|
+
/**
|
|
45073
|
+
* Both sides, the one with room first: that is the half a visitor can act on,
|
|
45074
|
+
* and it should not arrive after a full stop's worth of bad news.
|
|
45075
|
+
*/
|
|
45076
|
+
function formatBothHybridSides(rows, labels) {
|
|
45077
|
+
return (isMoreOpen(getRemainingPlaces(rows.online), getRemainingPlaces(rows.inPerson)) ? [["online", labels.online], ["in_person", labels.inPerson]] : [["in_person", labels.inPerson], ["online", labels.online]]).map(([mode, label]) => namedModePlaces(mode, label)).join(" · ");
|
|
45078
|
+
}
|
|
45079
|
+
function namedModePlaces(mode, label) {
|
|
45080
|
+
return `${ATTENDANCE_MODE_LABEL[mode]}: ${label ?? PLACES_AVAILABLE}`;
|
|
45081
|
+
}
|
|
45082
|
+
/**
|
|
45083
|
+
* Pills and timetable cells have room for one short phrase, so they name the
|
|
45084
|
+
* single mode that carries news rather than listing both: the scarce side
|
|
45085
|
+
* when there is a count to show, and otherwise the side that has closed —
|
|
45086
|
+
* "In person: Full", never "Online only", which reads as a statement about
|
|
45087
|
+
* how the event is delivered rather than about its remaining places.
|
|
45088
|
+
*/
|
|
45089
|
+
function formatCompactHybridPlaces(rows, wording) {
|
|
45090
|
+
const inPerson = getRemainingPlaces(rows.inPerson);
|
|
45091
|
+
const online = getRemainingPlaces(rows.online);
|
|
45092
|
+
if (inPerson.kind === "full" && online.kind === "full") return formatRemainingPlaces(inPerson.waitlist ? rows.inPerson : rows.online, wording);
|
|
45093
|
+
if (inPerson.kind === "full" || online.kind === "full") {
|
|
45094
|
+
const fullSide = inPerson.kind === "full" ? "in_person" : "online";
|
|
45095
|
+
const openSide = inPerson.kind === "full" ? "online" : "in_person";
|
|
45096
|
+
const openLabel = formatRemainingPlaces(rowFor(rows, openSide), wording);
|
|
45097
|
+
return openLabel !== null ? namedModePlaces(openSide, openLabel) : namedModePlaces(fullSide, formatRemainingPlaces(rowFor(rows, fullSide), wording));
|
|
45098
|
+
}
|
|
45099
|
+
const scarcerSide = isScarcer(online, inPerson) ? "online" : "in_person";
|
|
45100
|
+
return namedModePlaces(scarcerSide, formatRemainingPlaces(rowFor(rows, scarcerSide), wording));
|
|
45101
|
+
}
|
|
45102
|
+
function rowFor(rows, mode) {
|
|
45103
|
+
return mode === "online" ? rows.online : rows.inPerson;
|
|
45104
|
+
}
|
|
45105
|
+
//#endregion
|
|
45106
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/registrationDisplay.ts
|
|
45107
|
+
const registrationDisplaySchema = z.object({
|
|
45108
|
+
venue: z.enum(["shown", "hidden"]),
|
|
45109
|
+
placesLeft: z.enum(["shown", "hidden"])
|
|
45110
|
+
});
|
|
45111
|
+
function resolveRegistrationDisplay(source) {
|
|
45112
|
+
return {
|
|
45113
|
+
venue: source.showVenue === false ? "hidden" : "shown",
|
|
45114
|
+
placesLeft: source.showCapacity === false ? "hidden" : "shown"
|
|
45115
|
+
};
|
|
45116
|
+
}
|
|
45117
|
+
/** Venue stays in domain data; views receive only the permitted presentation. */
|
|
45118
|
+
function shownVenue(event, display) {
|
|
45119
|
+
return display.venue === "shown" ? event.venue?.name ?? null : null;
|
|
45120
|
+
}
|
|
45121
|
+
/** Full/waitlist explanations remain visible even when optional counts are hidden. */
|
|
45122
|
+
function placesLeftLabel(source, display, wording = {}) {
|
|
45123
|
+
if ("kind" in source) return ticketPlacesLabel(source.remaining, display);
|
|
45124
|
+
if (source.deliveryMode === "hybrid" && source.attendanceModes?.length) return hybridPlacesLabel(source, display, wording);
|
|
45125
|
+
return capacityPlacesLabel(source, display, wording);
|
|
45126
|
+
}
|
|
45127
|
+
function capacityPlacesLabel(source, display, wording) {
|
|
45128
|
+
const remaining = getRemainingPlaces(source);
|
|
45129
|
+
if (display.placesLeft === "hidden" && remaining.kind !== "full") return null;
|
|
45130
|
+
switch (remaining.kind) {
|
|
45131
|
+
case "full": return formatRemainingPlaces(source, wording);
|
|
45132
|
+
case "low": return formatRemainingPlaces(source, wording);
|
|
45133
|
+
case "unlimited": return wording.unlimited ?? null;
|
|
45134
|
+
case "open": return wording.open ?? null;
|
|
45135
|
+
default: return assertNever$6(remaining);
|
|
45136
|
+
}
|
|
45137
|
+
}
|
|
45138
|
+
function hybridPlacesLabel(event, display, wording) {
|
|
45139
|
+
if (display.placesLeft === "shown") return formatEventRemainingPlaces(event, wording);
|
|
45140
|
+
return (event.attendanceModes ?? []).flatMap((mode) => {
|
|
45141
|
+
const label = placesLeftLabel(mode, display, wording);
|
|
45142
|
+
return label ? [`${mode.mode === "online" ? "Online" : "In person"}: ${label}`] : [];
|
|
45143
|
+
}).join(" · ") || null;
|
|
45144
|
+
}
|
|
45145
|
+
function ticketPlacesLabel(remaining, display) {
|
|
45146
|
+
if (remaining !== null && remaining > 0 && display.placesLeft === "hidden") return null;
|
|
45147
|
+
return formatTicketTypeRemaining(remaining);
|
|
45148
|
+
}
|
|
45149
|
+
//#endregion
|
|
45150
|
+
//#region ../blocks/src/system/runtime/api/readAuthority.ts
|
|
45151
|
+
const browserReadAuthoritySchema = z.discriminatedUnion("kind", [z.object({ kind: z.literal("published") }).strict(), z.object({
|
|
45152
|
+
kind: z.literal("preview"),
|
|
45153
|
+
token: z.string().min(1)
|
|
45154
|
+
}).strict()]);
|
|
44580
45155
|
//#endregion
|
|
44581
45156
|
//#region ../calendar/src/grid.ts
|
|
44582
45157
|
const MONTH_NAMES = [
|
|
@@ -44664,6 +45239,11 @@ function buildCalendarViewport(input) {
|
|
|
44664
45239
|
//#endregion
|
|
44665
45240
|
//#region ../blocks/src/system/runtime/nodes/events/domain/dates.ts
|
|
44666
45241
|
/**
|
|
45242
|
+
* Date and time presentation for events: the single place an event's
|
|
45243
|
+
* timestamps become strings or date buckets. Calendar-grid primitives are
|
|
45244
|
+
* re-exported from @riverbankcms/calendar so block code has one import.
|
|
45245
|
+
*/
|
|
45246
|
+
/**
|
|
44667
45247
|
* The English locale a site's public dates are written in, read from the
|
|
44668
45248
|
* site's own time zone (Will, 2026-09-26: "date style from site time zone").
|
|
44669
45249
|
*
|
|
@@ -44683,6 +45263,28 @@ function eventDateLocale(siteTimeZone) {
|
|
|
44683
45263
|
if (siteTimeZone === "Pacific/Auckland" || siteTimeZone === "Pacific/Chatham") return "en-NZ";
|
|
44684
45264
|
return "en-US";
|
|
44685
45265
|
}
|
|
45266
|
+
function formatEventCompactDateRail(isoTimestamp, options, letterCase = "capitals") {
|
|
45267
|
+
const locale = options?.locale ?? "en-US";
|
|
45268
|
+
const dateTime = toScheduledBookingDateTime({
|
|
45269
|
+
startsAt: isoTimestamp,
|
|
45270
|
+
timeZone: toBookingTimeZone(options?.timeZone ?? "UTC"),
|
|
45271
|
+
locale
|
|
45272
|
+
});
|
|
45273
|
+
const cased = (value) => letterCase === "capitals" ? value.toLocaleUpperCase(locale) : value;
|
|
45274
|
+
const weekday = cased(formatBookingDate(dateTime, { weekday: "short" }));
|
|
45275
|
+
const month = cased(formatBookingDate(dateTime, { month: "short" }).slice(0, 3));
|
|
45276
|
+
return {
|
|
45277
|
+
weekday,
|
|
45278
|
+
day: formatBookingDate(dateTime, { day: "numeric" }),
|
|
45279
|
+
month,
|
|
45280
|
+
label: formatBookingDate(dateTime, {
|
|
45281
|
+
weekday: "long",
|
|
45282
|
+
year: "numeric",
|
|
45283
|
+
month: "long",
|
|
45284
|
+
day: "numeric"
|
|
45285
|
+
})
|
|
45286
|
+
};
|
|
45287
|
+
}
|
|
44686
45288
|
//#endregion
|
|
44687
45289
|
//#region ../blocks/src/system/runtime/nodes/events/domain/destination.ts
|
|
44688
45290
|
function isRecord$8(value) {
|
|
@@ -44702,6 +45304,15 @@ function resolveRuntimeEventDestination(event) {
|
|
|
44702
45304
|
};
|
|
44703
45305
|
}
|
|
44704
45306
|
//#endregion
|
|
45307
|
+
//#region ../blocks/src/system/runtime/nodes/events/domain/pricing.ts
|
|
45308
|
+
/**
|
|
45309
|
+
* Format an event's price directly from its pricing value (without the full
|
|
45310
|
+
* event). Same output as {@link formatEventPrice}.
|
|
45311
|
+
*/
|
|
45312
|
+
function formatEventPriceDisplay(pricing) {
|
|
45313
|
+
return formatEventPricing(pricing, { decimals: "auto" });
|
|
45314
|
+
}
|
|
45315
|
+
//#endregion
|
|
44705
45316
|
//#region ../blocks/src/system/runtime/nodes/events/domain/listWeek.ts
|
|
44706
45317
|
/** Civil weeks use the site zone, including weeks containing a clock change. */
|
|
44707
45318
|
function buildEventListWeek(anchor, startOfWeek, timeZone) {
|
|
@@ -44736,6 +45347,642 @@ function eventListWindowEvents(events, window) {
|
|
|
44736
45347
|
});
|
|
44737
45348
|
}
|
|
44738
45349
|
//#endregion
|
|
45350
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/registrationDerivations.ts
|
|
45351
|
+
function eventMatchesOccurrenceId(event, occurrenceId) {
|
|
45352
|
+
return event.registrationSubject.kind === "occurrence" && (event.registrationSubject.occurrenceId === occurrenceId || event.selectionId === occurrenceId);
|
|
45353
|
+
}
|
|
45354
|
+
function findPreSelectedEvent(input) {
|
|
45355
|
+
const occurrenceContext = input.occurrenceContext;
|
|
45356
|
+
if (!occurrenceContext) return input.scopedEvents.length === 1 ? input.scopedEvents[0] ?? null : null;
|
|
45357
|
+
const contextDate = getBookingLocalDateKey(toScheduledBookingDateTime({
|
|
45358
|
+
startsAt: occurrenceContext.startsAt,
|
|
45359
|
+
timeZone: occurrenceContext.timeZone
|
|
45360
|
+
}));
|
|
45361
|
+
return input.scopedEvents.find((event) => eventMatchesOccurrenceId(event, occurrenceContext.id) || getBookingLocalDateKey(toScheduledBookingDateTime({
|
|
45362
|
+
startsAt: event.startsAt,
|
|
45363
|
+
timeZone: event.timeZone
|
|
45364
|
+
})) === contextDate) ?? null;
|
|
45365
|
+
}
|
|
45366
|
+
function resolveEventRequiresPayment(input) {
|
|
45367
|
+
if (input.eligibility) return input.eligibility.requiresPayment;
|
|
45368
|
+
if (input.selectedTicketType) return input.selectedTicketType.priceAmount > 0;
|
|
45369
|
+
if (!input.event) return false;
|
|
45370
|
+
return publicEventPricingType(input.event.pricing) === "paid";
|
|
45371
|
+
}
|
|
45372
|
+
//#endregion
|
|
45373
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/utils.ts
|
|
45374
|
+
/**
|
|
45375
|
+
* The locale a site's booking dates are written in: the one the site's time
|
|
45376
|
+
* zone places it in (`eventDateLocale`, shared with event cards), or British
|
|
45377
|
+
* English when the site names no zone.
|
|
45378
|
+
*/
|
|
45379
|
+
function bookingDateLocale(siteTimeZone) {
|
|
45380
|
+
return siteTimeZone ? eventDateLocale(siteTimeZone) : "en-GB";
|
|
45381
|
+
}
|
|
45382
|
+
function bookingInstant(startsAt, input) {
|
|
45383
|
+
return toScheduledBookingDateTime({
|
|
45384
|
+
startsAt,
|
|
45385
|
+
timeZone: toBookingTimeZone(input.timeZone),
|
|
45386
|
+
locale: bookingDateLocale(input.siteTimeZone)
|
|
45387
|
+
});
|
|
45388
|
+
}
|
|
45389
|
+
/** "7:00pm": a twelve-hour clock with a lowercase, unspaced day period. */
|
|
45390
|
+
function bookingClock(startsAt, input) {
|
|
45391
|
+
return formatBookingTime(bookingInstant(startsAt, input), {
|
|
45392
|
+
hour: "numeric",
|
|
45393
|
+
minute: "2-digit",
|
|
45394
|
+
hour12: true
|
|
45395
|
+
}).replace(/\s*([ap])\.?\s?m\.?$/i, (_match, period) => `${period.toLowerCase()}m`);
|
|
45396
|
+
}
|
|
45397
|
+
/** "7:00pm – 8:15pm", or just the start when there's no distinct end. */
|
|
45398
|
+
function clockRange(input) {
|
|
45399
|
+
const start = bookingClock(input.startsAt, input);
|
|
45400
|
+
const end = input.endsAt ? bookingClock(input.endsAt, input) : null;
|
|
45401
|
+
return end && end !== start ? `${start} – ${end}` : start;
|
|
45402
|
+
}
|
|
45403
|
+
/** A stored local clock has no date or DST offset; UTC preserves its digits. */
|
|
45404
|
+
function formatBookingScheduleSummary(event) {
|
|
45405
|
+
const summary = event.scheduleSummary;
|
|
45406
|
+
if (!summary) return null;
|
|
45407
|
+
const time = summary.startTime ? formatBookingWhen({
|
|
45408
|
+
startsAt: `1970-01-01T${summary.startTime}:00Z`,
|
|
45409
|
+
timeZone: "UTC",
|
|
45410
|
+
siteTimeZone: event.siteTimeZone
|
|
45411
|
+
}, "time") : null;
|
|
45412
|
+
return [summary.recurrenceDescription, time].filter(Boolean).join(" · ");
|
|
45413
|
+
}
|
|
45414
|
+
/** The one booking date formatter; every variant derives from it. */
|
|
45415
|
+
function formatBookingWhen(input, variant) {
|
|
45416
|
+
const instant = bookingInstant(input.startsAt, input);
|
|
45417
|
+
const day = formatBookingDate(instant, {
|
|
45418
|
+
weekday: "short",
|
|
45419
|
+
day: "numeric",
|
|
45420
|
+
month: "short"
|
|
45421
|
+
});
|
|
45422
|
+
switch (variant) {
|
|
45423
|
+
case "day": return day;
|
|
45424
|
+
case "dayLong": return formatBookingDate(instant, {
|
|
45425
|
+
weekday: "long",
|
|
45426
|
+
day: "numeric",
|
|
45427
|
+
month: "long"
|
|
45428
|
+
});
|
|
45429
|
+
case "month": return formatBookingDate(instant, { month: "long" });
|
|
45430
|
+
case "monthYear": return formatBookingDate(instant, {
|
|
45431
|
+
month: "long",
|
|
45432
|
+
year: "numeric"
|
|
45433
|
+
});
|
|
45434
|
+
case "time": return bookingClock(input.startsAt, input);
|
|
45435
|
+
case "timeRange": return clockRange(input);
|
|
45436
|
+
case "short": return `${day}, ${bookingClock(input.startsAt, input)}`;
|
|
45437
|
+
case "long": return `${day} · ${clockRange(input)}`;
|
|
45438
|
+
}
|
|
45439
|
+
}
|
|
45440
|
+
/** A single instant in the short form, e.g. "Mon 5 Oct, 7:00pm". */
|
|
45441
|
+
function formatEventDateTime(isoTimestamp, options) {
|
|
45442
|
+
return formatBookingWhen({
|
|
45443
|
+
startsAt: isoTimestamp,
|
|
45444
|
+
timeZone: options?.timeZone,
|
|
45445
|
+
siteTimeZone: options?.siteTimeZone
|
|
45446
|
+
}, "short");
|
|
45447
|
+
}
|
|
45448
|
+
/** The title an occurrence was given on its own, when it overrides the event's. */
|
|
45449
|
+
function occurrenceTitleOverride(occurrence) {
|
|
45450
|
+
const title = occurrence?.overrides?.title;
|
|
45451
|
+
return typeof title === "string" && title.trim() ? title.trim() : null;
|
|
45452
|
+
}
|
|
45453
|
+
/** The event as this page names it: an occurrence's own title wins. */
|
|
45454
|
+
function withOccurrenceTitle(event, occurrence) {
|
|
45455
|
+
const title = occurrenceTitleOverride(occurrence);
|
|
45456
|
+
return event && title ? {
|
|
45457
|
+
...event,
|
|
45458
|
+
title
|
|
45459
|
+
} : event;
|
|
45460
|
+
}
|
|
45461
|
+
function courseSchedule(sessions, siteTimeZone) {
|
|
45462
|
+
const first = sessions[0];
|
|
45463
|
+
if (!first) return null;
|
|
45464
|
+
const last = sessions[sessions.length - 1] ?? first;
|
|
45465
|
+
const firstLabel = formatEventDateTime(first.startsAt, {
|
|
45466
|
+
timeZone: first.timeZone,
|
|
45467
|
+
siteTimeZone
|
|
45468
|
+
});
|
|
45469
|
+
if (last.startsAt === first.startsAt) return `${sessions.length} session${sessions.length === 1 ? "" : "s"} · ${firstLabel}`;
|
|
45470
|
+
const lastLabel = formatEventDateTime(last.startsAt, {
|
|
45471
|
+
timeZone: last.timeZone,
|
|
45472
|
+
siteTimeZone
|
|
45473
|
+
});
|
|
45474
|
+
return `${sessions.length} sessions · ${firstLabel} – ${lastLabel}`;
|
|
45475
|
+
}
|
|
45476
|
+
/**
|
|
45477
|
+
* When a booking happens, in one line: the occurrence's date and time, or a
|
|
45478
|
+
* course's session count and first and last dates. `short` by default (bar,
|
|
45479
|
+
* confirmation); `long` adds the end time (card, panel header).
|
|
45480
|
+
*/
|
|
45481
|
+
function formatRegistrationSchedule(event, occurrence, variant = "short") {
|
|
45482
|
+
if (event.registrationSubject.kind === "wholeSeries") return courseSchedule(event.registrationSubject.sessions, event.siteTimeZone);
|
|
45483
|
+
const input = scheduleInput(event, occurrence ?? null);
|
|
45484
|
+
return input ? formatBookingWhen(input, variant) : null;
|
|
45485
|
+
}
|
|
45486
|
+
/** The occurrence's own times when the page names one, otherwise the event's. */
|
|
45487
|
+
function scheduleInput(event, occurrence) {
|
|
45488
|
+
const times = occurrence?.startsAt ? {
|
|
45489
|
+
startsAt: occurrence.startsAt,
|
|
45490
|
+
endsAt: occurrence.endsAt ?? null
|
|
45491
|
+
} : {
|
|
45492
|
+
startsAt: event.startsAt,
|
|
45493
|
+
endsAt: event.endsAt
|
|
45494
|
+
};
|
|
45495
|
+
if (!times.startsAt) return null;
|
|
45496
|
+
return {
|
|
45497
|
+
...times,
|
|
45498
|
+
timeZone: occurrence?.timeZone ?? event.timeZone ?? null,
|
|
45499
|
+
siteTimeZone: event.siteTimeZone
|
|
45500
|
+
};
|
|
45501
|
+
}
|
|
45502
|
+
//#endregion
|
|
45503
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/wizardSteps.ts
|
|
45504
|
+
function registrationRoute(input) {
|
|
45505
|
+
const base = input.chooseEvent ? [
|
|
45506
|
+
"select-event",
|
|
45507
|
+
"select-tickets",
|
|
45508
|
+
"enter-details"
|
|
45509
|
+
] : ["select-tickets", "enter-details"];
|
|
45510
|
+
switch (input.payment) {
|
|
45511
|
+
case "none": return base;
|
|
45512
|
+
case "options": return [...base, "select-payment"];
|
|
45513
|
+
case "optionsAndPayment": return [
|
|
45514
|
+
...base,
|
|
45515
|
+
"select-payment",
|
|
45516
|
+
"payment"
|
|
45517
|
+
];
|
|
45518
|
+
}
|
|
45519
|
+
}
|
|
45520
|
+
const REGISTRATION_STEP_LABELS = [
|
|
45521
|
+
"Event",
|
|
45522
|
+
"Date",
|
|
45523
|
+
"Tickets",
|
|
45524
|
+
"Places",
|
|
45525
|
+
"Your details",
|
|
45526
|
+
"How you’ll pay",
|
|
45527
|
+
"Payment"
|
|
45528
|
+
];
|
|
45529
|
+
/** Several dates of one series are a date choice; anything else is an event choice. */
|
|
45530
|
+
function getEventSelectionMode(events) {
|
|
45531
|
+
const firstSeriesId = events[0]?.seriesId;
|
|
45532
|
+
return events.length > 1 && firstSeriesId && events.every((event) => event.seriesId === firstSeriesId) ? "date" : "event";
|
|
45533
|
+
}
|
|
45534
|
+
/** The label facts for a surface: what the visitor chooses from, and what they book. */
|
|
45535
|
+
function registrationStepLabelContext(scopedEvents, bookedEvent) {
|
|
45536
|
+
return {
|
|
45537
|
+
eventSelection: getEventSelectionMode(scopedEvents),
|
|
45538
|
+
booksWholeSeries: bookedEvent?.registrationSubject.kind === "wholeSeries"
|
|
45539
|
+
};
|
|
45540
|
+
}
|
|
45541
|
+
/** One label owner for the live progress and the server placeholder. */
|
|
45542
|
+
function registrationStepLabel(step, context) {
|
|
45543
|
+
switch (step) {
|
|
45544
|
+
case "select-event": return context.eventSelection === "date" ? "Date" : "Event";
|
|
45545
|
+
case "select-tickets": return context.booksWholeSeries ? "Places" : "Tickets";
|
|
45546
|
+
case "enter-details": return "Your details";
|
|
45547
|
+
case "select-payment": return "How you’ll pay";
|
|
45548
|
+
case "payment": return "Payment";
|
|
45549
|
+
}
|
|
45550
|
+
}
|
|
45551
|
+
function bookingButtonText(buttonText) {
|
|
45552
|
+
return buttonText?.trim() || "Book your place";
|
|
45553
|
+
}
|
|
45554
|
+
function placesLabel(event, input, compact) {
|
|
45555
|
+
return placesLeftLabel(selectEventCapacitySource(event, input.attendanceMode), input.display, { compact });
|
|
45556
|
+
}
|
|
45557
|
+
function isFull(event, mode) {
|
|
45558
|
+
return formatRemainingPlaces(selectEventCapacitySource(event, mode), {
|
|
45559
|
+
full: "full",
|
|
45560
|
+
waitlist: "full"
|
|
45561
|
+
}) === "full";
|
|
45562
|
+
}
|
|
45563
|
+
function priceLabel(event) {
|
|
45564
|
+
return formatEventPriceDisplay(event.pricing).trim() || null;
|
|
45565
|
+
}
|
|
45566
|
+
/** The lowest price a display can mean; null when it names no paid amount. */
|
|
45567
|
+
function lowestPaidAmount(display) {
|
|
45568
|
+
switch (display.kind) {
|
|
45569
|
+
case "exact":
|
|
45570
|
+
case "from": return display.amount;
|
|
45571
|
+
case "range": return display.minAmount;
|
|
45572
|
+
case "mixed": return display.paidFromAmount;
|
|
45573
|
+
case "free":
|
|
45574
|
+
case "unavailable":
|
|
45575
|
+
case "external": return null;
|
|
45576
|
+
}
|
|
45577
|
+
}
|
|
45578
|
+
/**
|
|
45579
|
+
* One price for a set of dates: the shared label when every date costs the
|
|
45580
|
+
* same, otherwise "From" the lowest paid amount, through the one formatter.
|
|
45581
|
+
*/
|
|
45582
|
+
function seriesPriceLabel(events) {
|
|
45583
|
+
const firstEvent = events[0];
|
|
45584
|
+
if (!firstEvent) return null;
|
|
45585
|
+
const displays = events.map((event) => publicEventPricingDisplay(event.pricing));
|
|
45586
|
+
const labels = new Set(displays.map((display) => formatBookingPriceDisplay(display, { decimals: "auto" })));
|
|
45587
|
+
if (labels.size === 1) return [...labels][0] || null;
|
|
45588
|
+
const lowest = displays.flatMap((display) => {
|
|
45589
|
+
const amount = lowestPaidAmount(display);
|
|
45590
|
+
return amount === null || !("currency" in display) ? [] : [{
|
|
45591
|
+
amount,
|
|
45592
|
+
currency: display.currency
|
|
45593
|
+
}];
|
|
45594
|
+
}).reduce((best, candidate) => best === null || candidate.amount < best.amount ? candidate : best, null);
|
|
45595
|
+
return lowest ? formatBookingPriceDisplay({
|
|
45596
|
+
kind: "from",
|
|
45597
|
+
amount: lowest.amount,
|
|
45598
|
+
currency: lowest.currency
|
|
45599
|
+
}, { decimals: "auto" }) : priceLabel(firstEvent);
|
|
45600
|
+
}
|
|
45601
|
+
function dateTile(event) {
|
|
45602
|
+
if (event.registrationSubject.kind === "wholeSeries" || !event.startsAt) return null;
|
|
45603
|
+
const rail = formatEventCompactDateRail(event.startsAt, { timeZone: event.timeZone });
|
|
45604
|
+
return {
|
|
45605
|
+
month: rail.month,
|
|
45606
|
+
day: rail.day
|
|
45607
|
+
};
|
|
45608
|
+
}
|
|
45609
|
+
/** "Mon 5 Oct": the compact date the chips and the bar share. */
|
|
45610
|
+
function formatBookingShortDate(event) {
|
|
45611
|
+
return formatBookingWhen(event, "day");
|
|
45612
|
+
}
|
|
45613
|
+
function byStart(left, right) {
|
|
45614
|
+
return Date.parse(left.startsAt) - Date.parse(right.startsAt);
|
|
45615
|
+
}
|
|
45616
|
+
function singleEntry(event, input) {
|
|
45617
|
+
const isCourse = event.registrationSubject.kind === "wholeSeries";
|
|
45618
|
+
return {
|
|
45619
|
+
kind: "single",
|
|
45620
|
+
title: event.title,
|
|
45621
|
+
when: formatRegistrationSchedule(event, null, "long"),
|
|
45622
|
+
shortWhen: formatRegistrationSchedule(event),
|
|
45623
|
+
venue: shownVenue(event, input.display),
|
|
45624
|
+
price: priceLabel(event),
|
|
45625
|
+
places: placesLabel(event, input, false),
|
|
45626
|
+
tile: dateTile(event),
|
|
45627
|
+
action: isCourse ? `Book the ${input.noun.label}` : bookingButtonText(input.buttonText)
|
|
45628
|
+
};
|
|
45629
|
+
}
|
|
45630
|
+
function chooseDateEntry(input) {
|
|
45631
|
+
const ordered = [...input.events].sort(byStart);
|
|
45632
|
+
const first = ordered[0];
|
|
45633
|
+
const shown = ordered.slice(0, 4);
|
|
45634
|
+
return {
|
|
45635
|
+
kind: "chooseDate",
|
|
45636
|
+
title: first?.title ?? "",
|
|
45637
|
+
schedule: (first ? formatBookingScheduleSummary(first) : null) ?? (ordered.length === 1 ? "1 date" : `${ordered.length} dates`),
|
|
45638
|
+
venue: first ? shownVenue(first, input.display) : null,
|
|
45639
|
+
price: seriesPriceLabel(ordered),
|
|
45640
|
+
nextDate: first ? formatBookingShortDate(first) : null,
|
|
45641
|
+
dateCount: ordered.length,
|
|
45642
|
+
dates: shown.map((event) => ({
|
|
45643
|
+
selectionId: event.selectionId,
|
|
45644
|
+
label: formatBookingShortDate(event),
|
|
45645
|
+
places: placesLabel(event, input, true),
|
|
45646
|
+
full: isFull(event, input.attendanceMode)
|
|
45647
|
+
})),
|
|
45648
|
+
moreCount: Math.max(0, ordered.length - shown.length),
|
|
45649
|
+
action: "Choose a date"
|
|
45650
|
+
};
|
|
45651
|
+
}
|
|
45652
|
+
/** The card before a booking starts; the server renders this too. */
|
|
45653
|
+
function idleBookingEntry(input) {
|
|
45654
|
+
if (input.event) return singleEntry(input.event, input);
|
|
45655
|
+
const only = input.events.length === 1 ? input.events[0] : void 0;
|
|
45656
|
+
if (only) return singleEntry(only, input);
|
|
45657
|
+
if (getEventSelectionMode(input.events) === "date") return chooseDateEntry(input);
|
|
45658
|
+
return {
|
|
45659
|
+
kind: "chooseEvent",
|
|
45660
|
+
title: input.events[0]?.title ?? "",
|
|
45661
|
+
count: input.events.length,
|
|
45662
|
+
noun: input.noun.pluralLabel,
|
|
45663
|
+
action: "Choose an event"
|
|
45664
|
+
};
|
|
45665
|
+
}
|
|
45666
|
+
//#endregion
|
|
45667
|
+
//#region ../blocks/src/system/blocks/offerings-preview/model.ts
|
|
45668
|
+
const OFFERINGS_PREVIEW_DEFAULT_BUTTON_TEXT = "Book";
|
|
45669
|
+
const OFFERINGS_PREVIEW_DEFAULT_EMPTY_MESSAGE = "Nothing scheduled just yet.";
|
|
45670
|
+
const OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS = [
|
|
45671
|
+
{
|
|
45672
|
+
preset: "class",
|
|
45673
|
+
sourceKey: "eventPreset:class",
|
|
45674
|
+
dataKey: "classEvents",
|
|
45675
|
+
label: "Classes"
|
|
45676
|
+
},
|
|
45677
|
+
{
|
|
45678
|
+
preset: "workshop",
|
|
45679
|
+
sourceKey: "eventPreset:workshop",
|
|
45680
|
+
dataKey: "workshopEvents",
|
|
45681
|
+
label: "Workshops"
|
|
45682
|
+
},
|
|
45683
|
+
{
|
|
45684
|
+
preset: "retreat",
|
|
45685
|
+
sourceKey: "eventPreset:retreat",
|
|
45686
|
+
dataKey: "retreatEvents",
|
|
45687
|
+
label: "Retreats"
|
|
45688
|
+
},
|
|
45689
|
+
{
|
|
45690
|
+
preset: "performance",
|
|
45691
|
+
sourceKey: "eventPreset:performance",
|
|
45692
|
+
dataKey: "performanceEvents",
|
|
45693
|
+
label: "Performances"
|
|
45694
|
+
}
|
|
45695
|
+
];
|
|
45696
|
+
const OFFERINGS_PREVIEW_EVENT_PRESETS = OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.map((definition) => definition.preset);
|
|
45697
|
+
const OFFERINGS_PREVIEW_AUTHORABLE_SOURCE_KEYS = [...OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.map((definition) => definition.sourceKey), "course"];
|
|
45698
|
+
const OFFERINGS_PREVIEW_SOURCE_KEYS = OFFERINGS_PREVIEW_AUTHORABLE_SOURCE_KEYS;
|
|
45699
|
+
Object.fromEntries(OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.map((definition) => [definition.sourceKey, {
|
|
45700
|
+
kind: "eventPreset",
|
|
45701
|
+
preset: definition.preset
|
|
45702
|
+
}]));
|
|
45703
|
+
function isOfferingsPreviewSourceKey(value) {
|
|
45704
|
+
return typeof value === "string" && OFFERINGS_PREVIEW_SOURCE_KEYS.includes(value);
|
|
45705
|
+
}
|
|
45706
|
+
function normalizeOfferingsPreviewGroupOrder(value) {
|
|
45707
|
+
if (value == null) return { kind: "legacy" };
|
|
45708
|
+
if (value.length === 0) return { kind: "default" };
|
|
45709
|
+
const keys = uniqueOfferingsPreviewSourceKeys(value);
|
|
45710
|
+
return keys.length > 0 ? {
|
|
45711
|
+
kind: "custom",
|
|
45712
|
+
keys
|
|
45713
|
+
} : { kind: "default" };
|
|
45714
|
+
}
|
|
45715
|
+
function inferLegacyOfferingsPreviewGroupOrder(overrides) {
|
|
45716
|
+
const keys = uniqueOfferingsPreviewSourceKeys((overrides ?? []).map((override) => override.sourceKey));
|
|
45717
|
+
return keys.length >= 2 ? keys : [];
|
|
45718
|
+
}
|
|
45719
|
+
function normalizeOfferingsPreviewContentForWrite(value) {
|
|
45720
|
+
if (!isRecord$7(value)) return null;
|
|
45721
|
+
const groupOrderValue = value.groupOrder;
|
|
45722
|
+
if (Array.isArray(groupOrderValue)) {
|
|
45723
|
+
const normalized = normalizeOfferingsPreviewGroupOrder(groupOrderValue);
|
|
45724
|
+
return {
|
|
45725
|
+
...value,
|
|
45726
|
+
groupOrder: normalized.kind === "custom" ? normalized.keys : []
|
|
45727
|
+
};
|
|
45728
|
+
}
|
|
45729
|
+
if (groupOrderValue != null) return {
|
|
45730
|
+
...value,
|
|
45731
|
+
groupOrder: []
|
|
45732
|
+
};
|
|
45733
|
+
const legacyOrder = inferLegacyOfferingsPreviewGroupOrder(Array.isArray(value.groupOverrides) ? value.groupOverrides.filter(isRecord$7) : []);
|
|
45734
|
+
return legacyOrder.length > 0 ? {
|
|
45735
|
+
...value,
|
|
45736
|
+
groupOrder: legacyOrder
|
|
45737
|
+
} : value;
|
|
45738
|
+
}
|
|
45739
|
+
/** Which offerings a site preset row names; one owner for "the course preset means whole-series runs". */
|
|
45740
|
+
function sourceFromPresetSummary(preset) {
|
|
45741
|
+
if (preset.engine === "event_series" && preset.canonicalBehaviour === "course") return { kind: "wholeSeries" };
|
|
45742
|
+
if (preset.engine !== "event_series") return null;
|
|
45743
|
+
if (isOfferingsPreviewEventPreset(preset.canonicalBehaviour)) return {
|
|
45744
|
+
kind: "eventPreset",
|
|
45745
|
+
preset: preset.canonicalBehaviour
|
|
45746
|
+
};
|
|
45747
|
+
return null;
|
|
45748
|
+
}
|
|
45749
|
+
function uniqueOfferingsPreviewSourceKeys(values) {
|
|
45750
|
+
const keys = [];
|
|
45751
|
+
for (const value of values) {
|
|
45752
|
+
if (!isOfferingsPreviewSourceKey(value)) continue;
|
|
45753
|
+
if (!keys.includes(value)) keys.push(value);
|
|
45754
|
+
}
|
|
45755
|
+
return keys;
|
|
45756
|
+
}
|
|
45757
|
+
function isRecord$7(value) {
|
|
45758
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
45759
|
+
}
|
|
45760
|
+
function isOfferingsPreviewEventPreset(value) {
|
|
45761
|
+
return typeof value === "string" && OFFERINGS_PREVIEW_EVENT_PRESETS.includes(value);
|
|
45762
|
+
}
|
|
45763
|
+
//#endregion
|
|
45764
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/offeringNoun.ts
|
|
45765
|
+
function offeringKindForEvent(event) {
|
|
45766
|
+
return event.registrationSubject.kind === "wholeSeries" ? "course" : event.eventPreset ?? "event";
|
|
45767
|
+
}
|
|
45768
|
+
function presetKind(preset) {
|
|
45769
|
+
const source = sourceFromPresetSummary(preset);
|
|
45770
|
+
if (!source) return null;
|
|
45771
|
+
return source.kind === "wholeSeries" ? "course" : source.preset;
|
|
45772
|
+
}
|
|
45773
|
+
/**
|
|
45774
|
+
* What the site calls this kind of offering, in lower case for use mid-sentence
|
|
45775
|
+
* ("Book the course", "3 workshops"). Site preset labels win; the canonical
|
|
45776
|
+
* name stands in when the site has none.
|
|
45777
|
+
*/
|
|
45778
|
+
function offeringNounForEvent(event, presets) {
|
|
45779
|
+
if (!event) return lowerCased(EVENT_PRESET_VOCABULARY.event);
|
|
45780
|
+
const kind = offeringKindForEvent(event);
|
|
45781
|
+
const preset = presets?.find((candidate) => presetKind(candidate) === kind);
|
|
45782
|
+
return lowerCased(preset?.label.trim() && preset.pluralLabel.trim() ? preset : EVENT_PRESET_VOCABULARY[kind]);
|
|
45783
|
+
}
|
|
45784
|
+
function lowerCased(noun) {
|
|
45785
|
+
return {
|
|
45786
|
+
label: noun.label.trim().toLocaleLowerCase(),
|
|
45787
|
+
pluralLabel: noun.pluralLabel.trim().toLocaleLowerCase()
|
|
45788
|
+
};
|
|
45789
|
+
}
|
|
45790
|
+
//#endregion
|
|
45791
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.ts
|
|
45792
|
+
function toRegistrationEvent(event) {
|
|
45793
|
+
return {
|
|
45794
|
+
...event,
|
|
45795
|
+
selectionId: event.id,
|
|
45796
|
+
registrationSubject: {
|
|
45797
|
+
kind: "occurrence",
|
|
45798
|
+
occurrenceId: event.occurrenceId
|
|
45799
|
+
}
|
|
45800
|
+
};
|
|
45801
|
+
}
|
|
45802
|
+
function toRegistrationEvents(events) {
|
|
45803
|
+
return events.filter((event) => event.bookingScope === "single_occurrence").map(toRegistrationEvent);
|
|
45804
|
+
}
|
|
45805
|
+
/**
|
|
45806
|
+
* Project one whole-series run onto the registration surface.
|
|
45807
|
+
*
|
|
45808
|
+
* Capacity, pricing, payment terms and consent come straight off the canonical
|
|
45809
|
+
* Event record; only the schedule is widened from the single occurrence to the
|
|
45810
|
+
* live run. A run without live sessions has no registration event.
|
|
45811
|
+
*/
|
|
45812
|
+
function toWholeSeriesRegistrationEvent(group) {
|
|
45813
|
+
const { representative, run } = group;
|
|
45814
|
+
const sessions = orderedLiveRunSessions(run.sessions);
|
|
45815
|
+
const firstSession = sessions[0];
|
|
45816
|
+
if (!firstSession) return null;
|
|
45817
|
+
const lastSession = sessions[sessions.length - 1] ?? firstSession;
|
|
45818
|
+
return {
|
|
45819
|
+
...representative,
|
|
45820
|
+
selectionId: run.eventSeriesId,
|
|
45821
|
+
registrationSubject: {
|
|
45822
|
+
kind: "wholeSeries",
|
|
45823
|
+
eventSeriesId: run.eventSeriesId,
|
|
45824
|
+
sessions
|
|
45825
|
+
},
|
|
45826
|
+
startsAt: firstSession.startsAt,
|
|
45827
|
+
endsAt: lastSession.endsAt,
|
|
45828
|
+
timeZone: firstSession.timeZone
|
|
45829
|
+
};
|
|
45830
|
+
}
|
|
45831
|
+
function toWholeSeriesRegistrationEvents(events) {
|
|
45832
|
+
return groupPublicEventsByRun(events).map(toWholeSeriesRegistrationEvent).filter((event) => event !== null);
|
|
45833
|
+
}
|
|
45834
|
+
//#endregion
|
|
45835
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/bookingCardDisplay.ts
|
|
45836
|
+
/**
|
|
45837
|
+
* The booking card the server renders on CMS pages (issue 1581), and the
|
|
45838
|
+
* offering noun it resolves for the wizard. Kept beside the island contract
|
|
45839
|
+
* so the server and the client agree on one card.
|
|
45840
|
+
*/
|
|
45841
|
+
const bookingHostSchema = z.enum(["overlay", "inPlace"]);
|
|
45842
|
+
const tileSchema = z.object({
|
|
45843
|
+
month: z.string(),
|
|
45844
|
+
day: z.string()
|
|
45845
|
+
}).nullable();
|
|
45846
|
+
const idleBookingEntrySchema = z.discriminatedUnion("kind", [
|
|
45847
|
+
z.object({
|
|
45848
|
+
kind: z.literal("single"),
|
|
45849
|
+
title: z.string(),
|
|
45850
|
+
when: z.string().nullable(),
|
|
45851
|
+
shortWhen: z.string().nullable(),
|
|
45852
|
+
venue: z.string().nullable(),
|
|
45853
|
+
price: z.string().nullable(),
|
|
45854
|
+
places: z.string().nullable(),
|
|
45855
|
+
tile: tileSchema,
|
|
45856
|
+
action: z.string()
|
|
45857
|
+
}),
|
|
45858
|
+
z.object({
|
|
45859
|
+
kind: z.literal("chooseDate"),
|
|
45860
|
+
title: z.string(),
|
|
45861
|
+
schedule: z.string(),
|
|
45862
|
+
venue: z.string().nullable(),
|
|
45863
|
+
price: z.string().nullable(),
|
|
45864
|
+
nextDate: z.string().nullable(),
|
|
45865
|
+
dateCount: z.number(),
|
|
45866
|
+
dates: z.array(z.object({
|
|
45867
|
+
selectionId: z.string(),
|
|
45868
|
+
label: z.string(),
|
|
45869
|
+
places: z.string().nullable(),
|
|
45870
|
+
full: z.boolean()
|
|
45871
|
+
})),
|
|
45872
|
+
moreCount: z.number(),
|
|
45873
|
+
action: z.string()
|
|
45874
|
+
}),
|
|
45875
|
+
z.object({
|
|
45876
|
+
kind: z.literal("chooseEvent"),
|
|
45877
|
+
title: z.string(),
|
|
45878
|
+
count: z.number(),
|
|
45879
|
+
noun: z.string(),
|
|
45880
|
+
action: z.string()
|
|
45881
|
+
})
|
|
45882
|
+
]);
|
|
45883
|
+
function toScopedEventRegistrationEvents(scopedSourceEvents) {
|
|
45884
|
+
return [...toRegistrationEvents(scopedSourceEvents), ...toWholeSeriesRegistrationEvents(scopedSourceEvents)];
|
|
45885
|
+
}
|
|
45886
|
+
function scopedRegistrationEvents(source, scopedSourceEvents) {
|
|
45887
|
+
const scopedEvents = toScopedEventRegistrationEvents(scopedSourceEvents);
|
|
45888
|
+
return {
|
|
45889
|
+
scopedEvents,
|
|
45890
|
+
preSelected: findPreSelectedEvent({
|
|
45891
|
+
scopedEvents,
|
|
45892
|
+
occurrenceContext: source.occurrenceContext
|
|
45893
|
+
})
|
|
45894
|
+
};
|
|
45895
|
+
}
|
|
45896
|
+
function nounFor(scoped, presets) {
|
|
45897
|
+
return offeringNounForEvent(scoped.preSelected ?? scoped.scopedEvents[0] ?? null, presets);
|
|
45898
|
+
}
|
|
45899
|
+
/** What the site calls the offering this block books, from its preset rows. */
|
|
45900
|
+
function resolveOfferingNoun(source, scopedSourceEvents) {
|
|
45901
|
+
return nounFor(scopedRegistrationEvents(source, scopedSourceEvents), source.bookingOfferingPresets);
|
|
45902
|
+
}
|
|
45903
|
+
function idleEntry(source, scopedSourceEvents, display) {
|
|
45904
|
+
const scoped = scopedRegistrationEvents(source, scopedSourceEvents);
|
|
45905
|
+
if (scoped.scopedEvents.length === 0) return null;
|
|
45906
|
+
return idleBookingEntry({
|
|
45907
|
+
events: scoped.scopedEvents,
|
|
45908
|
+
event: withOccurrenceTitle(scoped.preSelected, source.occurrenceContext),
|
|
45909
|
+
display,
|
|
45910
|
+
buttonText: source.buttonText,
|
|
45911
|
+
noun: nounFor(scoped, source.bookingOfferingPresets),
|
|
45912
|
+
attendanceMode: null
|
|
45913
|
+
});
|
|
45914
|
+
}
|
|
45915
|
+
/** The server's card on CMS pages, or null where the shell still applies. */
|
|
45916
|
+
function bookingCardDisplay(source, scopedSourceEvents, display) {
|
|
45917
|
+
if ((source.host ?? "overlay") !== "overlay") return null;
|
|
45918
|
+
const entry = idleEntry(source, scopedSourceEvents, display);
|
|
45919
|
+
if (!entry) return null;
|
|
45920
|
+
return {
|
|
45921
|
+
kind: "event-registration",
|
|
45922
|
+
state: "booking-card",
|
|
45923
|
+
className: source.className ?? null,
|
|
45924
|
+
entry,
|
|
45925
|
+
buttonVariant: source.buttonVariant ?? null,
|
|
45926
|
+
buttonText: source.buttonText?.trim() ?? ""
|
|
45927
|
+
};
|
|
45928
|
+
}
|
|
45929
|
+
const unsupportedEventRegistrationPageSurfaceSubjectSchema = z.object({
|
|
45930
|
+
kind: z.literal("unsupported"),
|
|
45931
|
+
reason: z.enum([
|
|
45932
|
+
"unsupportedSubject",
|
|
45933
|
+
"invalidEventSeriesId",
|
|
45934
|
+
"invalidEventSeriesBookingScope",
|
|
45935
|
+
"invalidEventOfferingId",
|
|
45936
|
+
"invalidEventOfferingBookingScope",
|
|
45937
|
+
"invalidEventOfferingCatalogue"
|
|
45938
|
+
])
|
|
45939
|
+
});
|
|
45940
|
+
const eventRegistrationPageSurfaceSubjectSchema = z.unknown().transform((value, ctx) => {
|
|
45941
|
+
const unsupported = unsupportedEventRegistrationPageSurfaceSubjectSchema.safeParse(value);
|
|
45942
|
+
if (unsupported.success) return unsupported.data;
|
|
45943
|
+
const parsed = parseEventPageSurfaceSubject(value);
|
|
45944
|
+
if (parsed.ok) return parsed.value;
|
|
45945
|
+
ctx.addIssue({
|
|
45946
|
+
code: z.ZodIssueCode.custom,
|
|
45947
|
+
message: `Invalid event page-surface subject (${parsed.error.kind})`
|
|
45948
|
+
});
|
|
45949
|
+
return z.NEVER;
|
|
45950
|
+
});
|
|
45951
|
+
function resolveEventRegistrationScope(context) {
|
|
45952
|
+
const occurrenceSeriesId = context.occurrenceContext?.seriesId;
|
|
45953
|
+
if (occurrenceSeriesId) return {
|
|
45954
|
+
kind: "occurrenceSeries",
|
|
45955
|
+
seriesId: occurrenceSeriesId
|
|
45956
|
+
};
|
|
45957
|
+
if (context.subject?.kind === "eventSeries") return {
|
|
45958
|
+
kind: "pageSurfaceSeries",
|
|
45959
|
+
seriesId: context.subject.eventSeriesId
|
|
45960
|
+
};
|
|
45961
|
+
if (context.subject?.kind === "eventOffering") return {
|
|
45962
|
+
kind: "pageSurfaceOffering",
|
|
45963
|
+
offeringId: context.subject.eventOfferingId,
|
|
45964
|
+
seriesIds: context.subject.catalogueEventSeriesIds
|
|
45965
|
+
};
|
|
45966
|
+
if (context.subject?.kind === "unsupported") return {
|
|
45967
|
+
kind: "unsupportedPageSurfaceSubject",
|
|
45968
|
+
reason: context.subject.reason
|
|
45969
|
+
};
|
|
45970
|
+
return { kind: "unscoped" };
|
|
45971
|
+
}
|
|
45972
|
+
function resolveEventRegistrationScopedEvents(events, context) {
|
|
45973
|
+
const scope = resolveEventRegistrationScope(context);
|
|
45974
|
+
switch (scope.kind) {
|
|
45975
|
+
case "occurrenceSeries":
|
|
45976
|
+
case "pageSurfaceSeries": return events.filter((event) => event.seriesId === scope.seriesId);
|
|
45977
|
+
case "pageSurfaceOffering": {
|
|
45978
|
+
const seriesIds = new Set(scope.seriesIds);
|
|
45979
|
+
return events.filter((event) => seriesIds.has(event.seriesId));
|
|
45980
|
+
}
|
|
45981
|
+
case "unsupportedPageSurfaceSubject": return [];
|
|
45982
|
+
case "unscoped": return [...events];
|
|
45983
|
+
}
|
|
45984
|
+
}
|
|
45985
|
+
//#endregion
|
|
44739
45986
|
//#region ../blocks/src/system/runtime/nodes/shared/contract-schemas.ts
|
|
44740
45987
|
const previewStageSchema = z.enum(["preview", "published"]);
|
|
44741
45988
|
const registrationButtonVariantSchema = blockButtonRoleSchema;
|
|
@@ -44760,95 +46007,6 @@ const calendarTabViewsSchema = z.enum([
|
|
|
44760
46007
|
"week"
|
|
44761
46008
|
]);
|
|
44762
46009
|
//#endregion
|
|
44763
|
-
//#region ../blocks/src/system/runtime/nodes/event-registration/wizardSteps.ts
|
|
44764
|
-
/**
|
|
44765
|
-
* Determine which wizard steps to show based on context and payment requirements.
|
|
44766
|
-
*
|
|
44767
|
-
* @param hasPreSelectedContext - Whether event is pre-selected (skips event selection)
|
|
44768
|
-
* @param needsPaymentStep - Whether user must complete payment method selection
|
|
44769
|
-
* @returns Array of wizard steps to display
|
|
44770
|
-
*/
|
|
44771
|
-
function getWizardStepsForContext(hasPreSelectedContext, needsPaymentStep, paymentActive = false) {
|
|
44772
|
-
const baseSteps = hasPreSelectedContext ? ["select-tickets", "enter-details"] : [
|
|
44773
|
-
"select-event",
|
|
44774
|
-
"select-tickets",
|
|
44775
|
-
"enter-details"
|
|
44776
|
-
];
|
|
44777
|
-
if (!needsPaymentStep) return baseSteps;
|
|
44778
|
-
return paymentActive ? [
|
|
44779
|
-
...baseSteps,
|
|
44780
|
-
"select-payment",
|
|
44781
|
-
"payment"
|
|
44782
|
-
] : [...baseSteps, "select-payment"];
|
|
44783
|
-
}
|
|
44784
|
-
//#endregion
|
|
44785
|
-
//#region ../blocks/src/system/runtime/nodes/event-registration/registrationDerivations.ts
|
|
44786
|
-
function eventMatchesOccurrenceId(event, occurrenceId) {
|
|
44787
|
-
return event.registrationSubject.kind === "occurrence" && (event.registrationSubject.occurrenceId === occurrenceId || event.selectionId === occurrenceId);
|
|
44788
|
-
}
|
|
44789
|
-
function findPreSelectedEvent(input) {
|
|
44790
|
-
const occurrenceContext = input.occurrenceContext;
|
|
44791
|
-
if (!occurrenceContext) return input.scopedEvents.length === 1 ? input.scopedEvents[0] ?? null : null;
|
|
44792
|
-
const contextDate = getBookingLocalDateKey(toScheduledBookingDateTime({
|
|
44793
|
-
startsAt: occurrenceContext.startsAt,
|
|
44794
|
-
timeZone: occurrenceContext.timeZone
|
|
44795
|
-
}));
|
|
44796
|
-
return input.scopedEvents.find((event) => eventMatchesOccurrenceId(event, occurrenceContext.id) || getBookingLocalDateKey(toScheduledBookingDateTime({
|
|
44797
|
-
startsAt: event.startsAt,
|
|
44798
|
-
timeZone: event.timeZone
|
|
44799
|
-
})) === contextDate) ?? null;
|
|
44800
|
-
}
|
|
44801
|
-
function resolveEventRequiresPayment(input) {
|
|
44802
|
-
if (input.eligibility) return input.eligibility.requiresPayment;
|
|
44803
|
-
if (input.selectedTicketType) return input.selectedTicketType.priceAmount > 0;
|
|
44804
|
-
if (!input.event) return false;
|
|
44805
|
-
return publicEventPricingType(input.event.pricing) === "paid";
|
|
44806
|
-
}
|
|
44807
|
-
//#endregion
|
|
44808
|
-
//#region ../blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.ts
|
|
44809
|
-
function toRegistrationEvent(event) {
|
|
44810
|
-
return {
|
|
44811
|
-
...event,
|
|
44812
|
-
selectionId: event.id,
|
|
44813
|
-
registrationSubject: {
|
|
44814
|
-
kind: "occurrence",
|
|
44815
|
-
occurrenceId: event.occurrenceId
|
|
44816
|
-
}
|
|
44817
|
-
};
|
|
44818
|
-
}
|
|
44819
|
-
function toRegistrationEvents(events) {
|
|
44820
|
-
return events.filter((event) => event.bookingScope === "single_occurrence").map(toRegistrationEvent);
|
|
44821
|
-
}
|
|
44822
|
-
/**
|
|
44823
|
-
* Project one whole-series run onto the registration surface.
|
|
44824
|
-
*
|
|
44825
|
-
* Capacity, pricing, payment terms and consent come straight off the canonical
|
|
44826
|
-
* Event record; only the schedule is widened from the single occurrence to the
|
|
44827
|
-
* live run. A run without live sessions has no registration event.
|
|
44828
|
-
*/
|
|
44829
|
-
function toWholeSeriesRegistrationEvent(group) {
|
|
44830
|
-
const { representative, run } = group;
|
|
44831
|
-
const sessions = orderedLiveRunSessions(run.sessions);
|
|
44832
|
-
const firstSession = sessions[0];
|
|
44833
|
-
if (!firstSession) return null;
|
|
44834
|
-
const lastSession = sessions[sessions.length - 1] ?? firstSession;
|
|
44835
|
-
return {
|
|
44836
|
-
...representative,
|
|
44837
|
-
selectionId: run.eventSeriesId,
|
|
44838
|
-
registrationSubject: {
|
|
44839
|
-
kind: "wholeSeries",
|
|
44840
|
-
eventSeriesId: run.eventSeriesId,
|
|
44841
|
-
sessions
|
|
44842
|
-
},
|
|
44843
|
-
startsAt: firstSession.startsAt,
|
|
44844
|
-
endsAt: lastSession.endsAt,
|
|
44845
|
-
timeZone: firstSession.timeZone
|
|
44846
|
-
};
|
|
44847
|
-
}
|
|
44848
|
-
function toWholeSeriesRegistrationEvents(events) {
|
|
44849
|
-
return groupPublicEventsByRun(events).map(toWholeSeriesRegistrationEvent).filter((event) => event !== null);
|
|
44850
|
-
}
|
|
44851
|
-
//#endregion
|
|
44852
46010
|
//#region ../blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.ts
|
|
44853
46011
|
const { limit: _rawLimit, eventSurface: _rawEventSurface, scheduleScope: _rawScheduleScope, detailLevel: _rawDetailLevel, ...stringEventQueryShape } = publicEventLoaderQuerySchemaShape;
|
|
44854
46012
|
const eventRecoveryRequestSchema = z.object({
|
|
@@ -44891,27 +46049,17 @@ function parseEventLoaderRecoveryRequest(value) {
|
|
|
44891
46049
|
const EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS = [
|
|
44892
46050
|
"Date",
|
|
44893
46051
|
"Tickets",
|
|
44894
|
-
"
|
|
44895
|
-
];
|
|
44896
|
-
const EVENT_REGISTRATION_SHELL_STEP_LABELS = [
|
|
44897
|
-
"Event",
|
|
44898
|
-
"Date",
|
|
44899
|
-
"Tickets",
|
|
44900
|
-
"Details",
|
|
44901
|
-
"Payment options",
|
|
44902
|
-
"Payment"
|
|
46052
|
+
"Your details"
|
|
44903
46053
|
];
|
|
44904
46054
|
const eventRegistrationPublicEventSchema = z.preprocess(normalizeEventRegistrationEventInput, publicEventSchema);
|
|
44905
|
-
const
|
|
46055
|
+
const eventRegistrationCommonSchemaShape = {
|
|
44906
46056
|
demoEmailSuppressed: z.boolean().optional(),
|
|
44907
46057
|
occurrenceContext: occurrenceContextSchema.optional(),
|
|
44908
46058
|
subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
|
|
44909
46059
|
maxTickets: z.string().optional(),
|
|
44910
|
-
showVenue: z.boolean().optional(),
|
|
44911
|
-
showCapacity: z.boolean().optional(),
|
|
44912
46060
|
successMessage: z.string().optional(),
|
|
44913
46061
|
buttonVariant: registrationButtonVariantSchema.optional(),
|
|
44914
|
-
|
|
46062
|
+
host: bookingHostSchema.optional(),
|
|
44915
46063
|
spamProtectionEnabled: z.boolean().optional(),
|
|
44916
46064
|
supportEmail: z.string().optional(),
|
|
44917
46065
|
sitePasses: publicPassProductCollectionSchema.nullable().optional(),
|
|
@@ -44936,32 +46084,51 @@ const eventRegistrationSourceSchema = z.object({
|
|
|
44936
46084
|
portalToken: z.string().nullable().optional(),
|
|
44937
46085
|
previewToken: z.string().nullable().optional(),
|
|
44938
46086
|
readAuthority: browserReadAuthoritySchema.optional(),
|
|
44939
|
-
...
|
|
46087
|
+
...eventRegistrationCommonSchemaShape,
|
|
46088
|
+
showVenue: z.boolean().optional(),
|
|
46089
|
+
showCapacity: z.boolean().optional(),
|
|
44940
46090
|
events: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
|
|
44941
46091
|
wholeSeriesRunEvents: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
|
|
44942
46092
|
eventLoaderFailures: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
44943
46093
|
className: z.string().nullable().optional(),
|
|
44944
46094
|
buttonText: z.string().nullable().optional(),
|
|
44945
46095
|
maxTickets: z.string().nullable().optional(),
|
|
44946
|
-
stage: previewStageSchema.optional()
|
|
46096
|
+
stage: previewStageSchema.optional(),
|
|
46097
|
+
bookingOfferingPresets: z.array(z.custom((value) => typeof value === "object" && value !== null && typeof value.label === "string")).nullable().optional()
|
|
44947
46098
|
});
|
|
44948
|
-
const eventRegistrationDisplaySchema = z.discriminatedUnion("state", [
|
|
44949
|
-
|
|
44950
|
-
|
|
44951
|
-
|
|
44952
|
-
|
|
44953
|
-
|
|
44954
|
-
|
|
44955
|
-
|
|
44956
|
-
|
|
44957
|
-
|
|
44958
|
-
|
|
44959
|
-
|
|
44960
|
-
|
|
44961
|
-
|
|
44962
|
-
|
|
46099
|
+
const eventRegistrationDisplaySchema = z.discriminatedUnion("state", [
|
|
46100
|
+
z.object({
|
|
46101
|
+
kind: z.literal("event-registration"),
|
|
46102
|
+
state: z.literal("generic-shell"),
|
|
46103
|
+
className: z.string().nullable(),
|
|
46104
|
+
titleText: z.string(),
|
|
46105
|
+
bodyText: z.string(),
|
|
46106
|
+
stepLabels: z.array(z.enum(REGISTRATION_STEP_LABELS)).min(1),
|
|
46107
|
+
summaryButtonText: z.string()
|
|
46108
|
+
}),
|
|
46109
|
+
z.object({
|
|
46110
|
+
kind: z.literal("event-registration"),
|
|
46111
|
+
state: z.literal("registration-closed"),
|
|
46112
|
+
className: z.string().nullable(),
|
|
46113
|
+
titleText: z.string(),
|
|
46114
|
+
bodyText: z.string()
|
|
46115
|
+
}),
|
|
46116
|
+
z.object({
|
|
46117
|
+
kind: z.literal("event-registration"),
|
|
46118
|
+
state: z.literal("booking-card"),
|
|
46119
|
+
className: z.string().nullable(),
|
|
46120
|
+
entry: idleBookingEntrySchema,
|
|
46121
|
+
buttonVariant: registrationButtonVariantSchema.nullable(),
|
|
46122
|
+
buttonText: z.string()
|
|
46123
|
+
})
|
|
46124
|
+
]);
|
|
44963
46125
|
const eventRegistrationHydrationSchema = z.object({
|
|
44964
|
-
...
|
|
46126
|
+
...eventRegistrationCommonSchemaShape,
|
|
46127
|
+
display: registrationDisplaySchema,
|
|
46128
|
+
offeringNoun: z.object({
|
|
46129
|
+
label: z.string(),
|
|
46130
|
+
pluralLabel: z.string()
|
|
46131
|
+
}).optional(),
|
|
44965
46132
|
eventSource: eventRegistrationEventSourceSchema
|
|
44966
46133
|
});
|
|
44967
46134
|
const eventRegistrationRenderSchema = z.object({
|
|
@@ -44976,7 +46143,7 @@ z.object({
|
|
|
44976
46143
|
readAuthority: browserReadAuthoritySchema.optional(),
|
|
44977
46144
|
stage: previewStageSchema.optional()
|
|
44978
46145
|
});
|
|
44979
|
-
function buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents) {
|
|
46146
|
+
function buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents, display) {
|
|
44980
46147
|
const selectedRun = resolveSelectedWholeSeriesRun(scopedSourceEvents);
|
|
44981
46148
|
if (selectedRun && (!selectedRun.run.enrollmentOpen || toWholeSeriesRegistrationEvent(selectedRun) === null)) return {
|
|
44982
46149
|
kind: "event-registration",
|
|
@@ -44985,6 +46152,8 @@ function buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvent
|
|
|
44985
46152
|
titleText: "Registration closed",
|
|
44986
46153
|
bodyText: "This run is no longer open for bookings."
|
|
44987
46154
|
};
|
|
46155
|
+
const card = bookingCardDisplay(source, scopedSourceEvents, display);
|
|
46156
|
+
if (card) return card;
|
|
44988
46157
|
const stepLabels = buildEventRegistrationShellStepLabels(source, scopedSourceEvents);
|
|
44989
46158
|
return {
|
|
44990
46159
|
kind: "event-registration",
|
|
@@ -45001,11 +46170,14 @@ function buildEventRegistrationShellStepLabels(source, scopedSourceEvents) {
|
|
|
45001
46170
|
if (selectedRun) {
|
|
45002
46171
|
const selectedEvent = toWholeSeriesRegistrationEvent(selectedRun);
|
|
45003
46172
|
if (!selectedEvent) return EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS;
|
|
45004
|
-
return
|
|
45005
|
-
|
|
45006
|
-
|
|
45007
|
-
|
|
45008
|
-
|
|
46173
|
+
return shellStepLabels(registrationRoute({
|
|
46174
|
+
chooseEvent: false,
|
|
46175
|
+
payment: resolveEventRequiresPayment({
|
|
46176
|
+
eligibility: null,
|
|
46177
|
+
selectedTicketType: null,
|
|
46178
|
+
event: selectedEvent
|
|
46179
|
+
}) ? "optionsAndPayment" : "none"
|
|
46180
|
+
}), registrationStepLabelContext([selectedEvent], selectedEvent));
|
|
45009
46181
|
}
|
|
45010
46182
|
const scopedEvents = toScopedEventRegistrationEvents(scopedSourceEvents);
|
|
45011
46183
|
if (scopedEvents.length === 0) return EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS;
|
|
@@ -45014,14 +46186,15 @@ function buildEventRegistrationShellStepLabels(source, scopedSourceEvents) {
|
|
|
45014
46186
|
occurrenceContext: source.occurrenceContext
|
|
45015
46187
|
});
|
|
45016
46188
|
const hasPreSelectedContext = Boolean(source.occurrenceContext || preSelectedEvent);
|
|
45017
|
-
|
|
46189
|
+
const needsPaymentStep = hasPreSelectedContext && preSelectedEvent ? resolveEventRequiresPayment({
|
|
45018
46190
|
eligibility: null,
|
|
45019
46191
|
selectedTicketType: null,
|
|
45020
46192
|
event: preSelectedEvent
|
|
45021
|
-
}) : false
|
|
45022
|
-
|
|
45023
|
-
|
|
45024
|
-
|
|
46193
|
+
}) : false;
|
|
46194
|
+
return shellStepLabels(registrationRoute({
|
|
46195
|
+
chooseEvent: !hasPreSelectedContext,
|
|
46196
|
+
payment: needsPaymentStep ? "optionsAndPayment" : "none"
|
|
46197
|
+
}), registrationStepLabelContext(scopedEvents, preSelectedEvent));
|
|
45025
46198
|
}
|
|
45026
46199
|
function scopeEventRegistrationSourceEvents(source, eventSource) {
|
|
45027
46200
|
return resolveEventRegistrationScopedEvents(eventSource.kind === "loaded" ? eventSource.events : [], {
|
|
@@ -45037,29 +46210,12 @@ function resolveSelectedWholeSeriesRun(scopedSourceEvents) {
|
|
|
45037
46210
|
const runs = groupPublicEventsByRun(scopedSourceEvents);
|
|
45038
46211
|
return runs.length === 1 ? runs[0] : null;
|
|
45039
46212
|
}
|
|
45040
|
-
function
|
|
45041
|
-
|
|
45042
|
-
case "select-event": return isDateSelection(events) ? "Date" : "Event";
|
|
45043
|
-
case "select-tickets": return "Tickets";
|
|
45044
|
-
case "enter-details": return "Details";
|
|
45045
|
-
case "select-payment": return "Payment options";
|
|
45046
|
-
case "payment": return "Payment";
|
|
45047
|
-
case "error":
|
|
45048
|
-
case "success":
|
|
45049
|
-
case "submitting":
|
|
45050
|
-
case "verifying-payment":
|
|
45051
|
-
case "verifying-timeout":
|
|
45052
|
-
case "payment-status":
|
|
45053
|
-
case "payment-failed": return "Details";
|
|
45054
|
-
}
|
|
45055
|
-
}
|
|
45056
|
-
function isDateSelection(events) {
|
|
45057
|
-
const firstSeriesId = events[0]?.seriesId;
|
|
45058
|
-
return Boolean(events.length > 1 && firstSeriesId && events.every((event) => event.seriesId === firstSeriesId));
|
|
46213
|
+
function shellStepLabels(route, context) {
|
|
46214
|
+
return route.map((step) => registrationStepLabel(step, context));
|
|
45059
46215
|
}
|
|
45060
46216
|
function buildEventRegistrationShellBodyText(stepLabels) {
|
|
45061
|
-
if (stepLabels.includes("
|
|
45062
|
-
if (stepLabels[0] === "Tickets") return "Preparing tickets and booking details.";
|
|
46217
|
+
if (stepLabels.includes("How you’ll pay")) return "Preparing tickets, details, and payment options.";
|
|
46218
|
+
if (stepLabels[0] === "Tickets" || stepLabels[0] === "Places") return "Preparing tickets and booking details.";
|
|
45063
46219
|
return "Preparing dates, tickets, and booking details.";
|
|
45064
46220
|
}
|
|
45065
46221
|
const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
|
|
@@ -45069,6 +46225,7 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
|
|
|
45069
46225
|
render: createZodCodec(eventRegistrationRenderSchema)
|
|
45070
46226
|
},
|
|
45071
46227
|
buildRender: (source) => {
|
|
46228
|
+
const display = resolveRegistrationDisplay(source);
|
|
45072
46229
|
const eventSource = resolveEventRegistrationEventSource({
|
|
45073
46230
|
events: source.events,
|
|
45074
46231
|
wholeSeriesRunEvents: source.wholeSeriesRunEvents,
|
|
@@ -45076,7 +46233,7 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
|
|
|
45076
46233
|
});
|
|
45077
46234
|
const scopedSourceEvents = scopeEventRegistrationSourceEvents(source, eventSource);
|
|
45078
46235
|
return {
|
|
45079
|
-
display: buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents),
|
|
46236
|
+
display: buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents, display),
|
|
45080
46237
|
hydration: {
|
|
45081
46238
|
occurrenceContext: source.occurrenceContext ?? null,
|
|
45082
46239
|
subject: source.subject ?? null,
|
|
@@ -45086,29 +46243,29 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
|
|
|
45086
46243
|
} : eventSource,
|
|
45087
46244
|
demoEmailSuppressed: source.demoEmailSuppressed,
|
|
45088
46245
|
maxTickets: source.maxTickets ?? void 0,
|
|
45089
|
-
|
|
45090
|
-
showCapacity: source.showCapacity,
|
|
46246
|
+
display,
|
|
45091
46247
|
successMessage: source.successMessage,
|
|
45092
46248
|
buttonVariant: source.buttonVariant,
|
|
45093
|
-
|
|
46249
|
+
host: source.host ?? "overlay",
|
|
45094
46250
|
spamProtectionEnabled: source.spamProtectionEnabled,
|
|
45095
46251
|
supportEmail: source.supportEmail,
|
|
45096
46252
|
sitePasses: source.sitePasses ?? null,
|
|
45097
46253
|
siteMemberships: source.siteMemberships ?? null,
|
|
45098
46254
|
mailingList: source.mailingList,
|
|
45099
|
-
siteName: source.siteName
|
|
46255
|
+
siteName: source.siteName,
|
|
46256
|
+
offeringNoun: resolveOfferingNoun(source, scopedSourceEvents)
|
|
45100
46257
|
}
|
|
45101
46258
|
};
|
|
45102
46259
|
}
|
|
45103
46260
|
});
|
|
45104
46261
|
function normalizeEventRegistrationEventInput(value) {
|
|
45105
|
-
if (!isRecord$
|
|
46262
|
+
if (!isRecord$6(value)) return value;
|
|
45106
46263
|
return {
|
|
45107
46264
|
...value,
|
|
45108
46265
|
destination: resolveRuntimeEventDestination(value)
|
|
45109
46266
|
};
|
|
45110
46267
|
}
|
|
45111
|
-
function isRecord$
|
|
46268
|
+
function isRecord$6(value) {
|
|
45112
46269
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
45113
46270
|
}
|
|
45114
46271
|
const eventRegistrationBlockDefinition = {
|
|
@@ -45148,7 +46305,7 @@ const eventRegistrationBlockDefinition = {
|
|
|
45148
46305
|
description: "Main heading for the registration form",
|
|
45149
46306
|
required: false,
|
|
45150
46307
|
multiline: false,
|
|
45151
|
-
defaultValue: "
|
|
46308
|
+
defaultValue: ""
|
|
45152
46309
|
},
|
|
45153
46310
|
{
|
|
45154
46311
|
id: "description",
|
|
@@ -45220,11 +46377,11 @@ const eventRegistrationBlockDefinition = {
|
|
|
45220
46377
|
{
|
|
45221
46378
|
id: "buttonText",
|
|
45222
46379
|
type: "text",
|
|
45223
|
-
label: "
|
|
45224
|
-
description: "Text
|
|
46380
|
+
label: "Button text",
|
|
46381
|
+
description: "Text on the booking button",
|
|
45225
46382
|
required: false,
|
|
45226
46383
|
multiline: false,
|
|
45227
|
-
defaultValue: "
|
|
46384
|
+
defaultValue: "Book your place",
|
|
45228
46385
|
maxLength: 40
|
|
45229
46386
|
},
|
|
45230
46387
|
createButtonVariantField()
|
|
@@ -45256,21 +46413,21 @@ const eventRegistrationBlockDefinition = {
|
|
|
45256
46413
|
successMessage: { $bind: { from: "content.successMessage" } },
|
|
45257
46414
|
buttonText: { $bind: {
|
|
45258
46415
|
from: "content.buttonText",
|
|
45259
|
-
fallback: "
|
|
46416
|
+
fallback: "Book your place"
|
|
45260
46417
|
} },
|
|
45261
46418
|
buttonVariant: { $bind: {
|
|
45262
46419
|
from: "content.buttonVariant",
|
|
45263
46420
|
fallback: "primary"
|
|
45264
46421
|
} },
|
|
45265
|
-
overlayEnabled: { $bind: {
|
|
45266
|
-
from: "$root.eventRegistrationOverlayEnabled",
|
|
45267
|
-
fallback: false
|
|
45268
|
-
} },
|
|
45269
46422
|
events: { $bind: { from: "data.events" } },
|
|
45270
46423
|
wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
|
|
45271
46424
|
loaderFailures: { $bind: { from: "$root.loaderFailures" } },
|
|
45272
46425
|
mailingList: { $bind: { from: "$root.mailingList" } },
|
|
45273
46426
|
siteName: { $bind: { from: "$root.siteName" } },
|
|
46427
|
+
bookingOfferingPresets: { $bind: {
|
|
46428
|
+
from: "$root.bookingOfferingPresets",
|
|
46429
|
+
fallback: []
|
|
46430
|
+
} },
|
|
45274
46431
|
sitePasses: { $bind: { from: "data.sitePasses" } },
|
|
45275
46432
|
siteMemberships: { $bind: { from: "data.siteMemberships" } },
|
|
45276
46433
|
stage: { $bind: {
|
|
@@ -47931,7 +49088,21 @@ const eventCalendarBlockDefinition = {
|
|
|
47931
49088
|
list: { label: "List" }
|
|
47932
49089
|
}
|
|
47933
49090
|
}, eventCalendarContentShape),
|
|
47934
|
-
|
|
49091
|
+
contentNormalizer: {
|
|
49092
|
+
fieldIds: [
|
|
49093
|
+
"variant",
|
|
49094
|
+
"displayMode",
|
|
49095
|
+
"listLayout",
|
|
49096
|
+
"defaultCalendarView",
|
|
49097
|
+
"eventSurface",
|
|
49098
|
+
"filterEventPresets",
|
|
49099
|
+
"scheduleScope",
|
|
49100
|
+
"filterCategoryIds",
|
|
49101
|
+
"filterStaffMemberId",
|
|
49102
|
+
"filterVenueId"
|
|
49103
|
+
],
|
|
49104
|
+
normalize: normalizeEventCalendarContent
|
|
49105
|
+
},
|
|
47935
49106
|
dataSchemas: {
|
|
47936
49107
|
events: publicEventsArraySchema.optional(),
|
|
47937
49108
|
calendarWindow: calendarWindowPageSchema.optional()
|
|
@@ -48404,90 +49575,6 @@ const recurringScheduleBlockDefinition = {
|
|
|
48404
49575
|
} }
|
|
48405
49576
|
};
|
|
48406
49577
|
//#endregion
|
|
48407
|
-
//#region ../blocks/src/system/blocks/offerings-preview/model.ts
|
|
48408
|
-
const OFFERINGS_PREVIEW_DEFAULT_BUTTON_TEXT = "Book";
|
|
48409
|
-
const OFFERINGS_PREVIEW_DEFAULT_EMPTY_MESSAGE = "Nothing scheduled just yet.";
|
|
48410
|
-
const OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS = [
|
|
48411
|
-
{
|
|
48412
|
-
preset: "class",
|
|
48413
|
-
sourceKey: "eventPreset:class",
|
|
48414
|
-
dataKey: "classEvents",
|
|
48415
|
-
label: "Classes"
|
|
48416
|
-
},
|
|
48417
|
-
{
|
|
48418
|
-
preset: "workshop",
|
|
48419
|
-
sourceKey: "eventPreset:workshop",
|
|
48420
|
-
dataKey: "workshopEvents",
|
|
48421
|
-
label: "Workshops"
|
|
48422
|
-
},
|
|
48423
|
-
{
|
|
48424
|
-
preset: "retreat",
|
|
48425
|
-
sourceKey: "eventPreset:retreat",
|
|
48426
|
-
dataKey: "retreatEvents",
|
|
48427
|
-
label: "Retreats"
|
|
48428
|
-
},
|
|
48429
|
-
{
|
|
48430
|
-
preset: "performance",
|
|
48431
|
-
sourceKey: "eventPreset:performance",
|
|
48432
|
-
dataKey: "performanceEvents",
|
|
48433
|
-
label: "Performances"
|
|
48434
|
-
}
|
|
48435
|
-
];
|
|
48436
|
-
OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.map((definition) => definition.preset);
|
|
48437
|
-
const OFFERINGS_PREVIEW_AUTHORABLE_SOURCE_KEYS = [...OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.map((definition) => definition.sourceKey), "course"];
|
|
48438
|
-
const OFFERINGS_PREVIEW_SOURCE_KEYS = OFFERINGS_PREVIEW_AUTHORABLE_SOURCE_KEYS;
|
|
48439
|
-
Object.fromEntries(OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.map((definition) => [definition.sourceKey, {
|
|
48440
|
-
kind: "eventPreset",
|
|
48441
|
-
preset: definition.preset
|
|
48442
|
-
}]));
|
|
48443
|
-
function isOfferingsPreviewSourceKey(value) {
|
|
48444
|
-
return typeof value === "string" && OFFERINGS_PREVIEW_SOURCE_KEYS.includes(value);
|
|
48445
|
-
}
|
|
48446
|
-
function normalizeOfferingsPreviewGroupOrder(value) {
|
|
48447
|
-
if (value == null) return { kind: "legacy" };
|
|
48448
|
-
if (value.length === 0) return { kind: "default" };
|
|
48449
|
-
const keys = uniqueOfferingsPreviewSourceKeys(value);
|
|
48450
|
-
return keys.length > 0 ? {
|
|
48451
|
-
kind: "custom",
|
|
48452
|
-
keys
|
|
48453
|
-
} : { kind: "default" };
|
|
48454
|
-
}
|
|
48455
|
-
function inferLegacyOfferingsPreviewGroupOrder(overrides) {
|
|
48456
|
-
const keys = uniqueOfferingsPreviewSourceKeys((overrides ?? []).map((override) => override.sourceKey));
|
|
48457
|
-
return keys.length >= 2 ? keys : [];
|
|
48458
|
-
}
|
|
48459
|
-
function normalizeOfferingsPreviewContentForWrite(value) {
|
|
48460
|
-
if (!isRecord$6(value)) return null;
|
|
48461
|
-
const groupOrderValue = value.groupOrder;
|
|
48462
|
-
if (Array.isArray(groupOrderValue)) {
|
|
48463
|
-
const normalized = normalizeOfferingsPreviewGroupOrder(groupOrderValue);
|
|
48464
|
-
return {
|
|
48465
|
-
...value,
|
|
48466
|
-
groupOrder: normalized.kind === "custom" ? normalized.keys : []
|
|
48467
|
-
};
|
|
48468
|
-
}
|
|
48469
|
-
if (groupOrderValue != null) return {
|
|
48470
|
-
...value,
|
|
48471
|
-
groupOrder: []
|
|
48472
|
-
};
|
|
48473
|
-
const legacyOrder = inferLegacyOfferingsPreviewGroupOrder(Array.isArray(value.groupOverrides) ? value.groupOverrides.filter(isRecord$6) : []);
|
|
48474
|
-
return legacyOrder.length > 0 ? {
|
|
48475
|
-
...value,
|
|
48476
|
-
groupOrder: legacyOrder
|
|
48477
|
-
} : value;
|
|
48478
|
-
}
|
|
48479
|
-
function uniqueOfferingsPreviewSourceKeys(values) {
|
|
48480
|
-
const keys = [];
|
|
48481
|
-
for (const value of values) {
|
|
48482
|
-
if (!isOfferingsPreviewSourceKey(value)) continue;
|
|
48483
|
-
if (!keys.includes(value)) keys.push(value);
|
|
48484
|
-
}
|
|
48485
|
-
return keys;
|
|
48486
|
-
}
|
|
48487
|
-
function isRecord$6(value) {
|
|
48488
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
48489
|
-
}
|
|
48490
|
-
//#endregion
|
|
48491
49578
|
//#region ../blocks/src/system/blocks/offerings-preview/fields.ts
|
|
48492
49579
|
const groupOverrideFields = [
|
|
48493
49580
|
{
|
|
@@ -48851,7 +49938,22 @@ const offeringsPreviewEventDataSchemas = Object.fromEntries(OFFERINGS_PREVIEW_EV
|
|
|
48851
49938
|
const offeringsPreviewEventDataLoaders = Object.fromEntries(OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.map((definition) => [definition.dataKey, eventPresetLoader(definition.preset)]));
|
|
48852
49939
|
const offeringsPreviewBlockDefinition = {
|
|
48853
49940
|
manifest: offeringsPreviewManifest,
|
|
48854
|
-
|
|
49941
|
+
contentNormalizer: {
|
|
49942
|
+
fieldIds: [
|
|
49943
|
+
"displayMode",
|
|
49944
|
+
"heading",
|
|
49945
|
+
"description",
|
|
49946
|
+
"itemLimit",
|
|
49947
|
+
"groupOrder",
|
|
49948
|
+
"groupOverrides",
|
|
49949
|
+
"_cardStyles",
|
|
49950
|
+
"buttonVariant",
|
|
49951
|
+
"buttonText",
|
|
49952
|
+
"emptyMessage",
|
|
49953
|
+
"_sectionStyles"
|
|
49954
|
+
],
|
|
49955
|
+
normalize: normalizeOfferingsPreviewBlockContent
|
|
49956
|
+
},
|
|
48855
49957
|
dataSchemas: {
|
|
48856
49958
|
...offeringsPreviewEventDataSchemas,
|
|
48857
49959
|
routeCandidates: publicRouteCandidatesSchema.optional(),
|
|
@@ -52449,11 +53551,11 @@ function buildNewsletterDisplay(source) {
|
|
|
52449
53551
|
successMessage: DEFAULT_MAILING_LIST_SUCCESS_MESSAGE,
|
|
52450
53552
|
privacyNote: null
|
|
52451
53553
|
};
|
|
52452
|
-
const
|
|
52453
|
-
const choices = resolveRuntimeChoices(
|
|
53554
|
+
const assessment = assessMailingListTargeting(context, source.targeting ?? { mode: "default" });
|
|
53555
|
+
const choices = resolveRuntimeChoices(assessment);
|
|
52454
53556
|
return {
|
|
52455
53557
|
kind: "newsletter-form",
|
|
52456
|
-
availability:
|
|
53558
|
+
availability: assessment.tag === "available" ? "ready" : "unavailable",
|
|
52457
53559
|
className: source.className ?? null,
|
|
52458
53560
|
buttonLabel: form.buttonLabel,
|
|
52459
53561
|
successMessage: form.successMessage,
|
|
@@ -52510,60 +53612,12 @@ function projectNewsletterFormHydrationTarget(source) {
|
|
|
52510
53612
|
default: return assertNever$6(source);
|
|
52511
53613
|
}
|
|
52512
53614
|
}
|
|
52513
|
-
function resolveRuntimeChoices(
|
|
52514
|
-
if (
|
|
52515
|
-
|
|
52516
|
-
|
|
52517
|
-
|
|
52518
|
-
|
|
52519
|
-
id: item.id,
|
|
52520
|
-
label: item.name
|
|
52521
|
-
})) : [];
|
|
52522
|
-
}
|
|
52523
|
-
case "brevo": {
|
|
52524
|
-
const offered = new Set(targeting.selection.offeredListIds);
|
|
52525
|
-
return context.provider.provider === "brevo" ? context.provider.lists.filter((item) => offered.has(item.id)).map((item) => ({
|
|
52526
|
-
id: String(item.id),
|
|
52527
|
-
label: item.name
|
|
52528
|
-
})) : [];
|
|
52529
|
-
}
|
|
52530
|
-
case "mailchimp": {
|
|
52531
|
-
const offered = new Set(targeting.selection.offeredInterestIds);
|
|
52532
|
-
return (context.provider.provider === "mailchimp" ? context.provider.audiences.find((item) => item.id === targeting.audienceId) : void 0)?.interests.filter((item) => offered.has(item.id)).map((item) => ({
|
|
52533
|
-
id: item.id,
|
|
52534
|
-
label: item.name
|
|
52535
|
-
})) ?? [];
|
|
52536
|
-
}
|
|
52537
|
-
}
|
|
52538
|
-
}
|
|
52539
|
-
function runtimeTargetingIsAvailable(context, targeting, choices) {
|
|
52540
|
-
if (context?.tag !== "configured") return false;
|
|
52541
|
-
const provider = context.provider;
|
|
52542
|
-
if (targeting.mode === "default") switch (provider.provider) {
|
|
52543
|
-
case "native": return provider.topics.some((item) => item.id === provider.defaultTopicId);
|
|
52544
|
-
case "brevo": return provider.lists.some((item) => item.id === provider.defaultListId);
|
|
52545
|
-
case "mailchimp": return provider.audiences.some((item) => item.id === provider.defaultAudienceId);
|
|
52546
|
-
}
|
|
52547
|
-
if (targeting.provider !== provider.provider) return false;
|
|
52548
|
-
switch (targeting.provider) {
|
|
52549
|
-
case "native": return provider.provider === "native" && nativeTargetIsAvailable(provider, targeting, choices);
|
|
52550
|
-
case "brevo": return provider.provider === "brevo" && brevoTargetIsAvailable(provider, targeting, choices);
|
|
52551
|
-
case "mailchimp": return provider.provider === "mailchimp" && mailchimpTargetIsAvailable(provider, targeting, choices);
|
|
52552
|
-
}
|
|
52553
|
-
}
|
|
52554
|
-
function nativeTargetIsAvailable(provider, targeting, choices) {
|
|
52555
|
-
const ids = targeting.selection.tag === "fixed" ? targeting.selection.topicIds : targeting.selection.offeredTopicIds;
|
|
52556
|
-
return ids.every((id) => provider.topics.some((item) => item.id === id)) && (targeting.selection.tag !== "visitor_choice" || choices.length === ids.length);
|
|
52557
|
-
}
|
|
52558
|
-
function brevoTargetIsAvailable(provider, targeting, choices) {
|
|
52559
|
-
const ids = targeting.selection.tag === "fixed" ? targeting.selection.listIds : targeting.selection.offeredListIds;
|
|
52560
|
-
return ids.every((id) => provider.lists.some((item) => item.id === id)) && (targeting.selection.tag !== "visitor_choice" || choices.length === ids.length);
|
|
52561
|
-
}
|
|
52562
|
-
function mailchimpTargetIsAvailable(provider, targeting, choices) {
|
|
52563
|
-
const audience = provider.audiences.find((item) => item.id === targeting.audienceId);
|
|
52564
|
-
if (!audience) return false;
|
|
52565
|
-
const ids = targeting.selection.tag === "fixed" ? targeting.selection.interestIds : targeting.selection.offeredInterestIds;
|
|
52566
|
-
return ids.every((id) => audience.interests.some((item) => item.id === id)) && (targeting.selection.tag !== "visitor_choice" || choices.length === ids.length);
|
|
53615
|
+
function resolveRuntimeChoices(assessment) {
|
|
53616
|
+
if (!("value" in assessment) || assessment.value.mode !== "custom" || !("selectedChoices" in assessment.value) || assessment.value.targeting.selection.tag !== "visitor_choice") return [];
|
|
53617
|
+
return assessment.value.selectedChoices.map((item) => ({
|
|
53618
|
+
id: String(item.id),
|
|
53619
|
+
label: item.name
|
|
53620
|
+
}));
|
|
52567
53621
|
}
|
|
52568
53622
|
function parseRequiredMailingListSignupBlockId(value) {
|
|
52569
53623
|
const parsed = parseMailingListBlockId(value);
|
|
@@ -52672,6 +53726,10 @@ function sanitizeNewsletterSignupPublicContent(content) {
|
|
|
52672
53726
|
}
|
|
52673
53727
|
const newsletterSignupBlockDefinition = {
|
|
52674
53728
|
manifest: newsletterSignupManifest,
|
|
53729
|
+
contentNormalizer: {
|
|
53730
|
+
fieldIds: ["targeting"],
|
|
53731
|
+
normalize: normalizeMailingListBlockContent
|
|
53732
|
+
},
|
|
52675
53733
|
runtime: newsletterFormBlockRuntime
|
|
52676
53734
|
};
|
|
52677
53735
|
//#endregion
|
|
@@ -52699,7 +53757,7 @@ const memberPhotoClassName = (baseClass) => cardRoleChildClass({
|
|
|
52699
53757
|
baseClass,
|
|
52700
53758
|
stylesFrom: "content._cardStyles"
|
|
52701
53759
|
});
|
|
52702
|
-
const teamMemberPhotoSchema =
|
|
53760
|
+
const teamMemberPhotoSchema = runtimeMediaSchema.refine((media) => media.type === "image", { message: "Team member photos must be image media" }).nullable();
|
|
52703
53761
|
const teamMemberDataSchema = z.object({
|
|
52704
53762
|
_type: z.literal("teamMember"),
|
|
52705
53763
|
id: z.string(),
|
|
@@ -53404,7 +54462,20 @@ const locationMapBlockDefinition = {
|
|
|
53404
54462
|
})], { gap: "md" })
|
|
53405
54463
|
})
|
|
53406
54464
|
}),
|
|
53407
|
-
|
|
54465
|
+
contentNormalizer: {
|
|
54466
|
+
fieldIds: [
|
|
54467
|
+
"heading",
|
|
54468
|
+
"locationSource",
|
|
54469
|
+
"venueId",
|
|
54470
|
+
"location",
|
|
54471
|
+
"showAddressText",
|
|
54472
|
+
"showDirections",
|
|
54473
|
+
"directionsLabel",
|
|
54474
|
+
"zoom",
|
|
54475
|
+
"heightPx"
|
|
54476
|
+
],
|
|
54477
|
+
normalize: normalizeLocationMapContent
|
|
54478
|
+
}
|
|
53408
54479
|
};
|
|
53409
54480
|
//#endregion
|
|
53410
54481
|
//#region ../blocks/src/system/blocks/index.ts
|
|
@@ -54228,11 +55299,14 @@ const offeringsPreviewDatesReadEnabled = {
|
|
|
54228
55299
|
//#endregion
|
|
54229
55300
|
//#region ../blocks/src/system/helpers/backgroundMedia.ts
|
|
54230
55301
|
function resolveBackgroundMedia(input) {
|
|
54231
|
-
const parsedMedia =
|
|
55302
|
+
const parsedMedia = runtimeMediaSchema.safeParse(input.image);
|
|
54232
55303
|
if (!parsedMedia.success) return null;
|
|
54233
55304
|
switch (parsedMedia.data.type) {
|
|
54234
55305
|
case "image":
|
|
54235
|
-
case "video": return
|
|
55306
|
+
case "video": return {
|
|
55307
|
+
...parsedMedia.data,
|
|
55308
|
+
type: parsedMedia.data.type
|
|
55309
|
+
};
|
|
54236
55310
|
case "audio":
|
|
54237
55311
|
case "document":
|
|
54238
55312
|
case "spreadsheet":
|
|
@@ -54244,6 +55318,75 @@ function backgroundVideoMobileClassNames(input) {
|
|
|
54244
55318
|
return input.showVideoOnMobile === true ? "" : "rb-hidden rb-md-block";
|
|
54245
55319
|
}
|
|
54246
55320
|
//#endregion
|
|
55321
|
+
//#region ../blocks/src/system/runtime/nodes/mediaContext.ts
|
|
55322
|
+
/**
|
|
55323
|
+
* Server-side: AsyncLocalStorage for request isolation.
|
|
55324
|
+
* Prevents race conditions when multiple requests are processed concurrently.
|
|
55325
|
+
*
|
|
55326
|
+
* Lazy initialization to avoid issues in environments that don't support async_hooks.
|
|
55327
|
+
*/
|
|
55328
|
+
const serverStorageState = {
|
|
55329
|
+
storage: null,
|
|
55330
|
+
checked: false
|
|
55331
|
+
};
|
|
55332
|
+
function getServerStorage() {
|
|
55333
|
+
if (typeof window !== "undefined") return null;
|
|
55334
|
+
if (serverStorageState.checked) return serverStorageState.storage;
|
|
55335
|
+
serverStorageState.checked = true;
|
|
55336
|
+
try {
|
|
55337
|
+
const globalWithNonWebpackRequire = globalThis;
|
|
55338
|
+
const AsyncLocalStorage = (typeof globalWithNonWebpackRequire.__non_webpack_require__ === "function" ? globalWithNonWebpackRequire.__non_webpack_require__ : new Function("id", "return require(id)"))("async_hooks").AsyncLocalStorage;
|
|
55339
|
+
if (AsyncLocalStorage) {
|
|
55340
|
+
serverStorageState.storage = new AsyncLocalStorage();
|
|
55341
|
+
return serverStorageState.storage;
|
|
55342
|
+
}
|
|
55343
|
+
return null;
|
|
55344
|
+
} catch {
|
|
55345
|
+
if (process.env.NODE_ENV !== "production") console.warn("[blocks] AsyncLocalStorage not available - using module-level state");
|
|
55346
|
+
return null;
|
|
55347
|
+
}
|
|
55348
|
+
}
|
|
55349
|
+
/**
|
|
55350
|
+
* Client-side context storage.
|
|
55351
|
+
* Safe because browsers are single-threaded per tab.
|
|
55352
|
+
*
|
|
55353
|
+
* IMPORTANT: This must be shared across bundles.
|
|
55354
|
+
* SDK preview mode can load multiple independently-bundled entrypoints
|
|
55355
|
+
* (e.g. `@riverbankcms/sdk/rendering` + `@riverbankcms/sdk/preview-next/client`),
|
|
55356
|
+
* which can otherwise each get their own module-scoped singleton.
|
|
55357
|
+
*/
|
|
55358
|
+
const RB_MEDIA_CONTEXT_KEY = Symbol.for("riverbankcms.blocks.mediaContext");
|
|
55359
|
+
function getClientContextStore() {
|
|
55360
|
+
const g = globalThis;
|
|
55361
|
+
const existing = g[RB_MEDIA_CONTEXT_KEY];
|
|
55362
|
+
if (existing && typeof existing === "object") return existing;
|
|
55363
|
+
const next = {};
|
|
55364
|
+
g[RB_MEDIA_CONTEXT_KEY] = next;
|
|
55365
|
+
return next;
|
|
55366
|
+
}
|
|
55367
|
+
/**
|
|
55368
|
+
* Get the current media context.
|
|
55369
|
+
* Server-side: Uses AsyncLocalStorage for request isolation.
|
|
55370
|
+
* Client-side: Uses module-level state (safe in single-threaded browser).
|
|
55371
|
+
*/
|
|
55372
|
+
function getMediaContext() {
|
|
55373
|
+
const storage = getServerStorage();
|
|
55374
|
+
if (storage) return storage.getStore() ?? {};
|
|
55375
|
+
return getClientContextStore();
|
|
55376
|
+
}
|
|
55377
|
+
function getCurrentResolveImageUrlContext() {
|
|
55378
|
+
const context = getMediaContext();
|
|
55379
|
+
if (!context.supabaseUrl && !context.siteId && !context.mediaAssetIndex) return;
|
|
55380
|
+
return {
|
|
55381
|
+
supabaseUrl: context.supabaseUrl,
|
|
55382
|
+
siteId: context.siteId,
|
|
55383
|
+
mediaAssetIndex: context.mediaAssetIndex
|
|
55384
|
+
};
|
|
55385
|
+
}
|
|
55386
|
+
function getMediaAssetIndex(context) {
|
|
55387
|
+
return context?.mediaAssetIndex ?? getMediaContext().mediaAssetIndex;
|
|
55388
|
+
}
|
|
55389
|
+
//#endregion
|
|
54247
55390
|
//#region ../blocks/src/system/runtime/nodes/media.tsx
|
|
54248
55391
|
function getValidSourceDimension(value) {
|
|
54249
55392
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
@@ -54279,41 +55422,72 @@ function applyRectTransform(existingStyle, patch) {
|
|
|
54279
55422
|
if (patch.transform) next.transform = appendTransform(existingStyle?.transform, patch.transform);
|
|
54280
55423
|
return next;
|
|
54281
55424
|
}
|
|
54282
|
-
|
|
55425
|
+
/** Resolve portable content without exposing runtime metadata as saved values. */
|
|
55426
|
+
function resolveMediaWithContext(reference, context) {
|
|
55427
|
+
return resolveManagedMediaReference(reference, getMediaAssetIndex(context ?? void 0));
|
|
55428
|
+
}
|
|
55429
|
+
function sourceFromAsset(value, asset) {
|
|
55430
|
+
return {
|
|
55431
|
+
type: value.type,
|
|
55432
|
+
alt: value.alt,
|
|
55433
|
+
filename: value.filename,
|
|
55434
|
+
purpose: value.purpose,
|
|
55435
|
+
placeholder: value.placeholder,
|
|
55436
|
+
transform: value.transform,
|
|
55437
|
+
poster: value.poster,
|
|
55438
|
+
identifier: asset.identifier,
|
|
55439
|
+
assetId: asset.id,
|
|
55440
|
+
storageBucket: asset.storageBucket,
|
|
55441
|
+
storagePath: asset.storagePath,
|
|
55442
|
+
mimeType: asset.mimeType,
|
|
55443
|
+
width: asset.width,
|
|
55444
|
+
height: asset.height
|
|
55445
|
+
};
|
|
55446
|
+
}
|
|
55447
|
+
function resolveRuntimeMedia(value, context) {
|
|
55448
|
+
if ("asset" in value && value.asset) return sourceFromAsset(value, value.asset);
|
|
55449
|
+
if ("src" in value && value.src) return value;
|
|
55450
|
+
if (!value.identifier) return void 0;
|
|
55451
|
+
const resolved = resolveMediaWithContext(value, context);
|
|
55452
|
+
return resolved.kind === "resolved" ? sourceFromAsset(resolved.reference, resolved.asset) : void 0;
|
|
55453
|
+
}
|
|
55454
|
+
function usesProxyFraming(source, transform) {
|
|
55455
|
+
if (!source?.assetId || !isExplicitCropProxyEnabled()) return false;
|
|
55456
|
+
return Boolean(transform.rotation) || isExplicitRectCrop(transform.rect, getValidSourceDimension(source.width), getValidSourceDimension(source.height));
|
|
55457
|
+
}
|
|
55458
|
+
function rectFramingPatch(source, rect, proxy, style) {
|
|
55459
|
+
if (!source || !rect || proxy) return {};
|
|
55460
|
+
const patch = buildCssRectStylePatch(source, rect);
|
|
55461
|
+
return patch ? applyRectTransform(style, patch) : {};
|
|
55462
|
+
}
|
|
55463
|
+
function hotspotFramingPatch(transform, proxy, rectPatch, style) {
|
|
55464
|
+
if (!transform.hotspot || rectPatch.objectPosition !== void 0) return {};
|
|
55465
|
+
const fit = style?.objectFit;
|
|
55466
|
+
if (fit && fit !== "cover" && fit !== "contain") return {};
|
|
55467
|
+
const point = proxy && transform.rotation ? rotateNormalizedPoint(transform.hotspot, transform.rotation) : transform.hotspot;
|
|
55468
|
+
return { objectPosition: `${point.x * 100}% ${point.y * 100}%` };
|
|
55469
|
+
}
|
|
55470
|
+
function rotationFramingPatch(rotation, proxy, rectPatch, style) {
|
|
55471
|
+
if (!rotation || proxy) return {};
|
|
55472
|
+
return {
|
|
55473
|
+
transform: appendTransform(rectPatch.transform ?? style?.transform, `rotate(${rotation}deg)`),
|
|
55474
|
+
transformOrigin: rectPatch.transformOrigin ?? "center"
|
|
55475
|
+
};
|
|
55476
|
+
}
|
|
55477
|
+
/** CSS framing is a pure projection of the resolved source and per-use transform. */
|
|
55478
|
+
function deriveMediaFramingStyle(source, transform, proxy, style) {
|
|
55479
|
+
if (!transform.rect && !transform.hotspot && !transform.rotation) return style;
|
|
55480
|
+
const rectPatch = rectFramingPatch(source, transform.rect, proxy, style);
|
|
55481
|
+
return mergeStyles(style, {
|
|
55482
|
+
...rectPatch,
|
|
55483
|
+
...hotspotFramingPatch(transform, proxy, rectPatch, style),
|
|
55484
|
+
...rotationFramingPatch(transform.rotation, proxy, rectPatch, style)
|
|
55485
|
+
});
|
|
55486
|
+
}
|
|
55487
|
+
function computeMediaTransformStyle(value, style, targetAspectRatio, options, context) {
|
|
55488
|
+
const source = resolveRuntimeMedia(value, context ?? getCurrentResolveImageUrlContext());
|
|
54283
55489
|
const transform = options?.resolvedTransform ?? resolveMediaTransformForAspect(value.transform, targetAspectRatio);
|
|
54284
|
-
|
|
54285
|
-
const hotspot = transform.hotspot;
|
|
54286
|
-
const rotation = transform.rotation;
|
|
54287
|
-
if (!rect && !hotspot && !rotation) return style;
|
|
54288
|
-
const stylePatch = {};
|
|
54289
|
-
const heuristicSuppressCss = Boolean(isExplicitCropProxyEnabled() && value.assetId && (typeof rotation === "number" && rotation !== 0 || isExplicitRectCrop(rect, getValidSourceDimension(value.width), getValidSourceDimension(value.height))));
|
|
54290
|
-
const shouldSuppressCss = options?.isProxy ?? heuristicSuppressCss;
|
|
54291
|
-
if (rect && !shouldSuppressCss) {
|
|
54292
|
-
const rectPatch = buildCssRectStylePatch(value, rect);
|
|
54293
|
-
if (rectPatch) {
|
|
54294
|
-
const mergedRect = applyRectTransform(style, rectPatch);
|
|
54295
|
-
Object.assign(stylePatch, mergedRect);
|
|
54296
|
-
}
|
|
54297
|
-
}
|
|
54298
|
-
if (hotspot) {
|
|
54299
|
-
const effectiveObjectFit = stylePatch.objectFit ?? style?.objectFit;
|
|
54300
|
-
if ((!effectiveObjectFit || effectiveObjectFit === "cover" || effectiveObjectFit === "contain") && stylePatch.objectPosition === void 0) {
|
|
54301
|
-
const resolved = shouldSuppressCss && rotation ? rotateNormalizedPoint({
|
|
54302
|
-
x: hotspot.x,
|
|
54303
|
-
y: hotspot.y
|
|
54304
|
-
}, rotation) : {
|
|
54305
|
-
x: hotspot.x,
|
|
54306
|
-
y: hotspot.y
|
|
54307
|
-
};
|
|
54308
|
-
stylePatch.objectPosition = `${resolved.x * 100}% ${resolved.y * 100}%`;
|
|
54309
|
-
}
|
|
54310
|
-
}
|
|
54311
|
-
if (rotation && !shouldSuppressCss) {
|
|
54312
|
-
const existingTransform = stylePatch.transform ?? style?.transform;
|
|
54313
|
-
stylePatch.transform = existingTransform ? `${existingTransform} rotate(${rotation}deg)` : `rotate(${rotation}deg)`;
|
|
54314
|
-
if (!stylePatch.transformOrigin) stylePatch.transformOrigin = "center";
|
|
54315
|
-
}
|
|
54316
|
-
return mergeStyles(style, stylePatch);
|
|
55490
|
+
return deriveMediaFramingStyle(source, transform, options?.isProxy ?? usesProxyFraming(source, transform), style);
|
|
54317
55491
|
}
|
|
54318
55492
|
//#endregion
|
|
54319
55493
|
//#region ../blocks/src/system/transforms/registry/background.ts
|
|
@@ -54462,11 +55636,11 @@ const backgroundTransforms = [
|
|
|
54462
55636
|
}
|
|
54463
55637
|
];
|
|
54464
55638
|
function parseMediaBackground(value) {
|
|
54465
|
-
const background =
|
|
55639
|
+
const background = parseRuntimeBackgroundContent(value);
|
|
54466
55640
|
return background?.type === "image" || background?.type === "video" ? background : null;
|
|
54467
55641
|
}
|
|
54468
55642
|
function resolveBackgroundLayerStyle(value, fallbackToken, context) {
|
|
54469
|
-
const background =
|
|
55643
|
+
const background = parseRuntimeBackgroundContent(value);
|
|
54470
55644
|
const style = {};
|
|
54471
55645
|
const gradient = background?.type === "gradient" ? isString(background.gradient) ? background.gradient.trim() : gradientPresetCss(background.gradientPresetId) : null;
|
|
54472
55646
|
const color = background?.type === "color" && isString(background.color) ? background.color.trim() : null;
|
|
@@ -54609,17 +55783,7 @@ const linksTransforms = [{
|
|
|
54609
55783
|
id: "links.resolve",
|
|
54610
55784
|
kind: "formatter",
|
|
54611
55785
|
summary: "Resolve LinkValue objects to href strings using the route map",
|
|
54612
|
-
run: (value, _options, context) =>
|
|
54613
|
-
if (!value || typeof value !== "object") return null;
|
|
54614
|
-
const link = value;
|
|
54615
|
-
const kind = typeof link.kind === "string" ? link.kind : null;
|
|
54616
|
-
if (kind === "internal") return resolveInternalLink(link, context);
|
|
54617
|
-
if (kind === "page") return resolvePageLink(link, context);
|
|
54618
|
-
if (kind === "entry") return resolveEntryLink(link, context);
|
|
54619
|
-
if (kind === "external" || kind === "url") return resolveExternalLink(link);
|
|
54620
|
-
if (!kind && typeof link.href === "string") return resolveExternalLink(link);
|
|
54621
|
-
return null;
|
|
54622
|
-
}
|
|
55786
|
+
run: (value, _options, context) => resolveAuthoredLinkHref(value, context)
|
|
54623
55787
|
}, {
|
|
54624
55788
|
id: "links.label",
|
|
54625
55789
|
kind: "formatter",
|
|
@@ -54646,6 +55810,21 @@ const linksTransforms = [{
|
|
|
54646
55810
|
return null;
|
|
54647
55811
|
}
|
|
54648
55812
|
}];
|
|
55813
|
+
function resolveAuthoredLinkHref(value, context = {}) {
|
|
55814
|
+
if (!value || typeof value !== "object") return null;
|
|
55815
|
+
const link = value;
|
|
55816
|
+
switch (link.kind) {
|
|
55817
|
+
case "internal": return resolveInternalLink(link, context);
|
|
55818
|
+
case "page": return resolvePageLink(link, context);
|
|
55819
|
+
case "entry": return resolveEntryLink(link, context);
|
|
55820
|
+
case "external":
|
|
55821
|
+
case "url": return resolveExternalLink(link);
|
|
55822
|
+
default: return resolvePreResolvedLink(link);
|
|
55823
|
+
}
|
|
55824
|
+
}
|
|
55825
|
+
function resolvePreResolvedLink(link) {
|
|
55826
|
+
return !(typeof link.kind === "string" ? link.kind : null) && typeof link.href === "string" ? resolveExternalLink(link) : null;
|
|
55827
|
+
}
|
|
54649
55828
|
const eventCalendarSelectionParam = {
|
|
54650
55829
|
id: "events.calendarSelectionParam",
|
|
54651
55830
|
kind: "formatter",
|