riverbankcms 0.27.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { $ as createFooterRef, $n as parseCanonicalMediaIdentifier, $r as textColorStyle, $t as cardVariantRoleValues, An as stripStaleTransitionStyleGroup, Ar as eyebrowTreatmentValues, At as parseGradientPresetId, B as eventCommandScheduleSchema, Bn as resolveMediaTransformForAspect, Br as parseResolvedSurface, Bt as MQ_MD_DOWN, C as sortRecord, Cn as resolveCompiledSectionContextFromContent, Ct as resolveModeArrangement, D as resolveEventSeriesWaitlistMapping, Dn as boxBackgroundSchema, Dr as defineFrameCapability, Dt as compiledRuntimeStyleFieldNames, En as boxBackgroundOverlaySchema, Er as defineBlockDesignCapability, Et as requireCuratedSiteStyle, F as entryIdentifierForCommand, Fn as looksLikeUuid, Fr as offeringsPreviewCompositionTreatmentValues, Ft as renderHeaderPaintTargetRules, G as require_react, Gn as mediaSchema, Gr as isCssColorLiteral, Gt as generateDefaultButtonSystem, H as bookingPaymentCollectionOptionSchema, Hn as getDirectImageUrlForSiteScopedPath, Hr as resolveSurface, Ht as getComponentBorderWidthPx, I as pageIdentifierForBlockCommand, In as rotateNormalizedPoint, Ir as testimonialsCompositionTreatmentValues, It as BREAKPOINT_LG, J as createBlocksRef, Jn as buildRenderableMediaAssetIndex, Jr as resolveTokenOrCssColorValue, Jt as themeButtonSizeClassName, K as ianaTimezoneSchema, Kn as persistableMediaSchema, Kr as resolveOnColorForThemeToken, Kt as parseThemeButtonVariantId, L as pageIdentifierForCommand, Ln as normalizeWidthCandidates, Lr as tileTreatmentValues, Lt as BREAKPOINT_MD, M as eventManagementTiming, Mn as summarizePortableMediaReferences, Mr as headingDecorationColorTokenValues, Mt as generateHeaderScrollTreatmentStyles, N as blockIdentifierForCommand, Nn as walkAndCollectImageAttrs, Nr as introCompositionTreatmentValues, Nt as generateMobileOverlayBackdropFilterFix, O as mapEventCommandContent, On as runtimeBoxBackgroundSchema, Or as defineNoBlockDesignCapability, Ot as gradientToCss, P as blockOrderIdentifiersForCommand, Pn as deleteEnvSpecificKeys, Pr as makeBoundaryId, Pt as getHeaderPaintTargets, Q as createEventSeriesRef, Qn as buildMediaIdentifierFromFilename, Qr as rgbColorValue, Qt as cardRoleSchema, R as pagePathForCommand, Rn as isExplicitRectCrop, Rr as toNonEmptyReadonlyArray, Rt as BREAKPOINT_SM, S as venueManagementFields, Sn as parseCanonicalRuntimeBackground, Sr as asLayoutVariantKey, St as resolveEffectiveArrangement, Tn as sectionForegroundBackground, Tr as assertNever$10, Tt as deriveSiteStyleBlockPolicy, U as bookingPaymentTermsSchema, Un as getImageUrl, Ur as serializeSurfaceTree, Ut as getComponentShadowVar, Vn as getDirectImageUrlForRelativePath, Vr as parseSurfaceTree, Vt as headerVariantValues, W as require_jsx_runtime, Wn as isSiteScopedDirectImageStoragePath, Wr as surfaceDecorationColors, Wt as ICON_CONFIG, X as createContentEntryRef, Xn as mediaTypeDiscriminants, Xr as borderColorStyle, Xt as parseThemeForPersistence, Y as createCommandRef, Yn as resolveManagedMediaReference, Yr as backgroundColorStyle, Yt as themeButtonVariantClassNames, Z as createEventCategoryRef, Zn as mediaIdentifierSchema, Zr as mergeStyles, Zt as renderCssDeclarations, _i as parseThemeColorToken, _n as composeBoundary, _r as cardListFamilyBlocks, _t as arrangementSlotNames, ai as surfaceInkPublication, at as refSlug, b as isEventVisibility, bi as __toESM, bn as deriveSectionGround, bt as arrangementManifestFromVariants, c as customLinkSchema$1, ci as TokenResolver, cn as footerForegroundCandidates, ct as headerForegroundCandidates, d as internalLinkSchema, di as surfaceForegroundInputFromResolved, dt as readOpeningForegroundProjection, ei as mapDrawingStyle, en as normalizeCardRole, er as parseMediaIdentifier, et as createFormRef, f as internalResolvedLinkSchema, fi as surfaceForegroundStyle, fr as classifyKnownMimeType, ft as readOpeningToneProjection, g as linkSchema, gi as PUBLIC_BUTTON_ROLES, gn as boundaryLayout, gr as resolveEffectiveKnobs, gt as arrangementLookHooks, h as isResolvedInternalLinkEntityType, hi as surfaceInkStyle, hn as headerRootPaint, hr as defineBlockDesignMetadata, ht as readHeaderNavFontSizePreference, i as sdkEventUpsertOptionalFieldSchemas, ii as resolveSurfaceForeground, ir as resolveVideoSelectionIntentForMediaField, it as createVenueRef, jn as collectPortableMediaReferencesFromContent, jr as featureCardCompositionTreatmentValues, jt as themeSchema, kn as siteChromeBackgroundOverrideOwner, kr as eventListTreatmentValues, kt as getGradientPreset, l as entryLinkSchema$1, li as defaultThemeTokens, ln as buildTextContrastShadow, lr as parseRelativeStoragePath, lt as headerLeafTextColor, mi as surfaceInkDeclarations, mn as headerNeedsPhotoShade, mr as parseSafeDownloadFilename, mt as mergeHeaderNavTypographyPreference, ni as selectLogoVariant, nt as createPageRef, o as classifySdkEventBookingOffer, oi as expandPalette, or as getMimeType, p as internalRouteOnlyLinkSchema, pi as surfaceForegroundValue, pr as managementMediaLibraryUploadLimitForMimeType, q as createBlockRef, qn as runtimeMediaSchema, qr as resolveThemeColorReferenceValue, qt as themeButtonExtraClassesWithTrailingIcon, ri as surfaceToneFromForegroundToken, rr as deriveVideoSlotPolicy, s as RESOLVED_INTERNAL_LINK_ENTITY_TYPES, si as getTextColorForBackground, sr as asRecord, st as effectiveHeaderNavLinkStyle, t as classifySdkEventTiming, ti as opaqueSurfaceDeclarations, tt as createNavigationRef, u as externalLinkSchema$1, ui as surfaceForegroundDeclarations, un as generateNavLinkCSS, ur as FILE_SIZE_LIMITS, ut as transparentHeaderForegroundInput, v as pageLinkSchema$1, vi as parseBlockColorToken, vn as sectionFactsForContent, vr as cardListKnobBlocks, vt as resolveItemSurface, w as stableStringify, wn as resolveSectionBackground, wr as asSiteStyleId, wt as resolvePublishedLook, xn as heroPhotoPaintsGround, xr as asDesignBlockId, xt as readStoredMode, yi as __commonJSMin, yn as applyLookPhotoTreatment, yr as arrangementModes, yt as resolveLookSlotSurfaces, z as hasConfiguredBookingVertical, zn as parseAspectRatioValue, zr as visibleHeadingDecorationFamilyValues, zt as BREAKPOINT_XL } from "../sdk-event-upsert-CnvVuQJy.mjs";
3
- import { $n as err, $t as mapReadonlyNonEmptyArray, A as parseMailingListRuntimeContext, At as isSettleableOrderInstalmentPlanStatus, B as formatOpeningHoursRows, Bn as unsafeAsPositiveByteCount, Bt as deriveTotalTicketQuantity, C as createSecret, Cn as parseUserId, Ct as toBookingTimeZone, D as parseMailingListBlockId, Dn as unsafeAsCheckoutLineId, Dt as validateBookingPaymentOptionKinds, E as slugify, Ft as getBookingInstalmentProtectedDepositAmountCents, Gt as publicEventPricingCurrency, H as parseWeeklyOpeningHours, Hn as unsafeAsPricingOptionId, Ht as formatBookingPriceDisplay, I as parseMailingListPlacementTargeting, In as unsafeAsMediaAssetId, It as omitZeroAmountFutureRows, J as normalizeLocationAddressText, Jt as publicEventPricingType, K as locationMapLinks, Kt as publicEventPricingDisplay, L as DEFAULT_MAILING_LIST_TARGETING, Ln as unsafeAsOccurrenceId, Lt as splitAmountWithRemainderInFirst, M as DEFAULT_MAILING_LIST_SUCCESS_MESSAGE, Mn as unsafeAsEventInstanceId, Mt as clampConfiguredAmount, N as parseMailingListProviderScope, Nt as getBookingInstalmentDepositRefundability, O as parseMailingListContentVersionId, Ot as isLiveOrderInstalmentPlanStatus, P as parseFooterCompositionV1, Pt as getBookingInstalmentPlanIntervalCount, Q as toLocationCoordinates, R as planMailingListChoicePresentation, Rt as resolveFlexibleBalanceDueAt, S as resolveWholeSeriesRunLifecycle, Sn as parseSiteTermsVersionId, St as resolveBookingTimeZoneId, T as parseManagementKey, Tt as toUtcIsoDateTimeString, U as assertAllowedPublicUrl, Ut as formatEventPricing, Vt as parseEventPageSurfaceSubject, W as decideLocationSave, Wt as isPublicEventPricingOptionDisplayable, X as projectPublicLocation, Xt as resolvePricingOptionsPriceDisplay, Y as parseLocationValue, Yt as resolveExactOrFreePriceDisplay, Z as publicLocationSchema$1, Zt as fromArray, a as NAVIGATION_LOCATIONS, an as unsafeAsNonNegativeCents, at as formatDateTimeRange, b as orderedLiveRunSessions, bn as parseRetiredCourseId, bt as parseUtcIsoDateTimeString, cn as parseCurrencyCode, ct as inferSiteDateLocale, dn as parseApiKeyId, dt as compareLocalScheduleDates, en as isNonNegativeWholeCents$1, er as ok, et as mapDrawingSchema, f as EVENT_PRESET_VALUES, fn as parseCustomerId, ft as formatLocalScheduleDate, gn as parseEventSeriesId, gt as getLocalScheduleTime, h as WHOLE_SERIES_EVENT_PRESET_VALUES, ht as getLocalScheduleDate, i as EVENT_PRESET_VOCABULARY, in as toNonNegativeCents, it as formatDateTime, j as assessMailingListTargeting, jt as addIntervalPreservingMonthAnchor, k as parseMailingListSignedSourceToken, kn as unsafeAsDemoCapability, kt as isSettleableFlexibleBalanceContractStatus, ln as assertNever, lt as resolveBookingDisplayContext, m as SURFACE_EVENT_PRESET_VALUES, mn as parseDatedOfferingCapacityHoldId, mt as getBookingLocalDateKey, nn as parsePositiveCents, nt as formatDate, on as unsafeAsPositiveCents, ot as formatTime$1, pn as parseDatedOfferingCapacityHoldAuditRef, pt as formatLocalScheduleTime, q as locationValueSchema, qt as publicEventPricingOptions, rn as toCents, rt as formatDateRange, sn as formatCurrencyAmount, st as formatTimeRange, tn as parseNonNegativeCents, tr as blockInteractionContextSchema, tt as selectCategoryView, u as resolveSiteVerticalBookingConfig, un as formatDurationUnitLabel, ut as buildBookingUtcDateWindow, v as CANCELLED_SESSION_STATUS, vn as parseMembershipId, vt as parseBookingLocalDate, w as exposeSecret, wt as toScheduledBookingDateTime, x as resolveWholeSeriesBookingPhase, xn as parseSiteId, xt as resolveBookingBusinessTimeZone, y as nextLiveRunSessionStartMs, yt as parseLocalScheduleTime, z as isCanonicalRichTextDoc, zn as unsafeAsPassId, zt as resolveFlexibleBalanceInitialPaymentCents } from "../src-DqoU7zKs.mjs";
4
- import { $ as normalizeMediaValueToIdentifierOnly, $t as createCommandContext, A as formatDiffDetail, An as getEnvPrefix, At as navigationIdentity, B as buildFieldChanges, Bn as portablePageDesignSchema, Bt as preparePushConfigTarget, C as reportFromOutcomes, Cn as requireEnvironmentWriteAuthorization, Ct as fileExists, D as normalizeRemoteHomepageReference, Dn as transportSuggestion, Dt as writeJsonFileAtomic, E as createEmptySyncResult, En as formatError, Et as writeJsonFile, F as calculatePullDiff, Fn as createManagementClient, Ft as navigationCommandItemToManagementInput, G as syncLocalMediaForPull, Gt as APPOINTMENT_SERVICE_VISIBILITY_VALUES, H as formatFieldPath, Hn as API_ENDPOINTS, Ht as extractApiErrorMessage, I as buildJsonDiff, In as ManagementApiError, It as normalizeNavigationConfigItemForCommand, J as admitBinaryWriteDestination, Jt as ApiRequestError, K as applyLocalMediaPush, Kt as createBearerAPIClient, L as hasPageOperations, Ln as sdkEventScheduleSchema, Lt as applyPushConfigPlan, M as hasPendingChanges, Mn as isLocalConfigured, Mt as convertPulledFooterToLocal, N as findChangedFieldsWithValues, Nn as isRemoteConfigured, Nt as convertPulledNavigationToLocal, O as calculateDiff, On as CliExit, Ot as isMediaValue, P as formatHumanDiff, Pn as loadSdkEnvironment, Pt as convertPulledPagesToLocal, Q as normalizeMediaIdentifierInput, Qt as createClientForEnv, R as pageMetadataForUpsert, Rn as sdkSettingsUpdateSchema, Rt as createPushConfigCommand, S as planCliCommandBatchForBindings, Sn as planEnvironmentWriteAuthorization, St as ensureDir, T as executeResidualSettingsSyncPlan, Tn as ErrorCodes, Tt as readJsonFile, U as revalidateLocalMediaPushPlan, Un as ApiEnvelopeError, Ut as normalizeApiError, V as formatFieldChange, Vn as sdkConfiguredBookingVerticalConfigSchema, Vt as revalidatePushConfigPlan, Wn as unwrapResponse, Wt as isRecord$2, X as writeBinaryFileAtomic, Xt as bindRequestTimeout, Y as readStableBinaryFile, Yt as mapEnvironmentExecutionOutcomesJson, Z as sha256, Zt as confirmAction, _ as commandExecutionToReport, _n as withErrorHandling, _t as metadataFilePath, a as executeEntryCommandPlanAsReport, an as getOutputContext, at as readEntries, b as executeCompiledCliCommandPlanAsReport, bn as parseEnvironmentSelection, bt as writeMetadataFile, c as titleFromEntryData, cn as managementClientConfigFor, ct as readEventsMeta, d as unsafeAsCliEntryIdentifier, dn as parseJsonData, dt as readNavigationMeta, en as createGetCommand, et as walkLocalContentMedia, f as unsafeAsCliFormSlug, fn as parsePaginationOptions, ft as readPagesMeta, g as commandCompileFailureToReport, gn as withConfirmation, gt as ensureMetadataDir, h as mutationCounterForEffect, hn as withCommandContext, ht as writeMediaManifest, i as entrySiteCommandTypes, in as formatDateShort, it as findLegacyEntryFiles, j as formatDiffSummary, jn as getEnvironmentDebugInfo, jt as navigationIdentityMap, k as calculateFooterDiff, kt as duplicateNavigationIdentityMessage, l as unsafeAsCliBlockIdentifier, ln as mapEntryForOutput, lt as readFooterMeta, m as commandReportToSyncResult, mn as runWithInvocation, mt as readVenuesMeta, n as entryCommandCompileErrorToReport, nn as createOutputForCommand, nt as downloadMedia, o as executeEntryCommandPlanAsSyncResult, on as getOutputOnlyContext, ot as readAllMeta, p as unsafeAsCliPageIdentifier, pn as resolveCommandPath, pt as readSettingsMeta, q as prepareLocalMediaForPush, qt as deriveCmsApiUrlFromDashboardUrl, r as entryCommandReportToSyncResult, rn as currentInvocationEnvelope, rt as extractMediaIdentifiers, s as syncResultForEntryCommandCompileError, sn as handleCommandError, st as readEventCategoriesMeta, t as compileEntryPushCommands, tn as createListCommand, tt as buildStorageUrl, u as unsafeAsCliContentTypeKey, un as parseJsonArray, ut as readFormsMeta, v as commandReportHasFailures, vn as withOutputOnlyErrorHandling, vt as metadataTargetFromEnvironment, w as mergeManySyncResults, wn as withRiverbankEnv, wt as listFiles, x as formatManagementError, xn as planEnvironmentExecution, xt as writeMetadataRecordMap, y as executeCliCommandPlan, yn as executeEnvironmentPlan, yt as readMetadataFile, zn as linkPayloadSchema, zt as loadPushConfigTarget } from "../entryCommands-Dg5IT7Uv.mjs";
5
- import { r as CLI_VERSION, t as loadConfigFile } from "../load-config-DsPKn5yN.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-D4xpVjUT.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-oltx4aO0.mjs";
2
+ import { $ as createEventSeriesRef, $n as isSiteScopedDirectImageStoragePath, $r as surfaceDecorationColors, $t as themeButtonSizeClassName, An as resolveCompiledSectionContextFromContent, Ar as asDesignBlockId, At as deriveSiteStyleBlockPolicy, B as eventCommandScheduleSchema, Bn as collectPortableMediaReferencesFromContent, Br as featureCardCompositionTreatmentValues, Bt as renderHeaderPaintTargetRules, C as sortRecord, Ci as surfaceInkDeclarations, Cn as sectionFactsForContent, Cr as parseSafeDownloadFilename, Ct as resolveItemSurface, D as resolveEventSeriesWaitlistMapping, Di as parseBlockColorToken, Dn as applyLookPhotoTreatment, Dr as cardListKnobBlocks, Dt as resolveEffectiveArrangement, Ei as parseThemeColorToken, En as sectionShapeHook, Er as cardListFamilyBlocks, Et as readStoredMode, F as entryIdentifierForCommand, Fn as boxBackgroundSchema, Fr as defineBlockDesignCapability, Ft as parseGradientPresetId, G as require_react, Gn as rotateNormalizedPoint, Gr as testimonialsCompositionTreatmentValues, Gt as MQ_MD_DOWN, H as bookingPaymentCollectionOptionSchema, Hn as walkAndCollectImageAttrs, Hr as introCompositionTreatmentValues, Ht as BREAKPOINT_MD, I as pageIdentifierForBlockCommand, In as runtimeBoxBackgroundSchema, Ir as defineFrameCapability, It as themeSchema, J as createBlockRef, Jn as parseAspectRatioValue, Jr as visibleHeadingDecorationFamilyValues, Jt as getComponentShadowVar, Kn as normalizeWidthCandidates, Kr as tileTreatmentValues, Kt as headerVariantValues, L as pageIdentifierForCommand, Ln as siteChromeBackgroundOverrideOwner, Lr as defineNoBlockDesignCapability, Lt as generateHeaderScrollTreatmentStyles, M as eventManagementTiming, Mn as resolveSectionPhotoPlacement, Mt as compiledRuntimeStyleFieldNames, N as blockIdentifierForCommand, Nn as sectionForegroundBackground, Nr as asSiteStyleId, Nt as gradientToCss, O as mapEventCommandContent, Oi as __commonJSMin, On as deriveSectionGround, Or as arrangementModes, Ot as resolveModeArrangement, P as blockOrderIdentifiersForCommand, Pn as boxBackgroundOverlaySchema, Pr as assertNever$10, Pt as getGradientPreset, Q as createEventCategoryRef, Qn as getImageUrl, Qr as serializeSurfaceTree, Qt as themeButtonExtraClassesWithTrailingIcon, R as pagePathForCommand, Rn as stripStaleTransitionStyleGroup, Rr as eventListTreatmentValues, Rt as generateMobileOverlayBackdropFilterFix, S as venueManagementFields, Si as surfaceForegroundValue, Sn as composeBoundary, Sr as managementMediaLibraryUploadLimitForMimeType, St as arrangementSlotNames, Ti as PUBLIC_BUTTON_ROLES, Tn as sectionShapeFromContent, Tr as resolveEffectiveKnobs, Tt as arrangementManifestFromVariants, U as bookingPaymentTermsSchema, Un as deleteEnvSpecificKeys, Ur as makeBoundaryId, Ut as BREAKPOINT_SM, Vn as summarizePortableMediaReferences, Vr as headingDecorationColorTokenValues, Vt as BREAKPOINT_LG, W as require_jsx_runtime, Wn as looksLikeUuid, Wr as offeringsPreviewCompositionTreatmentValues, Wt as BREAKPOINT_XL, X as createCommandRef, Xn as getDirectImageUrlForRelativePath, Xr as parseSurfaceTree, Xt as generateDefaultButtonSystem, Y as createBlocksRef, Yn as resolveMediaTransformForAspect, Yr as parseResolvedSurface, Yt as ICON_CONFIG, Z as createContentEntryRef, Zn as getDirectImageUrlForSiteScopedPath, Zr as resolveSurface, Zt as parseThemeButtonVariantId, _i as TokenResolver, _t as mergeHeaderNavTypographyPreference, ai as borderColorStyle, an as normalizeCardRole, ar as mediaTypeDiscriminants, at as createVenueRef, b as isEventVisibility, bi as surfaceForegroundInputFromResolved, bn as headerRootPaint, bt as arrangementAppearancePresets, c as customLinkSchema$1, ci as textColorStyle, cr as parseCanonicalMediaIdentifier, d as internalLinkSchema, di as selectLogoVariant, dt as headerForegroundCandidates, ei as isCssColorLiteral, en as themeButtonVariantClassNames, er as mediaSchema, et as createFooterRef, f as internalResolvedLinkSchema, fi as surfaceToneFromForegroundToken, fr as deriveVideoSlotPolicy, ft as headerLeafTextColor, g as linkSchema, gi as getTextColorForBackground, gr as asRecord, h as isResolvedInternalLinkEntityType, hi as expandPalette, hn as generateNavLinkCSS, hr as getMimeType, ht as readOpeningToneProjection, i as sdkEventUpsertOptionalFieldSchemas, ii as backgroundColorStyle, in as cardVariantRoleValues, ir as resolveManagedMediaReference, jn as resolveSectionBackground, jr as asLayoutVariantKey, jt as requireCuratedSiteStyle, ki as __toESM, kn as parseCanonicalRuntimeBackground, kt as resolvePublishedLook, l as entryLinkSchema$1, li as mapDrawingStyle, lr as parseMediaIdentifier, lt as heroPhotoPaintsGround, mi as surfaceInkPublication, mn as buildTextContrastShadow, mt as readOpeningForegroundProjection, ni as resolveThemeColorReferenceValue, nn as renderCssDeclarations, nr as runtimeMediaSchema, nt as createNavigationRef, o as classifySdkEventBookingOffer, oi as mergeStyles, or as mediaIdentifierSchema, ot as refSlug, p as internalRouteOnlyLinkSchema, pi as resolveSurfaceForeground, pn as footerForegroundCandidates, pr as resolveVideoSelectionIntentForMediaField, pt as transparentHeaderForegroundInput, q as ianaTimezoneSchema, qn as isExplicitRectCrop, qr as toNonEmptyReadonlyArray, qt as getComponentBorderWidthPx, ri as resolveTokenOrCssColorValue, rn as cardRoleSchema, rr as buildRenderableMediaAssetIndex, rt as createPageRef, s as RESOLVED_INTERNAL_LINK_ENTITY_TYPES, si as rgbColorValue, sr as buildMediaIdentifierFromFilename, t as classifySdkEventTiming, ti as resolveOnColorForThemeToken, tn as parseThemeForPersistence, tr as persistableMediaSchema, tt as createFormRef, u as externalLinkSchema$1, ui as opaqueSurfaceDeclarations, ut as effectiveHeaderNavLinkStyle, v as pageLinkSchema$1, vi as defaultThemeTokens, vr as parseRelativeStoragePath, vt as readHeaderNavFontSizePreference, w as stableStringify, wi as surfaceInkStyle, wn as sectionShapeForGround, wr as defineBlockDesignMetadata, wt as resolveLookSlotSurfaces, xi as surfaceForegroundStyle, xn as boundaryLayout, xr as classifyKnownMimeType, xt as arrangementLookHooks, yi as surfaceForegroundDeclarations, yn as headerNeedsPhotoShade, yr as FILE_SIZE_LIMITS, yt as storedSectionPhoto, z as hasConfiguredBookingVertical, zn as themeV2CompilerOwnedFieldNames, zr as eyebrowTreatmentValues, zt as getHeaderPaintTargets } from "../sdk-event-upsert-BrJvTQ-D.mjs";
3
+ import { $ as parseLocationValue, $t as resolveExactOrFreePriceDisplay, A as parseMailingListRuntimeContext, B as DEFAULT_MAILING_LIST_TARGETING, Bn as unsafeAsMediaAssetId, Bt as omitZeroAmountFutureRows, C as createSecret, Ct as parseLocalScheduleTime, D as parseMailingListBlockId, Dn as parseUserId, Dt as toBookingTimeZone, E as slugify, En as parseSiteTermsVersionId, Et as resolveBookingTimeZoneId, F as DEFAULT_MAILING_LIST_SUCCESS_MESSAGE, Ft as addIntervalPreservingMonthAnchor, G as parseWeeklyOpeningHours, Gt as parseEventPageSurfaceSubject, H as isCanonicalRichTextDoc, Ht as resolveFlexibleBalanceDueAt, I as parseMailingListProviderScope, In as unsafeAsEventInstanceId, It as clampConfiguredAmount, J as decideLocationSave, Jt as isPublicEventPricingOptionDisplayable, K as assertAllowedPublicUrl, Kn as unsafeAsPricingOptionId, Kt as formatBookingPriceDisplay, L as parseFooterCompositionV1, Lt as getBookingInstalmentDepositRefundability, Mt as isLiveOrderInstalmentPlanStatus, Nn as unsafeAsDemoCapability, Nt as isSettleableFlexibleBalanceContractStatus, O as parseMailingListContentVersionId, Ot as toScheduledBookingDateTime, P as DEFAULT_MAILING_LIST_PRIVACY_NOTE, Pt as isSettleableOrderInstalmentPlanStatus, Q as normalizeLocationAddressText, Qt as publicEventPricingType, Rt as getBookingInstalmentPlanIntervalCount, S as resolveWholeSeriesRunLifecycle, Sn as parseMembershipId, St as parseBookingLocalDate, T as parseManagementKey, Tn as parseSiteId, Tt as resolveBookingBusinessTimeZone, U as formatOpeningHoursRows, Un as unsafeAsPassId, Ut as resolveFlexibleBalanceInitialPaymentCents, V as planMailingListChoicePresentation, Vn as unsafeAsOccurrenceId, Vt as splitAmountWithRemainderInFirst, Wn as unsafeAsPositiveByteCount, Wt as deriveTotalTicketQuantity, X as locationMapLinks, Xt as publicEventPricingDisplay, Yt as publicEventPricingCurrency, Z as locationValueSchema, Zt as publicEventPricingOptions, _n as parseDatedOfferingCapacityHoldAuditRef, _t as formatLocalScheduleTime, a as NAVIGATION_LOCATIONS, an as parseNonNegativeCents, ar as blockInteractionContextSchema, at as selectCategoryView, b as orderedLiveRunSessions, bn as parseEventSeriesId, bt as getLocalScheduleTime, cn as toNonNegativeCents, ct as formatDateTime, dn as formatCurrencyAmount, dt as formatTimeRange, en as resolvePricingOptionsPriceDisplay, et as projectPublicLocation, f as EVENT_PRESET_VALUES, fn as parseCurrencyCode, ft as inferSiteDateLocale, gn as parseCustomerId, gt as formatLocalScheduleDate, h as WHOLE_SERIES_EVENT_PRESET_VALUES, hn as parseApiKeyId, ht as compareLocalScheduleDates, i as EVENT_PRESET_VOCABULARY, in as isNonNegativeWholeCents$1, ir as ok, it as mapDrawingSchema, j as assessMailingListTargeting, jn as unsafeAsCheckoutLineId, jt as validateBookingPaymentOptionKinds, k as parseMailingListSignedSourceToken, kt as toUtcIsoDateTimeString, ln as unsafeAsNonNegativeCents, lt as formatDateTimeRange, m as SURFACE_EVENT_PRESET_VALUES, mn as formatDurationUnitLabel, mt as buildBookingUtcDateWindow, nt as toLocationCoordinates, on as parsePositiveCents, ot as formatDate, pn as assertNever, pt as resolveBookingDisplayContext, qt as formatEventPricing, rn as mapReadonlyNonEmptyArray, rr as err, sn as toCents, st as formatDateRange, tn as fromArray, tt as publicLocationSchema$1, u as resolveSiteVerticalBookingConfig, un as unsafeAsPositiveCents, ut as formatTime$1, v as CANCELLED_SESSION_STATUS, vn as parseDatedOfferingCapacityHoldId, vt as getBookingLocalDateKey, w as exposeSecret, wn as parseRetiredCourseId, wt as parseUtcIsoDateTimeString, x as resolveWholeSeriesBookingPhase, y as nextLiveRunSessionStartMs, yt as getLocalScheduleDate, z as parseMailingListPlacementTargeting, zt as getBookingInstalmentProtectedDepositAmountCents } from "../src-D9-RAM-l.mjs";
4
+ import { $ as normalizeMediaValueToIdentifierOnly, $t as createCommandContext, A as formatDiffDetail, An as getEnvPrefix, At as navigationIdentity, B as buildFieldChanges, Bn as portablePageDesignSchema, Bt as preparePushConfigTarget, C as reportFromOutcomes, Cn as requireEnvironmentWriteAuthorization, Ct as fileExists, D as normalizeRemoteHomepageReference, Dn as transportSuggestion, Dt as writeJsonFileAtomic, E as createEmptySyncResult, En as formatError, Et as writeJsonFile, F as calculatePullDiff, Fn as createManagementClient, Ft as navigationCommandItemToManagementInput, G as syncLocalMediaForPull, Gt as APPOINTMENT_SERVICE_VISIBILITY_VALUES, H as formatFieldPath, Hn as API_ENDPOINTS, Ht as extractApiErrorMessage, I as buildJsonDiff, In as ManagementApiError, It as normalizeNavigationConfigItemForCommand, J as admitBinaryWriteDestination, Jt as ApiRequestError, K as applyLocalMediaPush, Kt as createBearerAPIClient, L as hasPageOperations, Ln as sdkEventScheduleSchema, Lt as applyPushConfigPlan, M as hasPendingChanges, Mn as isLocalConfigured, Mt as convertPulledFooterToLocal, N as findChangedFieldsWithValues, Nn as isRemoteConfigured, Nt as convertPulledNavigationToLocal, O as calculateDiff, On as CliExit, Ot as isMediaValue, P as formatHumanDiff, Pn as loadSdkEnvironment, Pt as convertPulledPagesToLocal, Q as normalizeMediaIdentifierInput, Qt as createClientForEnv, R as pageMetadataForUpsert, Rn as sdkSettingsUpdateSchema, Rt as createPushConfigCommand, S as planCliCommandBatchForBindings, Sn as planEnvironmentWriteAuthorization, St as ensureDir, T as executeResidualSettingsSyncPlan, Tn as ErrorCodes, Tt as readJsonFile, U as revalidateLocalMediaPushPlan, Un as ApiEnvelopeError, Ut as normalizeApiError, V as formatFieldChange, Vn as sdkConfiguredBookingVerticalConfigSchema, Vt as revalidatePushConfigPlan, Wn as unwrapResponse, Wt as isRecord$2, X as writeBinaryFileAtomic, Xt as bindRequestTimeout, Y as readStableBinaryFile, Yt as mapEnvironmentExecutionOutcomesJson, Z as sha256, Zt as confirmAction, _ as commandExecutionToReport, _n as withErrorHandling, _t as metadataFilePath, a as executeEntryCommandPlanAsReport, an as getOutputContext, at as readEntries, b as executeCompiledCliCommandPlanAsReport, bn as parseEnvironmentSelection, bt as writeMetadataFile, c as titleFromEntryData, cn as managementClientConfigFor, ct as readEventsMeta, d as unsafeAsCliEntryIdentifier, dn as parseJsonData, dt as readNavigationMeta, en as createGetCommand, et as walkLocalContentMedia, f as unsafeAsCliFormSlug, fn as parsePaginationOptions, ft as readPagesMeta, g as commandCompileFailureToReport, gn as withConfirmation, gt as ensureMetadataDir, h as mutationCounterForEffect, hn as withCommandContext, ht as writeMediaManifest, i as entrySiteCommandTypes, in as formatDateShort, it as findLegacyEntryFiles, j as formatDiffSummary, jn as getEnvironmentDebugInfo, jt as navigationIdentityMap, k as calculateFooterDiff, kt as duplicateNavigationIdentityMessage, l as unsafeAsCliBlockIdentifier, ln as mapEntryForOutput, lt as readFooterMeta, m as commandReportToSyncResult, mn as runWithInvocation, mt as readVenuesMeta, n as entryCommandCompileErrorToReport, nn as createOutputForCommand, nt as downloadMedia, o as executeEntryCommandPlanAsSyncResult, on as getOutputOnlyContext, ot as readAllMeta, p as unsafeAsCliPageIdentifier, pn as resolveCommandPath, pt as readSettingsMeta, q as prepareLocalMediaForPush, qt as deriveCmsApiUrlFromDashboardUrl, r as entryCommandReportToSyncResult, rn as currentInvocationEnvelope, rt as extractMediaIdentifiers, s as syncResultForEntryCommandCompileError, sn as handleCommandError, st as readEventCategoriesMeta, t as compileEntryPushCommands, tn as createListCommand, tt as buildStorageUrl, u as unsafeAsCliContentTypeKey, un as parseJsonArray, ut as readFormsMeta, v as commandReportHasFailures, vn as withOutputOnlyErrorHandling, vt as metadataTargetFromEnvironment, w as mergeManySyncResults, wn as withRiverbankEnv, wt as listFiles, x as formatManagementError, xn as planEnvironmentExecution, xt as writeMetadataRecordMap, y as executeCliCommandPlan, yn as executeEnvironmentPlan, yt as readMetadataFile, zn as linkPayloadSchema, zt as loadPushConfigTarget } from "../entryCommands-Bus1LjSx.mjs";
5
+ import { r as CLI_VERSION, t as loadConfigFile } from "../load-config-9DBnYiBm.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-COwkcsq7.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-DU4T2YGq.mjs";
8
8
  import { config } from "dotenv";
