@shopify/shop-minis-react 0.2.7 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/index4.js +2 -2
- package/dist/_virtual/index5.js +2 -3
- package/dist/_virtual/index5.js.map +1 -1
- package/dist/_virtual/index6.js +3 -2
- package/dist/_virtual/index6.js.map +1 -1
- package/dist/components/MinisContainer.js +10 -10
- package/dist/components/MinisContainer.js.map +1 -1
- package/dist/components/atoms/product-variant-price.js +36 -43
- package/dist/components/atoms/product-variant-price.js.map +1 -1
- package/dist/components/commerce/add-to-cart.js +70 -53
- package/dist/components/commerce/add-to-cart.js.map +1 -1
- package/dist/components/commerce/buy-now.js +75 -0
- package/dist/components/commerce/buy-now.js.map +1 -0
- package/dist/components/commerce/product-card.js +16 -17
- package/dist/components/commerce/product-card.js.map +1 -1
- package/dist/index.js +230 -230
- package/dist/{hooks/shop → internal}/useShopCartActions.js +2 -2
- package/dist/internal/useShopCartActions.js.map +1 -0
- package/dist/shop-minis-react/node_modules/.pnpm/@videojs_xhr@2.7.0/node_modules/@videojs/xhr/lib/index.js +1 -1
- package/dist/shop-minis-react/node_modules/.pnpm/mpd-parser@1.3.1/node_modules/mpd-parser/dist/mpd-parser.es.js +1 -1
- package/dist/shop-minis-react/node_modules/.pnpm/querystringify@2.2.0/node_modules/querystringify/index.js +1 -1
- package/dist/shop-minis-react/node_modules/.pnpm/simple-swizzle@0.2.2/node_modules/simple-swizzle/index.js +1 -1
- package/dist/shop-minis-react/node_modules/.pnpm/use-sync-external-store@1.5.0_react@19.1.0/node_modules/use-sync-external-store/shim/index.js +1 -1
- package/generated-hook-maps/hook-actions-map.json +0 -4
- package/package.json +2 -2
- package/src/components/MinisContainer.tsx +5 -3
- package/src/components/atoms/product-variant-price.tsx +1 -5
- package/src/components/commerce/add-to-cart.test.tsx +218 -3
- package/src/components/commerce/add-to-cart.tsx +40 -16
- package/src/components/commerce/buy-now.test.tsx +272 -0
- package/src/components/commerce/buy-now.tsx +108 -0
- package/src/components/commerce/product-card.tsx +5 -6
- package/src/components/index.ts +1 -0
- package/src/hooks/index.ts +0 -1
- package/src/{hooks/shop → internal}/useShopCartActions.ts +2 -2
- package/src/stories/AddToCart.stories.tsx +75 -10
- package/src/stories/ProductVariantPrice.stories.tsx +1 -4
- package/dist/hooks/shop/useShopCartActions.js.map +0 -1
package/dist/_virtual/index4.js
CHANGED
package/dist/_virtual/index5.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index5.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index5.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
package/dist/_virtual/index6.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index6.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index6.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
@@ -3,35 +3,35 @@ import { useState as u, useCallback as f, useEffect as p } from "react";
|
|
|
3
3
|
import { useShopActions as v } from "../internal/useShopActions.js";
|
|
4
4
|
import { injectMocks as y } from "../mocks.js";
|
|
5
5
|
import { ImagePickerProvider as h } from "../providers/ImagePickerProvider.js";
|
|
6
|
-
import { ErrorBoundary as
|
|
6
|
+
import { ErrorBoundary as E } from "./ErrorBoundary.js";
|
|
7
7
|
y();
|
|
8
8
|
function b({ children: a }) {
|
|
9
|
-
const [i,
|
|
10
|
-
async (
|
|
9
|
+
const [i, o] = u(!1), t = v(), c = f(
|
|
10
|
+
async (n) => {
|
|
11
11
|
try {
|
|
12
|
-
await
|
|
12
|
+
t && t.reportError && await t.reportError(n);
|
|
13
13
|
} catch (e) {
|
|
14
14
|
console.error("Failed to report error to app:", e);
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
|
-
[
|
|
17
|
+
[t]
|
|
18
18
|
);
|
|
19
19
|
return p(() => {
|
|
20
|
-
const
|
|
21
|
-
if (
|
|
20
|
+
const n = () => window.minisSDK ? (o(!0), !0) : !1;
|
|
21
|
+
if (n())
|
|
22
22
|
return;
|
|
23
23
|
const e = (d) => {
|
|
24
24
|
const { type: m } = JSON.parse(d.data);
|
|
25
|
-
m === "MINIS_SDK_READY" &&
|
|
25
|
+
m === "MINIS_SDK_READY" && o(!0);
|
|
26
26
|
};
|
|
27
27
|
window.addEventListener("message", e), document.addEventListener("message", e);
|
|
28
28
|
const s = setInterval(() => {
|
|
29
|
-
|
|
29
|
+
n() && clearInterval(s);
|
|
30
30
|
}, 100);
|
|
31
31
|
return () => {
|
|
32
32
|
clearInterval(s), window.removeEventListener("message", e), document.removeEventListener("message", e);
|
|
33
33
|
};
|
|
34
|
-
}, []), i ? /* @__PURE__ */ r(
|
|
34
|
+
}, []), i ? /* @__PURE__ */ r(E, { onError: c, children: /* @__PURE__ */ r(h, { children: a }) }) : /* @__PURE__ */ r("div", { className: "h-screen bg-gray-50 flex items-center justify-center", children: /* @__PURE__ */ l("div", { className: "text-center", children: [
|
|
35
35
|
/* @__PURE__ */ r("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900 mx-auto mb-4" }),
|
|
36
36
|
/* @__PURE__ */ r("p", { className: "text-gray-600", children: "Loading..." })
|
|
37
37
|
] }) });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MinisContainer.js","sources":["../../src/components/MinisContainer.tsx"],"sourcesContent":["import React, {useCallback, useEffect, useState} from 'react'\n\nimport {ReportErrorParams} from '@shopify/shop-minis-platform/actions'\n\nimport {useShopActions} from '../internal/useShopActions'\nimport {injectMocks} from '../mocks'\nimport {ImagePickerProvider} from '../providers/ImagePickerProvider'\n\nimport {ErrorBoundary} from './ErrorBoundary'\n\ninjectMocks()\n\nexport function MinisContainer({children}: {children: React.ReactNode}) {\n const [isSDKReady, setIsSDKReady] = useState(false)\n const
|
|
1
|
+
{"version":3,"file":"MinisContainer.js","sources":["../../src/components/MinisContainer.tsx"],"sourcesContent":["import React, {useCallback, useEffect, useState} from 'react'\n\nimport {ReportErrorParams} from '@shopify/shop-minis-platform/actions'\n\nimport {useShopActions} from '../internal/useShopActions'\nimport {injectMocks} from '../mocks'\nimport {ImagePickerProvider} from '../providers/ImagePickerProvider'\n\nimport {ErrorBoundary} from './ErrorBoundary'\n\ninjectMocks()\n\nexport function MinisContainer({children}: {children: React.ReactNode}) {\n const [isSDKReady, setIsSDKReady] = useState(false)\n const actions = useShopActions()\n\n const handleError = useCallback(\n async (params: ReportErrorParams) => {\n try {\n if (actions && actions.reportError) {\n await actions.reportError(params)\n }\n } catch (error) {\n // If reporting fails, at least log to console\n console.error('Failed to report error to app:', error)\n }\n },\n [actions]\n )\n\n useEffect(() => {\n // Function to check if SDK is ready\n const checkSDKReady = () => {\n if (window.minisSDK) {\n setIsSDKReady(true)\n return true\n }\n return false\n }\n\n // Check immediately\n if (checkSDKReady()) {\n return\n }\n\n // If not ready, set up a listener for the MINIS_SDK_READY event\n const handleSDKReady = (event: any) => {\n const {type} = JSON.parse(event.data)\n\n if (type === 'MINIS_SDK_READY') {\n setIsSDKReady(true)\n }\n }\n\n // Listen for the MINIS_SDK_READY event\n window.addEventListener('message', handleSDKReady)\n document.addEventListener('message', handleSDKReady)\n\n // Also poll for SDK availability as a fallback\n const pollInterval = setInterval(() => {\n if (checkSDKReady()) {\n clearInterval(pollInterval)\n }\n }, 100)\n\n // Cleanup\n return () => {\n clearInterval(pollInterval)\n window.removeEventListener('message', handleSDKReady)\n document.removeEventListener('message', handleSDKReady)\n }\n }, [])\n\n // Don't render anything until SDK is ready\n if (!isSDKReady) {\n return (\n <div className=\"h-screen bg-gray-50 flex items-center justify-center\">\n <div className=\"text-center\">\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900 mx-auto mb-4\" />\n <p className=\"text-gray-600\">Loading...</p>\n </div>\n </div>\n )\n }\n\n return (\n <ErrorBoundary onError={handleError}>\n <ImagePickerProvider>{children}</ImagePickerProvider>\n </ErrorBoundary>\n )\n}\n"],"names":["injectMocks","MinisContainer","children","isSDKReady","setIsSDKReady","useState","actions","useShopActions","handleError","useCallback","params","error","useEffect","checkSDKReady","handleSDKReady","event","type","pollInterval","ErrorBoundary","jsx","ImagePickerProvider","jsxs"],"mappings":";;;;;;AAUAA,EAAY;AAEI,SAAAC,EAAe,EAAC,UAAAC,KAAwC;AACtE,QAAM,CAACC,GAAYC,CAAa,IAAIC,EAAS,EAAK,GAC5CC,IAAUC,EAAe,GAEzBC,IAAcC;AAAA,IAClB,OAAOC,MAA8B;AAC/B,UAAA;AACE,QAAAJ,KAAWA,EAAQ,eACf,MAAAA,EAAQ,YAAYI,CAAM;AAAA,eAE3BC,GAAO;AAEN,gBAAA,MAAM,kCAAkCA,CAAK;AAAA,MAAA;AAAA,IAEzD;AAAA,IACA,CAACL,CAAO;AAAA,EACV;AA8CA,SA5CAM,EAAU,MAAM;AAEd,UAAMC,IAAgB,MAChB,OAAO,YACTT,EAAc,EAAI,GACX,MAEF;AAIT,QAAIS;AACF;AAII,UAAAC,IAAiB,CAACC,MAAe;AACrC,YAAM,EAAC,MAAAC,EAAI,IAAI,KAAK,MAAMD,EAAM,IAAI;AAEpC,MAAIC,MAAS,qBACXZ,EAAc,EAAI;AAAA,IAEtB;AAGO,WAAA,iBAAiB,WAAWU,CAAc,GACxC,SAAA,iBAAiB,WAAWA,CAAc;AAG7C,UAAAG,IAAe,YAAY,MAAM;AACrC,MAAIJ,OACF,cAAcI,CAAY;AAAA,OAE3B,GAAG;AAGN,WAAO,MAAM;AACX,oBAAcA,CAAY,GACnB,OAAA,oBAAoB,WAAWH,CAAc,GAC3C,SAAA,oBAAoB,WAAWA,CAAc;AAAA,IACxD;AAAA,EACF,GAAG,EAAE,GAGAX,sBAYFe,GAAc,EAAA,SAASV,GACtB,UAAC,gBAAAW,EAAAC,GAAA,EAAqB,UAAAlB,GAAS,EACjC,CAAA,sBAZG,OAAI,EAAA,WAAU,wDACb,UAAC,gBAAAmB,EAAA,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,IAAC,gBAAAF,EAAA,OAAA,EAAI,WAAU,4EAA4E,CAAA;AAAA,IAC1F,gBAAAA,EAAA,KAAA,EAAE,WAAU,iBAAgB,UAAU,aAAA,CAAA;AAAA,EAAA,EAAA,CACzC,EACF,CAAA;AASN;"}
|
|
@@ -1,61 +1,54 @@
|
|
|
1
|
-
import { jsx as n, jsxs as
|
|
1
|
+
import { jsx as n, jsxs as h, Fragment as d } from "react/jsx-runtime";
|
|
2
2
|
import { formatMoney as a } from "../../lib/formatMoney.js";
|
|
3
3
|
import { cn as i } from "../../lib/utils.js";
|
|
4
|
-
function
|
|
4
|
+
function N({
|
|
5
5
|
amount: r,
|
|
6
6
|
currencyCode: t,
|
|
7
7
|
compareAtPriceAmount: s,
|
|
8
8
|
compareAtPriceCurrencyCode: o,
|
|
9
9
|
currentPriceClassName: e,
|
|
10
10
|
originalPriceClassName: m,
|
|
11
|
-
|
|
12
|
-
className: f
|
|
11
|
+
className: x
|
|
13
12
|
}) {
|
|
14
13
|
if (!r || !t)
|
|
15
14
|
return null;
|
|
16
|
-
const
|
|
17
|
-
return /* @__PURE__ */ n(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
15
|
+
const f = s && s !== r, l = String(r), g = s ? String(s) : void 0;
|
|
16
|
+
return /* @__PURE__ */ n("div", { className: i("flex items-center gap-2", x), children: f ? /* @__PURE__ */ h(d, { children: [
|
|
17
|
+
/* @__PURE__ */ n(
|
|
18
|
+
"span",
|
|
19
|
+
{
|
|
20
|
+
className: i(
|
|
21
|
+
"text-sm font-semibold text-gray-900",
|
|
22
|
+
e
|
|
23
|
+
),
|
|
24
|
+
children: a(l, t)
|
|
25
|
+
}
|
|
26
|
+
),
|
|
27
|
+
/* @__PURE__ */ n(
|
|
28
|
+
"span",
|
|
29
|
+
{
|
|
30
|
+
className: i(
|
|
31
|
+
"text-sm text-gray-500 line-through",
|
|
32
|
+
m
|
|
31
33
|
),
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
className: i(
|
|
36
|
-
"text-sm text-gray-500 line-through",
|
|
37
|
-
m
|
|
38
|
-
),
|
|
39
|
-
children: a(
|
|
40
|
-
h,
|
|
41
|
-
o || t
|
|
42
|
-
)
|
|
43
|
-
}
|
|
34
|
+
children: a(
|
|
35
|
+
g,
|
|
36
|
+
o || t
|
|
44
37
|
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
)
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
] }) : /* @__PURE__ */ n(
|
|
41
|
+
"span",
|
|
42
|
+
{
|
|
43
|
+
className: i(
|
|
44
|
+
"text-sm font-semibold text-gray-900",
|
|
45
|
+
e
|
|
46
|
+
),
|
|
47
|
+
children: a(l, t)
|
|
55
48
|
}
|
|
56
|
-
);
|
|
49
|
+
) });
|
|
57
50
|
}
|
|
58
51
|
export {
|
|
59
|
-
|
|
52
|
+
N as ProductVariantPrice
|
|
60
53
|
};
|
|
61
54
|
//# sourceMappingURL=product-variant-price.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-variant-price.js","sources":["../../../src/components/atoms/product-variant-price.tsx"],"sourcesContent":["import {formatMoney} from '../../lib/formatMoney'\nimport {cn} from '../../lib/utils'\n\nexport interface ProductVariantPriceProps {\n amount: number | string\n currencyCode?: string\n compareAtPriceAmount?: number | string\n compareAtPriceCurrencyCode?: string\n currentPriceClassName?: string\n originalPriceClassName?: string\n
|
|
1
|
+
{"version":3,"file":"product-variant-price.js","sources":["../../../src/components/atoms/product-variant-price.tsx"],"sourcesContent":["import {formatMoney} from '../../lib/formatMoney'\nimport {cn} from '../../lib/utils'\n\nexport interface ProductVariantPriceProps {\n amount: number | string\n currencyCode?: string\n compareAtPriceAmount?: number | string\n compareAtPriceCurrencyCode?: string\n currentPriceClassName?: string\n originalPriceClassName?: string\n className?: string\n}\n\nexport function ProductVariantPrice({\n amount,\n currencyCode,\n compareAtPriceAmount,\n compareAtPriceCurrencyCode,\n currentPriceClassName,\n originalPriceClassName,\n className,\n}: ProductVariantPriceProps) {\n if (!amount || !currencyCode) {\n return null\n }\n\n const hasDiscount = compareAtPriceAmount && compareAtPriceAmount !== amount\n\n const amountStr = String(amount)\n const compareAtPriceAmountStr = compareAtPriceAmount\n ? String(compareAtPriceAmount)\n : undefined\n\n return (\n <div className={cn('flex items-center gap-2', className)}>\n {hasDiscount ? (\n <>\n <span\n className={cn(\n 'text-sm font-semibold text-gray-900',\n currentPriceClassName\n )}\n >\n {formatMoney(amountStr, currencyCode)}\n </span>\n <span\n className={cn(\n 'text-sm text-gray-500 line-through',\n originalPriceClassName\n )}\n >\n {formatMoney(\n compareAtPriceAmountStr!,\n compareAtPriceCurrencyCode || currencyCode\n )}\n </span>\n </>\n ) : (\n <span\n className={cn(\n 'text-sm font-semibold text-gray-900',\n currentPriceClassName\n )}\n >\n {formatMoney(amountStr, currencyCode)}\n </span>\n )}\n </div>\n )\n}\n"],"names":["ProductVariantPrice","amount","currencyCode","compareAtPriceAmount","compareAtPriceCurrencyCode","currentPriceClassName","originalPriceClassName","className","hasDiscount","amountStr","compareAtPriceAmountStr","jsx","cn","jsxs","Fragment","formatMoney"],"mappings":";;;AAaO,SAASA,EAAoB;AAAA,EAClC,QAAAC;AAAA,EACA,cAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,4BAAAC;AAAA,EACA,uBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,WAAAC;AACF,GAA6B;AACvB,MAAA,CAACN,KAAU,CAACC;AACP,WAAA;AAGH,QAAAM,IAAcL,KAAwBA,MAAyBF,GAE/DQ,IAAY,OAAOR,CAAM,GACzBS,IAA0BP,IAC5B,OAAOA,CAAoB,IAC3B;AAGF,SAAA,gBAAAQ,EAAC,SAAI,WAAWC,EAAG,2BAA2BL,CAAS,GACpD,cAEG,gBAAAM,EAAAC,GAAA,EAAA,UAAA;AAAA,IAAA,gBAAAH;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWC;AAAA,UACT;AAAA,UACAP;AAAA,QACF;AAAA,QAEC,UAAAU,EAAYN,GAAWP,CAAY;AAAA,MAAA;AAAA,IACtC;AAAA,IACA,gBAAAS;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWC;AAAA,UACT;AAAA,UACAN;AAAA,QACF;AAAA,QAEC,UAAAS;AAAA,UACCL;AAAA,UACAN,KAA8BF;AAAA,QAAA;AAAA,MAChC;AAAA,IAAA;AAAA,EACF,EAAA,CACF,IAEA,gBAAAS;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC;AAAA,QACT;AAAA,QACAP;AAAA,MACF;AAAA,MAEC,UAAAU,EAAYN,GAAWP,CAAY;AAAA,IAAA;AAAA,EAAA,GAG1C;AAEJ;"}
|
|
@@ -1,62 +1,79 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import * as
|
|
3
|
-
import { useState as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
productVariantId:
|
|
17
|
-
discountCodes:
|
|
1
|
+
import { jsx as o, jsxs as g } from "react/jsx-runtime";
|
|
2
|
+
import * as p from "react";
|
|
3
|
+
import { useState as w, useCallback as y } from "react";
|
|
4
|
+
import { useShopCartActions as k } from "../../internal/useShopCartActions.js";
|
|
5
|
+
import { cn as h } from "../../lib/utils.js";
|
|
6
|
+
import { Button as j } from "../atoms/button.js";
|
|
7
|
+
import { useShopNavigation as E } from "../../hooks/navigation/useShopNavigation.js";
|
|
8
|
+
import { useErrorToast as R } from "../../hooks/util/useErrorToast.js";
|
|
9
|
+
import { AnimatePresence as S } from "../../shop-minis-react/node_modules/.pnpm/motion@12.17.3_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/motion/dist/es/framer-motion/dist/es/components/AnimatePresence/index.js";
|
|
10
|
+
import { motion as B } from "../../shop-minis-react/node_modules/.pnpm/motion@12.17.3_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/motion/dist/es/framer-motion/dist/es/render/components/motion/proxy.js";
|
|
11
|
+
import F from "../../shop-minis-react/node_modules/.pnpm/lucide-react@0.513.0_react@19.1.0/node_modules/lucide-react/dist/esm/icons/check.js";
|
|
12
|
+
function L({
|
|
13
|
+
disabled: i = !1,
|
|
14
|
+
className: T,
|
|
15
|
+
size: v = "default",
|
|
16
|
+
productVariantId: a,
|
|
17
|
+
discountCodes: l,
|
|
18
|
+
product: x
|
|
18
19
|
}) {
|
|
19
|
-
const { addToCart:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}).catch(() => {
|
|
29
|
-
l({ message: "Failed to add to cart" });
|
|
30
|
-
}), s(!0), e.current && clearTimeout(e.current), e.current = window.setTimeout(() => {
|
|
31
|
-
s(!1);
|
|
32
|
-
}, 2e3);
|
|
33
|
-
} catch (p) {
|
|
34
|
-
s(!1), console.error("Failed to add to cart:", p);
|
|
20
|
+
const { addToCart: d } = k(), { navigateToProduct: m } = E(), [t, n] = w(!1), e = p.useRef(void 0), { id: r, referral: s, variants: C } = x ?? {}, u = C?.find(
|
|
21
|
+
(c) => c.id === a
|
|
22
|
+
)?.image?.url, { showErrorToast: f } = R(), A = y(async () => {
|
|
23
|
+
if (!i) {
|
|
24
|
+
if (r && s) {
|
|
25
|
+
m({
|
|
26
|
+
productId: r
|
|
27
|
+
});
|
|
28
|
+
return;
|
|
35
29
|
}
|
|
30
|
+
if (!t)
|
|
31
|
+
try {
|
|
32
|
+
r && a && d({
|
|
33
|
+
productId: r,
|
|
34
|
+
productVariantId: a,
|
|
35
|
+
quantity: 1,
|
|
36
|
+
discountCodes: l,
|
|
37
|
+
variantImageUrl: u
|
|
38
|
+
}).then(() => {
|
|
39
|
+
}).catch(() => {
|
|
40
|
+
f({ message: "Failed to add to cart" });
|
|
41
|
+
}), n(!0), e.current && clearTimeout(e.current), e.current = window.setTimeout(() => {
|
|
42
|
+
n(!1);
|
|
43
|
+
}, 2e3);
|
|
44
|
+
} catch (c) {
|
|
45
|
+
n(!1), console.error("Failed to add to cart:", c);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
36
48
|
}, [
|
|
49
|
+
i,
|
|
50
|
+
r,
|
|
51
|
+
s,
|
|
37
52
|
t,
|
|
38
|
-
|
|
39
|
-
c,
|
|
53
|
+
m,
|
|
40
54
|
a,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
55
|
+
d,
|
|
56
|
+
l,
|
|
57
|
+
u,
|
|
58
|
+
f
|
|
44
59
|
]);
|
|
45
|
-
|
|
60
|
+
p.useEffect(() => () => {
|
|
46
61
|
e.current && clearTimeout(e.current);
|
|
47
|
-
}, [])
|
|
48
|
-
|
|
62
|
+
}, []);
|
|
63
|
+
const N = s ? "View product" : t ? "Added to cart" : "Add to cart";
|
|
64
|
+
return /* @__PURE__ */ o(
|
|
65
|
+
j,
|
|
49
66
|
{
|
|
50
|
-
onClick:
|
|
51
|
-
disabled:
|
|
52
|
-
className:
|
|
67
|
+
onClick: A,
|
|
68
|
+
disabled: i,
|
|
69
|
+
className: h(
|
|
53
70
|
"relative overflow-hidden transition-all duration-300",
|
|
54
|
-
|
|
71
|
+
T
|
|
55
72
|
),
|
|
56
|
-
size:
|
|
57
|
-
children: /* @__PURE__ */
|
|
58
|
-
/* @__PURE__ */
|
|
59
|
-
|
|
73
|
+
size: v,
|
|
74
|
+
children: /* @__PURE__ */ g("div", { className: "relative flex items-center justify-center", children: [
|
|
75
|
+
/* @__PURE__ */ o(S, { children: t && /* @__PURE__ */ o(
|
|
76
|
+
B.div,
|
|
60
77
|
{
|
|
61
78
|
initial: { scale: 0, rotate: -180 },
|
|
62
79
|
animate: { scale: 1, rotate: 0 },
|
|
@@ -66,17 +83,17 @@ function P({
|
|
|
66
83
|
ease: [0.175, 0.885, 0.32, 1.275]
|
|
67
84
|
// bounce effect
|
|
68
85
|
},
|
|
69
|
-
className: "absolute left-
|
|
86
|
+
className: "absolute left-2",
|
|
70
87
|
style: { x: -8 },
|
|
71
|
-
children: /* @__PURE__ */
|
|
88
|
+
children: /* @__PURE__ */ o(F, { className: "size-4" })
|
|
72
89
|
}
|
|
73
90
|
) }),
|
|
74
|
-
/* @__PURE__ */
|
|
91
|
+
/* @__PURE__ */ o("span", { className: h(t && "pl-5", "transition-all duration-300"), children: N })
|
|
75
92
|
] })
|
|
76
93
|
}
|
|
77
94
|
);
|
|
78
95
|
}
|
|
79
96
|
export {
|
|
80
|
-
|
|
97
|
+
L as AddToCartButton
|
|
81
98
|
};
|
|
82
99
|
//# sourceMappingURL=add-to-cart.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add-to-cart.js","sources":["../../../src/components/commerce/add-to-cart.tsx"],"sourcesContent":["import * as React from 'react'\nimport {useState, useCallback} from 'react'\n\nimport {CheckIcon} from 'lucide-react'\nimport {motion, AnimatePresence} from 'motion/react'\n\nimport {useErrorToast,
|
|
1
|
+
{"version":3,"file":"add-to-cart.js","sources":["../../../src/components/commerce/add-to-cart.tsx"],"sourcesContent":["import * as React from 'react'\nimport {useState, useCallback} from 'react'\n\nimport {Product} from '@shopify/shop-minis-platform'\nimport {CheckIcon} from 'lucide-react'\nimport {motion, AnimatePresence} from 'motion/react'\n\nimport {useErrorToast, useShopNavigation} from '../../hooks'\nimport {useShopCartActions} from '../../internal/useShopCartActions'\nimport {cn} from '../../lib/utils'\nimport {Button} from '../atoms/button'\n\ninterface AddToCartButtonProps {\n disabled?: boolean\n className?: string\n size?: 'default' | 'sm' | 'lg'\n /**\n * The discount codes to apply to the cart.\n */\n discountCodes?: string[]\n /**\n * The GID of the product variant. E.g. `gid://shopify/ProductVariant/456`.\n */\n productVariantId: string\n\n /**\n * The product to add to the cart.\n */\n product?: Product\n}\n\nexport function AddToCartButton({\n disabled = false,\n className,\n size = 'default',\n productVariantId,\n discountCodes,\n product,\n}: AddToCartButtonProps) {\n const {addToCart} = useShopCartActions()\n const {navigateToProduct} = useShopNavigation()\n const [isAdded, setIsAdded] = useState(false)\n const timeoutRef = React.useRef<number | undefined>(undefined)\n const {id, referral, variants} = product ?? {}\n\n const variantImageUrl = variants?.find(\n variant => variant.id === productVariantId\n )?.image?.url\n\n const {showErrorToast} = useErrorToast()\n\n const handleClick = useCallback(async () => {\n if (disabled) return\n\n if (id && referral) {\n navigateToProduct({\n productId: id,\n })\n\n return\n }\n\n if (isAdded) return\n\n try {\n if (id && productVariantId) {\n addToCart({\n productId: id,\n productVariantId,\n quantity: 1,\n discountCodes,\n variantImageUrl,\n })\n .then(() => {})\n .catch(() => {\n showErrorToast({message: 'Failed to add to cart'})\n })\n }\n\n // Show success state\n setIsAdded(true)\n\n // Clear any existing timeout\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current)\n }\n\n // Reset to initial state after delay\n timeoutRef.current = window.setTimeout(() => {\n setIsAdded(false)\n }, 2000)\n } catch (error) {\n // Handle error - reset to initial state\n setIsAdded(false)\n console.error('Failed to add to cart:', error)\n }\n }, [\n disabled,\n id,\n referral,\n isAdded,\n navigateToProduct,\n productVariantId,\n addToCart,\n discountCodes,\n variantImageUrl,\n showErrorToast,\n ])\n\n // Cleanup timeout on unmount\n React.useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current)\n }\n }\n }, [])\n\n const addToCartText = isAdded ? 'Added to cart' : 'Add to cart'\n const buttonText = referral ? 'View product' : addToCartText\n\n return (\n <Button\n onClick={handleClick}\n disabled={disabled}\n className={cn(\n 'relative overflow-hidden transition-all duration-300',\n className\n )}\n size={size}\n >\n <div className=\"relative flex items-center justify-center\">\n <AnimatePresence>\n {isAdded && (\n <motion.div\n initial={{scale: 0, rotate: -180}}\n animate={{scale: 1, rotate: 0}}\n exit={{scale: 0, rotate: 180}}\n transition={{\n duration: 0.4,\n ease: [0.175, 0.885, 0.32, 1.275], // bounce effect\n }}\n className=\"absolute left-2\"\n style={{x: -8}}\n >\n <CheckIcon className=\"size-4\" />\n </motion.div>\n )}\n </AnimatePresence>\n <span className={cn(isAdded && 'pl-5', 'transition-all duration-300')}>\n {buttonText}\n </span>\n </div>\n </Button>\n )\n}\n"],"names":["AddToCartButton","disabled","className","size","productVariantId","discountCodes","product","addToCart","useShopCartActions","navigateToProduct","useShopNavigation","isAdded","setIsAdded","useState","timeoutRef","React","id","referral","variants","variantImageUrl","variant","showErrorToast","useErrorToast","handleClick","useCallback","error","buttonText","jsx","Button","cn","jsxs","AnimatePresence","motion","CheckIcon"],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
2
|
+
import { useState as h, useCallback as d } from "react";
|
|
3
|
+
import { useShopCartActions as w } from "../../internal/useShopCartActions.js";
|
|
4
|
+
import { cn as g } from "../../lib/utils.js";
|
|
5
|
+
import { Button as v } from "../atoms/button.js";
|
|
6
|
+
import { AnimatePresence as P } from "../../shop-minis-react/node_modules/.pnpm/motion@12.17.3_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/motion/dist/es/framer-motion/dist/es/components/AnimatePresence/index.js";
|
|
7
|
+
import { motion as x } from "../../shop-minis-react/node_modules/.pnpm/motion@12.17.3_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/motion/dist/es/framer-motion/dist/es/render/components/motion/proxy.js";
|
|
8
|
+
import { useShopNavigation as B } from "../../hooks/navigation/useShopNavigation.js";
|
|
9
|
+
import { useErrorToast as k } from "../../hooks/util/useErrorToast.js";
|
|
10
|
+
function I({
|
|
11
|
+
disabled: r = !1,
|
|
12
|
+
className: f,
|
|
13
|
+
size: l = "default",
|
|
14
|
+
productVariantId: i,
|
|
15
|
+
discountCode: s,
|
|
16
|
+
product: p
|
|
17
|
+
}) {
|
|
18
|
+
const { buyProduct: c } = w(), { navigateToProduct: m } = B(), [o, e] = h(!1), { id: t, referral: a } = p ?? {}, { showErrorToast: u } = k(), y = d(async () => {
|
|
19
|
+
if (!r) {
|
|
20
|
+
if (t && a) {
|
|
21
|
+
m({
|
|
22
|
+
productId: t
|
|
23
|
+
});
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (!o)
|
|
27
|
+
try {
|
|
28
|
+
t && i && (e(!0), await c({
|
|
29
|
+
productId: t,
|
|
30
|
+
productVariantId: i,
|
|
31
|
+
quantity: 1,
|
|
32
|
+
discountCode: s
|
|
33
|
+
}), e(!1));
|
|
34
|
+
} catch {
|
|
35
|
+
u({ message: "Failed to complete purchase" }), e(!1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}, [
|
|
39
|
+
r,
|
|
40
|
+
t,
|
|
41
|
+
a,
|
|
42
|
+
o,
|
|
43
|
+
m,
|
|
44
|
+
i,
|
|
45
|
+
c,
|
|
46
|
+
s,
|
|
47
|
+
u
|
|
48
|
+
]);
|
|
49
|
+
return /* @__PURE__ */ n(
|
|
50
|
+
v,
|
|
51
|
+
{
|
|
52
|
+
onClick: y,
|
|
53
|
+
disabled: r || o,
|
|
54
|
+
className: g("relative overflow-hidden", f),
|
|
55
|
+
size: l,
|
|
56
|
+
"aria-live": "polite",
|
|
57
|
+
"aria-busy": o,
|
|
58
|
+
children: /* @__PURE__ */ n(P, { mode: "wait", children: /* @__PURE__ */ n(
|
|
59
|
+
x.span,
|
|
60
|
+
{
|
|
61
|
+
initial: { opacity: 0, y: 10 },
|
|
62
|
+
animate: { opacity: 1, y: 0 },
|
|
63
|
+
exit: { opacity: 0, y: -10 },
|
|
64
|
+
transition: { duration: 0.2 },
|
|
65
|
+
children: a ? "View product" : "Buy now"
|
|
66
|
+
},
|
|
67
|
+
"text"
|
|
68
|
+
) })
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
export {
|
|
73
|
+
I as BuyNowButton
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=buy-now.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buy-now.js","sources":["../../../src/components/commerce/buy-now.tsx"],"sourcesContent":["import {useState, useCallback} from 'react'\n\nimport {Product} from '@shopify/shop-minis-platform'\nimport {motion, AnimatePresence} from 'motion/react'\n\nimport {useErrorToast, useShopNavigation} from '../../hooks'\nimport {useShopCartActions} from '../../internal/useShopCartActions'\nimport {cn} from '../../lib/utils'\nimport {Button} from '../atoms/button'\n\ninterface BuyNowButtonProps {\n disabled?: boolean\n className?: string\n size?: 'default' | 'sm' | 'lg'\n /**\n * The discount code to apply to the purchase.\n */\n discountCode?: string\n /**\n * The GID of the product variant. E.g. `gid://shopify/ProductVariant/456`.\n */\n productVariantId: string\n /**\n * The product to buy now.\n */\n product?: Product\n}\n\nexport function BuyNowButton({\n disabled = false,\n className,\n size = 'default',\n productVariantId,\n discountCode,\n product,\n}: BuyNowButtonProps) {\n const {buyProduct} = useShopCartActions()\n const {navigateToProduct} = useShopNavigation()\n const [isPurchasing, setIsPurchasing] = useState(false)\n const {id, referral} = product ?? {}\n\n const {showErrorToast} = useErrorToast()\n\n const handleClick = useCallback(async () => {\n if (disabled) return\n\n if (id && referral) {\n navigateToProduct({\n productId: id,\n })\n\n return\n }\n\n if (isPurchasing) return\n\n try {\n if (id && productVariantId) {\n setIsPurchasing(true)\n\n await buyProduct({\n productId: id,\n productVariantId,\n quantity: 1,\n discountCode,\n })\n\n setIsPurchasing(false)\n }\n } catch (error) {\n showErrorToast({message: 'Failed to complete purchase'})\n setIsPurchasing(false)\n }\n }, [\n disabled,\n id,\n referral,\n isPurchasing,\n navigateToProduct,\n productVariantId,\n buyProduct,\n discountCode,\n showErrorToast,\n ])\n\n return (\n <Button\n onClick={handleClick}\n disabled={disabled || isPurchasing}\n className={cn('relative overflow-hidden', className)}\n size={size}\n aria-live=\"polite\"\n aria-busy={isPurchasing}\n >\n <AnimatePresence mode=\"wait\">\n <motion.span\n key=\"text\"\n initial={{opacity: 0, y: 10}}\n animate={{opacity: 1, y: 0}}\n exit={{opacity: 0, y: -10}}\n transition={{duration: 0.2}}\n >\n {referral ? 'View product' : 'Buy now'}\n </motion.span>\n </AnimatePresence>\n </Button>\n )\n}\n"],"names":["BuyNowButton","disabled","className","size","productVariantId","discountCode","product","buyProduct","useShopCartActions","navigateToProduct","useShopNavigation","isPurchasing","setIsPurchasing","useState","id","referral","showErrorToast","useErrorToast","handleClick","useCallback","jsx","Button","cn","AnimatePresence","motion"],"mappings":";;;;;;;;;AA4BO,SAASA,EAAa;AAAA,EAC3B,UAAAC,IAAW;AAAA,EACX,WAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,kBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,SAAAC;AACF,GAAsB;AACd,QAAA,EAAC,YAAAC,EAAU,IAAIC,EAAmB,GAClC,EAAC,mBAAAC,EAAiB,IAAIC,EAAkB,GACxC,CAACC,GAAcC,CAAe,IAAIC,EAAS,EAAK,GAChD,EAAC,IAAAC,GAAI,UAAAC,EAAQ,IAAIT,KAAW,CAAC,GAE7B,EAAC,gBAAAU,EAAc,IAAIC,EAAc,GAEjCC,IAAcC,EAAY,YAAY;AAC1C,QAAI,CAAAlB,GAEJ;AAAA,UAAIa,KAAMC,GAAU;AACA,QAAAN,EAAA;AAAA,UAChB,WAAWK;AAAA,QAAA,CACZ;AAED;AAAA,MAAA;AAGF,UAAI,CAAAH;AAEA,YAAA;AACF,UAAIG,KAAMV,MACRQ,EAAgB,EAAI,GAEpB,MAAML,EAAW;AAAA,YACf,WAAWO;AAAA,YACX,kBAAAV;AAAA,YACA,UAAU;AAAA,YACV,cAAAC;AAAA,UAAA,CACD,GAEDO,EAAgB,EAAK;AAAA,gBAET;AACC,UAAAI,EAAA,EAAC,SAAS,+BAA8B,GACvDJ,EAAgB,EAAK;AAAA,QAAA;AAAA;AAAA,EACvB,GACC;AAAA,IACDX;AAAA,IACAa;AAAA,IACAC;AAAA,IACAJ;AAAA,IACAF;AAAA,IACAL;AAAA,IACAG;AAAA,IACAF;AAAA,IACAW;AAAA,EAAA,CACD;AAGC,SAAA,gBAAAI;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,SAASH;AAAA,MACT,UAAUjB,KAAYU;AAAA,MACtB,WAAWW,EAAG,4BAA4BpB,CAAS;AAAA,MACnD,MAAAC;AAAA,MACA,aAAU;AAAA,MACV,aAAWQ;AAAA,MAEX,UAAA,gBAAAS,EAACG,GAAgB,EAAA,MAAK,QACpB,UAAA,gBAAAH;AAAA,QAACI,EAAO;AAAA,QAAP;AAAA,UAEC,SAAS,EAAC,SAAS,GAAG,GAAG,GAAE;AAAA,UAC3B,SAAS,EAAC,SAAS,GAAG,GAAG,EAAC;AAAA,UAC1B,MAAM,EAAC,SAAS,GAAG,GAAG,IAAG;AAAA,UACzB,YAAY,EAAC,UAAU,IAAG;AAAA,UAEzB,cAAW,iBAAiB;AAAA,QAAA;AAAA,QANzB;AAAA,MAAA,EAQR,CAAA;AAAA,IAAA;AAAA,EACF;AAEJ;"}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { jsx as o, jsxs as v } from "react/jsx-runtime";
|
|
2
|
-
import * as
|
|
3
|
-
import { useState as A, useCallback as C, useMemo as k, useContext as
|
|
4
|
-
import { useShopNavigation as
|
|
5
|
-
import { useSavedProductsActions as
|
|
6
|
-
import { formatMoney as
|
|
2
|
+
import * as N from "react";
|
|
3
|
+
import { useState as A, useCallback as C, useMemo as k, useContext as z } from "react";
|
|
4
|
+
import { useShopNavigation as B } from "../../hooks/navigation/useShopNavigation.js";
|
|
5
|
+
import { useSavedProductsActions as V } from "../../hooks/user/useSavedProductsActions.js";
|
|
6
|
+
import { formatMoney as j } from "../../lib/formatMoney.js";
|
|
7
7
|
import { cn as s } from "../../lib/utils.js";
|
|
8
8
|
import { Image as T } from "../atoms/image.js";
|
|
9
9
|
import { ProductVariantPrice as E } from "../atoms/product-variant-price.js";
|
|
10
10
|
import { Touchable as O } from "../atoms/touchable.js";
|
|
11
11
|
import { Badge as S } from "../ui/badge.js";
|
|
12
12
|
import { FavoriteButton as L } from "./favorite-button.js";
|
|
13
|
-
const b =
|
|
13
|
+
const b = N.createContext(void 0);
|
|
14
14
|
function u() {
|
|
15
|
-
const t =
|
|
15
|
+
const t = z(b);
|
|
16
16
|
if (!t)
|
|
17
17
|
throw new Error(
|
|
18
18
|
"ProductCard components must be used within a ProductCard provider"
|
|
@@ -27,7 +27,7 @@ function M({
|
|
|
27
27
|
"div",
|
|
28
28
|
{
|
|
29
29
|
className: s(
|
|
30
|
-
"relative
|
|
30
|
+
"relative size-full overflow-hidden rounded-xl border-0",
|
|
31
31
|
t
|
|
32
32
|
),
|
|
33
33
|
...e
|
|
@@ -55,10 +55,8 @@ function R({
|
|
|
55
55
|
{
|
|
56
56
|
"data-slot": "product-card-image-container",
|
|
57
57
|
className: s(
|
|
58
|
-
// Ensure the product image is stretched to the full size of the container (can't use width/height: 100% because of flex)
|
|
59
|
-
"flex justify-stretch items-stretch",
|
|
60
58
|
"relative overflow-hidden rounded-xl border border-gray-200",
|
|
61
|
-
"
|
|
59
|
+
"aspect-square",
|
|
62
60
|
r === "compact" ? "min-h-[104px]" : "min-h-[134px]",
|
|
63
61
|
t
|
|
64
62
|
),
|
|
@@ -76,7 +74,8 @@ function q({ className: t, ...e }) {
|
|
|
76
74
|
alt: d,
|
|
77
75
|
aspectRatio: 1,
|
|
78
76
|
thumbhash: c,
|
|
79
|
-
|
|
77
|
+
objectFit: "cover",
|
|
78
|
+
className: s("size-full", t),
|
|
80
79
|
...e
|
|
81
80
|
}
|
|
82
81
|
) : /* @__PURE__ */ o(
|
|
@@ -85,7 +84,7 @@ function q({ className: t, ...e }) {
|
|
|
85
84
|
"data-slot": "product-card-image",
|
|
86
85
|
src: l,
|
|
87
86
|
alt: d,
|
|
88
|
-
className: s("size-full", t),
|
|
87
|
+
className: s("size-full object-cover", t),
|
|
89
88
|
...e
|
|
90
89
|
}
|
|
91
90
|
),
|
|
@@ -179,7 +178,7 @@ function K() {
|
|
|
179
178
|
const { product: t, selectedProductVariant: e, variant: r } = u();
|
|
180
179
|
if (r !== "priceOverlay") return null;
|
|
181
180
|
const a = e?.price || t.price, n = a?.currencyCode, i = a?.amount;
|
|
182
|
-
return !n || !i ? null : /* @__PURE__ */ o(w, { position: "top-left", children:
|
|
181
|
+
return !n || !i ? null : /* @__PURE__ */ o(w, { position: "top-left", children: j(i, n) });
|
|
183
182
|
}
|
|
184
183
|
function at({
|
|
185
184
|
product: t,
|
|
@@ -193,7 +192,7 @@ function at({
|
|
|
193
192
|
children: p,
|
|
194
193
|
favoriteButtonDisabled: l = !1
|
|
195
194
|
}) {
|
|
196
|
-
const { navigateToProduct: h } =
|
|
195
|
+
const { navigateToProduct: h } = B(), { saveProduct: g, unsaveProduct: P } = V(), [f, y] = A(t.isFavorited), x = C(() => {
|
|
197
196
|
a && (d?.(), h({
|
|
198
197
|
productId: t.id
|
|
199
198
|
}));
|
|
@@ -222,7 +221,7 @@ function at({
|
|
|
222
221
|
g,
|
|
223
222
|
P,
|
|
224
223
|
c
|
|
225
|
-
]),
|
|
224
|
+
]), F = k(
|
|
226
225
|
() => ({
|
|
227
226
|
// Core data
|
|
228
227
|
product: t,
|
|
@@ -252,7 +251,7 @@ function at({
|
|
|
252
251
|
l
|
|
253
252
|
]
|
|
254
253
|
);
|
|
255
|
-
return /* @__PURE__ */ o(b.Provider, { value:
|
|
254
|
+
return /* @__PURE__ */ o(b.Provider, { value: F, children: p ?? /* @__PURE__ */ v(M, { children: [
|
|
256
255
|
/* @__PURE__ */ v(R, { children: [
|
|
257
256
|
/* @__PURE__ */ o(q, {}),
|
|
258
257
|
r === "priceOverlay" && /* @__PURE__ */ o(K, {}),
|