@wix/headless-bookings 0.0.87 → 0.0.89
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 +36 -117
- package/cjs/dist/react/booking/Booking.js +40 -109
- package/cjs/dist/react/booking/BookingItem.d.ts +64 -0
- package/cjs/dist/react/booking/BookingItem.js +71 -0
- package/cjs/dist/react/core/payment/Payment.d.ts +3 -3
- package/cjs/dist/react/core/payment/Payment.js +4 -4
- package/cjs/dist/react/core/time-slot-list/TimeSlotList.d.ts +2 -0
- package/cjs/dist/react/core/time-slot-list/TimeSlotList.js +3 -0
- package/cjs/dist/react/index.d.ts +1 -0
- package/cjs/dist/react/index.js +1 -0
- package/cjs/dist/react/payment/Payment.d.ts +3 -46
- package/cjs/dist/react/payment/Payment.js +4 -37
- package/cjs/dist/react/service/Service.d.ts +0 -2
- package/cjs/dist/react/service/Service.js +3 -3
- package/cjs/dist/react/service/ServiceMedia.d.ts +1 -63
- package/cjs/dist/react/service/ServiceMedia.js +1 -60
- package/cjs/dist/react/time-slot-list/TimeSlot.d.ts +21 -6
- package/cjs/dist/react/time-slot-list/TimeSlot.js +34 -14
- package/cjs/dist/react/time-slot-list/TimeSlotList.d.ts +3 -49
- package/cjs/dist/react/time-slot-list/TimeSlotList.js +24 -21
- package/cjs/dist/services/payment/payment.d.ts +2 -2
- package/cjs/dist/services/payment/payment.def.d.ts +1 -1
- package/cjs/dist/services/payment/payment.js +11 -11
- package/dist/react/booking/Booking.d.ts +36 -117
- package/dist/react/booking/Booking.js +40 -109
- package/dist/react/booking/BookingItem.d.ts +64 -0
- package/dist/react/booking/BookingItem.js +71 -0
- package/dist/react/core/payment/Payment.d.ts +3 -3
- package/dist/react/core/payment/Payment.js +4 -4
- package/dist/react/core/time-slot-list/TimeSlotList.d.ts +2 -0
- package/dist/react/core/time-slot-list/TimeSlotList.js +3 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/react/payment/Payment.d.ts +3 -46
- package/dist/react/payment/Payment.js +4 -37
- package/dist/react/service/Service.d.ts +0 -2
- package/dist/react/service/Service.js +3 -3
- package/dist/react/service/ServiceMedia.d.ts +1 -63
- package/dist/react/service/ServiceMedia.js +1 -60
- package/dist/react/time-slot-list/TimeSlot.d.ts +21 -6
- package/dist/react/time-slot-list/TimeSlot.js +34 -14
- package/dist/react/time-slot-list/TimeSlotList.d.ts +3 -49
- package/dist/react/time-slot-list/TimeSlotList.js +24 -21
- package/dist/services/payment/payment.d.ts +2 -2
- package/dist/services/payment/payment.def.d.ts +1 -1
- package/dist/services/payment/payment.js +11 -11
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
3
|
* TimeSlotList - High-level component for displaying time slot list information
|
|
4
4
|
* Provides components for displaying timezone and time slot data
|
|
@@ -6,6 +6,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import { GenericList } from '@wix/headless-components/react';
|
|
8
8
|
import { AsChildSlot } from '@wix/headless-utils/react';
|
|
9
|
+
import { startOfDay, endOfDay, parse, format } from 'date-fns';
|
|
9
10
|
import * as CoreTimeSlotList from '../core/time-slot-list/TimeSlotList.js';
|
|
10
11
|
import * as CoreTimeSlot from '../core/time-slot-list/TimeSlot.js';
|
|
11
12
|
import { StartDate as TimeSlotStartDate, EndDate as TimeSlotEndDate, Duration, Actions as TimeSlotActions, Location, StaffMembers, StaffMemberRepeater, StaffMember, Root as TimeSlotRoot, } from './TimeSlot.js';
|
|
@@ -14,9 +15,19 @@ import { StartDate as TimeSlotStartDate, EndDate as TimeSlotEndDate, Duration, A
|
|
|
14
15
|
// ============================================================================
|
|
15
16
|
/**
|
|
16
17
|
* Converts a Date to ISO date string format (YYYY-MM-DD) for input[type="date"]
|
|
18
|
+
* Uses the specified timezone or falls back to local timezone
|
|
17
19
|
*/
|
|
18
|
-
function toISODateString(date) {
|
|
19
|
-
|
|
20
|
+
function toISODateString(date, timezone) {
|
|
21
|
+
if (timezone) {
|
|
22
|
+
const formatter = new Intl.DateTimeFormat('en-CA', {
|
|
23
|
+
timeZone: timezone,
|
|
24
|
+
year: 'numeric',
|
|
25
|
+
month: '2-digit',
|
|
26
|
+
day: '2-digit',
|
|
27
|
+
});
|
|
28
|
+
return formatter.format(date);
|
|
29
|
+
}
|
|
30
|
+
return format(date, 'yyyy-MM-dd');
|
|
20
31
|
}
|
|
21
32
|
/**
|
|
22
33
|
* TimeSlot with required id field for GenericList
|
|
@@ -117,34 +128,22 @@ export const TimeSlots = React.forwardRef((props, ref) => {
|
|
|
117
128
|
TimeSlots.displayName = 'TimeSlotList.TimeSlots';
|
|
118
129
|
/**
|
|
119
130
|
* Internal component that wraps each time slot item with context provider.
|
|
120
|
-
* Supports both ReactNode and function children patterns.
|
|
121
131
|
*/
|
|
122
132
|
const TimeSlotItemWrapper = ({ timeSlot, children, }) => {
|
|
123
|
-
return (_jsx(TimeSlotRoot, { timeSlot: timeSlot, children: _jsx(CoreTimeSlot.Info, { children: (props) => (_jsx("div", { "data-testid": TestIds.timeSlotListTimeSlot, "data-bookable": props.bookable, "data-selected": props.isSelected, children:
|
|
133
|
+
return (_jsx(TimeSlotRoot, { timeSlot: timeSlot, children: _jsx(CoreTimeSlot.Info, { children: (props) => (_jsx("div", { "data-testid": TestIds.timeSlotListTimeSlot, "data-bookable": props.bookable, "data-selected": props.isSelected, children: children })) }) }));
|
|
124
134
|
};
|
|
125
135
|
/**
|
|
126
|
-
* Repeater component that renders each time slot.
|
|
136
|
+
* Repeater component that renders TimeSlot.Root for each time slot.
|
|
127
137
|
* Follows Repeater Level pattern and uses GenericList.Repeater for consistency.
|
|
128
|
-
* Automatically provides TimeSlot context to children.
|
|
129
138
|
*
|
|
130
139
|
* @component
|
|
131
140
|
* @example
|
|
132
141
|
* ```tsx
|
|
133
|
-
* // Standard usage with nested components
|
|
134
142
|
* <TimeSlotList.TimeSlotRepeater>
|
|
135
143
|
* <TimeSlot.StartDate />
|
|
136
144
|
* <TimeSlot.Duration />
|
|
137
145
|
* <TimeSlot.Actions.Select />
|
|
138
146
|
* </TimeSlotList.TimeSlotRepeater>
|
|
139
|
-
*
|
|
140
|
-
* // Function children pattern - all data available directly
|
|
141
|
-
* <TimeSlotList.TimeSlotRepeater>
|
|
142
|
-
* {({ isSelected, bookable, startDate }) => (
|
|
143
|
-
* <button disabled={!bookable} className={isSelected ? 'selected' : ''}>
|
|
144
|
-
* {formatTime(startDate)}
|
|
145
|
-
* </button>
|
|
146
|
-
* )}
|
|
147
|
-
* </TimeSlotList.TimeSlotRepeater>
|
|
148
147
|
* ```
|
|
149
148
|
*/
|
|
150
149
|
const generateSlotKey = (timeSlot) => {
|
|
@@ -152,7 +151,7 @@ const generateSlotKey = (timeSlot) => {
|
|
|
152
151
|
};
|
|
153
152
|
export const TimeSlotRepeater = React.forwardRef((props, ref) => {
|
|
154
153
|
const { children } = props;
|
|
155
|
-
return (_jsx(GenericList.Repeater, { ref: ref, itemWrapper: ({ item: timeSlot }) => (_jsx(TimeSlotItemWrapper, { timeSlot: timeSlot, children:
|
|
154
|
+
return (_jsx(GenericList.Repeater, { ref: ref, itemWrapper: ({ item: timeSlot, children: itemChildren }) => (_jsx(TimeSlotItemWrapper, { timeSlot: timeSlot, children: itemChildren }, generateSlotKey(timeSlot))), children: children }));
|
|
156
155
|
});
|
|
157
156
|
TimeSlotRepeater.displayName = 'TimeSlotList.TimeSlotRepeater';
|
|
158
157
|
/**
|
|
@@ -203,14 +202,18 @@ export const Actions = {
|
|
|
203
202
|
* </TimeSlotList.DateRange.Input>
|
|
204
203
|
* ```
|
|
205
204
|
*/
|
|
206
|
-
|
|
205
|
+
const DateRangeInput = React.forwardRef((props, ref) => {
|
|
207
206
|
const { asChild, children, className, ...otherProps } = props;
|
|
208
|
-
return (_jsx(CoreTimeSlotList.DateRange, { children: ({ startDate, endDate, setDateRange }) => {
|
|
209
|
-
const defaultContent = (
|
|
207
|
+
return (_jsx(CoreTimeSlotList.DateRange, { children: ({ startDate, endDate, setDateRange, timezone }) => {
|
|
208
|
+
const defaultContent = (_jsx("input", { ref: ref, type: "date", className: className, "data-testid": TestIds.timeSlotListDateRangeInput, value: toISODateString(startDate, timezone), required: true, onChange: (e) => {
|
|
209
|
+
const date = parse(e.target.value, 'yyyy-MM-dd', new Date());
|
|
210
|
+
setDateRange(startOfDay(date), endOfDay(date));
|
|
211
|
+
} }));
|
|
210
212
|
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotListDateRangeInput, customElement: children, customElementProps: {
|
|
211
213
|
startDate,
|
|
212
214
|
endDate,
|
|
213
215
|
onChange: setDateRange,
|
|
216
|
+
timezone,
|
|
214
217
|
}, ...otherProps, children: defaultContent }));
|
|
215
218
|
} }));
|
|
216
219
|
});
|
|
@@ -24,9 +24,9 @@ export type ErrorPaymentConfigResult = {
|
|
|
24
24
|
* Calls the pricing APIs and returns pre-calculated payment details.
|
|
25
25
|
*
|
|
26
26
|
* @param params.pricingServiceSelections - Pricing service selections for calculation
|
|
27
|
-
* @param params.
|
|
27
|
+
* @param params.totalParticipants - Number of participants (default: 1)
|
|
28
28
|
*/
|
|
29
29
|
export declare function loadPaymentConfig(params: {
|
|
30
30
|
pricingServiceSelections: PricingServiceSelection[];
|
|
31
|
-
|
|
31
|
+
totalParticipants?: number;
|
|
32
32
|
}): Promise<SuccessPaymentConfigResult | ErrorPaymentConfigResult>;
|
|
@@ -53,7 +53,7 @@ export interface PaymentServiceInternalConfig extends PaymentServiceConfig {
|
|
|
53
53
|
/** Booking services for lazy loading (internal use) */
|
|
54
54
|
pricingServiceSelections?: PricingServiceSelection[];
|
|
55
55
|
/** Number of participants for lazy loading (internal use) */
|
|
56
|
-
|
|
56
|
+
totalParticipants?: number;
|
|
57
57
|
}
|
|
58
58
|
export interface PaymentServiceAPI {
|
|
59
59
|
paymentDetailsSignal: Signal<PaymentDetails | null>;
|
|
@@ -36,15 +36,15 @@ function getPaymentOption(service, hasDeposit) {
|
|
|
36
36
|
}
|
|
37
37
|
return 'FULL_PAYMENT_ONLINE';
|
|
38
38
|
}
|
|
39
|
-
function buildLineItem(service,
|
|
39
|
+
function buildLineItem(service, totalParticipants, lineItemId) {
|
|
40
40
|
// Get fixed price from service
|
|
41
41
|
const servicePrice = service.payment?.fixed?.price?.value;
|
|
42
|
-
const price = Number(servicePrice || 0) *
|
|
42
|
+
const price = Number(servicePrice || 0) * totalParticipants;
|
|
43
43
|
// Get deposit if configured
|
|
44
44
|
const depositValue = service.payment?.fixed?.deposit?.value;
|
|
45
45
|
const hasDeposit = !!depositValue && Number(depositValue) > 0;
|
|
46
46
|
const deposit = hasDeposit
|
|
47
|
-
? Number(depositValue) *
|
|
47
|
+
? Number(depositValue) * totalParticipants
|
|
48
48
|
: undefined;
|
|
49
49
|
// Get payment option from service configuration (pass hasDeposit for correct API behavior)
|
|
50
50
|
const paymentOption = getPaymentOption(service, hasDeposit);
|
|
@@ -60,13 +60,13 @@ function buildLineItem(service, numberOfParticipants, lineItemId) {
|
|
|
60
60
|
paymentOption,
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
|
-
async function calculatePaymentDetails(pricingServiceSelections,
|
|
63
|
+
async function calculatePaymentDetails(pricingServiceSelections, totalParticipants) {
|
|
64
64
|
// Ensure all booking services have a lineItemId
|
|
65
65
|
const data = pricingServiceSelections.map((selection) => ({
|
|
66
66
|
...selection,
|
|
67
67
|
lineItemId: selection.lineItemId || generateLineItemId(),
|
|
68
68
|
}));
|
|
69
|
-
const lineItems = data.map((item) => buildLineItem(item.service,
|
|
69
|
+
const lineItems = data.map((item) => buildLineItem(item.service, totalParticipants, item.lineItemId));
|
|
70
70
|
const response = await calculateTotals({
|
|
71
71
|
lineItems,
|
|
72
72
|
});
|
|
@@ -96,7 +96,7 @@ export const PaymentService = implementService.withConfig()(PaymentServiceDefini
|
|
|
96
96
|
const isLoadingSignal = signalsService.signal(false);
|
|
97
97
|
const errorSignal = signalsService.signal(null);
|
|
98
98
|
// Internal calculate function
|
|
99
|
-
const calculate = async (pricingServiceSelections,
|
|
99
|
+
const calculate = async (pricingServiceSelections, totalParticipants) => {
|
|
100
100
|
if (!pricingServiceSelections.length) {
|
|
101
101
|
paymentDetailsSignal.set(null);
|
|
102
102
|
return;
|
|
@@ -104,7 +104,7 @@ export const PaymentService = implementService.withConfig()(PaymentServiceDefini
|
|
|
104
104
|
isLoadingSignal.set(true);
|
|
105
105
|
errorSignal.set(null);
|
|
106
106
|
try {
|
|
107
|
-
const paymentDetails = await calculatePaymentDetails(pricingServiceSelections,
|
|
107
|
+
const paymentDetails = await calculatePaymentDetails(pricingServiceSelections, totalParticipants);
|
|
108
108
|
paymentDetailsSignal.set(paymentDetails);
|
|
109
109
|
}
|
|
110
110
|
catch (error) {
|
|
@@ -124,7 +124,7 @@ export const PaymentService = implementService.withConfig()(PaymentServiceDefini
|
|
|
124
124
|
}
|
|
125
125
|
// Mode 2: Lazy loading - pricingServiceSelections provided via internal config
|
|
126
126
|
else if (config.pricingServiceSelections?.length) {
|
|
127
|
-
void calculate(config.pricingServiceSelections, config.
|
|
127
|
+
void calculate(config.pricingServiceSelections, config.totalParticipants ?? 1);
|
|
128
128
|
}
|
|
129
129
|
// Mode 3: Reactive - observe BookingService signals (client-side only)
|
|
130
130
|
else if (typeof window !== 'undefined' && bookingService) {
|
|
@@ -159,18 +159,18 @@ export const PaymentService = implementService.withConfig()(PaymentServiceDefini
|
|
|
159
159
|
* Calls the pricing APIs and returns pre-calculated payment details.
|
|
160
160
|
*
|
|
161
161
|
* @param params.pricingServiceSelections - Pricing service selections for calculation
|
|
162
|
-
* @param params.
|
|
162
|
+
* @param params.totalParticipants - Number of participants (default: 1)
|
|
163
163
|
*/
|
|
164
164
|
export async function loadPaymentConfig(params) {
|
|
165
165
|
try {
|
|
166
|
-
const { pricingServiceSelections,
|
|
166
|
+
const { pricingServiceSelections, totalParticipants = 1 } = params;
|
|
167
167
|
if (!pricingServiceSelections.length) {
|
|
168
168
|
return {
|
|
169
169
|
type: 'success',
|
|
170
170
|
config: { paymentDetails: undefined },
|
|
171
171
|
};
|
|
172
172
|
}
|
|
173
|
-
const paymentDetails = await calculatePaymentDetails(pricingServiceSelections,
|
|
173
|
+
const paymentDetails = await calculatePaymentDetails(pricingServiceSelections, totalParticipants);
|
|
174
174
|
return {
|
|
175
175
|
type: 'success',
|
|
176
176
|
config: { paymentDetails },
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import * as CoreBooking from '../core/booking/Booking.js';
|
|
7
7
|
import type { BookingServiceConfig } from '../../services/booking/booking.js';
|
|
8
|
-
import
|
|
8
|
+
import * as BookingItemComponents from './BookingItem.js';
|
|
9
9
|
export type { BookingData, DataProps, BookingItem, } from '../core/booking/Booking.js';
|
|
10
10
|
/**
|
|
11
11
|
* Props for Booking.Root component
|
|
@@ -63,132 +63,70 @@ export declare const Actions: {
|
|
|
63
63
|
*/
|
|
64
64
|
export declare const useBookingItem: typeof CoreBooking.useBookingItemContext;
|
|
65
65
|
/**
|
|
66
|
-
* Props for Booking.
|
|
66
|
+
* Props for Booking.BookingItems component
|
|
67
67
|
*/
|
|
68
|
-
export interface
|
|
69
|
-
children: React.ReactNode;
|
|
70
|
-
className?: string;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Container component that provides GenericList.Root context for booking items.
|
|
74
|
-
* Use Booking.Items inside for list container with emptyState support.
|
|
75
|
-
*
|
|
76
|
-
* @component
|
|
77
|
-
* @example
|
|
78
|
-
* ```tsx
|
|
79
|
-
* <Booking.ItemsRoot>
|
|
80
|
-
* <Booking.Items emptyState={<div>No bookings selected</div>}>
|
|
81
|
-
* <Booking.ItemRepeater>
|
|
82
|
-
* <div className="booking-card">
|
|
83
|
-
* <Booking.Service>
|
|
84
|
-
* <Service.Name />
|
|
85
|
-
* </Booking.Service>
|
|
86
|
-
* </div>
|
|
87
|
-
* </Booking.ItemRepeater>
|
|
88
|
-
* </Booking.Items>
|
|
89
|
-
* </Booking.ItemsRoot>
|
|
90
|
-
* ```
|
|
91
|
-
*/
|
|
92
|
-
export declare const ItemsRoot: React.ForwardRefExoticComponent<ItemsRootProps & React.RefAttributes<HTMLDivElement>>;
|
|
93
|
-
/**
|
|
94
|
-
* Props for Booking.Items component (List Container Level)
|
|
95
|
-
*/
|
|
96
|
-
export interface ItemsProps {
|
|
68
|
+
export interface BookingItemsProps {
|
|
97
69
|
children: React.ReactNode;
|
|
98
70
|
/** Content to render when there are no booking items */
|
|
99
71
|
emptyState?: React.ReactNode;
|
|
100
72
|
className?: string;
|
|
101
73
|
}
|
|
102
74
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
75
|
+
* Container component for booking items with emptyState support.
|
|
76
|
+
* Provides GenericList context and renders items.
|
|
105
77
|
*
|
|
106
78
|
* @component
|
|
107
79
|
* @example
|
|
108
80
|
* ```tsx
|
|
109
|
-
* <Booking.
|
|
110
|
-
* <Booking.
|
|
111
|
-
* <
|
|
112
|
-
* <
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* </Booking.Items>
|
|
117
|
-
* </Booking.ItemsRoot>
|
|
81
|
+
* <Booking.BookingItems emptyState={<div>No bookings selected</div>}>
|
|
82
|
+
* <Booking.BookingItemRepeater>
|
|
83
|
+
* <BookingItem.Service>
|
|
84
|
+
* <Service.Name />
|
|
85
|
+
* </BookingItem.Service>
|
|
86
|
+
* </Booking.BookingItemRepeater>
|
|
87
|
+
* </Booking.BookingItems>
|
|
118
88
|
* ```
|
|
119
89
|
*/
|
|
120
|
-
export declare const
|
|
90
|
+
export declare const BookingItems: React.ForwardRefExoticComponent<BookingItemsProps & React.RefAttributes<HTMLDivElement>>;
|
|
91
|
+
/** @deprecated Use Booking.BookingItems instead */
|
|
92
|
+
export declare const ItemsRoot: React.ForwardRefExoticComponent<BookingItemsProps & React.RefAttributes<HTMLDivElement>>;
|
|
93
|
+
/** @deprecated Use Booking.BookingItems instead */
|
|
94
|
+
export declare const Items: React.ForwardRefExoticComponent<BookingItemsProps & React.RefAttributes<HTMLDivElement>>;
|
|
121
95
|
/**
|
|
122
|
-
* Props for Booking.
|
|
96
|
+
* Props for Booking.BookingItemRepeater component
|
|
123
97
|
*/
|
|
124
|
-
export interface
|
|
98
|
+
export interface BookingItemRepeaterProps {
|
|
125
99
|
children: React.ReactNode;
|
|
126
100
|
}
|
|
127
101
|
/**
|
|
128
102
|
* Repeater component that maps over booking items and provides context per item.
|
|
129
103
|
* Uses GenericList.Repeater internally with itemWrapper that provides BookingItemContext.
|
|
130
|
-
* Children have access to
|
|
104
|
+
* Children have access to BookingItem.Service, BookingItem.TimeSlot, etc.
|
|
131
105
|
*
|
|
132
106
|
* @component
|
|
133
107
|
* @example
|
|
134
108
|
* ```tsx
|
|
135
|
-
* <Booking.
|
|
109
|
+
* <Booking.BookingItemRepeater>
|
|
136
110
|
* <div className="booking-card">
|
|
137
|
-
* <
|
|
111
|
+
* <BookingItem.Service>
|
|
138
112
|
* <Service.Name />
|
|
139
113
|
* <Service.Price />
|
|
140
|
-
* </
|
|
141
|
-
* <
|
|
114
|
+
* </BookingItem.Service>
|
|
115
|
+
* <BookingItem.TimeSlot>
|
|
142
116
|
* <TimeSlot.StartDate />
|
|
143
|
-
* </
|
|
144
|
-
* <
|
|
117
|
+
* </BookingItem.TimeSlot>
|
|
118
|
+
* <BookingItem.StaffName />
|
|
145
119
|
* </div>
|
|
146
|
-
* </Booking.
|
|
147
|
-
* ```
|
|
148
|
-
*/
|
|
149
|
-
export declare const ItemRepeater: React.ForwardRefExoticComponent<ItemRepeaterProps & React.RefAttributes<HTMLElement>>;
|
|
150
|
-
/**
|
|
151
|
-
* Props for Booking.Service component
|
|
152
|
-
*/
|
|
153
|
-
export interface BookingServiceProps {
|
|
154
|
-
children: React.ReactNode;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Wraps Service.Root with the service from the current booking item context.
|
|
158
|
-
* Children can use all Service.* components (Service.Name, Service.Price, etc.).
|
|
159
|
-
*
|
|
160
|
-
* @component
|
|
161
|
-
* @example
|
|
162
|
-
* ```tsx
|
|
163
|
-
* <Booking.Service>
|
|
164
|
-
* <Service.Name className="text-xl font-bold" />
|
|
165
|
-
* <Service.Description />
|
|
166
|
-
* <Service.Price />
|
|
167
|
-
* </Booking.Service>
|
|
120
|
+
* </Booking.BookingItemRepeater>
|
|
168
121
|
* ```
|
|
169
122
|
*/
|
|
170
|
-
export declare
|
|
171
|
-
/**
|
|
172
|
-
|
|
173
|
-
*/
|
|
174
|
-
export
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Wraps TimeSlot.Root with the timeSlot from the current booking item context.
|
|
179
|
-
* Children can use all TimeSlot.* components (TimeSlot.StartDate, TimeSlot.Duration, etc.).
|
|
180
|
-
* Always renders with data-has-time-slot attribute for CSS targeting.
|
|
181
|
-
*
|
|
182
|
-
* @component
|
|
183
|
-
* @example
|
|
184
|
-
* ```tsx
|
|
185
|
-
* <Booking.TimeSlot>
|
|
186
|
-
* <TimeSlot.StartDate />
|
|
187
|
-
* <TimeSlot.Duration />
|
|
188
|
-
* </Booking.TimeSlot>
|
|
189
|
-
* ```
|
|
190
|
-
*/
|
|
191
|
-
export declare function TimeSlot(props: BookingTimeSlotProps): React.ReactNode;
|
|
123
|
+
export declare const BookingItemRepeater: React.ForwardRefExoticComponent<BookingItemRepeaterProps & React.RefAttributes<HTMLElement>>;
|
|
124
|
+
/** @deprecated Use Booking.BookingItemRepeater instead */
|
|
125
|
+
export declare const ItemRepeater: React.ForwardRefExoticComponent<BookingItemRepeaterProps & React.RefAttributes<HTMLElement>>;
|
|
126
|
+
/** @deprecated Use BookingItem.Service instead */
|
|
127
|
+
export declare const Service: typeof BookingItemComponents.Service;
|
|
128
|
+
/** @deprecated Use BookingItem.TimeSlot instead */
|
|
129
|
+
export declare const TimeSlot: typeof BookingItemComponents.TimeSlot;
|
|
192
130
|
/**
|
|
193
131
|
* Props for Booking.Payment component
|
|
194
132
|
*/
|
|
@@ -244,24 +182,5 @@ export interface BookingLocationProps {
|
|
|
244
182
|
* ```
|
|
245
183
|
*/
|
|
246
184
|
export declare function Location(props: BookingLocationProps): React.ReactNode;
|
|
247
|
-
/**
|
|
248
|
-
|
|
249
|
-
*/
|
|
250
|
-
export interface StaffNameProps {
|
|
251
|
-
asChild?: boolean;
|
|
252
|
-
children?: AsChildChildren<{
|
|
253
|
-
name: string;
|
|
254
|
-
}>;
|
|
255
|
-
className?: string;
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Displays the first staff member's name from the current booking item.
|
|
259
|
-
* Returns null when staff name is empty.
|
|
260
|
-
*
|
|
261
|
-
* @component
|
|
262
|
-
* @example
|
|
263
|
-
* ```tsx
|
|
264
|
-
* <Booking.StaffName className="text-foreground" />
|
|
265
|
-
* ```
|
|
266
|
-
*/
|
|
267
|
-
export declare const StaffName: React.ForwardRefExoticComponent<StaffNameProps & React.RefAttributes<HTMLElement>>;
|
|
185
|
+
/** @deprecated Use BookingItem.StaffName instead */
|
|
186
|
+
export declare const StaffName: React.ForwardRefExoticComponent<BookingItemComponents.StaffNameProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -6,12 +6,11 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import * as CoreBooking from '../core/booking/Booking.js';
|
|
8
8
|
import { Book } from './Book.js';
|
|
9
|
-
import { AsChildSlot } from '@wix/headless-utils/react';
|
|
10
|
-
import * as ServiceComponent from '../service/Service.js';
|
|
11
|
-
import * as TimeSlotComponent from '../time-slot-list/TimeSlot.js';
|
|
12
9
|
import * as PaymentComponent from '../payment/Payment.js';
|
|
13
10
|
import * as CoreLocation from '../core/location/Location.js';
|
|
14
11
|
import { GenericList } from '@wix/headless-components/react';
|
|
12
|
+
// Re-export BookingItem components for backward compatibility
|
|
13
|
+
import * as BookingItemComponents from './BookingItem.js';
|
|
15
14
|
// ============================================================================
|
|
16
15
|
// TestIds
|
|
17
16
|
// ============================================================================
|
|
@@ -82,56 +81,33 @@ export const Actions = {
|
|
|
82
81
|
*/
|
|
83
82
|
export const useBookingItem = CoreBooking.useBookingItemContext;
|
|
84
83
|
/**
|
|
85
|
-
* Container component
|
|
86
|
-
*
|
|
84
|
+
* Container component for booking items with emptyState support.
|
|
85
|
+
* Provides GenericList context and renders items.
|
|
87
86
|
*
|
|
88
87
|
* @component
|
|
89
88
|
* @example
|
|
90
89
|
* ```tsx
|
|
91
|
-
* <Booking.
|
|
92
|
-
* <Booking.
|
|
93
|
-
* <
|
|
94
|
-
* <
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* </div>
|
|
99
|
-
* </Booking.ItemRepeater>
|
|
100
|
-
* </Booking.Items>
|
|
101
|
-
* </Booking.ItemsRoot>
|
|
90
|
+
* <Booking.BookingItems emptyState={<div>No bookings selected</div>}>
|
|
91
|
+
* <Booking.BookingItemRepeater>
|
|
92
|
+
* <BookingItem.Service>
|
|
93
|
+
* <Service.Name />
|
|
94
|
+
* </BookingItem.Service>
|
|
95
|
+
* </Booking.BookingItemRepeater>
|
|
96
|
+
* </Booking.BookingItems>
|
|
102
97
|
* ```
|
|
103
98
|
*/
|
|
104
|
-
export const
|
|
105
|
-
const { children, ...otherProps } = props;
|
|
99
|
+
export const BookingItems = React.forwardRef((props, ref) => {
|
|
100
|
+
const { children, emptyState, ...otherProps } = props;
|
|
106
101
|
return (_jsx(CoreBooking.ItemsData, { children: ({ items }) => (_jsx(GenericList.Root, { ref: ref, items: items.map((item) => ({
|
|
107
102
|
...item,
|
|
108
103
|
id: item.instanceId,
|
|
109
|
-
})), hasMore: false, isLoading: false, "data-testid": TestIds.
|
|
110
|
-
});
|
|
111
|
-
ItemsRoot.displayName = 'Booking.ItemsRoot';
|
|
112
|
-
/**
|
|
113
|
-
* List container component with emptyState support.
|
|
114
|
-
* Wraps GenericList.Items. Must be used within Booking.ItemsRoot.
|
|
115
|
-
*
|
|
116
|
-
* @component
|
|
117
|
-
* @example
|
|
118
|
-
* ```tsx
|
|
119
|
-
* <Booking.ItemsRoot>
|
|
120
|
-
* <Booking.Items emptyState={<div>No bookings selected</div>}>
|
|
121
|
-
* <Booking.ItemRepeater>
|
|
122
|
-
* <Booking.Service>
|
|
123
|
-
* <Service.Name />
|
|
124
|
-
* </Booking.Service>
|
|
125
|
-
* </Booking.ItemRepeater>
|
|
126
|
-
* </Booking.Items>
|
|
127
|
-
* </Booking.ItemsRoot>
|
|
128
|
-
* ```
|
|
129
|
-
*/
|
|
130
|
-
export const Items = React.forwardRef((props, ref) => {
|
|
131
|
-
const { children, ...otherProps } = props;
|
|
132
|
-
return (_jsx(GenericList.Items, { ref: ref, "data-testid": TestIds.bookingItems, ...otherProps, children: children }));
|
|
104
|
+
})), hasMore: false, isLoading: false, "data-testid": TestIds.bookingItems, ...otherProps, children: _jsx(GenericList.Items, { emptyState: emptyState, children: children }) })) }));
|
|
133
105
|
});
|
|
134
|
-
|
|
106
|
+
BookingItems.displayName = 'Booking.BookingItems';
|
|
107
|
+
/** @deprecated Use Booking.BookingItems instead */
|
|
108
|
+
export const ItemsRoot = BookingItems;
|
|
109
|
+
/** @deprecated Use Booking.BookingItems instead */
|
|
110
|
+
export const Items = BookingItems;
|
|
135
111
|
/**
|
|
136
112
|
* Internal component that wraps each booking item with context provider.
|
|
137
113
|
*/
|
|
@@ -141,66 +117,39 @@ const BookingItemWrapper = ({ item, children, }) => {
|
|
|
141
117
|
/**
|
|
142
118
|
* Repeater component that maps over booking items and provides context per item.
|
|
143
119
|
* Uses GenericList.Repeater internally with itemWrapper that provides BookingItemContext.
|
|
144
|
-
* Children have access to
|
|
120
|
+
* Children have access to BookingItem.Service, BookingItem.TimeSlot, etc.
|
|
145
121
|
*
|
|
146
122
|
* @component
|
|
147
123
|
* @example
|
|
148
124
|
* ```tsx
|
|
149
|
-
* <Booking.
|
|
125
|
+
* <Booking.BookingItemRepeater>
|
|
150
126
|
* <div className="booking-card">
|
|
151
|
-
* <
|
|
127
|
+
* <BookingItem.Service>
|
|
152
128
|
* <Service.Name />
|
|
153
129
|
* <Service.Price />
|
|
154
|
-
* </
|
|
155
|
-
* <
|
|
130
|
+
* </BookingItem.Service>
|
|
131
|
+
* <BookingItem.TimeSlot>
|
|
156
132
|
* <TimeSlot.StartDate />
|
|
157
|
-
* </
|
|
158
|
-
* <
|
|
133
|
+
* </BookingItem.TimeSlot>
|
|
134
|
+
* <BookingItem.StaffName />
|
|
159
135
|
* </div>
|
|
160
|
-
* </Booking.
|
|
136
|
+
* </Booking.BookingItemRepeater>
|
|
161
137
|
* ```
|
|
162
138
|
*/
|
|
163
|
-
export const
|
|
139
|
+
export const BookingItemRepeater = React.forwardRef((props, ref) => {
|
|
164
140
|
const { children } = props;
|
|
165
141
|
return (_jsx(GenericList.Repeater, { ref: ref, itemWrapper: ({ item }) => (_jsx(BookingItemWrapper, { item: item, children: children }, item.instanceId)), children: undefined }));
|
|
166
142
|
});
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
* <Service.Description />
|
|
178
|
-
* <Service.Price />
|
|
179
|
-
* </Booking.Service>
|
|
180
|
-
* ```
|
|
181
|
-
*/
|
|
182
|
-
export function Service(props) {
|
|
183
|
-
const { children } = props;
|
|
184
|
-
return (_jsx(CoreBooking.BookingItemInfo, { children: ({ service }) => (_jsx(ServiceComponent.Root, { service: service, children: children })) }));
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Wraps TimeSlot.Root with the timeSlot from the current booking item context.
|
|
188
|
-
* Children can use all TimeSlot.* components (TimeSlot.StartDate, TimeSlot.Duration, etc.).
|
|
189
|
-
* Always renders with data-has-time-slot attribute for CSS targeting.
|
|
190
|
-
*
|
|
191
|
-
* @component
|
|
192
|
-
* @example
|
|
193
|
-
* ```tsx
|
|
194
|
-
* <Booking.TimeSlot>
|
|
195
|
-
* <TimeSlot.StartDate />
|
|
196
|
-
* <TimeSlot.Duration />
|
|
197
|
-
* </Booking.TimeSlot>
|
|
198
|
-
* ```
|
|
199
|
-
*/
|
|
200
|
-
export function TimeSlot(props) {
|
|
201
|
-
const { children } = props;
|
|
202
|
-
return (_jsx(CoreBooking.BookingItemInfo, { children: ({ timeSlot }) => timeSlot ? (_jsx(TimeSlotComponent.Root, { timeSlot: timeSlot, children: children })) : null }));
|
|
203
|
-
}
|
|
143
|
+
BookingItemRepeater.displayName = 'Booking.BookingItemRepeater';
|
|
144
|
+
/** @deprecated Use Booking.BookingItemRepeater instead */
|
|
145
|
+
export const ItemRepeater = BookingItemRepeater;
|
|
146
|
+
// ============================================================================
|
|
147
|
+
// Deprecated: Service, TimeSlot, StaffName (moved to BookingItem namespace)
|
|
148
|
+
// ============================================================================
|
|
149
|
+
/** @deprecated Use BookingItem.Service instead */
|
|
150
|
+
export const Service = BookingItemComponents.Service;
|
|
151
|
+
/** @deprecated Use BookingItem.TimeSlot instead */
|
|
152
|
+
export const TimeSlot = BookingItemComponents.TimeSlot;
|
|
204
153
|
/**
|
|
205
154
|
* Wraps Payment.Root with all services from all booking items.
|
|
206
155
|
* Should be used outside of ItemRepeater - it calculates payment for all items.
|
|
@@ -245,23 +194,5 @@ export function Location(props) {
|
|
|
245
194
|
const { children } = props;
|
|
246
195
|
return (_jsx(CoreBooking.Data, { children: ({ location }) => location ? (_jsx(CoreLocation.Root, { location: location, children: children })) : null }));
|
|
247
196
|
}
|
|
248
|
-
/**
|
|
249
|
-
|
|
250
|
-
* Returns null when staff name is empty.
|
|
251
|
-
*
|
|
252
|
-
* @component
|
|
253
|
-
* @example
|
|
254
|
-
* ```tsx
|
|
255
|
-
* <Booking.StaffName className="text-foreground" />
|
|
256
|
-
* ```
|
|
257
|
-
*/
|
|
258
|
-
export const StaffName = React.forwardRef((props, ref) => {
|
|
259
|
-
const { asChild, children, className } = props;
|
|
260
|
-
return (_jsx(CoreBooking.BookingItemInfo, { children: ({ staffName }) => {
|
|
261
|
-
if (!staffName) {
|
|
262
|
-
return null;
|
|
263
|
-
}
|
|
264
|
-
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.bookingStaffName, customElement: children, customElementProps: { name: staffName }, children: _jsx("span", { children: staffName }) }));
|
|
265
|
-
} }));
|
|
266
|
-
});
|
|
267
|
-
StaffName.displayName = 'Booking.StaffName';
|
|
197
|
+
/** @deprecated Use BookingItem.StaffName instead */
|
|
198
|
+
export const StaffName = BookingItemComponents.StaffName;
|