@wix/headless-bookings 0.0.11 → 0.0.13

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.
Files changed (59) hide show
  1. package/cjs/dist/api/index.d.ts +1 -0
  2. package/cjs/dist/api/index.js +1 -0
  3. package/cjs/dist/api/query-services/index.d.ts +6 -7
  4. package/cjs/dist/api/query-services/index.js +4 -4
  5. package/cjs/dist/api/time-slot-list/index.d.ts +53 -0
  6. package/cjs/dist/api/time-slot-list/index.js +133 -0
  7. package/cjs/dist/react/core/booking/Booking.d.ts +7 -7
  8. package/cjs/dist/react/core/booking/Booking.js +5 -5
  9. package/cjs/dist/react/core/location/Location.d.ts +3 -3
  10. package/cjs/dist/react/core/location/Location.js +2 -2
  11. package/cjs/dist/react/core/service/Service.d.ts +8 -8
  12. package/cjs/dist/react/core/service-list/ServiceList.d.ts +2 -2
  13. package/cjs/dist/react/location/Location.d.ts +3 -3
  14. package/cjs/dist/react/service/Service.d.ts +9 -9
  15. package/cjs/dist/react/service/Service.js +5 -5
  16. package/cjs/dist/react/service-list/ServiceList.d.ts +3 -3
  17. package/cjs/dist/services/booking/booking.d.ts +25 -16
  18. package/cjs/dist/services/booking/booking.js +50 -16
  19. package/cjs/dist/services/index.d.ts +2 -1
  20. package/cjs/dist/services/index.js +1 -0
  21. package/cjs/dist/services/service/service.d.ts +5 -5
  22. package/cjs/dist/services/service/service.js +20 -21
  23. package/cjs/dist/services/service-list/service-list.d.ts +3 -3
  24. package/cjs/dist/services/time-slot-list/index.d.ts +6 -0
  25. package/cjs/dist/services/time-slot-list/index.js +6 -0
  26. package/cjs/dist/services/time-slot-list/time-slot-list.d.ts +58 -0
  27. package/cjs/dist/services/time-slot-list/time-slot-list.def.d.ts +84 -0
  28. package/cjs/dist/services/time-slot-list/time-slot-list.def.js +17 -0
  29. package/cjs/dist/services/time-slot-list/time-slot-list.js +349 -0
  30. package/dist/api/index.d.ts +1 -0
  31. package/dist/api/index.js +1 -0
  32. package/dist/api/query-services/index.d.ts +6 -7
  33. package/dist/api/query-services/index.js +4 -4
  34. package/dist/api/time-slot-list/index.d.ts +53 -0
  35. package/dist/api/time-slot-list/index.js +133 -0
  36. package/dist/react/core/booking/Booking.d.ts +7 -7
  37. package/dist/react/core/booking/Booking.js +5 -5
  38. package/dist/react/core/location/Location.d.ts +3 -3
  39. package/dist/react/core/location/Location.js +2 -2
  40. package/dist/react/core/service/Service.d.ts +8 -8
  41. package/dist/react/core/service-list/ServiceList.d.ts +2 -2
  42. package/dist/react/location/Location.d.ts +3 -3
  43. package/dist/react/service/Service.d.ts +9 -9
  44. package/dist/react/service/Service.js +5 -5
  45. package/dist/react/service-list/ServiceList.d.ts +3 -3
  46. package/dist/services/booking/booking.d.ts +25 -16
  47. package/dist/services/booking/booking.js +50 -16
  48. package/dist/services/index.d.ts +2 -1
  49. package/dist/services/index.js +1 -0
  50. package/dist/services/service/service.d.ts +5 -5
  51. package/dist/services/service/service.js +20 -21
  52. package/dist/services/service-list/service-list.d.ts +3 -3
  53. package/dist/services/time-slot-list/index.d.ts +6 -0
  54. package/dist/services/time-slot-list/index.js +6 -0
  55. package/dist/services/time-slot-list/time-slot-list.d.ts +58 -0
  56. package/dist/services/time-slot-list/time-slot-list.def.d.ts +84 -0
  57. package/dist/services/time-slot-list/time-slot-list.def.js +17 -0
  58. package/dist/services/time-slot-list/time-slot-list.js +349 -0
  59. package/package.json +2 -2
