@cimplify/sdk 0.73.0 → 0.74.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/react.d.mts CHANGED
@@ -3,7 +3,7 @@ import { d as AdSlot, c as AdPosition, a as AdContextValue, S as SignInOptions }
3
3
  export { A as AdConfig, g as getVariantDisplayName } from './sign-in-DQlIdqsi.mjs';
4
4
  import { ad as CimplifyClient, cj as ProcessCheckoutResult, aa as CheckoutStatus, ab as CheckoutStatusContext, aV as EnrichedOrderItem, aU as EnrichedOrder, w as Business, bp as Location, cA as ReorderResult, b$ as OrderStatus, bF as Order, cl as QuoteBundleSelectionInput, cm as QuoteCompositeSelectionInput, cf as PriceQuote, cp as QuoteUiMessage, cV as Service, r as AvailableSlot, av as DayAvailability, an as CustomerBooking, M as CancelBookingResult, f as ActivityStateResponse, d2 as SessionMessage, c as ActivityRecommendation, ax as DeliveryFeeResponse, b6 as FxRateResponse, db as StorefrontBootstrap, Y as ChatWidgetStarter, X as ChatMessage, h as AddressInfo, n as AuthenticatedData, aT as ElementsOptions, c9 as PaymentMethodInfo, aR as ElementsCheckoutResult, ci as ProcessCheckoutOptions, ag as CimplifyElements, bg as LineItem, d5 as Staff, cQ as Room } from './client-C7EMuGoz.mjs';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
- import { ab as CurrencyCode, aX as Product, aO as Pagination, T as CimplifyError, b9 as ProductWithDetails, Q as Category, aM as Money, C as BundleSelectionInput, $ as ComponentSelectionInput, z as BundleSelectionData, a8 as CompositeSelectionData, U as Collection, b4 as ProductTaxonomy, bt as TaxonomyWithChildren, b5 as ProductTimeProfile, ah as Deal, b0 as ProductDealInfo, an as DiscountValidation, E as BundleSummary, a6 as CompositePriceResult, bo as SubscriptionWithDetails, bn as SubscriptionStatus, bk as Subscription, ac as CustomAttributeDefinition, ba as PropertyFacet, a$ as ProductBillingPlan, bL as VariantView, bF as VariantAxisWithValues, f as AddOnWithOptions, w as BundleComponentView, x as BundlePriceType, a4 as CompositeGroupView, aq as DisplayCart, b1 as ProductInputField, bg as SchedulingMode, at as DurationUnit, ad as CustomAttributeValue, b2 as ProductProperty, bc as QuantityPricingTier } from './product-B_kS4Oxa.mjs';
6
+ import { ab as CurrencyCode, aX as Product, aO as Pagination, T as CimplifyError, b9 as ProductWithDetails, Q as Category, aM as Money, C as BundleSelectionInput, $ as ComponentSelectionInput, z as BundleSelectionData, a8 as CompositeSelectionData, U as Collection, b4 as ProductTaxonomy, bt as TaxonomyWithChildren, b5 as ProductTimeProfile, ah as Deal, b0 as ProductDealInfo, an as DiscountValidation, E as BundleSummary, a6 as CompositePriceResult, bo as SubscriptionWithDetails, bn as SubscriptionStatus, bk as Subscription, ac as CustomAttributeDefinition, ba as PropertyFacet, a$ as ProductBillingPlan, bL as VariantView, bF as VariantAxisWithValues, f as AddOnWithOptions, w as BundleComponentView, x as BundlePriceType, a4 as CompositeGroupView, aq as DisplayCart, b1 as ProductInputField, bg as SchedulingMode, at as DurationUnit, aj as DepositType, ad as CustomAttributeValue, b2 as ProductProperty, bc as QuantityPricingTier } from './product-B_kS4Oxa.mjs';
7
7
  import { P as ProductWithPrice } from './price-Cm0tU0V5.mjs';
8
8
  import { ClassValue } from 'clsx';
9
9
  import { Matcher } from 'react-day-picker';
@@ -2632,6 +2632,40 @@ interface StaffPickerProps {
2632
2632
  }
2633
2633
  declare function StaffPicker({ staff, selectedStaffId, onStaffSelect, showAnyOption, anyLabel, className, classNames, }: StaffPickerProps): React$1.ReactElement;
2634
2634
 