9
9
  import { Command, CommanderError } from "commander";
10
10
  import * as fs$2 from "fs/promises";
@@ -1274,6 +1274,8 @@ function parseLocalEventRun(raw, filePath) {
1274
1274
  if ("schedule" in raw) throw new LegacyEventScheduleShapeError(filePath);
1275
1275
  const identity = parseLocalEventRunScheduleIdentity(raw, filePath);
1276
1276
  const fields$1 = raw;
1277
+ const questions = sdkEventUpsertOptionalFieldSchemas.bookingQuestions.safeParse(fields$1.bookingQuestions);
1278
+ if (!questions.success) throw new InvalidLocalEventScheduleIdentityError(filePath, "bookingQuestions must name a valid question set and collection settings");
1277
1279
  assertLocalEventRunName(fields$1, identity.bookingScope, filePath);
1278
1280
  assertLocalEventRunRefs(fields$1, filePath);
1279
1281
  assertLocalEventRunVisibility(fields$1, filePath);
@@ -1286,7 +1288,8 @@ function parseLocalEventRun(raw, filePath) {
1286
1288
  const { presentation: _retiredPresentation, ...run } = raw;
1287
1289
  return {
1288
1290
  ...run,
1289
- ...identity
1291
+ ...identity,
1292
+ bookingQuestions: questions.data
1290
1293
  };
1291
1294
  }
1292
1295
  async function readEventRuns(contentDir) {
@@ -4855,6 +4858,7 @@ function buildEventSeriesCommand(event, run, schedule, offer) {
4855
4858
  venueIdentifier: run.venueRef ?? undefined,
4856
4859
  categoryIdentifier: event.categoryRef ?? undefined,
4857
4860
  formIdentifier: run.formRef ?? undefined,
4861
+ bookingQuestions: run.bookingQuestions,
4858
4862
  capacity: eventCapacity(run.capacity),
4859
4863
  ...run.waitlistMode === undefined ? {} : { waitlist: { kind: run.waitlistMode === "on" ? "enabled_when_full" : run.waitlistMode === "off" ? "disabled" : "inherit" } },
4860
4864
  bookingOffer: offer.bookingOffer,
@@ -5305,10 +5309,10 @@ function formCommandDisplayIdentifier(command) {
5305
5309
  return command.input.slug;
5306
5310
  }
5307
5311
  function managementFormSchema(schema) {
5308
- return {
5312
+ return "fields" in schema ? {
5309
5313
  ...schema,
5310
5314
  fields: schema.fields.map((field) => ({ ...field }))
5311
- };
5315
+ } : schema;
5312
5316
  }
5313
5317
  function incrementFormSuccess(result, subject, effect) {
5314
5318
  if (!effect) {
@@ -7087,6 +7091,7 @@ const uiSchema = z.object({
7087
7091
  "behavior",
7088
7092
  "style"
7089
7093
  ]).optional(),
7094
+ underLooks: z.literal("owner").optional(),
7090
7095
  valueContract: z.enum(["boxBackground", "location"]).optional()
7091
7096
  }).partial().superRefine((ui, ctx) => {
7092
7097
  if (ui.layoutGridColumns !== undefined && ui.layoutGridColumnsFields !== undefined) {
@@ -7612,7 +7617,6 @@ const manifestSchema = z.object({
7612
7617
  }).optional()
7613
7618
  }).optional(),
7614
7619
  promotedFields: z.array(z.string().min(1)).optional(),
7615
- arrangementOwnedFieldIds: z.array(z.string().min(1)).readonly().optional(),
7616
7620
  variantMeaning: z.discriminatedUnion("kind", [z.object({
7617
7621
  kind: z.literal("arrangement"),
7618
7622
  lookOnlyKeys: z.array(z.string().min(1)).readonly().optional()
@@ -7884,6 +7888,16 @@ const MARK_ORDER = {
7884
7888
  function plainTextToInlineText(value) {
7885
7889
  return normalizeInlineText(value.length > 0 ? [{ text: value }] : []);
7886
7890
  }
7891
+ /** One authored inline value decides both fields; adapters execute through their existing write contract. */
7892
+ function deriveInlineTextFieldChanges(value, fields$1) {
7893
+ return [{
7894
+ path: fields$1.formatted,
7895
+ value
7896
+ }, {
7897
+ path: fields$1.plain,
7898
+ value: inlineTextToPlainText(value)
7899
+ }];
7900
+ }
7887
7901
  function inlineTextToPlainText(value) {
7888
7902
  return value.map((run) => run.text).join("");
7889
7903
  }
@@ -11409,6 +11423,274 @@ function blockDesignMetadataMapFromDefinitions(definitions$1) {
11409
11423
  }));
11410
11424
  }
11411
11425
 
11426
+ //#endregion
11427
+ //#region ../blocks/src/system/helpers/api-bindings.ts
11428
+ /**
11429
+ * Standard API bindings that all interactive blocks need.
11430
+ */
11431
+ const apiBindings = {
11432
+ now: { $bind: { from: "$root.now" } },
11433
+ siteId: { $bind: { from: "$root.siteId" } },
11434
+ apiBaseUrl: { $bind: { from: "$root.apiBaseUrl" } }
11435
+ };
11436
+ function withApiBindings(props$1, options) {
11437
+ const includeApiBaseUrl = options?.includeApiBaseUrl ?? true;
11438
+ const bindings = includeApiBaseUrl ? apiBindings : {
11439
+ siteId: apiBindings.siteId,
11440
+ now: apiBindings.now
11441
+ };
11442
+ return {
11443
+ ...bindings,
11444
+ ...props$1
11445
+ };
11446
+ }
11447
+
11448
+ //#endregion
11449
+ //#region ../blocks/src/utils/env.ts
11450
+ /**
11451
+ * Environment detection utilities
11452
+ *
11453
+ * Provides type-safe environment detection without relying on `any`-typed globals.
11454
+ */
11455
+ /**
11456
+ * Check if the current environment is development.
11457
+ *
11458
+ * Returns true if NODE_ENV is not 'production', or if NODE_ENV cannot be determined
11459
+ * (which is the safe default for validation and warnings).
11460
+ *
11461
+ * @returns true if in development mode, false if in production
11462
+ */
11463
+ function isDevEnvironment() {
11464
+ try {
11465
+ if (typeof process !== "undefined" && process.env?.NODE_ENV !== undefined) {
11466
+ return process.env.NODE_ENV !== "production";
11467
+ }
11468
+ return true;
11469
+ } catch {
11470
+ return true;
11471
+ }
11472
+ }
11473
+
11474
+ //#endregion
11475
+ //#region ../blocks/src/system/node/types.ts
11476
+ /**
11477
+ * List of reserved keys (for runtime validation).
11478
+ * Kept in sync with the ReservedNodeKeys type above.
11479
+ */
11480
+ const RESERVED_KEYS = [
11481
+ "children",
11482
+ "key",
11483
+ "$bind",
11484
+ "$when",
11485
+ "$repeat",
11486
+ "$scopes"
11487
+ ];
11488
+ /**
11489
+ * Type guard to check if props contain reserved keys at runtime.
11490
+ * Use this in development mode to catch bugs early.
11491
+ *
11492
+ * @param props - Props object to validate
11493
+ * @returns Array of reserved keys found in props, or empty array if none
11494
+ */
11495
+ function findReservedKeysInProps(props$1) {
11496
+ if (!props$1) return [];
11497
+ return RESERVED_KEYS.filter((key) => key in props$1);
11498
+ }
11499
+ /**
11500
+ * Validates that props don't contain reserved keys.
11501
+ * Throws in development, warns in production.
11502
+ *
11503
+ * @param props - Props to validate
11504
+ * @param context - Context for error message (e.g., "el('grid', ...)")
11505
+ */
11506
+ function validateProps(props$1, context = "node builder") {
11507
+ const reserved = findReservedKeysInProps(props$1);
11508
+ if (reserved.length === 0) return;
11509
+ const message = `[blocks:${context}] Reserved keys found in props: ${reserved.join(", ")}. ` + `These should be passed as separate parameters or modifiers, not in props. ` + `For example, 'children' should be the 3rd parameter to el(), not in the props object.`;
11510
+ if (isDevEnvironment()) {
11511
+ throw new TypeError(message);
11512
+ } else {
11513
+ console.error(message);
11514
+ }
11515
+ }
11516
+
11517
+ //#endregion
11518
+ //#region ../blocks/src/system/node/builder.ts
11519
+ function normalizeChildren(children) {
11520
+ if (!children) return undefined;
11521
+ const flat = children.flat().filter(Boolean);
11522
+ return flat.length > 0 ? flat : undefined;
11523
+ }
11524
+ function el(type, props$1, children, ...mods) {
11525
+ validateProps(props$1, `el('${type}', ...)`);
11526
+ const node = {
11527
+ type,
11528
+ ...props$1 && Object.keys(props$1).length > 0 ? { props: props$1 } : {},
11529
+ ...children && children.length ? { children: normalizeChildren(children) } : {}
11530
+ };
11531
+ if (mods && mods.length > 0) {
11532
+ const validMods = mods.filter((mod) => typeof mod === "function");
11533
+ if (validMods.length > 0) {
11534
+ const modified = validMods.reduce((acc, fn) => fn(acc), node);
11535
+ return devValidate(modified);
11536
+ }
11537
+ }
11538
+ return devValidate(node);
11539
+ }
11540
+ const section$1 = (props$1, children, ...mods) => el("section", props$1, children, ...mods);
11541
+ const headerSection = (props$1, children, ...mods) => el("headerSection", props$1, children, ...mods);
11542
+ const stack = (props$1, children, ...mods) => el("stack", props$1, children, ...mods);
11543
+ const inline = (props$1, children, ...mods) => el("inline", props$1, children, ...mods);
11544
+ const accordion = (props$1, children, ...mods) => el("accordion", props$1, children, ...mods);
11545
+ const accordionItem = (props$1, children, ...mods) => el("accordionItem", props$1, children, ...mods);
11546
+ const carousel = (props$1, children, ...mods) => el("carousel", {
11547
+ mode: "legacy",
11548
+ ...props$1
11549
+ }, children, ...mods);
11550
+ const text = (props$1, ...mods) => el("text", props$1, undefined, ...mods);
11551
+ const richText = (props$1, ...mods) => el("richText", props$1, undefined, ...mods);
11552
+ const icon = (props$1, ...mods) => el("icon", props$1, undefined, ...mods);
11553
+ const media = (props$1, ...mods) => el("media", props$1, undefined, ...mods);
11554
+ const fileDownload = (props$1, ...mods) => el("file-download", props$1, undefined, ...mods);
11555
+ const videoEmbed = (props$1, ...mods) => el("videoEmbed", props$1, undefined, ...mods);
11556
+ const spinner = (props$1, ...mods) => el("spinner", props$1, undefined, ...mods);
11557
+ const button = (props$1, children, ...mods) => el("button", props$1, children, ...mods);
11558
+ const link$1 = (props$1, children, ...mods) => el("link", props$1, children, ...mods);
11559
+ const form = (props$1, children, ...mods) => el("form", props$1, children, ...mods);
11560
+ const bookingForm = (props$1, children, ...mods) => el("booking-form", props$1, children, ...mods);
11561
+ const eventRegistration = (props$1, children, ...mods) => el("event-registration", props$1, children, ...mods);
11562
+ const shop = (props$1, children, ...mods) => el("shop", props$1, children, ...mods);
11563
+ const productList = (props$1, children, ...mods) => el("product-list", props$1, children, ...mods);
11564
+ const productDetail = (props$1, children, ...mods) => el("product-detail", props$1, children, ...mods);
11565
+ const cart = (props$1, children, ...mods) => el("cart", props$1, children, ...mods);
11566
+ const checkout = (props$1, children, ...mods) => el("checkout", props$1, children, ...mods);
11567
+ const gifting = (props$1, children, ...mods) => el("gifting", props$1, children, ...mods);
11568
+ function bind(from, options) {
11569
+ return (node) => ({
11570
+ ...node,
11571
+ $bind: {
11572
+ from,
11573
+ ...options?.fallback !== undefined ? { fallback: options.fallback } : {},
11574
+ ...options?.transforms ? { transforms: options.transforms } : {},
11575
+ ...options?.pick ? { pick: options.pick } : {},
11576
+ ...options?.coerce ? { coerce: options.coerce } : {}
11577
+ }
11578
+ });
11579
+ }
11580
+ function when(path$3, options) {
11581
+ return (node) => ({
11582
+ ...node,
11583
+ $when: {
11584
+ when: { from: path$3 },
11585
+ ...options?.equals !== undefined ? { equals: options.equals } : {},
11586
+ ...options?.not ? { not: true } : {},
11587
+ ...options?.authoringPresence ? { authoringPresence: options.authoringPresence } : {}
11588
+ }
11589
+ });
11590
+ }
11591
+ function scopes(entries) {
11592
+ const scoped = entries.map((entry) => ({
11593
+ name: entry.name,
11594
+ from: {
11595
+ from: entry.from.from,
11596
+ transforms: entry.from.transforms ?? [],
11597
+ pick: entry.from.pick ?? "value",
11598
+ ...entry.from.fallback !== undefined ? { fallback: entry.from.fallback } : {},
11599
+ ...entry.from.coerce ? { coerce: entry.from.coerce } : {}
11600
+ }
11601
+ }));
11602
+ return (node) => ({
11603
+ ...node,
11604
+ $scopes: scoped
11605
+ });
11606
+ }
11607
+ function repeat(collectionPath, itemName = "item", options) {
11608
+ return (node) => ({
11609
+ ...node,
11610
+ $repeat: {
11611
+ collection: {
11612
+ from: collectionPath,
11613
+ pick: "collection"
11614
+ },
11615
+ itemName,
11616
+ ...options?.indexName ? { indexName: options.indexName } : {},
11617
+ ...options?.limit ? { limit: options.limit } : {},
11618
+ ...options?.sortBy ? { sortBy: {
11619
+ path: options.sortBy.path,
11620
+ direction: options.sortBy.direction ?? "asc"
11621
+ } } : {}
11622
+ }
11623
+ });
11624
+ }
11625
+ function props(extra) {
11626
+ validateProps(extra, "props() modifier");
11627
+ return (node) => ({
11628
+ ...node,
11629
+ props: {
11630
+ ...node.props ?? {},
11631
+ ...extra
11632
+ }
11633
+ });
11634
+ }
11635
+ function accordionList({ collection, itemName = "item", indexName, accordionProps = null, itemProps = null, triggerFrom, contentFrom, valueFrom }, ...mods) {
11636
+ const resolvedIndexName = indexName ?? `${itemName}Index`;
11637
+ const resolvedValuePath = valueFrom === null ? null : valueFrom ?? resolvedIndexName;
11638
+ const baseItemProps = {
11639
+ ...itemProps ?? {},
11640
+ trigger: { $bind: { from: triggerFrom } }
11641
+ };
11642
+ if (contentFrom) {
11643
+ baseItemProps.content = { $bind: { from: contentFrom } };
11644
+ }
11645
+ if (resolvedValuePath) {
11646
+ baseItemProps.value = { $bind: { from: resolvedValuePath } };
11647
+ }
11648
+ return accordion(accordionProps ?? undefined, [accordionItem(baseItemProps, undefined, repeat(collection, itemName, { indexName: resolvedIndexName }))], ...mods);
11649
+ }
11650
+ function devValidate(node) {
11651
+ try {
11652
+ if (isDevEnvironment()) {
11653
+ const res = NodeSchema.safeParse(node);
11654
+ if (!res.success) {
11655
+ console.warn("[blocks:builder] Invalid node produced by builder", res.error.format());
11656
+ }
11657
+ }
11658
+ } catch {}
11659
+ return node;
11660
+ }
11661
+
11662
+ //#endregion
11663
+ //#region ../blocks/src/system/blocks/hero-newsletter.ts
11664
+ const heroNewsletterAction = stack({
11665
+ gap: "md",
11666
+ className: "hero-newsletter rb-w-full rb-min-w-0",
11667
+ style: {
11668
+ maxWidth: "32rem",
11669
+ overflowWrap: "anywhere"
11670
+ }
11671
+ }, [
11672
+ text({
11673
+ as: "p",
11674
+ className: "rb-body"
11675
+ }, bind("data.heroNewsletter.lead")),
11676
+ text({
11677
+ as: "p",
11678
+ className: "rb-body"
11679
+ }, bind("data.heroNewsletter.intro")),
11680
+ el("newsletter-form", withApiBindings({
11681
+ source: { $bind: { from: "data.heroNewsletter.runtime.source" } },
11682
+ sourceRef: { $bind: { from: "data.heroNewsletter.runtime.sourceRef" } },
11683
+ mailingList: { $bind: { from: "data.heroNewsletter.runtime.mailingList" } },
11684
+ targeting: { $bind: { from: "data.heroNewsletter.runtime.targeting" } },
11685
+ buttonVariant: "primary",
11686
+ spamProtectionEnabled: { $bind: { from: "$root.spamProtectionEnabled" } }
11687
+ }), []),
11688
+ el("div", { className: "rb-body" }, [text({
11689
+ as: "span",
11690
+ value: "Or email "
11691
+ }), link$1({ href: { $bind: { from: "data.heroNewsletter.contact.href" } } }, [text({ as: "span" }, bind("data.heroNewsletter.contact.email"))])], when("data.heroNewsletter.contact"))
11692
+ ], when("data.heroNewsletter"));
11693
+
11412
11694
  //#endregion
11413
11695
  //#region ../blocks/src/system/transforms/registry/core.ts
11414
11696
  /**
@@ -12365,220 +12647,6 @@ function createImageShapeField(options = {}) {
12365
12647
  };
12366
12648
  }
12367
12649
 
12368
- //#endregion
12369
- //#region ../blocks/src/utils/env.ts
12370
- /**
12371
- * Environment detection utilities
12372
- *
12373
- * Provides type-safe environment detection without relying on `any`-typed globals.
12374
- */
12375
- /**
12376
- * Check if the current environment is development.
12377
- *
12378
- * Returns true if NODE_ENV is not 'production', or if NODE_ENV cannot be determined
12379
- * (which is the safe default for validation and warnings).
12380
- *
12381
- * @returns true if in development mode, false if in production
12382
- */
12383
- function isDevEnvironment() {
12384
- try {
12385
- if (typeof process !== "undefined" && process.env?.NODE_ENV !== undefined) {
12386
- return process.env.NODE_ENV !== "production";
12387
- }
12388
- return true;
12389
- } catch {
12390
- return true;
12391
- }
12392
- }
12393
-
12394
- //#endregion
12395
- //#region ../blocks/src/system/node/types.ts
12396
- /**
12397
- * List of reserved keys (for runtime validation).
12398
- * Kept in sync with the ReservedNodeKeys type above.
12399
- */
12400
- const RESERVED_KEYS = [
12401
- "children",
12402
- "key",
12403
- "$bind",
12404
- "$when",
12405
- "$repeat",
12406
- "$scopes"
12407
- ];
12408
- /**
12409
- * Type guard to check if props contain reserved keys at runtime.
12410
- * Use this in development mode to catch bugs early.
12411
- *
12412
- * @param props - Props object to validate
12413
- * @returns Array of reserved keys found in props, or empty array if none
12414
- */
12415
- function findReservedKeysInProps(props$1) {
12416
- if (!props$1) return [];
12417
- return RESERVED_KEYS.filter((key) => key in props$1);
12418
- }
12419
- /**
12420
- * Validates that props don't contain reserved keys.
12421
- * Throws in development, warns in production.
12422
- *
12423
- * @param props - Props to validate
12424
- * @param context - Context for error message (e.g., "el('grid', ...)")
12425
- */
12426
- function validateProps(props$1, context = "node builder") {
12427
- const reserved = findReservedKeysInProps(props$1);
12428
- if (reserved.length === 0) return;
12429
- const message = `[blocks:${context}] Reserved keys found in props: ${reserved.join(", ")}. ` + `These should be passed as separate parameters or modifiers, not in props. ` + `For example, 'children' should be the 3rd parameter to el(), not in the props object.`;
12430
- if (isDevEnvironment()) {
12431
- throw new TypeError(message);
12432
- } else {
12433
- console.error(message);
12434
- }
12435
- }
12436
-
12437
- //#endregion
12438
- //#region ../blocks/src/system/node/builder.ts
12439
- function normalizeChildren(children) {
12440
- if (!children) return undefined;
12441
- const flat = children.flat().filter(Boolean);
12442
- return flat.length > 0 ? flat : undefined;
12443
- }
12444
- function el(type, props$1, children, ...mods) {
12445
- validateProps(props$1, `el('${type}', ...)`);
12446
- const node = {
12447
- type,
12448
- ...props$1 && Object.keys(props$1).length > 0 ? { props: props$1 } : {},
12449
- ...children && children.length ? { children: normalizeChildren(children) } : {}
12450
- };
12451
- if (mods && mods.length > 0) {
12452
- const validMods = mods.filter((mod) => typeof mod === "function");
12453
- if (validMods.length > 0) {
12454
- const modified = validMods.reduce((acc, fn) => fn(acc), node);
12455
- return devValidate(modified);
12456
- }
12457
- }
12458
- return devValidate(node);
12459
- }
12460
- const section$1 = (props$1, children, ...mods) => el("section", props$1, children, ...mods);
12461
- const headerSection = (props$1, children, ...mods) => el("headerSection", props$1, children, ...mods);
12462
- const stack = (props$1, children, ...mods) => el("stack", props$1, children, ...mods);
12463
- const inline = (props$1, children, ...mods) => el("inline", props$1, children, ...mods);
12464
- const accordion = (props$1, children, ...mods) => el("accordion", props$1, children, ...mods);
12465
- const accordionItem = (props$1, children, ...mods) => el("accordionItem", props$1, children, ...mods);
12466
- const carousel = (props$1, children, ...mods) => el("carousel", {
12467
- mode: "legacy",
12468
- ...props$1
12469
- }, children, ...mods);
12470
- const text = (props$1, ...mods) => el("text", props$1, undefined, ...mods);
12471
- const richText = (props$1, ...mods) => el("richText", props$1, undefined, ...mods);
12472
- const icon = (props$1, ...mods) => el("icon", props$1, undefined, ...mods);
12473
- const media = (props$1, ...mods) => el("media", props$1, undefined, ...mods);
12474
- const fileDownload = (props$1, ...mods) => el("file-download", props$1, undefined, ...mods);
12475
- const videoEmbed = (props$1, ...mods) => el("videoEmbed", props$1, undefined, ...mods);
12476
- const spinner = (props$1, ...mods) => el("spinner", props$1, undefined, ...mods);
12477
- const button = (props$1, children, ...mods) => el("button", props$1, children, ...mods);
12478
- const link$1 = (props$1, children, ...mods) => el("link", props$1, children, ...mods);
12479
- const form = (props$1, children, ...mods) => el("form", props$1, children, ...mods);
12480
- const bookingForm = (props$1, children, ...mods) => el("booking-form", props$1, children, ...mods);
12481
- const eventRegistration = (props$1, children, ...mods) => el("event-registration", props$1, children, ...mods);
12482
- const shop = (props$1, children, ...mods) => el("shop", props$1, children, ...mods);
12483
- const productList = (props$1, children, ...mods) => el("product-list", props$1, children, ...mods);
12484
- const productDetail = (props$1, children, ...mods) => el("product-detail", props$1, children, ...mods);
12485
- const cart = (props$1, children, ...mods) => el("cart", props$1, children, ...mods);
12486
- const checkout = (props$1, children, ...mods) => el("checkout", props$1, children, ...mods);
12487
- const gifting = (props$1, children, ...mods) => el("gifting", props$1, children, ...mods);
12488
- function bind(from, options) {
12489
- return (node) => ({
12490
- ...node,
12491
- $bind: {
12492
- from,
12493
- ...options?.fallback !== undefined ? { fallback: options.fallback } : {},
12494
- ...options?.transforms ? { transforms: options.transforms } : {},
12495
- ...options?.pick ? { pick: options.pick } : {},
12496
- ...options?.coerce ? { coerce: options.coerce } : {}
12497
- }
12498
- });
12499
- }
12500
- function when(path$3, options) {
12501
- return (node) => ({
12502
- ...node,
12503
- $when: {
12504
- when: { from: path$3 },
12505
- ...options?.equals !== undefined ? { equals: options.equals } : {},
12506
- ...options?.not ? { not: true } : {},
12507
- ...options?.authoringPresence ? { authoringPresence: options.authoringPresence } : {}
12508
- }
12509
- });
12510
- }
12511
- function scopes(entries) {
12512
- const scoped = entries.map((entry) => ({
12513
- name: entry.name,
12514
- from: {
12515
- from: entry.from.from,
12516
- transforms: entry.from.transforms ?? [],
12517
- pick: entry.from.pick ?? "value",
12518
- ...entry.from.fallback !== undefined ? { fallback: entry.from.fallback } : {},
12519
- ...entry.from.coerce ? { coerce: entry.from.coerce } : {}
12520
- }
12521
- }));
12522
- return (node) => ({
12523
- ...node,
12524
- $scopes: scoped
12525
- });
12526
- }
12527
- function repeat(collectionPath, itemName = "item", options) {
12528
- return (node) => ({
12529
- ...node,
12530
- $repeat: {
12531
- collection: {
12532
- from: collectionPath,
12533
- pick: "collection"
12534
- },
12535
- itemName,
12536
- ...options?.indexName ? { indexName: options.indexName } : {},
12537
- ...options?.limit ? { limit: options.limit } : {},
12538
- ...options?.sortBy ? { sortBy: {
12539
- path: options.sortBy.path,
12540
- direction: options.sortBy.direction ?? "asc"
12541
- } } : {}
12542
- }
12543
- });
12544
- }
12545
- function props(extra) {
12546
- validateProps(extra, "props() modifier");
12547
- return (node) => ({
12548
- ...node,
12549
- props: {
12550
- ...node.props ?? {},
12551
- ...extra
12552
- }
12553
- });
12554
- }
12555
- function accordionList({ collection, itemName = "item", indexName, accordionProps = null, itemProps = null, triggerFrom, contentFrom, valueFrom }, ...mods) {
12556
- const resolvedIndexName = indexName ?? `${itemName}Index`;
12557
- const resolvedValuePath = valueFrom === null ? null : valueFrom ?? resolvedIndexName;
12558
- const baseItemProps = {
12559
- ...itemProps ?? {},
12560
- trigger: { $bind: { from: triggerFrom } }
12561
- };
12562
- if (contentFrom) {
12563
- baseItemProps.content = { $bind: { from: contentFrom } };
12564
- }
12565
- if (resolvedValuePath) {
12566
- baseItemProps.value = { $bind: { from: resolvedValuePath } };
12567
- }
12568
- return accordion(accordionProps ?? undefined, [accordionItem(baseItemProps, undefined, repeat(collection, itemName, { indexName: resolvedIndexName }))], ...mods);
12569
- }
12570
- function devValidate(node) {
12571
- try {
12572
- if (isDevEnvironment()) {
12573
- const res = NodeSchema.safeParse(node);
12574
- if (!res.success) {
12575
- console.warn("[blocks:builder] Invalid node produced by builder", res.error.format());
12576
- }
12577
- }
12578
- } catch {}
12579
- return node;
12580
- }
12581
-
12582
12650
  //#endregion
12583
12651
  //#region ../blocks/src/system/node/fragments/backgroundLayer.ts
12584
12652
  const BACKGROUND_FRAME_BASE_CLASS = "rb-background-frame rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full rb-w-full rb-isolate rb-pointer-events-none";
@@ -15162,17 +15230,14 @@ const semanticGapTransform = {
15162
15230
  *
15163
15231
  * Use this transform when binding gap as an inline style rather than a class.
15164
15232
  * The output values use CSS calc() with --space-mult for theme-aware sizing.
15233
+ * An unset or unknown gap gives nothing, so the binding's fallback supplies
15234
+ * the default and a Look-owned gap stays unset.
15165
15235
  */
15166
15236
  const semanticGapValueTransform = {
15167
15237
  id: "boxStyles.semanticGapValue",
15168
15238
  kind: "string",
15169
15239
  summary: "Map semantic gap value to CSS gap value for inline styles",
15170
- run: (value, options, context) => {
15171
- if (options?.legacyOnly && asPartialObject(context.viewModel?.content)?._lookSlots !== undefined) return undefined;
15172
- const fallback = options?.fallback ?? "medium";
15173
- const gap = isSemanticSpacing(value) ? value : fallback;
15174
- return GAP_VALUE_MAP[gap];
15175
- }
15240
+ run: (value) => isSemanticSpacing(value) ? GAP_VALUE_MAP[value] : undefined
15176
15241
  };
15177
15242
  const boxStylesTransforms = [
15178
15243
  spacingTransform,
@@ -15214,14 +15279,8 @@ function twoColumnProps(config$1) {
15214
15279
  } },
15215
15280
  ...config$1.gapFrom ? { style: { gap: { $bind: {
15216
15281
  from: config$1.gapFrom,
15217
- transforms: [{
15218
- id: "boxStyles.semanticGapValue",
15219
- options: {
15220
- fallback,
15221
- legacyOnly: config$1.lookSlots === true
15222
- }
15223
- }],
15224
- ...config$1.lookSlots ? {} : { fallback: GAP_VALUE_MAP[fallback] }
15282
+ transforms: [{ id: "boxStyles.semanticGapValue" }],
15283
+ fallback: GAP_VALUE_MAP[fallback]
15225
15284
  } } } } : {}
15226
15285
  };
15227
15286
  }
@@ -16057,6 +16116,7 @@ function createButtonGroup(options = {}) {
16057
16116
  ...defaultVariant ? { defaultValue: defaultVariant } : {},
16058
16117
  ui: {
16059
16118
  intent: "style",
16119
+ underLooks: "owner",
16060
16120
  widget: "buttonVariant"
16061
16121
  }
16062
16122
  },
@@ -16097,6 +16157,7 @@ function createButtonGroup(options = {}) {
16097
16157
  maxLength: 64,
16098
16158
  ui: {
16099
16159
  intent: "style",
16160
+ underLooks: "owner",
16100
16161
  widget: "iconPicker",
16101
16162
  iconPickerPreset: "cta"
16102
16163
  }
@@ -16109,6 +16170,7 @@ function createButtonGroup(options = {}) {
16109
16170
  maxLength: 64,
16110
16171
  ui: {
16111
16172
  intent: "style",
16173
+ underLooks: "owner",
16112
16174
  widget: "iconPicker",
16113
16175
  iconPickerPreset: "cta"
16114
16176
  }
@@ -16866,28 +16928,6 @@ const formCopyFragment = defineFragment({
16866
16928
  } }), bind("content.intro"))]
16867
16929
  });
16868
16930
 
16869
- //#endregion
16870
- //#region ../blocks/src/system/helpers/api-bindings.ts
16871
- /**
16872
- * Standard API bindings that all interactive blocks need.
16873
- */
16874
- const apiBindings = {
16875
- now: { $bind: { from: "$root.now" } },
16876
- siteId: { $bind: { from: "$root.siteId" } },
16877
- apiBaseUrl: { $bind: { from: "$root.apiBaseUrl" } }
16878
- };
16879
- function withApiBindings(props$1, options) {
16880
- const includeApiBaseUrl = options?.includeApiBaseUrl ?? true;
16881
- const bindings = includeApiBaseUrl ? apiBindings : {
16882
- siteId: apiBindings.siteId,
16883
- now: apiBindings.now
16884
- };
16885
- return {
16886
- ...bindings,
16887
- ...props$1
16888
- };
16889
- }
16890
-
16891
16931
  //#endregion
16892
16932
  //#region ../blocks/src/system/fragments/library/formEmbed.ts
16893
16933
  const formEmbedFragment = defineFragment({
@@ -18556,7 +18596,6 @@ function createBlockManifest(config$1) {
18556
18596
  icon: config$1.icon ?? "Box",
18557
18597
  layout,
18558
18598
  variants,
18559
- arrangementOwnedFieldIds: config$1.arrangementOwnedFieldIds,
18560
18599
  variantMeaning: config$1.variantMeaning,
18561
18600
  defaultVariant: config$1.defaultVariant,
18562
18601
  variantOptions: config$1.variantOptions,
@@ -18639,7 +18678,8 @@ const heroActionsNote = richText({ className: "hero-actions-note" }, when("conte
18639
18678
  const heroContentNodes = [
18640
18679
  lookCaption,
18641
18680
  ...heroCopyAndCta.layout,
18642
- heroActionsNote
18681
+ heroActionsNote,
18682
+ heroNewsletterAction
18643
18683
  ];
18644
18684
  function heroContentCard(children, gap, copyAtCard) {
18645
18685
  return styledContainer({
@@ -18770,7 +18810,8 @@ const headlineRowLayout = heroLookLayout([
18770
18810
  lookCaption,
18771
18811
  ...heroCopyFragment.layout.slice(2),
18772
18812
  ...heroCtaRowFragment.layout,
18773
- heroActionsNote
18813
+ heroActionsNote,
18814
+ heroNewsletterAction
18774
18815
  ]),
18775
18816
  lookPhoto
18776
18817
  ]);
@@ -19310,26 +19351,20 @@ const introConfig = {
19310
19351
  gapSelectField({
19311
19352
  label: "Gap between media and text",
19312
19353
  defaultValue: "comfortable",
19313
- visibleWhen: { allOf: [{
19354
+ visibleWhen: {
19314
19355
  field: "variant",
19315
19356
  equals: "media-copy"
19316
- }, {
19317
- field: "blockLook",
19318
- notEquals: "intro-photo-beside-text"
19319
- }] }
19357
+ }
19320
19358
  }),
19321
19359
  createImageColSizeField({
19322
19360
  id: "ratio",
19323
19361
  label: "Media column size",
19324
19362
  defaultValue: "1/2",
19325
19363
  uiIntent: "display",
19326
- visibleWhen: { allOf: [{
19364
+ visibleWhen: {
19327
19365
  field: "variant",
19328
19366
  equals: "media-copy"
19329
- }, {
19330
- field: "blockLook",
19331
- notEquals: "intro-photo-beside-text"
19332
- }] }
19367
+ }
19333
19368
  }),
19334
19369
  createAspectRatioField({
19335
19370
  id: "aspectRatio",
@@ -19833,6 +19868,7 @@ const ctaFullConfig = {
19833
19868
  },
19834
19869
  id: "block.cta-full",
19835
19870
  title: "Call to action",
19871
+ titleSource: "title",
19836
19872
  category: "text-and-images",
19837
19873
  contentSource: { kind: "inline" },
19838
19874
  fragments: [{
@@ -22958,6 +22994,7 @@ const footerStandardContactBindings = {
22958
22994
  successMessage: { $bind: { from: "module.engagement.runtime.successMessage" } }
22959
22995
  };
22960
22996
  const footerMailingListBindings = {
22997
+ buttonVariant: { $bind: { from: "module.engagement.runtime.buttonVariant" } },
22961
22998
  source: { $bind: { from: "module.engagement.runtime.source" } },
22962
22999
  sourceRef: { $bind: { from: "module.engagement.runtime.sourceRef" } },
22963
23000
  mailingList: { $bind: { from: "module.engagement.runtime.mailingList" } },
@@ -23462,7 +23499,6 @@ const dataLoaders = { ...entriesLoader ? { entries: {
23462
23499
  }
23463
23500
  } } : {} };
23464
23501
  const testimonialsManifest = createBlockManifest({
23465
- arrangementOwnedFieldIds: ["maxEntries", "avatarLayout"],
23466
23502
  variantMeaning: {
23467
23503
  kind: "arrangement",
23468
23504
  lookOnlyKeys: [
@@ -23480,6 +23516,7 @@ const testimonialsManifest = createBlockManifest({
23480
23516
  },
23481
23517
  promotedFields: ["maxEntries"],
23482
23518
  title: "Testimonials",
23519
+ titleSource: "heading",
23483
23520
  category: "people",
23484
23521
  contentSource: { kind: "inline" },
23485
23522
  includeContainerStyles: true,
@@ -25068,7 +25105,10 @@ const mediaTextManifest = createBlockManifest({
25068
25105
  leadParagraphSlot: { $bind: { from: "content._lookSlots.lede" } },
25069
25106
  lookSlots: { $bind: { from: "content._lookSlots" } }
25070
25107
  };
25071
- return [styledCard([richText(props$1, bind("content.text"))], mediaTextCardOptions, when("content.wrapTextInCard")), richText(props$1, when("content.wrapTextInCard", { not: true }), bind("content.text"))];
25108
+ return [styledCard([richText(props$1, bind("content.text"))], mediaTextCardOptions, when("content.wrapTextInCard")), richText(props$1, when("content.wrapTextInCard", {
25109
+ equals: true,
25110
+ not: true
25111
+ }), bind("content.text"))];
25072
25112
  };
25073
25113
  const bodyTextColumn = el("div", {}, textContentNodes("rb-prose rb-max-w-none"));
25074
25114
  const defaultTextColumn = el("div", {}, [lookCopyHeading, ...textContentNodes("rb-prose rb-max-w-none")]);
@@ -26144,7 +26184,7 @@ const eventDisplayFields = [
26144
26184
  description: "Shows the venue's name and address.",
26145
26185
  required: false,
26146
26186
  defaultValue: true,
26147
- ui: { intent: "display" }
26187
+ ui: { intent: "behavior" }
26148
26188
  },
26149
26189
  {
26150
26190
  id: "showMap",
@@ -26153,7 +26193,7 @@ const eventDisplayFields = [
26153
26193
  description: "Shows a map when the event's venue has a location set.",
26154
26194
  required: false,
26155
26195
  defaultValue: true,
26156
- ui: { intent: "display" }
26196
+ ui: { intent: "behavior" }
26157
26197
  },
26158
26198
  {
26159
26199
  id: "showCapacity",
@@ -26162,7 +26202,7 @@ const eventDisplayFields = [
26162
26202
  description: "Shows how many places are left.",
26163
26203
  required: false,
26164
26204
  defaultValue: true,
26165
- ui: { intent: "display" }
26205
+ ui: { intent: "behavior" }
26166
26206
  }
26167
26207
  ];
26168
26208
  /**
@@ -26177,7 +26217,7 @@ const emptyStateField = {
26177
26217
  multiline: false,
26178
26218
  defaultValue: "No upcoming events scheduled.",
26179
26219
  maxLength: 200,
26180
- ui: { intent: "display" }
26220
+ ui: { intent: "behavior" }
26181
26221
  };
26182
26222
  /**
26183
26223
  * Layout selection field with grid/stack options
@@ -26968,6 +27008,31 @@ function resolveEventCta(event, buttonText) {
26968
27008
  hidden: false
26969
27009
  };
26970
27010
  }
27011
+ /**
27012
+ * The CTA for a catalogue card that stands for a whole dated series. The card
27013
+ * carries the next occurrence's capacity, but the visitor picks from the
27014
+ * series' upcoming dates, so it says "Sold out" (or offers the waitlist) only
27015
+ * when none of `upcomingDates` can be booked. The first date with places
27016
+ * decides; failing that, the first full date with a waitlist; failing both,
27017
+ * the next occurrence as {@link resolveEventCta} reads it. The link always
27018
+ * goes to the series, never to the date that decided.
27019
+ *
27020
+ * Whole-series events share one run capacity, so they need no dates and read
27021
+ * exactly as {@link resolveEventCta}; so does a dated series with none listed.
27022
+ */
27023
+ function resolveDatedSeriesCta(series, upcomingDates, buttonText) {
27024
+ const deciding = series.bookingScope === "single_occurrence" ? upcomingDates.find((date) => isOpenForBooking(date) && !isEventFull(date)) ?? upcomingDates.find((date) => isOpenForBooking(date) && isEventFull(date) && canJoinEventWaitlistOnAnyMode(date)) : undefined;
27025
+ if (!deciding) return resolveEventCta(series, buttonText);
27026
+ const cta = resolveEventCta(deciding, buttonText);
27027
+ return {
27028
+ ...cta,
27029
+ href: resolveEventHref(series),
27030
+ external: resolveRuntimeEventDestination(series).kind === "external"
27031
+ };
27032
+ }
27033
+ function isOpenForBooking(event) {
27034
+ return event.bookingAvailability.kind !== "closed";
27035
+ }
26971
27036
 
26972
27037
  //#endregion
26973
27038
  //#region ../calendar/dist/grid.js
@@ -29320,6 +29385,7 @@ function buildEventListWeek(anchor, startOfWeek, timeZone) {
29320
29385
  timeZone
29321
29386
  });
29322
29387
  return {
29388
+ days: viewport.days.map(formatDateKey),
29323
29389
  title: formatDateRange({
29324
29390
  kind: "civil",
29325
29391
  value: viewport.days[0]
@@ -29342,6 +29408,70 @@ function eventListWindowEvents(events, window$1) {
29342
29408
  return instant >= start && instant <= end;
29343
29409
  });
29344
29410
  }
29411
+ /** Server and client describe the shown week the same way, from the same inputs. */
29412
+ function eventListWeekDays(week, today, timeZone) {
29413
+ return {
29414
+ days: week.days,
29415
+ today: formatDateKey(today),
29416
+ timeZone
29417
+ };
29418
+ }
29419
+ /**
29420
+ * All seven days of the shown week, in week order and including empty ones.
29421
+ * A session goes under the day it starts on in its own zone, the day its tile
29422
+ * time describes. One whose own date falls outside the week (only possible in
29423
+ * another zone) goes under its day in the site zone, so it still shows.
29424
+ * Sessions arrive in start order, so with more pages to load a day is only
29425
+ * known to be empty when a later day already has a session.
29426
+ */
29427
+ function weekColumnDays(week, events, allLoaded) {
29428
+ const siteDay = groupItemsByDate(events, {
29429
+ getStartsAt: (event) => event.startsAt,
29430
+ getTimeZone: () => week.timeZone
29431
+ });
29432
+ const siteKey = new Map([...siteDay].flatMap(([key, items]) => items.map((item) => [item, key])));
29433
+ const columnKey = (event) => {
29434
+ const own = eventLocalDateKey(event);
29435
+ return week.days.includes(own) ? own : siteKey.get(event);
29436
+ };
29437
+ const options = eventDateOptions({
29438
+ siteTimeZone: week.timeZone,
29439
+ timeZone: week.timeZone
29440
+ });
29441
+ const lastLoaded = events.map(columnKey).filter((key) => key !== undefined).sort().at(-1);
29442
+ return week.days.map((dateKey) => {
29443
+ const date = {
29444
+ kind: "civil",
29445
+ value: parseBookingLocalDate(dateKey)
29446
+ };
29447
+ const dayEvents = events.filter((event) => columnKey(event) === dateKey).sort((left, right) => new Date(left.startsAt).getTime() - new Date(right.startsAt).getTime());
29448
+ return {
29449
+ dateKey,
29450
+ isToday: dateKey === week.today,
29451
+ label: {
29452
+ weekday: formatDate(date, options, {
29453
+ date: "omit",
29454
+ weekday: "short",
29455
+ year: "omit"
29456
+ }),
29457
+ fullWeekday: formatDate(date, options, {
29458
+ date: "omit",
29459
+ weekday: "long",
29460
+ year: "omit"
29461
+ }),
29462
+ day: formatDate(date, options, {
29463
+ date: "omit",
29464
+ day: "numeric",
29465
+ year: "omit"
29466
+ })
29467
+ },
29468
+ sessions: dayEvents.length > 0 ? {
29469
+ kind: "some",
29470
+ events: dayEvents
29471
+ } : allLoaded || lastLoaded !== undefined && dateKey < lastLoaded ? { kind: "none" } : { kind: "unknown" }
29472
+ };
29473
+ });
29474
+ }
29345
29475
 
29346
29476
  //#endregion
29347
29477
  //#region ../blocks/src/system/runtime/shared/bookingPaymentOptionCopy.ts
@@ -40697,6 +40827,20 @@ function normalizeOfferingsPreviewGroupOrder(value) {
40697
40827
  keys
40698
40828
  } : { kind: "default" };
40699
40829
  }
40830
+ /** Choosing a target opens its effective existing override, or supplies a complete target for one append. */
40831
+ function planOfferingPreviewCardSelection(overrides, sourceKey) {
40832
+ const existing = overrides.map((override, index) => ({
40833
+ override,
40834
+ index
40835
+ })).filter((item) => item.override.sourceKey === sourceKey).at(-1);
40836
+ return existing ? {
40837
+ kind: "open",
40838
+ index: existing.index
40839
+ } : {
40840
+ kind: "append",
40841
+ value: { sourceKey }
40842
+ };
40843
+ }
40700
40844
  function inferLegacyOfferingsPreviewGroupOrder(overrides) {
40701
40845
  const keys = uniqueOfferingsPreviewSourceKeys((overrides ?? []).map((override) => override.sourceKey));
40702
40846
  return keys.length >= 2 ? keys : [];
@@ -41203,7 +41347,11 @@ const eventCalendarListLayoutValues = [
41203
41347
  "grid",
41204
41348
  "compact"
41205
41349
  ];
41206
- const arrangementOnlyListLayouts = ["ledger", "day-groups"];
41350
+ const arrangementOnlyListLayouts = [
41351
+ "ledger",
41352
+ "day-groups",
41353
+ "week-columns"
41354
+ ];
41207
41355
  const eventListArrangementValues = [...eventCalendarListLayoutValues, ...arrangementOnlyListLayouts];
41208
41356
  const eventCalendarListLayoutOptions = [
41209
41357
  {
@@ -42257,7 +42405,7 @@ const eventDetailsManifest = createBlockManifest({
42257
42405
  label: "Show venue",
42258
42406
  required: false,
42259
42407
  defaultValue: true,
42260
- ui: { intent: "display" }
42408
+ ui: { intent: "behavior" }
42261
42409
  },
42262
42410
  {
42263
42411
  id: "showTitle",
@@ -42265,7 +42413,7 @@ const eventDetailsManifest = createBlockManifest({
42265
42413
  label: "Show event title",
42266
42414
  required: false,
42267
42415
  defaultValue: false,
42268
- ui: { intent: "display" }
42416
+ ui: { intent: "behavior" }
42269
42417
  },
42270
42418
  {
42271
42419
  id: "showDescription",
@@ -42273,7 +42421,7 @@ const eventDetailsManifest = createBlockManifest({
42273
42421
  label: "Show event description",
42274
42422
  required: false,
42275
42423
  defaultValue: false,
42276
- ui: { intent: "display" }
42424
+ ui: { intent: "behavior" }
42277
42425
  },
42278
42426
  {
42279
42427
  id: "showMap",
@@ -42282,7 +42430,7 @@ const eventDetailsManifest = createBlockManifest({
42282
42430
  description: "Shows a map, as long as the venue's location is set.",
42283
42431
  required: false,
42284
42432
  defaultValue: true,
42285
- ui: { intent: "display" }
42433
+ ui: { intent: "behavior" }
42286
42434
  },
42287
42435
  {
42288
42436
  id: "showOtherDates",
@@ -42290,7 +42438,7 @@ const eventDetailsManifest = createBlockManifest({
42290
42438
  label: "Show other dates",
42291
42439
  required: false,
42292
42440
  defaultValue: true,
42293
- ui: { intent: "display" }
42441
+ ui: { intent: "behavior" }
42294
42442
  },
42295
42443
  {
42296
42444
  id: "otherDatesLimit",
@@ -42317,7 +42465,7 @@ const eventDetailsManifest = createBlockManifest({
42317
42465
  label: "All dates"
42318
42466
  }
42319
42467
  ],
42320
- ui: { intent: "display" }
42468
+ ui: { intent: "behavior" }
42321
42469
  },
42322
42470
  {
42323
42471
  id: "showCapacity",
@@ -42325,7 +42473,7 @@ const eventDetailsManifest = createBlockManifest({
42325
42473
  label: "Show capacity",
42326
42474
  required: false,
42327
42475
  defaultValue: false,
42328
- ui: { intent: "display" }
42476
+ ui: { intent: "behavior" }
42329
42477
  },
42330
42478
  {
42331
42479
  id: "showCost",
@@ -42334,7 +42482,7 @@ const eventDetailsManifest = createBlockManifest({
42334
42482
  description: "Shows the ticket price for paid events.",
42335
42483
  required: false,
42336
42484
  defaultValue: true,
42337
- ui: { intent: "display" }
42485
+ ui: { intent: "behavior" }
42338
42486
  },
42339
42487
  {
42340
42488
  id: "showAcceptedPasses",
@@ -42343,7 +42491,7 @@ const eventDetailsManifest = createBlockManifest({
42343
42491
  description: "Shows which passes can be used for this event.",
42344
42492
  required: false,
42345
42493
  defaultValue: true,
42346
- ui: { intent: "display" }
42494
+ ui: { intent: "behavior" }
42347
42495
  },
42348
42496
  {
42349
42497
  id: "showAcceptedMemberships",
@@ -42352,7 +42500,7 @@ const eventDetailsManifest = createBlockManifest({
42352
42500
  description: "Shows which memberships include this event.",
42353
42501
  required: false,
42354
42502
  defaultValue: true,
42355
- ui: { intent: "display" }
42503
+ ui: { intent: "behavior" }
42356
42504
  }
42357
42505
  ],
42358
42506
  layout: [styledSection({
@@ -42692,6 +42840,7 @@ function getCardOrientation(layout) {
42692
42840
  case "grid": return "vertical";
42693
42841
  case "ledger":
42694
42842
  case "day-groups":
42843
+ case "week-columns":
42695
42844
  case "compact": return "vertical";
42696
42845
  }
42697
42846
  }
@@ -44158,19 +44307,33 @@ function mediaImageHostProps(props$1, style) {
44158
44307
  }
44159
44308
 
44160
44309
  //#endregion
44161
- //#region ../blocks/src/primitives/content/components/RichText.tsx
44310
+ //#region ../blocks/src/primitives/content/richTextImageSize.ts
44162
44311
  function parseDimension(value) {
44163
- if (typeof value === "number" && Number.isFinite(value) && value > 0) {
44164
- return Math.round(value);
44165
- }
44166
- if (typeof value === "string" && value.trim().length > 0) {
44167
- const parsed = Number(value);
44168
- if (Number.isFinite(parsed) && parsed > 0) {
44169
- return Math.round(parsed);
44170
- }
44171
- }
44172
- return undefined;
44312
+ const parsed = typeof value === "number" || typeof value === "string" ? Number(value) : NaN;
44313
+ return Number.isFinite(parsed) && parsed > 0 ? Math.round(parsed) : undefined;
44173
44314
  }
44315
+ /** View and editor images must request the same resource to preserve browser cache reuse. */
44316
+ function getRichTextImageSize(attrs) {
44317
+ const width = parseDimension(attrs.width);
44318
+ const height = parseDimension(attrs.height);
44319
+ const urlOptions = width ? {
44320
+ width,
44321
+ resize: "contain",
44322
+ quality: 85
44323
+ } : height ? {
44324
+ height,
44325
+ resize: "contain",
44326
+ quality: 85
44327
+ } : ImagePresets.full;
44328
+ return {
44329
+ width,
44330
+ height,
44331
+ urlOptions
44332
+ };
44333
+ }
44334
+
44335
+ //#endregion
44336
+ //#region ../blocks/src/primitives/content/components/RichText.tsx
44174
44337
  function normalizeRel(target, rel) {
44175
44338
  const normalizedRel = rel?.trim();
44176
44339
  if (target !== "_blank") {
@@ -44249,20 +44412,7 @@ function renderSimpleNode(node, key, children, context) {
44249
44412
  default: return null;
44250
44413
  }
44251
44414
  }
44252
- function richTextImageOptions(width, height) {
44253
- if (width) return {
44254
- width,
44255
- resize: "contain",
44256
- quality: 85
44257
- };
44258
- if (height) return {
44259
- height,
44260
- resize: "contain",
44261
- quality: 85
44262
- };
44263
- return ImagePresets.full;
44264
- }
44265
- function resolveRichTextImageSource(attrs, width, height, context) {
44415
+ function resolveRichTextImageSource(attrs, context) {
44266
44416
  if (attrs.identifier !== undefined && attrs.identifier !== null) {
44267
44417
  const parsed = parseCanonicalMediaIdentifier(attrs.identifier);
44268
44418
  if (!parsed.ok) return undefined;
@@ -44270,7 +44420,7 @@ function resolveRichTextImageSource(attrs, width, height, context) {
44270
44420
  return resolveImageUrlWithContext({
44271
44421
  type: "image",
44272
44422
  identifier: parsed.value
44273
- }, richTextImageOptions(width, height), context);
44423
+ }, getRichTextImageSize(attrs).urlOptions, context);
44274
44424
  }
44275
44425
  return typeof attrs.src === "string" ? attrs.src.trim() || undefined : undefined;
44276
44426
  }
@@ -44278,9 +44428,8 @@ function resolveRichTextImageSource(attrs, width, height, context) {
44278
44428
  }
44279
44429
  function renderRichTextImage(node, key, context) {
44280
44430
  const attrs = node.attrs ?? {};
44281
- const width = parseDimension(attrs.width);
44282
- const height = parseDimension(attrs.height);
44283
- const src = resolveRichTextImageSource(attrs, width, height, context.imageResolveContext);
44431
+ const { width, height } = getRichTextImageSize(attrs);
44432
+ const src = resolveRichTextImageSource(attrs, context.imageResolveContext);
44284
44433
  if (!src) return null;
44285
44434
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
44286
44435
  src,
@@ -44700,6 +44849,12 @@ const eventItemParts = {
44700
44849
  "description",
44701
44850
  "action"
44702
44851
  ],
44852
+ "week-columns": [
44853
+ "time",
44854
+ "title",
44855
+ "meta",
44856
+ "places"
44857
+ ],
44703
44858
  grid: [
44704
44859
  "image",
44705
44860
  "date",
@@ -44811,7 +44966,7 @@ function renderCalendarTrailingParts(props$1, parts, renderPart) {
44811
44966
  }) : content;
44812
44967
  }
44813
44968
  function eventItemTag(arrangement) {
44814
- return arrangement === "ledger" || arrangement === "day-groups" ? "li" : "article";
44969
+ return arrangement === "ledger" || arrangement === "day-groups" || arrangement === "week-columns" ? "li" : "article";
44815
44970
  }
44816
44971
  function renderEventItemContentPart({ part, props: props$1, facts }) {
44817
44972
  switch (part) {
@@ -45303,7 +45458,7 @@ function eventCardCategoryBadge(category) {
45303
45458
  *
45304
45459
  * This component is server-safe (uses no client APIs like Intl).
45305
45460
  */
45306
- const EventCard = ({ event, cardRole = "default", buttonVariant = "primary", buttonText, showVenue = true, showMap = true, mapSlot, allowMap = true, lookSlots, itemSurfaces, showCapacity = true, showImage = true, showCategory = true, showSummary = true, orientation = "vertical", presentation, headingLevel, imageResolveContext }) => {
45461
+ const EventCard = ({ event, cardRole = "default", buttonVariant = "primary", buttonText, showVenue = true, showMap = true, mapSlot, allowMap = true, lookSlots, itemSurfaces, showCapacity = true, showImage = true, showCategory = true, showSummary = true, orientation = "vertical", presentation, headingLevel, imageResolveContext, upcomingDates }) => {
45307
45462
  const { presentationClass, cardHeadingLevel, formattedDate, formattedTime, cta, cardClass, title, summary, image, category, categoryBadge, hasImage, dateFact, priceText, teacherLine, capacityText, orientationClass } = eventCardFacts({
45308
45463
  event,
45309
45464
  presentation,
@@ -45313,7 +45468,8 @@ const EventCard = ({ event, cardRole = "default", buttonVariant = "primary", but
45313
45468
  showCategory,
45314
45469
  showImage,
45315
45470
  showCapacity,
45316
- orientation
45471
+ orientation,
45472
+ upcomingDates
45317
45473
  });
45318
45474
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", {
45319
45475
  ...listLookSlot({
@@ -45591,13 +45747,13 @@ function EventLookDate({ event, ...presentation }) {
45591
45747
  })]
45592
45748
  });
45593
45749
  }
45594
- function eventCardFacts({ event, presentation, headingLevel, buttonText, cardRole, showCategory, showImage, showCapacity, orientation }) {
45750
+ function eventCardFacts({ event, presentation, headingLevel, buttonText, cardRole, showCategory, showImage, showCapacity, orientation, upcomingDates }) {
45595
45751
  const { presentation: cardPresentation, presentationClass, headingLevel: cardHeadingLevel } = resolveEventCardOptions({
45596
45752
  presentation,
45597
45753
  headingLevel
45598
45754
  });
45599
45755
  const { formattedDate, formattedTime } = formatEventCardWhen(event);
45600
- const cta = resolveEventCta(event, buttonText);
45756
+ const cta = resolveDatedSeriesCta(event, upcomingDates ?? [], buttonText);
45601
45757
  const cardClass = boxStyleClassNames({ role: cardRole }, { baseClass: "event-card" });
45602
45758
  const title = event.title;
45603
45759
  const summary = event.presentation?.summary ?? event.description;
@@ -46071,6 +46227,157 @@ function canonicalEventSeriesScope(seriesIds) {
46071
46227
  return seriesIds == null ? null : [...new Set(seriesIds.split(",").filter(Boolean))].sort().join(",");
46072
46228
  }
46073
46229
 
46230
+ //#endregion
46231
+ //#region ../blocks/src/system/runtime/hooks/loadStateError.ts
46232
+ function toError(error$1, fallbackMessage) {
46233
+ return error$1 instanceof Error ? error$1 : new Error(fallbackMessage);
46234
+ }
46235
+
46236
+ //#endregion
46237
+ //#region ../blocks/src/system/runtime/hooks/useEventPagination.state.ts
46238
+ function createInitialEventPaginationLoadState(events, scope) {
46239
+ return {
46240
+ kind: "ready",
46241
+ requestId: 0,
46242
+ page: {
46243
+ scope,
46244
+ events,
46245
+ hasMore: hasMoreEventPages(events, scope.pageSize)
46246
+ }
46247
+ };
46248
+ }
46249
+ function eventPaginationLoadReducer(state, action) {
46250
+ switch (action.type) {
46251
+ case "started": return {
46252
+ kind: "loading",
46253
+ requestId: state.requestId + 1,
46254
+ operation: action.operation
46255
+ };
46256
+ case "succeeded": return state.kind === "loading" && state.requestId === action.requestId ? {
46257
+ kind: "ready",
46258
+ requestId: state.requestId,
46259
+ page: acceptEventPage(state.operation, action.events)
46260
+ } : state;
46261
+ case "failed": return state.kind === "loading" && state.requestId === action.requestId ? {
46262
+ ...state,
46263
+ kind: "error",
46264
+ error: action.error
46265
+ } : state;
46266
+ case "synced": return {
46267
+ ...createInitialEventPaginationLoadState(action.events, action.scope),
46268
+ requestId: state.requestId + 1
46269
+ };
46270
+ default: return assertNever$4(action);
46271
+ }
46272
+ }
46273
+ function eventPageOperationScope(operation) {
46274
+ switch (operation.kind) {
46275
+ case "replace": return operation.scope;
46276
+ case "append": return operation.page.scope;
46277
+ default: return assertNever$4(operation);
46278
+ }
46279
+ }
46280
+ function eventPageOperationQuery(operation) {
46281
+ switch (operation.kind) {
46282
+ case "replace": return operation.scope.query;
46283
+ case "append": return operation.query;
46284
+ default: return assertNever$4(operation);
46285
+ }
46286
+ }
46287
+ function acceptEventPage(operation, events) {
46288
+ const scope = eventPageOperationScope(operation);
46289
+ const hasMore = hasMoreEventPages(events, scope.pageSize);
46290
+ switch (operation.kind) {
46291
+ case "replace": return {
46292
+ scope,
46293
+ events,
46294
+ hasMore
46295
+ };
46296
+ case "append": return {
46297
+ scope,
46298
+ events: mergeEventPaginationEvents(operation.page.events, events),
46299
+ hasMore
46300
+ };
46301
+ default: return assertNever$4(operation);
46302
+ }
46303
+ }
46304
+ /** Retry consumes the recorded operation. Load more is possible only from an accepted page. */
46305
+ function planEventPageOperation(state, scope, intent) {
46306
+ if (scope.query.seriesIds === "") return null;
46307
+ switch (intent) {
46308
+ case "replace": return {
46309
+ kind: "replace",
46310
+ scope
46311
+ };
46312
+ case "retry": return state.kind === "error" && eventPageOperationScope(state.operation).key === scope.key ? state.operation : null;
46313
+ case "append": {
46314
+ if (state.kind !== "ready" || state.page.scope.key !== scope.key || !state.page.hasMore) return null;
46315
+ const cursor = state.page.events.at(-1);
46316
+ return {
46317
+ kind: "append",
46318
+ page: state.page,
46319
+ query: {
46320
+ ...scope.query,
46321
+ afterStartsAt: cursor?.startsAt,
46322
+ afterId: cursor?.occurrenceId
46323
+ }
46324
+ };
46325
+ }
46326
+ default: return assertNever$4(intent);
46327
+ }
46328
+ }
46329
+ /** A changed scope is pending even before the effect starts its replacement request. */
46330
+ function getEventPaginationView(state, scope) {
46331
+ const stateScope = state.kind === "ready" ? state.page.scope : eventPageOperationScope(state.operation);
46332
+ if (stateScope.key !== scope.key) return {
46333
+ events: [],
46334
+ loading: true,
46335
+ error: null,
46336
+ hasMore: false
46337
+ };
46338
+ switch (state.kind) {
46339
+ case "ready": return {
46340
+ ...state.page,
46341
+ loading: false,
46342
+ error: null
46343
+ };
46344
+ case "loading": return {
46345
+ ...getOperationPage(state.operation),
46346
+ loading: true,
46347
+ error: null
46348
+ };
46349
+ case "error": return {
46350
+ ...getOperationPage(state.operation),
46351
+ loading: false,
46352
+ error: state.error
46353
+ };
46354
+ default: return assertNever$4(state);
46355
+ }
46356
+ }
46357
+ function getOperationPage(operation) {
46358
+ switch (operation.kind) {
46359
+ case "replace": return {
46360
+ events: [],
46361
+ hasMore: false
46362
+ };
46363
+ case "append": return operation.page;
46364
+ default: return assertNever$4(operation);
46365
+ }
46366
+ }
46367
+ function getEventIdentity(event) {
46368
+ return event.occurrenceId || event.id;
46369
+ }
46370
+ function mergeEventPaginationEvents(existingEvents, newEvents) {
46371
+ const existingIds = new Set(existingEvents.map(getEventIdentity));
46372
+ return [...existingEvents, ...newEvents.filter((event) => !existingIds.has(getEventIdentity(event)))];
46373
+ }
46374
+ function toEventPaginationLoadError(error$1) {
46375
+ return toError(error$1, "Unknown error");
46376
+ }
46377
+ function hasMoreEventPages(events, pageSize) {
46378
+ return events.length >= pageSize;
46379
+ }
46380
+
46074
46381
  //#endregion
46075
46382
  //#region ../blocks/src/system/blocks/events/shared/calendarWindow.ts
46076
46383
  function resolveCalendarReadProfile(content) {
@@ -46422,6 +46729,7 @@ function buildEventCollectionHydration(source) {
46422
46729
  function buildEventCollectionListingDisplay(display, prefetchedEvents, className) {
46423
46730
  const initialEvents = display.events.slice(0, display.eventsPerPage);
46424
46731
  return {
46732
+ allLoaded: prefetchedEvents && !hasMoreEventPages(display.events, display.eventsPerPage),
46425
46733
  kind: "event-listing",
46426
46734
  sectionAction: display.sectionAction,
46427
46735
  panelHeading: display.panelHeading,
@@ -46500,7 +46808,13 @@ const eventListingDisplaySchema = z.object({
46500
46808
  showCapacity: z.boolean(),
46501
46809
  showPhotos: z.boolean().optional(),
46502
46810
  orientation: cardOrientationSchema,
46503
- events: z.array(publicEventSchema)
46811
+ events: z.array(publicEventSchema),
46812
+ week: z.object({
46813
+ days: z.array(z.string()).length(7),
46814
+ today: z.string(),
46815
+ timeZone: z.string()
46816
+ }).optional(),
46817
+ allLoaded: z.boolean().optional()
46504
46818
  });
46505
46819
  const eventListingHydrationSchema = z.object({
46506
46820
  siteId: z.string(),
@@ -46998,6 +47312,115 @@ const eventListingBlockDefinition = {
46998
47312
  } }
46999
47313
  };
47000
47314
 
47315
+ //#endregion
47316
+ //#region ../blocks/src/system/blocks/events/eventSelectionChips.ts
47317
+ /** The event types a calendar can be narrowed to, in the order they're offered. */
47318
+ const EVENT_SELECTION_TYPE_OPTIONS = [
47319
+ {
47320
+ value: "course",
47321
+ label: "Courses"
47322
+ },
47323
+ {
47324
+ value: "class",
47325
+ label: "Classes"
47326
+ },
47327
+ {
47328
+ value: "workshop",
47329
+ label: "Workshops"
47330
+ },
47331
+ {
47332
+ value: "retreat",
47333
+ label: "Retreats"
47334
+ },
47335
+ {
47336
+ value: "performance",
47337
+ label: "Performances"
47338
+ }
47339
+ ];
47340
+ /** Regular and one-off, as the chips' second row names them. */
47341
+ const EVENT_SELECTION_SCOPE_OPTIONS = [
47342
+ {
47343
+ value: "any",
47344
+ label: "Regular and one-off"
47345
+ },
47346
+ {
47347
+ value: "recurring",
47348
+ label: "Regular only"
47349
+ },
47350
+ {
47351
+ value: "oneOff",
47352
+ label: "One-off only"
47353
+ }
47354
+ ];
47355
+ const SPECIAL_DATED_PRESETS = [
47356
+ "workshop",
47357
+ "retreat",
47358
+ "performance"
47359
+ ];
47360
+ /**
47361
+ * Reads the stored fields as chips. The named presets show as the chips that
47362
+ * mean the same thing, so "Regular class schedule" reads as Classes, regular
47363
+ * only, matching how the event loader expands them.
47364
+ */
47365
+ function readEventSelectionChips(fields$1) {
47366
+ switch (fields$1.eventSurface) {
47367
+ case "regularClassSchedule": return {
47368
+ types: ["class"],
47369
+ scope: "recurring"
47370
+ };
47371
+ case "specialDatedEvents": return {
47372
+ types: SPECIAL_DATED_PRESETS,
47373
+ scope: "any"
47374
+ };
47375
+ case "custom": return {
47376
+ types: fields$1.filterEventPresets ?? [],
47377
+ scope: fields$1.scheduleScope ?? "any"
47378
+ };
47379
+ case "all":
47380
+ case undefined: return {
47381
+ types: [],
47382
+ scope: fields$1.scheduleScope ?? "any"
47383
+ };
47384
+ }
47385
+ }
47386
+ /**
47387
+ * The stored fields for a chip choice. Choosing types stores them as Custom;
47388
+ * clearing every type goes back to All events and drops the old type list, so
47389
+ * nothing stale keeps filtering.
47390
+ */
47391
+ function writeEventSelectionChips(chips) {
47392
+ return chips.types.length === 0 && chips.scope === "any" ? {
47393
+ eventSurface: "all",
47394
+ filterEventPresets: [],
47395
+ scheduleScope: "any"
47396
+ } : {
47397
+ eventSurface: "custom",
47398
+ filterEventPresets: chips.types,
47399
+ scheduleScope: chips.scope
47400
+ };
47401
+ }
47402
+ /** "All events": every type, regular and one-off. */
47403
+ function chooseAllEvents() {
47404
+ return {
47405
+ types: [],
47406
+ scope: "any"
47407
+ };
47408
+ }
47409
+ /** Adds or removes one type, keeping the list in the order the options give. */
47410
+ function toggleEventType(chips, type, order) {
47411
+ const next = chips.types.includes(type) ? chips.types.filter((t$1) => t$1 !== type) : [...chips.types, type];
47412
+ return {
47413
+ ...chips,
47414
+ types: order.filter((t$1) => next.includes(t$1))
47415
+ };
47416
+ }
47417
+ function chooseScheduleScope(chips, scope) {
47418
+ return {
47419
+ ...chips,
47420
+ scope
47421
+ };
47422
+ }
47423
+
47001
47424
  //#endregion
47002
47425
  //#region ../blocks/src/system/blocks/events/recurring-schedule-projection.ts
47003
47426
  const weekdayOrder = [
@@ -47966,7 +48389,7 @@ const eventCalendarAdditionalFields = [
47966
48389
  label: "Week"
47967
48390
  }],
47968
48391
  ui: {
47969
- intent: "display",
48392
+ intent: "behavior",
47970
48393
  visibleWhen: {
47971
48394
  field: "variant",
47972
48395
  equals: "list"
@@ -48080,7 +48503,7 @@ const eventCalendarAdditionalFields = [
48080
48503
  }
48081
48504
  ],
48082
48505
  ui: {
48083
- intent: "display",
48506
+ intent: "behavior",
48084
48507
  visibleWhen: {
48085
48508
  field: "variant",
48086
48509
  oneOf: ["combined", "list"]
@@ -48110,7 +48533,7 @@ const eventCalendarAdditionalFields = [
48110
48533
  }
48111
48534
  ],
48112
48535
  ui: {
48113
- intent: "display",
48536
+ intent: "behavior",
48114
48537
  visibleWhen: {
48115
48538
  field: "variant",
48116
48539
  oneOf: ["combined", "list"]
@@ -48123,7 +48546,7 @@ const eventCalendarAdditionalFields = [
48123
48546
  label: "Link to the full list",
48124
48547
  required: false,
48125
48548
  ui: {
48126
- intent: "display",
48549
+ intent: "behavior",
48127
48550
  visibleWhen: { anyOf: [{ allOf: [{
48128
48551
  field: "variant",
48129
48552
  oneOf: ["combined", "list"]
@@ -48145,7 +48568,7 @@ const eventCalendarAdditionalFields = [
48145
48568
  multiline: false,
48146
48569
  defaultValue: "Load more events",
48147
48570
  ui: {
48148
- intent: "display",
48571
+ intent: "behavior",
48149
48572
  visibleWhen: {
48150
48573
  field: "variant",
48151
48574
  oneOf: [
@@ -48172,7 +48595,7 @@ const eventCalendarAdditionalFields = [
48172
48595
  label: "Monday"
48173
48596
  }],
48174
48597
  ui: {
48175
- intent: "display",
48598
+ intent: "behavior",
48176
48599
  visibleWhen: {
48177
48600
  field: "variant",
48178
48601
  oneOf: [
@@ -48208,7 +48631,7 @@ const eventCalendarAdditionalFields = [
48208
48631
  }
48209
48632
  ],
48210
48633
  ui: {
48211
- intent: "display",
48634
+ intent: "behavior",
48212
48635
  visibleWhen: {
48213
48636
  field: "variant",
48214
48637
  equals: "combined"
@@ -48252,7 +48675,7 @@ const eventCalendarAdditionalFields = [
48252
48675
  required: false,
48253
48676
  defaultValue: true,
48254
48677
  ui: {
48255
- intent: "display",
48678
+ intent: "behavior",
48256
48679
  visibleWhen: {
48257
48680
  field: "variant",
48258
48681
  oneOf: [
@@ -48288,7 +48711,7 @@ const eventCalendarAdditionalFields = [
48288
48711
  }
48289
48712
  ],
48290
48713
  ui: {
48291
- intent: "display",
48714
+ intent: "behavior",
48292
48715
  visibleWhen: { allOf: [{
48293
48716
  field: "variant",
48294
48717
  oneOf: [
@@ -48312,7 +48735,7 @@ const eventCalendarAdditionalFields = [
48312
48735
  required: false,
48313
48736
  defaultValue: false,
48314
48737
  ui: {
48315
- intent: "display",
48738
+ intent: "behavior",
48316
48739
  visibleWhen: { allOf: [{
48317
48740
  field: "variant",
48318
48741
  oneOf: [
@@ -48336,7 +48759,7 @@ const eventCalendarAdditionalFields = [
48336
48759
  required: false,
48337
48760
  defaultValue: true,
48338
48761
  ui: {
48339
- intent: "display",
48762
+ intent: "behavior",
48340
48763
  visibleWhen: { allOf: [{
48341
48764
  field: "variant",
48342
48765
  oneOf: [
@@ -48442,8 +48865,7 @@ const eventCalendarAdditionalFields = [
48442
48865
  {
48443
48866
  id: "eventSurface",
48444
48867
  type: "select",
48445
- label: "Event types",
48446
- description: "Choose whether this block shows everything, regular classes, or workshops and special events.",
48868
+ label: "Which events",
48447
48869
  required: false,
48448
48870
  multiple: false,
48449
48871
  defaultValue: "all",
@@ -48465,7 +48887,10 @@ const eventCalendarAdditionalFields = [
48465
48887
  label: "Custom"
48466
48888
  }
48467
48889
  ],
48468
- ui: { intent: "behavior" }
48890
+ ui: {
48891
+ intent: "behavior",
48892
+ widget: "eventSelectionChips"
48893
+ }
48469
48894
  },
48470
48895
  {
48471
48896
  id: "filterEventPresets",
@@ -48475,34 +48900,10 @@ const eventCalendarAdditionalFields = [
48475
48900
  required: false,
48476
48901
  multiple: true,
48477
48902
  defaultValue: [],
48478
- options: [
48479
- {
48480
- value: "course",
48481
- label: "Courses"
48482
- },
48483
- {
48484
- value: "class",
48485
- label: "Classes"
48486
- },
48487
- {
48488
- value: "workshop",
48489
- label: "Workshops"
48490
- },
48491
- {
48492
- value: "retreat",
48493
- label: "Retreats"
48494
- },
48495
- {
48496
- value: "performance",
48497
- label: "Performances"
48498
- }
48499
- ],
48903
+ options: EVENT_SELECTION_TYPE_OPTIONS.map((option) => ({ ...option })),
48500
48904
  ui: {
48501
48905
  intent: "behavior",
48502
- visibleWhen: {
48503
- field: "eventSurface",
48504
- equals: "custom"
48505
- }
48906
+ hidden: true
48506
48907
  }
48507
48908
  },
48508
48909
  {
@@ -48529,10 +48930,7 @@ const eventCalendarAdditionalFields = [
48529
48930
  ],
48530
48931
  ui: {
48531
48932
  intent: "behavior",
48532
- visibleWhen: {
48533
- field: "eventSurface",
48534
- equals: "custom"
48535
- }
48933
+ hidden: true
48536
48934
  }
48537
48935
  },
48538
48936
  createSiteOptionSelectField({
@@ -48579,13 +48977,7 @@ const eventCalendarAdditionalFields = [
48579
48977
  intent: field.id === "_cardStyles" || field.id === "buttonVariant" ? "style" : "content"
48580
48978
  }
48581
48979
  })),
48582
- {
48583
- ...emptyStateField,
48584
- ui: {
48585
- ...emptyStateField.ui ?? {},
48586
- intent: "display"
48587
- }
48588
- },
48980
+ emptyStateField,
48589
48981
  sectionStylesField({
48590
48982
  id: "_sectionStyles",
48591
48983
  label: "Section styles",
@@ -48739,7 +49131,6 @@ const eventCalendarConfig = {
48739
49131
  icon: "CalendarDays",
48740
49132
  layout: eventCalendarLayout,
48741
49133
  variants: eventCalendarVariants,
48742
- arrangementOwnedFieldIds: ["defaultCalendarView"],
48743
49134
  variantMeaning: eventCalendarVariantMeaning,
48744
49135
  defaultVariant: "combined",
48745
49136
  variantOptions: {
@@ -48757,7 +49148,11 @@ const eventCalendarManifest = {
48757
49148
  fields: generatedEventCalendarManifest.fields?.map((field) => field.id === "variant" ? {
48758
49149
  ...field,
48759
49150
  label: "Show events as",
48760
- description: undefined
49151
+ description: undefined,
49152
+ ui: {
49153
+ ...field.ui,
49154
+ widget: "segmented"
49155
+ }
48761
49156
  } : field)
48762
49157
  };
48763
49158
  const eventCalendarBlockDefinition = {
@@ -49066,7 +49461,7 @@ const groupOverrideFields = [
49066
49461
  label: "Hide this card",
49067
49462
  required: false,
49068
49463
  defaultValue: false,
49069
- ui: { intent: "display" }
49464
+ ui: { intent: "behavior" }
49070
49465
  },
49071
49466
  {
49072
49467
  id: "presentation",
@@ -49169,7 +49564,7 @@ const offeringsPreviewFields = [
49169
49564
  label: "6 items"
49170
49565
  }
49171
49566
  ],
49172
- ui: { intent: "display" }
49567
+ ui: { intent: "behavior" }
49173
49568
  },
49174
49569
  {
49175
49570
  id: "groupOrder",
@@ -49183,7 +49578,7 @@ const offeringsPreviewFields = [
49183
49578
  label: labelForOfferingPreviewSourceKey(sourceKey)
49184
49579
  })),
49185
49580
  ui: {
49186
- intent: "display",
49581
+ intent: "behavior",
49187
49582
  widget: "offeringGroupOrder"
49188
49583
  }
49189
49584
  },
@@ -49197,7 +49592,10 @@ const offeringsPreviewFields = [
49197
49592
  itemLabel: "Offering card",
49198
49593
  itemLabelSource: "title",
49199
49594
  allowConversion: false,
49200
- ui: { intent: "content" },
49595
+ ui: {
49596
+ intent: "content",
49597
+ widget: "offeringCardChanges"
49598
+ },
49201
49599
  schema: { fields: groupOverrideFields }
49202
49600
  },
49203
49601
  createButtonVariantField(),
@@ -49438,7 +49836,6 @@ const offeringsPreviewLayout = [styledSection({
49438
49836
  spacing: "comfortable"
49439
49837
  })];
49440
49838
  const offeringsPreviewConfig = {
49441
- arrangementOwnedFieldIds: ["groupOverrides.presentation"],
49442
49839
  variantMeaning: {
49443
49840
  kind: "arrangement",
49444
49841
  lookOnlyKeys: [
@@ -50200,7 +50597,7 @@ const imageGalleryFields = parseFieldDefinitions([
50200
50597
  label: "Show arrows",
50201
50598
  defaultValue: true,
50202
50599
  ui: {
50203
- intent: "behavior",
50600
+ intent: "display",
50204
50601
  visibleWhen: {
50205
50602
  field: "variant",
50206
50603
  equals: "carousel"
@@ -50213,7 +50610,7 @@ const imageGalleryFields = parseFieldDefinitions([
50213
50610
  label: "Show dots",
50214
50611
  defaultValue: false,
50215
50612
  ui: {
50216
- intent: "behavior",
50613
+ intent: "display",
50217
50614
  visibleWhen: {
50218
50615
  field: "variant",
50219
50616
  equals: "carousel"
@@ -50226,7 +50623,7 @@ const imageGalleryFields = parseFieldDefinitions([
50226
50623
  label: "Autoplay",
50227
50624
  defaultValue: false,
50228
50625
  ui: {
50229
- intent: "behavior",
50626
+ intent: "display",
50230
50627
  visibleWhen: {
50231
50628
  field: "variant",
50232
50629
  equals: "carousel"
@@ -50257,7 +50654,7 @@ const imageGalleryFields = parseFieldDefinitions([
50257
50654
  }
50258
50655
  ],
50259
50656
  ui: {
50260
- intent: "behavior",
50657
+ intent: "display",
50261
50658
  visibleWhen: {
50262
50659
  field: "variant",
50263
50660
  equals: "carousel"
@@ -50277,7 +50674,7 @@ const imageGalleryFields = parseFieldDefinitions([
50277
50674
  label: "Show on hover"
50278
50675
  }],
50279
50676
  ui: {
50280
- intent: "behavior",
50677
+ intent: "display",
50281
50678
  visibleWhen: {
50282
50679
  field: "variant",
50283
50680
  equals: "carousel"
@@ -50290,7 +50687,7 @@ const imageGalleryFields = parseFieldDefinitions([
50290
50687
  label: "Loop slides",
50291
50688
  defaultValue: true,
50292
50689
  ui: {
50293
- intent: "behavior",
50690
+ intent: "display",
50294
50691
  visibleWhen: {
50295
50692
  field: "variant",
50296
50693
  equals: "carousel"
@@ -50350,7 +50747,7 @@ const imageGalleryFields = parseFieldDefinitions([
50350
50747
  label: "Pause on hover",
50351
50748
  defaultValue: true,
50352
50749
  ui: {
50353
- intent: "behavior",
50750
+ intent: "display",
50354
50751
  visibleWhen: {
50355
50752
  field: "variant",
50356
50753
  equals: "marquee"
@@ -50388,6 +50785,16 @@ const imageGalleryFields = parseFieldDefinitions([
50388
50785
  }
50389
50786
  }
50390
50787
  },
50788
+ {
50789
+ id: "blackAndWhite",
50790
+ type: "boolean",
50791
+ required: false,
50792
+ label: "Black and white",
50793
+ ui: {
50794
+ intent: "display",
50795
+ hidden: true
50796
+ }
50797
+ },
50391
50798
  {
50392
50799
  id: "imageFilter",
50393
50800
  type: "select",
@@ -52438,7 +52845,6 @@ function shopProductPresentation(hydration, productId, index, count) {
52438
52845
  * - Stripe handles payment security
52439
52846
  */
52440
52847
  const shopManifest = createBlockManifest({
52441
- arrangementOwnedFieldIds: ["layout", "columns"],
52442
52848
  variantMeaning: {
52443
52849
  kind: "arrangement",
52444
52850
  lookOnlyKeys: [
@@ -52479,7 +52885,7 @@ const shopManifest = createBlockManifest({
52479
52885
  description: "Lets visitors buy your class passes.",
52480
52886
  required: false,
52481
52887
  defaultValue: true,
52482
- ui: { intent: "display" }
52888
+ ui: { intent: "behavior" }
52483
52889
  },
52484
52890
  {
52485
52891
  id: "showMemberships",
@@ -52488,7 +52894,7 @@ const shopManifest = createBlockManifest({
52488
52894
  description: "Lets visitors buy your memberships.",
52489
52895
  required: false,
52490
52896
  defaultValue: true,
52491
- ui: { intent: "display" }
52897
+ ui: { intent: "behavior" }
52492
52898
  },
52493
52899
  {
52494
52900
  id: "layout",
@@ -52549,7 +52955,7 @@ const shopManifest = createBlockManifest({
52549
52955
  description: "Shows the description under each one.",
52550
52956
  required: false,
52551
52957
  defaultValue: true,
52552
- ui: { intent: "display" }
52958
+ ui: { intent: "behavior" }
52553
52959
  },
52554
52960
  {
52555
52961
  id: "showValidityPeriod",
@@ -52558,7 +52964,7 @@ const shopManifest = createBlockManifest({
52558
52964
  description: "Shows how long each pass lasts, like 'Valid for 30 days'.",
52559
52965
  required: false,
52560
52966
  defaultValue: true,
52561
- ui: { intent: "display" }
52967
+ ui: { intent: "behavior" }
52562
52968
  },
52563
52969
  {
52564
52970
  id: "showPricePerCredit",
@@ -52567,7 +52973,7 @@ const shopManifest = createBlockManifest({
52567
52973
  description: "Shows what each credit works out at, for passes and packs.",
52568
52974
  required: false,
52569
52975
  defaultValue: true,
52570
- ui: { intent: "display" }
52976
+ ui: { intent: "behavior" }
52571
52977
  },
52572
52978
  createButtonVariantField({
52573
52979
  label: "Button style",
@@ -53716,7 +54122,7 @@ const newsletterSourceSchema = z.discriminatedUnion("source", [
53716
54122
  ])
53717
54123
  }),
53718
54124
  newsletterSourceCommonSchema.extend({
53719
- source: z.literal("signed-footer"),
54125
+ source: z.enum(["signed-footer", "signed-hosted-booking"]),
53720
54126
  sourceRef: z.object({
53721
54127
  tag: z.literal("signed_source_ref"),
53722
54128
  token: signedMailingListSourceTokenSchema
@@ -53746,7 +54152,7 @@ const newsletterHydrationSchema = z.object({
53746
54152
  sourceRef: mailingListSignupBlockSourceRefSchema.nullable()
53747
54153
  }),
53748
54154
  z.object({
53749
- tag: z.literal("signed-footer-source"),
54155
+ tag: z.literal("signed-source"),
53750
54156
  sourceRef: z.object({
53751
54157
  tag: z.literal("signed_source_ref"),
53752
54158
  token: signedMailingListSourceTokenSchema
@@ -53804,7 +54210,7 @@ function buildNewsletterDisplay(source) {
53804
54210
  buttonLabel: form$1.buttonLabel,
53805
54211
  successMessage: source.interactionContext?.kind === "demo" ? NEWSLETTER_DEMO_MESSAGE : form$1.successMessage,
53806
54212
  buttonVariant: source.buttonVariant ?? "primary",
53807
- privacyNote: form$1.privacyNote,
54213
+ privacyNote: newsletterPrivacyNote(source.source, form$1.privacyNote),
53808
54214
  fields: getGlobalFormFields(form$1, source),
53809
54215
  choices
53810
54216
  };
@@ -53851,8 +54257,9 @@ function projectNewsletterFormHydrationTarget(source) {
53851
54257
  default: return assertNever(source.newsletterBlockSubmission);
53852
54258
  }
53853
54259
  }
54260
+ case "signed-hosted-booking":
53854
54261
  case "signed-footer": return {
53855
- tag: "signed-footer-source",
54262
+ tag: "signed-source",
53856
54263
  sourceRef: source.sourceRef
53857
54264
  };
53858
54265
  case "preview": return { tag: "preview" };
@@ -53908,6 +54315,10 @@ function parseRequiredMailingListSignedSourceToken(value) {
53908
54315
  }
53909
54316
  return parsed;
53910
54317
  }
54318
+ /** Hosted signup always explains preferences, alongside any owner-authored note. */
54319
+ function newsletterPrivacyNote(source, privacyNote) {
54320
+ return source !== "signed-hosted-booking" || privacyNote?.includes(DEFAULT_MAILING_LIST_PRIVACY_NOTE) ? privacyNote : [privacyNote, DEFAULT_MAILING_LIST_PRIVACY_NOTE].filter(Boolean).join(" ");
54321
+ }
53911
54322
 
53912
54323
  //#endregion
53913
54324
  //#region ../blocks/src/system/blocks/newsletter-signup.ts
@@ -54518,15 +54929,6 @@ const teamMembersManifest = createBlockManifest({
54518
54929
  stack: [when("content._effectiveLook", { not: true })(stackVariant), when("content._effectiveLook")(cardListVariant)],
54519
54930
  ...Object.fromEntries(arrangementOnlyKeys.map((key) => [key, cardListVariant]))
54520
54931
  },
54521
- arrangementOwnedFieldIds: [
54522
- "layoutWidth",
54523
- "thumbnailShape",
54524
- "thumbnailPadding",
54525
- "imageColSize",
54526
- "stackImagePosition",
54527
- "stackContentAlignment",
54528
- "gap"
54529
- ],
54530
54932
  variantMeaning: {
54531
54933
  kind: "arrangement",
54532
54934
  lookOnlyKeys: [...arrangementOnlyKeys]
@@ -54980,21 +55382,21 @@ const locationMapManifest = createBlockManifest({
54980
55382
  type: "boolean",
54981
55383
  label: "Show opening hours",
54982
55384
  defaultValue: true,
54983
- ui: { intent: "display" }
55385
+ ui: { intent: "behavior" }
54984
55386
  }),
54985
55387
  parseFieldDefinition({
54986
55388
  id: "showAddressText",
54987
55389
  type: "boolean",
54988
55390
  label: "Show the address",
54989
55391
  defaultValue: true,
54990
- ui: { intent: "display" }
55392
+ ui: { intent: "behavior" }
54991
55393
  }),
54992
55394
  parseFieldDefinition({
54993
55395
  id: "showDirections",
54994
55396
  type: "boolean",
54995
55397
  label: "Show directions button",
54996
55398
  defaultValue: true,
54997
- ui: { intent: "display" }
55399
+ ui: { intent: "behavior" }
54998
55400
  }),
54999
55401
  parseFieldDefinition({
55000
55402
  id: "directionsLabel",
@@ -55003,7 +55405,7 @@ const locationMapManifest = createBlockManifest({
55003
55405
  defaultValue: LOCATION_MAP_DEFAULTS.directionsLabel,
55004
55406
  maxLength: 60,
55005
55407
  ui: {
55006
- intent: "display",
55408
+ intent: "behavior",
55007
55409
  visibleWhen: {
55008
55410
  field: "showDirections",
55009
55411
  equals: true
@@ -55015,7 +55417,7 @@ const locationMapManifest = createBlockManifest({
55015
55417
  type: "boolean",
55016
55418
  label: "Show a wider area",
55017
55419
  defaultValue: false,
55018
- ui: { intent: "display" }
55420
+ ui: { intent: "behavior" }
55019
55421
  }),
55020
55422
  parseFieldDefinition({
55021
55423
  id: "googleMapsLabel",
@@ -55023,7 +55425,7 @@ const locationMapManifest = createBlockManifest({
55023
55425
  label: "Google Maps button label",
55024
55426
  defaultValue: "Open in Google Maps",
55025
55427
  maxLength: 60,
55026
- ui: { intent: "display" }
55428
+ ui: { intent: "behavior" }
55027
55429
  }),
55028
55430
  parseFieldDefinition({
55029
55431
  id: "heightPx",
@@ -55945,230 +56347,6 @@ function clearBlockDefinitions() {
55945
56347
  resetSystemBlockDefinitionRegistration();
55946
56348
  }
55947
56349
 
55948
- //#endregion
55949
- //#region ../blocks/src/system/manifest/storedLayout.ts
55950
- /** The content field `parseStoredVariant` also reads; a block without stored variants keeps its layout there. */
55951
- const layoutFieldId = "layout";
55952
- function storedVariantKeys(manifest) {
55953
- const lookOnly = manifest.variantMeaning.lookOnlyKeys ?? [];
55954
- return Object.keys(manifest.variants ?? {}).filter((key) => !lookOnly.includes(key));
55955
- }
55956
- function optionValues(options) {
55957
- return Array.isArray(options) ? options.flatMap((option) => typeof option === "object" && option !== null && "value" in option && typeof option.value === "string" ? [option.value] : []) : [];
55958
- }
55959
- /**
55960
- * A block with no stored variants that offers a `layout` select (the shop)
55961
- * declares its layouts there. Read as a mode's arrangement declaration, so the
55962
- * same resolver decides: a stored value the block still has, or the default.
55963
- */
55964
- function layoutFieldDeclaration(manifest) {
55965
- const field = (manifest.fields ?? []).find((candidate) => typeof candidate === "object" && candidate !== null && "id" in candidate && candidate.id === layoutFieldId && "type" in candidate && candidate.type === "select");
55966
- const keys = optionValues(field?.options);
55967
- const [firstKey] = keys;
55968
- if (field === undefined || firstKey === undefined) return null;
55969
- return {
55970
- arrangementField: layoutFieldId,
55971
- keys,
55972
- defaultKey: typeof field.defaultValue === "string" && keys.includes(field.defaultValue) ? field.defaultValue : firstKey
55973
- };
55974
- }
55975
- function fieldDeclaration(manifest) {
55976
- if (manifest.variantMeaning.kind === "mode") return manifest.variantMeaning;
55977
- return storedVariantKeys(manifest).length === 0 ? layoutFieldDeclaration(manifest) : null;
55978
- }
55979
- /** Every layout a block can store, for the block's own layout axis. Look-only arrangements are never stored. */
55980
- function storedLayoutKeys(manifest) {
55981
- return fieldDeclaration(manifest)?.keys ?? storedVariantKeys(manifest);
55982
- }
55983
- /**
55984
- * The layout a block renders by when no Look arranges it: the stored value if
55985
- * the block still has it, otherwise the default. The renderer's own resolvers
55986
- * decide, so a reader of stored layouts cannot disagree with the page.
55987
- */
55988
- function resolveStoredLayout(manifest, content) {
55989
- const field = fieldDeclaration(manifest);
55990
- return field === null ? resolveEffectiveArrangement({
55991
- manifest: arrangementManifestFromVariants(manifest),
55992
- storedVariant: parseStoredVariant(manifest, content)
55993
- }).key : resolveModeArrangement({
55994
- declaration: field,
55995
- content,
55996
- mode: null
55997
- }).key;
55998
- }
55999
-
56000
- //#endregion
56001
- //#region ../blocks/src/system/data/selectBlockContent.ts
56002
- /** Canonical admitted content: legacy publishedContent never selects a version. */
56003
- function selectBlockContent(block, stage = "published") {
56004
- const source = stage === "preview" && block.draftContent ? block.draftContent : block.content;
56005
- return isObjectRecord(source) ? stripStaleTransitionStyleGroup(source) : {};
56006
- }
56007
-
56008
- //#endregion
56009
- //#region ../blocks/src/system/data/readinessPresentation.ts
56010
- /** Presentation-only wording; domain assessments and tests use closed reason codes. */
56011
- const READINESS_REASON_COPY = {
56012
- mailing_destination: "Pick where sign-ups go. Until you do, this signup stays hidden from visitors.",
56013
- mailing_setup: "Pick where sign-ups go. Until you do, this signup stays hidden from visitors.",
56014
- form_not_chosen: "Choose a form. Until you do, this block stays hidden from visitors.",
56015
- form_deleted: "The form this block used has been deleted. Choose another one. Until you do, this block stays hidden from visitors.",
56016
- testimonials_none: "Add a testimonial to show here. Until you do, this block stays hidden from visitors.",
56017
- testimonials_unpublished: "Publish a testimonial to show it here. Until you do, this block stays hidden from visitors.",
56018
- testimonials_empty: "There are no testimonials to show here yet. Until there are, this block stays hidden from visitors.",
56019
- team_empty: "Add people to your team to show them here. Until you do, this block stays hidden from visitors.",
56020
- members_empty: "Add someone to show here. Until you do, this block stays hidden from visitors.",
56021
- product_not_chosen: "Choose a product. Until you do, this block stays hidden from visitors.",
56022
- product_gone: "The product this block showed is no longer available. Choose another one. Until you do, this block stays hidden from visitors.",
56023
- gallery_empty: "Add a photo. Until you do, this gallery stays hidden from visitors."
56024
- };
56025
-
56026
- //#endregion
56027
- //#region ../blocks/src/system/data/readinessFacts.ts
56028
- const countSchema = z.array(z.unknown()).transform((entries) => entries.length);
56029
- const formSchema = z.union([z.null(), z.object({
56030
- id: z.string(),
56031
- slug: z.string().optional()
56032
- })]).transform((form$1) => form$1 !== null);
56033
- const productsSchema = z.object({ products: z.array(z.object({ slug: z.string() })) });
56034
- /** Both producers pass raw facts through the same stage admission. */
56035
- function readinessFactsFromLoaders(stage, input) {
56036
- const facts = {
56037
- mailingList: loaderFactProducers.mailingList(input),
56038
- testimonials: loaderFactProducers.testimonials(input),
56039
- team: loaderFactProducers.team(input),
56040
- forms: loaderFactProducers.forms(input),
56041
- products: loaderFactProducers.products(input),
56042
- template: loaderFactProducers.template(input)
56043
- };
56044
- return admitReadinessFacts(stage, {
56045
- stage: input.prefetched?.loaderSnapshot?.stage ?? (input.previewStage === "preview" ? "draft" : "published"),
56046
- facts
56047
- });
56048
- }
56049
- const loaderFactProducers = {
56050
- mailingList: (input) => input.mailingList === undefined ? unavailableReadinessFact : loadedReadinessFact(input.mailingList),
56051
- testimonials: (input) => mapFact(firstLoaderFact(input, "testimonials", "entries", countSchema), (count) => ({
56052
- count,
56053
- total: "unknown"
56054
- })),
56055
- team: (input) => firstLoaderFact(input, "team", "members", countSchema),
56056
- forms: (input) => new Map(projections(input, "forms").flatMap(({ id, block }) => {
56057
- const selection = chosenString(block.requests.form?.params.formSlug ?? block.requests.form?.params.formId);
56058
- return selection ? [[selection, loaderFact(input, id, "form", formSchema)]] : [];
56059
- })),
56060
- products: (input) => new Map(projections(input, "products").flatMap(({ id, block }) => {
56061
- const selection = chosenString(block.content.productSlug);
56062
- return selection ? [[selection, mapFact(loaderFact(input, id, "products", productsSchema), ({ products }) => products.some((product) => product.slug === selection))]] : [];
56063
- })),
56064
- template: (input) => loadedReadinessFact(input.template)
56065
- };
56066
- function projections(input, need) {
56067
- return Object.entries(input.prefetched?.loaderSnapshot?.blocks ?? {}).flatMap(([id, block]) => getBlockDefinition(block.kind)?.readiness?.needs.includes(need) ? [{
56068
- id,
56069
- block
56070
- }] : []);
56071
- }
56072
- function firstLoaderFact(input, need, key, schema) {
56073
- const source = projections(input, need)[0];
56074
- return source ? loaderFact(input, source.id, key, schema) : unavailableReadinessFact;
56075
- }
56076
- function loaderFact(input, id, key, schema) {
56077
- const prefetched = input.prefetched;
56078
- if (!prefetched) return unavailableReadinessFact;
56079
- if (!prefetched.loaderSnapshot.blocks[id]?.requests[key] || prefetched.loaderFailures[id]?.[key]) return unavailableReadinessFact;
56080
- const parsed = schema.safeParse(prefetched.resolvedData[id]?.[key]);
56081
- return parsed.success ? loadedReadinessFact(parsed.data) : unavailableReadinessFact;
56082
- }
56083
- function mapFact(fact, project) {
56084
- return fact.kind === "Loaded" ? loadedReadinessFact(project(fact.value)) : fact;
56085
- }
56086
-
56087
- //#endregion
56088
- //#region ../blocks/src/system/data/pageReadiness.ts
56089
- function assessPageReadiness(blocks, facts) {
56090
- return blocks.map((block) => ({
56091
- blockId: block.id,
56092
- readiness: getBlockDefinition(block.kind)?.readiness?.assess(selectBlockContent(block, "preview"), facts) ?? ready
56093
- }));
56094
- }
56095
- const PUBLISH_READINESS_COPY = {
56096
- title: "Some blocks aren't set up yet",
56097
- body: "These won't show on your live site until they're set up:",
56098
- publish: "Publish anyway",
56099
- cancel: "Not yet",
56100
- repair: "Set up"
56101
- };
56102
- function publishReadinessWarning(blocks, facts) {
56103
- return assessPageReadiness(blocks, facts).flatMap(({ blockId, readiness }) => readiness.kind === "NeedsSetup" ? [{
56104
- blockId,
56105
- ...readiness
56106
- }] : []);
56107
- }
56108
- function declaredReadinessNeeds(blocks) {
56109
- return new Set(blocks.flatMap((block) => getBlockDefinition(block.kind)?.readiness?.needs ?? []));
56110
- }
56111
- function publishedReadinessFactsPayload(facts) {
56112
- return {
56113
- ...facts,
56114
- stage: "published",
56115
- forms: [...facts.forms],
56116
- products: [...facts.products]
56117
- };
56118
- }
56119
- function readinessFactsFromPayload(stage, payload) {
56120
- return admitReadinessFacts(stage, {
56121
- stage: payload.stage,
56122
- facts: {
56123
- ...payload,
56124
- forms: new Map(payload.forms),
56125
- products: new Map(payload.products)
56126
- }
56127
- });
56128
- }
56129
-
56130
- //#endregion
56131
- //#region ../blocks/src/pageRenderAdmission.ts
56132
- function toPresentationPage(page) {
56133
- if (!page) return null;
56134
- return {
56135
- ...page,
56136
- blocks: page.blocks.map((block) => {
56137
- const presentationMetadata = {
56138
- id: block.id,
56139
- kind: block.kind,
56140
- purpose: block.purpose,
56141
- ...block.contentVersionId ? { contentVersionId: block.contentVersionId } : {},
56142
- ...block.draftContentId !== undefined ? { draftContentId: block.draftContentId } : {},
56143
- publishedPlacement: block.publishedPlacement,
56144
- ...block.bindings ? { bindings: block.bindings } : {}
56145
- };
56146
- return block.admission.kind === "renderable" ? {
56147
- ...presentationMetadata,
56148
- content: block.admission.content,
56149
- presentationAdmission: { kind: "renderable" }
56150
- } : {
56151
- ...presentationMetadata,
56152
- presentationAdmission: {
56153
- kind: "invalid",
56154
- error: block.admission.error
56155
- }
56156
- };
56157
- })
56158
- };
56159
- }
56160
- function toEditorPresentationPage(page) {
56161
- if (!page) return null;
56162
- return {
56163
- ...page,
56164
- blocks: page.blocks.map((block) => ({
56165
- ...block,
56166
- publishedPlacement: block.publishedPlacement,
56167
- presentationAdmission: { kind: "editor" }
56168
- }))
56169
- };
56170
- }
56171
-
56172
56350
  //#endregion
56173
56351
  //#region ../blocks/src/system/customize/arrangementKnobs.ts
56174
56352
  /**
@@ -56320,6 +56498,20 @@ const onOff = [{
56320
56498
  value: "false",
56321
56499
  label: "Off"
56322
56500
  }];
56501
+ const columnCounts = [
56502
+ {
56503
+ value: "2",
56504
+ label: "2"
56505
+ },
56506
+ {
56507
+ value: "3",
56508
+ label: "3"
56509
+ },
56510
+ {
56511
+ value: "4",
56512
+ label: "4"
56513
+ }
56514
+ ];
56323
56515
  const systemCustomizeFacetDefinitions = [
56324
56516
  eventCalendarListLayoutFacet,
56325
56517
  fixedKnob("block.offerings-preview", "dates", "Dates", [{
@@ -56412,6 +56604,9 @@ const systemCustomizeFacetDefinitions = [
56412
56604
  ...fixedKnob("block.feature-cards", "showPhotos", "Show photos", onOff, "true", false, true),
56413
56605
  blockKinds: cardListFamilyBlocks
56414
56606
  },
56607
+ fixedKnob("block.feature-cards", "columns", "Columns", columnCounts, "3", true),
56608
+ fixedKnob("block.image-gallery", "blackAndWhite", "Black and white", onOff, "false", false, true),
56609
+ fixedKnob("block.event-calendar", "listColumns", "Columns", columnCounts, "3", true),
56415
56610
  fixedKnob("block.event-calendar", "showPhotos", "Photos", [{
56416
56611
  value: "true",
56417
56612
  label: "Show"
@@ -56574,6 +56769,392 @@ function omitRecordKey(content, key) {
56574
56769
  return Object.fromEntries(Object.entries(content).filter(([entryKey]) => entryKey !== key));
56575
56770
  }
56576
56771
 
56772
+ //#endregion
56773
+ //#region ../blocks/src/system/customize/fieldOwnership.ts
56774
+ /**
56775
+ * Values with their own owner, whatever their fields are tagged: the Background
56776
+ * row and Photo control edit `_sectionStyles`, and the style compiler writes the
56777
+ * other style groups (card, container and text-card styles), which the editor
56778
+ * already hides on styles with a page design.
56779
+ */
56780
+ const dedicatedPaths = ["_sectionStyles", ...themeV2CompilerOwnedFieldNames];
56781
+ /**
56782
+ * One owner for "does this setting belong to the Look?". The editor form, the
56783
+ * renderer's bindings, publish validation and the catalogue all ask here.
56784
+ * With no arrangement Look resolved (older styles, recipes, blocks without
56785
+ * Looks on a newer style), every field stays with the owner.
56786
+ */
56787
+ function resolveFieldOwnership(input) {
56788
+ if (!input.arrangementLook) return { kind: "no-look" };
56789
+ const knobFields = new Set(systemCustomizeFacetDefinitionsForBlock(input.blockKind).flatMap((facet) => facet.knob && facet.target.kind === "content-field" ? [facet.target.field] : []));
56790
+ const meaning = input.manifest.variantMeaning;
56791
+ const arrangementField = meaning?.kind === "mode" ? meaning.arrangementField : meaning ? "variant" : null;
56792
+ const modeField = meaning?.kind === "mode" ? "variant" : null;
56793
+ const paths = new Map();
56794
+ const dataPaths = new Map();
56795
+ const visit = (fields$1, parent, inherited, inRepeaterItem = false) => {
56796
+ fields$1.forEach((field) => {
56797
+ const path$3 = parent.schema ? `${parent.schema}.${field.id}` : field.id;
56798
+ const flattened = inRepeaterItem && field.type === "group" && field.ui?.flattenInRepeater === true;
56799
+ const dataPath = flattened ? parent.data : parent.data ? `${parent.data}.${field.id}` : field.id;
56800
+ const owner = ownerOf(field, path$3, inherited, {
56801
+ knobFields,
56802
+ arrangementField,
56803
+ modeField
56804
+ });
56805
+ paths.set(path$3, owner);
56806
+ if (!flattened) dataPaths.set(dataPath, owner);
56807
+ childFields(field).forEach((children) => visit(children, {
56808
+ schema: path$3,
56809
+ data: dataPath
56810
+ }, owner, field.type === "repeater"));
56811
+ });
56812
+ };
56813
+ visit(input.manifest.fields ?? [], {
56814
+ schema: "",
56815
+ data: ""
56816
+ }, "owner");
56817
+ knobFields.forEach((field) => {
56818
+ if (!paths.has(field)) paths.set(field, "knob");
56819
+ if (!dataPaths.has(field)) dataPaths.set(field, "knob");
56820
+ });
56821
+ return {
56822
+ kind: "look",
56823
+ paths,
56824
+ dataPaths
56825
+ };
56826
+ }
56827
+ const blocksWithLooks = new Set(arrangementAppearancePresets.flatMap((preset) => preset.blockKinds));
56828
+ /**
56829
+ * Whether any style can show this block through an arrangement Look. Docs and
56830
+ * the catalogue, which describe a block rather than one placed on a page, use
56831
+ * it to say which fields a Look would take over.
56832
+ */
56833
+ function blockHasArrangementLooks(blockKind) {
56834
+ return blocksWithLooks.has(blockKind);
56835
+ }
56836
+ /** A stored content path's owner; item indices are ignored and unlisted descendants take their parent's. */
56837
+ function fieldOwnerAt(ownership, path$3) {
56838
+ if (ownership.kind === "no-look") return "owner";
56839
+ const segments = path$3.split(".").filter((segment) => !/^\d+$/u.test(segment));
56840
+ const innermostFirst = segments.map((_$1, index) => segments.slice(0, segments.length - index).join("."));
56841
+ return innermostFirst.map((prefix) => ownership.dataPaths.get(prefix)).find((owner) => owner !== undefined) ?? "owner";
56842
+ }
56843
+ /** Schema paths with a given owner, outermost first, without repeating covered descendants. */
56844
+ function fieldPathsOwnedBy(ownership, owners) {
56845
+ return ownership.kind === "no-look" ? [] : outermost(ownership.paths, owners);
56846
+ }
56847
+ /** Content paths with a given owner, for the renderer, outermost first. */
56848
+ function contentPathsOwnedBy(ownership, owners) {
56849
+ return ownership.kind === "no-look" ? [] : outermost(ownership.dataPaths, owners);
56850
+ }
56851
+ function outermost(paths, owners) {
56852
+ const matching = [...paths].filter(([, owner]) => owners.includes(owner)).map(([path$3]) => path$3);
56853
+ return matching.filter((path$3) => !matching.some((other) => path$3.startsWith(`${other}.`)));
56854
+ }
56855
+ /**
56856
+ * Content with the owner's values for Look-owned paths taken out, so nothing
56857
+ * that renders the block (bindings, views, media delivery) can read them.
56858
+ */
56859
+ function withoutLookOwnedContent(content, paths) {
56860
+ return paths.reduce((current, path$3) => withoutPath(current, path$3.split(".")), { ...content });
56861
+ }
56862
+ function withoutPath(value, [key, ...rest]) {
56863
+ if (key === undefined || !(key in value)) return { ...value };
56864
+ if (rest.length === 0) return Object.fromEntries(Object.entries(value).filter(([entry]) => entry !== key));
56865
+ const child = value[key];
56866
+ const stripped = Array.isArray(child) ? child.map((item) => isContentRecord(item) ? withoutPath(item, rest) : item) : isContentRecord(child) ? withoutPath(child, rest) : child;
56867
+ return {
56868
+ ...value,
56869
+ [key]: stripped
56870
+ };
56871
+ }
56872
+ function isContentRecord(value) {
56873
+ return typeof value === "object" && value !== null && !Array.isArray(value);
56874
+ }
56875
+ function ownerOf(field, path$3, inherited, facts) {
56876
+ return inheritedOwner(path$3, inherited) ?? lookSectionOwner(field, path$3, facts) ?? keptByOwner(field, path$3, facts) ?? intentOwner(field, inherited);
56877
+ }
56878
+ /** Below a dedicated or Look-owned container, everything goes with it. */
56879
+ function inheritedOwner(path$3, inherited) {
56880
+ if (inherited === "dedicated" || dedicatedPaths.includes(path$3)) return "dedicated";
56881
+ return inherited === "look" ? "look" : null;
56882
+ }
56883
+ function lookSectionOwner(field, path$3, facts) {
56884
+ if (!path$3.includes(".") && facts.knobFields.has(path$3)) return "knob";
56885
+ if (field.ui?.hidden === true || field.ui?.renderInHeader === true) return "dedicated";
56886
+ return path$3 === facts.arrangementField ? "arrangement" : null;
56887
+ }
56888
+ function keptByOwner(field, path$3, facts) {
56889
+ return path$3 === facts.modeField || field.ui?.underLooks === "owner" ? "owner" : null;
56890
+ }
56891
+ function intentOwner(field, inherited) {
56892
+ switch (field.ui?.intent) {
56893
+ case "display":
56894
+ case "style": return "look";
56895
+ case "content":
56896
+ case "behavior": return "owner";
56897
+ case undefined: return inherited;
56898
+ }
56899
+ }
56900
+ function childFields(field) {
56901
+ if (field.type === "group" || field.type === "modal") return [field.schema.fields];
56902
+ if (field.type === "repeater") return [field.schema?.fields ?? [], ...Object.values(field.itemTypes ?? {}).map((item) => item.fields)];
56903
+ if (field.type === "tabGroup") return field.tabs.map((tab) => tab.fields);
56904
+ return [];
56905
+ }
56906
+
56907
+ //#endregion
56908
+ //#region ../blocks/src/system/manifest/storedLayout.ts
56909
+ /** The content field `parseStoredVariant` also reads; a block without stored variants keeps its layout there. */
56910
+ const layoutFieldId = "layout";
56911
+ function storedVariantKeys(manifest) {
56912
+ const lookOnly = manifest.variantMeaning.lookOnlyKeys ?? [];
56913
+ return Object.keys(manifest.variants ?? {}).filter((key) => !lookOnly.includes(key));
56914
+ }
56915
+ function optionValues(options) {
56916
+ return Array.isArray(options) ? options.flatMap((option) => typeof option === "object" && option !== null && "value" in option && typeof option.value === "string" ? [option.value] : []) : [];
56917
+ }
56918
+ /**
56919
+ * A block with no stored variants that offers a `layout` select (the shop)
56920
+ * declares its layouts there. Read as a mode's arrangement declaration, so the
56921
+ * same resolver decides: a stored value the block still has, or the default.
56922
+ */
56923
+ function layoutFieldDeclaration(manifest) {
56924
+ const field = (manifest.fields ?? []).find((candidate) => typeof candidate === "object" && candidate !== null && "id" in candidate && candidate.id === layoutFieldId && "type" in candidate && candidate.type === "select");
56925
+ const keys = optionValues(field?.options);
56926
+ const [firstKey] = keys;
56927
+ if (field === undefined || firstKey === undefined) return null;
56928
+ return {
56929
+ arrangementField: layoutFieldId,
56930
+ keys,
56931
+ defaultKey: typeof field.defaultValue === "string" && keys.includes(field.defaultValue) ? field.defaultValue : firstKey
56932
+ };
56933
+ }
56934
+ function fieldDeclaration(manifest) {
56935
+ if (manifest.variantMeaning.kind === "mode") return manifest.variantMeaning;
56936
+ return storedVariantKeys(manifest).length === 0 ? layoutFieldDeclaration(manifest) : null;
56937
+ }
56938
+ /** Every layout a block can store, for the block's own layout axis. Look-only arrangements are never stored. */
56939
+ function storedLayoutKeys(manifest) {
56940
+ return fieldDeclaration(manifest)?.keys ?? storedVariantKeys(manifest);
56941
+ }
56942
+ /**
56943
+ * The layout a block renders by when no Look arranges it: the stored value if
56944
+ * the block still has it, otherwise the default. The renderer's own resolvers
56945
+ * decide, so a reader of stored layouts cannot disagree with the page.
56946
+ */
56947
+ function resolveStoredLayout(manifest, content) {
56948
+ const field = fieldDeclaration(manifest);
56949
+ return field === null ? resolveEffectiveArrangement({
56950
+ manifest: arrangementManifestFromVariants(manifest),
56951
+ storedVariant: parseStoredVariant(manifest, content)
56952
+ }).key : resolveModeArrangement({
56953
+ declaration: field,
56954
+ content,
56955
+ mode: null
56956
+ }).key;
56957
+ }
56958
+
56959
+ //#endregion
56960
+ //#region ../blocks/src/system/data/selectBlockContent.ts
56961
+ /** Canonical admitted content: legacy publishedContent never selects a version. */
56962
+ function selectBlockContent(block, stage = "published") {
56963
+ const source = stage === "preview" && block.draftContent ? block.draftContent : block.content;
56964
+ return isObjectRecord(source) ? stripStaleTransitionStyleGroup(source) : {};
56965
+ }
56966
+
56967
+ //#endregion
56968
+ //#region ../blocks/src/system/data/readinessPresentation.ts
56969
+ /** Presentation-only wording; domain assessments and tests use closed reason codes. */
56970
+ const READINESS_REASON_COPY = {
56971
+ mailing_destination: "Pick where sign-ups go. Until you do, this signup stays hidden from visitors.",
56972
+ mailing_setup: "Pick where sign-ups go. Until you do, this signup stays hidden from visitors.",
56973
+ form_not_chosen: "Choose a form. Until you do, this block stays hidden from visitors.",
56974
+ form_deleted: "The form this block used has been deleted. Choose another one. Until you do, this block stays hidden from visitors.",
56975
+ testimonials_none: "Add a testimonial to show here. Until you do, this block stays hidden from visitors.",
56976
+ testimonials_unpublished: "Publish a testimonial to show it here. Until you do, this block stays hidden from visitors.",
56977
+ testimonials_empty: "There are no testimonials to show here yet. Until there are, this block stays hidden from visitors.",
56978
+ team_empty: "Add people to your team to show them here. Until you do, this block stays hidden from visitors.",
56979
+ members_empty: "Add someone to show here. Until you do, this block stays hidden from visitors.",
56980
+ product_not_chosen: "Choose a product. Until you do, this block stays hidden from visitors.",
56981
+ product_gone: "The product this block showed is no longer available. Choose another one. Until you do, this block stays hidden from visitors.",
56982
+ gallery_empty: "Add a photo. Until you do, this gallery stays hidden from visitors."
56983
+ };
56984
+
56985
+ //#endregion
56986
+ //#region ../blocks/src/system/data/readinessFacts.ts
56987
+ const countSchema = z.array(z.unknown()).transform((entries) => entries.length);
56988
+ const formSchema = z.union([z.null(), z.object({
56989
+ id: z.string(),
56990
+ slug: z.string().optional()
56991
+ })]).transform((form$1) => form$1 !== null);
56992
+ const productsSchema = z.object({ products: z.array(z.object({ slug: z.string() })) });
56993
+ /** Both producers pass raw facts through the same stage admission. */
56994
+ function readinessFactsFromLoaders(stage, input) {
56995
+ const facts = {
56996
+ mailingList: loaderFactProducers.mailingList(input),
56997
+ testimonials: loaderFactProducers.testimonials(input),
56998
+ team: loaderFactProducers.team(input),
56999
+ forms: loaderFactProducers.forms(input),
57000
+ products: loaderFactProducers.products(input),
57001
+ template: loaderFactProducers.template(input)
57002
+ };
57003
+ return admitReadinessFacts(stage, {
57004
+ stage: input.prefetched?.loaderSnapshot?.stage ?? (input.previewStage === "preview" ? "draft" : "published"),
57005
+ facts
57006
+ });
57007
+ }
57008
+ const loaderFactProducers = {
57009
+ mailingList: (input) => input.mailingList === undefined ? unavailableReadinessFact : loadedReadinessFact(input.mailingList),
57010
+ testimonials: (input) => mapFact(firstLoaderFact(input, "testimonials", "entries", countSchema), (count) => ({
57011
+ count,
57012
+ total: "unknown"
57013
+ })),
57014
+ team: (input) => firstLoaderFact(input, "team", "members", countSchema),
57015
+ forms: (input) => new Map(projections(input, "forms").flatMap(({ id, block }) => {
57016
+ const selection = chosenString(block.requests.form?.params.formSlug ?? block.requests.form?.params.formId);
57017
+ return selection ? [[selection, loaderFact(input, id, "form", formSchema)]] : [];
57018
+ })),
57019
+ products: (input) => new Map(projections(input, "products").flatMap(({ id, block }) => {
57020
+ const selection = chosenString(block.content.productSlug);
57021
+ return selection ? [[selection, mapFact(loaderFact(input, id, "products", productsSchema), ({ products }) => products.some((product) => product.slug === selection))]] : [];
57022
+ })),
57023
+ template: (input) => loadedReadinessFact(input.template)
57024
+ };
57025
+ function projections(input, need) {
57026
+ return Object.entries(input.prefetched?.loaderSnapshot?.blocks ?? {}).flatMap(([id, block]) => getBlockDefinition(block.kind)?.readiness?.needs.includes(need) ? [{
57027
+ id,
57028
+ block
57029
+ }] : []);
57030
+ }
57031
+ function firstLoaderFact(input, need, key, schema) {
57032
+ const source = projections(input, need)[0];
57033
+ return source ? loaderFact(input, source.id, key, schema) : unavailableReadinessFact;
57034
+ }
57035
+ function loaderFact(input, id, key, schema) {
57036
+ const prefetched = input.prefetched;
57037
+ if (!prefetched) return unavailableReadinessFact;
57038
+ if (!prefetched.loaderSnapshot.blocks[id]?.requests[key] || prefetched.loaderFailures[id]?.[key]) return unavailableReadinessFact;
57039
+ const parsed = schema.safeParse(prefetched.resolvedData[id]?.[key]);
57040
+ return parsed.success ? loadedReadinessFact(parsed.data) : unavailableReadinessFact;
57041
+ }
57042
+ function mapFact(fact, project) {
57043
+ return fact.kind === "Loaded" ? loadedReadinessFact(project(fact.value)) : fact;
57044
+ }
57045
+
57046
+ //#endregion
57047
+ //#region ../blocks/src/system/data/pageReadiness.ts
57048
+ function assessPageReadiness(blocks, facts, interaction) {
57049
+ return blocks.map((block) => ({
57050
+ blockId: block.id,
57051
+ readiness: getBlockDefinition(block.kind)?.readiness?.assess(selectBlockContent(block, "preview"), facts, interaction) ?? ready
57052
+ }));
57053
+ }
57054
+ const PUBLISH_READINESS_COPY = {
57055
+ title: "Some blocks aren't set up yet",
57056
+ body: "These won't show on your live site until they're set up:",
57057
+ publish: "Publish anyway",
57058
+ cancel: "Not yet",
57059
+ repair: "Set up"
57060
+ };
57061
+ function publishReadinessWarning(blocks, facts) {
57062
+ return assessPageReadiness(blocks, facts).flatMap(({ blockId, readiness }) => readiness.kind === "NeedsSetup" ? [{
57063
+ blockId,
57064
+ ...readiness
57065
+ }] : []);
57066
+ }
57067
+ function declaredReadinessNeeds(blocks) {
57068
+ return new Set(blocks.flatMap((block) => getBlockDefinition(block.kind)?.readiness?.needs ?? []));
57069
+ }
57070
+ function publishedReadinessFactsPayload(facts) {
57071
+ return {
57072
+ ...facts,
57073
+ stage: "published",
57074
+ forms: [...facts.forms],
57075
+ products: [...facts.products]
57076
+ };
57077
+ }
57078
+ function readinessFactsFromPayload(stage, payload) {
57079
+ return admitReadinessFacts(stage, {
57080
+ stage: payload.stage,
57081
+ facts: {
57082
+ ...payload,
57083
+ forms: new Map(payload.forms),
57084
+ products: new Map(payload.products)
57085
+ }
57086
+ });
57087
+ }
57088
+
57089
+ //#endregion
57090
+ //#region ../blocks/src/pageRenderAdmission.ts
57091
+ function toPresentationPage(page) {
57092
+ if (!page) return null;
57093
+ return {
57094
+ ...page,
57095
+ blocks: page.blocks.map(presentPublicBlock)
57096
+ };
57097
+ }
57098
+ function toEditorPresentationPage(page) {
57099
+ if (!page) return null;
57100
+ return {
57101
+ ...page,
57102
+ blocks: page.blocks.map(presentEditorBlock)
57103
+ };
57104
+ }
57105
+ function presentPublicBlock(block) {
57106
+ const metadata = {
57107
+ id: block.id,
57108
+ kind: block.kind,
57109
+ purpose: block.purpose,
57110
+ ...block.contentVersionId ? { contentVersionId: block.contentVersionId } : {},
57111
+ ...block.draftContentId !== undefined ? { draftContentId: block.draftContentId } : {},
57112
+ publishedPlacement: block.publishedPlacement,
57113
+ ...block.bindings ? { bindings: block.bindings } : {}
57114
+ };
57115
+ return block.admission.kind === "renderable" ? {
57116
+ ...metadata,
57117
+ content: block.admission.content,
57118
+ presentationAdmission: { kind: "renderable" }
57119
+ } : {
57120
+ ...metadata,
57121
+ presentationAdmission: {
57122
+ kind: "invalid",
57123
+ error: block.admission.error
57124
+ }
57125
+ };
57126
+ }
57127
+ function presentEditorBlock(block) {
57128
+ return {
57129
+ ...block,
57130
+ presentationAdmission: { kind: "editor" }
57131
+ };
57132
+ }
57133
+ function createPresentationPageReader() {
57134
+ const readBlock = memoizePresentationBlock(presentPublicBlock);
57135
+ return (page) => page ? {
57136
+ ...page,
57137
+ blocks: page.blocks.map(readBlock)
57138
+ } : null;
57139
+ }
57140
+ function createEditorPresentationPageReader() {
57141
+ const readBlock = memoizePresentationBlock(presentEditorBlock);
57142
+ return (page) => page ? {
57143
+ ...page,
57144
+ blocks: page.blocks.map(readBlock)
57145
+ } : null;
57146
+ }
57147
+ function memoizePresentationBlock(present) {
57148
+ const blocks = new WeakMap();
57149
+ return (block) => {
57150
+ const cached = blocks.get(block);
57151
+ if (cached) return cached;
57152
+ const presentation = present(block);
57153
+ blocks.set(block, presentation);
57154
+ return presentation;
57155
+ };
57156
+ }
57157
+
56577
57158
  //#endregion
56578
57159
  //#region ../blocks/src/system/transforms/registry/offeringsPreview.ts
56579
57160
  /** Reuse the existing occurrence read for the date strip and card date rows. */
@@ -57282,7 +57863,10 @@ function coerceLinkedContentEntriesPayload(payload) {
57282
57863
  function getLinkedContentEntryMeta(value) {
57283
57864
  if (!isRecord$17(value)) return null;
57284
57865
  const candidate = value[LINKED_CONTENT_ENTRY_META_KEY];
57285
- return isLinkedContentEntryMeta(candidate) ? candidate : null;
57866
+ return isLinkedContentEntryMeta(candidate) ? {
57867
+ ...candidate,
57868
+ editRevision: candidate.editRevision ?? null
57869
+ } : null;
57286
57870
  }
57287
57871
  function buildLinkedContentEditTarget(input) {
57288
57872
  const { entry, sourceBlockId, sourceBlockKind, itemIndex } = input;
@@ -57297,6 +57881,7 @@ function buildLinkedContentEditTarget(input) {
57297
57881
  contentTypeLabel: meta.contentTypeLabel,
57298
57882
  title: meta.title,
57299
57883
  optimisticHash: meta.optimisticHash,
57884
+ editRevision: meta.editRevision,
57300
57885
  sourceBlockId: sourceBlockId ?? null,
57301
57886
  sourceBlockKind: sourceBlockKind ?? null,
57302
57887
  itemIndex,
@@ -57369,6 +57954,7 @@ function enrichLinkedContentEntry(entry, contentType) {
57369
57954
  const title = typeof entry.title === "string" && entry.title.trim().length > 0 ? entry.title : entryId;
57370
57955
  const optimisticHash = typeof entry.optimisticHash === "string" && entry.optimisticHash.length > 0 ? entry.optimisticHash : null;
57371
57956
  const content = isRecord$17(entry.content) ? entry.content : {};
57957
+ const editRevision = typeof entry.editRevision === "number" ? entry.editRevision : null;
57372
57958
  const meta = {
57373
57959
  kind: "linked-content-entry",
57374
57960
  entryId,
@@ -57376,6 +57962,7 @@ function enrichLinkedContentEntry(entry, contentType) {
57376
57962
  contentTypeLabel: contentTypeKeyToLabel(contentType.key),
57377
57963
  title,
57378
57964
  optimisticHash,
57965
+ editRevision,
57379
57966
  support: resolveLinkedContentEditSupport(contentType),
57380
57967
  contentType,
57381
57968
  fieldSources: deriveLinkedEntryFieldSources(entry, contentType, content)
@@ -57513,16 +58100,23 @@ function parseStringArray(value) {
57513
58100
  return value.filter((item) => typeof item === "string");
57514
58101
  }
57515
58102
  function isLinkedContentEntryMeta(value) {
57516
- if (!isRecord$17(value)) return false;
57517
- if (value.kind !== "linked-content-entry") return false;
57518
- if (typeof value.entryId !== "string") return false;
57519
- if (typeof value.contentTypeKey !== "string") return false;
57520
- if (typeof value.contentTypeLabel !== "string") return false;
57521
- if (typeof value.title !== "string") return false;
57522
- if (!(value.optimisticHash === null || typeof value.optimisticHash === "string")) return false;
57523
- if (!isRecord$17(value.contentType)) return false;
57524
- if (!isLinkedEntryFieldSourceArray(value.fieldSources)) return false;
57525
- return isLinkedContentEditSupport(value.support);
58103
+ if (!isRecord$17(value) || value.kind !== "linked-content-entry") return false;
58104
+ return [
58105
+ [
58106
+ "entryId",
58107
+ "contentTypeKey",
58108
+ "contentTypeLabel",
58109
+ "title"
58110
+ ].every((key) => typeof value[key] === "string"),
58111
+ isNullOrOfType(value.optimisticHash, "string"),
58112
+ value.editRevision === undefined || isNullOrOfType(value.editRevision, "number"),
58113
+ isRecord$17(value.contentType),
58114
+ isLinkedEntryFieldSourceArray(value.fieldSources),
58115
+ isLinkedContentEditSupport(value.support)
58116
+ ].every(Boolean);
58117
+ }
58118
+ function isNullOrOfType(value, type) {
58119
+ return value === null || typeof value === type;
57526
58120
  }
57527
58121
  function isLinkedEntryFieldSourceArray(value) {
57528
58122
  return Array.isArray(value) && value.every(isLinkedEntryFieldSource);
@@ -57955,6 +58549,30 @@ function toAbsolutePath(base, path$3) {
57955
58549
  const baseStr = base.endsWith(".") ? base : `${base}.`;
57956
58550
  return `${baseStr}${trimmed}`;
57957
58551
  }
58552
+ /** Copy only the path being changed; existing setters remain for explicitly mutable adapters. */
58553
+ function withValueAtPath(target, path$3, value) {
58554
+ const segments = parsePath(path$3);
58555
+ if (segments.length === 0) return target;
58556
+ const result = replacePathValue(target, segments, value);
58557
+ return isRecord$16(result) ? result : target;
58558
+ }
58559
+ function replacePathValue(current, segments, value) {
58560
+ const [segment, ...rest] = segments;
58561
+ if (segment === undefined) return value;
58562
+ const container = isPathContainer(current) ? current : createPathContainer(typeof segment === "number");
58563
+ const before = getContainerValue(container, segment);
58564
+ const after = replacePathValue(before, rest, value);
58565
+ if (Object.is(before, after) && isPathContainer(current)) return current;
58566
+ if (Array.isArray(container)) {
58567
+ const next = container.slice();
58568
+ Reflect.set(next, segment, after);
58569
+ return next;
58570
+ }
58571
+ return typeof segment === "number" ? container : {
58572
+ ...container,
58573
+ [segment]: after
58574
+ };
58575
+ }
57958
58576
 
57959
58577
  //#endregion
57960
58578
  //#region ../blocks/src/primitives/content/components/Text.tsx
@@ -61151,7 +61769,7 @@ function isValidOccurrence(value) {
61151
61769
  //#region ../blocks/src/system/runtime/nodes/events/shared/eventCardListContent.ts
61152
61770
  /** Live offering data only; editorial cards never acquire booking fields. */
61153
61771
  function eventCardListContent(event, context, buttonText) {
61154
- const { content, external } = cardProjectionBase(event, buttonText, context.kind === "offering");
61772
+ const { content, external } = cardProjectionBase(event, buttonText, context.kind === "offering", context.kind === "offering" ? context.upcomingDates ?? [] : []);
61155
61773
  switch (context.kind) {
61156
61774
  case "event-details": return {
61157
61775
  ...content,
@@ -61170,8 +61788,8 @@ function eventCardListContent(event, context, buttonText) {
61170
61788
  default: return assertNever(context);
61171
61789
  }
61172
61790
  }
61173
- function cardProjectionBase(event, buttonText, offering) {
61174
- const cta = offeringCardCta(event, buttonText, offering);
61791
+ function cardProjectionBase(event, buttonText, offering, upcomingDates) {
61792
+ const cta = offeringCardCta(event, buttonText, offering, upcomingDates);
61175
61793
  const places = offeringAvailability(event);
61176
61794
  return {
61177
61795
  external: cta.external,
@@ -61282,8 +61900,8 @@ function offeringFacts(event, places, offering) {
61282
61900
  }]
61283
61901
  ];
61284
61902
  }
61285
- function offeringCardCta(event, buttonText, offering) {
61286
- return resolveEventCta(event, offering && event.destination.kind === "external" ? undefined : buttonText);
61903
+ function offeringCardCta(event, buttonText, offering, upcomingDates) {
61904
+ return resolveDatedSeriesCta(event, upcomingDates, offering && event.destination.kind === "external" ? undefined : buttonText);
61287
61905
  }
61288
61906
  function offeringTypeChips(event, typeLabel) {
61289
61907
  return event.eventCategory ? [event.eventCategory.name] : typeLabel ? [typeLabel] : [];
@@ -61356,26 +61974,39 @@ function EventHeader({ selection, presentation, showCost }) {
61356
61974
  });
61357
61975
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
61358
61976
  ...listLookSlot(presentation, "frame"),
61359
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
61360
- ...listLookSlot(presentation, "copy"),
61361
- children: [
61362
- part("chips"),
61363
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
61364
- ...listLookSlot(presentation, "headline"),
61365
- children: item.title
61366
- }),
61367
- item.text ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
61368
- ...listLookSlot(presentation, "lede"),
61369
- children: item.text
61370
- }) : null,
61371
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
61372
- "aria-label": "At a glance",
61373
- children: part("facts")
61374
- }),
61375
- part("availability"),
61376
- part("action")
61377
- ]
61378
- }), part("numeral")]
61977
+ children: [
61978
+ item.media ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("figure", {
61979
+ ...listLookSlot(presentation, "item-media"),
61980
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MediaNodeServer, {
61981
+ value: item.media,
61982
+ size: ImagePresets.full,
61983
+ loading: "eager",
61984
+ fetchPriority: "high",
61985
+ ...listLookSlot(presentation, "photo")
61986
+ })
61987
+ }) : null,
61988
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
61989
+ ...listLookSlot(presentation, "copy"),
61990
+ children: [
61991
+ part("chips"),
61992
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
61993
+ ...listLookSlot(presentation, "headline"),
61994
+ children: item.title
61995
+ }),
61996
+ item.text ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
61997
+ ...listLookSlot(presentation, "lede"),
61998
+ children: item.text
61999
+ }) : null,
62000
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
62001
+ "aria-label": "At a glance",
62002
+ children: part("facts")
62003
+ }),
62004
+ part("availability"),
62005
+ part("action")
62006
+ ]
62007
+ }),
62008
+ part("numeral")
62009
+ ]
61379
62010
  });
61380
62011
  }
61381
62012
 
@@ -62163,10 +62794,22 @@ function buildLoadedOfferingsPreviewListing(input) {
62163
62794
 
62164
62795
  //#endregion
62165
62796
  //#region ../blocks/src/system/runtime/nodes/events/shared/offeringNextDates.ts
62797
+ /**
62798
+ * The upcoming dates a dated series' card lists: its next three live
62799
+ * occurrences from the block's one occurrence batch. The date rows and the
62800
+ * card's own booking button both read from this, so they can't disagree.
62801
+ */
62802
+ function upcomingOccurrencesBySeries(events, now) {
62803
+ const groups = events.reduce((result, event) => new Map([...result, [event.seriesId, [...result.get(event.seriesId) ?? [], event]]]), new Map());
62804
+ return new Map([...groups].map(([seriesId, occurrences]) => [seriesId, orderedUniqueEventOccurrences(occurrences.filter((event) => event.bookingScope !== "whole_series" && Date.parse(event.startsAt) >= now.getTime())).slice(0, 3)]));
62805
+ }
62166
62806
  /** One occurrence batch supplies every occurrence-targeted card in the block. */
62167
62807
  function offeringDatesBySeries(events, now, booking) {
62168
- const groups = events.reduce((result, event) => new Map([...result, [event.seriesId, [...result.get(event.seriesId) ?? [], event]]]), new Map());
62169
- return new Map([...groups].map(([seriesId, occurrences]) => [seriesId, orderedUniqueEventOccurrences(occurrences.filter((event) => event.bookingScope !== "whole_series" && Date.parse(event.startsAt) >= now.getTime())).slice(0, 3).map((event) => offeringDateRow(event, event, booking))]));
62808
+ return offeringDateRowsBySeries(upcomingOccurrencesBySeries(events, now), booking);
62809
+ }
62810
+ /** Date rows for occurrences already chosen by {@link upcomingOccurrencesBySeries}. */
62811
+ function offeringDateRowsBySeries(upcoming, booking) {
62812
+ return new Map([...upcoming].map(([seriesId, occurrences]) => [seriesId, occurrences.map((event) => offeringDateRow(event, event, booking))]));
62170
62813
  }
62171
62814
  /** Whole-series sessions share the run-level booking capacity, by contract. */
62172
62815
  function offeringRunDates(event, now) {
@@ -62299,14 +62942,13 @@ function renderOfferingsCatalogueGroups({ props: props$1, groups, shape }) {
62299
62942
  }
62300
62943
  function renderCatalogueItems({ props: props$1, items, shape, groupTitle }) {
62301
62944
  const events = items.map((item) => item.kind === "event" ? item.event : item.run.representative);
62945
+ const dates = catalogueDates(props$1.quickDateEvents ?? [], props$1.now, shape, props$1.pathname);
62302
62946
  if (props$1.lookSlots) {
62303
- const now = props$1.now;
62304
- const dates = offeringDatesBySeries(props$1.quickDateEvents ?? [], now, catalogueDateBooking(shape, props$1.pathname));
62305
62947
  return CardListItems({
62306
62948
  Carousel: props$1.Carousel,
62307
62949
  Title: shape === "single" ? "h3" : "h4",
62308
62950
  presentation: props$1,
62309
- items: items.map((item) => catalogueCardContent(item, now, dates, shape === "single" ? groupTitle : undefined))
62951
+ items: items.map((item) => catalogueCardContent(item, props$1.now, dates, shape === "single" ? groupTitle : undefined))
62310
62952
  });
62311
62953
  }
62312
62954
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
@@ -62314,10 +62956,19 @@ function renderCatalogueItems({ props: props$1, items, shape, groupTitle }) {
62314
62956
  style: { gridTemplateColumns: "repeat(auto-fill, minmax(min(100%, 18rem), 1fr))" },
62315
62957
  children: events.map((event) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventCard, {
62316
62958
  event,
62959
+ upcomingDates: dates.upcoming.get(event.seriesId),
62317
62960
  ...catalogueEventCardProps(event, props$1.buttonVariant ?? "primary")
62318
62961
  }, event.seriesId))
62319
62962
  });
62320
62963
  }
62964
+ /** The listed dates and their rows, from one reading so the button and the rows agree. */
62965
+ function catalogueDates(events, now, shape, pathname) {
62966
+ const upcoming = upcomingOccurrencesBySeries(events, now);
62967
+ return {
62968
+ upcoming,
62969
+ rows: offeringDateRowsBySeries(upcoming, catalogueDateBooking(shape, pathname))
62970
+ };
62971
+ }
62321
62972
  function catalogueCardContent(item, now, dates, typeLabel) {
62322
62973
  const event = item.kind === "event" ? item.event : item.run.representative;
62323
62974
  return {
@@ -62325,9 +62976,10 @@ function catalogueCardContent(item, now, dates, typeLabel) {
62325
62976
  kind: "offering",
62326
62977
  now,
62327
62978
  nextStartMs: item.nextStartMs,
62328
- typeLabel
62979
+ typeLabel,
62980
+ upcomingDates: dates.upcoming.get(event.seriesId)
62329
62981
  }, catalogueEventCardProps(event).buttonText),
62330
- dates: event.bookingScope === "whole_series" ? offeringRunDates(event, now) : dates.get(event.seriesId)
62982
+ dates: event.bookingScope === "whole_series" ? offeringRunDates(event, now) : dates.rows.get(event.seriesId)
62331
62983
  };
62332
62984
  }
62333
62985
  function renderCatalogueEmpty({ props: props$1, failed }) {
@@ -62342,7 +62994,7 @@ function renderCatalogueEmpty({ props: props$1, failed }) {
62342
62994
  });
62343
62995
  }
62344
62996
  function renderCatalogueMergedList({ props: props$1, listing, now, shape }) {
62345
- const dates = offeringDatesBySeries(props$1.quickDateEvents ?? [], now, catalogueDateBooking(shape, props$1.pathname));
62997
+ const dates = catalogueDates(props$1.quickDateEvents ?? [], now, shape, props$1.pathname);
62346
62998
  const items = listing.items.map(({ item, group }) => catalogueCardContent(item, now, dates, group.singularLabel));
62347
62999
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
62348
63000
  ...listLookSlot(props$1, "layout"),
@@ -64079,7 +64731,11 @@ function EventListBody({ display, renderEventCard: renderEventCard$1, footer })
64079
64731
  className: display.containerClass,
64080
64732
  children: display.events.map(renderEventCard$1)
64081
64733
  });
64082
- if (display.listLayout === "day-groups") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", {
64734
+ if (display.listLayout === "week-columns" && display.week !== undefined) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WeekColumns, {
64735
+ display,
64736
+ week: display.week
64737
+ });
64738
+ if (display.listLayout === "day-groups" || display.listLayout === "week-columns") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", {
64083
64739
  ...listLookSlot(display, "list"),
64084
64740
  children: display.events.filter((event, index, events) => events.findIndex((candidate) => eventLocalDateKey(candidate) === eventLocalDateKey(event)) === index).map((first) => {
64085
64741
  const date = formatEventCompactDateRail(first.startsAt, eventDateOptions(first), "as-written");
@@ -64136,6 +64792,45 @@ function EventListBody({ display, renderEventCard: renderEventCard$1, footer })
64136
64792
  children: display.events.map(renderEventCard$1)
64137
64793
  });
64138
64794
  }
64795
+ /** All seven days of the shown week; a day known to be empty says so, and a wholly empty week never reaches here. */
64796
+ function WeekColumns({ display, week }) {
64797
+ const todayMark = display.itemSurfaces?.today;
64798
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", {
64799
+ ...listLookSlot(display, "list"),
64800
+ children: weekColumnDays(week, display.events, display.allLoaded === true).map((day) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", {
64801
+ ...listLookSlot(display, "group"),
64802
+ ...day.isToday ? { "data-today": "true" } : {},
64803
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h3", {
64804
+ ...listLookSlot(display, "group-label"),
64805
+ children: [
64806
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
64807
+ ...listLookSlot(display, "group-day"),
64808
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
64809
+ "aria-hidden": "true",
64810
+ children: day.label.weekday
64811
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
64812
+ className: "rb-sr-only",
64813
+ children: day.label.fullWeekday
64814
+ })]
64815
+ }),
64816
+ " ",
64817
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
64818
+ ...listLookSlot(display, "group-date"),
64819
+ ...day.isToday && todayMark !== undefined && display.lookSlots?.["group-date"] !== undefined ? resolvedItemSurfaceProps(todayMark, "group-date") : {},
64820
+ children: day.label.day
64821
+ })
64822
+ ]
64823
+ }), day.sessions.kind === "some" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { children: day.sessions.events.map((event) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventItem, {
64824
+ ...listItemPresentation(display, display.events.indexOf(event), display.events.length),
64825
+ event,
64826
+ arrangement: "week-columns"
64827
+ }, event.occurrenceId || event.id)) }) : day.sessions.kind === "none" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
64828
+ ...listLookSlot(display, "group-empty"),
64829
+ children: "Nothing on"
64830
+ }) : null]
64831
+ }, day.dateKey))
64832
+ });
64833
+ }
64139
64834
  function hasArrangementPanel(display) {
64140
64835
  return display.state === "ready" && display.lookSlots !== undefined && display.listLayout === "compact";
64141
64836
  }
@@ -64823,13 +65518,19 @@ function renderCombinedSsr(display, prefetchedEvents) {
64823
65518
  });
64824
65519
  }
64825
65520
  function renderListSsr(display, hydration) {
64826
- const listDisplay = buildEventCalendarListingDisplay(display, hydration.prefetchedEvents);
64827
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [display.listBy === "week" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventListWeekNavigation, {
65521
+ const { initialToday, timeZone } = hydration.calendarContext;
65522
+ const week = display.listBy === "week" ? buildEventListWeek(initialToday, display.startOfWeek, timeZone) : null;
65523
+ const listing = buildEventCalendarListingDisplay(display, hydration.prefetchedEvents);
65524
+ const listDisplay = week === null ? listing : {
65525
+ ...listing,
65526
+ week: eventListWeekDays(week, initialToday, timeZone)
65527
+ };
65528
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [week !== null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventListWeekNavigation, {
64828
65529
  ...display,
64829
- title: buildEventListWeek(hydration.calendarContext.initialToday, display.startOfWeek, hydration.calendarContext.timeZone).title
65530
+ title: week.title
64830
65531
  }) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventListingFrameView, {
64831
65532
  display: listDisplay,
64832
- emptyState: display.listBy === "week" && display.lookSlots !== undefined ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventListWeekEmptyState, {
65533
+ emptyState: week !== null && display.lookSlots !== undefined ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventListWeekEmptyState, {
64833
65534
  ...display,
64834
65535
  nextWeek: {}
64835
65536
  }) : undefined,
@@ -66604,6 +67305,47 @@ function derivePreviewLinkedEntryFieldBinding(node, parsedBinding, context) {
66604
67305
  function stripNumericPathSegments(path$3) {
66605
67306
  return path$3.split(".").filter((segment) => !/^\d+$/.test(segment)).join(".");
66606
67307
  }
67308
+ const lookOwnedPathCache = new WeakMap();
67309
+ function lookOwnedPathsOf(content) {
67310
+ if (!isPlainObject$3(content)) return [];
67311
+ const cached = lookOwnedPathCache.get(content);
67312
+ if (cached) return cached;
67313
+ const value = content._lookOwnedPaths;
67314
+ const paths = Array.isArray(value) ? value.filter((path$3) => typeof path$3 === "string") : [];
67315
+ lookOwnedPathCache.set(content, paths);
67316
+ return paths;
67317
+ }
67318
+ /**
67319
+ * Under an arrangement Look, the render plan has already removed the owner's
67320
+ * values for presentation the Look owns, and lists those field paths. A binding
67321
+ * on one of them skips its own default, so the Look decides: its CSS, or a
67322
+ * value the Look wrote itself (the crop its shape knob implies). Transforms
67323
+ * still run, which keeps the base classes they compose. Older styles list none
67324
+ * and bind as before.
67325
+ */
67326
+ function readsLookOwnedField(fromPath, context) {
67327
+ const owned = lookOwnedPathsOf(context.viewModel.content);
67328
+ if (owned.length === 0) return false;
67329
+ const segments = contentFieldSegments(fromPath, context);
67330
+ if (!segments) return false;
67331
+ const path$3 = segments.filter((segment) => typeof segment === "string").join(".");
67332
+ return owned.some((ownedPath) => path$3 === ownedPath || path$3.startsWith(`${ownedPath}.`));
67333
+ }
67334
+ /** The block-content path a binding reads, or undefined when it reads something else. */
67335
+ function contentFieldSegments(fromPath, context) {
67336
+ const [first, ...rest] = splitPath$1(fromPath);
67337
+ if (typeof first !== "string" || first === "$root") return undefined;
67338
+ if (first === "content") return rest;
67339
+ const named = [...context.scopes].reverse().find((entry) => entry.name === first);
67340
+ if (named) return scopedContentSegments(named, rest);
67341
+ const innermost = [...context.scopes].reverse().find((entry) => isPlainObject$3(entry.value) || Array.isArray(entry.value));
67342
+ if (!innermost || first in context.viewModel) return undefined;
67343
+ return innermost.name === "content" ? [first, ...rest] : scopedContentSegments(innermost, [first, ...rest]);
67344
+ }
67345
+ function scopedContentSegments(scope, rest) {
67346
+ const [root, ...base] = scope.basePathSegments ?? [];
67347
+ return root === "content" ? [...base, ...rest] : undefined;
67348
+ }
66607
67349
  /**
66608
67350
  * Resolves a binding path to absolute segments for editor/media metadata injection.
66609
67351
  *
@@ -66937,6 +67679,12 @@ function previewAuthoringFieldsEqual(left, right) {
66937
67679
  * @internal Exported for testing
66938
67680
  */
66939
67681
  function resolveBindingValue(binding, context) {
67682
+ return resolveReadBindingValue(readsLookOwnedField(binding.from, context) ? {
67683
+ ...binding,
67684
+ fallback: undefined
67685
+ } : binding, context);
67686
+ }
67687
+ function resolveReadBindingValue(binding, context) {
66940
67688
  const fullPath = binding.from;
66941
67689
  const segments = splitPath$1(fullPath);
66942
67690
  if (!segments.length) return undefined;
@@ -67984,10 +68732,19 @@ function prepareDefaultBlockRender(manifest, props$1) {
67984
68732
  fieldConstraints: buildPreviewFieldConstraints(manifest)
67985
68733
  };
67986
68734
  }
68735
+ const blockComponentCache = new WeakMap();
68736
+ /** One React component type per manifest, shared by page and standalone rendering. */
67987
68737
  function makeDefaultBlockComponent(args) {
68738
+ const cached = blockComponentCache.get(args.manifest);
68739
+ if (cached) return cached;
68740
+ const component = createDefaultBlockComponent(args.manifest);
68741
+ blockComponentCache.set(args.manifest, component);
68742
+ return component;
68743
+ }
68744
+ function createDefaultBlockComponent(manifest) {
67988
68745
  return function DefaultBlockComponent(props$1) {
67989
68746
  const perf = beginBlockRenderMeasurement();
67990
- const prepared = prepareDefaultBlockRender(args.manifest, props$1);
68747
+ const prepared = prepareDefaultBlockRender(manifest, props$1);
67991
68748
  const result = resolveTree(prepared.layout, {
67992
68749
  registry: prepared.registry,
67993
68750
  viewModel: prepared.viewModel,
@@ -68011,8 +68768,8 @@ function makeDefaultBlockComponent(args) {
68011
68768
  reportSlowBlockRender(perf, {
68012
68769
  content: props$1.content,
68013
68770
  blockId: props$1.blockId,
68014
- blockKind: props$1.blockKind ?? args.manifest.name,
68015
- manifestName: args.manifest.name
68771
+ blockKind: props$1.blockKind ?? manifest.name,
68772
+ manifestName: manifest.name
68016
68773
  });
68017
68774
  return result;
68018
68775
  };
@@ -68155,335 +68912,6 @@ function runtimeDateContext(viewModel) {
68155
68912
  return resolveDateRuntimeContext(typeof root.bookingTimeZone === "string" ? root.bookingTimeZone : undefined);
68156
68913
  }
68157
68914
 
68158
- //#endregion
68159
- //#region ../blocks/src/system/ai/hints/registry.ts
68160
- const HINTS = [
68161
- {
68162
- blockKind: "block.hero",
68163
- fieldPath: "variant",
68164
- hint: {
68165
- fieldLabelOverride: "Layout style",
68166
- impactSummary: "Changes the overall layout of the top banner (how text and media are arranged). Different styles can feel more minimal, more bold, or more split across the page.",
68167
- category: "layout",
68168
- suggestWhen: "visual-request-only"
68169
- }
68170
- },
68171
- {
68172
- blockKind: "block.columns",
68173
- fieldPath: "desktopColumns",
68174
- hint: {
68175
- fieldLabelOverride: "Columns on larger screens",
68176
- impactSummary: "Changes how many columns appear on larger screens. More columns increase density, fewer columns make each column wider.",
68177
- category: "layout",
68178
- suggestWhen: "visual-request-only"
68179
- }
68180
- },
68181
- {
68182
- blockKind: "block.columns",
68183
- fieldPath: "gap",
68184
- hint: {
68185
- fieldLabelOverride: "Column gap",
68186
- impactSummary: "Adjusts the spacing between columns and blocks. Larger gaps feel more open; smaller gaps feel more compact.",
68187
- category: "visual",
68188
- suggestWhen: "visual-request-only"
68189
- }
68190
- },
68191
- {
68192
- blockKind: "block.media-text",
68193
- fieldPath: "imagePosition",
68194
- hint: {
68195
- fieldLabelOverride: "Image position",
68196
- impactSummary: "Moves where the image sits relative to the text. This changes reading flow and visual balance.",
68197
- category: "layout",
68198
- suggestWhen: "visual-request-only"
68199
- }
68200
- },
68201
- {
68202
- blockKind: "block.media-text",
68203
- fieldPath: "wrapTextInCard",
68204
- hint: {
68205
- fieldLabelOverride: "Text card",
68206
- impactSummary: "Wraps text content in a styled card container. This makes text stand out more strongly from the background media.",
68207
- category: "visual",
68208
- suggestWhen: "visual-request-only"
68209
- }
68210
- },
68211
- {
68212
- blockKind: "block.single-button",
68213
- fieldPath: "button.variant",
68214
- hint: {
68215
- fieldLabelOverride: "Button style",
68216
- impactSummary: "Switches the button to a different theme variant (for example primary, secondary, or subtle). This changes emphasis and contrast.",
68217
- category: "theme",
68218
- suggestWhen: "visual-request-only"
68219
- }
68220
- },
68221
- {
68222
- blockKind: "block.body-text",
68223
- fieldPath: "alignment",
68224
- hint: {
68225
- fieldLabelOverride: "Text alignment",
68226
- impactSummary: "Changes whether text is left, center, or right aligned. This affects readability and the overall visual rhythm of the section.",
68227
- category: "layout",
68228
- suggestWhen: "visual-request-only"
68229
- }
68230
- },
68231
- {
68232
- blockKind: "block.testimonials",
68233
- fieldPath: "variant",
68234
- hint: {
68235
- fieldLabelOverride: "Layout style",
68236
- impactSummary: "Changes how testimonials are presented, for example as a grid or carousel, affecting hierarchy and emphasis.",
68237
- category: "layout",
68238
- suggestWhen: "visual-request-only"
68239
- }
68240
- },
68241
- {
68242
- blockKind: "block.testimonials",
68243
- fieldPath: "gridColumns",
68244
- hint: {
68245
- fieldLabelOverride: "Grid columns",
68246
- impactSummary: "Controls how many testimonial cards appear per row in grid layouts. This changes density and scanability.",
68247
- category: "layout",
68248
- suggestWhen: "visual-request-only"
68249
- }
68250
- },
68251
- {
68252
- blockKind: "block.embed",
68253
- fieldPath: "layout",
68254
- hint: {
68255
- fieldLabelOverride: "Layout",
68256
- impactSummary: "Changes how embedded entries are arranged (for example list vs grid). This affects how much content appears per row.",
68257
- category: "layout",
68258
- suggestWhen: "visual-request-only"
68259
- }
68260
- },
68261
- {
68262
- blockKind: "block.embed",
68263
- fieldPath: "contentType",
68264
- hint: {
68265
- fieldLabelOverride: "Content type",
68266
- impactSummary: "Switches which content type is rendered in this block. This changes the kind of items shown, not just wording.",
68267
- category: "structure",
68268
- suggestWhen: "visual-request-only"
68269
- }
68270
- },
68271
- {
68272
- blockKind: "block.blog-listing",
68273
- fieldPath: "variant",
68274
- hint: {
68275
- fieldLabelOverride: "Listing layout",
68276
- impactSummary: "Changes whether blog posts are displayed in a list or grid style. This affects visual density and browsing behavior.",
68277
- category: "layout",
68278
- suggestWhen: "visual-request-only"
68279
- }
68280
- },
68281
- {
68282
- blockKind: "block.blog-listing",
68283
- fieldPath: "columns",
68284
- hint: {
68285
- fieldLabelOverride: "Columns",
68286
- impactSummary: "Sets how many columns appear in grid mode. More columns show more posts at once; fewer columns give each card more space.",
68287
- category: "layout",
68288
- suggestWhen: "visual-request-only"
68289
- }
68290
- },
68291
- {
68292
- blockKind: "block.blog-listing",
68293
- fieldPath: "showImages",
68294
- hint: {
68295
- fieldLabelOverride: "Show featured images",
68296
- impactSummary: "Turns post thumbnails on or off. This strongly changes the visual look and emphasis of each listing item.",
68297
- category: "visual",
68298
- suggestWhen: "visual-request-only"
68299
- }
68300
- },
68301
- {
68302
- blockKind: "block.event-registration",
68303
- fieldPath: "buttonVariant",
68304
- hint: {
68305
- fieldLabelOverride: "Button style",
68306
- impactSummary: "Applies a different theme variant to the registration button, changing its visual prominence and contrast.",
68307
- category: "theme",
68308
- suggestWhen: "visual-request-only"
68309
- }
68310
- },
68311
- {
68312
- blockKind: "block.event-spotlight",
68313
- fieldPath: "layout",
68314
- hint: {
68315
- fieldLabelOverride: "Layout",
68316
- impactSummary: "Changes how spotlight events are arranged (for example stacked or grid). This affects hierarchy and scanability.",
68317
- category: "layout",
68318
- suggestWhen: "visual-request-only"
68319
- }
68320
- },
68321
- {
68322
- blockKind: "block.event-spotlight",
68323
- fieldPath: "columns",
68324
- hint: {
68325
- fieldLabelOverride: "Columns",
68326
- impactSummary: "Controls how many spotlight cards appear per row in grid layouts, affecting density and card width.",
68327
- category: "layout",
68328
- suggestWhen: "visual-request-only"
68329
- }
68330
- },
68331
- {
68332
- blockKind: "block.event-spotlight",
68333
- fieldPath: "_cardStyles.role",
68334
- hint: {
68335
- fieldLabelOverride: "Card style",
68336
- impactSummary: "Switches the visual style of each event card, such as emphasis, borders, and spacing.",
68337
- category: "theme",
68338
- suggestWhen: "visual-request-only"
68339
- }
68340
- },
68341
- {
68342
- blockKind: "block.event-listing",
68343
- fieldPath: "layout",
68344
- hint: {
68345
- fieldLabelOverride: "Layout",
68346
- impactSummary: "Changes how listing events are arranged (for example stacked or grid). This affects browsing flow and density.",
68347
- category: "layout",
68348
- suggestWhen: "visual-request-only"
68349
- }
68350
- },
68351
- {
68352
- blockKind: "block.event-listing",
68353
- fieldPath: "columns",
68354
- hint: {
68355
- fieldLabelOverride: "Columns",
68356
- impactSummary: "Controls how many event cards appear per row in grid layouts, changing balance between density and readability.",
68357
- category: "layout",
68358
- suggestWhen: "visual-request-only"
68359
- }
68360
- },
68361
- {
68362
- blockKind: "block.event-listing",
68363
- fieldPath: "_cardStyles.role",
68364
- hint: {
68365
- fieldLabelOverride: "Card style",
68366
- impactSummary: "Switches the visual style of event cards, including emphasis and overall card presentation.",
68367
- category: "theme",
68368
- suggestWhen: "visual-request-only"
68369
- }
68370
- },
68371
- {
68372
- blockKind: "*",
68373
- fieldPath: "_sectionStyles",
68374
- hint: {
68375
- fieldLabelOverride: "Section styles",
68376
- impactSummary: "Controls spacing and background for this section (padding, background color/image). These changes affect the look and feel, not the wording.",
68377
- category: "visual",
68378
- suggestWhen: "visual-request-only"
68379
- }
68380
- },
68381
- {
68382
- blockKind: "*",
68383
- fieldPath: "_sectionStyles.background",
68384
- hint: {
68385
- fieldLabelOverride: "Background",
68386
- impactSummary: "Controls the section background (color, gradient, or image). This changes the visual mood and contrast behind the content.",
68387
- category: "visual",
68388
- suggestWhen: "visual-request-only"
68389
- }
68390
- },
68391
- {
68392
- blockKind: "*",
68393
- fieldPath: "_cardStyles",
68394
- hint: {
68395
- fieldLabelOverride: "Card styles",
68396
- impactSummary: "Controls the look of the cards inside this section (rounded corners, shadow, padding, background, border). This affects this section’s cards, not the whole site theme.",
68397
- category: "visual",
68398
- suggestWhen: "visual-request-only"
68399
- }
68400
- },
68401
- {
68402
- blockKind: "*",
68403
- fieldPath: "_cardStyles.rounded",
68404
- hint: {
68405
- fieldLabelOverride: "Rounded corners",
68406
- impactSummary: "Adjusts how rounded the card corners are for this section’s cards only (small, medium, large, fully rounded).",
68407
- category: "visual",
68408
- suggestWhen: "visual-request-only"
68409
- }
68410
- },
68411
- {
68412
- blockKind: "*",
68413
- fieldPath: "_containerStyles",
68414
- hint: {
68415
- fieldLabelOverride: "Container styles",
68416
- impactSummary: "Controls the main container styling for this section (rounded corners, shadow, padding, background). This is section-specific, not a whole-site theme change.",
68417
- category: "visual",
68418
- suggestWhen: "visual-request-only"
68419
- }
68420
- },
68421
- {
68422
- blockKind: "*",
68423
- fieldPath: "_containerStyles.rounded",
68424
- hint: {
68425
- fieldLabelOverride: "Rounded corners",
68426
- impactSummary: "Adjusts how rounded the container corners are for this section only (small, medium, large, fully rounded).",
68427
- category: "visual",
68428
- suggestWhen: "visual-request-only"
68429
- }
68430
- },
68431
- {
68432
- blockKind: "block.event-calendar",
68433
- fieldPath: "displayMode",
68434
- hint: {
68435
- fieldLabelOverride: "Display mode",
68436
- impactSummary: "Changes how events are shown (list view, calendar view, or both). This affects the layout and how visitors browse events.",
68437
- category: "layout",
68438
- suggestWhen: "visual-request-only"
68439
- }
68440
- },
68441
- {
68442
- blockKind: "block.event-calendar",
68443
- fieldPath: "listLayout",
68444
- hint: {
68445
- fieldLabelOverride: "List layout",
68446
- impactSummary: "Changes the layout style for the event list (stacked cards vs a grid). This affects how many events show per row and the overall density.",
68447
- category: "layout",
68448
- suggestWhen: "visual-request-only"
68449
- }
68450
- }
68451
- ];
68452
- function isBoundaryMatch(prefix, fieldPath) {
68453
- if (prefix === fieldPath) return true;
68454
- if (!fieldPath.startsWith(prefix)) return false;
68455
- const next = fieldPath.charAt(prefix.length);
68456
- return next === ".";
68457
- }
68458
- function resolveByExactMatch(blockKind, fieldPath) {
68459
- return HINTS.find((entry) => entry.blockKind === blockKind && entry.fieldPath === fieldPath) ?? HINTS.find((entry) => entry.blockKind === "*" && entry.fieldPath === fieldPath) ?? null;
68460
- }
68461
- function resolveByPrefixMatch(blockKind, fieldPath) {
68462
- const candidates = HINTS.filter((entry) => {
68463
- if (entry.fieldPath === fieldPath) return false;
68464
- if (!(entry.blockKind === blockKind || entry.blockKind === "*")) return false;
68465
- return isBoundaryMatch(entry.fieldPath, fieldPath);
68466
- });
68467
- if (candidates.length === 0) return null;
68468
- candidates.sort((a$1, b$1) => {
68469
- if (a$1.blockKind !== b$1.blockKind) {
68470
- if (a$1.blockKind !== "*" && b$1.blockKind === "*") return -1;
68471
- if (a$1.blockKind === "*" && b$1.blockKind !== "*") return 1;
68472
- }
68473
- return b$1.fieldPath.length - a$1.fieldPath.length;
68474
- });
68475
- return candidates[0] ?? null;
68476
- }
68477
- function resolveAiFieldHint(input) {
68478
- const blockKind = input.blockKind.trim();
68479
- const fieldPath = input.fieldPath.trim();
68480
- if (!blockKind || !fieldPath) return null;
68481
- const exact = resolveByExactMatch(blockKind, fieldPath);
68482
- if (exact) return exact.hint;
68483
- const prefix = resolveByPrefixMatch(blockKind, fieldPath);
68484
- return prefix?.hint ?? null;
68485
- }
68486
-
68487
68915
  //#endregion
68488
68916
  //#region ../blocks/src/system/media/constrainedVideoMedia.ts
68489
68917
  function isRecord$10(value) {
@@ -68792,7 +69220,8 @@ function composePageJoins(input) {
68792
69220
  return [{
68793
69221
  previousBlockId: previous.id,
68794
69222
  nextBlockId: next.id,
68795
- join: join$1 ? composeJoin(join$1, previous, next) : null
69223
+ join: join$1 ? composeJoin(join$1, previous, next) : null,
69224
+ fieldsMeet: sectionShapeFromContent(previous.content) === "field" && sectionShapeFromContent(next.content) === "field"
68796
69225
  }];
68797
69226
  });
68798
69227
  }
@@ -68832,11 +69261,31 @@ function pairKey(previousBlockId, nextBlockId) {
68832
69261
  * runs inside a `useMemo` whose recomputation React makes no promises about.
68833
69262
  */
68834
69263
  function buildPageRenderPlan(input) {
69264
+ return planPageRender(input).plan;
69265
+ }
69266
+ /** Owner-local derived reuse; shared settings and admitted rhythm position remain inputs. */
69267
+ function createPageRenderPlanReader() {
69268
+ const memo = { current: null };
69269
+ return (input) => {
69270
+ memo.current = planPageRender(input, memo.current);
69271
+ return memo.current.plan;
69272
+ };
69273
+ }
69274
+ function planPageRender(input, previous = null) {
68835
69275
  const resolveTarget = createRenderTargetResolver(input);
68836
- const outcomes = input.page.blocks.map((block) => planPageBlock(block, input, resolveTarget));
69276
+ const reusable = previous && samePlanSettings(previous.input, input) ? previous : null;
69277
+ const planned = input.page.blocks.map((block) => [block, reusable?.outcomes.get(block) ?? planPageBlock(block, input, resolveTarget)]);
69278
+ const outcomes = planned.map(([, outcome]) => outcome);
68837
69279
  const entries = outcomes.flatMap((outcome) => outcome.kind === "admitted" ? [outcome.entry] : []);
68838
- return {
68839
- entries: entries.map(applyArrangementRhythm),
69280
+ const rhythmic = entries.map((entry, position) => {
69281
+ const cached = reusable?.rhythm.get(entry);
69282
+ return [entry, {
69283
+ position,
69284
+ entry: cached?.position === position ? cached.entry : applyArrangementRhythm(entry, position)
69285
+ }];
69286
+ });
69287
+ const plan = {
69288
+ entries: rhythmic.map(([, value]) => value.entry),
68840
69289
  omitted: outcomes.flatMap((outcome) => outcome.kind === "omitted" ? [outcome.omission] : []),
68841
69290
  runtimeJoins: retargetJoinsAcrossOmissions({
68842
69291
  joins: input.runtimeJoins ?? [],
@@ -68844,6 +69293,15 @@ function buildPageRenderPlan(input) {
68844
69293
  survivingBlocks: new Set(entries.map((entry) => entry.block))
68845
69294
  })
68846
69295
  };
69296
+ return {
69297
+ input,
69298
+ outcomes: new Map(planned),
69299
+ rhythm: new Map(rhythmic),
69300
+ plan
69301
+ };
69302
+ }
69303
+ function samePlanSettings(previous, current) {
69304
+ return previous.siteStyleId === current.siteStyleId && previous.audience === current.audience && previous.previewStage === current.previewStage && previous.sdkConfig === current.sdkConfig && previous.customBlocks === current.customBlocks && previous.blockOverrides === current.blockOverrides;
68847
69305
  }
68848
69306
  /**
68849
69307
  * Mirrors the order of the checks `MemoBlockSection` used to make inline, so no
@@ -69009,8 +69467,11 @@ function restoreCompiledLook(look) {
69009
69467
  };
69010
69468
  }
69011
69469
  function restoreArrangementRuntime(runtime) {
69470
+ const transported = runtime;
69471
+ const fieldGrounds = Array.isArray(transported.fieldGrounds) ? transported.fieldGrounds.filter((token) => typeof token === "string") : [];
69012
69472
  return {
69013
69473
  ...runtime,
69474
+ fieldGrounds,
69014
69475
  available: runtime.available.map(restoreCompiledLook),
69015
69476
  byMode: Object.fromEntries(Object.entries(runtime.byMode).map(([mode, look]) => [mode, restoreCompiledLook(look)]))
69016
69477
  };
@@ -69031,7 +69492,7 @@ function planArrangementContent(blockKind, manifest, content, audience) {
69031
69492
  const { facts } = arrangementContentFacts(content);
69032
69493
  const published = resolvePublishedLook({
69033
69494
  look: selected.look,
69034
- contentFacts: facts,
69495
+ facts,
69035
69496
  audience,
69036
69497
  catalogue: runtime.available.map((entry) => entry.look)
69037
69498
  });
@@ -69043,7 +69504,12 @@ function planArrangementContent(blockKind, manifest, content, audience) {
69043
69504
  });
69044
69505
  const values = Object.fromEntries(Object.entries(knobs).flatMap(([key, knob]) => knob.kind === "kept" ? [] : [[key, knob.value]]));
69045
69506
  const effectiveContent = Object.fromEntries(Object.entries(values).map(([key, value]) => [key, effectiveContentKnobValue(blockKind, key, value)]));
69046
- const activeContent = Object.fromEntries(Object.entries(content).filter(([key]) => knobs[key]?.kind !== "kept"));
69507
+ const lookOwnedPaths = contentPathsOwnedBy(resolveFieldOwnership({
69508
+ blockKind,
69509
+ manifest,
69510
+ arrangementLook: true
69511
+ }), ["look"]);
69512
+ const activeContent = withoutLookOwnedContent(Object.fromEntries(Object.entries(content).filter(([key]) => knobs[key]?.kind !== "kept")), lookOwnedPaths);
69047
69513
  const photoContent = arrangementPhotoContent(activeContent, effectiveContent);
69048
69514
  const visiblePhotos = arrangementContentFacts({
69049
69515
  ...activeContent,
@@ -69056,19 +69522,17 @@ function planArrangementContent(blockKind, manifest, content, audience) {
69056
69522
  ...mode !== null ? { variant: mode } : {},
69057
69523
  ...effectiveContent,
69058
69524
  ...photoContent,
69059
- ...arrangementShapeContent(effective.look.id, {
69060
- ...activeContent,
69061
- ...effectiveContent
69062
- }),
69525
+ ...arrangementShapeContent(knobs),
69063
69526
  ...arrangementPanelContent(activeContent, effective, mode),
69064
69527
  ...arrangementQuoteContent(blockKind, effective, values),
69065
69528
  _arrangementLooks: runtime,
69066
69529
  _effectiveLook: effective,
69067
69530
  _lookHooks: arrangementContentHooks(effective, mode, length, {
69068
- ...facts,
69069
- photo: visiblePhotos.facts.photo
69531
+ ...facts.content,
69532
+ photo: visiblePhotos.facts.content.photo
69070
69533
  }, values, visiblePhotos.photoCount),
69071
69534
  _effectiveKnobs: knobs,
69535
+ _lookOwnedPaths: lookOwnedPaths,
69072
69536
  _lookAudience: audience,
69073
69537
  _lookSlots: arrangementContentSlots(blockKind),
69074
69538
  blockLook: effective.look.id
@@ -69088,10 +69552,11 @@ function arrangementPhotoTreatmentContent(content, look) {
69088
69552
  function arrangementContentSlots(blockKind) {
69089
69553
  return Object.fromEntries(arrangementSlotNames.filter((slot) => (!slot.startsWith("price-") || blockKind === "block.shop") && slot !== "schedule-section" && slot !== "shop-section" && (slot !== "background" || blockKind === "block.hero")).map((slot) => [slot, slot]));
69090
69554
  }
69091
- /** C photo Looks render shape-specific crops without rewriting authored preferences. */
69092
- function arrangementShapeContent(lookId, content) {
69093
- if (lookId !== "intro-photo-beside-text" && lookId !== "media-text-photo-beside-text") return {};
69094
- return content.imageShape === "circle" ? { aspectRatio: "1/1" } : content.imageShape === "arch" ? { aspectRatio: "4/5" } : {};
69555
+ /** Where a Look offers the photo shape, the shape sets the crop, without rewriting authored preferences. */
69556
+ function arrangementShapeContent(knobs) {
69557
+ const shape = knobs.imageShape;
69558
+ if (!shape || shape.kind === "kept") return {};
69559
+ return shape.value === "circle" ? { aspectRatio: "1/1" } : shape.value === "arch" ? { aspectRatio: "4/5" } : {};
69095
69560
  }
69096
69561
  function arrangementQuoteContent(blockKind, effective, values) {
69097
69562
  if (blockKind !== "block.testimonials") return {};
@@ -69122,18 +69587,25 @@ function arrangementPhotoContent(content, knobs) {
69122
69587
  return copy;
69123
69588
  }) };
69124
69589
  }
69590
+ /**
69591
+ * The one owner of the facts `whenMissing` rules read from block content.
69592
+ * Content facts also become `data-has-*` hooks; setting facts never do.
69593
+ */
69125
69594
  function arrangementContentFacts(content) {
69126
69595
  const photoCount = arrangementPhotoCount(content);
69127
69596
  const featured = typeof content.featured === "string" ? content.featured.trim().length > 0 : content.featured !== undefined && content.featured !== null;
69128
69597
  return {
69129
69598
  photoCount,
69130
69599
  facts: {
69131
- photo: photoCount > 0,
69132
- facts: Array.isArray(content.facts) && content.facts.length > 0,
69133
- featured,
69134
- outcome: typeof content.outcome === "string" && content.outcome.length > 0,
69135
- figure: typeof content.figure === "string" && content.figure.trim().length > 0,
69136
- entrance: isObjectRecord(content.entrancePhoto)
69600
+ content: {
69601
+ photo: photoCount > 0,
69602
+ facts: Array.isArray(content.facts) && content.facts.length > 0,
69603
+ featured,
69604
+ outcome: typeof content.outcome === "string" && content.outcome.length > 0,
69605
+ figure: typeof content.figure === "string" && content.figure.trim().length > 0,
69606
+ entrance: isObjectRecord(content.entrancePhoto)
69607
+ },
69608
+ settings: { "listed-by-week": content.listBy === "week" }
69137
69609
  }
69138
69610
  };
69139
69611
  }
@@ -69143,9 +69615,7 @@ function arrangementPhotoCount(content) {
69143
69615
  if (Array.isArray(content.members)) return content.members.filter((member) => isObjectRecord(member) && isObjectRecord(member.photo)).length;
69144
69616
  if (Array.isArray(content.images)) return content.images.filter((item) => isObjectRecord(item) && isObjectRecord(item.image)).length;
69145
69617
  if (isObjectRecord(content.media) || isObjectRecord(content.entrancePhoto)) return 1;
69146
- const section$2 = isObjectRecord(content._sectionStyles) ? content._sectionStyles : {};
69147
- const background = isObjectRecord(section$2.background) ? section$2.background : {};
69148
- return isObjectRecord(background.image) ? 1 : 0;
69618
+ return storedSectionPhoto(content) === null ? 0 : 1;
69149
69619
  }
69150
69620
  function effectiveContentKnobValue(blockKind, key, value) {
69151
69621
  const facet = systemCustomizeFacetDefinitionsForBlock(blockKind).find((entry) => entry.target.kind === "content-field" && entry.target.field === key);
@@ -69169,11 +69639,12 @@ function applyArrangementRhythm(entry, position) {
69169
69639
  if (!runtime || !look) return entry;
69170
69640
  const rhythm = runtime.rhythm.length === 0 ? null : runtime.rhythm[position % runtime.rhythm.length];
69171
69641
  const content = entry.renderableContent;
69172
- const resolved = resolveSectionBackground(parseCanonicalRuntimeBackground(content), null, rhythm, heroPhotoGround(entry));
69642
+ const resolved = resolveSectionBackground(parseCanonicalRuntimeBackground(content), null, rhythm, heroPhotoGround(entry.block.kind, entry.kind === "renderable" ? entry.effectiveArrangementKey ?? undefined : undefined));
69173
69643
  const updated$1 = applyResolvedArrangementBackground(content, resolved);
69174
69644
  const surface = arrangementGroundToken(resolved);
69175
69645
  const grounded = resolveArrangementRoleSurfaces(look, runtime, resolved);
69176
69646
  const tinted = resolveArrangementTints(updated$1, grounded, runtime, surface) ?? grounded;
69647
+ const shape = sectionShapeHook(sectionShapeForGround(runtime.fieldGrounds, surface));
69177
69648
  return {
69178
69649
  ...entry,
69179
69650
  styleBackground: arrangementGroundToken(resolveSectionBackground({ kind: "none" }, null, rhythm)),
@@ -69182,7 +69653,8 @@ function applyArrangementRhythm(entry, position) {
69182
69653
  _effectiveLook: tinted,
69183
69654
  _lookHooks: {
69184
69655
  ...isObjectRecord(updated$1._lookHooks) ? updated$1._lookHooks : {},
69185
- "data-surface": surface
69656
+ "data-surface": surface,
69657
+ ...shape
69186
69658
  }
69187
69659
  }
69188
69660
  };
@@ -69292,9 +69764,13 @@ function resolveArrangementRoleSurfaces(look, runtime, background) {
69292
69764
  itemSurfaces: resolveLookSlotSurfaces(look, look.itemRoles, roleSurfaces)
69293
69765
  };
69294
69766
  }
69295
- /** The arrangement key is resolved once by planBlock, including pinned Looks. */
69296
- function heroPhotoGround(entry) {
69297
- return entry.kind === "renderable" && entry.block.kind === "block.hero" ? { paintsGround: heroPhotoPaintsGround(entry.effectiveArrangementKey ?? undefined) } : undefined;
69767
+ function heroPhotoGround(blockKind, arrangementKey) {
69768
+ return blockKind === "block.hero" ? { paintsGround: heroPhotoPaintsGround(arrangementKey) } : undefined;
69769
+ }
69770
+ /** Both admitted server openings and current editor projections use the decided arrangement key. */
69771
+ function pageOpeningPhotoPlacement(blockKind, content, arrangementKey) {
69772
+ const background = resolveSectionBackground(parseCanonicalRuntimeBackground(content), null);
69773
+ return resolveSectionPhotoPlacement(background, heroPhotoGround(blockKind, arrangementKey));
69298
69774
  }
69299
69775
  /** Header consumers receive the opening that the public render plan actually admits. */
69300
69776
  function resolvePageOpeningSection(page, options) {
@@ -69311,7 +69787,7 @@ function resolvePageOpeningSection(page, options) {
69311
69787
  blockOverrides: undefined
69312
69788
  }).entries[0];
69313
69789
  if (!opening) return null;
69314
- const appearance = resolveCompiledSectionContextFromContent(opening.renderableContent, expandPalette(options.theme.palette), heroPhotoGround(opening));
69790
+ const appearance = resolveCompiledSectionContextFromContent(opening.renderableContent, expandPalette(options.theme.palette), heroPhotoGround(opening.block.kind, opening.kind === "renderable" ? opening.effectiveArrangementKey ?? undefined : undefined));
69315
69791
  return {
69316
69792
  blockKind: opening.block.kind,
69317
69793
  content: opening.renderableContent,
@@ -69670,12 +70146,12 @@ function shouldSkipResolvedLoader(input) {
69670
70146
  async function prefetchBlockData(page, context, options) {
69671
70147
  return (await prefetchBlockDataWithFailures(page, context, options)).resolvedData;
69672
70148
  }
69673
- async function prefetchBlockDataWithFailures(page, context, options) {
70149
+ /** Resolve once through the shared bindings owner; request reuse never reuses content provenance. */
70150
+ function planBlockDataRequests(page, context, options = {}) {
69674
70151
  const runtime = admitLoaderDateRuntime(context);
69675
70152
  const blocks = page.blocks.flatMap((block) => block.id ? [planBlockRequests(block, block.id, context, options, runtime)] : []);
69676
- const outcomes = await Promise.all(blocks.flatMap((block) => block.requests.map((request) => executeLoaderRequest(request, options))));
69677
70153
  return {
69678
- ...projectLoaderOutcomes(blocks, outcomes),
70154
+ blocks,
69679
70155
  loaderSnapshot: {
69680
70156
  stage: context.previewStage === "preview" ? "draft" : "published",
69681
70157
  blocks: Object.fromEntries(blocks.map((block) => [block.id, {
@@ -69689,6 +70165,17 @@ async function prefetchBlockDataWithFailures(page, context, options) {
69689
70165
  }
69690
70166
  };
69691
70167
  }
70168
+ async function prefetchBlockDataWithFailures(page, context, options) {
70169
+ const plan = planBlockDataRequests(page, context, options);
70170
+ const outcomes = await Promise.all(plan.blocks.flatMap((block) => block.requests.map((request) => executeBlockDataRequest(request, options))));
70171
+ return projectBlockDataOutcomes(plan, outcomes);
70172
+ }
70173
+ function projectBlockDataOutcomes(plan, outcomes) {
70174
+ return {
70175
+ ...projectLoaderOutcomes(plan.blocks, outcomes),
70176
+ loaderSnapshot: plan.loaderSnapshot
70177
+ };
70178
+ }
69692
70179
  function planBlockRequests(block, id, context, options, runtime) {
69693
70180
  const definition$1 = (options.getBlockDefinition ?? getBlockDefinition)(block.kind);
69694
70181
  const loaders = definition$1 ? normalizeDataLoaders(definition$1) : customLoaders(block.kind, options);
@@ -69738,7 +70225,7 @@ function planLoaderRequest({ key, loader }, block, blockId, vm, options, runtime
69738
70225
  params
69739
70226
  };
69740
70227
  }
69741
- async function executeLoaderRequest(request, options) {
70228
+ async function executeBlockDataRequest(request, options) {
69742
70229
  try {
69743
70230
  return {
69744
70231
  kind: "loaded",
@@ -78764,7 +79251,8 @@ const THEME_FIELD_CATEGORY_MAP = {
78764
79251
  "Site Style Dressing": [
78765
79252
  "skin",
78766
79253
  "skinTokens",
78767
- "skinMarks"
79254
+ "skinMarks",
79255
+ "skinBookingBar"
78768
79256
  ],
78769
79257
  "Custom CSS": [
78770
79258
  "customCssRules",
@@ -79560,9 +80048,21 @@ function renderSystemBlockDefinition(definition$1) {
79560
80048
  } else {
79561
80049
  lines.push(...renderFieldList(manifest.fields, 0));
79562
80050
  }
80051
+ lines.push(...renderLookOwnedFields(manifest));
79563
80052
  lines.push("");
79564
80053
  return lines;
79565
80054
  }
80055
+ /** Fields an arrangement Look takes over, from the same decision the editor uses. */
80056
+ function renderLookOwnedFields(manifest) {
80057
+ if (!blockHasArrangementLooks(manifest.name)) return [];
80058
+ const ownership = resolveFieldOwnership({
80059
+ blockKind: manifest.name,
80060
+ manifest,
80061
+ arrangementLook: true
80062
+ });
80063
+ const paths = fieldPathsOwnedBy(ownership, ["look"]);
80064
+ return paths.length === 0 ? [] : ["", `On site styles with Looks, the Look sets these while it shows the block, and stored values have no effect: ${paths.join(", ")}`];
80065
+ }
79566
80066
  function renderVariantDocumentation(manifest) {
79567
80067
  if (!manifest.variants || Object.keys(manifest.variants).length === 0) {
79568
80068
  return [];
@@ -80048,7 +80548,7 @@ async function loadConfig(configPath, output) {
80048
80548
  return { errorMessage: "No config path provided." };
80049
80549
  }
80050
80550
  try {
80051
- const { loadConfigFile: loadConfigFile$1 } = await import("../load-config-BcATOVmw.mjs");
80551
+ const { loadConfigFile: loadConfigFile$1 } = await import("../load-config-DX04ekBQ.mjs");
80052
80552
  const rawConfig = await loadConfigFile$1(configPath);
80053
80553
  const parsed = riverbankSiteConfigSchema.safeParse(rawConfig);
80054
80554
  if (!parsed.success) {
@@ -93915,7 +94415,7 @@ async function publishContentEntry(apiClient, { type, siteId, entryId, body, opt
93915
94415
  return normalizeApiError(error$1, "Failed to publish entry");
93916
94416
  }
93917
94417
  }
93918
- async function scheduleContentEntry(apiClient, { type, siteId, entryId, publishAt, options }) {
94418
+ async function scheduleContentEntry(apiClient, { type, siteId, entryId, publishAt, expectedPublishAt, options }) {
93919
94419
  try {
93920
94420
  return unwrapResponse(await apiClient({
93921
94421
  endpoint: "scheduleContentEntry",
@@ -93924,21 +94424,29 @@ async function scheduleContentEntry(apiClient, { type, siteId, entryId, publishA
93924
94424
  type,
93925
94425
  entryId
93926
94426
  },
93927
- body: { publishAt },
94427
+ body: expectedPublishAt === undefined ? { publishAt } : {
94428
+ publishAt,
94429
+ expectedPublishAt
94430
+ },
93928
94431
  options
93929
94432
  }));
93930
94433
  } catch (error$1) {
93931
94434
  return normalizeApiError(error$1, "Failed to schedule publish");
93932
94435
  }
93933
94436
  }
93934
- async function cancelScheduledContentEntry(apiClient, { type, siteId, entryId, options }) {
94437
+ async function cancelScheduledContentEntry(apiClient, { type, siteId, entryId, expectedPublishAt, options }) {
93935
94438
  try {
93936
94439
  return unwrapResponse(await apiClient({
93937
94440
  endpoint: "cancelScheduledContentEntry",
93938
- params: {
94441
+ params: expectedPublishAt === undefined ? {
93939
94442
  siteId,
93940
94443
  type,
93941
94444
  entryId
94445
+ } : {
94446
+ siteId,
94447
+ type,
94448
+ entryId,
94449
+ expectedPublishAt
93942
94450
  },
93943
94451
  options
93944
94452
  }));
@@ -94125,12 +94633,13 @@ const blocksKeys = {
94125
94633
  function normalizeError(error$1, fallback) {
94126
94634
  return normalizeApiError(error$1, fallback);
94127
94635
  }
94128
- async function createBlock(apiClient, { siteId, pageId, kind, position, purpose, duplicatedFromBlockId, options }) {
94636
+ async function createBlock(apiClient, { siteId, pageId, kind, position, purpose, duplicatedFromBlockId, initialLookId, options }) {
94129
94637
  const payload = {
94130
94638
  kind,
94131
94639
  position,
94132
94640
  purpose,
94133
- duplicatedFromBlockId
94641
+ duplicatedFromBlockId,
94642
+ ...initialLookId ? { initialLookId } : {}
94134
94643
  };
94135
94644
  try {
94136
94645
  return unwrapResponse(await apiClient({
@@ -94450,16 +94959,6 @@ async function savePageDesignState(apiClient, { siteId, pageId, body, options })
94450
94959
  options
94451
94960
  }));
94452
94961
  }
94453
- async function getPageDesignEditorState(apiClient, { siteId, pageId, options }) {
94454
- return unwrapResponse(await apiClient({
94455
- endpoint: "getPageDesignEditorState",
94456
- params: {
94457
- siteId,
94458
- pageId
94459
- },
94460
- options
94461
- }));
94462
- }
94463
94962
  async function applyPageDesignEditorAction(apiClient, { siteId, pageId, body, options }) {
94464
94963
  return unwrapResponse(await apiClient({
94465
94964
  endpoint: "applyPageDesignEditorAction",