@@ -28,9 +28,9 @@ export function Root(props) {
28
28
  * @example
29
29
  * ```tsx
30
30
  * <Booking.Data>
31
- * {({ selectedServices }) => (
32
- * selectedServices.length > 0 ? (
33
- * <div>{selectedServices.map(s => s.service.name).join(', ')}</div>
31
+ * {({ bookingSelections }) => (
32
+ * bookingSelections.length > 0 ? (
33
+ * <div>{bookingSelections.map(s => s.service.name).join(', ')}</div>
34
34
  * ) : (
35
35
  * <div>No services selected</div>
36
36
  * )
@@ -41,10 +41,10 @@ export function Root(props) {
41
41
  export function Data(props) {
42
42
  const { children } = props;
43
43
  const bookingService = useService(BookingServiceDefinition);
44
- const selectedServices = bookingService.services.get();
44
+ const bookingSelections = bookingService.bookingSelections.get();
45
45
  const selectedTimeSlot = bookingService.timeSlot.get();
46
46
  return children({
47
- selectedServices,
47
+ bookingSelections,
48
48
  selectedTimeSlot,
49
49
  });
50
50
  }
@@ -4,7 +4,7 @@
4
4
  * Converts location data to Address component format
5
5
  */
6
6
  import React from 'react';
7
- import { services } from '@wix/bookings';
7
+ import { LocationType, type Service } from '@wix/auto_sdk_bookings_services';
8
8
  import type { AddressData as AddressDataType } from '@wix/headless-components/react';
9
9
  /**
10
10
  * Re-export AddressData type from Address component for convenience
@@ -14,14 +14,14 @@ export type AddressData = AddressDataType;
14
14
  * Location render props passed to children
15
15
  */
16
16
  export interface LocationRenderProps {
17
- locationType: services.LocationType;
17
+ locationType: LocationType;
18
18
  address: AddressData | null;
19
19
  }
20
20
  /**
21
21
  * Props for the core Location component
22
22
  */
23
23
  export interface LocationProps {
24
- location: NonNullable<services.Service['locations']>[number];
24
+ location: NonNullable<Service['locations']>[number];
25
25
  children: (props: LocationRenderProps) => React.ReactNode;
26
26
  }
27
27
  /**
@@ -3,13 +3,13 @@
3
3
  * Handles business, custom, and customer location types
4
4
  * Converts location data to Address component format
5
5
  */
6
- import { services } from '@wix/bookings';
6
+ import { LocationType } from '@wix/auto_sdk_bookings_services';
7
7
  /**
8
8
  * Parses location data into Address component format
9
9
  */
10
10
  function parseLocationAddress(location, locationType) {
11
11
  // Handle customer location specially
12
- if (locationType === services.LocationType.CUSTOMER) {
12
+ if (locationType === LocationType.CUSTOMER) {
13
13
  // For customer location, return an AddressData object with Customer's Place
14
14
  return {
15
15
  address: {
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import React from 'react';
6
6
  import { type ServiceServiceConfig } from '../../../services/service/service.js';
7
- import { services } from '@wix/bookings';
7
+ import type { Service, Payment, BookingPolicy, Schedule } from '@wix/auto_sdk_bookings_services';
8
8
  import type { MoneyData } from '@wix/headless-components/react';
9
9
  /**
10
10
  * Props for Service.Root component
@@ -22,7 +22,7 @@ export declare function Root(props: RootProps): React.ReactNode;
22
22
  */
23
23
  export interface ServiceProps {
24
24
  children: (data: {
25
- service: services.Service;
25
+ service: Service;
26
26
  isLoading: boolean;
27
27
  error: string | null;
28
28
  }) => React.ReactNode;
@@ -55,7 +55,7 @@ export interface InfoProps {
55
55
  name?: string;
56
56
  _id?: string;
57
57
  };
58
- locations?: Array<NonNullable<services.Service['locations']>[number]>;
58
+ locations?: Array<NonNullable<Service['locations']>[number]>;
59
59
  staff?: Array<{
60
60
  name?: string;
61
61
  _id?: string;
@@ -110,8 +110,8 @@ export declare function Info(props: InfoProps): React.ReactNode;
110
110
  */
111
111
  export interface PriceProps {
112
112
  children: (data: {
113
- servicePayment: services.Payment | undefined;
114
- rateType: services.Payment['rateType'] | undefined;
113
+ servicePayment: Payment | undefined;
114
+ rateType: Payment['rateType'] | undefined;
115
115
  money: MoneyData | null;
116
116
  minPrice: MoneyData | null;
117
117
  maxPrice: MoneyData | null;
@@ -151,7 +151,7 @@ export interface ActionsProps {
151
151
  select: () => void;
152
152
  add: () => void;
153
153
  remove: () => void;
154
- rawService: services.Service;
154
+ rawService: Service;
155
155
  bookable: boolean;
156
156
  selected: boolean;
157
157
  requiresAvailability: boolean;
@@ -180,7 +180,7 @@ export declare function Actions(props: ActionsProps): React.ReactNode;
180
180
  */
181
181
  export interface PolicyProps {
182
182
  children: (data: {
183
- bookingPolicy: services.BookingPolicy | null;
183
+ bookingPolicy: BookingPolicy | null;
184
184
  cancellationPolicyEnabled: boolean;
185
185
  limitLatestCancellationEnabled: boolean;
186
186
  latestCancellationInMinutes: number | undefined;
@@ -219,7 +219,7 @@ export declare function Policy(props: PolicyProps): React.ReactNode;
219
219
  */
220
220
  export interface ScheduleProps {
221
221
  children: (data: {
222
- schedule: services.Schedule | null;
222
+ schedule: Schedule | null;
223
223
  isClassOrCourse: boolean;
224
224
  }) => React.ReactNode;
225
225
  }
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import React from 'react';
6
6
  import { type ServiceListServiceConfig, type QueryOptions } from '../../../services/service-list/service-list.js';
7
- import type { services } from '@wix/bookings';
7
+ import type { Service } from '@wix/auto_sdk_bookings_services';
8
8
  import type { PagingMetadata } from '../../../api/query-services/index.js';
9
9
  /**
10
10
  * Props for ServiceList.Root component
@@ -37,7 +37,7 @@ export interface ServicesProps {
37
37
  */
38
38
  export interface ServicesRenderProps {
39
39
  /** Array of services */
40
- services: services.Service[];
40
+ services: Service[];
41
41
  /** Whether services are currently loading */
42
42
  isLoading: boolean;
43
43
  /** Error message, or null if no error */
@@ -5,7 +5,7 @@
5
5
  import React from 'react';
6
6
  import * as CoreLocation from '../core/location/Location.js';
7
7
  import { AsChildChildren } from '@wix/headless-utils/react';
8
- import type { services } from '@wix/bookings';
8
+ import { LocationType, type Service } from '@wix/auto_sdk_bookings_services';
9
9
  /**
10
10
  * Re-export AddressData type from core for convenience
11
11
  */
@@ -14,10 +14,10 @@ export type { AddressData } from '../core/location/Location.js';
14
14
  * Props for Location.Root component
15
15
  */
16
16
  export interface LocationRootProps {
17
- location: NonNullable<services.Service['locations']>[number];
17
+ location: NonNullable<Service['locations']>[number];
18
18
  asChild?: boolean;
19
19
  children?: React.ReactNode | AsChildChildren<{
20
- locationType: services.LocationType;
20
+ locationType: LocationType;
21
21
  address: CoreLocation.AddressData | null;
22
22
  }>;
23
23
  className?: string;
@@ -5,7 +5,7 @@
5
5
  import React from 'react';
6
6
  import { AsChildChildren } from '@wix/headless-utils/react';
7
7
  import { MoneyData } from '@wix/headless-components/react';
8
- import { services } from '@wix/bookings';
8
+ import { type Service, type Payment } from '@wix/auto_sdk_bookings_services';
9
9
  /**
10
10
  * Props for Service.Root component
11
11
  */
@@ -14,7 +14,7 @@ export interface ServiceRootProps {
14
14
  selected: boolean;
15
15
  bookable: boolean;
16
16
  }>;
17
- service: services.Service;
17
+ service: Service;
18
18
  appId?: string;
19
19
  asChild?: boolean;
20
20
  className?: string;
@@ -106,8 +106,8 @@ export declare const Description: React.ForwardRefExoticComponent<DescriptionPro
106
106
  export interface PriceProps {
107
107
  asChild?: boolean;
108
108
  children?: AsChildChildren<{
109
- servicePayment: services.Payment | undefined;
110
- rateType: services.Payment['rateType'] | undefined;
109
+ servicePayment: Payment | undefined;
110
+ rateType: Payment['rateType'] | undefined;
111
111
  money: MoneyData | null;
112
112
  minPrice: MoneyData | null;
113
113
  maxPrice: MoneyData | null;
@@ -327,7 +327,7 @@ export declare const Category: React.ForwardRefExoticComponent<CategoryProps & R
327
327
  /**
328
328
  * Type for location
329
329
  */
330
- type LocationType = NonNullable<services.Service['locations']>[number] & {
330
+ type LocationType = NonNullable<Service['locations']>[number] & {
331
331
  id: string;
332
332
  };
333
333
  /**
@@ -717,7 +717,7 @@ export declare const MediaItems: React.ForwardRefExoticComponent<MediaItemsProps
717
717
  export interface RawProps {
718
718
  asChild?: boolean;
719
719
  children?: AsChildChildren<{
720
- service: services.Service;
720
+ service: Service;
721
721
  isLoading: boolean;
722
722
  error: string | null;
723
723
  }>;
@@ -755,7 +755,7 @@ export declare namespace Actions {
755
755
  selected: boolean;
756
756
  requiresAvailability: boolean;
757
757
  onClick: () => void;
758
- service: services.Service;
758
+ service: Service;
759
759
  }) => React.ReactNode);
760
760
  className?: string;
761
761
  label?: string;
@@ -795,7 +795,7 @@ export declare namespace Actions {
795
795
  selected: boolean;
796
796
  requiresAvailability: boolean;
797
797
  onClick: () => void;
798
- service: services.Service;
798
+ service: Service;
799
799
  }) => React.ReactNode);
800
800
  className?: string;
801
801
  label?: string;
@@ -835,7 +835,7 @@ export declare namespace Actions {
835
835
  selected: boolean;
836
836
  requiresAvailability: boolean;
837
837
  onClick: () => void;
838
- service: services.Service;
838
+ service: Service;
839
839
  }) => React.ReactNode);
840
840
  className?: string;
841
841
  label?: string;
@@ -9,7 +9,7 @@ import { AsChildSlot } from '@wix/headless-utils/react';
9
9
  import { Money, GenericList } from '@wix/headless-components/react';
10
10
  import { WixMediaImage } from '@wix/headless-media/react';
11
11
  import { MediaGallery } from '@wix/headless-media/react';
12
- import { services } from '@wix/bookings';
12
+ import { RateType, } from '@wix/auto_sdk_bookings_services';
13
13
  import * as Location from '../location/Location.js';
14
14
  var TestIds;
15
15
  (function (TestIds) {
@@ -160,17 +160,17 @@ export const Price = React.forwardRef((props, ref) => {
160
160
  // Default rendering based on rate type
161
161
  const renderDefaultPrice = () => {
162
162
  switch (rateType) {
163
- case services.RateType.FIXED:
163
+ case RateType.FIXED:
164
164
  return money ? (_jsx(Money, { money: money, className: className })) : null;
165
- case services.RateType.VARIED:
165
+ case RateType.VARIED:
166
166
  if (minPrice && maxPrice) {
167
167
  return (_jsxs("span", { className: className, "data-testid": TestIds.servicePrice, children: [_jsx(Money, { money: minPrice }), " - ", _jsx(Money, { money: maxPrice })] }));
168
168
  }
169
169
  // Fallback to defaultPrice if min/max not available
170
170
  return money ? (_jsx(Money, { money: money, className: className })) : null;
171
- case services.RateType.CUSTOM:
171
+ case RateType.CUSTOM:
172
172
  return priceDescription ? (_jsx("span", { className: className, "data-testid": TestIds.servicePrice, children: priceDescription })) : null;
173
- case services.RateType.NO_FEE:
173
+ case RateType.NO_FEE:
174
174
  return money ? (_jsx(Money, { money: money, className: className })) : null;
175
175
  default:
176
176
  // UNKNOWN_RATE_TYPE or undefined
@@ -6,7 +6,7 @@ import React from 'react';
6
6
  import { ListVariant, GenericListLoadMoreRenderProps } from '@wix/headless-components/react';
7
7
  import { AsChildChildren } from '@wix/headless-utils/react';
8
8
  import type { ServiceListServiceConfig } from '../../services/service-list/service-list.js';
9
- import type { services } from '@wix/bookings';
9
+ import type { Service as ServiceType } from '@wix/auto_sdk_bookings_services';
10
10
  /**
11
11
  * Props for the ServiceList root component
12
12
  */
@@ -79,7 +79,7 @@ export type ServiceRootChildren = AsChildChildren<{
79
79
  * Supports both ReactNode and function children that receive { selected, bookable }
80
80
  */
81
81
  export interface ServiceItemWrapperProps {
82
- item: services.Service;
82
+ item: ServiceType;
83
83
  index?: number;
84
84
  /** Children can be ReactNode or a function that receives { selected, bookable } from Service.Root */
85
85
  children: React.ReactNode | ServiceRootChildren;
@@ -89,7 +89,7 @@ export interface ServiceItemWrapperProps {
89
89
  * Provides items array and itemWrapper function for custom rendering
90
90
  */
91
91
  export interface ServiceRepeaterRenderProps {
92
- items: services.Service[];
92
+ items: ServiceType[];
93
93
  variant?: ListVariant;
94
94
  /** Wraps each item in Service.Root - children can be ReactNode or function receiving { selected, bookable } */
95
95
  itemWrapper: (props: ServiceItemWrapperProps) => React.ReactNode;
@@ -4,15 +4,20 @@
4
4
  * Persists across page navigation in SPA until page refresh
5
5
  */
6
6
  import { type Signal } from '@wix/services-definitions/core-services/signals';
7
- import type { services, availabilityTimeSlots } from '@wix/bookings';
7
+ import type { Service } from '@wix/auto_sdk_bookings_services';
8
+ import type { TimeSlot, Resource, NestedTimeSlot } from '@wix/auto_sdk_bookings_availability-time-slots';
8
9
  import type { FormValues } from '@wix/form-public';
9
10
  /**
10
- * ServiceSelection contains the service AND its related selections
11
+ * BookingSelection contains the service AND its related selections
11
12
  */
12
- export interface ServiceSelection {
13
- service: services.Service;
13
+ export interface BookingSelection {
14
+ /** Unique identifier for this booking instance (allows same service multiple times) */
15
+ instanceId: string;
16
+ service: Service;
14
17
  /** Selected resources (staff members, rooms, etc.) */
15
- resources?: availabilityTimeSlots.Resource[];
18
+ staff?: Resource;
19
+ /** Per-service slot data from nested slots (for multi-service bookings) */
20
+ nestedSlotData?: NestedTimeSlot;
16
21
  }
17
22
  export interface Location {
18
23
  id: string;
@@ -22,12 +27,16 @@ export interface Location {
22
27
  * BookingService actions - setters only, no API calls
23
28
  */
24
29
  export interface BookingServiceActions {
25
- setServices(services: ServiceSelection[]): void;
26
- addService(service: ServiceSelection): void;
27
- updateService(serviceId: string, updates: Partial<ServiceSelection>): void;
28
- removeService(serviceId: string): void;
30
+ /** Clears all booking selections and sets a single service (instanceId is auto-generated) */
31
+ setService(service: Omit<BookingSelection, 'instanceId'>): string;
32
+ /** Adds a service and returns the generated instanceId */
33
+ addService(service: Omit<BookingSelection, 'instanceId'>): string;
34
+ /** Updates a booking selection. If no instanceId provided, updates the first selection. */
35
+ updateBookingSelection(updates: Partial<Omit<BookingSelection, 'instanceId'>>, instanceId?: string): void;
36
+ /** Removes a booking selection. If no instanceId provided, removes the first selection. */
37
+ removeBookingSelection(instanceId?: string): void;
29
38
  clearServices(): void;
30
- setTimeSlot(slot: availabilityTimeSlots.TimeSlot | null): void;
39
+ setTimeSlot(slot: TimeSlot | null): void;
31
40
  clearTimeSlot(): void;
32
41
  setLocation(location: Location | null): void;
33
42
  clearLocation(): void;
@@ -40,10 +49,10 @@ export interface BookingServiceActions {
40
49
  * Pure state management - no API calls
41
50
  */
42
51
  export interface BookingService {
43
- /** Signal containing the currently selected services with their selections */
44
- services: Signal<ServiceSelection[]>;
52
+ /** Signal containing the booking selections (services with their related data) */
53
+ bookingSelections: Signal<BookingSelection[]>;
45
54
  /** Signal containing the currently selected time slot */
46
- timeSlot: Signal<availabilityTimeSlots.TimeSlot | null>;
55
+ timeSlot: Signal<TimeSlot | null>;
47
56
  /** Signal containing the selected location (derived from timeSlot) */
48
57
  location: Signal<Location | null>;
49
58
  /** Signal containing the form values */
@@ -64,10 +73,10 @@ export declare const BookingServiceDefinition: string & {
64
73
  * Note: location is NOT in config - it's derived internally from timeSlot
65
74
  */
66
75
  export interface BookingServiceConfig {
67
- /** Optional initial services to pre-populate */
68
- initialServices?: ServiceSelection[];
76
+ /** Optional initial booking selections to pre-populate */
77
+ initialBookingSelections?: BookingSelection[];
69
78
  /** Optional initial time slot to pre-populate */
70
- initialTimeSlot?: availabilityTimeSlots.TimeSlot | null;
79
+ initialTimeSlot?: TimeSlot | null;
71
80
  /** Optional initial form values */
72
81
  initialFormValues?: FormValues | null;
73
82
  }
@@ -5,6 +5,15 @@
5
5
  */
6
6
  import { defineService, implementService } from '@wix/services-definitions';
7
7
  import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
8
+ // ============================================================================
9
+ // Types
10
+ // ============================================================================
11
+ /**
12
+ * Generates a unique instance ID for service selections
13
+ */
14
+ function generateInstanceId() {
15
+ return crypto.randomUUID();
16
+ }
8
17
  /**
9
18
  * Service definition for Booking
10
19
  */
@@ -39,7 +48,12 @@ export const BookingServiceDefinition = defineService('booking');
39
48
  export const BookingService = implementService.withConfig()(BookingServiceDefinition, ({ getService, config }) => {
40
49
  const signalsService = getService(SignalsServiceDefinition);
41
50
  // Initialize signals with config values
42
- const servicesSignal = signalsService.signal(config.initialServices || []);
51
+ // Ensure all initial booking selections have instanceIds
52
+ const initialSelectionsWithIds = (config.initialBookingSelections || []).map((s) => ({
53
+ ...s,
54
+ instanceId: s.instanceId || generateInstanceId(),
55
+ }));
56
+ const bookingSelectionsSignal = signalsService.signal(initialSelectionsWithIds);
43
57
  const timeSlotSignal = signalsService.signal(config.initialTimeSlot || null);
44
58
  // Location is derived internally - initialize as null
45
59
  const locationSignal = signalsService.signal(null);
@@ -49,25 +63,45 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
49
63
  // ========================================================================
50
64
  const actions = {
51
65
  // Services actions
52
- setServices(newServices) {
53
- servicesSignal.set(newServices);
66
+ setService(service) {
67
+ const instanceId = generateInstanceId();
68
+ const newSelection = {
69
+ ...service,
70
+ instanceId,
71
+ };
72
+ bookingSelectionsSignal.set([newSelection]);
73
+ return instanceId;
54
74
  },
55
75
  addService(service) {
56
- const current = servicesSignal.get();
57
- servicesSignal.set([...current, service]);
76
+ const instanceId = generateInstanceId();
77
+ const current = bookingSelectionsSignal.get();
78
+ const newSelection = {
79
+ ...service,
80
+ instanceId,
81
+ };
82
+ bookingSelectionsSignal.set([...current, newSelection]);
83
+ return instanceId;
58
84
  },
59
- updateService(serviceId, updates) {
60
- const current = servicesSignal.get();
61
- const updated = current.map((s) => s.service._id === serviceId ? { ...s, ...updates } : s);
62
- servicesSignal.set(updated);
85
+ updateBookingSelection(updates, instanceId) {
86
+ const current = bookingSelectionsSignal.get();
87
+ // If no instanceId provided, update the first selection (index 0)
88
+ const targetId = instanceId ?? current[0]?.instanceId;
89
+ const updated = current.map((s) => s.instanceId === targetId ? { ...s, ...updates } : s);
90
+ bookingSelectionsSignal.set(updated);
63
91
  },
64
- removeService(serviceId) {
65
- const current = servicesSignal.get();
66
- const filtered = current.filter((s) => s.service._id !== serviceId);
67
- servicesSignal.set(filtered);
92
+ removeBookingSelection(instanceId) {
93
+ const current = bookingSelectionsSignal.get();
94
+ if (!instanceId) {
95
+ // Remove first selection if no instanceId provided
96
+ bookingSelectionsSignal.set(current.slice(1));
97
+ }
98
+ else {
99
+ const filtered = current.filter((s) => s.instanceId !== instanceId);
100
+ bookingSelectionsSignal.set(filtered);
101
+ }
68
102
  },
69
103
  clearServices() {
70
- servicesSignal.set([]);
104
+ bookingSelectionsSignal.set([]);
71
105
  },
72
106
  // Time Slot actions
73
107
  setTimeSlot(slot) {
@@ -92,14 +126,14 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
92
126
  },
93
127
  // Clear all
94
128
  clearAll() {
95
- servicesSignal.set([]);
129
+ bookingSelectionsSignal.set([]);
96
130
  timeSlotSignal.set(null);
97
131
  locationSignal.set(null);
98
132
  formValuesSignal.set(null);
99
133
  },
100
134
  };
101
135
  return {
102
- services: servicesSignal,
136
+ bookingSelections: bookingSelectionsSignal,
103
137
  timeSlot: timeSlotSignal,
104
138
  location: locationSignal,
105
139
  formValues: formValuesSignal,
@@ -3,5 +3,6 @@
3
3
  * Main export file for all service definitions and implementations
4
4
  */
5
5
  export { ServiceService, ServiceServiceDefinition, type ServiceServiceAPI, type ServiceServiceConfig, type ServiceActions, type ServicePaymentData, loadServiceServiceInitialData, type SuccessServiceServiceConfigResult, type NotFoundServiceServiceConfigResult, } from './service/service.js';
6
- export { BookingService, BookingServiceDefinition, type BookingServiceConfig, type ServiceSelection, type Location, type BookingServiceActions, } from './booking/booking.js';
6
+ export { BookingService, BookingServiceDefinition, type BookingServiceConfig, type BookingSelection, type Location, type BookingServiceActions, } from './booking/booking.js';
7
+ export { TimeSlotListService, TimeSlotListServiceDefinition, ViewMode, loadTimeSlotListConfig, type TimeSlotListServiceAPI, type TimeSlotListServiceActions, type TimeSlotListServiceConfig, type SlotSelection, type LoadTimeSlotListConfigOptions, type LoadTimeSlotListConfigResult, } from './time-slot-list/index.js';
7
8
  export { ServiceListService, ServiceListServiceDefinition, type ServiceListServiceAPI, type ServiceListServiceConfig, type ServiceListActions, type QueryOptions, loadServiceListServiceInitialData, type SuccessServiceListServiceConfigResult, type ErrorServiceListServiceConfigResult, } from './service-list/service-list.js';
@@ -4,4 +4,5 @@
4
4
  */
5
5
  export { ServiceService, ServiceServiceDefinition, loadServiceServiceInitialData, } from './service/service.js';
6
6
  export { BookingService, BookingServiceDefinition, } from './booking/booking.js';
7
+ export { TimeSlotListService, TimeSlotListServiceDefinition, ViewMode, loadTimeSlotListConfig, } from './time-slot-list/index.js';
7
8
  export { ServiceListService, ServiceListServiceDefinition, loadServiceListServiceInitialData, } from './service-list/service-list.js';
@@ -3,7 +3,7 @@
3
3
  * Handles loading and managing a single service's data, loading state, and errors.
4
4
  */
5
5
  import { type Signal, type ReadOnlySignal } from '@wix/services-definitions/core-services/signals';
6
- import { services } from '@wix/bookings';
6
+ import { type Service, type Payment } from '@wix/auto_sdk_bookings_services';
7
7
  import type { MoneyData } from '@wix/headless-components/react';
8
8
  /**
9
9
  * Actions object for service selection
@@ -23,9 +23,9 @@ export interface ServiceActions {
23
23
  */
24
24
  export interface ServicePaymentData {
25
25
  /** The service payment information from the service */
26
- servicePayment: services.Payment | undefined;
26
+ servicePayment: Payment | undefined;
27
27
  /** The rate type of the service (FIXED, VARIED, CUSTOM, NO_FEE, etc.) */
28
- rateType: services.Payment['rateType'] | undefined;
28
+ rateType: Payment['rateType'] | undefined;
29
29
  /** Primary price (used for FIXED or VARIED default) */
30
30
  money: MoneyData | null;
31
31
  /** Minimum price (used for VARIED) */
@@ -46,7 +46,7 @@ export interface ServicePaymentData {
46
46
  */
47
47
  export interface ServiceServiceAPI {
48
48
  /** Reactive signal containing the current service data */
49
- serviceSignal: Signal<services.Service>;
49
+ serviceSignal: Signal<Service>;
50
50
  /** Reactive signal indicating if a service is currently being loaded */
51
51
  isLoadingSignal: Signal<boolean>;
52
52
  /** Reactive signal containing any error message, or null if no error */
@@ -83,7 +83,7 @@ export declare const ServiceServiceDefinition: string & {
83
83
  */
84
84
  export interface ServiceServiceConfig {
85
85
  /** The initial service data to configure the service with */
86
- service?: services.Service;
86
+ service?: Service;
87
87
  /** The service ID to load if no initial service is provided */
88
88
  serviceId?: string;
89
89
  /** The service slug to load if no initial service is provided */
@@ -4,9 +4,9 @@
4
4
  */
5
5
  import { defineService, implementService } from '@wix/services-definitions';
6
6
  import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
7
- import { services } from '@wix/bookings';
7
+ import { ServiceType, RateType, } from '@wix/auto_sdk_bookings_services';
8
8
  import { getServiceById, getServiceBySlug, } from '../../api/query-services/index.js';
9
- import { BookingServiceDefinition, } from '../booking/booking.js';
9
+ import { BookingServiceDefinition } from '../booking/booking.js';
10
10
  import { convertToMoneyData } from '../../utils/money.js';
11
11
  /**
12
12
  * Booking app ID constant
@@ -81,15 +81,15 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
81
81
  const currentService = serviceSignal.get();
82
82
  if (!currentService._id)
83
83
  return false;
84
- const services = bookingService.services.get();
85
- return services.some((selection) => selection.service._id === currentService._id);
84
+ const selections = bookingService.bookingSelections.get();
85
+ return selections.some((selection) => selection.service._id === currentService._id);
86
86
  });
87
87
  // requiresAvailability signal - true for APPOINTMENT and CLASS types
88
88
  const requiresAvailabilitySignal = signalsService.computed(() => {
89
89
  const currentService = serviceSignal.get();
90
90
  const serviceType = currentService.type;
91
- return (serviceType === services.ServiceType.APPOINTMENT ||
92
- serviceType === services.ServiceType.CLASS);
91
+ return (serviceType === ServiceType.APPOINTMENT ||
92
+ serviceType === ServiceType.CLASS);
93
93
  });
94
94
  // paymentData signal - computed payment data from service
95
95
  const paymentDataSignal = signalsService.computed(() => {
@@ -104,21 +104,21 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
104
104
  // Extract pricing based on rate type
105
105
  if (payment) {
106
106
  switch (rateType) {
107
- case services.RateType.FIXED:
107
+ case RateType.FIXED:
108
108
  // FIXED: Use payment.fixed.price
109
109
  money = convertToMoneyData(payment.fixed?.price);
110
110
  break;
111
- case services.RateType.VARIED:
111
+ case RateType.VARIED:
112
112
  // VARIED: Use defaultPrice as money, plus min/max for range
113
113
  money = convertToMoneyData(payment.varied?.defaultPrice);
114
114
  minPrice = convertToMoneyData(payment.varied?.minPrice);
115
115
  maxPrice = convertToMoneyData(payment.varied?.maxPrice);
116
116
  break;
117
- case services.RateType.CUSTOM:
117
+ case RateType.CUSTOM:
118
118
  // CUSTOM: Use description text (no numeric price)
119
119
  priceDescription = payment.custom?.description || null;
120
120
  break;
121
- case services.RateType.NO_FEE:
121
+ case RateType.NO_FEE:
122
122
  // NO_FEE: Free service (amount = 0)
123
123
  money = { amount: 0, currency: 'USD' };
124
124
  break;
@@ -185,27 +185,26 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
185
185
  if (!bookableSignal.get() || !bookingService)
186
186
  return;
187
187
  const currentService = serviceSignal.get();
188
- const selection = {
189
- service: currentService,
190
- };
191
- bookingService.actions.setServices([selection]);
188
+ bookingService.actions.setService({ service: currentService });
192
189
  },
193
190
  add: () => {
194
191
  if (!bookableSignal.get() || !bookingService)
195
192
  return;
196
193
  const currentService = serviceSignal.get();
197
- const selection = {
198
- service: currentService,
199
- };
200
- bookingService.actions.addService(selection);
194
+ bookingService.actions.addService({ service: currentService });
201
195
  },
202
196
  remove: () => {
203
197
  if (!bookableSignal.get() || !bookingService)
204
198
  return;
205
199
  const currentService = serviceSignal.get();
206
- if (currentService._id) {
207
- bookingService.actions.removeService(currentService._id);
208
- }
200
+ // Remove all instances of this service (by serviceId)
201
+ const selections = bookingService.bookingSelections.get();
202
+ const instancesToRemove = selections
203
+ .filter((s) => s.service._id === currentService._id)
204
+ .map((s) => s.instanceId);
205
+ instancesToRemove.forEach((instanceId) => {
206
+ bookingService.actions.removeBookingSelection(instanceId);
207
+ });
209
208
  },
210
209
  };
211
210
  return {