2635
+ interface BookingSummaryClassNames {
2636
+ root?: string;
2637
+ header?: string;
2638
+ row?: string;
2639
+ label?: string;
2640
+ value?: string;
2641
+ totals?: string;
2642
+ deposit?: string;
2643
+ balance?: string;
2644
+ }
2645
+ interface BookingSummaryProps {
2646
+ /** The chosen slot — provides the date and time. */
2647
+ slot: AvailableSlot;
2648
+ /** Resolved per-booking total (variant/add-ons included), pre-deposit. */
2649
+ total: number;
2650
+ /** Selected staff member's name, when one was chosen. */
2651
+ staffName?: string | null;
2652
+ /** Service duration, shown in the header. */
2653
+ durationMinutes?: number;
2654
+ /** Deposit policy — drives the "due now" / "balance" split. */
2655
+ depositType?: DepositType;
2656
+ depositAmount?: Money;
2657
+ currency?: CurrencyCode;
2658
+ className?: string;
2659
+ classNames?: BookingSummaryClassNames;
2660
+ }
2661
+ /**
2662
+ * BookingSummary — a live recap of a service booking: who, when, and the
2663
+ * deposit-due / balance split derived from the product's deposit policy.
2664
+ *
2665
+ * Presentational: the host owns the selected slot, staff and quote total.
2666
+ */
2667
+ declare function BookingSummary({ slot, total, staffName, durationMinutes, depositType, depositAmount, currency, className, classNames, }: BookingSummaryProps): React$1.ReactElement;
2668
+
2635
2669
  interface BookingCardClassNames {
2636
2670
  root?: string;
2637
2671
  service?: string;
@@ -3662,4 +3696,4 @@ interface ChatWidgetProps {
3662
3696
  }
3663
3697
  declare function ChatWidget({ client: clientProp, businessName, greeting, subtitle, starters, placeholder, position, defaultOpen, pollInterval, className, classNames, }: ChatWidgetProps): react_jsx_runtime.JSX.Element;
3664
3698
 
3665
- export { AccommodationCard, AccountContent, type AccountContentProps, AccountDashboardPage, type AccountDashboardPageProps, AccountHero, type AccountHeroProps, AccountIdentityStrip, type AccountIdentityStripProps, AccountLineItem, type AccountLineItemData, type AccountLineItemProps, AccountLineItems, type AccountLineItemsProps, AccountNav, type AccountNavProps, AccountOrderDetailPage, type AccountOrderDetailPageProps, AccountOrderView, type AccountOrderViewProps, AccountOrdersPage, type AccountOrdersPageProps, type AccountPageBaseProps, AccountShell, type AccountShellProps, AccountSidebar, type AccountSidebarProps, AccountSignedOutPrompt, type AccountSignedOutPromptProps, AccountSubscriptionDetailPage, type AccountSubscriptionDetailPageProps, AccountSubscriptionsPage, type AccountSubscriptionsPageProps, Ad, AdPosition, type AdProps, AdProvider, AdSlot, AddOnSelector, type AddOnSelectorClassNames, type AddOnSelectorProps, type AddToCartOptions, AddressElement, AuthElement, AvailabilityBadge, type AvailabilityBadgeClassNames, type AvailabilityBadgeProps, BackLink, type BackLinkProps, BillingPlanSelector, type BillingPlanSelectorClassNames, type BillingPlanSelectorProps, BookingCard, type BookingCardClassNames, type BookingCardProps, BookingList, type BookingListClassNames, type BookingListProps, BookingPage, type BookingPageClassNames, type BookingPageProps, BookingsPage, type BookingsPageClassNames, type BookingsPageProps, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, type BundleSelectorClassNames, type BundleSelectorProps, Button, type ButtonProps, CardImage, type CardLayoutProps, CardShell, CardVariant, type CartAddOnOptionSelection, CartDrawer, type CartDrawerProps, CartDrawerProvider, type CartLayoutProps, CartPage, type CartPageClassNames, type CartPageProps, CartSummary, type CartSummaryClassNames, type CartSummaryProps, CartTemplate, type CartVariantSelection, CatalogueCollectionLayout, type CatalogueLayoutProps, CataloguePage, type CataloguePageClassNames, type CataloguePageProps, CatalogueTemplate, CategoryFilter, type CategoryFilterClassNames, type CategoryFilterProps, CategoryGrid, type CategoryGridClassNames, type CategoryGridProps, ChatWidget, type ChatWidgetClassNames, type ChatWidgetProps, CheckIcon, CheckoutPage, type CheckoutPageClassNames, type CheckoutPageProps, CimplifyCheckout, type CimplifyCheckoutProps, type CimplifyClientContextValue, type CimplifyClientSession, type CimplifyContextValue, CimplifyProvider, type CimplifyProviderProps, CimplifySignInButton, type CimplifySignInButtonProps, CimplifyUserButton, type CimplifyUserButtonProps, type CollectionLayoutProps, CollectionPage, type CollectionPageClassNames, type CollectionPageProps, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, type CompositeSelectorClassNames, type CompositeSelectorProps, ContextCard, type ContextCardProps, type ContextRow, ContinuityCard, type ContinuityCardProps, CurrencySelector, type CurrencySelectorClassNames, type CurrencySelectorProps, CustomAttributesTable, type CustomerInput, CustomerInputFields, type CustomerInputFieldsClassNames, type CustomerInputFieldsProps, type CustomerInputType, DashboardIcon, DashboardIcon20, DatePicker, type DatePickerClassNames, type DatePickerProps, DateSlotPicker, type DateSlotPickerClassNames, type DateSlotPickerProps, DealBanner, type DealBannerClassNames, type DealBannerProps, DealsPage, type DealsPageClassNames, type DealsPageProps, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, type DeliveryEstimateClassNames, type DeliveryEstimateProps, type DeliveryLive, type DeliveryRider, DeliveryTracker, type DeliveryTrackerProps, DeliveryTruckIcon, type DigitalFulfillment, DigitalProductCard, DigitalProductLayout, DiscountInput, type DiscountInputClassNames, type DiscountInputProps, ElementsProvider, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, FeaturedCollectionLayout, type FilterTabItem, FilterTabs, type FilterTabsProps, FoodProductCard, FoodProductLayout, HappeningCard, type HappeningCardProps, type HappeningPaneData, IdentityIcon, IdentityOfframp, type IdentityOfframpProps, type IdentitySummary, InventoryBadge, ItemsCard, type ItemsCardProps, LeaseServiceCard, LineItemDetails, type LineItemSemanticKind, type LineScheduling, type LineSelection, type LineStateTone, LocationPicker, type LocationPickerClassNames, type LocationPickerProps, MediaGallery, type MediaGalleryProps, type MediaItem, MetadataStringList, MobileAccountShell, type MobileAccountShellProps, MobileBackButton, MobileMoreButton, MobileTabBar, type MobileTabBarProps, type NavItem, NextDeliveryCard, type NextDeliveryCardProps, OrderDetailHeader, type OrderDetailHeaderProps, OrderDetailMetaPipe, OrderDetailPage, type OrderDetailPageClassNames, type OrderDetailPageProps, OrderHistory, type OrderHistoryClassNames, OrderHistoryPage, type OrderHistoryPageClassNames, type OrderHistoryPageProps, type OrderHistoryProps, type OrderItemData, OrderList, type OrderListProps, OrderRow, type OrderRowData, type OrderRowProps, type OrderRowStatus, type OrderStatusTone, OrderSummary, type OrderSummaryClassNames, type OrderSummaryProps, OrderTimeline, type OrderTimelineProps, OrderTotals, type OrderTotalsProps, type OrderViewDelivery, type OrderViewPayment, type OrderViewPaymentRow, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, type PriceProps, PriceRange, type PriceRangeProps, ProductCard, type ProductCardClassNames, type ProductCardProps, ProductCustomizer, type ProductCustomizerClassNames, type ProductCustomizerProps, ProductGrid, type ProductGridClassNames, type ProductGridProps, ProductImageGallery, type ProductImageGalleryProps, type ProductLayoutProps, ProductModel3D, type ProductModel3DProps, ProductPage, type ProductPageClassNames, type ProductPageProps, ProductSheet, type ProductSheetClassNames, type ProductSheetProps, ProductTemplate, PropertiesTable, QuantitySelector, type QuantitySelectorClassNames, type QuantitySelectorProps, QuickAddButton, RecentlyViewed, type RecentlyViewedClassNames, type RecentlyViewedProps, RecommendationCarousel, type RecommendationCarouselClassNames, type RecommendationCarouselProps, RelatedProductsSection, RentalServiceCard, type Resource, ResourcePicker, type ResourcePickerClassNames, type ResourcePickerProps, RetailProductCard, RichText, type RichTextProps, SaleBadge, type SaleBadgeClassNames, type SaleBadgeProps, ScheduleServiceCard, SearchInput, type SearchInputClassNames, type SearchInputProps, type SearchLayoutProps, SearchPage, type SearchPageClassNames, type SearchPageProps, SearchTemplate, Section, SectionMore, type SectionMoreProps, type SectionProps, type ServiceCardLayoutProps, ServiceProductLayout, SessionMessageBanner, type SessionMessageBannerClassNames, type SessionMessageBannerProps, SignOutIcon, Skeleton, type SkeletonProps, SlotPicker, type SlotPickerClassNames, type SlotPickerProps, SoldOutOverlay, StaffPicker, type StaffPickerClassNames, type StaffPickerProps, StandardServiceCard, Status, type StatusProps, StoreNav, type StoreNavClassNames, type StoreNavProps, StoreVideo, type StoreVideoProps, SubscriptionCard, SubscriptionList, type SubscriptionListProps, SubscriptionRow, type SubscriptionRowData, type SubscriptionRowProps, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, type TimePickerClassNames, type TimePickerProps, type TimelineStep, type ToAccountOrderViewOptions, Toast, type ToastProps, type TotalsData, TwoColumnGrid, type UseActivityStateOptions, type UseActivityStateResult, type UseAttributeDefinitionsOptions, type UseAttributeDefinitionsResult, type UseAvailableSlotsOptions, type UseAvailableSlotsResult, type UseBillingPlansOptions, type UseBillingPlansResult, type UseBookingsOptions, type UseBookingsResult, type UseBootstrapOptions, type UseBootstrapResult, type UseBundlesOptions, type UseBundlesResult, type UseCartItem, type UseCartOptions, type UseCartResult, type UseCategoriesOptions, type UseCategoriesResult, type UseChatOptions, type UseChatResult, type UseCimplifySessionOptions, type UseCimplifySessionResult, type UseCollectionOptions, type UseCollectionResult, type UseCollectionsOptions, type UseCollectionsResult, type UseDealsOptions, type UseDealsResult, type UseDeliveryFeeOptions, type UseDeliveryFeeResult, type UseFxRateOptions, type UseFxRateResult, type UseLocationsOptions, type UseLocationsResult, type UseOrderOptions, type UseOrderResult, type UseOrdersOptions, type UseOrdersResult, type UseProductAvailabilityOptions, type UseProductAvailabilityResult, type UseProductDealsOptions, type UseProductDealsResult, type UseProductOptions, type UseProductPriceInput, type UseProductPriceResult, type UseProductResult, type UseProductSchedulesOptions, type UseProductSchedulesResult, type UseProductsOnSaleOptions, type UseProductsOnSaleResult, type UseProductsOptions, type UseProductsResult, type UsePropertyFacetsOptions, type UsePropertyFacetsResult, type UseQuoteInput, type UseQuoteOptions, type UseQuoteResult, type UseRecommendationsOptions, type UseRecommendationsResult, type UseSearchOptions, type UseSearchResult, type UseServiceAvailabilityOptions, type UseServiceAvailabilityResult, type UseServicesOptions, type UseServicesResult, type UseTaxonomiesOptions, type UseTaxonomiesResult, type UseTaxonomyOptions, type UseTaxonomyPathOptions, type UseTaxonomyPathResult, type UseTaxonomyResult, type UseValidateDiscountOptions, type UseValidateDiscountResult, type UseVariantSelectorOptions, type UseVariantSelectorResult, type UserButtonLink, VariantSelector, type VariantSelectorClassNames, type VariantSelectorProps, VolumePricing, type VolumePricingClassNames, type VolumePricingProps, WelcomeCard, type WelcomeCardProps, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
3699
+ export { AccommodationCard, AccountContent, type AccountContentProps, AccountDashboardPage, type AccountDashboardPageProps, AccountHero, type AccountHeroProps, AccountIdentityStrip, type AccountIdentityStripProps, AccountLineItem, type AccountLineItemData, type AccountLineItemProps, AccountLineItems, type AccountLineItemsProps, AccountNav, type AccountNavProps, AccountOrderDetailPage, type AccountOrderDetailPageProps, AccountOrderView, type AccountOrderViewProps, AccountOrdersPage, type AccountOrdersPageProps, type AccountPageBaseProps, AccountShell, type AccountShellProps, AccountSidebar, type AccountSidebarProps, AccountSignedOutPrompt, type AccountSignedOutPromptProps, AccountSubscriptionDetailPage, type AccountSubscriptionDetailPageProps, AccountSubscriptionsPage, type AccountSubscriptionsPageProps, Ad, AdPosition, type AdProps, AdProvider, AdSlot, AddOnSelector, type AddOnSelectorClassNames, type AddOnSelectorProps, type AddToCartOptions, AddressElement, AuthElement, AvailabilityBadge, type AvailabilityBadgeClassNames, type AvailabilityBadgeProps, BackLink, type BackLinkProps, BillingPlanSelector, type BillingPlanSelectorClassNames, type BillingPlanSelectorProps, BookingCard, type BookingCardClassNames, type BookingCardProps, BookingList, type BookingListClassNames, type BookingListProps, BookingPage, type BookingPageClassNames, type BookingPageProps, BookingSummary, type BookingSummaryClassNames, type BookingSummaryProps, BookingsPage, type BookingsPageClassNames, type BookingsPageProps, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, type BundleSelectorClassNames, type BundleSelectorProps, Button, type ButtonProps, CardImage, type CardLayoutProps, CardShell, CardVariant, type CartAddOnOptionSelection, CartDrawer, type CartDrawerProps, CartDrawerProvider, type CartLayoutProps, CartPage, type CartPageClassNames, type CartPageProps, CartSummary, type CartSummaryClassNames, type CartSummaryProps, CartTemplate, type CartVariantSelection, CatalogueCollectionLayout, type CatalogueLayoutProps, CataloguePage, type CataloguePageClassNames, type CataloguePageProps, CatalogueTemplate, CategoryFilter, type CategoryFilterClassNames, type CategoryFilterProps, CategoryGrid, type CategoryGridClassNames, type CategoryGridProps, ChatWidget, type ChatWidgetClassNames, type ChatWidgetProps, CheckIcon, CheckoutPage, type CheckoutPageClassNames, type CheckoutPageProps, CimplifyCheckout, type CimplifyCheckoutProps, type CimplifyClientContextValue, type CimplifyClientSession, type CimplifyContextValue, CimplifyProvider, type CimplifyProviderProps, CimplifySignInButton, type CimplifySignInButtonProps, CimplifyUserButton, type CimplifyUserButtonProps, type CollectionLayoutProps, CollectionPage, type CollectionPageClassNames, type CollectionPageProps, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, type CompositeSelectorClassNames, type CompositeSelectorProps, ContextCard, type ContextCardProps, type ContextRow, ContinuityCard, type ContinuityCardProps, CurrencySelector, type CurrencySelectorClassNames, type CurrencySelectorProps, CustomAttributesTable, type CustomerInput, CustomerInputFields, type CustomerInputFieldsClassNames, type CustomerInputFieldsProps, type CustomerInputType, DashboardIcon, DashboardIcon20, DatePicker, type DatePickerClassNames, type DatePickerProps, DateSlotPicker, type DateSlotPickerClassNames, type DateSlotPickerProps, DealBanner, type DealBannerClassNames, type DealBannerProps, DealsPage, type DealsPageClassNames, type DealsPageProps, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, type DeliveryEstimateClassNames, type DeliveryEstimateProps, type DeliveryLive, type DeliveryRider, DeliveryTracker, type DeliveryTrackerProps, DeliveryTruckIcon, type DigitalFulfillment, DigitalProductCard, DigitalProductLayout, DiscountInput, type DiscountInputClassNames, type DiscountInputProps, ElementsProvider, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, FeaturedCollectionLayout, type FilterTabItem, FilterTabs, type FilterTabsProps, FoodProductCard, FoodProductLayout, HappeningCard, type HappeningCardProps, type HappeningPaneData, IdentityIcon, IdentityOfframp, type IdentityOfframpProps, type IdentitySummary, InventoryBadge, ItemsCard, type ItemsCardProps, LeaseServiceCard, LineItemDetails, type LineItemSemanticKind, type LineScheduling, type LineSelection, type LineStateTone, LocationPicker, type LocationPickerClassNames, type LocationPickerProps, MediaGallery, type MediaGalleryProps, type MediaItem, MetadataStringList, MobileAccountShell, type MobileAccountShellProps, MobileBackButton, MobileMoreButton, MobileTabBar, type MobileTabBarProps, type NavItem, NextDeliveryCard, type NextDeliveryCardProps, OrderDetailHeader, type OrderDetailHeaderProps, OrderDetailMetaPipe, OrderDetailPage, type OrderDetailPageClassNames, type OrderDetailPageProps, OrderHistory, type OrderHistoryClassNames, OrderHistoryPage, type OrderHistoryPageClassNames, type OrderHistoryPageProps, type OrderHistoryProps, type OrderItemData, OrderList, type OrderListProps, OrderRow, type OrderRowData, type OrderRowProps, type OrderRowStatus, type OrderStatusTone, OrderSummary, type OrderSummaryClassNames, type OrderSummaryProps, OrderTimeline, type OrderTimelineProps, OrderTotals, type OrderTotalsProps, type OrderViewDelivery, type OrderViewPayment, type OrderViewPaymentRow, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, type PriceProps, PriceRange, type PriceRangeProps, ProductCard, type ProductCardClassNames, type ProductCardProps, ProductCustomizer, type ProductCustomizerClassNames, type ProductCustomizerProps, ProductGrid, type ProductGridClassNames, type ProductGridProps, ProductImageGallery, type ProductImageGalleryProps, type ProductLayoutProps, ProductModel3D, type ProductModel3DProps, ProductPage, type ProductPageClassNames, type ProductPageProps, ProductSheet, type ProductSheetClassNames, type ProductSheetProps, ProductTemplate, PropertiesTable, QuantitySelector, type QuantitySelectorClassNames, type QuantitySelectorProps, QuickAddButton, RecentlyViewed, type RecentlyViewedClassNames, type RecentlyViewedProps, RecommendationCarousel, type RecommendationCarouselClassNames, type RecommendationCarouselProps, RelatedProductsSection, RentalServiceCard, type Resource, ResourcePicker, type ResourcePickerClassNames, type ResourcePickerProps, RetailProductCard, RichText, type RichTextProps, SaleBadge, type SaleBadgeClassNames, type SaleBadgeProps, ScheduleServiceCard, SearchInput, type SearchInputClassNames, type SearchInputProps, type SearchLayoutProps, SearchPage, type SearchPageClassNames, type SearchPageProps, SearchTemplate, Section, SectionMore, type SectionMoreProps, type SectionProps, type ServiceCardLayoutProps, ServiceProductLayout, SessionMessageBanner, type SessionMessageBannerClassNames, type SessionMessageBannerProps, SignOutIcon, Skeleton, type SkeletonProps, SlotPicker, type SlotPickerClassNames, type SlotPickerProps, SoldOutOverlay, StaffPicker, type StaffPickerClassNames, type StaffPickerProps, StandardServiceCard, Status, type StatusProps, StoreNav, type StoreNavClassNames, type StoreNavProps, StoreVideo, type StoreVideoProps, SubscriptionCard, SubscriptionList, type SubscriptionListProps, SubscriptionRow, type SubscriptionRowData, type SubscriptionRowProps, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, type TimePickerClassNames, type TimePickerProps, type TimelineStep, type ToAccountOrderViewOptions, Toast, type ToastProps, type TotalsData, TwoColumnGrid, type UseActivityStateOptions, type UseActivityStateResult, type UseAttributeDefinitionsOptions, type UseAttributeDefinitionsResult, type UseAvailableSlotsOptions, type UseAvailableSlotsResult, type UseBillingPlansOptions, type UseBillingPlansResult, type UseBookingsOptions, type UseBookingsResult, type UseBootstrapOptions, type UseBootstrapResult, type UseBundlesOptions, type UseBundlesResult, type UseCartItem, type UseCartOptions, type UseCartResult, type UseCategoriesOptions, type UseCategoriesResult, type UseChatOptions, type UseChatResult, type UseCimplifySessionOptions, type UseCimplifySessionResult, type UseCollectionOptions, type UseCollectionResult, type UseCollectionsOptions, type UseCollectionsResult, type UseDealsOptions, type UseDealsResult, type UseDeliveryFeeOptions, type UseDeliveryFeeResult, type UseFxRateOptions, type UseFxRateResult, type UseLocationsOptions, type UseLocationsResult, type UseOrderOptions, type UseOrderResult, type UseOrdersOptions, type UseOrdersResult, type UseProductAvailabilityOptions, type UseProductAvailabilityResult, type UseProductDealsOptions, type UseProductDealsResult, type UseProductOptions, type UseProductPriceInput, type UseProductPriceResult, type UseProductResult, type UseProductSchedulesOptions, type UseProductSchedulesResult, type UseProductsOnSaleOptions, type UseProductsOnSaleResult, type UseProductsOptions, type UseProductsResult, type UsePropertyFacetsOptions, type UsePropertyFacetsResult, type UseQuoteInput, type UseQuoteOptions, type UseQuoteResult, type UseRecommendationsOptions, type UseRecommendationsResult, type UseSearchOptions, type UseSearchResult, type UseServiceAvailabilityOptions, type UseServiceAvailabilityResult, type UseServicesOptions, type UseServicesResult, type UseTaxonomiesOptions, type UseTaxonomiesResult, type UseTaxonomyOptions, type UseTaxonomyPathOptions, type UseTaxonomyPathResult, type UseTaxonomyResult, type UseValidateDiscountOptions, type UseValidateDiscountResult, type UseVariantSelectorOptions, type UseVariantSelectorResult, type UserButtonLink, VariantSelector, type VariantSelectorClassNames, type VariantSelectorProps, VolumePricing, type VolumePricingClassNames, type VolumePricingProps, WelcomeCard, type WelcomeCardProps, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
package/dist/react.d.ts CHANGED
@@ -3,7 +3,7 @@ import { d as AdSlot, c as AdPosition, a as AdContextValue, S as SignInOptions }
3
3
  export { A as AdConfig, g as getVariantDisplayName } from './sign-in-DQlIdqsi.js';
4
4
  import { ad as CimplifyClient, cj as ProcessCheckoutResult, aa as CheckoutStatus, ab as CheckoutStatusContext, aV as EnrichedOrderItem, aU as EnrichedOrder, w as Business, bp as Location, cA as ReorderResult, b$ as OrderStatus, bF as Order, cl as QuoteBundleSelectionInput, cm as QuoteCompositeSelectionInput, cf as PriceQuote, cp as QuoteUiMessage, cV as Service, r as AvailableSlot, av as DayAvailability, an as CustomerBooking, M as CancelBookingResult, f as ActivityStateResponse, d2 as SessionMessage, c as ActivityRecommendation, ax as DeliveryFeeResponse, b6 as FxRateResponse, db as StorefrontBootstrap, Y as ChatWidgetStarter, X as ChatMessage, h as AddressInfo, n as AuthenticatedData, aT as ElementsOptions, c9 as PaymentMethodInfo, aR as ElementsCheckoutResult, ci as ProcessCheckoutOptions, ag as CimplifyElements, bg as LineItem, d5 as Staff, cQ as Room } from './client-D6CZ2Ggp.js';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
- import { ab as CurrencyCode, aX as Product, aO as Pagination, T as CimplifyError, b9 as ProductWithDetails, Q as Category, aM as Money, C as BundleSelectionInput, $ as ComponentSelectionInput, z as BundleSelectionData, a8 as CompositeSelectionData, U as Collection, b4 as ProductTaxonomy, bt as TaxonomyWithChildren, b5 as ProductTimeProfile, ah as Deal, b0 as ProductDealInfo, an as DiscountValidation, E as BundleSummary, a6 as CompositePriceResult, bo as SubscriptionWithDetails, bn as SubscriptionStatus, bk as Subscription, ac as CustomAttributeDefinition, ba as PropertyFacet, a$ as ProductBillingPlan, bL as VariantView, bF as VariantAxisWithValues, f as AddOnWithOptions, w as BundleComponentView, x as BundlePriceType, a4 as CompositeGroupView, aq as DisplayCart, b1 as ProductInputField, bg as SchedulingMode, at as DurationUnit, ad as CustomAttributeValue, b2 as ProductProperty, bc as QuantityPricingTier } from './product-B_kS4Oxa.js';
6
+ import { ab as CurrencyCode, aX as Product, aO as Pagination, T as CimplifyError, b9 as ProductWithDetails, Q as Category, aM as Money, C as BundleSelectionInput, $ as ComponentSelectionInput, z as BundleSelectionData, a8 as CompositeSelectionData, U as Collection, b4 as ProductTaxonomy, bt as TaxonomyWithChildren, b5 as ProductTimeProfile, ah as Deal, b0 as ProductDealInfo, an as DiscountValidation, E as BundleSummary, a6 as CompositePriceResult, bo as SubscriptionWithDetails, bn as SubscriptionStatus, bk as Subscription, ac as CustomAttributeDefinition, ba as PropertyFacet, a$ as ProductBillingPlan, bL as VariantView, bF as VariantAxisWithValues, f as AddOnWithOptions, w as BundleComponentView, x as BundlePriceType, a4 as CompositeGroupView, aq as DisplayCart, b1 as ProductInputField, bg as SchedulingMode, at as DurationUnit, aj as DepositType, ad as CustomAttributeValue, b2 as ProductProperty, bc as QuantityPricingTier } from './product-B_kS4Oxa.js';
7
7
  import { P as ProductWithPrice } from './price-9T1Y47oS.js';
8
8
  import { ClassValue } from 'clsx';
9
9
  import { Matcher } from 'react-day-picker';
@@ -2632,6 +2632,40 @@ interface StaffPickerProps {
2632
2632
  }
2633
2633
  declare function StaffPicker({ staff, selectedStaffId, onStaffSelect, showAnyOption, anyLabel, className, classNames, }: StaffPickerProps): React$1.ReactElement;
2634
2634
 
2635
+ interface BookingSummaryClassNames {
2636
+ root?: string;
2637
+ header?: string;
2638
+ row?: string;
2639
+ label?: string;
2640
+ value?: string;
2641
+ totals?: string;
2642
+ deposit?: string;
2643
+ balance?: string;
2644
+ }
2645
+ interface BookingSummaryProps {
2646
+ /** The chosen slot — provides the date and time. */
2647
+ slot: AvailableSlot;
2648
+ /** Resolved per-booking total (variant/add-ons included), pre-deposit. */
2649
+ total: number;
2650
+ /** Selected staff member's name, when one was chosen. */
2651
+ staffName?: string | null;
2652
+ /** Service duration, shown in the header. */
2653
+ durationMinutes?: number;
2654
+ /** Deposit policy — drives the "due now" / "balance" split. */
2655
+ depositType?: DepositType;
2656
+ depositAmount?: Money;
2657
+ currency?: CurrencyCode;
2658
+ className?: string;
2659
+ classNames?: BookingSummaryClassNames;
2660
+ }
2661
+ /**
2662
+ * BookingSummary — a live recap of a service booking: who, when, and the
2663
+ * deposit-due / balance split derived from the product's deposit policy.
2664
+ *
2665
+ * Presentational: the host owns the selected slot, staff and quote total.
2666
+ */
2667
+ declare function BookingSummary({ slot, total, staffName, durationMinutes, depositType, depositAmount, currency, className, classNames, }: BookingSummaryProps): React$1.ReactElement;
2668
+
2635
2669
  interface BookingCardClassNames {
2636
2670
  root?: string;
2637
2671
  service?: string;
@@ -3662,4 +3696,4 @@ interface ChatWidgetProps {
3662
3696
  }
3663
3697
  declare function ChatWidget({ client: clientProp, businessName, greeting, subtitle, starters, placeholder, position, defaultOpen, pollInterval, className, classNames, }: ChatWidgetProps): react_jsx_runtime.JSX.Element;
3664
3698
 
3665
- export { AccommodationCard, AccountContent, type AccountContentProps, AccountDashboardPage, type AccountDashboardPageProps, AccountHero, type AccountHeroProps, AccountIdentityStrip, type AccountIdentityStripProps, AccountLineItem, type AccountLineItemData, type AccountLineItemProps, AccountLineItems, type AccountLineItemsProps, AccountNav, type AccountNavProps, AccountOrderDetailPage, type AccountOrderDetailPageProps, AccountOrderView, type AccountOrderViewProps, AccountOrdersPage, type AccountOrdersPageProps, type AccountPageBaseProps, AccountShell, type AccountShellProps, AccountSidebar, type AccountSidebarProps, AccountSignedOutPrompt, type AccountSignedOutPromptProps, AccountSubscriptionDetailPage, type AccountSubscriptionDetailPageProps, AccountSubscriptionsPage, type AccountSubscriptionsPageProps, Ad, AdPosition, type AdProps, AdProvider, AdSlot, AddOnSelector, type AddOnSelectorClassNames, type AddOnSelectorProps, type AddToCartOptions, AddressElement, AuthElement, AvailabilityBadge, type AvailabilityBadgeClassNames, type AvailabilityBadgeProps, BackLink, type BackLinkProps, BillingPlanSelector, type BillingPlanSelectorClassNames, type BillingPlanSelectorProps, BookingCard, type BookingCardClassNames, type BookingCardProps, BookingList, type BookingListClassNames, type BookingListProps, BookingPage, type BookingPageClassNames, type BookingPageProps, BookingsPage, type BookingsPageClassNames, type BookingsPageProps, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, type BundleSelectorClassNames, type BundleSelectorProps, Button, type ButtonProps, CardImage, type CardLayoutProps, CardShell, CardVariant, type CartAddOnOptionSelection, CartDrawer, type CartDrawerProps, CartDrawerProvider, type CartLayoutProps, CartPage, type CartPageClassNames, type CartPageProps, CartSummary, type CartSummaryClassNames, type CartSummaryProps, CartTemplate, type CartVariantSelection, CatalogueCollectionLayout, type CatalogueLayoutProps, CataloguePage, type CataloguePageClassNames, type CataloguePageProps, CatalogueTemplate, CategoryFilter, type CategoryFilterClassNames, type CategoryFilterProps, CategoryGrid, type CategoryGridClassNames, type CategoryGridProps, ChatWidget, type ChatWidgetClassNames, type ChatWidgetProps, CheckIcon, CheckoutPage, type CheckoutPageClassNames, type CheckoutPageProps, CimplifyCheckout, type CimplifyCheckoutProps, type CimplifyClientContextValue, type CimplifyClientSession, type CimplifyContextValue, CimplifyProvider, type CimplifyProviderProps, CimplifySignInButton, type CimplifySignInButtonProps, CimplifyUserButton, type CimplifyUserButtonProps, type CollectionLayoutProps, CollectionPage, type CollectionPageClassNames, type CollectionPageProps, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, type CompositeSelectorClassNames, type CompositeSelectorProps, ContextCard, type ContextCardProps, type ContextRow, ContinuityCard, type ContinuityCardProps, CurrencySelector, type CurrencySelectorClassNames, type CurrencySelectorProps, CustomAttributesTable, type CustomerInput, CustomerInputFields, type CustomerInputFieldsClassNames, type CustomerInputFieldsProps, type CustomerInputType, DashboardIcon, DashboardIcon20, DatePicker, type DatePickerClassNames, type DatePickerProps, DateSlotPicker, type DateSlotPickerClassNames, type DateSlotPickerProps, DealBanner, type DealBannerClassNames, type DealBannerProps, DealsPage, type DealsPageClassNames, type DealsPageProps, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, type DeliveryEstimateClassNames, type DeliveryEstimateProps, type DeliveryLive, type DeliveryRider, DeliveryTracker, type DeliveryTrackerProps, DeliveryTruckIcon, type DigitalFulfillment, DigitalProductCard, DigitalProductLayout, DiscountInput, type DiscountInputClassNames, type DiscountInputProps, ElementsProvider, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, FeaturedCollectionLayout, type FilterTabItem, FilterTabs, type FilterTabsProps, FoodProductCard, FoodProductLayout, HappeningCard, type HappeningCardProps, type HappeningPaneData, IdentityIcon, IdentityOfframp, type IdentityOfframpProps, type IdentitySummary, InventoryBadge, ItemsCard, type ItemsCardProps, LeaseServiceCard, LineItemDetails, type LineItemSemanticKind, type LineScheduling, type LineSelection, type LineStateTone, LocationPicker, type LocationPickerClassNames, type LocationPickerProps, MediaGallery, type MediaGalleryProps, type MediaItem, MetadataStringList, MobileAccountShell, type MobileAccountShellProps, MobileBackButton, MobileMoreButton, MobileTabBar, type MobileTabBarProps, type NavItem, NextDeliveryCard, type NextDeliveryCardProps, OrderDetailHeader, type OrderDetailHeaderProps, OrderDetailMetaPipe, OrderDetailPage, type OrderDetailPageClassNames, type OrderDetailPageProps, OrderHistory, type OrderHistoryClassNames, OrderHistoryPage, type OrderHistoryPageClassNames, type OrderHistoryPageProps, type OrderHistoryProps, type OrderItemData, OrderList, type OrderListProps, OrderRow, type OrderRowData, type OrderRowProps, type OrderRowStatus, type OrderStatusTone, OrderSummary, type OrderSummaryClassNames, type OrderSummaryProps, OrderTimeline, type OrderTimelineProps, OrderTotals, type OrderTotalsProps, type OrderViewDelivery, type OrderViewPayment, type OrderViewPaymentRow, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, type PriceProps, PriceRange, type PriceRangeProps, ProductCard, type ProductCardClassNames, type ProductCardProps, ProductCustomizer, type ProductCustomizerClassNames, type ProductCustomizerProps, ProductGrid, type ProductGridClassNames, type ProductGridProps, ProductImageGallery, type ProductImageGalleryProps, type ProductLayoutProps, ProductModel3D, type ProductModel3DProps, ProductPage, type ProductPageClassNames, type ProductPageProps, ProductSheet, type ProductSheetClassNames, type ProductSheetProps, ProductTemplate, PropertiesTable, QuantitySelector, type QuantitySelectorClassNames, type QuantitySelectorProps, QuickAddButton, RecentlyViewed, type RecentlyViewedClassNames, type RecentlyViewedProps, RecommendationCarousel, type RecommendationCarouselClassNames, type RecommendationCarouselProps, RelatedProductsSection, RentalServiceCard, type Resource, ResourcePicker, type ResourcePickerClassNames, type ResourcePickerProps, RetailProductCard, RichText, type RichTextProps, SaleBadge, type SaleBadgeClassNames, type SaleBadgeProps, ScheduleServiceCard, SearchInput, type SearchInputClassNames, type SearchInputProps, type SearchLayoutProps, SearchPage, type SearchPageClassNames, type SearchPageProps, SearchTemplate, Section, SectionMore, type SectionMoreProps, type SectionProps, type ServiceCardLayoutProps, ServiceProductLayout, SessionMessageBanner, type SessionMessageBannerClassNames, type SessionMessageBannerProps, SignOutIcon, Skeleton, type SkeletonProps, SlotPicker, type SlotPickerClassNames, type SlotPickerProps, SoldOutOverlay, StaffPicker, type StaffPickerClassNames, type StaffPickerProps, StandardServiceCard, Status, type StatusProps, StoreNav, type StoreNavClassNames, type StoreNavProps, StoreVideo, type StoreVideoProps, SubscriptionCard, SubscriptionList, type SubscriptionListProps, SubscriptionRow, type SubscriptionRowData, type SubscriptionRowProps, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, type TimePickerClassNames, type TimePickerProps, type TimelineStep, type ToAccountOrderViewOptions, Toast, type ToastProps, type TotalsData, TwoColumnGrid, type UseActivityStateOptions, type UseActivityStateResult, type UseAttributeDefinitionsOptions, type UseAttributeDefinitionsResult, type UseAvailableSlotsOptions, type UseAvailableSlotsResult, type UseBillingPlansOptions, type UseBillingPlansResult, type UseBookingsOptions, type UseBookingsResult, type UseBootstrapOptions, type UseBootstrapResult, type UseBundlesOptions, type UseBundlesResult, type UseCartItem, type UseCartOptions, type UseCartResult, type UseCategoriesOptions, type UseCategoriesResult, type UseChatOptions, type UseChatResult, type UseCimplifySessionOptions, type UseCimplifySessionResult, type UseCollectionOptions, type UseCollectionResult, type UseCollectionsOptions, type UseCollectionsResult, type UseDealsOptions, type UseDealsResult, type UseDeliveryFeeOptions, type UseDeliveryFeeResult, type UseFxRateOptions, type UseFxRateResult, type UseLocationsOptions, type UseLocationsResult, type UseOrderOptions, type UseOrderResult, type UseOrdersOptions, type UseOrdersResult, type UseProductAvailabilityOptions, type UseProductAvailabilityResult, type UseProductDealsOptions, type UseProductDealsResult, type UseProductOptions, type UseProductPriceInput, type UseProductPriceResult, type UseProductResult, type UseProductSchedulesOptions, type UseProductSchedulesResult, type UseProductsOnSaleOptions, type UseProductsOnSaleResult, type UseProductsOptions, type UseProductsResult, type UsePropertyFacetsOptions, type UsePropertyFacetsResult, type UseQuoteInput, type UseQuoteOptions, type UseQuoteResult, type UseRecommendationsOptions, type UseRecommendationsResult, type UseSearchOptions, type UseSearchResult, type UseServiceAvailabilityOptions, type UseServiceAvailabilityResult, type UseServicesOptions, type UseServicesResult, type UseTaxonomiesOptions, type UseTaxonomiesResult, type UseTaxonomyOptions, type UseTaxonomyPathOptions, type UseTaxonomyPathResult, type UseTaxonomyResult, type UseValidateDiscountOptions, type UseValidateDiscountResult, type UseVariantSelectorOptions, type UseVariantSelectorResult, type UserButtonLink, VariantSelector, type VariantSelectorClassNames, type VariantSelectorProps, VolumePricing, type VolumePricingClassNames, type VolumePricingProps, WelcomeCard, type WelcomeCardProps, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
3699
+ export { AccommodationCard, AccountContent, type AccountContentProps, AccountDashboardPage, type AccountDashboardPageProps, AccountHero, type AccountHeroProps, AccountIdentityStrip, type AccountIdentityStripProps, AccountLineItem, type AccountLineItemData, type AccountLineItemProps, AccountLineItems, type AccountLineItemsProps, AccountNav, type AccountNavProps, AccountOrderDetailPage, type AccountOrderDetailPageProps, AccountOrderView, type AccountOrderViewProps, AccountOrdersPage, type AccountOrdersPageProps, type AccountPageBaseProps, AccountShell, type AccountShellProps, AccountSidebar, type AccountSidebarProps, AccountSignedOutPrompt, type AccountSignedOutPromptProps, AccountSubscriptionDetailPage, type AccountSubscriptionDetailPageProps, AccountSubscriptionsPage, type AccountSubscriptionsPageProps, Ad, AdPosition, type AdProps, AdProvider, AdSlot, AddOnSelector, type AddOnSelectorClassNames, type AddOnSelectorProps, type AddToCartOptions, AddressElement, AuthElement, AvailabilityBadge, type AvailabilityBadgeClassNames, type AvailabilityBadgeProps, BackLink, type BackLinkProps, BillingPlanSelector, type BillingPlanSelectorClassNames, type BillingPlanSelectorProps, BookingCard, type BookingCardClassNames, type BookingCardProps, BookingList, type BookingListClassNames, type BookingListProps, BookingPage, type BookingPageClassNames, type BookingPageProps, BookingSummary, type BookingSummaryClassNames, type BookingSummaryProps, BookingsPage, type BookingsPageClassNames, type BookingsPageProps, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, type BundleSelectorClassNames, type BundleSelectorProps, Button, type ButtonProps, CardImage, type CardLayoutProps, CardShell, CardVariant, type CartAddOnOptionSelection, CartDrawer, type CartDrawerProps, CartDrawerProvider, type CartLayoutProps, CartPage, type CartPageClassNames, type CartPageProps, CartSummary, type CartSummaryClassNames, type CartSummaryProps, CartTemplate, type CartVariantSelection, CatalogueCollectionLayout, type CatalogueLayoutProps, CataloguePage, type CataloguePageClassNames, type CataloguePageProps, CatalogueTemplate, CategoryFilter, type CategoryFilterClassNames, type CategoryFilterProps, CategoryGrid, type CategoryGridClassNames, type CategoryGridProps, ChatWidget, type ChatWidgetClassNames, type ChatWidgetProps, CheckIcon, CheckoutPage, type CheckoutPageClassNames, type CheckoutPageProps, CimplifyCheckout, type CimplifyCheckoutProps, type CimplifyClientContextValue, type CimplifyClientSession, type CimplifyContextValue, CimplifyProvider, type CimplifyProviderProps, CimplifySignInButton, type CimplifySignInButtonProps, CimplifyUserButton, type CimplifyUserButtonProps, type CollectionLayoutProps, CollectionPage, type CollectionPageClassNames, type CollectionPageProps, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, type CompositeSelectorClassNames, type CompositeSelectorProps, ContextCard, type ContextCardProps, type ContextRow, ContinuityCard, type ContinuityCardProps, CurrencySelector, type CurrencySelectorClassNames, type CurrencySelectorProps, CustomAttributesTable, type CustomerInput, CustomerInputFields, type CustomerInputFieldsClassNames, type CustomerInputFieldsProps, type CustomerInputType, DashboardIcon, DashboardIcon20, DatePicker, type DatePickerClassNames, type DatePickerProps, DateSlotPicker, type DateSlotPickerClassNames, type DateSlotPickerProps, DealBanner, type DealBannerClassNames, type DealBannerProps, DealsPage, type DealsPageClassNames, type DealsPageProps, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, type DeliveryEstimateClassNames, type DeliveryEstimateProps, type DeliveryLive, type DeliveryRider, DeliveryTracker, type DeliveryTrackerProps, DeliveryTruckIcon, type DigitalFulfillment, DigitalProductCard, DigitalProductLayout, DiscountInput, type DiscountInputClassNames, type DiscountInputProps, ElementsProvider, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, FeaturedCollectionLayout, type FilterTabItem, FilterTabs, type FilterTabsProps, FoodProductCard, FoodProductLayout, HappeningCard, type HappeningCardProps, type HappeningPaneData, IdentityIcon, IdentityOfframp, type IdentityOfframpProps, type IdentitySummary, InventoryBadge, ItemsCard, type ItemsCardProps, LeaseServiceCard, LineItemDetails, type LineItemSemanticKind, type LineScheduling, type LineSelection, type LineStateTone, LocationPicker, type LocationPickerClassNames, type LocationPickerProps, MediaGallery, type MediaGalleryProps, type MediaItem, MetadataStringList, MobileAccountShell, type MobileAccountShellProps, MobileBackButton, MobileMoreButton, MobileTabBar, type MobileTabBarProps, type NavItem, NextDeliveryCard, type NextDeliveryCardProps, OrderDetailHeader, type OrderDetailHeaderProps, OrderDetailMetaPipe, OrderDetailPage, type OrderDetailPageClassNames, type OrderDetailPageProps, OrderHistory, type OrderHistoryClassNames, OrderHistoryPage, type OrderHistoryPageClassNames, type OrderHistoryPageProps, type OrderHistoryProps, type OrderItemData, OrderList, type OrderListProps, OrderRow, type OrderRowData, type OrderRowProps, type OrderRowStatus, type OrderStatusTone, OrderSummary, type OrderSummaryClassNames, type OrderSummaryProps, OrderTimeline, type OrderTimelineProps, OrderTotals, type OrderTotalsProps, type OrderViewDelivery, type OrderViewPayment, type OrderViewPaymentRow, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, type PriceProps, PriceRange, type PriceRangeProps, ProductCard, type ProductCardClassNames, type ProductCardProps, ProductCustomizer, type ProductCustomizerClassNames, type ProductCustomizerProps, ProductGrid, type ProductGridClassNames, type ProductGridProps, ProductImageGallery, type ProductImageGalleryProps, type ProductLayoutProps, ProductModel3D, type ProductModel3DProps, ProductPage, type ProductPageClassNames, type ProductPageProps, ProductSheet, type ProductSheetClassNames, type ProductSheetProps, ProductTemplate, PropertiesTable, QuantitySelector, type QuantitySelectorClassNames, type QuantitySelectorProps, QuickAddButton, RecentlyViewed, type RecentlyViewedClassNames, type RecentlyViewedProps, RecommendationCarousel, type RecommendationCarouselClassNames, type RecommendationCarouselProps, RelatedProductsSection, RentalServiceCard, type Resource, ResourcePicker, type ResourcePickerClassNames, type ResourcePickerProps, RetailProductCard, RichText, type RichTextProps, SaleBadge, type SaleBadgeClassNames, type SaleBadgeProps, ScheduleServiceCard, SearchInput, type SearchInputClassNames, type SearchInputProps, type SearchLayoutProps, SearchPage, type SearchPageClassNames, type SearchPageProps, SearchTemplate, Section, SectionMore, type SectionMoreProps, type SectionProps, type ServiceCardLayoutProps, ServiceProductLayout, SessionMessageBanner, type SessionMessageBannerClassNames, type SessionMessageBannerProps, SignOutIcon, Skeleton, type SkeletonProps, SlotPicker, type SlotPickerClassNames, type SlotPickerProps, SoldOutOverlay, StaffPicker, type StaffPickerClassNames, type StaffPickerProps, StandardServiceCard, Status, type StatusProps, StoreNav, type StoreNavClassNames, type StoreNavProps, StoreVideo, type StoreVideoProps, SubscriptionCard, SubscriptionList, type SubscriptionListProps, SubscriptionRow, type SubscriptionRowData, type SubscriptionRowProps, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, type TimePickerClassNames, type TimePickerProps, type TimelineStep, type ToAccountOrderViewOptions, Toast, type ToastProps, type TotalsData, TwoColumnGrid, type UseActivityStateOptions, type UseActivityStateResult, type UseAttributeDefinitionsOptions, type UseAttributeDefinitionsResult, type UseAvailableSlotsOptions, type UseAvailableSlotsResult, type UseBillingPlansOptions, type UseBillingPlansResult, type UseBookingsOptions, type UseBookingsResult, type UseBootstrapOptions, type UseBootstrapResult, type UseBundlesOptions, type UseBundlesResult, type UseCartItem, type UseCartOptions, type UseCartResult, type UseCategoriesOptions, type UseCategoriesResult, type UseChatOptions, type UseChatResult, type UseCimplifySessionOptions, type UseCimplifySessionResult, type UseCollectionOptions, type UseCollectionResult, type UseCollectionsOptions, type UseCollectionsResult, type UseDealsOptions, type UseDealsResult, type UseDeliveryFeeOptions, type UseDeliveryFeeResult, type UseFxRateOptions, type UseFxRateResult, type UseLocationsOptions, type UseLocationsResult, type UseOrderOptions, type UseOrderResult, type UseOrdersOptions, type UseOrdersResult, type UseProductAvailabilityOptions, type UseProductAvailabilityResult, type UseProductDealsOptions, type UseProductDealsResult, type UseProductOptions, type UseProductPriceInput, type UseProductPriceResult, type UseProductResult, type UseProductSchedulesOptions, type UseProductSchedulesResult, type UseProductsOnSaleOptions, type UseProductsOnSaleResult, type UseProductsOptions, type UseProductsResult, type UsePropertyFacetsOptions, type UsePropertyFacetsResult, type UseQuoteInput, type UseQuoteOptions, type UseQuoteResult, type UseRecommendationsOptions, type UseRecommendationsResult, type UseSearchOptions, type UseSearchResult, type UseServiceAvailabilityOptions, type UseServiceAvailabilityResult, type UseServicesOptions, type UseServicesResult, type UseTaxonomiesOptions, type UseTaxonomiesResult, type UseTaxonomyOptions, type UseTaxonomyPathOptions, type UseTaxonomyPathResult, type UseTaxonomyResult, type UseValidateDiscountOptions, type UseValidateDiscountResult, type UseVariantSelectorOptions, type UseVariantSelectorResult, type UserButtonLink, VariantSelector, type VariantSelectorClassNames, type VariantSelectorProps, VolumePricing, type VolumePricingClassNames, type VolumePricingProps, WelcomeCard, type WelcomeCardProps, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
package/dist/react.js CHANGED
@@ -7311,6 +7311,144 @@ function formatDuration2(value, unit) {
7311
7311
  const label = value === 1 ? labels.singular : labels.plural;
7312
7312
  return `${value} ${label}`;
7313
7313
  }
7314
+ var ANY_VALUE = "__any__";
7315
+ function StaffPicker({
7316
+ staff,
7317
+ selectedStaffId,
7318
+ onStaffSelect,
7319
+ showAnyOption = true,
7320
+ anyLabel = "Any available",
7321
+ className,
7322
+ classNames
7323
+ }) {
7324
+ const groupValue = selectedStaffId === null ? ANY_VALUE : selectedStaffId ?? "";
7325
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7326
+ radioGroup.RadioGroup,
7327
+ {
7328
+ "data-cimplify-staff-picker": true,
7329
+ className: cn(className, classNames?.root),
7330
+ value: groupValue,
7331
+ onValueChange: (value) => {
7332
+ onStaffSelect?.(value === ANY_VALUE ? null : value);
7333
+ },
7334
+ children: [
7335
+ showAnyOption && /* @__PURE__ */ jsxRuntime.jsx(
7336
+ radio.Radio.Root,
7337
+ {
7338
+ value: ANY_VALUE,
7339
+ "data-cimplify-staff-option": true,
7340
+ "data-selected": selectedStaffId === null || void 0,
7341
+ "data-any": true,
7342
+ className: classNames?.option,
7343
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: anyLabel })
7344
+ }
7345
+ ),
7346
+ staff.map((member) => /* @__PURE__ */ jsxRuntime.jsxs(
7347
+ radio.Radio.Root,
7348
+ {
7349
+ value: member.id,
7350
+ "data-cimplify-staff-option": true,
7351
+ "data-selected": selectedStaffId === member.id || void 0,
7352
+ className: classNames?.option,
7353
+ children: [
7354
+ member.avatar_url && /* @__PURE__ */ jsxRuntime.jsx(
7355
+ "img",
7356
+ {
7357
+ src: member.avatar_url,
7358
+ alt: member.name,
7359
+ "data-cimplify-staff-avatar": true,
7360
+ className: classNames?.avatar
7361
+ }
7362
+ ),
7363
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: member.name }),
7364
+ member.bio && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-staff-bio": true, className: classNames?.bio, children: member.bio })
7365
+ ]
7366
+ },
7367
+ member.id
7368
+ ))
7369
+ ]
7370
+ }
7371
+ );
7372
+ }
7373
+ function formatDate(value) {
7374
+ const date = new Date(value);
7375
+ if (Number.isNaN(date.getTime())) return value;
7376
+ return date.toLocaleDateString(void 0, {
7377
+ weekday: "short",
7378
+ month: "short",
7379
+ day: "numeric"
7380
+ });
7381
+ }
7382
+ function formatTime(value) {
7383
+ const date = new Date(value);
7384
+ if (Number.isNaN(date.getTime())) return value;
7385
+ return date.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
7386
+ }
7387
+ function BookingSummary({
7388
+ slot,
7389
+ total,
7390
+ staffName,
7391
+ durationMinutes,
7392
+ depositType,
7393
+ depositAmount,
7394
+ currency,
7395
+ className,
7396
+ classNames
7397
+ }) {
7398
+ const depositValue = depositAmount != null ? chunk7Y2O3E4D_js.parsePrice(depositAmount) : 0;
7399
+ const depositDue = depositType === "percentage" ? total * depositValue / 100 : depositType === "fixed" ? depositValue : 0;
7400
+ const hasDeposit = depositDue > 0;
7401
+ const balance = Math.max(0, total - depositDue);
7402
+ const rowClass = cn("flex items-center justify-between", classNames?.row);
7403
+ const labelClass = cn("text-muted-foreground", classNames?.label);
7404
+ const valueClass = cn("font-medium", classNames?.value);
7405
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7406
+ "div",
7407
+ {
7408
+ "data-cimplify-booking-summary": true,
7409
+ className: cn("rounded-lg border border-border p-4 space-y-3", className, classNames?.root),
7410
+ children: [
7411
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center justify-between", classNames?.header), children: [
7412
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: "Your booking" }),
7413
+ durationMinutes != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
7414
+ durationMinutes,
7415
+ " min"
7416
+ ] })
7417
+ ] }),
7418
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5 text-sm", children: [
7419
+ staffName && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: rowClass, children: [
7420
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: labelClass, children: "With" }),
7421
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: valueClass, children: staffName })
7422
+ ] }),
7423
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: rowClass, children: [
7424
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: labelClass, children: "Date" }),
7425
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: valueClass, children: formatDate(slot.start_time) })
7426
+ ] }),
7427
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: rowClass, children: [
7428
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: labelClass, children: "Time" }),
7429
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: valueClass, children: formatTime(slot.start_time) })
7430
+ ] })
7431
+ ] }),
7432
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("border-t border-border pt-3 space-y-1.5 text-sm", classNames?.totals), children: [
7433
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: rowClass, children: [
7434
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: labelClass, children: "Subtotal" }),
7435
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: total, currency }) })
7436
+ ] }),
7437
+ hasDeposit && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7438
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(rowClass, classNames?.deposit), children: [
7439
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: labelClass, children: "Due now (deposit)" }),
7440
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: depositDue, currency }) })
7441
+ ] }),
7442
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(rowClass, "text-xs text-muted-foreground", classNames?.balance), children: [
7443
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Balance at appointment" }),
7444
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: balance, currency })
7445
+ ] })
7446
+ ] })
7447
+ ] })
7448
+ ]
7449
+ }
7450
+ );
7451
+ }
7314
7452
  var FREQUENCY_LABELS = {
7315
7453
  weekly: "Weekly",
7316
7454
  biweekly: "Biweekly",
@@ -8675,7 +8813,7 @@ function groupSlots(slots) {
8675
8813
  }
8676
8814
  return ["morning", "afternoon", "evening"].filter((tod) => groups[tod]?.length).map((tod) => ({ label: TIME_OF_DAY_LABELS[tod], slots: groups[tod] }));
8677
8815
  }
