@wix/headless-bookings 0.0.17 → 0.0.19

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.
@@ -3,7 +3,7 @@
3
3
  * Provides low-level access to BookingService via render props and service setup
4
4
  */
5
5
  import React from 'react';
6
- import { type BookingServiceConfig, type BookingItem, type Location, type BookingServiceActions } from '../../../services/booking/booking.js';
6
+ import { type BookingServiceConfig, type ServiceSelection, type Location, type BookingServiceActions } from '../../../services/booking/booking.js';
7
7
  import type { FormValues } from '@wix/form-public';
8
8
  /**
9
9
  * Props for Booking.Root component
@@ -33,10 +33,9 @@ export declare function Root(props: RootProps): React.ReactNode;
33
33
  * Mirrors BookingServiceConfig structure with actions
34
34
  */
35
35
  export interface BookingData {
36
- bookingItems: BookingItem[];
36
+ serviceSelections: ServiceSelection[];
37
37
  location: Location | null;
38
- formValues: FormValues | null;
39
- numberOfParticipants: number;
38
+ formSubmission: FormValues | null;
40
39
  actions: BookingServiceActions;
41
40
  }
42
41
  /**
@@ -53,9 +52,9 @@ export interface DataProps {
53
52
  * @example
54
53
  * ```tsx
55
54
  * <Booking.Data>
56
- * {({ bookingItems, location, formValues, numberOfParticipants, actions }) => (
57
- * bookingItems.length > 0 ? (
58
- * <div>{bookingItems.map(item => item.service.name).join(', ')}</div>
55
+ * {({ serviceSelections, location, formSubmission, actions }) => (
56
+ * serviceSelections.length > 0 ? (
57
+ * <div>{serviceSelections.map(item => item.service.name).join(', ')}</div>
59
58
  * ) : (
60
59
  * <div>No services selected</div>
61
60
  * )
@@ -28,9 +28,9 @@ export function Root(props) {
28
28
  * @example
29
29
  * ```tsx
30
30
  * <Booking.Data>
31
- * {({ bookingItems, location, formValues, numberOfParticipants, actions }) => (
32
- * bookingItems.length > 0 ? (
33
- * <div>{bookingItems.map(item => item.service.name).join(', ')}</div>
31
+ * {({ serviceSelections, location, formSubmission, actions }) => (
32
+ * serviceSelections.length > 0 ? (
33
+ * <div>{serviceSelections.map(item => item.service.name).join(', ')}</div>
34
34
  * ) : (
35
35
  * <div>No services selected</div>
36
36
  * )
@@ -41,16 +41,14 @@ export function Root(props) {
41
41
  export function Data(props) {
42
42
  const { children } = props;
43
43
  const bookingService = useService(BookingServiceDefinition);
44
- const bookingItems = bookingService.bookingItems.get();
44
+ const serviceSelections = bookingService.serviceSelections.get();
45
45
  const location = bookingService.location.get();
46
- const formValues = bookingService.formValues.get();
47
- const numberOfParticipants = bookingService.numberOfParticipants.get();
46
+ const formSubmission = bookingService.formSubmission.get();
48
47
  const { actions } = bookingService;
49
48
  return children({
50
- bookingItems,
49
+ serviceSelections,
51
50
  location,
52
- formValues,
53
- numberOfParticipants,
51
+ formSubmission,
54
52
  actions,
55
53
  });
56
54
  }
@@ -77,7 +77,7 @@ Root.displayName = 'TimeSlotList.Root';
77
77
  */
78
78
  const RootContent = React.forwardRef((props, ref) => {
79
79
  const { children, className, variant } = props;
80
- return (_jsx(CoreTimeSlotList.ListData, { children: ({ timeSlots, hasMore, isLoading, loadMore }) => (_jsx(GenericList.Root, { items: timeSlots, loadMore: loadMore, hasMore: hasMore, isLoading: isLoading, className: className, ref: ref, "data-testid": TestIds.timeSlotListRoot, variant: variant, children: children })) }));
80
+ return (_jsx(CoreTimeSlotList.ListData, { children: ({ timeSlots, hasMore, isLoading, error, loadMore }) => (_jsx(GenericList.Root, { items: timeSlots, loadMore: loadMore, hasMore: hasMore, isLoading: isLoading, error: error, className: className, ref: ref, "data-testid": TestIds.timeSlotListRoot, variant: variant, children: children })) }));
81
81
  });
82
82
  RootContent.displayName = 'TimeSlotList.RootContent';
83
83
  /**
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Booking Service - Global booking store
3
- * Manages booking flow state (selected services, time slot, location, form values)
3
+ * Manages booking flow state (selected services, time slot, location, form submission)
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';
@@ -8,9 +8,9 @@ import type { Service } from '@wix/auto_sdk_bookings_services';
8
8
  import type { Resource, EventInfo } from '@wix/auto_sdk_bookings_availability-time-slots';
9
9
  import type { FormValues } from '@wix/form-public';
10
10
  /**
11
- * Minimal time slot data for booking items
11
+ * Minimal time slot data for service selections
12
12
  */
