@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.
Files changed (69) hide show
  1. package/cjs/dist/__mocks__/gift-card.d.ts +14 -0
  2. package/cjs/dist/__mocks__/gift-card.d.ts.map +1 -0
  3. package/cjs/dist/__mocks__/gift-card.js +49 -0
  4. package/cjs/dist/enums/index.d.ts +52 -0
  5. package/cjs/dist/enums/index.d.ts.map +1 -0
  6. package/cjs/dist/enums/index.js +52 -0
  7. package/cjs/dist/react/GiftCard.d.ts +1318 -0
  8. package/cjs/dist/react/GiftCard.d.ts.map +1 -0
  9. package/cjs/dist/react/GiftCard.js +1126 -0
  10. package/cjs/dist/react/core/GiftCard.d.ts +863 -0
  11. package/cjs/dist/react/core/GiftCard.d.ts.map +1 -0
  12. package/cjs/dist/react/core/GiftCard.js +737 -0
  13. package/cjs/dist/react/index.d.ts +2 -0
  14. package/cjs/dist/react/index.d.ts.map +1 -0
  15. package/cjs/dist/react/index.js +1 -0
  16. package/cjs/dist/services/gift-card-checkout-service.d.ts +133 -0
  17. package/cjs/dist/services/gift-card-checkout-service.d.ts.map +1 -0
  18. package/cjs/dist/services/gift-card-checkout-service.js +159 -0
  19. package/cjs/dist/services/gift-card-service.d.ts +102 -0
  20. package/cjs/dist/services/gift-card-service.d.ts.map +1 -0
  21. package/cjs/dist/services/gift-card-service.js +165 -0
  22. package/cjs/dist/services/index.d.ts +3 -0
  23. package/cjs/dist/services/index.d.ts.map +1 -0
  24. package/cjs/dist/services/index.js +2 -0
  25. package/cjs/dist/utils/formatting-utils.d.ts +13 -0
  26. package/cjs/dist/utils/formatting-utils.d.ts.map +1 -0
  27. package/cjs/dist/utils/formatting-utils.js +38 -0
  28. package/cjs/dist/utils/gift-card-utils.d.ts +18 -0
  29. package/cjs/dist/utils/gift-card-utils.d.ts.map +1 -0
  30. package/cjs/dist/utils/gift-card-utils.js +118 -0
  31. package/cjs/dist/utils/validation-utils.d.ts +10 -0
  32. package/cjs/dist/utils/validation-utils.d.ts.map +1 -0
  33. package/cjs/dist/utils/validation-utils.js +24 -0
  34. package/dist/__mocks__/gift-card.d.ts +14 -0
  35. package/dist/__mocks__/gift-card.d.ts.map +1 -0
  36. package/dist/__mocks__/gift-card.js +49 -0
  37. package/dist/enums/index.d.ts +52 -0
  38. package/dist/enums/index.d.ts.map +1 -0
  39. package/dist/enums/index.js +52 -0
  40. package/dist/react/GiftCard.d.ts +1318 -0
  41. package/dist/react/GiftCard.d.ts.map +1 -0
  42. package/dist/react/GiftCard.js +1126 -0
  43. package/dist/react/core/GiftCard.d.ts +863 -0
  44. package/dist/react/core/GiftCard.d.ts.map +1 -0
  45. package/dist/react/core/GiftCard.js +737 -0
  46. package/dist/react/index.d.ts +2 -0
  47. package/dist/react/index.d.ts.map +1 -0
  48. package/dist/react/index.js +1 -0
  49. package/dist/services/gift-card-checkout-service.d.ts +133 -0
  50. package/dist/services/gift-card-checkout-service.d.ts.map +1 -0
  51. package/dist/services/gift-card-checkout-service.js +159 -0
  52. package/dist/services/gift-card-service.d.ts +102 -0
  53. package/dist/services/gift-card-service.d.ts.map +1 -0
  54. package/dist/services/gift-card-service.js +165 -0
  55. package/dist/services/index.d.ts +3 -0
  56. package/dist/services/index.d.ts.map +1 -0
  57. package/dist/services/index.js +2 -0
  58. package/dist/utils/formatting-utils.d.ts +13 -0
  59. package/dist/utils/formatting-utils.d.ts.map +1 -0
  60. package/dist/utils/formatting-utils.js +38 -0
  61. package/dist/utils/gift-card-utils.d.ts +18 -0
  62. package/dist/utils/gift-card-utils.d.ts.map +1 -0
  63. package/dist/utils/gift-card-utils.js +118 -0
  64. package/dist/utils/validation-utils.d.ts +10 -0
  65. package/dist/utils/validation-utils.d.ts.map +1 -0
  66. package/dist/utils/validation-utils.js +24 -0
  67. package/package.json +72 -0
  68. package/react/package.json +4 -0
  69. 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
+ };