pb-sxp-ui 1.20.26 → 1.20.27

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 (42) hide show
  1. package/dist/index.cjs +292 -395
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.css +355 -291
  4. package/dist/index.js +292 -395
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.min.cjs +6 -6
  7. package/dist/index.min.cjs.map +1 -1
  8. package/dist/index.min.js +6 -6
  9. package/dist/index.min.js.map +1 -1
  10. package/dist/pb-ui.js +292 -395
  11. package/dist/pb-ui.js.map +1 -1
  12. package/dist/pb-ui.min.js +6 -6
  13. package/dist/pb-ui.min.js.map +1 -1
  14. package/es/core/components/StructurePage/index.d.ts +4 -0
  15. package/es/core/components/StructurePage/index.js +8 -1
  16. package/es/core/components/SxpPageRender/Modal/index.d.ts +1 -0
  17. package/es/core/components/SxpPageRender/Modal/index.js +3 -3
  18. package/es/core/components/SxpPageRender/index.d.ts +1 -0
  19. package/es/core/components/SxpPageRender/typing.d.ts +1 -0
  20. package/es/materials/sxp/popup/AddToCart/index.d.ts +1 -27
  21. package/es/materials/sxp/popup/AddToCart/index.js +117 -173
  22. package/es/materials/sxp/popup/AddToCart/index.new.d.ts +8 -0
  23. package/es/materials/sxp/popup/AddToCart/index.new.js +174 -0
  24. package/es/materials/sxp/popup/AddToCart/index.old.d.ts +33 -0
  25. package/es/materials/sxp/popup/AddToCart/index.old.js +299 -0
  26. package/es/materials/sxp/popup/AddToCart/material.js +1 -54
  27. package/es/materials/sxp/popup/CommodityDetailDiroNew/index.js +48 -53
  28. package/lib/core/components/StructurePage/index.d.ts +4 -0
  29. package/lib/core/components/StructurePage/index.js +8 -1
  30. package/lib/core/components/SxpPageRender/Modal/index.d.ts +1 -0
  31. package/lib/core/components/SxpPageRender/Modal/index.js +3 -3
  32. package/lib/core/components/SxpPageRender/index.d.ts +1 -0
  33. package/lib/core/components/SxpPageRender/typing.d.ts +1 -0
  34. package/lib/materials/sxp/popup/AddToCart/index.d.ts +1 -27
  35. package/lib/materials/sxp/popup/AddToCart/index.js +115 -171
  36. package/lib/materials/sxp/popup/AddToCart/index.new.d.ts +8 -0
  37. package/lib/materials/sxp/popup/AddToCart/index.new.js +176 -0
  38. package/lib/materials/sxp/popup/AddToCart/index.old.d.ts +33 -0
  39. package/lib/materials/sxp/popup/AddToCart/index.old.js +301 -0
  40. package/lib/materials/sxp/popup/AddToCart/material.js +1 -54
  41. package/lib/materials/sxp/popup/CommodityDetailDiroNew/index.js +48 -53
  42. package/package.json +1 -1
