@wix/headless-gift-voucher 0.0.1
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/__mocks__/gift-card.d.ts +14 -0
- package/cjs/dist/__mocks__/gift-card.d.ts.map +1 -0
- package/cjs/dist/__mocks__/gift-card.js +49 -0
- package/cjs/dist/enums/index.d.ts +52 -0
- package/cjs/dist/enums/index.d.ts.map +1 -0
- package/cjs/dist/enums/index.js +52 -0
- package/cjs/dist/react/GiftCard.d.ts +1318 -0
- package/cjs/dist/react/GiftCard.d.ts.map +1 -0
- package/cjs/dist/react/GiftCard.js +1126 -0
- package/cjs/dist/react/core/GiftCard.d.ts +863 -0
- package/cjs/dist/react/core/GiftCard.d.ts.map +1 -0
- package/cjs/dist/react/core/GiftCard.js +737 -0
- package/cjs/dist/react/index.d.ts +2 -0
- package/cjs/dist/react/index.d.ts.map +1 -0
- package/cjs/dist/react/index.js +1 -0
- package/cjs/dist/services/gift-card-checkout-service.d.ts +133 -0
- package/cjs/dist/services/gift-card-checkout-service.d.ts.map +1 -0
- package/cjs/dist/services/gift-card-checkout-service.js +159 -0
- package/cjs/dist/services/gift-card-service.d.ts +102 -0
- package/cjs/dist/services/gift-card-service.d.ts.map +1 -0
- package/cjs/dist/services/gift-card-service.js +165 -0
- package/cjs/dist/services/index.d.ts +3 -0
- package/cjs/dist/services/index.d.ts.map +1 -0
- package/cjs/dist/services/index.js +2 -0
- package/cjs/dist/utils/formatting-utils.d.ts +13 -0
- package/cjs/dist/utils/formatting-utils.d.ts.map +1 -0
- package/cjs/dist/utils/formatting-utils.js +38 -0
- package/cjs/dist/utils/gift-card-utils.d.ts +18 -0
- package/cjs/dist/utils/gift-card-utils.d.ts.map +1 -0
- package/cjs/dist/utils/gift-card-utils.js +118 -0
- package/cjs/dist/utils/validation-utils.d.ts +10 -0
- package/cjs/dist/utils/validation-utils.d.ts.map +1 -0
- package/cjs/dist/utils/validation-utils.js +24 -0
- package/dist/__mocks__/gift-card.d.ts +14 -0
- package/dist/__mocks__/gift-card.d.ts.map +1 -0
- package/dist/__mocks__/gift-card.js +49 -0
- package/dist/enums/index.d.ts +52 -0
- package/dist/enums/index.d.ts.map +1 -0
- package/dist/enums/index.js +52 -0
- package/dist/react/GiftCard.d.ts +1318 -0
- package/dist/react/GiftCard.d.ts.map +1 -0
- package/dist/react/GiftCard.js +1126 -0
- package/dist/react/core/GiftCard.d.ts +863 -0
- package/dist/react/core/GiftCard.d.ts.map +1 -0
- package/dist/react/core/GiftCard.js +737 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +1 -0
- package/dist/services/gift-card-checkout-service.d.ts +133 -0
- package/dist/services/gift-card-checkout-service.d.ts.map +1 -0
- package/dist/services/gift-card-checkout-service.js +159 -0
- package/dist/services/gift-card-service.d.ts +102 -0
- package/dist/services/gift-card-service.d.ts.map +1 -0
- package/dist/services/gift-card-service.js +165 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +2 -0
- package/dist/utils/formatting-utils.d.ts +13 -0
- package/dist/utils/formatting-utils.d.ts.map +1 -0
- package/dist/utils/formatting-utils.js +38 -0
- package/dist/utils/gift-card-utils.d.ts +18 -0
- package/dist/utils/gift-card-utils.d.ts.map +1 -0
- package/dist/utils/gift-card-utils.js +118 -0
- package/dist/utils/validation-utils.d.ts +10 -0
- package/dist/utils/validation-utils.d.ts.map +1 -0
- package/dist/utils/validation-utils.js +24 -0
- package/package.json +72 -0
- package/react/package.json +4 -0
- package/services/package.json +4 -0
|
@@ -0,0 +1,1126 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import * as CoreGiftCard from './core/GiftCard.js';
|
|
4
|
+
import { AsChildSlot } from '@wix/headless-utils/react';
|
|
5
|
+
import { WixMediaImage } from '@wix/headless-media/react';
|
|
6
|
+
import { Money, Quantity as QuantityComponent, } from '@wix/headless-components/react';
|
|
7
|
+
import { Commerce } from '@wix/headless-ecom/react';
|
|
8
|
+
import { DEFAULT_LOADING_TEXT, TestIds } from '../enums/index.js';
|
|
9
|
+
/**
|
|
10
|
+
* Root component that provides the GiftCard service context.
|
|
11
|
+
* Supports both SSR (with product in config) and client-side auto-fetch (empty config).
|
|
12
|
+
*
|
|
13
|
+
* @component
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* // With SSR config
|
|
17
|
+
* <GiftCard.Root giftCardServiceConfig={{ product: myProduct }}>
|
|
18
|
+
* <GiftCard.Name className="text-2xl font-bold" />
|
|
19
|
+
* </GiftCard.Root>
|
|
20
|
+
*
|
|
21
|
+
* // Without config (auto-fetch)
|
|
22
|
+
* <GiftCard.Root giftCardServiceConfig={{}}>
|
|
23
|
+
* <GiftCard.Name className="text-2xl font-bold" />
|
|
24
|
+
* </GiftCard.Root>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export const Root = (props) => {
|
|
28
|
+
const { children, giftCardServiceConfig, ...attrs } = props;
|
|
29
|
+
return (_jsx(CoreGiftCard.Root, { giftCardServiceConfig: giftCardServiceConfig, children: _jsx("div", { "data-testid": TestIds.giftCardRoot, ...attrs, children: children }) }));
|
|
30
|
+
};
|
|
31
|
+
Root.displayName = 'GiftCard.Root';
|
|
32
|
+
/**
|
|
33
|
+
* Provides direct access to the gift card data via render props.
|
|
34
|
+
* Should be used only when you need full control over rendering all states.
|
|
35
|
+
* For standard usage, use GiftCard.Loading and GiftCard.Error as siblings.
|
|
36
|
+
*
|
|
37
|
+
* @component
|
|
38
|
+
* @example
|
|
39
|
+
* ```tsx
|
|
40
|
+
* // Full control with render props
|
|
41
|
+
* <GiftCard.Raw asChild>
|
|
42
|
+
* {({ giftCard, isLoading, error }) => {
|
|
43
|
+
* if (isLoading) return <div>Loading gift card...</div>;
|
|
44
|
+
* if (error) return <div>Error: {error}</div>;
|
|
45
|
+
* return (
|
|
46
|
+
* <div className="flex flex-col gap-4">
|
|
47
|
+
* <h2>Gift Card: {giftCard.name}</h2>
|
|
48
|
+
* <p>ID: {giftCard.product_id}</p>
|
|
49
|
+
* </div>
|
|
50
|
+
* );
|
|
51
|
+
* }}
|
|
52
|
+
* </GiftCard.Raw>
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export const Raw = React.forwardRef((props, ref) => {
|
|
56
|
+
const { asChild, children, className } = props;
|
|
57
|
+
return (_jsx(CoreGiftCard.Raw, { children: (rawData) => {
|
|
58
|
+
if (!asChild || !children) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardRaw, customElement: children, customElementProps: rawData }));
|
|
62
|
+
} }));
|
|
63
|
+
});
|
|
64
|
+
Raw.displayName = 'GiftCard.Raw';
|
|
65
|
+
/**
|
|
66
|
+
* Displays the gift card image using WixMediaImage
|
|
67
|
+
*
|
|
68
|
+
* @component
|
|
69
|
+
* @example
|
|
70
|
+
* ```tsx
|
|
71
|
+
* // Default usage
|
|
72
|
+
* <GiftCard.Image className="w-full h-full object-cover" />
|
|
73
|
+
*
|
|
74
|
+
* // asChild with primitive
|
|
75
|
+
* <GiftCard.Image asChild>
|
|
76
|
+
* <img className="w-full h-full object-cover" />
|
|
77
|
+
* </GiftCard.Image>
|
|
78
|
+
*
|
|
79
|
+
* // asChild with react component
|
|
80
|
+
* <GiftCard.Image asChild>
|
|
81
|
+
* {React.forwardRef(({src, ...props}, ref) => (
|
|
82
|
+
* <img ref={ref} {...props} src={src} className="w-full h-full object-cover" />
|
|
83
|
+
* ))}
|
|
84
|
+
* </GiftCard.Image>
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export const Image = React.forwardRef((props, ref) => (_jsx(CoreGiftCard.Image, { children: (renderProps) => (_jsx(WixMediaImage, { ...props, ref: ref, media: { image: renderProps.image }, "data-testid": TestIds.giftCardImage })) })));
|
|
88
|
+
/**
|
|
89
|
+
* Displays the gift card product name with customizable rendering.
|
|
90
|
+
*
|
|
91
|
+
* @component
|
|
92
|
+
* @example
|
|
93
|
+
* ```tsx
|
|
94
|
+
* // Default usage
|
|
95
|
+
* <GiftCard.Name className="text-2xl font-bold" />
|
|
96
|
+
*
|
|
97
|
+
* // asChild with primitive
|
|
98
|
+
* <GiftCard.Name asChild>
|
|
99
|
+
* <h1 className="text-4xl font-bold" />
|
|
100
|
+
* </GiftCard.Name>
|
|
101
|
+
*
|
|
102
|
+
* // asChild with react component
|
|
103
|
+
* <GiftCard.Name asChild>
|
|
104
|
+
* {React.forwardRef(({ name, ...props }, ref) => (
|
|
105
|
+
* <h1 ref={ref} {...props} className="text-4xl font-bold">
|
|
106
|
+
* {name}
|
|
107
|
+
* </h1>
|
|
108
|
+
* ))}
|
|
109
|
+
* </GiftCard.Name>
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export const Name = React.forwardRef((props, ref) => {
|
|
113
|
+
const { asChild, children, className, ...otherProps } = props;
|
|
114
|
+
return (_jsx(CoreGiftCard.Name, { children: ({ name }) => {
|
|
115
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardName, customElement: children, customElementProps: { name }, content: name, ...otherProps, children: _jsx("div", { children: name }) }));
|
|
116
|
+
} }));
|
|
117
|
+
});
|
|
118
|
+
Name.displayName = 'GiftCard.Name';
|
|
119
|
+
/**
|
|
120
|
+
* Renders the gift card product description.
|
|
121
|
+
*
|
|
122
|
+
* @component
|
|
123
|
+
* @example
|
|
124
|
+
* ```tsx
|
|
125
|
+
* // Default usage
|
|
126
|
+
* <GiftCard.Description className="text-content-secondary" />
|
|
127
|
+
*
|
|
128
|
+
* // asChild with primitive
|
|
129
|
+
* <GiftCard.Description asChild>
|
|
130
|
+
* <p className="text-sm" />
|
|
131
|
+
* </GiftCard.Description>
|
|
132
|
+
*
|
|
133
|
+
* // asChild with react component
|
|
134
|
+
* <GiftCard.Description asChild>
|
|
135
|
+
* {React.forwardRef(({ description, ...props }, ref) => (
|
|
136
|
+
* <p ref={ref} {...props}>{description}</p>
|
|
137
|
+
* ))}
|
|
138
|
+
* </GiftCard.Description>
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
export const Description = React.forwardRef((props, ref) => {
|
|
142
|
+
const { asChild, children, className, ...otherProps } = props;
|
|
143
|
+
return (_jsx(CoreGiftCard.Description, { children: ({ description }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardDescription, customElement: children, customElementProps: { description }, content: description, ...otherProps, children: _jsx("div", { children: description }) })) }));
|
|
144
|
+
});
|
|
145
|
+
Description.displayName = 'GiftCard.Description';
|
|
146
|
+
/**
|
|
147
|
+
* Displays loading state indicator.
|
|
148
|
+
* Only renders content when isLoading is true.
|
|
149
|
+
*
|
|
150
|
+
* @component
|
|
151
|
+
* @example
|
|
152
|
+
* ```tsx
|
|
153
|
+
* <GiftCard.Loading className="text-gray-500">
|
|
154
|
+
* Loading...
|
|
155
|
+
* </GiftCard.Loading>
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export const Loading = React.forwardRef((props, ref) => {
|
|
159
|
+
const { className, children, ...otherProps } = props;
|
|
160
|
+
return (_jsx(CoreGiftCard.Loading, { children: ({ isLoading }) => {
|
|
161
|
+
if (!isLoading)
|
|
162
|
+
return null;
|
|
163
|
+
return (_jsx("div", { ref: ref, className: className, "data-testid": TestIds.giftCardLoading, ...otherProps, children: children ?? DEFAULT_LOADING_TEXT }));
|
|
164
|
+
} }));
|
|
165
|
+
});
|
|
166
|
+
Loading.displayName = 'GiftCard.Loading';
|
|
167
|
+
/**
|
|
168
|
+
* Displays error state.
|
|
169
|
+
* Only renders when there's an error.
|
|
170
|
+
*
|
|
171
|
+
* @component
|
|
172
|
+
* @example
|
|
173
|
+
* ```tsx
|
|
174
|
+
* <GiftCard.Error className="text-red-500" />
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
export const Error = React.forwardRef((props, ref) => {
|
|
178
|
+
const { className, ...otherProps } = props;
|
|
179
|
+
return (_jsx(CoreGiftCard.Error, { children: ({ error }) => {
|
|
180
|
+
if (!error)
|
|
181
|
+
return null;
|
|
182
|
+
return (_jsx("div", { ref: ref, className: className, "data-testid": TestIds.giftCardError, ...otherProps, children: error }));
|
|
183
|
+
} }));
|
|
184
|
+
});
|
|
185
|
+
Error.displayName = 'GiftCard.Error';
|
|
186
|
+
/**
|
|
187
|
+
* Context for individual preset variant data
|
|
188
|
+
*/
|
|
189
|
+
const PresetVariantContext = React.createContext(null);
|
|
190
|
+
/**
|
|
191
|
+
* Hook to access PresetVariant context
|
|
192
|
+
*/
|
|
193
|
+
function usePresetVariantContext() {
|
|
194
|
+
const context = React.useContext(PresetVariantContext);
|
|
195
|
+
if (!context) {
|
|
196
|
+
// Use globalThis.Error to avoid conflict with exported Error component
|
|
197
|
+
throw new globalThis.Error('PresetVariant components must be used within PresetVariantRepeater');
|
|
198
|
+
}
|
|
199
|
+
return context;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Container component for preset variant selection.
|
|
203
|
+
* Provides label and empty state support.
|
|
204
|
+
*
|
|
205
|
+
* @component
|
|
206
|
+
* @example
|
|
207
|
+
* ```tsx
|
|
208
|
+
* // With label and empty state
|
|
209
|
+
* <GiftCard.PresetVariants label="Select Amount" emptyState={<div>No variants</div>}>
|
|
210
|
+
* <GiftCard.PresetVariantRepeater>
|
|
211
|
+
* <GiftCard.PresetVariant.Amount />
|
|
212
|
+
* </GiftCard.PresetVariantRepeater>
|
|
213
|
+
* <GiftCard.CustomVariantTrigger label="Other amount" />
|
|
214
|
+
* </GiftCard.PresetVariants>
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
export const PresetVariants = React.forwardRef((props, ref) => {
|
|
218
|
+
const { asChild, children, className, label, emptyState, ...otherProps } = props;
|
|
219
|
+
return (_jsx(CoreGiftCard.PresetVariants, { children: (variantsData) => {
|
|
220
|
+
if (variantsData.presetVariants.length === 0 && emptyState) {
|
|
221
|
+
return _jsx(_Fragment, { children: emptyState });
|
|
222
|
+
}
|
|
223
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardPresetVariants, customElement: children, customElementProps: variantsData, ...otherProps, children: _jsxs("div", { children: [label && _jsx("label", { children: label }), children] }) }));
|
|
224
|
+
} }));
|
|
225
|
+
});
|
|
226
|
+
PresetVariants.displayName = 'GiftCard.PresetVariants';
|
|
227
|
+
/**
|
|
228
|
+
* Repeater component that renders children for each preset variant.
|
|
229
|
+
* Creates a PresetVariant context for each variant that child components can access.
|
|
230
|
+
*
|
|
231
|
+
* @component
|
|
232
|
+
* @example
|
|
233
|
+
* ```tsx
|
|
234
|
+
* <GiftCard.PresetVariantRepeater>
|
|
235
|
+
* <GiftCard.PresetVariant.Amount />
|
|
236
|
+
* </GiftCard.PresetVariantRepeater>
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
export const PresetVariantRepeater = (props) => {
|
|
240
|
+
const { children, className } = props;
|
|
241
|
+
return (_jsx(CoreGiftCard.PresetVariantRepeater, { children: ({ presetVariants }) => (_jsx(_Fragment, { children: presetVariants.map((variant) => (_jsx(PresetVariantContext.Provider, { value: variant, children: _jsx("div", { "data-testid": TestIds.giftCardPresetVariant, "data-variant-id": variant.id, "data-selected": variant.isSelected || undefined, "data-has-discount": variant.hasDiscount || undefined, className: className, children: children }) }, variant.id))) })) }));
|
|
242
|
+
};
|
|
243
|
+
PresetVariantRepeater.displayName = 'GiftCard.PresetVariantRepeater';
|
|
244
|
+
/**
|
|
245
|
+
* Clickable button for selecting a preset variant amount.
|
|
246
|
+
* Default renders a button with Money-formatted value.
|
|
247
|
+
* Use asChild for custom rendering with price/value/hasDiscount for discount display.
|
|
248
|
+
*
|
|
249
|
+
* @component
|
|
250
|
+
* @example
|
|
251
|
+
* ```tsx
|
|
252
|
+
* // Default usage - shows value
|
|
253
|
+
* <GiftCard.PresetVariant.Amount className="px-4 py-2 border rounded" />
|
|
254
|
+
*
|
|
255
|
+
* // asChild with primitive element - Money is passed as children
|
|
256
|
+
* <GiftCard.PresetVariant.Amount asChild>
|
|
257
|
+
* <div className="px-4 py-2 border rounded" />
|
|
258
|
+
* </GiftCard.PresetVariant.Amount>
|
|
259
|
+
*
|
|
260
|
+
* // asChild with render function for custom discount display
|
|
261
|
+
* <GiftCard.PresetVariant.Amount asChild>
|
|
262
|
+
* {React.forwardRef(({ price, value, hasDiscount, currencyCode, ...props }, ref) => (
|
|
263
|
+
* <button ref={ref} {...props}>
|
|
264
|
+
* {hasDiscount && <Money money={{ amount: value, currency: currencyCode }} className="line-through" />}
|
|
265
|
+
* <Money money={{ amount: price, currency: currencyCode }} />
|
|
266
|
+
* </button>
|
|
267
|
+
* ))}
|
|
268
|
+
* </GiftCard.PresetVariant.Amount>
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
271
|
+
const PresetVariantAmount = React.forwardRef((props, ref) => {
|
|
272
|
+
const { asChild, children, className, ...otherProps } = props;
|
|
273
|
+
const variant = usePresetVariantContext();
|
|
274
|
+
const amountData = {
|
|
275
|
+
id: variant.id,
|
|
276
|
+
price: variant.price,
|
|
277
|
+
value: variant.value,
|
|
278
|
+
hasDiscount: variant.hasDiscount,
|
|
279
|
+
hasImage: variant.hasImage,
|
|
280
|
+
isSelected: variant.isSelected,
|
|
281
|
+
currencyCode: variant.currencyCode,
|
|
282
|
+
locale: variant.locale,
|
|
283
|
+
};
|
|
284
|
+
const moneyContent = (_jsx(Money, { money: {
|
|
285
|
+
amount: variant.value,
|
|
286
|
+
currency: variant.currencyCode,
|
|
287
|
+
locale: variant.locale,
|
|
288
|
+
numberFormatOptions: {
|
|
289
|
+
minimumFractionDigits: 0,
|
|
290
|
+
maximumFractionDigits: 2,
|
|
291
|
+
},
|
|
292
|
+
} }));
|
|
293
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardPresetVariantAmount, "data-selected": variant.isSelected || undefined, "data-has-discount": variant.hasDiscount || undefined, onClick: variant.select, customElement: children, customElementProps: amountData, content: moneyContent, ...otherProps, children: _jsx("button", { onClick: variant.select, children: moneyContent }) }));
|
|
294
|
+
});
|
|
295
|
+
PresetVariantAmount.displayName = 'GiftCard.PresetVariant.Amount';
|
|
296
|
+
/**
|
|
297
|
+
== * PresetVariant namespace containing preset variant sub-components
|
|
298
|
+
*/
|
|
299
|
+
export const PresetVariant = {
|
|
300
|
+
Amount: PresetVariantAmount,
|
|
301
|
+
};
|
|
302
|
+
/**
|
|
303
|
+
* Displays the current price based on the selected variant (preset or custom amount).
|
|
304
|
+
* Uses the Money component for formatting. Supports discount display when price differs from value.
|
|
305
|
+
*
|
|
306
|
+
* Price vs Value:
|
|
307
|
+
* - `price` - What the customer pays (raw number)
|
|
308
|
+
* - `value` - What the gift card is worth (raw number)
|
|
309
|
+
* - `hasDiscount` - `true` when `price < value`, indicating a discounted variant
|
|
310
|
+
*
|
|
311
|
+
* @component
|
|
312
|
+
* @example
|
|
313
|
+
* ```tsx
|
|
314
|
+
* // Default usage - shows price, with strikethrough value when discounted
|
|
315
|
+
* <GiftCard.CurrentPrice className="text-3xl font-bold text-brand-primary" />
|
|
316
|
+
*
|
|
317
|
+
* // asChild with primitive
|
|
318
|
+
* <GiftCard.CurrentPrice asChild>
|
|
319
|
+
* <span className="text-2xl font-bold" />
|
|
320
|
+
* </GiftCard.CurrentPrice>
|
|
321
|
+
*
|
|
322
|
+
* // asChild with react component for full control
|
|
323
|
+
* <GiftCard.CurrentPrice asChild>
|
|
324
|
+
* {React.forwardRef(({ price, value, hasDiscount, currencyCode, ...props }, ref) => (
|
|
325
|
+
* <div ref={ref} {...props} className="flex items-baseline gap-3">
|
|
326
|
+
* {hasDiscount && (
|
|
327
|
+
* <Money money={{ amount: value, currency: currencyCode }} className="line-through text-lg text-content-muted" />
|
|
328
|
+
* )}
|
|
329
|
+
* <Money money={{ amount: price, currency: currencyCode }} className="text-4xl font-bold text-brand-primary" />
|
|
330
|
+
* </div>
|
|
331
|
+
* ))}
|
|
332
|
+
* </GiftCard.CurrentPrice>
|
|
333
|
+
* ```
|
|
334
|
+
*/
|
|
335
|
+
export const CurrentPrice = React.forwardRef((props, ref) => {
|
|
336
|
+
const { asChild, children, className, ...otherProps } = props;
|
|
337
|
+
return (_jsx(CoreGiftCard.CurrentPrice, { children: (priceData) => {
|
|
338
|
+
const priceContent = (_jsxs(_Fragment, { children: [priceData.hasDiscount && (_jsx("span", { style: { textDecoration: 'line-through', marginRight: '8px' }, children: _jsx(Money, { money: {
|
|
339
|
+
amount: priceData.value,
|
|
340
|
+
currency: priceData.currencyCode,
|
|
341
|
+
locale: priceData.locale,
|
|
342
|
+
numberFormatOptions: {
|
|
343
|
+
minimumFractionDigits: 0,
|
|
344
|
+
maximumFractionDigits: 2,
|
|
345
|
+
},
|
|
346
|
+
} }) })), _jsx("span", { children: _jsx(Money, { money: {
|
|
347
|
+
amount: priceData.price,
|
|
348
|
+
currency: priceData.currencyCode,
|
|
349
|
+
locale: priceData.locale,
|
|
350
|
+
numberFormatOptions: {
|
|
351
|
+
minimumFractionDigits: 0,
|
|
352
|
+
maximumFractionDigits: 2,
|
|
353
|
+
},
|
|
354
|
+
} }) })] }));
|
|
355
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardCurrentPrice, "data-has-discount": priceData.hasDiscount || undefined, customElement: children, customElementProps: priceData, content: priceContent, ...otherProps, children: _jsx("div", { children: priceContent }) }));
|
|
356
|
+
} }));
|
|
357
|
+
});
|
|
358
|
+
CurrentPrice.displayName = 'GiftCard.CurrentPrice';
|
|
359
|
+
/**
|
|
360
|
+
* Trigger button for selecting custom amount option.
|
|
361
|
+
* Use alongside PresetVariantRepeater to allow custom amounts.
|
|
362
|
+
* Only renders when custom variant is enabled for the gift card.
|
|
363
|
+
*
|
|
364
|
+
* @component
|
|
365
|
+
* @example
|
|
366
|
+
* ```tsx
|
|
367
|
+
* // Default usage
|
|
368
|
+
* <GiftCard.CustomVariantTrigger label="Other amount" className="px-6 py-4 border-2 border-dashed rounded-xl" />
|
|
369
|
+
*
|
|
370
|
+
* // asChild with primitive
|
|
371
|
+
* <GiftCard.CustomVariantTrigger label="Other amount" asChild>
|
|
372
|
+
* <button className="px-6 py-4 border-2 border-dashed rounded-xl hover:border-brand-primary" />
|
|
373
|
+
* </GiftCard.CustomVariantTrigger>
|
|
374
|
+
*
|
|
375
|
+
* // asChild with react component
|
|
376
|
+
* <GiftCard.CustomVariantTrigger>
|
|
377
|
+
* {React.forwardRef(({ isSelected, onClick, ...props }, ref) => (
|
|
378
|
+
* <button
|
|
379
|
+
* ref={ref}
|
|
380
|
+
* {...props}
|
|
381
|
+
* onClick={onClick}
|
|
382
|
+
* data-selected={isSelected}
|
|
383
|
+
* className="px-6 py-4 border-2 border-dashed rounded-xl"
|
|
384
|
+
* >
|
|
385
|
+
* Custom amount
|
|
386
|
+
* </button>
|
|
387
|
+
* ))}
|
|
388
|
+
* </GiftCard.CustomVariantTrigger>
|
|
389
|
+
* ```
|
|
390
|
+
*/
|
|
391
|
+
export const CustomVariantTrigger = React.forwardRef((props, ref) => {
|
|
392
|
+
const { label = 'Other amount', asChild, children, className, ...otherProps } = props;
|
|
393
|
+
return (_jsx(CoreGiftCard.CustomVariantTrigger, { children: ({ isSelected, onClick }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardCustomVariantTrigger, "data-selected": isSelected || undefined, customElement: children, customElementProps: { isSelected, onClick }, onClick: onClick, content: label, ...otherProps, children: _jsx("button", { onClick: onClick, children: label }) })) }));
|
|
394
|
+
});
|
|
395
|
+
CustomVariantTrigger.displayName = 'GiftCard.CustomVariantTrigger';
|
|
396
|
+
/**
|
|
397
|
+
* Input for entering a custom gift card amount.
|
|
398
|
+
* Only renders when custom variant is selected.
|
|
399
|
+
* The custom amount changes the currentPrice value displayed by GiftCard.CurrentPrice.
|
|
400
|
+
*
|
|
401
|
+
* Validation:
|
|
402
|
+
* - Amount must be within min/max range defined by the product's custom variant
|
|
403
|
+
* - data-invalid attribute is applied when showError is true and amount is outside the allowed range
|
|
404
|
+
* - The showError flag is controlled by the checkout service (set to true after form submission attempts)
|
|
405
|
+
*
|
|
406
|
+
* @component
|
|
407
|
+
* @example
|
|
408
|
+
* ```tsx
|
|
409
|
+
* // Default usage
|
|
410
|
+
* <GiftCard.CustomAmountInput
|
|
411
|
+
* label="Enter amount"
|
|
412
|
+
* className="w-full p-4 border-2 rounded-xl text-2xl font-bold text-center"
|
|
413
|
+
* />
|
|
414
|
+
*
|
|
415
|
+
* // asChild with primitive
|
|
416
|
+
* <GiftCard.CustomAmountInput label="Enter amount" asChild>
|
|
417
|
+
* <input type="number" className="w-full p-4 border-2 rounded-xl" />
|
|
418
|
+
* </GiftCard.CustomAmountInput>
|
|
419
|
+
*
|
|
420
|
+
* // asChild with react component with validation error display
|
|
421
|
+
* <GiftCard.CustomAmountInput>
|
|
422
|
+
* {React.forwardRef(({ value, setValue, min, max, isValid, showError, isVisible, currencyCode, ...props }, ref) =>
|
|
423
|
+
* isVisible && (
|
|
424
|
+
* <div className="space-y-2">
|
|
425
|
+
* <label>Enter amount ({currencyCode})</label>
|
|
426
|
+
* <input
|
|
427
|
+
* ref={ref}
|
|
428
|
+
* {...props}
|
|
429
|
+
* type="number"
|
|
430
|
+
* value={value || ''}
|
|
431
|
+
* onChange={(e) => setValue(parseFloat(e.target.value) || 0)}
|
|
432
|
+
* min={min ?? undefined}
|
|
433
|
+
* max={max ?? undefined}
|
|
434
|
+
* data-invalid={showError && !isValid}
|
|
435
|
+
* />
|
|
436
|
+
* {showError && !isValid && (
|
|
437
|
+
* <p className="text-red-500">
|
|
438
|
+
* {min && max
|
|
439
|
+
* ? `Amount must be between ${min} and ${max}`
|
|
440
|
+
* : min
|
|
441
|
+
* ? `Amount must be at least ${min}`
|
|
442
|
+
* : max
|
|
443
|
+
* ? `Amount must be no more than ${max}`
|
|
444
|
+
* : 'Please enter a valid amount'}
|
|
445
|
+
* </p>
|
|
446
|
+
* )}
|
|
447
|
+
* </div>
|
|
448
|
+
* )
|
|
449
|
+
* )}
|
|
450
|
+
* </GiftCard.CustomAmountInput>
|
|
451
|
+
* ```
|
|
452
|
+
*/
|
|
453
|
+
export const CustomAmountInput = React.forwardRef((props, ref) => {
|
|
454
|
+
const { label, asChild, children, className, ...otherProps } = props;
|
|
455
|
+
return (_jsx(CoreGiftCard.CustomAmountInput, { children: (inputData) => {
|
|
456
|
+
// Don't render if not visible (not custom variant) unless using asChild
|
|
457
|
+
if (!inputData.isVisible && !asChild) {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardCustomAmountInput, "data-invalid": !inputData.isValid || undefined, "data-visible": inputData.isVisible || undefined, customElement: children, customElementProps: inputData, ...otherProps, children: _jsx("div", { children: inputData.isVisible && (_jsxs("div", { children: [label && _jsx("label", { children: label }), _jsxs("div", { children: [_jsx("span", { children: inputData.currencySymbol }), _jsx("input", { prefix: inputData.currencySymbol, type: "number", value: inputData.value, onChange: (e) => inputData.setValue(parseFloat(e.target.value) || 0), min: inputData.min ?? undefined, max: inputData.max ?? undefined, className: className })] })] })) }) }));
|
|
461
|
+
} }));
|
|
462
|
+
});
|
|
463
|
+
CustomAmountInput.displayName = 'GiftCard.CustomAmountInput';
|
|
464
|
+
/**
|
|
465
|
+
* Container for quantity selection controls.
|
|
466
|
+
* Renders a Quantity.Root from @wix/headless-components connected to the gift card service state.
|
|
467
|
+
*
|
|
468
|
+
* Use with Quantity.Decrement, Quantity.Input, Quantity.Increment components from @wix/headless-components.
|
|
469
|
+
*
|
|
470
|
+
* @component
|
|
471
|
+
* @example
|
|
472
|
+
* ```tsx
|
|
473
|
+
* import { Quantity } from '@wix/headless-components/react';
|
|
474
|
+
*
|
|
475
|
+
* // Default usage - renders built-in Quantity components
|
|
476
|
+
* <GiftCard.Quantity steps={1} />
|
|
477
|
+
*
|
|
478
|
+
* // With label and custom styling
|
|
479
|
+
* <GiftCard.Quantity
|
|
480
|
+
* label="Quantity"
|
|
481
|
+
* className="flex items-center gap-2"
|
|
482
|
+
* steps={1}
|
|
483
|
+
* />
|
|
484
|
+
*
|
|
485
|
+
* // asChild with custom Quantity children (use platform Quantity components)
|
|
486
|
+
* <GiftCard.Quantity asChild steps={1}>
|
|
487
|
+
* {({ quantity, setQuantity }) => (
|
|
488
|
+
* <QuantityComponent.Root
|
|
489
|
+
* initialValue={quantity}
|
|
490
|
+
* onValueChange={setQuantity}
|
|
491
|
+
* steps={1}
|
|
492
|
+
* min={1}
|
|
493
|
+
* >
|
|
494
|
+
* <Quantity.Decrement className="px-4 py-2 border rounded-l-lg" />
|
|
495
|
+
* <Quantity.Input className="w-16 text-center border-y" />
|
|
496
|
+
* <Quantity.Increment className="px-4 py-2 border rounded-r-lg" />
|
|
497
|
+
* </QuantityComponent.Root>
|
|
498
|
+
* )}
|
|
499
|
+
* </GiftCard.Quantity>
|
|
500
|
+
*
|
|
501
|
+
* // asChild with fully custom implementation
|
|
502
|
+
* <GiftCard.Quantity asChild>
|
|
503
|
+
* {React.forwardRef(({ quantity, setQuantity, ...props }, ref) => (
|
|
504
|
+
* <div ref={ref} {...props} className="flex items-center gap-2">
|
|
505
|
+
* <button
|
|
506
|
+
* onClick={() => setQuantity(quantity - 1)}
|
|
507
|
+
* disabled={quantity <= 1}
|
|
508
|
+
* className="w-10 h-10 border rounded-lg"
|
|
509
|
+
* >
|
|
510
|
+
* -
|
|
511
|
+
* </button>
|
|
512
|
+
* <span className="w-16 text-center text-2xl font-bold">
|
|
513
|
+
* {quantity}
|
|
514
|
+
* </span>
|
|
515
|
+
* <button
|
|
516
|
+
* onClick={() => setQuantity(quantity + 1)}
|
|
517
|
+
* className="w-10 h-10 border rounded-lg"
|
|
518
|
+
* >
|
|
519
|
+
* +
|
|
520
|
+
* </button>
|
|
521
|
+
* </div>
|
|
522
|
+
* ))}
|
|
523
|
+
* </GiftCard.Quantity>
|
|
524
|
+
* ```
|
|
525
|
+
*/
|
|
526
|
+
export const Quantity = React.forwardRef((props, ref) => {
|
|
527
|
+
const { asChild, children, className, steps = 1, label, ...otherProps } = props;
|
|
528
|
+
return (_jsx(CoreGiftCard.Quantity, { children: ({ quantity, setQuantity }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardQuantity, customElement: children, customElementProps: { quantity, setQuantity }, ...otherProps, children: _jsxs("div", { children: [label && _jsx("label", { children: label }), _jsxs(QuantityComponent.Root, { initialValue: quantity, onValueChange: setQuantity, steps: steps, min: 1, className: className, children: [_jsx(QuantityComponent.Decrement, {}), _jsx(QuantityComponent.Input, {}), _jsx(QuantityComponent.Increment, {})] })] }) })) }));
|
|
529
|
+
});
|
|
530
|
+
Quantity.displayName = 'GiftCard.Quantity';
|
|
531
|
+
/**
|
|
532
|
+
* Toggle between "For someone else" (gift) and "For myself" purchase modes.
|
|
533
|
+
* When isGift is true, the recipient form should be shown.
|
|
534
|
+
* When isGift is false, the recipient form should be hidden.
|
|
535
|
+
*
|
|
536
|
+
* @component
|
|
537
|
+
* @example
|
|
538
|
+
* ```tsx
|
|
539
|
+
* // Default usage
|
|
540
|
+
* <GiftCard.GiftToggle
|
|
541
|
+
* label="Who is the gift card for?"
|
|
542
|
+
* forSomeoneLabel="For someone else"
|
|
543
|
+
* forMyselfLabel="For myself"
|
|
544
|
+
* className="flex gap-2"
|
|
545
|
+
* />
|
|
546
|
+
*
|
|
547
|
+
* // asChild with primitive
|
|
548
|
+
* <GiftCard.GiftToggle
|
|
549
|
+
* label="Who is the gift card for?"
|
|
550
|
+
* forSomeoneLabel="For someone else"
|
|
551
|
+
* forMyselfLabel="For myself"
|
|
552
|
+
* asChild
|
|
553
|
+
* >
|
|
554
|
+
* <div className="space-y-3" />
|
|
555
|
+
* </GiftCard.GiftToggle>
|
|
556
|
+
*
|
|
557
|
+
* // asChild with react component
|
|
558
|
+
* <GiftCard.GiftToggle>
|
|
559
|
+
* {React.forwardRef(({ isGift, setIsGift, ...props }, ref) => (
|
|
560
|
+
* <div ref={ref} {...props} className="space-y-3">
|
|
561
|
+
* <h3>Who is the gift card for?</h3>
|
|
562
|
+
* <div className="flex rounded-xl overflow-hidden border-2">
|
|
563
|
+
* <button
|
|
564
|
+
* onClick={() => setIsGift(true)}
|
|
565
|
+
* data-selected={isGift}
|
|
566
|
+
* className="flex-1 px-6 py-3 data-[selected]:bg-brand-primary data-[selected]:text-white"
|
|
567
|
+
* >
|
|
568
|
+
* For someone else
|
|
569
|
+
* </button>
|
|
570
|
+
* <button
|
|
571
|
+
* onClick={() => setIsGift(false)}
|
|
572
|
+
* data-selected={!isGift}
|
|
573
|
+
* className="flex-1 px-6 py-3 data-[selected]:bg-brand-primary data-[selected]:text-white"
|
|
574
|
+
* >
|
|
575
|
+
* For myself
|
|
576
|
+
* </button>
|
|
577
|
+
* </div>
|
|
578
|
+
* </div>
|
|
579
|
+
* ))}
|
|
580
|
+
* </GiftCard.GiftToggle>
|
|
581
|
+
* ```
|
|
582
|
+
*/
|
|
583
|
+
export const GiftToggle = React.forwardRef((props, ref) => {
|
|
584
|
+
const { label, forSomeoneLabel = 'For someone else', forMyselfLabel = 'For myself', asChild, children, className, ...otherProps } = props;
|
|
585
|
+
return (_jsx(CoreGiftCard.GiftToggle, { children: ({ isGift, setIsGift }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardGiftToggle, customElement: children, customElementProps: { isGift, setIsGift }, ...otherProps, children: _jsxs("div", { children: [label && _jsx("label", { children: label }), _jsxs("div", { className: className, children: [_jsx("button", { type: "button", onClick: () => setIsGift(true), "data-selected": isGift || undefined, "data-testid": TestIds.giftCardGiftToggleSomeone, children: forSomeoneLabel }), _jsx("button", { type: "button", onClick: () => setIsGift(false), "data-selected": !isGift || undefined, "data-testid": TestIds.giftCardGiftToggleMyself, children: forMyselfLabel })] })] }) })) }));
|
|
586
|
+
});
|
|
587
|
+
GiftToggle.displayName = 'GiftCard.GiftToggle';
|
|
588
|
+
/**
|
|
589
|
+
* Input for entering recipient email address.
|
|
590
|
+
* Provides email state, validation, and error display control.
|
|
591
|
+
*
|
|
592
|
+
* The `showError` flag is controlled by the checkout service and indicates
|
|
593
|
+
* whether validation errors should be displayed (typically set to true after
|
|
594
|
+
* a form submission attempt).
|
|
595
|
+
*
|
|
596
|
+
* @component
|
|
597
|
+
* @example
|
|
598
|
+
* ```tsx
|
|
599
|
+
* // Default usage
|
|
600
|
+
* <GiftCard.RecipientEmail label="Recipient email" className="w-full p-3 border rounded-lg" />
|
|
601
|
+
*
|
|
602
|
+
* // asChild with primitive
|
|
603
|
+
* <GiftCard.RecipientEmail label="Recipient email" asChild>
|
|
604
|
+
* <input type="email" className="w-full p-3 border-2 rounded-lg" />
|
|
605
|
+
* </GiftCard.RecipientEmail>
|
|
606
|
+
*
|
|
607
|
+
* // asChild with react component
|
|
608
|
+
* <GiftCard.RecipientEmail>
|
|
609
|
+
* {React.forwardRef(({ value, setValue, isValid, showError, ...props }, ref) => (
|
|
610
|
+
* <div className="space-y-2">
|
|
611
|
+
* <label className="text-sm font-medium">
|
|
612
|
+
* Email <span className="text-status-error">*</span>
|
|
613
|
+
* </label>
|
|
614
|
+
* <input
|
|
615
|
+
* ref={ref}
|
|
616
|
+
* {...props}
|
|
617
|
+
* type="email"
|
|
618
|
+
* value={value}
|
|
619
|
+
* onChange={(e) => setValue(e.target.value)}
|
|
620
|
+
* data-invalid={showError && !isValid}
|
|
621
|
+
* className="w-full p-3 border-2 rounded-lg data-[invalid]:border-status-error"
|
|
622
|
+
* />
|
|
623
|
+
* {showError && !isValid && (
|
|
624
|
+
* <p className="text-sm text-status-error">Please enter a valid email</p>
|
|
625
|
+
* )}
|
|
626
|
+
* </div>
|
|
627
|
+
* ))}
|
|
628
|
+
* </GiftCard.RecipientEmail>
|
|
629
|
+
* ```
|
|
630
|
+
*/
|
|
631
|
+
export const RecipientEmail = React.forwardRef((props, ref) => {
|
|
632
|
+
const { label, asChild, children, className, ...otherProps } = props;
|
|
633
|
+
return (_jsx(CoreGiftCard.RecipientEmail, { children: ({ value, setValue, isValid, showError, isVisible }) => {
|
|
634
|
+
// Don't render if not visible (isGift is false) unless using asChild
|
|
635
|
+
if (!isVisible && !asChild) {
|
|
636
|
+
return null;
|
|
637
|
+
}
|
|
638
|
+
const showInvalidState = showError && !isValid;
|
|
639
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardRecipientEmail, "data-invalid": showInvalidState || undefined, "data-visible": isVisible || undefined, customElement: children, customElementProps: {
|
|
640
|
+
value,
|
|
641
|
+
setValue,
|
|
642
|
+
isValid,
|
|
643
|
+
showError,
|
|
644
|
+
isVisible,
|
|
645
|
+
}, ...otherProps, children: _jsx("div", { children: isVisible && (_jsxs(_Fragment, { children: [label && _jsx("label", { children: label }), _jsx("input", { type: "email", value: value, onChange: (e) => setValue(e.target.value), className: className, "data-invalid": showInvalidState || undefined })] })) }) }));
|
|
646
|
+
} }));
|
|
647
|
+
});
|
|
648
|
+
RecipientEmail.displayName = 'GiftCard.RecipientEmail';
|
|
649
|
+
/**
|
|
650
|
+
* Input for entering recipient name.
|
|
651
|
+
* Only renders when isGift is true (purchasing for someone else).
|
|
652
|
+
* This field is optional - no validation is required.
|
|
653
|
+
*
|
|
654
|
+
* @component
|
|
655
|
+
* @example
|
|
656
|
+
* ```tsx
|
|
657
|
+
* // Default usage
|
|
658
|
+
* <GiftCard.RecipientName label="Recipient name" className="w-full p-3 border rounded-lg" />
|
|
659
|
+
*
|
|
660
|
+
* // asChild with primitive
|
|
661
|
+
* <GiftCard.RecipientName label="Recipient name" asChild>
|
|
662
|
+
* <input type="text" className="w-full p-3 border-2 rounded-lg" />
|
|
663
|
+
* </GiftCard.RecipientName>
|
|
664
|
+
*
|
|
665
|
+
* // asChild with react component
|
|
666
|
+
* <GiftCard.RecipientName>
|
|
667
|
+
* {React.forwardRef(({ value, setValue, isVisible, ...props }, ref) =>
|
|
668
|
+
* isVisible && (
|
|
669
|
+
* <div className="space-y-2">
|
|
670
|
+
* <label className="text-sm font-medium">Name (optional)</label>
|
|
671
|
+
* <input
|
|
672
|
+
* ref={ref}
|
|
673
|
+
* {...props}
|
|
674
|
+
* type="text"
|
|
675
|
+
* value={value}
|
|
676
|
+
* onChange={(e) => setValue(e.target.value)}
|
|
677
|
+
* className="w-full p-3 border-2 rounded-lg"
|
|
678
|
+
* />
|
|
679
|
+
* </div>
|
|
680
|
+
* )
|
|
681
|
+
* )}
|
|
682
|
+
* </GiftCard.RecipientName>
|
|
683
|
+
* ```
|
|
684
|
+
*/
|
|
685
|
+
export const RecipientName = React.forwardRef((props, ref) => {
|
|
686
|
+
const { label, asChild, children, className, ...otherProps } = props;
|
|
687
|
+
return (_jsx(CoreGiftCard.RecipientName, { children: ({ value, setValue, isVisible }) => {
|
|
688
|
+
// Don't render if not visible (isGift is false) unless using asChild
|
|
689
|
+
if (!isVisible && !asChild) {
|
|
690
|
+
return null;
|
|
691
|
+
}
|
|
692
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardRecipientName, "data-visible": isVisible || undefined, customElement: children, customElementProps: {
|
|
693
|
+
value,
|
|
694
|
+
setValue,
|
|
695
|
+
isVisible,
|
|
696
|
+
}, ...otherProps, children: _jsx("div", { children: isVisible && (_jsxs(_Fragment, { children: [label && _jsx("label", { children: label }), _jsx("input", { type: "text", value: value, onChange: (e) => setValue(e.target.value), className: className })] })) }) }));
|
|
697
|
+
} }));
|
|
698
|
+
});
|
|
699
|
+
RecipientName.displayName = 'GiftCard.RecipientName';
|
|
700
|
+
/**
|
|
701
|
+
* Input for selecting gift card delivery date.
|
|
702
|
+
* Only renders when isGift is true (purchasing for someone else).
|
|
703
|
+
* Provides both raw Date value and locale-formatted string.
|
|
704
|
+
*
|
|
705
|
+
* @component
|
|
706
|
+
* @example
|
|
707
|
+
* ```tsx
|
|
708
|
+
* // Default usage
|
|
709
|
+
* <GiftCard.RecipientDate label="Delivery date" className="w-full p-3 border rounded-lg" />
|
|
710
|
+
*
|
|
711
|
+
* // asChild with primitive
|
|
712
|
+
* <GiftCard.RecipientDate label="Delivery date" asChild>
|
|
713
|
+
* <input type="date" className="w-full p-3 border-2 rounded-lg" />
|
|
714
|
+
* </GiftCard.RecipientDate>
|
|
715
|
+
*
|
|
716
|
+
* // asChild with react component - using inputValue for date input and formattedValue for display
|
|
717
|
+
* <GiftCard.RecipientDate>
|
|
718
|
+
* {React.forwardRef(({ value, formattedValue, inputValue, setValue, isVisible, ...props }, ref) =>
|
|
719
|
+
* isVisible && (
|
|
720
|
+
* <div className="space-y-2">
|
|
721
|
+
* <label className="text-sm font-medium">Delivery date</label>
|
|
722
|
+
* <input
|
|
723
|
+
* ref={ref}
|
|
724
|
+
* {...props}
|
|
725
|
+
* type="date"
|
|
726
|
+
* value={inputValue}
|
|
727
|
+
* onChange={(e) => setValue(new Date(e.target.value))}
|
|
728
|
+
* className="w-full p-3 border-2 rounded-lg"
|
|
729
|
+
* />
|
|
730
|
+
* <p className="text-xs text-muted">Selected: {formattedValue}</p>
|
|
731
|
+
* </div>
|
|
732
|
+
* )
|
|
733
|
+
* )}
|
|
734
|
+
* </GiftCard.RecipientDate>
|
|
735
|
+
* ```
|
|
736
|
+
*/
|
|
737
|
+
export const RecipientDate = React.forwardRef((props, ref) => {
|
|
738
|
+
const { label, asChild, children, className, ...otherProps } = props;
|
|
739
|
+
return (_jsx(CoreGiftCard.RecipientDate, { children: ({ value, formattedValue, inputValue, setValue, isVisible }) => {
|
|
740
|
+
// Don't render if not visible (isGift is false) unless using asChild
|
|
741
|
+
if (!isVisible && !asChild) {
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardRecipientDate, "data-visible": isVisible || undefined, customElement: children, customElementProps: {
|
|
745
|
+
value,
|
|
746
|
+
formattedValue,
|
|
747
|
+
inputValue,
|
|
748
|
+
setValue,
|
|
749
|
+
isVisible,
|
|
750
|
+
}, ...otherProps, children: _jsx("div", { children: isVisible && (_jsxs(_Fragment, { children: [label && _jsx("label", { children: label }), _jsx("input", { type: "date", value: inputValue, onChange: (e) => {
|
|
751
|
+
if (e.target.value) {
|
|
752
|
+
setValue(new Date(e.target.value));
|
|
753
|
+
}
|
|
754
|
+
}, className: className })] })) }) }));
|
|
755
|
+
} }));
|
|
756
|
+
});
|
|
757
|
+
RecipientDate.displayName = 'GiftCard.RecipientDate';
|
|
758
|
+
/**
|
|
759
|
+
* Textarea for entering a personal message to include with the gift card.
|
|
760
|
+
* Only renders when isGift is true (purchasing for someone else).
|
|
761
|
+
* This field is optional - no validation is required.
|
|
762
|
+
*
|
|
763
|
+
* @component
|
|
764
|
+
* @example
|
|
765
|
+
* ```tsx
|
|
766
|
+
* // Default usage
|
|
767
|
+
* <GiftCard.RecipientMessage label="Message" className="w-full p-3 border rounded-lg" />
|
|
768
|
+
*
|
|
769
|
+
* // asChild with primitive
|
|
770
|
+
* <GiftCard.RecipientMessage label="Message" asChild>
|
|
771
|
+
* <textarea className="w-full p-3 border-2 rounded-lg resize-none" rows={4} />
|
|
772
|
+
* </GiftCard.RecipientMessage>
|
|
773
|
+
*
|
|
774
|
+
* // asChild with react component
|
|
775
|
+
* <GiftCard.RecipientMessage>
|
|
776
|
+
* {React.forwardRef(({ value, setValue, isVisible, ...props }, ref) =>
|
|
777
|
+
* isVisible && (
|
|
778
|
+
* <div className="space-y-2">
|
|
779
|
+
* <label className="text-sm font-medium">Message (optional)</label>
|
|
780
|
+
* <textarea
|
|
781
|
+
* ref={ref}
|
|
782
|
+
* {...props}
|
|
783
|
+
* value={value}
|
|
784
|
+
* onChange={(e) => setValue(e.target.value)}
|
|
785
|
+
* className="w-full p-3 border-2 rounded-lg resize-none"
|
|
786
|
+
* rows={4}
|
|
787
|
+
* />
|
|
788
|
+
* </div>
|
|
789
|
+
* )
|
|
790
|
+
* )}
|
|
791
|
+
* </GiftCard.RecipientMessage>
|
|
792
|
+
* ```
|
|
793
|
+
*/
|
|
794
|
+
export const RecipientMessage = React.forwardRef((props, ref) => {
|
|
795
|
+
const { label, asChild, children, className, ...otherProps } = props;
|
|
796
|
+
return (_jsx(CoreGiftCard.RecipientMessage, { children: ({ value, setValue, isVisible }) => {
|
|
797
|
+
// Don't render if not visible (isGift is false) unless using asChild
|
|
798
|
+
if (!isVisible && !asChild) {
|
|
799
|
+
return null;
|
|
800
|
+
}
|
|
801
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardRecipientMessage, "data-visible": isVisible || undefined, customElement: children, customElementProps: {
|
|
802
|
+
value,
|
|
803
|
+
setValue,
|
|
804
|
+
isVisible,
|
|
805
|
+
}, ...otherProps, children: _jsx("div", { children: isVisible && (_jsxs(_Fragment, { children: [label && _jsx("label", { children: label }), _jsx("textarea", { value: value, onChange: (e) => setValue(e.target.value), className: className, rows: 4 })] })) }) }));
|
|
806
|
+
} }));
|
|
807
|
+
});
|
|
808
|
+
RecipientMessage.displayName = 'GiftCard.RecipientMessage';
|
|
809
|
+
/**
|
|
810
|
+
* Form for entering recipient details when purchasing a gift card for someone else.
|
|
811
|
+
* Only renders when isGift is true (purchasing for someone else).
|
|
812
|
+
*
|
|
813
|
+
* This is a convenience component that combines all recipient fields (email, name, date, message).
|
|
814
|
+
* For granular control over layout and styling, use the individual components:
|
|
815
|
+
* `GiftCard.RecipientEmail`, `GiftCard.RecipientName`, `GiftCard.RecipientDate`, `GiftCard.RecipientMessage`.
|
|
816
|
+
*
|
|
817
|
+
* @component
|
|
818
|
+
* @example
|
|
819
|
+
* ```tsx
|
|
820
|
+
* // Default usage
|
|
821
|
+
* <GiftCard.RecipientForm
|
|
822
|
+
* emailLabel="Recipient email"
|
|
823
|
+
* nameLabel="Recipient name"
|
|
824
|
+
* dateLabel="Delivery date"
|
|
825
|
+
* messageLabel="Message"
|
|
826
|
+
* className="space-y-4"
|
|
827
|
+
* />
|
|
828
|
+
*
|
|
829
|
+
* // asChild with primitive
|
|
830
|
+
* <GiftCard.RecipientForm
|
|
831
|
+
* emailLabel="Recipient email"
|
|
832
|
+
* nameLabel="Recipient name"
|
|
833
|
+
* dateLabel="Delivery date"
|
|
834
|
+
* messageLabel="Message"
|
|
835
|
+
* asChild
|
|
836
|
+
* >
|
|
837
|
+
* <div className="space-y-6 p-6 bg-surface-secondary rounded-xl" />
|
|
838
|
+
* </GiftCard.RecipientForm>
|
|
839
|
+
*
|
|
840
|
+
* // asChild with react component
|
|
841
|
+
* <GiftCard.RecipientForm>
|
|
842
|
+
* {React.forwardRef(({
|
|
843
|
+
* isVisible,
|
|
844
|
+
* showErrors,
|
|
845
|
+
* email,
|
|
846
|
+
* name,
|
|
847
|
+
* deliverAt,
|
|
848
|
+
* message,
|
|
849
|
+
* ...props
|
|
850
|
+
* }, ref) =>
|
|
851
|
+
* isVisible && (
|
|
852
|
+
* <div ref={ref} {...props} className="space-y-6 p-6 bg-surface-secondary rounded-xl">
|
|
853
|
+
* <h3 className="text-lg font-semibold">Recipient Details</h3>
|
|
854
|
+
*
|
|
855
|
+
* <div className="space-y-2">
|
|
856
|
+
* <label className="text-sm font-medium">
|
|
857
|
+
* Recipient email <span className="text-status-error">*</span>
|
|
858
|
+
* </label>
|
|
859
|
+
* <input
|
|
860
|
+
* type="email"
|
|
861
|
+
* value={email.value}
|
|
862
|
+
* onChange={(e) => email.setValue(e.target.value)}
|
|
863
|
+
* data-invalid={showErrors && !email.isValid}
|
|
864
|
+
* className="w-full p-3 border-2 rounded-lg data-[invalid]:border-status-error"
|
|
865
|
+
* />
|
|
866
|
+
* {showErrors && !email.isValid && (
|
|
867
|
+
* <p className="text-sm text-status-error">Please enter a valid email</p>
|
|
868
|
+
* )}
|
|
869
|
+
* </div>
|
|
870
|
+
*
|
|
871
|
+
* <div className="space-y-2">
|
|
872
|
+
* <label className="text-sm font-medium">Recipient name (optional)</label>
|
|
873
|
+
* <input
|
|
874
|
+
* type="text"
|
|
875
|
+
* value={name.value}
|
|
876
|
+
* onChange={(e) => name.setValue(e.target.value)}
|
|
877
|
+
* className="w-full p-3 border-2 rounded-lg"
|
|
878
|
+
* />
|
|
879
|
+
* </div>
|
|
880
|
+
*
|
|
881
|
+
* <div className="space-y-2">
|
|
882
|
+
* <label className="text-sm font-medium">Delivery date</label>
|
|
883
|
+
* <input
|
|
884
|
+
* type="date"
|
|
885
|
+
* value={deliverAt.inputValue}
|
|
886
|
+
* onChange={(e) => deliverAt.setValue(new Date(e.target.value))}
|
|
887
|
+
* className="w-full p-3 border-2 rounded-lg"
|
|
888
|
+
* />
|
|
889
|
+
* <p className="text-xs text-content-muted">
|
|
890
|
+
* Scheduled for: {deliverAt.formattedValue}
|
|
891
|
+
* </p>
|
|
892
|
+
* </div>
|
|
893
|
+
*
|
|
894
|
+
* <div className="space-y-2">
|
|
895
|
+
* <label className="text-sm font-medium">Message (optional)</label>
|
|
896
|
+
* <textarea
|
|
897
|
+
* value={message.value}
|
|
898
|
+
* onChange={(e) => message.setValue(e.target.value)}
|
|
899
|
+
* className="w-full p-3 border-2 rounded-lg resize-none"
|
|
900
|
+
* rows={4}
|
|
901
|
+
* />
|
|
902
|
+
* </div>
|
|
903
|
+
* </div>
|
|
904
|
+
* )
|
|
905
|
+
* )}
|
|
906
|
+
* </GiftCard.RecipientForm>
|
|
907
|
+
* ```
|
|
908
|
+
*/
|
|
909
|
+
export const RecipientForm = React.forwardRef((props, ref) => {
|
|
910
|
+
const { emailLabel, nameLabel, dateLabel, messageLabel, asChild, children, className, ...otherProps } = props;
|
|
911
|
+
return (_jsx(CoreGiftCard.RecipientForm, { children: (formData) => {
|
|
912
|
+
// Don't render if not visible (isGift is false) unless using asChild
|
|
913
|
+
if (!formData.isVisible && !asChild) {
|
|
914
|
+
return null;
|
|
915
|
+
}
|
|
916
|
+
const showEmailError = formData.showErrors && !formData.email.isValid;
|
|
917
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.giftCardRecipientForm, "data-visible": formData.isVisible || undefined, customElement: children, customElementProps: formData, ...otherProps, children: _jsx("div", { className: className, children: formData.isVisible && (_jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": TestIds.giftCardRecipientEmail, children: [emailLabel && _jsx("label", { children: emailLabel }), _jsx("input", { type: "email", value: formData.email.value, onChange: (e) => formData.email.setValue(e.target.value), "data-invalid": showEmailError || undefined })] }), _jsxs("div", { "data-testid": TestIds.giftCardRecipientName, children: [nameLabel && _jsx("label", { children: nameLabel }), _jsx("input", { type: "text", value: formData.name.value, onChange: (e) => formData.name.setValue(e.target.value) })] }), _jsxs("div", { "data-testid": TestIds.giftCardRecipientDate, children: [dateLabel && _jsx("label", { children: dateLabel }), _jsx("input", { type: "date", value: formData.deliverAt.inputValue, onChange: (e) => {
|
|
918
|
+
if (e.target.value) {
|
|
919
|
+
formData.deliverAt.setValue(new Date(e.target.value));
|
|
920
|
+
}
|
|
921
|
+
} })] }), _jsxs("div", { "data-testid": TestIds.giftCardRecipientMessage, children: [messageLabel && _jsx("label", { children: messageLabel }), _jsx("textarea", { value: formData.message.value, onChange: (e) => formData.message.setValue(e.target.value), rows: 4 })] })] })) }) }));
|
|
922
|
+
} }));
|
|
923
|
+
});
|
|
924
|
+
RecipientForm.displayName = 'GiftCard.RecipientForm';
|
|
925
|
+
/**
|
|
926
|
+
* Add to cart button for gift cards.
|
|
927
|
+
* Validates the form (triggers showErrors), then adds the gift card to cart.
|
|
928
|
+
*
|
|
929
|
+
* Validation flow:
|
|
930
|
+
* 1. When clicked, sets showErrors to true (makes validation errors visible)
|
|
931
|
+
* 2. Checks if form is valid (variant selected, valid custom amount, valid email if gift)
|
|
932
|
+
* 3. If invalid, exits early (user sees validation errors)
|
|
933
|
+
* 4. If valid, adds the gift card line items to cart
|
|
934
|
+
*
|
|
935
|
+
* @component
|
|
936
|
+
* @example
|
|
937
|
+
* ```tsx
|
|
938
|
+
* // Default usage
|
|
939
|
+
* <GiftCard.Action.AddToCart
|
|
940
|
+
* label="Add to Cart"
|
|
941
|
+
* loadingLabel="Adding..."
|
|
942
|
+
* className="w-full py-4 bg-brand-primary text-white rounded-xl font-semibold"
|
|
943
|
+
* />
|
|
944
|
+
*
|
|
945
|
+
* // asChild with primitive
|
|
946
|
+
* <GiftCard.Action.AddToCart asChild>
|
|
947
|
+
* <button className="w-full py-4 bg-brand-primary text-white rounded-xl font-semibold" />
|
|
948
|
+
* </GiftCard.Action.AddToCart>
|
|
949
|
+
*
|
|
950
|
+
* // asChild with react component (full control)
|
|
951
|
+
* <GiftCard.Action.AddToCart asChild>
|
|
952
|
+
* {React.forwardRef(({ onClick, isLoading, ...props }, ref) => (
|
|
953
|
+
* <button
|
|
954
|
+
* ref={ref}
|
|
955
|
+
* {...props}
|
|
956
|
+
* onClick={onClick}
|
|
957
|
+
* disabled={isLoading}
|
|
958
|
+
* className="w-full py-4 bg-brand-primary text-white rounded-xl font-semibold disabled:opacity-50"
|
|
959
|
+
* >
|
|
960
|
+
* {isLoading ? (
|
|
961
|
+
* <span className="flex items-center justify-center gap-2">
|
|
962
|
+
* <Spinner className="w-5 h-5" />
|
|
963
|
+
* Adding to cart...
|
|
964
|
+
* </span>
|
|
965
|
+
* ) : (
|
|
966
|
+
* 'Add to Cart'
|
|
967
|
+
* )}
|
|
968
|
+
* </button>
|
|
969
|
+
* ))}
|
|
970
|
+
* </GiftCard.Action.AddToCart>
|
|
971
|
+
*
|
|
972
|
+
* // With success callback
|
|
973
|
+
* <GiftCard.Action.AddToCart
|
|
974
|
+
* label="Add to Cart"
|
|
975
|
+
* onSuccess={() => {
|
|
976
|
+
* toast.success('Added to cart!');
|
|
977
|
+
* }}
|
|
978
|
+
* />
|
|
979
|
+
* ```
|
|
980
|
+
*/
|
|
981
|
+
export const ActionAddToCart = React.forwardRef((props, ref) => {
|
|
982
|
+
const { label = 'Add to Cart', loadingLabel, asChild, children, className, onSuccess, ...otherProps } = props;
|
|
983
|
+
return (_jsx(CoreGiftCard.Actions, { children: ({ lineItems, validateAndShowErrors }) => {
|
|
984
|
+
// asChild
|
|
985
|
+
if (asChild && children) {
|
|
986
|
+
return (_jsx(Commerce.Actions.AddToCart, { ref: ref, lineItems: lineItems, asChild: true, onSuccess: onSuccess, children: (commerceProps, commerceRef) => {
|
|
987
|
+
const onClick = async () => {
|
|
988
|
+
if (!validateAndShowErrors()) {
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
await commerceProps.onClick();
|
|
992
|
+
};
|
|
993
|
+
return (_jsx(AsChildSlot, { ref: commerceRef, asChild: asChild, className: className, "data-testid": TestIds.giftCardAddToCart, customElement: children, customElementProps: {
|
|
994
|
+
onClick,
|
|
995
|
+
isLoading: commerceProps.isLoading,
|
|
996
|
+
}, content: commerceProps.isLoading && loadingLabel
|
|
997
|
+
? loadingLabel
|
|
998
|
+
: label }));
|
|
999
|
+
} }));
|
|
1000
|
+
}
|
|
1001
|
+
// default rendering
|
|
1002
|
+
return (_jsx(Commerce.Actions.AddToCart, { ref: ref, lineItems: lineItems, asChild: true, onSuccess: onSuccess, children: (commerceProps, commerceRef) => {
|
|
1003
|
+
const onClick = async () => {
|
|
1004
|
+
if (!validateAndShowErrors()) {
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
await commerceProps.onClick();
|
|
1008
|
+
};
|
|
1009
|
+
return (_jsx("button", { ref: commerceRef, className: className, disabled: commerceProps.isLoading, onClick: onClick, "data-testid": TestIds.giftCardAddToCart, "data-loading": commerceProps.isLoading || undefined, ...otherProps, children: commerceProps.isLoading && loadingLabel
|
|
1010
|
+
? loadingLabel
|
|
1011
|
+
: label }));
|
|
1012
|
+
} }));
|
|
1013
|
+
} }));
|
|
1014
|
+
});
|
|
1015
|
+
ActionAddToCart.displayName = 'GiftCard.Action.AddToCart';
|
|
1016
|
+
/**
|
|
1017
|
+
* Buy now button for gift cards.
|
|
1018
|
+
* Validates the form (triggers showErrors), then redirects to checkout.
|
|
1019
|
+
*
|
|
1020
|
+
* Validation flow:
|
|
1021
|
+
* 1. When clicked, sets showErrors to true (makes validation errors visible)
|
|
1022
|
+
* 2. Checks if form is valid (variant selected, valid custom amount, valid email if gift)
|
|
1023
|
+
* 3. If invalid, exits early (user sees validation errors)
|
|
1024
|
+
* 4. If valid, redirects to checkout with the gift card line items
|
|
1025
|
+
*
|
|
1026
|
+
* @component
|
|
1027
|
+
* @example
|
|
1028
|
+
* ```tsx
|
|
1029
|
+
* // Default usage
|
|
1030
|
+
* <GiftCard.Action.BuyNow
|
|
1031
|
+
* label="Buy Now"
|
|
1032
|
+
* loadingLabel="Processing..."
|
|
1033
|
+
* className="w-full py-4 bg-brand-primary text-white rounded-xl font-semibold"
|
|
1034
|
+
* />
|
|
1035
|
+
*
|
|
1036
|
+
* // asChild with primitive
|
|
1037
|
+
* <GiftCard.Action.BuyNow asChild>
|
|
1038
|
+
* <button className="w-full py-4 bg-brand-primary text-white rounded-xl font-semibold" />
|
|
1039
|
+
* </GiftCard.Action.BuyNow>
|
|
1040
|
+
*
|
|
1041
|
+
* // asChild with react component (full control)
|
|
1042
|
+
* <GiftCard.Action.BuyNow asChild>
|
|
1043
|
+
* {React.forwardRef(({ onClick, isLoading, ...props }, ref) => (
|
|
1044
|
+
* <button
|
|
1045
|
+
* ref={ref}
|
|
1046
|
+
* {...props}
|
|
1047
|
+
* onClick={onClick}
|
|
1048
|
+
* disabled={isLoading}
|
|
1049
|
+
* className="w-full py-4 bg-brand-primary text-white rounded-xl font-semibold disabled:opacity-50"
|
|
1050
|
+
* >
|
|
1051
|
+
* {isLoading ? (
|
|
1052
|
+
* <span className="flex items-center justify-center gap-2">
|
|
1053
|
+
* <Spinner className="w-5 h-5" />
|
|
1054
|
+
* Processing...
|
|
1055
|
+
* </span>
|
|
1056
|
+
* ) : (
|
|
1057
|
+
* 'Buy Now'
|
|
1058
|
+
* )}
|
|
1059
|
+
* </button>
|
|
1060
|
+
* ))}
|
|
1061
|
+
* </GiftCard.Action.BuyNow>
|
|
1062
|
+
* ```
|
|
1063
|
+
*/
|
|
1064
|
+
export const ActionBuyNow = React.forwardRef((props, ref) => {
|
|
1065
|
+
const { label = 'Buy Now', loadingLabel, asChild, children, className, ...otherProps } = props;
|
|
1066
|
+
return (_jsx(CoreGiftCard.Actions, { children: ({ lineItems, validateAndShowErrors }) => {
|
|
1067
|
+
// asChild
|
|
1068
|
+
if (asChild && children) {
|
|
1069
|
+
return (_jsx(Commerce.Actions.BuyNow, { ref: ref, lineItems: lineItems, asChild: true, children: (commerceProps, commerceRef) => {
|
|
1070
|
+
const onClick = async () => {
|
|
1071
|
+
if (!validateAndShowErrors()) {
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
await commerceProps.onClick();
|
|
1075
|
+
};
|
|
1076
|
+
return (_jsx(AsChildSlot, { ref: commerceRef, asChild: asChild, className: className, "data-testid": TestIds.giftCardBuyNow, customElement: children, customElementProps: {
|
|
1077
|
+
onClick,
|
|
1078
|
+
isLoading: commerceProps.isLoading,
|
|
1079
|
+
}, content: commerceProps.isLoading && loadingLabel
|
|
1080
|
+
? loadingLabel
|
|
1081
|
+
: label }));
|
|
1082
|
+
} }));
|
|
1083
|
+
}
|
|
1084
|
+
// default rendering
|
|
1085
|
+
return (_jsx(Commerce.Actions.BuyNow, { ref: ref, lineItems: lineItems, asChild: true, children: (commerceProps, commerceRef) => {
|
|
1086
|
+
const onClick = async () => {
|
|
1087
|
+
if (!validateAndShowErrors()) {
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1090
|
+
await commerceProps.onClick();
|
|
1091
|
+
};
|
|
1092
|
+
return (_jsx("button", { ref: commerceRef, className: className, disabled: commerceProps.isLoading, onClick: onClick, "data-testid": TestIds.giftCardBuyNow, "data-loading": commerceProps.isLoading || undefined, ...otherProps, children: commerceProps.isLoading && loadingLabel
|
|
1093
|
+
? loadingLabel
|
|
1094
|
+
: label }));
|
|
1095
|
+
} }));
|
|
1096
|
+
} }));
|
|
1097
|
+
});
|
|
1098
|
+
ActionBuyNow.displayName = 'GiftCard.Action.BuyNow';
|
|
1099
|
+
/**
|
|
1100
|
+
* Namespace containing all gift card action components.
|
|
1101
|
+
* These components provide consistent interfaces for gift card purchase actions.
|
|
1102
|
+
*
|
|
1103
|
+
* @namespace
|
|
1104
|
+
* @example
|
|
1105
|
+
* ```tsx
|
|
1106
|
+
* // Add to cart with validation
|
|
1107
|
+
* <GiftCard.Action.AddToCart
|
|
1108
|
+
* label="Add to Cart"
|
|
1109
|
+
* loadingLabel="Adding..."
|
|
1110
|
+
* className="btn-primary"
|
|
1111
|
+
* />
|
|
1112
|
+
*
|
|
1113
|
+
* // Buy now with validation
|
|
1114
|
+
* <GiftCard.Action.BuyNow
|
|
1115
|
+
* label="Buy Now"
|
|
1116
|
+
* loadingLabel="Processing..."
|
|
1117
|
+
* className="btn-primary"
|
|
1118
|
+
* />
|
|
1119
|
+
* ```
|
|
1120
|
+
*/
|
|
1121
|
+
export const Action = {
|
|
1122
|
+
/** Add to Cart button for adding gift card to the current cart */
|
|
1123
|
+
AddToCart: ActionAddToCart,
|
|
1124
|
+
/** Buy Now button for immediate checkout with the gift card */
|
|
1125
|
+
BuyNow: ActionBuyNow,
|
|
1126
|
+
};
|