@wix/headless-bookings 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/cjs/dist/api/index.d.ts +10 -1
  2. package/cjs/dist/api/index.js +10 -1
  3. package/cjs/dist/api/query-services/index.d.ts +78 -0
  4. package/cjs/dist/api/query-services/index.js +137 -0
  5. package/cjs/dist/react/core/location/Location.d.ts +44 -0
  6. package/cjs/dist/react/core/location/Location.js +78 -0
  7. package/cjs/dist/react/core/service/Service.d.ts +160 -17
  8. package/cjs/dist/react/core/service/Service.js +211 -13
  9. package/cjs/dist/react/core/service-list/ServiceList.d.ts +75 -0
  10. package/cjs/dist/react/core/service-list/ServiceList.js +58 -0
  11. package/cjs/dist/react/index.d.ts +2 -0
  12. package/cjs/dist/react/index.js +2 -0
  13. package/cjs/dist/react/location/Location.d.ts +77 -0
  14. package/cjs/dist/react/location/Location.js +89 -0
  15. package/cjs/dist/react/service/Service.d.ts +1036 -31
  16. package/cjs/dist/react/service/Service.js +1060 -47
  17. package/cjs/dist/react/service-list/ServiceList.d.ts +185 -0
  18. package/cjs/dist/react/service-list/ServiceList.js +184 -0
  19. package/cjs/dist/services/index.d.ts +2 -1
  20. package/cjs/dist/services/index.js +2 -1
  21. package/cjs/dist/services/service/service.d.ts +71 -18
  22. package/cjs/dist/services/service/service.js +186 -50
  23. package/cjs/dist/services/service-list/service-list.d.ts +157 -0
  24. package/cjs/dist/services/service-list/service-list.js +274 -0
  25. package/cjs/dist/utils/dateAndTime.d.ts +2 -0
  26. package/cjs/dist/utils/dateAndTime.js +18 -0
  27. package/cjs/dist/utils/money.d.ts +21 -0
  28. package/cjs/dist/utils/money.js +34 -0
  29. package/dist/api/index.d.ts +10 -1
  30. package/dist/api/index.js +10 -1
  31. package/dist/api/query-services/index.d.ts +78 -0
  32. package/dist/api/query-services/index.js +137 -0
  33. package/dist/react/core/location/Location.d.ts +44 -0
  34. package/dist/react/core/location/Location.js +78 -0
  35. package/dist/react/core/service/Service.d.ts +160 -17
  36. package/dist/react/core/service/Service.js +211 -13
  37. package/dist/react/core/service-list/ServiceList.d.ts +75 -0
  38. package/dist/react/core/service-list/ServiceList.js +58 -0
  39. package/dist/react/index.d.ts +2 -0
  40. package/dist/react/index.js +2 -0
  41. package/dist/react/location/Location.d.ts +77 -0
  42. package/dist/react/location/Location.js +89 -0
  43. package/dist/react/service/Service.d.ts +1036 -31
  44. package/dist/react/service/Service.js +1060 -47
  45. package/dist/react/service-list/ServiceList.d.ts +185 -0
  46. package/dist/react/service-list/ServiceList.js +184 -0
  47. package/dist/services/index.d.ts +2 -1
  48. package/dist/services/index.js +2 -1
  49. package/dist/services/service/service.d.ts +71 -18
  50. package/dist/services/service/service.js +186 -50
  51. package/dist/services/service-list/service-list.d.ts +157 -0
  52. package/dist/services/service-list/service-list.js +274 -0
  53. package/dist/utils/dateAndTime.d.ts +2 -0
  54. package/dist/utils/dateAndTime.js +18 -0
  55. package/dist/utils/money.d.ts +21 -0
  56. package/dist/utils/money.js +34 -0
  57. package/package.json +2 -2
  58. package/cjs/dist/api/query-service/index.d.ts +0 -23
  59. package/cjs/dist/api/query-service/index.js +0 -41
  60. package/dist/api/query-service/index.d.ts +0 -23
  61. package/dist/api/query-service/index.js +0 -41
