@wix/headless-bookings 0.0.15 → 0.0.17
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/api/time-slot-list/index.d.ts +21 -1
- package/cjs/dist/api/time-slot-list/index.js +46 -8
- package/cjs/dist/react/core/booking/Booking.d.ts +17 -9
- package/cjs/dist/react/core/booking/Booking.js +13 -7
- package/cjs/dist/react/core/time-slot-list/TimeSlot.d.ts +22 -18
- package/cjs/dist/react/core/time-slot-list/TimeSlot.js +41 -28
- package/cjs/dist/react/core/time-slot-list/TimeSlotList.d.ts +39 -7
- package/cjs/dist/react/core/time-slot-list/TimeSlotList.js +56 -11
- package/cjs/dist/react/time-slot-list/TimeSlot.js +3 -3
- package/cjs/dist/react/time-slot-list/TimeSlotList.d.ts +55 -12
- package/cjs/dist/react/time-slot-list/TimeSlotList.js +47 -17
- package/cjs/dist/services/booking/booking.d.ts +48 -30
- package/cjs/dist/services/booking/booking.js +74 -44
- package/cjs/dist/services/index.d.ts +3 -3
- package/cjs/dist/services/service/service.js +10 -7
- package/cjs/dist/services/time-slot-list/index.d.ts +1 -1
- package/cjs/dist/services/time-slot-list/time-slot-list.d.ts +3 -3
- package/cjs/dist/services/time-slot-list/time-slot-list.def.d.ts +23 -4
- package/cjs/dist/services/time-slot-list/time-slot-list.js +146 -65
- package/dist/api/time-slot-list/index.d.ts +21 -1
- package/dist/api/time-slot-list/index.js +46 -8
- package/dist/react/core/booking/Booking.d.ts +17 -9
- package/dist/react/core/booking/Booking.js +13 -7
- package/dist/react/core/time-slot-list/TimeSlot.d.ts +22 -18
- package/dist/react/core/time-slot-list/TimeSlot.js +41 -28
- package/dist/react/core/time-slot-list/TimeSlotList.d.ts +39 -7
- package/dist/react/core/time-slot-list/TimeSlotList.js +56 -11
- package/dist/react/time-slot-list/TimeSlot.js +3 -3
- package/dist/react/time-slot-list/TimeSlotList.d.ts +55 -12
- package/dist/react/time-slot-list/TimeSlotList.js +47 -17
- package/dist/services/booking/booking.d.ts +48 -30
- package/dist/services/booking/booking.js +74 -44
- package/dist/services/index.d.ts +3 -3
- package/dist/services/service/service.js +10 -7
- package/dist/services/time-slot-list/index.d.ts +1 -1
- package/dist/services/time-slot-list/time-slot-list.d.ts +3 -3
- package/dist/services/time-slot-list/time-slot-list.def.d.ts +23 -4
- package/dist/services/time-slot-list/time-slot-list.js +146 -65
- package/package.json +3 -2
|
@@ -6,17 +6,17 @@
|
|
|
6
6
|
* which provides the TimeSlotProvider context.
|
|
7
7
|
*/
|
|
8
8
|
import React from 'react';
|
|
9
|
-
import type
|
|
9
|
+
import { type TimeSlot as TimeSlotType } from '../../../services/time-slot-list/time-slot-list.def.js';
|
|
10
10
|
/**
|
|
11
11
|
* Context value for TimeSlot components
|
|
12
12
|
*/
|
|
13
13
|
export interface TimeSlotContextValue {
|
|
14
14
|
/** The current time slot data */
|
|
15
|
-
|
|
16
|
-
/** Whether this slot is currently selected */
|
|
15
|
+
timeSlot: TimeSlotType;
|
|
16
|
+
/** Whether this time slot is currently selected */
|
|
17
17
|
isSelected: boolean;
|
|
18
|
-
/** Action to select this slot */
|
|
19
|
-
|
|
18
|
+
/** Action to select this time slot */
|
|
19
|
+
selectTimeSlot: () => void;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
22
|
* Hook to access TimeSlot context
|
|
@@ -28,7 +28,7 @@ export declare function useTimeSlotContext(): TimeSlotContextValue;
|
|
|
28
28
|
*/
|
|
29
29
|
export interface TimeSlotProviderProps {
|
|
30
30
|
children: React.ReactNode;
|
|
31
|
-
|
|
31
|
+
timeSlot: TimeSlotType;
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* Provider component used by TimeSlotRepeater to provide context.
|
|
@@ -88,18 +88,18 @@ export declare function StaffMemberProvider(props: StaffMemberProviderProps): Re
|
|
|
88
88
|
*/
|
|
89
89
|
export interface InfoProps {
|
|
90
90
|
children: (data: {
|
|
91
|
-
/** Raw localStartDate string from
|
|
91
|
+
/** Raw localStartDate string from timeSlot */
|
|
92
92
|
startDate: string | undefined;
|
|
93
|
-
/** Raw localEndDate string from
|
|
93
|
+
/** Raw localEndDate string from timeSlot */
|
|
94
94
|
endDate: string | undefined;
|
|
95
95
|
/** Calculated duration in minutes (null if dates unavailable) */
|
|
96
96
|
durationInMinutes: number | null;
|
|
97
|
-
/** Whether the
|
|
97
|
+
/** Whether the timeSlot is bookable */
|
|
98
98
|
bookable: boolean;
|
|
99
|
-
/** Whether this
|
|
99
|
+
/** Whether this timeSlot is currently selected */
|
|
100
100
|
isSelected: boolean;
|
|
101
|
-
/** The raw
|
|
102
|
-
|
|
101
|
+
/** The raw timeSlot object for advanced use cases */
|
|
102
|
+
timeSlot: TimeSlotType;
|
|
103
103
|
}) => React.ReactNode;
|
|
104
104
|
}
|
|
105
105
|
/**
|
|
@@ -125,15 +125,15 @@ export declare function Info(props: InfoProps): React.ReactNode;
|
|
|
125
125
|
*/
|
|
126
126
|
export interface ActionsProps {
|
|
127
127
|
children: (data: {
|
|
128
|
-
/** Action to select this
|
|
129
|
-
|
|
128
|
+
/** Action to select this timeSlot */
|
|
129
|
+
selectTimeSlot: () => void;
|
|
130
130
|
/** Action to clear preferences */
|
|
131
131
|
clearPreferences?: () => void;
|
|
132
|
-
/** The raw
|
|
133
|
-
|
|
134
|
-
/** Whether the
|
|
132
|
+
/** The raw timeSlot object */
|
|
133
|
+
timeSlot: TimeSlotType;
|
|
134
|
+
/** Whether the timeSlot is bookable */
|
|
135
135
|
bookable: boolean;
|
|
136
|
-
/** Whether this
|
|
136
|
+
/** Whether this timeSlot is currently selected */
|
|
137
137
|
isSelected: boolean;
|
|
138
138
|
}) => React.ReactNode;
|
|
139
139
|
}
|
|
@@ -187,6 +187,8 @@ export interface LocationsProps {
|
|
|
187
187
|
* Extracts locations from slot.staffByLocation and enriches with name from originalSlots.
|
|
188
188
|
* Each location includes isSelected and isSelectable based on current selection state.
|
|
189
189
|
*
|
|
190
|
+
* Returns null if there's only 1 location (nothing to choose from).
|
|
191
|
+
*
|
|
190
192
|
* @component
|
|
191
193
|
* @example
|
|
192
194
|
* ```tsx
|
|
@@ -291,6 +293,8 @@ export interface StaffMembersProps {
|
|
|
291
293
|
* Extracts unique staff members from slot.staffByLocation (names already included).
|
|
292
294
|
* Each staff member includes isSelected and isSelectable based on current selection state.
|
|
293
295
|
*
|
|
296
|
+
* Returns null if there's only 1 staff member (nothing to choose from).
|
|
297
|
+
*
|
|
294
298
|
* @component
|
|
295
299
|
* @example
|
|
296
300
|
* ```tsx
|
|
@@ -7,7 +7,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
7
7
|
* which provides the TimeSlotProvider context.
|
|
8
8
|
*/
|
|
9
9
|
import React from 'react';
|
|
10
|
-
import {
|
|
10
|
+
import { useService } from '@wix/services-manager-react';
|
|
11
|
+
import { TimeSlotListServiceDefinition, } from '../../../services/time-slot-list/time-slot-list.def.js';
|
|
11
12
|
const TimeSlotContext = React.createContext(null);
|
|
12
13
|
/**
|
|
13
14
|
* Hook to access TimeSlot context
|
|
@@ -25,17 +26,17 @@ export function useTimeSlotContext() {
|
|
|
25
26
|
* Not used directly by consumers - only by TimeSlotList.TimeSlotRepeater.
|
|
26
27
|
*/
|
|
27
28
|
export function TimeSlotProvider(props) {
|
|
28
|
-
const { children,
|
|
29
|
-
const service =
|
|
29
|
+
const { children, timeSlot } = props;
|
|
30
|
+
const service = useService(TimeSlotListServiceDefinition);
|
|
30
31
|
const selection = service.selection.get();
|
|
31
|
-
const isSelected = selection?.slot?.id ===
|
|
32
|
-
const
|
|
33
|
-
service.actions.selectSlot(
|
|
32
|
+
const isSelected = selection?.slot?.id === timeSlot.id;
|
|
33
|
+
const selectTimeSlot = () => {
|
|
34
|
+
service.actions.selectSlot(timeSlot);
|
|
34
35
|
};
|
|
35
36
|
const contextValue = {
|
|
36
|
-
|
|
37
|
+
timeSlot,
|
|
37
38
|
isSelected,
|
|
38
|
-
|
|
39
|
+
selectTimeSlot,
|
|
39
40
|
};
|
|
40
41
|
return (_jsx(TimeSlotContext.Provider, { value: contextValue, children: children }));
|
|
41
42
|
}
|
|
@@ -57,7 +58,7 @@ export function useLocationContext() {
|
|
|
57
58
|
*/
|
|
58
59
|
export function LocationProvider(props) {
|
|
59
60
|
const { children, location } = props;
|
|
60
|
-
const service =
|
|
61
|
+
const service = useService(TimeSlotListServiceDefinition);
|
|
61
62
|
const selectLocation = () => {
|
|
62
63
|
service.actions.selectLocation(location.id);
|
|
63
64
|
};
|
|
@@ -85,7 +86,7 @@ export function useStaffMemberContext() {
|
|
|
85
86
|
*/
|
|
86
87
|
export function StaffMemberProvider(props) {
|
|
87
88
|
const { children, staffMember } = props;
|
|
88
|
-
const service =
|
|
89
|
+
const service = useService(TimeSlotListServiceDefinition);
|
|
89
90
|
const selectStaffMember = () => {
|
|
90
91
|
service.actions.selectStaffMember(staffMember.id);
|
|
91
92
|
};
|
|
@@ -113,10 +114,10 @@ export function StaffMemberProvider(props) {
|
|
|
113
114
|
* ```
|
|
114
115
|
*/
|
|
115
116
|
export function Info(props) {
|
|
116
|
-
const {
|
|
117
|
-
const startDate =
|
|
118
|
-
const endDate =
|
|
119
|
-
const bookable =
|
|
117
|
+
const { timeSlot, isSelected } = useTimeSlotContext();
|
|
118
|
+
const startDate = timeSlot.localStartDate ?? undefined;
|
|
119
|
+
const endDate = timeSlot.localEndDate ?? undefined;
|
|
120
|
+
const bookable = timeSlot.bookable ?? false;
|
|
120
121
|
// Calculate duration from start and end dates
|
|
121
122
|
let durationInMinutes = null;
|
|
122
123
|
if (startDate && endDate) {
|
|
@@ -130,7 +131,7 @@ export function Info(props) {
|
|
|
130
131
|
durationInMinutes,
|
|
131
132
|
bookable,
|
|
132
133
|
isSelected,
|
|
133
|
-
|
|
134
|
+
timeSlot,
|
|
134
135
|
});
|
|
135
136
|
}
|
|
136
137
|
/**
|
|
@@ -154,24 +155,24 @@ export function Info(props) {
|
|
|
154
155
|
* ```
|
|
155
156
|
*/
|
|
156
157
|
export function Actions(props) {
|
|
157
|
-
const {
|
|
158
|
-
const service =
|
|
158
|
+
const { selectTimeSlot, timeSlot, isSelected } = useTimeSlotContext();
|
|
159
|
+
const service = useService(TimeSlotListServiceDefinition);
|
|
159
160
|
const selection = service.selection.get();
|
|
160
|
-
const bookable =
|
|
161
|
+
const bookable = timeSlot.bookable ?? false;
|
|
161
162
|
// Check if at least one preference is selected
|
|
162
163
|
const hasPreferenceSelected = !!selection?.locationId || !!selection?.staffMemberId;
|
|
163
164
|
// Check if there are multiple options
|
|
164
|
-
const locationCount =
|
|
165
|
-
const staffCount = new Set(
|
|
165
|
+
const locationCount = timeSlot.staffByLocation.length;
|
|
166
|
+
const staffCount = new Set(timeSlot.staffByLocation.flatMap(({ staffMembers }) => staffMembers.map((s) => s.id))).size;
|
|
166
167
|
const hasMultipleOptions = locationCount > 1 || staffCount > 1;
|
|
167
168
|
const shouldShowClearPreferences = hasPreferenceSelected && hasMultipleOptions;
|
|
168
169
|
const clearPreferences = shouldShowClearPreferences
|
|
169
170
|
? service.actions.clearPreferences
|
|
170
171
|
: undefined;
|
|
171
172
|
return props.children({
|
|
172
|
-
|
|
173
|
+
selectTimeSlot,
|
|
173
174
|
clearPreferences,
|
|
174
|
-
|
|
175
|
+
timeSlot,
|
|
175
176
|
bookable,
|
|
176
177
|
isSelected,
|
|
177
178
|
});
|
|
@@ -181,6 +182,8 @@ export function Actions(props) {
|
|
|
181
182
|
* Extracts locations from slot.staffByLocation and enriches with name from originalSlots.
|
|
182
183
|
* Each location includes isSelected and isSelectable based on current selection state.
|
|
183
184
|
*
|
|
185
|
+
* Returns null if there's only 1 location (nothing to choose from).
|
|
186
|
+
*
|
|
184
187
|
* @component
|
|
185
188
|
* @example
|
|
186
189
|
* ```tsx
|
|
@@ -194,13 +197,13 @@ export function Actions(props) {
|
|
|
194
197
|
* ```
|
|
195
198
|
*/
|
|
196
199
|
export function Locations(props) {
|
|
197
|
-
const {
|
|
198
|
-
const service =
|
|
200
|
+
const { timeSlot } = useTimeSlotContext();
|
|
201
|
+
const service = useService(TimeSlotListServiceDefinition);
|
|
199
202
|
const selection = service.selection.get();
|
|
200
203
|
const selectedLocationId = selection?.locationId ?? null;
|
|
201
204
|
const selectedStaffMemberId = selection?.staffMemberId ?? null;
|
|
202
205
|
// Build locations array from staffByLocation (names already included)
|
|
203
|
-
const locations =
|
|
206
|
+
const locations = timeSlot.staffByLocation.map(({ location, staffMembers }) => {
|
|
204
207
|
// Check if this location is selectable based on selected staff
|
|
205
208
|
// If no staff selected, all locations are selectable
|
|
206
209
|
// If staff selected, only locations where that staff works are selectable
|
|
@@ -214,6 +217,10 @@ export function Locations(props) {
|
|
|
214
217
|
isSelectable,
|
|
215
218
|
};
|
|
216
219
|
});
|
|
220
|
+
// Return null if only 1 location - nothing to choose from
|
|
221
|
+
if (locations.length <= 1) {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
217
224
|
return props.children({
|
|
218
225
|
locations,
|
|
219
226
|
selectLocation: service.actions.selectLocation,
|
|
@@ -272,6 +279,8 @@ export function LocationActions(props) {
|
|
|
272
279
|
* Extracts unique staff members from slot.staffByLocation (names already included).
|
|
273
280
|
* Each staff member includes isSelected and isSelectable based on current selection state.
|
|
274
281
|
*
|
|
282
|
+
* Returns null if there's only 1 staff member (nothing to choose from).
|
|
283
|
+
*
|
|
275
284
|
* @component
|
|
276
285
|
* @example
|
|
277
286
|
* ```tsx
|
|
@@ -285,14 +294,14 @@ export function LocationActions(props) {
|
|
|
285
294
|
* ```
|
|
286
295
|
*/
|
|
287
296
|
export function StaffMembers(props) {
|
|
288
|
-
const {
|
|
289
|
-
const service =
|
|
297
|
+
const { timeSlot } = useTimeSlotContext();
|
|
298
|
+
const service = useService(TimeSlotListServiceDefinition);
|
|
290
299
|
const selection = service.selection.get();
|
|
291
300
|
const selectedStaffMemberId = selection?.staffMemberId ?? null;
|
|
292
301
|
const selectedLocationId = selection?.locationId ?? null;
|
|
293
302
|
// Build unique staff members array from staffByLocation
|
|
294
303
|
// Flatten all staff members with their location IDs, then dedupe by ID
|
|
295
|
-
const allStaff =
|
|
304
|
+
const allStaff = timeSlot.staffByLocation.flatMap(({ location, staffMembers }) => staffMembers.map((s) => ({ ...s, locationId: location.id })));
|
|
296
305
|
// Group by staff ID to get all locations per staff member
|
|
297
306
|
const grouped = Object.groupBy(allStaff, (s) => s.id);
|
|
298
307
|
const staffMembers = Object.entries(grouped).map(([id, entries]) => ({
|
|
@@ -302,6 +311,10 @@ export function StaffMembers(props) {
|
|
|
302
311
|
isSelectable: !selectedLocationId ||
|
|
303
312
|
entries.some((e) => e.locationId === selectedLocationId),
|
|
304
313
|
}));
|
|
314
|
+
// Return null if only 1 staff member - nothing to choose from
|
|
315
|
+
if (staffMembers.length <= 1) {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
305
318
|
return props.children({
|
|
306
319
|
staffMembers,
|
|
307
320
|
selectStaffMember: service.actions.selectStaffMember,
|
|
@@ -3,11 +3,7 @@
|
|
|
3
3
|
* Provides low-level access to TimeSlotListService via render props
|
|
4
4
|
*/
|
|
5
5
|
import React from 'react';
|
|
6
|
-
import { type
|
|
7
|
-
/**
|
|
8
|
-
* Hook to access TimeSlotListService from within TimeSlotList.Root
|
|
9
|
-
*/
|
|
10
|
-
export declare const useTimeSlotListService: () => TimeSlotListServiceAPI;
|
|
6
|
+
import { type TimeSlotListServiceConfig, type TimeSlot } from '../../../services/time-slot-list/index.js';
|
|
11
7
|
/**
|
|
12
8
|
* Props for Root component
|
|
13
9
|
*/
|
|
@@ -32,7 +28,10 @@ export declare function Root(props: RootProps): React.ReactNode;
|
|
|
32
28
|
*/
|
|
33
29
|
export interface TimezoneProps {
|
|
34
30
|
children: (data: {
|
|
31
|
+
/** Raw IANA timezone string (e.g., "America/New_York") */
|
|
35
32
|
timezone: string | undefined;
|
|
33
|
+
/** User-friendly display name (e.g., "Eastern Standard Time") */
|
|
34
|
+
displayName: string;
|
|
36
35
|
}) => React.ReactNode;
|
|
37
36
|
}
|
|
38
37
|
/**
|
|
@@ -42,8 +41,8 @@ export interface TimezoneProps {
|
|
|
42
41
|
* @example
|
|
43
42
|
* ```tsx
|
|
44
43
|
* <Timezone>
|
|
45
|
-
* {({ timezone }) => (
|
|
46
|
-
* <span>{
|
|
44
|
+
* {({ timezone, displayName }) => (
|
|
45
|
+
* <span>{displayName}</span> // "Eastern Standard Time"
|
|
47
46
|
* )}
|
|
48
47
|
* </Timezone>
|
|
49
48
|
* ```
|
|
@@ -82,3 +81,36 @@ export interface ListDataProps {
|
|
|
82
81
|
* ```
|
|
83
82
|
*/
|
|
84
83
|
export declare function ListData(props: ListDataProps): React.ReactNode;
|
|
84
|
+
/**
|
|
85
|
+
* Render props for DateRange component
|
|
86
|
+
*/
|
|
87
|
+
export interface DateRangeRenderProps {
|
|
88
|
+
startDate: Date;
|
|
89
|
+
endDate: Date;
|
|
90
|
+
setDateRange: (start: Date, end: Date) => void;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Props for DateRange render prop component
|
|
94
|
+
*/
|
|
95
|
+
export interface DateRangeProps {
|
|
96
|
+
children: (data: DateRangeRenderProps) => React.ReactNode;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Core component that provides access to date range data and actions via render props.
|
|
100
|
+
* Use this to build date range inputs for calendar/week view navigation.
|
|
101
|
+
*
|
|
102
|
+
* @component
|
|
103
|
+
* @example
|
|
104
|
+
* ```tsx
|
|
105
|
+
* <DateRange>
|
|
106
|
+
* {({ startDate, endDate, setDateRange }) => (
|
|
107
|
+
* <MyDateRangePicker
|
|
108
|
+
* start={startDate}
|
|
109
|
+
* end={endDate}
|
|
110
|
+
* onChange={(start, end) => setDateRange(start, end)}
|
|
111
|
+
* />
|
|
112
|
+
* )}
|
|
113
|
+
* </DateRange>
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export declare function DateRange(props: DateRangeProps): React.ReactNode;
|
|
@@ -2,12 +2,6 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { useService, WixServices } from '@wix/services-manager-react';
|
|
3
3
|
import { createServicesMap } from '@wix/services-manager';
|
|
4
4
|
import { TimeSlotListServiceDefinition, TimeSlotListService, } from '../../../services/time-slot-list/index.js';
|
|
5
|
-
/**
|
|
6
|
-
* Hook to access TimeSlotListService from within TimeSlotList.Root
|
|
7
|
-
*/
|
|
8
|
-
export const useTimeSlotListService = () => {
|
|
9
|
-
return useService(TimeSlotListServiceDefinition);
|
|
10
|
-
};
|
|
11
5
|
/**
|
|
12
6
|
* Root component that provides TimeSlotListService context to its children.
|
|
13
7
|
*
|
|
@@ -22,6 +16,30 @@ export const useTimeSlotListService = () => {
|
|
|
22
16
|
export function Root(props) {
|
|
23
17
|
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(TimeSlotListServiceDefinition, TimeSlotListService, props.config || {}), children: props.children }));
|
|
24
18
|
}
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Timezone Component
|
|
21
|
+
// ============================================================================
|
|
22
|
+
/**
|
|
23
|
+
* Gets the display name for a timezone using Intl.DateTimeFormat
|
|
24
|
+
* @param timezone - IANA timezone string (e.g., "America/New_York")
|
|
25
|
+
* @returns User-friendly display name (e.g., "Eastern Standard Time")
|
|
26
|
+
*/
|
|
27
|
+
function getTimezoneDisplayName(timezone) {
|
|
28
|
+
if (!timezone)
|
|
29
|
+
return '';
|
|
30
|
+
try {
|
|
31
|
+
const formatter = new Intl.DateTimeFormat('en', {
|
|
32
|
+
timeZone: timezone,
|
|
33
|
+
timeZoneName: 'long',
|
|
34
|
+
});
|
|
35
|
+
const parts = formatter.formatToParts(new Date());
|
|
36
|
+
const timeZonePart = parts.find((part) => part.type === 'timeZoneName');
|
|
37
|
+
return timeZonePart?.value || timezone;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return timezone;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
25
43
|
/**
|
|
26
44
|
* Core component that provides access to the current timezone via render props.
|
|
27
45
|
*
|
|
@@ -29,16 +47,17 @@ export function Root(props) {
|
|
|
29
47
|
* @example
|
|
30
48
|
* ```tsx
|
|
31
49
|
* <Timezone>
|
|
32
|
-
* {({ timezone }) => (
|
|
33
|
-
* <span>{
|
|
50
|
+
* {({ timezone, displayName }) => (
|
|
51
|
+
* <span>{displayName}</span> // "Eastern Standard Time"
|
|
34
52
|
* )}
|
|
35
53
|
* </Timezone>
|
|
36
54
|
* ```
|
|
37
55
|
*/
|
|
38
56
|
export function Timezone(props) {
|
|
39
|
-
const service =
|
|
57
|
+
const service = useService(TimeSlotListServiceDefinition);
|
|
40
58
|
const timezone = service.timezone.get();
|
|
41
|
-
|
|
59
|
+
const displayName = getTimezoneDisplayName(timezone);
|
|
60
|
+
return props.children({ timezone, displayName });
|
|
42
61
|
}
|
|
43
62
|
/**
|
|
44
63
|
* Core component that provides access to time slots list data via render props.
|
|
@@ -57,7 +76,7 @@ export function Timezone(props) {
|
|
|
57
76
|
* ```
|
|
58
77
|
*/
|
|
59
78
|
export function ListData(props) {
|
|
60
|
-
const service =
|
|
79
|
+
const service = useService(TimeSlotListServiceDefinition);
|
|
61
80
|
return props.children({
|
|
62
81
|
timeSlots: service.timeSlots.get(),
|
|
63
82
|
hasMore: service.hasMore.get(),
|
|
@@ -66,3 +85,29 @@ export function ListData(props) {
|
|
|
66
85
|
loadMore: service.actions.loadMore,
|
|
67
86
|
});
|
|
68
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Core component that provides access to date range data and actions via render props.
|
|
90
|
+
* Use this to build date range inputs for calendar/week view navigation.
|
|
91
|
+
*
|
|
92
|
+
* @component
|
|
93
|
+
* @example
|
|
94
|
+
* ```tsx
|
|
95
|
+
* <DateRange>
|
|
96
|
+
* {({ startDate, endDate, setDateRange }) => (
|
|
97
|
+
* <MyDateRangePicker
|
|
98
|
+
* start={startDate}
|
|
99
|
+
* end={endDate}
|
|
100
|
+
* onChange={(start, end) => setDateRange(start, end)}
|
|
101
|
+
* />
|
|
102
|
+
* )}
|
|
103
|
+
* </DateRange>
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export function DateRange(props) {
|
|
107
|
+
const service = useService(TimeSlotListServiceDefinition);
|
|
108
|
+
return props.children({
|
|
109
|
+
startDate: service.startDate.get(),
|
|
110
|
+
endDate: service.endDate.get(),
|
|
111
|
+
setDateRange: service.actions.setDateRange,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
@@ -128,13 +128,13 @@ Duration.displayName = 'TimeSlot.Duration';
|
|
|
128
128
|
*/
|
|
129
129
|
export const Select = React.forwardRef((props, ref) => {
|
|
130
130
|
const { asChild, children, className, label } = props;
|
|
131
|
-
return (_jsx(CoreTimeSlot.Actions, { children: ({
|
|
131
|
+
return (_jsx(CoreTimeSlot.Actions, { children: ({ selectTimeSlot, isSelected, bookable }) => {
|
|
132
132
|
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotActionSelect, "data-selected": isSelected, "data-bookable": bookable, customElement: children, customElementProps: {
|
|
133
|
-
onClick:
|
|
133
|
+
onClick: selectTimeSlot,
|
|
134
134
|
disabled: !bookable,
|
|
135
135
|
isSelected,
|
|
136
136
|
bookable,
|
|
137
|
-
}, children: _jsx("button", { onClick:
|
|
137
|
+
}, children: _jsx("button", { onClick: selectTimeSlot, disabled: !bookable, children: label }) }));
|
|
138
138
|
} }));
|
|
139
139
|
});
|
|
140
140
|
Select.displayName = 'TimeSlot.Actions.Select';
|
|
@@ -7,14 +7,21 @@ import { ListVariant } from '@wix/headless-components/react';
|
|
|
7
7
|
import { AsChildChildren } from '@wix/headless-utils/react';
|
|
8
8
|
import type { TimeSlotListServiceConfig } from '../../services/time-slot-list/time-slot-list.def.js';
|
|
9
9
|
export type { StartDateProps as TimeSlotStartDateProps, EndDateProps as TimeSlotEndDateProps, DurationProps as TimeSlotDurationProps, SelectProps as TimeSlotSelectProps, LocationsProps as TimeSlotLocationsProps, LocationRepeaterProps as TimeSlotLocationRepeaterProps, LocationNameProps as TimeSlotLocationNameProps, SelectLocationProps as TimeSlotSelectLocationProps, StaffMembersProps as TimeSlotStaffMembersProps, StaffMemberRepeaterProps as TimeSlotStaffMemberRepeaterProps, StaffMemberNameProps as TimeSlotStaffMemberNameProps, SelectStaffMemberProps as TimeSlotSelectStaffMemberProps, } from './TimeSlot.js';
|
|
10
|
+
/**
|
|
11
|
+
* Render props for TimeSlotList.Timezone component
|
|
12
|
+
*/
|
|
13
|
+
export interface TimezoneRenderProps {
|
|
14
|
+
/** Raw IANA timezone string (e.g., "America/New_York") */
|
|
15
|
+
timezone: string | undefined;
|
|
16
|
+
/** User-friendly display name (e.g., "Eastern Standard Time") */
|
|
17
|
+
displayName: string;
|
|
18
|
+
}
|
|
10
19
|
/**
|
|
11
20
|
* Props for TimeSlotList.Timezone component
|
|
12
21
|
*/
|
|
13
22
|
export interface TimezoneProps {
|
|
14
23
|
asChild?: boolean;
|
|
15
|
-
children?: AsChildChildren<
|
|
16
|
-
timezone: string | undefined;
|
|
17
|
-
}>;
|
|
24
|
+
children?: AsChildChildren<TimezoneRenderProps>;
|
|
18
25
|
className?: string;
|
|
19
26
|
}
|
|
20
27
|
/**
|
|
@@ -23,19 +30,14 @@ export interface TimezoneProps {
|
|
|
23
30
|
* @component
|
|
24
31
|
* @example
|
|
25
32
|
* ```tsx
|
|
26
|
-
* // Default usage
|
|
33
|
+
* // Default usage - shows display name
|
|
27
34
|
* <TimeSlotList.Timezone className="text-sm text-gray-600" />
|
|
28
35
|
*
|
|
29
|
-
* // asChild with
|
|
30
|
-
* <TimeSlotList.Timezone asChild>
|
|
31
|
-
* <span className="font-medium" />
|
|
32
|
-
* </TimeSlotList.Timezone>
|
|
33
|
-
*
|
|
34
|
-
* // asChild with render function
|
|
36
|
+
* // asChild with render function for custom formatting
|
|
35
37
|
* <TimeSlotList.Timezone asChild>
|
|
36
|
-
* {({ timezone }) => (
|
|
38
|
+
* {({ timezone, displayName }) => (
|
|
37
39
|
* <span className="text-sm">
|
|
38
|
-
*
|
|
40
|
+
* {displayName} // "Eastern Standard Time"
|
|
39
41
|
* </span>
|
|
40
42
|
* )}
|
|
41
43
|
* </TimeSlotList.Timezone>
|
|
@@ -153,6 +155,47 @@ export declare const LoadMore: React.ForwardRefExoticComponent<LoadMoreProps & R
|
|
|
153
155
|
export declare const Actions: {
|
|
154
156
|
LoadMore: React.ForwardRefExoticComponent<LoadMoreProps & React.RefAttributes<HTMLButtonElement>>;
|
|
155
157
|
};
|
|
158
|
+
/**
|
|
159
|
+
* Props for DateRange.Input component
|
|
160
|
+
*/
|
|
161
|
+
export interface DateRangeInputProps {
|
|
162
|
+
/** Whether to render as a child component */
|
|
163
|
+
asChild?: boolean;
|
|
164
|
+
/** Children for custom rendering */
|
|
165
|
+
children?: AsChildChildren<{
|
|
166
|
+
startDate: Date;
|
|
167
|
+
endDate: Date;
|
|
168
|
+
onChange: (start: Date, end: Date) => void;
|
|
169
|
+
}>;
|
|
170
|
+
/** CSS classes to apply to the container */
|
|
171
|
+
className?: string;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Date range input for setting the start and end date filter.
|
|
175
|
+
* Uses the core DateRange component to access service data.
|
|
176
|
+
* Both dates are set together and trigger a single fetch.
|
|
177
|
+
*
|
|
178
|
+
* @component
|
|
179
|
+
* @example
|
|
180
|
+
* ```tsx
|
|
181
|
+
* <TimeSlotList.DateRange.Input asChild>
|
|
182
|
+
* {({ startDate, endDate, onChange }) => (
|
|
183
|
+
* <MyDateRangePicker
|
|
184
|
+
* start={startDate}
|
|
185
|
+
* end={endDate}
|
|
186
|
+
* onRangeChange={(start, end) => onChange(start, end)}
|
|
187
|
+
* />
|
|
188
|
+
* )}
|
|
189
|
+
* </TimeSlotList.DateRange.Input>
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
export declare const DateRangeInput: React.ForwardRefExoticComponent<DateRangeInputProps & React.RefAttributes<HTMLElement>>;
|
|
193
|
+
/**
|
|
194
|
+
* DateRange namespace for TimeSlotList date range filter
|
|
195
|
+
*/
|
|
196
|
+
export declare const DateRange: {
|
|
197
|
+
Input: React.ForwardRefExoticComponent<DateRangeInputProps & React.RefAttributes<HTMLElement>>;
|
|
198
|
+
};
|
|
156
199
|
/**
|
|
157
200
|
* TimeSlot namespace containing components for displaying individual time slot data.
|
|
158
201
|
* These components must be used within TimeSlotList.TimeSlotRepeater.
|