@wix/headless-bookings 0.0.50 → 0.0.52
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/cjs/dist/react/booking/Booking.d.ts +213 -2
- package/cjs/dist/react/booking/Booking.js +226 -0
- package/cjs/dist/react/core/booking/Booking.d.ts +139 -11
- package/cjs/dist/react/core/booking/Booking.js +219 -1
- package/cjs/dist/react/index.d.ts +1 -0
- package/cjs/dist/react/index.js +1 -0
- package/cjs/dist/react/location/Location.js +2 -2
- package/cjs/dist/services/payment/payment.def.d.ts +1 -1
- package/cjs/dist/services/payment/payment.js +11 -5
- package/dist/react/booking/Booking.d.ts +213 -2
- package/dist/react/booking/Booking.js +226 -0
- package/dist/react/core/booking/Booking.d.ts +139 -11
- package/dist/react/core/booking/Booking.js +219 -1
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/react/location/Location.js +2 -2
- package/dist/services/payment/payment.def.d.ts +1 -1
- package/dist/services/payment/payment.js +11 -5
- package/package.json +2 -2
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Core Booking Components
|
|
4
|
+
* Provides low-level access to BookingService via render props and service setup
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
2
7
|
import { WixServices, useService } from '@wix/services-manager-react';
|
|
3
8
|
import { createServicesMap } from '@wix/services-manager';
|
|
4
9
|
import { BookingServiceDefinition, BookingService, } from '../../../services/booking/booking.js';
|
|
@@ -39,14 +44,53 @@ export function Root(props) {
|
|
|
39
44
|
* </Booking.Data>
|
|
40
45
|
* ```
|
|
41
46
|
*/
|
|
47
|
+
/**
|
|
48
|
+
* Maps a TimeSlotLocationType to ServiceLocationType.
|
|
49
|
+
* TimeSlot location has flat structure: { name, formattedAddress, locationType }
|
|
50
|
+
* Service location has nested structure: { business: { name, address }, type }
|
|
51
|
+
*/
|
|
52
|
+
function mapTimeSlotLocationToServiceLocation(timeSlotLocation) {
|
|
53
|
+
// TimeSlot location has flat name/formattedAddress at top level
|
|
54
|
+
// Convert to nested business structure that CoreLocation expects
|
|
55
|
+
return {
|
|
56
|
+
_id: timeSlotLocation._id ?? undefined,
|
|
57
|
+
type: timeSlotLocation.locationType,
|
|
58
|
+
business: {
|
|
59
|
+
_id: timeSlotLocation._id ?? undefined,
|
|
60
|
+
name: timeSlotLocation.name ?? undefined,
|
|
61
|
+
address: timeSlotLocation.formattedAddress
|
|
62
|
+
? {
|
|
63
|
+
addressLine: timeSlotLocation.formattedAddress,
|
|
64
|
+
}
|
|
65
|
+
: undefined,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Resolves the location with fallback logic:
|
|
71
|
+
* 1. First, use the explicitly set booking location
|
|
72
|
+
* 2. If not set, fall back to the first service selection's slot location
|
|
73
|
+
*/
|
|
74
|
+
function resolveLocation(bookingLocation, serviceSelections) {
|
|
75
|
+
if (bookingLocation) {
|
|
76
|
+
return bookingLocation;
|
|
77
|
+
}
|
|
78
|
+
// Fallback to first slot's location
|
|
79
|
+
const firstSlotLocation = serviceSelections[0]?.timeSlot?.location;
|
|
80
|
+
if (firstSlotLocation) {
|
|
81
|
+
return mapTimeSlotLocationToServiceLocation(firstSlotLocation);
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
42
85
|
export function Data(props) {
|
|
43
86
|
const { children } = props;
|
|
44
87
|
const bookingService = useService(BookingServiceDefinition);
|
|
45
88
|
const serviceSelections = bookingService.serviceSelections.get();
|
|
46
|
-
const
|
|
89
|
+
const bookingLocation = bookingService.location.get();
|
|
47
90
|
const timezone = bookingService.timezone.get();
|
|
48
91
|
const formSubmission = bookingService.formSubmission.get();
|
|
49
92
|
const { actions } = bookingService;
|
|
93
|
+
const location = resolveLocation(bookingLocation, serviceSelections);
|
|
50
94
|
return children({
|
|
51
95
|
serviceSelections,
|
|
52
96
|
location,
|
|
@@ -55,3 +99,177 @@ export function Data(props) {
|
|
|
55
99
|
actions,
|
|
56
100
|
});
|
|
57
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Context for the current BookingItem
|
|
104
|
+
*/
|
|
105
|
+
const BookingItemContext = React.createContext(null);
|
|
106
|
+
/**
|
|
107
|
+
* Hook to access the current BookingItem from context.
|
|
108
|
+
* Must be used within BookingItemProvider.
|
|
109
|
+
*
|
|
110
|
+
* @throws Error if used outside of BookingItemProvider context
|
|
111
|
+
*/
|
|
112
|
+
export function useBookingItemContext() {
|
|
113
|
+
const context = React.useContext(BookingItemContext);
|
|
114
|
+
if (!context) {
|
|
115
|
+
throw new Error('BookingItem components must be used within BookingItemProvider');
|
|
116
|
+
}
|
|
117
|
+
return context;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Provider component used by repeaters to provide BookingItem context.
|
|
121
|
+
* Can be used by core consumers to create their own repeater.
|
|
122
|
+
*
|
|
123
|
+
* @component
|
|
124
|
+
* @example
|
|
125
|
+
* ```tsx
|
|
126
|
+
* {items.map((item) => (
|
|
127
|
+
* <BookingItemProvider key={item.instanceId} item={item}>
|
|
128
|
+
* {children}
|
|
129
|
+
* </BookingItemProvider>
|
|
130
|
+
* ))}
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
export function BookingItemProvider(props) {
|
|
134
|
+
const { children, item } = props;
|
|
135
|
+
return (_jsx(BookingItemContext.Provider, { value: item, children: children }));
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Core component that provides access to booking item info via render props.
|
|
139
|
+
* Must be used within BookingItemProvider.
|
|
140
|
+
*
|
|
141
|
+
* @component
|
|
142
|
+
* @example
|
|
143
|
+
* ```tsx
|
|
144
|
+
* <BookingItemInfo>
|
|
145
|
+
* {({ service, timeSlot, staffName }) => (
|
|
146
|
+
* <div>
|
|
147
|
+
* <span>{service.name}</span>
|
|
148
|
+
* <span>{staffName}</span>
|
|
149
|
+
* </div>
|
|
150
|
+
* )}
|
|
151
|
+
* </BookingItemInfo>
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export function BookingItemInfo(props) {
|
|
155
|
+
const item = useBookingItemContext();
|
|
156
|
+
const staffName = item.staff?.[0]?.name || '';
|
|
157
|
+
return props.children({
|
|
158
|
+
service: item.service,
|
|
159
|
+
timeSlot: item.timeSlot,
|
|
160
|
+
staffName,
|
|
161
|
+
instanceId: item.instanceId,
|
|
162
|
+
index: item.index,
|
|
163
|
+
item,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// ============================================================================
|
|
167
|
+
// Helper: Convert ServiceSelectionTimeSlot to SDK TimeSlot
|
|
168
|
+
// ============================================================================
|
|
169
|
+
/**
|
|
170
|
+
* Converts a ServiceSelectionTimeSlot to SDK TimeSlot format
|
|
171
|
+
* for compatibility with TimeSlot.Root component.
|
|
172
|
+
*/
|
|
173
|
+
function mapSelectionTimeSlotToTimeSlot(serviceSelectionTimeSlot) {
|
|
174
|
+
if (!serviceSelectionTimeSlot) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
const availableResources = serviceSelectionTimeSlot.resources?.length
|
|
178
|
+
? [{ resources: serviceSelectionTimeSlot.resources }]
|
|
179
|
+
: undefined;
|
|
180
|
+
return {
|
|
181
|
+
localStartDate: serviceSelectionTimeSlot.startDate,
|
|
182
|
+
localEndDate: serviceSelectionTimeSlot.endDate,
|
|
183
|
+
bookable: true,
|
|
184
|
+
totalCapacity: serviceSelectionTimeSlot.totalCapacity,
|
|
185
|
+
remainingCapacity: serviceSelectionTimeSlot.remainingCapacity,
|
|
186
|
+
scheduleId: serviceSelectionTimeSlot.scheduleId,
|
|
187
|
+
eventInfo: serviceSelectionTimeSlot.eventInfo,
|
|
188
|
+
location: serviceSelectionTimeSlot.location,
|
|
189
|
+
availableResources,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
// ============================================================================
|
|
193
|
+
// Helper: Resolve Staff with Priority Logic
|
|
194
|
+
// ============================================================================
|
|
195
|
+
/**
|
|
196
|
+
* Gets selected staff resources with priority:
|
|
197
|
+
* 1. From selected time slot (if resources exist)
|
|
198
|
+
* 2. From service selection resources
|
|
199
|
+
* Returns null if no staff is chosen
|
|
200
|
+
*/
|
|
201
|
+
function getSelectedStaff(serviceSelection) {
|
|
202
|
+
// Priority 1: From selected time slot
|
|
203
|
+
if (serviceSelection.timeSlot?.resources?.length) {
|
|
204
|
+
return serviceSelection.timeSlot.resources;
|
|
205
|
+
}
|
|
206
|
+
// Priority 2: From service selection
|
|
207
|
+
if (serviceSelection.resources?.length) {
|
|
208
|
+
return serviceSelection.resources;
|
|
209
|
+
}
|
|
210
|
+
// No staff chosen
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Creates a BookingItem from a ServiceSelection
|
|
215
|
+
*/
|
|
216
|
+
function createBookingItem(serviceSelection, index) {
|
|
217
|
+
return {
|
|
218
|
+
service: serviceSelection.service,
|
|
219
|
+
timeSlot: mapSelectionTimeSlotToTimeSlot(serviceSelection.timeSlot),
|
|
220
|
+
staff: getSelectedStaff(serviceSelection),
|
|
221
|
+
instanceId: serviceSelection.instanceId,
|
|
222
|
+
index,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Core component that provides access to booking items array via render props.
|
|
227
|
+
* Transforms serviceSelections into BookingItem objects.
|
|
228
|
+
*
|
|
229
|
+
* @component
|
|
230
|
+
* @example
|
|
231
|
+
* ```tsx
|
|
232
|
+
* <Booking.ItemsData>
|
|
233
|
+
* {({ items }) => (
|
|
234
|
+
* items.length > 0 ? (
|
|
235
|
+
* <div>{items.length} bookings</div>
|
|
236
|
+
* ) : (
|
|
237
|
+
* <div>No bookings</div>
|
|
238
|
+
* )
|
|
239
|
+
* )}
|
|
240
|
+
* </Booking.ItemsData>
|
|
241
|
+
* ```
|
|
242
|
+
*/
|
|
243
|
+
export function ItemsData(props) {
|
|
244
|
+
const { children } = props;
|
|
245
|
+
const bookingService = useService(BookingServiceDefinition);
|
|
246
|
+
const serviceSelections = bookingService.serviceSelections.get();
|
|
247
|
+
const items = serviceSelections.map((selection, index) => createBookingItem(selection, index));
|
|
248
|
+
return children({ items });
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Core component that provides payment data via render props.
|
|
252
|
+
* Computes slotServices from serviceSelections.
|
|
253
|
+
*
|
|
254
|
+
* @component
|
|
255
|
+
* @example
|
|
256
|
+
* ```tsx
|
|
257
|
+
* <Booking.PaymentData>
|
|
258
|
+
* {({ slotServices }) => (
|
|
259
|
+
* <Payment.Root slotServices={slotServices}>
|
|
260
|
+
* <Payment.TotalPrice />
|
|
261
|
+
* </Payment.Root>
|
|
262
|
+
* )}
|
|
263
|
+
* </Booking.PaymentData>
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
export function PaymentData(props) {
|
|
267
|
+
const { children } = props;
|
|
268
|
+
const bookingService = useService(BookingServiceDefinition);
|
|
269
|
+
const serviceSelections = bookingService.serviceSelections.get();
|
|
270
|
+
const slotServices = serviceSelections.map((selection) => ({
|
|
271
|
+
service: selection.service,
|
|
272
|
+
lineItemId: selection.instanceId,
|
|
273
|
+
}));
|
|
274
|
+
return children({ slotServices });
|
|
275
|
+
}
|
|
@@ -3,6 +3,7 @@ export * as BookingForm from './booking-form/BookingForm.js';
|
|
|
3
3
|
export * as Service from './service/Service.js';
|
|
4
4
|
export * as ServiceMedia from './service/ServiceMedia.js';
|
|
5
5
|
export * as TimeSlotList from './time-slot-list/TimeSlotList.js';
|
|
6
|
+
export * as TimeSlot from './time-slot-list/TimeSlot.js';
|
|
6
7
|
export * as ServiceList from './service-list/ServiceList.js';
|
|
7
8
|
export * as Location from './location/Location.js';
|
|
8
9
|
export * as LocationList from './location/LocationList.js';
|
package/cjs/dist/react/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export * as BookingForm from './booking-form/BookingForm.js';
|
|
|
3
3
|
export * as Service from './service/Service.js';
|
|
4
4
|
export * as ServiceMedia from './service/ServiceMedia.js';
|
|
5
5
|
export * as TimeSlotList from './time-slot-list/TimeSlotList.js';
|
|
6
|
+
export * as TimeSlot from './time-slot-list/TimeSlot.js';
|
|
6
7
|
export * as ServiceList from './service-list/ServiceList.js';
|
|
7
8
|
export * as Location from './location/Location.js';
|
|
8
9
|
export * as LocationList from './location/LocationList.js';
|
|
@@ -89,7 +89,7 @@ Root.displayName = 'Location.Root';
|
|
|
89
89
|
export const Name = React.forwardRef((props, ref) => {
|
|
90
90
|
const { asChild, children, className, ...attrs } = props;
|
|
91
91
|
const { name } = useLocationContext();
|
|
92
|
-
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.locationName, customElement: children, customElementProps: { name: name ?? '' }, ...attrs, children: _jsx("span", { children: name }) }));
|
|
92
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.locationName, customElement: children, customElementProps: { name: name ?? '' }, ...attrs, children: name ? _jsx("span", { children: name }) : null }));
|
|
93
93
|
});
|
|
94
94
|
Name.displayName = 'Location.Name';
|
|
95
95
|
/**
|
|
@@ -117,7 +117,7 @@ export const Type = React.forwardRef((props, ref) => {
|
|
|
117
117
|
locationType,
|
|
118
118
|
isCustomerLocation,
|
|
119
119
|
isCustomLocation,
|
|
120
|
-
}, ...attrs, children: _jsx("span", { children: locationType }) }));
|
|
120
|
+
}, ...attrs, children: locationType ? _jsx("span", { children: locationType }) : null }));
|
|
121
121
|
});
|
|
122
122
|
Type.displayName = 'Location.Type';
|
|
123
123
|
/**
|
|
@@ -8,7 +8,7 @@ import type { Service } from '@wix/auto_sdk_bookings_services';
|
|
|
8
8
|
/**
|
|
9
9
|
* Payment option for line items
|
|
10
10
|
*/
|
|
11
|
-
export type PaymentOption = 'FULL_PAYMENT_ONLINE' | 'FULL_PAYMENT_OFFLINE';
|
|
11
|
+
export type PaymentOption = 'FULL_PAYMENT_ONLINE' | 'FULL_PAYMENT_OFFLINE' | 'DEPOSIT_ONLINE';
|
|
12
12
|
/**
|
|
13
13
|
* Additional computed info for a line item (not in SDK response)
|
|
14
14
|
*/
|
|
@@ -25,11 +25,15 @@ function getAdditionalInfo(service, lineItemId) {
|
|
|
25
25
|
: undefined;
|
|
26
26
|
return { lineItemId, priceText };
|
|
27
27
|
}
|
|
28
|
-
function getPaymentOption(service) {
|
|
28
|
+
function getPaymentOption(service, hasDeposit) {
|
|
29
29
|
const options = service.payment?.options;
|
|
30
30
|
if (options?.inPerson) {
|
|
31
31
|
return 'FULL_PAYMENT_OFFLINE';
|
|
32
32
|
}
|
|
33
|
+
// If deposit is configured, use DEPOSIT_ONLINE to get correct payNow/payLater split
|
|
34
|
+
if (hasDeposit) {
|
|
35
|
+
return 'DEPOSIT_ONLINE';
|
|
36
|
+
}
|
|
33
37
|
return 'FULL_PAYMENT_ONLINE';
|
|
34
38
|
}
|
|
35
39
|
function buildLineItem(service, numberOfParticipants, lineItemId) {
|
|
@@ -37,11 +41,13 @@ function buildLineItem(service, numberOfParticipants, lineItemId) {
|
|
|
37
41
|
const servicePrice = service.payment?.fixed?.price?.value;
|
|
38
42
|
const price = Number(servicePrice || 0) * numberOfParticipants;
|
|
39
43
|
// Get deposit if configured
|
|
40
|
-
const
|
|
41
|
-
|
|
44
|
+
const depositValue = service.payment?.fixed?.deposit?.value;
|
|
45
|
+
const hasDeposit = !!depositValue && Number(depositValue) > 0;
|
|
46
|
+
const deposit = hasDeposit
|
|
47
|
+
? Number(depositValue) * numberOfParticipants
|
|
42
48
|
: undefined;
|
|
43
|
-
// Get payment option from service configuration
|
|
44
|
-
const paymentOption = getPaymentOption(service);
|
|
49
|
+
// Get payment option from service configuration (pass hasDeposit for correct API behavior)
|
|
50
|
+
const paymentOption = getPaymentOption(service, hasDeposit);
|
|
45
51
|
return {
|
|
46
52
|
_id: lineItemId,
|
|
47
53
|
catalogReference: {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Booking - High-level component for managing bookings
|
|
3
|
-
* Provides root component for booking context
|
|
3
|
+
* Provides root component for booking context and booking item display components
|
|
4
4
|
*/
|
|
5
5
|
import React from 'react';
|
|
6
|
+
import * as CoreBooking from '../core/booking/Booking.js';
|
|
6
7
|
import type { BookingServiceConfig } from '../../services/booking/booking.js';
|
|
7
|
-
|
|
8
|
+
import { type AsChildChildren } from '@wix/headless-utils/react';
|
|
9
|
+
export type { BookingData, DataProps, BookingItem, } from '../core/booking/Booking.js';
|
|
8
10
|
/**
|
|
9
11
|
* Props for Booking.Root component
|
|
10
12
|
*/
|
|
@@ -52,3 +54,212 @@ export declare const Root: {
|
|
|
52
54
|
export declare const Actions: {
|
|
53
55
|
Book: React.ForwardRefExoticComponent<import("./Book.js").BookProps & React.RefAttributes<HTMLButtonElement>>;
|
|
54
56
|
};
|
|
57
|
+
/**
|
|
58
|
+
* Hook to access the current BookingItem from context.
|
|
59
|
+
* Must be used within Booking.ItemRepeater.
|
|
60
|
+
*
|
|
61
|
+
* @throws Error if used outside of ItemRepeater context
|
|
62
|
+
*/
|
|
63
|
+
export declare const useBookingItem: typeof CoreBooking.useBookingItemContext;
|
|
64
|
+
/**
|
|
65
|
+
* Props for Booking.ItemsRoot component (Container Level)
|
|
66
|
+
*/
|
|
67
|
+
export interface ItemsRootProps {
|
|
68
|
+
children: React.ReactNode;
|
|
69
|
+
className?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Container component that provides GenericList.Root context for booking items.
|
|
73
|
+
* Use Booking.Items inside for list container with emptyState support.
|
|
74
|
+
*
|
|
75
|
+
* @component
|
|
76
|
+
* @example
|
|
77
|
+
* ```tsx
|
|
78
|
+
* <Booking.ItemsRoot>
|
|
79
|
+
* <Booking.Items emptyState={<div>No bookings selected</div>}>
|
|
80
|
+
* <Booking.ItemRepeater>
|
|
81
|
+
* <div className="booking-card">
|
|
82
|
+
* <Booking.Service>
|
|
83
|
+
* <Service.Name />
|
|
84
|
+
* </Booking.Service>
|
|
85
|
+
* </div>
|
|
86
|
+
* </Booking.ItemRepeater>
|
|
87
|
+
* </Booking.Items>
|
|
88
|
+
* </Booking.ItemsRoot>
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export declare const ItemsRoot: React.ForwardRefExoticComponent<ItemsRootProps & React.RefAttributes<HTMLDivElement>>;
|
|
92
|
+
/**
|
|
93
|
+
* Props for Booking.Items component (List Container Level)
|
|
94
|
+
*/
|
|
95
|
+
export interface ItemsProps {
|
|
96
|
+
children: React.ReactNode;
|
|
97
|
+
/** Content to render when there are no booking items */
|
|
98
|
+
emptyState?: React.ReactNode;
|
|
99
|
+
className?: string;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* List container component with emptyState support.
|
|
103
|
+
* Wraps GenericList.Items. Must be used within Booking.ItemsRoot.
|
|
104
|
+
*
|
|
105
|
+
* @component
|
|
106
|
+
* @example
|
|
107
|
+
* ```tsx
|
|
108
|
+
* <Booking.ItemsRoot>
|
|
109
|
+
* <Booking.Items emptyState={<div>No bookings selected</div>}>
|
|
110
|
+
* <Booking.ItemRepeater>
|
|
111
|
+
* <Booking.Service>
|
|
112
|
+
* <Service.Name />
|
|
113
|
+
* </Booking.Service>
|
|
114
|
+
* </Booking.ItemRepeater>
|
|
115
|
+
* </Booking.Items>
|
|
116
|
+
* </Booking.ItemsRoot>
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare const Items: React.ForwardRefExoticComponent<ItemsProps & React.RefAttributes<HTMLElement>>;
|
|
120
|
+
/**
|
|
121
|
+
* Props for Booking.ItemRepeater component
|
|
122
|
+
*/
|
|
123
|
+
export interface ItemRepeaterProps {
|
|
124
|
+
children: React.ReactNode;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Repeater component that maps over booking items and provides context per item.
|
|
128
|
+
* Uses GenericList.Repeater internally with itemWrapper that provides BookingItemContext.
|
|
129
|
+
* Children have access to Booking.Service, Booking.TimeSlot, etc.
|
|
130
|
+
*
|
|
131
|
+
* @component
|
|
132
|
+
* @example
|
|
133
|
+
* ```tsx
|
|
134
|
+
* <Booking.ItemRepeater>
|
|
135
|
+
* <div className="booking-card">
|
|
136
|
+
* <Booking.Service>
|
|
137
|
+
* <Service.Name />
|
|
138
|
+
* <Service.Price />
|
|
139
|
+
* </Booking.Service>
|
|
140
|
+
* <Booking.TimeSlot>
|
|
141
|
+
* <TimeSlot.StartDate />
|
|
142
|
+
* </Booking.TimeSlot>
|
|
143
|
+
* <Booking.StaffName />
|
|
144
|
+
* </div>
|
|
145
|
+
* </Booking.ItemRepeater>
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export declare const ItemRepeater: React.ForwardRefExoticComponent<ItemRepeaterProps & React.RefAttributes<HTMLElement>>;
|
|
149
|
+
/**
|
|
150
|
+
* Props for Booking.Service component
|
|
151
|
+
*/
|
|
152
|
+
export interface BookingServiceProps {
|
|
153
|
+
children: React.ReactNode;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Wraps Service.Root with the service from the current booking item context.
|
|
157
|
+
* Children can use all Service.* components (Service.Name, Service.Price, etc.).
|
|
158
|
+
*
|
|
159
|
+
* @component
|
|
160
|
+
* @example
|
|
161
|
+
* ```tsx
|
|
162
|
+
* <Booking.Service>
|
|
163
|
+
* <Service.Name className="text-xl font-bold" />
|
|
164
|
+
* <Service.Description />
|
|
165
|
+
* <Service.Price />
|
|
166
|
+
* </Booking.Service>
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
export declare function Service(props: BookingServiceProps): React.ReactNode;
|
|
170
|
+
/**
|
|
171
|
+
* Props for Booking.TimeSlot component
|
|
172
|
+
*/
|
|
173
|
+
export interface BookingTimeSlotProps {
|
|
174
|
+
children: React.ReactNode;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Wraps TimeSlot.Root with the timeSlot from the current booking item context.
|
|
178
|
+
* Children can use all TimeSlot.* components (TimeSlot.StartDate, TimeSlot.Duration, etc.).
|
|
179
|
+
* Always renders with data-has-time-slot attribute for CSS targeting.
|
|
180
|
+
*
|
|
181
|
+
* @component
|
|
182
|
+
* @example
|
|
183
|
+
* ```tsx
|
|
184
|
+
* <Booking.TimeSlot>
|
|
185
|
+
* <TimeSlot.StartDate />
|
|
186
|
+
* <TimeSlot.Duration />
|
|
187
|
+
* </Booking.TimeSlot>
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export declare function TimeSlot(props: BookingTimeSlotProps): React.ReactNode;
|
|
191
|
+
/**
|
|
192
|
+
* Props for Booking.Payment component
|
|
193
|
+
*/
|
|
194
|
+
export interface BookingPaymentProps {
|
|
195
|
+
children: React.ReactNode;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Wraps Payment.Root with all services from all booking items.
|
|
199
|
+
* Should be used outside of ItemRepeater - it calculates payment for all items.
|
|
200
|
+
* Children can use all Payment.* components (Payment.Total, Payment.Subtotal, etc.).
|
|
201
|
+
* Always renders with data-has-payment attribute for CSS targeting.
|
|
202
|
+
*
|
|
203
|
+
* @component
|
|
204
|
+
* @example
|
|
205
|
+
* ```tsx
|
|
206
|
+
* <Booking.Root>
|
|
207
|
+
* <Booking.ItemsRoot>
|
|
208
|
+
* <Booking.Items>
|
|
209
|
+
* <Booking.ItemRepeater>
|
|
210
|
+
* <Booking.Service><Service.Name /></Booking.Service>
|
|
211
|
+
* </Booking.ItemRepeater>
|
|
212
|
+
* </Booking.Items>
|
|
213
|
+
* </Booking.ItemsRoot>
|
|
214
|
+
*
|
|
215
|
+
* <Booking.Payment>
|
|
216
|
+
* <Payment.Total className="text-xl font-bold" />
|
|
217
|
+
* <Payment.Subtotal />
|
|
218
|
+
* </Booking.Payment>
|
|
219
|
+
* </Booking.Root>
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
222
|
+
export declare function Payment(props: BookingPaymentProps): React.ReactNode;
|
|
223
|
+
/**
|
|
224
|
+
* Props for Booking.Location component
|
|
225
|
+
*/
|
|
226
|
+
export interface BookingLocationProps {
|
|
227
|
+
children: React.ReactNode;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Wraps Location context with the location from the booking context.
|
|
231
|
+
* Children can use all Location.* components (Location.Name, Location.Address, etc.).
|
|
232
|
+
* Returns null if no location is set.
|
|
233
|
+
*
|
|
234
|
+
* @component
|
|
235
|
+
* @example
|
|
236
|
+
* ```tsx
|
|
237
|
+
* <Booking.Location>
|
|
238
|
+
* <Location.Name className="font-bold" />
|
|
239
|
+
* <Location.Address />
|
|
240
|
+
* <Location.Phone />
|
|
241
|
+
* </Booking.Location>
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
export declare function Location(props: BookingLocationProps): React.ReactNode;
|
|
245
|
+
/**
|
|
246
|
+
* Props for Booking.StaffName component
|
|
247
|
+
*/
|
|
248
|
+
export interface StaffNameProps {
|
|
249
|
+
asChild?: boolean;
|
|
250
|
+
children?: AsChildChildren<{
|
|
251
|
+
name: string;
|
|
252
|
+
}>;
|
|
253
|
+
className?: string;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Displays the first staff member's name from the current booking item.
|
|
257
|
+
* Returns null when staff name is empty.
|
|
258
|
+
*
|
|
259
|
+
* @component
|
|
260
|
+
* @example
|
|
261
|
+
* ```tsx
|
|
262
|
+
* <Booking.StaffName className="text-foreground" />
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
265
|
+
export declare const StaffName: React.ForwardRefExoticComponent<StaffNameProps & React.RefAttributes<HTMLElement>>;
|