@riverbankcms/sdk 0.144.0 → 0.145.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/dist/{PreviewEditorSidebar-CQZNnFiM.mjs → PreviewEditorSidebar-O-V6Pl5a.mjs} +4 -4
- package/dist/{PreviewEditorUI-DCNxnmI0.mjs → PreviewEditorUI-1UlX_9cw.mjs} +3 -3
- package/dist/{PreviewQueryProvider-BCYICImX.mjs → PreviewQueryProvider-BxGwdOCV.mjs} +1 -1
- package/dist/{SdkPreviewModeRuntime-BJolUbr1.mjs → SdkPreviewModeRuntime-DYbA_4iv.mjs} +419 -348
- package/dist/{SiteChromeCustomizeContext-CKgEpoxi.mjs → SiteChromeCustomizeContext-CNTKQ9nx.mjs} +2081 -1313
- package/dist/_dts/ai/src/contracts/proposals.d.ts +4719 -66
- package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +429 -6
- package/dist/_dts/api/src/appointmentEndpointDefinitions.d.ts +49 -0
- package/dist/_dts/api/src/appointmentServiceCategoryEndpoints.d.ts +75 -0
- package/dist/_dts/api/src/appointmentServiceContracts.d.ts +80 -0
- package/dist/_dts/api/src/appointmentSetup.d.ts +8 -1
- package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +2 -12
- package/dist/_dts/api/src/communications.d.ts +14 -22
- package/dist/_dts/api/src/contentRuntime.d.ts +2 -0
- package/dist/_dts/api/src/endpoints.d.ts +105 -58
- package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
- package/dist/_dts/api/src/launchReadiness.d.ts +2 -0
- package/dist/_dts/api/src/newsletterEndpointDefinitions.d.ts +0 -23
- package/dist/_dts/api/src/onboarding/confirmationResend.d.ts +3 -0
- package/dist/_dts/api/src/publicBookingService.d.ts +35 -1
- package/dist/_dts/api/src/publicExperience/newsletterEndpoints.d.ts +13 -0
- package/dist/_dts/api/src/publicNewsletterEndpointDefinitions.d.ts +58 -0
- package/dist/_dts/api/src/schemas/admin-observability-logs.d.ts +3 -3
- package/dist/_dts/api/src/siteManagementEndpoints.d.ts +2 -6
- package/dist/_dts/api/src/types.d.ts +2 -1
- package/dist/_dts/blocks/src/PageRenderer.d.ts +4 -4
- package/dist/_dts/blocks/src/bindings/index.d.ts +2 -2
- package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +24 -0
- package/dist/_dts/blocks/src/index.d.ts +1 -1
- package/dist/_dts/blocks/src/pageRenderJoins.d.ts +68 -0
- package/dist/_dts/blocks/src/pageRenderPlan.d.ts +8 -27
- package/dist/_dts/blocks/src/pageRenderPreparation.d.ts +7 -4
- package/dist/_dts/blocks/src/pageRendererBoundaries.d.ts +40 -23
- package/dist/_dts/blocks/src/server.d.ts +1 -1
- package/dist/_dts/blocks/src/system/blocks/appointment-services.d.ts +2 -0
- package/dist/_dts/blocks/src/system/blocks/events/eventSelectionFields.d.ts +2 -2
- package/dist/_dts/blocks/src/system/blocks/events/shared/calendarWindow.d.ts +1 -1
- package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +2 -2
- package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +47 -47
- package/dist/_dts/blocks/src/system/manifest/schema.d.ts +29 -3
- package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.d.ts +8 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +22 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +3 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +57 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.service-categories.d.ts +29 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.service-choices.d.ts +13 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +3 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +13 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +3 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.submission.d.ts +20 -1
- package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +2 -0
- package/dist/_dts/content-model/src/content-types/schema.d.ts +1 -1
- package/dist/_dts/core/src/appointment-service-categories.d.ts +108 -0
- package/dist/_dts/core/src/editor-state.d.ts +6 -0
- package/dist/_dts/core/src/index.d.ts +1 -0
- package/dist/_dts/core/src/public-profile.d.ts +9 -0
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +663 -241
- package/dist/_dts/editor-blocks/src/block-editor/types.d.ts +6 -0
- package/dist/_dts/editor-blocks/src/widgets/site-option-picker/loaders.d.ts +16 -1
- package/dist/_dts/editor-blocks/src/widgets/site-option-picker/types.d.ts +13 -0
- package/dist/_dts/editor-blocks/src/widgets/site-option-picker/utils.d.ts +29 -0
- package/dist/_dts/preview-next/src/client/blocks/BoundaryControl.d.ts +7 -2
- package/dist/_dts/preview-next/src/client/blocks/composer/mergeDrafts.d.ts +1 -1
- package/dist/_dts/preview-next/src/client/blocks/composer/types.d.ts +1 -0
- package/dist/_dts/preview-next/src/client/blocks/previewProjection/applyPreviewProjections.d.ts +1 -3
- package/dist/_dts/preview-next/src/client/blocks/previewProjection/runtimeContentDecoration.d.ts +2 -2
- package/dist/_dts/preview-next/src/client/blocks/previewProjection/types.d.ts +2 -2
- package/dist/_dts/preview-next/src/client/preview/PreviewEntryControllerProvider.d.ts +1 -0
- package/dist/_dts/sdk/src/client/runtimeCacheKeys.d.ts +8 -0
- package/dist/_dts/sdk/src/client/types.d.ts +1 -1
- package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
- package/dist/_dts/sdk/src/contracts/page.d.ts +7 -2
- package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +5 -0
- package/dist/_dts/sdk/src/manifest/passes/pass1-fields.d.ts +2 -2
- package/dist/_dts/sdk/src/public-api/contracts.d.ts +6 -8
- package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +2 -2
- package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +2 -2
- package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +1 -1
- package/dist/_dts/sdk/src/rendering/hooks/useContent.d.ts +1 -1
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/surfaces/src/index.d.ts +1 -0
- package/dist/_dts/theme-core/src/layout/boundaryCss.d.ts +3 -0
- package/dist/_dts/theme-core/src/site-styles/compositionBudget.d.ts +8 -0
- package/dist/_dts/theme-core/src/site-styles/contentTemplateRuntimeCompiler.d.ts +3 -2
- package/dist/_dts/theme-core/src/site-styles/designState.d.ts +1 -3
- package/dist/_dts/theme-core/src/site-styles/generatedDesignPipeline.d.ts +3 -0
- package/dist/_dts/theme-core/src/site-styles/index.d.ts +3 -0
- package/dist/_dts/theme-core/src/site-styles/joinTreatment.d.ts +132 -0
- package/dist/_dts/theme-core/src/site-styles/pageDesignEditorBoundaries.d.ts +31 -0
- package/dist/_dts/theme-core/src/site-styles/pageDesignEditorModel.d.ts +33 -29
- package/dist/_dts/theme-core/src/site-styles/pageDesignIntent.d.ts +4 -4
- package/dist/_dts/theme-core/src/site-styles/pageFlowPresets.d.ts +36 -0
- package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +4 -10
- package/dist/_dts/theme-core/src/site-styles/rawStyleFields.d.ts +17 -4
- package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +20 -74
- package/dist/_dts/theme-core/src/site-styles/sectionBoundaryComposition.d.ts +95 -0
- package/dist/_dts/theme-core/src/site-styles/sectionTransitions.d.ts +80 -518
- package/dist/_dts/theme-core/src/site-styles/siteStyleBlockPolicies.d.ts +9 -4
- package/dist/_dts/theme-core/src/site-styles/transitionCatalogue.d.ts +320 -0
- package/dist/_dts/theme-core/src/site-styles/types.d.ts +3 -18
- package/dist/client/{BookingConsentAgreement-DoAILrkN.mjs → BookingConsentAgreement-DlVOmpW4.mjs} +2 -2
- package/dist/client/{DiscountCodeDisclosure-X528hUTf.mjs → DiscountCodeDisclosure-T9q623PQ.mjs} +1 -1
- package/dist/client/{EventCombined.client-DSBVwq5m.mjs → EventCombined.client-DnsUeONl.mjs} +6 -6
- package/dist/client/{EventListing.client-DmFAX7Vb.mjs → EventListing.client-CNBFqJS4.mjs} +2 -2
- package/dist/client/{LeafletStaticMap-BAqXdfhq.mjs → LeafletStaticMap-C7higg52.mjs} +1 -1
- package/dist/client/{ThemedButton-BwNFVwi4.mjs → ThemedButton-LAJTNrS8.mjs} +1 -1
- package/dist/client/{accordion-DRhMdkbd.mjs → accordion-BcNF9TjX.mjs} +1 -1
- package/dist/client/{bookingForm-iJ_nCsNF.mjs → bookingForm-BUaQ3S03.mjs} +142 -50
- package/dist/client/bookings.mjs +191 -64
- package/dist/client/{carousel-D8zuffZr.mjs → carousel-CTdF6e0V.mjs} +1 -1
- package/dist/client/{cart-DeMGJViN.mjs → cart-pGtyf_XU.mjs} +3 -3
- package/dist/client/{checkout-DXc06Km2.mjs → checkout-Da9WSn7Y.mjs} +3 -3
- package/dist/client/client.mjs +1630 -816
- package/dist/client/{context-CDLCfDep.mjs → context-BFeY_Wbm.mjs} +1 -1
- package/dist/client/{dates-ClFx7Epy.mjs → dates-BhwVSxDg.mjs} +2 -2
- package/dist/client/{eventCalendar-BaGpnOGN.mjs → eventCalendar-BAtdnR4s.mjs} +9 -9
- package/dist/client/{eventCombined-ywONOx2m.mjs → eventCombined-RksA3tRC.mjs} +4 -4
- package/dist/client/{eventDetails-B2LlOTYY.mjs → eventDetails-BB9hB4wR.mjs} +4 -4
- package/dist/client/{eventListing-CMgxWpqP.mjs → eventListing-BpJBkviM.mjs} +4 -4
- package/dist/client/{eventRegistration-BarLDNHR.mjs → eventRegistration-B18jFq_o.mjs} +8 -8
- package/dist/client/{form-BjqKaBJ7.mjs → form-Dodt8Y8t.mjs} +3 -3
- package/dist/client/{headerSection-CP4XDwz1.mjs → headerSection-B0qj9ttg.mjs} +3 -3
- package/dist/client/hooks.mjs +550 -99
- package/dist/client/{locationMap-C5gW-d-w.mjs → locationMap-gn-iMk7a.mjs} +3 -3
- package/dist/client/{newsletterForm-afXlVSA0.mjs → newsletterForm-oByLdFkr.mjs} +26 -5
- package/dist/client/{pricing-Bl1CAl28.mjs → pricing-BOU0_Hai.mjs} +1 -1
- package/dist/client/{productDetail-CvQ3jWQe.mjs → productDetail-D9v1zH2j.mjs} +3 -3
- package/dist/client/{productList-U874PGO7.mjs → productList-D-mItx1n.mjs} +3 -3
- package/dist/client/{propsDecoder-DPXtCZWP.mjs → propsDecoder-C3TP_z4x.mjs} +72 -33
- package/dist/client/rendering/client.mjs +900 -266
- package/dist/client/rendering/islands.mjs +17 -17
- package/dist/client/rendering.mjs +1637 -788
- package/dist/client/{routeIslandApiConfig-NGYiUWXu.mjs → routeIslandApiConfig-DzN1W0sq.mjs} +1 -1
- package/dist/client/{scrollToBlock-0-C3DVhK.mjs → scrollToBlock-CWs8EIdo.mjs} +1 -1
- package/dist/client/{shop-BXjXhM9P.mjs → shop-Dufw7N7o.mjs} +7 -7
- package/dist/client/{shop-commerce-BZ6UlWJ7.mjs → shop-commerce-gklw_hLF.mjs} +6 -6
- package/dist/client/{shop-commerce-store-DlSBXb3D.mjs → shop-commerce-store-Sf1eyTaZ.mjs} +1 -1
- package/dist/client/{shopShared-kkEOiLPA.mjs → shopShared-B5nyA41S.mjs} +4 -4
- package/dist/client/{useEventFilters-zvnnE1ro.mjs → useEventFilters-CLL829vy.mjs} +6 -6
- package/dist/preview-next/before-render.mjs +147 -77
- package/dist/preview-next/client/runtime.mjs +4 -4
- package/dist/preview-next/keepAlive.mjs +147 -77
- package/dist/preview-next/middleware.mjs +147 -77
- package/dist/{previewAuthStore-JA6-I_sL.mjs → previewAuthStore-BxAFlu-j.mjs} +147 -77
- package/dist/{sdk-runtime-DFJlQt3q.mjs → sdk-runtime-D0uZFev7.mjs} +2 -2
- package/dist/{separator-o8GHb1xh.mjs → separator-EvdCAn4V.mjs} +1 -1
- package/dist/server/components.mjs +1727 -991
- package/dist/server/config-validation.mjs +537 -97
- package/dist/server/config.mjs +537 -97
- package/dist/server/data.mjs +549 -98
- package/dist/server/index.mjs +159 -81
- package/dist/server/next.mjs +1460 -748
- package/dist/server/page-converter.mjs +384 -54
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +1712 -973
- package/dist/server/rendering.mjs +1748 -1001
- package/dist/server/routing.mjs +624 -131
- package/dist/server/server.mjs +554 -138
- package/dist/server/theme-bridge.mjs +1192 -27
- package/dist/server/theme.mjs +6 -4
- package/package.json +2 -1
|
@@ -1,19 +1,59 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { C as unsafeAsPassId, b as unsafeAsCustomerPassId, v as unsafeAsAppointmentResourceId, x as unsafeAsFormId, y as unsafeAsAppointmentServiceId } from "./colorStyles-CuJBiS-1.mjs";
|
|
3
|
-
import { i as buildBookingPaymentSelectionViewModel, n as StepIndicator, r as usePolling, t as BookingConsentAgreement } from "./BookingConsentAgreement-
|
|
4
|
-
import { $t as formatBookingInstant, At as resolveBookingSiteId, Bt as clearWorkflowFeedback, Ct as getBookingServiceSlidingScale, Dt as prepareBookingSubmission, Et as parseBookingCurrencyInputToCents, Ft as BOOKING_FORM_DATA_RESERVED_KEYS, Gt as reportWorkflowSuccess, It as isBookingRequirementConsentFieldId, Mt as toSelectedCollectionOptionKind, Nt as projectSelectedAppointmentConsentIntoForm, Ot as resolveAppointmentCheckoutVerificationState, Pt as resolveSelectedAppointmentConsent, St as getBookingRedirectStateFromLocation, Tt as isBookingServiceSlidingAmountInRange, Ut as okWith, Vt as err, Wt as reportWorkflowError, Yt as addLocalScheduleDays, _n as formatCurrencyAmount, an as resolveBookingTimeZoneId, bt as formatBookingCentsAsCurrencyInput, in as parseBookingLocalDate, jt as resolveDefaultBookingServiceId, kt as resolveBookingPaymentStep, t as defineIslandPropsDecoder, tn as formatLocalScheduleDate, vt as logger, wt as getBookingSuccessMessage, xt as formatBookingSubmissionPreparationError, yt as deriveBookingFormViewState, zt as assertNever } from "./propsDecoder-
|
|
5
|
-
import { n as useBlockApi, t as BlockApiProvider } from "./context-
|
|
3
|
+
import { i as buildBookingPaymentSelectionViewModel, n as StepIndicator, r as usePolling, t as BookingConsentAgreement } from "./BookingConsentAgreement-DlVOmpW4.mjs";
|
|
4
|
+
import { $t as formatBookingInstant, At as resolveBookingSiteId, Bt as clearWorkflowFeedback, Ct as getBookingServiceSlidingScale, Dt as prepareBookingSubmission, Et as parseBookingCurrencyInputToCents, Ft as BOOKING_FORM_DATA_RESERVED_KEYS, Gt as reportWorkflowSuccess, It as isBookingRequirementConsentFieldId, Mt as toSelectedCollectionOptionKind, Nt as projectSelectedAppointmentConsentIntoForm, Ot as resolveAppointmentCheckoutVerificationState, Pt as resolveSelectedAppointmentConsent, St as getBookingRedirectStateFromLocation, Tt as isBookingServiceSlidingAmountInRange, Ut as okWith, Vt as err, Wt as reportWorkflowError, Yt as addLocalScheduleDays, _n as formatCurrencyAmount, an as resolveBookingTimeZoneId, bt as formatBookingCentsAsCurrencyInput, in as parseBookingLocalDate, jt as resolveDefaultBookingServiceId, kt as resolveBookingPaymentStep, t as defineIslandPropsDecoder, tn as formatLocalScheduleDate, vt as logger, wt as getBookingSuccessMessage, xt as formatBookingSubmissionPreparationError, yt as deriveBookingFormViewState, zt as assertNever } from "./propsDecoder-C3TP_z4x.mjs";
|
|
5
|
+
import { n as useBlockApi, t as BlockApiProvider } from "./context-BFeY_Wbm.mjs";
|
|
6
6
|
import { n as isSpamProtectionEnabled, r as AltchaWidget, t as getChallengeUrl } from "./src-B833rYRr.mjs";
|
|
7
|
-
import { a as CheckIcon, i as StateIcon, n as useDiscountCodeUi, r as TerminalPanel, t as scrollToBlock } from "./scrollToBlock-
|
|
8
|
-
import { t as DiscountCodeDisclosure } from "./DiscountCodeDisclosure-
|
|
9
|
-
import { i as SpinnerNode, t as ThemedButton } from "./ThemedButton-
|
|
7
|
+
import { a as CheckIcon, i as StateIcon, n as useDiscountCodeUi, r as TerminalPanel, t as scrollToBlock } from "./scrollToBlock-CWs8EIdo.mjs";
|
|
8
|
+
import { t as DiscountCodeDisclosure } from "./DiscountCodeDisclosure-T9q623PQ.mjs";
|
|
9
|
+
import { i as SpinnerNode, t as ThemedButton } from "./ThemedButton-LAJTNrS8.mjs";
|
|
10
10
|
import { t as FeedbackMessage } from "./FeedbackMessage-CtLvvS_d.mjs";
|
|
11
11
|
import { n as getFieldValidationControlProps, t as FieldValidationMessage } from "./FieldValidationMessage-AYanWFb-.mjs";
|
|
12
12
|
import { t as buildCheckoutReturnUrls } from "./checkoutUrls-CW3-78uu.mjs";
|
|
13
13
|
import { t as mountReactIsland } from "./reactMount-SY8AVRof.mjs";
|
|
14
|
-
import { t as buildRouteIslandApiConfig } from "./routeIslandApiConfig-
|
|
14
|
+
import { t as buildRouteIslandApiConfig } from "./routeIslandApiConfig-DzN1W0sq.mjs";
|
|
15
15
|
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
16
16
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
17
|
+
//#region ../core/src/appointment-service-categories.ts
|
|
18
|
+
/**
|
|
19
|
+
* Groups services under their categories.
|
|
20
|
+
*
|
|
21
|
+
* A service whose `categoryId` names no category in `categories` lands in
|
|
22
|
+
* Other. The composite foreign key keeps that from happening with stored data,
|
|
23
|
+
* so this is only the total, safe answer for a caller holding a stale list.
|
|
24
|
+
*/
|
|
25
|
+
function layoutServicesByCategory(categories, services, options) {
|
|
26
|
+
if (categories.length === 0) return {
|
|
27
|
+
kind: "uncategorized-site",
|
|
28
|
+
services: [...services]
|
|
29
|
+
};
|
|
30
|
+
const buckets = new Map(categories.map((category) => [category.id, []]));
|
|
31
|
+
const other = [];
|
|
32
|
+
for (const service of services) {
|
|
33
|
+
const bucket = service.categoryId === null ? void 0 : buckets.get(service.categoryId);
|
|
34
|
+
if (bucket !== void 0) bucket.push(service);
|
|
35
|
+
else other.push(service);
|
|
36
|
+
}
|
|
37
|
+
const groups = [];
|
|
38
|
+
for (const category of categories) {
|
|
39
|
+
const groupServices = buckets.get(category.id) ?? [];
|
|
40
|
+
if (groupServices.length === 0 && !options.keepEmptyGroups) continue;
|
|
41
|
+
groups.push({
|
|
42
|
+
category,
|
|
43
|
+
services: groupServices
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if (groups.length === 0 && !options.keepEmptyGroups) return {
|
|
47
|
+
kind: "uncategorized-site",
|
|
48
|
+
services: other
|
|
49
|
+
};
|
|
50
|
+
return {
|
|
51
|
+
kind: "categorized-site",
|
|
52
|
+
groups,
|
|
53
|
+
other
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
17
57
|
//#region ../blocks/src/system/runtime/components/booking/SuccessMessage.tsx
|
|
18
58
|
const SuccessMessage = ({ message, resourceName, className }) => {
|
|
19
59
|
return /* @__PURE__ */ jsx(TerminalPanel, {
|
|
@@ -1897,6 +1937,7 @@ function useHeadlessBookingFlow(options) {
|
|
|
1897
1937
|
data,
|
|
1898
1938
|
services: {
|
|
1899
1939
|
items: options.services,
|
|
1940
|
+
categories: readServiceCategories(options),
|
|
1900
1941
|
selected: selectedService,
|
|
1901
1942
|
defaultServiceId,
|
|
1902
1943
|
requiresSelection: Boolean(options.requiresServiceSelection)
|
|
@@ -1961,6 +2002,10 @@ function useHeadlessBookingFlow(options) {
|
|
|
1961
2002
|
actions
|
|
1962
2003
|
};
|
|
1963
2004
|
}
|
|
2005
|
+
const EMPTY_SERVICE_CATEGORIES = [];
|
|
2006
|
+
function readServiceCategories(options) {
|
|
2007
|
+
return options.serviceCategories ?? EMPTY_SERVICE_CATEGORIES;
|
|
2008
|
+
}
|
|
1964
2009
|
function navigateToCheckout(checkoutUrl) {
|
|
1965
2010
|
window.location.href = checkoutUrl;
|
|
1966
2011
|
}
|
|
@@ -2182,10 +2227,97 @@ const TimeSlotSelector = ({ value, onChange, slots, isLoading, timezone, require
|
|
|
2182
2227
|
});
|
|
2183
2228
|
};
|
|
2184
2229
|
//#endregion
|
|
2185
|
-
//#region ../blocks/src/system/runtime/nodes/booking-form.
|
|
2230
|
+
//#region ../blocks/src/system/runtime/nodes/booking-form.service-choices.tsx
|
|
2186
2231
|
function optionCardClassName(isSelected) {
|
|
2187
2232
|
return `rb-option-card${isSelected ? " rb-option-card--selected" : ""}`;
|
|
2188
2233
|
}
|
|
2234
|
+
function SelectedCheck() {
|
|
2235
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2236
|
+
className: "rb-option-check",
|
|
2237
|
+
children: /* @__PURE__ */ jsx(CheckIcon, {})
|
|
2238
|
+
});
|
|
2239
|
+
}
|
|
2240
|
+
/**
|
|
2241
|
+
* The service buttons. A site with no categories keeps its single grid; a
|
|
2242
|
+
* categorised site gets a heading per category, then "Other", above the same
|
|
2243
|
+
* grid (issue 1403). Empty categories are skipped, and there are no intros
|
|
2244
|
+
* here, to keep the step compact.
|
|
2245
|
+
*/
|
|
2246
|
+
function DefaultServiceChoices({ booking }) {
|
|
2247
|
+
const layout = layoutServicesByCategory(booking.services.categories, booking.services.items.map((service) => ({
|
|
2248
|
+
service,
|
|
2249
|
+
categoryId: service.categoryId ?? null
|
|
2250
|
+
})), { keepEmptyGroups: false });
|
|
2251
|
+
switch (layout.kind) {
|
|
2252
|
+
case "uncategorized-site": return /* @__PURE__ */ jsxs("div", {
|
|
2253
|
+
className: "rb-reg-stack rb-reg-stack--sm",
|
|
2254
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2255
|
+
className: "ab-subtitle",
|
|
2256
|
+
children: "Service"
|
|
2257
|
+
}), /* @__PURE__ */ jsx(ServiceChoiceGrid, {
|
|
2258
|
+
booking,
|
|
2259
|
+
choices: layout.services
|
|
2260
|
+
})]
|
|
2261
|
+
});
|
|
2262
|
+
case "categorized-site": return /* @__PURE__ */ jsx("div", {
|
|
2263
|
+
className: "rb-reg-stack",
|
|
2264
|
+
children: [...layout.groups.map((group) => ({
|
|
2265
|
+
key: group.category.id,
|
|
2266
|
+
heading: group.category.name,
|
|
2267
|
+
choices: group.services
|
|
2268
|
+
})), ...layout.other.length > 0 ? [{
|
|
2269
|
+
key: "other",
|
|
2270
|
+
heading: "Other",
|
|
2271
|
+
choices: layout.other
|
|
2272
|
+
}] : []].map((group) => /* @__PURE__ */ jsxs("div", {
|
|
2273
|
+
className: "rb-reg-stack rb-reg-stack--sm",
|
|
2274
|
+
"data-booking-service-group": group.key,
|
|
2275
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
2276
|
+
className: "ab-subtitle",
|
|
2277
|
+
children: group.heading
|
|
2278
|
+
}), /* @__PURE__ */ jsx(ServiceChoiceGrid, {
|
|
2279
|
+
booking,
|
|
2280
|
+
choices: group.choices
|
|
2281
|
+
})]
|
|
2282
|
+
}, group.key))
|
|
2283
|
+
});
|
|
2284
|
+
default: return assertNever(layout);
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
function ServiceChoiceGrid({ booking, choices }) {
|
|
2288
|
+
const selectedServiceId = booking.services.selected?.id;
|
|
2289
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2290
|
+
className: "rb-reg-grid",
|
|
2291
|
+
children: choices.map(({ service }) => {
|
|
2292
|
+
const isSelected = selectedServiceId === service.id;
|
|
2293
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
2294
|
+
type: "button",
|
|
2295
|
+
onClick: () => booking.actions.selectService(service.id),
|
|
2296
|
+
className: optionCardClassName(isSelected),
|
|
2297
|
+
"aria-pressed": isSelected,
|
|
2298
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
2299
|
+
className: "rb-flex-1",
|
|
2300
|
+
children: [
|
|
2301
|
+
/* @__PURE__ */ jsx("div", {
|
|
2302
|
+
className: "ab-subtitle",
|
|
2303
|
+
children: service.title
|
|
2304
|
+
}),
|
|
2305
|
+
service.description ? /* @__PURE__ */ jsx("div", {
|
|
2306
|
+
className: "ab-text rb-on-surface--muted",
|
|
2307
|
+
children: service.description
|
|
2308
|
+
}) : null,
|
|
2309
|
+
service.durationMinutes ? /* @__PURE__ */ jsxs("div", {
|
|
2310
|
+
className: "ab-text rb-on-surface--muted",
|
|
2311
|
+
children: [service.durationMinutes, " minutes"]
|
|
2312
|
+
}) : null
|
|
2313
|
+
]
|
|
2314
|
+
}), isSelected ? /* @__PURE__ */ jsx(SelectedCheck, {}) : null]
|
|
2315
|
+
}, service.id);
|
|
2316
|
+
})
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
//#endregion
|
|
2320
|
+
//#region ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
|
|
2189
2321
|
function formatBookingAmount(amount, currency) {
|
|
2190
2322
|
return formatCurrencyAmount(amount, currency, { decimals: "auto" });
|
|
2191
2323
|
}
|
|
@@ -2276,7 +2408,6 @@ function DefaultBookingStepContent({ booking, errorSummaryId }) {
|
|
|
2276
2408
|
function DefaultServiceSelectionStep({ booking }) {
|
|
2277
2409
|
const services = booking.services.items;
|
|
2278
2410
|
const resources = booking.resources.items;
|
|
2279
|
-
const selectedServiceId = booking.services.selected?.id;
|
|
2280
2411
|
const selectedResourceId = booking.resources.selectedResourceId;
|
|
2281
2412
|
const showServiceSelect = booking.services.requiresSelection || services.length > 1;
|
|
2282
2413
|
const showResourceSelect = booking.resources.requiresSelection || resources.length > 1;
|
|
@@ -2291,41 +2422,7 @@ function DefaultServiceSelectionStep({ booking }) {
|
|
|
2291
2422
|
className: "ab-text rb-on-surface--muted",
|
|
2292
2423
|
children: "Choose the service you'd like to book"
|
|
2293
2424
|
})] }),
|
|
2294
|
-
showServiceSelect ? /* @__PURE__ */
|
|
2295
|
-
className: "rb-reg-stack rb-reg-stack--sm",
|
|
2296
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
2297
|
-
className: "ab-subtitle",
|
|
2298
|
-
children: "Service"
|
|
2299
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
2300
|
-
className: "rb-reg-grid",
|
|
2301
|
-
children: services.map((service) => {
|
|
2302
|
-
const isSelected = selectedServiceId === service.id;
|
|
2303
|
-
return /* @__PURE__ */ jsxs("button", {
|
|
2304
|
-
type: "button",
|
|
2305
|
-
onClick: () => booking.actions.selectService(service.id),
|
|
2306
|
-
className: optionCardClassName(isSelected),
|
|
2307
|
-
"aria-pressed": isSelected,
|
|
2308
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
2309
|
-
className: "rb-flex-1",
|
|
2310
|
-
children: [
|
|
2311
|
-
/* @__PURE__ */ jsx("div", {
|
|
2312
|
-
className: "ab-subtitle",
|
|
2313
|
-
children: service.title
|
|
2314
|
-
}),
|
|
2315
|
-
service.description ? /* @__PURE__ */ jsx("div", {
|
|
2316
|
-
className: "ab-text rb-on-surface--muted",
|
|
2317
|
-
children: service.description
|
|
2318
|
-
}) : null,
|
|
2319
|
-
service.durationMinutes ? /* @__PURE__ */ jsxs("div", {
|
|
2320
|
-
className: "ab-text rb-on-surface--muted",
|
|
2321
|
-
children: [service.durationMinutes, " minutes"]
|
|
2322
|
-
}) : null
|
|
2323
|
-
]
|
|
2324
|
-
}), isSelected ? /* @__PURE__ */ jsx(SelectedCheck, {}) : null]
|
|
2325
|
-
}, service.id);
|
|
2326
|
-
})
|
|
2327
|
-
})]
|
|
2328
|
-
}) : null,
|
|
2425
|
+
showServiceSelect ? /* @__PURE__ */ jsx(DefaultServiceChoices, { booking }) : null,
|
|
2329
2426
|
booking.resources.state.tag === "loading" ? /* @__PURE__ */ jsxs("div", {
|
|
2330
2427
|
className: "ab-center",
|
|
2331
2428
|
children: [/* @__PURE__ */ jsx(SpinnerNode, {
|
|
@@ -2904,12 +3001,6 @@ function DefaultBookingErrorSummary({ errors, id }) {
|
|
|
2904
3001
|
children: [errors.formError ? /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: errors.formError }) }) : null, Object.entries(errors.fieldErrors).map(([key, message]) => /* @__PURE__ */ jsx("p", { children: message }, key))]
|
|
2905
3002
|
});
|
|
2906
3003
|
}
|
|
2907
|
-
function SelectedCheck() {
|
|
2908
|
-
return /* @__PURE__ */ jsx("div", {
|
|
2909
|
-
className: "rb-option-check",
|
|
2910
|
-
children: /* @__PURE__ */ jsx(CheckIcon, {})
|
|
2911
|
-
});
|
|
2912
|
-
}
|
|
2913
3004
|
//#endregion
|
|
2914
3005
|
//#region ../blocks/src/system/runtime/nodes/booking-form.client.tsx
|
|
2915
3006
|
const PORTAL_REBOOK_QUERY_PARAM = "rebook";
|
|
@@ -2962,6 +3053,7 @@ const BookingFormClient = ({ siteId: siteIdProp, render }) => {
|
|
|
2962
3053
|
formId: render.hydration.formId ?? form?.id ?? "booking-form",
|
|
2963
3054
|
form,
|
|
2964
3055
|
services,
|
|
3056
|
+
serviceCategories: render.hydration.serviceCategories,
|
|
2965
3057
|
initialServiceId,
|
|
2966
3058
|
initialResourceId,
|
|
2967
3059
|
initialData: render.hydration.initialData ?? void 0,
|
package/dist/client/bookings.mjs
CHANGED
|
@@ -2786,7 +2786,7 @@ function parseEventPageSurfaceDestinationMode(value) {
|
|
|
2786
2786
|
return value === "cms-managed" || value === "system-managed" ? value : void 0;
|
|
2787
2787
|
}
|
|
2788
2788
|
function parseEventPageSurfaceSubject(value) {
|
|
2789
|
-
if (!isRecord$
|
|
2789
|
+
if (!isRecord$7(value)) return err$1({ kind: "notObject" });
|
|
2790
2790
|
switch (value.kind) {
|
|
2791
2791
|
case "eventSeries": {
|
|
2792
2792
|
const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
|
|
@@ -2841,7 +2841,7 @@ function parseEventSeriesIdList(values) {
|
|
|
2841
2841
|
}
|
|
2842
2842
|
return ok$1(parsed);
|
|
2843
2843
|
}
|
|
2844
|
-
function isRecord$
|
|
2844
|
+
function isRecord$7(value) {
|
|
2845
2845
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2846
2846
|
}
|
|
2847
2847
|
//#endregion
|
|
@@ -3122,6 +3122,46 @@ function addLocalScheduleDays(date, days) {
|
|
|
3122
3122
|
day: utcDate.getUTCDate()
|
|
3123
3123
|
};
|
|
3124
3124
|
}
|
|
3125
|
+
//#endregion
|
|
3126
|
+
//#region ../core/src/appointment-service-categories.ts
|
|
3127
|
+
/**
|
|
3128
|
+
* Groups services under their categories.
|
|
3129
|
+
*
|
|
3130
|
+
* A service whose `categoryId` names no category in `categories` lands in
|
|
3131
|
+
* Other. The composite foreign key keeps that from happening with stored data,
|
|
3132
|
+
* so this is only the total, safe answer for a caller holding a stale list.
|
|
3133
|
+
*/
|
|
3134
|
+
function layoutServicesByCategory(categories, services, options) {
|
|
3135
|
+
if (categories.length === 0) return {
|
|
3136
|
+
kind: "uncategorized-site",
|
|
3137
|
+
services: [...services]
|
|
3138
|
+
};
|
|
3139
|
+
const buckets = new Map(categories.map((category) => [category.id, []]));
|
|
3140
|
+
const other = [];
|
|
3141
|
+
for (const service of services) {
|
|
3142
|
+
const bucket = service.categoryId === null ? void 0 : buckets.get(service.categoryId);
|
|
3143
|
+
if (bucket !== void 0) bucket.push(service);
|
|
3144
|
+
else other.push(service);
|
|
3145
|
+
}
|
|
3146
|
+
const groups = [];
|
|
3147
|
+
for (const category of categories) {
|
|
3148
|
+
const groupServices = buckets.get(category.id) ?? [];
|
|
3149
|
+
if (groupServices.length === 0 && !options.keepEmptyGroups) continue;
|
|
3150
|
+
groups.push({
|
|
3151
|
+
category,
|
|
3152
|
+
services: groupServices
|
|
3153
|
+
});
|
|
3154
|
+
}
|
|
3155
|
+
if (groups.length === 0 && !options.keepEmptyGroups) return {
|
|
3156
|
+
kind: "uncategorized-site",
|
|
3157
|
+
services: other
|
|
3158
|
+
};
|
|
3159
|
+
return {
|
|
3160
|
+
kind: "categorized-site",
|
|
3161
|
+
groups,
|
|
3162
|
+
other
|
|
3163
|
+
};
|
|
3164
|
+
}
|
|
3125
3165
|
function sessionStartMs(session) {
|
|
3126
3166
|
return Date.parse(session.startsAt);
|
|
3127
3167
|
}
|
|
@@ -6777,16 +6817,18 @@ const themeV2RuntimeStyleFieldNames = [
|
|
|
6777
6817
|
"_frameStyles",
|
|
6778
6818
|
"_sectionStyles",
|
|
6779
6819
|
"_containerStyles",
|
|
6780
|
-
"_cardStyles"
|
|
6781
|
-
"_transitionStyles",
|
|
6782
|
-
"styleGroup"
|
|
6820
|
+
"_cardStyles"
|
|
6783
6821
|
];
|
|
6784
6822
|
const themeV2BlockSpecificRawStyleFieldNames = [
|
|
6785
6823
|
"_contentCardStyles",
|
|
6786
6824
|
"_heroLayoutStyles",
|
|
6787
6825
|
"_textCardStyles"
|
|
6788
6826
|
];
|
|
6789
|
-
const themeV2NormalEditorRawStyleFieldNames = [
|
|
6827
|
+
const themeV2NormalEditorRawStyleFieldNames = [
|
|
6828
|
+
...themeV2RuntimeStyleFieldNames,
|
|
6829
|
+
...themeV2BlockSpecificRawStyleFieldNames,
|
|
6830
|
+
"styleGroup"
|
|
6831
|
+
];
|
|
6790
6832
|
new Set(themeV2NormalEditorRawStyleFieldNames);
|
|
6791
6833
|
[...themeV2RuntimeStyleFieldNames, ...themeV2BlockSpecificRawStyleFieldNames];
|
|
6792
6834
|
const pageDesignEditorBackgroundOverrideOwner = "page-design-editor";
|
|
@@ -6975,7 +7017,7 @@ const boxBackgroundSchema = z.discriminatedUnion("type", [
|
|
|
6975
7017
|
})
|
|
6976
7018
|
]);
|
|
6977
7019
|
function normalizeAuthoringOpacity(value) {
|
|
6978
|
-
if (!isRecord$
|
|
7020
|
+
if (!isRecord$6(value)) return value;
|
|
6979
7021
|
return {
|
|
6980
7022
|
...value,
|
|
6981
7023
|
opacity: normalizeOpacity(value.opacity)
|
|
@@ -6984,7 +7026,7 @@ function normalizeAuthoringOpacity(value) {
|
|
|
6984
7026
|
function normalizeOpacity(value) {
|
|
6985
7027
|
return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
|
|
6986
7028
|
}
|
|
6987
|
-
function isRecord$
|
|
7029
|
+
function isRecord$6(value) {
|
|
6988
7030
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6989
7031
|
}
|
|
6990
7032
|
//#endregion
|
|
@@ -8666,7 +8708,7 @@ var BlockApiError = class extends Error {
|
|
|
8666
8708
|
this.name = "BlockApiError";
|
|
8667
8709
|
}
|
|
8668
8710
|
};
|
|
8669
|
-
function isRecord$
|
|
8711
|
+
function isRecord$5(value) {
|
|
8670
8712
|
return typeof value === "object" && value !== null;
|
|
8671
8713
|
}
|
|
8672
8714
|
function isJsonResponseContentType(contentType) {
|
|
@@ -8690,15 +8732,15 @@ async function parseJsonBody(response) {
|
|
|
8690
8732
|
}
|
|
8691
8733
|
}
|
|
8692
8734
|
function isFieldError(value) {
|
|
8693
|
-
return isRecord$
|
|
8735
|
+
return isRecord$5(value) && !Array.isArray(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
|
|
8694
8736
|
}
|
|
8695
8737
|
function fieldErrorsFromUnknown(value) {
|
|
8696
8738
|
if (!Array.isArray(value)) return void 0;
|
|
8697
8739
|
return value.every(isFieldError) ? value : void 0;
|
|
8698
8740
|
}
|
|
8699
8741
|
function getBlockApiErrorDetails(data) {
|
|
8700
|
-
if (!isRecord$
|
|
8701
|
-
const nestedError = isRecord$
|
|
8742
|
+
if (!isRecord$5(data)) return {};
|
|
8743
|
+
const nestedError = isRecord$5(data.error) ? data.error : void 0;
|
|
8702
8744
|
const message = typeof nestedError?.message === "string" ? nestedError.message : typeof data.message === "string" ? data.message : void 0;
|
|
8703
8745
|
const code = typeof nestedError?.code === "string" ? nestedError.code : typeof data.code === "string" ? data.code : void 0;
|
|
8704
8746
|
const fieldErrors = fieldErrorsFromUnknown(nestedError?.fieldErrors) ?? fieldErrorsFromUnknown(data.fieldErrors);
|
|
@@ -9669,12 +9711,12 @@ function resolveBookingSiteId(siteId, form) {
|
|
|
9669
9711
|
return siteId || form?.siteId || "";
|
|
9670
9712
|
}
|
|
9671
9713
|
function normalizeBookingFormConfig(form) {
|
|
9672
|
-
if (!isRecord$
|
|
9714
|
+
if (!isRecord$4(form)) return null;
|
|
9673
9715
|
const id = readNonEmptyString(form.id);
|
|
9674
9716
|
const name = readNonEmptyString(form.name);
|
|
9675
9717
|
if (!id || !name) return null;
|
|
9676
|
-
const schemaSource = isRecord$
|
|
9677
|
-
const settingsSource = isRecord$
|
|
9718
|
+
const schemaSource = isRecord$4(form.schema) ? form.schema : isRecord$4(form.schemaJson) ? form.schemaJson : null;
|
|
9719
|
+
const settingsSource = isRecord$4(form.settings) ? form.settings : isRecord$4(form.settingsJson) ? form.settingsJson : null;
|
|
9678
9720
|
return {
|
|
9679
9721
|
id,
|
|
9680
9722
|
name,
|
|
@@ -9694,8 +9736,8 @@ function normalizeBookingServices(services) {
|
|
|
9694
9736
|
};
|
|
9695
9737
|
if (!services) return [];
|
|
9696
9738
|
if (Array.isArray(services)) return services.filter(isBookingFormService).map(normalizeService);
|
|
9697
|
-
if (isRecord$
|
|
9698
|
-
return isRecord$
|
|
9739
|
+
if (isRecord$4(services) && "services" in services) return Array.isArray(services.services) ? services.services.filter(isBookingFormService).map(normalizeService) : [];
|
|
9740
|
+
return isRecord$4(services) ? Object.values(services).filter(isBookingFormService).map(normalizeService) : [];
|
|
9699
9741
|
}
|
|
9700
9742
|
function normalizeBookingSchema(value) {
|
|
9701
9743
|
if (!value) return void 0;
|
|
@@ -9706,7 +9748,7 @@ function normalizeBookingSchema(value) {
|
|
|
9706
9748
|
};
|
|
9707
9749
|
}
|
|
9708
9750
|
function readBookingFormField(value) {
|
|
9709
|
-
if (!isRecord$
|
|
9751
|
+
if (!isRecord$4(value)) return null;
|
|
9710
9752
|
const id = readNonEmptyString(value.id);
|
|
9711
9753
|
const label = readNonEmptyString(value.label);
|
|
9712
9754
|
const type = readBookingFieldType(value.type);
|
|
@@ -9749,7 +9791,7 @@ function readBookingFieldOptions(value) {
|
|
|
9749
9791
|
return options.length > 0 ? options : void 0;
|
|
9750
9792
|
}
|
|
9751
9793
|
function readBookingFieldOption(value) {
|
|
9752
|
-
if (!isRecord$
|
|
9794
|
+
if (!isRecord$4(value)) return null;
|
|
9753
9795
|
const optionValue = readNonEmptyString(value.value);
|
|
9754
9796
|
const label = readNonEmptyString(value.label);
|
|
9755
9797
|
return optionValue && label ? {
|
|
@@ -9769,7 +9811,7 @@ function normalizeBookingSettings(value) {
|
|
|
9769
9811
|
};
|
|
9770
9812
|
}
|
|
9771
9813
|
function isBookingFormService(value) {
|
|
9772
|
-
return isRecord$
|
|
9814
|
+
return isRecord$4(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string" && (value.consent === void 0 || blockBookingConsentSchema.safeParse(value.consent).success);
|
|
9773
9815
|
}
|
|
9774
9816
|
function collectBookingCustomFields(data) {
|
|
9775
9817
|
const customFields = {};
|
|
@@ -9819,7 +9861,7 @@ function readStringArray(value) {
|
|
|
9819
9861
|
const strings = value.filter((item) => typeof item === "string");
|
|
9820
9862
|
return strings.length > 0 ? strings : void 0;
|
|
9821
9863
|
}
|
|
9822
|
-
function isRecord$
|
|
9864
|
+
function isRecord$4(value) {
|
|
9823
9865
|
return typeof value === "object" && value !== null;
|
|
9824
9866
|
}
|
|
9825
9867
|
function getBookingServicePaymentSelectionMode(service) {
|
|
@@ -11078,6 +11120,38 @@ function formatScheduleDate(isoString, locale) {
|
|
|
11078
11120
|
return new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(date);
|
|
11079
11121
|
}
|
|
11080
11122
|
//#endregion
|
|
11123
|
+
//#region ../blocks/src/system/runtime/nodes/booking-form.service-categories.ts
|
|
11124
|
+
function isRecord$3(value) {
|
|
11125
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11126
|
+
}
|
|
11127
|
+
function readCategory(value) {
|
|
11128
|
+
if (!isRecord$3(value)) return [];
|
|
11129
|
+
const { id, name, description } = value;
|
|
11130
|
+
if (typeof id !== "string" || id.trim() === "" || typeof name !== "string") return [];
|
|
11131
|
+
return [{
|
|
11132
|
+
id,
|
|
11133
|
+
name,
|
|
11134
|
+
description: typeof description === "string" ? description : null
|
|
11135
|
+
}];
|
|
11136
|
+
}
|
|
11137
|
+
/**
|
|
11138
|
+
* The ordered service categories carried by a catalogue-shaped services
|
|
11139
|
+
* source (`{ services, categories }`). Every other shape has none, which
|
|
11140
|
+
* reads as a site without categories. Order is preserved: the database owns
|
|
11141
|
+
* it.
|
|
11142
|
+
*/
|
|
11143
|
+
function normalizeBookingServiceCategories(services) {
|
|
11144
|
+
if (!isRecord$3(services) || !Array.isArray(services.categories)) return [];
|
|
11145
|
+
return services.categories.flatMap(readCategory);
|
|
11146
|
+
}
|
|
11147
|
+
/**
|
|
11148
|
+
* The ordered service categories a headless booking override was given in
|
|
11149
|
+
* its loader data (`data.services`).
|
|
11150
|
+
*/
|
|
11151
|
+
function readOverrideServiceCategories(data) {
|
|
11152
|
+
return isRecord$3(data) ? normalizeBookingServiceCategories(data.services) : [];
|
|
11153
|
+
}
|
|
11154
|
+
//#endregion
|
|
11081
11155
|
//#region ../blocks/src/system/runtime/nodes/booking-form.validationErrors.ts
|
|
11082
11156
|
function omitRecordKey(record, key) {
|
|
11083
11157
|
if (!(key in record)) return record;
|
|
@@ -11687,6 +11761,7 @@ function getAppointmentBookingOverrideInput(props) {
|
|
|
11687
11761
|
formId,
|
|
11688
11762
|
form,
|
|
11689
11763
|
services,
|
|
11764
|
+
serviceCategories: readOverrideServiceCategories(props.data),
|
|
11690
11765
|
initialServiceId: defaultServiceId,
|
|
11691
11766
|
initialResourceId: toOptionalAppointmentResourceId(content.resourceId ?? form.settings?.resourceId),
|
|
11692
11767
|
requiresServiceSelection: Boolean(content.requiresServiceSelection),
|
|
@@ -12400,6 +12475,7 @@ function useHeadlessBookingFlow(options) {
|
|
|
12400
12475
|
data,
|
|
12401
12476
|
services: {
|
|
12402
12477
|
items: options.services,
|
|
12478
|
+
categories: readServiceCategories(options),
|
|
12403
12479
|
selected: selectedService,
|
|
12404
12480
|
defaultServiceId,
|
|
12405
12481
|
requiresSelection: Boolean(options.requiresServiceSelection)
|
|
@@ -12464,6 +12540,10 @@ function useHeadlessBookingFlow(options) {
|
|
|
12464
12540
|
actions
|
|
12465
12541
|
};
|
|
12466
12542
|
}
|
|
12543
|
+
const EMPTY_SERVICE_CATEGORIES = [];
|
|
12544
|
+
function readServiceCategories(options) {
|
|
12545
|
+
return options.serviceCategories ?? EMPTY_SERVICE_CATEGORIES;
|
|
12546
|
+
}
|
|
12467
12547
|
function navigateToCheckout(checkoutUrl) {
|
|
12468
12548
|
window.location.href = checkoutUrl;
|
|
12469
12549
|
}
|
|
@@ -14026,10 +14106,97 @@ function BookingConsentAgreement({ agreement, showTitle = true, title, titleId }
|
|
|
14026
14106
|
})] });
|
|
14027
14107
|
}
|
|
14028
14108
|
//#endregion
|
|
14029
|
-
//#region ../blocks/src/system/runtime/nodes/booking-form.
|
|
14109
|
+
//#region ../blocks/src/system/runtime/nodes/booking-form.service-choices.tsx
|
|
14030
14110
|
function optionCardClassName(isSelected) {
|
|
14031
14111
|
return `rb-option-card${isSelected ? " rb-option-card--selected" : ""}`;
|
|
14032
14112
|
}
|
|
14113
|
+
function SelectedCheck() {
|
|
14114
|
+
return /* @__PURE__ */ jsx("div", {
|
|
14115
|
+
className: "rb-option-check",
|
|
14116
|
+
children: /* @__PURE__ */ jsx(CheckIcon, {})
|
|
14117
|
+
});
|
|
14118
|
+
}
|
|
14119
|
+
/**
|
|
14120
|
+
* The service buttons. A site with no categories keeps its single grid; a
|
|
14121
|
+
* categorised site gets a heading per category, then "Other", above the same
|
|
14122
|
+
* grid (issue 1403). Empty categories are skipped, and there are no intros
|
|
14123
|
+
* here, to keep the step compact.
|
|
14124
|
+
*/
|
|
14125
|
+
function DefaultServiceChoices({ booking }) {
|
|
14126
|
+
const layout = layoutServicesByCategory(booking.services.categories, booking.services.items.map((service) => ({
|
|
14127
|
+
service,
|
|
14128
|
+
categoryId: service.categoryId ?? null
|
|
14129
|
+
})), { keepEmptyGroups: false });
|
|
14130
|
+
switch (layout.kind) {
|
|
14131
|
+
case "uncategorized-site": return /* @__PURE__ */ jsxs("div", {
|
|
14132
|
+
className: "rb-reg-stack rb-reg-stack--sm",
|
|
14133
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
14134
|
+
className: "ab-subtitle",
|
|
14135
|
+
children: "Service"
|
|
14136
|
+
}), /* @__PURE__ */ jsx(ServiceChoiceGrid, {
|
|
14137
|
+
booking,
|
|
14138
|
+
choices: layout.services
|
|
14139
|
+
})]
|
|
14140
|
+
});
|
|
14141
|
+
case "categorized-site": return /* @__PURE__ */ jsx("div", {
|
|
14142
|
+
className: "rb-reg-stack",
|
|
14143
|
+
children: [...layout.groups.map((group) => ({
|
|
14144
|
+
key: group.category.id,
|
|
14145
|
+
heading: group.category.name,
|
|
14146
|
+
choices: group.services
|
|
14147
|
+
})), ...layout.other.length > 0 ? [{
|
|
14148
|
+
key: "other",
|
|
14149
|
+
heading: "Other",
|
|
14150
|
+
choices: layout.other
|
|
14151
|
+
}] : []].map((group) => /* @__PURE__ */ jsxs("div", {
|
|
14152
|
+
className: "rb-reg-stack rb-reg-stack--sm",
|
|
14153
|
+
"data-booking-service-group": group.key,
|
|
14154
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
14155
|
+
className: "ab-subtitle",
|
|
14156
|
+
children: group.heading
|
|
14157
|
+
}), /* @__PURE__ */ jsx(ServiceChoiceGrid, {
|
|
14158
|
+
booking,
|
|
14159
|
+
choices: group.choices
|
|
14160
|
+
})]
|
|
14161
|
+
}, group.key))
|
|
14162
|
+
});
|
|
14163
|
+
default: return assertNever(layout);
|
|
14164
|
+
}
|
|
14165
|
+
}
|
|
14166
|
+
function ServiceChoiceGrid({ booking, choices }) {
|
|
14167
|
+
const selectedServiceId = booking.services.selected?.id;
|
|
14168
|
+
return /* @__PURE__ */ jsx("div", {
|
|
14169
|
+
className: "rb-reg-grid",
|
|
14170
|
+
children: choices.map(({ service }) => {
|
|
14171
|
+
const isSelected = selectedServiceId === service.id;
|
|
14172
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
14173
|
+
type: "button",
|
|
14174
|
+
onClick: () => booking.actions.selectService(service.id),
|
|
14175
|
+
className: optionCardClassName(isSelected),
|
|
14176
|
+
"aria-pressed": isSelected,
|
|
14177
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
14178
|
+
className: "rb-flex-1",
|
|
14179
|
+
children: [
|
|
14180
|
+
/* @__PURE__ */ jsx("div", {
|
|
14181
|
+
className: "ab-subtitle",
|
|
14182
|
+
children: service.title
|
|
14183
|
+
}),
|
|
14184
|
+
service.description ? /* @__PURE__ */ jsx("div", {
|
|
14185
|
+
className: "ab-text rb-on-surface--muted",
|
|
14186
|
+
children: service.description
|
|
14187
|
+
}) : null,
|
|
14188
|
+
service.durationMinutes ? /* @__PURE__ */ jsxs("div", {
|
|
14189
|
+
className: "ab-text rb-on-surface--muted",
|
|
14190
|
+
children: [service.durationMinutes, " minutes"]
|
|
14191
|
+
}) : null
|
|
14192
|
+
]
|
|
14193
|
+
}), isSelected ? /* @__PURE__ */ jsx(SelectedCheck, {}) : null]
|
|
14194
|
+
}, service.id);
|
|
14195
|
+
})
|
|
14196
|
+
});
|
|
14197
|
+
}
|
|
14198
|
+
//#endregion
|
|
14199
|
+
//#region ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
|
|
14033
14200
|
function formatBookingAmount(amount, currency) {
|
|
14034
14201
|
return formatCurrencyAmount(amount, currency, { decimals: "auto" });
|
|
14035
14202
|
}
|
|
@@ -14120,7 +14287,6 @@ function DefaultBookingStepContent({ booking, errorSummaryId }) {
|
|
|
14120
14287
|
function DefaultServiceSelectionStep({ booking }) {
|
|
14121
14288
|
const services = booking.services.items;
|
|
14122
14289
|
const resources = booking.resources.items;
|
|
14123
|
-
const selectedServiceId = booking.services.selected?.id;
|
|
14124
14290
|
const selectedResourceId = booking.resources.selectedResourceId;
|
|
14125
14291
|
const showServiceSelect = booking.services.requiresSelection || services.length > 1;
|
|
14126
14292
|
const showResourceSelect = booking.resources.requiresSelection || resources.length > 1;
|
|
@@ -14135,41 +14301,7 @@ function DefaultServiceSelectionStep({ booking }) {
|
|
|
14135
14301
|
className: "ab-text rb-on-surface--muted",
|
|
14136
14302
|
children: "Choose the service you'd like to book"
|
|
14137
14303
|
})] }),
|
|
14138
|
-
showServiceSelect ? /* @__PURE__ */
|
|
14139
|
-
className: "rb-reg-stack rb-reg-stack--sm",
|
|
14140
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
14141
|
-
className: "ab-subtitle",
|
|
14142
|
-
children: "Service"
|
|
14143
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
14144
|
-
className: "rb-reg-grid",
|
|
14145
|
-
children: services.map((service) => {
|
|
14146
|
-
const isSelected = selectedServiceId === service.id;
|
|
14147
|
-
return /* @__PURE__ */ jsxs("button", {
|
|
14148
|
-
type: "button",
|
|
14149
|
-
onClick: () => booking.actions.selectService(service.id),
|
|
14150
|
-
className: optionCardClassName(isSelected),
|
|
14151
|
-
"aria-pressed": isSelected,
|
|
14152
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
14153
|
-
className: "rb-flex-1",
|
|
14154
|
-
children: [
|
|
14155
|
-
/* @__PURE__ */ jsx("div", {
|
|
14156
|
-
className: "ab-subtitle",
|
|
14157
|
-
children: service.title
|
|
14158
|
-
}),
|
|
14159
|
-
service.description ? /* @__PURE__ */ jsx("div", {
|
|
14160
|
-
className: "ab-text rb-on-surface--muted",
|
|
14161
|
-
children: service.description
|
|
14162
|
-
}) : null,
|
|
14163
|
-
service.durationMinutes ? /* @__PURE__ */ jsxs("div", {
|
|
14164
|
-
className: "ab-text rb-on-surface--muted",
|
|
14165
|
-
children: [service.durationMinutes, " minutes"]
|
|
14166
|
-
}) : null
|
|
14167
|
-
]
|
|
14168
|
-
}), isSelected ? /* @__PURE__ */ jsx(SelectedCheck, {}) : null]
|
|
14169
|
-
}, service.id);
|
|
14170
|
-
})
|
|
14171
|
-
})]
|
|
14172
|
-
}) : null,
|
|
14304
|
+
showServiceSelect ? /* @__PURE__ */ jsx(DefaultServiceChoices, { booking }) : null,
|
|
14173
14305
|
booking.resources.state.tag === "loading" ? /* @__PURE__ */ jsxs("div", {
|
|
14174
14306
|
className: "ab-center",
|
|
14175
14307
|
children: [/* @__PURE__ */ jsx(SpinnerNode, {
|
|
@@ -14748,12 +14880,6 @@ function DefaultBookingErrorSummary({ errors, id }) {
|
|
|
14748
14880
|
children: [errors.formError ? /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: errors.formError }) }) : null, Object.entries(errors.fieldErrors).map(([key, message]) => /* @__PURE__ */ jsx("p", { children: message }, key))]
|
|
14749
14881
|
});
|
|
14750
14882
|
}
|
|
14751
|
-
function SelectedCheck() {
|
|
14752
|
-
return /* @__PURE__ */ jsx("div", {
|
|
14753
|
-
className: "rb-option-check",
|
|
14754
|
-
children: /* @__PURE__ */ jsx(CheckIcon, {})
|
|
14755
|
-
});
|
|
14756
|
-
}
|
|
14757
14883
|
//#endregion
|
|
14758
14884
|
//#region ../blocks/src/system/runtime/shared/utils/checkoutUrls.ts
|
|
14759
14885
|
/**
|
|
@@ -14871,6 +14997,7 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
|
|
|
14871
14997
|
formId: render.hydration.formId ?? form?.id ?? "booking-form",
|
|
14872
14998
|
form,
|
|
14873
14999
|
services,
|
|
15000
|
+
serviceCategories: render.hydration.serviceCategories,
|
|
14874
15001
|
initialServiceId,
|
|
14875
15002
|
initialResourceId,
|
|
14876
15003
|
initialData: render.hydration.initialData ?? void 0,
|