8678
- function formatTime(timeStr) {
8816
+ function formatTime2(timeStr) {
8679
8817
  try {
8680
8818
  const date = new Date(timeStr);
8681
8819
  if (!isNaN(date.getTime())) {
@@ -8850,7 +8988,7 @@ function SlotPicker({
8850
8988
  classNames?.slot
8851
8989
  ),
8852
8990
  children: [
8853
- /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-slot-time": true, className: classNames?.slotTime, children: isMultiDay ? formatStaySummary(slot, durationUnit, durationValue) : formatTime(slot.start_time) }),
8991
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-slot-time": true, className: classNames?.slotTime, children: isMultiDay ? formatStaySummary(slot, durationUnit, durationValue) : formatTime2(slot.start_time) }),
8854
8992
  showPrice && slot.price && /* @__PURE__ */ jsxRuntime.jsx(
8855
8993
  "span",
8856
8994
  {
@@ -8884,7 +9022,7 @@ function SlotPicker({
8884
9022
  }
8885
9023
  );
8886
9024
  }
8887
- function formatDate(dateStr) {
9025
+ function formatDate2(dateStr) {
8888
9026
  const date = /* @__PURE__ */ new Date(dateStr + "T00:00:00");
8889
9027
  return date.toLocaleDateString(void 0, { weekday: "short", month: "short", day: "numeric" });
8890
9028
  }
@@ -9029,7 +9167,7 @@ function DateSlotPicker({
9029
9167
  "flex flex-col items-center justify-center rounded-md border border-border bg-background px-1 py-2 text-center text-xs font-medium text-foreground transition-colors hover:border-foreground/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring data-[selected]:border-foreground data-[selected]:bg-foreground data-[selected]:text-background data-[fully-booked]:cursor-not-allowed data-[fully-booked]:opacity-40",
9030
9168
  classNames?.dateButton
9031
9169
  ),
9032
- children: formatDate(date)
9170
+ children: formatDate2(date)
9033
9171
  },
9034
9172
  date
9035
9173
  );
@@ -9089,6 +9227,7 @@ function ProductCustomizer({
9089
9227
  const [customerInputValues, setCustomerInputValues] = React14.useState({});
9090
9228
  const [specialInstructions, setSpecialInstructions] = React14.useState("");
9091
9229
  const [selectedSlot, setSelectedSlot] = React14.useState(null);
9230
+ const [selectedStaffId, setSelectedStaffId] = React14.useState(null);
9092
9231
  const cart = useCart();
9093
9232
  const currency = chunk7Y2O3E4D_js.getProductCurrency(product);
9094
9233
  const productType = product.type || "product";
@@ -9116,7 +9255,16 @@ function ProductCustomizer({
9116
9255
  setCustomerInputValues({});
9117
9256
  setSpecialInstructions("");
9118
9257
  setSelectedSlot(null);
9258
+ setSelectedStaffId(null);
9119
9259
  }, [product.id, product.min_order_quantity]);
9260
+ const slotStaff = React14.useMemo(
9261
+ () => (selectedSlot?.available_staff ?? []).map((member) => ({
9262
+ id: member.staff_id,
9263
+ name: member.name
9264
+ })),
9265
+ [selectedSlot]
9266
+ );
9267
+ const selectedStaffName = selectedStaffId ? slotStaff.find((member) => member.id === selectedStaffId)?.name ?? null : null;
9120
9268
  const selectedAddOnOptions = React14.useMemo(() => {
9121
9269
  if (!product.add_ons) return [];
9122
9270
  const options = [];
@@ -9228,7 +9376,7 @@ function ProductCustomizer({
9228
9376
  ...isService && selectedSlot ? {
9229
9377
  scheduledStart: selectedSlot.start_time,
9230
9378
  scheduledEnd: selectedSlot.end_time,
9231
- staffId: selectedSlot.available_staff?.[0]?.staff_id,
9379
+ staffId: selectedStaffId ?? selectedSlot.available_staff?.[0]?.staff_id,
9232
9380
  resourceId: selectedSlot.available_resources?.[0]?.resource_id
9233
9381
  } : {},
9234
9382
  customerInputs: Object.keys(customerInputValues).length > 0 ? Object.entries(customerInputValues).filter(([, v]) => v !== void 0 && v !== "").map(([fieldId, value]) => ({ field_id: fieldId, value })) : void 0,
@@ -9250,7 +9398,7 @@ function ProductCustomizer({
9250
9398
  } finally {
9251
9399
  setIsSubmitting(false);
9252
9400
  }
9253
- }, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, isSubmitting, onAddToCart, cart]);
9401
+ }, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, selectedStaffId, isSubmitting, onAddToCart, cart]);
9254
9402
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-customizer": true, className: cn("space-y-6", className, classNames?.root), children: [
9255
9403
  isComposite && product.groups && product.composite_id && /* @__PURE__ */ jsxRuntime.jsx(
9256
9404
  CompositeSelector,
@@ -9282,11 +9430,30 @@ function ProductCustomizer({
9282
9430
  {
9283
9431
  serviceId: product.id,
9284
9432
  selectedSlot,
9285
- onSlotSelect: (slot) => setSelectedSlot(slot),
9433
+ onSlotSelect: (slot) => {
9434
+ setSelectedSlot(slot);
9435
+ setSelectedStaffId(null);
9436
+ },
9286
9437
  participantCount: quantity,
9287
9438
  currency
9288
9439
  }
9289
9440
  ),
9441
+ isService && slotStaff.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-customizer-staff": true, children: [
9442
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", children: "Choose your specialist" }),
9443
+ /* @__PURE__ */ jsxRuntime.jsx(
9444
+ StaffPicker,
9445
+ {
9446
+ staff: slotStaff,
9447
+ selectedStaffId,
9448
+ onStaffSelect: setSelectedStaffId,
9449
+ className: "flex flex-wrap gap-2",
9450
+ classNames: {
9451
+ option: "inline-flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium transition-colors hover:border-foreground/40 cursor-pointer data-[selected]:border-foreground data-[selected]:bg-foreground data-[selected]:text-background",
9452
+ avatar: "w-6 h-6 rounded-full object-cover"
9453
+ }
9454
+ }
9455
+ )
9456
+ ] }),
9290
9457
  hasVariants && /* @__PURE__ */ jsxRuntime.jsx(
9291
9458
  VariantSelector,
9292
9459
  {
@@ -9371,6 +9538,18 @@ function ProductCustomizer({
9371
9538
  )
9372
9539
  }
9373
9540
  ) }),
9541
+ isService && selectedSlot && /* @__PURE__ */ jsxRuntime.jsx(
9542
+ BookingSummary,
9543
+ {
9544
+ slot: selectedSlot,
9545
+ total: displayTotalPrice,
9546
+ staffName: selectedStaffName,
9547
+ durationMinutes: product.duration_minutes,
9548
+ depositType: product.deposit_type,
9549
+ depositAmount: product.deposit_amount,
9550
+ currency
9551
+ }
9552
+ ),
9374
9553
  /* @__PURE__ */ jsxRuntime.jsxs(
9375
9554
  "div",
9376
9555
  {
@@ -12486,65 +12665,6 @@ function StoreNav({
12486
12665
  ] })
12487
12666
  ] });
12488
12667
  }
12489
- var ANY_VALUE = "__any__";
12490
- function StaffPicker({
12491
- staff,
12492
- selectedStaffId,
12493
- onStaffSelect,
12494
- showAnyOption = true,
12495
- anyLabel = "Any available",
12496
- className,
12497
- classNames
12498
- }) {
12499
- const groupValue = selectedStaffId === null ? ANY_VALUE : selectedStaffId ?? "";
12500
- return /* @__PURE__ */ jsxRuntime.jsxs(
12501
- radioGroup.RadioGroup,
12502
- {
12503
- "data-cimplify-staff-picker": true,
12504
- className: cn(className, classNames?.root),
12505
- value: groupValue,
12506
- onValueChange: (value) => {
12507
- onStaffSelect?.(value === ANY_VALUE ? null : value);
12508
- },
12509
- children: [
12510
- showAnyOption && /* @__PURE__ */ jsxRuntime.jsx(
12511
- radio.Radio.Root,
12512
- {
12513
- value: ANY_VALUE,
12514
- "data-cimplify-staff-option": true,
12515
- "data-selected": selectedStaffId === null || void 0,
12516
- "data-any": true,
12517
- className: classNames?.option,
12518
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: anyLabel })
12519
- }
12520
- ),
12521
- staff.map((member) => /* @__PURE__ */ jsxRuntime.jsxs(
12522
- radio.Radio.Root,
12523
- {
12524
- value: member.id,
12525
- "data-cimplify-staff-option": true,
12526
- "data-selected": selectedStaffId === member.id || void 0,
12527
- className: classNames?.option,
12528
- children: [
12529
- member.avatar_url && /* @__PURE__ */ jsxRuntime.jsx(
12530
- "img",
12531
- {
12532
- src: member.avatar_url,
12533
- alt: member.name,
12534
- "data-cimplify-staff-avatar": true,
12535
- className: classNames?.avatar
12536
- }
12537
- ),
12538
- /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: member.name }),
12539
- member.bio && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-staff-bio": true, className: classNames?.bio, children: member.bio })
12540
- ]
12541
- },
12542
- member.id
12543
- ))
12544
- ]
12545
- }
12546
- );
12547
- }
12548
12668
  var STATUS_LABELS3 = {
12549
12669
  pending: "Pending",
12550
12670
  confirmed: "Confirmed",
@@ -16668,6 +16788,7 @@ exports.BillingPlanSelector = BillingPlanSelector;
16668
16788
  exports.BookingCard = BookingCard;
16669
16789
  exports.BookingList = BookingList;
16670
16790
  exports.BookingPage = BookingPage;
16791
+ exports.BookingSummary = BookingSummary;
16671
16792
  exports.BookingsPage = BookingsPage;
16672
16793
  exports.BoxIcon24 = BoxIcon24;
16673
16794
  exports.BundleProductCard = BundleProductCard;
package/dist/react.mjs CHANGED
@@ -7306,6 +7306,144 @@ function formatDuration2(value, unit) {
7306
7306
  const label = value === 1 ? labels.singular : labels.plural;
7307
7307
  return `${value} ${label}`;
7308
7308
  }
7309
+ var ANY_VALUE = "__any__";
7310
+ function StaffPicker({
7311
+ staff,
7312
+ selectedStaffId,
7313
+ onStaffSelect,
7314
+ showAnyOption = true,
7315
+ anyLabel = "Any available",
7316
+ className,
7317
+ classNames
7318
+ }) {
7319
+ const groupValue = selectedStaffId === null ? ANY_VALUE : selectedStaffId ?? "";
7320
+ return /* @__PURE__ */ jsxs(
7321
+ RadioGroup,
7322
+ {
7323
+ "data-cimplify-staff-picker": true,
7324
+ className: cn(className, classNames?.root),
7325
+ value: groupValue,
7326
+ onValueChange: (value) => {
7327
+ onStaffSelect?.(value === ANY_VALUE ? null : value);
7328
+ },
7329
+ children: [
7330
+ showAnyOption && /* @__PURE__ */ jsx(
7331
+ Radio.Root,
7332
+ {
7333
+ value: ANY_VALUE,
7334
+ "data-cimplify-staff-option": true,
7335
+ "data-selected": selectedStaffId === null || void 0,
7336
+ "data-any": true,
7337
+ className: classNames?.option,
7338
+ children: /* @__PURE__ */ jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: anyLabel })
7339
+ }
7340
+ ),
7341
+ staff.map((member) => /* @__PURE__ */ jsxs(
7342
+ Radio.Root,
7343
+ {
7344
+ value: member.id,
7345
+ "data-cimplify-staff-option": true,
7346
+ "data-selected": selectedStaffId === member.id || void 0,
7347
+ className: classNames?.option,
7348
+ children: [
7349
+ member.avatar_url && /* @__PURE__ */ jsx(
7350
+ "img",
7351
+ {
7352
+ src: member.avatar_url,
7353
+ alt: member.name,
7354
+ "data-cimplify-staff-avatar": true,
7355
+ className: classNames?.avatar
7356
+ }
7357
+ ),
7358
+ /* @__PURE__ */ jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: member.name }),
7359
+ member.bio && /* @__PURE__ */ jsx("span", { "data-cimplify-staff-bio": true, className: classNames?.bio, children: member.bio })
7360
+ ]
7361
+ },
7362
+ member.id
7363
+ ))
7364
+ ]
7365
+ }
7366
+ );
7367
+ }
7368
+ function formatDate(value) {
7369
+ const date = new Date(value);
7370
+ if (Number.isNaN(date.getTime())) return value;
7371
+ return date.toLocaleDateString(void 0, {
7372
+ weekday: "short",
7373
+ month: "short",
7374
+ day: "numeric"
7375
+ });
7376
+ }
7377
+ function formatTime(value) {
7378
+ const date = new Date(value);
7379
+ if (Number.isNaN(date.getTime())) return value;
7380
+ return date.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
7381
+ }
7382
+ function BookingSummary({
7383
+ slot,
7384
+ total,
7385
+ staffName,
7386
+ durationMinutes,
7387
+ depositType,
7388
+ depositAmount,
7389
+ currency,
7390
+ className,
7391
+ classNames
7392
+ }) {
7393
+ const depositValue = depositAmount != null ? parsePrice(depositAmount) : 0;
7394
+ const depositDue = depositType === "percentage" ? total * depositValue / 100 : depositType === "fixed" ? depositValue : 0;
7395
+ const hasDeposit = depositDue > 0;
7396
+ const balance = Math.max(0, total - depositDue);
7397
+ const rowClass = cn("flex items-center justify-between", classNames?.row);
7398
+ const labelClass = cn("text-muted-foreground", classNames?.label);
7399
+ const valueClass = cn("font-medium", classNames?.value);
7400
+ return /* @__PURE__ */ jsxs(
7401
+ "div",
7402
+ {
7403
+ "data-cimplify-booking-summary": true,
7404
+ className: cn("rounded-lg border border-border p-4 space-y-3", className, classNames?.root),
7405
+ children: [
7406
+ /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between", classNames?.header), children: [
7407
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: "Your booking" }),
7408
+ durationMinutes != null && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
7409
+ durationMinutes,
7410
+ " min"
7411
+ ] })
7412
+ ] }),
7413
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5 text-sm", children: [
7414
+ staffName && /* @__PURE__ */ jsxs("div", { className: rowClass, children: [
7415
+ /* @__PURE__ */ jsx("span", { className: labelClass, children: "With" }),
7416
+ /* @__PURE__ */ jsx("span", { className: valueClass, children: staffName })
7417
+ ] }),
7418
+ /* @__PURE__ */ jsxs("div", { className: rowClass, children: [
7419
+ /* @__PURE__ */ jsx("span", { className: labelClass, children: "Date" }),
7420
+ /* @__PURE__ */ jsx("span", { className: valueClass, children: formatDate(slot.start_time) })
7421
+ ] }),
7422
+ /* @__PURE__ */ jsxs("div", { className: rowClass, children: [
7423
+ /* @__PURE__ */ jsx("span", { className: labelClass, children: "Time" }),
7424
+ /* @__PURE__ */ jsx("span", { className: valueClass, children: formatTime(slot.start_time) })
7425
+ ] })
7426
+ ] }),
7427
+ /* @__PURE__ */ jsxs("div", { className: cn("border-t border-border pt-3 space-y-1.5 text-sm", classNames?.totals), children: [
7428
+ /* @__PURE__ */ jsxs("div", { className: rowClass, children: [
7429
+ /* @__PURE__ */ jsx("span", { className: labelClass, children: "Subtotal" }),
7430
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: /* @__PURE__ */ jsx(Price, { amount: total, currency }) })
7431
+ ] }),
7432
+ hasDeposit && /* @__PURE__ */ jsxs(Fragment, { children: [
7433
+ /* @__PURE__ */ jsxs("div", { className: cn(rowClass, classNames?.deposit), children: [
7434
+ /* @__PURE__ */ jsx("span", { className: labelClass, children: "Due now (deposit)" }),
7435
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: /* @__PURE__ */ jsx(Price, { amount: depositDue, currency }) })
7436
+ ] }),
7437
+ /* @__PURE__ */ jsxs("div", { className: cn(rowClass, "text-xs text-muted-foreground", classNames?.balance), children: [
7438
+ /* @__PURE__ */ jsx("span", { children: "Balance at appointment" }),
7439
+ /* @__PURE__ */ jsx(Price, { amount: balance, currency })
7440
+ ] })
7441
+ ] })
7442
+ ] })
7443
+ ]
7444
+ }
7445
+ );
7446
+ }
7309
7447
  var FREQUENCY_LABELS = {
7310
7448
  weekly: "Weekly",
7311
7449
  biweekly: "Biweekly",
@@ -8670,7 +8808,7 @@ function groupSlots(slots) {
8670
8808
  }
8671
8809
  return ["morning", "afternoon", "evening"].filter((tod) => groups[tod]?.length).map((tod) => ({ label: TIME_OF_DAY_LABELS[tod], slots: groups[tod] }));
8672
8810
  }
