@riverbankcms/sdk 0.135.1 → 0.137.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +114 -0
- package/README.md +4 -8
- package/dist/{PreviewEditorSidebar-D4p_5TdY.mjs → PreviewEditorSidebar-Bn6cONPa.mjs} +8 -8
- package/dist/{PreviewEditorUI-D0cRoTX1.mjs → PreviewEditorUI-LAwXZPSx.mjs} +3 -3
- package/dist/{PreviewQueryProvider-DcgaESkm.mjs → PreviewQueryProvider-ztQUdsNo.mjs} +1 -1
- package/dist/{SdkPreviewModeRuntime-BKLtM3Nz.mjs → SdkPreviewModeRuntime-BbbGsI_v.mjs} +621 -238
- package/dist/{SiteChromeCustomizeContext-61X2m7QV.mjs → SiteChromeCustomizeContext-BbkNSt5a.mjs} +5041 -2407
- package/dist/_dts/ai/src/contracts/proposals.d.ts +18 -850
- package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +412 -2316
- package/dist/_dts/ai/src/designer/themePatch.d.ts +5 -10
- package/dist/_dts/api/src/accessAdmin.d.ts +1 -9
- package/dist/_dts/api/src/accountApi.d.ts +49 -2
- package/dist/_dts/api/src/contentRuntime.d.ts +7 -4
- package/dist/_dts/api/src/domainConnection.d.ts +41 -0
- package/dist/_dts/api/src/endpoints.d.ts +201 -181
- package/dist/_dts/api/src/index.d.ts +5 -3
- package/dist/_dts/api/src/media.d.ts +19 -2
- package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +7 -0
- package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +26 -0
- package/dist/_dts/api/src/sdkBlockContentAdmission.d.ts +5 -0
- package/dist/_dts/api/src/sdkContracts.d.ts +2 -15
- package/dist/_dts/api/src/sdkMediaContracts.d.ts +40 -0
- package/dist/_dts/api/src/sdkMediaEndpointDefinitions.d.ts +61 -0
- package/dist/_dts/api/src/sdkThemeWire.d.ts +21 -436
- package/dist/_dts/api/src/siteInfrastructure.d.ts +17 -23
- package/dist/_dts/api/src/siteManagementEndpoints.d.ts +7 -21
- package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +27 -3
- package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +37 -17
- package/dist/_dts/api/src/types.d.ts +1 -1
- package/dist/_dts/block-form/src/blockDraftSaveability.d.ts +2 -3
- package/dist/_dts/block-form/src/utils/slug.d.ts +6 -0
- package/dist/_dts/blocks/src/PageRenderer.d.ts +13 -7
- package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +48 -0
- package/dist/_dts/blocks/src/definitions.d.ts +14 -0
- package/dist/_dts/blocks/src/index.d.ts +4 -3
- package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +49 -0
- package/dist/_dts/blocks/src/pageRendererBlockSupport.d.ts +75 -0
- package/dist/_dts/blocks/src/pageRendererBoundaries.d.ts +2 -0
- package/dist/_dts/blocks/src/server.d.ts +2 -2
- package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +1 -1
- package/dist/_dts/blocks/src/system/data/index.d.ts +2 -0
- package/dist/_dts/blocks/src/system/data/publicLoaderCachePolicy.d.ts +78 -0
- package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +2 -18
- package/dist/_dts/blocks/src/system/manifest/validation.d.ts +103 -16
- package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +4 -2
- package/dist/_dts/blocks/src/system/runtime/api/endpoints.d.ts +8 -0
- package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +19 -0
- package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +52 -0
- package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +24 -0
- package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.d.ts +47 -21
- package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.state.d.ts +38 -9
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/ErrorStep.d.ts +3 -5
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/VerifyingTimeoutStep.d.ts +3 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationErrorPresentation.d.ts +5 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationErrorRecovery.d.ts +25 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationWizardContext.d.ts +4 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.d.ts +8 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +5 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useWaitlistClaimRestoration.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.client.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.interactive.d.ts +40 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +43 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/capacity.d.ts +164 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/cta.d.ts +29 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/dates.d.ts +47 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/index.d.ts +14 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/people.d.ts +6 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/pricing.d.ts +31 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarDayCell.d.ts +3 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarNavigationChevron.d.ts +4 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/DayEventsModal.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventModalContext.d.ts +3 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/OfferingTitle.d.ts +11 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekAgendaView.d.ts +4 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekBoardView.d.ts +31 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekTimetableView.d.ts +3 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +9 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/index.d.ts +3 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/listingLayout.d.ts +23 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/timetableModel.d.ts +4 -3
- package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +0 -1
- package/dist/_dts/calendar/src/grid.d.ts +24 -66
- package/dist/_dts/calendar/src/index.d.ts +2 -2
- package/dist/_dts/calendar/src/timetable.d.ts +5 -9
- package/dist/_dts/commerce/src/purchase/allocation.d.ts +11 -0
- package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +57 -0
- package/dist/_dts/commerce/src/purchase/index.d.ts +3 -0
- package/dist/_dts/commerce/src/purchase/settlement.d.ts +33 -0
- package/dist/_dts/commerce/src/purchase/stripeCheckoutReturnUrl.d.ts +8 -0
- package/dist/_dts/content-model/src/templates/defaults.d.ts +6 -0
- package/dist/_dts/core/src/slug.d.ts +20 -5
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +8 -40
- package/dist/_dts/db/src/index.d.ts +1 -0
- package/dist/_dts/db/src/utils/postgrestFilter.d.ts +2 -0
- package/dist/_dts/media-core/src/bulkDeletePlanning.d.ts +4 -0
- package/dist/_dts/media-core/src/fileDomain.d.ts +3 -0
- package/dist/_dts/preview-next/src/client/blocks/EditablePageRenderer.d.ts +1 -1
- package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +1 -0
- package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +1 -0
- package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +3 -2
- package/dist/_dts/preview-next/src/client/preview/headerInteractionPaletteSurfaceState.d.ts +2 -1
- package/dist/_dts/preview-next/src/client/preview/siteChromeBrandPreferences.d.ts +1 -1
- package/dist/_dts/preview-next/src/client/preview/siteChromeQuickControlHistoryState.d.ts +2 -0
- package/dist/_dts/preview-next/src/client/preview/siteChromeQuickControlSaveRequest.d.ts +51 -0
- package/dist/_dts/preview-next/src/client/preview/siteChromeSavePlan.d.ts +24 -2
- package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +23 -1
- package/dist/_dts/preview-next/src/client/preview/usePersistedHeaderPreferences.d.ts +8 -0
- package/dist/_dts/sdk/src/client/publicLoaderCacheAccess.d.ts +6 -0
- package/dist/_dts/sdk/src/public-api/contracts.d.ts +7 -2
- package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +10 -6
- package/dist/_dts/sdk/src/rendering/components/Block.shared.d.ts +0 -1
- package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +4 -4
- package/dist/_dts/sdk/src/rendering/helpers/footerPageOutline.d.ts +3 -0
- package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +3 -0
- package/dist/_dts/sdk/src/rendering/helpers/loadPage.d.ts +1 -1
- package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +17 -0
- package/dist/_dts/sdk/src/rendering/helpers/templateContent.d.ts +9 -3
- package/dist/_dts/sdk/src/rendering/hooks/usePage.d.ts +1 -1
- package/dist/_dts/sdk/src/rendering/index.d.ts +2 -2
- package/dist/_dts/sdk/src/rendering/overrideResolution.d.ts +7 -4
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/theme-core/src/cards/types.d.ts +8 -8
- package/dist/_dts/theme-core/src/data.d.ts +12 -0
- package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
- package/dist/_dts/theme-core/src/gradients/types.d.ts +5 -0
- package/dist/_dts/theme-core/src/header/interactionPalette.d.ts +25 -2
- package/dist/_dts/theme-core/src/header/legacyHeaderVariant.d.ts +2 -6
- package/dist/_dts/theme-core/src/mock-themes/all.d.ts +9 -810
- package/dist/_dts/theme-core/src/schema.d.ts +460 -1285
- package/dist/_dts/theme-core/src/site-styles/compilationPlan.d.ts +43 -3
- package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +223 -1
- package/dist/_dts/theme-core/src/site-styles/headerBrandPresentation.d.ts +63 -0
- package/dist/_dts/theme-core/src/site-styles/headerBytesComparison.d.ts +30 -0
- package/dist/_dts/theme-core/src/site-styles/headerInteractionPalette.d.ts +50 -1
- package/dist/_dts/theme-core/src/site-styles/headerLayoutCatalog.d.ts +48 -38
- package/dist/_dts/theme-core/src/site-styles/headerLayoutStyles.d.ts +10 -0
- package/dist/_dts/theme-core/src/site-styles/headerLayoutTypes.d.ts +8 -5
- package/dist/_dts/theme-core/src/site-styles/headerOpeningForeground.d.ts +4 -4
- package/dist/_dts/theme-core/src/site-styles/headerPreferences.d.ts +162 -0
- package/dist/_dts/theme-core/src/site-styles/headerPreferencesPersistence.d.ts +73 -0
- package/dist/_dts/theme-core/src/site-styles/headerRecompile.d.ts +118 -0
- package/dist/_dts/theme-core/src/site-styles/headerStyleCompiler.d.ts +25 -2
- package/dist/_dts/theme-core/src/site-styles/headerStyleDefaults.d.ts +465 -0
- package/dist/_dts/theme-core/src/site-styles/headerStyleRecipe.d.ts +168 -0
- package/dist/_dts/theme-core/src/site-styles/index.d.ts +5 -0
- package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +1 -1
- package/dist/_dts/theme-core/src/site-styles/siteChromeBackgrounds.d.ts +20 -1
- package/dist/_dts/theme-core/src/site-styles/siteChromeNavPreferences.d.ts +43 -2
- package/dist/client/{BookingConsentAgreement-Bz9znbpn.mjs → BookingConsentAgreement--_fUCZe-.mjs} +2 -2
- package/dist/client/{DiscountCodeDisclosure-35Ru8yB9.mjs → DiscountCodeDisclosure-BMipSoDJ.mjs} +1 -1
- package/dist/client/{EventCombined.client-BKB0ZxRR.mjs → EventCombined.client-CwJOxn7A.mjs} +274 -278
- package/dist/client/{EventListing.client-Dx8I21ok.mjs → EventListing.client-eVwiylPW.mjs} +2 -2
- package/dist/client/{LeafletStaticMap-CEWx-Bhe.mjs → LeafletStaticMap-IKenna5u.mjs} +1 -1
- package/dist/client/{accordion-KIDsKTwS.mjs → accordion-MGAO3PuE.mjs} +1 -1
- package/dist/client/{bookingForm-D96Rmp-5.mjs → bookingForm-CudlQPUu.mjs} +5 -5
- package/dist/client/bookings.mjs +476 -98
- package/dist/client/capacity-BW00PO7s.mjs +271 -0
- package/dist/client/{carousel-YwUgyL66.mjs → carousel-BrbGJ2Jl.mjs} +1 -1
- package/dist/client/{cart-BbwuNrUT.mjs → cart-Bq5eU0xZ.mjs} +3 -3
- package/dist/client/{checkout-hp1ucmEY.mjs → checkout-BAFVRdrK.mjs} +3 -3
- package/dist/client/client.mjs +4641 -2721
- package/dist/client/{context-DljQn8L5.mjs → context-DCkiHVdD.mjs} +20 -5
- package/dist/client/dates-2RPXHQy4.mjs +264 -0
- package/dist/client/{eventCalendar-DU4iNLpo.mjs → eventCalendar-B0O-hPF7.mjs} +261 -126
- package/dist/client/{eventCombined-CZuupW8m.mjs → eventCombined-DCkDaoDI.mjs} +3 -3
- package/dist/client/{eventDetails-DPQWwCIi.mjs → eventDetails-D8GG2dnD.mjs} +7 -4
- package/dist/client/{eventListing-C7oMidwS.mjs → eventListing-3ssV_bxz.mjs} +3 -3
- package/dist/client/{eventRegistration-zEiunlUs.mjs → eventRegistration-bPQo3kVw.mjs} +610 -313
- package/dist/client/{form-D2KIyCVJ.mjs → form-qMv8RDkk.mjs} +2 -2
- package/dist/client/{headerSection-CK5uChUK.mjs → headerSection-CH0Sc5hX.mjs} +2 -2
- package/dist/client/hooks.mjs +2514 -308
- package/dist/client/{locationMap-DLQNH1ln.mjs → locationMap-0_xlBnNI.mjs} +2 -2
- package/dist/client/{newsletterForm-ZuhIG7fZ.mjs → newsletterForm-NUW7m9RI.mjs} +2 -2
- package/dist/client/{productDetail-7hIcGeae.mjs → productDetail-FBEOM7jW.mjs} +3 -3
- package/dist/client/{productList-T4Cii1ot.mjs → productList-R0OSGhnn.mjs} +3 -3
- package/dist/client/{propsDecoder-mB0aC_Fi.mjs → propsDecoder-pYvx_Srl.mjs} +179 -401
- package/dist/client/rendering/client.mjs +3496 -2223
- package/dist/client/rendering/islands.mjs +17 -17
- package/dist/client/rendering.mjs +4400 -2510
- package/dist/client/{scrollToBlock-Du5mHgvL.mjs → scrollToBlock-ByQv96M2.mjs} +1 -1
- package/dist/client/{shop-B5zAcKZn.mjs → shop-RUG9DmRE.mjs} +6 -6
- package/dist/client/{shop-commerce-BKBZB6l5.mjs → shop-commerce-B76Jz23B.mjs} +5 -5
- package/dist/client/{shop-commerce-store-Cq4qlNtQ.mjs → shop-commerce-store-QuQNdDsD.mjs} +1 -1
- package/dist/client/{shopShared-DYGzEs9D.mjs → shopShared-vXU1omwJ.mjs} +3 -3
- package/dist/client/{useEventFilters-Bphkda8m.mjs → useEventFilters-ByuU6HLA.mjs} +33 -18
- package/dist/preview-next/before-render.mjs +86 -51
- package/dist/preview-next/client/runtime.mjs +4 -4
- package/dist/preview-next/keepAlive.mjs +86 -51
- package/dist/preview-next/middleware.mjs +86 -51
- package/dist/{previewAuthStore-C7ksxt5b.mjs → previewAuthStore-L_cKW8Sb.mjs} +86 -51
- package/dist/{sdk-runtime-BbIC8G4J.mjs → sdk-runtime-sUMr5d70.mjs} +2 -2
- package/dist/{separator-CadhAtI7.mjs → separator-BIHkie5i.mjs} +1 -1
- package/dist/server/components.mjs +4397 -2960
- package/dist/server/config-validation.mjs +354 -145
- package/dist/server/config.mjs +354 -145
- package/dist/server/data.mjs +354 -144
- package/dist/server/index.mjs +201 -55
- package/dist/server/manifest.mjs +0 -1
- package/dist/server/next.mjs +4046 -2611
- package/dist/server/page-converter.mjs +225 -122
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +4105 -2636
- package/dist/server/rendering.mjs +4522 -3087
- package/dist/server/routing.mjs +3289 -1637
- package/dist/server/server.mjs +23175 -21079
- package/dist/server/theme-bridge.mjs +708 -272
- package/dist/server/theme.mjs +29 -25
- package/dist/styles/index.css +624 -181
- package/package.json +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCapacity.d.ts +0 -48
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/pricing.d.ts +0 -17
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/utils.d.ts +0 -100
- /package/dist/_dts/blocks/src/system/runtime/nodes/events/{shared → domain}/destination.d.ts +0 -0
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { D as clsx } from "./colorStyles-CrxJrPjJ.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { a as EventCardClient, i as EventPaginatedListView, n as useEventPagination, o as EventFilters, r as toError, t as useEventFilters } from "./useEventFilters-
|
|
5
|
-
import {
|
|
3
|
+
import { Dt as buildBookingUtcDateWindow, Ft as getLocalScheduleDate, L as getCardOrientation, M as buildEventRuntimeFilters, N as getEventRuntimeFiltersKey, Nt as formatLocalScheduleDate, R as getContainerClass, X as themeButtonClassName, z as formatEventPrice } from "./propsDecoder-pYvx_Srl.mjs";
|
|
4
|
+
import { a as EventCardClient, i as EventPaginatedListView, n as useEventPagination, o as EventFilters, r as toError, s as formatEventTeacherLine, t as useEventFilters } from "./useEventFilters-ByuU6HLA.mjs";
|
|
5
|
+
import { r as formatEventRemainingPlaces, u as isEventFull } from "./capacity-BW00PO7s.mjs";
|
|
6
|
+
import { a as groupEventsByDate, i as formatTime, l as resolveEventLinkProps, t as formatDate } from "./dates-2RPXHQy4.mjs";
|
|
7
|
+
import { n as useBlockApi } from "./context-DCkiHVdD.mjs";
|
|
6
8
|
import { t as createBodyThemePortalRoot } from "./themePortalRoot-AGs4cE7t.mjs";
|
|
7
9
|
import { t as ModalShell } from "./ModalShell-CqkBvBIC.mjs";
|
|
8
|
-
import React, { createContext, useCallback, useContext, useEffect, useId, useMemo,
|
|
10
|
+
import React, { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
|
|
9
11
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
12
|
//#region ../calendar/src/grid.ts
|
|
11
13
|
const DAY_NAMES = [
|
|
@@ -31,111 +33,73 @@ const MONTH_NAMES = [
|
|
|
31
33
|
"November",
|
|
32
34
|
"December"
|
|
33
35
|
];
|
|
34
|
-
/** Format a date as YYYY-MM-DD using the runtime's local timezone. */
|
|
35
36
|
function formatDateKey(date) {
|
|
36
|
-
return `${date.
|
|
37
|
+
return `${String(date.year).padStart(4, "0")}-${String(date.month).padStart(2, "0")}-${String(date.day).padStart(2, "0")}`;
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
* `now` defaults to `new Date()` so casual callers don't need to thread it,
|
|
41
|
-
* but tests and snapshot-rendering should pass an explicit value.
|
|
42
|
-
*/
|
|
43
|
-
function isToday(date, now = /* @__PURE__ */ new Date()) {
|
|
44
|
-
return isSameLocalDay(date, now);
|
|
39
|
+
function isToday(date, today) {
|
|
40
|
+
return isSameCalendarDay(date, today);
|
|
45
41
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return left.getFullYear() === right.getFullYear() && left.getMonth() === right.getMonth() && left.getDate() === right.getDate();
|
|
42
|
+
function isSameCalendarDay(left, right) {
|
|
43
|
+
return left.year === right.year && left.month === right.month && left.day === right.day;
|
|
49
44
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const year = date.getFullYear();
|
|
57
|
-
const month = date.getMonth();
|
|
58
|
-
const day = date.getDate();
|
|
59
|
-
const hours = date.getHours();
|
|
60
|
-
const minutes = date.getMinutes();
|
|
61
|
-
const seconds = date.getSeconds();
|
|
62
|
-
const ms = date.getMilliseconds();
|
|
63
|
-
const base = new Date(year, month + months, 1, hours, minutes, seconds, ms);
|
|
64
|
-
const lastDayOfTargetMonth = new Date(base.getFullYear(), base.getMonth() + 1, 0).getDate();
|
|
65
|
-
base.setDate(Math.min(day, lastDayOfTargetMonth));
|
|
66
|
-
return base;
|
|
45
|
+
function getStartOfMonth(date) {
|
|
46
|
+
return {
|
|
47
|
+
year: date.year,
|
|
48
|
+
month: date.month,
|
|
49
|
+
day: 1
|
|
50
|
+
};
|
|
67
51
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const result = new Date(date);
|
|
71
|
-
result.setDate(result.getDate() + days);
|
|
72
|
-
return result;
|
|
52
|
+
function getEndOfMonth(date) {
|
|
53
|
+
return addDays(addMonths(getStartOfMonth(date), 1), -1);
|
|
73
54
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
55
|
+
function addMonths(date, months) {
|
|
56
|
+
const target = new Date(Date.UTC(date.year, date.month - 1 + months, 1, 12));
|
|
57
|
+
const year = target.getUTCFullYear();
|
|
58
|
+
const month = target.getUTCMonth() + 1;
|
|
59
|
+
const lastDay = new Date(Date.UTC(year, month, 0, 12)).getUTCDate();
|
|
60
|
+
return {
|
|
61
|
+
year,
|
|
62
|
+
month,
|
|
63
|
+
day: Math.min(date.day, lastDay)
|
|
64
|
+
};
|
|
78
65
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
* with UTC midnight bounds. Suitable for prefetching event windows when
|
|
82
|
-
* the consumer handles timezone conversion downstream.
|
|
83
|
-
*/
|
|
84
|
-
function getThreeMonthRange(date) {
|
|
85
|
-
const year = date.getFullYear();
|
|
86
|
-
const month = date.getMonth();
|
|
87
|
-
const prevStart = new Date(year, month - 1, 1);
|
|
88
|
-
const nextEnd = new Date(year, month + 2, 0);
|
|
66
|
+
function addDays(date, days) {
|
|
67
|
+
const result = new Date(Date.UTC(date.year, date.month - 1, date.day + days, 12));
|
|
89
68
|
return {
|
|
90
|
-
|
|
91
|
-
|
|
69
|
+
year: result.getUTCFullYear(),
|
|
70
|
+
month: result.getUTCMonth() + 1,
|
|
71
|
+
day: result.getUTCDate()
|
|
92
72
|
};
|
|
93
73
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
*/
|
|
74
|
+
function shiftCalendarAnchorDate(date, view, steps) {
|
|
75
|
+
return view === "week" ? addDays(date, steps * 7) : addMonths(date, steps);
|
|
76
|
+
}
|
|
98
77
|
function getMonthCalendarDays(year, month, startOfWeek) {
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const nextDay = days.length - startOffset - lastDayOfMonth.getDate() + 1;
|
|
108
|
-
days.push(new Date(year, month + 1, nextDay));
|
|
109
|
-
}
|
|
110
|
-
return days;
|
|
78
|
+
const firstDay = {
|
|
79
|
+
year,
|
|
80
|
+
month,
|
|
81
|
+
day: 1
|
|
82
|
+
};
|
|
83
|
+
const dayOfWeek = getDayOfWeek(firstDay);
|
|
84
|
+
const gridStart = addDays(firstDay, -(startOfWeek === "monday" ? dayOfWeek === 0 ? 6 : dayOfWeek - 1 : dayOfWeek));
|
|
85
|
+
return Array.from({ length: 42 }, (_, index) => addDays(gridStart, index));
|
|
111
86
|
}
|
|
112
|
-
/** Build the 7 dates of the week containing `baseDate`. */
|
|
113
87
|
function getWeekCalendarDays(baseDate, startOfWeek) {
|
|
114
|
-
const
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const date = new Date(weekStart);
|
|
121
|
-
date.setDate(weekStart.getDate() + i);
|
|
122
|
-
days.push(date);
|
|
123
|
-
}
|
|
124
|
-
return days;
|
|
88
|
+
const dayOfWeek = getDayOfWeek(baseDate);
|
|
89
|
+
const weekStart = addDays(baseDate, -(startOfWeek === "monday" ? dayOfWeek === 0 ? 6 : dayOfWeek - 1 : dayOfWeek));
|
|
90
|
+
return Array.from({ length: 7 }, (_, index) => addDays(weekStart, index));
|
|
91
|
+
}
|
|
92
|
+
function getDayOfWeek(date) {
|
|
93
|
+
return new Date(Date.UTC(date.year, date.month - 1, date.day, 12)).getUTCDay();
|
|
125
94
|
}
|
|
126
|
-
/** Build the 7 dates of the week containing `baseDate` as a fixed-width tuple. */
|
|
127
95
|
function getWeekCalendarDayTuple(baseDate, startOfWeek) {
|
|
128
96
|
const days = getWeekCalendarDays(baseDate, startOfWeek);
|
|
129
97
|
assertWeekCalendarDays(days);
|
|
130
98
|
return days;
|
|
131
99
|
}
|
|
132
100
|
function assertWeekCalendarDays(days) {
|
|
133
|
-
if (days.length !== 7) throw new Error("Expected
|
|
101
|
+
if (days.length !== 7) throw new Error("Expected exactly 7 calendar days");
|
|
134
102
|
}
|
|
135
|
-
/**
|
|
136
|
-
* Day-name labels reordered for the chosen week start. Pass a custom
|
|
137
|
-
* `dayNames` array (length 7, Sunday-first) to localize.
|
|
138
|
-
*/
|
|
139
103
|
function getOrderedDayNames(startOfWeek, dayNames = DAY_NAMES) {
|
|
140
104
|
if (startOfWeek === "monday") {
|
|
141
105
|
const sunday = dayNames[0] ?? "Sun";
|
|
@@ -143,22 +107,17 @@ function getOrderedDayNames(startOfWeek, dayNames = DAY_NAMES) {
|
|
|
143
107
|
}
|
|
144
108
|
return [...dayNames];
|
|
145
109
|
}
|
|
146
|
-
/**
|
|
147
|
-
* Header title for a calendar view.
|
|
148
|
-
* - month: "January 2025"
|
|
149
|
-
* - week: "January 5 - 11, 2025" or "December 30 - January 5, 2025"
|
|
150
|
-
*/
|
|
151
110
|
function formatCalendarTitle(viewDate, view, days, monthNames = MONTH_NAMES) {
|
|
152
111
|
if (view === "week") {
|
|
153
112
|
const weekStart = days[0];
|
|
154
113
|
const weekEnd = days[6];
|
|
155
|
-
if (weekStart === void 0 || weekEnd === void 0) return `${monthNames[viewDate.
|
|
156
|
-
const startMonth = monthNames[weekStart.
|
|
157
|
-
const endMonth = monthNames[weekEnd.
|
|
158
|
-
if (weekStart.
|
|
159
|
-
return `${startMonth} ${weekStart.
|
|
114
|
+
if (weekStart === void 0 || weekEnd === void 0) return `${monthNames[viewDate.month - 1] ?? ""} ${viewDate.year}`;
|
|
115
|
+
const startMonth = monthNames[weekStart.month - 1] ?? "";
|
|
116
|
+
const endMonth = monthNames[weekEnd.month - 1] ?? "";
|
|
117
|
+
if (weekStart.month === weekEnd.month) return `${startMonth} ${weekStart.day} - ${weekEnd.day}, ${weekEnd.year}`;
|
|
118
|
+
return `${startMonth} ${weekStart.day} - ${endMonth} ${weekEnd.day}, ${weekEnd.year}`;
|
|
160
119
|
}
|
|
161
|
-
return `${monthNames[viewDate.
|
|
120
|
+
return `${monthNames[viewDate.month - 1] ?? ""} ${viewDate.year}`;
|
|
162
121
|
}
|
|
163
122
|
function buildCalendarViewport(input) {
|
|
164
123
|
const monthNames = input.monthNames ?? MONTH_NAMES;
|
|
@@ -168,10 +127,10 @@ function buildCalendarViewport(input) {
|
|
|
168
127
|
kind: "week",
|
|
169
128
|
anchorDate: input.anchorDate,
|
|
170
129
|
days,
|
|
171
|
-
title: formatCalendarTitle(input.anchorDate, "week",
|
|
130
|
+
title: formatCalendarTitle(input.anchorDate, "week", days, monthNames)
|
|
172
131
|
};
|
|
173
132
|
}
|
|
174
|
-
const days = getMonthCalendarDays(input.anchorDate.
|
|
133
|
+
const days = getMonthCalendarDays(input.anchorDate.year, input.anchorDate.month, input.startOfWeek);
|
|
175
134
|
return {
|
|
176
135
|
kind: "month",
|
|
177
136
|
anchorDate: input.anchorDate,
|
|
@@ -250,25 +209,80 @@ const TabBar = ({ tabs, activeTab, onTabChange, className }) => {
|
|
|
250
209
|
};
|
|
251
210
|
//#endregion
|
|
252
211
|
//#region ../blocks/src/system/runtime/hooks/useCalendarEvents.state.ts
|
|
253
|
-
function
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
212
|
+
function calendarMonthKey(date) {
|
|
213
|
+
return `${date.year}-${String(date.month).padStart(2, "0")}`;
|
|
214
|
+
}
|
|
215
|
+
function calendarWindowMonths(date, radius) {
|
|
216
|
+
const months = [];
|
|
217
|
+
for (let offset = -radius; offset <= radius; offset++) months.push(calendarMonthKey(addMonths(date, offset)));
|
|
218
|
+
return months;
|
|
219
|
+
}
|
|
220
|
+
function groupEvents(events, timeZone) {
|
|
221
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
222
|
+
for (const event of events) {
|
|
223
|
+
const key = calendarMonthKey(getLocalScheduleDate(new Date(event.startsAt), timeZone));
|
|
224
|
+
const month = grouped.get(key) ?? [];
|
|
225
|
+
if (!month.some((existing) => existing.id === event.id)) month.push(event);
|
|
226
|
+
grouped.set(key, month);
|
|
227
|
+
}
|
|
228
|
+
return grouped;
|
|
229
|
+
}
|
|
230
|
+
function seedCalendarCache(events, timeZone) {
|
|
231
|
+
return new Map([...groupEvents(events, timeZone)].map(([key, values]) => [key, {
|
|
232
|
+
kind: "seeded",
|
|
233
|
+
events: values
|
|
234
|
+
}]));
|
|
235
|
+
}
|
|
236
|
+
function planCalendarRequest(state, months, retry) {
|
|
237
|
+
const missing = months.filter((key) => {
|
|
238
|
+
const month = state.get(key);
|
|
239
|
+
return !month || month.kind === "seeded" || retry && month.kind === "failed";
|
|
240
|
+
});
|
|
241
|
+
return missing.length > 0 ? { months: missing } : null;
|
|
242
|
+
}
|
|
243
|
+
function startCalendarRequest(state, request) {
|
|
244
|
+
const next = new Map(state);
|
|
245
|
+
for (const key of request.months) {
|
|
246
|
+
const month = state.get(key);
|
|
247
|
+
if (month?.kind === "loading" || month?.kind === "ready") continue;
|
|
248
|
+
next.set(key, {
|
|
249
|
+
kind: "loading",
|
|
250
|
+
request,
|
|
251
|
+
events: month?.events ?? []
|
|
252
|
+
});
|
|
262
253
|
}
|
|
254
|
+
return next;
|
|
263
255
|
}
|
|
264
|
-
function
|
|
265
|
-
|
|
256
|
+
function calendarCacheReducer(state, action) {
|
|
257
|
+
if (action.kind === "started") return startCalendarRequest(state, action.request);
|
|
258
|
+
const next = new Map(state);
|
|
259
|
+
const grouped = action.kind === "succeeded" ? groupEvents(action.events, action.timeZone) : null;
|
|
260
|
+
for (const key of action.request.months) {
|
|
261
|
+
const month = state.get(key);
|
|
262
|
+
if (month?.kind === "loading" && month.request === action.request) next.set(key, action.kind === "succeeded" ? {
|
|
263
|
+
kind: "ready",
|
|
264
|
+
events: grouped?.get(key) ?? []
|
|
265
|
+
} : {
|
|
266
|
+
kind: "failed",
|
|
267
|
+
error: action.error,
|
|
268
|
+
events: month.events
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
return next;
|
|
266
272
|
}
|
|
267
|
-
function
|
|
268
|
-
|
|
273
|
+
function selectCalendarEvents(state, months) {
|
|
274
|
+
const events = /* @__PURE__ */ new Map();
|
|
275
|
+
for (const key of months) for (const event of state.get(key)?.events ?? []) events.set(event.id, event);
|
|
276
|
+
return [...events.values()].sort((a, b) => new Date(a.startsAt).getTime() - new Date(b.startsAt).getTime());
|
|
269
277
|
}
|
|
270
|
-
function
|
|
271
|
-
|
|
278
|
+
function projectCalendarLoadState(state, months) {
|
|
279
|
+
const entries = months.map((key) => state.get(key));
|
|
280
|
+
const failed = entries.find((entry) => entry?.kind === "failed");
|
|
281
|
+
if (failed?.kind === "failed") return {
|
|
282
|
+
kind: "error",
|
|
283
|
+
error: failed.error
|
|
284
|
+
};
|
|
285
|
+
return entries.some((entry) => !entry || entry.kind === "seeded" || entry.kind === "loading") ? { kind: "loading" } : { kind: "idle" };
|
|
272
286
|
}
|
|
273
287
|
//#endregion
|
|
274
288
|
//#region ../blocks/src/system/runtime/hooks/useCalendarEvents.ts
|
|
@@ -280,18 +294,28 @@ function getCalendarEventCacheError(state) {
|
|
|
280
294
|
*/
|
|
281
295
|
/** Maximum events to fetch per calendar request (covers 3 months of events) */
|
|
282
296
|
const CALENDAR_FETCH_LIMIT = 200;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
297
|
+
async function loadCalendarEventPages(loadPage, request) {
|
|
298
|
+
const events = [];
|
|
299
|
+
let afterStartsAt;
|
|
300
|
+
let afterId;
|
|
301
|
+
for (;;) {
|
|
302
|
+
const page = await loadPage({
|
|
303
|
+
...request,
|
|
304
|
+
afterStartsAt,
|
|
305
|
+
afterId,
|
|
306
|
+
limit: CALENDAR_FETCH_LIMIT
|
|
307
|
+
});
|
|
308
|
+
events.push(...page);
|
|
309
|
+
if (page.length < CALENDAR_FETCH_LIMIT) return events;
|
|
310
|
+
const last = page[page.length - 1];
|
|
311
|
+
if (!last) return events;
|
|
312
|
+
if (last.startsAt === afterStartsAt && last.occurrenceId === afterId) throw new Error("Calendar event pagination cursor did not advance");
|
|
313
|
+
afterStartsAt = last.startsAt;
|
|
314
|
+
afterId = last.occurrenceId;
|
|
315
|
+
}
|
|
288
316
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
* period, and navigation by the natural unit for the active view.
|
|
292
|
-
*/
|
|
293
|
-
function useCalendarViewport({ view = "month", startOfWeek = "monday", initialDate } = {}) {
|
|
294
|
-
const [viewDate, setViewDate] = useState(() => initialDate ?? /* @__PURE__ */ new Date());
|
|
317
|
+
function useCalendarViewport({ view = "month", startOfWeek = "monday", initialDate }) {
|
|
318
|
+
const [viewDate, setViewDate] = useState(initialDate);
|
|
295
319
|
const viewport = useMemo(() => buildCalendarViewport({
|
|
296
320
|
view,
|
|
297
321
|
anchorDate: viewDate,
|
|
@@ -316,168 +340,135 @@ function useCalendarViewport({ view = "month", startOfWeek = "monday", initialDa
|
|
|
316
340
|
goToPrevious,
|
|
317
341
|
goToNext,
|
|
318
342
|
goToToday: useCallback(() => {
|
|
319
|
-
setViewDate(
|
|
320
|
-
}, [])
|
|
343
|
+
setViewDate(initialDate);
|
|
344
|
+
}, [initialDate])
|
|
321
345
|
};
|
|
322
346
|
}
|
|
323
347
|
/**
|
|
324
|
-
*
|
|
325
|
-
*
|
|
348
|
+
* The reducer owns month data and request ownership. The hook only performs I/O.
|
|
349
|
+
* Requests for other months remain useful until the query context changes.
|
|
326
350
|
*/
|
|
327
|
-
function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1, filters, stage }) {
|
|
351
|
+
function useCalendarEventCache({ viewDate, initialEvents = [], preloadMonths = 1, filters, stage, timeZone }) {
|
|
328
352
|
const { getPublicEvents } = useBlockApi();
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
filters
|
|
337
|
-
|
|
353
|
+
const context = useMemo(() => ({
|
|
354
|
+
getPublicEvents,
|
|
355
|
+
filters,
|
|
356
|
+
stage,
|
|
357
|
+
timeZone
|
|
358
|
+
}), [
|
|
359
|
+
getPublicEvents,
|
|
360
|
+
getEventRuntimeFiltersKey(filters),
|
|
361
|
+
stage,
|
|
362
|
+
timeZone
|
|
338
363
|
]);
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
if (
|
|
361
|
-
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
+
const [snapshot, setSnapshot] = useState(() => ({
|
|
365
|
+
context,
|
|
366
|
+
cache: seedCalendarCache(initialEvents, timeZone)
|
|
367
|
+
}));
|
|
368
|
+
if (snapshot.context !== context) setSnapshot({
|
|
369
|
+
context,
|
|
370
|
+
cache: seedCalendarCache(initialEvents, timeZone)
|
|
371
|
+
});
|
|
372
|
+
const months = useMemo(() => calendarWindowMonths(viewDate, preloadMonths), [
|
|
373
|
+
viewDate.year,
|
|
374
|
+
viewDate.month,
|
|
375
|
+
preloadMonths
|
|
376
|
+
]);
|
|
377
|
+
const displayMonths = useMemo(() => calendarWindowMonths(viewDate, 1), [viewDate.year, viewDate.month]);
|
|
378
|
+
const request = useMemo(() => snapshot.context === context ? planCalendarRequest(snapshot.cache, months, false) : null, [
|
|
379
|
+
snapshot,
|
|
380
|
+
context,
|
|
381
|
+
months
|
|
382
|
+
]);
|
|
383
|
+
const launched = useRef(/* @__PURE__ */ new WeakSet());
|
|
384
|
+
const runRequest = useCallback(async (planned) => {
|
|
385
|
+
if (launched.current.has(planned)) return;
|
|
386
|
+
launched.current.add(planned);
|
|
387
|
+
const apply = (action) => setSnapshot((current) => current.context === context ? {
|
|
388
|
+
context,
|
|
389
|
+
cache: calendarCacheReducer(current.cache, action)
|
|
390
|
+
} : current);
|
|
391
|
+
apply({
|
|
392
|
+
kind: "started",
|
|
393
|
+
request: planned
|
|
394
|
+
});
|
|
364
395
|
try {
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
396
|
+
const range = buildBookingUtcDateWindow({
|
|
397
|
+
startDate: formatLocalScheduleDate(getStartOfMonth(addMonths(viewDate, -preloadMonths))),
|
|
398
|
+
endDate: formatLocalScheduleDate(getEndOfMonth(addMonths(viewDate, preloadMonths))),
|
|
399
|
+
timeZone
|
|
400
|
+
});
|
|
401
|
+
apply({
|
|
402
|
+
kind: "succeeded",
|
|
403
|
+
request: planned,
|
|
404
|
+
events: await loadCalendarEventPages(context.getPublicEvents, {
|
|
405
|
+
...context.filters,
|
|
406
|
+
stage: context.stage,
|
|
407
|
+
from: range.startAt.toISOString(),
|
|
408
|
+
to: (/* @__PURE__ */ new Date(range.endExclusive.getTime() - 1)).toISOString(),
|
|
409
|
+
detailLevel: "listing"
|
|
410
|
+
}),
|
|
411
|
+
timeZone
|
|
377
412
|
});
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
}
|
|
384
|
-
for (const month of monthsToFetch) {
|
|
385
|
-
loadedMonthsRef.current.add(month);
|
|
386
|
-
if (!cacheRef.current.has(month)) cacheRef.current.set(month, []);
|
|
387
|
-
}
|
|
388
|
-
setCacheVersion((v) => v + 1);
|
|
389
|
-
dispatchLoadState({ type: "succeeded" });
|
|
390
|
-
}
|
|
391
|
-
} catch (err) {
|
|
392
|
-
if (currentRequestId === requestIdRef.current) dispatchLoadState({
|
|
393
|
-
type: "failed",
|
|
394
|
-
error: toCalendarEventCacheLoadError(err)
|
|
413
|
+
} catch (error) {
|
|
414
|
+
apply({
|
|
415
|
+
kind: "failed",
|
|
416
|
+
request: planned,
|
|
417
|
+
error: toError(error, "Failed to load events")
|
|
395
418
|
});
|
|
396
|
-
} finally {
|
|
397
|
-
monthsToFetch.forEach((m) => fetchingRef.current.delete(m));
|
|
398
419
|
}
|
|
399
420
|
}, [
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
filters?.staffMemberId,
|
|
406
|
-
filters?.venueId,
|
|
407
|
-
stage
|
|
421
|
+
context,
|
|
422
|
+
viewDate.year,
|
|
423
|
+
viewDate.month,
|
|
424
|
+
preloadMonths,
|
|
425
|
+
timeZone
|
|
408
426
|
]);
|
|
409
|
-
const ensureEventsLoaded = useCallback((date) => {
|
|
410
|
-
const targetMonths = [];
|
|
411
|
-
for (let i = -preloadMonths; i <= preloadMonths; i++) {
|
|
412
|
-
const targetDate = addMonths(date, i);
|
|
413
|
-
targetMonths.push(getMonthKey(targetDate));
|
|
414
|
-
}
|
|
415
|
-
const unloadedMonths = targetMonths.filter((m) => !loadedMonthsRef.current.has(m) && !fetchingRef.current.has(m));
|
|
416
|
-
if (unloadedMonths.length > 0) {
|
|
417
|
-
const range = getThreeMonthRange(date);
|
|
418
|
-
fetchEventsForRange(range.from, range.to, unloadedMonths);
|
|
419
|
-
}
|
|
420
|
-
}, [preloadMonths, fetchEventsForRange]);
|
|
421
427
|
useEffect(() => {
|
|
422
|
-
|
|
423
|
-
}, [
|
|
428
|
+
if (request) runRequest(request);
|
|
429
|
+
}, [request, runRequest]);
|
|
430
|
+
const retryCurrentView = useCallback(() => {
|
|
431
|
+
if (snapshot.context !== context) return;
|
|
432
|
+
const retry = planCalendarRequest(snapshot.cache, months, true);
|
|
433
|
+
if (retry) runRequest(retry);
|
|
434
|
+
}, [
|
|
435
|
+
snapshot,
|
|
436
|
+
context,
|
|
437
|
+
months,
|
|
438
|
+
runRequest
|
|
439
|
+
]);
|
|
424
440
|
return {
|
|
425
|
-
events:
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const monthKey = getMonthKey(addMonths(viewDate, i));
|
|
429
|
-
const monthEvents = cacheRef.current.get(monthKey) || [];
|
|
430
|
-
allEvents.push(...monthEvents);
|
|
431
|
-
}
|
|
432
|
-
const seen = /* @__PURE__ */ new Set();
|
|
433
|
-
return allEvents.filter((e) => {
|
|
434
|
-
if (seen.has(e.id)) return false;
|
|
435
|
-
seen.add(e.id);
|
|
436
|
-
return true;
|
|
437
|
-
}).sort((a, b) => new Date(a.startsAt).getTime() - new Date(b.startsAt).getTime());
|
|
438
|
-
}, [viewDate, cacheVersion]),
|
|
439
|
-
loading: isCalendarEventCacheLoading(loadState),
|
|
440
|
-
error: getCalendarEventCacheError(loadState)
|
|
441
|
+
events: selectCalendarEvents(snapshot.cache, displayMonths),
|
|
442
|
+
loadState: projectCalendarLoadState(snapshot.cache, months),
|
|
443
|
+
retryCurrentView
|
|
441
444
|
};
|
|
442
445
|
}
|
|
443
|
-
|
|
444
|
-
* Hook for calendar event management with month-based caching.
|
|
445
|
-
*
|
|
446
|
-
* Pre-fetches 3 months (previous, current, next) and caches by month.
|
|
447
|
-
* Navigation within cached range is instant; fetches at boundaries.
|
|
448
|
-
*
|
|
449
|
-
* @example
|
|
450
|
-
* ```tsx
|
|
451
|
-
* const { events, viewDate, loading, goToPrevious, goToNext } = useCalendarEvents({
|
|
452
|
-
* siteId: 'site-123',
|
|
453
|
-
* initialEvents: serverEvents,
|
|
454
|
-
* });
|
|
455
|
-
* ```
|
|
456
|
-
*/
|
|
457
|
-
function useCalendarEvents({ siteId: _siteId, initialEvents = [], view = "month", startOfWeek = "monday", preloadMonths = 1, filters, stage }) {
|
|
446
|
+
function useCalendarEvents({ siteId: _siteId, initialEvents = [], view = "month", startOfWeek = "monday", preloadMonths = 1, filters, stage, calendarContext }) {
|
|
458
447
|
const { viewDate, viewport, goToDate, goToPrevious, goToNext, goToToday } = useCalendarViewport({
|
|
459
448
|
view,
|
|
460
|
-
startOfWeek
|
|
449
|
+
startOfWeek,
|
|
450
|
+
initialDate: calendarContext.initialToday
|
|
461
451
|
});
|
|
462
|
-
const { events,
|
|
452
|
+
const { events, loadState, retryCurrentView } = useCalendarEventCache({
|
|
463
453
|
viewDate,
|
|
464
454
|
initialEvents,
|
|
465
455
|
preloadMonths,
|
|
466
456
|
filters,
|
|
467
|
-
stage
|
|
457
|
+
stage,
|
|
458
|
+
timeZone: calendarContext.timeZone
|
|
468
459
|
});
|
|
469
460
|
return {
|
|
470
461
|
events,
|
|
471
462
|
viewDate,
|
|
472
463
|
viewport,
|
|
473
|
-
|
|
474
|
-
error,
|
|
464
|
+
loadState,
|
|
475
465
|
setViewDate: useCallback((date) => {
|
|
476
466
|
goToDate(date);
|
|
477
467
|
}, [goToDate]),
|
|
478
468
|
goToPrevious,
|
|
479
469
|
goToNext,
|
|
480
|
-
goToToday
|
|
470
|
+
goToToday,
|
|
471
|
+
retryCurrentView
|
|
481
472
|
};
|
|
482
473
|
}
|
|
483
474
|
//#endregion
|
|
@@ -544,9 +535,9 @@ function useEventModal() {
|
|
|
544
535
|
* Clicking an event opens the EventDetailModal.
|
|
545
536
|
* Clicking "+N more" opens the DayEventsModal.
|
|
546
537
|
*/
|
|
547
|
-
const CalendarDayCell = ({ date, events, isCurrentMonth }) => {
|
|
538
|
+
const CalendarDayCell = ({ date, events, isCurrentMonth, today: currentDate }) => {
|
|
548
539
|
const { openEventModal, openDayModal } = useEventModal();
|
|
549
|
-
const today = isToday(date);
|
|
540
|
+
const today = isToday(date, currentDate);
|
|
550
541
|
const dayClasses = [
|
|
551
542
|
"event-calendar-day",
|
|
552
543
|
!isCurrentMonth && "event-calendar-day--other-month",
|
|
@@ -562,7 +553,7 @@ const CalendarDayCell = ({ date, events, isCurrentMonth }) => {
|
|
|
562
553
|
className: dayClasses,
|
|
563
554
|
children: [/* @__PURE__ */ jsx("div", {
|
|
564
555
|
className: "event-calendar-day-number",
|
|
565
|
-
children: date.
|
|
556
|
+
children: date.day
|
|
566
557
|
}), /* @__PURE__ */ jsxs("div", {
|
|
567
558
|
className: "event-calendar-events",
|
|
568
559
|
children: [events.slice(0, 3).map((event) => {
|
|
@@ -608,8 +599,8 @@ const AgendaEventCard = ({ event, showCapacity, onClick }) => {
|
|
|
608
599
|
const eventLinkProps = resolveEventLinkProps(event);
|
|
609
600
|
const categoryColor = event.eventCategory?.color || "rgb(var(--tb-accent))";
|
|
610
601
|
const price = formatEventPrice(event);
|
|
611
|
-
const
|
|
612
|
-
const
|
|
602
|
+
const capacity = showCapacity ? formatEventRemainingPlaces(event) : null;
|
|
603
|
+
const isFull = isEventFull(event);
|
|
613
604
|
const title = event.title;
|
|
614
605
|
const timeZone = event.timeZone ?? null;
|
|
615
606
|
const teacherLine = formatEventTeacherLine(event);
|
|
@@ -694,9 +685,9 @@ const FULL_DAY_NAMES = [
|
|
|
694
685
|
* @returns "Monday, January 13"
|
|
695
686
|
*/
|
|
696
687
|
function formatAgendaDayHeader(date) {
|
|
697
|
-
const dayName = FULL_DAY_NAMES[date
|
|
698
|
-
const monthName = MONTH_NAMES[date.
|
|
699
|
-
return `${dayName ?? "Day"}, ${monthName ?? "Month"} ${date.
|
|
688
|
+
const dayName = FULL_DAY_NAMES[getDayOfWeek(date)];
|
|
689
|
+
const monthName = MONTH_NAMES[date.month - 1];
|
|
690
|
+
return `${dayName ?? "Day"}, ${monthName ?? "Month"} ${date.day}`;
|
|
700
691
|
}
|
|
701
692
|
/**
|
|
702
693
|
* WeekAgendaView Component
|
|
@@ -704,14 +695,14 @@ function formatAgendaDayHeader(date) {
|
|
|
704
695
|
* Displays a week of events in an agenda/list style with rich event details.
|
|
705
696
|
* Shows all 7 days with date headers, empty days show "No events scheduled".
|
|
706
697
|
*/
|
|
707
|
-
const WeekAgendaView = ({ days, events, showCapacity, emptyMessage = "No events scheduled" }) => {
|
|
708
|
-
const eventsByDate = groupEventsByDate(events);
|
|
698
|
+
const WeekAgendaView = ({ days, events, showCapacity, emptyMessage = "No events scheduled", calendarTimeZone, today: currentDate }) => {
|
|
699
|
+
const eventsByDate = groupEventsByDate(events, calendarTimeZone);
|
|
709
700
|
return /* @__PURE__ */ jsx("div", {
|
|
710
701
|
className: "event-agenda-week",
|
|
711
702
|
children: days.map((date) => {
|
|
712
703
|
const dateKey = formatDateKey(date);
|
|
713
704
|
const dayEvents = eventsByDate.get(dateKey) || [];
|
|
714
|
-
const today = isToday(date);
|
|
705
|
+
const today = isToday(date, currentDate);
|
|
715
706
|
return /* @__PURE__ */ jsxs("div", {
|
|
716
707
|
className: `event-agenda-day ${today ? "event-agenda-day--today" : ""}`,
|
|
717
708
|
children: [/* @__PURE__ */ jsx("div", {
|
|
@@ -810,7 +801,7 @@ function EventDetailModal({ event, showCapacity, onClose, portalRoot, cardRole =
|
|
|
810
801
|
* Clicking an event triggers onSelectEvent (typically opens EventDetailModal).
|
|
811
802
|
*/
|
|
812
803
|
function DayEventsModal({ date, events, showCapacity, onClose, onSelectEvent, portalRoot }) {
|
|
813
|
-
const formattedDate = formatDate(date
|
|
804
|
+
const formattedDate = formatDate(`${formatLocalScheduleDate(date)}T12:00:00Z`);
|
|
814
805
|
return /* @__PURE__ */ jsxs(ModalShell, {
|
|
815
806
|
title: formattedDate,
|
|
816
807
|
titleId: "ec-day-modal-title",
|
|
@@ -950,7 +941,8 @@ function toEventCombinedControllerProps(props) {
|
|
|
950
941
|
buttonVariant: props.render.display.buttonVariant,
|
|
951
942
|
buttonText: props.render.display.buttonText,
|
|
952
943
|
emptyMessage: props.render.display.emptyMessage,
|
|
953
|
-
className: props.render.display.className ?? void 0
|
|
944
|
+
className: props.render.display.className ?? void 0,
|
|
945
|
+
calendarContext: props.render.hydration.calendarContext
|
|
954
946
|
};
|
|
955
947
|
}
|
|
956
948
|
/**
|
|
@@ -962,7 +954,7 @@ function toEventCombinedControllerProps(props) {
|
|
|
962
954
|
const EventCombinedClient = ({ events: initialEvents, siteId, stage, listLayout = "stack", listColumns = "3", eventsPerPage = 12, paginationAction = {
|
|
963
955
|
kind: "loadMore",
|
|
964
956
|
label: "Load more events"
|
|
965
|
-
}, startOfWeek = "monday", calendarTabViews = "both", defaultCalendarView, showFilters, showCategoryFilter = "auto", showVenueFilter, showStaffFilter, eventSurface, filterEventPresets, scheduleScope, filterCategoryIds, filterStaffMemberId, filterVenueId, showVenue, showMap, showCapacity, cardRole, buttonVariant = "primary", buttonText = "Book", emptyMessage = "No upcoming events scheduled.", className }) => {
|
|
957
|
+
}, startOfWeek = "monday", calendarTabViews = "both", defaultCalendarView, showFilters, showCategoryFilter = "auto", showVenueFilter, showStaffFilter, eventSurface, filterEventPresets, scheduleScope, filterCategoryIds, filterStaffMemberId, filterVenueId, showVenue, showMap, showCapacity, cardRole, buttonVariant = "primary", buttonText = "Book", emptyMessage = "No upcoming events scheduled.", className, calendarContext }) => {
|
|
966
958
|
const fetchInitialEventsOnMount = initialEvents == null;
|
|
967
959
|
const resolvedShowFilters = showFilters ?? true;
|
|
968
960
|
const resolvedShowVenueFilter = showVenueFilter ?? false;
|
|
@@ -1020,7 +1012,7 @@ const EventCombinedClient = ({ events: initialEvents, siteId, stage, listLayout
|
|
|
1020
1012
|
pageSize,
|
|
1021
1013
|
stage
|
|
1022
1014
|
});
|
|
1023
|
-
const { events: calendarEventsRaw, viewDate, viewport,
|
|
1015
|
+
const { events: calendarEventsRaw, viewDate, viewport, loadState: calendarLoadState, goToPrevious, goToNext, goToToday } = useCalendarEvents({
|
|
1024
1016
|
siteId,
|
|
1025
1017
|
initialEvents: useMemo(() => {
|
|
1026
1018
|
return getEventRuntimeFiltersKey(initialListFilters) === getEventRuntimeFiltersKey(listFilters) ? initialEvents ?? [] : [];
|
|
@@ -1033,9 +1025,10 @@ const EventCombinedClient = ({ events: initialEvents, siteId, stage, listLayout
|
|
|
1033
1025
|
startOfWeek,
|
|
1034
1026
|
preloadMonths: 1,
|
|
1035
1027
|
filters: listFilters,
|
|
1036
|
-
stage
|
|
1028
|
+
stage,
|
|
1029
|
+
calendarContext
|
|
1037
1030
|
});
|
|
1038
|
-
const eventsByDate = useMemo(() => groupEventsByDate(calendarEventsRaw), [calendarEventsRaw]);
|
|
1031
|
+
const eventsByDate = useMemo(() => groupEventsByDate(calendarEventsRaw, calendarContext.timeZone), [calendarContext.timeZone, calendarEventsRaw]);
|
|
1039
1032
|
const dayNames = useMemo(() => getOrderedDayNames(startOfWeek), [startOfWeek]);
|
|
1040
1033
|
const tabs = [{
|
|
1041
1034
|
id: "list",
|
|
@@ -1137,7 +1130,7 @@ const EventCombinedClient = ({ events: initialEvents, siteId, stage, listLayout
|
|
|
1137
1130
|
}),
|
|
1138
1131
|
/* @__PURE__ */ jsxs("h3", {
|
|
1139
1132
|
className: "event-calendar-title",
|
|
1140
|
-
children: [viewport.title,
|
|
1133
|
+
children: [viewport.title, calendarLoadState.kind === "loading" && /* @__PURE__ */ jsx("span", {
|
|
1141
1134
|
className: "rb-ml-2 rb-caption status-muted",
|
|
1142
1135
|
children: "(loading...)"
|
|
1143
1136
|
})]
|
|
@@ -1176,7 +1169,9 @@ const EventCombinedClient = ({ events: initialEvents, siteId, stage, listLayout
|
|
|
1176
1169
|
days: viewport.days,
|
|
1177
1170
|
events: calendarEventsRaw,
|
|
1178
1171
|
emptyMessage: "No events scheduled",
|
|
1179
|
-
showCapacity: resolvedShowCapacity
|
|
1172
|
+
showCapacity: resolvedShowCapacity,
|
|
1173
|
+
calendarTimeZone: calendarContext.timeZone,
|
|
1174
|
+
today: calendarContext.initialToday
|
|
1180
1175
|
}) : /* @__PURE__ */ jsxs("div", {
|
|
1181
1176
|
className: "event-calendar-container",
|
|
1182
1177
|
children: [/* @__PURE__ */ jsx("div", {
|
|
@@ -1192,12 +1187,13 @@ const EventCombinedClient = ({ events: initialEvents, siteId, stage, listLayout
|
|
|
1192
1187
|
return /* @__PURE__ */ jsx(CalendarDayCell, {
|
|
1193
1188
|
date,
|
|
1194
1189
|
events: eventsByDate.get(dateKey) || [],
|
|
1195
|
-
isCurrentMonth: date.
|
|
1190
|
+
isCurrentMonth: date.month === viewDate.month,
|
|
1191
|
+
today: calendarContext.initialToday
|
|
1196
1192
|
}, dateKey);
|
|
1197
1193
|
})
|
|
1198
1194
|
})]
|
|
1199
1195
|
}),
|
|
1200
|
-
calendarEventsRaw.length === 0 &&
|
|
1196
|
+
calendarEventsRaw.length === 0 && calendarLoadState.kind === "idle" && /* @__PURE__ */ jsx("p", {
|
|
1201
1197
|
className: "event-calendar-empty",
|
|
1202
1198
|
children: emptyMessage
|
|
1203
1199
|
})
|
|
@@ -1213,4 +1209,4 @@ const EventCombinedClient = ({ events: initialEvents, siteId, stage, listLayout
|
|
|
1213
1209
|
};
|
|
1214
1210
|
const EventCombinedIslandClient = (props) => /* @__PURE__ */ jsx(EventCombinedClient, { ...toEventCombinedControllerProps(props) });
|
|
1215
1211
|
//#endregion
|
|
1216
|
-
export { CalendarDayCell as a, useCalendarEvents as c,
|
|
1212
|
+
export { CalendarDayCell as a, useCalendarEvents as c, formatDateKey as d, getDayOfWeek as f, isToday as g, isSameCalendarDay as h, WeekAgendaView as i, MONTH_NAMES as l, getWeekCalendarDays as m, EventCombinedIslandClient as n, EventModalProvider as o, getOrderedDayNames as p, EventModals as r, useEventModal as s, EventCombinedClient as t, addDays as u };
|