riverbankcms 0.22.1 → 0.22.2

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.
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { $ as createFormRef, $n as managementMediaLibraryUploadLimitForMimeType, $r as parseThemeColorToken, An as mediaPosterSchema, Ar as surfaceDecorationColors, At as BREAKPOINT_MD, Bn as parseMediaIdentifier, Br as resolveOnColorForThemeToken, Bt as themeButtonExtraClassesWithTrailingIcon, C as sortRecord, Cn as isExplicitRectCrop, Cr as makeBoundaryId, Ct as deriveSiteStyleBlockPolicy, D as mapEventCommandContent, Dn as getDirectImageUrlForSiteScopedPath, Dr as toNonEmptyReadonlyArray, Dt as getHeaderPaintTargets, En as getDirectImageUrlForRelativePath, Er as tileTreatmentValues, Et as generateMobileOverlayBackdropFilterFix, F as pageIdentifierForBlockCommand, Fn as resolveManagedMediaReference, Fr as mergeStyles, Ft as getComponentBorderWidthPx, G as ianaTimezoneSchema, Gr as surfaceToneFromForegroundToken, Gt as footerForegroundCandidates, H as bookingPaymentTermsSchema, Hr as resolveTokenOrCssColorValue, Ht as themeButtonVariantClassNames, I as pageIdentifierForCommand, In as mediaTypeDiscriminants, Ir as rgbColorValue, It as getComponentShadowVar, J as createCommandRef, Jr as surfaceForegroundInputFromResolved, Jt as arrangementLookHooks, K as createBlockRef, Kn as getMimeType, Kr as defaultThemeTokens, Kt as buildTextContrastShadow, L as pagePathForCommand, Ln as mediaIdentifierSchema, Lr as textColorStyle, Lt as ICON_CONFIG, M as blockIdentifierForCommand, Mn as persistableMediaSchema, Mr as TokenResolver, Mt as BREAKPOINT_XL, N as blockOrderIdentifiersForCommand, Nn as runtimeMediaSchema, Nr as backgroundColorStyle, Nt as MQ_MD_DOWN, On as getImageUrl, Or as visibleHeadingDecorationFamilyValues, Ot as renderHeaderPaintTargetRules, P as entryIdentifierForCommand, Pn as buildRenderableMediaAssetIndex, Pr as borderColorStyle, Pt as headerVariantValues, Q as createFooterRef, Qn as classifyKnownMimeType, Qr as getTextColorForBackground, R as hasConfiguredBookingVertical, Rn as buildMediaIdentifierFromFilename, Rr as opaqueSurfaceDeclarations, Rt as generateDefaultButtonSystem, S as venueManagementFields, Sn as normalizeWidthCandidates, Sr as introCompositionTreatmentValues, St as parseGradientPresetId, Tn as resolveMediaTransformForAspect, Tr as testimonialsCompositionTreatmentValues, Tt as generateHeaderScrollTreatmentStyles, U as require_jsx_runtime, Un as deriveVideoSlotPolicy, Ur as PUBLIC_BUTTON_ROLES, Ut as parseThemeForPersistence, V as bookingPaymentCollectionOptionSchema, Vr as resolveThemeColorReferenceValue, Vt as themeButtonSizeClassName, W as require_react, Wn as resolveVideoSelectionIntentForMediaField, Wr as selectLogoVariant, X as createEventCategoryRef, Xn as FILE_SIZE_LIMITS, Xr as surfaceForegroundValue, Xt as resolveItemSurface, Y as createContentEntryRef, Yn as parseRelativeStoragePath, Yr as surfaceForegroundStyle, Yt as arrangementSlotNames, Z as createEventSeriesRef, Zr as expandPalette, Zt as resolveLookSlotSurfaces, _n as summarizePortableMediaReferences, _r as defineNoBlockDesignCapability, _t as resolvePublishedLook, an as deriveSectionGround, ar as defineBlockDesignMetadata, b as isEventVisibility, bn as looksLikeUuid, br as featureCardCompositionTreatmentValues, bt as gradientToCss, c as customLinkSchema$1, cn as resolveSectionBackground, cr as cardListKnobBlocks, ct as headerLeafTextColor, d as internalLinkSchema, dn as boxBackgroundOverlaySchema, dr as asLayoutVariantKey, dt as mergeHeaderNavTypographyPreference, ei as parseBlockColorToken, er as parseSafeDownloadFilename, et as createNavigationRef, f as internalResolvedLinkSchema, fn as boxBackgroundSchema, ft as readHeaderNavFontSizePreference, g as linkSchema, gn as collectPortableMediaReferencesFromContent, gr as defineFrameCapability, gt as resolveModeArrangement, h as isResolvedInternalLinkEntityType, hn as stripStaleTransitionStyleGroup, hr as defineBlockDesignCapability, ht as resolveEffectiveArrangement, in as sectionFactsForContent, ir as normalizeCardRole, it as refSlug, j as eventManagementTiming, jn as mediaSchema, jr as resolveSurfaceForeground, jt as BREAKPOINT_SM, kn as isSiteScopedDirectImageStoragePath, kr as resolveSurface, kt as BREAKPOINT_LG, l as entryLinkSchema$1, ln as resolveSectionPhotoPlacement, lt as transparentHeaderForegroundInput, mn as siteChromeBackgroundOverrideOwner, mr as assertNever$11, mt as readStoredMode, ni as __toESM, nn as boundaryLayout, nr as cardRoleSchema, o as classifySdkEventBookingOffer, on as heroPhotoPaintsGround, or as resolveEffectiveKnobs, ot as effectiveHeaderNavLinkStyle, p as internalRouteOnlyLinkSchema, pn as runtimeBoxBackgroundSchema, pr as asSiteStyleId, pt as arrangementManifestFromVariants, q as createBlocksRef, qn as asRecord, qr as surfaceForegroundDeclarations, qt as generateNavLinkCSS, rn as composeBoundary, rr as cardVariantRoleValues, rt as createVenueRef, s as RESOLVED_INTERNAL_LINK_ENTITY_TYPES, sn as parseCanonicalRuntimeBackground, sr as cardListFamilyBlocks, st as headerForegroundCandidates, t as classifySdkEventTiming, ti as __commonJSMin, tn as headerRootPaint, tr as renderCssDeclarations, tt as createPageRef, u as externalLinkSchema$1, un as sectionForegroundBackground, ur as asDesignBlockId, ut as readOpeningForegroundProjection, v as pageLinkSchema$1, vn as walkAndCollectImageAttrs, vr as eventListTreatmentValues, vt as requireCuratedSiteStyle, w as stableStringify, wn as parseAspectRatioValue, wr as offeringsPreviewCompositionTreatmentValues, wt as themeSchema, xn as rotateNormalizedPoint, xr as headingDecorationColorTokenValues, xt as getGradientPreset, yn as deleteEnvSpecificKeys, yr as eyebrowTreatmentValues, yt as compiledRuntimeStyleFieldNames, z as eventCommandScheduleSchema, zn as parseCanonicalMediaIdentifier, zr as isCssColorLiteral, zt as parseThemeButtonVariantId } from "../sdk-event-upsert-B3gflo1K.mjs";
3
- import { $ as resolveBookingDisplayContext, $t as formatDurationUnitLabel, A as DEFAULT_MAILING_LIST_SUCCESS_MESSAGE, An as unsafeAsPricingOptionId, At as parseEventPageSurfaceSubject, B as parseWeeklyOpeningHours, Bt as fromArray, Ct as getBookingInstalmentPlanIntervalCount, D as parseMailingListSignedSourceToken, Dn as unsafeAsPassId, Dt as resolveFlexibleBalanceDueAt, E as parseMailingListContentVersionId, Et as splitAmountWithRemainderInFirst, F as DEFAULT_MAILING_LIST_TARGETING, Ft as publicEventPricingDisplay, G as selectCategoryView, Gt as parsePositiveCents, Hn as ok, Ht as mapReadonlyNonEmptyArray, I as planMailingListChoicePresentation, It as publicEventPricingOptions, J as formatDateTime, Jt as unsafeAsNonNegativeCents, K as formatDate, Kt as toCents, L as isCanonicalRichTextDoc, Lt as publicEventPricingType, M as parseFooterCompositionV1, Mt as formatEventPricing, Nt as isPublicEventPricingOptionDisplayable, O as parseMailingListRuntimeContext, On as unsafeAsPositiveByteCount, Ot as resolveFlexibleBalanceInitialPaymentCents, P as parseMailingListPlacementTargeting, Pt as publicEventPricingCurrency, Q as inferSiteDateLocale, Qt as assertNever, R as formatOpeningHoursRows, Rt as resolveExactOrFreePriceDisplay, S as parseManagementKey, St as getBookingInstalmentDepositRefundability, T as parseMailingListBlockId, Tn as unsafeAsOccurrenceId, Tt as omitZeroAmountFutureRows, U as normalizeLocationAddressText, Ut as isNonNegativeWholeCents$1, V as assertAllowedPublicUrl, Vn as err, W as toLocationCoordinates, Wt as parseNonNegativeCents, X as formatTime$1, Xt as formatCurrencyAmount, Y as formatDateTimeRange, Yt as unsafeAsPositiveCents, Z as formatTimeRange, Zt as parseCurrencyCode, _ as orderedLiveRunSessions, _n as unsafeAsDemoCapability, _t as isLiveOrderInstalmentPlanStatus, at as getLocalScheduleDate, b as createSecret, bn as unsafeAsEventInstanceId, bt as addIntervalPreservingMonthAnchor, c as resolveSiteVerticalBookingConfig, cn as parseRetiredCourseId, ct as parseBookingLocalDate, dn as parseUserId, dt as resolveBookingTimeZoneId, en as parseApiKeyId, et as buildBookingUtcDateWindow, f as SURFACE_EVENT_PRESET_VALUES, ft as toBookingTimeZone, g as nextLiveRunSessionStartMs, gt as validateBookingPaymentOptionKinds, h as CANCELLED_SESSION_STATUS, hn as unsafeAsCheckoutLineId, in as parseEventSeriesId, it as getBookingLocalDateKey, j as parseMailingListProviderScope, jt as formatBookingPriceDisplay, k as assessMailingListTargeting, kt as deriveTotalTicketQuantity, ln as parseSiteId, lt as parseUtcIsoDateTimeString, mt as toUtcIsoDateTimeString, n as EVENT_PRESET_VOCABULARY, nn as parseDatedOfferingCapacityHoldAuditRef, nt as formatLocalScheduleDate, on as parseMembershipId, ot as getLocalScheduleTime, p as WHOLE_SERIES_EVENT_PRESET_VALUES, pt as toScheduledBookingDateTime, q as formatDateRange, qt as toNonNegativeCents, r as NAVIGATION_LOCATIONS, rn as parseDatedOfferingCapacityHoldId, rt as formatLocalScheduleTime, tn as parseCustomerId, tt as compareLocalScheduleDates, u as EVENT_PRESET_VALUES, un as parseSiteTermsVersionId, ut as resolveBookingBusinessTimeZone, v as resolveWholeSeriesBookingPhase, vt as isSettleableFlexibleBalanceContractStatus, w as slugify, wn as unsafeAsMediaAssetId, wt as getBookingInstalmentProtectedDepositAmountCents, x as exposeSecret, xt as clampConfiguredAmount, y as resolveWholeSeriesRunLifecycle, yt as isSettleableOrderInstalmentPlanStatus, zt as resolvePricingOptionsPriceDisplay } from "../src-RfhyMOpX.mjs";
4
- import { $ as normalizeMediaValueToIdentifierOnly, $t as bindRequestTimeout, A as formatDiffDetail, An as transportSuggestion, At as navigationIdentity, B as buildFieldChanges, Bn as sdkEventScheduleSchema, Bt as preparePushConfigTarget, C as reportFromOutcomes, Cn as parseEnvironmentSelection, Ct as fileExists, D as normalizeRemoteHomepageReference, Dn as withRiverbankEnv, Dt as writeJsonFileAtomic, E as createEmptySyncResult, En as requireEnvironmentWriteAuthorization, Et as writeJsonFile, F as calculatePullDiff, Fn as isLocalConfigured, Ft as navigationCommandItemToManagementInput, G as syncLocalMediaForPull, Gt as APPOINTMENT_SERVICE_VISIBILITY_VALUES, H as formatFieldPath, Hn as linkPayloadSchema, Ht as extractApiErrorMessage, I as buildJsonDiff, In as isRemoteConfigured, It as normalizeNavigationConfigItemForCommand, J as admitBinaryWriteDestination, Jt as ApiEnvelopeError, K as applyLocalMediaPush, Kt as ApiRequestError, L as hasPageOperations, Ln as loadSdkEnvironment, Lt as applyPushConfigPlan, M as hasPendingChanges, Mt as convertPulledFooterToLocal, N as findChangedFieldsWithValues, Nn as getEnvPrefix, Nt as convertPulledNavigationToLocal, O as calculateDiff, On as ErrorCodes, Ot as isMediaValue, P as formatHumanDiff, Pn as getEnvironmentDebugInfo, Pt as convertPulledPagesToLocal, Q as normalizeMediaIdentifierInput, Qt as mapEnvironmentExecutionOutcomesJson, R as pageMetadataForUpsert, Rn as createManagementClient, Rt as createPushConfigCommand, S as planCliCommandBatchForBindings, Sn as executeEnvironmentPlan, St as ensureDir, T as executeResidualSettingsSyncPlan, Tn as planEnvironmentWriteAuthorization, Tt as readJsonFile, U as revalidateLocalMediaPushPlan, Un as portablePageDesignSchema, Ut as normalizeApiError, V as formatFieldChange, Vn as sdkSettingsUpdateSchema, Vt as revalidatePushConfigPlan, Wn as sdkConfiguredBookingVerticalConfigSchema, Wt as isRecord$2, X as writeBinaryFileAtomic, Xt as deriveCmsApiUrlFromDashboardUrl, Y as readStableBinaryFile, Yt as unwrapResponse, Z as sha256, Zt as API_ENDPOINTS, _ as commandExecutionToReport, _n as runWithInvocation, _t as metadataFilePath, a as executeEntryCommandPlanAsReport, an as createOutputForCommand, at as readEntries, b as executeCompiledCliCommandPlanAsReport, bn as withErrorHandling, bt as writeMetadataFile, c as titleFromEntryData, cn as getOutputContext, ct as readEventsMeta, d as unsafeAsCliEntryIdentifier, dn as managementClientConfigFor, dt as readNavigationMeta, en as confirmAction, et as walkLocalContentMedia, f as unsafeAsCliFormSlug, fn as mapEntryForOutput, ft as readPagesMeta, g as commandCompileFailureToReport, gn as resolveCommandPath, gt as ensureMetadataDir, h as mutationCounterForEffect, hn as parsePaginationOptions, ht as writeMediaManifest, i as entrySiteCommandTypes, in as createListCommand, it as findLegacyEntryFiles, j as formatDiffSummary, jn as CliExit, jt as navigationIdentityMap, k as calculateFooterDiff, kn as formatError, kt as duplicateNavigationIdentityMessage, l as unsafeAsCliBlockIdentifier, ln as getOutputOnlyContext, lt as readFooterMeta, m as commandReportToSyncResult, mn as parseJsonData, mt as readVenuesMeta, n as entryCommandCompileErrorToReport, nn as createCommandContext, nt as downloadMedia, o as executeEntryCommandPlanAsSyncResult, on as currentInvocationEnvelope, ot as readAllMeta, p as unsafeAsCliPageIdentifier, pn as parseJsonArray, pt as readSettingsMeta, q as prepareLocalMediaForPush, qt as createBearerAPIClient, r as entryCommandReportToSyncResult, rn as createGetCommand, rt as extractMediaIdentifiers, s as syncResultForEntryCommandCompileError, sn as formatDateShort, st as readEventCategoriesMeta, t as compileEntryPushCommands, tn as createClientForEnv, tt as buildStorageUrl, u as unsafeAsCliContentTypeKey, un as handleCommandError, ut as readFormsMeta, v as commandReportHasFailures, vn as withCommandContext, vt as metadataTargetFromEnvironment, w as mergeManySyncResults, wn as planEnvironmentExecution, wt as listFiles, x as formatManagementError, xn as withOutputOnlyErrorHandling, xt as writeMetadataRecordMap, y as executeCliCommandPlan, yn as withConfirmation, yt as readMetadataFile, zn as ManagementApiError, zt as loadPushConfigTarget } from "../entryCommands-Bu-z9kxb.mjs";
5
- import { r as CLI_VERSION, t as loadConfigFile } from "../load-config-pAPKpeE0.mjs";
6
- import { a as RichTextDocSchema, c as isRecord$18, i as findUnfilledSentinels, n as buildEntryScaffold, o as isRichTextDoc, r as validateEntryInstance, s as isObjectRecord, t as eventUpsertInputSchema } from "../eventUpsertInputSchema-xHmuEKwM.mjs";
7
- import { a as prepareScaffoldExecution, c as LOCAL_PACKAGE_VENDOR_DIR, d as loadGeneratedPackageRanges, i as preflightScaffoldTargets, n as createScaffoldCompletion, s as deriveScaffoldLocalManifest, t as deriveScaffoldPlan } from "../plan-DUdJbgTV.mjs";
2
+ import { $ as createFormRef, $n as managementMediaLibraryUploadLimitForMimeType, $r as parseThemeColorToken, An as mediaPosterSchema, Ar as surfaceDecorationColors, At as BREAKPOINT_MD, Bn as parseMediaIdentifier, Br as resolveOnColorForThemeToken, Bt as themeButtonExtraClassesWithTrailingIcon, C as sortRecord, Cn as isExplicitRectCrop, Cr as makeBoundaryId, Ct as deriveSiteStyleBlockPolicy, D as mapEventCommandContent, Dn as getDirectImageUrlForSiteScopedPath, Dr as toNonEmptyReadonlyArray, Dt as getHeaderPaintTargets, En as getDirectImageUrlForRelativePath, Er as tileTreatmentValues, Et as generateMobileOverlayBackdropFilterFix, F as pageIdentifierForBlockCommand, Fn as resolveManagedMediaReference, Fr as mergeStyles, Ft as getComponentBorderWidthPx, G as ianaTimezoneSchema, Gr as surfaceToneFromForegroundToken, Gt as footerForegroundCandidates, H as bookingPaymentTermsSchema, Hr as resolveTokenOrCssColorValue, Ht as themeButtonVariantClassNames, I as pageIdentifierForCommand, In as mediaTypeDiscriminants, Ir as rgbColorValue, It as getComponentShadowVar, J as createCommandRef, Jr as surfaceForegroundInputFromResolved, Jt as arrangementLookHooks, K as createBlockRef, Kn as getMimeType, Kr as defaultThemeTokens, Kt as buildTextContrastShadow, L as pagePathForCommand, Ln as mediaIdentifierSchema, Lr as textColorStyle, Lt as ICON_CONFIG, M as blockIdentifierForCommand, Mn as persistableMediaSchema, Mr as TokenResolver, Mt as BREAKPOINT_XL, N as blockOrderIdentifiersForCommand, Nn as runtimeMediaSchema, Nr as backgroundColorStyle, Nt as MQ_MD_DOWN, On as getImageUrl, Or as visibleHeadingDecorationFamilyValues, Ot as renderHeaderPaintTargetRules, P as entryIdentifierForCommand, Pn as buildRenderableMediaAssetIndex, Pr as borderColorStyle, Pt as headerVariantValues, Q as createFooterRef, Qn as classifyKnownMimeType, Qr as getTextColorForBackground, R as hasConfiguredBookingVertical, Rn as buildMediaIdentifierFromFilename, Rr as opaqueSurfaceDeclarations, Rt as generateDefaultButtonSystem, S as venueManagementFields, Sn as normalizeWidthCandidates, Sr as introCompositionTreatmentValues, St as parseGradientPresetId, Tn as resolveMediaTransformForAspect, Tr as testimonialsCompositionTreatmentValues, Tt as generateHeaderScrollTreatmentStyles, U as require_jsx_runtime, Un as deriveVideoSlotPolicy, Ur as PUBLIC_BUTTON_ROLES, Ut as parseThemeForPersistence, V as bookingPaymentCollectionOptionSchema, Vr as resolveThemeColorReferenceValue, Vt as themeButtonSizeClassName, W as require_react, Wn as resolveVideoSelectionIntentForMediaField, Wr as selectLogoVariant, X as createEventCategoryRef, Xn as FILE_SIZE_LIMITS, Xr as surfaceForegroundValue, Xt as resolveItemSurface, Y as createContentEntryRef, Yn as parseRelativeStoragePath, Yr as surfaceForegroundStyle, Yt as arrangementSlotNames, Z as createEventSeriesRef, Zr as expandPalette, Zt as resolveLookSlotSurfaces, _n as summarizePortableMediaReferences, _r as defineNoBlockDesignCapability, _t as resolvePublishedLook, an as deriveSectionGround, ar as defineBlockDesignMetadata, b as isEventVisibility, bn as looksLikeUuid, br as featureCardCompositionTreatmentValues, bt as gradientToCss, c as customLinkSchema$1, cn as resolveSectionBackground, cr as cardListKnobBlocks, ct as headerLeafTextColor, d as internalLinkSchema, dn as boxBackgroundOverlaySchema, dr as asLayoutVariantKey, dt as mergeHeaderNavTypographyPreference, ei as parseBlockColorToken, er as parseSafeDownloadFilename, et as createNavigationRef, f as internalResolvedLinkSchema, fn as boxBackgroundSchema, ft as readHeaderNavFontSizePreference, g as linkSchema, gn as collectPortableMediaReferencesFromContent, gr as defineFrameCapability, gt as resolveModeArrangement, h as isResolvedInternalLinkEntityType, hn as stripStaleTransitionStyleGroup, hr as defineBlockDesignCapability, ht as resolveEffectiveArrangement, in as sectionFactsForContent, ir as normalizeCardRole, it as refSlug, j as eventManagementTiming, jn as mediaSchema, jr as resolveSurfaceForeground, jt as BREAKPOINT_SM, kn as isSiteScopedDirectImageStoragePath, kr as resolveSurface, kt as BREAKPOINT_LG, l as entryLinkSchema$1, ln as resolveSectionPhotoPlacement, lt as transparentHeaderForegroundInput, mn as siteChromeBackgroundOverrideOwner, mr as assertNever$11, mt as readStoredMode, ni as __toESM, nn as boundaryLayout, nr as cardRoleSchema, o as classifySdkEventBookingOffer, on as heroPhotoPaintsGround, or as resolveEffectiveKnobs, ot as effectiveHeaderNavLinkStyle, p as internalRouteOnlyLinkSchema, pn as runtimeBoxBackgroundSchema, pr as asSiteStyleId, pt as arrangementManifestFromVariants, q as createBlocksRef, qn as asRecord, qr as surfaceForegroundDeclarations, qt as generateNavLinkCSS, rn as composeBoundary, rr as cardVariantRoleValues, rt as createVenueRef, s as RESOLVED_INTERNAL_LINK_ENTITY_TYPES, sn as parseCanonicalRuntimeBackground, sr as cardListFamilyBlocks, st as headerForegroundCandidates, t as classifySdkEventTiming, ti as __commonJSMin, tn as headerRootPaint, tr as renderCssDeclarations, tt as createPageRef, u as externalLinkSchema$1, un as sectionForegroundBackground, ur as asDesignBlockId, ut as readOpeningForegroundProjection, v as pageLinkSchema$1, vn as walkAndCollectImageAttrs, vr as eventListTreatmentValues, vt as requireCuratedSiteStyle, w as stableStringify, wn as parseAspectRatioValue, wr as offeringsPreviewCompositionTreatmentValues, wt as themeSchema, xn as rotateNormalizedPoint, xr as headingDecorationColorTokenValues, xt as getGradientPreset, yn as deleteEnvSpecificKeys, yr as eyebrowTreatmentValues, yt as compiledRuntimeStyleFieldNames, z as eventCommandScheduleSchema, zn as parseCanonicalMediaIdentifier, zr as isCssColorLiteral, zt as parseThemeButtonVariantId } from "../sdk-event-upsert-zWw5VolM.mjs";
3
+ import { $ as resolveBookingDisplayContext, $t as assertNever, A as DEFAULT_MAILING_LIST_SUCCESS_MESSAGE, At as deriveTotalTicketQuantity, B as parseWeeklyOpeningHours, Bt as resolvePricingOptionsPriceDisplay, Ct as getBookingInstalmentDepositRefundability, D as parseMailingListSignedSourceToken, Dt as splitAmountWithRemainderInFirst, E as parseMailingListContentVersionId, En as unsafeAsOccurrenceId, Et as omitZeroAmountFutureRows, F as DEFAULT_MAILING_LIST_TARGETING, Ft as publicEventPricingCurrency, G as selectCategoryView, Gt as parseNonNegativeCents, Hn as err, I as planMailingListChoicePresentation, It as publicEventPricingDisplay, J as formatDateTime, Jt as toNonNegativeCents, K as formatDate, Kt as parsePositiveCents, L as isCanonicalRichTextDoc, Lt as publicEventPricingOptions, M as parseFooterCompositionV1, Mt as formatBookingPriceDisplay, Nt as formatEventPricing, O as parseMailingListRuntimeContext, On as unsafeAsPassId, Ot as resolveFlexibleBalanceDueAt, P as parseMailingListPlacementTargeting, Pt as isPublicEventPricingOptionDisplayable, Q as inferSiteDateLocale, Qt as parseCurrencyCode, R as formatOpeningHoursRows, Rt as publicEventPricingType, S as parseManagementKey, St as clampConfiguredAmount, T as parseMailingListBlockId, Tn as unsafeAsMediaAssetId, Tt as getBookingInstalmentProtectedDepositAmountCents, U as normalizeLocationAddressText, Un as ok, Ut as mapReadonlyNonEmptyArray, V as assertAllowedPublicUrl, Vt as fromArray, W as toLocationCoordinates, Wt as isNonNegativeWholeCents$1, X as formatTime$1, Xt as unsafeAsPositiveCents, Y as formatDateTimeRange, Yt as unsafeAsNonNegativeCents, Z as formatTimeRange, Zt as formatCurrencyAmount, _ as orderedLiveRunSessions, _t as validateBookingPaymentOptionKinds, an as parseEventSeriesId, at as getLocalScheduleDate, b as createSecret, bt as isSettleableOrderInstalmentPlanStatus, c as resolveSiteVerticalBookingConfig, ct as parseBookingLocalDate, dn as parseSiteTermsVersionId, dt as resolveBookingBusinessTimeZone, en as formatDurationUnitLabel, et as buildBookingUtcDateWindow, f as SURFACE_EVENT_PRESET_VALUES, fn as parseUserId, ft as resolveBookingTimeZoneId, g as nextLiveRunSessionStartMs, gn as unsafeAsCheckoutLineId, h as CANCELLED_SESSION_STATUS, ht as toUtcIsoDateTimeString, in as parseDatedOfferingCapacityHoldId, it as getBookingLocalDateKey, j as parseMailingListProviderScope, jn as unsafeAsPricingOptionId, jt as parseEventPageSurfaceSubject, k as assessMailingListTargeting, kn as unsafeAsPositiveByteCount, kt as resolveFlexibleBalanceInitialPaymentCents, ln as parseRetiredCourseId, lt as parseLocalScheduleTime, mt as toScheduledBookingDateTime, n as EVENT_PRESET_VOCABULARY, nn as parseCustomerId, nt as formatLocalScheduleDate, ot as getLocalScheduleTime, p as WHOLE_SERIES_EVENT_PRESET_VALUES, pt as toBookingTimeZone, q as formatDateRange, qt as toCents, r as NAVIGATION_LOCATIONS, rn as parseDatedOfferingCapacityHoldAuditRef, rt as formatLocalScheduleTime, sn as parseMembershipId, tn as parseApiKeyId, tt as compareLocalScheduleDates, u as EVENT_PRESET_VALUES, un as parseSiteId, ut as parseUtcIsoDateTimeString, v as resolveWholeSeriesBookingPhase, vn as unsafeAsDemoCapability, vt as isLiveOrderInstalmentPlanStatus, w as slugify, wt as getBookingInstalmentPlanIntervalCount, x as exposeSecret, xn as unsafeAsEventInstanceId, xt as addIntervalPreservingMonthAnchor, y as resolveWholeSeriesRunLifecycle, yt as isSettleableFlexibleBalanceContractStatus, zt as resolveExactOrFreePriceDisplay } from "../src-ZACBG29u.mjs";
4
+ import { $ as normalizeMediaValueToIdentifierOnly, $t as bindRequestTimeout, A as formatDiffDetail, An as transportSuggestion, At as navigationIdentity, B as buildFieldChanges, Bn as sdkEventScheduleSchema, Bt as preparePushConfigTarget, C as reportFromOutcomes, Cn as parseEnvironmentSelection, Ct as fileExists, D as normalizeRemoteHomepageReference, Dn as withRiverbankEnv, Dt as writeJsonFileAtomic, E as createEmptySyncResult, En as requireEnvironmentWriteAuthorization, Et as writeJsonFile, F as calculatePullDiff, Fn as isLocalConfigured, Ft as navigationCommandItemToManagementInput, G as syncLocalMediaForPull, Gt as APPOINTMENT_SERVICE_VISIBILITY_VALUES, H as formatFieldPath, Hn as linkPayloadSchema, Ht as extractApiErrorMessage, I as buildJsonDiff, In as isRemoteConfigured, It as normalizeNavigationConfigItemForCommand, J as admitBinaryWriteDestination, Jt as ApiEnvelopeError, K as applyLocalMediaPush, Kt as ApiRequestError, L as hasPageOperations, Ln as loadSdkEnvironment, Lt as applyPushConfigPlan, M as hasPendingChanges, Mt as convertPulledFooterToLocal, N as findChangedFieldsWithValues, Nn as getEnvPrefix, Nt as convertPulledNavigationToLocal, O as calculateDiff, On as ErrorCodes, Ot as isMediaValue, P as formatHumanDiff, Pn as getEnvironmentDebugInfo, Pt as convertPulledPagesToLocal, Q as normalizeMediaIdentifierInput, Qt as mapEnvironmentExecutionOutcomesJson, R as pageMetadataForUpsert, Rn as createManagementClient, Rt as createPushConfigCommand, S as planCliCommandBatchForBindings, Sn as executeEnvironmentPlan, St as ensureDir, T as executeResidualSettingsSyncPlan, Tn as planEnvironmentWriteAuthorization, Tt as readJsonFile, U as revalidateLocalMediaPushPlan, Un as portablePageDesignSchema, Ut as normalizeApiError, V as formatFieldChange, Vn as sdkSettingsUpdateSchema, Vt as revalidatePushConfigPlan, Wn as sdkConfiguredBookingVerticalConfigSchema, Wt as isRecord$2, X as writeBinaryFileAtomic, Xt as deriveCmsApiUrlFromDashboardUrl, Y as readStableBinaryFile, Yt as unwrapResponse, Z as sha256, Zt as API_ENDPOINTS, _ as commandExecutionToReport, _n as runWithInvocation, _t as metadataFilePath, a as executeEntryCommandPlanAsReport, an as createOutputForCommand, at as readEntries, b as executeCompiledCliCommandPlanAsReport, bn as withErrorHandling, bt as writeMetadataFile, c as titleFromEntryData, cn as getOutputContext, ct as readEventsMeta, d as unsafeAsCliEntryIdentifier, dn as managementClientConfigFor, dt as readNavigationMeta, en as confirmAction, et as walkLocalContentMedia, f as unsafeAsCliFormSlug, fn as mapEntryForOutput, ft as readPagesMeta, g as commandCompileFailureToReport, gn as resolveCommandPath, gt as ensureMetadataDir, h as mutationCounterForEffect, hn as parsePaginationOptions, ht as writeMediaManifest, i as entrySiteCommandTypes, in as createListCommand, it as findLegacyEntryFiles, j as formatDiffSummary, jn as CliExit, jt as navigationIdentityMap, k as calculateFooterDiff, kn as formatError, kt as duplicateNavigationIdentityMessage, l as unsafeAsCliBlockIdentifier, ln as getOutputOnlyContext, lt as readFooterMeta, m as commandReportToSyncResult, mn as parseJsonData, mt as readVenuesMeta, n as entryCommandCompileErrorToReport, nn as createCommandContext, nt as downloadMedia, o as executeEntryCommandPlanAsSyncResult, on as currentInvocationEnvelope, ot as readAllMeta, p as unsafeAsCliPageIdentifier, pn as parseJsonArray, pt as readSettingsMeta, q as prepareLocalMediaForPush, qt as createBearerAPIClient, r as entryCommandReportToSyncResult, rn as createGetCommand, rt as extractMediaIdentifiers, s as syncResultForEntryCommandCompileError, sn as formatDateShort, st as readEventCategoriesMeta, t as compileEntryPushCommands, tn as createClientForEnv, tt as buildStorageUrl, u as unsafeAsCliContentTypeKey, un as handleCommandError, ut as readFormsMeta, v as commandReportHasFailures, vn as withCommandContext, vt as metadataTargetFromEnvironment, w as mergeManySyncResults, wn as planEnvironmentExecution, wt as listFiles, x as formatManagementError, xn as withOutputOnlyErrorHandling, xt as writeMetadataRecordMap, y as executeCliCommandPlan, yn as withConfirmation, yt as readMetadataFile, zn as ManagementApiError, zt as loadPushConfigTarget } from "../entryCommands-BGVgMNMw.mjs";
5
+ import { r as CLI_VERSION, t as loadConfigFile } from "../load-config-BV9Ig2CH.mjs";
6
+ import { a as RichTextDocSchema, c as isRecord$18, i as findUnfilledSentinels, n as buildEntryScaffold, o as isRichTextDoc, r as validateEntryInstance, s as isObjectRecord, t as eventUpsertInputSchema } from "../eventUpsertInputSchema-CdX--hHz.mjs";
7
+ import { a as prepareScaffoldExecution, c as LOCAL_PACKAGE_VENDOR_DIR, d as loadGeneratedPackageRanges, i as preflightScaffoldTargets, n as createScaffoldCompletion, s as deriveScaffoldLocalManifest, t as deriveScaffoldPlan } from "../plan-CFMj_Hee.mjs";
8
8
  import { config } from "dotenv";