8673
- function formatTime(timeStr) {
8811
+ function formatTime2(timeStr) {
8674
8812
  try {
8675
8813
  const date = new Date(timeStr);
8676
8814
  if (!isNaN(date.getTime())) {
@@ -8845,7 +8983,7 @@ function SlotPicker({
8845
8983
  classNames?.slot
8846
8984
  ),
8847
8985
  children: [
8848
- /* @__PURE__ */ jsx("span", { "data-cimplify-slot-time": true, className: classNames?.slotTime, children: isMultiDay ? formatStaySummary(slot, durationUnit, durationValue) : formatTime(slot.start_time) }),
8986
+ /* @__PURE__ */ jsx("span", { "data-cimplify-slot-time": true, className: classNames?.slotTime, children: isMultiDay ? formatStaySummary(slot, durationUnit, durationValue) : formatTime2(slot.start_time) }),
8849
8987
  showPrice && slot.price && /* @__PURE__ */ jsx(
8850
8988
  "span",
8851
8989
  {
@@ -8879,7 +9017,7 @@ function SlotPicker({
8879
9017
  }
8880
9018
  );
8881
9019
  }
8882
- function formatDate(dateStr) {
9020
+ function formatDate2(dateStr) {
8883
9021
  const date = /* @__PURE__ */ new Date(dateStr + "T00:00:00");
8884
9022
  return date.toLocaleDateString(void 0, { weekday: "short", month: "short", day: "numeric" });
8885
9023
  }
@@ -9024,7 +9162,7 @@ function DateSlotPicker({
9024
9162
  "flex flex-col items-center justify-center rounded-md border border-border bg-background px-1 py-2 text-center text-xs font-medium text-foreground transition-colors hover:border-foreground/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring data-[selected]:border-foreground data-[selected]:bg-foreground data-[selected]:text-background data-[fully-booked]:cursor-not-allowed data-[fully-booked]:opacity-40",
9025
9163
  classNames?.dateButton
9026
9164
  ),
9027
- children: formatDate(date)
9165
+ children: formatDate2(date)
9028
9166
  },
9029
9167
  date
9030
9168
  );
@@ -9084,6 +9222,7 @@ function ProductCustomizer({
9084
9222
  const [customerInputValues, setCustomerInputValues] = useState({});
9085
9223
  const [specialInstructions, setSpecialInstructions] = useState("");
9086
9224
  const [selectedSlot, setSelectedSlot] = useState(null);
9225
+ const [selectedStaffId, setSelectedStaffId] = useState(null);
9087
9226
  const cart = useCart();
9088
9227
  const currency = getProductCurrency(product);
9089
9228
  const productType = product.type || "product";
@@ -9111,7 +9250,16 @@ function ProductCustomizer({
9111
9250
  setCustomerInputValues({});
9112
9251
  setSpecialInstructions("");
9113
9252
  setSelectedSlot(null);
9253
+ setSelectedStaffId(null);
9114
9254
  }, [product.id, product.min_order_quantity]);
9255
+ const slotStaff = useMemo(
9256
+ () => (selectedSlot?.available_staff ?? []).map((member) => ({
9257
+ id: member.staff_id,
9258
+ name: member.name
9259
+ })),
9260
+ [selectedSlot]
9261
+ );
9262
+ const selectedStaffName = selectedStaffId ? slotStaff.find((member) => member.id === selectedStaffId)?.name ?? null : null;
9115
9263
  const selectedAddOnOptions = useMemo(() => {
9116
9264
  if (!product.add_ons) return [];
9117
9265
  const options = [];
@@ -9223,7 +9371,7 @@ function ProductCustomizer({
9223
9371
  ...isService && selectedSlot ? {
9224
9372
  scheduledStart: selectedSlot.start_time,
9225
9373
  scheduledEnd: selectedSlot.end_time,
9226
- staffId: selectedSlot.available_staff?.[0]?.staff_id,
9374
+ staffId: selectedStaffId ?? selectedSlot.available_staff?.[0]?.staff_id,
9227
9375
  resourceId: selectedSlot.available_resources?.[0]?.resource_id
9228
9376
  } : {},
9229
9377
  customerInputs: Object.keys(customerInputValues).length > 0 ? Object.entries(customerInputValues).filter(([, v]) => v !== void 0 && v !== "").map(([fieldId, value]) => ({ field_id: fieldId, value })) : void 0,
@@ -9245,7 +9393,7 @@ function ProductCustomizer({
9245
9393
  } finally {
9246
9394
  setIsSubmitting(false);
9247
9395
  }
9248
- }, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, isSubmitting, onAddToCart, cart]);
9396
+ }, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, selectedStaffId, isSubmitting, onAddToCart, cart]);
9249
9397
  return /* @__PURE__ */ jsxs("div", { "data-cimplify-customizer": true, className: cn("space-y-6", className, classNames?.root), children: [
9250
9398
  isComposite && product.groups && product.composite_id && /* @__PURE__ */ jsx(
9251
9399
  CompositeSelector,
@@ -9277,11 +9425,30 @@ function ProductCustomizer({
9277
9425
  {
9278
9426
  serviceId: product.id,
9279
9427
  selectedSlot,
9280
- onSlotSelect: (slot) => setSelectedSlot(slot),
9428
+ onSlotSelect: (slot) => {
9429
+ setSelectedSlot(slot);
9430
+ setSelectedStaffId(null);
9431
+ },
9281
9432
  participantCount: quantity,
9282
9433
  currency
9283
9434
  }
9284
9435
  ),
9436
+ isService && slotStaff.length > 0 && /* @__PURE__ */ jsxs("div", { "data-cimplify-customizer-staff": true, children: [
9437
+ /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", children: "Choose your specialist" }),
9438
+ /* @__PURE__ */ jsx(
9439
+ StaffPicker,
9440
+ {
9441
+ staff: slotStaff,
9442
+ selectedStaffId,
9443
+ onStaffSelect: setSelectedStaffId,
9444
+ className: "flex flex-wrap gap-2",
9445
+ classNames: {
9446
+ option: "inline-flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium transition-colors hover:border-foreground/40 cursor-pointer data-[selected]:border-foreground data-[selected]:bg-foreground data-[selected]:text-background",
9447
+ avatar: "w-6 h-6 rounded-full object-cover"
9448
+ }
9449
+ }
9450
+ )
9451
+ ] }),
9285
9452
  hasVariants && /* @__PURE__ */ jsx(
9286
9453
  VariantSelector,
9287
9454
  {
@@ -9366,6 +9533,18 @@ function ProductCustomizer({
9366
9533
  )
9367
9534
  }
9368
9535
  ) }),
9536
+ isService && selectedSlot && /* @__PURE__ */ jsx(
9537
+ BookingSummary,
9538
+ {
9539
+ slot: selectedSlot,
9540
+ total: displayTotalPrice,
9541
+ staffName: selectedStaffName,
9542
+ durationMinutes: product.duration_minutes,
9543
+ depositType: product.deposit_type,
9544
+ depositAmount: product.deposit_amount,
9545
+ currency
9546
+ }
9547
+ ),
9369
9548
  /* @__PURE__ */ jsxs(
9370
9549
  "div",
9371
9550
  {
@@ -12481,65 +12660,6 @@ function StoreNav({
12481
12660
  ] })
12482
12661
  ] });
12483
12662
  }
12484
- var ANY_VALUE = "__any__";
12485
- function StaffPicker({
12486
- staff,
12487
- selectedStaffId,
12488
- onStaffSelect,
12489
- showAnyOption = true,
12490
- anyLabel = "Any available",
12491
- className,
12492
- classNames
12493
- }) {
12494
- const groupValue = selectedStaffId === null ? ANY_VALUE : selectedStaffId ?? "";
12495
- return /* @__PURE__ */ jsxs(
12496
- RadioGroup,
12497
- {
12498
- "data-cimplify-staff-picker": true,
12499
- className: cn(className, classNames?.root),
12500
- value: groupValue,
12501
- onValueChange: (value) => {
12502
- onStaffSelect?.(value === ANY_VALUE ? null : value);
12503
- },
12504
- children: [
12505
- showAnyOption && /* @__PURE__ */ jsx(
12506
- Radio.Root,
12507
- {
12508
- value: ANY_VALUE,
12509
- "data-cimplify-staff-option": true,
12510
- "data-selected": selectedStaffId === null || void 0,
12511
- "data-any": true,
12512
- className: classNames?.option,
12513
- children: /* @__PURE__ */ jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: anyLabel })
12514
- }
12515
- ),
12516
- staff.map((member) => /* @__PURE__ */ jsxs(
12517
- Radio.Root,
12518
- {
12519
- value: member.id,
12520
- "data-cimplify-staff-option": true,
12521
- "data-selected": selectedStaffId === member.id || void 0,
12522
- className: classNames?.option,
12523
- children: [
12524
- member.avatar_url && /* @__PURE__ */ jsx(
12525
- "img",
12526
- {
12527
- src: member.avatar_url,
12528
- alt: member.name,
12529
- "data-cimplify-staff-avatar": true,
12530
- className: classNames?.avatar
12531
- }
12532
- ),
12533
- /* @__PURE__ */ jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: member.name }),
12534
- member.bio && /* @__PURE__ */ jsx("span", { "data-cimplify-staff-bio": true, className: classNames?.bio, children: member.bio })
12535
- ]
12536
- },
12537
- member.id
12538
- ))
12539
- ]
12540
- }
12541
- );
12542
- }
12543
12663
  var STATUS_LABELS3 = {
12544
12664
  pending: "Pending",
12545
12665
  confirmed: "Confirmed",
@@ -16632,4 +16752,4 @@ function SparkleIcon({ className }) {
16632
16752
  );
16633
16753
  }
16634
16754
 
16635
- export { AccommodationCard, AccountContent, AccountDashboardPage, AccountHero, AccountIdentityStrip, AccountLineItem, AccountLineItems, AccountNav, AccountOrderDetailPage, AccountOrderView, AccountOrdersPage, AccountShell, AccountSidebar, AccountSignedOutPrompt, AccountSubscriptionDetailPage, AccountSubscriptionsPage, Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BackLink, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingsPage, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, Button, CardImage, CardShell, CardVariant, CartDrawer, CartDrawerProvider, CartPage, CartSummary, CartTemplate, CatalogueCollectionLayout, CataloguePage, CatalogueTemplate, CategoryFilter, CategoryGrid, ChatWidget, CheckIcon, CheckoutPage, CimplifyCheckout, CimplifyProvider, CimplifySignInButton, CimplifyUserButton, CollectionPage, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, ContextCard, ContinuityCard, CurrencySelector, CustomAttributesTable, CustomerInputFields, DashboardIcon, DashboardIcon20, DatePicker, DateSlotPicker, DealBanner, DealsPage, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, DeliveryTracker, DeliveryTruckIcon, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, EmptyState, ErrorState, FeaturedCollectionLayout, FilterTabs, FoodProductCard, FoodProductLayout, HappeningCard, IdentityIcon, IdentityOfframp, InventoryBadge, ItemsCard, LeaseServiceCard, LineItemDetails, LocationPicker, MediaGallery, MetadataStringList, MobileAccountShell, MobileBackButton, MobileMoreButton, MobileTabBar, NextDeliveryCard, OrderDetailHeader, OrderDetailMetaPipe, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderList, OrderRow, OrderSummary, OrderTimeline, OrderTotals, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductModel3D, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, RichText, SaleBadge, ScheduleServiceCard, SearchInput, SearchPage, SearchTemplate, Section, SectionMore, ServiceProductLayout, SessionMessageBanner, SignOutIcon, Skeleton, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, Status, StoreNav, StoreVideo, SubscriptionCard, SubscriptionList, SubscriptionRow, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, Toast, TwoColumnGrid, VariantSelector, VolumePricing, WelcomeCard, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
16755
+ export { AccommodationCard, AccountContent, AccountDashboardPage, AccountHero, AccountIdentityStrip, AccountLineItem, AccountLineItems, AccountNav, AccountOrderDetailPage, AccountOrderView, AccountOrdersPage, AccountShell, AccountSidebar, AccountSignedOutPrompt, AccountSubscriptionDetailPage, AccountSubscriptionsPage, Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BackLink, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingSummary, BookingsPage, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, Button, CardImage, CardShell, CardVariant, CartDrawer, CartDrawerProvider, CartPage, CartSummary, CartTemplate, CatalogueCollectionLayout, CataloguePage, CatalogueTemplate, CategoryFilter, CategoryGrid, ChatWidget, CheckIcon, CheckoutPage, CimplifyCheckout, CimplifyProvider, CimplifySignInButton, CimplifyUserButton, CollectionPage, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, ContextCard, ContinuityCard, CurrencySelector, CustomAttributesTable, CustomerInputFields, DashboardIcon, DashboardIcon20, DatePicker, DateSlotPicker, DealBanner, DealsPage, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, DeliveryTracker, DeliveryTruckIcon, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, EmptyState, ErrorState, FeaturedCollectionLayout, FilterTabs, FoodProductCard, FoodProductLayout, HappeningCard, IdentityIcon, IdentityOfframp, InventoryBadge, ItemsCard, LeaseServiceCard, LineItemDetails, LocationPicker, MediaGallery, MetadataStringList, MobileAccountShell, MobileBackButton, MobileMoreButton, MobileTabBar, NextDeliveryCard, OrderDetailHeader, OrderDetailMetaPipe, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderList, OrderRow, OrderSummary, OrderTimeline, OrderTotals, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductModel3D, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, RichText, SaleBadge, ScheduleServiceCard, SearchInput, SearchPage, SearchTemplate, Section, SectionMore, ServiceProductLayout, SessionMessageBanner, SignOutIcon, Skeleton, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, Status, StoreNav, StoreVideo, SubscriptionCard, SubscriptionList, SubscriptionRow, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, Toast, TwoColumnGrid, VariantSelector, VolumePricing, WelcomeCard, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cimplify/sdk",
3
- "version": "0.73.0",
3
+ "version": "0.74.0",
4
4
  "description": "Cimplify Commerce SDK for storefronts",
5
5
  "keywords": [
6
6
  "cimplify",
@@ -14,7 +14,7 @@
14
14
  "files": [
15
15
  {
16
16
  "path": "product-customizer.tsx",
17
- "content": "\"use client\";\n\nimport React, { useState, useCallback, useMemo, useEffect, useRef } from \"react\";\nimport { Button } from \"@base-ui/react/button\";\nimport type {\n ProductWithDetails,\n VariantView,\n AddOnOption,\n ComponentSelectionInput,\n CompositePriceResult,\n} from \"@cimplify/sdk\";\nimport type { ProductBillingPlan } from \"@cimplify/sdk\";\nimport type { BundleSelectionInput } from \"@cimplify/sdk\";\nimport { parsePrice, getUnitPriceAtQuantity, getProductCurrency } from \"@cimplify/sdk\";\nimport { formatDuration } from \"./utils/format-duration\";\nimport { useCart, useQuote } from \"@cimplify/sdk/react\";\nimport type { AddToCartOptions } from \"@cimplify/sdk/react\";\nimport { Price } from \"@cimplify/sdk/react\";\nimport { QuantitySelector } from \"@cimplify/sdk/react\";\nimport { VariantSelector } from \"@cimplify/sdk/react\";\nimport { AddOnSelector } from \"@cimplify/sdk/react\";\nimport { CompositeSelector } from \"@cimplify/sdk/react\";\nimport { BundleSelector } from \"@cimplify/sdk/react\";\nimport { BillingPlanSelector } from \"@cimplify/sdk/react\";\nimport { VolumePricing } from \"@cimplify/sdk/react\";\nimport { CustomerInputFields } from \"./customer-input-fields\";\nimport { DateSlotPicker } from \"@cimplify/sdk/react\";\nimport type { AvailableSlot } from \"@cimplify/sdk\";\nimport { cn } from \"@cimplify/sdk/react\";\n\nexport interface ProductCustomizerClassNames {\n root?: string;\n actions?: string;\n submitButton?: string;\n submitButtonAdded?: string;\n validation?: string;\n specialInstructions?: string;\n depositInfo?: string;\n allergens?: string;\n duration?: string;\n}\n\nexport interface ProductCustomizerProps {\n product: ProductWithDetails;\n onAddToCart?: (\n product: ProductWithDetails,\n quantity: number,\n options: AddToCartOptions,\n ) => void | Promise<void>;\n /** Lets the parent swap its gallery for `variant.images` on selection. */\n onVariantChange?: (\n variantId: string | undefined,\n variant: VariantView | undefined,\n ) => void;\n showSpecialInstructions?: boolean;\n className?: string;\n classNames?: ProductCustomizerClassNames;\n}\n\nexport function ProductCustomizer({\n product,\n onAddToCart,\n onVariantChange,\n showSpecialInstructions = true,\n className,\n classNames,\n}: ProductCustomizerProps): React.ReactElement {\n const [quantity, setQuantity] = useState(product.min_order_quantity ?? 1);\n const [isAdded, setIsAdded] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [selectedVariantId, setSelectedVariantId] = useState<string | undefined>();\n const [selectedVariant, setSelectedVariant] = useState<VariantView | undefined>();\n const [selectedAddOnOptionIds, setSelectedAddOnOptionIds] = useState<string[]>([]);\n\n const [compositeSelections, setCompositeSelections] = useState<ComponentSelectionInput[]>([]);\n const [compositePrice, setCompositePrice] = useState<CompositePriceResult | null>(null);\n const [compositeReady, setCompositeReady] = useState(false);\n\n const [bundleSelections, setBundleSelections] = useState<BundleSelectionInput[]>([]);\n const [bundleTotalPrice, setBundleTotalPrice] = useState<number | null>(null);\n const [bundleReady, setBundleReady] = useState(false);\n const [selectedBillingPlan, setSelectedBillingPlan] = useState<ProductBillingPlan | null>(null);\n const [customerInputValues, setCustomerInputValues] = useState<Record<string, unknown>>({});\n const [specialInstructions, setSpecialInstructions] = useState(\"\");\n const [selectedSlot, setSelectedSlot] = useState<AvailableSlot | null>(null);\n\n const cart = useCart();\n\n const currency = getProductCurrency(product);\n const productType = product.type || \"product\";\n const isComposite = productType === \"composite\";\n const isBundle = productType === \"bundle\";\n const isDigital = productType === \"digital\";\n const isService = productType === \"service\";\n const isStandard = !isComposite && !isBundle;\n\n const hasVariants = isStandard && product.variants && product.variants.length > 0;\n const hasAddOns = isStandard && product.add_ons && product.add_ons.length > 0;\n\n useEffect(() => {\n setQuantity(product.min_order_quantity ?? 1);\n setIsAdded(false);\n setIsSubmitting(false);\n setSelectedVariantId(undefined);\n setSelectedVariant(undefined);\n setSelectedAddOnOptionIds([]);\n setCompositeSelections([]);\n setCompositePrice(null);\n setCompositeReady(false);\n setBundleSelections([]);\n setBundleTotalPrice(null);\n setBundleReady(false);\n setSelectedBillingPlan(null);\n setCustomerInputValues({});\n setSpecialInstructions(\"\");\n setSelectedSlot(null);\n }, [product.id, product.min_order_quantity]);\n\n const selectedAddOnOptions = useMemo(() => {\n if (!product.add_ons) return [];\n const options: AddOnOption[] = [];\n for (const addOn of product.add_ons) {\n for (const option of addOn.options) {\n if (selectedAddOnOptionIds.includes(option.id)) {\n options.push(option);\n }\n }\n }\n return options;\n }, [product.add_ons, selectedAddOnOptionIds]);\n\n const normalizedAddOnOptionIds = useMemo(() => {\n if (selectedAddOnOptionIds.length === 0) return [];\n return Array.from(new Set(selectedAddOnOptionIds.map((id) => id.trim()).filter(Boolean))).sort();\n }, [selectedAddOnOptionIds]);\n\n const localTotalPrice = useMemo(() => {\n if (isComposite && compositePrice) {\n return parsePrice(compositePrice.final_price) * quantity;\n }\n\n if (isBundle && bundleTotalPrice != null) {\n return bundleTotalPrice * quantity;\n }\n\n let price = parsePrice(product.default_price);\n\n if (selectedVariant?.price_adjustment) {\n price += parsePrice(selectedVariant.price_adjustment);\n }\n\n for (const option of selectedAddOnOptions) {\n if (option.default_price) {\n price += parsePrice(option.default_price);\n }\n }\n\n return price * quantity;\n }, [product.default_price, selectedVariant, selectedAddOnOptions, quantity, isComposite, compositePrice, isBundle, bundleTotalPrice]);\n\n const requiredAddOnsSatisfied = useMemo(() => {\n if (!product.add_ons) return true;\n\n for (const addOn of product.add_ons) {\n if (addOn.is_required) {\n const selectedInGroup = selectedAddOnOptionIds.filter((id) =>\n addOn.options.some((opt) => opt.id === id),\n ).length;\n\n const minRequired = addOn.min_selections || 1;\n if (selectedInGroup < minRequired) {\n return false;\n }\n }\n }\n return true;\n }, [product.add_ons, selectedAddOnOptionIds]);\n\n const quoteInput = useMemo(\n () => ({\n productId: product.id,\n quantity,\n variantId: selectedVariantId,\n addOnOptionIds: normalizedAddOnOptionIds.length > 0 ? normalizedAddOnOptionIds : undefined,\n bundleSelections: isBundle && bundleSelections.length > 0 ? bundleSelections : undefined,\n compositeSelections: isComposite && compositeSelections.length > 0 ? compositeSelections : undefined,\n }),\n [product.id, quantity, selectedVariantId, normalizedAddOnOptionIds, isBundle, bundleSelections, isComposite, compositeSelections],\n );\n\n const requiredInputsSatisfied = useMemo(() => {\n if (!product.input_fields || product.input_fields.length === 0) return true;\n return product.input_fields.every((field) => {\n if (!field.is_required) return true;\n const val = customerInputValues[field.id];\n return val !== undefined && val !== \"\" && val !== null;\n });\n }, [product.input_fields, customerInputValues]);\n\n const quoteEnabled = isComposite\n ? compositeReady && requiredInputsSatisfied\n : isBundle\n ? bundleReady && requiredInputsSatisfied\n : requiredAddOnsSatisfied && requiredInputsSatisfied;\n\n const { quote } = useQuote(quoteInput, {\n enabled: quoteEnabled,\n });\n\n const quoteId = quote?.quote_id;\n const quotedTotalPrice = useMemo(() => {\n if (!quote) return undefined;\n\n const priceInfo = quote.quoted_total_price_info ?? quote.final_price_info;\n const perUnit = priceInfo.pre_tax_price;\n if (perUnit === undefined || perUnit === null) return undefined;\n return parsePrice(perUnit) * quantity;\n }, [quote, quantity]);\n\n const displayTotalPrice = quotedTotalPrice ?? localTotalPrice;\n\n const handleVariantChange = useCallback(\n (variantId: string | undefined, variant: VariantView | undefined) => {\n setSelectedVariantId(variantId);\n setSelectedVariant(variant);\n onVariantChange?.(variantId, variant);\n },\n [onVariantChange],\n );\n\n const addedTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n useEffect(() => () => clearTimeout(addedTimerRef.current), []);\n\n const handleAddToCart = useCallback(async () => {\n if (isSubmitting) return;\n\n setIsSubmitting(true);\n\n const options: AddToCartOptions = {\n variantId: selectedVariantId,\n variant: selectedVariant\n ? { id: selectedVariant.id, name: selectedVariant.name || \"\", price_adjustment: selectedVariant.price_adjustment }\n : undefined,\n quoteId,\n addOnOptionIds: normalizedAddOnOptionIds.length > 0 ? normalizedAddOnOptionIds : undefined,\n addOnOptions: selectedAddOnOptions.length > 0\n ? selectedAddOnOptions.map((opt) => ({\n id: opt.id,\n name: opt.name,\n add_on_id: opt.add_on_id,\n default_price: opt.default_price,\n }))\n : undefined,\n compositeSelections: isComposite && compositeSelections.length > 0 ? compositeSelections : undefined,\n bundleSelections: isBundle && bundleSelections.length > 0 ? bundleSelections : undefined,\n billingPlanId: selectedBillingPlan?.id,\n ...(isService && selectedSlot\n ? {\n scheduledStart: selectedSlot.start_time,\n scheduledEnd: selectedSlot.end_time,\n staffId: selectedSlot.available_staff?.[0]?.staff_id,\n resourceId: selectedSlot.available_resources?.[0]?.resource_id,\n }\n : {}),\n customerInputs: Object.keys(customerInputValues).length > 0\n ? Object.entries(customerInputValues)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([fieldId, value]) => ({ field_id: fieldId, value }))\n : undefined,\n specialInstructions: specialInstructions.trim() || undefined,\n };\n\n try {\n if (onAddToCart) {\n await onAddToCart(product, quantity, options);\n } else {\n await cart.addItem(product, quantity, options);\n }\n setIsAdded(true);\n clearTimeout(addedTimerRef.current);\n addedTimerRef.current = setTimeout(() => {\n setIsAdded(false);\n setQuantity(product.min_order_quantity ?? 1);\n }, 2000);\n } catch {\n // Caller handles errors via onAddToCart or cart hook error state\n } finally {\n setIsSubmitting(false);\n }\n }, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, isSubmitting, onAddToCart, cart]);\n\n return (\n <div data-cimplify-customizer className={cn(\"space-y-6\", className, classNames?.root)}>\n {isComposite && product.groups && product.composite_id && (\n <CompositeSelector\n compositeId={product.composite_id}\n groups={product.groups}\n currency={currency}\n onSelectionsChange={setCompositeSelections}\n onPriceChange={setCompositePrice}\n onReady={setCompositeReady}\n skipPriceFetch\n />\n )}\n\n {isBundle && product.components && (\n <BundleSelector\n components={product.components}\n bundlePrice={product.bundle_price}\n discountValue={product.discount_value}\n pricingType={product.pricing_type}\n currency={currency}\n onSelectionsChange={setBundleSelections}\n onPriceChange={setBundleTotalPrice}\n onReady={setBundleReady}\n />\n )}\n\n {isService && (\n <DateSlotPicker\n serviceId={product.id}\n selectedSlot={selectedSlot}\n onSlotSelect={(slot) => setSelectedSlot(slot)}\n participantCount={quantity}\n currency={currency}\n />\n )}\n\n {hasVariants && (\n <VariantSelector\n variants={product.variants!}\n variantAxes={product.variant_axes}\n basePrice={product.default_price}\n currency={currency}\n selectedVariantId={selectedVariantId}\n onVariantChange={handleVariantChange}\n productName={product.name}\n />\n )}\n\n {hasAddOns && (\n <AddOnSelector\n addOns={product.add_ons!}\n selectedOptions={selectedAddOnOptionIds}\n onOptionsChange={setSelectedAddOnOptionIds}\n currency={currency}\n />\n )}\n\n {/* Billing plans */}\n {product.billing_plans && product.billing_plans.length > 0 && (\n <BillingPlanSelector\n productId={product.id}\n plans={product.billing_plans}\n currency={currency}\n onPlanSelect={setSelectedBillingPlan}\n selectedPlanId={selectedBillingPlan?.id ?? null}\n showOneTimePurchase\n />\n )}\n\n {/* Volume pricing tiers */}\n {product.quantity_pricing && product.quantity_pricing.length > 1 && (\n <VolumePricing\n tiers={product.quantity_pricing}\n currentQuantity={quantity}\n currency={currency}\n />\n )}\n\n {/* Customer input fields */}\n {product.input_fields && product.input_fields.length > 0 && (\n <CustomerInputFields\n fields={product.input_fields}\n values={customerInputValues}\n onChange={setCustomerInputValues}\n currency={currency}\n />\n )}\n\n {/* Deposit info for service products */}\n {product.deposit_type && product.deposit_type !== \"none\" && product.deposit_amount && (\n <div data-cimplify-customizer-deposit className={cn(\"text-sm text-muted-foreground\", classNames?.depositInfo)}>\n {product.deposit_type === \"fixed\" ? (\n <span>Deposit required: <Price amount={product.deposit_amount} currency={currency} /></span>\n ) : (\n <span>Deposit required: {parsePrice(product.deposit_amount)}%</span>\n )}\n </div>\n )}\n\n {/* Allergens */}\n {product.allergies && product.allergies.length > 0 && (\n <div data-cimplify-customizer-allergens className={cn(\"flex flex-wrap gap-1.5\", classNames?.allergens)}>\n {product.allergies.map((allergen) => (\n <span\n key={allergen}\n data-cimplify-allergen-tag\n className=\"inline-block text-xs px-2 py-0.5 rounded-full bg-muted text-muted-foreground\"\n >\n {allergen}\n </span>\n ))}\n </div>\n )}\n\n {/* Service duration */}\n {isService && product.duration_minutes != null && (\n <div data-cimplify-customizer-duration className={cn(\"text-sm text-muted-foreground\", classNames?.duration)}>\n Duration: {formatDuration(product.duration_minutes, product.duration_unit)}\n </div>\n )}\n\n {/* Special instructions */}\n {showSpecialInstructions && !isDigital && (\n <div data-cimplify-customizer-special-instructions>\n <textarea\n value={specialInstructions}\n onChange={(e) => setSpecialInstructions(e.target.value)}\n placeholder=\"Special instructions (e.g., no onions, extra sauce)\"\n rows={2}\n data-cimplify-customizer-textarea\n className={cn(\n \"w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring resize-none\",\n classNames?.specialInstructions,\n )}\n />\n </div>\n )}\n\n <div\n data-cimplify-customizer-actions\n className={cn(\"pt-4 border-t border-border\", classNames?.actions)}\n >\n {!quoteEnabled && (\n <p\n id=\"cimplify-customizer-validation\"\n data-cimplify-customizer-validation\n className={cn(\"text-sm text-destructive mb-3\", classNames?.validation)}\n >\n Please select all required options\n </p>\n )}\n <div className=\"flex items-center gap-4\">\n <div className=\"flex flex-col gap-1\">\n <QuantitySelector\n value={quantity}\n onChange={setQuantity}\n min={product.min_order_quantity ?? 1}\n />\n {product.min_order_quantity && product.min_order_quantity > 1 && (\n <span data-cimplify-customizer-min-hint className=\"text-xs text-muted-foreground text-center\">\n Min. {product.min_order_quantity}\n </span>\n )}\n </div>\n\n {product.quantity_pricing && product.quantity_pricing.length > 0 && (\n <div data-cimplify-customizer-unit-price className=\"text-sm text-muted-foreground text-right shrink-0\">\n <Price amount={getUnitPriceAtQuantity(product.quantity_pricing, quantity, parsePrice(product.default_price))} currency={currency} className=\"font-medium text-foreground\" /> ea.\n </div>\n )}\n\n <Button\n onClick={handleAddToCart}\n disabled={isAdded || isSubmitting || !quoteEnabled}\n aria-describedby={!quoteEnabled ? \"cimplify-customizer-validation\" : undefined}\n data-cimplify-customizer-submit\n className={cn(\n \"flex-1 h-14 text-base bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed rounded-full\",\n isAdded && classNames?.submitButtonAdded,\n classNames?.submitButton,\n )}\n >\n {isAdded ? \"Added to Cart\" : (\n <>\n Add to Cart &middot; <Price amount={displayTotalPrice} currency={currency} />\n </>\n )}\n </Button>\n </div>\n </div>\n\n </div>\n );\n}\n"
17
+ "content": "\"use client\";\n\nimport React, { useState, useCallback, useMemo, useEffect, useRef } from \"react\";\nimport { Button } from \"@base-ui/react/button\";\nimport type {\n ProductWithDetails,\n VariantView,\n AddOnOption,\n ComponentSelectionInput,\n CompositePriceResult,\n} from \"@cimplify/sdk\";\nimport type { ProductBillingPlan } from \"@cimplify/sdk\";\nimport type { BundleSelectionInput } from \"@cimplify/sdk\";\nimport { parsePrice, getUnitPriceAtQuantity, getProductCurrency } from \"@cimplify/sdk\";\nimport { formatDuration } from \"./utils/format-duration\";\nimport { useCart, useQuote } from \"@cimplify/sdk/react\";\nimport type { AddToCartOptions } from \"@cimplify/sdk/react\";\nimport { Price } from \"@cimplify/sdk/react\";\nimport { QuantitySelector } from \"@cimplify/sdk/react\";\nimport { VariantSelector } from \"@cimplify/sdk/react\";\nimport { AddOnSelector } from \"@cimplify/sdk/react\";\nimport { StaffPicker } from \"@cimplify/sdk/react\";\nimport { BookingSummary } from \"./booking-summary\";\nimport type { Staff } from \"@cimplify/sdk\";\nimport { CompositeSelector } from \"@cimplify/sdk/react\";\nimport { BundleSelector } from \"@cimplify/sdk/react\";\nimport { BillingPlanSelector } from \"@cimplify/sdk/react\";\nimport { VolumePricing } from \"@cimplify/sdk/react\";\nimport { CustomerInputFields } from \"./customer-input-fields\";\nimport { DateSlotPicker } from \"@cimplify/sdk/react\";\nimport type { AvailableSlot } from \"@cimplify/sdk\";\nimport { cn } from \"@cimplify/sdk/react\";\n\nexport interface ProductCustomizerClassNames {\n root?: string;\n actions?: string;\n submitButton?: string;\n submitButtonAdded?: string;\n validation?: string;\n specialInstructions?: string;\n depositInfo?: string;\n allergens?: string;\n duration?: string;\n}\n\nexport interface ProductCustomizerProps {\n product: ProductWithDetails;\n onAddToCart?: (\n product: ProductWithDetails,\n quantity: number,\n options: AddToCartOptions,\n ) => void | Promise<void>;\n /** Lets the parent swap its gallery for `variant.images` on selection. */\n onVariantChange?: (\n variantId: string | undefined,\n variant: VariantView | undefined,\n ) => void;\n showSpecialInstructions?: boolean;\n className?: string;\n classNames?: ProductCustomizerClassNames;\n}\n\nexport function ProductCustomizer({\n product,\n onAddToCart,\n onVariantChange,\n showSpecialInstructions = true,\n className,\n classNames,\n}: ProductCustomizerProps): React.ReactElement {\n const [quantity, setQuantity] = useState(product.min_order_quantity ?? 1);\n const [isAdded, setIsAdded] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [selectedVariantId, setSelectedVariantId] = useState<string | undefined>();\n const [selectedVariant, setSelectedVariant] = useState<VariantView | undefined>();\n const [selectedAddOnOptionIds, setSelectedAddOnOptionIds] = useState<string[]>([]);\n\n const [compositeSelections, setCompositeSelections] = useState<ComponentSelectionInput[]>([]);\n const [compositePrice, setCompositePrice] = useState<CompositePriceResult | null>(null);\n const [compositeReady, setCompositeReady] = useState(false);\n\n const [bundleSelections, setBundleSelections] = useState<BundleSelectionInput[]>([]);\n const [bundleTotalPrice, setBundleTotalPrice] = useState<number | null>(null);\n const [bundleReady, setBundleReady] = useState(false);\n const [selectedBillingPlan, setSelectedBillingPlan] = useState<ProductBillingPlan | null>(null);\n const [customerInputValues, setCustomerInputValues] = useState<Record<string, unknown>>({});\n const [specialInstructions, setSpecialInstructions] = useState(\"\");\n const [selectedSlot, setSelectedSlot] = useState<AvailableSlot | null>(null);\n const [selectedStaffId, setSelectedStaffId] = useState<string | null>(null);\n\n const cart = useCart();\n\n const currency = getProductCurrency(product);\n const productType = product.type || \"product\";\n const isComposite = productType === \"composite\";\n const isBundle = productType === \"bundle\";\n const isDigital = productType === \"digital\";\n const isService = productType === \"service\";\n const isStandard = !isComposite && !isBundle;\n\n const hasVariants = isStandard && product.variants && product.variants.length > 0;\n const hasAddOns = isStandard && product.add_ons && product.add_ons.length > 0;\n\n useEffect(() => {\n setQuantity(product.min_order_quantity ?? 1);\n setIsAdded(false);\n setIsSubmitting(false);\n setSelectedVariantId(undefined);\n setSelectedVariant(undefined);\n setSelectedAddOnOptionIds([]);\n setCompositeSelections([]);\n setCompositePrice(null);\n setCompositeReady(false);\n setBundleSelections([]);\n setBundleTotalPrice(null);\n setBundleReady(false);\n setSelectedBillingPlan(null);\n setCustomerInputValues({});\n setSpecialInstructions(\"\");\n setSelectedSlot(null);\n setSelectedStaffId(null);\n }, [product.id, product.min_order_quantity]);\n\n // Staff offered for the chosen slot. SlotStaffInfo carries id + name; richer\n // profiles (avatars/bios) would come from a staff roster fetch.\n const slotStaff = useMemo<Staff[]>(\n () =>\n (selectedSlot?.available_staff ?? []).map((member) => ({\n id: member.staff_id,\n name: member.name,\n })),\n [selectedSlot],\n );\n const selectedStaffName = selectedStaffId\n ? (slotStaff.find((member) => member.id === selectedStaffId)?.name ?? null)\n : null;\n\n const selectedAddOnOptions = useMemo(() => {\n if (!product.add_ons) return [];\n const options: AddOnOption[] = [];\n for (const addOn of product.add_ons) {\n for (const option of addOn.options) {\n if (selectedAddOnOptionIds.includes(option.id)) {\n options.push(option);\n }\n }\n }\n return options;\n }, [product.add_ons, selectedAddOnOptionIds]);\n\n const normalizedAddOnOptionIds = useMemo(() => {\n if (selectedAddOnOptionIds.length === 0) return [];\n return Array.from(new Set(selectedAddOnOptionIds.map((id) => id.trim()).filter(Boolean))).sort();\n }, [selectedAddOnOptionIds]);\n\n const localTotalPrice = useMemo(() => {\n if (isComposite && compositePrice) {\n return parsePrice(compositePrice.final_price) * quantity;\n }\n\n if (isBundle && bundleTotalPrice != null) {\n return bundleTotalPrice * quantity;\n }\n\n let price = parsePrice(product.default_price);\n\n if (selectedVariant?.price_adjustment) {\n price += parsePrice(selectedVariant.price_adjustment);\n }\n\n for (const option of selectedAddOnOptions) {\n if (option.default_price) {\n price += parsePrice(option.default_price);\n }\n }\n\n return price * quantity;\n }, [product.default_price, selectedVariant, selectedAddOnOptions, quantity, isComposite, compositePrice, isBundle, bundleTotalPrice]);\n\n const requiredAddOnsSatisfied = useMemo(() => {\n if (!product.add_ons) return true;\n\n for (const addOn of product.add_ons) {\n if (addOn.is_required) {\n const selectedInGroup = selectedAddOnOptionIds.filter((id) =>\n addOn.options.some((opt) => opt.id === id),\n ).length;\n\n const minRequired = addOn.min_selections || 1;\n if (selectedInGroup < minRequired) {\n return false;\n }\n }\n }\n return true;\n }, [product.add_ons, selectedAddOnOptionIds]);\n\n const quoteInput = useMemo(\n () => ({\n productId: product.id,\n quantity,\n variantId: selectedVariantId,\n addOnOptionIds: normalizedAddOnOptionIds.length > 0 ? normalizedAddOnOptionIds : undefined,\n bundleSelections: isBundle && bundleSelections.length > 0 ? bundleSelections : undefined,\n compositeSelections: isComposite && compositeSelections.length > 0 ? compositeSelections : undefined,\n }),\n [product.id, quantity, selectedVariantId, normalizedAddOnOptionIds, isBundle, bundleSelections, isComposite, compositeSelections],\n );\n\n const requiredInputsSatisfied = useMemo(() => {\n if (!product.input_fields || product.input_fields.length === 0) return true;\n return product.input_fields.every((field) => {\n if (!field.is_required) return true;\n const val = customerInputValues[field.id];\n return val !== undefined && val !== \"\" && val !== null;\n });\n }, [product.input_fields, customerInputValues]);\n\n const quoteEnabled = isComposite\n ? compositeReady && requiredInputsSatisfied\n : isBundle\n ? bundleReady && requiredInputsSatisfied\n : requiredAddOnsSatisfied && requiredInputsSatisfied;\n\n const { quote } = useQuote(quoteInput, {\n enabled: quoteEnabled,\n });\n\n const quoteId = quote?.quote_id;\n const quotedTotalPrice = useMemo(() => {\n if (!quote) return undefined;\n\n const priceInfo = quote.quoted_total_price_info ?? quote.final_price_info;\n const perUnit = priceInfo.pre_tax_price;\n if (perUnit === undefined || perUnit === null) return undefined;\n return parsePrice(perUnit) * quantity;\n }, [quote, quantity]);\n\n const displayTotalPrice = quotedTotalPrice ?? localTotalPrice;\n\n const handleVariantChange = useCallback(\n (variantId: string | undefined, variant: VariantView | undefined) => {\n setSelectedVariantId(variantId);\n setSelectedVariant(variant);\n onVariantChange?.(variantId, variant);\n },\n [onVariantChange],\n );\n\n const addedTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n useEffect(() => () => clearTimeout(addedTimerRef.current), []);\n\n const handleAddToCart = useCallback(async () => {\n if (isSubmitting) return;\n\n setIsSubmitting(true);\n\n const options: AddToCartOptions = {\n variantId: selectedVariantId,\n variant: selectedVariant\n ? { id: selectedVariant.id, name: selectedVariant.name || \"\", price_adjustment: selectedVariant.price_adjustment }\n : undefined,\n quoteId,\n addOnOptionIds: normalizedAddOnOptionIds.length > 0 ? normalizedAddOnOptionIds : undefined,\n addOnOptions: selectedAddOnOptions.length > 0\n ? selectedAddOnOptions.map((opt) => ({\n id: opt.id,\n name: opt.name,\n add_on_id: opt.add_on_id,\n default_price: opt.default_price,\n }))\n : undefined,\n compositeSelections: isComposite && compositeSelections.length > 0 ? compositeSelections : undefined,\n bundleSelections: isBundle && bundleSelections.length > 0 ? bundleSelections : undefined,\n billingPlanId: selectedBillingPlan?.id,\n ...(isService && selectedSlot\n ? {\n scheduledStart: selectedSlot.start_time,\n scheduledEnd: selectedSlot.end_time,\n staffId: selectedStaffId ?? selectedSlot.available_staff?.[0]?.staff_id,\n resourceId: selectedSlot.available_resources?.[0]?.resource_id,\n }\n : {}),\n customerInputs: Object.keys(customerInputValues).length > 0\n ? Object.entries(customerInputValues)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([fieldId, value]) => ({ field_id: fieldId, value }))\n : undefined,\n specialInstructions: specialInstructions.trim() || undefined,\n };\n\n try {\n if (onAddToCart) {\n await onAddToCart(product, quantity, options);\n } else {\n await cart.addItem(product, quantity, options);\n }\n setIsAdded(true);\n clearTimeout(addedTimerRef.current);\n addedTimerRef.current = setTimeout(() => {\n setIsAdded(false);\n setQuantity(product.min_order_quantity ?? 1);\n }, 2000);\n } catch {\n // Caller handles errors via onAddToCart or cart hook error state\n } finally {\n setIsSubmitting(false);\n }\n }, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, selectedStaffId, isSubmitting, onAddToCart, cart]);\n\n return (\n <div data-cimplify-customizer className={cn(\"space-y-6\", className, classNames?.root)}>\n {isComposite && product.groups && product.composite_id && (\n <CompositeSelector\n compositeId={product.composite_id}\n groups={product.groups}\n currency={currency}\n onSelectionsChange={setCompositeSelections}\n onPriceChange={setCompositePrice}\n onReady={setCompositeReady}\n skipPriceFetch\n />\n )}\n\n {isBundle && product.components && (\n <BundleSelector\n components={product.components}\n bundlePrice={product.bundle_price}\n discountValue={product.discount_value}\n pricingType={product.pricing_type}\n currency={currency}\n onSelectionsChange={setBundleSelections}\n onPriceChange={setBundleTotalPrice}\n onReady={setBundleReady}\n />\n )}\n\n {isService && (\n <DateSlotPicker\n serviceId={product.id}\n selectedSlot={selectedSlot}\n onSlotSelect={(slot) => {\n setSelectedSlot(slot);\n setSelectedStaffId(null);\n }}\n participantCount={quantity}\n currency={currency}\n />\n )}\n\n {isService && slotStaff.length > 0 && (\n <div data-cimplify-customizer-staff>\n <label className=\"block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3\">\n Choose your specialist\n </label>\n <StaffPicker\n staff={slotStaff}\n selectedStaffId={selectedStaffId}\n onStaffSelect={setSelectedStaffId}\n className=\"flex flex-wrap gap-2\"\n classNames={{\n option:\n \"inline-flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium transition-colors hover:border-foreground/40 cursor-pointer data-[selected]:border-foreground data-[selected]:bg-foreground data-[selected]:text-background\",\n avatar: \"w-6 h-6 rounded-full object-cover\",\n }}\n />\n </div>\n )}\n\n {hasVariants && (\n <VariantSelector\n variants={product.variants!}\n variantAxes={product.variant_axes}\n basePrice={product.default_price}\n currency={currency}\n selectedVariantId={selectedVariantId}\n onVariantChange={handleVariantChange}\n productName={product.name}\n />\n )}\n\n {hasAddOns && (\n <AddOnSelector\n addOns={product.add_ons!}\n selectedOptions={selectedAddOnOptionIds}\n onOptionsChange={setSelectedAddOnOptionIds}\n currency={currency}\n />\n )}\n\n {/* Billing plans */}\n {product.billing_plans && product.billing_plans.length > 0 && (\n <BillingPlanSelector\n productId={product.id}\n plans={product.billing_plans}\n currency={currency}\n onPlanSelect={setSelectedBillingPlan}\n selectedPlanId={selectedBillingPlan?.id ?? null}\n showOneTimePurchase\n />\n )}\n\n {/* Volume pricing tiers */}\n {product.quantity_pricing && product.quantity_pricing.length > 1 && (\n <VolumePricing\n tiers={product.quantity_pricing}\n currentQuantity={quantity}\n currency={currency}\n />\n )}\n\n {/* Customer input fields */}\n {product.input_fields && product.input_fields.length > 0 && (\n <CustomerInputFields\n fields={product.input_fields}\n values={customerInputValues}\n onChange={setCustomerInputValues}\n currency={currency}\n />\n )}\n\n {/* Deposit info for service products */}\n {product.deposit_type && product.deposit_type !== \"none\" && product.deposit_amount && (\n <div data-cimplify-customizer-deposit className={cn(\"text-sm text-muted-foreground\", classNames?.depositInfo)}>\n {product.deposit_type === \"fixed\" ? (\n <span>Deposit required: <Price amount={product.deposit_amount} currency={currency} /></span>\n ) : (\n <span>Deposit required: {parsePrice(product.deposit_amount)}%</span>\n )}\n </div>\n )}\n\n {/* Allergens */}\n {product.allergies && product.allergies.length > 0 && (\n <div data-cimplify-customizer-allergens className={cn(\"flex flex-wrap gap-1.5\", classNames?.allergens)}>\n {product.allergies.map((allergen) => (\n <span\n key={allergen}\n data-cimplify-allergen-tag\n className=\"inline-block text-xs px-2 py-0.5 rounded-full bg-muted text-muted-foreground\"\n >\n {allergen}\n </span>\n ))}\n </div>\n )}\n\n {/* Service duration */}\n {isService && product.duration_minutes != null && (\n <div data-cimplify-customizer-duration className={cn(\"text-sm text-muted-foreground\", classNames?.duration)}>\n Duration: {formatDuration(product.duration_minutes, product.duration_unit)}\n </div>\n )}\n\n {/* Special instructions */}\n {showSpecialInstructions && !isDigital && (\n <div data-cimplify-customizer-special-instructions>\n <textarea\n value={specialInstructions}\n onChange={(e) => setSpecialInstructions(e.target.value)}\n placeholder=\"Special instructions (e.g., no onions, extra sauce)\"\n rows={2}\n data-cimplify-customizer-textarea\n className={cn(\n \"w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring resize-none\",\n classNames?.specialInstructions,\n )}\n />\n </div>\n )}\n\n {isService && selectedSlot && (\n <BookingSummary\n slot={selectedSlot}\n total={displayTotalPrice}\n staffName={selectedStaffName}\n durationMinutes={product.duration_minutes}\n depositType={product.deposit_type}\n depositAmount={product.deposit_amount}\n currency={currency}\n />\n )}\n\n <div\n data-cimplify-customizer-actions\n className={cn(\"pt-4 border-t border-border\", classNames?.actions)}\n >\n {!quoteEnabled && (\n <p\n id=\"cimplify-customizer-validation\"\n data-cimplify-customizer-validation\n className={cn(\"text-sm text-destructive mb-3\", classNames?.validation)}\n >\n Please select all required options\n </p>\n )}\n <div className=\"flex items-center gap-4\">\n <div className=\"flex flex-col gap-1\">\n <QuantitySelector\n value={quantity}\n onChange={setQuantity}\n min={product.min_order_quantity ?? 1}\n />\n {product.min_order_quantity && product.min_order_quantity > 1 && (\n <span data-cimplify-customizer-min-hint className=\"text-xs text-muted-foreground text-center\">\n Min. {product.min_order_quantity}\n </span>\n )}\n </div>\n\n {product.quantity_pricing && product.quantity_pricing.length > 0 && (\n <div data-cimplify-customizer-unit-price className=\"text-sm text-muted-foreground text-right shrink-0\">\n <Price amount={getUnitPriceAtQuantity(product.quantity_pricing, quantity, parsePrice(product.default_price))} currency={currency} className=\"font-medium text-foreground\" /> ea.\n </div>\n )}\n\n <Button\n onClick={handleAddToCart}\n disabled={isAdded || isSubmitting || !quoteEnabled}\n aria-describedby={!quoteEnabled ? \"cimplify-customizer-validation\" : undefined}\n data-cimplify-customizer-submit\n className={cn(\n \"flex-1 h-14 text-base bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed rounded-full\",\n isAdded && classNames?.submitButtonAdded,\n classNames?.submitButton,\n )}\n >\n {isAdded ? \"Added to Cart\" : (\n <>\n Add to Cart &middot; <Price amount={displayTotalPrice} currency={currency} />\n </>\n )}\n </Button>\n </div>\n </div>\n\n </div>\n );\n}\n"
18
18
  }
19
19
  ]
20
20
  }