@shopify/shop-minis-react 0.0.31 → 0.0.33

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.
@@ -1,60 +1,42 @@
1
- import { jsxs as y, jsx as e } from "react/jsx-runtime";
2
- import * as g from "react";
3
- import { useCallback as L } from "react";
4
- import { cva as q } from "../../shop-minis-react/node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.js";
5
- import { useShopNavigation as E } from "../../hooks/navigation/useShopNavigation.js";
6
- import { useSavedProductsActions as M } from "../../hooks/user/useSavedProductsActions.js";
7
- import { formatMoney as U } from "../../lib/formatMoney.js";
8
- import { cn as c } from "../../lib/utils.js";
9
- import { FavoriteButton as V } from "../atoms/favorite-button.js";
10
- import { ProductVariantPrice as D } from "../atoms/product-variant-price.js";
11
- import { ThumbhashImage as G } from "../atoms/thumbhash-image.js";
12
- import { Touchable as H } from "../atoms/touchable.js";
13
- import { Badge as J } from "../ui/badge.js";
14
- import { Root as K } 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";
15
- const Q = q(
16
- "relative w-full overflow-hidden rounded-xl border border-gray-200",
17
- {
18
- variants: {
19
- variant: {
20
- default: "",
21
- priceOverlay: "",
22
- compact: ""
23
- },
24
- touchable: {
25
- true: "cursor-pointer",
26
- false: ""
27
- }
28
- },
29
- defaultVariants: {
30
- variant: "default",
31
- touchable: !0
32
- }
33
- }
34
- );
35
- function W({
36
- className: o,
37
- variant: t,
38
- touchable: r = !0,
39
- asChild: a = !1,
40
- onPress: i,
41
- ...d
1
+ import { jsx as o, jsxs as v } from "react/jsx-runtime";
2
+ import * as N from "react";
3
+ import { useState as F, useCallback as C, useMemo as A, useContext as k } from "react";
4
+ import { useShopNavigation as T } from "../../hooks/navigation/useShopNavigation.js";
5
+ import { useSavedProductsActions as V } from "../../hooks/user/useSavedProductsActions.js";
6
+ import { formatMoney as j } from "../../lib/formatMoney.js";
7
+ import { cn as s } from "../../lib/utils.js";
8
+ import { FavoriteButton as B } from "../atoms/favorite-button.js";
9
+ import { ProductVariantPrice as E } from "../atoms/product-variant-price.js";
10
+ import { ThumbhashImage as O } from "../atoms/thumbhash-image.js";
11
+ import { Touchable as S } from "../atoms/touchable.js";
12
+ import { Badge as z } from "../ui/badge.js";
13
+ const I = N.createContext(void 0);
14
+ function u() {
15
+ const t = k(I);
16
+ if (!t)
17
+ throw new Error(
18
+ "ProductCard components must be used within a ProductCard provider"
19
+ );
20
+ return t;
21
+ }
22
+ function L({
23
+ className: t,
24
+ ...e
42
25
  }) {
43
- const n = /* @__PURE__ */ e(
44
- a ? K : "div",
26
+ const { touchable: r, onClick: a } = u(), n = /* @__PURE__ */ o(
27
+ "div",
45
28
  {
46
- className: c(
47
- Q({ variant: t, touchable: r }),
48
- "border-0",
49
- o
29
+ className: s(
30
+ "relative w-full overflow-hidden rounded-xl border-0",
31
+ t
50
32
  ),
51
- ...d
33
+ ...e
52
34
  }
53
35
  );
54
- return r && i ? /* @__PURE__ */ e(
55
- H,
36
+ return r && a ? /* @__PURE__ */ o(
37
+ S,
56
38
  {
57
- onClick: i,
39
+ onClick: a,
58
40
  whileTap: { opacity: 0.7 },
59
41
  transition: {
60
42
  opacity: { type: "tween", duration: 0.08, ease: "easeInOut" }
@@ -63,218 +45,232 @@ function W({
63
45
  }
64
46
  ) : n;
65
47
  }
66
- function X({
67
- className: o,
68
- variant: t = "default",
69
- ...r
48
+ function M({
49
+ className: t,
50
+ ...e
70
51
  }) {
71
- return /* @__PURE__ */ e(
52
+ const { variant: r } = u();
53
+ return /* @__PURE__ */ o(
72
54
  "div",
73
55
  {
74
56
  "data-slot": "product-card-image-container",
75
- className: c(
57
+ className: s(
76
58
  // Ensure the product image is stretched to the full size of the container (can't use width/height: 100% because of flex)
77
59
  "flex justify-stretch items-stretch",
78
60
  "relative overflow-hidden rounded-xl border border-gray-200",
79
61
  "w-full aspect-square",
80
- t === "compact" ? "min-h-[104px]" : "min-h-[134px]",
81
- o
62
+ r === "compact" ? "min-h-[104px]" : "min-h-[134px]",
63
+ t
82
64
  ),
83
- ...r
65
+ ...e
84
66
  }
85
67
  );
86
68
  }
87
- function Y({
88
- className: o,
89
- src: t,
90
- alt: r,
91
- aspectRatio: a,
92
- thumbhash: i,
93
- ...d
94
- }) {
95
- const s = L(
96
- (n) => i ? /* @__PURE__ */ e(
97
- G,
69
+ function R({ className: t, ...e }) {
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
+ (l) => c ? /* @__PURE__ */ o(
72
+ O,
98
73
  {
99
74
  "data-slot": "product-card-image",
100
- src: n,
101
- alt: r,
102
- aspectRatio: a,
103
- thumbhash: i,
104
- className: c("w-full h-full object-cover", o),
105
- ...d
75
+ src: l,
76
+ alt: d,
77
+ aspectRatio: 1,
78
+ thumbhash: c,
79
+ className: s("w-full h-full object-cover", t),
80
+ ...e
106
81
  }
107
- ) : /* @__PURE__ */ e(
82
+ ) : /* @__PURE__ */ o(
108
83
  "img",
109
84
  {
110
85
  "data-slot": "product-card-image",
111
- src: n,
112
- alt: r,
113
- className: c("w-full h-full", o),
114
- ...d
86
+ src: l,
87
+ alt: d,
88
+ className: s("w-full h-full", t),
89
+ ...e
115
90
  }
116
91
  ),
117
- [r, a, o, d, i]
92
+ [d, t, e, c]
118
93
  );
119
- return /* @__PURE__ */ e("div", { className: "bg-gray-100 flex items-center justify-center w-full h-full", children: t ? s(t) : /* @__PURE__ */ e("div", { className: "text-gray-400 text-sm w-full text-center", children: "No Image" }) });
94
+ return /* @__PURE__ */ o("div", { className: "bg-gray-100 flex items-center justify-center w-full h-full", children: i ? p(i) : /* @__PURE__ */ o("div", { className: "text-gray-400 text-sm w-full text-center", children: "No Image" }) });
120
95
  }
121
- function k({
122
- className: o,
123
- position: t = "bottom-left",
124
- children: r,
125
- ...a
96
+ function w({
97
+ className: t,
98
+ position: e = "bottom-left",
99
+ variant: r,
100
+ children: a,
101
+ ...n
126
102
  }) {
127
- return /* @__PURE__ */ e(
103
+ const { badgeText: i, badgeVariant: d } = u(), c = a || i;
104
+ return c ? /* @__PURE__ */ o(
128
105
  "div",
129
106
  {
130
- className: c(
107
+ className: s(
131
108
  "absolute z-10",
132
- t === "top-left" ? "top-3 left-3" : "bottom-2 left-2"
109
+ e === "top-left" ? "top-3 left-3" : "bottom-2 left-2"
133
110
  ),
134
- children: /* @__PURE__ */ e(
135
- J,
111
+ children: /* @__PURE__ */ o(
112
+ z,
136
113
  {
137
- className: c("bg-black/50 text-white rounded", o),
138
- ...a,
139
- children: r
114
+ variant: r ?? d ?? "none",
115
+ className: s(
116
+ !d && !r && "bg-black/50 text-white border-transparent",
117
+ "rounded",
118
+ t
119
+ ),
120
+ ...n,
121
+ children: c
140
122
  }
141
123
  )
142
124
  }
143
- );
125
+ ) : null;
144
126
  }
145
- function Z({
146
- className: o,
147
- onPress: t,
148
- filled: r = !1,
149
- ...a
127
+ function q({
128
+ className: t,
129
+ ...e
150
130
  }) {
151
- return /* @__PURE__ */ e("div", { className: c("absolute bottom-3 right-3 z-10", o), ...a, children: /* @__PURE__ */ e(V, { onClick: t, filled: r }) });
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(B, { onClick: a, filled: r }) });
152
133
  }
153
- function _({
154
- className: o,
155
- variant: t = "default",
156
- ...r
157
- }) {
158
- return t !== "default" ? null : /* @__PURE__ */ e(
134
+ function D({ className: t, ...e }) {
135
+ const { variant: r } = u();
136
+ return r !== "default" ? null : /* @__PURE__ */ o(
159
137
  "div",
160
138
  {
161
139
  "data-slot": "product-card-info",
162
- className: c("px-1 pt-2 pb-0 space-y-1", o),
163
- ...r
140
+ className: s("px-1 pt-2 pb-0 space-y-1", t),
141
+ ...e
164
142
  }
165
143
  );
166
144
  }
167
- function $({
168
- className: o,
169
- children: t,
145
+ function G({
146
+ className: t,
147
+ children: e,
170
148
  ...r
171
149
  }) {
172
- return /* @__PURE__ */ e(
150
+ const { product: a } = u();
151
+ return /* @__PURE__ */ o(
173
152
  "h3",
174
153
  {
175
154
  "data-slot": "product-card-title",
176
- className: c(
155
+ className: s(
177
156
  "text-sm font-medium leading-tight text-gray-900",
178
157
  "truncate overflow-hidden whitespace-nowrap text-ellipsis",
179
- o
158
+ t
180
159
  ),
181
160
  ...r,
182
- children: t
161
+ children: e || a.title
162
+ }
163
+ );
164
+ }
165
+ function H({ className: t }) {
166
+ const { product: e, selectedProductVariant: r } = u(), a = r?.price || e?.price, n = r?.compareAtPrice || e?.compareAtPrice;
167
+ return /* @__PURE__ */ o(
168
+ E,
169
+ {
170
+ amount: a?.amount || "",
171
+ currencyCode: a?.currencyCode || "",
172
+ compareAtPriceAmount: n?.amount,
173
+ compareAtPriceCurrencyCode: n?.currencyCode,
174
+ className: t
183
175
  }
184
176
  );
185
177
  }
186
- function pt({
187
- product: o,
188
- selectedProductVariant: t,
178
+ function J() {
179
+ const { product: t, selectedProductVariant: e, variant: r } = u();
180
+ if (r !== "priceOverlay") return null;
181
+ const a = e?.price || t.price, n = a?.currencyCode, i = a?.amount;
182
+ return !n || !i ? null : /* @__PURE__ */ o(w, { position: "top-left", children: j(i, n) });
183
+ }
184
+ function ot({
185
+ product: t,
186
+ selectedProductVariant: e,
189
187
  variant: r = "default",
190
188
  touchable: a = !0,
191
- badgeText: i,
192
- badgeVariant: d = "secondary",
193
- onFavoriteToggled: s
189
+ badgeText: n,
190
+ badgeVariant: i,
191
+ onProductClick: d,
192
+ onFavoriteToggled: c,
193
+ children: p
194
194
  }) {
195
- const { navigateToProduct: n } = E(), { saveProduct: C, unsaveProduct: b } = M(), {
196
- id: l,
197
- title: x,
198
- featuredImage: I,
199
- price: j,
200
- compareAtPrice: S,
201
- isFavorited: B,
202
- defaultVariantId: m,
203
- shop: f
204
- } = o, P = t?.image || I, w = t?.price || j, N = t?.compareAtPrice || S, [p, A] = g.useState(B), h = w?.currencyCode, v = w?.amount, F = P?.url, T = P?.altText || x, O = N?.amount, R = g.useCallback(() => {
205
- a && n({
206
- productId: l
207
- });
208
- }, [n, l, a]), z = g.useCallback(async () => {
209
- const u = p;
210
- A(!u), s?.(!u);
195
+ const { navigateToProduct: l } = T(), { saveProduct: h, unsaveProduct: g } = V(), [f, P] = F(t.isFavorited), y = C(() => {
196
+ a && (d?.(), l({
197
+ productId: t.id
198
+ }));
199
+ }, [l, t.id, a, d]), x = C(async () => {
200
+ const m = f;
201
+ P(!m), c?.(!m);
211
202
  try {
212
- u ? await b({
213
- productId: l,
214
- shopId: f.id,
215
- productVariantId: t?.id || m
216
- }) : await C({
217
- productId: l,
218
- shopId: f.id,
219
- productVariantId: t?.id || m
203
+ m ? await g({
204
+ productId: t.id,
205
+ shopId: t.shop.id,
206
+ productVariantId: e?.id || t.defaultVariantId
207
+ }) : await h({
208
+ productId: t.id,
209
+ shopId: t.shop.id,
210
+ productVariantId: e?.id || t.defaultVariantId
220
211
  });
221
212
  } catch {
222
- A(u), s?.(u);
213
+ P(m), c?.(m);
223
214
  }
224
215
  }, [
225
- p,
226
- l,
227
- f.id,
228
- t?.id,
229
- m,
230
- C,
231
- b,
232
- s
233
- ]);
234
- return /* @__PURE__ */ y(
235
- W,
236
- {
216
+ f,
217
+ t.id,
218
+ t.shop.id,
219
+ t.defaultVariantId,
220
+ e?.id,
221
+ h,
222
+ g,
223
+ c
224
+ ]), b = A(
225
+ () => ({
226
+ // Core data
227
+ product: t,
228
+ selectedProductVariant: e,
229
+ // UI configuration
237
230
  variant: r,
238
231
  touchable: a,
239
- onPress: R,
240
- children: [
241
- /* @__PURE__ */ y(X, { variant: r, children: [
242
- /* @__PURE__ */ e(
243
- Y,
244
- {
245
- src: F,
246
- alt: T,
247
- aspectRatio: 1,
248
- thumbhash: I?.thumbhash ?? void 0
249
- }
250
- ),
251
- r === "priceOverlay" && h && v && /* @__PURE__ */ e(k, { position: "top-left", children: U(v, h) }),
252
- i && /* @__PURE__ */ e(k, { position: "bottom-left", variant: d, children: i }),
253
- /* @__PURE__ */ e(
254
- Z,
255
- {
256
- filled: p,
257
- onPress: z
258
- }
259
- )
260
- ] }),
261
- /* @__PURE__ */ y(_, { variant: r, children: [
262
- /* @__PURE__ */ e($, { children: x }),
263
- /* @__PURE__ */ e(
264
- D,
265
- {
266
- amount: v,
267
- currencyCode: h,
268
- compareAtPriceAmount: O,
269
- compareAtPriceCurrencyCode: N?.currencyCode
270
- }
271
- )
272
- ] })
273
- ]
274
- }
232
+ badgeText: n,
233
+ badgeVariant: i,
234
+ // State
235
+ isFavorited: f,
236
+ // Actions
237
+ onClick: y,
238
+ onFavoriteToggle: x
239
+ }),
240
+ [
241
+ t,
242
+ e,
243
+ r,
244
+ a,
245
+ n,
246
+ i,
247
+ f,
248
+ y,
249
+ x
250
+ ]
275
251
  );
252
+ return /* @__PURE__ */ o(I.Provider, { value: b, children: p ?? /* @__PURE__ */ v(L, { children: [
253
+ /* @__PURE__ */ v(M, { children: [
254
+ /* @__PURE__ */ o(R, {}),
255
+ r === "priceOverlay" && /* @__PURE__ */ o(J, {}),
256
+ /* @__PURE__ */ o(w, {}),
257
+ /* @__PURE__ */ o(q, {})
258
+ ] }),
259
+ r === "default" && /* @__PURE__ */ v(D, { children: [
260
+ /* @__PURE__ */ o(G, {}),
261
+ /* @__PURE__ */ o(H, {})
262
+ ] })
263
+ ] }) });
276
264
  }
277
265
  export {
278
- pt as ProductCard
266
+ ot as ProductCard,
267
+ w as ProductCardBadge,
268
+ L as ProductCardContainer,
269
+ q as ProductCardFavoriteButton,
270
+ R as ProductCardImage,
271
+ M as ProductCardImageContainer,
272
+ D as ProductCardInfo,
273
+ H as ProductCardPrice,
274
+ G as ProductCardTitle
279
275
  };
280
276
  //# 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'\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 {ProductVariantPrice} from '../atoms/product-variant-price'\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\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\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 <ProductVariantPrice\n amount={amount}\n currencyCode={currencyCode}\n compareAtPriceAmount={compareAtPriceAmount}\n compareAtPriceCurrencyCode={displayCompareAtPrice?.currencyCode}\n />\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","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","handlePress","handleFavoritePress","previousState","jsxs","formatMoney","ProductVariantPrice"],"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 {FavoriteButton} from '../atoms/favorite-button'\nimport {ProductVariantPrice} from '../atoms/product-variant-price'\nimport {ThumbhashImage} from '../atoms/thumbhash-image'\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 <ThumbhashImage\n data-slot=\"product-card-image\"\n src={src}\n alt={alt}\n aspectRatio={1}\n thumbhash={thumbhash}\n className={cn('w-full h-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('w-full h-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 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 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","ThumbhashImage","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":";;;;;;;;;;;;AAmCA,MAAMA,IAAqBC,EAAM,cAE/B,MAAS;AAEX,SAASC,IAAwB;AACzB,QAAAC,IAAUC,EAAWJ,CAAkB;AAC7C,MAAI,CAACG;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAEK,SAAAA;AACT;AAGA,SAASE,EAAqB;AAAA,EAC5B,WAAAC;AAAA,EACA,GAAGC;AACL,GAAgC;AAC9B,QAAM,EAAC,WAAAC,GAAW,SAAAC,EAAO,IAAIP,EAAsB,GAE7CQ,IACJ,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC;AAAA,QACT;AAAA,QACAN;AAAA,MACF;AAAA,MACC,GAAGC;AAAA,IAAA;AAAA,EACN;AAGF,SAAIC,KAAaC,IAEb,gBAAAE;AAAA,IAACE;AAAA,IAAA;AAAA,MACC,SAAAJ;AAAA,MACA,UAAU,EAAC,SAAS,IAAG;AAAA,MACvB,YAAY;AAAA,QACV,SAAS,EAAC,MAAM,SAAS,UAAU,MAAM,MAAM,YAAW;AAAA,MAC5D;AAAA,MAEC,UAAAC;AAAA,IAAA;AAAA,EACH,IAIGA;AACT;AAEA,SAASI,EAA0B;AAAA,EACjC,WAAAR;AAAA,EACA,GAAGC;AACL,GAAgC;AACxB,QAAA,EAAC,SAAAQ,EAAO,IAAIb,EAAsB;AAGtC,SAAA,gBAAAS;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWC;AAAA;AAAA,QAET;AAAA,QACA;AAAA,QACA;AAAA,QACAG,MAAY,YAAY,kBAAkB;AAAA,QAC1CT;AAAA,MACF;AAAA,MACC,GAAGC;AAAA,IAAA;AAAA,EACN;AAEJ;AAEA,SAASS,EAAiB,EAAC,WAAAV,GAAW,GAAGC,KAAqC;AAC5E,QAAM,EAAC,SAAAU,GAAS,wBAAAC,EAAsB,IAAIhB,EAAsB,GAG1DiB,IAAeD,GAAwB,SAASD,EAAQ,eACxDG,IAAMD,GAAc,KACpBE,IAAMF,GAAc,WAAWF,EAAQ,OACvCK,IAAYL,EAAQ,eAAe,WAEnCM,IAAqBC;AAAA,IACzB,CAACJ,MACsBE,IACnB,gBAAAX;AAAA,MAACc;AAAA,MAAA;AAAA,QACC,aAAU;AAAA,QACV,KAAKL;AAAAA,QACL,KAAAC;AAAA,QACA,aAAa;AAAA,QACb,WAAAC;AAAA,QACA,WAAWV,EAAG,8BAA8BN,CAAS;AAAA,QACpD,GAAGC;AAAA,MAAA;AAAA,IAAA,IAGN,gBAAAI;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,aAAU;AAAA,QACV,KAAKS;AAAAA,QACL,KAAAC;AAAA,QACA,WAAWT,EAAG,iBAAiBN,CAAS;AAAA,QACvC,GAAGC;AAAA,MAAA;AAAA,IACN;AAAA,IAKJ,CAACc,GAAKf,GAAWC,GAAOe,CAAS;AAAA,EACnC;AAEA,SACG,gBAAAX,EAAA,OAAA,EAAI,WAAU,8DACZ,UACCS,IAAAG,EAAmBH,CAAG,IAErB,gBAAAT,EAAA,OAAA,EAAI,WAAU,4CAA2C,qBAAQ,CAAA,GAEtE;AAEJ;AAEA,SAASe,EAAiB;AAAA,EACxB,WAAApB;AAAA,EACA,UAAAqB,IAAW;AAAA,EACX,SAAAZ;AAAA,EACA,UAAAa;AAAA,EACA,GAAGrB;AACL,GAEG;AACD,QAAM,EAAC,WAAAsB,GAAW,cAAAC,EAAY,IAAI5B,EAAsB,GAElDQ,IAAUkB,KAAYC;AAExB,SAACnB,IAGH,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC;AAAA,QACT;AAAA,QACAe,MAAa,aAAa,iBAAiB;AAAA,MAC7C;AAAA,MAEA,UAAA,gBAAAhB;AAAA,QAACoB;AAAA,QAAA;AAAA,UACC,SAAShB,KAAWe,KAAgB;AAAA,UACpC,WAAWlB;AAAA,YACT,CAACkB,KACC,CAACf,KACD;AAAA,YACF;AAAA,YACAT;AAAA,UACF;AAAA,UACC,GAAGC;AAAA,UAEH,UAAAG;AAAA,QAAA;AAAA,MAAA;AAAA,IACH;AAAA,EACF,IAtBmB;AAwBvB;AAEA,SAASsB,EAA0B;AAAA,EACjC,WAAA1B;AAAA,EACA,GAAGC;AACL,GAAgC;AAC9B,QAAM,EAAC,aAAA0B,GAAa,kBAAAC,EAAgB,IAAIhC,EAAsB;AAC9D,SACG,gBAAAS,EAAA,OAAA,EAAI,WAAWC,EAAG,kCAAkCN,CAAS,GAAI,GAAGC,GACnE,4BAAC4B,GAAe,EAAA,SAASD,GAAkB,QAAQD,EAAa,CAAA,GAClE;AAEJ;AAEA,SAASG,EAAgB,EAAC,WAAA9B,GAAW,GAAGC,KAAqC;AACrE,QAAA,EAAC,SAAAQ,EAAO,IAAIb,EAAsB;AACxC,SAAIa,MAAY,YACP,OAIP,gBAAAJ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWC,EAAG,4BAA4BN,CAAS;AAAA,MAClD,GAAGC;AAAA,IAAA;AAAA,EACN;AAEJ;AAEA,SAAS8B,EAAiB;AAAA,EACxB,WAAA/B;AAAA,EACA,UAAAsB;AAAA,EACA,GAAGrB;AACL,GAA+B;AACvB,QAAA,EAAC,SAAAU,EAAO,IAAIf,EAAsB;AAEtC,SAAA,gBAAAS;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAWC;AAAA,QACT;AAAA,QACA;AAAA,QACAN;AAAA,MACF;AAAA,MACC,GAAGC;AAAA,MAEH,eAAYU,EAAQ;AAAA,IAAA;AAAA,EACvB;AAEJ;AAEA,SAASqB,EAAiB,EAAC,WAAAhC,KAAkC;AAC3D,QAAM,EAAC,SAAAW,GAAS,wBAAAC,EAAsB,IAAIhB,EAAsB,GAG1DqC,IAAerB,GAAwB,SAASD,GAAS,OACzDuB,IACJtB,GAAwB,kBAAkBD,GAAS;AAGnD,SAAA,gBAAAN;AAAA,IAAC8B;AAAA,IAAA;AAAA,MACC,QAAQF,GAAc,UAAU;AAAA,MAChC,cAAcA,GAAc,gBAAgB;AAAA,MAC5C,sBAAsBC,GAAuB;AAAA,MAC7C,4BAA4BA,GAAuB;AAAA,MACnD,WAAAlC;AAAA,IAAA;AAAA,EACF;AAEJ;AAGA,SAASoC,IAA+B;AACtC,QAAM,EAAC,SAAAzB,GAAS,wBAAAC,GAAwB,SAAAH,EAAA,IAAWb,EAAsB;AACrE,MAAAa,MAAY,eAAuB,QAAA;AACjC,QAAAwB,IAAerB,GAAwB,SAASD,EAAQ,OACxD0B,IAAeJ,GAAc,cAC7BK,IAASL,GAAc;AAE7B,SAAI,CAACI,KAAgB,CAACC,IAAe,yBAElClB,GAAiB,EAAA,UAAS,YACxB,UAAYmB,EAAAD,GAAQD,CAAY,GACnC;AAEJ;AAuBA,SAASG,GAAY;AAAA,EACnB,SAAA7B;AAAA,EACA,wBAAAC;AAAA,EACA,SAAAH,IAAU;AAAA,EACV,WAAAP,IAAY;AAAA,EACZ,WAAAqB;AAAA,EACA,cAAAC;AAAA,EACA,gBAAAiB;AAAA,EACA,mBAAAC;AAAA,EACA,UAAApB;AACF,GAAqB;AACb,QAAA,EAAC,mBAAAqB,EAAiB,IAAIC,EAAkB,GACxC,EAAC,aAAAC,GAAa,eAAAC,EAAa,IAAIC,EAAwB,GAGvD,CAACC,GAAkBC,CAAmB,IAAIC,EAASvC,EAAQ,WAAW,GAEtEwC,IAAcjC,EAAY,MAAM;AACpC,IAAKhB,MAEYuC,IAAA,GAECE,EAAA;AAAA,MAChB,WAAWhC,EAAQ;AAAA,IAAA,CACpB;AAAA,EAAA,GACA,CAACgC,GAAmBhC,EAAQ,IAAIT,GAAWuC,CAAc,CAAC,GAEvDW,IAAsBlC,EAAY,YAAY;AAClD,UAAMmC,IAAgBL;AAGtB,IAAAC,EAAoB,CAACI,CAAa,GAClCX,IAAoB,CAACW,CAAa;AAE9B,QAAA;AACF,MAAIA,IACF,MAAMP,EAAc;AAAA,QAClB,WAAWnC,EAAQ;AAAA,QACnB,QAAQA,EAAQ,KAAK;AAAA,QACrB,kBACEC,GAAwB,MAAMD,EAAQ;AAAA,MAAA,CACzC,IAED,MAAMkC,EAAY;AAAA,QAChB,WAAWlC,EAAQ;AAAA,QACnB,QAAQA,EAAQ,KAAK;AAAA,QACrB,kBACEC,GAAwB,MAAMD,EAAQ;AAAA,MAAA,CACzC;AAAA,YAEW;AAEd,MAAAsC,EAAoBI,CAAa,GACjCX,IAAoBW,CAAa;AAAA,IAAA;AAAA,EACnC,GACC;AAAA,IACDL;AAAA,IACArC,EAAQ;AAAA,IACRA,EAAQ,KAAK;AAAA,IACbA,EAAQ;AAAA,IACRC,GAAwB;AAAA,IACxBiC;AAAA,IACAC;AAAA,IACAJ;AAAA,EAAA,CACD,GAEKY,IAAeC;AAAA,IACnB,OAAO;AAAA;AAAA,MAEL,SAAA5C;AAAA,MACA,wBAAAC;AAAA;AAAA,MAGA,SAAAH;AAAA,MACA,WAAAP;AAAA,MACA,WAAAqB;AAAA,MACA,cAAAC;AAAA;AAAA,MAGA,aAAawB;AAAA;AAAA,MAGb,SAASG;AAAA,MACT,kBAAkBC;AAAA,IAAA;AAAA,IAEpB;AAAA,MACEzC;AAAA,MACAC;AAAA,MACAH;AAAA,MACAP;AAAA,MACAqB;AAAA,MACAC;AAAA,MACAwB;AAAA,MACAG;AAAA,MACAC;AAAA,IAAA;AAAA,EAEJ;AAGE,SAAA,gBAAA/C,EAACX,EAAmB,UAAnB,EAA4B,OAAO4D,GACjC,UAAAhC,uBACEvB,GACC,EAAA,UAAA;AAAA,IAAA,gBAAAyD,EAAChD,GACC,EAAA,UAAA;AAAA,MAAA,gBAAAH,EAACK,GAAiB,EAAA;AAAA,MACjBD,MAAY,kBAAkB,gBAAAJ,EAAC+B,GAA6B,CAAA,CAAA;AAAA,wBAC5DhB,GAAiB,EAAA;AAAA,wBACjBM,GAA0B,CAAA,CAAA;AAAA,IAAA,GAC7B;AAAA,IACCjB,MAAY,aACX,gBAAA+C,EAAC1B,GACC,EAAA,UAAA;AAAA,MAAA,gBAAAzB,EAAC0B,GAAiB,EAAA;AAAA,wBACjBC,GAAiB,CAAA,CAAA;AAAA,IAAA,EACpB,CAAA;AAAA,EAAA,EAAA,CAEJ,EAEJ,CAAA;AAEJ;"}
@@ -1,40 +1,42 @@
1
- import { jsx as a } from "react/jsx-runtime";
2
- import { cva as o } from "../../shop-minis-react/node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.js";
3
- import { cn as n } from "../../lib/utils.js";
1
+ import { jsx as n } from "react/jsx-runtime";
2
+ import { cva as a } from "../../shop-minis-react/node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.js";
3
+ import { cn as i } from "../../lib/utils.js";
4
4
  import { Root as s } 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";
5
- const d = o(
6
- "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
5
+ const d = a(
6
+ "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none transition-[color,box-shadow] overflow-hidden",
7
7
  {
8
8
  variants: {
9
9
  variant: {
10
- default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
11
- secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
12
- destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
13
- outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
10
+ primary: "border-transparent bg-primary text-primary-foreground",
11
+ secondary: "border-transparent bg-secondary text-secondary-foreground",
12
+ destructive: "border-transparent bg-destructive text-white dark:bg-destructive/60",
13
+ outline: "bg-white text-foreground",
14
+ none: ""
15
+ // Allows custom classes
14
16
  }
15
17
  },
16
18
  defaultVariants: {
17
- variant: "default"
19
+ variant: "primary"
18
20
  }
19
21
  }
20
22
  );
21
- function b({
23
+ function u({
22
24
  className: r,
23
- variant: e,
24
- asChild: t = !1,
25
- ...i
25
+ variant: t,
26
+ asChild: e = !1,
27
+ ...o
26
28
  }) {
27
- return /* @__PURE__ */ a(
28
- t ? s : "span",
29
+ return /* @__PURE__ */ n(
30
+ e ? s : "span",
29
31
  {
30
32
  "data-slot": "badge",
31
- className: n(d({ variant: e }), r),
32
- ...i
33
+ className: i(d({ variant: t }), r),
34
+ ...o
33
35
  }
34
36
  );
35
37
  }
36
38
  export {
37
- b as Badge,
39
+ u as Badge,
38
40
  d as badgeVariants
39
41
  };
40
42
  //# sourceMappingURL=badge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"badge.js","sources":["../../../src/components/ui/badge.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport {cva, type VariantProps} from 'class-variance-authority'\nimport {Slot as SlotPrimitive} from 'radix-ui'\n\nimport {cn} from '../../lib/utils'\n\nconst badgeVariants = cva(\n 'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden',\n {\n variants: {\n variant: {\n default:\n 'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90',\n secondary:\n 'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90',\n destructive:\n 'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',\n outline:\n 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n)\n\nfunction Badge({\n className,\n variant,\n asChild = false,\n ...props\n}: React.ComponentProps<'span'> &\n VariantProps<typeof badgeVariants> & {asChild?: boolean}) {\n const Comp = asChild ? SlotPrimitive.Slot : 'span'\n\n return (\n <Comp\n data-slot=\"badge\"\n className={cn(badgeVariants({variant}), className)}\n {...props}\n />\n )\n}\n\nexport {Badge, badgeVariants}\n"],"names":["badgeVariants","cva","Badge","className","variant","asChild","props","jsx","SlotPrimitive.Slot","cn"],"mappings":";;;;AAOA,MAAMA,IAAgBC;AAAA,EACpB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SACE;AAAA,QACF,WACE;AAAA,QACF,aACE;AAAA,QACF,SACE;AAAA,MAAA;AAAA,IAEN;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ;AAEA,SAASC,EAAM;AAAA,EACb,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,GAAGC;AACL,GAC4D;AAIxD,SAAA,gBAAAC;AAAA,IAHWF,IAAUG,IAAqB;AAAA,IAGzC;AAAA,MACC,aAAU;AAAA,MACV,WAAWC,EAAGT,EAAc,EAAC,SAAAI,EAAQ,CAAA,GAAGD,CAAS;AAAA,MAChD,GAAGG;AAAA,IAAA;AAAA,EACN;AAEJ;"}
1
+ {"version":3,"file":"badge.js","sources":["../../../src/components/ui/badge.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport {cva, type VariantProps} from 'class-variance-authority'\nimport {Slot as SlotPrimitive} from 'radix-ui'\n\nimport {cn} from '../../lib/utils'\n\nconst badgeVariants = cva(\n 'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none transition-[color,box-shadow] overflow-hidden',\n {\n variants: {\n variant: {\n primary: 'border-transparent bg-primary text-primary-foreground',\n secondary: 'border-transparent bg-secondary text-secondary-foreground',\n destructive:\n 'border-transparent bg-destructive text-white dark:bg-destructive/60',\n outline: 'bg-white text-foreground',\n none: '', // Allows custom classes\n },\n },\n defaultVariants: {\n variant: 'primary',\n },\n }\n)\n\nfunction Badge({\n className,\n variant,\n asChild = false,\n ...props\n}: React.ComponentProps<'span'> &\n VariantProps<typeof badgeVariants> & {asChild?: boolean}) {\n const Comp = asChild ? SlotPrimitive.Slot : 'span'\n\n return (\n <Comp\n data-slot=\"badge\"\n className={cn(badgeVariants({variant}), className)}\n {...props}\n />\n )\n}\n\nexport {Badge, badgeVariants}\n"],"names":["badgeVariants","cva","Badge","className","variant","asChild","props","jsx","SlotPrimitive.Slot","cn"],"mappings":";;;;AAOA,MAAMA,IAAgBC;AAAA,EACpB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,WAAW;AAAA,QACX,aACE;AAAA,QACF,SAAS;AAAA,QACT,MAAM;AAAA;AAAA,MAAA;AAAA,IAEV;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ;AAEA,SAASC,EAAM;AAAA,EACb,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,GAAGC;AACL,GAC4D;AAIxD,SAAA,gBAAAC;AAAA,IAHWF,IAAUG,IAAqB;AAAA,IAGzC;AAAA,MACC,aAAU;AAAA,MACV,WAAWC,EAAGT,EAAc,EAAC,SAAAI,EAAQ,CAAA,GAAGD,CAAS;AAAA,MAChD,GAAGG;AAAA,IAAA;AAAA,EACN;AAEJ;"}