@shopify/shop-minis-react 0.1.5 → 0.1.7
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/index10.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/_virtual/index7.js +2 -2
- package/dist/_virtual/index9.js +2 -2
- package/dist/components/atoms/list.js +106 -41
- package/dist/components/atoms/list.js.map +1 -1
- package/dist/components/commerce/add-to-cart.js +82 -0
- package/dist/components/commerce/add-to-cart.js.map +1 -0
- package/dist/components/{atoms → commerce}/favorite-button.js +1 -1
- package/dist/components/commerce/favorite-button.js.map +1 -0
- package/dist/components/commerce/product-card.js +10 -10
- package/dist/components/commerce/product-card.js.map +1 -1
- package/dist/components/commerce/product-link.js +6 -6
- package/dist/components/commerce/product-link.js.map +1 -1
- package/dist/index.js +276 -274
- package/dist/index.js.map +1 -1
- package/dist/internal/components/refresh-indicator.js +83 -0
- package/dist/internal/components/refresh-indicator.js.map +1 -0
- package/dist/internal/usePullToRefresh.js +149 -0
- package/dist/internal/usePullToRefresh.js.map +1 -0
- package/dist/internal/utils/virtuoso-dom.js +20 -0
- package/dist/internal/utils/virtuoso-dom.js.map +1 -0
- package/dist/mocks.js +1 -0
- package/dist/mocks.js.map +1 -1
- package/dist/shop-minis-react/node_modules/.pnpm/@radix-ui_react-use-is-hydrated@0.1.0_@types_react@19.1.6_react@19.1.0/node_modules/@radix-ui/react-use-is-hydrated/dist/index.js +1 -1
- 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/@xmldom_xmldom@0.8.10/node_modules/@xmldom/xmldom/lib/index.js +1 -1
- package/dist/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/PopChild.js +55 -0
- package/dist/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/PopChild.js.map +1 -0
- package/dist/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/PresenceChild.js +35 -0
- package/dist/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/PresenceChild.js.map +1 -0
- package/dist/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 +46 -0
- package/dist/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.map +1 -0
- package/dist/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/utils.js +13 -0
- package/dist/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/utils.js.map +1 -0
- 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/use-sync-external-store@1.5.0_react@19.1.0/node_modules/use-sync-external-store/shim/index.js +1 -1
- package/package.json +2 -2
- package/src/components/atoms/list.tsx +97 -12
- package/src/components/commerce/add-to-cart.test.tsx +73 -0
- package/src/components/commerce/add-to-cart.tsx +132 -0
- package/src/components/{atoms → commerce}/favorite-button.tsx +1 -1
- package/src/components/commerce/product-card.tsx +2 -1
- package/src/components/commerce/product-link.test.tsx +1 -0
- package/src/components/commerce/product-link.tsx +2 -1
- package/src/components/index.ts +2 -1
- package/src/internal/components/refresh-indicator.tsx +103 -0
- package/src/internal/usePullToRefresh.ts +286 -0
- package/src/internal/utils/virtuoso-dom.ts +26 -0
- package/src/mocks.ts +1 -0
- package/src/stories/AddToCart.stories.tsx +186 -0
- package/src/stories/FavoriteButton.stories.tsx +2 -2
- package/src/stories/PullToRefreshList.stories.tsx +122 -0
- package/src/styles/animations.css +54 -0
- package/src/test-utils.tsx +1 -0
- package/dist/components/atoms/favorite-button.js.map +0 -1
- /package/src/components/{atoms → commerce}/favorite-button.test.tsx +0 -0
package/dist/_virtual/index10.js
CHANGED
package/dist/_virtual/index5.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
var i = r();
|
|
1
|
+
var e = { exports: {} };
|
|
3
2
|
export {
|
|
4
|
-
|
|
3
|
+
e as __module
|
|
5
4
|
};
|
|
6
5
|
//# sourceMappingURL=index5.js.map
|
|
@@ -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":";;"}
|
package/dist/_virtual/index7.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { __require as r } from "../shop-minis-react/node_modules/.pnpm
|
|
1
|
+
import { __require as r } from "../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";
|
|
2
2
|
var i = r();
|
|
3
3
|
export {
|
|
4
|
-
i as
|
|
4
|
+
i as s
|
|
5
5
|
};
|
|
6
6
|
//# sourceMappingURL=index7.js.map
|
package/dist/_virtual/index9.js
CHANGED
|
@@ -1,55 +1,120 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { useRef as
|
|
3
|
-
import { Virtuoso as
|
|
4
|
-
import {
|
|
1
|
+
import { jsx as e, Fragment as D, jsxs as g } from "react/jsx-runtime";
|
|
2
|
+
import { useRef as f, useCallback as a, useEffect as w } from "react";
|
|
3
|
+
import { Virtuoso as I } from "../../shop-minis-react/node_modules/.pnpm/react-virtuoso@4.14.0_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-virtuoso/dist/index.js";
|
|
4
|
+
import { RefreshIndicator as M } from "../../internal/components/refresh-indicator.js";
|
|
5
|
+
import { usePullToRefresh as U } from "../../internal/usePullToRefresh.js";
|
|
6
|
+
import { findVirtuosoScrollableElement as V } from "../../internal/utils/virtuoso-dom.js";
|
|
7
|
+
import { cn as x } from "../../lib/utils.js";
|
|
5
8
|
/* empty css */
|
|
6
|
-
import { Pagination as
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
import { Pagination as k } from "./pagination.js";
|
|
10
|
+
const H = 200, q = 100;
|
|
11
|
+
function W({
|
|
12
|
+
items: L,
|
|
13
|
+
height: N,
|
|
14
|
+
renderItem: p,
|
|
15
|
+
className: _,
|
|
16
|
+
showScrollbar: F = !1,
|
|
17
|
+
header: u,
|
|
14
18
|
fetchMore: r,
|
|
15
|
-
loadingComponent:
|
|
16
|
-
isFetchingMore:
|
|
17
|
-
|
|
19
|
+
loadingComponent: E,
|
|
20
|
+
isFetchingMore: h,
|
|
21
|
+
onRefresh: n,
|
|
22
|
+
refreshing: m,
|
|
23
|
+
enablePullToRefresh: i = !0,
|
|
24
|
+
...R
|
|
18
25
|
}) {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
const l = f(null), y = f(null), s = f(null), { state: o, bindToElement: v } = U({
|
|
27
|
+
onRefresh: n,
|
|
28
|
+
threshold: H,
|
|
29
|
+
enabled: i && !!n
|
|
30
|
+
}), d = a(() => {
|
|
31
|
+
if (l.current) return;
|
|
32
|
+
const t = Promise.resolve(r?.()).finally(() => {
|
|
33
|
+
l.current === t && (l.current = null);
|
|
23
34
|
});
|
|
24
|
-
|
|
25
|
-
}, [r]),
|
|
26
|
-
(
|
|
27
|
-
[
|
|
28
|
-
),
|
|
29
|
-
|
|
35
|
+
l.current = t;
|
|
36
|
+
}, [r]), A = a(
|
|
37
|
+
(t, c) => /* @__PURE__ */ e(D, { children: p(c, t) }),
|
|
38
|
+
[p]
|
|
39
|
+
), B = a(() => r ? /* @__PURE__ */ e(
|
|
40
|
+
k,
|
|
30
41
|
{
|
|
31
|
-
fetchMore:
|
|
32
|
-
loadingComponent:
|
|
33
|
-
isFetchingMore:
|
|
42
|
+
fetchMore: d,
|
|
43
|
+
loadingComponent: E,
|
|
44
|
+
isFetchingMore: h
|
|
34
45
|
}
|
|
35
|
-
) : null, [
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
) : null, [d, r, E, h]), S = x(F ? void 0 : "no-scrollbars", _);
|
|
47
|
+
w(() => {
|
|
48
|
+
if (s.current && i && n) {
|
|
49
|
+
let t;
|
|
50
|
+
const j = setTimeout(() => {
|
|
51
|
+
if (!s.current) return;
|
|
52
|
+
const b = V(
|
|
53
|
+
s.current
|
|
54
|
+
);
|
|
55
|
+
t = v(b);
|
|
56
|
+
}, q);
|
|
57
|
+
return () => {
|
|
58
|
+
clearTimeout(j), t && t();
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}, [v, i, n]);
|
|
62
|
+
const T = a(() => {
|
|
63
|
+
const t = m ? Math.max(o.pullDistance, 140) : o.pullDistance, c = Math.min(
|
|
64
|
+
Math.max(t, 0),
|
|
65
|
+
140
|
|
66
|
+
);
|
|
67
|
+
return /* @__PURE__ */ g(D, { children: [
|
|
68
|
+
i && n && /* @__PURE__ */ e(
|
|
69
|
+
"div",
|
|
70
|
+
{
|
|
71
|
+
className: "flex items-center justify-center",
|
|
72
|
+
style: {
|
|
73
|
+
height: c,
|
|
74
|
+
overflow: "hidden"
|
|
75
|
+
},
|
|
76
|
+
children: /* @__PURE__ */ e(
|
|
77
|
+
M,
|
|
78
|
+
{
|
|
79
|
+
pullDistance: o.pullDistance,
|
|
80
|
+
threshold: H,
|
|
81
|
+
isRefreshing: m ?? !1,
|
|
82
|
+
canRefresh: o.canRefresh,
|
|
83
|
+
className: "relative top-0 inset-x-auto"
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
),
|
|
88
|
+
u && /* @__PURE__ */ e("div", { children: u })
|
|
89
|
+
] });
|
|
90
|
+
}, [u, i, n, o, m]);
|
|
91
|
+
return /* @__PURE__ */ e(
|
|
92
|
+
"div",
|
|
38
93
|
{
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
components: {
|
|
44
|
-
Header: c ? () => /* @__PURE__ */ o("div", { children: c }) : void 0,
|
|
45
|
-
Footer: F
|
|
94
|
+
ref: s,
|
|
95
|
+
className: x("relative transition-all duration-200", S),
|
|
96
|
+
style: {
|
|
97
|
+
height: N
|
|
46
98
|
},
|
|
47
|
-
|
|
48
|
-
|
|
99
|
+
children: /* @__PURE__ */ e(
|
|
100
|
+
I,
|
|
101
|
+
{
|
|
102
|
+
ref: y,
|
|
103
|
+
className: "h-full w-full",
|
|
104
|
+
data: L,
|
|
105
|
+
itemContent: A,
|
|
106
|
+
components: {
|
|
107
|
+
Header: T,
|
|
108
|
+
Footer: B
|
|
109
|
+
},
|
|
110
|
+
endReached: r ? d : void 0,
|
|
111
|
+
...R
|
|
112
|
+
}
|
|
113
|
+
)
|
|
49
114
|
}
|
|
50
115
|
);
|
|
51
116
|
}
|
|
52
117
|
export {
|
|
53
|
-
|
|
118
|
+
W as List
|
|
54
119
|
};
|
|
55
120
|
//# sourceMappingURL=list.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.js","sources":["../../../src/components/atoms/list.tsx"],"sourcesContent":["import {useCallback, useRef} from 'react'\n\nimport {Virtuoso, VirtuosoProps} from 'react-virtuoso'\n\nimport {cn} from '../../lib/utils'\nimport '../../styles/utilities.css'\n\nimport {Pagination} from './pagination'\n\ninterface Props<T = any>\n extends Omit<\n VirtuosoProps<T, unknown>,\n 'data' | 'itemContent' | 'endReached'\n > {\n items: T[]\n renderItem: (item: T, index: number) => React.ReactNode\n showScrollbar?: boolean\n header?: React.ReactNode\n fetchMore?: () => Promise<void>\n loadingComponent?: React.ReactNode\n isFetchingMore?: boolean\n}\n\nexport function List<T = any>({\n items,\n height,\n renderItem,\n className,\n showScrollbar = false,\n header,\n fetchMore,\n loadingComponent,\n isFetchingMore,\n ...virtuosoProps\n}: Props<T>) {\n const inFlightFetchMoreRef = useRef<Promise<void> | null>(null)\n\n const _fetchMore = useCallback(() => {\n // Dedupe concurrent calls by returning the same in-flight promise\n if (inFlightFetchMoreRef.current) return\n\n const current = Promise.resolve(fetchMore?.()).finally(() => {\n // Only clear if this is still the most recent promise\n if (inFlightFetchMoreRef.current === current) {\n inFlightFetchMoreRef.current = null\n }\n })\n\n inFlightFetchMoreRef.current = current\n }, [fetchMore])\n\n const itemContent = useCallback(\n (index: number, item: T) => <>{renderItem(item, index)}</>,\n [renderItem]\n )\n\n const Footer = useCallback(() => {\n if (!fetchMore) return null\n\n return (\n <Pagination\n fetchMore={_fetchMore}\n loadingComponent={loadingComponent}\n isFetchingMore={isFetchingMore}\n />\n )\n }, [_fetchMore, fetchMore, loadingComponent, isFetchingMore])\n\n const classNames = cn(showScrollbar ? undefined : 'no-scrollbars', className)\n\n return (\n
|
|
1
|
+
{"version":3,"file":"list.js","sources":["../../../src/components/atoms/list.tsx"],"sourcesContent":["import {useCallback, useEffect, useRef} from 'react'\n\nimport {Virtuoso, VirtuosoProps} from 'react-virtuoso'\n\nimport {RefreshIndicator} from '../../internal/components/refresh-indicator'\nimport {usePullToRefresh} from '../../internal/usePullToRefresh'\nimport {findVirtuosoScrollableElement} from '../../internal/utils/virtuoso-dom'\nimport {cn} from '../../lib/utils'\nimport '../../styles/utilities.css'\n\nimport {Pagination} from './pagination'\n\nconst DEFAULT_REFRESH_PULL_THRESHOLD = 200\nconst ELEMENT_BIND_DELAY = 100\n\ninterface Props<T = any>\n extends Omit<\n VirtuosoProps<T, unknown>,\n 'data' | 'itemContent' | 'endReached'\n > {\n items: T[]\n renderItem: (item: T, index: number) => React.ReactNode\n showScrollbar?: boolean\n header?: React.ReactNode\n fetchMore?: () => Promise<void>\n loadingComponent?: React.ReactNode\n isFetchingMore?: boolean\n onRefresh?: () => Promise<void>\n refreshing?: boolean\n enablePullToRefresh?: boolean\n}\n\nexport function List<T = any>({\n items,\n height,\n renderItem,\n className,\n showScrollbar = false,\n header,\n fetchMore,\n loadingComponent,\n isFetchingMore,\n onRefresh,\n refreshing,\n enablePullToRefresh = true,\n ...virtuosoProps\n}: Props<T>) {\n const inFlightFetchMoreRef = useRef<Promise<void> | null>(null)\n const virtuosoRef = useRef<any>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n\n const {state: pullToRefreshState, bindToElement} = usePullToRefresh({\n onRefresh,\n threshold: DEFAULT_REFRESH_PULL_THRESHOLD,\n enabled: enablePullToRefresh && Boolean(onRefresh),\n })\n\n const _fetchMore = useCallback(() => {\n // Dedupe concurrent calls by returning the same in-flight promise\n if (inFlightFetchMoreRef.current) return\n\n const current = Promise.resolve(fetchMore?.()).finally(() => {\n // Only clear if this is still the most recent promise\n if (inFlightFetchMoreRef.current === current) {\n inFlightFetchMoreRef.current = null\n }\n })\n\n inFlightFetchMoreRef.current = current\n }, [fetchMore])\n\n const itemContent = useCallback(\n (index: number, item: T) => <>{renderItem(item, index)}</>,\n [renderItem]\n )\n\n const Footer = useCallback(() => {\n if (!fetchMore) return null\n\n return (\n <Pagination\n fetchMore={_fetchMore}\n loadingComponent={loadingComponent}\n isFetchingMore={isFetchingMore}\n />\n )\n }, [_fetchMore, fetchMore, loadingComponent, isFetchingMore])\n\n const classNames = cn(showScrollbar ? undefined : 'no-scrollbars', className)\n\n useEffect(() => {\n if (containerRef.current && enablePullToRefresh && onRefresh) {\n let cleanup: (() => void) | undefined\n\n const findAndBind = () => {\n if (!containerRef.current) return\n\n const scrollableElement = findVirtuosoScrollableElement(\n containerRef.current\n )\n cleanup = bindToElement(scrollableElement)\n }\n\n const timeoutId = setTimeout(findAndBind, ELEMENT_BIND_DELAY)\n\n return () => {\n clearTimeout(timeoutId)\n if (cleanup) cleanup()\n }\n }\n return undefined\n }, [bindToElement, enablePullToRefresh, onRefresh])\n\n const EnhancedHeader = useCallback(() => {\n const effectivePullDistance = refreshing\n ? Math.max(pullToRefreshState.pullDistance, 140)\n : pullToRefreshState.pullDistance\n\n const refreshHeaderHeight = Math.min(\n Math.max(effectivePullDistance, 0),\n 140\n )\n\n return (\n <>\n {enablePullToRefresh && onRefresh && (\n <div\n className=\"flex items-center justify-center\"\n style={{\n height: refreshHeaderHeight,\n overflow: 'hidden',\n }}\n >\n <RefreshIndicator\n pullDistance={pullToRefreshState.pullDistance}\n threshold={DEFAULT_REFRESH_PULL_THRESHOLD}\n isRefreshing={refreshing ?? false}\n canRefresh={pullToRefreshState.canRefresh}\n className=\"relative top-0 inset-x-auto\"\n />\n </div>\n )}\n {header && <div>{header}</div>}\n </>\n )\n }, [header, enablePullToRefresh, onRefresh, pullToRefreshState, refreshing])\n\n return (\n <div\n ref={containerRef}\n className={cn('relative transition-all duration-200', classNames)}\n style={{\n height,\n }}\n >\n <Virtuoso\n ref={virtuosoRef}\n className=\"h-full w-full\"\n data={items}\n itemContent={itemContent}\n components={{\n Header: EnhancedHeader,\n Footer,\n }}\n endReached={fetchMore ? _fetchMore : undefined}\n {...virtuosoProps}\n />\n </div>\n )\n}\n"],"names":["DEFAULT_REFRESH_PULL_THRESHOLD","ELEMENT_BIND_DELAY","List","items","height","renderItem","className","showScrollbar","header","fetchMore","loadingComponent","isFetchingMore","onRefresh","refreshing","enablePullToRefresh","virtuosoProps","inFlightFetchMoreRef","useRef","virtuosoRef","containerRef","pullToRefreshState","bindToElement","usePullToRefresh","_fetchMore","useCallback","current","itemContent","index","item","Footer","jsx","Pagination","classNames","cn","useEffect","cleanup","timeoutId","scrollableElement","findVirtuosoScrollableElement","EnhancedHeader","effectivePullDistance","refreshHeaderHeight","jsxs","Fragment","RefreshIndicator","Virtuoso"],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { jsx as r, jsxs as A } from "react/jsx-runtime";
|
|
2
|
+
import * as m from "react";
|
|
3
|
+
import { useState as T, useCallback as v } from "react";
|
|
4
|
+
import { cn as f } from "../../lib/utils.js";
|
|
5
|
+
import { Button as x } from "../atoms/button.js";
|
|
6
|
+
import { useShopCartActions as C } from "../../hooks/shop/useShopCartActions.js";
|
|
7
|
+
import { useErrorToast as y } from "../../hooks/util/useErrorToast.js";
|
|
8
|
+
import { AnimatePresence as N } 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";
|
|
9
|
+
import { motion as k } 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";
|
|
10
|
+
import w 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";
|
|
11
|
+
function P({
|
|
12
|
+
disabled: o = !1,
|
|
13
|
+
className: u,
|
|
14
|
+
size: d = "default",
|
|
15
|
+
productId: a,
|
|
16
|
+
productVariantId: i,
|
|
17
|
+
discountCodes: n
|
|
18
|
+
}) {
|
|
19
|
+
const { addToCart: c } = C(), [t, s] = T(!1), e = m.useRef(void 0), { showErrorToast: l } = y(), h = v(async () => {
|
|
20
|
+
if (!(t || o))
|
|
21
|
+
try {
|
|
22
|
+
a && i && c({
|
|
23
|
+
productId: a,
|
|
24
|
+
productVariantId: i,
|
|
25
|
+
quantity: 1,
|
|
26
|
+
discountCodes: n
|
|
27
|
+
}).then(() => {
|
|
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);
|
|
35
|
+
}
|
|
36
|
+
}, [
|
|
37
|
+
t,
|
|
38
|
+
o,
|
|
39
|
+
c,
|
|
40
|
+
a,
|
|
41
|
+
i,
|
|
42
|
+
n,
|
|
43
|
+
l
|
|
44
|
+
]);
|
|
45
|
+
return m.useEffect(() => () => {
|
|
46
|
+
e.current && clearTimeout(e.current);
|
|
47
|
+
}, []), /* @__PURE__ */ r(
|
|
48
|
+
x,
|
|
49
|
+
{
|
|
50
|
+
onClick: h,
|
|
51
|
+
disabled: o,
|
|
52
|
+
className: f(
|
|
53
|
+
"relative overflow-hidden transition-all duration-300",
|
|
54
|
+
u
|
|
55
|
+
),
|
|
56
|
+
size: d,
|
|
57
|
+
children: /* @__PURE__ */ A("div", { className: "relative flex items-center justify-center", children: [
|
|
58
|
+
/* @__PURE__ */ r(N, { children: t && /* @__PURE__ */ r(
|
|
59
|
+
k.div,
|
|
60
|
+
{
|
|
61
|
+
initial: { scale: 0, rotate: -180 },
|
|
62
|
+
animate: { scale: 1, rotate: 0 },
|
|
63
|
+
exit: { scale: 0, rotate: 180 },
|
|
64
|
+
transition: {
|
|
65
|
+
duration: 0.4,
|
|
66
|
+
ease: [0.175, 0.885, 0.32, 1.275]
|
|
67
|
+
// bounce effect
|
|
68
|
+
},
|
|
69
|
+
className: "absolute left-0",
|
|
70
|
+
style: { x: -8 },
|
|
71
|
+
children: /* @__PURE__ */ r(w, { className: "size-4" })
|
|
72
|
+
}
|
|
73
|
+
) }),
|
|
74
|
+
/* @__PURE__ */ r("span", { className: f(t && "pl-5", "transition-all duration-300"), children: t ? "Added to cart" : "Add to cart" })
|
|
75
|
+
] })
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
P as AddToCartButton
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=add-to-cart.js.map
|
|
@@ -0,0 +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, useShopCartActions} from '../../hooks'\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. E.g. `gid://shopify/Product/123`.\n */\n productId: string\n /**\n * The GID of the product variant. E.g. `gid://shopify/ProductVariant/456`.\n */\n productVariantId: string\n}\n\nexport function AddToCartButton({\n disabled = false,\n className,\n size = 'default',\n productId,\n productVariantId,\n discountCodes,\n}: AddToCartButtonProps) {\n const {addToCart} = useShopCartActions()\n const [isAdded, setIsAdded] = useState(false)\n const timeoutRef = React.useRef<number | undefined>(undefined)\n\n const {showErrorToast} = useErrorToast()\n\n const handleClick = useCallback(async () => {\n if (isAdded || disabled) return\n\n try {\n // Call the callback if provided\n if (productId && productVariantId) {\n // Optimistic update with error toast\n addToCart({\n productId,\n productVariantId,\n quantity: 1,\n discountCodes,\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 isAdded,\n disabled,\n addToCart,\n productId,\n productVariantId,\n discountCodes,\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 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-0\"\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 {isAdded ? 'Added to cart' : 'Add to cart'}\n </span>\n </div>\n </Button>\n )\n}\n"],"names":["AddToCartButton","disabled","className","size","productId","productVariantId","discountCodes","addToCart","useShopCartActions","isAdded","setIsAdded","useState","timeoutRef","React","showErrorToast","useErrorToast","handleClick","useCallback","error","jsx","Button","cn","jsxs","AnimatePresence","motion","CheckIcon"],"mappings":";;;;;;;;;;AA4BO,SAASA,EAAgB;AAAA,EAC9B,UAAAC,IAAW;AAAA,EACX,WAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,WAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,eAAAC;AACF,GAAyB;AACjB,QAAA,EAAC,WAAAC,EAAS,IAAIC,EAAmB,GACjC,CAACC,GAASC,CAAU,IAAIC,EAAS,EAAK,GACtCC,IAAaC,EAAM,OAA2B,MAAS,GAEvD,EAAC,gBAAAC,EAAc,IAAIC,EAAc,GAEjCC,IAAcC,EAAY,YAAY;AAC1C,QAAI,EAAAR,KAAWR;AAEX,UAAA;AAEF,QAAIG,KAAaC,KAELE,EAAA;AAAA,UACR,WAAAH;AAAA,UACA,kBAAAC;AAAA,UACA,UAAU;AAAA,UACV,eAAAC;AAAA,QAAA,CACD,EACE,KAAK,MAAM;AAAA,QAAA,CAAE,EACb,MAAM,MAAM;AACI,UAAAQ,EAAA,EAAC,SAAS,yBAAwB;AAAA,QAAA,CAClD,GAILJ,EAAW,EAAI,GAGXE,EAAW,WACb,aAAaA,EAAW,OAAO,GAItBA,EAAA,UAAU,OAAO,WAAW,MAAM;AAC3C,UAAAF,EAAW,EAAK;AAAA,WACf,GAAI;AAAA,eACAQ,GAAO;AAEd,QAAAR,EAAW,EAAK,GACR,QAAA,MAAM,0BAA0BQ,CAAK;AAAA,MAAA;AAAA,EAC/C,GACC;AAAA,IACDT;AAAA,IACAR;AAAA,IACAM;AAAA,IACAH;AAAA,IACAC;AAAA,IACAC;AAAA,IACAQ;AAAA,EAAA,CACD;AAGD,SAAAD,EAAM,UAAU,MACP,MAAM;AACX,IAAID,EAAW,WACb,aAAaA,EAAW,OAAO;AAAA,EAEnC,GACC,EAAE,GAGH,gBAAAO;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,SAASJ;AAAA,MACT,UAAAf;AAAA,MACA,WAAWoB;AAAA,QACT;AAAA,QACAnB;AAAA,MACF;AAAA,MACA,MAAAC;AAAA,MAEA,UAAA,gBAAAmB,EAAC,OAAI,EAAA,WAAU,6CACb,UAAA;AAAA,QAAA,gBAAAH,EAACI,KACE,UACCd,KAAA,gBAAAU;AAAA,UAACK,EAAO;AAAA,UAAP;AAAA,YACC,SAAS,EAAC,OAAO,GAAG,QAAQ,KAAI;AAAA,YAChC,SAAS,EAAC,OAAO,GAAG,QAAQ,EAAC;AAAA,YAC7B,MAAM,EAAC,OAAO,GAAG,QAAQ,IAAG;AAAA,YAC5B,YAAY;AAAA,cACV,UAAU;AAAA,cACV,MAAM,CAAC,OAAO,OAAO,MAAM,KAAK;AAAA;AAAA,YAClC;AAAA,YACA,WAAU;AAAA,YACV,OAAO,EAAC,GAAG,GAAE;AAAA,YAEb,UAAA,gBAAAL,EAACM,GAAU,EAAA,WAAU,SAAS,CAAA;AAAA,UAAA;AAAA,QAAA,GAGpC;AAAA,QACA,gBAAAN,EAAC,QAAK,EAAA,WAAWE,EAAGZ,KAAW,QAAQ,6BAA6B,GACjE,UAAUA,IAAA,kBAAkB,cAC/B,CAAA;AAAA,MAAA,EACF,CAAA;AAAA,IAAA;AAAA,EACF;AAEJ;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as r } from "react/jsx-runtime";
|
|
2
|
-
import { IconButton as n } from "
|
|
2
|
+
import { IconButton as n } from "../atoms/icon-button.js";
|
|
3
3
|
import m from "../../shop-minis-react/node_modules/.pnpm/lucide-react@0.513.0_react@19.1.0/node_modules/lucide-react/dist/esm/icons/heart.js";
|
|
4
4
|
function e({
|
|
5
5
|
onClick: t,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"favorite-button.js","sources":["../../../src/components/commerce/favorite-button.tsx"],"sourcesContent":["import {Heart} from 'lucide-react'\n\nimport {IconButton} from '../atoms/icon-button'\n\nexport function FavoriteButton({\n onClick,\n filled = false,\n}: {\n onClick?: () => void\n filled?: boolean\n}) {\n return (\n <IconButton\n Icon={Heart}\n filled={filled}\n onClick={onClick}\n buttonStyles={\n filled ? 'bg-primary' : 'bg-button-overlay/30 backdrop-blur-sm'\n }\n />\n )\n}\n"],"names":["FavoriteButton","onClick","filled","jsx","IconButton","Heart"],"mappings":";;;AAIO,SAASA,EAAe;AAAA,EAC7B,SAAAC;AAAA,EACA,QAAAC,IAAS;AACX,GAGG;AAEC,SAAA,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,MAAMC;AAAA,MACN,QAAAH;AAAA,MACA,SAAAD;AAAA,MACA,cACEC,IAAS,eAAe;AAAA,IAAA;AAAA,EAE5B;AAEJ;"}
|
|
@@ -5,11 +5,11 @@ import { useShopNavigation as V } from "../../hooks/navigation/useShopNavigation
|
|
|
5
5
|
import { useSavedProductsActions as j } from "../../hooks/user/useSavedProductsActions.js";
|
|
6
6
|
import { formatMoney as z } from "../../lib/formatMoney.js";
|
|
7
7
|
import { cn as s } from "../../lib/utils.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
8
|
+
import { Image as B } from "../atoms/image.js";
|
|
9
|
+
import { ProductVariantPrice as T } from "../atoms/product-variant-price.js";
|
|
10
|
+
import { Touchable as E } from "../atoms/touchable.js";
|
|
11
|
+
import { Badge as O } from "../ui/badge.js";
|
|
12
|
+
import { FavoriteButton as S } from "./favorite-button.js";
|
|
13
13
|
const I = N.createContext(void 0);
|
|
14
14
|
function u() {
|
|
15
15
|
const t = k(I);
|
|
@@ -34,7 +34,7 @@ function L({
|
|
|
34
34
|
}
|
|
35
35
|
);
|
|
36
36
|
return r && a ? /* @__PURE__ */ o(
|
|
37
|
-
|
|
37
|
+
E,
|
|
38
38
|
{
|
|
39
39
|
onClick: a,
|
|
40
40
|
whileTap: { opacity: 0.7 },
|
|
@@ -69,7 +69,7 @@ function M({
|
|
|
69
69
|
function R({ className: t, ...e }) {
|
|
70
70
|
const { product: r, selectedProductVariant: a } = u(), n = a?.image || r.featuredImage, i = n?.url, d = n?.altText || r.title, c = r.featuredImage?.thumbhash, p = C(
|
|
71
71
|
(l) => c ? /* @__PURE__ */ o(
|
|
72
|
-
|
|
72
|
+
B,
|
|
73
73
|
{
|
|
74
74
|
"data-slot": "product-card-image",
|
|
75
75
|
src: l,
|
|
@@ -109,7 +109,7 @@ function b({
|
|
|
109
109
|
e === "top-left" ? "top-3 left-3" : "bottom-2 left-2"
|
|
110
110
|
),
|
|
111
111
|
children: /* @__PURE__ */ o(
|
|
112
|
-
|
|
112
|
+
O,
|
|
113
113
|
{
|
|
114
114
|
variant: r ?? d ?? "none",
|
|
115
115
|
className: s(
|
|
@@ -129,7 +129,7 @@ function q({
|
|
|
129
129
|
...e
|
|
130
130
|
}) {
|
|
131
131
|
const { isFavorited: r, onFavoriteToggle: a } = u();
|
|
132
|
-
return /* @__PURE__ */ o("div", { className: s("absolute bottom-3 right-3 z-10", t), ...e, children: /* @__PURE__ */ o(
|
|
132
|
+
return /* @__PURE__ */ o("div", { className: s("absolute bottom-3 right-3 z-10", t), ...e, children: /* @__PURE__ */ o(S, { onClick: a, filled: r }) });
|
|
133
133
|
}
|
|
134
134
|
function D({ className: t, ...e }) {
|
|
135
135
|
const { variant: r } = u();
|
|
@@ -165,7 +165,7 @@ function G({
|
|
|
165
165
|
function H({ className: t }) {
|
|
166
166
|
const { product: e, selectedProductVariant: r } = u(), a = r?.price || e?.price, n = r?.compareAtPrice || e?.compareAtPrice;
|
|
167
167
|
return /* @__PURE__ */ o(
|
|
168
|
-
|
|
168
|
+
T,
|
|
169
169
|
{
|
|
170
170
|
amount: a?.amount || "",
|
|
171
171
|
currencyCode: a?.currencyCode || "",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-card.js","sources":["../../../src/components/commerce/product-card.tsx"],"sourcesContent":["import * as React from 'react'\nimport {useCallback, useContext, useMemo, useState} from 'react'\n\nimport {type Product, type ProductVariant} from '@shopify/shop-minis-platform'\n\nimport {useShopNavigation} from '../../hooks/navigation/useShopNavigation'\nimport {useSavedProductsActions} from '../../hooks/user/useSavedProductsActions'\nimport {formatMoney} from '../../lib/formatMoney'\nimport {cn} from '../../lib/utils'\nimport {FavoriteButton} from '../atoms/favorite-button'\nimport {Image} from '../atoms/image'\nimport {ProductVariantPrice} from '../atoms/product-variant-price'\nimport {Touchable} from '../atoms/touchable'\nimport {Badge} from '../ui/badge'\n\n// Context definition\ninterface ProductCardContextValue {\n // Core data\n product: Product\n selectedProductVariant?: ProductVariant\n\n // UI configuration\n variant: 'default' | 'priceOverlay' | 'compact'\n touchable: boolean\n badgeText?: string\n badgeVariant?: 'primary' | 'secondary' | 'destructive' | 'outline' | 'none'\n\n // State\n isFavorited: boolean\n\n // Actions\n onClick: () => void\n onFavoriteToggle: () => void\n}\n\nconst ProductCardContext = React.createContext<\n ProductCardContextValue | undefined\n>(undefined)\n\nfunction useProductCardContext() {\n const context = useContext(ProductCardContext)\n if (!context) {\n throw new Error(\n 'ProductCard components must be used within a ProductCard provider'\n )\n }\n return context\n}\n\n// Primitive components (building blocks)\nfunction ProductCardContainer({\n className,\n ...props\n}: React.ComponentProps<'div'>) {\n const {touchable, onClick} = useProductCardContext()\n\n const content = (\n <div\n className={cn(\n 'relative w-full overflow-hidden rounded-xl border-0',\n className\n )}\n {...props}\n />\n )\n\n if (touchable && onClick) {\n return (\n <Touchable\n onClick={onClick}\n whileTap={{opacity: 0.7}}\n transition={{\n opacity: {type: 'tween', duration: 0.08, ease: 'easeInOut'},\n }}\n >\n {content}\n </Touchable>\n )\n }\n\n return content\n}\n\nfunction ProductCardImageContainer({\n className,\n ...props\n}: React.ComponentProps<'div'>) {\n const {variant} = useProductCardContext()\n\n return (\n <div\n data-slot=\"product-card-image-container\"\n className={cn(\n // Ensure the product image is stretched to the full size of the container (can't use width/height: 100% because of flex)\n 'flex justify-stretch items-stretch',\n 'relative overflow-hidden rounded-xl border border-gray-200',\n 'w-full aspect-square',\n variant === 'compact' ? 'min-h-[104px]' : 'min-h-[134px]',\n className\n )}\n {...props}\n />\n )\n}\n\nfunction ProductCardImage({className, ...props}: React.ComponentProps<'img'>) {\n const {product, selectedProductVariant} = useProductCardContext()\n\n // Derive display image locally\n const displayImage = selectedProductVariant?.image || product.featuredImage\n const src = displayImage?.url\n const alt = displayImage?.altText || product.title\n const thumbhash = product.featuredImage?.thumbhash\n\n const renderImageElement = useCallback(\n (src: string) => {\n const imageElement = thumbhash ? (\n <Image\n data-slot=\"product-card-image\"\n src={src}\n alt={alt}\n aspectRatio={1}\n thumbhash={thumbhash}\n className={cn('size-full object-cover', className)}\n {...props}\n />\n ) : (\n <img\n data-slot=\"product-card-image\"\n src={src}\n alt={alt}\n className={cn('size-full', className)}\n {...props}\n />\n )\n\n return imageElement\n },\n [alt, className, props, thumbhash]\n )\n\n return (\n <div className=\"bg-gray-100 flex items-center justify-center size-full\">\n {src ? (\n renderImageElement(src)\n ) : (\n <div className=\"text-gray-400 text-sm w-full text-center\">No Image</div>\n )}\n </div>\n )\n}\n\nfunction ProductCardBadge({\n className,\n position = 'bottom-left',\n variant,\n children,\n ...props\n}: React.ComponentProps<typeof Badge> & {\n position?: 'top-left' | 'bottom-left'\n}) {\n const {badgeText, badgeVariant} = useProductCardContext()\n // If no children provided, use badgeText from context\n const content = children || badgeText\n\n if (!content) return null\n\n return (\n <div\n className={cn(\n 'absolute z-10',\n position === 'top-left' ? 'top-3 left-3' : 'bottom-2 left-2'\n )}\n >\n <Badge\n variant={variant ?? badgeVariant ?? 'none'}\n className={cn(\n !badgeVariant &&\n !variant &&\n 'bg-black/50 text-white border-transparent',\n 'rounded',\n className\n )}\n {...props}\n >\n {content}\n </Badge>\n </div>\n )\n}\n\nfunction ProductCardFavoriteButton({\n className,\n ...props\n}: React.ComponentProps<'div'>) {\n const {isFavorited, onFavoriteToggle} = useProductCardContext()\n return (\n <div className={cn('absolute bottom-3 right-3 z-10', className)} {...props}>\n <FavoriteButton onClick={onFavoriteToggle} filled={isFavorited} />\n </div>\n )\n}\n\nfunction ProductCardInfo({className, ...props}: React.ComponentProps<'div'>) {\n const {variant} = useProductCardContext()\n if (variant !== 'default') {\n return null\n }\n\n return (\n <div\n data-slot=\"product-card-info\"\n className={cn('px-1 pt-2 pb-0 space-y-1', className)}\n {...props}\n />\n )\n}\n\nfunction ProductCardTitle({\n className,\n children,\n ...props\n}: React.ComponentProps<'h3'>) {\n const {product} = useProductCardContext()\n return (\n <h3\n data-slot=\"product-card-title\"\n className={cn(\n 'text-sm font-medium leading-tight text-gray-900',\n 'truncate overflow-hidden whitespace-nowrap text-ellipsis',\n className\n )}\n {...props}\n >\n {children || product.title}\n </h3>\n )\n}\n\nfunction ProductCardPrice({className}: {className?: string}) {\n const {product, selectedProductVariant} = useProductCardContext()\n\n // Derive price data locally\n const displayPrice = selectedProductVariant?.price || product?.price\n const displayCompareAtPrice =\n selectedProductVariant?.compareAtPrice || product?.compareAtPrice\n\n return (\n <ProductVariantPrice\n amount={displayPrice?.amount || ''}\n currencyCode={displayPrice?.currencyCode || ''}\n compareAtPriceAmount={displayCompareAtPrice?.amount}\n compareAtPriceCurrencyCode={displayCompareAtPrice?.currencyCode}\n className={className}\n />\n )\n}\n\n// Special PriceOverlayBadge for price overlay variant\nfunction ProductCardPriceOverlayBadge() {\n const {product, selectedProductVariant, variant} = useProductCardContext()\n if (variant !== 'priceOverlay') return null\n const displayPrice = selectedProductVariant?.price || product.price\n const currencyCode = displayPrice?.currencyCode\n const amount = displayPrice?.amount\n\n if (!currencyCode || !amount) return null\n return (\n <ProductCardBadge position=\"top-left\">\n {formatMoney(amount, currencyCode)}\n </ProductCardBadge>\n )\n}\n\nexport interface ProductCardProps {\n /** The product to display in the card */\n product: Product\n /** Optional selected variant of the product to show specific variant data */\n selectedProductVariant?: ProductVariant\n /** Visual style variant of the card */\n variant?: 'default' | 'priceOverlay' | 'compact'\n /** Whether the card can be clicked/tapped to navigate to product details */\n touchable?: boolean\n /** Optional text to display in a badge on the card */\n badgeText?: string\n /** Visual style variant for the badge */\n badgeVariant?: 'primary' | 'secondary' | 'destructive' | 'outline' | 'none'\n /** Callback fired when the product is clicked */\n onProductClick?: () => void\n /** Callback fired when the favorite button is toggled */\n onFavoriteToggled?: (isFavorited: boolean) => void\n /** Custom layout via children */\n children?: React.ReactNode\n}\n\nfunction ProductCard({\n product,\n selectedProductVariant,\n variant = 'default',\n touchable = true,\n badgeText,\n badgeVariant,\n onProductClick,\n onFavoriteToggled,\n children,\n}: ProductCardProps) {\n const {navigateToProduct} = useShopNavigation()\n const {saveProduct, unsaveProduct} = useSavedProductsActions()\n\n // Local state for optimistic UI updates\n const [isFavoritedLocal, setIsFavoritedLocal] = useState(product.isFavorited)\n\n const handleClick = useCallback(() => {\n if (!touchable) return\n\n onProductClick?.()\n\n navigateToProduct({\n productId: product.id,\n })\n }, [navigateToProduct, product.id, touchable, onProductClick])\n\n const handleFavoriteClick = useCallback(async () => {\n const previousState = isFavoritedLocal\n\n // Optimistic update\n setIsFavoritedLocal(!previousState)\n onFavoriteToggled?.(!previousState)\n\n try {\n if (previousState) {\n await unsaveProduct({\n productId: product.id,\n shopId: product.shop.id,\n productVariantId:\n selectedProductVariant?.id || product.defaultVariantId,\n })\n } else {\n await saveProduct({\n productId: product.id,\n shopId: product.shop.id,\n productVariantId:\n selectedProductVariant?.id || product.defaultVariantId,\n })\n }\n } catch (error) {\n // Revert optimistic update on error\n setIsFavoritedLocal(previousState)\n onFavoriteToggled?.(previousState)\n }\n }, [\n isFavoritedLocal,\n product.id,\n product.shop.id,\n product.defaultVariantId,\n selectedProductVariant?.id,\n saveProduct,\n unsaveProduct,\n onFavoriteToggled,\n ])\n\n const contextValue = useMemo<ProductCardContextValue>(\n () => ({\n // Core data\n product,\n selectedProductVariant,\n\n // UI configuration\n variant,\n touchable,\n badgeText,\n badgeVariant,\n\n // State\n isFavorited: isFavoritedLocal,\n\n // Actions\n onClick: handleClick,\n onFavoriteToggle: handleFavoriteClick,\n }),\n [\n product,\n selectedProductVariant,\n variant,\n touchable,\n badgeText,\n badgeVariant,\n isFavoritedLocal,\n handleClick,\n handleFavoriteClick,\n ]\n )\n\n return (\n <ProductCardContext.Provider value={contextValue}>\n {children ?? (\n <ProductCardContainer>\n <ProductCardImageContainer>\n <ProductCardImage />\n {variant === 'priceOverlay' && <ProductCardPriceOverlayBadge />}\n <ProductCardBadge />\n <ProductCardFavoriteButton />\n </ProductCardImageContainer>\n {variant === 'default' && (\n <ProductCardInfo>\n <ProductCardTitle />\n <ProductCardPrice />\n </ProductCardInfo>\n )}\n </ProductCardContainer>\n )}\n </ProductCardContext.Provider>\n )\n}\n\nexport {\n ProductCard,\n ProductCardContainer,\n ProductCardImageContainer,\n ProductCardImage,\n ProductCardBadge,\n ProductCardFavoriteButton,\n ProductCardInfo,\n ProductCardTitle,\n ProductCardPrice,\n}\n"],"names":["ProductCardContext","React","useProductCardContext","context","useContext","ProductCardContainer","className","props","touchable","onClick","content","jsx","cn","Touchable","ProductCardImageContainer","variant","ProductCardImage","product","selectedProductVariant","displayImage","src","alt","thumbhash","renderImageElement","useCallback","Image","ProductCardBadge","position","children","badgeText","badgeVariant","Badge","ProductCardFavoriteButton","isFavorited","onFavoriteToggle","FavoriteButton","ProductCardInfo","ProductCardTitle","ProductCardPrice","displayPrice","displayCompareAtPrice","ProductVariantPrice","ProductCardPriceOverlayBadge","currencyCode","amount","formatMoney","ProductCard","onProductClick","onFavoriteToggled","navigateToProduct","useShopNavigation","saveProduct","unsaveProduct","useSavedProductsActions","isFavoritedLocal","setIsFavoritedLocal","useState","handleClick","handleFavoriteClick","previousState","contextValue","useMemo","jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"product-card.js","sources":["../../../src/components/commerce/product-card.tsx"],"sourcesContent":["import * as React from 'react'\nimport {useCallback, useContext, useMemo, useState} from 'react'\n\nimport {type Product, type ProductVariant} from '@shopify/shop-minis-platform'\n\nimport {useShopNavigation} from '../../hooks/navigation/useShopNavigation'\nimport {useSavedProductsActions} from '../../hooks/user/useSavedProductsActions'\nimport {formatMoney} from '../../lib/formatMoney'\nimport {cn} from '../../lib/utils'\nimport {Image} from '../atoms/image'\nimport {ProductVariantPrice} from '../atoms/product-variant-price'\nimport {Touchable} from '../atoms/touchable'\nimport {Badge} from '../ui/badge'\n\nimport {FavoriteButton} from './favorite-button'\n\n// Context definition\ninterface ProductCardContextValue {\n // Core data\n product: Product\n selectedProductVariant?: ProductVariant\n\n // UI configuration\n variant: 'default' | 'priceOverlay' | 'compact'\n touchable: boolean\n badgeText?: string\n badgeVariant?: 'primary' | 'secondary' | 'destructive' | 'outline' | 'none'\n\n // State\n isFavorited: boolean\n\n // Actions\n onClick: () => void\n onFavoriteToggle: () => void\n}\n\nconst ProductCardContext = React.createContext<\n ProductCardContextValue | undefined\n>(undefined)\n\nfunction useProductCardContext() {\n const context = useContext(ProductCardContext)\n if (!context) {\n throw new Error(\n 'ProductCard components must be used within a ProductCard provider'\n )\n }\n return context\n}\n\n// Primitive components (building blocks)\nfunction ProductCardContainer({\n className,\n ...props\n}: React.ComponentProps<'div'>) {\n const {touchable, onClick} = useProductCardContext()\n\n const content = (\n <div\n className={cn(\n 'relative w-full overflow-hidden rounded-xl border-0',\n className\n )}\n {...props}\n />\n )\n\n if (touchable && onClick) {\n return (\n <Touchable\n onClick={onClick}\n whileTap={{opacity: 0.7}}\n transition={{\n opacity: {type: 'tween', duration: 0.08, ease: 'easeInOut'},\n }}\n >\n {content}\n </Touchable>\n )\n }\n\n return content\n}\n\nfunction ProductCardImageContainer({\n className,\n ...props\n}: React.ComponentProps<'div'>) {\n const {variant} = useProductCardContext()\n\n return (\n <div\n data-slot=\"product-card-image-container\"\n className={cn(\n // Ensure the product image is stretched to the full size of the container (can't use width/height: 100% because of flex)\n 'flex justify-stretch items-stretch',\n 'relative overflow-hidden rounded-xl border border-gray-200',\n 'w-full aspect-square',\n variant === 'compact' ? 'min-h-[104px]' : 'min-h-[134px]',\n className\n )}\n {...props}\n />\n )\n}\n\nfunction ProductCardImage({className, ...props}: React.ComponentProps<'img'>) {\n const {product, selectedProductVariant} = useProductCardContext()\n\n // Derive display image locally\n const displayImage = selectedProductVariant?.image || product.featuredImage\n const src = displayImage?.url\n const alt = displayImage?.altText || product.title\n const thumbhash = product.featuredImage?.thumbhash\n\n const renderImageElement = useCallback(\n (src: string) => {\n const imageElement = thumbhash ? (\n <Image\n data-slot=\"product-card-image\"\n src={src}\n alt={alt}\n aspectRatio={1}\n thumbhash={thumbhash}\n className={cn('size-full object-cover', className)}\n {...props}\n />\n ) : (\n <img\n data-slot=\"product-card-image\"\n src={src}\n alt={alt}\n className={cn('size-full', className)}\n {...props}\n />\n )\n\n return imageElement\n },\n [alt, className, props, thumbhash]\n )\n\n return (\n <div className=\"bg-gray-100 flex items-center justify-center size-full\">\n {src ? (\n renderImageElement(src)\n ) : (\n <div className=\"text-gray-400 text-sm w-full text-center\">No Image</div>\n )}\n </div>\n )\n}\n\nfunction ProductCardBadge({\n className,\n position = 'bottom-left',\n variant,\n children,\n ...props\n}: React.ComponentProps<typeof Badge> & {\n position?: 'top-left' | 'bottom-left'\n}) {\n const {badgeText, badgeVariant} = useProductCardContext()\n // If no children provided, use badgeText from context\n const content = children || badgeText\n\n if (!content) return null\n\n return (\n <div\n className={cn(\n 'absolute z-10',\n position === 'top-left' ? 'top-3 left-3' : 'bottom-2 left-2'\n )}\n >\n <Badge\n variant={variant ?? badgeVariant ?? 'none'}\n className={cn(\n !badgeVariant &&\n !variant &&\n 'bg-black/50 text-white border-transparent',\n 'rounded',\n className\n )}\n {...props}\n >\n {content}\n </Badge>\n </div>\n )\n}\n\nfunction ProductCardFavoriteButton({\n className,\n ...props\n}: React.ComponentProps<'div'>) {\n const {isFavorited, onFavoriteToggle} = useProductCardContext()\n return (\n <div className={cn('absolute bottom-3 right-3 z-10', className)} {...props}>\n <FavoriteButton onClick={onFavoriteToggle} filled={isFavorited} />\n </div>\n )\n}\n\nfunction ProductCardInfo({className, ...props}: React.ComponentProps<'div'>) {\n const {variant} = useProductCardContext()\n if (variant !== 'default') {\n return null\n }\n\n return (\n <div\n data-slot=\"product-card-info\"\n className={cn('px-1 pt-2 pb-0 space-y-1', className)}\n {...props}\n />\n )\n}\n\nfunction ProductCardTitle({\n className,\n children,\n ...props\n}: React.ComponentProps<'h3'>) {\n const {product} = useProductCardContext()\n return (\n <h3\n data-slot=\"product-card-title\"\n className={cn(\n 'text-sm font-medium leading-tight text-gray-900',\n 'truncate overflow-hidden whitespace-nowrap text-ellipsis',\n className\n )}\n {...props}\n >\n {children || product.title}\n </h3>\n )\n}\n\nfunction ProductCardPrice({className}: {className?: string}) {\n const {product, selectedProductVariant} = useProductCardContext()\n\n // Derive price data locally\n const displayPrice = selectedProductVariant?.price || product?.price\n const displayCompareAtPrice =\n selectedProductVariant?.compareAtPrice || product?.compareAtPrice\n\n return (\n <ProductVariantPrice\n amount={displayPrice?.amount || ''}\n currencyCode={displayPrice?.currencyCode || ''}\n compareAtPriceAmount={displayCompareAtPrice?.amount}\n compareAtPriceCurrencyCode={displayCompareAtPrice?.currencyCode}\n className={className}\n />\n )\n}\n\n// Special PriceOverlayBadge for price overlay variant\nfunction ProductCardPriceOverlayBadge() {\n const {product, selectedProductVariant, variant} = useProductCardContext()\n if (variant !== 'priceOverlay') return null\n const displayPrice = selectedProductVariant?.price || product.price\n const currencyCode = displayPrice?.currencyCode\n const amount = displayPrice?.amount\n\n if (!currencyCode || !amount) return null\n return (\n <ProductCardBadge position=\"top-left\">\n {formatMoney(amount, currencyCode)}\n </ProductCardBadge>\n )\n}\n\nexport interface ProductCardProps {\n /** The product to display in the card */\n product: Product\n /** Optional selected variant of the product to show specific variant data */\n selectedProductVariant?: ProductVariant\n /** Visual style variant of the card */\n variant?: 'default' | 'priceOverlay' | 'compact'\n /** Whether the card can be clicked/tapped to navigate to product details */\n touchable?: boolean\n /** Optional text to display in a badge on the card */\n badgeText?: string\n /** Visual style variant for the badge */\n badgeVariant?: 'primary' | 'secondary' | 'destructive' | 'outline' | 'none'\n /** Callback fired when the product is clicked */\n onProductClick?: () => void\n /** Callback fired when the favorite button is toggled */\n onFavoriteToggled?: (isFavorited: boolean) => void\n /** Custom layout via children */\n children?: React.ReactNode\n}\n\nfunction ProductCard({\n product,\n selectedProductVariant,\n variant = 'default',\n touchable = true,\n badgeText,\n badgeVariant,\n onProductClick,\n onFavoriteToggled,\n children,\n}: ProductCardProps) {\n const {navigateToProduct} = useShopNavigation()\n const {saveProduct, unsaveProduct} = useSavedProductsActions()\n\n // Local state for optimistic UI updates\n const [isFavoritedLocal, setIsFavoritedLocal] = useState(product.isFavorited)\n\n const handleClick = useCallback(() => {\n if (!touchable) return\n\n onProductClick?.()\n\n navigateToProduct({\n productId: product.id,\n })\n }, [navigateToProduct, product.id, touchable, onProductClick])\n\n const handleFavoriteClick = useCallback(async () => {\n const previousState = isFavoritedLocal\n\n // Optimistic update\n setIsFavoritedLocal(!previousState)\n onFavoriteToggled?.(!previousState)\n\n try {\n if (previousState) {\n await unsaveProduct({\n productId: product.id,\n shopId: product.shop.id,\n productVariantId:\n selectedProductVariant?.id || product.defaultVariantId,\n })\n } else {\n await saveProduct({\n productId: product.id,\n shopId: product.shop.id,\n productVariantId:\n selectedProductVariant?.id || product.defaultVariantId,\n })\n }\n } catch (error) {\n // Revert optimistic update on error\n setIsFavoritedLocal(previousState)\n onFavoriteToggled?.(previousState)\n }\n }, [\n isFavoritedLocal,\n product.id,\n product.shop.id,\n product.defaultVariantId,\n selectedProductVariant?.id,\n saveProduct,\n unsaveProduct,\n onFavoriteToggled,\n ])\n\n const contextValue = useMemo<ProductCardContextValue>(\n () => ({\n // Core data\n product,\n selectedProductVariant,\n\n // UI configuration\n variant,\n touchable,\n badgeText,\n badgeVariant,\n\n // State\n isFavorited: isFavoritedLocal,\n\n // Actions\n onClick: handleClick,\n onFavoriteToggle: handleFavoriteClick,\n }),\n [\n product,\n selectedProductVariant,\n variant,\n touchable,\n badgeText,\n badgeVariant,\n isFavoritedLocal,\n handleClick,\n handleFavoriteClick,\n ]\n )\n\n return (\n <ProductCardContext.Provider value={contextValue}>\n {children ?? (\n <ProductCardContainer>\n <ProductCardImageContainer>\n <ProductCardImage />\n {variant === 'priceOverlay' && <ProductCardPriceOverlayBadge />}\n <ProductCardBadge />\n <ProductCardFavoriteButton />\n </ProductCardImageContainer>\n {variant === 'default' && (\n <ProductCardInfo>\n <ProductCardTitle />\n <ProductCardPrice />\n </ProductCardInfo>\n )}\n </ProductCardContainer>\n )}\n </ProductCardContext.Provider>\n )\n}\n\nexport {\n ProductCard,\n ProductCardContainer,\n ProductCardImageContainer,\n ProductCardImage,\n ProductCardBadge,\n ProductCardFavoriteButton,\n ProductCardInfo,\n ProductCardTitle,\n ProductCardPrice,\n}\n"],"names":["ProductCardContext","React","useProductCardContext","context","useContext","ProductCardContainer","className","props","touchable","onClick","content","jsx","cn","Touchable","ProductCardImageContainer","variant","ProductCardImage","product","selectedProductVariant","displayImage","src","alt","thumbhash","renderImageElement","useCallback","Image","ProductCardBadge","position","children","badgeText","badgeVariant","Badge","ProductCardFavoriteButton","isFavorited","onFavoriteToggle","FavoriteButton","ProductCardInfo","ProductCardTitle","ProductCardPrice","displayPrice","displayCompareAtPrice","ProductVariantPrice","ProductCardPriceOverlayBadge","currencyCode","amount","formatMoney","ProductCard","onProductClick","onFavoriteToggled","navigateToProduct","useShopNavigation","saveProduct","unsaveProduct","useSavedProductsActions","isFavoritedLocal","setIsFavoritedLocal","useState","handleClick","handleFavoriteClick","previousState","contextValue","useMemo","jsxs"],"mappings":"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"}
|
|
@@ -5,9 +5,9 @@ import { useShopNavigation as M } from "../../hooks/navigation/useShopNavigation
|
|
|
5
5
|
import { useSavedProductsActions as D } from "../../hooks/user/useSavedProductsActions.js";
|
|
6
6
|
import { formatMoney as z } from "../../lib/formatMoney.js";
|
|
7
7
|
import { cn as n } from "../../lib/utils.js";
|
|
8
|
-
import { FavoriteButton as q } from "../atoms/favorite-button.js";
|
|
9
8
|
import { Touchable as T } from "../atoms/touchable.js";
|
|
10
|
-
import { Card as
|
|
9
|
+
import { Card as q, CardContent as B, CardAction as U } from "../ui/card.js";
|
|
10
|
+
import { FavoriteButton as _ } from "./favorite-button.js";
|
|
11
11
|
import E from "../../shop-minis-react/node_modules/.pnpm/lucide-react@0.513.0_react@19.1.0/node_modules/lucide-react/dist/esm/icons/star.js";
|
|
12
12
|
import { Root as G } from "../../shop-minis-react/node_modules/.pnpm/@radix-ui_react-slot@1.2.3_@types_react@19.1.6_react@19.1.0/node_modules/@radix-ui/react-slot/dist/index.js";
|
|
13
13
|
const H = O("", {
|
|
@@ -44,7 +44,7 @@ function J({
|
|
|
44
44
|
opacity: { type: "tween", duration: 0.08, ease: "easeInOut" }
|
|
45
45
|
},
|
|
46
46
|
children: /* @__PURE__ */ t(
|
|
47
|
-
a ? G :
|
|
47
|
+
a ? G : q,
|
|
48
48
|
{
|
|
49
49
|
className: n(
|
|
50
50
|
H({ layout: o, discount: r }),
|
|
@@ -81,7 +81,7 @@ function Q({
|
|
|
81
81
|
...r
|
|
82
82
|
}) {
|
|
83
83
|
return /* @__PURE__ */ t(
|
|
84
|
-
|
|
84
|
+
B,
|
|
85
85
|
{
|
|
86
86
|
className: n(
|
|
87
87
|
o === "horizontal" ? "flex-1 min-w-0 space-y-1 px-0 py-0" : "space-y-2",
|
|
@@ -178,7 +178,7 @@ function et({
|
|
|
178
178
|
...a
|
|
179
179
|
}) {
|
|
180
180
|
return /* @__PURE__ */ t(
|
|
181
|
-
|
|
181
|
+
U,
|
|
182
182
|
{
|
|
183
183
|
className: n("flex-shrink-0 self-center px-0 py-0", e),
|
|
184
184
|
...a,
|
|
@@ -192,7 +192,7 @@ function et({
|
|
|
192
192
|
opacity: { type: "tween", duration: 0.08, ease: "easeInOut" },
|
|
193
193
|
scale: { type: "tween", duration: 0.08, ease: "easeInOut" }
|
|
194
194
|
},
|
|
195
|
-
children: /* @__PURE__ */ t(
|
|
195
|
+
children: /* @__PURE__ */ t(_, { filled: r, onClick: o })
|
|
196
196
|
}
|
|
197
197
|
)
|
|
198
198
|
}
|