9
9
  import { Command, CommanderError } from "commander";
10
10
  import * as fs$2 from "fs/promises";
@@ -5996,7 +5996,7 @@ function isAllowedTransformId(id) {
5996
5996
  }
5997
5997
 
5998
5998
  //#endregion
5999
- //#region ../blocks/src/system/layout/repeaterGrid.ts
5999
+ //#region ../blocks/src/system/layout/repeaterGridModel.ts
6000
6000
  const DEFAULT_REPEATER_GRID_SPAN_FIELD_ID = "gridSpan";
6001
6001
  const DEFAULT_REPEATER_GRID_ROW_FIELD_ID = "gridRow";
6002
6002
  const DEFAULT_REPEATER_GRID_COLUMN_FIELD_ID = "gridColumn";
@@ -6137,16 +6137,10 @@ function withRepeaterGridSpanField(fields$1, options) {
6137
6137
  return [createRepeaterGridSpanField(options), ...fields$1];
6138
6138
  }
6139
6139
  function withRepeaterGridPositionFields(fields$1, options) {
6140
- let nextFields = [...fields$1];
6141
6140
  const rowFieldId = resolveRepeaterGridRowFieldId(options?.row);
6142
- if (!nextFields.some((field) => field.id === rowFieldId)) {
6143
- nextFields = [createRepeaterGridRowField(options?.row), ...nextFields];
6144
- }
6141
+ const withRow = fields$1.some((field) => field.id === rowFieldId) ? [...fields$1] : [createRepeaterGridRowField(options?.row), ...fields$1];
6145
6142
  const columnFieldId = resolveRepeaterGridColumnFieldId(options?.column);
6146
- if (!nextFields.some((field) => field.id === columnFieldId)) {
6147
- nextFields = [createRepeaterGridColumnField(options?.column), ...nextFields];
6148
- }
6149
- return nextFields;
6143
+ return withRow.some((field) => field.id === columnFieldId) ? withRow : [createRepeaterGridColumnField(options?.column), ...withRow];
6150
6144
  }