@@ -0,0 +1,174 @@
1
+ import { __awaiter } from "tslib";
2
+ import React, { useState, useEffect, useCallback } from 'react';
3
+ import { useSxpDataSource } from '../../../../core/hooks';
4
+ import './index.less';
5
+ const AddToCartPopup = ({ isActive = true, onClose }) => {
6
+ var _a, _b, _c, _d, _e, _f, _g;
7
+ const { popupDetailData, globalConfig } = useSxpDataSource();
8
+ const [productData, setProductData] = useState(null);
9
+ const [selectedOptions, setSelectedOptions] = useState({});
10
+ const [selectedVariant, setSelectedVariant] = useState(null);
11
+ const [quantity, setQuantity] = useState(1);
12
+ const [loading, setLoading] = useState(true);
13
+ const [error, setError] = useState(null);
14
+ const data = popupDetailData;
15
+ const product = (_e = (_b = (_a = data === null || data === void 0 ? void 0 : data.video) === null || _a === void 0 ? void 0 : _a.bindProduct) !== null && _b !== void 0 ? _b : (_d = (_c = data === null || data === void 0 ? void 0 : data.video) === null || _c === void 0 ? void 0 : _c.bindProducts) === null || _d === void 0 ? void 0 : _d[0]) !== null && _e !== void 0 ? _e : data === null || data === void 0 ? void 0 : data.product;
16
+ const shopifyConfig = window.__SHOPIFY_CONFIG__;
17
+ const shopifyDomain = (globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.shopifyDomain) || (shopifyConfig === null || shopifyConfig === void 0 ? void 0 : shopifyConfig.domain) || 'dev-store-749237498237498636.myshopify.com';
18
+ const storefrontToken = (globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.storefrontAccessToken) || (shopifyConfig === null || shopifyConfig === void 0 ? void 0 : shopifyConfig.storefrontAccessToken) || '77d894c490f79430ce7bd0a7efdff6b7';
19
+ const productId = (product === null || product === void 0 ? void 0 : product.shopifyId) || (product === null || product === void 0 ? void 0 : product.itemId) || '';
20
+ const fetchProductData = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
21
+ if (!productId || !shopifyDomain || !storefrontToken) {
22
+ setLoading(false);
23
+ return;
24
+ }
25
+ setLoading(true);
26
+ setError(null);
27
+ try {
28
+ const query = `
29
+ query getProduct($id: ID!) {
30
+ product(id: $id) {
31
+ id
32
+ title
33
+ images(first: 10) {
34
+ edges {
35
+ node {
36
+ url
37
+ }
38
+ }
39
+ }
40
+ options {
41
+ name
42
+ values
43
+ }
44
+ variants(first: 100) {
45
+ edges {
46
+ node {
47
+ id
48
+ title
49
+ availableForSale
50
+ price {
51
+ amount
52
+ currencyCode
53
+ }
54
+ image {
55
+ url
56
+ }
57
+ selectedOptions {
58
+ name
59
+ value
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+ `;
67
+ const fullProductId = productId.startsWith('gid://') ? productId : `gid://shopify/Product/${productId}`;
68
+ const response = yield fetch(`https://${shopifyDomain}/api/2024-01/graphql.json`, {
69
+ method: 'POST',
70
+ headers: {
71
+ 'Content-Type': 'application/json',
72
+ 'X-Shopify-Storefront-Access-Token': storefrontToken
73
+ },
74
+ body: JSON.stringify({
75
+ query,
76
+ variables: { id: fullProductId }
77
+ })
78
+ });
79
+ const result = yield response.json();
80
+ if (result.errors) {
81
+ throw new Error(result.errors[0].message);
82
+ }
83
+ setProductData(result.data.product);
84
+ }
85
+ catch (err) {
86
+ setError(err instanceof Error ? err.message : 'Failed to load product');
87
+ console.error('[AddToCartPopup] 加载失败:', err);
88
+ }
89
+ finally {
90
+ setLoading(false);
91
+ }
92
+ }), [productId, shopifyDomain, storefrontToken]);
93
+ useEffect(() => {
94
+ if (isActive) {
95
+ fetchProductData();
96
+ }
97
+ }, [isActive, fetchProductData]);
98
+ useEffect(() => {
99
+ if (!productData)
100
+ return;
101
+ const variants = productData.variants.edges.map(edge => edge.node);
102
+ const optionsCount = productData.options.length;
103
+ const selectedCount = Object.keys(selectedOptions).length;
104
+ if (selectedCount === 0 || selectedCount < optionsCount) {
105
+ setSelectedVariant(null);
106
+ return;
107
+ }
108
+ const matchedVariant = variants.find(variant => {
109
+ return variant.selectedOptions.every(option => {
110
+ return selectedOptions[option.name] === option.value;
111
+ });
112
+ });
113
+ setSelectedVariant(matchedVariant || null);
114
+ }, [selectedOptions, productData]);
115
+ const handleOptionSelect = (optionName, value) => {
116
+ setSelectedOptions(prev => (Object.assign(Object.assign({}, prev), { [optionName]: value })));
117
+ };
118
+ const handleAddToCart = () => {
119
+ if (!selectedVariant) {
120
+ alert('Please select all options');
121
+ return;
122
+ }
123
+ const variantId = selectedVariant.id.split('/').pop();
124
+ const checkoutUrl = `https://${shopifyDomain}/cart/${variantId}:${quantity}`;
125
+ window.location.href = checkoutUrl;
126
+ };
127
+ const totalPrice = selectedVariant
128
+ ? (parseFloat(selectedVariant.price.amount) * quantity).toFixed(2)
129
+ : '0.00';
130
+ const currency = (selectedVariant === null || selectedVariant === void 0 ? void 0 : selectedVariant.price.currencyCode) || 'USD';
131
+ if (loading) {
132
+ return (React.createElement("div", { className: "add-to-cart-popup" },
133
+ React.createElement("div", { className: "loading" }, "Loading...")));
134
+ }
135
+ if (error) {
136
+ return (React.createElement("div", { className: "add-to-cart-popup" },
137
+ React.createElement("div", { className: "error" }, error)));
138
+ }
139
+ if (!productData) {
140
+ return null;
141
+ }
142
+ const mainImage = ((_f = productData.images.edges[0]) === null || _f === void 0 ? void 0 : _f.node.url) || '';
143
+ const variantImage = ((_g = selectedVariant === null || selectedVariant === void 0 ? void 0 : selectedVariant.image) === null || _g === void 0 ? void 0 : _g.url) || mainImage;
144
+ return (React.createElement("div", { className: "add-to-cart-popup" },
145
+ React.createElement("div", { className: "product-header" },
146
+ React.createElement("img", { src: mainImage, alt: productData.title, className: "product-thumb" }),
147
+ React.createElement("div", { className: "product-title" }, productData.title),
148
+ onClose && (React.createElement("button", { className: "close-btn", onClick: onClose }, "\u00D7"))),
149
+ React.createElement("div", { className: "variant-detail" },
150
+ React.createElement("div", { className: "variant-image-container" },
151
+ React.createElement("img", { src: variantImage, alt: "Selected variant", className: "variant-image" })),
152
+ React.createElement("div", { className: "variant-info" },
153
+ React.createElement("div", { className: "variant-specs" }, Object.keys(selectedOptions).length > 0 ? (Object.entries(selectedOptions).map(([key, value]) => (React.createElement("span", { key: key, className: "spec-item" }, value)))) : (React.createElement("span", { className: "spec-placeholder" }, "Please select options"))),
154
+ React.createElement("div", { className: "variant-price-row" },
155
+ React.createElement("div", { className: "price" },
156
+ "$",
157
+ totalPrice),
158
+ React.createElement("div", { className: "quantity-selector" },
159
+ React.createElement("button", { className: "qty-btn", onClick: () => setQuantity(Math.max(1, quantity - 1)), disabled: quantity <= 1 }, "\u2212"),
160
+ React.createElement("span", { className: "qty-value" }, quantity),
161
+ React.createElement("button", { className: "qty-btn", onClick: () => setQuantity(quantity + 1) }, "+"))))),
162
+ React.createElement("div", { className: "variant-options" }, productData.options.map(option => (React.createElement("div", { key: option.name, className: "option-group" },
163
+ React.createElement("div", { className: "option-label" }, option.name),
164
+ React.createElement("div", { className: "option-values" }, option.values.map(value => {
165
+ const isAvailable = productData.variants.edges.some(({ node: variant }) => {
166
+ const hasThisOption = variant.selectedOptions.some(opt => opt.name === option.name && opt.value === value);
167
+ return hasThisOption && variant.availableForSale;
168
+ });
169
+ const isSelected = selectedOptions[option.name] === value;
170
+ return (React.createElement("button", { key: value, className: `option-btn ${isSelected ? 'selected' : ''} ${!isAvailable ? 'disabled' : ''}`, onClick: () => isAvailable && handleOptionSelect(option.name, value), disabled: !isAvailable }, value));
171
+ })))))),
172
+ React.createElement("button", { className: "add-to-cart-btn", onClick: handleAddToCart, disabled: !selectedVariant }, "Add To Cart")));
173
+ };
174
+ export default AddToCartPopup;
@@ -0,0 +1,33 @@
1
+ import { FC, CSSProperties } from 'react';
2
+ import './index.less';
3
+ export interface IAddToCartPopupProps {
4
+ style?: CSSProperties;
5
+ isActive?: boolean;
6
+ index?: number;
7
+ shopifyDomain?: string;
8
+ storefrontAccessToken?: string;
9
+ variantStyles?: {
10
+ title?: CSSProperties;
11
+ price?: CSSProperties;
12
+ option?: CSSProperties;
13
+ selectedOption?: CSSProperties;
14
+ };
15
+ buttonStyle?: CSSProperties;
16
+ quantityStyle?: CSSProperties;
17
+ texts?: {
18
+ addToCart?: string;
19
+ selectOptions?: string;
20
+ loading?: string;
21
+ error?: string;
22
+ color?: string;
23
+ size?: string;
24
+ material?: string;
25
+ style?: string;
26
+ };
27
+ popupBg?: {
28
+ horizontalMargin?: number;
29
+ bottomMargin?: number;
30
+ };
31
+ }
32
+ declare const AddToCartPopup: FC<IAddToCartPopupProps>;
33
+ export default AddToCartPopup;
@@ -0,0 +1,299 @@
1
+ import { __awaiter, __rest } from "tslib";
2
+ import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
3
+ import { useSxpDataSource } from '../../../../core/hooks';
4
+ import { useEventReport } from '../../../../core/hooks/useEventReport';
5
+ import { setFontForText } from '../../../../core/utils/tool';
6
+ import './index.less';
7
+ const AddToCartPopup = (_a) => {
8
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
9
+ var { style, isActive = true, index, shopifyDomain = '', storefrontAccessToken = '', variantStyles = {}, buttonStyle = {}, quantityStyle = {}, texts = {}, popupBg = {} } = _a, props = __rest(_a, ["style", "isActive", "index", "shopifyDomain", "storefrontAccessToken", "variantStyles", "buttonStyle", "quantityStyle", "texts", "popupBg"]);
10
+ const { sxpParameter, popupDetailData, isPreview, bffFbReport, globalConfig } = useSxpDataSource();
11
+ const { jumpToWeb } = useEventReport();
12
+ const curTimeRef = useRef(null);
13
+ const [productData, setProductData] = useState(null);
14
+ const [selectedOptions, setSelectedOptions] = useState({});
15
+ const [selectedVariant, setSelectedVariant] = useState(null);
16
+ const [quantity, setQuantity] = useState(1);
17
+ const [loading, setLoading] = useState(true);
18
+ const [error, setError] = useState(null);
19
+ const data = popupDetailData;
20
+ const product = (_f = (_c = (_b = data === null || data === void 0 ? void 0 : data.video) === null || _b === void 0 ? void 0 : _b.bindProduct) !== null && _c !== void 0 ? _c : (_e = (_d = data === null || data === void 0 ? void 0 : data.video) === null || _d === void 0 ? void 0 : _d.bindProducts) === null || _e === void 0 ? void 0 : _e[0]) !== null && _f !== void 0 ? _f : data === null || data === void 0 ? void 0 : data.product;
21
+ const cta = product === null || product === void 0 ? void 0 : product.bindCta;
22
+ const position = (_h = (_g = popupDetailData === null || popupDetailData === void 0 ? void 0 : popupDetailData.index) !== null && _g !== void 0 ? _g : index) !== null && _h !== void 0 ? _h : 0;
23
+ console.log('[AddToCartPopup] 组件挂载,数据:', {
24
+ popupDetailData,
25
+ 'video.bindProduct': (_j = data === null || data === void 0 ? void 0 : data.video) === null || _j === void 0 ? void 0 : _j.bindProduct,
26
+ 'video.bindProducts[0]': (_l = (_k = data === null || data === void 0 ? void 0 : data.video) === null || _k === void 0 ? void 0 : _k.bindProducts) === null || _l === void 0 ? void 0 : _l[0],
27
+ 'data.product': data === null || data === void 0 ? void 0 : data.product,
28
+ product,
29
+ isActive
30
+ });
31
+ const shopifyConfig = window.__SHOPIFY_CONFIG__;
32
+ const finalShopifyDomain = shopifyDomain ||
33
+ (globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.shopifyDomain) ||
34
+ (shopifyConfig === null || shopifyConfig === void 0 ? void 0 : shopifyConfig.domain) ||
35
+ 'dev-store-749237498237498636.myshopify.com';
36
+ const finalStorefrontToken = storefrontAccessToken ||
37
+ (globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.storefrontAccessToken) ||
38
+ (shopifyConfig === null || shopifyConfig === void 0 ? void 0 : shopifyConfig.storefrontAccessToken) ||
39
+ '77d894c490f79430ce7bd0a7efdff6b7';
40
+ const productId = (product === null || product === void 0 ? void 0 : product.shopifyId) || (product === null || product === void 0 ? void 0 : product.itemId) || '';
41
+ console.log('[AddToCartPopup] Shopify 配置:', {
42
+ productId,
43
+ finalShopifyDomain,
44
+ hasToken: !!finalStorefrontToken,
45
+ shopifyConfig
46
+ });
47
+ const finalTexts = {
48
+ addToCart: texts.addToCart || 'Add to Cart',
49
+ selectOptions: texts.selectOptions || 'Please select options',
50
+ loading: texts.loading || 'Loading...',
51
+ error: texts.error || 'Failed to load product',
52
+ color: texts.color || 'Color',
53
+ size: texts.size || 'Size',
54
+ material: texts.material || 'Material',
55
+ style: texts.style || 'Style'
56
+ };
57
+ const fetchProductData = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
58
+ var _r;
59
+ if (!productId || !finalShopifyDomain || !finalStorefrontToken) {
60
+ console.log('[AddToCartPopup] 缺少必要配置:', {
61
+ productId,
62
+ shopifyDomain: finalShopifyDomain,
63
+ hasToken: !!finalStorefrontToken
64
+ });
65
+ setLoading(false);
66
+ return;
67
+ }
68
+ console.log('[AddToCartPopup] 开始加载商品数据:', {
69
+ productId,
70
+ shopifyDomain: finalShopifyDomain
71
+ });
72
+ setLoading(true);
73
+ setError(null);
74
+ try {
75
+ const query = `
76
+ query getProduct($id: ID!) {
77
+ product(id: $id) {
78
+ id
79
+ title
80
+ images(first: 10) {
81
+ edges {
82
+ node {
83
+ url
84
+ }
85
+ }
86
+ }
87
+ options {
88
+ name
89
+ values
90
+ }
91
+ variants(first: 100) {
92
+ edges {
93
+ node {
94
+ id
95
+ title
96
+ availableForSale
97
+ price {
98
+ amount
99
+ currencyCode
100
+ }
101
+ image {
102
+ url
103
+ }
104
+ selectedOptions {
105
+ name
106
+ value
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ `;
114
+ const formattedProductId = productId.startsWith('gid://')
115
+ ? productId
116
+ : `gid://shopify/Product/${productId}`;
117
+ console.log('[AddToCartPopup] 使用的 Product ID:', formattedProductId);
118
+ const response = yield fetch(`https://${finalShopifyDomain}/api/2024-01/graphql.json`, {
119
+ method: 'POST',
120
+ headers: {
121
+ 'Content-Type': 'application/json',
122
+ 'X-Shopify-Storefront-Access-Token': finalStorefrontToken
123
+ },
124
+ body: JSON.stringify({
125
+ query,
126
+ variables: { id: formattedProductId }
127
+ })
128
+ });
129
+ if (!response.ok) {
130
+ throw new Error(`HTTP ${response.status}`);
131
+ }
132
+ const result = yield response.json();
133
+ if (result.errors) {
134
+ console.error('[AddToCartPopup] GraphQL 错误:', result.errors);
135
+ throw new Error(result.errors[0].message);
136
+ }
137
+ if (!((_r = result.data) === null || _r === void 0 ? void 0 : _r.product)) {
138
+ console.error('[AddToCartPopup] 未找到商品');
139
+ throw new Error('Product not found');
140
+ }
141
+ console.log('[AddToCartPopup] 商品数据加载成功:', result.data.product.title);
142
+ setProductData(result.data.product);
143
+ }
144
+ catch (err) {
145
+ const errorMessage = err instanceof Error ? err.message : finalTexts.error;
146
+ setError(errorMessage);
147
+ console.error('[AddToCartPopup] 加载失败:', err);
148
+ }
149
+ finally {
150
+ setLoading(false);
151
+ }
152
+ }), [productId, finalShopifyDomain, finalStorefrontToken, finalTexts.error]);
153
+ useEffect(() => {
154
+ if (isActive) {
155
+ fetchProductData();
156
+ }
157
+ }, [isActive, fetchProductData]);
158
+ useEffect(() => {
159
+ if (!productData)
160
+ return;
161
+ const variants = productData.variants.edges.map(edge => edge.node);
162
+ const optionsCount = productData.options.length;
163
+ const selectedCount = Object.keys(selectedOptions).length;
164
+ if (selectedCount === 0 || selectedCount < optionsCount) {
165
+ setSelectedVariant(null);
166
+ return;
167
+ }
168
+ const matchedVariant = variants.find(variant => {
169
+ return variant.selectedOptions.every(option => selectedOptions[option.name] === option.value);
170
+ });
171
+ setSelectedVariant(matchedVariant || null);
172
+ setQuantity(1);
173
+ }, [selectedOptions, productData]);
174
+ const handleOptionSelect = useCallback((optionName, value) => {
175
+ setSelectedOptions(prev => {
176
+ const newOptions = Object.assign({}, prev);
177
+ if (newOptions[optionName] === value) {
178
+ delete newOptions[optionName];
179
+ }
180
+ else {
181
+ newOptions[optionName] = value;
182
+ }
183
+ return newOptions;
184
+ });
185
+ }, []);
186
+ const handleQuantityChange = useCallback((delta) => {
187
+ setQuantity(prev => {
188
+ var _a;
189
+ const newQuantity = prev + delta;
190
+ const maxQuantity = (_a = selectedVariant === null || selectedVariant === void 0 ? void 0 : selectedVariant.quantityAvailable) !== null && _a !== void 0 ? _a : 999;
191
+ return Math.max(1, Math.min(newQuantity, maxQuantity));
192
+ });
193
+ }, [selectedVariant]);
194
+ const isOptionValueAvailable = useCallback((optionName, value) => {
195
+ if (!productData)
196
+ return false;
197
+ const variants = productData.variants.edges.map(edge => edge.node);
198
+ const tempOptions = Object.assign(Object.assign({}, selectedOptions), { [optionName]: value });
199
+ return variants.some(variant => {
200
+ const matches = variant.selectedOptions.every(option => !tempOptions[option.name] || tempOptions[option.name] === option.value);
201
+ const hasStock = variant.quantityAvailable === null || variant.quantityAvailable > 0;
202
+ return matches && variant.availableForSale && hasStock;
203
+ });
204
+ }, [productData, selectedOptions]);
205
+ const handleAddToCart = useCallback(() => {
206
+ var _a;
207
+ if (!selectedVariant || quantity === 0)
208
+ return;
209
+ const variantId = selectedVariant.id.split('/').pop();
210
+ const cartUrl = `https://${finalShopifyDomain}/cart/add?id=${variantId}&quantity=${quantity}`;
211
+ console.log('[AddToCartPopup] 加购:', {
212
+ variantId,
213
+ quantity,
214
+ cartUrl
215
+ });
216
+ bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
217
+ eventName: 'AddToCart',
218
+ product: product ? [product] : undefined,
219
+ contentType: 'product',
220
+ data,
221
+ position,
222
+ content_id: (_a = product === null || product === void 0 ? void 0 : product.itemId) !== null && _a !== void 0 ? _a : '',
223
+ value: parseFloat(selectedVariant.price.amount) * quantity,
224
+ currency: selectedVariant.price.currencyCode,
225
+ contents: [{
226
+ id: variantId,
227
+ quantity
228
+ }]
229
+ });
230
+ window.location.href = cartUrl;
231
+ }, [selectedVariant, quantity, finalShopifyDomain, bffFbReport, product, data, position]);
232
+ const totalPrice = useMemo(() => {
233
+ if (!selectedVariant)
234
+ return null;
235
+ const price = parseFloat(selectedVariant.price.amount);
236
+ const total = price * quantity;
237
+ return total.toFixed(2);
238
+ }, [selectedVariant, quantity]);
239
+ useEffect(() => {
240
+ const initTime = () => {
241
+ curTimeRef.current = new Date();
242
+ };
243
+ initTime();
244
+ window.addEventListener('pageshow', initTime);
245
+ return () => {
246
+ window.removeEventListener('pageshow', initTime);
247
+ };
248
+ }, []);
249
+ if (loading) {
250
+ return (React.createElement("div", { className: "add-to-cart-popup-loading", style: style },
251
+ React.createElement("div", null, finalTexts.loading)));
252
+ }
253
+ if (error || !productData) {
254
+ return (React.createElement("div", { className: "add-to-cart-popup-error", style: style },
255
+ React.createElement("div", null,
256
+ finalTexts.error,
257
+ ": ",
258
+ error || 'Product not found')));
259
+ }
260
+ const mainImage = ((_m = selectedVariant === null || selectedVariant === void 0 ? void 0 : selectedVariant.image) === null || _m === void 0 ? void 0 : _m.url) || ((_o = productData.images.edges[0]) === null || _o === void 0 ? void 0 : _o.node.url) || ((_p = product === null || product === void 0 ? void 0 : product.homePage) === null || _p === void 0 ? void 0 : _p[0]) || '';
261
+ const hasAllOptionsSelected = productData.options.length === Object.keys(selectedOptions).length;
262
+ const isAddToCartDisabled = !selectedVariant || quantity === 0;
263
+ return (React.createElement("div", Object.assign({ className: "add-to-cart-popup-container", style: style }, props),
264
+ React.createElement("div", { className: "variant-detail-section" },
265
+ React.createElement("div", { className: "variant-image-wrapper" },
266
+ React.createElement("img", { src: mainImage, alt: productData.title, className: "variant-image" })),
267
+ React.createElement("div", { className: "variant-info-wrapper" },
268
+ React.createElement("h2", { className: "product-title-text", style: variantStyles.title, dangerouslySetInnerHTML: {
269
+ __html: setFontForText(productData.title, variantStyles.title)
270
+ } }),
271
+ selectedVariant && (React.createElement(React.Fragment, null,
272
+ React.createElement("div", { className: "selected-options-tags" }, selectedVariant.selectedOptions.map(option => (React.createElement("span", { key: option.name, className: "option-tag", style: variantStyles.selectedOption },
273
+ option.name,
274
+ ": ",
275
+ option.value)))),
276
+ React.createElement("div", { className: "price-display" },
277
+ React.createElement("span", { className: "price-value", style: variantStyles.price, dangerouslySetInnerHTML: {
278
+ __html: setFontForText(`${selectedVariant.price.currencyCode} $${totalPrice}`, variantStyles.price)
279
+ } })),
280
+ React.createElement("div", { className: "quantity-selector-wrapper", style: quantityStyle },
281
+ React.createElement("button", { className: "quantity-btn quantity-decrease", onClick: () => handleQuantityChange(-1), disabled: quantity <= 1, "aria-label": "Decrease quantity" }, "-"),
282
+ React.createElement("input", { type: "number", value: quantity, readOnly: true, className: "quantity-input-field", "aria-label": "Quantity" }),
283
+ React.createElement("button", { className: "quantity-btn quantity-increase", onClick: () => handleQuantityChange(1), disabled: quantity >= ((_q = selectedVariant.quantityAvailable) !== null && _q !== void 0 ? _q : 999), "aria-label": "Increase quantity" }, "+")))),
284
+ !hasAllOptionsSelected && (React.createElement("div", { className: "no-selection-hint", style: variantStyles.option }, finalTexts.selectOptions)))),
285
+ React.createElement("div", { className: "variant-options-section" }, productData.options.map(option => (React.createElement("div", { key: option.name, className: "option-group-wrapper" },
286
+ React.createElement("h3", { className: "option-group-name", style: variantStyles.option, dangerouslySetInnerHTML: {
287
+ __html: setFontForText(option.name, variantStyles.option)
288
+ } }),
289
+ React.createElement("div", { className: "option-values-grid" }, option.values.map(value => {
290
+ const isSelected = selectedOptions[option.name] === value;
291
+ const isAvailable = isOptionValueAvailable(option.name, value);
292
+ return (React.createElement("button", { key: value, className: `option-value-button ${isSelected ? 'selected' : ''} ${!isAvailable ? 'disabled' : ''}`, onClick: () => isAvailable && handleOptionSelect(option.name, value), disabled: !isAvailable, "aria-label": `${option.name}: ${value}`, "aria-pressed": isSelected }, value));
293
+ })))))),
294
+ React.createElement("button", { className: `add-to-cart-button ${isAddToCartDisabled ? 'disabled' : ''}`, style: buttonStyle, onClick: handleAddToCart, disabled: isAddToCartDisabled, "aria-label": finalTexts.addToCart },
295
+ React.createElement("span", { dangerouslySetInnerHTML: {
296
+ __html: setFontForText(finalTexts.addToCart, buttonStyle)
297
+ } }))));
298
+ };
299
+ export default AddToCartPopup;
@@ -12,60 +12,7 @@ const AddToCartPopup = createMaterial(AddToCartPopupComponent, {
12
12
  interactionRender
13
13
  },
14
14
  defaulSetting: {
15
- props: {
16
- shopifyDomain: '',
17
- storefrontAccessToken: '',
18
- variantStyles: {
19
- title: {
20
- color: '#000',
21
- fontSize: 20,
22
- fontWeight: 600,
23
- marginBottom: 12
24
- },
25
- price: {
26
- color: '#000',
27
- fontSize: 24,
28
- fontWeight: 700,
29
- marginBottom: 16
30
- },
31
- option: {
32
- color: '#111',
33
- fontSize: 16,
34
- fontWeight: 600,
35
- marginBottom: 12
36
- },
37
- selectedOption: {
38
- fontSize: 14,
39
- color: '#374151'
40
- }
41
- },
42
- buttonStyle: {
43
- backgroundColor: '#000',
44
- color: '#fff',
45
- fontSize: 16,
46
- height: 52,
47
- fontWeight: 600,
48
- textAlign: 'center',
49
- textTransform: 'uppercase'
50
- },
51
- quantityStyle: {
52
- gap: 12
53
- },
54
- texts: {
55
- addToCart: 'Add to Cart',
56
- selectOptions: 'Please select options',
57
- loading: 'Loading...',
58
- error: 'Failed to load product',
59
- color: 'Color',
60
- size: 'Size',
61
- material: 'Material',
62
- style: 'Style'
63
- },
64
- popupBg: {
65
- horizontalMargin: 0,
66
- bottomMargin: 0
67
- }
68
- },
15
+ props: {},
69
16
  style: {}
70
17
  },
71
18
  w: 100,