@wix/headless-stores 0.0.52 → 0.0.53
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/astro/actions/custom-checkout.d.ts +1 -1
- package/cjs/dist/astro/actions/custom-checkout.js +2 -2
- package/cjs/dist/astro/actions/index.d.ts +1 -1
- package/cjs/dist/astro/actions/index.js +1 -1
- package/cjs/dist/enums/index.d.ts +2 -2
- package/cjs/dist/enums/index.js +2 -2
- package/cjs/dist/react/Category.d.ts +168 -67
- package/cjs/dist/react/Category.js +166 -50
- package/cjs/dist/react/CategoryList.d.ts +56 -138
- package/cjs/dist/react/CategoryList.js +44 -129
- package/cjs/dist/react/Choice.d.ts +193 -0
- package/cjs/dist/react/Choice.js +259 -0
- package/cjs/dist/react/Option.d.ts +224 -0
- package/cjs/dist/react/Option.js +388 -0
- package/cjs/dist/react/Product.d.ts +339 -96
- package/cjs/dist/react/Product.js +507 -94
- package/cjs/dist/react/{BuyNow.js → core/BuyNow.js} +2 -2
- package/cjs/dist/react/core/Category.d.ts +98 -0
- package/cjs/dist/react/core/Category.js +81 -0
- package/cjs/dist/react/core/CategoryList.d.ts +185 -0
- package/cjs/dist/react/core/CategoryList.js +174 -0
- package/{dist/react → cjs/dist/react/core}/PayNow.js +2 -2
- package/cjs/dist/react/core/Product.d.ts +148 -0
- package/cjs/dist/react/core/Product.js +126 -0
- package/cjs/dist/react/{ProductList.d.ts → core/ProductList.d.ts} +3 -3
- package/cjs/dist/react/{ProductList.js → core/ProductList.js} +10 -10
- package/{dist/react → cjs/dist/react/core}/ProductListFilters.d.ts +3 -3
- package/{dist/react → cjs/dist/react/core}/ProductListFilters.js +7 -7
- package/cjs/dist/react/{ProductListPagination.js → core/ProductListPagination.js} +8 -8
- package/{dist/react → cjs/dist/react/core}/ProductListSort.d.ts +1 -1
- package/cjs/dist/react/{ProductListSort.js → core/ProductListSort.js} +3 -3
- package/{dist/react → cjs/dist/react/core}/ProductModifiers.d.ts +1 -1
- package/{dist/react → cjs/dist/react/core}/ProductModifiers.js +13 -13
- package/{dist/react → cjs/dist/react/core}/ProductVariantSelector.d.ts +2 -2
- package/{dist/react → cjs/dist/react/core}/ProductVariantSelector.js +7 -10
- package/{dist/react → cjs/dist/react/core}/SelectedVariant.d.ts +2 -2
- package/{dist/react → cjs/dist/react/core}/SelectedVariant.js +43 -15
- package/cjs/dist/react/index.d.ts +15 -10
- package/cjs/dist/react/index.js +15 -10
- package/cjs/dist/react/types.d.ts +8 -0
- package/cjs/dist/react/types.js +9 -0
- package/cjs/dist/server-actions/custom-checkout-action.js +14 -10
- package/cjs/dist/server-actions/index.d.ts +1 -1
- package/cjs/dist/server-actions/index.js +1 -1
- package/cjs/dist/services/buy-now-service.d.ts +1 -1
- package/cjs/dist/services/buy-now-service.js +6 -6
- package/cjs/dist/services/categories-list-service.d.ts +4 -4
- package/cjs/dist/services/categories-list-service.js +10 -10
- package/cjs/dist/services/category-service.d.ts +18 -22
- package/cjs/dist/services/category-service.js +12 -10
- package/cjs/dist/services/index.d.ts +7 -7
- package/cjs/dist/services/index.js +7 -7
- package/cjs/dist/services/pay-now-service.d.ts +1 -1
- package/cjs/dist/services/pay-now-service.js +4 -4
- package/cjs/dist/services/product-modifiers-service.d.ts +3 -3
- package/cjs/dist/services/product-modifiers-service.js +7 -7
- package/cjs/dist/services/product-service.d.ts +4 -4
- package/cjs/dist/services/product-service.js +18 -18
- package/cjs/dist/services/products-list-search-service.d.ts +5 -5
- package/cjs/dist/services/products-list-search-service.js +117 -117
- package/cjs/dist/services/products-list-service.d.ts +4 -4
- package/cjs/dist/services/products-list-service.js +12 -12
- package/cjs/dist/services/selected-variant-service.d.ts +6 -2
- package/cjs/dist/services/selected-variant-service.js +86 -83
- package/cjs/dist/utils/index.d.ts +1 -0
- package/cjs/dist/utils/index.js +5 -4
- package/cjs/dist/utils/renderAsChild.d.ts +96 -0
- package/cjs/dist/utils/renderAsChild.js +66 -0
- package/cjs/dist/utils/renderChildren.d.ts +41 -0
- package/cjs/dist/utils/renderChildren.js +44 -0
- package/cjs/dist/utils/url-params.js +3 -3
- package/dist/astro/actions/custom-checkout.d.ts +1 -1
- package/dist/astro/actions/custom-checkout.js +2 -2
- package/dist/astro/actions/index.d.ts +1 -1
- package/dist/astro/actions/index.js +1 -1
- package/dist/enums/index.d.ts +2 -2
- package/dist/enums/index.js +2 -2
- package/dist/react/Category.d.ts +168 -67
- package/dist/react/Category.js +166 -50
- package/dist/react/CategoryList.d.ts +56 -138
- package/dist/react/CategoryList.js +44 -129
- package/dist/react/Choice.d.ts +193 -0
- package/dist/react/Choice.js +259 -0
- package/dist/react/Option.d.ts +224 -0
- package/dist/react/Option.js +388 -0
- package/dist/react/Product.d.ts +339 -96
- package/dist/react/Product.js +507 -94
- package/dist/react/{BuyNow.js → core/BuyNow.js} +2 -2
- package/dist/react/core/Category.d.ts +98 -0
- package/dist/react/core/Category.js +81 -0
- package/dist/react/core/CategoryList.d.ts +185 -0
- package/dist/react/core/CategoryList.js +174 -0
- package/{cjs/dist/react → dist/react/core}/PayNow.js +2 -2
- package/dist/react/core/Product.d.ts +148 -0
- package/dist/react/core/Product.js +126 -0
- package/dist/react/{ProductList.d.ts → core/ProductList.d.ts} +3 -3
- package/dist/react/{ProductList.js → core/ProductList.js} +10 -10
- package/{cjs/dist/react → dist/react/core}/ProductListFilters.d.ts +3 -3
- package/{cjs/dist/react → dist/react/core}/ProductListFilters.js +7 -7
- package/dist/react/{ProductListPagination.js → core/ProductListPagination.js} +8 -8
- package/{cjs/dist/react → dist/react/core}/ProductListSort.d.ts +1 -1
- package/dist/react/{ProductListSort.js → core/ProductListSort.js} +3 -3
- package/{cjs/dist/react → dist/react/core}/ProductModifiers.d.ts +1 -1
- package/{cjs/dist/react → dist/react/core}/ProductModifiers.js +13 -13
- package/{cjs/dist/react → dist/react/core}/ProductVariantSelector.d.ts +2 -2
- package/{cjs/dist/react → dist/react/core}/ProductVariantSelector.js +7 -10
- package/{cjs/dist/react → dist/react/core}/SelectedVariant.d.ts +2 -2
- package/{cjs/dist/react → dist/react/core}/SelectedVariant.js +43 -15
- package/dist/react/index.d.ts +15 -10
- package/dist/react/index.js +15 -10
- package/dist/react/types.d.ts +8 -0
- package/dist/react/types.js +9 -0
- package/dist/server-actions/custom-checkout-action.js +14 -10
- package/dist/server-actions/index.d.ts +1 -1
- package/dist/server-actions/index.js +1 -1
- package/dist/services/buy-now-service.d.ts +1 -1
- package/dist/services/buy-now-service.js +6 -6
- package/dist/services/categories-list-service.d.ts +4 -4
- package/dist/services/categories-list-service.js +10 -10
- package/dist/services/category-service.d.ts +18 -22
- package/dist/services/category-service.js +12 -10
- package/dist/services/index.d.ts +7 -7
- package/dist/services/index.js +7 -7
- package/dist/services/pay-now-service.d.ts +1 -1
- package/dist/services/pay-now-service.js +4 -4
- package/dist/services/product-modifiers-service.d.ts +3 -3
- package/dist/services/product-modifiers-service.js +7 -7
- package/dist/services/product-service.d.ts +4 -4
- package/dist/services/product-service.js +18 -18
- package/dist/services/products-list-search-service.d.ts +5 -5
- package/dist/services/products-list-search-service.js +117 -117
- package/dist/services/products-list-service.d.ts +4 -4
- package/dist/services/products-list-service.js +12 -12
- package/dist/services/selected-variant-service.d.ts +6 -2
- package/dist/services/selected-variant-service.js +86 -83
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +5 -4
- package/dist/utils/renderAsChild.d.ts +96 -0
- package/dist/utils/renderAsChild.js +66 -0
- package/dist/utils/renderChildren.d.ts +41 -0
- package/dist/utils/renderChildren.js +44 -0
- package/dist/utils/url-params.js +3 -3
- package/package.json +7 -3
- /package/cjs/dist/react/{BuyNow.d.ts → core/BuyNow.d.ts} +0 -0
- /package/cjs/dist/react/{PayNow.d.ts → core/PayNow.d.ts} +0 -0
- /package/cjs/dist/react/{ProductListPagination.d.ts → core/ProductListPagination.d.ts} +0 -0
- /package/dist/react/{BuyNow.d.ts → core/BuyNow.d.ts} +0 -0
- /package/dist/react/{PayNow.d.ts → core/PayNow.d.ts} +0 -0
- /package/dist/react/{ProductListPagination.d.ts → core/ProductListPagination.d.ts} +0 -0
package/dist/react/Product.js
CHANGED
|
@@ -1,10 +1,52 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { renderAsChild } from '../utils/index.js';
|
|
4
|
+
import * as CoreProduct from './core/Product.js';
|
|
5
|
+
import * as ProductVariantSelector from './core/ProductVariantSelector.js';
|
|
6
|
+
import * as ProductModifiers from './core/ProductModifiers.js';
|
|
7
|
+
import * as SelectedVariant from './core/SelectedVariant.js';
|
|
8
|
+
import * as Option from './Option.js';
|
|
9
|
+
import { AsContent } from './types.js';
|
|
10
|
+
const VariantsContext = React.createContext(null);
|
|
5
11
|
/**
|
|
6
|
-
*
|
|
7
|
-
|
|
12
|
+
* Hook to access variants context
|
|
13
|
+
*/
|
|
14
|
+
export function useVariantsContext() {
|
|
15
|
+
const context = React.useContext(VariantsContext);
|
|
16
|
+
if (!context) {
|
|
17
|
+
throw new Error('useVariantsContext must be used within a Product.Variants component');
|
|
18
|
+
}
|
|
19
|
+
return context;
|
|
20
|
+
}
|
|
21
|
+
const ModifiersContext = React.createContext(null);
|
|
22
|
+
/**
|
|
23
|
+
* Hook to access modifiers context
|
|
24
|
+
*/
|
|
25
|
+
export function useModifiersContext() {
|
|
26
|
+
const context = React.useContext(ModifiersContext);
|
|
27
|
+
if (!context) {
|
|
28
|
+
throw new Error('useModifiersContext must be used within a Product.Modifiers component');
|
|
29
|
+
}
|
|
30
|
+
return context;
|
|
31
|
+
}
|
|
32
|
+
var TestIds;
|
|
33
|
+
(function (TestIds) {
|
|
34
|
+
TestIds["productRoot"] = "product-root";
|
|
35
|
+
TestIds["productName"] = "product-name";
|
|
36
|
+
TestIds["productDescription"] = "product-description";
|
|
37
|
+
TestIds["productPrice"] = "product-price";
|
|
38
|
+
TestIds["productCompareAtPrice"] = "product-compare-at-price";
|
|
39
|
+
TestIds["productVariants"] = "product-variants";
|
|
40
|
+
TestIds["productVariantOptions"] = "product-variant-options";
|
|
41
|
+
TestIds["productVariantOption"] = "product-variant-option";
|
|
42
|
+
TestIds["productModifiers"] = "product-modifiers";
|
|
43
|
+
TestIds["productModifierOptions"] = "product-modifier-options";
|
|
44
|
+
TestIds["productModifierOption"] = "product-modifier-option";
|
|
45
|
+
})(TestIds || (TestIds = {}));
|
|
46
|
+
/**
|
|
47
|
+
* Root component that provides all necessary service contexts for a complete product experience.
|
|
48
|
+
* This composite component combines Product, ProductVariantSelector, ProductModifiers, and SelectedVariant
|
|
49
|
+
* functionality following the documented API patterns with proper data attributes.
|
|
8
50
|
*
|
|
9
51
|
* @order 1
|
|
10
52
|
* @component
|
|
@@ -12,115 +54,486 @@ import { createServicesMap } from "@wix/services-manager";
|
|
|
12
54
|
* ```tsx
|
|
13
55
|
* import { Product } from '@wix/stores/components';
|
|
14
56
|
*
|
|
15
|
-
* function ProductPage() {
|
|
57
|
+
* function ProductPage({ product }) {
|
|
16
58
|
* return (
|
|
17
|
-
* <Product.Root
|
|
18
|
-
* <
|
|
19
|
-
* <Product.Name>
|
|
20
|
-
* {({ name }) => (
|
|
21
|
-
* <h1
|
|
22
|
-
* className="text-4xl font-bold text-content-primary mb-4"
|
|
23
|
-
* data-testid="product-name"
|
|
24
|
-
* >
|
|
25
|
-
* {name}
|
|
26
|
-
* </h1>
|
|
27
|
-
* )}
|
|
28
|
-
* </Product.Name>
|
|
29
|
-
* </div>
|
|
59
|
+
* <Product.Root product={product}>
|
|
60
|
+
* <Product.Name className="text-4xl font-bold" />
|
|
30
61
|
* </Product.Root>
|
|
31
62
|
* );
|
|
32
63
|
* }
|
|
33
64
|
* ```
|
|
34
65
|
*/
|
|
35
66
|
export function Root(props) {
|
|
36
|
-
return (_jsx(
|
|
67
|
+
return (_jsx(CoreProduct.Root, { productServiceConfig: { product: props.product }, "data-testid": TestIds.productRoot, children: _jsx(ProductVariantSelector.Root, { children: _jsx(ProductModifiers.Root, { children: _jsx(SelectedVariant.Root, { children: props.children }) }) }) }));
|
|
37
68
|
}
|
|
38
69
|
/**
|
|
39
|
-
*
|
|
70
|
+
* Displays the product name with customizable rendering following the documented API.
|
|
40
71
|
*
|
|
41
72
|
* @component
|
|
42
73
|
* @example
|
|
43
74
|
* ```tsx
|
|
44
|
-
*
|
|
75
|
+
* // Default usage
|
|
76
|
+
* <Product.Name className="text-4xl font-bold" />
|
|
45
77
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* )
|
|
54
|
-
* }
|
|
78
|
+
* // asChild with primitive
|
|
79
|
+
* <Product.Name asChild>
|
|
80
|
+
* <h1 className="text-4xl font-bold" />
|
|
81
|
+
* </Product.Name>
|
|
82
|
+
*
|
|
83
|
+
* // asChild with react component
|
|
84
|
+
* <Product.Name asChild>
|
|
85
|
+
* {React.forwardRef(({name, ...props}, ref) => (
|
|
86
|
+
* <h1 ref={ref} {...props} className="text-4xl font-bold">
|
|
87
|
+
* {name}
|
|
88
|
+
* </h1>
|
|
89
|
+
* ))}
|
|
90
|
+
* </Product.Name>
|
|
55
91
|
* ```
|
|
56
92
|
*/
|
|
57
|
-
export
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
93
|
+
export const Name = React.forwardRef((props, ref) => {
|
|
94
|
+
const { asChild, children, className } = props;
|
|
95
|
+
return (_jsx(CoreProduct.Name, { children: ({ name }) => {
|
|
96
|
+
const attributes = {
|
|
97
|
+
'data-testid': TestIds.productName,
|
|
98
|
+
};
|
|
99
|
+
if (asChild) {
|
|
100
|
+
const rendered = renderAsChild({
|
|
101
|
+
children,
|
|
102
|
+
props: { name },
|
|
103
|
+
ref,
|
|
104
|
+
content: name,
|
|
105
|
+
attributes,
|
|
106
|
+
});
|
|
107
|
+
if (rendered)
|
|
108
|
+
return rendered;
|
|
109
|
+
}
|
|
110
|
+
return (_jsx("div", { className: className, ...attributes, children: name }));
|
|
111
|
+
} }));
|
|
112
|
+
});
|
|
65
113
|
/**
|
|
66
|
-
*
|
|
114
|
+
* Displays the product description with customizable rendering and format options following the documented API.
|
|
67
115
|
*
|
|
68
116
|
* @component
|
|
69
117
|
* @example
|
|
70
118
|
* ```tsx
|
|
71
|
-
*
|
|
119
|
+
* // Default usage (plain text)
|
|
120
|
+
* <Product.Description className="text-content-secondary" />
|
|
72
121
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* {description && (
|
|
86
|
-
* <div>Rich content description available</div>
|
|
87
|
-
* )}
|
|
88
|
-
* </div>
|
|
89
|
-
* )}
|
|
90
|
-
* </Product.Description>
|
|
91
|
-
* );
|
|
92
|
-
* }
|
|
122
|
+
* // HTML content
|
|
123
|
+
* <Product.Description as="html" className="prose" />
|
|
124
|
+
*
|
|
125
|
+
* // asChild with custom rendering
|
|
126
|
+
* <Product.Description as="html" asChild>
|
|
127
|
+
* {({ description }) => (
|
|
128
|
+
* <div
|
|
129
|
+
* className="text-content-secondary"
|
|
130
|
+
* dangerouslySetInnerHTML={{ __html: description }}
|
|
131
|
+
* />
|
|
132
|
+
* )}
|
|
133
|
+
* </Product.Description>
|
|
93
134
|
* ```
|
|
94
135
|
*/
|
|
95
|
-
export
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
export const Description = React.forwardRef((props, ref) => {
|
|
137
|
+
const { asChild, children, className, as = AsContent.Plain } = props;
|
|
138
|
+
return (_jsx(CoreProduct.Description, { children: ({ description: richDescription, plainDescription }) => {
|
|
139
|
+
const attributes = {
|
|
140
|
+
'data-testid': TestIds.productDescription,
|
|
141
|
+
};
|
|
142
|
+
// Determine which description to use based on the 'as' prop
|
|
143
|
+
let description;
|
|
144
|
+
switch (as) {
|
|
145
|
+
case AsContent.Html:
|
|
146
|
+
description = plainDescription || '';
|
|
147
|
+
break;
|
|
148
|
+
case AsContent.Ricos:
|
|
149
|
+
description = JSON.stringify(richDescription) || '';
|
|
150
|
+
break;
|
|
151
|
+
case AsContent.Plain:
|
|
152
|
+
default:
|
|
153
|
+
// For plain text, we'll strip HTML tags from plainDescription
|
|
154
|
+
description = plainDescription
|
|
155
|
+
? plainDescription.replace(/<[^>]*>/g, '')
|
|
156
|
+
: '';
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
if (asChild) {
|
|
160
|
+
const rendered = renderAsChild({
|
|
161
|
+
children,
|
|
162
|
+
props: { description },
|
|
163
|
+
ref,
|
|
164
|
+
content: description,
|
|
165
|
+
attributes,
|
|
166
|
+
});
|
|
167
|
+
if (rendered)
|
|
168
|
+
return rendered;
|
|
169
|
+
}
|
|
170
|
+
// Default rendering based on format
|
|
171
|
+
if (as === AsContent.Html) {
|
|
172
|
+
return (_jsx("div", { className: className, ...attributes, dangerouslySetInnerHTML: { __html: description } }));
|
|
173
|
+
}
|
|
174
|
+
return (_jsx("div", { className: className, ...attributes, children: description }));
|
|
175
|
+
} }));
|
|
176
|
+
});
|
|
177
|
+
/**
|
|
178
|
+
* Displays the current product price with customizable rendering following the documented API.
|
|
179
|
+
*
|
|
180
|
+
* @component
|
|
181
|
+
* @example
|
|
182
|
+
* ```tsx
|
|
183
|
+
* // Default usage
|
|
184
|
+
* <Product.Price className="text-3xl font-bold text-content-primary data-[discounted]:text-brand-primary" />
|
|
185
|
+
*
|
|
186
|
+
* // asChild with primitive
|
|
187
|
+
* <Product.Price asChild>
|
|
188
|
+
* <span className="text-3xl font-bold text-content-primary" />
|
|
189
|
+
* </Product.Price>
|
|
190
|
+
*
|
|
191
|
+
* // asChild with react component
|
|
192
|
+
* <Product.Price asChild>
|
|
193
|
+
* {React.forwardRef(({price, formattedPrice, ...props}, ref) => (
|
|
194
|
+
* <span ref={ref} {...props} className="text-3xl font-bold text-content-primary">
|
|
195
|
+
* {formattedPrice}
|
|
196
|
+
* </span>
|
|
197
|
+
* ))}
|
|
198
|
+
* </Product.Price>
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
export const Price = React.forwardRef((props, ref) => {
|
|
202
|
+
const { asChild, children, className } = props;
|
|
203
|
+
return (_jsx(SelectedVariant.Price, { children: ({ price, compareAtPrice }) => {
|
|
204
|
+
const attributes = {
|
|
205
|
+
'data-testid': TestIds.productPrice,
|
|
206
|
+
'data-discounted': compareAtPrice !== null,
|
|
207
|
+
};
|
|
208
|
+
const priceData = {
|
|
209
|
+
price,
|
|
210
|
+
formattedPrice: price,
|
|
211
|
+
};
|
|
212
|
+
if (asChild) {
|
|
213
|
+
const rendered = renderAsChild({
|
|
214
|
+
children,
|
|
215
|
+
props: priceData,
|
|
216
|
+
ref,
|
|
217
|
+
content: price,
|
|
218
|
+
attributes,
|
|
219
|
+
});
|
|
220
|
+
if (rendered)
|
|
221
|
+
return rendered;
|
|
222
|
+
}
|
|
223
|
+
return (_jsx("span", { className: className, ...attributes, ref: ref, children: price }));
|
|
224
|
+
} }));
|
|
225
|
+
});
|
|
226
|
+
/**
|
|
227
|
+
* Displays the compare-at (original) price when on sale with customizable rendering following the documented API.
|
|
228
|
+
*
|
|
229
|
+
* @component
|
|
230
|
+
* @example
|
|
231
|
+
* ```tsx
|
|
232
|
+
* // Default usage (only shows when on sale)
|
|
233
|
+
* <Product.CompareAtPrice className="text-lg text-content-faded line-through hidden data-[discounted]:inline" />
|
|
234
|
+
*
|
|
235
|
+
* // asChild with primitive
|
|
236
|
+
* <Product.CompareAtPrice asChild>
|
|
237
|
+
* <span className="text-lg text-content-faded line-through" />
|
|
238
|
+
* </Product.CompareAtPrice>
|
|
239
|
+
*
|
|
240
|
+
* // asChild with react component
|
|
241
|
+
* <Product.CompareAtPrice asChild>
|
|
242
|
+
* {React.forwardRef(({formattedPrice, ...props}, ref) => (
|
|
243
|
+
* <span
|
|
244
|
+
* ref={ref}
|
|
245
|
+
* {...props}
|
|
246
|
+
* className="hidden data-[discounted]:inline text-lg text-content-faded line-through"
|
|
247
|
+
* >
|
|
248
|
+
* Was: {formattedPrice}
|
|
249
|
+
* </span>
|
|
250
|
+
* ))}
|
|
251
|
+
* </Product.CompareAtPrice>
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
export const CompareAtPrice = React.forwardRef((props, ref) => {
|
|
255
|
+
const { asChild, children, className } = props;
|
|
256
|
+
const testId = TestIds.productCompareAtPrice;
|
|
257
|
+
return (_jsx(SelectedVariant.Price, { children: ({ compareAtPrice }) => {
|
|
258
|
+
const attributes = {
|
|
259
|
+
'data-testid': testId,
|
|
260
|
+
'data-discounted': compareAtPrice !== null,
|
|
261
|
+
};
|
|
262
|
+
// Don't render anything if there's no compare-at price
|
|
263
|
+
if (!compareAtPrice) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
const priceData = {
|
|
267
|
+
price: compareAtPrice,
|
|
268
|
+
formattedPrice: compareAtPrice,
|
|
269
|
+
};
|
|
270
|
+
if (asChild) {
|
|
271
|
+
const rendered = renderAsChild({
|
|
272
|
+
children,
|
|
273
|
+
props: priceData,
|
|
274
|
+
ref,
|
|
275
|
+
content: compareAtPrice,
|
|
276
|
+
attributes,
|
|
277
|
+
});
|
|
278
|
+
if (rendered)
|
|
279
|
+
return rendered;
|
|
280
|
+
}
|
|
281
|
+
return (_jsx("span", { className: className, ...attributes, ref: ref, children: compareAtPrice }));
|
|
282
|
+
} }));
|
|
283
|
+
});
|
|
284
|
+
/**
|
|
285
|
+
* Container for product variant selection system.
|
|
286
|
+
* Does not render when there are no variants.
|
|
287
|
+
*
|
|
288
|
+
* @component
|
|
289
|
+
* @example
|
|
290
|
+
* ```tsx
|
|
291
|
+
* // Default usage
|
|
292
|
+
* <Product.Variants>
|
|
293
|
+
* <Product.VariantOptions>
|
|
294
|
+
* <Product.VariantOptionRepeater>
|
|
295
|
+
* <Option.Name className="text-lg font-medium mb-3" />
|
|
296
|
+
* <Option.Choices>
|
|
297
|
+
* <Option.ChoiceRepeater>
|
|
298
|
+
* <Choice.Text className="px-4 py-2 border rounded-lg" />
|
|
299
|
+
* <Choice.Color className="w-10 h-10 rounded-full border-4" />
|
|
300
|
+
* </Option.ChoiceRepeater>
|
|
301
|
+
* </Option.Choices>
|
|
302
|
+
* </Product.VariantOptionRepeater>
|
|
303
|
+
* </Product.VariantOptions>
|
|
304
|
+
* </Product.Variants>
|
|
305
|
+
*
|
|
306
|
+
* // asChild with primitive
|
|
307
|
+
* <Product.Variants asChild>
|
|
308
|
+
* <section className="variant-section">
|
|
309
|
+
* <Product.VariantOptions>
|
|
310
|
+
* // variant options
|
|
311
|
+
* </Product.VariantOptions>
|
|
312
|
+
* </section>
|
|
313
|
+
* </Product.Variants>
|
|
314
|
+
*
|
|
315
|
+
* // asChild with react component
|
|
316
|
+
* <Product.Variants asChild>
|
|
317
|
+
* {React.forwardRef(({hasOptions, ...props}, ref) => (
|
|
318
|
+
* <section ref={ref} {...props} className="variant-section">
|
|
319
|
+
* {hasOptions && <h3>Choose Options</h3>}
|
|
320
|
+
* {props.children}
|
|
321
|
+
* </section>
|
|
322
|
+
* ))}
|
|
323
|
+
* </Product.Variants>
|
|
324
|
+
* ```
|
|
325
|
+
*/
|
|
326
|
+
export const Variants = React.forwardRef((props, ref) => {
|
|
327
|
+
const { asChild, children } = props;
|
|
328
|
+
return (_jsx(ProductVariantSelector.Options, { children: ({ hasOptions, options }) => {
|
|
329
|
+
if (!hasOptions)
|
|
330
|
+
return null;
|
|
331
|
+
const contextValue = {
|
|
332
|
+
hasOptions,
|
|
333
|
+
options,
|
|
334
|
+
};
|
|
335
|
+
const attributes = {
|
|
336
|
+
'data-testid': TestIds.productVariants,
|
|
337
|
+
};
|
|
338
|
+
const content = (_jsx(VariantsContext.Provider, { value: contextValue, children: typeof children === 'function'
|
|
339
|
+
? null
|
|
340
|
+
: children }));
|
|
341
|
+
if (asChild) {
|
|
342
|
+
const rendered = renderAsChild({
|
|
343
|
+
children,
|
|
344
|
+
props: { hasOptions },
|
|
345
|
+
ref,
|
|
346
|
+
content,
|
|
347
|
+
attributes,
|
|
348
|
+
});
|
|
349
|
+
if (rendered)
|
|
350
|
+
return rendered;
|
|
351
|
+
}
|
|
352
|
+
return (_jsx("div", { ...attributes, ref: ref, children: content }));
|
|
353
|
+
} }));
|
|
354
|
+
});
|
|
355
|
+
/**
|
|
356
|
+
* Component that provides access to variant options.
|
|
357
|
+
*
|
|
358
|
+
* @component
|
|
359
|
+
* @example
|
|
360
|
+
* ```tsx
|
|
361
|
+
* // Default usage
|
|
362
|
+
* <Product.VariantOptions emptyState={<div>No options available</div>}>
|
|
363
|
+
* <Product.VariantOptionRepeater>
|
|
364
|
+
* <Option.Name />
|
|
365
|
+
* <Option.Choices>
|
|
366
|
+
* <Option.ChoiceRepeater>
|
|
367
|
+
* <Choice.Text />
|
|
368
|
+
* </Option.ChoiceRepeater>
|
|
369
|
+
* </Option.Choices>
|
|
370
|
+
* </Product.VariantOptionRepeater>
|
|
371
|
+
* </Product.VariantOptions>
|
|
372
|
+
*
|
|
373
|
+
* // Simple container usage
|
|
374
|
+
* <Product.VariantOptions emptyState={<div>No options</div>}>
|
|
375
|
+
* <div className="options-container">
|
|
376
|
+
* <Product.VariantOptionRepeater>
|
|
377
|
+
* // option content
|
|
378
|
+
* </Product.VariantOptionRepeater>
|
|
379
|
+
* </div>
|
|
380
|
+
* </Product.VariantOptions>
|
|
381
|
+
* ```
|
|
382
|
+
*/
|
|
383
|
+
export const VariantOptions = React.forwardRef((props, ref) => {
|
|
384
|
+
const { children, emptyState } = props;
|
|
385
|
+
const { hasOptions } = useVariantsContext();
|
|
386
|
+
if (!hasOptions) {
|
|
387
|
+
return emptyState || null;
|
|
388
|
+
}
|
|
389
|
+
const attributes = {
|
|
390
|
+
'data-testid': TestIds.productVariantOptions,
|
|
391
|
+
};
|
|
392
|
+
return (_jsx("div", { ...attributes, ref: ref, children: children }));
|
|
393
|
+
});
|
|
394
|
+
/**
|
|
395
|
+
* Repeater component that renders children for each variant option.
|
|
396
|
+
*
|
|
397
|
+
* @component
|
|
398
|
+
*/
|
|
399
|
+
export const VariantOptionRepeater = React.forwardRef((props, _ref) => {
|
|
400
|
+
const { children } = props;
|
|
401
|
+
const { hasOptions, options } = useVariantsContext();
|
|
402
|
+
if (!hasOptions)
|
|
403
|
+
return null;
|
|
404
|
+
return (_jsx(_Fragment, { children: options.map((option) => {
|
|
405
|
+
return (_jsx(ProductVariantSelector.Option, { option: option, children: (optionData) => (_jsx(Option.Root, { option: {
|
|
406
|
+
...optionData,
|
|
407
|
+
mandatory: false,
|
|
408
|
+
}, children: children })) }, option._id));
|
|
409
|
+
}) }));
|
|
410
|
+
});
|
|
411
|
+
/**
|
|
412
|
+
* Container for product modifier system.
|
|
413
|
+
* Does not render when there are no modifiers.
|
|
414
|
+
*
|
|
415
|
+
* @component
|
|
416
|
+
* @example
|
|
417
|
+
* ```tsx
|
|
418
|
+
* // Default usage
|
|
419
|
+
* <Product.Modifiers>
|
|
420
|
+
* <Product.ModifierOptions>
|
|
421
|
+
* <Product.ModifierOptionRepeater>
|
|
422
|
+
* <Option.Name className="text-lg font-medium mb-3" />
|
|
423
|
+
* <Option.Choices>
|
|
424
|
+
* <Option.ChoiceRepeater>
|
|
425
|
+
* <Choice.Text className="px-4 py-2 border rounded-lg" />
|
|
426
|
+
* <Choice.Color className="w-10 h-10 rounded-full border-4" />
|
|
427
|
+
* <Choice.FreeText className="w-full p-3 border rounded-lg resize-none" />
|
|
428
|
+
* </Option.ChoiceRepeater>
|
|
429
|
+
* </Option.Choices>
|
|
430
|
+
* </Product.ModifierOptionRepeater>
|
|
431
|
+
* </Product.ModifierOptions>
|
|
432
|
+
* </Product.Modifiers>
|
|
433
|
+
*
|
|
434
|
+
* // asChild with primitive
|
|
435
|
+
* <Product.Modifiers asChild>
|
|
436
|
+
* <section className="modifier-section">
|
|
437
|
+
* <Product.ModifierOptions>
|
|
438
|
+
* // modifier options
|
|
439
|
+
* </Product.ModifierOptions>
|
|
440
|
+
* </section>
|
|
441
|
+
* </Product.Modifiers>
|
|
442
|
+
*
|
|
443
|
+
* // asChild with react component
|
|
444
|
+
* <Product.Modifiers asChild>
|
|
445
|
+
* {React.forwardRef(({hasModifiers, ...props}, ref) => (
|
|
446
|
+
* <section ref={ref} {...props} className="modifier-section">
|
|
447
|
+
* {hasModifiers && <h3>Customize Your Product</h3>}
|
|
448
|
+
* {props.children}
|
|
449
|
+
* </section>
|
|
450
|
+
* ))}
|
|
451
|
+
* </Product.Modifiers>
|
|
452
|
+
* ```
|
|
453
|
+
*/
|
|
454
|
+
export const Modifiers = React.forwardRef((props, ref) => {
|
|
455
|
+
const { asChild, children } = props;
|
|
456
|
+
return (_jsx(ProductModifiers.Modifiers, { children: ({ hasModifiers, modifiers }) => {
|
|
457
|
+
if (!hasModifiers)
|
|
458
|
+
return null;
|
|
459
|
+
const contextValue = {
|
|
460
|
+
hasModifiers,
|
|
461
|
+
modifiers,
|
|
462
|
+
};
|
|
463
|
+
const attributes = {
|
|
464
|
+
'data-testid': TestIds.productModifiers,
|
|
465
|
+
};
|
|
466
|
+
const content = (_jsx(ModifiersContext.Provider, { value: contextValue, children: typeof children === 'function'
|
|
467
|
+
? null
|
|
468
|
+
: children }));
|
|
469
|
+
if (asChild) {
|
|
470
|
+
const rendered = renderAsChild({
|
|
471
|
+
children,
|
|
472
|
+
props: { hasModifiers },
|
|
473
|
+
ref,
|
|
474
|
+
content,
|
|
475
|
+
attributes,
|
|
476
|
+
});
|
|
477
|
+
if (rendered)
|
|
478
|
+
return rendered;
|
|
479
|
+
}
|
|
480
|
+
return (_jsx("div", { ...attributes, ref: ref, children: content }));
|
|
481
|
+
} }));
|
|
482
|
+
});
|
|
483
|
+
/**
|
|
484
|
+
* Component that provides access to modifier options.
|
|
485
|
+
*
|
|
486
|
+
* @component
|
|
487
|
+
* @example
|
|
488
|
+
* ```tsx
|
|
489
|
+
* // Default usage
|
|
490
|
+
* <Product.ModifierOptions emptyState={<div>No options available</div>}>
|
|
491
|
+
* <Product.ModifierOptionRepeater>
|
|
492
|
+
* <Option.Name />
|
|
493
|
+
* <Option.Choices>
|
|
494
|
+
* <Option.ChoiceRepeater>
|
|
495
|
+
* <Choice.Text />
|
|
496
|
+
* <Choice.Color />
|
|
497
|
+
* <Choice.FreeText />
|
|
498
|
+
* </Option.ChoiceRepeater>
|
|
499
|
+
* </Option.Choices>
|
|
500
|
+
* </Product.ModifierOptionRepeater>
|
|
501
|
+
* </Product.ModifierOptions>
|
|
502
|
+
*
|
|
503
|
+
* // Simple container usage
|
|
504
|
+
* <Product.ModifierOptions emptyState={<div>No options</div>}>
|
|
505
|
+
* <div className="options-container">
|
|
506
|
+
* <Product.ModifierOptionRepeater>
|
|
507
|
+
* // option content
|
|
508
|
+
* </Product.ModifierOptionRepeater>
|
|
509
|
+
* </div>
|
|
510
|
+
* </Product.ModifierOptions>
|
|
511
|
+
* ```
|
|
512
|
+
*/
|
|
513
|
+
export const ModifierOptions = React.forwardRef((props, ref) => {
|
|
514
|
+
const { children, emptyState } = props;
|
|
515
|
+
const { hasModifiers } = useModifiersContext();
|
|
516
|
+
if (!hasModifiers) {
|
|
517
|
+
return emptyState || null;
|
|
518
|
+
}
|
|
519
|
+
const attributes = {
|
|
520
|
+
'data-testid': TestIds.productModifierOptions,
|
|
521
|
+
};
|
|
522
|
+
return (_jsx("div", { ...attributes, ref: ref, children: children }));
|
|
523
|
+
});
|
|
524
|
+
/**
|
|
525
|
+
* Repeater component that renders children for each modifier option.
|
|
526
|
+
*
|
|
527
|
+
* @component
|
|
528
|
+
*/
|
|
529
|
+
export const ModifierOptionRepeater = React.forwardRef((props, _ref) => {
|
|
530
|
+
const { children, allowedTypes = ['color', 'text', 'free-text'] } = props;
|
|
531
|
+
const { hasModifiers, modifiers } = useModifiersContext();
|
|
532
|
+
if (!hasModifiers)
|
|
533
|
+
return null;
|
|
534
|
+
return (_jsx(_Fragment, { children: modifiers.map((modifier) => {
|
|
535
|
+
return (_jsx(ProductModifiers.Modifier, { modifier: modifier, children: (modifierData) => (_jsx(Option.Root, { option: {
|
|
536
|
+
...modifierData,
|
|
537
|
+
}, allowedTypes: allowedTypes, children: children })) }, modifier._id));
|
|
538
|
+
}) }));
|
|
539
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useService } from
|
|
2
|
-
import { BuyNowServiceDefinition } from
|
|
1
|
+
import { useService } from '@wix/services-manager-react';
|
|
2
|
+
import { BuyNowServiceDefinition } from '../../services/buy-now-service.js';
|
|
3
3
|
/**
|
|
4
4
|
* A headless component that provides buy now functionality using the render props pattern.
|
|
5
5
|
*
|