@wix/headless-restaurants-olo 0.0.0
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 +9 -0
- package/cjs/dist/react/ClickableItem.js +14 -0
- package/cjs/dist/react/ItemDetails.d.ts +279 -0
- package/cjs/dist/react/ItemDetails.js +137 -0
- package/cjs/dist/react/OLO.d.ts +179 -0
- package/cjs/dist/react/OLO.js +134 -0
- package/cjs/dist/react/core/ClickableItem.d.ts +13 -0
- package/cjs/dist/react/core/ClickableItem.js +21 -0
- package/cjs/dist/react/core/ItemDetails.d.ts +68 -0
- package/cjs/dist/react/core/ItemDetails.js +127 -0
- package/cjs/dist/react/core/OLO.d.ts +92 -0
- package/cjs/dist/react/core/OLO.js +122 -0
- package/cjs/dist/react/core/index.d.ts +3 -0
- package/cjs/dist/react/core/index.js +3 -0
- package/cjs/dist/react/index.d.ts +3 -0
- package/cjs/dist/react/index.js +3 -0
- package/cjs/dist/services/common-types.d.ts +19 -0
- package/cjs/dist/services/common-types.js +8 -0
- package/cjs/dist/services/index.d.ts +3 -0
- package/cjs/dist/services/index.js +3 -0
- package/cjs/dist/services/item-details-service.d.ts +169 -0
- package/cjs/dist/services/item-details-service.js +248 -0
- package/cjs/dist/services/olo-settings-service.d.ts +37 -0
- package/cjs/dist/services/olo-settings-service.js +45 -0
- package/cjs/dist/services/utils.d.ts +20 -0
- package/cjs/dist/services/utils.js +34 -0
- package/dist/react/ClickableItem.d.ts +9 -0
- package/dist/react/ClickableItem.js +14 -0
- package/dist/react/ItemDetails.d.ts +279 -0
- package/dist/react/ItemDetails.js +137 -0
- package/dist/react/OLO.d.ts +179 -0
- package/dist/react/OLO.js +134 -0
- package/dist/react/core/ClickableItem.d.ts +13 -0
- package/dist/react/core/ClickableItem.js +21 -0
- package/dist/react/core/ItemDetails.d.ts +68 -0
- package/dist/react/core/ItemDetails.js +127 -0
- package/dist/react/core/OLO.d.ts +92 -0
- package/dist/react/core/OLO.js +122 -0
- package/dist/react/core/index.d.ts +3 -0
- package/dist/react/core/index.js +3 -0
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.js +3 -0
- package/dist/services/common-types.d.ts +19 -0
- package/dist/services/common-types.js +8 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.js +3 -0
- package/dist/services/item-details-service.d.ts +169 -0
- package/dist/services/item-details-service.js +248 -0
- package/dist/services/olo-settings-service.d.ts +37 -0
- package/dist/services/olo-settings-service.js +45 -0
- package/dist/services/utils.d.ts +20 -0
- package/dist/services/utils.js +34 -0
- package/package.json +81 -0
- package/react/package.json +4 -0
- package/services/package.json +4 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Commerce } from '@wix/ecom/components';
|
|
3
|
+
import { type LineItem } from '@wix/ecom/services';
|
|
4
|
+
import { type AsChildChildren } from '@wix/headless-utils/react';
|
|
5
|
+
import { ItemServiceConfig } from '../services/item-details-service.js';
|
|
6
|
+
import { EnhancedModifier, EnhancedModifierGroup, EnhancedVariant } from '@wix/headless-restaurants-menus/services';
|
|
7
|
+
import { AvailabilityStatus, AvailabilityStatusMap } from '../services/common-types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Root component for menu item display and interaction.
|
|
10
|
+
* Provides context for all menu item-related components like name, price, description, image, etc.
|
|
11
|
+
*
|
|
12
|
+
* @component
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <ItemDetails>
|
|
16
|
+
* <ItemDetailsImage src="wix:image://v1/abc123.jpg" alt="Menu item" />
|
|
17
|
+
* <ItemDetailsName />
|
|
18
|
+
* <ItemDetailsPrice />
|
|
19
|
+
* <ItemDetailsDescription />
|
|
20
|
+
* </ItemDetails>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export interface RootProps {
|
|
24
|
+
asChild?: boolean;
|
|
25
|
+
children: React.ReactNode;
|
|
26
|
+
itemDetailsServiceConfig?: ItemServiceConfig;
|
|
27
|
+
}
|
|
28
|
+
export declare const Root: ({ children, itemDetailsServiceConfig }: RootProps) => import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
/**
|
|
30
|
+
* Displays the item name with customizable rendering.
|
|
31
|
+
*
|
|
32
|
+
* @component
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* <ItemDetails.Name />
|
|
36
|
+
* <ItemDetails.Name asChild>
|
|
37
|
+
* <h2 className="font-heading text-lg" />
|
|
38
|
+
* </ItemDetails.Name>
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export interface ItemDetailsNameProps {
|
|
42
|
+
asChild?: boolean;
|
|
43
|
+
/** Custom render function when using asChild */
|
|
44
|
+
children?: AsChildChildren<{
|
|
45
|
+
name: string;
|
|
46
|
+
}>;
|
|
47
|
+
/** CSS classes to apply to the default element */
|
|
48
|
+
className?: string;
|
|
49
|
+
}
|
|
50
|
+
export declare const Name: React.ForwardRefExoticComponent<ItemDetailsNameProps & React.RefAttributes<HTMLElement>>;
|
|
51
|
+
/**
|
|
52
|
+
* Displays the item price with customizable rendering.
|
|
53
|
+
*
|
|
54
|
+
* @component
|
|
55
|
+
* @example
|
|
56
|
+
* ```tsx
|
|
57
|
+
* <ItemDetails.Price />
|
|
58
|
+
* <ItemDetails.Price asChild>
|
|
59
|
+
* <span className="font-semibold text-lg" />
|
|
60
|
+
* </ItemDetails.Price>
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export interface ItemDetailsPriceProps {
|
|
64
|
+
asChild?: boolean;
|
|
65
|
+
/** CSS classes to apply to the default element */
|
|
66
|
+
className?: string;
|
|
67
|
+
}
|
|
68
|
+
export declare const Price: React.ForwardRefExoticComponent<ItemDetailsPriceProps & React.RefAttributes<HTMLElement>>;
|
|
69
|
+
/**
|
|
70
|
+
* Displays the item description with customizable rendering.
|
|
71
|
+
*
|
|
72
|
+
* @component
|
|
73
|
+
* @example
|
|
74
|
+
* ```tsx
|
|
75
|
+
* <ItemDetails.Description />
|
|
76
|
+
* <ItemDetails.Description asChild>
|
|
77
|
+
* <p className="text-sm" />
|
|
78
|
+
* </ItemDetails.Description>
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export interface ItemDetailsDescriptionProps {
|
|
82
|
+
asChild?: boolean;
|
|
83
|
+
/** CSS classes to apply to the default element */
|
|
84
|
+
className?: string;
|
|
85
|
+
}
|
|
86
|
+
export declare const Description: React.ForwardRefExoticComponent<ItemDetailsDescriptionProps & React.RefAttributes<HTMLElement>>;
|
|
87
|
+
/**
|
|
88
|
+
* Wrapper component for CoreItemDetails.ModifierComponent.
|
|
89
|
+
* Renders a single modifier with checkbox functionality.
|
|
90
|
+
*
|
|
91
|
+
* @component
|
|
92
|
+
* @example
|
|
93
|
+
* ```tsx
|
|
94
|
+
* <ItemDetails.Modifier>
|
|
95
|
+
* {({ modifier, isSelected, onToggle }) => (
|
|
96
|
+
* <div style={{ display: "flex", alignItems: "center" }}>
|
|
97
|
+
* <CheckboxPrimitive.Root
|
|
98
|
+
* className="CheckboxRoot"
|
|
99
|
+
* checked={isSelected}
|
|
100
|
+
* onCheckedChange={onToggle}
|
|
101
|
+
* id={modifier._id}
|
|
102
|
+
* >
|
|
103
|
+
* <CheckboxPrimitive.Indicator className="CheckboxIndicator">
|
|
104
|
+
* <CheckIcon />
|
|
105
|
+
* </CheckboxPrimitive.Indicator>
|
|
106
|
+
* </CheckboxPrimitive.Root>
|
|
107
|
+
* <label className="Label" htmlFor={modifier._id}>
|
|
108
|
+
* {modifier.name}
|
|
109
|
+
* </label>
|
|
110
|
+
* </div>
|
|
111
|
+
* )}
|
|
112
|
+
* </ItemDetails.Modifier>
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
export interface ItemDetailsModifiersSingleSelectProps {
|
|
116
|
+
children?: AsChildChildren<{
|
|
117
|
+
selectedModifierIds: string[];
|
|
118
|
+
onToggle: (modifierId: string) => void;
|
|
119
|
+
modifierGroup: EnhancedModifierGroup;
|
|
120
|
+
modifiers: EnhancedModifier[];
|
|
121
|
+
}>;
|
|
122
|
+
className?: string;
|
|
123
|
+
asChild?: boolean;
|
|
124
|
+
modifierNameClassName?: string;
|
|
125
|
+
modifierPriceClassName?: string;
|
|
126
|
+
}
|
|
127
|
+
export interface ModifierCheckboxProps {
|
|
128
|
+
selectedModifierIds: string[];
|
|
129
|
+
onToggle: (modifierId: string) => void;
|
|
130
|
+
className?: string;
|
|
131
|
+
asChild?: boolean;
|
|
132
|
+
modifierNameClassName?: string;
|
|
133
|
+
modifierPriceClassName?: string;
|
|
134
|
+
children?: AsChildChildren<{
|
|
135
|
+
selectedModifierIds: string[];
|
|
136
|
+
onToggle: (modifierId: string) => void;
|
|
137
|
+
}>;
|
|
138
|
+
}
|
|
139
|
+
export declare const ModifierCheckbox: React.ForwardRefExoticComponent<ModifierCheckboxProps & React.RefAttributes<HTMLElement>>;
|
|
140
|
+
export interface ModifierRadioProps {
|
|
141
|
+
modifierNameClassName?: string;
|
|
142
|
+
modifierPriceClassName?: string;
|
|
143
|
+
}
|
|
144
|
+
export declare const ModifierRadio: React.ForwardRefExoticComponent<ModifierRadioProps & React.RefAttributes<HTMLElement>>;
|
|
145
|
+
export declare const ModifiersSingleSelect: React.ForwardRefExoticComponent<ItemDetailsModifiersSingleSelectProps & React.RefAttributes<HTMLElement>>;
|
|
146
|
+
export interface ItemDetailsModifiersMultiSelectProps {
|
|
147
|
+
children?: AsChildChildren<{
|
|
148
|
+
selectedModifierIds: string[];
|
|
149
|
+
onToggle: (modifierId: string) => void;
|
|
150
|
+
modifierGroup: EnhancedModifierGroup;
|
|
151
|
+
modifiers: EnhancedModifier[];
|
|
152
|
+
}>;
|
|
153
|
+
className?: string;
|
|
154
|
+
asChild?: boolean;
|
|
155
|
+
modifierNameClassName?: string;
|
|
156
|
+
modifierPriceClassName?: string;
|
|
157
|
+
}
|
|
158
|
+
export declare const ModifiersMultiSelect: React.ForwardRefExoticComponent<ItemDetailsModifiersMultiSelectProps & React.RefAttributes<HTMLElement>>;
|
|
159
|
+
/**
|
|
160
|
+
* Wrapper component for CoreItemDetails.VariantsComponent.
|
|
161
|
+
* Renders the variants for the item using Radix UI RadioGroup.
|
|
162
|
+
*
|
|
163
|
+
* @component
|
|
164
|
+
* @example
|
|
165
|
+
* ```tsx
|
|
166
|
+
* <ItemDetails.Variants>
|
|
167
|
+
* {(variant) => <span>{variant.name}</span>}
|
|
168
|
+
* </ItemDetails.Variants>
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
export interface ItemDetailsVariantsProps {
|
|
172
|
+
children?: AsChildChildren<{
|
|
173
|
+
variants: EnhancedVariant[];
|
|
174
|
+
selectedVariantId?: string;
|
|
175
|
+
onVariantChange?: (variantId: string) => void;
|
|
176
|
+
}>;
|
|
177
|
+
className?: string;
|
|
178
|
+
asChild?: boolean;
|
|
179
|
+
variantNameClassName?: string;
|
|
180
|
+
variantPriceClassName?: string;
|
|
181
|
+
}
|
|
182
|
+
export declare const Variants: React.ForwardRefExoticComponent<ItemDetailsVariantsProps & React.RefAttributes<HTMLElement>>;
|
|
183
|
+
export interface AddToCartActionProps {
|
|
184
|
+
/** Whether to render as a child component */
|
|
185
|
+
asChild?: boolean;
|
|
186
|
+
/** Text label for the button */
|
|
187
|
+
label: string;
|
|
188
|
+
/** Custom render function when using asChild */
|
|
189
|
+
lineItems: LineItem[];
|
|
190
|
+
/** CSS classes to apply to the button */
|
|
191
|
+
className?: string;
|
|
192
|
+
/** Content to display when loading */
|
|
193
|
+
loadingState?: string | React.ReactNode;
|
|
194
|
+
children?: React.ReactNode;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Add to Cart button for the menu item.
|
|
198
|
+
* Triggers the action to add the selected item (and its modifiers/variants) to the cart.
|
|
199
|
+
*
|
|
200
|
+
* @component
|
|
201
|
+
* @example
|
|
202
|
+
* ```tsx
|
|
203
|
+
* <ItemDetails>
|
|
204
|
+
* <AddToCart
|
|
205
|
+
* label="Add to Cart"
|
|
206
|
+
* lineItems={[{ catalogReference: { ... }, quantity: 1 }]}
|
|
207
|
+
* />
|
|
208
|
+
* </ItemDetails>
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
export declare const AddToCart: React.ForwardRefExoticComponent<AddToCartActionProps & React.RefAttributes<HTMLButtonElement>>;
|
|
212
|
+
/**
|
|
213
|
+
* Multi-line text input component for special requests or instructions.
|
|
214
|
+
* Provides a textarea for customers to add custom notes or modifications.
|
|
215
|
+
*
|
|
216
|
+
* @component
|
|
217
|
+
* @example
|
|
218
|
+
* ```tsx
|
|
219
|
+
* <ItemDetails>
|
|
220
|
+
* <SpecialRequest
|
|
221
|
+
* placeholder="Any special requests or dietary restrictions?"
|
|
222
|
+
* maxLength={200}
|
|
223
|
+
* className="mt-4"
|
|
224
|
+
* />
|
|
225
|
+
* </ItemDetails>
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
export interface SpecialRequestProps {
|
|
229
|
+
asChild?: boolean;
|
|
230
|
+
children?: AsChildChildren<{
|
|
231
|
+
description: string;
|
|
232
|
+
}>;
|
|
233
|
+
/** Placeholder text for the textarea */
|
|
234
|
+
placeholder?: string;
|
|
235
|
+
/** Maximum number of characters allowed */
|
|
236
|
+
maxLength?: number;
|
|
237
|
+
/** Number of visible text lines */
|
|
238
|
+
rows?: number;
|
|
239
|
+
/** CSS classes to apply to the textarea */
|
|
240
|
+
className?: string;
|
|
241
|
+
labelClassName?: string;
|
|
242
|
+
/** Label text for the input */
|
|
243
|
+
label?: string;
|
|
244
|
+
/** Whether to show character count */
|
|
245
|
+
showCharCount?: boolean;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* AddToCartButton component that uses Commerce.Actions.AddToCart with AsChildSlot,
|
|
249
|
+
* and gets the lineItem from CoreItemDetails.LineItemComponent.
|
|
250
|
+
*
|
|
251
|
+
* Usage:
|
|
252
|
+
* <ItemDetails.AddToCartButton>Add to cart</ItemDetails.AddToCartButton>
|
|
253
|
+
*/
|
|
254
|
+
export interface AddToCartButtonProps extends Omit<React.ComponentPropsWithoutRef<typeof Commerce.Actions.AddToCart>, 'lineItems'> {
|
|
255
|
+
asChild?: boolean;
|
|
256
|
+
children?: React.ReactNode;
|
|
257
|
+
className?: string;
|
|
258
|
+
label?: string;
|
|
259
|
+
onClick?: () => void;
|
|
260
|
+
}
|
|
261
|
+
export interface ItemDetailsQuantityProps {
|
|
262
|
+
children: React.ReactNode;
|
|
263
|
+
}
|
|
264
|
+
export declare const AddToCartButton: React.FC<AddToCartButtonProps>;
|
|
265
|
+
export declare const Quantity: React.FC<ItemDetailsQuantityProps>;
|
|
266
|
+
export declare const SpecialRequest: React.ForwardRefExoticComponent<SpecialRequestProps & React.RefAttributes<never>>;
|
|
267
|
+
export interface ItemDetailsAvailabilityProps {
|
|
268
|
+
asChild?: boolean;
|
|
269
|
+
textClassName?: string;
|
|
270
|
+
buttonClassName?: string;
|
|
271
|
+
availabilityStatusMap: AvailabilityStatusMap;
|
|
272
|
+
children: (props: {
|
|
273
|
+
availabilityStatus: AvailabilityStatus;
|
|
274
|
+
availabilityStatusText?: string;
|
|
275
|
+
availabilityStatusButtonText?: string;
|
|
276
|
+
availabilityAction?: () => void;
|
|
277
|
+
}) => React.ReactNode;
|
|
278
|
+
}
|
|
279
|
+
export declare const AvailabilityComponent: React.ForwardRefExoticComponent<ItemDetailsAvailabilityProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Commerce } from '@wix/ecom/components';
|
|
4
|
+
import { AsChildSlot } from '@wix/headless-utils/react';
|
|
5
|
+
import { Quantity as QuantityComponent } from '@wix/headless-components/react';
|
|
6
|
+
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
7
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
8
|
+
import { Item, Modifier, ModifierGroup, useModifierContext, } from '@wix/headless-restaurants-menus/react';
|
|
9
|
+
import * as CoreItemDetails from './core/ItemDetails.js';
|
|
10
|
+
import { AvailabilityStatus, } from '../services/common-types.js';
|
|
11
|
+
var TestIds;
|
|
12
|
+
(function (TestIds) {
|
|
13
|
+
TestIds["itemName"] = "item-name";
|
|
14
|
+
TestIds["itemPrice"] = "item-price";
|
|
15
|
+
TestIds["itemDescription"] = "item-description";
|
|
16
|
+
TestIds["itemImage"] = "item-image";
|
|
17
|
+
TestIds["itemAddToCart"] = "item-add-to-cart";
|
|
18
|
+
TestIds["itemSpecialRequest"] = "item-special-request";
|
|
19
|
+
TestIds["itemLabels"] = "item-labels";
|
|
20
|
+
TestIds["itemVariants"] = "item-variants";
|
|
21
|
+
TestIds["itemModifier"] = "item-modifier";
|
|
22
|
+
TestIds["itemAvailability"] = "item-availability";
|
|
23
|
+
})(TestIds || (TestIds = {}));
|
|
24
|
+
const CheckIcon = () => (_jsx("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z", fill: "currentColor" }) }));
|
|
25
|
+
export const Root = ({ children, itemDetailsServiceConfig }) => {
|
|
26
|
+
return (_jsx(CoreItemDetails.Root, { itemDetailsServiceConfig: itemDetailsServiceConfig, children: ({ item }) => _jsx(Item.Root, { item: item, children: children }) }));
|
|
27
|
+
};
|
|
28
|
+
export const Name = React.forwardRef(({ asChild, children, className, ...rest }, ref) => {
|
|
29
|
+
return (_jsx(Item.Name, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.itemName, ...rest, children: children }));
|
|
30
|
+
});
|
|
31
|
+
Name.displayName = 'ItemDetails.Name';
|
|
32
|
+
export const Price = React.forwardRef(({ asChild, className, ...rest }, ref) => {
|
|
33
|
+
return (_jsx(Item.Price, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.itemPrice, ...rest }));
|
|
34
|
+
});
|
|
35
|
+
Price.displayName = 'ItemDetails.Price';
|
|
36
|
+
export const Description = React.forwardRef(({ asChild, className, ...rest }, ref) => {
|
|
37
|
+
return (_jsx(Item.Description, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.itemDescription, ...rest }));
|
|
38
|
+
});
|
|
39
|
+
Description.displayName = 'ItemDetails.Description';
|
|
40
|
+
export const ModifierCheckbox = React.forwardRef(({ selectedModifierIds, onToggle, className, asChild, modifierNameClassName, modifierPriceClassName, children, ...rest }) => {
|
|
41
|
+
const { modifier } = useModifierContext();
|
|
42
|
+
const isSelected = selectedModifierIds.includes(modifier._id || '');
|
|
43
|
+
return (_jsx(AsChildSlot, { asChild: asChild, testId: TestIds.itemModifier, className: className, customElement: children, customElementProps: {
|
|
44
|
+
selectedModifierIds,
|
|
45
|
+
onToggle,
|
|
46
|
+
}, ...rest, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [_jsx(CheckboxPrimitive.Root, { className: "CheckboxRoot", checked: isSelected, onCheckedChange: () => onToggle(modifier._id || ''), id: modifier._id || undefined, children: _jsx(CheckboxPrimitive.Indicator, { className: "CheckboxIndicator", children: _jsx(CheckIcon, {}) }) }), _jsxs("label", { className: "Label", htmlFor: modifier._id || undefined, children: [_jsx(Modifier.Name, { className: modifierNameClassName }), _jsx(Modifier.Price, { className: modifierPriceClassName })] })] }) }));
|
|
47
|
+
});
|
|
48
|
+
ModifierCheckbox.displayName = 'ItemDetails.ModifierCheckbox';
|
|
49
|
+
export const ModifierRadio = React.forwardRef(({ modifierNameClassName, modifierPriceClassName }) => {
|
|
50
|
+
const { modifier } = useModifierContext();
|
|
51
|
+
return (_jsx(RadioGroupPrimitive.Item, { className: "RadioGroupItem", value: modifier._id || '', id: modifier._id || undefined, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [_jsx(RadioGroupPrimitive.Indicator, { className: "RadioGroupIndicator" }), _jsxs("label", { className: "Label", htmlFor: modifier._id || undefined, children: [_jsx(Modifier.Name, { className: modifierNameClassName }), _jsx(Modifier.Price, { className: modifierPriceClassName })] })] }) }));
|
|
52
|
+
});
|
|
53
|
+
ModifierRadio.displayName = 'ItemDetails.ModifierRadio';
|
|
54
|
+
export const ModifiersSingleSelect = React.forwardRef(({ children, className, asChild, modifierNameClassName, modifierPriceClassName, ...rest }) => {
|
|
55
|
+
return (_jsx(CoreItemDetails.ModifiersComponent, { singleSelect: true, children: ({ selectedModifierIds, onToggle, modifierGroup, modifiers }) => {
|
|
56
|
+
const selectedModifierId = selectedModifierIds.length > 0 ? selectedModifierIds[0] : '';
|
|
57
|
+
return (_jsx(AsChildSlot, { asChild: asChild, testId: TestIds.itemModifier, className: className, customElement: children, customElementProps: {
|
|
58
|
+
selectedModifierIds,
|
|
59
|
+
onToggle,
|
|
60
|
+
modifierGroup,
|
|
61
|
+
modifiers,
|
|
62
|
+
}, ...rest, children: _jsx(RadioGroupPrimitive.Root, { value: selectedModifierId, onValueChange: onToggle, children: _jsx(ModifierGroup.ModifiersRepeater, { children: _jsx(ModifierRadio, { modifierNameClassName: modifierNameClassName, modifierPriceClassName: modifierPriceClassName }) }) }) }));
|
|
63
|
+
} }));
|
|
64
|
+
});
|
|
65
|
+
ModifiersSingleSelect.displayName = 'ItemDetails.ModifiersSingleSelect';
|
|
66
|
+
export const ModifiersMultiSelect = React.forwardRef(({ children, className, asChild, modifierNameClassName, modifierPriceClassName, ...rest }) => {
|
|
67
|
+
return (_jsx(CoreItemDetails.ModifiersComponent, { singleSelect: false, children: ({ selectedModifierIds, onToggle, modifierGroup, modifiers }) => {
|
|
68
|
+
return (_jsx(AsChildSlot, { asChild: asChild, testId: TestIds.itemModifier, className: className, customElement: children, customElementProps: {
|
|
69
|
+
selectedModifierIds,
|
|
70
|
+
onToggle,
|
|
71
|
+
modifierGroup,
|
|
72
|
+
modifiers,
|
|
73
|
+
}, ...rest, children: _jsx(ModifierGroup.ModifiersRepeater, { children: _jsx(ModifierCheckbox, { selectedModifierIds: selectedModifierIds, onToggle: onToggle, modifierNameClassName: modifierNameClassName, modifierPriceClassName: modifierPriceClassName }) }) }));
|
|
74
|
+
} }));
|
|
75
|
+
});
|
|
76
|
+
ModifiersMultiSelect.displayName = 'ItemDetails.ModifiersMultiSelect';
|
|
77
|
+
export const Variants = React.forwardRef(({ children, className, asChild, variantNameClassName, variantPriceClassName, }, ref) => {
|
|
78
|
+
return (_jsx(CoreItemDetails.VariantsComponent, { children: ({ variants, hasVariants, selectedVariantId, onVariantChange }) => {
|
|
79
|
+
if (!hasVariants) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, testId: TestIds.itemVariants, className: className, customElement: children, customElementProps: {
|
|
83
|
+
variants,
|
|
84
|
+
selectedVariantId,
|
|
85
|
+
onVariantChange,
|
|
86
|
+
}, children: _jsx(RadioGroupPrimitive.Root, { value: selectedVariantId, onValueChange: onVariantChange, children: variants.map((variant) => (_jsx(RadioGroupPrimitive.Item, { value: variant._id ?? '', children: _jsxs("div", { children: [_jsx("div", { className: variantNameClassName, children: variant.name }), _jsx("div", { className: variantPriceClassName, children: variant.priceInfo?.formattedPrice ||
|
|
87
|
+
variant.priceInfo?.price ||
|
|
88
|
+
'' })] }) }, variant._id))) }) }));
|
|
89
|
+
} }));
|
|
90
|
+
});
|
|
91
|
+
Variants.displayName = 'ItemDetails.Variants';
|
|
92
|
+
/**
|
|
93
|
+
* Add to Cart button for the menu item.
|
|
94
|
+
* Triggers the action to add the selected item (and its modifiers/variants) to the cart.
|
|
95
|
+
*
|
|
96
|
+
* @component
|
|
97
|
+
* @example
|
|
98
|
+
* ```tsx
|
|
99
|
+
* <ItemDetails>
|
|
100
|
+
* <AddToCart
|
|
101
|
+
* label="Add to Cart"
|
|
102
|
+
* lineItems={[{ catalogReference: { ... }, quantity: 1 }]}
|
|
103
|
+
* />
|
|
104
|
+
* </ItemDetails>
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export const AddToCart = React.forwardRef(({ lineItems, className, label, ...props }, ref) => {
|
|
108
|
+
return (_jsx(Commerce.Actions.AddToCart, { ref: ref, asChild: false, label: label, className: className, lineItems: lineItems, children: props.children }));
|
|
109
|
+
});
|
|
110
|
+
AddToCart.displayName = 'AddToCart';
|
|
111
|
+
export const AddToCartButton = ({ asChild = false, children, className, onClick, label = 'Add to cart', ...props }) => {
|
|
112
|
+
return (_jsx(CoreItemDetails.LineItemComponent, { children: ({ lineItem }) => (_jsx(AsChildSlot, { asChild: asChild, className: className, customElement: children, customElementProps: {
|
|
113
|
+
onClick,
|
|
114
|
+
}, children: _jsx(Commerce.Actions.AddToCart, { asChild: false, label: label, className: className, lineItems: [lineItem], ...props, children: children }) })) }));
|
|
115
|
+
};
|
|
116
|
+
export const Quantity = ({ children }) => {
|
|
117
|
+
return (_jsx(CoreItemDetails.QuantityComponent, { children: ({ quantity, onValueChange, }) => (_jsx(QuantityComponent.Root, { onValueChange: onValueChange, initialValue: quantity, children: children })) }));
|
|
118
|
+
};
|
|
119
|
+
Quantity.displayName = 'Quantity';
|
|
120
|
+
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) => {
|
|
121
|
+
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 }, 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 })] })) }));
|
|
122
|
+
});
|
|
123
|
+
SpecialRequest.displayName = 'SpecialRequest';
|
|
124
|
+
export const AvailabilityComponent = React.forwardRef(({ asChild, children, textClassName, buttonClassName, availabilityStatusMap, ...rest }, ref) => {
|
|
125
|
+
return (_jsx(CoreItemDetails.AvailabilityComponent, { availabilityStatusMap: availabilityStatusMap, children: ({ availabilityStatus, availabilityAction, availabilityStatusText, availabilityStatusButtonText, }) => {
|
|
126
|
+
if (availabilityStatus === AvailabilityStatus.AVAILABLE) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
return (_jsxs(AsChildSlot, { asChild: asChild, "data-testid": TestIds.itemAvailability, customElement: children, customElementProps: {
|
|
130
|
+
availabilityStatus,
|
|
131
|
+
availabilityStatusText,
|
|
132
|
+
availabilityStatusButtonText,
|
|
133
|
+
availabilityAction,
|
|
134
|
+
}, ref: ref, ...rest, children: [_jsx("p", { className: textClassName, children: availabilityStatusText }), availabilityStatusButtonText && availabilityAction && (_jsx("button", { className: buttonClassName, onClick: availabilityAction, children: availabilityStatusButtonText }))] }));
|
|
135
|
+
} }));
|
|
136
|
+
});
|
|
137
|
+
AvailabilityComponent.displayName = 'AvailabilityComponent';
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ItemServiceConfig } from '../services/item-details-service.js';
|
|
3
|
+
interface OLORootProps {
|
|
4
|
+
/** The ID of the item to load */
|
|
5
|
+
itemId?: string;
|
|
6
|
+
/** Pre-loaded item service config (optional) */
|
|
7
|
+
itemServiceConfig?: any;
|
|
8
|
+
/** Pre-loaded OLO settings service config (optional) */
|
|
9
|
+
oloSettingsServiceConfig?: any;
|
|
10
|
+
/** Children render prop that receives the service state */
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Root headless component for OLO service management
|
|
15
|
+
* Wraps CoreOLO.Root and provides service state to children
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* <OLO.Root itemId="item-123">
|
|
20
|
+
* {({ isLoading, hasServices, error, retry }) => (
|
|
21
|
+
* isLoading ? (
|
|
22
|
+
* <LoadingSpinner />
|
|
23
|
+
* ) : error ? (
|
|
24
|
+
* <ErrorMessage error={error} onRetry={retry} />
|
|
25
|
+
* ) : hasServices ? (
|
|
26
|
+
* <ItemDetailsComponents />
|
|
27
|
+
* ) : null
|
|
28
|
+
* )}
|
|
29
|
+
* </OLO.Root>
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare const Root: React.FC<OLORootProps>;
|
|
33
|
+
interface OLOProviderProps {
|
|
34
|
+
/** The ID of the item to load */
|
|
35
|
+
itemId?: string;
|
|
36
|
+
/** Pre-loaded configurations (optional) */
|
|
37
|
+
configs?: {
|
|
38
|
+
itemServiceConfig?: ItemServiceConfig;
|
|
39
|
+
};
|
|
40
|
+
/** Loading component to show while services are initializing */
|
|
41
|
+
loading?: React.ReactNode;
|
|
42
|
+
/** Error component to show if service initialization fails */
|
|
43
|
+
error?: (props: {
|
|
44
|
+
error: string;
|
|
45
|
+
retry: () => void;
|
|
46
|
+
}) => React.ReactNode;
|
|
47
|
+
/** Children that will receive the services context */
|
|
48
|
+
children: React.ReactNode;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Convenience provider that handles loading and error states automatically
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* <OLO.Provider
|
|
56
|
+
* itemId="item-123"
|
|
57
|
+
* loading={<Spinner />}
|
|
58
|
+
* error={({ error, retry }) => <ErrorBanner message={error} onRetry={retry} />}
|
|
59
|
+
* >
|
|
60
|
+
* <ItemDetailsComponents />
|
|
61
|
+
* </OLO.Provider>
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare const Provider: React.FC<OLOProviderProps>;
|
|
65
|
+
interface OLOItemDetailsProps {
|
|
66
|
+
/** The ID of the item to load */
|
|
67
|
+
itemId: string;
|
|
68
|
+
/** Pre-loaded configurations (optional) */
|
|
69
|
+
configs?: {
|
|
70
|
+
itemServiceConfig?: ItemServiceConfig;
|
|
71
|
+
cartServiceConfig?: any;
|
|
72
|
+
};
|
|
73
|
+
/** Custom loading component */
|
|
74
|
+
loading?: React.ReactNode;
|
|
75
|
+
/** Custom error component */
|
|
76
|
+
error?: (props: {
|
|
77
|
+
error: string;
|
|
78
|
+
retry: () => void;
|
|
79
|
+
}) => React.ReactNode;
|
|
80
|
+
/** Custom not found component */
|
|
81
|
+
notFound?: React.ReactNode;
|
|
82
|
+
/** Children that will have access to item services */
|
|
83
|
+
children: React.ReactNode;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Specialized headless component for item details
|
|
87
|
+
* Includes item-specific error handling (like 404 not found)
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```tsx
|
|
91
|
+
* <OLO.ItemDetails
|
|
92
|
+
* itemId="item-123"
|
|
93
|
+
* notFound={<NotFoundPage />}
|
|
94
|
+
* >
|
|
95
|
+
* <ItemDetailsUI />
|
|
96
|
+
* </OLO.ItemDetails>
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare const ItemDetails: React.FC<OLOItemDetailsProps>;
|
|
100
|
+
interface OLOCartProps {
|
|
101
|
+
/** Pre-loaded cart service config (optional) */
|
|
102
|
+
cartServiceConfig?: any;
|
|
103
|
+
/** Loading component */
|
|
104
|
+
loading?: React.ReactNode;
|
|
105
|
+
/** Error component */
|
|
106
|
+
error?: (props: {
|
|
107
|
+
error: string;
|
|
108
|
+
retry: () => void;
|
|
109
|
+
}) => React.ReactNode;
|
|
110
|
+
/** Children that will have access to cart services */
|
|
111
|
+
children: React.ReactNode;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Headless component for cart-only functionality
|
|
115
|
+
* Doesn't load item services, only cart services
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```tsx
|
|
119
|
+
* <OLO.Cart>
|
|
120
|
+
* <CartComponents />
|
|
121
|
+
* </OLO.Cart>
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
export declare const Cart: React.FC<OLOCartProps>;
|
|
125
|
+
interface OLOServicesStatusProps {
|
|
126
|
+
/** The ID of the item to check */
|
|
127
|
+
itemId?: string;
|
|
128
|
+
/** Children render prop that receives service status */
|
|
129
|
+
children: React.ReactNode;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Headless component for checking service status
|
|
133
|
+
* Useful for debugging or conditional rendering
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```tsx
|
|
137
|
+
* <OLO.ServicesStatus itemId="item-123">
|
|
138
|
+
* {({ hasItemService, hasCartService, error }) => (
|
|
139
|
+
* <div>
|
|
140
|
+
* Item Service: {hasItemService ? '✅' : '❌'}
|
|
141
|
+
* Cart Service: {hasCartService ? '✅' : '❌'}
|
|
142
|
+
* {error && <div>Error: {error}</div>}
|
|
143
|
+
* </div>
|
|
144
|
+
* )}
|
|
145
|
+
* </OLO.ServicesStatus>
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export declare const ServicesStatus: React.FC<OLOServicesStatusProps>;
|
|
149
|
+
/**
|
|
150
|
+
* Headless component for Menus service management.
|
|
151
|
+
* Wraps CoreOLO.Menus and provides render props for UI.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```tsx
|
|
155
|
+
* <OLO.Menus>
|
|
156
|
+
* {({ menus, isLoading, error }) => (
|
|
157
|
+
* isLoading ? (
|
|
158
|
+
* <div>Loading...</div>
|
|
159
|
+
* ) : error ? (
|
|
160
|
+
* <div className="text-destructive">{error}</div>
|
|
161
|
+
* ) : (
|
|
162
|
+
* <ul>
|
|
163
|
+
* {menus.map(menu => (
|
|
164
|
+
* <li key={menu.id} className="text-foreground font-paragraph">{menu.name}</li>
|
|
165
|
+
* ))}
|
|
166
|
+
* </ul>
|
|
167
|
+
* )
|
|
168
|
+
* )}
|
|
169
|
+
* </OLO.Menus>
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
interface OLOMenusProps {
|
|
173
|
+
/** Optional menu service config */
|
|
174
|
+
menuServiceConfig?: any;
|
|
175
|
+
/** Children render prop that receives menus state */
|
|
176
|
+
children?: React.ReactNode;
|
|
177
|
+
}
|
|
178
|
+
export declare const Menus: React.FC<OLOMenusProps>;
|
|
179
|
+
export {};
|