@@ -13,8 +13,17 @@ import { ServiceServiceDefinition, ServiceService, } from '../../../services/ser
13
13
  * </Service.Root>
14
14
  * ```
15
15
  */
16
+ function RootContent({ children, }) {
17
+ const serviceService = useService(ServiceServiceDefinition);
18
+ const selected = serviceService.selectedSignal.get();
19
+ const bookable = serviceService.bookableSignal.get();
20
+ if (typeof children === 'function') {
21
+ return children({ selected, bookable });
22
+ }
23
+ return children;
24
+ }
16
25
  export function Root(props) {
17
- return (_jsx(WixServices, { servicesMap: createServicesMap().addService(ServiceServiceDefinition, ServiceService, props.serviceServiceConfig), children: props.children }));
26
+ return (_jsx(WixServices, { servicesMap: createServicesMap().addService(ServiceServiceDefinition, ServiceService, props.serviceServiceConfig), children: _jsx(RootContent, { children: props.children }) }));
18
27
  }
19
28
  /**
20
29
  * Core component that provides access to full service data via render props.
@@ -31,23 +40,27 @@ export function Root(props) {
31
40
  */
32
41
  export function Service(props) {
33
42
  const serviceService = useService(ServiceServiceDefinition);
34
- const service = serviceService.service.get();
35
- const isLoading = serviceService.isLoading.get();
36
- const error = serviceService.error.get();
43
+ const service = serviceService.serviceSignal.get();
44
+ const isLoading = serviceService.isLoadingSignal.get();
45
+ const error = serviceService.errorSignal.get();
37
46
  return props.children({ service, isLoading, error });
38
47
  }
39
48
  /**
40
49
  * Core component that provides access to service catalog info via render props.
41
- * Includes name and description for static catalog display.
50
+ * Includes name, description, tagline, duration, type, category, locations, staff, media, and price.
42
51
  *
43
52
  * @component
44
53
  * @example
45
54
  * ```tsx
46
55
  * <Service.Info>
