@shopify/shop-minis-react
Version:
React component library for Shopify Shop Minis with Tailwind CSS v4 support (source-only, requires TypeScript)
306 lines (305 loc) • 7.76 kB
JavaScript
import { jsx as o, jsxs as h } from "react/jsx-runtime";
import * as F from "react";
import { useState as R, useCallback as C, useMemo as k, useContext as z } from "react";
import { useShopNavigation as S } from "../../hooks/navigation/useShopNavigation.js";
import { useSavedProductsActions as V } from "../../hooks/user/useSavedProductsActions.js";
import { ProductReviewStars as j } from "../../internal/components/product-review-stars.js";
import { cn as d } from "../../lib/utils.js";
import { formatMoney as B } from "../../utils/formatMoney.js";
import { Image as T } from "../atoms/image.js";
import { ProductVariantPrice as E } from "../atoms/product-variant-price.js";
import { Touchable as O } from "../atoms/touchable.js";
import { Badge as L } from "../ui/badge.js";
import { FavoriteButton as M } from "./favorite-button.js";
const b = F.createContext(void 0);
function s() {
const t = z(b);
if (!t)
throw new Error(
"ProductCard components must be used within a ProductCard provider"
);
return t;
}
function q({
className: t,
...e
}) {
const { touchable: r, onClick: a } = s(), n = /* @__PURE__ */ o(
"div",
{
className: d(
"relative size-full overflow-hidden rounded-xl border-0 isolate",
t
),
...e
}
);
return r && a ? /* @__PURE__ */ o(
O,
{
onClick: a,
whileTap: { opacity: 0.7 },
transition: {
opacity: { type: "tween", duration: 0.08, ease: "easeInOut" }
},
children: n
}
) : n;
}
function D({
className: t,
...e
}) {
const { variant: r } = s();
return /* @__PURE__ */ o(
"div",
{
"data-slot": "product-card-image-container",
className: d(
"relative overflow-hidden rounded-xl border border-gray-200",
"aspect-square",
r === "compact" ? "min-h-[104px]" : "min-h-[134px]",
t
),
...e
}
);
}
function G({ className: t, ...e }) {
const { product: r, selectedProductVariant: a } = s(), n = a?.image || r.featuredImage, i = n?.url, u = n?.altText || r.title, c = r.featuredImage?.thumbhash, p = C(
(l) => c ? /* @__PURE__ */ o(
T,
{
"data-slot": "product-card-image",
src: l,
alt: u,
aspectRatio: 1,
thumbhash: c,
objectFit: "cover",
className: d("size-full", t),
...e
}
) : /* @__PURE__ */ o(
"img",
{
"data-slot": "product-card-image",
src: l,
alt: u,
className: d("size-full object-cover", t),
...e
}
),
[u, t, e, c]
);
return /* @__PURE__ */ o("div", { className: "bg-gray-100 flex items-center justify-center size-full", children: i ? p(i) : /* @__PURE__ */ o("div", { className: "text-gray-400 text-sm w-full text-center", children: "No Image" }) });
}
function N({
className: t,
position: e = "bottom-left",
variant: r,
children: a,
...n
}) {
const { badgeText: i, badgeVariant: u } = s(), c = a || i;
return c ? /* @__PURE__ */ o(
"div",
{
className: d(
"absolute z-10",
e === "top-left" ? "top-3 left-3" : "bottom-2 left-2"
),
children: /* @__PURE__ */ o(
L,
{
variant: r ?? u ?? "none",
className: d(
!u && !r && "bg-black/50 text-white border-transparent",
"rounded",
t
),
...n,
children: c
}
)
}
) : null;
}
function H({
className: t,
...e
}) {
const { isFavorited: r, favoriteButtonDisabled: a, onFavoriteToggle: n } = s();
return a ? null : /* @__PURE__ */ o("div", { className: d("absolute bottom-3 right-3 z-10", t), ...e, children: /* @__PURE__ */ o(M, { onClick: n, filled: r }) });
}
function J({ className: t, ...e }) {
const { variant: r } = s();
return r !== "default" ? null : /* @__PURE__ */ o(
"div",
{
"data-testid": "product-card-info",
className: d("px-1 pt-2 pb-0 space-y-1", t),
...e
}
);
}
function K({
className: t,
children: e,
...r
}) {
const { product: a } = s();
return /* @__PURE__ */ o(
"h3",
{
"data-slot": "product-card-title",
className: d(
"text-sm font-medium leading-tight text-gray-900",
"truncate overflow-hidden whitespace-nowrap text-ellipsis",
t
),
...r,
children: e || a.title
}
);
}
function Q({
className: t,
...e
}) {
const { product: r, reviewsDisabled: a } = s(), n = r.reviewAnalytics;
return a || !n?.averageRating ? null : /* @__PURE__ */ o(
"div",
{
"data-slot": "product-card-review-stars",
className: d("", t),
...e,
children: /* @__PURE__ */ o(
j,
{
averageRating: n.averageRating,
reviewCount: n.reviewCount
}
)
}
);
}
function U({ className: t }) {
const { product: e, selectedProductVariant: r } = s(), a = r?.price || e?.price, n = r?.compareAtPrice || e?.compareAtPrice;
return /* @__PURE__ */ o(
E,
{
amount: a?.amount || "",
currencyCode: a?.currencyCode || "",
compareAtPriceAmount: n?.amount,
compareAtPriceCurrencyCode: n?.currencyCode,
className: t
}
);
}
function W() {
const { product: t, selectedProductVariant: e, variant: r } = s();
if (r !== "priceOverlay") return null;
const a = e?.price || t.price, n = a?.currencyCode, i = a?.amount;
return !n || !i ? null : /* @__PURE__ */ o(N, { position: "top-left", children: B(i, n) });
}
function dt({
product: t,
selectedProductVariant: e,
variant: r = "default",
touchable: a = !0,
badgeText: n,
badgeVariant: i,
onProductClick: u,
onFavoriteToggled: c,
children: p,
favoriteButtonDisabled: l = !1,
reviewsDisabled: v = !1
}) {
const { navigateToProduct: g } = S(), { saveProduct: P, unsaveProduct: y } = V(), [f, x] = R(t.isFavorited), w = C(() => {
a && (u?.(), g({
productId: t.id
}));
}, [g, t.id, a, u]), I = C(async () => {
const m = f;
x(!m), c?.(!m);
try {
m ? await y({
productId: t.id,
shopId: t.shop.id,
productVariantId: e?.id || t.defaultVariantId
}) : await P({
productId: t.id,
shopId: t.shop.id,
productVariantId: e?.id || t.defaultVariantId
});
} catch {
x(m), c?.(m);
}
}, [
f,
t.id,
t.shop.id,
t.defaultVariantId,
e?.id,
P,
y,
c
]), A = k(
() => ({
// Core data
product: t,
selectedProductVariant: e,
// UI configuration
variant: r,
touchable: a,
badgeText: n,
badgeVariant: i,
favoriteButtonDisabled: l,
reviewsDisabled: v,
// State
isFavorited: f,
// Actions
onClick: w,
onFavoriteToggle: I
}),
[
t,
e,
r,
a,
n,
i,
f,
w,
I,
l,
v
]
);
return /* @__PURE__ */ o(b.Provider, { value: A, children: p ?? /* @__PURE__ */ h(q, { children: [
/* @__PURE__ */ h(D, { children: [
/* @__PURE__ */ o(G, {}),
r === "priceOverlay" && /* @__PURE__ */ o(W, {}),
/* @__PURE__ */ o(N, {}),
/* @__PURE__ */ o(H, {})
] }),
r === "default" && /* @__PURE__ */ h(J, { children: [
/* @__PURE__ */ o(K, {}),
/* @__PURE__ */ o(Q, {}),
/* @__PURE__ */ o(U, {})
] })
] }) });
}
export {
dt as ProductCard,
N as ProductCardBadge,
q as ProductCardContainer,
H as ProductCardFavoriteButton,
G as ProductCardImage,
D as ProductCardImageContainer,
J as ProductCardInfo,
U as ProductCardPrice,
Q as ProductCardReviewStars,
K as ProductCardTitle
};
//# sourceMappingURL=product-card.js.map