6151
6145
  function withRepeaterGridSpanFieldOnItemTypes(itemTypes, options) {
6152
6146
  const entries = Object.entries(itemTypes).map(([typeKey, itemType]) => {
@@ -6289,6 +6283,7 @@ function flowRepeaterGridItems(items, columns) {
6289
6283
  }];
6290
6284
  }, []);
6291
6285
  }
6286
+ /** @internal */
6292
6287
  function orderedGridItems(layout) {
6293
6288
  return [...layout.placements].sort((a$1, b$1) => a$1.sourceIndex - b$1.sourceIndex);
6294
6289
  }
@@ -6315,6 +6310,7 @@ function findFlowAppendPlacement(layout, span, startNewRow) {
6315
6310
  colStart: next.colStart
6316
6311
  } : null;
6317
6312
  }
6313
+ /** @internal */
6318
6314
  function planFlowItems(layout, items) {
6319
6315
  const placed = flowRepeaterGridItems(items, layout.columns);
6320
6316
  if (isRepeaterGridLayoutInvalid(layout) || placed.some((item) => !isAcceptedRepeaterGridSpan(item.span, layout.columns, item.acceptedSpans) || layout.maxRows != null && item.row > layout.maxRows)) return { kind: "blocked" };
@@ -6412,6 +6408,7 @@ function buildRepeaterGridLayout(input) {
6412
6408
  const overCapacity = maxRows != null && maxRowUsed > maxRows;
6413
6409
  return {
6414
6410
  placementPolicy: input.placementPolicy,
6411
+ sourceItems: input.items.map((item) => ({ ...item })),
6415
6412
  columns,
6416
6413
  maxRows,
6417
6414
  capacityCells,
@@ -6459,6 +6456,9 @@ function canAppendRepeaterGridItem(input) {
6459
6456
  maxRows: input.maxRows
6460
6457
  }) != null;
6461
6458
  }
6459
+
6460
+ //#endregion
6461
+ //#region ../blocks/src/system/layout/repeaterGrid.ts
6462
6462
  function placementsOverlap(left, right) {
6463
6463
  return left.row === right.row && left.colStart < right.colStart + right.span && right.colStart < left.colStart + left.span;
6464
6464
  }
@@ -6478,10 +6478,44 @@ function swapPositionUpdates(active, target) {
6478
6478
  span: target.span
6479
6479
  }];
6480
6480
  }