47
- * {({ name, description }) => (
56
+ * {({ name, description, tagline, duration, type, category, locations, staff, media, price }) => (
48
57
  * <div>
49
58
  * <h1>{name}</h1>
50
59
  * <p>{description}</p>
60
+ * {tagline && <p>{tagline}</p>}
61
+ * {duration && <p>Duration: {duration} minutes</p>}
62
+ * {type && <p>Type: {type}</p>}
63
+ * {category && <p>Category: {category.name}</p>}
51
64
  * </div>
52
65
  * )}
53
66
  * </Service.Info>
@@ -55,12 +68,99 @@ export function Service(props) {
55
68
  */
56
69
  export function Info(props) {
57
70
  const serviceService = useService(ServiceServiceDefinition);
58
- const service = serviceService.service.get();
71
+ const service = serviceService.serviceSignal.get();
72
+ const selected = serviceService.selectedSignal.get();
73
+ // Extract price from service.payment for Info component
74
+ const payment = service.payment;
75
+ let priceInfo = undefined;
76
+ if (payment?.rateType === 'FIXED' && payment.fixed?.price) {
77
+ const priceValue = payment.fixed.price.value;
78
+ const currency = payment.fixed.price.currency || 'USD';
79
+ priceInfo = {
80
+ amount: priceValue || undefined,
81
+ currency,
82
+ };
83
+ }
84
+ // Extract duration from schedule.availabilityConstraints.sessionDurations
85
+ // Use the first duration if multiple are available
86
+ const duration = service.schedule?.availabilityConstraints?.sessionDurations?.[0];
87
+ // Get staff members from staffMemberDetails.staffMembers
88
+ // (available when using conditionalFields: ['STAFF_MEMBER_DETAILS'] in queryServices)
89
+ const staff = service.staffMembers?.map((member) => ({
90
+ _id: member.staffMemberId,
91
+ name: member.name || undefined,
92
+ })) || [];
93
+ // Convert mainMedia to WixMediaImage format
94
+ // Handle both snake_case (main_media) and camelCase (mainMedia) from API
95
+ // Handle both string and object formats for image
96
+ const serviceMedia = service.media;
97
+ const mainMedia = {
98
+ image: serviceMedia?.mainMedia?.image,
99
+ };
100
+ // Convert coverMedia to WixMediaImage format
101
+ // Handle both snake_case (cover_media) and camelCase (coverMedia) from API
102
+ // Handle both string and object formats for image
103
+ const coverMedia = {
104
+ image: serviceMedia?.coverMedia?.image,
105
+ };
106
+ // Convert media items to MediaGallery format
107
+ // Handle both string and object formats for image
108
+ const mediaItems = service.media?.items?.map((item) => {
109
+ return {
110
+ image: item.image,
111
+ };
112
+ }) || [];
113
+ // Extract default capacity directly from service (convert null to undefined)
114
+ const defaultCapacity = service.defaultCapacity ?? undefined;
59
115
  return props.children({
60
116
  name: service.name || '',
61
117
  description: service.description || '',
118
+ tagline: service.tagLine || undefined,
119
+ duration: duration,
120
+ type: service.type,
121
+ category: service.category
122
+ ? {
123
+ name: service.category.name || undefined,
124
+ _id: service.category._id || undefined,
125
+ }
126
+ : undefined,
127
+ locations: service.locations,
128
+ staff: staff,
129
+ mainMedia: mainMedia,
130
+ coverMedia: coverMedia,
131
+ mediaItems: mediaItems.length > 0 ? mediaItems : undefined,
132
+ price: priceInfo,
133
+ defaultCapacity: defaultCapacity,
134
+ selected,
62
135
  });
63
136
  }
137
+ /**
138
+ * Core component that provides access to service price via render props.
139
+ * Returns comprehensive pricing data including money, rate type, and service capabilities.
140
+ *
141
+ * @component
142
+ * @example
143
+ * ```tsx
144
+ * <Service.Price>
145
+ * {({ money, rateType, minPrice, maxPrice, priceDescription, hasAddOns, hasPricingPlans }) => (
146
+ * rateType === 'FIXED' && money ? (
147
+ * <Money money={money} />
148
+ * ) : rateType === 'VARIED' && minPrice && maxPrice ? (
149
+ * <span><Money money={minPrice} /> - <Money money={maxPrice} /></span>
150
+ * ) : rateType === 'CUSTOM' && priceDescription ? (
151
+ * <span>{priceDescription}</span>
152
+ * ) : rateType === 'NO_FEE' ? (
153
+ * <span>Free</span>
154
+ * ) : null
155
+ * )}
156
+ * </Service.Price>
157
+ * ```
158
+ */
159
+ export function Price(props) {
160
+ const serviceService = useService(ServiceServiceDefinition);
161
+ const paymentData = serviceService.paymentDataSignal.get();
162
+ return props.children(paymentData);
163
+ }
64
164
  /**
65
165
  * Core component that provides booking selection actions via render props.
66
166
  *
@@ -68,7 +168,7 @@ export function Info(props) {
68
168
  * @example
69
169
  * ```tsx
70
170
  * <Service.Actions>
71
- * {({ select, add, remove, service }) => (
171
+ * {({ select, add, remove, rawService, requiresAvailability }) => (
72
172
  * <div>
73
173
  * <button onClick={select}>Select</button>
74
174
  * <button onClick={add}>Add</button>
@@ -80,11 +180,109 @@ export function Info(props) {
80
180
  */
81
181
  export function Actions(props) {
82
182
  const serviceService = useService(ServiceServiceDefinition);
83
- const service = serviceService.service.get();
183
+ const rawService = serviceService.serviceSignal.get();
184
+ const bookable = serviceService.bookableSignal.get();
185
+ const selected = serviceService.selectedSignal.get();
186
+ const requiresAvailability = serviceService.requiresAvailabilitySignal.get();
187
+ return props.children({
188
+ select: serviceService.actions.select,
189
+ add: serviceService.actions.add,
190
+ remove: serviceService.actions.remove,
191
+ rawService,
192
+ bookable,
193
+ selected,
194
+ requiresAvailability,
195
+ });
196
+ }
197
+ /**
198
+ * Core component that provides access to service booking policy via render props.
199
+ * Computes all enabled flags and values from the booking policy.
200
+ *
201
+ * @component
202
+ * @example
203
+ * ```tsx
204
+ * <Service.Policy>
205
+ * {({ bookingPolicy, cancellationPolicyEnabled, latestCancellationInMinutes }) => (
206
+ * cancellationPolicyEnabled ? (
207
+ * <div>Cancel up to {latestCancellationInMinutes} minutes before</div>
208
+ * ) : null
209
+ * )}
210
+ * </Service.Policy>
211
+ * ```
212
+ */
213
+ export function Policy(props) {
214
+ const serviceService = useService(ServiceServiceDefinition);
215
+ const service = serviceService.serviceSignal.get();
216
+ const bookingPolicy = service.bookingPolicy || null;
217
+ // Compute all flags here (not in headless components)
218
+ const cancellationPolicy = bookingPolicy?.cancellationPolicy;
219
+ const cancellationPolicyEnabled = cancellationPolicy?.enabled ?? false;
220
+ const limitLatestCancellationEnabled = cancellationPolicy?.limitLatestCancellation ?? false;
221
+ const latestCancellationInMinutes = cancellationPolicy?.latestCancellationInMinutes;
222
+ const lateBookingPolicy = bookingPolicy?.limitLateBookingPolicy;
223
+ const latestBookingPolicyEnabled = lateBookingPolicy?.enabled ?? false;
224
+ const latestBookingInMinutes = lateBookingPolicy?.latestBookingInMinutes;
225
+ const earlyBookingPolicy = bookingPolicy?.limitEarlyBookingPolicy;
226
+ const earliestBookingPolicyEnabled = earlyBookingPolicy?.enabled ?? false;
227
+ const earliestBookingInMinutes = earlyBookingPolicy?.earliestBookingInMinutes;
228
+ const reschedulePolicy = bookingPolicy?.reschedulePolicy;
229
+ const reschedulePolicyEnabled = reschedulePolicy?.enabled ?? false;
230
+ const limitLatestRescheduleEnabled = reschedulePolicy?.limitLatestReschedule ?? false;
231
+ const latestRescheduleInMinutes = reschedulePolicy?.latestRescheduleInMinutes;
232
+ const waitlistPolicy = bookingPolicy?.waitlistPolicy;
233
+ const waitlistPolicyEnabled = waitlistPolicy?.enabled ?? false;
234
+ const waitlistCapacity = waitlistPolicy?.capacity;
235
+ const bookAfterStartPolicy = bookingPolicy?.bookAfterStartPolicy;
236
+ const bookAfterStartEnabled = bookAfterStartPolicy?.enabled ?? false;
237
+ const participantsPolicy = bookingPolicy?.participantsPolicy;
238
+ const maxParticipantsPerBooking = participantsPolicy?.maxParticipantsPerBooking;
239
+ return props.children({
240
+ bookingPolicy,
241
+ cancellationPolicyEnabled,
242
+ limitLatestCancellationEnabled,
243
+ latestCancellationInMinutes,
244
+ latestBookingPolicyEnabled,
245
+ latestBookingInMinutes,
246
+ earliestBookingPolicyEnabled,
247
+ earliestBookingInMinutes,
248
+ reschedulePolicyEnabled,
249
+ limitLatestRescheduleEnabled,
250
+ latestRescheduleInMinutes,
251
+ waitlistPolicyEnabled,
252
+ waitlistCapacity,
253
+ bookAfterStartEnabled,
254
+ maxParticipantsPerBooking,
255
+ });
256
+ }
257
+ /**
258
+ * Core component that provides access to service schedule via render props.
259
+ * Uses the SDK's Schedule type directly. Only renders for CLASS or COURSE service types.
260
+ *
261
+ * @component
262
+ * @example
263
+ * ```tsx
264
+ * <Service.Schedule>
265
+ * {({ schedule, isClassOrCourse }) => (
266
+ * schedule && isClassOrCourse ? (
267
+ * <div>
268
+ * {schedule.firstSessionStart && (
269
+ * <span>Starts: {new Date(schedule.firstSessionStart).toLocaleDateString()}</span>
270
+ * )}
271
+ * {schedule.lastSessionEnd && (
272
+ * <span>Ends: {new Date(schedule.lastSessionEnd).toLocaleDateString()}</span>
273
+ * )}
274
+ * </div>
275
+ * ) : null
276
+ * )}
277
+ * </Service.Schedule>
278
+ * ```
279
+ */
280
+ export function Schedule(props) {
281
+ const serviceService = useService(ServiceServiceDefinition);
282
+ const service = serviceService.serviceSignal.get();
283
+ const isClassOrCourse = service.type === 'CLASS' || service.type === 'COURSE';
84
284
  return props.children({
85
- select: serviceService.select,
86
- add: serviceService.add,
87
- remove: serviceService.remove,
88
- service,
285
+ schedule: service.schedule || null,
286
+ isClassOrCourse,
89
287
  });
90
288
  }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Core ServiceList Components
3
+ * Provides low-level access to ServiceListService via render props
4
+ */
5
+ import React from 'react';
6
+ import { type ServiceListServiceConfig, type QueryOptions } from '../../../services/service-list/service-list.js';
7
+ import type { services } from '@wix/bookings';
8
+ import type { PagingMetadata } from '../../../api/query-services/index.js';
9
+ /**
10
+ * Props for ServiceList.Root component
11
+ */
12
+ export interface RootProps {
13
+ children: React.ReactNode;
14
+ serviceListConfig: ServiceListServiceConfig;
15
+ }
16
+ /**
17
+ * Root component that provides ServiceList service context.
18
+ *
19
+ * @component
20
+ * @example
21
+ * ```tsx
22
+ * <ServiceList.Root serviceListConfig={{ services: myServices }}>
23
+ * {children}
24
+ * </ServiceList.Root>
25
+ * ```
26
+ */
27
+ export declare function Root(props: RootProps): React.ReactNode;
28
+ /**
29
+ * Props for Services render prop component
30
+ */
31
+ export interface ServicesProps {
32
+ /** Render function that receives services list and metadata */
33
+ children: (props: ServicesRenderProps) => React.ReactNode;
34
+ }
35
+ /**
36
+ * Render props for Services component
37
+ */
38
+ export interface ServicesRenderProps {
39
+ /** Array of services */
40
+ services: services.Service[];
41
+ /** Whether services are currently loading */
42
+ isLoading: boolean;
43
+ /** Error message, or null if no error */
44
+ error: string | null;
45
+ /** Current query options (appId, filters, sort) */
46
+ queryOptions: QueryOptions;
47
+ /** Pagination metadata (limit, offset, count, hasNext) */
48
+ pagingMetadata: PagingMetadata;
49
+ }
50
+ /**
51
+ * Component that provides services list data through render props.
52
+ * Exposes services, loading state, error, query options, and pagination metadata (including hasNext flag).
53
+ *
54
+ * @component
55
+ * @example
56
+ * ```tsx
57
+ * <ServiceList.Services>
58
+ * {({ services, isLoading, error, pagingMetadata }) => {
59
+ * if (isLoading) return <div>Loading...</div>;
60
+ * if (error) return <div>Error: {error}</div>;
61
+ * return (
62
+ * <div>
63
+ * {services.map(service => (
64
+ * <div key={service._id}>{service.name}</div>
65
+ * ))}
66
+ * {pagingMetadata.hasNext && (
67
+ * <button>Load More Services</button>
68
+ * )}
69
+ * </div>
70
+ * );
71
+ * }}
72
+ * </ServiceList.Services>
73
+ * ```
74
+ */
75
+ export declare function Services(props: ServicesProps): React.ReactNode;
@@ -0,0 +1,58 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useService, WixServices } from '@wix/services-manager-react';
3
+ import { createServicesMap } from '@wix/services-manager';
4
+ import { ServiceListServiceDefinition, ServiceListService, } from '../../../services/service-list/service-list.js';
5
+ /**
6
+ * Root component that provides ServiceList service context.
7
+ *
8
+ * @component
9
+ * @example
10
+ * ```tsx
11
+ * <ServiceList.Root serviceListConfig={{ services: myServices }}>
12
+ * {children}
13
+ * </ServiceList.Root>
14
+ * ```
15
+ */
16
+ export function Root(props) {
17
+ return (_jsx(WixServices, { servicesMap: createServicesMap().addService(ServiceListServiceDefinition, ServiceListService, props.serviceListConfig), children: props.children }));
18
+ }
19
+ /**
20
+ * Component that provides services list data through render props.
21
+ * Exposes services, loading state, error, query options, and pagination metadata (including hasNext flag).
22
+ *
23
+ * @component
24
+ * @example
25
+ * ```tsx
26
+ * <ServiceList.Services>
27
+ * {({ services, isLoading, error, pagingMetadata }) => {
28
+ * if (isLoading) return <div>Loading...</div>;
29
+ * if (error) return <div>Error: {error}</div>;
30
+ * return (
31
+ * <div>
32
+ * {services.map(service => (
33
+ * <div key={service._id}>{service.name}</div>
34
+ * ))}
35
+ * {pagingMetadata.hasNext && (
36
+ * <button>Load More Services</button>
37
+ * )}
38
+ * </div>
39
+ * );
40
+ * }}
41
+ * </ServiceList.Services>
42
+ * ```
43
+ */
44
+ export function Services(props) {
45
+ const serviceListService = useService(ServiceListServiceDefinition);
46
+ const services = serviceListService.servicesSignal.get();
47
+ const isLoading = serviceListService.isLoadingSignal.get();
48
+ const error = serviceListService.errorSignal.get();
49
+ const queryOptions = serviceListService.queryOptionsSignal.get();
50
+ const pagingMetadata = serviceListService.pagingMetadataSignal.get();
51
+ return props.children({
52
+ services,
53
+ isLoading,
54
+ error,
55
+ queryOptions,
56
+ pagingMetadata,
57
+ });
58
+ }
@@ -1,2 +1,4 @@
1
1
  export * as Booking from './booking/Booking.js';
2
2
  export * as Service from './service/Service.js';
3
+ export * as ServiceList from './service-list/ServiceList.js';
4
+ export * as Location from './location/Location.js';
@@ -1,2 +1,4 @@
1
1
  export * as Booking from './booking/Booking.js';
2
2
  export * as Service from './service/Service.js';
3
+ export * as ServiceList from './service-list/ServiceList.js';
4
+ export * as Location from './location/Location.js';
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Location - Headless component for displaying service location information
3
+ * Provides components for displaying location type and address
4
+ */
5
+ import React from 'react';
6
+ import * as CoreLocation from '../core/location/Location.js';
7
+ import { AsChildChildren } from '@wix/headless-utils/react';
8
+ import type { services } from '@wix/bookings';
9
+ /**
10
+ * Re-export AddressData type from core for convenience
11
+ */
12
+ export type { AddressData } from '../core/location/Location.js';
13
+ /**
14
+ * Props for Location.Root component
15
+ */
16
+ export interface LocationRootProps {
17
+ location: NonNullable<services.Service['locations']>[number];
18
+ asChild?: boolean;
19
+ children?: React.ReactNode | AsChildChildren<{
20
+ locationType: services.LocationType;
21
+ address: CoreLocation.AddressData | null;
22
+ }>;
23
+ className?: string;
24
+ }
25
+ /**
26
+ * Root component that provides location context and handles location type detection
27
+ * and address parsing.
28
+ *
29
+ * @component
30
+ * @example
31
+ * ```tsx
32
+ * import { Location } from '@wix/bookings/components';
33
+ *
34
+ * // Default usage - automatically renders Address.Formatted
35
+ * function ServiceLocations({ location }) {
36
+ * return (
37
+ * <Location.Root location={location} />
38
+ * );
39
+ * }
40
+ * ```
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * // With asChild to access location data
45
+ * <Location.Root location={location} asChild>
46
+ * {({ locationType, address }) => (
47
+ * <div>
48
+ * <span className="badge">{locationType}</span>
49
+ * {address && (
50
+ * <Address.Root address={address}>
51
+ * <Address.Formatted />
52
+ * </Address.Root>
53
+ * )}
54
+ * </div>
55
+ * )}
56
+ * </Location.Root>
57
+ * ```
58
+ *
59
+ * @example
60
+ * ```tsx
61
+ * // Conditional rendering based on location type
62
+ * <Location.Root location={location} asChild>
63
+ * {({ locationType, address }) => (
64
+ * locationType === 'customer' ? (
65
+ * <span className="text-primary">At your location</span>
66
+ * ) : (
67
+ * address && (
68
+ * <Address.Root address={address}>
69
+ * <Address.Formatted />
70
+ * </Address.Root>
71
+ * )
72
+ * )
73
+ * )}
74
+ * </Location.Root>
75
+ * ```
76
+ */
77
+ export declare const Root: React.ForwardRefExoticComponent<LocationRootProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1,89 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Location - Headless component for displaying service location information
4
+ * Provides components for displaying location type and address
5
+ */
6
+ import React from 'react';
7
+ import * as CoreLocation from '../core/location/Location.js';
8
+ import { AsChildSlot } from '@wix/headless-utils/react';
9
+ import { Address } from '@wix/headless-components/react';
10
+ // ==========================================
11
+ // TestIds Enum
12
+ // ==========================================
13
+ var TestIds;
14
+ (function (TestIds) {
15
+ TestIds["locationRoot"] = "location-root";
16
+ })(TestIds || (TestIds = {}));
17
+ // ==========================================
18
+ // Components
19
+ // ==========================================
20
+ /**
21
+ * Root component that provides location context and handles location type detection
22
+ * and address parsing.
23
+ *
24
+ * @component
25
+ * @example
26
+ * ```tsx
27
+ * import { Location } from '@wix/bookings/components';
28
+ *
29
+ * // Default usage - automatically renders Address.Formatted
30
+ * function ServiceLocations({ location }) {
31
+ * return (
32
+ * <Location.Root location={location} />
33
+ * );
34
+ * }
35
+ * ```
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * // With asChild to access location data
40
+ * <Location.Root location={location} asChild>
41
+ * {({ locationType, address }) => (
42
+ * <div>
43
+ * <span className="badge">{locationType}</span>
44
+ * {address && (
45
+ * <Address.Root address={address}>
46
+ * <Address.Formatted />
47
+ * </Address.Root>
48
+ * )}
49
+ * </div>
50
+ * )}
51
+ * </Location.Root>
52
+ * ```
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * // Conditional rendering based on location type
57
+ * <Location.Root location={location} asChild>
58
+ * {({ locationType, address }) => (
59
+ * locationType === 'customer' ? (
60
+ * <span className="text-primary">At your location</span>
61
+ * ) : (
62
+ * address && (
63
+ * <Address.Root address={address}>
64
+ * <Address.Formatted />
65
+ * </Address.Root>
66
+ * )
67
+ * )
68
+ * )}
69
+ * </Location.Root>
70
+ * ```
71
+ */
72
+ export const Root = React.forwardRef((props, ref) => {
73
+ const { location, asChild, children, className, ...attrs } = props;
74
+ return (_jsx(CoreLocation.Location, { location: location, children: ({ locationType, address }) => {
75
+ // If asChild is used with custom children, always pass location data to children
76
+ if (asChild && children) {
77
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.locationRoot, "data-location-type": locationType, customElement: children, customElementProps: { locationType, address }, ...attrs, children: address ? (_jsx(Address.Root, { address: address, children: _jsx(Address.Formatted, {}) })) : null }));
78
+ }
79
+ // Default rendering: return null if no address data
80
+ if (!address) {
81
+ return null;
82
+ }
83
+ // Default rendering with Address.Formatted and optional children
84
+ return (_jsxs("span", { ref: ref, "data-testid": TestIds.locationRoot, "data-location-type": locationType, className: className, ...attrs, children: [_jsx(Address.Root, { address: address, children: _jsx(Address.Formatted, {}) }), typeof children !== 'function'
85
+ ? children
86
+ : null] }));
87
+ } }));
88
+ });
89
+ Root.displayName = 'Location.Root';