@shopify/shop-minis-react 0.0.17 → 0.0.19
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/index3.js +6 -0
- package/dist/_virtual/index3.js.map +1 -0
- package/dist/_virtual/index4.js +5 -0
- package/dist/_virtual/index4.js.map +1 -0
- package/dist/_virtual/use-sync-external-store-shim.development.js +5 -0
- package/dist/_virtual/use-sync-external-store-shim.development.js.map +1 -0
- package/dist/_virtual/use-sync-external-store-shim.production.js +5 -0
- package/dist/_virtual/use-sync-external-store-shim.production.js.map +1 -0
- package/dist/components/atoms/alert-dialog.js +41 -0
- package/dist/components/atoms/alert-dialog.js.map +1 -0
- package/dist/components/atoms/thumbhash-image.js +54 -0
- package/dist/components/atoms/thumbhash-image.js.map +1 -0
- package/dist/components/commerce/merchant-card-skeleton.js +29 -0
- package/dist/components/commerce/merchant-card-skeleton.js.map +1 -0
- package/dist/components/commerce/merchant-card.js +28 -22
- package/dist/components/commerce/merchant-card.js.map +1 -1
- package/dist/components/commerce/product-card-skeleton.js +20 -0
- package/dist/components/commerce/product-card-skeleton.js.map +1 -0
- package/dist/components/commerce/product-card.js +105 -78
- package/dist/components/commerce/product-card.js.map +1 -1
- package/dist/components/navigation/transition-container.js +8 -0
- package/dist/components/navigation/transition-container.js.map +1 -0
- package/dist/components/navigation/transition-link.js +27 -0
- package/dist/components/navigation/transition-link.js.map +1 -0
- package/dist/components/ui/avatar.js +54 -0
- package/dist/components/ui/avatar.js.map +1 -0
- package/dist/components/ui/skeleton.js +16 -0
- package/dist/components/ui/skeleton.js.map +1 -0
- package/dist/hooks/navigation/useNavigateWithTransition.js +43 -0
- package/dist/hooks/navigation/useNavigateWithTransition.js.map +1 -0
- package/dist/hooks/navigation/useViewTransitions.js +45 -0
- package/dist/hooks/navigation/useViewTransitions.js.map +1 -0
- package/dist/index.js +215 -192
- package/dist/index.js.map +1 -1
- package/dist/shop-minis-react/node_modules/.pnpm/@radix-ui_react-avatar@1.1.10_@types_react-dom@19.1.6_@types_react@19.1.6__@types_react@19.1._hkz57sehyui4ndfh3rsqwxftli/node_modules/@radix-ui/react-avatar/dist/index.js +77 -0
- package/dist/shop-minis-react/node_modules/.pnpm/@radix-ui_react-avatar@1.1.10_@types_react-dom@19.1.6_@types_react@19.1.6__@types_react@19.1._hkz57sehyui4ndfh3rsqwxftli/node_modules/@radix-ui/react-avatar/dist/index.js.map +1 -0
- 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 +16 -0
- 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.map +1 -0
- package/dist/shop-minis-react/node_modules/.pnpm/js-base64@3.7.7/node_modules/js-base64/base64.js +21 -0
- package/dist/shop-minis-react/node_modules/.pnpm/js-base64@3.7.7/node_modules/js-base64/base64.js.map +1 -0
- package/dist/shop-minis-react/node_modules/.pnpm/react-router@7.7.0_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-router/dist/development/chunk-EF7DTUVF.js +1298 -0
- package/dist/shop-minis-react/node_modules/.pnpm/react-router@7.7.0_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-router/dist/development/chunk-EF7DTUVF.js.map +1 -0
- package/dist/shop-minis-react/node_modules/.pnpm/thumbhash@0.1.1/node_modules/thumbhash/thumbhash.js +145 -0
- package/dist/shop-minis-react/node_modules/.pnpm/thumbhash@0.1.1/node_modules/thumbhash/thumbhash.js.map +1 -0
- 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/cjs/use-sync-external-store-shim.development.js +68 -0
- 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/cjs/use-sync-external-store-shim.development.js.map +1 -0
- 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/cjs/use-sync-external-store-shim.production.js +56 -0
- 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/cjs/use-sync-external-store-shim.production.js.map +1 -0
- 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 +11 -0
- 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.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/image.js +15 -0
- package/dist/utils/image.js.map +1 -0
- package/package.json +13 -3
- package/src/components/atoms/alert-dialog.tsx +67 -0
- package/src/components/atoms/thumbhash-image.tsx +66 -0
- package/src/components/commerce/merchant-card-skeleton.tsx +31 -0
- package/src/components/commerce/merchant-card.tsx +5 -2
- package/src/components/commerce/product-card-skeleton.tsx +30 -0
- package/src/components/commerce/product-card.tsx +49 -8
- package/src/components/index.ts +9 -0
- package/src/components/navigation/transition-container.tsx +7 -0
- package/src/components/navigation/transition-link.tsx +48 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/navigation/useNavigateWithTransition.ts +62 -0
- package/src/hooks/navigation/useViewTransitions.ts +79 -0
- package/src/index.css +1 -0
- package/src/mocks.ts +8 -2
- package/src/stories/Accordion.stories.tsx +124 -0
- package/src/stories/Alert.stories.tsx +38 -0
- package/src/stories/AlertDialog.stories.tsx +48 -0
- package/src/stories/Avatar.stories.tsx +29 -0
- package/src/stories/Badge.stories.tsx +46 -0
- package/src/stories/Button.stories.tsx +81 -0
- package/src/stories/Card.stories.tsx +40 -0
- package/src/stories/Checkbox.stories.tsx +44 -0
- package/src/stories/FavoriteButton.stories.tsx +58 -0
- package/src/stories/IconButton.stories.tsx +68 -0
- package/src/stories/Input.stories.tsx +44 -0
- package/src/stories/Label.stories.tsx +19 -0
- package/src/stories/MerchantCard.stories.tsx +55 -0
- package/src/stories/ProductCard.stories.tsx +85 -0
- package/src/stories/ProductLink.stories.tsx +46 -0
- package/src/stories/Progress.stories.tsx +30 -0
- package/src/stories/RadioGroup.stories.tsx +51 -0
- package/src/stories/Select.stories.tsx +85 -0
- package/src/stories/Skeleton.stories.tsx +19 -0
- package/src/stories/Toaster.stories.tsx +46 -0
- package/src/stories/Touchable.stories.tsx +40 -0
- package/src/styles/animations.css +90 -0
- package/src/styles/globals.css +8 -0
- package/src/styles/theme.css +1 -1
- package/src/types/index.ts +7 -1
- package/src/utils/image.ts +18 -0
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { jsxs as p, jsx as r, Fragment as
|
|
1
|
+
import { jsxs as p, jsx as r, Fragment as E } from "react/jsx-runtime";
|
|
2
2
|
import * as x from "react";
|
|
3
|
+
import { useCallback as M } from "react";
|
|
3
4
|
import { cva as U } from "../../shop-minis-react/node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.js";
|
|
4
|
-
import { useShopNavigation as
|
|
5
|
-
import { useSavedProductsActions as
|
|
6
|
-
import { formatMoney as
|
|
5
|
+
import { useShopNavigation as G } from "../../hooks/navigation/useShopNavigation.js";
|
|
6
|
+
import { useSavedProductsActions as H } from "../../hooks/user/useSavedProductsActions.js";
|
|
7
|
+
import { formatMoney as h } from "../../lib/formatMoney.js";
|
|
7
8
|
import { cn as c } from "../../lib/utils.js";
|
|
8
|
-
import { FavoriteButton as
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
9
|
+
import { FavoriteButton as J } from "../atoms/favorite-button.js";
|
|
10
|
+
import { ThumbhashImage as K } from "../atoms/thumbhash-image.js";
|
|
11
|
+
import { Touchable as Q } from "../atoms/touchable.js";
|
|
12
|
+
import { Badge as V } from "../ui/badge.js";
|
|
13
|
+
import { Root as W } 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";
|
|
14
|
+
const X = U(
|
|
13
15
|
"relative w-full overflow-hidden rounded-xl border border-gray-200",
|
|
14
16
|
{
|
|
15
17
|
variants: {
|
|
@@ -29,27 +31,27 @@ const V = U(
|
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
);
|
|
32
|
-
function
|
|
34
|
+
function Y({
|
|
33
35
|
className: e,
|
|
34
36
|
variant: t,
|
|
35
37
|
touchable: o = !0,
|
|
36
38
|
asChild: a = !1,
|
|
37
39
|
onPress: i,
|
|
38
|
-
...
|
|
40
|
+
...d
|
|
39
41
|
}) {
|
|
40
42
|
const n = /* @__PURE__ */ r(
|
|
41
|
-
a ?
|
|
43
|
+
a ? W : "div",
|
|
42
44
|
{
|
|
43
45
|
className: c(
|
|
44
|
-
|
|
46
|
+
X({ variant: t, touchable: o }),
|
|
45
47
|
"border-0",
|
|
46
48
|
e
|
|
47
49
|
),
|
|
48
|
-
...
|
|
50
|
+
...d
|
|
49
51
|
}
|
|
50
52
|
);
|
|
51
53
|
return o && i ? /* @__PURE__ */ r(
|
|
52
|
-
|
|
54
|
+
Q,
|
|
53
55
|
{
|
|
54
56
|
onClick: i,
|
|
55
57
|
whileTap: { opacity: 0.7 },
|
|
@@ -60,7 +62,7 @@ function W({
|
|
|
60
62
|
}
|
|
61
63
|
) : n;
|
|
62
64
|
}
|
|
63
|
-
function
|
|
65
|
+
function Z({
|
|
64
66
|
className: e,
|
|
65
67
|
variant: t = "default",
|
|
66
68
|
...o
|
|
@@ -73,7 +75,7 @@ function X({
|
|
|
73
75
|
// Ensure the product image is stretched to the full size of the container (can't use width/height: 100% because of flex)
|
|
74
76
|
"flex justify-stretch items-stretch",
|
|
75
77
|
"relative overflow-hidden rounded-xl border border-gray-200",
|
|
76
|
-
"w-full
|
|
78
|
+
"w-full aspect-square",
|
|
77
79
|
t === "compact" ? "min-h-[104px]" : "min-h-[134px]",
|
|
78
80
|
e
|
|
79
81
|
),
|
|
@@ -81,24 +83,41 @@ function X({
|
|
|
81
83
|
}
|
|
82
84
|
);
|
|
83
85
|
}
|
|
84
|
-
function
|
|
86
|
+
function _({
|
|
85
87
|
className: e,
|
|
86
88
|
src: t,
|
|
87
89
|
alt: o,
|
|
88
|
-
|
|
90
|
+
aspectRatio: a,
|
|
91
|
+
thumbhash: i,
|
|
92
|
+
...d
|
|
89
93
|
}) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
94
|
+
const s = M(
|
|
95
|
+
(n) => i ? /* @__PURE__ */ r(
|
|
96
|
+
K,
|
|
97
|
+
{
|
|
98
|
+
"data-slot": "product-card-image",
|
|
99
|
+
src: n,
|
|
100
|
+
alt: o,
|
|
101
|
+
aspectRatio: a,
|
|
102
|
+
thumbhash: i,
|
|
103
|
+
className: c("w-full h-full object-cover", e),
|
|
104
|
+
...d
|
|
105
|
+
}
|
|
106
|
+
) : /* @__PURE__ */ r(
|
|
107
|
+
"img",
|
|
108
|
+
{
|
|
109
|
+
"data-slot": "product-card-image",
|
|
110
|
+
src: n,
|
|
111
|
+
alt: o,
|
|
112
|
+
className: c("w-full h-full", e),
|
|
113
|
+
...d
|
|
114
|
+
}
|
|
115
|
+
),
|
|
116
|
+
[o, a, e, d, i]
|
|
117
|
+
);
|
|
118
|
+
return /* @__PURE__ */ r("div", { className: "bg-gray-100 flex items-center justify-center w-full h-full", children: t ? s(t) : /* @__PURE__ */ r("div", { className: "text-gray-400 text-sm w-full text-center", children: "No Image" }) });
|
|
100
119
|
}
|
|
101
|
-
function
|
|
120
|
+
function F({
|
|
102
121
|
className: e,
|
|
103
122
|
position: t = "bottom-left",
|
|
104
123
|
children: o,
|
|
@@ -112,7 +131,7 @@ function k({
|
|
|
112
131
|
t === "top-left" ? "top-3 left-3" : "bottom-2 left-2"
|
|
113
132
|
),
|
|
114
133
|
children: /* @__PURE__ */ r(
|
|
115
|
-
|
|
134
|
+
V,
|
|
116
135
|
{
|
|
117
136
|
className: c("bg-black/50 text-white rounded", e),
|
|
118
137
|
...a,
|
|
@@ -122,15 +141,15 @@ function k({
|
|
|
122
141
|
}
|
|
123
142
|
);
|
|
124
143
|
}
|
|
125
|
-
function
|
|
144
|
+
function $({
|
|
126
145
|
className: e,
|
|
127
146
|
onPress: t,
|
|
128
147
|
filled: o = !1,
|
|
129
148
|
...a
|
|
130
149
|
}) {
|
|
131
|
-
return /* @__PURE__ */ r("div", { className: c("absolute bottom-3 right-3 z-10", e), ...a, children: /* @__PURE__ */ r(
|
|
150
|
+
return /* @__PURE__ */ r("div", { className: c("absolute bottom-3 right-3 z-10", e), ...a, children: /* @__PURE__ */ r(J, { onClick: t, filled: o }) });
|
|
132
151
|
}
|
|
133
|
-
function
|
|
152
|
+
function tt({
|
|
134
153
|
className: e,
|
|
135
154
|
variant: t = "default",
|
|
136
155
|
...o
|
|
@@ -144,7 +163,7 @@ function _({
|
|
|
144
163
|
}
|
|
145
164
|
);
|
|
146
165
|
}
|
|
147
|
-
function
|
|
166
|
+
function rt({
|
|
148
167
|
className: e,
|
|
149
168
|
children: t,
|
|
150
169
|
...o
|
|
@@ -163,7 +182,7 @@ function $({
|
|
|
163
182
|
}
|
|
164
183
|
);
|
|
165
184
|
}
|
|
166
|
-
function
|
|
185
|
+
function et({ className: e, ...t }) {
|
|
167
186
|
return /* @__PURE__ */ r(
|
|
168
187
|
"div",
|
|
169
188
|
{
|
|
@@ -173,7 +192,7 @@ function tt({ className: e, ...t }) {
|
|
|
173
192
|
}
|
|
174
193
|
);
|
|
175
194
|
}
|
|
176
|
-
function
|
|
195
|
+
function S({
|
|
177
196
|
className: e,
|
|
178
197
|
...t
|
|
179
198
|
}) {
|
|
@@ -186,7 +205,7 @@ function F({
|
|
|
186
205
|
}
|
|
187
206
|
);
|
|
188
207
|
}
|
|
189
|
-
function
|
|
208
|
+
function ot({
|
|
190
209
|
className: e,
|
|
191
210
|
...t
|
|
192
211
|
}) {
|
|
@@ -199,88 +218,96 @@ function rt({
|
|
|
199
218
|
}
|
|
200
219
|
);
|
|
201
220
|
}
|
|
202
|
-
function
|
|
221
|
+
function vt({
|
|
203
222
|
product: e,
|
|
204
223
|
selectedProductVariant: t,
|
|
205
224
|
variant: o = "default",
|
|
206
225
|
touchable: a = !0,
|
|
207
226
|
badgeText: i,
|
|
208
|
-
badgeVariant:
|
|
209
|
-
onFavoriteToggled:
|
|
227
|
+
badgeVariant: d = "secondary",
|
|
228
|
+
onFavoriteToggled: s
|
|
210
229
|
}) {
|
|
211
|
-
const { navigateToProduct: n } =
|
|
212
|
-
id:
|
|
230
|
+
const { navigateToProduct: n } = G(), { saveProduct: P, unsaveProduct: b } = H(), {
|
|
231
|
+
id: l,
|
|
213
232
|
title: I,
|
|
214
|
-
featuredImage:
|
|
233
|
+
featuredImage: w,
|
|
215
234
|
price: B,
|
|
216
235
|
compareAtPrice: O,
|
|
217
|
-
isFavorited:
|
|
218
|
-
defaultVariantId:
|
|
219
|
-
shop:
|
|
220
|
-
} = e, N = t?.image ||
|
|
236
|
+
isFavorited: T,
|
|
237
|
+
defaultVariantId: g,
|
|
238
|
+
shop: v
|
|
239
|
+
} = e, N = t?.image || w, A = t?.price || B, k = t?.compareAtPrice || O, [y, j] = x.useState(T), u = A?.currencyCode, m = A?.amount, R = N?.url, z = N?.altText || I, C = k?.amount, L = C && C !== m, q = x.useCallback(() => {
|
|
221
240
|
a && n({
|
|
222
|
-
productId:
|
|
241
|
+
productId: l
|
|
223
242
|
});
|
|
224
|
-
}, [n,
|
|
225
|
-
const
|
|
226
|
-
j(!
|
|
243
|
+
}, [n, l, a]), D = x.useCallback(async () => {
|
|
244
|
+
const f = y;
|
|
245
|
+
j(!f), s?.(!f);
|
|
227
246
|
try {
|
|
228
|
-
|
|
229
|
-
productId:
|
|
230
|
-
shopId:
|
|
231
|
-
productVariantId: t?.id ||
|
|
247
|
+
f ? await b({
|
|
248
|
+
productId: l,
|
|
249
|
+
shopId: v.id,
|
|
250
|
+
productVariantId: t?.id || g
|
|
232
251
|
}) : await P({
|
|
233
|
-
productId:
|
|
234
|
-
shopId:
|
|
235
|
-
productVariantId: t?.id ||
|
|
252
|
+
productId: l,
|
|
253
|
+
shopId: v.id,
|
|
254
|
+
productVariantId: t?.id || g
|
|
236
255
|
});
|
|
237
256
|
} catch {
|
|
238
|
-
j(
|
|
257
|
+
j(f), s?.(f);
|
|
239
258
|
}
|
|
240
259
|
}, [
|
|
241
260
|
y,
|
|
242
|
-
|
|
243
|
-
|
|
261
|
+
l,
|
|
262
|
+
v.id,
|
|
244
263
|
t?.id,
|
|
245
|
-
|
|
264
|
+
g,
|
|
246
265
|
P,
|
|
247
266
|
b,
|
|
248
|
-
|
|
267
|
+
s
|
|
249
268
|
]);
|
|
250
269
|
return /* @__PURE__ */ p(
|
|
251
|
-
|
|
270
|
+
Y,
|
|
252
271
|
{
|
|
253
272
|
variant: o,
|
|
254
273
|
touchable: a,
|
|
255
274
|
onPress: q,
|
|
256
275
|
children: [
|
|
257
|
-
/* @__PURE__ */ p(
|
|
258
|
-
/* @__PURE__ */ r(
|
|
259
|
-
|
|
260
|
-
|
|
276
|
+
/* @__PURE__ */ p(Z, { variant: o, children: [
|
|
277
|
+
/* @__PURE__ */ r(
|
|
278
|
+
_,
|
|
279
|
+
{
|
|
280
|
+
src: R,
|
|
281
|
+
alt: z,
|
|
282
|
+
aspectRatio: 1,
|
|
283
|
+
thumbhash: w?.thumbhash ?? void 0
|
|
284
|
+
}
|
|
285
|
+
),
|
|
286
|
+
o === "priceOverlay" && u && m && /* @__PURE__ */ r(F, { position: "top-left", children: h(m, u) }),
|
|
287
|
+
i && /* @__PURE__ */ r(F, { position: "bottom-left", variant: d, children: i }),
|
|
261
288
|
/* @__PURE__ */ r(
|
|
262
|
-
|
|
289
|
+
$,
|
|
263
290
|
{
|
|
264
291
|
filled: y,
|
|
265
292
|
onPress: D
|
|
266
293
|
}
|
|
267
294
|
)
|
|
268
295
|
] }),
|
|
269
|
-
/* @__PURE__ */ p(
|
|
270
|
-
/* @__PURE__ */ r(
|
|
271
|
-
/* @__PURE__ */ r(
|
|
272
|
-
/* @__PURE__ */ r(
|
|
273
|
-
/* @__PURE__ */ r(
|
|
296
|
+
/* @__PURE__ */ p(tt, { variant: o, children: [
|
|
297
|
+
/* @__PURE__ */ r(rt, { children: I }),
|
|
298
|
+
/* @__PURE__ */ r(et, { children: L ? /* @__PURE__ */ p(E, { children: [
|
|
299
|
+
/* @__PURE__ */ r(S, { children: h(m, u) }),
|
|
300
|
+
/* @__PURE__ */ r(ot, { children: h(
|
|
274
301
|
C,
|
|
275
|
-
|
|
302
|
+
k?.currencyCode || u
|
|
276
303
|
) })
|
|
277
|
-
] }) : /* @__PURE__ */ r(
|
|
304
|
+
] }) : /* @__PURE__ */ r(S, { children: h(m, u) }) })
|
|
278
305
|
] })
|
|
279
306
|
]
|
|
280
307
|
}
|
|
281
308
|
);
|
|
282
309
|
}
|
|
283
310
|
export {
|
|
284
|
-
|
|
311
|
+
vt as ProductCard
|
|
285
312
|
};
|
|
286
313
|
//# sourceMappingURL=product-card.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-card.js","sources":["../../../src/components/commerce/product-card.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport {type Product, type ProductVariant} from '@shopify/shop-minis-platform'\nimport {cva, type VariantProps} from 'class-variance-authority'\nimport {Heart} from 'lucide-react'\nimport {Slot as SlotPrimitive} from 'radix-ui'\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 {Touchable} from '../atoms/touchable'\nimport {Badge} from '../ui/badge'\n\nconst productCardVariants = cva(\n 'relative w-full overflow-hidden rounded-xl border border-gray-200',\n {\n variants: {\n variant: {\n default: '',\n priceOverlay: '',\n compact: '',\n },\n touchable: {\n true: 'cursor-pointer',\n false: '',\n },\n },\n defaultVariants: {\n variant: 'default',\n touchable: true,\n },\n }\n)\n\n// Primitive components (building blocks)\nexport interface ProductCardRootProps\n extends React.ComponentProps<'div'>,\n VariantProps<typeof productCardVariants> {\n variant?: 'default' | 'priceOverlay' | 'compact'\n touchable?: boolean\n asChild?: boolean\n onPress?: () => void\n}\n\nfunction ProductCardRoot({\n className,\n variant,\n touchable = true,\n asChild = false,\n onPress,\n ...props\n}: ProductCardRootProps) {\n const Comp = asChild ? SlotPrimitive.Slot : 'div'\n\n const content = (\n <Comp\n className={cn(\n productCardVariants({variant, touchable}),\n 'border-0',\n className\n )}\n {...props}\n />\n )\n\n if (touchable && onPress) {\n return (\n <Touchable\n onClick={onPress}\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 variant = 'default',\n ...props\n}: React.ComponentProps<'div'> & {\n variant?: 'default' | 'priceOverlay' | 'compact'\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({\n className,\n src,\n alt,\n ...props\n}: React.ComponentProps<'img'> & {\n src?: string\n alt?: string\n}) {\n return (\n <div className=\"bg-gray-100 flex items-center justify-center\">\n {src ? (\n <img\n data-slot=\"product-card-image\"\n src={src}\n alt={alt}\n className={cn('w-full h-full object-cover', className)}\n {...props}\n />\n ) : (\n <div className=\"text-gray-400 text-sm\">No Image</div>\n )}\n </div>\n )\n}\n\nfunction ProductCardBadge({\n className,\n position = 'bottom-left',\n children,\n ...props\n}: React.ComponentProps<typeof Badge> & {\n position?: 'top-left' | 'bottom-left'\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 className={cn('bg-black/50 text-white rounded', className)}\n {...props}\n >\n {children}\n </Badge>\n </div>\n )\n}\n\nfunction ProductCardFavoriteButton({\n className,\n onPress,\n filled = false,\n ...props\n}: React.ComponentProps<'div'> & {\n onPress?: () => void\n filled?: boolean\n}) {\n return (\n <div className={cn('absolute bottom-3 right-3 z-10', className)} {...props}>\n <FavoriteButton onClick={onPress} filled={filled} />\n </div>\n )\n}\n\nfunction ProductCardInfo({\n className,\n variant = 'default',\n ...props\n}: React.ComponentProps<'div'> & {\n variant?: 'default' | 'priceOverlay' | 'compact'\n}) {\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 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}\n </h3>\n )\n}\n\nfunction ProductCardPrice({className, ...props}: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"product-card-price\"\n className={cn('flex items-center gap-2', className)}\n {...props}\n />\n )\n}\n\nfunction ProductCardCurrentPrice({\n className,\n ...props\n}: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"product-card-current-price\"\n className={cn('text-sm font-semibold text-gray-900', className)}\n {...props}\n />\n )\n}\n\nfunction ProductCardOriginalPrice({\n className,\n ...props\n}: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"product-card-original-price\"\n className={cn('text-sm text-gray-500 line-through', className)}\n {...props}\n />\n )\n}\n\nexport interface ProductCardProps {\n product: Product\n selectedProductVariant?: ProductVariant\n variant?: 'default' | 'priceOverlay' | 'compact'\n touchable?: boolean\n badgeText?: string\n badgeVariant?: 'default' | 'secondary' | 'destructive' | 'outline'\n onFavoriteToggled?: (isFavorited: boolean) => void\n sectionId?: string\n}\n\n// Composed ProductCard component\nfunction ProductCard({\n product,\n selectedProductVariant,\n variant = 'default',\n touchable = true,\n badgeText,\n badgeVariant = 'secondary',\n onFavoriteToggled,\n}: ProductCardProps) {\n const {navigateToProduct} = useShopNavigation()\n const {saveProduct, unsaveProduct} = useSavedProductsActions()\n\n const {\n id,\n title,\n featuredImage,\n price,\n compareAtPrice,\n isFavorited,\n defaultVariantId,\n shop,\n } = product\n\n // Use selected variant data if available\n const displayImage = selectedProductVariant?.image || featuredImage\n const displayPrice = selectedProductVariant?.price || price\n const displayCompareAtPrice =\n selectedProductVariant?.compareAtPrice || compareAtPrice\n\n // Local state for optimistic UI updates\n const [isFavoritedLocal, setIsFavoritedLocal] = React.useState(isFavorited)\n\n const currencyCode = displayPrice?.currencyCode\n const amount = displayPrice?.amount\n const imageUrl = displayImage?.url\n const imageAltText = displayImage?.altText || title\n const compareAtPriceAmount = displayCompareAtPrice?.amount\n const hasDiscount = compareAtPriceAmount && compareAtPriceAmount !== amount\n\n const handlePress = React.useCallback(() => {\n if (!touchable) return\n\n navigateToProduct({\n productId: id,\n })\n }, [navigateToProduct, id, touchable])\n\n const handleFavoritePress = React.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: id,\n shopId: shop.id,\n productVariantId: selectedProductVariant?.id || defaultVariantId,\n })\n } else {\n await saveProduct({\n productId: id,\n shopId: shop.id,\n productVariantId: selectedProductVariant?.id || defaultVariantId,\n })\n }\n } catch (error) {\n // Revert optimistic update on error\n setIsFavoritedLocal(previousState)\n onFavoriteToggled?.(previousState)\n }\n }, [\n isFavoritedLocal,\n id,\n shop.id,\n selectedProductVariant?.id,\n defaultVariantId,\n saveProduct,\n unsaveProduct,\n onFavoriteToggled,\n ])\n\n return (\n <ProductCardRoot\n variant={variant}\n touchable={touchable}\n onPress={handlePress}\n >\n <ProductCardImageContainer variant={variant}>\n <ProductCardImage src={imageUrl} alt={imageAltText} />\n\n {/* Price overlay badge for priceOverlay variant */}\n {variant === 'priceOverlay' && currencyCode && amount && (\n <ProductCardBadge position=\"top-left\">\n {formatMoney(amount, currencyCode)}\n </ProductCardBadge>\n )}\n\n {/* Custom badge */}\n {badgeText && (\n <ProductCardBadge position=\"bottom-left\" variant={badgeVariant}>\n {badgeText}\n </ProductCardBadge>\n )}\n\n {/* Favorite button */}\n <ProductCardFavoriteButton\n filled={isFavoritedLocal}\n onPress={handleFavoritePress}\n />\n </ProductCardImageContainer>\n\n {/* Product info for default variant */}\n <ProductCardInfo variant={variant}>\n <ProductCardTitle>{title}</ProductCardTitle>\n\n <ProductCardPrice>\n {hasDiscount ? (\n <>\n <ProductCardCurrentPrice>\n {formatMoney(amount, currencyCode)}\n </ProductCardCurrentPrice>\n <ProductCardOriginalPrice>\n {formatMoney(\n compareAtPriceAmount,\n displayCompareAtPrice?.currencyCode || currencyCode\n )}\n </ProductCardOriginalPrice>\n </>\n ) : (\n <ProductCardCurrentPrice>\n {formatMoney(amount, currencyCode)}\n </ProductCardCurrentPrice>\n )}\n </ProductCardPrice>\n </ProductCardInfo>\n </ProductCardRoot>\n )\n}\n\nexport {ProductCard}\n"],"names":["productCardVariants","cva","ProductCardRoot","className","variant","touchable","asChild","onPress","props","content","jsx","SlotPrimitive.Slot","cn","Touchable","ProductCardImageContainer","ProductCardImage","src","alt","ProductCardBadge","position","children","Badge","ProductCardFavoriteButton","filled","FavoriteButton","ProductCardInfo","ProductCardTitle","ProductCardPrice","ProductCardCurrentPrice","ProductCardOriginalPrice","ProductCard","product","selectedProductVariant","badgeText","badgeVariant","onFavoriteToggled","navigateToProduct","useShopNavigation","saveProduct","unsaveProduct","useSavedProductsActions","id","title","featuredImage","price","compareAtPrice","isFavorited","defaultVariantId","shop","displayImage","displayPrice","displayCompareAtPrice","isFavoritedLocal","setIsFavoritedLocal","React","currencyCode","amount","imageUrl","imageAltText","compareAtPriceAmount","hasDiscount","handlePress","handleFavoritePress","previousState","jsxs","formatMoney","Fragment"],"mappings":";;;;;;;;;;;AAeA,MAAMA,IAAsBC;AAAA,EAC1B;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,cAAc;AAAA,QACd,SAAS;AAAA,MACX;AAAA,MACA,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IAEX;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,WAAW;AAAA,IAAA;AAAA,EACb;AAEJ;AAYA,SAASC,EAAgB;AAAA,EACvB,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,SAAAC,IAAU;AAAA,EACV,SAAAC;AAAA,EACA,GAAGC;AACL,GAAyB;AAGvB,QAAMC,IACJ,gBAAAC;AAAA,IAHWJ,IAAUK,IAAqB;AAAA,IAGzC;AAAA,MACC,WAAWC;AAAA,QACTZ,EAAoB,EAAC,SAAAI,GAAS,WAAAC,GAAU;AAAA,QACxC;AAAA,QACAF;AAAA,MACF;AAAA,MACC,GAAGK;AAAA,IAAA;AAAA,EACN;AAGF,SAAIH,KAAaE,IAEb,gBAAAG;AAAA,IAACG;AAAA,IAAA;AAAA,MACC,SAASN;AAAA,MACT,UAAU,EAAC,SAAS,IAAG;AAAA,MACvB,YAAY;AAAA,QACV,SAAS,EAAC,MAAM,SAAS,UAAU,MAAM,MAAM,YAAW;AAAA,MAC5D;AAAA,MAEC,UAAAE;AAAA,IAAA;AAAA,EACH,IAIGA;AACT;AAEA,SAASK,EAA0B;AAAA,EACjC,WAAAX;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,GAAGI;AACL,GAEG;AAEC,SAAA,gBAAAE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWE;AAAA;AAAA,QAET;AAAA,QACA;AAAA,QACA;AAAA,QACAR,MAAY,YAAY,kBAAkB;AAAA,QAC1CD;AAAA,MACF;AAAA,MACC,GAAGK;AAAA,IAAA;AAAA,EACN;AAEJ;AAEA,SAASO,EAAiB;AAAA,EACxB,WAAAZ;AAAA,EACA,KAAAa;AAAA,EACA,KAAAC;AAAA,EACA,GAAGT;AACL,GAGG;AACD,SACG,gBAAAE,EAAA,OAAA,EAAI,WAAU,gDACZ,UACCM,IAAA,gBAAAN;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,KAAAM;AAAA,MACA,KAAAC;AAAA,MACA,WAAWL,EAAG,8BAA8BT,CAAS;AAAA,MACpD,GAAGK;AAAA,IAAA;AAAA,EAAA,IAGL,gBAAAE,EAAA,OAAA,EAAI,WAAU,yBAAwB,qBAAQ,CAAA,GAEnD;AAEJ;AAEA,SAASQ,EAAiB;AAAA,EACxB,WAAAf;AAAA,EACA,UAAAgB,IAAW;AAAA,EACX,UAAAC;AAAA,EACA,GAAGZ;AACL,GAEG;AAEC,SAAA,gBAAAE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWE;AAAA,QACT;AAAA,QACAO,MAAa,aAAa,iBAAiB;AAAA,MAC7C;AAAA,MAEA,UAAA,gBAAAT;AAAA,QAACW;AAAA,QAAA;AAAA,UACC,WAAWT,EAAG,kCAAkCT,CAAS;AAAA,UACxD,GAAGK;AAAA,UAEH,UAAAY;AAAA,QAAA;AAAA,MAAA;AAAA,IACH;AAAA,EACF;AAEJ;AAEA,SAASE,EAA0B;AAAA,EACjC,WAAAnB;AAAA,EACA,SAAAI;AAAA,EACA,QAAAgB,IAAS;AAAA,EACT,GAAGf;AACL,GAGG;AACD,SACG,gBAAAE,EAAA,OAAA,EAAI,WAAWE,EAAG,kCAAkCT,CAAS,GAAI,GAAGK,GACnE,UAAC,gBAAAE,EAAAc,GAAA,EAAe,SAASjB,GAAS,QAAAgB,EAAgB,CAAA,GACpD;AAEJ;AAEA,SAASE,EAAgB;AAAA,EACvB,WAAAtB;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,GAAGI;AACL,GAEG;AACD,SAAIJ,MAAY,YACP,OAIP,gBAAAM;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWE,EAAG,4BAA4BT,CAAS;AAAA,MAClD,GAAGK;AAAA,IAAA;AAAA,EACN;AAEJ;AAEA,SAASkB,EAAiB;AAAA,EACxB,WAAAvB;AAAA,EACA,UAAAiB;AAAA,EACA,GAAGZ;AACL,GAA+B;AAE3B,SAAA,gBAAAE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWE;AAAA,QACT;AAAA,QACA;AAAA,QACAT;AAAA,MACF;AAAA,MACC,GAAGK;AAAA,MAEH,UAAAY;AAAA,IAAA;AAAA,EACH;AAEJ;AAEA,SAASO,GAAiB,EAAC,WAAAxB,GAAW,GAAGK,KAAqC;AAE1E,SAAA,gBAAAE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWE,EAAG,2BAA2BT,CAAS;AAAA,MACjD,GAAGK;AAAA,IAAA;AAAA,EACN;AAEJ;AAEA,SAASoB,EAAwB;AAAA,EAC/B,WAAAzB;AAAA,EACA,GAAGK;AACL,GAAiC;AAE7B,SAAA,gBAAAE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWE,EAAG,uCAAuCT,CAAS;AAAA,MAC7D,GAAGK;AAAA,IAAA;AAAA,EACN;AAEJ;AAEA,SAASqB,GAAyB;AAAA,EAChC,WAAA1B;AAAA,EACA,GAAGK;AACL,GAAiC;AAE7B,SAAA,gBAAAE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWE,EAAG,sCAAsCT,CAAS;AAAA,MAC5D,GAAGK;AAAA,IAAA;AAAA,EACN;AAEJ;AAcA,SAASsB,GAAY;AAAA,EACnB,SAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,SAAA5B,IAAU;AAAA,EACV,WAAAC,IAAY;AAAA,EACZ,WAAA4B;AAAA,EACA,cAAAC,IAAe;AAAA,EACf,mBAAAC;AACF,GAAqB;AACb,QAAA,EAAC,mBAAAC,EAAiB,IAAIC,EAAkB,GACxC,EAAC,aAAAC,GAAa,eAAAC,EAAa,IAAIC,EAAwB,GAEvD;AAAA,IACJ,IAAAC;AAAA,IACA,OAAAC;AAAA,IACA,eAAAC;AAAA,IACA,OAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,aAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,MAAAC;AAAA,EAAA,IACEjB,GAGEkB,IAAejB,GAAwB,SAASW,GAChDO,IAAelB,GAAwB,SAASY,GAChDO,IACJnB,GAAwB,kBAAkBa,GAGtC,CAACO,GAAkBC,CAAmB,IAAIC,EAAM,SAASR,CAAW,GAEpES,IAAeL,GAAc,cAC7BM,IAASN,GAAc,QACvBO,IAAWR,GAAc,KACzBS,IAAeT,GAAc,WAAWP,GACxCiB,IAAuBR,GAAuB,QAC9CS,IAAcD,KAAwBA,MAAyBH,GAE/DK,IAAcP,EAAM,YAAY,MAAM;AAC1C,IAAKjD,KAEa+B,EAAA;AAAA,MAChB,WAAWK;AAAA,IAAA,CACZ;AAAA,EACA,GAAA,CAACL,GAAmBK,GAAIpC,CAAS,CAAC,GAE/ByD,IAAsBR,EAAM,YAAY,YAAY;AACxD,UAAMS,IAAgBX;AAGtB,IAAAC,EAAoB,CAACU,CAAa,GAClC5B,IAAoB,CAAC4B,CAAa;AAE9B,QAAA;AACF,MAAIA,IACF,MAAMxB,EAAc;AAAA,QAClB,WAAWE;AAAA,QACX,QAAQO,EAAK;AAAA,QACb,kBAAkBhB,GAAwB,MAAMe;AAAA,MAAA,CACjD,IAED,MAAMT,EAAY;AAAA,QAChB,WAAWG;AAAA,QACX,QAAQO,EAAK;AAAA,QACb,kBAAkBhB,GAAwB,MAAMe;AAAA,MAAA,CACjD;AAAA,YAEW;AAEd,MAAAM,EAAoBU,CAAa,GACjC5B,IAAoB4B,CAAa;AAAA,IAAA;AAAA,EACnC,GACC;AAAA,IACDX;AAAA,IACAX;AAAA,IACAO,EAAK;AAAA,IACLhB,GAAwB;AAAA,IACxBe;AAAA,IACAT;AAAA,IACAC;AAAA,IACAJ;AAAA,EAAA,CACD;AAGC,SAAA,gBAAA6B;AAAA,IAAC9D;AAAA,IAAA;AAAA,MACC,SAAAE;AAAA,MACA,WAAAC;AAAA,MACA,SAASwD;AAAA,MAET,UAAA;AAAA,QAAA,gBAAAG,EAAClD,KAA0B,SAAAV,GACzB,UAAA;AAAA,UAAA,gBAAAM,EAACK,GAAiB,EAAA,KAAK0C,GAAU,KAAKC,GAAc;AAAA,UAGnDtD,MAAY,kBAAkBmD,KAAgBC,KAC7C,gBAAA9C,EAACQ,GAAiB,EAAA,UAAS,YACxB,UAAA+C,EAAYT,GAAQD,CAAY,EACnC,CAAA;AAAA,UAIDtB,KACE,gBAAAvB,EAAAQ,GAAA,EAAiB,UAAS,eAAc,SAASgB,GAC/C,UACHD,GAAA;AAAA,UAIF,gBAAAvB;AAAA,YAACY;AAAA,YAAA;AAAA,cACC,QAAQ8B;AAAA,cACR,SAASU;AAAA,YAAA;AAAA,UAAA;AAAA,QACX,GACF;AAAA,QAGA,gBAAAE,EAACvC,KAAgB,SAAArB,GACf,UAAA;AAAA,UAAA,gBAAAM,EAACgB,KAAkB,UAAMgB,EAAA,CAAA;AAAA,UAEzB,gBAAAhC,EAACiB,IACE,EAAA,UAAAiC,IAEG,gBAAAI,EAAAE,GAAA,EAAA,UAAA;AAAA,YAAA,gBAAAxD,EAACkB,GACE,EAAA,UAAAqC,EAAYT,GAAQD,CAAY,GACnC;AAAA,8BACC1B,IACE,EAAA,UAAAoC;AAAA,cACCN;AAAA,cACAR,GAAuB,gBAAgBI;AAAA,YAAA,EAE3C,CAAA;AAAA,UAAA,GACF,IAEC,gBAAA7C,EAAAkB,GAAA,EACE,YAAY4B,GAAQD,CAAY,GACnC,EAEJ,CAAA;AAAA,QAAA,EACF,CAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EACF;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"product-card.js","sources":["../../../src/components/commerce/product-card.tsx"],"sourcesContent":["import * as React from 'react'\nimport {useCallback} from 'react'\n\nimport {type Product, type ProductVariant} from '@shopify/shop-minis-platform'\nimport {cva, type VariantProps} from 'class-variance-authority'\nimport {Slot as SlotPrimitive} from 'radix-ui'\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 {ThumbhashImage} from '../atoms/thumbhash-image'\nimport {Touchable} from '../atoms/touchable'\nimport {Badge} from '../ui/badge'\n\nconst productCardVariants = cva(\n 'relative w-full overflow-hidden rounded-xl border border-gray-200',\n {\n variants: {\n variant: {\n default: '',\n priceOverlay: '',\n compact: '',\n },\n touchable: {\n true: 'cursor-pointer',\n false: '',\n },\n },\n defaultVariants: {\n variant: 'default',\n touchable: true,\n },\n }\n)\n\n// Primitive components (building blocks)\nexport interface ProductCardRootProps\n extends React.ComponentProps<'div'>,\n VariantProps<typeof productCardVariants> {\n variant?: 'default' | 'priceOverlay' | 'compact'\n touchable?: boolean\n asChild?: boolean\n onPress?: () => void\n}\n\nfunction ProductCardRoot({\n className,\n variant,\n touchable = true,\n asChild = false,\n onPress,\n ...props\n}: ProductCardRootProps) {\n const Comp = asChild ? SlotPrimitive.Slot : 'div'\n\n const content = (\n <Comp\n className={cn(\n productCardVariants({variant, touchable}),\n 'border-0',\n className\n )}\n {...props}\n />\n )\n\n if (touchable && onPress) {\n return (\n <Touchable\n onClick={onPress}\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 variant = 'default',\n ...props\n}: React.ComponentProps<'div'> & {\n variant?: 'default' | 'priceOverlay' | 'compact'\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({\n className,\n src,\n alt,\n aspectRatio,\n thumbhash,\n ...props\n}: React.ComponentProps<'img'> & {\n src?: string\n alt?: string\n aspectRatio?: number\n thumbhash?: string\n}) {\n const renderImageElement = useCallback(\n (src: string) => {\n if (thumbhash) {\n return (\n <ThumbhashImage\n data-slot=\"product-card-image\"\n src={src}\n alt={alt}\n aspectRatio={aspectRatio}\n thumbhash={thumbhash}\n className={cn('w-full h-full object-cover', className)}\n {...props}\n />\n )\n }\n\n return (\n <img\n data-slot=\"product-card-image\"\n src={src}\n alt={alt}\n className={cn('w-full h-full', className)}\n {...props}\n />\n )\n },\n [alt, aspectRatio, className, props, thumbhash]\n )\n\n return (\n <div className=\"bg-gray-100 flex items-center justify-center w-full h-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 children,\n ...props\n}: React.ComponentProps<typeof Badge> & {\n position?: 'top-left' | 'bottom-left'\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 className={cn('bg-black/50 text-white rounded', className)}\n {...props}\n >\n {children}\n </Badge>\n </div>\n )\n}\n\nfunction ProductCardFavoriteButton({\n className,\n onPress,\n filled = false,\n ...props\n}: React.ComponentProps<'div'> & {\n onPress?: () => void\n filled?: boolean\n}) {\n return (\n <div className={cn('absolute bottom-3 right-3 z-10', className)} {...props}>\n <FavoriteButton onClick={onPress} filled={filled} />\n </div>\n )\n}\n\nfunction ProductCardInfo({\n className,\n variant = 'default',\n ...props\n}: React.ComponentProps<'div'> & {\n variant?: 'default' | 'priceOverlay' | 'compact'\n}) {\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 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}\n </h3>\n )\n}\n\nfunction ProductCardPrice({className, ...props}: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"product-card-price\"\n className={cn('flex items-center gap-2', className)}\n {...props}\n />\n )\n}\n\nfunction ProductCardCurrentPrice({\n className,\n ...props\n}: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"product-card-current-price\"\n className={cn('text-sm font-semibold text-gray-900', className)}\n {...props}\n />\n )\n}\n\nfunction ProductCardOriginalPrice({\n className,\n ...props\n}: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"product-card-original-price\"\n className={cn('text-sm text-gray-500 line-through', className)}\n {...props}\n />\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?: 'default' | 'secondary' | 'destructive' | 'outline'\n /** Callback fired when the favorite button is toggled */\n onFavoriteToggled?: (isFavorited: boolean) => void\n /** Optional ID for the section containing this card */\n sectionId?: string\n}\n\n// Composed ProductCard component\nfunction ProductCard({\n product,\n selectedProductVariant,\n variant = 'default',\n touchable = true,\n badgeText,\n badgeVariant = 'secondary',\n onFavoriteToggled,\n}: ProductCardProps) {\n const {navigateToProduct} = useShopNavigation()\n const {saveProduct, unsaveProduct} = useSavedProductsActions()\n\n const {\n id,\n title,\n featuredImage,\n price,\n compareAtPrice,\n isFavorited,\n defaultVariantId,\n shop,\n } = product\n\n // Use selected variant data if available\n const displayImage = selectedProductVariant?.image || featuredImage\n const displayPrice = selectedProductVariant?.price || price\n const displayCompareAtPrice =\n selectedProductVariant?.compareAtPrice || compareAtPrice\n\n // Local state for optimistic UI updates\n const [isFavoritedLocal, setIsFavoritedLocal] = React.useState(isFavorited)\n\n const currencyCode = displayPrice?.currencyCode\n const amount = displayPrice?.amount\n const imageUrl = displayImage?.url\n const imageAltText = displayImage?.altText || title\n const compareAtPriceAmount = displayCompareAtPrice?.amount\n const hasDiscount = compareAtPriceAmount && compareAtPriceAmount !== amount\n\n const handlePress = React.useCallback(() => {\n if (!touchable) return\n\n navigateToProduct({\n productId: id,\n })\n }, [navigateToProduct, id, touchable])\n\n const handleFavoritePress = React.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: id,\n shopId: shop.id,\n productVariantId: selectedProductVariant?.id || defaultVariantId,\n })\n } else {\n await saveProduct({\n productId: id,\n shopId: shop.id,\n productVariantId: selectedProductVariant?.id || defaultVariantId,\n })\n }\n } catch (error) {\n // Revert optimistic update on error\n setIsFavoritedLocal(previousState)\n onFavoriteToggled?.(previousState)\n }\n }, [\n isFavoritedLocal,\n id,\n shop.id,\n selectedProductVariant?.id,\n defaultVariantId,\n saveProduct,\n unsaveProduct,\n onFavoriteToggled,\n ])\n\n return (\n <ProductCardRoot\n variant={variant}\n touchable={touchable}\n onPress={handlePress}\n >\n <ProductCardImageContainer variant={variant}>\n <ProductCardImage\n src={imageUrl}\n alt={imageAltText}\n aspectRatio={1}\n thumbhash={featuredImage?.thumbhash ?? undefined}\n />\n\n {/* Price overlay badge for priceOverlay variant */}\n {variant === 'priceOverlay' && currencyCode && amount && (\n <ProductCardBadge position=\"top-left\">\n {formatMoney(amount, currencyCode)}\n </ProductCardBadge>\n )}\n\n {/* Custom badge */}\n {badgeText && (\n <ProductCardBadge position=\"bottom-left\" variant={badgeVariant}>\n {badgeText}\n </ProductCardBadge>\n )}\n\n {/* Favorite button */}\n <ProductCardFavoriteButton\n filled={isFavoritedLocal}\n onPress={handleFavoritePress}\n />\n </ProductCardImageContainer>\n\n {/* Product info for default variant */}\n <ProductCardInfo variant={variant}>\n <ProductCardTitle>{title}</ProductCardTitle>\n\n <ProductCardPrice>\n {hasDiscount ? (\n <>\n <ProductCardCurrentPrice>\n {formatMoney(amount, currencyCode)}\n </ProductCardCurrentPrice>\n <ProductCardOriginalPrice>\n {formatMoney(\n compareAtPriceAmount,\n displayCompareAtPrice?.currencyCode || currencyCode\n )}\n </ProductCardOriginalPrice>\n </>\n ) : (\n <ProductCardCurrentPrice>\n {formatMoney(amount, currencyCode)}\n </ProductCardCurrentPrice>\n )}\n </ProductCardPrice>\n </ProductCardInfo>\n </ProductCardRoot>\n )\n}\n\nexport {ProductCard}\n"],"names":["productCardVariants","cva","ProductCardRoot","className","variant","touchable","asChild","onPress","props","content","jsx","SlotPrimitive.Slot","cn","Touchable","ProductCardImageContainer","ProductCardImage","src","alt","aspectRatio","thumbhash","renderImageElement","useCallback","ThumbhashImage","ProductCardBadge","position","children","Badge","ProductCardFavoriteButton","filled","FavoriteButton","ProductCardInfo","ProductCardTitle","ProductCardPrice","ProductCardCurrentPrice","ProductCardOriginalPrice","ProductCard","product","selectedProductVariant","badgeText","badgeVariant","onFavoriteToggled","navigateToProduct","useShopNavigation","saveProduct","unsaveProduct","useSavedProductsActions","id","title","featuredImage","price","compareAtPrice","isFavorited","defaultVariantId","shop","displayImage","displayPrice","displayCompareAtPrice","isFavoritedLocal","setIsFavoritedLocal","React","currencyCode","amount","imageUrl","imageAltText","compareAtPriceAmount","hasDiscount","handlePress","handleFavoritePress","previousState","jsxs","formatMoney","Fragment"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transition-container.js","sources":["../../../src/components/navigation/transition-container.tsx"],"sourcesContent":["import {useViewTransitions} from '../../hooks/navigation/useViewTransitions'\n\nexport function TransitionContainer({children}: {children: React.ReactNode}) {\n useViewTransitions()\n\n return children\n}\n"],"names":["TransitionContainer","children","useViewTransitions"],"mappings":";AAEgB,SAAAA,EAAoB,EAAC,UAAAC,KAAwC;AACxD,SAAAC,EAAA,GAEZD;AACT;"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as l } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as p } from "react";
|
|
3
|
+
import { useHref as c } from "../../shop-minis-react/node_modules/.pnpm/react-router@7.7.0_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-router/dist/development/chunk-EF7DTUVF.js";
|
|
4
|
+
import { useNavigateWithTransition as d } from "../../hooks/navigation/useNavigateWithTransition.js";
|
|
5
|
+
const u = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i, R = p(({ onClick: i, to: t, children: o, ...a }, n) => {
|
|
6
|
+
const s = d(), r = typeof t == "string" && u.test(t);
|
|
7
|
+
r && console.warn(
|
|
8
|
+
"TransitionLink: absolute URLs are not supported. Please update to a valid relative path."
|
|
9
|
+
);
|
|
10
|
+
const f = c(t);
|
|
11
|
+
return /* @__PURE__ */ l(
|
|
12
|
+
"a",
|
|
13
|
+
{
|
|
14
|
+
...a,
|
|
15
|
+
onClick: (e) => {
|
|
16
|
+
i && i(e), e.defaultPrevented || (e.preventDefault(), s(t));
|
|
17
|
+
},
|
|
18
|
+
href: r ? void 0 : f,
|
|
19
|
+
ref: n,
|
|
20
|
+
children: o
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
export {
|
|
25
|
+
R as TransitionLink
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=transition-link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transition-link.js","sources":["../../../src/components/navigation/transition-link.tsx"],"sourcesContent":["import {forwardRef, AnchorHTMLAttributes} from 'react'\n\nimport {useHref} from 'react-router'\n\nimport {useNavigateWithTransition} from '../../hooks/navigation/useNavigateWithTransition'\n\ntype TransitionLinkProps = AnchorHTMLAttributes<HTMLAnchorElement> & {\n to: string\n}\n\nconst ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\\/\\/)/i\n\nexport const TransitionLink = forwardRef<\n HTMLAnchorElement,\n TransitionLinkProps\n>(({onClick, to, children, ...props}, forwardedRef) => {\n const transitionNavigate = useNavigateWithTransition()\n\n const isAbsolute = typeof to === 'string' && ABSOLUTE_URL_REGEX.test(to)\n\n if (isAbsolute) {\n console.warn(\n `TransitionLink: absolute URLs are not supported. Please update to a valid relative path.`\n )\n }\n\n const href = useHref(to)\n\n const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {\n if (onClick) onClick(event)\n\n if (!event.defaultPrevented) {\n event.preventDefault()\n transitionNavigate(to)\n }\n }\n\n return (\n <a\n {...props}\n onClick={handleClick}\n href={isAbsolute ? undefined : href}\n ref={forwardedRef}\n >\n {children}\n </a>\n )\n})\n"],"names":["ABSOLUTE_URL_REGEX","TransitionLink","forwardRef","onClick","to","children","props","forwardedRef","transitionNavigate","useNavigateWithTransition","isAbsolute","href","useHref","jsx","event"],"mappings":";;;;AAUA,MAAMA,IAAqB,iCAEdC,IAAiBC,EAG5B,CAAC,EAAC,SAAAC,GAAS,IAAAC,GAAI,UAAAC,GAAU,GAAGC,EAAK,GAAGC,MAAiB;AACrD,QAAMC,IAAqBC,EAA0B,GAE/CC,IAAa,OAAON,KAAO,YAAYJ,EAAmB,KAAKI,CAAE;AAEvE,EAAIM,KACM,QAAA;AAAA,IACN;AAAA,EACF;AAGI,QAAAC,IAAOC,EAAQR,CAAE;AAYrB,SAAA,gBAAAS;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAGP;AAAA,MACJ,SAZgB,CAACQ,MAA+C;AAC9D,QAAAX,OAAiBW,CAAK,GAErBA,EAAM,qBACTA,EAAM,eAAe,GACrBN,EAAmBJ,CAAE;AAAA,MAEzB;AAAA,MAMI,MAAMM,IAAa,SAAYC;AAAA,MAC/B,KAAKJ;AAAA,MAEJ,UAAAF;AAAA,IAAA;AAAA,EACH;AAEJ,CAAC;"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { cn as r } from "../../lib/utils.js";
|
|
3
|
+
import { Root as l, Image as o, Fallback as s } from "../../shop-minis-react/node_modules/.pnpm/@radix-ui_react-avatar@1.1.10_@types_react-dom@19.1.6_@types_react@19.1.6__@types_react@19.1._hkz57sehyui4ndfh3rsqwxftli/node_modules/@radix-ui/react-avatar/dist/index.js";
|
|
4
|
+
function u({
|
|
5
|
+
className: a,
|
|
6
|
+
...t
|
|
7
|
+
}) {
|
|
8
|
+
return /* @__PURE__ */ e(
|
|
9
|
+
l,
|
|
10
|
+
{
|
|
11
|
+
"data-slot": "avatar",
|
|
12
|
+
className: r(
|
|
13
|
+
"relative flex size-8 shrink-0 overflow-hidden rounded-full",
|
|
14
|
+
a
|
|
15
|
+
),
|
|
16
|
+
...t
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
function m({
|
|
21
|
+
className: a,
|
|
22
|
+
...t
|
|
23
|
+
}) {
|
|
24
|
+
return /* @__PURE__ */ e(
|
|
25
|
+
o,
|
|
26
|
+
{
|
|
27
|
+
"data-slot": "avatar-image",
|
|
28
|
+
className: r("aspect-square size-full", a),
|
|
29
|
+
...t
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function c({
|
|
34
|
+
className: a,
|
|
35
|
+
...t
|
|
36
|
+
}) {
|
|
37
|
+
return /* @__PURE__ */ e(
|
|
38
|
+
s,
|
|
39
|
+
{
|
|
40
|
+
"data-slot": "avatar-fallback",
|
|
41
|
+
className: r(
|
|
42
|
+
"bg-muted flex size-full items-center justify-center rounded-full",
|
|
43
|
+
a
|
|
44
|
+
),
|
|
45
|
+
...t
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
u as Avatar,
|
|
51
|
+
c as AvatarFallback,
|
|
52
|
+
m as AvatarImage
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=avatar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avatar.js","sources":["../../../src/components/ui/avatar.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport {Avatar as AvatarPrimitive} from 'radix-ui'\n\nimport {cn} from '../../lib/utils'\n\nfunction Avatar({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n className={cn(\n 'relative flex size-8 shrink-0 overflow-hidden rounded-full',\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarImage({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn('aspect-square size-full', className)}\n {...props}\n />\n )\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n 'bg-muted flex size-full items-center justify-center rounded-full',\n className\n )}\n {...props}\n />\n )\n}\n\nexport {Avatar, AvatarImage, AvatarFallback}\n"],"names":["Avatar","className","props","jsx","AvatarPrimitive.Root","cn","AvatarImage","AvatarPrimitive.Image","AvatarFallback","AvatarPrimitive.Fallback"],"mappings":";;;AAMA,SAASA,EAAO;AAAA,EACd,WAAAC;AAAA,EACA,GAAGC;AACL,GAAsD;AAElD,SAAA,gBAAAC;AAAA,IAACC;AAAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWC;AAAA,QACT;AAAA,QACAJ;AAAA,MACF;AAAA,MACC,GAAGC;AAAA,IAAA;AAAA,EACN;AAEJ;AAEA,SAASI,EAAY;AAAA,EACnB,WAAAL;AAAA,EACA,GAAGC;AACL,GAAuD;AAEnD,SAAA,gBAAAC;AAAA,IAACI;AAAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWF,EAAG,2BAA2BJ,CAAS;AAAA,MACjD,GAAGC;AAAA,IAAA;AAAA,EACN;AAEJ;AAEA,SAASM,EAAe;AAAA,EACtB,WAAAP;AAAA,EACA,GAAGC;AACL,GAA0D;AAEtD,SAAA,gBAAAC;AAAA,IAACM;AAAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWJ;AAAA,QACT;AAAA,QACAJ;AAAA,MACF;AAAA,MACC,GAAGC;AAAA,IAAA;AAAA,EACN;AAEJ;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as o } from "react/jsx-runtime";
|
|
2
|
+
import { cn as n } from "../../lib/utils.js";
|
|
3
|
+
function m({ className: e, ...t }) {
|
|
4
|
+
return /* @__PURE__ */ o(
|
|
5
|
+
"div",
|
|
6
|
+
{
|
|
7
|
+
"data-slot": "skeleton",
|
|
8
|
+
className: n("bg-accent animate-pulse rounded-md", e),
|
|
9
|
+
...t
|
|
10
|
+
}
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
m as Skeleton
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=skeleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skeleton.js","sources":["../../../src/components/ui/skeleton.tsx"],"sourcesContent":["import {cn} from '../../lib/utils'\n\nfunction Skeleton({className, ...props}: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"skeleton\"\n className={cn('bg-accent animate-pulse rounded-md', className)}\n {...props}\n />\n )\n}\n\nexport {Skeleton}\n"],"names":["Skeleton","className","props","jsx","cn"],"mappings":";;AAEA,SAASA,EAAS,EAAC,WAAAC,GAAW,GAAGC,KAAqC;AAElE,SAAA,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWC,EAAG,sCAAsCH,CAAS;AAAA,MAC5D,GAAGC;AAAA,IAAA;AAAA,EACN;AAEJ;"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useNavigate as c, useLocation as u } from "../../shop-minis-react/node_modules/.pnpm/react-router@7.7.0_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-router/dist/development/chunk-EF7DTUVF.js";
|
|
2
|
+
import { DATA_NAVIGATION_TYPE_ATTRIBUTE as r } from "../../types/index.js";
|
|
3
|
+
function l() {
|
|
4
|
+
const e = c(), o = u();
|
|
5
|
+
return (t, i) => {
|
|
6
|
+
if (typeof t == "number") {
|
|
7
|
+
if (document.startViewTransition)
|
|
8
|
+
document.startViewTransition(() => {
|
|
9
|
+
e(t);
|
|
10
|
+
}).finished.then(() => {
|
|
11
|
+
document.documentElement.removeAttribute(
|
|
12
|
+
r
|
|
13
|
+
);
|
|
14
|
+
}).catch((n) => {
|
|
15
|
+
console.error("View transition error:", n);
|
|
16
|
+
});
|
|
17
|
+
else
|
|
18
|
+
return e(t);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const a = t === o.pathname;
|
|
22
|
+
if (document.startViewTransition)
|
|
23
|
+
document.startViewTransition(() => {
|
|
24
|
+
e(t, {
|
|
25
|
+
preventScrollReset: !0,
|
|
26
|
+
replace: a,
|
|
27
|
+
...i
|
|
28
|
+
});
|
|
29
|
+
}).finished.then(() => {
|
|
30
|
+
document.documentElement.removeAttribute(
|
|
31
|
+
r
|
|
32
|
+
);
|
|
33
|
+
}).catch((n) => {
|
|
34
|
+
console.error("View transition error:", n);
|
|
35
|
+
});
|
|
36
|
+
else
|
|
37
|
+
return e(t, i);
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
l as useNavigateWithTransition
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=useNavigateWithTransition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useNavigateWithTransition.js","sources":["../../../src/hooks/navigation/useNavigateWithTransition.ts"],"sourcesContent":["import {useLocation, useNavigate, NavigateOptions} from 'react-router'\n\nimport {DATA_NAVIGATION_TYPE_ATTRIBUTE} from '../../types'\n\nexport function useNavigateWithTransition() {\n const navigate = useNavigate()\n const location = useLocation()\n\n const transitionNavigate = (\n to: string | number,\n options?: NavigateOptions\n ) => {\n if (typeof to === 'number') {\n // Delta navigation - no options parameter\n if (document.startViewTransition) {\n const transition = document.startViewTransition(() => {\n navigate(to)\n })\n\n transition.finished\n .then(() => {\n document.documentElement.removeAttribute(\n DATA_NAVIGATION_TYPE_ATTRIBUTE\n )\n })\n .catch(error => {\n console.error('View transition error:', error)\n })\n } else {\n return navigate(to)\n }\n return\n }\n\n const isSameRoute = to === location.pathname\n\n // Path navigation - with options\n if (document.startViewTransition) {\n const transition = document.startViewTransition(() => {\n navigate(to, {\n preventScrollReset: true,\n replace: isSameRoute,\n ...options,\n })\n })\n\n transition.finished\n .then(() => {\n document.documentElement.removeAttribute(\n DATA_NAVIGATION_TYPE_ATTRIBUTE\n )\n })\n .catch(error => {\n console.error('View transition error:', error)\n })\n } else {\n return navigate(to, options)\n }\n }\n\n return transitionNavigate\n}\n"],"names":["useNavigateWithTransition","navigate","useNavigate","location","useLocation","to","options","DATA_NAVIGATION_TYPE_ATTRIBUTE","error","isSameRoute"],"mappings":";;AAIO,SAASA,IAA4B;AAC1C,QAAMC,IAAWC,EAAY,GACvBC,IAAWC,EAAY;AAsDtB,SApDoB,CACzBC,GACAC,MACG;AACC,QAAA,OAAOD,KAAO,UAAU;AAE1B,UAAI,SAAS;AAKA,QAJQ,SAAS,oBAAoB,MAAM;AACpD,UAAAJ,EAASI,CAAE;AAAA,QAAA,CACZ,EAEU,SACR,KAAK,MAAM;AACV,mBAAS,gBAAgB;AAAA,YACvBE;AAAA,UACF;AAAA,QAAA,CACD,EACA,MAAM,CAASC,MAAA;AACN,kBAAA,MAAM,0BAA0BA,CAAK;AAAA,QAAA,CAC9C;AAAA;AAEH,eAAOP,EAASI,CAAE;AAEpB;AAAA,IAAA;AAGI,UAAAI,IAAcJ,MAAOF,EAAS;AAGpC,QAAI,SAAS;AASA,MARQ,SAAS,oBAAoB,MAAM;AACpD,QAAAF,EAASI,GAAI;AAAA,UACX,oBAAoB;AAAA,UACpB,SAASI;AAAA,UACT,GAAGH;AAAA,QAAA,CACJ;AAAA,MAAA,CACF,EAEU,SACR,KAAK,MAAM;AACV,iBAAS,gBAAgB;AAAA,UACvBC;AAAA,QACF;AAAA,MAAA,CACD,EACA,MAAM,CAASC,MAAA;AACN,gBAAA,MAAM,0BAA0BA,CAAK;AAAA,MAAA,CAC9C;AAAA;AAEI,aAAAP,EAASI,GAAIC,CAAO;AAAA,EAE/B;AAGF;"}
|