13
- export interface BookingItemTimeSlot {
13
+ export interface ServiceSelectionTimeSlot {
14
14
  startDate: string;
15
15
  endDate: string;
16
16
  totalCapacity?: number;
@@ -19,9 +19,9 @@ export interface BookingItemTimeSlot {
19
19
  eventInfo?: EventInfo;
20
20
  }
21
21
  /**
22
- * BookingItem contains the service AND its related selections
22
+ * ServiceSelection contains the service AND its related selections
23
23
  */
24
- export interface BookingItem {
24
+ export interface ServiceSelection {
25
25
  /** Unique identifier for this booking instance (allows same service multiple times) */
26
26
  instanceId: string;
27
27
  /** The selected service */
@@ -29,7 +29,9 @@ export interface BookingItem {
29
29
  /** Selected resources (staff members, rooms, etc.) */
30
30
  resources: Resource[];
31
31
  /** Per-item time slot data */
32
- timeSlot?: BookingItemTimeSlot;
32
+ timeSlot?: ServiceSelectionTimeSlot;
33
+ /** Number of participants for this service selection */
34
+ totalParticipants?: number;
33
35
  }
34
36
  export interface Location {
35
37
  id: string;
@@ -39,25 +41,24 @@ export interface Location {
39
41
  * BookingService actions - setters only, no API calls
40
42
  */
41
43
  export interface BookingServiceActions {
42
- /** Clears all booking items and sets a single item (instanceId is auto-generated) */
43
- setItem(item: Omit<BookingItem, 'instanceId'>): string;
44
+ /** Clears all service selections and sets a single item (instanceId is auto-generated) */
45
+ setItem(item: Omit<ServiceSelection, 'instanceId'>): string;
44
46
  /** Adds an item and returns the generated instanceId */
45
- addItem(item: Omit<BookingItem, 'instanceId'>): string;
46
- /** Updates a booking item. If no instanceId provided, updates the first item. */
47
- updateItem(updates: Partial<Omit<BookingItem, 'instanceId'>>, instanceId?: string): void;
48
- /** Removes a booking item. If no instanceId provided, removes the first item. */
47
+ addItem(item: Omit<ServiceSelection, 'instanceId'>): string;
48
+ /** Updates a service selection. If no instanceId provided, updates the first item. */
49
+ updateItem(updates: Partial<Omit<ServiceSelection, 'instanceId'>>, instanceId?: string): void;
50
+ /** Removes a service selection. If no instanceId provided, removes the first item. */
49
51
  removeItem(instanceId?: string): void;
50
- /** Clears all booking items */
52
+ /** Clears all service selections */
51
53
  clearItems(): void;
52
- /** Sets a resource by ID within a booking item. If no instanceId provided, uses the first item. */
54
+ /** Sets a resource by ID within a service selection. If no instanceId provided, uses the first item. */
53
55
  setResourceById(resourceId: string, resource: Resource, instanceId?: string): void;
54
- /** Gets a resource by ID from a booking item. If no instanceId provided, uses the first item. */
56
+ /** Gets a resource by ID from a service selection. If no instanceId provided, uses the first item. */
55
57
  getResourceById(resourceId: string, instanceId?: string): Resource | undefined;
56
58
  setLocation(location: Location | null): void;
57
59
  clearLocation(): void;
58
- setFormValues(values: FormValues | null): void;
59
- clearFormValues(): void;
60
- setNumberOfParticipants(count: number): void;
60
+ setFormSubmission(values: FormValues | null): void;
61
+ clearFormSubmission(): void;
61
62
  clearAll(): void;
62
63
  }
63
64
  /**
@@ -65,14 +66,12 @@ export interface BookingServiceActions {
65
66
  * Pure state management - no API calls
66
67
  */
67
68
  export interface BookingService {
68
- /** Signal containing the booking items (services with their related data) */
69
- bookingItems: Signal<BookingItem[]>;
69
+ /** Signal containing the service selections (services with their related data) */
70
+ serviceSelections: Signal<ServiceSelection[]>;
70
71
  /** Signal containing the selected location */
71
72
  location: Signal<Location | null>;
72
- /** Signal containing the form values */
73
- formValues: Signal<FormValues | null>;
74
- /** Signal containing the number of participants */
75
- numberOfParticipants: Signal<number>;
73
+ /** Signal containing the form submission */
74
+ formSubmission: Signal<FormValues | null>;
76
75
  /** Actions for modifying booking state */
77
76
  actions: BookingServiceActions;
78
77
  }
@@ -89,14 +88,12 @@ export declare const BookingServiceDefinition: string & {
89
88
  * Mirrors BookingService structure (without actions and Signal wrappers)
90
89
  */
91
90
  export interface BookingServiceConfig {
92
- /** Optional initial booking items to pre-populate */
93
- bookingItems?: BookingItem[];
91
+ /** Optional initial service selections to pre-populate */
92
+ serviceSelections?: ServiceSelection[];
94
93
  /** Optional initial location */
95
94
  location?: Location | null;
96
- /** Optional initial form values */
97
- formValues?: FormValues | null;
98
- /** Optional initial number of participants (defaults to 1) */
99
- numberOfParticipants?: number;
95
+ /** Optional initial form submission */
96
+ formSubmission?: FormValues | null;
100
97
  }
101
98
  /**
102
99
  * Implementation of BookingService
@@ -116,8 +113,8 @@ export interface BookingServiceConfig {
116
113
  *
117
114
  * // In any page - access booking data
118
115
  * <Booking.Data>
119
- * {({ bookingItems, location, formValues, actions }) => (
120
- * <div>{bookingItems.map(item => item.service.name).join(', ')}</div>
116
+ * {({ serviceSelections, location, formSubmission, actions }) => (
117
+ * <div>{serviceSelections.map(item => item.service.name).join(', ')}</div>
121
118
  * )}
122
119
  * </Booking.Data>
123
120
  * ```
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Booking Service - Global booking store
3
- * Manages booking flow state (selected services, time slot, location, form values)
3
+ * Manages booking flow state (selected services, time slot, location, form submission)
4
4
  * Persists across page navigation in SPA until page refresh
5
5
  */
6
6
  import { defineService, implementService } from '@wix/services-definitions';
@@ -9,7 +9,7 @@ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-servic
9
9
  // Types
10
10
  // ============================================================================
11
11
  /**
12
- * Generates a unique instance ID for booking items
12
+ * Generates a unique instance ID for service selections
13
13
  */
14
14
  function generateInstanceId() {
15
15
  return crypto.randomUUID();
@@ -39,8 +39,8 @@ export const BookingServiceDefinition = defineService('booking');
39
39
  *
40
40
  * // In any page - access booking data
41
41
  * <Booking.Data>
42
- * {({ bookingItems, location, formValues, actions }) => (
43
- * <div>{bookingItems.map(item => item.service.name).join(', ')}</div>
42
+ * {({ serviceSelections, location, formSubmission, actions }) => (
43
+ * <div>{serviceSelections.map(item => item.service.name).join(', ')}</div>
44
44
  * )}
45
45
  * </Booking.Data>
46
46
  * ```
@@ -48,15 +48,14 @@ export const BookingServiceDefinition = defineService('booking');
48
48
  export const BookingService = implementService.withConfig()(BookingServiceDefinition, ({ getService, config }) => {
49
49
  const signalsService = getService(SignalsServiceDefinition);
50
50
  // Initialize signals with config values
51
- // Ensure all initial booking items have instanceIds
52
- const initialItemsWithIds = (config.bookingItems || []).map((item) => ({
51
+ // Ensure all initial service selections have instanceIds
52
+ const initialItemsWithIds = (config.serviceSelections || []).map((item) => ({
53
53
  ...item,
54
54
  instanceId: item.instanceId || generateInstanceId(),
55
55
  }));
56
- const bookingItemsSignal = signalsService.signal(initialItemsWithIds);
56
+ const serviceSelectionsSignal = signalsService.signal(initialItemsWithIds);
57
57
  const locationSignal = signalsService.signal(config.location || null);
58
- const formValuesSignal = signalsService.signal(config.formValues || null);
59
- const numberOfParticipantsSignal = signalsService.signal(config.numberOfParticipants ?? 1);
58
+ const formSubmissionSignal = signalsService.signal(config.formSubmission || null);
60
59
  // ========================================================================
61
60
  // Actions Implementation
62
61
  // ========================================================================
@@ -68,43 +67,43 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
68
67
  ...item,
69
68
  instanceId,
70
69
  };
71
- bookingItemsSignal.set([newItem]);
70
+ serviceSelectionsSignal.set([newItem]);
72
71
  return instanceId;
73
72
  },
74
73
  addItem(item) {
75
74
  const instanceId = generateInstanceId();
76
- const current = bookingItemsSignal.get();
75
+ const current = serviceSelectionsSignal.get();
77
76
  const newItem = {
78
77
  ...item,
79
78
  instanceId,
80
79
  };
81
- bookingItemsSignal.set([...current, newItem]);
80
+ serviceSelectionsSignal.set([...current, newItem]);
82
81
  return instanceId;
83
82
  },
84
83
  updateItem(updates, instanceId) {
85
- const current = bookingItemsSignal.get();
84
+ const current = serviceSelectionsSignal.get();
86
85
  // If no instanceId provided, update the first item (index 0)
87
86
  const targetId = instanceId ?? current[0]?.instanceId;
88
87
  const updated = current.map((item) => item.instanceId === targetId ? { ...item, ...updates } : item);
89
- bookingItemsSignal.set(updated);
88
+ serviceSelectionsSignal.set(updated);
90
89
  },
91
90
  removeItem(instanceId) {
92
- const current = bookingItemsSignal.get();
91
+ const current = serviceSelectionsSignal.get();
93
92
  if (!instanceId) {
94
93
  // Remove first item if no instanceId provided
95
- bookingItemsSignal.set(current.slice(1));
94
+ serviceSelectionsSignal.set(current.slice(1));
96
95
  }
97
96
  else {
98
97
  const filtered = current.filter((item) => item.instanceId !== instanceId);
99
- bookingItemsSignal.set(filtered);
98
+ serviceSelectionsSignal.set(filtered);
100
99
  }
101
100
  },
102
101
  clearItems() {
103
- bookingItemsSignal.set([]);
102
+ serviceSelectionsSignal.set([]);
104
103
  },
105
104
  // Resource helpers
106
105
  setResourceById(resourceId, resource, instanceId) {
107
- const current = bookingItemsSignal.get();
106
+ const current = serviceSelectionsSignal.get();
108
107
  // If no instanceId provided, use the first item
109
108
  const targetId = instanceId ?? current[0]?.instanceId;
110
109
  if (!targetId)
@@ -123,10 +122,10 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
123
122
  }
124
123
  return { ...item, resources: newResources };
125
124
  });
126
- bookingItemsSignal.set(updated);
125
+ serviceSelectionsSignal.set(updated);
127
126
  },
128
127
  getResourceById(resourceId, instanceId) {
129
- const current = bookingItemsSignal.get();
128
+ const current = serviceSelectionsSignal.get();
130
129
  // If no instanceId provided, use the first item
131
130
  const targetId = instanceId ?? current[0]?.instanceId;
132
131
  if (!targetId)
@@ -143,30 +142,24 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
143
142
  clearLocation() {
144
143
  locationSignal.set(null);
145
144
  },
146
- // Form Values actions
147
- setFormValues(values) {
148
- formValuesSignal.set(values);
145
+ // Form Submission actions
146
+ setFormSubmission(values) {
147
+ formSubmissionSignal.set(values);
149
148
  },
150
- clearFormValues() {
151
- formValuesSignal.set(null);
152
- },
153
- // Number of Participants actions
154
- setNumberOfParticipants(count) {
155
- numberOfParticipantsSignal.set(count);
149
+ clearFormSubmission() {
150
+ formSubmissionSignal.set(null);
156
151
  },
157
152
  // Clear all
158
153
  clearAll() {
159
- bookingItemsSignal.set([]);
154
+ serviceSelectionsSignal.set([]);
160
155
  locationSignal.set(null);
161
- formValuesSignal.set(null);
162
- numberOfParticipantsSignal.set(1);
156
+ formSubmissionSignal.set(null);
163
157
  },
164
158
  };
165
159
  return {
166
- bookingItems: bookingItemsSignal,
160
+ serviceSelections: serviceSelectionsSignal,
167
161
  location: locationSignal,
168
- formValues: formValuesSignal,
169
- numberOfParticipants: numberOfParticipantsSignal,
162
+ formSubmission: formSubmissionSignal,
170
163
  actions,
171
164
  };
172
165
  });
@@ -3,6 +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 Location, type BookingServiceActions, } from './booking/booking.js';
6
+ export { BookingService, BookingServiceDefinition, type BookingServiceConfig, type Location, type BookingServiceActions, type ServiceSelection, type ServiceSelectionTimeSlot, } from './booking/booking.js';
7
7
  export { TimeSlotListService, TimeSlotListServiceDefinition, ViewMode, loadTimeSlotListConfig, type TimeSlotListServiceAPI, type TimeSlotListServiceActions, type TimeSlotListServiceConfig, type SlotSelection, type TimeSlot, type LoadTimeSlotListConfigOptions, type LoadTimeSlotListConfigResult, } from './time-slot-list/index.js';
8
8
  export { ServiceListService, ServiceListServiceDefinition, type ServiceListServiceAPI, type ServiceListServiceConfig, type ServiceListFilters, type ServiceListActions, type QueryOptions, loadServiceListServiceInitialData, type SuccessServiceListServiceConfigResult, type ErrorServiceListServiceConfigResult, } from './service-list/service-list.js';
@@ -81,8 +81,8 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
81
81
  const currentService = serviceSignal.get();
82
82
  if (!currentService._id)
83
83
  return false;
84
- const bookingItems = bookingService.bookingItems.get();
85
- return bookingItems.some(({ service }) => service._id === currentService._id);
84
+ const serviceSelections = bookingService.serviceSelections.get();
85
+ return serviceSelections.some(({ service }) => service._id === currentService._id);
86
86
  });
87
87
  // requiresAvailability signal - true for APPOINTMENT and CLASS types
88
88
  const requiresAvailabilitySignal = signalsService.computed(() => {
@@ -201,8 +201,8 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
201
201
  return;
202
202
  const currentService = serviceSignal.get();
203
203
  // Remove all instances of this service (by serviceId)
204
- const bookingItems = bookingService.bookingItems.get();
205
- const instancesToRemove = bookingItems
204
+ const serviceSelections = bookingService.serviceSelections.get();
205
+ const instancesToRemove = serviceSelections
206
206
  .filter((s) => s.service._id === currentService._id)
207
207
  .map((s) => s.instanceId);
208
208
  instancesToRemove.forEach((instanceId) => {
@@ -80,7 +80,7 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
80
80
  const getServices = () => {
81
81
  if (config.services?.length)
82
82
  return config.services;
83
- return bookingService.bookingItems.get().map((s) => s.service);
83
+ return bookingService.serviceSelections.get().map((s) => s.service);
84
84
  };
85
85
  /**
86
86
  * Helper: Get filters from config or BookingService
@@ -88,7 +88,7 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
88
88
  const getFilters = () => {
89
89
  // Get BookingService selections (these take priority)
90
90
  const location = bookingService.location.get();
91
- const selections = bookingService.bookingItems.get();
91
+ const selections = bookingService.serviceSelections.get();
92
92
  const selectedStaffMemberIds = selections
93
93
  .map(({ resources }) => resources.map((r) => r._id))
94
94
  .flat();
@@ -3,7 +3,7 @@
3
3
  * Provides low-level access to BookingService via render props and service setup
4
4
  */
5
5
  import React from 'react';
6
- import { type BookingServiceConfig, type BookingItem, type Location, type BookingServiceActions } from '../../../services/booking/booking.js';
6
+ import { type BookingServiceConfig, type ServiceSelection, type Location, type BookingServiceActions } from '../../../services/booking/booking.js';
7
7
  import type { FormValues } from '@wix/form-public';
8
8
  /**
9
9
  * Props for Booking.Root component
@@ -33,10 +33,9 @@ export declare function Root(props: RootProps): React.ReactNode;
33
33
  * Mirrors BookingServiceConfig structure with actions
34
34
  */
35
35
  export interface BookingData {
36
- bookingItems: BookingItem[];
36
+ serviceSelections: ServiceSelection[];
37
37
  location: Location | null;
38
- formValues: FormValues | null;
39
- numberOfParticipants: number;
38
+ formSubmission: FormValues | null;
40
39
  actions: BookingServiceActions;
41
40
  }
42
41
  /**
@@ -53,9 +52,9 @@ export interface DataProps {
53
52
  * @example
54
53
  * ```tsx
55
54
  * <Booking.Data>
56
- * {({ bookingItems, location, formValues, numberOfParticipants, actions }) => (
57
- * bookingItems.length > 0 ? (
58
- * <div>{bookingItems.map(item => item.service.name).join(', ')}</div>
55
+ * {({ serviceSelections, location, formSubmission, actions }) => (
56
+ * serviceSelections.length > 0 ? (
57
+ * <div>{serviceSelections.map(item => item.service.name).join(', ')}</div>
59
58
  * ) : (
60
59
  * <div>No services selected</div>
61
60
  * )
@@ -28,9 +28,9 @@ export function Root(props) {
28
28
  * @example
29
29
  * ```tsx
30
30
  * <Booking.Data>
31
- * {({ bookingItems, location, formValues, numberOfParticipants, actions }) => (
32
- * bookingItems.length > 0 ? (
33
- * <div>{bookingItems.map(item => item.service.name).join(', ')}</div>
31
+ * {({ serviceSelections, location, formSubmission, actions }) => (
32
+ * serviceSelections.length > 0 ? (
33
+ * <div>{serviceSelections.map(item => item.service.name).join(', ')}</div>
34
34
  * ) : (
35
35
  * <div>No services selected</div>
36
36
  * )
@@ -41,16 +41,14 @@ export function Root(props) {
41
41
  export function Data(props) {
42
42
  const { children } = props;
43
43
  const bookingService = useService(BookingServiceDefinition);
44
- const bookingItems = bookingService.bookingItems.get();
44
+ const serviceSelections = bookingService.serviceSelections.get();
45
45
  const location = bookingService.location.get();
46
- const formValues = bookingService.formValues.get();
47
- const numberOfParticipants = bookingService.numberOfParticipants.get();
46
+ const formSubmission = bookingService.formSubmission.get();
48
47
  const { actions } = bookingService;
49
48
  return children({
50
- bookingItems,
49
+ serviceSelections,
51
50
  location,
52
- formValues,
53
- numberOfParticipants,
51
+ formSubmission,
54
52
  actions,
55
53
  });
56
54
  }
@@ -77,7 +77,7 @@ Root.displayName = 'TimeSlotList.Root';
77
77
  */
78
78
  const RootContent = React.forwardRef((props, ref) => {
79
79
  const { children, className, variant } = props;
80
- return (_jsx(CoreTimeSlotList.ListData, { children: ({ timeSlots, hasMore, isLoading, loadMore }) => (_jsx(GenericList.Root, { items: timeSlots, loadMore: loadMore, hasMore: hasMore, isLoading: isLoading, className: className, ref: ref, "data-testid": TestIds.timeSlotListRoot, variant: variant, children: children })) }));
80
+ return (_jsx(CoreTimeSlotList.ListData, { children: ({ timeSlots, hasMore, isLoading, error, loadMore }) => (_jsx(GenericList.Root, { items: timeSlots, loadMore: loadMore, hasMore: hasMore, isLoading: isLoading, error: error, className: className, ref: ref, "data-testid": TestIds.timeSlotListRoot, variant: variant, children: children })) }));
81
81
  });
82
82
  RootContent.displayName = 'TimeSlotList.RootContent';
83
83
  /**
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Booking Service - Global booking store
3
- * Manages booking flow state (selected services, time slot, location, form values)
3
+ * Manages booking flow state (selected services, time slot, location, form submission)
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';
@@ -8,9 +8,9 @@ import type { Service } from '@wix/auto_sdk_bookings_services';
8
8
  import type { Resource, EventInfo } from '@wix/auto_sdk_bookings_availability-time-slots';
9
9
  import type { FormValues } from '@wix/form-public';
10
10
  /**
11
- * Minimal time slot data for booking items
11
+ * Minimal time slot data for service selections
12
12
  */
13
- export interface BookingItemTimeSlot {
13
+ export interface ServiceSelectionTimeSlot {
14
14
  startDate: string;
15
15
  endDate: string;
16
16
  totalCapacity?: number;
@@ -19,9 +19,9 @@ export interface BookingItemTimeSlot {
19
19
  eventInfo?: EventInfo;
20
20
  }
21
21
  /**
22
- * BookingItem contains the service AND its related selections
22
+ * ServiceSelection contains the service AND its related selections
23
23
  */
24
- export interface BookingItem {
24
+ export interface ServiceSelection {
25
25
  /** Unique identifier for this booking instance (allows same service multiple times) */
26
26
  instanceId: string;
27
27
  /** The selected service */
@@ -29,7 +29,9 @@ export interface BookingItem {
29
29
  /** Selected resources (staff members, rooms, etc.) */
30
30
  resources: Resource[];
31
31
  /** Per-item time slot data */
32
- timeSlot?: BookingItemTimeSlot;
32
+ timeSlot?: ServiceSelectionTimeSlot;
33
+ /** Number of participants for this service selection */
34
+ totalParticipants?: number;
33
35
  }
34
36
  export interface Location {
35
37
  id: string;
@@ -39,25 +41,24 @@ export interface Location {
39
41
  * BookingService actions - setters only, no API calls
40
42
  */
41
43
  export interface BookingServiceActions {
42
- /** Clears all booking items and sets a single item (instanceId is auto-generated) */
43
- setItem(item: Omit<BookingItem, 'instanceId'>): string;
44
+ /** Clears all service selections and sets a single item (instanceId is auto-generated) */
45
+ setItem(item: Omit<ServiceSelection, 'instanceId'>): string;
44
46
  /** Adds an item and returns the generated instanceId */
45
- addItem(item: Omit<BookingItem, 'instanceId'>): string;
46
- /** Updates a booking item. If no instanceId provided, updates the first item. */
47
- updateItem(updates: Partial<Omit<BookingItem, 'instanceId'>>, instanceId?: string): void;
48
- /** Removes a booking item. If no instanceId provided, removes the first item. */
47
+ addItem(item: Omit<ServiceSelection, 'instanceId'>): string;
48
+ /** Updates a service selection. If no instanceId provided, updates the first item. */
49
+ updateItem(updates: Partial<Omit<ServiceSelection, 'instanceId'>>, instanceId?: string): void;
50
+ /** Removes a service selection. If no instanceId provided, removes the first item. */
49
51
  removeItem(instanceId?: string): void;
50
- /** Clears all booking items */
52
+ /** Clears all service selections */
51
53
  clearItems(): void;
52
- /** Sets a resource by ID within a booking item. If no instanceId provided, uses the first item. */
54
+ /** Sets a resource by ID within a service selection. If no instanceId provided, uses the first item. */
53
55
  setResourceById(resourceId: string, resource: Resource, instanceId?: string): void;
54
- /** Gets a resource by ID from a booking item. If no instanceId provided, uses the first item. */
56
+ /** Gets a resource by ID from a service selection. If no instanceId provided, uses the first item. */
55
57
  getResourceById(resourceId: string, instanceId?: string): Resource | undefined;
56
58
  setLocation(location: Location | null): void;
57
59
  clearLocation(): void;
58
- setFormValues(values: FormValues | null): void;
59
- clearFormValues(): void;
60
- setNumberOfParticipants(count: number): void;
60
+ setFormSubmission(values: FormValues | null): void;
61
+ clearFormSubmission(): void;
61
62
  clearAll(): void;
62
63
  }
63
64
  /**
@@ -65,14 +66,12 @@ export interface BookingServiceActions {
65
66
  * Pure state management - no API calls
66
67
  */
67
68
  export interface BookingService {
68
- /** Signal containing the booking items (services with their related data) */
69
- bookingItems: Signal<BookingItem[]>;
69
+ /** Signal containing the service selections (services with their related data) */
70
+ serviceSelections: Signal<ServiceSelection[]>;
70
71
  /** Signal containing the selected location */
71
72
  location: Signal<Location | null>;
72
- /** Signal containing the form values */
73
- formValues: Signal<FormValues | null>;
74
- /** Signal containing the number of participants */
75
- numberOfParticipants: Signal<number>;
73
+ /** Signal containing the form submission */
74
+ formSubmission: Signal<FormValues | null>;
76
75
  /** Actions for modifying booking state */
77
76
  actions: BookingServiceActions;
78
77
  }
@@ -89,14 +88,12 @@ export declare const BookingServiceDefinition: string & {
89
88
  * Mirrors BookingService structure (without actions and Signal wrappers)
90
89
  */
91
90
  export interface BookingServiceConfig {
92
- /** Optional initial booking items to pre-populate */
93
- bookingItems?: BookingItem[];
91
+ /** Optional initial service selections to pre-populate */
92
+ serviceSelections?: ServiceSelection[];
94
93
  /** Optional initial location */
95
94
  location?: Location | null;
96
- /** Optional initial form values */
97
- formValues?: FormValues | null;
98
- /** Optional initial number of participants (defaults to 1) */
99
- numberOfParticipants?: number;
95
+ /** Optional initial form submission */
96
+ formSubmission?: FormValues | null;
100
97
  }
101
98
  /**
102
99
  * Implementation of BookingService
@@ -116,8 +113,8 @@ export interface BookingServiceConfig {
116
113
  *
117
114
  * // In any page - access booking data
118
115
  * <Booking.Data>
119
- * {({ bookingItems, location, formValues, actions }) => (
120
- * <div>{bookingItems.map(item => item.service.name).join(', ')}</div>
116
+ * {({ serviceSelections, location, formSubmission, actions }) => (
117
+ * <div>{serviceSelections.map(item => item.service.name).join(', ')}</div>
121
118
  * )}
122
119
  * </Booking.Data>
123
120
  * ```
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Booking Service - Global booking store
3
- * Manages booking flow state (selected services, time slot, location, form values)
3
+ * Manages booking flow state (selected services, time slot, location, form submission)
4
4
  * Persists across page navigation in SPA until page refresh
5
5
  */
6
6
  import { defineService, implementService } from '@wix/services-definitions';
@@ -9,7 +9,7 @@ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-servic
9
9
  // Types
10
10
  // ============================================================================
11
11
  /**
12
- * Generates a unique instance ID for booking items
12
+ * Generates a unique instance ID for service selections
13
13
  */
14
14
  function generateInstanceId() {
15
15
  return crypto.randomUUID();
@@ -39,8 +39,8 @@ export const BookingServiceDefinition = defineService('booking');
39
39
  *
40
40
  * // In any page - access booking data
41
41
  * <Booking.Data>
42
- * {({ bookingItems, location, formValues, actions }) => (
43
- * <div>{bookingItems.map(item => item.service.name).join(', ')}</div>
42
+ * {({ serviceSelections, location, formSubmission, actions }) => (
43
+ * <div>{serviceSelections.map(item => item.service.name).join(', ')}</div>
44
44
  * )}
45
45
  * </Booking.Data>
46
46
  * ```
@@ -48,15 +48,14 @@ export const BookingServiceDefinition = defineService('booking');
48
48
  export const BookingService = implementService.withConfig()(BookingServiceDefinition, ({ getService, config }) => {
49
49
  const signalsService = getService(SignalsServiceDefinition);
50
50
  // Initialize signals with config values
51
- // Ensure all initial booking items have instanceIds
52
- const initialItemsWithIds = (config.bookingItems || []).map((item) => ({
51
+ // Ensure all initial service selections have instanceIds
52
+ const initialItemsWithIds = (config.serviceSelections || []).map((item) => ({
53
53
  ...item,
54
54
  instanceId: item.instanceId || generateInstanceId(),
55
55
  }));
56
- const bookingItemsSignal = signalsService.signal(initialItemsWithIds);
56
+ const serviceSelectionsSignal = signalsService.signal(initialItemsWithIds);
57
57
  const locationSignal = signalsService.signal(config.location || null);
58
- const formValuesSignal = signalsService.signal(config.formValues || null);
59
- const numberOfParticipantsSignal = signalsService.signal(config.numberOfParticipants ?? 1);
58
+ const formSubmissionSignal = signalsService.signal(config.formSubmission || null);
60
59
  // ========================================================================
61
60
  // Actions Implementation
62
61
  // ========================================================================
@@ -68,43 +67,43 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
68
67
  ...item,
69
68
  instanceId,
70
69
  };
71
- bookingItemsSignal.set([newItem]);
70
+ serviceSelectionsSignal.set([newItem]);
72
71
  return instanceId;
73
72
  },
74
73
  addItem(item) {
75
74
  const instanceId = generateInstanceId();
76
- const current = bookingItemsSignal.get();
75
+ const current = serviceSelectionsSignal.get();
77
76
  const newItem = {
78
77
  ...item,
79
78
  instanceId,
80
79
  };
81
- bookingItemsSignal.set([...current, newItem]);
80
+ serviceSelectionsSignal.set([...current, newItem]);
82
81
  return instanceId;
83
82
  },
84
83
  updateItem(updates, instanceId) {
85
- const current = bookingItemsSignal.get();
84
+ const current = serviceSelectionsSignal.get();
86
85
  // If no instanceId provided, update the first item (index 0)
87
86
  const targetId = instanceId ?? current[0]?.instanceId;
88
87
  const updated = current.map((item) => item.instanceId === targetId ? { ...item, ...updates } : item);
89
- bookingItemsSignal.set(updated);
88
+ serviceSelectionsSignal.set(updated);
90
89
  },
91
90
  removeItem(instanceId) {
92
- const current = bookingItemsSignal.get();
91
+ const current = serviceSelectionsSignal.get();
93
92
  if (!instanceId) {
94
93
  // Remove first item if no instanceId provided
95
- bookingItemsSignal.set(current.slice(1));
94
+ serviceSelectionsSignal.set(current.slice(1));
96
95
  }
97
96
  else {
98
97
  const filtered = current.filter((item) => item.instanceId !== instanceId);
99
- bookingItemsSignal.set(filtered);
98
+ serviceSelectionsSignal.set(filtered);
100
99
  }
101
100
  },
102
101
  clearItems() {
103
- bookingItemsSignal.set([]);
102
+ serviceSelectionsSignal.set([]);
104
103
  },
105
104
  // Resource helpers
106
105
  setResourceById(resourceId, resource, instanceId) {
107
- const current = bookingItemsSignal.get();
106
+ const current = serviceSelectionsSignal.get();
108
107
  // If no instanceId provided, use the first item
109
108
  const targetId = instanceId ?? current[0]?.instanceId;
110
109
  if (!targetId)
@@ -123,10 +122,10 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
123
122
  }
124
123
  return { ...item, resources: newResources };
125
124
  });
126
- bookingItemsSignal.set(updated);
125
+ serviceSelectionsSignal.set(updated);
127
126
  },
128
127
  getResourceById(resourceId, instanceId) {
129
- const current = bookingItemsSignal.get();
128
+ const current = serviceSelectionsSignal.get();
130
129
  // If no instanceId provided, use the first item
131
130
  const targetId = instanceId ?? current[0]?.instanceId;
132
131
  if (!targetId)
@@ -143,30 +142,24 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
143
142
  clearLocation() {
144
143
  locationSignal.set(null);
145
144
  },
146
- // Form Values actions
147
- setFormValues(values) {
148
- formValuesSignal.set(values);
145
+ // Form Submission actions
146
+ setFormSubmission(values) {
147
+ formSubmissionSignal.set(values);
149
148
  },
150
- clearFormValues() {
151
- formValuesSignal.set(null);
152
- },
153
- // Number of Participants actions
154
- setNumberOfParticipants(count) {
155
- numberOfParticipantsSignal.set(count);
149
+ clearFormSubmission() {
150
+ formSubmissionSignal.set(null);
156
151
  },
157
152
  // Clear all
158
153
  clearAll() {
159
- bookingItemsSignal.set([]);
154
+ serviceSelectionsSignal.set([]);
160
155
  locationSignal.set(null);
161
- formValuesSignal.set(null);
162
- numberOfParticipantsSignal.set(1);
156
+ formSubmissionSignal.set(null);
163
157
  },
164
158
  };
165
159
  return {
166
- bookingItems: bookingItemsSignal,
160
+ serviceSelections: serviceSelectionsSignal,
167
161
  location: locationSignal,
168
- formValues: formValuesSignal,
169
- numberOfParticipants: numberOfParticipantsSignal,
162
+ formSubmission: formSubmissionSignal,
170
163
  actions,
171
164
  };
172
165
  });
@@ -3,6 +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 Location, type BookingServiceActions, } from './booking/booking.js';
6
+ export { BookingService, BookingServiceDefinition, type BookingServiceConfig, type Location, type BookingServiceActions, type ServiceSelection, type ServiceSelectionTimeSlot, } from './booking/booking.js';
7
7
  export { TimeSlotListService, TimeSlotListServiceDefinition, ViewMode, loadTimeSlotListConfig, type TimeSlotListServiceAPI, type TimeSlotListServiceActions, type TimeSlotListServiceConfig, type SlotSelection, type TimeSlot, type LoadTimeSlotListConfigOptions, type LoadTimeSlotListConfigResult, } from './time-slot-list/index.js';
8
8
  export { ServiceListService, ServiceListServiceDefinition, type ServiceListServiceAPI, type ServiceListServiceConfig, type ServiceListFilters, type ServiceListActions, type QueryOptions, loadServiceListServiceInitialData, type SuccessServiceListServiceConfigResult, type ErrorServiceListServiceConfigResult, } from './service-list/service-list.js';
@@ -81,8 +81,8 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
81
81
  const currentService = serviceSignal.get();
82
82
  if (!currentService._id)
83
83
  return false;
84
- const bookingItems = bookingService.bookingItems.get();
85
- return bookingItems.some(({ service }) => service._id === currentService._id);
84
+ const serviceSelections = bookingService.serviceSelections.get();
85
+ return serviceSelections.some(({ service }) => service._id === currentService._id);
86
86
  });
87
87
  // requiresAvailability signal - true for APPOINTMENT and CLASS types
88
88
  const requiresAvailabilitySignal = signalsService.computed(() => {
@@ -201,8 +201,8 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
201
201
  return;
202
202
  const currentService = serviceSignal.get();
203
203
  // Remove all instances of this service (by serviceId)
204
- const bookingItems = bookingService.bookingItems.get();
205
- const instancesToRemove = bookingItems
204
+ const serviceSelections = bookingService.serviceSelections.get();
205
+ const instancesToRemove = serviceSelections
206
206
  .filter((s) => s.service._id === currentService._id)
207
207
  .map((s) => s.instanceId);
208
208
  instancesToRemove.forEach((instanceId) => {
@@ -80,7 +80,7 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
80
80
  const getServices = () => {
81
81
  if (config.services?.length)
82
82
  return config.services;
83
- return bookingService.bookingItems.get().map((s) => s.service);
83
+ return bookingService.serviceSelections.get().map((s) => s.service);
84
84
  };
85
85
  /**
86
86
  * Helper: Get filters from config or BookingService
@@ -88,7 +88,7 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
88
88
  const getFilters = () => {
89
89
  // Get BookingService selections (these take priority)
90
90
  const location = bookingService.location.get();
91
- const selections = bookingService.bookingItems.get();
91
+ const selections = bookingService.serviceSelections.get();
92
92
  const selectedStaffMemberIds = selections
93
93
  .map(({ resources }) => resources.map((r) => r._id))
94
94
  .flat();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-bookings",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -69,5 +69,5 @@
69
69
  "groupId": "com.wixpress.headless-components"
70
70
  }
71
71
  },
72
- "falconPackageHash": "8c910b633cde19227cb0209fec691701a57a7e53b577ee76971bfa2a"
72
+ "falconPackageHash": "2a71ca796bb480604700e6cc7fde7a950ba7f71c92a189dbd0a2375a"
73
73
  }