@wix/headless-restaurants-olo 0.0.30 → 0.0.32
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/ClickableItem.d.ts +18 -3
- package/cjs/dist/react/ClickableItem.js +16 -9
- package/cjs/dist/react/FulfillmentDetails.d.ts +233 -0
- package/cjs/dist/react/FulfillmentDetails.js +255 -0
- package/cjs/dist/react/ItemDetails.d.ts +233 -36
- package/cjs/dist/react/ItemDetails.js +208 -0
- package/cjs/dist/react/ModifierGroup.js +0 -3
- package/cjs/dist/react/OLO.d.ts +5 -160
- package/cjs/dist/react/OLO.js +6 -122
- package/cjs/dist/react/OLOMenus.d.ts +8 -2
- package/cjs/dist/react/OLOMenus.js +3 -4
- package/cjs/dist/react/Settings.d.ts +176 -48
- package/cjs/dist/react/Settings.js +276 -26
- package/cjs/dist/react/core/ClickableItem.d.ts +12 -5
- package/cjs/dist/react/core/ClickableItem.js +13 -14
- package/cjs/dist/react/core/FulfillmentDetails.d.ts +78 -0
- package/cjs/dist/react/core/FulfillmentDetails.js +177 -0
- package/cjs/dist/react/core/ItemDetails.js +2 -4
- package/cjs/dist/react/core/OLO.d.ts +6 -74
- package/cjs/dist/react/core/OLO.js +5 -44
- package/cjs/dist/react/core/OLOMenus.d.ts +1 -1
- package/cjs/dist/react/core/OLOMenus.js +2 -3
- package/cjs/dist/react/core/Settings.d.ts +138 -22
- package/cjs/dist/react/core/Settings.js +157 -34
- package/cjs/dist/react/core/index.d.ts +1 -0
- package/cjs/dist/react/core/index.js +1 -0
- package/cjs/dist/react/index.d.ts +2 -0
- package/cjs/dist/react/index.js +1 -0
- package/cjs/dist/services/fulfillments-service.js +80 -22
- package/cjs/dist/types/fulfillments-types.d.ts +49 -2
- package/cjs/dist/types/operation.d.ts +1 -1
- package/cjs/dist/utils/fulfillments-utils.d.ts +34 -1
- package/cjs/dist/utils/fulfillments-utils.js +209 -1
- package/dist/react/ClickableItem.d.ts +18 -3
- package/dist/react/ClickableItem.js +16 -9
- package/dist/react/FulfillmentDetails.d.ts +233 -0
- package/dist/react/FulfillmentDetails.js +255 -0
- package/dist/react/ItemDetails.d.ts +233 -36
- package/dist/react/ItemDetails.js +208 -0
- package/dist/react/ModifierGroup.js +0 -3
- package/dist/react/OLO.d.ts +5 -160
- package/dist/react/OLO.js +6 -122
- package/dist/react/OLOMenus.d.ts +8 -2
- package/dist/react/OLOMenus.js +3 -4
- package/dist/react/Settings.d.ts +176 -48
- package/dist/react/Settings.js +276 -26
- package/dist/react/core/ClickableItem.d.ts +12 -5
- package/dist/react/core/ClickableItem.js +13 -14
- package/dist/react/core/FulfillmentDetails.d.ts +78 -0
- package/dist/react/core/FulfillmentDetails.js +177 -0
- package/dist/react/core/ItemDetails.js +2 -4
- package/dist/react/core/OLO.d.ts +6 -74
- package/dist/react/core/OLO.js +5 -44
- package/dist/react/core/OLOMenus.d.ts +1 -1
- package/dist/react/core/OLOMenus.js +2 -3
- package/dist/react/core/Settings.d.ts +138 -22
- package/dist/react/core/Settings.js +157 -34
- package/dist/react/core/index.d.ts +1 -0
- package/dist/react/core/index.js +1 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +1 -0
- package/dist/services/fulfillments-service.js +80 -22
- package/dist/types/fulfillments-types.d.ts +49 -2
- package/dist/types/operation.d.ts +1 -1
- package/dist/utils/fulfillments-utils.d.ts +34 -1
- package/dist/utils/fulfillments-utils.js +209 -1
- package/package.json +2 -2
|
@@ -5,39 +5,40 @@ import { ItemServiceConfig } from '../services/item-details-service.js';
|
|
|
5
5
|
import { EnhancedVariant } from '@wix/headless-restaurants-menus/services';
|
|
6
6
|
import { AvailabilityStatus, AvailabilityStatusMap, AddToCartButtonState } from '../services/common-types.js';
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
* Provides context for all menu item-related components like name, price, description, image, etc.
|
|
10
|
-
*
|
|
11
|
-
* @component
|
|
12
|
-
* @example
|
|
13
|
-
* ```tsx
|
|
14
|
-
* <ItemDetails>
|
|
15
|
-
* <ItemDetailsImage src="wix:image://v1/abc123.jpg" alt="Menu item" />
|
|
16
|
-
* <ItemDetailsName />
|
|
17
|
-
* <ItemDetailsPrice />
|
|
18
|
-
* <ItemDetailsDescription />
|
|
19
|
-
* </ItemDetails>
|
|
20
|
-
* ```
|
|
8
|
+
* Props for the ItemDetails Root component
|
|
21
9
|
*/
|
|
22
10
|
export interface RootProps {
|
|
11
|
+
/** Whether to render as a child component */
|
|
23
12
|
asChild?: boolean;
|
|
13
|
+
/** Child components that will have access to the item context */
|
|
24
14
|
children: React.ReactNode;
|
|
15
|
+
/** Optional pre-loaded item details service configuration */
|
|
25
16
|
itemDetailsServiceConfig?: ItemServiceConfig;
|
|
26
17
|
}
|
|
27
|
-
export declare const Root: ({ children, itemDetailsServiceConfig }: RootProps) => import("react/jsx-runtime").JSX.Element;
|
|
28
18
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
19
|
+
* Root headless component for menu item details
|
|
20
|
+
* Provides service context and item data for all child components
|
|
31
21
|
*
|
|
32
|
-
* @component
|
|
33
22
|
* @example
|
|
34
23
|
* ```tsx
|
|
35
|
-
* <ItemDetails.
|
|
36
|
-
*
|
|
37
|
-
*
|
|
24
|
+
* <ItemDetails.Root itemDetailsServiceConfig={config}>
|
|
25
|
+
* <ItemDetails.Name />
|
|
26
|
+
* <ItemDetails.Price />
|
|
27
|
+
* <ItemDetails.Description />
|
|
28
|
+
* <ItemDetails.Variants />
|
|
29
|
+
* <ItemDetails.AddToCartButton />
|
|
30
|
+
* </ItemDetails.Root>
|
|
38
31
|
* ```
|
|
39
32
|
*/
|
|
33
|
+
export declare const Root: {
|
|
34
|
+
({ children, itemDetailsServiceConfig }: RootProps): import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
displayName: string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Props for the ItemDetails Variants component
|
|
39
|
+
*/
|
|
40
40
|
export interface ItemDetailsVariantsProps {
|
|
41
|
+
/** Children render prop that receives variant data */
|
|
41
42
|
children?: AsChildChildren<{
|
|
42
43
|
variant: EnhancedVariant;
|
|
43
44
|
variants: EnhancedVariant[];
|
|
@@ -45,31 +46,60 @@ export interface ItemDetailsVariantsProps {
|
|
|
45
46
|
selectedVariantId?: string;
|
|
46
47
|
onVariantChange?: (variantId: string) => void;
|
|
47
48
|
}>;
|
|
49
|
+
/** CSS classes to apply to the default container */
|
|
48
50
|
className?: string;
|
|
51
|
+
/** Whether to render as a child component */
|
|
49
52
|
asChild?: boolean;
|
|
53
|
+
/** CSS classes to apply to variant names */
|
|
50
54
|
variantNameClassName?: string;
|
|
55
|
+
/** CSS classes to apply to variant prices */
|
|
51
56
|
variantPriceClassName?: string;
|
|
57
|
+
/** Optional content to display when no variants are available */
|
|
52
58
|
emptyState?: React.ReactNode;
|
|
53
59
|
}
|
|
54
|
-
export declare const Variants: React.ForwardRefExoticComponent<ItemDetailsVariantsProps & React.RefAttributes<HTMLElement>>;
|
|
55
60
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
61
|
+
* Headless component for item variants selection
|
|
62
|
+
* Renders variants using Radix UI RadioGroup for single selection
|
|
63
|
+
* Supports custom rendering via asChild or children render prop
|
|
58
64
|
*
|
|
59
|
-
* @component
|
|
60
65
|
* @example
|
|
61
66
|
* ```tsx
|
|
62
|
-
* <ItemDetails
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
67
|
+
* <ItemDetails.Variants
|
|
68
|
+
* variantNameClassName="font-paragraph text-foreground"
|
|
69
|
+
* variantPriceClassName="font-paragraph text-secondary-foreground"
|
|
70
|
+
* emptyState={<div>No variants available</div>}
|
|
71
|
+
* />
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* Custom rendering with children prop:
|
|
76
|
+
* ```tsx
|
|
77
|
+
* <ItemDetails.Variants asChild>
|
|
78
|
+
* {({ variants, selectedVariantId, onVariantChange }) => (
|
|
79
|
+
* <div className="variant-grid">
|
|
80
|
+
* {variants.map((variant) => (
|
|
81
|
+
* <button
|
|
82
|
+
* key={variant._id}
|
|
83
|
+
* onClick={() => onVariantChange?.(variant._id ?? '')}
|
|
84
|
+
* data-selected={selectedVariantId === variant._id}
|
|
85
|
+
* >
|
|
86
|
+
* <span>{variant.name}</span>
|
|
87
|
+
* <span>{variant.priceInfo?.formattedPrice}</span>
|
|
88
|
+
* </button>
|
|
89
|
+
* ))}
|
|
90
|
+
* </div>
|
|
91
|
+
* )}
|
|
92
|
+
* </ItemDetails.Variants>
|
|
69
93
|
* ```
|
|
70
94
|
*/
|
|
95
|
+
export declare const Variants: React.ForwardRefExoticComponent<ItemDetailsVariantsProps & React.RefAttributes<HTMLElement>>;
|
|
96
|
+
/**
|
|
97
|
+
* Props for the ItemDetails SpecialRequest component
|
|
98
|
+
*/
|
|
71
99
|
export interface SpecialRequestProps {
|
|
100
|
+
/** Whether to render as a child component */
|
|
72
101
|
asChild?: boolean;
|
|
102
|
+
/** Children render prop that receives value and onChange handler */
|
|
73
103
|
children?: AsChildChildren<{
|
|
74
104
|
value: string;
|
|
75
105
|
onChange: (value: string) => void;
|
|
@@ -82,6 +112,7 @@ export interface SpecialRequestProps {
|
|
|
82
112
|
rows?: number;
|
|
83
113
|
/** CSS classes to apply to the textarea */
|
|
84
114
|
className?: string;
|
|
115
|
+
/** CSS classes to apply to the label */
|
|
85
116
|
labelClassName?: string;
|
|
86
117
|
/** Label text for the input */
|
|
87
118
|
label?: string;
|
|
@@ -89,16 +120,16 @@ export interface SpecialRequestProps {
|
|
|
89
120
|
showCharCount?: boolean;
|
|
90
121
|
}
|
|
91
122
|
/**
|
|
92
|
-
*
|
|
93
|
-
* and gets the lineItem from CoreItemDetails.LineItemComponent.
|
|
94
|
-
*
|
|
95
|
-
* Usage:
|
|
96
|
-
* <ItemDetails.AddToCartButton>Add to cart</ItemDetails.AddToCartButton>
|
|
123
|
+
* Props for the ItemDetails AddToCartButton component
|
|
97
124
|
*/
|
|
98
125
|
export interface AddToCartButtonProps {
|
|
126
|
+
/** Whether to render as a child component */
|
|
99
127
|
asChild?: boolean;
|
|
128
|
+
/** CSS classes to apply to the button */
|
|
100
129
|
className?: string;
|
|
130
|
+
/** Map of button states to display text */
|
|
101
131
|
addToCartLabelMap: Record<AddToCartButtonState, string>;
|
|
132
|
+
/** Children render prop that receives button state and line item data */
|
|
102
133
|
children?: AsChildChildren<{
|
|
103
134
|
lineItem: LineItem;
|
|
104
135
|
buttonState: AddToCartButtonState;
|
|
@@ -111,10 +142,52 @@ export interface AddToCartButtonProps {
|
|
|
111
142
|
modifierGroupHasError: boolean;
|
|
112
143
|
}>;
|
|
113
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Headless component for adding item to cart
|
|
147
|
+
* Wraps Commerce.Actions.AddToCart and provides item-specific state
|
|
148
|
+
* Displays button state, price, and handles disabled states
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```tsx
|
|
152
|
+
* <ItemDetails.AddToCartButton
|
|
153
|
+
* className="bg-primary text-primary-foreground"
|
|
154
|
+
* addToCartLabelMap={{
|
|
155
|
+
* [AddToCartButtonState.ADD_TO_CART]: 'Add to Cart',
|
|
156
|
+
* [AddToCartButtonState.LOADING]: 'Adding...',
|
|
157
|
+
* [AddToCartButtonState.UPDATE_CART]: 'Update Cart',
|
|
158
|
+
* }}
|
|
159
|
+
* />
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* Custom rendering with children prop:
|
|
164
|
+
* ```tsx
|
|
165
|
+
* <ItemDetails.AddToCartButton
|
|
166
|
+
* addToCartLabelMap={labelMap}
|
|
167
|
+
* asChild
|
|
168
|
+
* >
|
|
169
|
+
* {({ buttonState, formattedPrice, modifierGroupHasError, addToCartButtonDisabled }) => (
|
|
170
|
+
* <button
|
|
171
|
+
* disabled={addToCartButtonDisabled || modifierGroupHasError}
|
|
172
|
+
* className="bg-primary text-primary-foreground"
|
|
173
|
+
* >
|
|
174
|
+
* <span>{labelMap[buttonState]}</span>
|
|
175
|
+
* <span>{formattedPrice}</span>
|
|
176
|
+
* </button>
|
|
177
|
+
* )}
|
|
178
|
+
* </ItemDetails.AddToCartButton>
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
114
181
|
export declare const AddToCartButton: React.ForwardRefExoticComponent<AddToCartButtonProps & React.RefAttributes<HTMLElement>>;
|
|
182
|
+
/**
|
|
183
|
+
* Props for the ItemDetails Quantity component
|
|
184
|
+
*/
|
|
115
185
|
export interface ItemDetailsQuantityProps {
|
|
186
|
+
/** Whether to render as a child component */
|
|
116
187
|
asChild?: boolean;
|
|
188
|
+
/** CSS classes to apply to the container */
|
|
117
189
|
className?: string;
|
|
190
|
+
/** Children render prop that receives quantity state and handlers */
|
|
118
191
|
children: (props: {
|
|
119
192
|
quantity: number;
|
|
120
193
|
increment: () => void;
|
|
@@ -125,13 +198,87 @@ export interface ItemDetailsQuantityProps {
|
|
|
125
198
|
onValueChange: (value: number) => void;
|
|
126
199
|
}) => React.ReactNode;
|
|
127
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Headless component for item quantity selection
|
|
203
|
+
* Provides increment/decrement controls with validation
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```tsx
|
|
207
|
+
* <ItemDetails.Quantity>
|
|
208
|
+
* {({ quantity, increment, decrement, canIncrement, canDecrement }) => (
|
|
209
|
+
* <div className="flex items-center gap-2">
|
|
210
|
+
* <button
|
|
211
|
+
* onClick={decrement}
|
|
212
|
+
* disabled={!canDecrement}
|
|
213
|
+
* className="bg-secondary text-secondary-foreground"
|
|
214
|
+
* >
|
|
215
|
+
* -
|
|
216
|
+
* </button>
|
|
217
|
+
* <span className="font-paragraph text-foreground">{quantity}</span>
|
|
218
|
+
* <button
|
|
219
|
+
* onClick={increment}
|
|
220
|
+
* disabled={!canIncrement}
|
|
221
|
+
* className="bg-secondary text-secondary-foreground"
|
|
222
|
+
* >
|
|
223
|
+
* +
|
|
224
|
+
* </button>
|
|
225
|
+
* </div>
|
|
226
|
+
* )}
|
|
227
|
+
* </ItemDetails.Quantity>
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
128
230
|
export declare const Quantity: React.FC<ItemDetailsQuantityProps>;
|
|
231
|
+
/**
|
|
232
|
+
* Headless component for special requests or custom instructions
|
|
233
|
+
* Provides a textarea for customers to add notes or modifications
|
|
234
|
+
* Supports character count and validation
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```tsx
|
|
238
|
+
* <ItemDetails.SpecialRequest
|
|
239
|
+
* placeholder="Any special requests?"
|
|
240
|
+
* maxLength={200}
|
|
241
|
+
* rows={3}
|
|
242
|
+
* label="Special Requests"
|
|
243
|
+
* className="border-foreground text-foreground"
|
|
244
|
+
* labelClassName="font-paragraph text-foreground"
|
|
245
|
+
* />
|
|
246
|
+
* ```
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* Custom rendering with children prop:
|
|
250
|
+
* ```tsx
|
|
251
|
+
* <ItemDetails.SpecialRequest asChild>
|
|
252
|
+
* {({ value, onChange }) => (
|
|
253
|
+
* <div>
|
|
254
|
+
* <label>Custom Instructions</label>
|
|
255
|
+
* <textarea
|
|
256
|
+
* value={value}
|
|
257
|
+
* onChange={(e) => onChange(e.target.value)}
|
|
258
|
+
* className="border-foreground text-foreground"
|
|
259
|
+
* />
|
|
260
|
+
* <span className="text-secondary-foreground">
|
|
261
|
+
* {value.length}/200
|
|
262
|
+
* </span>
|
|
263
|
+
* </div>
|
|
264
|
+
* )}
|
|
265
|
+
* </ItemDetails.SpecialRequest>
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
129
268
|
export declare const SpecialRequest: React.ForwardRefExoticComponent<SpecialRequestProps & React.RefAttributes<never>>;
|
|
269
|
+
/**
|
|
270
|
+
* Props for the ItemDetails Availability component
|
|
271
|
+
*/
|
|
130
272
|
export interface ItemDetailsAvailabilityProps {
|
|
273
|
+
/** Whether to render as a child component */
|
|
131
274
|
asChild?: boolean;
|
|
275
|
+
/** CSS classes to apply to the availability text */
|
|
132
276
|
textClassName?: string;
|
|
277
|
+
/** CSS classes to apply to the action button */
|
|
133
278
|
buttonClassName?: string;
|
|
279
|
+
/** Map of availability statuses to display text and actions */
|
|
134
280
|
availabilityStatusMap: AvailabilityStatusMap;
|
|
281
|
+
/** Children render prop that receives availability state and handlers */
|
|
135
282
|
children: (props: {
|
|
136
283
|
availabilityStatus: AvailabilityStatus;
|
|
137
284
|
availabilityStatusText?: string;
|
|
@@ -139,4 +286,54 @@ export interface ItemDetailsAvailabilityProps {
|
|
|
139
286
|
availabilityAction?: () => void;
|
|
140
287
|
}) => React.ReactNode;
|
|
141
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Headless component for item availability status display
|
|
291
|
+
* Shows availability messages and optional action buttons
|
|
292
|
+
* Does not render when item is available
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```tsx
|
|
296
|
+
* <ItemDetails.AvailabilityComponent
|
|
297
|
+
* availabilityStatusMap={{
|
|
298
|
+
* [AvailabilityStatus.OUT_OF_STOCK]: {
|
|
299
|
+
* text: 'Currently unavailable',
|
|
300
|
+
* buttonText: 'Notify me',
|
|
301
|
+
* action: () => handleNotify(),
|
|
302
|
+
* },
|
|
303
|
+
* [AvailabilityStatus.LIMITED_STOCK]: {
|
|
304
|
+
* text: 'Limited availability',
|
|
305
|
+
* },
|
|
306
|
+
* }}
|
|
307
|
+
* textClassName="text-destructive"
|
|
308
|
+
* buttonClassName="bg-primary text-primary-foreground"
|
|
309
|
+
* >
|
|
310
|
+
* {({ availabilityStatus, availabilityStatusText }) => (
|
|
311
|
+
* <div>{availabilityStatusText}</div>
|
|
312
|
+
* )}
|
|
313
|
+
* </ItemDetails.AvailabilityComponent>
|
|
314
|
+
* ```
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* Custom rendering with action button:
|
|
318
|
+
* ```tsx
|
|
319
|
+
* <ItemDetails.AvailabilityComponent
|
|
320
|
+
* availabilityStatusMap={statusMap}
|
|
321
|
+
* asChild
|
|
322
|
+
* >
|
|
323
|
+
* {({ availabilityStatus, availabilityStatusText, availabilityStatusButtonText, availabilityAction }) => (
|
|
324
|
+
* <div className="bg-destructive/10 p-4">
|
|
325
|
+
* <p className="text-destructive">{availabilityStatusText}</p>
|
|
326
|
+
* {availabilityStatusButtonText && availabilityAction && (
|
|
327
|
+
* <button
|
|
328
|
+
* onClick={availabilityAction}
|
|
329
|
+
* className="bg-primary text-primary-foreground"
|
|
330
|
+
* >
|
|
331
|
+
* {availabilityStatusButtonText}
|
|
332
|
+
* </button>
|
|
333
|
+
* )}
|
|
334
|
+
* </div>
|
|
335
|
+
* )}
|
|
336
|
+
* </ItemDetails.AvailabilityComponent>
|
|
337
|
+
* ```
|
|
338
|
+
*/
|
|
142
339
|
export declare const AvailabilityComponent: React.ForwardRefExoticComponent<ItemDetailsAvailabilityProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -7,6 +7,11 @@ import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
|
7
7
|
import { Item } from '@wix/headless-restaurants-menus/react';
|
|
8
8
|
import * as CoreItemDetails from './core/ItemDetails.js';
|
|
9
9
|
import { AvailabilityStatus, } from '../services/common-types.js';
|
|
10
|
+
// ========================================
|
|
11
|
+
// ITEM DETAILS HEADLESS COMPONENTS
|
|
12
|
+
// ========================================
|
|
13
|
+
// Headless components for menu item details display and interaction
|
|
14
|
+
// These components provide access to item data, variants, modifiers, and cart actions
|
|
10
15
|
var TestIds;
|
|
11
16
|
(function (TestIds) {
|
|
12
17
|
TestIds["itemName"] = "item-name";
|
|
@@ -19,9 +24,60 @@ var TestIds;
|
|
|
19
24
|
TestIds["itemVariants"] = "item-variants";
|
|
20
25
|
TestIds["itemAvailability"] = "item-availability";
|
|
21
26
|
})(TestIds || (TestIds = {}));
|
|
27
|
+
/**
|
|
28
|
+
* Root headless component for menu item details
|
|
29
|
+
* Provides service context and item data for all child components
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* <ItemDetails.Root itemDetailsServiceConfig={config}>
|
|
34
|
+
* <ItemDetails.Name />
|
|
35
|
+
* <ItemDetails.Price />
|
|
36
|
+
* <ItemDetails.Description />
|
|
37
|
+
* <ItemDetails.Variants />
|
|
38
|
+
* <ItemDetails.AddToCartButton />
|
|
39
|
+
* </ItemDetails.Root>
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
22
42
|
export const Root = ({ children, itemDetailsServiceConfig }) => {
|
|
23
43
|
return (_jsx(CoreItemDetails.Root, { itemDetailsServiceConfig: itemDetailsServiceConfig, children: ({ item }) => _jsx(Item.Root, { item: item, children: children }) }));
|
|
24
44
|
};
|
|
45
|
+
Root.displayName = 'ItemDetails.Root';
|
|
46
|
+
/**
|
|
47
|
+
* Headless component for item variants selection
|
|
48
|
+
* Renders variants using Radix UI RadioGroup for single selection
|
|
49
|
+
* Supports custom rendering via asChild or children render prop
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```tsx
|
|
53
|
+
* <ItemDetails.Variants
|
|
54
|
+
* variantNameClassName="font-paragraph text-foreground"
|
|
55
|
+
* variantPriceClassName="font-paragraph text-secondary-foreground"
|
|
56
|
+
* emptyState={<div>No variants available</div>}
|
|
57
|
+
* />
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* Custom rendering with children prop:
|
|
62
|
+
* ```tsx
|
|
63
|
+
* <ItemDetails.Variants asChild>
|
|
64
|
+
* {({ variants, selectedVariantId, onVariantChange }) => (
|
|
65
|
+
* <div className="variant-grid">
|
|
66
|
+
* {variants.map((variant) => (
|
|
67
|
+
* <button
|
|
68
|
+
* key={variant._id}
|
|
69
|
+
* onClick={() => onVariantChange?.(variant._id ?? '')}
|
|
70
|
+
* data-selected={selectedVariantId === variant._id}
|
|
71
|
+
* >
|
|
72
|
+
* <span>{variant.name}</span>
|
|
73
|
+
* <span>{variant.priceInfo?.formattedPrice}</span>
|
|
74
|
+
* </button>
|
|
75
|
+
* ))}
|
|
76
|
+
* </div>
|
|
77
|
+
* )}
|
|
78
|
+
* </ItemDetails.Variants>
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
25
81
|
export const Variants = React.forwardRef(({ children, className, asChild, variantNameClassName, variantPriceClassName, emptyState, }, ref) => {
|
|
26
82
|
return (_jsx(CoreItemDetails.VariantsComponent, { children: ({ variants, hasVariants, selectedVariantId, onVariantChange }) => {
|
|
27
83
|
if (!hasVariants) {
|
|
@@ -38,6 +94,42 @@ export const Variants = React.forwardRef(({ children, className, asChild, varian
|
|
|
38
94
|
} }));
|
|
39
95
|
});
|
|
40
96
|
Variants.displayName = 'ItemDetails.Variants';
|
|
97
|
+
/**
|
|
98
|
+
* Headless component for adding item to cart
|
|
99
|
+
* Wraps Commerce.Actions.AddToCart and provides item-specific state
|
|
100
|
+
* Displays button state, price, and handles disabled states
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```tsx
|
|
104
|
+
* <ItemDetails.AddToCartButton
|
|
105
|
+
* className="bg-primary text-primary-foreground"
|
|
106
|
+
* addToCartLabelMap={{
|
|
107
|
+
* [AddToCartButtonState.ADD_TO_CART]: 'Add to Cart',
|
|
108
|
+
* [AddToCartButtonState.LOADING]: 'Adding...',
|
|
109
|
+
* [AddToCartButtonState.UPDATE_CART]: 'Update Cart',
|
|
110
|
+
* }}
|
|
111
|
+
* />
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* Custom rendering with children prop:
|
|
116
|
+
* ```tsx
|
|
117
|
+
* <ItemDetails.AddToCartButton
|
|
118
|
+
* addToCartLabelMap={labelMap}
|
|
119
|
+
* asChild
|
|
120
|
+
* >
|
|
121
|
+
* {({ buttonState, formattedPrice, modifierGroupHasError, addToCartButtonDisabled }) => (
|
|
122
|
+
* <button
|
|
123
|
+
* disabled={addToCartButtonDisabled || modifierGroupHasError}
|
|
124
|
+
* className="bg-primary text-primary-foreground"
|
|
125
|
+
* >
|
|
126
|
+
* <span>{labelMap[buttonState]}</span>
|
|
127
|
+
* <span>{formattedPrice}</span>
|
|
128
|
+
* </button>
|
|
129
|
+
* )}
|
|
130
|
+
* </ItemDetails.AddToCartButton>
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
41
133
|
export const AddToCartButton = React.forwardRef(({ asChild, children, className, addToCartLabelMap, ...props }, ref) => {
|
|
42
134
|
return (_jsx(CoreItemDetails.LineItemComponent, { addToCartLabelMap: addToCartLabelMap, children: ({ lineItem, buttonState, addToCartButtonDisabled, loadingState, labelText, formattedPrice, modifierGroupHasError, }) => {
|
|
43
135
|
const label = (_jsxs(_Fragment, { children: [_jsx("span", { children: labelText }), " ", _jsx("span", { children: " | " }), _jsx("span", { children: formattedPrice })] }));
|
|
@@ -54,6 +146,35 @@ export const AddToCartButton = React.forwardRef(({ asChild, children, className,
|
|
|
54
146
|
} }));
|
|
55
147
|
});
|
|
56
148
|
AddToCartButton.displayName = 'AddToCartButton';
|
|
149
|
+
/**
|
|
150
|
+
* Headless component for item quantity selection
|
|
151
|
+
* Provides increment/decrement controls with validation
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```tsx
|
|
155
|
+
* <ItemDetails.Quantity>
|
|
156
|
+
* {({ quantity, increment, decrement, canIncrement, canDecrement }) => (
|
|
157
|
+
* <div className="flex items-center gap-2">
|
|
158
|
+
* <button
|
|
159
|
+
* onClick={decrement}
|
|
160
|
+
* disabled={!canDecrement}
|
|
161
|
+
* className="bg-secondary text-secondary-foreground"
|
|
162
|
+
* >
|
|
163
|
+
* -
|
|
164
|
+
* </button>
|
|
165
|
+
* <span className="font-paragraph text-foreground">{quantity}</span>
|
|
166
|
+
* <button
|
|
167
|
+
* onClick={increment}
|
|
168
|
+
* disabled={!canIncrement}
|
|
169
|
+
* className="bg-secondary text-secondary-foreground"
|
|
170
|
+
* >
|
|
171
|
+
* +
|
|
172
|
+
* </button>
|
|
173
|
+
* </div>
|
|
174
|
+
* )}
|
|
175
|
+
* </ItemDetails.Quantity>
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
57
178
|
export const Quantity = ({ children }) => {
|
|
58
179
|
return (_jsx(CoreItemDetails.QuantityComponent, { children: ({ quantity, onValueChange, increment, decrement, setQuantity, canIncrement, canDecrement, }) => (_jsx(QuantityComponent.Root, { onValueChange: onValueChange, initialValue: quantity, children: children({
|
|
59
180
|
quantity,
|
|
@@ -66,10 +187,97 @@ export const Quantity = ({ children }) => {
|
|
|
66
187
|
}) })) }));
|
|
67
188
|
};
|
|
68
189
|
Quantity.displayName = 'Quantity';
|
|
190
|
+
/**
|
|
191
|
+
* Headless component for special requests or custom instructions
|
|
192
|
+
* Provides a textarea for customers to add notes or modifications
|
|
193
|
+
* Supports character count and validation
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```tsx
|
|
197
|
+
* <ItemDetails.SpecialRequest
|
|
198
|
+
* placeholder="Any special requests?"
|
|
199
|
+
* maxLength={200}
|
|
200
|
+
* rows={3}
|
|
201
|
+
* label="Special Requests"
|
|
202
|
+
* className="border-foreground text-foreground"
|
|
203
|
+
* labelClassName="font-paragraph text-foreground"
|
|
204
|
+
* />
|
|
205
|
+
* ```
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* Custom rendering with children prop:
|
|
209
|
+
* ```tsx
|
|
210
|
+
* <ItemDetails.SpecialRequest asChild>
|
|
211
|
+
* {({ value, onChange }) => (
|
|
212
|
+
* <div>
|
|
213
|
+
* <label>Custom Instructions</label>
|
|
214
|
+
* <textarea
|
|
215
|
+
* value={value}
|
|
216
|
+
* onChange={(e) => onChange(e.target.value)}
|
|
217
|
+
* className="border-foreground text-foreground"
|
|
218
|
+
* />
|
|
219
|
+
* <span className="text-secondary-foreground">
|
|
220
|
+
* {value.length}/200
|
|
221
|
+
* </span>
|
|
222
|
+
* </div>
|
|
223
|
+
* )}
|
|
224
|
+
* </ItemDetails.SpecialRequest>
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
69
227
|
export const SpecialRequest = React.forwardRef(({ className, labelClassName, placeholder = 'Any special requests or dietary restrictions?', maxLength = 200, rows = 3, label = 'Special Requests', asChild, children, ...props }, ref) => {
|
|
70
228
|
return (_jsx(CoreItemDetails.SpecialRequest, { children: ({ value, onChange, }) => (_jsxs(AsChildSlot, { ref: ref, asChild: asChild, className: className, onChange: onChange, "data-testid": TestIds.itemSpecialRequest, customElement: children, customElementProps: { label, value, onChange }, content: value, ...props, children: [label && _jsx("label", { className: labelClassName, children: label }), _jsx("textarea", { value: value, onChange: (e) => onChange(e.target.value), placeholder: placeholder, maxLength: maxLength, rows: rows, className: className, children: value })] })) }));
|
|
71
229
|
});
|
|
72
230
|
SpecialRequest.displayName = 'SpecialRequest';
|
|
231
|
+
/**
|
|
232
|
+
* Headless component for item availability status display
|
|
233
|
+
* Shows availability messages and optional action buttons
|
|
234
|
+
* Does not render when item is available
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```tsx
|
|
238
|
+
* <ItemDetails.AvailabilityComponent
|
|
239
|
+
* availabilityStatusMap={{
|
|
240
|
+
* [AvailabilityStatus.OUT_OF_STOCK]: {
|
|
241
|
+
* text: 'Currently unavailable',
|
|
242
|
+
* buttonText: 'Notify me',
|
|
243
|
+
* action: () => handleNotify(),
|
|
244
|
+
* },
|
|
245
|
+
* [AvailabilityStatus.LIMITED_STOCK]: {
|
|
246
|
+
* text: 'Limited availability',
|
|
247
|
+
* },
|
|
248
|
+
* }}
|
|
249
|
+
* textClassName="text-destructive"
|
|
250
|
+
* buttonClassName="bg-primary text-primary-foreground"
|
|
251
|
+
* >
|
|
252
|
+
* {({ availabilityStatus, availabilityStatusText }) => (
|
|
253
|
+
* <div>{availabilityStatusText}</div>
|
|
254
|
+
* )}
|
|
255
|
+
* </ItemDetails.AvailabilityComponent>
|
|
256
|
+
* ```
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* Custom rendering with action button:
|
|
260
|
+
* ```tsx
|
|
261
|
+
* <ItemDetails.AvailabilityComponent
|
|
262
|
+
* availabilityStatusMap={statusMap}
|
|
263
|
+
* asChild
|
|
264
|
+
* >
|
|
265
|
+
* {({ availabilityStatus, availabilityStatusText, availabilityStatusButtonText, availabilityAction }) => (
|
|
266
|
+
* <div className="bg-destructive/10 p-4">
|
|
267
|
+
* <p className="text-destructive">{availabilityStatusText}</p>
|
|
268
|
+
* {availabilityStatusButtonText && availabilityAction && (
|
|
269
|
+
* <button
|
|
270
|
+
* onClick={availabilityAction}
|
|
271
|
+
* className="bg-primary text-primary-foreground"
|
|
272
|
+
* >
|
|
273
|
+
* {availabilityStatusButtonText}
|
|
274
|
+
* </button>
|
|
275
|
+
* )}
|
|
276
|
+
* </div>
|
|
277
|
+
* )}
|
|
278
|
+
* </ItemDetails.AvailabilityComponent>
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
73
281
|
export const AvailabilityComponent = React.forwardRef(({ asChild, children, textClassName, buttonClassName, availabilityStatusMap, ...rest }, ref) => {
|
|
74
282
|
return (_jsx(CoreItemDetails.AvailabilityComponent, { availabilityStatusMap: availabilityStatusMap, children: ({ availabilityStatus, availabilityAction, availabilityStatusText, availabilityStatusButtonText, }) => {
|
|
75
283
|
if (availabilityStatus === AvailabilityStatus.AVAILABLE) {
|
|
@@ -46,9 +46,6 @@ export const Description = React.forwardRef(({ ruleTypeMap, className, asChild,
|
|
|
46
46
|
Description.displayName = 'ItemDetailsModifierGroup.Description';
|
|
47
47
|
export const Error = React.forwardRef(({ ruleTypeMap, className, asChild, children, ...otherProps }, ref) => {
|
|
48
48
|
return (_jsx(GroupError, { ruleTypeMap: ruleTypeMap, children: ({ error }) => {
|
|
49
|
-
if (!error) {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
49
|
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, "data-testid": TestIds.modifierGroupError, className: className, customElement: children, customElementProps: { error }, content: error, ...otherProps, children: _jsx("p", { className: className, children: error }) }));
|
|
53
50
|
} }));
|
|
54
51
|
});
|