6481
+ /** Admission retains raw authoring geometry; display-only callers may supply placements alone. */
6482
+ function sourceGridItems(layout) {
6483
+ return layout.sourceItems ?? layout.placements;
6484
+ }
6485
+ /** Repair edits may remove existing defects, but cannot introduce another one. */
6486
+ function gridDefects(layout) {
6487
+ const geometry = sourceGridItems(layout).flatMap((item) => [
6488
+ ...!isAcceptedRepeaterGridSpan(item.span, layout.columns, item.acceptedSpans) ? [`span:${item.id}`] : [],
6489
+ ...!Number.isInteger(item.row) || item.row < 1 ? [`row:${item.id}`] : [],
6490
+ ...!Number.isInteger(item.colStart) || item.colStart < 1 || item.colStart + item.span - 1 > layout.columns ? [`column:${item.id}`] : []
6491
+ ]);
6492
+ const collisions = layout.placements.flatMap((item, index) => layout.placements.slice(index + 1).filter((other) => placementsOverlap(item, other)).map((other) => `collision:${[item.id, other.id].sort().join(":")}`));
6493
+ const capacity = layout.placements.filter((item) => layout.maxRows != null && item.row > layout.maxRows).map((item) => `capacity:${item.id}`);
6494
+ return new Set([
6495
+ ...geometry,
6496
+ ...collisions,
6497
+ ...capacity,
6498
+ ...(layout.invalidCoordinateIds ?? []).map((id) => `coordinate:${id}`)
6499
+ ]);
6500
+ }
6481
6501
  function validateGridMove(layout, updates) {
6482
- const moved = updates;
6483
- const stationary = layout.placements.filter((placement) => !updates.some((update) => update.id === placement.id));
6484
- const valid = !layout.hasInvalidItems && !layout.hasCollisions && !layout.overCapacity && moved.every((placement, index) => isAcceptedRepeaterGridSpan(placement.span, layout.columns, layout.byId[placement.id]?.acceptedSpans) && placement.colStart >= 1 && placement.colStart + placement.span - 1 <= layout.columns && placement.row >= 1 && (layout.maxRows == null || placement.row <= layout.maxRows) && !stationary.some((other) => placementsOverlap(placement, other)) && !moved.slice(index + 1).some((other) => placementsOverlap(placement, other)));
6502
+ const items = sourceGridItems(layout).map((item) => ({
6503
+ ...item,
6504
+ ...updates.find((update) => update.id === item.id)
6505
+ }));
6506
+ const candidate = buildRepeaterGridLayout({
6507
+ items,
6508
+ columns: layout.columns,
6509
+ maxRows: layout.maxRows,
6510
+ placementPolicy: layout.placementPolicy
6511
+ });
6512
+ const unresolved = (layout.invalidCoordinateIds ?? []).filter((id) => !updates.some((update) => update.id === id));
6513
+ const before = gridDefects(layout);
6514
+ const after = gridDefects({
6515
+ ...candidate,
6516
+ invalidCoordinateIds: unresolved
6517
+ });
6518
+ const valid = before.size === 0 ? after.size === 0 : after.size < before.size && [...after].every((defect) => before.has(defect));
6485
6519
  return valid ? {
6486
6520
  kind: "move",
6487
6521
  updates
@@ -6492,7 +6526,7 @@ function decideGridDrop(layout, active, destination) {
6492
6526
  if (occupants.length > 1) return { kind: "blocked" };
6493
6527
  const target = occupants[0];
6494
6528
  if (target) return validateGridMove(layout, swapPositionUpdates(active, target));
6495
- if (destination.row === active.row && destination.colStart === active.colStart) return { kind: "unchanged" };
6529
+ if (destination.row === active.row && destination.colStart === active.colStart && !isRepeaterGridLayoutInvalid(layout)) return { kind: "unchanged" };
6496
6530
  return validateGridMove(layout, [{
6497
6531
  id: active.id,
6498
6532
  row: destination.row,
@@ -6503,7 +6537,7 @@ function decideGridDrop(layout, active, destination) {
6503
6537
  function buildRepeaterGridDropTargets(input) {
6504
6538
  const { layout, draggedId, rowsToRender } = input;
6505
6539
  const active = layout.byId[draggedId];
6506
- if (!active || isRepeaterGridLayoutInvalid(layout)) return [];
6540
+ if (!active || layout.placementPolicy === "flow" && isRepeaterGridLayoutInvalid(layout)) return [];
6507
6541
  if (layout.placementPolicy === "flow") return orderedGridItems(layout).map((item, index) => ({
6508
6542
  id: `repeater-grid-drop-${item.row}-${item.colStart}`,
6509
6543
  row: item.row,
@@ -6512,7 +6546,7 @@ function buildRepeaterGridDropTargets(input) {
6512
6546
  decision: planRepeaterGridReorder(layout, draggedId, index, input.interaction ?? "drag")
6513
6547
  }));
6514
6548
  const rowCeiling = layout.maxRows ?? Math.max(1, rowsToRender ?? layout.maxRowUsed + 1, active.row + 1);
6515
- return Array.from({ length: rowCeiling * layout.columns }, (_$1, index) => {
6549
+ const targets = Array.from({ length: rowCeiling * layout.columns }, (_$1, index) => {
6516
6550
  const row$1 = Math.floor(index / layout.columns) + 1;
6517
6551
  const colStart = index % layout.columns + 1;
6518
6552
  return {
@@ -6526,6 +6560,13 @@ function buildRepeaterGridDropTargets(input) {
6526
6560
  })
6527
6561
  };
6528
6562
  });
6563
+ return targets.some((target) => target.row === active.row && target.colStart === active.colStart) ? targets : [...targets, {
6564
+ id: `repeater-grid-drop-${active.row}-${active.colStart}`,
6565
+ row: active.row,
6566
+ colStart: active.colStart,
6567
+ cell: active.startCell,
6568
+ decision: { kind: "unchanged" }
6569
+ }];
6529
6570
  }
6530
6571
  /** Width edits keep the item's start when it fits; otherwise relocate it to the first free cell.
6531
6572
  * Neighbours keep their positions. A full bounded grid blocks the change without partial writes.
@@ -6533,14 +6574,19 @@ function buildRepeaterGridDropTargets(input) {
6533
6574
  function planRepeaterGridSpanChange(input) {
6534
6575
  const { layout, id, span } = input;
6535
6576
  const active = layout.byId[id];
6536
- if (isRepeaterGridLayoutInvalid(layout)) return { kind: "blocked" };
6577
+ if (layout.placementPolicy === "flow" && isRepeaterGridLayoutInvalid(layout)) return { kind: "blocked" };
6537
6578
  if (!active || !isAcceptedRepeaterGridSpan(span, layout.columns, active.acceptedSpans)) return { kind: "blocked" };
6538
6579
  const nextSpan = Number(span);
6539
- if (active.span === nextSpan) return { kind: "unchanged" };
6580
+ if (!isRepeaterGridLayoutInvalid(layout) && sourceGridItems(layout).find((item) => item.id === id)?.span === nextSpan) return { kind: "unchanged" };
6540
6581
  if (layout.placementPolicy === "flow") return planFlowItems(layout, orderedGridItems(layout).map((item) => item.id === id ? {
6541
6582
  ...item,
6542
6583
  span: nextSpan
6543
6584
  } : item));
6585
+ return planFreeGridSpanChange(layout, active, nextSpan);
6586
+ }
6587
+ /** Free width edits retain the current start when possible, then use the shared first-free planner. */
6588
+ function planFreeGridSpanChange(layout, active, nextSpan) {
6589
+ const id = active.id;
6544
6590
  const atCurrent = validateGridMove(layout, [{
6545
6591
  id,
6546
6592
  span: nextSpan,
@@ -6612,6 +6658,33 @@ function projectRepeaterGridLayoutForRendering(layout, columns = layout.columns)
6612
6658
  const count = normalizeRepeaterGridColumns(columns);
6613
6659
  return buildProjectedRepeaterGridLayout(layout, flowRepeaterGridItems(orderedGridItems(layout), count), count);
6614
6660
  }
6661
+ /** An explicit column reduction re-places free grids through the existing placement primitive. */
6662
+ function planRepeaterGridColumnChange(layout, columns) {
6663
+ if (layout.placementPolicy === "flow" || columns >= layout.columns) return { kind: "unchanged" };
6664
+ if (isRepeaterGridLayoutInvalid(layout)) return { kind: "blocked" };
6665
+ const placed = orderedGridItems(layout).reduce((items, item) => {
6666
+ if (!items) return null;
6667
+ const bounded = normalizeRepeaterGridSpan(item.span, columns);
6668
+ const span = item.acceptedSpans ? Math.max(0, ...item.acceptedSpans.filter((width) => width <= bounded)) : bounded;
6669
+ const destination = findFirstAvailableRepeaterGridPlacement({
6670
+ items,
6671
+ columns,
6672
+ maxRows: layout.maxRows,
6673
+ newItemSpan: span,
6674
+ acceptedSpans: item.acceptedSpans
6675
+ });
6676
+ return destination ? [...items, {
6677
+ ...item,
6678
+ span,
6679
+ ...destination
6680
+ }] : null;
6681
+ }, []);
6682
+ const [first, ...rest] = placed ?? [];
6683
+ return first ? {
6684
+ kind: "move",
6685
+ updates: [first, ...rest]
6686
+ } : placed ? { kind: "unchanged" } : { kind: "blocked" };
6687
+ }
6615
6688
 
6616
6689
  //#endregion
6617
6690
  //#region ../blocks/src/system/manifest/layoutGridConfiguration.ts
@@ -7627,6 +7700,14 @@ function validateLayoutGridPlans(plans, value, rootValues = layoutGridRecord(val
7627
7700
  })];
7628
7701
  });
7629
7702
  }
7703
+ /** User-authored column edits only; never run this as a load/render projection. */
7704
+ function planLayoutGridColumnEdit(plan, items, before, after) {
7705
+ const grid$5 = plan.layoutGrid;
7706
+ if (!grid$5?.columnsFields) return { kind: "unchanged" };
7707
+ const columns = resolveRepeaterGridColumnsForBreakpoint(after, grid$5.columnsFields, "lg");
7708
+ const previous = buildLayoutGridForPlan(plan, items, before);
7709
+ return previous ? planRepeaterGridColumnChange(previous, columns) : { kind: "unchanged" };
7710
+ }
7630
7711
 
7631
7712
  //#endregion
7632
7713
  //#region ../blocks/src/system/inlineText.ts
@@ -10213,19 +10294,22 @@ function isEmptyRichTextDoc(value) {
10213
10294
 
10214
10295
  //#endregion
10215
10296
  //#region ../blocks/src/system/manifest/fieldValidation/layoutGridRendering.ts
10216
- function hasInvalidCoordinateValues(plan, items) {
10297
+ function invalidCoordinateIds(plan, items, itemIds) {
10217
10298
  const ids = layoutGridCoordinateFieldIds(plan);
10218
- return items.some((item) => {
10299
+ return items.flatMap((item, index) => {
10219
10300
  const row$1 = layoutGridRecord(item);
10220
- return row$1 !== null && resolveLayoutGridItemPlans(plan, row$1).some((field) => ids.includes(field.fieldId) && !fieldPlanToStrictObjectPropertyZod(field).safeParse(row$1[field.fieldId]).success);
10301
+ const invalid$1 = row$1 !== null && resolveLayoutGridItemPlans(plan, row$1).some((field) => ids.includes(field.fieldId) && !fieldPlanToStrictObjectPropertyZod(field).safeParse(row$1[field.fieldId]).success);
10302
+ return invalid$1 ? [itemIds?.[index] ?? String(index)] : [];
10221
10303
  });
10222
10304
  }
10223
10305
  /** Shared raw-coordinate admission for editor and public rendering; retains diagnostics. */
10224
10306
  function admitLayoutGridForPlan(plan, value, rootValues, ids) {
10225
10307
  const layout = buildLayoutGridForPlan(plan, value, rootValues, ids);
10226
- return layout && !layout.hasInvalidItems && hasInvalidCoordinateValues(plan, value) ? {
10308
+ const invalidIds = invalidCoordinateIds(plan, value, ids);
10309
+ return layout && invalidIds.length > 0 ? {
10227
10310
  ...layout,
10228
- hasInvalidItems: true
10311
+ hasInvalidItems: true,
10312
+ invalidCoordinateIds: invalidIds
10229
10313
  } : layout;
10230
10314
  }
10231
10315
  function projectGrid(plan, value, rootValues) {
@@ -25252,7 +25336,7 @@ const publicEventAttendanceModeSchema = z.enum(["in_person", "online"]);
25252
25336
  const publicEventAttendanceModeAvailabilitySchema = z.object({
25253
25337
  mode: publicEventAttendanceModeSchema,
25254
25338
  capacity: z.number().nullable(),
25255
- registeredCount: z.number(),
25339
+ registeredCount: z.number().nullable(),
25256
25340
  availableSpots: z.number().nullable(),
25257
25341
  waitlistEnabled: z.boolean()
25258
25342
  });
@@ -25417,7 +25501,7 @@ const publicEventBaseSchema = z.object({
25417
25501
  startsAt: z.string(),
25418
25502
  endsAt: z.string(),
25419
25503
  capacity: z.number().nullable(),
25420
- registeredCount: z.number(),
25504
+ registeredCount: z.number().nullable(),
25421
25505
  availableSpots: z.number().nullable(),
25422
25506
  waitlistEnabled: z.boolean(),
25423
25507
  venue: eventVenueSchema.nullable(),
@@ -25822,6 +25906,10 @@ function getEventAvailability(event) {
25822
25906
  isFull: false
25823
25907
  };
25824
25908
  }
25909
+ if (event.registeredCount === null) return {
25910
+ available: 0,
25911
+ isFull: true
25912
+ };
25825
25913
  const available = event.availableSpots ?? event.capacity - event.registeredCount;
25826
25914
  if (available <= 0) {
25827
25915
  return {
@@ -25877,12 +25965,12 @@ function lowCapacityThreshold(capacity) {
25877
25965
  }
25878
25966
  function getRemainingPlaces(source) {
25879
25967
  const { available, isFull: isFull$1 } = getEventAvailability(source);
25880
- if (available === null || source.capacity === null) return { kind: "unlimited" };
25968
+ if (available === null) return { kind: "unlimited" };
25881
25969
  if (isFull$1) return {
25882
25970
  kind: "full",
25883
25971
  waitlist: canJoinEventWaitlist(source)
25884
25972
  };
25885
- if (available <= lowCapacityThreshold(source.capacity)) {
25973
+ if (source.capacity !== null && available <= lowCapacityThreshold(source.capacity)) {
25886
25974
  return {
25887
25975
  kind: "low",
25888
25976
  remaining: available
@@ -26181,6 +26269,30 @@ function createHostedBlockApiConfig(input) {
26181
26269
  };
26182
26270
  }
26183
26271
 
26272
+ //#endregion
26273
+ //#region ../blocks/src/system/runtime/nodes/events/shared/eventScheduleSummary.ts
26274
+ function bookingDateLocale(siteTimeZone) {
26275
+ return inferSiteDateLocale(resolveBookingBusinessTimeZone(siteTimeZone));
26276
+ }
26277
+ /** A stored local clock has no date or DST offset; UTC preserves its digits. */
26278
+ function formatBookingSchedulePresentation(event) {
26279
+ const summary = event.scheduleSummary;
26280
+ if (!summary) return null;
26281
+ const start = summary.startTime ? parseUtcIsoDateTimeString(`1970-01-01T${summary.startTime}:00Z`) : null;
26282
+ const time = start?.ok ? formatTime$1(start.value, {
26283
+ timeZone: resolveBookingTimeZoneId("UTC"),
26284
+ locale: bookingDateLocale(event.siteTimeZone)
26285
+ }, { zone: "omit" }) : null;
26286
+ return {
26287
+ text: [summary.recurrenceDescription, time].filter(Boolean).join(", "),
26288
+ clock: time
26289
+ };
26290
+ }
26291
+ /** Text-only consumers delegate to the same authored-clock presentation. */
26292
+ function formatBookingScheduleSummary(event) {
26293
+ return formatBookingSchedulePresentation(event)?.text ?? null;
26294
+ }
26295
+
26184
26296
  //#endregion
26185
26297
  //#region ../blocks/src/system/runtime/nodes/events/domain/bookability.ts
26186
26298
  /**
@@ -28404,8 +28516,13 @@ function buildCalendarViewport(input) {
28404
28516
  }
28405
28517
  /** Tick digits are civil clock values, not session instants. */
28406
28518
  function formatEventHourLabel(hour, timeZone) {
28407
- return formatTime$1(toUtcIsoDateTimeString(`2000-01-01T${String(hour % 24).padStart(2, "0")}:00:00Z`), {
28408
- locale: eventDateLocale(timeZone),
28519
+ return formatEventClockLabel(`${String(hour % 24).padStart(2, "0")}:00`, eventDateLocale(timeZone));
28520
+ }
28521
+ /** Weekly cadence and tick clocks are civil values; UTC only carries their components. */
28522
+ function formatEventClockLabel(value, locale) {
28523
+ const clock = parseLocalScheduleTime(value);
28524
+ return formatTime$1(toUtcIsoDateTimeString(new Date(Date.UTC(2e3, 0, 1, clock.hour, clock.minute)).toISOString()), {
28525
+ locale,
28409
28526
  timeZone: resolveBookingBusinessTimeZone("UTC")
28410
28527
  }, { zone: "omit" });
28411
28528
  }
@@ -28824,9 +28941,9 @@ function findBookedEvent(events, identity) {
28824
28941
 
28825
28942
  //#endregion
28826
28943
  //#region ../blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.ts
28827
- /** Ticket selection requests a quote; only the server admits a booking. */
28828
- function canRequestTicketOption(availability) {
28829
- return availability.kind === "available" || availability.reason === "sold_out" || availability.reason === "overallCapacityUnavailable";
28944
+ /** Waitlists request places; bookings can only request currently available capacity. */
28945
+ function canRequestTicketOption(availability, purpose) {
28946
+ return availability.kind === "available" || purpose === "waitlist" && (availability.reason === "sold_out" || availability.reason === "overallCapacityUnavailable");
28830
28947
  }
28831
28948
  function normalizeTicketSelectionLines(lines) {
28832
28949
  const quantitiesByTicketType = new Map();
@@ -28854,8 +28971,20 @@ function getSingleSelectedPricingOptionId(lines) {
28854
28971
  function hasValidPricingOptionSelection(input) {
28855
28972
  if (!input.selectionRequired) return true;
28856
28973
  if (input.lines.length === 0) return false;
28857
- const availableOptionIds = new Set(input.visibleOptions.filter((option) => canRequestTicketOption(option.availability)).map((option) => option.pricingOptionId));
28858
- return input.lines.every((line) => line.pricingOptionId !== null && availableOptionIds.has(line.pricingOptionId));
28974
+ const totalSelectedQuantity = getTicketSelectionTotal(input.lines);
28975
+ return input.lines.every((line) => {
28976
+ const option = input.visibleOptions.find((option$1) => option$1.pricingOptionId === line.pricingOptionId);
28977
+ return option !== undefined && line.quantity <= getTicketTypeLineMax({
28978
+ currentQuantity: line.quantity,
28979
+ totalSelectedQuantity,
28980
+ maxTickets: input.maxTickets,
28981
+ purpose: input.purpose,
28982
+ pricingOptionId: option.pricingOptionId,
28983
+ availability: option.availability,
28984
+ heldPlacesBySelection: input.heldPlacesBySelection,
28985
+ overallRemainingPlaces: input.overallRemainingPlaces
28986
+ });
28987
+ });
28859
28988
  }
28860
28989
  function setTicketLineQuantity(input) {
28861
28990
  const nextQuantity = Math.max(0, Math.floor(input.quantity));
@@ -28869,9 +28998,19 @@ function setTicketLineQuantity(input) {
28869
28998
  }];
28870
28999
  }
28871
29000
  function getTicketTypeLineMax(input) {
29001
+ if (!canRequestTicketOption(input.availability, "waitlist")) return 0;
28872
29002
  const otherSelectedQuantity = input.totalSelectedQuantity - input.currentQuantity;
28873
29003
  const maxByBlock = input.maxTickets - otherSelectedQuantity;
28874
- return Math.max(0, maxByBlock);
29004
+ if (input.purpose === "waitlist") return Math.max(0, maxByBlock);
29005
+ const heldPlaces = input.heldPlacesBySelection ?? [];
29006
+ const heldForType = getTicketLineQuantity(heldPlaces, input.pricingOptionId);
29007
+ const publicRemaining = canRequestTicketOption(input.availability, input.purpose) ? input.availability.remainingPlaces ?? Infinity : 0;
29008
+ const maxByOverall = (input.overallRemainingPlaces ?? Infinity) + getTicketSelectionTotal(heldPlaces) - otherSelectedQuantity;
29009
+ return Math.max(0, Math.min(maxByBlock, publicRemaining + heldForType, maxByOverall));
29010
+ }
29011
+ /** Holds belong to the original event, mode and ticket types, not the edited draft. */
29012
+ function getHeldPlacesBySelection(current, held) {
29013
+ return held?.selectionId === current.selectionId && held?.attendanceMode === current.attendanceMode ? held.lines : [];
28875
29014
  }
28876
29015
 
28877
29016
  //#endregion
@@ -30792,20 +30931,6 @@ function formatTime$2(isoTimestamp, options) {
30792
30931
  const { context, zone } = bookingContext(options);
30793
30932
  return instant.ok ? formatTime$1(instant.value, context, { zone }) : isoTimestamp;
30794
30933
  }
30795
- function bookingDateLocale(siteTimeZone) {
30796
- return inferSiteDateLocale(resolveBookingBusinessTimeZone(siteTimeZone));
30797
- }
30798
- /** A stored local clock has no date or DST offset; UTC preserves its digits. */
30799
- function formatBookingScheduleSummary(event) {
30800
- const summary = event.scheduleSummary;
30801
- if (!summary) return null;
30802
- const start = summary.startTime ? parseUtcIsoDateTimeString(`1970-01-01T${summary.startTime}:00Z`) : null;
30803
- const time = start?.ok ? formatTime$1(start.value, {
30804
- timeZone: resolveBookingTimeZoneId("UTC"),
30805
- locale: bookingDateLocale(event.siteTimeZone)
30806
- }, { zone: "omit" }) : null;
30807
- return [summary.recurrenceDescription, time].filter(Boolean).join(", ");
30808
- }
30809
30934
  /** Variant meaning is closed here; core owns the resulting typography. */
30810
30935
  const BOOKING_DATE_PRESENTATIONS = {
30811
30936
  day: {
@@ -31054,10 +31179,34 @@ function getVisibleTicketTypes(input) {
31054
31179
  pricingOptionId: id
31055
31180
  })) : [];
31056
31181
  const source = input.eligibility?.ticketTypes ?? eventTicketTypes;
31057
- return source.filter((ticketType) => ticketType.isActive && (!input.selectedAttendanceMode || (ticketType.attendanceScope ?? "both") === "both" || (ticketType.attendanceScope ?? "both") === input.selectedAttendanceMode));
31182
+ const selectedIds = new Set(input.ticketSelections?.map((line) => line.pricingOptionId));
31183
+ return source.map((ticketType) => ticketTypeForSelectionMode(ticketType, input.selectedAttendanceMode)).filter((ticketType) => selectedIds.has(ticketType.pricingOptionId) || ticketType.isActive && ticketTypeMatchesMode(ticketType, input.selectedAttendanceMode));
31058
31184
  }
31059
- function getImplicitSingleTicketType(ticketTypes) {
31060
- return ticketTypes.length === 1 && ticketTypes[0] && canRequestTicketOption(ticketTypes[0].availability) ? ticketTypes[0] : null;
31185
+ function ticketTypeForSelectionMode(ticketType, mode) {
31186
+ if (!ticketType.isActive) return {
31187
+ ...ticketType,
31188
+ availability: {
31189
+ kind: "unavailable",
31190
+ reason: "inactive",
31191
+ remainingPlaces: ticketType.availability.remainingPlaces
31192
+ }
31193
+ };
31194
+ if (!ticketTypeMatchesMode(ticketType, mode)) return {
31195
+ ...ticketType,
31196
+ availability: {
31197
+ kind: "unavailable",
31198
+ reason: "attendance_mode_unavailable",
31199
+ remainingPlaces: ticketType.availability.remainingPlaces
31200
+ }
31201
+ };
31202
+ return ticketType;
31203
+ }
31204
+ function ticketTypeMatchesMode(ticketType, mode) {
31205
+ const scope = ticketType.attendanceScope ?? "both";
31206
+ return !mode || scope === "both" || scope === mode;
31207
+ }
31208
+ function getImplicitSingleTicketType(ticketTypes, purpose = "book") {
31209
+ return ticketTypes.length === 1 && ticketTypes[0] && canRequestTicketOption(ticketTypes[0].availability, purpose) ? ticketTypes[0] : null;
31061
31210
  }
31062
31211
  function findSelectedTicketType(input) {
31063
31212
  if (!input.selectedPricingOptionId) {
@@ -33404,6 +33553,27 @@ function getEligibilityFlowFlags(input) {
33404
33553
  isMembershipFastTrack: input.portalAuthState === "authenticated" && hasMembership && input.ticketsCount === 1 && input.paymentMethod === "membership"
33405
33554
  };
33406
33555
  }
33556
+ /** Prefer refreshed capacity, including a known zero; fall back while options load. */
33557
+ function getTicketSelectionRemainingPlaces(input) {
33558
+ const availability = input.eligibility?.availability;
33559
+ if (availability && "remainingPlaces" in availability) return availability.remainingPlaces ?? null;
33560
+ return input.event ? getEventAvailability(selectEventCapacitySource(input.event, input.attendanceMode)).available : null;
33561
+ }
33562
+ function resolveHeldTicketPlaces(current, invitation, paymentHold) {
33563
+ const held = invitation.kind === "ready" ? {
33564
+ selectionId: invitation.restoration.event?.selectionId ?? current.selectionId,
33565
+ attendanceMode: invitation.restoration.attendanceMode,
33566
+ lines: invitation.restoration.ticketSelections
33567
+ } : paymentHold;
33568
+ return getHeldPlacesBySelection(current, held);
33569
+ }
33570
+ function getCurrentTicketSelection(event, attendanceMode, lines) {
33571
+ return {
33572
+ selectionId: event?.selectionId ?? null,
33573
+ attendanceMode,
33574
+ lines
33575
+ };
33576
+ }
33407
33577
 
33408
33578
  //#endregion
33409
33579
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationDraft.state.ts
@@ -35686,9 +35856,7 @@ function buildConfirmationPaymentCandidate(input) {
35686
35856
  default: return assertNever$7(input);
35687
35857
  }
35688
35858
  }
35689
- /** Public payment evidence returns only schema-valid decisions. Legacy email
35690
- * snapshots deliberately use the amount calculation below instead of this boundary.
35691
- */
35859
+ /** Persisted booking payment evidence returns only schema-valid decisions. */
35692
35860
  function buildConfirmationPayment(input) {
35693
35861
  const payment = buildConfirmationPaymentCandidate(input);
35694
35862
  if (!payment.ok) return payment;
@@ -35699,24 +35867,6 @@ function buildConfirmationPayment(input) {
35699
35867
  function settledOrderItemTotalCents(item) {
35700
35868
  return effectiveOrderItemNetTotalCents(item) + (item.creditCents ?? 0);
35701
35869
  }
35702
- /** Historical notification amounts, not a validated public payment decision.
35703
- * Preserve HEAD's raw snapshot numbers; strict evidence validation belongs to
35704
- * the public read boundary, not notification-plan construction (#1587).
35705
- */
35706
- function calculateOrderItemsConfirmationPaymentAmounts(input) {
35707
- const totalCents = input.items.reduce((total, item) => total + settledOrderItemTotalCents(item), 0);
35708
- const amountPaidCents = input.settlement.kind === "settled_in_full" ? totalCents : input.settlement.collectedCents;
35709
- return {
35710
- amountPaidCents,
35711
- amountOutstandingCents: calculateOutstandingOrderAmountCents({
35712
- totalCents,
35713
- settledCents: amountPaidCents
35714
- })
35715
- };
35716
- }
35717
- function collectedOrderItemsConfirmationCents(items, collectedCentsByOrderItemId) {
35718
- return items.reduce((total, item) => total + (collectedCentsByOrderItemId[item.id] ?? 0), 0);
35719
- }
35720
35870
 
35721
35871
  //#endregion
35722
35872
  //#region ../commerce/src/purchase/confirmationEmailPayment.ts
@@ -35778,56 +35928,9 @@ function toConfirmationEmailPaymentSummary(payment) {
35778
35928
  default: return assertNever$7(payment);
35779
35929
  }
35780
35930
  }
35781
- /** Legacy notification adapter, retained unchanged in meaning until #1587. */
35782
- function buildOrderItemsConfirmationEmailPaymentSummary(options) {
35783
- switch (options.orderPaymentMethod) {
35784
- case "stripe":
35785
- case "store_credit":
35786
- case "mixed": {
35787
- const amounts = calculateOrderItemsConfirmationPaymentAmounts({
35788
- items: options.items,
35789
- settlement: options.settlement
35790
- });
35791
- return {
35792
- kind: "monetary",
35793
- amountPaidCents: amounts.amountPaidCents,
35794
- ...options.settlement.kind === "settled_in_full" ? {} : {
35795
- amountOutstandingCents: amounts.amountOutstandingCents,
35796
- dueAt: options.flexibleBalanceDueAt ?? null
35797
- },
35798
- currency: options.currency,
35799
- paymentMethod: options.orderPaymentMethod
35800
- };
35801
- }
35802
- case "pass_redemption": return { kind: "pass" };
35803
- case "membership_access": return { kind: "membership" };
35804
- case "manual": return options.flexibleBalanceDueAt ? {
35805
- kind: "managed_balance_due",
35806
- dueAt: options.flexibleBalanceDueAt
35807
- } : { kind: "manual_due" };
35808
- case "waived": return { kind: "waived" };
35809
- case "free": return { kind: "free" };
35810
- default: return assertNever$7(options.orderPaymentMethod);
35811
- }
35812
- }
35813
- function buildOrderItemConfirmationEmailPaymentSummary(options) {
35814
- return buildOrderItemsConfirmationEmailPaymentSummary({
35815
- ...options,
35816
- items: [options.item]
35817
- });
35818
- }
35819
- function buildEventRegistrationConfirmationEmailPaymentSummary(options) {
35820
- return buildNonMonetaryConfirmationEmailPaymentSummary({
35821
- paymentMethod: options.paymentMethod,
35822
- passCreditsUsed: options.passCreditsUsed
35823
- });
35824
- }
35825
35931
  function buildManualAttendeeConfirmationEmailPaymentSummary(options) {
35826
35932
  return buildNonMonetaryConfirmationEmailPaymentSummary(options);
35827
35933
  }
35828
- function buildBundleConfirmationEmailPaymentSummary(options) {
35829
- return buildNonMonetaryConfirmationEmailPaymentSummary(options);
35830
- }
35831
35934
  function buildTransferredAttendeeConfirmationEmailPaymentSummary(options) {
35832
35935
  switch (options.paymentMethod) {
35833
35936
  case "free":
@@ -35841,34 +35944,6 @@ function buildTransferredAttendeeConfirmationEmailPaymentSummary(options) {
35841
35944
  }
35842
35945
  return assertNever$7(options.paymentMethod);
35843
35946
  }
35844
- function buildEventSeriesRegistrationConfirmationEmailPaymentSummary(options) {
35845
- switch (options.paymentMethod) {
35846
- case "free":
35847
- case "membership": return buildNonMonetaryConfirmationEmailPaymentSummary({
35848
- paymentMethod: options.paymentMethod,
35849
- membershipName: options.membershipName
35850
- });
35851
- case "stripe": return buildMonetaryConfirmationEmailPaymentSummary({
35852
- amountPaidCents: options.amountPaidCents,
35853
- currency: options.currency,
35854
- paymentMethod: "stripe"
35855
- });
35856
- }
35857
- return assertNever$7(options.paymentMethod);
35858
- }
35859
- function buildBypassedCheckoutConfirmationEmailPaymentSummary(options) {
35860
- switch (options.bypassReason) {
35861
- case "free":
35862
- case "discount_free": return { kind: "free" };
35863
- case "store_credit": return {
35864
- kind: "monetary",
35865
- amountPaidCents: options.settledAmountCents,
35866
- currency: options.currency,
35867
- paymentMethod: "store_credit"
35868
- };
35869
- }
35870
- return assertNever$7(options.bypassReason);
35871
- }
35872
35947
  function toConfirmationEmailTemplatePaymentFields(summary) {
35873
35948
  if (!summary) {
35874
35949
  return {};
@@ -36432,170 +36507,143 @@ function resolveInstalmentPlanIntroText(input) {
36432
36507
 
36433
36508
  //#endregion
36434
36509
  //#region ../commerce/src/purchase/orderCompletionEmailPlan.ts
36435
- function buildEventConfirmationAction(items, options) {
36436
- const firstItem = items[0];
36437
- if (!firstItem) {
36438
- throw new Error("Cannot build an event confirmation without order items");
36439
- }
36440
- const settlement = options.settlement;
36441
- const paymentSummary = buildOrderItemsConfirmationEmailPaymentSummary({
36442
- orderPaymentMethod: options.orderPaymentMethod,
36443
- items,
36444
- currency: options.currency,
36445
- flexibleBalanceDueAt: options.flexibleBalanceDueAt,
36446
- settlement: settlement.kind === "settled_in_full" ? settlement : {
36447
- kind: "collected",
36448
- collectedCents: collectedOrderItemsConfirmationCents(items, settlement.collectedCentsByOrderItemId)
36449
- }
36450
- });
36451
- return {
36452
- kind: "send_event_confirmation",
36453
- attendeeId: firstItem.eventAttendeeId,
36454
- metadata: {
36455
- ...firstItem.metadata,
36456
- ticketCount: items.reduce((total, item) => total + item.metadata.ticketCount, 0)
36457
- },
36458
- paymentSummary
36459
- };
36460
- }
36461
36510
  function hasPassBundleFulfillment(metadata) {
36462
36511
  return !!metadata.bundleFulfillment;
36463
36512
  }
36464
36513
  function hasMembershipBundleFulfillment(metadata) {
36465
36514
  return !!metadata.bundleFulfillment;
36466
36515
  }
36467
- function buildOrderCompletionEmailPlan(options) {
36468
- const firstItem = options.items[0];
36469
- if (!firstItem) {
36470
- return {
36516
+ const noActions = () => ({
36517
+ actions: [],
36518
+ warnings: []
36519
+ });
36520
+ function planEventItem(item, input) {
36521
+ const id = item.kind === "event_ticket" ? item.eventAttendeeId : item.eventSeriesRegistrationId;
36522
+ if (!id) return {
36523
+ actions: [],
36524
+ warnings: [{
36525
+ kind: item.kind === "event_ticket" ? "missing_event_attendee_id" : "missing_event_series_registration_id",
36526
+ orderId: item.orderId,
36527
+ orderItemId: item.id
36528
+ }]
36529
+ };
36530
+ const facts = input.bookingFacts.get(id);
36531
+ if (!facts) return noActions();
36532
+ if (item.kind === "event_ticket" && item.eventAttendeeId) return {
36533
+ warnings: [],
36534
+ actions: [{
36535
+ kind: "send_event_confirmation",
36536
+ facts,
36537
+ metadata: item.metadata
36538
+ }]
36539
+ };
36540
+ return {
36541
+ warnings: [],
36542
+ actions: [{
36543
+ kind: "send_event_series_registration_confirmation",
36544
+ orderId: item.orderId,
36545
+ facts
36546
+ }]
36547
+ };
36548
+ }
36549
+ function planPassItem(item, input) {
36550
+ if (!hasPassBundleFulfillment(item.metadata)) return noActions();
36551
+ if (!item.eventAttendeeId) return {
36552
+ actions: [],
36553
+ warnings: [{
36554
+ kind: "missing_event_attendee_id",
36555
+ orderId: item.orderId,
36556
+ orderItemId: item.id
36557
+ }]
36558
+ };
36559
+ const facts = input.bookingFacts.get(item.eventAttendeeId);
36560
+ return facts ? {
36561
+ warnings: [],
36562
+ actions: [{
36563
+ kind: "send_pass_bundle_confirmation",
36564
+ facts,
36565
+ metadata: item.metadata
36566
+ }]
36567
+ } : noActions();
36568
+ }
36569
+ function planMembershipItem(item, input) {
36570
+ if (hasMembershipBundleFulfillment(item.metadata)) {
36571
+ if (!item.eventAttendeeId) return {
36471
36572
  actions: [],
36472
- warnings: []
36573
+ warnings: [{
36574
+ kind: "missing_event_attendee_id",
36575
+ orderId: item.orderId,
36576
+ orderItemId: item.id
36577
+ }]
36473
36578
  };
36579
+ const facts = input.bookingFacts.get(item.eventAttendeeId);
36580
+ return facts ? {
36581
+ warnings: [],
36582
+ actions: [{
36583
+ kind: "send_membership_bundle_confirmation",
36584
+ facts,
36585
+ metadata: item.metadata
36586
+ }]
36587
+ } : noActions();
36588
+ }
36589
+ if (!item.customerMembershipId) return {
36590
+ actions: [],
36591
+ warnings: [{
36592
+ kind: "missing_customer_membership_id",
36593
+ orderId: item.orderId,
36594
+ orderItemId: item.id
36595
+ }]
36596
+ };
36597
+ return {
36598
+ warnings: [],
36599
+ actions: [{
36600
+ kind: "send_membership_activation",
36601
+ customerMembershipId: item.customerMembershipId,
36602
+ amountPaidCents: settledOrderItemTotalCents(item)
36603
+ }]
36604
+ };
36605
+ }
36606
+ function planItem(item, input) {
36607
+ switch (item.kind) {
36608
+ case "event_ticket":
36609
+ case "event_series_registration": return planEventItem(item, input);
36610
+ case "pass": return planPassItem(item, input);
36611
+ case "membership": return planMembershipItem(item, input);
36612
+ case "appointment": return item.appointmentId ? {
36613
+ warnings: [],
36614
+ actions: [{
36615
+ kind: "send_appointment_confirmation",
36616
+ appointmentId: item.appointmentId
36617
+ }]
36618
+ } : {
36619
+ actions: [],
36620
+ warnings: [{
36621
+ kind: "missing_appointment_id",
36622
+ orderId: item.orderId,
36623
+ orderItemId: item.id
36624
+ }]
36625
+ };
36626
+ case "product": return noActions();
36474
36627
  }
36475
- const actions$1 = [];
36476
- const warnings = [];
36477
- const plannedEventAttendeeIds = new Set();
36478
- for (const item of options.items) {
36479
- switch (item.kind) {
36480
- case "event_ticket":
36481
- if (!item.eventAttendeeId) {
36482
- warnings.push({
36483
- kind: "missing_event_attendee_id",
36484
- orderItemId: item.id,
36485
- orderId: item.orderId
36486
- });
36487
- break;
36488
- }
36489
- if (plannedEventAttendeeIds.has(item.eventAttendeeId)) {
36490
- break;
36491
- }
36492
- plannedEventAttendeeIds.add(item.eventAttendeeId);
36493
- actions$1.push(buildEventConfirmationAction(options.items.filter((candidate) => candidate.kind === "event_ticket" && candidate.eventAttendeeId === item.eventAttendeeId), {
36494
- orderPaymentMethod: options.orderPaymentMethod,
36495
- currency: options.currency,
36496
- flexibleBalanceDueAt: options.flexibleBalanceDueAt ?? null,
36497
- settlement: options.settlement
36498
- }));
36499
- break;
36500
- case "pass":
36501
- if (hasPassBundleFulfillment(item.metadata)) {
36502
- if (!item.eventAttendeeId) {
36503
- warnings.push({
36504
- kind: "missing_event_attendee_id",
36505
- orderItemId: item.id,
36506
- orderId: item.orderId
36507
- });
36508
- break;
36509
- }
36510
- actions$1.push({
36511
- kind: "send_pass_bundle_confirmation",
36512
- attendeeId: item.eventAttendeeId,
36513
- metadata: item.metadata
36514
- });
36515
- }
36516
- break;
36517
- case "event_series_registration":
36518
- if (!item.eventSeriesRegistrationId) {
36519
- warnings.push({
36520
- kind: "missing_event_series_registration_id",
36521
- orderItemId: item.id,
36522
- orderId: item.orderId
36523
- });
36524
- break;
36525
- }
36526
- actions$1.push({
36527
- kind: "send_event_series_registration_confirmation",
36528
- orderId: item.orderId,
36529
- registrationId: item.eventSeriesRegistrationId,
36530
- paymentSummary: buildOrderItemConfirmationEmailPaymentSummary({
36531
- orderPaymentMethod: options.orderPaymentMethod,
36532
- item,
36533
- currency: options.currency,
36534
- flexibleBalanceDueAt: options.flexibleBalanceDueAt ?? null,
36535
- settlement: options.settlement.kind === "settled_in_full" ? options.settlement : {
36536
- kind: "collected",
36537
- collectedCents: options.settlement.collectedCentsByOrderItemId[item.id] ?? 0
36538
- }
36539
- })
36540
- });
36541
- break;
36542
- case "appointment":
36543
- if (!item.appointmentId) {
36544
- warnings.push({
36545
- kind: "missing_appointment_id",
36546
- orderItemId: item.id,
36547
- orderId: item.orderId
36548
- });
36549
- break;
36550
- }
36551
- actions$1.push({
36552
- kind: "send_appointment_confirmation",
36553
- appointmentId: item.appointmentId
36554
- });
36555
- break;
36556
- case "membership":
36557
- if (hasMembershipBundleFulfillment(item.metadata)) {
36558
- if (!item.eventAttendeeId) {
36559
- warnings.push({
36560
- kind: "missing_event_attendee_id",
36561
- orderItemId: item.id,
36562
- orderId: item.orderId
36563
- });
36564
- break;
36565
- }
36566
- actions$1.push({
36567
- kind: "send_membership_bundle_confirmation",
36568
- attendeeId: item.eventAttendeeId,
36569
- metadata: item.metadata
36570
- });
36571
- break;
36572
- }
36573
- if (!item.customerMembershipId) {
36574
- warnings.push({
36575
- kind: "missing_customer_membership_id",
36576
- orderItemId: item.id,
36577
- orderId: item.orderId
36578
- });
36579
- break;
36580
- }
36581
- actions$1.push({
36582
- kind: "send_membership_activation",
36583
- customerMembershipId: item.customerMembershipId,
36584
- amountPaidCents: settledOrderItemTotalCents(item)
36585
- });
36586
- break;
36587
- case "product": break;
36588
- }
36589
- }
36590
- if (options.items.some((item) => item.kind === "product" || item.kind === "pass")) {
36591
- actions$1.unshift({
36592
- kind: "send_order_confirmation",
36593
- orderId: firstItem.orderId
36594
- });
36595
- }
36628
+ }
36629
+ function bookingGroupId(item) {
36630
+ return item.eventAttendeeId ?? item.eventSeriesRegistrationId ?? null;
36631
+ }
36632
+ /** Complete booking facts are already decided; purchase receipts remain separate. */
36633
+ function buildOrderCompletionEmailPlan(input) {
36634
+ const first = input.items[0];
36635
+ if (!first) return noActions();
36636
+ const plans = input.items.filter((item, index) => {
36637
+ const id = bookingGroupId(item);
36638
+ return id === null || !input.items.slice(0, index).some((previous) => bookingGroupId(previous) === id);
36639
+ }).map((item) => planItem(item, input));
36640
+ const receipt = input.items.some((item) => item.kind === "product" || item.kind === "pass") ? [{
36641
+ kind: "send_order_confirmation",
36642
+ orderId: first.orderId
36643
+ }] : [];
36596
36644
  return {
36597
- actions: actions$1,
36598
- warnings
36645
+ actions: [...receipt, ...plans.flatMap((plan) => plan.actions)],
36646
+ warnings: plans.flatMap((plan) => plan.warnings)
36599
36647
  };
36600
36648
  }
36601
36649
 
@@ -39007,6 +39055,9 @@ function getStepLabel(step) {
39007
39055
  function visitorHoldsOwnPlace(input) {
39008
39056
  return input.hasWaitlistClaim || input.retryingHeldPlace;
39009
39057
  }
39058
+ function getTicketSelectionPurpose(admission) {
39059
+ return admission.kind === "waitlist" ? "waitlist" : "book";
39060
+ }
39010
39061
  function resolveRegistrationAdmission(input) {
39011
39062
  if (input.holdsOwnPlace) return { kind: "resume" };
39012
39063
  if (input.eligibilityLoading) return { kind: "checking" };
@@ -48040,6 +48091,7 @@ const recurringScheduleLayout = styledSection({
48040
48091
  fallback: "secondary"
48041
48092
  } }
48042
48093
  }, [text({}, bind("content.seeAllLabel"))], when("content.seeAllUrl"))]), el("recurring-schedule", {
48094
+ dateContext: { $bind: { from: "$root.dateContext" } },
48043
48095
  schedule: { $bind: { from: "data.schedule" } },
48044
48096
  buttonText: { $bind: {
48045
48097
  from: "content.buttonText",
@@ -50996,7 +51048,12 @@ const contentEntrySchema = z.object({
50996
51048
  id: z.string().nullable().optional(),
50997
51049
  slug: z.string().nullable().optional()
50998
51050
  }).nullable();
51051
+ const shopDateContextSchema = z.object({
51052
+ locale: z.string(),
51053
+ timeZone: z.string().transform(resolveBookingBusinessTimeZone)
51054
+ });
50999
51055
  const shopSourceSchema = z.object({
51056
+ dateContext: shopDateContextSchema.optional(),
51000
51057
  ...cardListPresentationSchemaShape,
51001
51058
  featured: z.string().nullable().optional(),
51002
51059
  className: z.string().nullable().optional(),
@@ -51161,6 +51218,7 @@ const checkoutDisplaySchema = z.object({
51161
51218
  submitButtonText: z.string()
51162
51219
  });
51163
51220
  const passesMembershipsHydrationSchema = z.object({
51221
+ dateContext: shopDateContextSchema,
51164
51222
  presentation: z.object(cardListPresentationSchemaShape).optional(),
51165
51223
  featured: z.string().optional(),
51166
51224
  memberships: z.array(publicMembershipProductSchema),
@@ -51241,6 +51299,7 @@ const shopBlockRuntime = defineProgressiveBlockRuntime({
51241
51299
  const passPurchaseMode = source.passPurchaseMode ?? "add_to_cart";
51242
51300
  const subscribeButtonText = source.subscribeButtonText ?? "Subscribe";
51243
51301
  const products = shopDisplayedProducts(source);
51302
+ const dateContext = source.dateContext ?? resolveDateRuntimeContext(undefined);
51244
51303
  return {
51245
51304
  display: buildPassesMembershipsDisplay({
51246
51305
  cardList: source.lookSlots !== undefined,
@@ -51261,6 +51320,10 @@ const shopBlockRuntime = defineProgressiveBlockRuntime({
51261
51320
  hydration: {
51262
51321
  ...source.lookSlots ? { presentation: shopCardListPresentation(source) } : {},
51263
51322
  ...shopFeaturedProduct(source, products),
51323
+ dateContext: {
51324
+ locale: dateContext.locale,
51325
+ timeZone: dateContext.timeZone
51326
+ },
51264
51327
  memberships: products.memberships,
51265
51328
  passPurchaseMode,
51266
51329
  buttonVariant: source.buttonVariant ?? "primary",
@@ -51785,6 +51848,7 @@ const shopManifest = createBlockManifest({
51785
51848
  featured: { $bind: { from: "content.featured" } },
51786
51849
  readAuthority: { $bind: { from: "$root.readAuthority" } },
51787
51850
  siteTerms: { $bind: { from: "$root.siteTerms" } },
51851
+ dateContext: { $bind: { from: "$root.dateContext" } },
51788
51852
  demoEmailSuppressed: { $bind: {
51789
51853
  from: "$root.demoEmailSuppressed",
51790
51854
  fallback: false
@@ -59745,7 +59809,7 @@ function resolveEventDetailsPresentation(input) {
59745
59809
  //#region ../blocks/src/system/blocks/offerings-preview/scheduleSummary.ts
59746
59810
  function deriveEventScheduleSummary(event) {
59747
59811
  const occurrence = occurrenceFromEvent(event);
59748
- return localDayNumber(occurrence.endsAt, occurrence.timeZone) > localDayNumber(occurrence.startsAt, occurrence.timeZone) ? {
59812
+ return compareLocalScheduleDates(getLocalScheduleDate(new Date(occurrence.endsAt), resolveBookingBusinessTimeZone(occurrence.timeZone)), getLocalScheduleDate(new Date(occurrence.startsAt), resolveBookingBusinessTimeZone(occurrence.timeZone))) > 0 ? {
59749
59813
  kind: "multi-day-span",
59750
59814
  occurrence
59751
59815
  } : {
@@ -59753,23 +59817,18 @@ function deriveEventScheduleSummary(event) {
59753
59817
  occurrence
59754
59818
  };
59755
59819
  }
59756
- function derivePreviewRunSchedule(runSessions) {
59757
- const sessions = orderedLiveRunSessions(runSessions).filter(isValidOccurrence);
59820
+ function derivePreviewRunSchedule(event) {
59821
+ const sessions = orderedLiveRunSessions(event.run.sessions).filter(isValidOccurrence);
59758
59822
  const first = sessions[0];
59759
59823
  const last = sessions[sessions.length - 1];
59760
59824
  if (!first || !last) return { kind: "no-live-sessions" };
59761
- const recurrence = sessions.length > 1 ? deriveFixedRecurrence(sessions) : null;
59762
- const summary = sessions.length === 1 ? deriveEventScheduleSummary(first) : recurrence ? {
59763
- kind: "fixed-recurring-run",
59825
+ const authoredSummary = formatBookingSchedulePresentation("representative" in event ? event.representative : event);
59826
+ const summary = !authoredSummary && sessions.length === 1 ? deriveEventScheduleSummary(first) : {
59827
+ kind: "scheduled-run",
59764
59828
  first,
59765
59829
  last,
59766
59830
  sessionCount: sessions.length,
59767
- recurrenceLabel: recurrence
59768
- } : {
59769
- kind: "irregular-multi-session-run",
59770
- first,
59771
- last,
59772
- sessionCount: sessions.length
59831
+ authoredSummary
59773
59832
  };
59774
59833
  return {
59775
59834
  kind: "scheduled",
@@ -59785,62 +59844,9 @@ function occurrenceFromEvent(event) {
59785
59844
  timeZone: event.timeZone
59786
59845
  };
59787
59846
  }
59788
- function deriveFixedRecurrence(sessions) {
59789
- const [first, second] = sessions;
59790
- if (!first || !second) return null;
59791
- if (!sessions.every((session) => sameLocalTime(first, session))) return null;
59792
- const intervalDays = localDayNumber(second.startsAt, second.timeZone) - localDayNumber(first.startsAt, first.timeZone);
59793
- if (intervalDays <= 0) return null;
59794
- for (let index = 2; index < sessions.length; index += 1) {
59795
- const previous = sessions[index - 1];
59796
- const current = sessions[index];
59797
- if (!previous || !current) return null;
59798
- const currentInterval = localDayNumber(current.startsAt, current.timeZone) - localDayNumber(previous.startsAt, previous.timeZone);
59799
- if (currentInterval !== intervalDays) return null;
59800
- }
59801
- if (intervalDays === 1) return "Every day";
59802
- const weekday = localDateParts(first.startsAt, first.timeZone).weekday;
59803
- if (intervalDays === 7) return `Every ${weekday}`;
59804
- if (intervalDays % 7 === 0) {
59805
- return `Every ${intervalDays / 7} weeks on ${weekday}`;
59806
- }
59807
- return `Every ${intervalDays} days`;
59808
- }
59809
- function sameLocalTime(reference, candidate) {
59810
- const referenceStart = localDateParts(reference.startsAt, reference.timeZone);
59811
- const candidateStart = localDateParts(candidate.startsAt, candidate.timeZone);
59812
- const referenceEnd = localDateParts(reference.endsAt, reference.timeZone);
59813
- const candidateEnd = localDateParts(candidate.endsAt, candidate.timeZone);
59814
- return referenceStart.hour === candidateStart.hour && referenceStart.minute === candidateStart.minute && referenceEnd.hour === candidateEnd.hour && referenceEnd.minute === candidateEnd.minute;
59815
- }
59816
59847
  function isValidOccurrence(value) {
59817
59848
  return Number.isFinite(Date.parse(value.startsAt)) && Number.isFinite(Date.parse(value.endsAt));
59818
59849
  }
59819
- function localDayNumber(isoTimestamp, timeZone) {
59820
- const parts = localDateParts(isoTimestamp, timeZone);
59821
- return Math.floor(Date.UTC(parts.year, parts.month - 1, parts.day) / 864e5);
59822
- }
59823
- function localDateParts(isoTimestamp, timeZone) {
59824
- const parts = new Intl.DateTimeFormat("en-GB", {
59825
- timeZone,
59826
- year: "numeric",
59827
- month: "numeric",
59828
- day: "numeric",
59829
- hour: "2-digit",
59830
- minute: "2-digit",
59831
- hourCycle: "h23",
59832
- weekday: "long"
59833
- }).formatToParts(new Date(isoTimestamp));
59834
- const value = (type) => parts.find((part) => part.type === type)?.value ?? "";
59835
- return {
59836
- year: Number(value("year")),
59837
- month: Number(value("month")),
59838
- day: Number(value("day")),
59839
- hour: Number(value("hour")),
59840
- minute: Number(value("minute")),
59841
- weekday: value("weekday")
59842
- };
59843
- }
59844
59850
 
59845
59851
  //#endregion
59846
59852
  //#region ../blocks/src/system/runtime/nodes/events/shared/eventCardListContent.ts
@@ -59895,7 +59901,7 @@ function offeringLeadDate(event, startMs) {
59895
59901
  };
59896
59902
  }
59897
59903
  function offeringSchedule(event, now) {
59898
- const run = event.bookingScope === "whole_series" ? derivePreviewRunSchedule(event.run.sessions) : null;
59904
+ const run = event.bookingScope === "whole_series" ? derivePreviewRunSchedule(event) : null;
59899
59905
  if (run?.kind === "no-live-sessions") return {
59900
59906
  numeral: null,
59901
59907
  schedule: null
@@ -59948,8 +59954,7 @@ function scheduleLine(summary, event, now) {
59948
59954
  zone
59949
59955
  }) : date(summary.occurrence.startsAt);
59950
59956
  case "multi-day-span": return dates(summary.occurrence.startsAt, summary.occurrence.endsAt);
59951
- case "fixed-recurring-run": return `${dates(summary.first.startsAt, summary.last.startsAt, "session")} · ${summary.recurrenceLabel}`;
59952
- case "irregular-multi-session-run": return `${dates(summary.first.startsAt, summary.last.startsAt, "session")} · ${summary.sessionCount} dates`;
59957
+ case "scheduled-run": return `${dates(summary.first.startsAt, summary.last.startsAt, "session")} · ${summary.authoredSummary?.text ?? `${summary.sessionCount} dates`}`;
59953
59958
  }
59954
59959
  }
59955
59960
  function offeringAvailability(event) {
@@ -61306,7 +61311,7 @@ function FeaturedOfferingSummary({ item }) {
61306
61311
  children: [
61307
61312
  details.recurrence ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Repeats" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: details.recurrence })] }) : null,
61308
61313
  details.sessionCount ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Sessions" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: details.sessionCount })] }) : null,
61309
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Time" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: details.timeRange })] }),
61314
+ details.timeRange ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Time" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: details.timeRange })] }) : null,
61310
61315
  details.venue ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Venue" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: details.venue })] }) : null
61311
61316
  ]
61312
61317
  })]
@@ -61320,7 +61325,7 @@ function featuredSummaryDetails(item) {
61320
61325
  deliveryMode: item.event.deliveryMode
61321
61326
  });
61322
61327
  case "run": {
61323
- const schedule = derivePreviewRunSchedule(item.run.run.sessions);
61328
+ const schedule = derivePreviewRunSchedule(item.run);
61324
61329
  return schedule.kind === "scheduled" ? formatFeaturedSummary(schedule.summary, {
61325
61330
  venue: item.run.representative.venue?.name ?? null,
61326
61331
  siteTimeZone: item.run.representative.siteTimeZone,
@@ -61334,33 +61339,33 @@ function formatFeaturedSummary(summary, place) {
61334
61339
  switch (summary.kind) {
61335
61340
  case "single-occurrence": return detailsFromOccurrences({
61336
61341
  first: summary.occurrence,
61337
- last: null,
61342
+ end: null,
61338
61343
  place
61339
61344
  });
61340
61345
  case "multi-day-span": return detailsFromOccurrences({
61341
61346
  first: summary.occurrence,
61342
- last: summary.occurrence,
61343
- place,
61344
- spanUsesEndDate: true
61345
- });
61346
- case "fixed-recurring-run": return detailsFromOccurrences({
61347
- first: summary.first,
61348
- last: summary.last,
61349
- place,
61350
- recurrence: summary.recurrenceLabel
61347
+ end: {
61348
+ dateTime: summary.occurrence.endsAt,
61349
+ timeZone: summary.occurrence.timeZone
61350
+ },
61351
+ place
61351
61352
  });
61352
- case "irregular-multi-session-run": return detailsFromOccurrences({
61353
+ case "scheduled-run": return detailsFromOccurrences({
61353
61354
  first: summary.first,
61354
- last: summary.last,
61355
+ end: {
61356
+ dateTime: summary.last.startsAt,
61357
+ timeZone: summary.last.timeZone
61358
+ },
61355
61359
  place,
61356
- sessionCount: `${summary.sessionCount} dates`
61360
+ recurrence: summary.authoredSummary ?? undefined,
61361
+ sessionCount: `${summary.sessionCount} date${summary.sessionCount === 1 ? "" : "s"}`
61357
61362
  });
61358
61363
  default: return assertNever(summary, "Unhandled offerings preview schedule summary");
61359
61364
  }
61360
61365
  }
61361
61366
  function detailsFromOccurrences(input) {
61362
- const { first, last, place } = input;
61363
- const endDateTime = input.spanUsesEndDate ? first.endsAt : last?.startsAt ?? first.startsAt;
61367
+ const { first, end, place } = input;
61368
+ const endDateTime = end?.dateTime ?? first.startsAt;
61364
61369
  const options = eventDateOptions({
61365
61370
  timeZone: first.timeZone,
61366
61371
  siteTimeZone: place.siteTimeZone,
@@ -61370,13 +61375,15 @@ function detailsFromOccurrences(input) {
61370
61375
  timeZone,
61371
61376
  locale: options.locale
61372
61377
  });
61378
+ const startDate = summaryDate(first.startsAt, first.timeZone);
61379
+ const endDate = end ? summaryDate(end.dateTime, end.timeZone) : null;
61373
61380
  return {
61374
- startDate: summaryDate(first.startsAt, first.timeZone),
61381
+ startDate,
61375
61382
  startDateTime: first.startsAt,
61376
- endDate: last ? summaryDate(endDateTime, last.timeZone) : null,
61383
+ endDate: endDate === startDate ? null : endDate,
61377
61384
  endDateTime,
61378
- timeRange: formatEventTimeRange(first, options),
61379
- recurrence: input.recurrence ?? null,
61385
+ timeRange: input.recurrence?.clock ? null : formatEventTimeRange(first, options),
61386
+ recurrence: input.recurrence?.text ?? null,
61380
61387
  sessionCount: input.sessionCount ?? null,
61381
61388
  venue: place.venue
61382
61389
  };
@@ -61426,8 +61433,13 @@ function renderSingleOfferingCard(item, options) {
61426
61433
  }, item.run.eventSeriesId);
61427
61434
  }
61428
61435
  }
61436
+ /** The authored clock replaces live time only when it was successfully formatted. */
61437
+ function formatRunScheduleTime(schedule, options) {
61438
+ const authored = schedule.summary.kind === "scheduled-run" ? schedule.summary.authoredSummary : null;
61439
+ return [authored?.text, authored?.clock ? null : formatEventTimeRange(schedule.firstSession, options)].filter(Boolean).join(" · ");
61440
+ }
61429
61441
  function WholeSeriesRunCompactRow({ group, path: path$3, now }) {
61430
- const schedule = derivePreviewRunSchedule(group.run.sessions);
61442
+ const schedule = derivePreviewRunSchedule(group);
61431
61443
  if (schedule.kind === "no-live-sessions") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunWithoutLiveDates, {
61432
61444
  group,
61433
61445
  path: path$3
@@ -61439,7 +61451,7 @@ function WholeSeriesRunCompactRow({ group, path: path$3, now }) {
61439
61451
  deliveryMode: group.representative.deliveryMode
61440
61452
  });
61441
61453
  const dateRail = formatEventCompactDateRail(firstSession.startsAt, options);
61442
- const timeRange = formatEventTimeRange(firstSession, options);
61454
+ const timeRange = formatRunScheduleTime(schedule, options);
61443
61455
  const price$1 = formatEventPriceDisplay(group.representative.pricing);
61444
61456
  const statusLabel = resolveWholeSeriesBookingPhase(group.run, now).kind === "open" ? null : "Registration closed";
61445
61457
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", {
@@ -61513,7 +61525,7 @@ function WholeSeriesRunCompactRow({ group, path: path$3, now }) {
61513
61525
  });
61514
61526
  }
61515
61527
  function WholeSeriesRunFeatureCard({ group, now, path: path$3, buttonVariant, buttonText }) {
61516
- const schedule = derivePreviewRunSchedule(group.run.sessions);
61528
+ const schedule = derivePreviewRunSchedule(group);
61517
61529
  if (schedule.kind === "no-live-sessions") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunWithoutLiveDates, {
61518
61530
  group,
61519
61531
  path: path$3
@@ -61525,7 +61537,7 @@ function WholeSeriesRunFeatureCard({ group, now, path: path$3, buttonVariant, bu
61525
61537
  deliveryMode: group.representative.deliveryMode
61526
61538
  });
61527
61539
  const formattedDate = formatEventCompactDateRail(firstSession.startsAt, options).label;
61528
- const timeRange = formatEventTimeRange(firstSession, options);
61540
+ const timeRange = formatRunScheduleTime(schedule, options);
61529
61541
  const price$1 = formatEventPriceDisplay(group.representative.pricing);
61530
61542
  const statusLabel = resolveWholeSeriesBookingPhase(group.run, now).kind === "open" ? null : "Registration closed";
61531
61543
  const description = group.representative.description;
@@ -61857,7 +61869,7 @@ function bookingActionContent(input) {
61857
61869
  default: return assertNever(input.booking);
61858
61870
  }
61859
61871
  }
61860
- function RecurringSchedule({ schedule, buttonText = "Book", buttonVariant = "primary", showVenue = true, emptyMessage = "Regular schedule details will be added shortly." }) {
61872
+ function RecurringSchedule({ dateContext = resolveDateRuntimeContext(undefined), schedule, buttonText = "Book", buttonVariant = "primary", showVenue = true, emptyMessage = "Regular schedule details will be added shortly." }) {
61861
61873
  const projection = schedule ?? {
61862
61874
  items: [],
61863
61875
  diagnostics: []
@@ -61869,8 +61881,28 @@ function RecurringSchedule({ schedule, buttonText = "Book", buttonVariant = "pri
61869
61881
  children: emptyMessage
61870
61882
  });
61871
61883
  }
61872
- const renderRow = (item) => {
61873
- const rowContent = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
61884
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
61885
+ className: "recurring-schedule",
61886
+ "data-diagnostic-count": projection.diagnostics.length,
61887
+ role: "list",
61888
+ children: projection.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RecurringScheduleRow, {
61889
+ item,
61890
+ locale: dateContext.locale,
61891
+ buttonText: buttonText ?? "Book",
61892
+ buttonVariant: buttonVariant ?? "primary",
61893
+ showVenue: showVenue ?? true
61894
+ }, item.seriesId))
61895
+ });
61896
+ }
61897
+ function RecurringScheduleRow({ item, locale, buttonText, buttonVariant, showVenue }) {
61898
+ const startLabel = formatEventClockLabel(item.cadence.startTime, locale);
61899
+ const endLabel = formatEventClockLabel(item.cadence.endTime, locale);
61900
+ const description = `${item.title}, ${item.cadence.weekday} at ${startLabel}`;
61901
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", {
61902
+ className: "recurring-schedule-row",
61903
+ role: "listitem",
61904
+ "aria-label": description,
61905
+ children: [
61874
61906
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
61875
61907
  className: "recurring-schedule-day",
61876
61908
  children: item.cadence.weekday
@@ -61880,7 +61912,7 @@ function RecurringSchedule({ schedule, buttonText = "Book", buttonVariant = "pri
61880
61912
  children: [
61881
61913
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("time", {
61882
61914
  dateTime: item.cadence.startTime,
61883
- children: item.cadence.startTime
61915
+ children: startLabel
61884
61916
  }),
61885
61917
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
61886
61918
  "aria-hidden": "true",
@@ -61888,7 +61920,7 @@ function RecurringSchedule({ schedule, buttonText = "Book", buttonVariant = "pri
61888
61920
  }),
61889
61921
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("time", {
61890
61922
  dateTime: item.cadence.endTime,
61891
- children: item.cadence.endTime
61923
+ children: endLabel
61892
61924
  })
61893
61925
  ]
61894
61926
  }),
@@ -61906,24 +61938,12 @@ function RecurringSchedule({ schedule, buttonText = "Book", buttonVariant = "pri
61906
61938
  className: "recurring-schedule-action",
61907
61939
  children: bookingActionContent({
61908
61940
  booking: item.booking,
61909
- buttonVariant: buttonVariant ?? "primary",
61910
- buttonText: buttonText ?? "Book",
61911
- accessibleName: `${buttonText ?? "Book"} ${item.title}, ${item.cadence.weekday} at ${item.cadence.startTime}`
61941
+ buttonVariant,
61942
+ buttonText,
61943
+ accessibleName: `${buttonText} ${description}`
61912
61944
  })
61913
61945
  })
61914
- ] });
61915
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("article", {
61916
- className: "recurring-schedule-row",
61917
- role: "listitem",
61918
- "aria-label": `${item.title}, ${item.cadence.weekday} at ${item.cadence.startTime}`,
61919
- children: rowContent
61920
- });
61921
- };
61922
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
61923
- className: "recurring-schedule",
61924
- "data-diagnostic-count": projection.diagnostics.length,
61925
- role: "list",
61926
- children: projection.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Fragment, { children: renderRow(item) }, item.seriesId))
61946
+ ]
61927
61947
  });
61928
61948
  }
61929
61949
 
@@ -78707,7 +78727,7 @@ async function loadConfig(configPath, output) {
78707
78727
  return { errorMessage: "No config path provided." };
78708
78728
  }
78709
78729
  try {
78710
- const { loadConfigFile: loadConfigFile$1 } = await import("../load-config-BRd0EUsF.mjs");
78730
+ const { loadConfigFile: loadConfigFile$1 } = await import("../load-config-JWz__Dkx.mjs");
78711
78731
  const rawConfig = await loadConfigFile$1(configPath);
78712
78732
  const parsed = riverbankSiteConfigSchema.safeParse(rawConfig);
78713
78733
  if (!parsed.success) {
@@ -81274,15 +81294,13 @@ function occurrenceCapacityFromOptions(options) {
81274
81294
  return options.inheritCapacity ? { kind: "inherit" } : undefined;
81275
81295
  }
81276
81296
  function formatOccurrenceLocal(iso, timeZone) {
81277
- return new Intl.DateTimeFormat("en-GB", {
81278
- timeZone,
81279
- year: "numeric",
81280
- month: "2-digit",
81281
- day: "2-digit",
81282
- hour: "2-digit",
81283
- minute: "2-digit",
81284
- hourCycle: "h23"
81285
- }).format(new Date(iso));
81297
+ return formatDateTime(toUtcIsoDateTimeString(iso), {
81298
+ locale: "en-GB",
81299
+ timeZone: resolveBookingTimeZoneId(timeZone)
81300
+ }, {
81301
+ date: "short",
81302
+ zone: "omit"
81303
+ });
81286
81304
  }
81287
81305
  function formatDeletionEligibility(occurrence) {
81288
81306
  switch (occurrence.deletionEligibility.kind) {