@shopify/shop-minis-react 0.4.16 → 0.4.18
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/components/atoms/alert-dialog.js.map +1 -1
- package/dist/components/atoms/button.js.map +1 -1
- package/dist/components/atoms/icon-button.js.map +1 -1
- package/dist/components/atoms/image.js +65 -51
- package/dist/components/atoms/image.js.map +1 -1
- package/dist/components/atoms/list.js.map +1 -1
- package/dist/components/atoms/text-input.js.map +1 -1
- package/dist/components/atoms/touchable.js.map +1 -1
- package/dist/components/atoms/video-player.js +1 -1
- package/dist/components/atoms/video-player.js.map +1 -1
- package/dist/components/commerce/add-to-cart.js.map +1 -1
- package/dist/components/commerce/buy-now.js.map +1 -1
- package/dist/components/commerce/favorite-button.js +1 -4
- package/dist/components/commerce/favorite-button.js.map +1 -1
- package/dist/components/commerce/merchant-card.js.map +1 -1
- package/dist/components/commerce/product-link.js.map +1 -1
- package/dist/components/commerce/quantity-selector.js.map +1 -1
- package/dist/components/content/image-content-wrapper.js.map +1 -1
- package/dist/components/navigation/minis-router.js.map +1 -1
- package/dist/components/navigation/transition-link.js.map +1 -1
- package/dist/components/ui/alert.js.map +1 -1
- package/dist/components/ui/badge.js.map +1 -1
- package/dist/components/ui/input.js.map +1 -1
- package/dist/index.js +75 -73
- package/dist/utils/image.js +44 -24
- package/dist/utils/image.js.map +1 -1
- package/eslint/config.cjs +1 -0
- package/eslint/index.cjs +2 -0
- package/eslint/rules/no-javascript-files.cjs +44 -0
- package/package.json +1 -1
- package/src/components/atoms/alert-dialog.tsx +3 -3
- package/src/components/atoms/button.tsx +22 -0
- package/src/components/atoms/icon-button.tsx +16 -8
- package/src/components/atoms/image.test.tsx +27 -13
- package/src/components/atoms/image.tsx +41 -8
- package/src/components/atoms/list.tsx +25 -2
- package/src/components/atoms/text-input.tsx +3 -1
- package/src/components/atoms/touchable.tsx +15 -4
- package/src/components/atoms/video-player.tsx +16 -6
- package/src/components/commerce/add-to-cart.tsx +7 -11
- package/src/components/commerce/buy-now.tsx +7 -10
- package/src/components/commerce/favorite-button.tsx +6 -5
- package/src/components/commerce/merchant-card.tsx +4 -0
- package/src/components/commerce/product-link.tsx +15 -0
- package/src/components/commerce/quantity-selector.tsx +6 -1
- package/src/components/content/image-content-wrapper.tsx +16 -1
- package/src/components/navigation/minis-router.tsx +2 -2
- package/src/components/navigation/transition-link.tsx +11 -1
- package/src/components/ui/alert.tsx +7 -0
- package/src/components/ui/badge.tsx +9 -0
- package/src/components/ui/input.tsx +15 -0
- package/src/utils/image.ts +38 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alert-dialog.js","sources":["../../../src/components/atoms/alert-dialog.tsx"],"sourcesContent":["import {useState} from 'react'\n\nimport {\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogCancel,\n AlertDialogAction,\n AlertDialog as AlertDialogPrimitive,\n} from '../ui/alert-dialog'\n\nexport interface AlertDialogAtomProps {\n /** The trigger element that opens the alert dialog */\n children: React.ReactNode\n /** The title text shown in the alert dialog header */\n title: string\n /** The description text shown in the alert dialog body */\n description: string\n /** The text shown in the cancel button */\n cancelButtonText
|
|
1
|
+
{"version":3,"file":"alert-dialog.js","sources":["../../../src/components/atoms/alert-dialog.tsx"],"sourcesContent":["import {useState} from 'react'\n\nimport {\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogCancel,\n AlertDialogAction,\n AlertDialog as AlertDialogPrimitive,\n} from '../ui/alert-dialog'\n\nexport interface AlertDialogAtomProps {\n /** The trigger element that opens the alert dialog */\n children: React.ReactNode\n /** The title text shown in the alert dialog header */\n title: string\n /** The description text shown in the alert dialog body */\n description: string\n /** The text shown in the cancel button */\n cancelButtonText?: string\n /** The text shown in the confirmation button */\n confirmationButtonText?: string\n /** Whether the alert dialog is open */\n open?: boolean\n /** Callback fired when the alert dialog open state changes */\n onOpenChange: (open: boolean) => void\n /** Callback fired when the confirmation button is clicked */\n onConfirmationAction: () => void\n}\n\nexport const AlertDialogAtom = ({\n children,\n title,\n description,\n cancelButtonText,\n confirmationButtonText,\n open,\n onOpenChange,\n onConfirmationAction,\n}: AlertDialogAtomProps) => {\n const [isOpen, setIsOpen] = useState(open)\n\n return (\n <AlertDialogPrimitive\n open={isOpen}\n onOpenChange={open => {\n setIsOpen(open)\n onOpenChange(open)\n }}\n >\n <AlertDialogTrigger asChild>{children}</AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>{title}</AlertDialogTitle>\n <AlertDialogDescription>{description}</AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>{cancelButtonText}</AlertDialogCancel>\n <AlertDialogAction onClick={onConfirmationAction}>\n {confirmationButtonText}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialogPrimitive>\n )\n}\n"],"names":["AlertDialogAtom","children","title","description","cancelButtonText","confirmationButtonText","open","onOpenChange","onConfirmationAction","isOpen","setIsOpen","useState","jsxs","AlertDialogPrimitive","jsx","AlertDialogTrigger","AlertDialogContent","AlertDialogHeader","AlertDialogTitle","AlertDialogDescription","AlertDialogFooter","AlertDialogCancel","AlertDialogAction"],"mappings":";;;AAiCO,MAAMA,IAAkB,CAAC;AAAA,EAC9B,UAAAC;AAAA,EACA,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,MAAAC;AAAA,EACA,cAAAC;AAAA,EACA,sBAAAC;AACF,MAA4B;AAC1B,QAAM,CAACC,GAAQC,CAAS,IAAIC,EAASL,CAAI;AAGvC,SAAA,gBAAAM;AAAA,IAACC;AAAAA,IAAA;AAAA,MACC,MAAMJ;AAAA,MACN,cAAc,CAAAH,MAAQ;AACpB,QAAAI,EAAUJ,CAAI,GACdC,EAAaD,CAAI;AAAA,MACnB;AAAA,MAEA,UAAA;AAAA,QAAC,gBAAAQ,EAAAC,GAAA,EAAmB,SAAO,IAAE,UAAAd,EAAS,CAAA;AAAA,0BACrCe,GACC,EAAA,UAAA;AAAA,UAAA,gBAAAJ,EAACK,GACC,EAAA,UAAA;AAAA,YAAA,gBAAAH,EAACI,KAAkB,UAAMhB,EAAA,CAAA;AAAA,YACzB,gBAAAY,EAACK,KAAwB,UAAYhB,EAAA,CAAA;AAAA,UAAA,GACvC;AAAA,4BACCiB,GACC,EAAA,UAAA;AAAA,YAAA,gBAAAN,EAACO,KAAmB,UAAiBjB,EAAA,CAAA;AAAA,YACpC,gBAAAU,EAAAQ,GAAA,EAAkB,SAASd,GACzB,UACHH,EAAA,CAAA;AAAA,UAAA,EACF,CAAA;AAAA,QAAA,EACF,CAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EACF;AAEJ;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.js","sources":["../../../src/components/atoms/button.tsx"],"sourcesContent":["import React from 'react'\n\nimport {VariantProps} from 'class-variance-authority'\n\nimport {cn} from '../../lib/utils'\nimport {BaseButton, buttonVariants} from '../ui/button'\n\nimport {Touchable} from './touchable'\n\nexport function Button({\n className,\n variant,\n size,\n onClick,\n stopPropagation = false,\n ...props\n}: React.ComponentProps<'button'> &\n VariantProps<typeof buttonVariants> & {stopPropagation?: boolean}) {\n const handleClick = React.useCallback(\n (event: React.MouseEvent<any>) => {\n onClick?.(event)\n },\n [onClick]\n )\n\n const wrapperClassName = cn(\n variant === 'icon' ? 'flex w-auto' : 'flex w-full'\n )\n\n return (\n <Touchable\n onClick={handleClick}\n stopPropagation={stopPropagation}\n className={wrapperClassName}\n >\n <BaseButton\n className={cn(className, wrapperClassName)}\n variant={variant}\n size={size}\n {...props}\n />\n </Touchable>\n )\n}\n"],"names":["Button","className","variant","size","onClick","stopPropagation","props","handleClick","React","event","wrapperClassName","cn","jsx","Touchable","BaseButton"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"button.js","sources":["../../../src/components/atoms/button.tsx"],"sourcesContent":["import React from 'react'\n\nimport {VariantProps} from 'class-variance-authority'\n\nimport {cn} from '../../lib/utils'\nimport {BaseButton, buttonVariants} from '../ui/button'\n\nimport {Touchable} from './touchable'\n\nexport interface ButtonDocProps {\n /** Visual style variant */\n variant?:\n | 'default'\n | 'secondary'\n | 'destructive'\n | 'outline'\n | 'ghost'\n | 'link'\n | 'icon'\n /** Button size */\n size?: 'default' | 'sm' | 'lg' | 'icon'\n /** Click handler */\n onClick?: React.MouseEventHandler<HTMLButtonElement>\n /** Prevent click from bubbling to parent elements */\n stopPropagation?: boolean\n /** Whether the button is disabled */\n disabled?: boolean\n /** Button content */\n children?: React.ReactNode\n}\n\nexport function Button({\n className,\n variant,\n size,\n onClick,\n stopPropagation = false,\n ...props\n}: React.ComponentProps<'button'> &\n VariantProps<typeof buttonVariants> & {stopPropagation?: boolean}) {\n const handleClick = React.useCallback(\n (event: React.MouseEvent<any>) => {\n onClick?.(event)\n },\n [onClick]\n )\n\n const wrapperClassName = cn(\n variant === 'icon' ? 'flex w-auto' : 'flex w-full'\n )\n\n return (\n <Touchable\n onClick={handleClick}\n stopPropagation={stopPropagation}\n className={wrapperClassName}\n >\n <BaseButton\n className={cn(className, wrapperClassName)}\n variant={variant}\n size={size}\n {...props}\n />\n </Touchable>\n )\n}\n"],"names":["Button","className","variant","size","onClick","stopPropagation","props","handleClick","React","event","wrapperClassName","cn","jsx","Touchable","BaseButton"],"mappings":";;;;;AA+BO,SAASA,EAAO;AAAA,EACrB,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,MAAAC;AAAA,EACA,SAAAC;AAAA,EACA,iBAAAC,IAAkB;AAAA,EAClB,GAAGC;AACL,GACqE;AACnE,QAAMC,IAAcC,EAAM;AAAA,IACxB,CAACC,MAAiC;AAChC,MAAAL,IAAUK,CAAK;AAAA,IACjB;AAAA,IACA,CAACL,CAAO;AAAA,EACV,GAEMM,IAAmBC;AAAA,IACvBT,MAAY,SAAS,gBAAgB;AAAA,EACvC;AAGE,SAAA,gBAAAU;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,SAASN;AAAA,MACT,iBAAAF;AAAA,MACA,WAAWK;AAAA,MAEX,UAAA,gBAAAE;AAAA,QAACE;AAAA,QAAA;AAAA,UACC,WAAWH,EAAGV,GAAWS,CAAgB;AAAA,UACzC,SAAAR;AAAA,UACA,MAAAC;AAAA,UACC,GAAGG;AAAA,QAAA;AAAA,MAAA;AAAA,IACN;AAAA,EACF;AAEJ;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon-button.js","sources":["../../../src/components/atoms/icon-button.tsx"],"sourcesContent":["import {LucideIcon} from 'lucide-react'\n\nimport {cn} from '../../lib/utils'\n\nimport {Button} from './button'\n\nexport
|
|
1
|
+
{"version":3,"file":"icon-button.js","sources":["../../../src/components/atoms/icon-button.tsx"],"sourcesContent":["import {LucideIcon} from 'lucide-react'\n\nimport {cn} from '../../lib/utils'\n\nimport {Button} from './button'\n\nexport interface IconButtonProps {\n /** Click handler */\n onClick?: () => void\n /** Whether the button is in a filled/active state */\n filled?: boolean\n /** Button size variant */\n size?: 'default' | 'sm' | 'lg'\n /** Lucide icon component to render */\n Icon: LucideIcon\n /** Custom CSS classes for the button container */\n buttonStyles?: string\n /** Custom CSS classes for the icon */\n iconStyles?: string\n}\n\nexport function IconButton({\n onClick,\n filled = false,\n size = 'default',\n Icon,\n buttonStyles,\n iconStyles,\n}: IconButtonProps) {\n const sizeMap = {\n sm: 'size-3',\n default: 'size-4',\n lg: 'size-6',\n }\n\n return (\n <Button\n onClick={onClick}\n variant=\"icon\"\n size={size}\n className={cn(buttonStyles)}\n stopPropagation\n >\n <Icon\n fill={filled ? 'currentColor' : 'none'}\n className={cn('text-primary-foreground', sizeMap[size], iconStyles)}\n />\n </Button>\n )\n}\n"],"names":["IconButton","onClick","filled","size","Icon","buttonStyles","iconStyles","sizeMap","jsx","Button","cn"],"mappings":";;;AAqBO,SAASA,EAAW;AAAA,EACzB,SAAAC;AAAA,EACA,QAAAC,IAAS;AAAA,EACT,MAAAC,IAAO;AAAA,EACP,MAAAC;AAAA,EACA,cAAAC;AAAA,EACA,YAAAC;AACF,GAAoB;AAClB,QAAMC,IAAU;AAAA,IACd,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,IAAI;AAAA,EACN;AAGE,SAAA,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,SAAAR;AAAA,MACA,SAAQ;AAAA,MACR,MAAAE;AAAA,MACA,WAAWO,EAAGL,CAAY;AAAA,MAC1B,iBAAe;AAAA,MAEf,UAAA,gBAAAG;AAAA,QAACJ;AAAA,QAAA;AAAA,UACC,MAAMF,IAAS,iBAAiB;AAAA,UAChC,WAAWQ,EAAG,2BAA2BH,EAAQJ,CAAI,GAAGG,CAAU;AAAA,QAAA;AAAA,MAAA;AAAA,IACpE;AAAA,EACF;AAEJ;"}
|
|
@@ -1,66 +1,80 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { memo as
|
|
3
|
-
import { cn as
|
|
4
|
-
import {
|
|
5
|
-
const
|
|
1
|
+
import { jsxs as y, jsx as m } from "react/jsx-runtime";
|
|
2
|
+
import { memo as I, useState as b, useEffect as f, useMemo as d, useCallback as N } from "react";
|
|
3
|
+
import { cn as r } from "../../lib/utils.js";
|
|
4
|
+
import { getThumbhashBlobURL as k, getResizedImageUrl as w } from "../../utils/image.js";
|
|
5
|
+
const C = I(function(h) {
|
|
6
6
|
const {
|
|
7
|
-
src:
|
|
8
|
-
file:
|
|
9
|
-
thumbhash:
|
|
10
|
-
onLoad:
|
|
11
|
-
className:
|
|
12
|
-
style:
|
|
13
|
-
aspectRatio:
|
|
14
|
-
objectFit:
|
|
15
|
-
...
|
|
16
|
-
} =
|
|
17
|
-
|
|
18
|
-
if (!
|
|
19
|
-
|
|
7
|
+
src: l,
|
|
8
|
+
file: s,
|
|
9
|
+
thumbhash: c,
|
|
10
|
+
onLoad: u,
|
|
11
|
+
className: L,
|
|
12
|
+
style: U,
|
|
13
|
+
aspectRatio: t = "auto",
|
|
14
|
+
objectFit: p = "contain",
|
|
15
|
+
...R
|
|
16
|
+
} = h, [i, g] = b(!1), [a, n] = b(null);
|
|
17
|
+
f(() => {
|
|
18
|
+
if (!s) {
|
|
19
|
+
n(null);
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
|
-
const
|
|
23
|
-
return
|
|
24
|
-
URL.revokeObjectURL(
|
|
22
|
+
const o = URL.createObjectURL(s);
|
|
23
|
+
return n(o), () => {
|
|
24
|
+
URL.revokeObjectURL(o);
|
|
25
25
|
};
|
|
26
|
-
}, [
|
|
27
|
-
const
|
|
28
|
-
() =>
|
|
29
|
-
[s]
|
|
30
|
-
), R = y(
|
|
31
|
-
(e) => {
|
|
32
|
-
U(!0), c?.(e);
|
|
33
|
-
},
|
|
26
|
+
}, [s]);
|
|
27
|
+
const e = d(
|
|
28
|
+
() => k(c ?? void 0),
|
|
34
29
|
[c]
|
|
35
|
-
)
|
|
36
|
-
|
|
30
|
+
);
|
|
31
|
+
f(() => () => {
|
|
32
|
+
e && URL.revokeObjectURL(e);
|
|
33
|
+
}, [e]);
|
|
34
|
+
const j = N(
|
|
35
|
+
(o) => {
|
|
36
|
+
g(!0), u?.(o);
|
|
37
|
+
},
|
|
38
|
+
[u]
|
|
39
|
+
), v = d(() => a || w(l), [a, l]);
|
|
40
|
+
return /* @__PURE__ */ y(
|
|
37
41
|
"div",
|
|
38
42
|
{
|
|
39
|
-
className:
|
|
43
|
+
className: r("relative w-full", L),
|
|
40
44
|
style: {
|
|
41
|
-
...
|
|
42
|
-
...
|
|
43
|
-
backgroundImage: n ? `url(${n})` : void 0,
|
|
44
|
-
backgroundSize: "cover",
|
|
45
|
-
backgroundPosition: "center"
|
|
45
|
+
...U,
|
|
46
|
+
...t !== "auto" && { aspectRatio: t }
|
|
46
47
|
},
|
|
47
|
-
children:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
48
|
+
children: [
|
|
49
|
+
e && !i && /* @__PURE__ */ m(
|
|
50
|
+
"img",
|
|
51
|
+
{
|
|
52
|
+
className: r(
|
|
53
|
+
t === "auto" ? "w-full h-auto" : "absolute inset-0 size-full",
|
|
54
|
+
"object-cover"
|
|
55
|
+
),
|
|
56
|
+
src: e,
|
|
57
|
+
"aria-hidden": "true"
|
|
58
|
+
}
|
|
59
|
+
),
|
|
60
|
+
/* @__PURE__ */ m(
|
|
61
|
+
"img",
|
|
62
|
+
{
|
|
63
|
+
className: r(
|
|
64
|
+
t === "auto" ? "opacity-0 w-full h-auto" : "absolute inset-0 opacity-0 size-full",
|
|
65
|
+
`object-${p}`,
|
|
66
|
+
i && "opacity-100"
|
|
67
|
+
),
|
|
68
|
+
src: v,
|
|
69
|
+
onLoad: j,
|
|
70
|
+
...R
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
]
|
|
60
74
|
}
|
|
61
75
|
);
|
|
62
76
|
});
|
|
63
77
|
export {
|
|
64
|
-
|
|
78
|
+
C as Image
|
|
65
79
|
};
|
|
66
80
|
//# sourceMappingURL=image.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.js","sources":["../../../src/components/atoms/image.tsx"],"sourcesContent":["/* eslint-disable jsx-a11y/alt-text */\n/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */\nimport {\n ImgHTMLAttributes,\n useCallback,\n useMemo,\n memo,\n useState,\n useEffect,\n} from 'react'\n\nimport {cn} from '../../lib/utils'\nimport {
|
|
1
|
+
{"version":3,"file":"image.js","sources":["../../../src/components/atoms/image.tsx"],"sourcesContent":["/* eslint-disable jsx-a11y/alt-text */\n/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */\nimport {\n ImgHTMLAttributes,\n useCallback,\n useMemo,\n memo,\n useState,\n useEffect,\n} from 'react'\n\nimport {cn} from '../../lib/utils'\nimport {getThumbhashBlobURL, getResizedImageUrl} from '../../utils'\n\nexport interface ImageDocProps {\n /** Remote image URL */\n src?: string\n /** File object from useImagePicker (auto-manages blob URL lifecycle) */\n file?: File\n /** Thumbhash string for progressive loading placeholder */\n thumbhash?: string | null\n /** Aspect ratio (e.g., 16/9, \"4/3\", or \"auto\") */\n aspectRatio?: number | string\n /** How the image should fit within its container */\n objectFit?: 'cover' | 'contain' | 'fill' | 'scale-down' | 'none'\n /** Alt text for accessibility */\n alt?: string\n /** Callback when image finishes loading */\n onLoad?: () => void\n}\n\ntype ImageProps = ImgHTMLAttributes<HTMLImageElement> & {\n src?: string\n file?: File\n thumbhash?: string | null\n aspectRatio?: number | string\n objectFit?: 'cover' | 'contain' | 'fill' | 'scale-down' | 'none'\n}\n\nexport const Image = memo(function Image(props: ImageProps) {\n const {\n src,\n file,\n thumbhash,\n onLoad,\n className,\n style,\n aspectRatio = 'auto',\n objectFit = 'contain',\n ...restProps\n } = props\n\n const [isLoaded, setIsLoaded] = useState(false)\n const [blobUrl, setBlobUrl] = useState<string | null>(null)\n\n // Create and manage blob URL for File objects\n useEffect(() => {\n if (!file) {\n setBlobUrl(null)\n return\n }\n\n const url = URL.createObjectURL(file)\n setBlobUrl(url)\n\n // Cleanup on unmount or when file changes\n return () => {\n URL.revokeObjectURL(url)\n }\n }, [file])\n\n const thumbhashBlobUrl = useMemo(\n () => getThumbhashBlobURL(thumbhash ?? undefined),\n [thumbhash]\n )\n\n // Cleanup blob URL when it changes or component unmounts\n useEffect(() => {\n return () => {\n if (thumbhashBlobUrl) {\n URL.revokeObjectURL(thumbhashBlobUrl)\n }\n }\n }, [thumbhashBlobUrl])\n\n const handleLoad = useCallback(\n (event: React.SyntheticEvent<HTMLImageElement, Event>) => {\n setIsLoaded(true)\n onLoad?.(event)\n },\n [onLoad]\n )\n\n // Use blob URL if file is provided, otherwise use src\n const imageSrc = useMemo(() => {\n if (blobUrl) return blobUrl\n return getResizedImageUrl(src)\n }, [blobUrl, src])\n\n return (\n <div\n className={cn('relative w-full', className)}\n style={{\n ...style,\n ...(aspectRatio !== 'auto' && {aspectRatio}),\n }}\n >\n {thumbhashBlobUrl && !isLoaded && (\n <img\n className={cn(\n aspectRatio === 'auto'\n ? 'w-full h-auto'\n : 'absolute inset-0 size-full',\n 'object-cover'\n )}\n src={thumbhashBlobUrl}\n aria-hidden=\"true\"\n />\n )}\n <img\n className={cn(\n aspectRatio === 'auto'\n ? 'opacity-0 w-full h-auto'\n : 'absolute inset-0 opacity-0 size-full',\n `object-${objectFit}`,\n isLoaded && 'opacity-100'\n )}\n src={imageSrc}\n onLoad={handleLoad}\n {...restProps}\n />\n </div>\n )\n})\n"],"names":["Image","memo","props","src","file","thumbhash","onLoad","className","style","aspectRatio","objectFit","restProps","isLoaded","setIsLoaded","useState","blobUrl","setBlobUrl","useEffect","url","thumbhashBlobUrl","useMemo","getThumbhashBlobURL","handleLoad","useCallback","event","imageSrc","getResizedImageUrl","jsxs","cn","jsx"],"mappings":";;;;AAuCO,MAAMA,IAAQC,EAAK,SAAeC,GAAmB;AACpD,QAAA;AAAA,IACJ,KAAAC;AAAA,IACA,MAAAC;AAAA,IACA,WAAAC;AAAA,IACA,QAAAC;AAAA,IACA,WAAAC;AAAA,IACA,OAAAC;AAAA,IACA,aAAAC,IAAc;AAAA,IACd,WAAAC,IAAY;AAAA,IACZ,GAAGC;AAAA,EAAA,IACDT,GAEE,CAACU,GAAUC,CAAW,IAAIC,EAAS,EAAK,GACxC,CAACC,GAASC,CAAU,IAAIF,EAAwB,IAAI;AAG1D,EAAAG,EAAU,MAAM;AACd,QAAI,CAACb,GAAM;AACT,MAAAY,EAAW,IAAI;AACf;AAAA,IAAA;AAGI,UAAAE,IAAM,IAAI,gBAAgBd,CAAI;AACpC,WAAAY,EAAWE,CAAG,GAGP,MAAM;AACX,UAAI,gBAAgBA,CAAG;AAAA,IACzB;AAAA,EAAA,GACC,CAACd,CAAI,CAAC;AAET,QAAMe,IAAmBC;AAAA,IACvB,MAAMC,EAAoBhB,KAAa,MAAS;AAAA,IAChD,CAACA,CAAS;AAAA,EACZ;AAGA,EAAAY,EAAU,MACD,MAAM;AACX,IAAIE,KACF,IAAI,gBAAgBA,CAAgB;AAAA,EAExC,GACC,CAACA,CAAgB,CAAC;AAErB,QAAMG,IAAaC;AAAA,IACjB,CAACC,MAAyD;AACxD,MAAAX,EAAY,EAAI,GAChBP,IAASkB,CAAK;AAAA,IAChB;AAAA,IACA,CAAClB,CAAM;AAAA,EACT,GAGMmB,IAAWL,EAAQ,MACnBL,KACGW,EAAmBvB,CAAG,GAC5B,CAACY,GAASZ,CAAG,CAAC;AAGf,SAAA,gBAAAwB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC,EAAG,mBAAmBrB,CAAS;AAAA,MAC1C,OAAO;AAAA,QACL,GAAGC;AAAA,QACH,GAAIC,MAAgB,UAAU,EAAC,aAAAA,EAAW;AAAA,MAC5C;AAAA,MAEC,UAAA;AAAA,QAAAU,KAAoB,CAACP,KACpB,gBAAAiB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAWD;AAAA,cACTnB,MAAgB,SACZ,kBACA;AAAA,cACJ;AAAA,YACF;AAAA,YACA,KAAKU;AAAA,YACL,eAAY;AAAA,UAAA;AAAA,QACd;AAAA,QAEF,gBAAAU;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAWD;AAAA,cACTnB,MAAgB,SACZ,4BACA;AAAA,cACJ,UAAUC,CAAS;AAAA,cACnBE,KAAY;AAAA,YACd;AAAA,YACA,KAAKa;AAAA,YACL,QAAQH;AAAA,YACP,GAAGX;AAAA,UAAA;AAAA,QAAA;AAAA,MACN;AAAA,IAAA;AAAA,EACF;AAEJ,CAAC;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.js","sources":["../../../src/components/atoms/list.tsx"],"sourcesContent":["import {useCallback, useEffect, useRef} from 'react'\n\nimport {Virtuoso, VirtuosoProps} from 'react-virtuoso'\n\nimport {RefreshIndicator} from '../../internal/components/refresh-indicator'\nimport {usePullToRefresh} from '../../internal/usePullToRefresh'\nimport {findVirtuosoScrollableElement} from '../../internal/utils/virtuoso-dom'\nimport {cn} from '../../lib/utils'\nimport '../../styles/utilities.css'\nimport {Skeleton} from '../ui/skeleton'\n\nconst DEFAULT_REFRESH_PULL_THRESHOLD = 200\nconst ELEMENT_BIND_DELAY = 100\n\
|
|
1
|
+
{"version":3,"file":"list.js","sources":["../../../src/components/atoms/list.tsx"],"sourcesContent":["import {useCallback, useEffect, useRef} from 'react'\n\nimport {Virtuoso, VirtuosoProps} from 'react-virtuoso'\n\nimport {RefreshIndicator} from '../../internal/components/refresh-indicator'\nimport {usePullToRefresh} from '../../internal/usePullToRefresh'\nimport {findVirtuosoScrollableElement} from '../../internal/utils/virtuoso-dom'\nimport {cn} from '../../lib/utils'\nimport '../../styles/utilities.css'\nimport {Skeleton} from '../ui/skeleton'\n\nconst DEFAULT_REFRESH_PULL_THRESHOLD = 200\nconst ELEMENT_BIND_DELAY = 100\n\nexport interface ListDocProps<T = any> {\n /** Array of items to render */\n items: T[]\n /** Function to render each item */\n renderItem: (item: T, index: number) => React.ReactNode\n /** Height of the list container */\n height?: string | number\n /** Show scrollbar (default: false) */\n showScrollbar?: boolean\n /** Header element rendered at the top of the list */\n header?: React.ReactNode\n /** Callback to fetch more items when scrolled to bottom */\n fetchMore?: () => Promise<void>\n /** Custom loading component shown while fetching more */\n loadingComponent?: React.ReactNode\n /** Callback for pull-to-refresh */\n onRefresh?: () => Promise<void>\n /** Whether the list is currently refreshing */\n refreshing?: boolean\n /** Enable pull-to-refresh gesture (default: true) */\n enablePullToRefresh?: boolean\n}\n\nexport interface ListProps<T = any>\n extends Omit<\n VirtuosoProps<T, unknown>,\n 'data' | 'itemContent' | 'endReached'\n > {\n items: T[]\n renderItem: (item: T, index: number) => React.ReactNode\n showScrollbar?: boolean\n header?: React.ReactNode\n fetchMore?: () => Promise<void>\n loadingComponent?: React.ReactNode\n onRefresh?: () => Promise<void>\n refreshing?: boolean\n enablePullToRefresh?: boolean\n}\n\nexport function List<T = any>({\n items,\n height,\n renderItem,\n className,\n showScrollbar = false,\n header,\n fetchMore,\n loadingComponent,\n onRefresh,\n refreshing,\n enablePullToRefresh = true,\n ...virtuosoProps\n}: ListProps<T>) {\n const inFlightFetchMoreRef = useRef<Promise<void> | null>(null)\n const virtuosoRef = useRef<any>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n\n const {state: pullToRefreshState, bindToElement} = usePullToRefresh({\n onRefresh,\n threshold: DEFAULT_REFRESH_PULL_THRESHOLD,\n enabled: enablePullToRefresh && Boolean(onRefresh),\n })\n\n const _fetchMore = useCallback(() => {\n // Dedupe concurrent calls by returning the same in-flight promise\n if (inFlightFetchMoreRef.current) return\n\n const current = Promise.resolve(fetchMore?.()).finally(() => {\n // Only clear if this is still the most recent promise\n if (inFlightFetchMoreRef.current === current) {\n inFlightFetchMoreRef.current = null\n }\n })\n\n inFlightFetchMoreRef.current = current\n }, [fetchMore])\n\n const itemContent = useCallback(\n (index: number, item: T) => <>{renderItem(item, index)}</>,\n [renderItem]\n )\n\n const Footer = useCallback(() => {\n if (!fetchMore) return null\n\n return loadingComponent ?? <Skeleton className=\"h-10 w-full p-8\" />\n }, [loadingComponent, fetchMore])\n\n const classNames = cn(showScrollbar ? undefined : 'no-scrollbars', className)\n\n useEffect(() => {\n if (containerRef.current && enablePullToRefresh && onRefresh) {\n let cleanup: (() => void) | undefined\n\n const findAndBind = () => {\n if (!containerRef.current) return\n\n const scrollableElement = findVirtuosoScrollableElement(\n containerRef.current\n )\n cleanup = bindToElement(scrollableElement)\n }\n\n const timeoutId = setTimeout(findAndBind, ELEMENT_BIND_DELAY)\n\n return () => {\n clearTimeout(timeoutId)\n if (cleanup) cleanup()\n }\n }\n return undefined\n }, [bindToElement, enablePullToRefresh, onRefresh])\n\n const EnhancedHeader = useCallback(() => {\n const effectivePullDistance = refreshing\n ? Math.max(pullToRefreshState.pullDistance, 140)\n : pullToRefreshState.pullDistance\n\n const refreshHeaderHeight = Math.min(\n Math.max(effectivePullDistance, 0),\n 140\n )\n\n return (\n <>\n {enablePullToRefresh && onRefresh && (\n <div\n className=\"flex items-center justify-center\"\n style={{\n height: refreshHeaderHeight,\n overflow: 'hidden',\n }}\n >\n <RefreshIndicator\n pullDistance={pullToRefreshState.pullDistance}\n threshold={DEFAULT_REFRESH_PULL_THRESHOLD}\n isRefreshing={refreshing ?? false}\n canRefresh={pullToRefreshState.canRefresh}\n className=\"relative top-0 inset-x-auto\"\n />\n </div>\n )}\n {header && <div>{header}</div>}\n </>\n )\n }, [header, enablePullToRefresh, onRefresh, pullToRefreshState, refreshing])\n\n return (\n <div\n ref={containerRef}\n className={cn('relative transition-all duration-200', classNames)}\n style={{\n height,\n }}\n >\n <Virtuoso\n ref={virtuosoRef}\n className=\"h-full w-full\"\n data={items}\n itemContent={itemContent}\n components={{\n Header: EnhancedHeader,\n Footer,\n }}\n endReached={fetchMore ? _fetchMore : undefined}\n {...virtuosoProps}\n />\n </div>\n )\n}\n"],"names":["DEFAULT_REFRESH_PULL_THRESHOLD","ELEMENT_BIND_DELAY","List","items","height","renderItem","className","showScrollbar","header","fetchMore","loadingComponent","onRefresh","refreshing","enablePullToRefresh","virtuosoProps","inFlightFetchMoreRef","useRef","virtuosoRef","containerRef","pullToRefreshState","bindToElement","usePullToRefresh","_fetchMore","useCallback","current","itemContent","index","item","Footer","jsx","Skeleton","classNames","cn","useEffect","cleanup","timeoutId","scrollableElement","findVirtuosoScrollableElement","EnhancedHeader","effectivePullDistance","refreshHeaderHeight","jsxs","Fragment","RefreshIndicator","Virtuoso"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-input.js","sources":["../../../src/components/atoms/text-input.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport {useKeyboardAvoidingView} from '../../hooks'\nimport {Input} from '../ui/input'\n\nfunction TextInput({...props}:
|
|
1
|
+
{"version":3,"file":"text-input.js","sources":["../../../src/components/atoms/text-input.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport {useKeyboardAvoidingView} from '../../hooks'\nimport {Input} from '../ui/input'\n\nexport type TextInputProps = React.ComponentProps<'input'>\n\nfunction TextInput({...props}: TextInputProps) {\n const inputRef = React.useRef<HTMLInputElement>(null)\n const {onBlur, onFocus} = useKeyboardAvoidingView()\n\n const _onFocus = React.useCallback(\n (event: React.FocusEvent<HTMLInputElement>) => {\n onFocus(inputRef)\n props.onFocus?.(event)\n },\n [props, onFocus, inputRef]\n )\n\n const _onBlur = React.useCallback(\n (event: React.FocusEvent<HTMLInputElement>) => {\n onBlur()\n props.onBlur?.(event)\n },\n [props, onBlur]\n )\n\n return (\n <Input innerRef={inputRef} onFocus={_onFocus} onBlur={_onBlur} {...props} />\n )\n}\n\nexport {TextInput}\n"],"names":["TextInput","props","inputRef","React","onBlur","onFocus","useKeyboardAvoidingView","_onFocus","event","_onBlur","jsx","Input"],"mappings":";;;;AAOA,SAASA,EAAU,EAAC,GAAGC,KAAwB;AACvC,QAAAC,IAAWC,EAAM,OAAyB,IAAI,GAC9C,EAAC,QAAAC,GAAQ,SAAAC,EAAO,IAAIC,EAAwB,GAE5CC,IAAWJ,EAAM;AAAA,IACrB,CAACK,MAA8C;AAC7C,MAAAH,EAAQH,CAAQ,GAChBD,EAAM,UAAUO,CAAK;AAAA,IACvB;AAAA,IACA,CAACP,GAAOI,GAASH,CAAQ;AAAA,EAC3B,GAEMO,IAAUN,EAAM;AAAA,IACpB,CAACK,MAA8C;AACtC,MAAAJ,EAAA,GACPH,EAAM,SAASO,CAAK;AAAA,IACtB;AAAA,IACA,CAACP,GAAOG,CAAM;AAAA,EAChB;AAGE,SAAA,gBAAAM,EAACC,KAAM,UAAUT,GAAU,SAASK,GAAU,QAAQE,GAAU,GAAGR,EAAO,CAAA;AAE9E;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"touchable.js","sources":["../../../src/components/atoms/touchable.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport {motion, HTMLMotionProps, useAnimationControls} from 'motion/react'\n\nexport
|
|
1
|
+
{"version":3,"file":"touchable.js","sources":["../../../src/components/atoms/touchable.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport {motion, HTMLMotionProps, useAnimationControls} from 'motion/react'\n\nexport interface TouchableDocProps {\n /** Click handler */\n onClick?: React.MouseEventHandler<HTMLDivElement>\n /** Prevent click event from bubbling to parent elements */\n stopPropagation?: boolean\n /** Content to render inside the touchable area */\n children?: React.ReactNode\n}\n\nexport interface TouchableProps extends HTMLMotionProps<'div'> {\n onClick?: React.MouseEventHandler<HTMLDivElement>\n stopPropagation?: boolean\n}\n\nexport const Touchable = ({\n children,\n onClick,\n stopPropagation = false,\n ...props\n}: TouchableProps) => {\n const ref = React.useRef<HTMLDivElement>(null)\n const controls = useAnimationControls()\n\n // Filter out props that shouldn't be passed to motion.div\n // Any other custom props that get added to the component interface should be filtered here\n const {ref: _, ...motionProps} = props\n\n const handleClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (stopPropagation) event.stopPropagation()\n onClick?.(event)\n },\n [stopPropagation, onClick]\n )\n\n // Handle animations manually when stopPropagation is true to prevent parent from receiving event\n React.useEffect(() => {\n if (!stopPropagation || !ref.current) return\n\n const element = ref.current\n\n const handlePointerDown = (event: PointerEvent) => {\n event.stopImmediatePropagation()\n event.stopPropagation()\n\n // Animate to pressed state\n controls.start({\n opacity: 0.7,\n transition: {\n opacity: {type: 'tween', duration: 0.08, ease: 'linear'},\n },\n })\n }\n\n const handlePointerUp = (event: PointerEvent) => {\n event.stopImmediatePropagation()\n event.stopPropagation()\n\n // Animate back to normal state\n controls.start({\n opacity: 1,\n transition: {\n opacity: {type: 'tween', duration: 0.08, ease: 'linear'},\n },\n })\n }\n\n // Capture pointer event before Motion\n element.addEventListener('pointerdown', handlePointerDown, true)\n element.addEventListener('pointerup', handlePointerUp, true)\n\n return () => {\n element.removeEventListener('pointerdown', handlePointerDown, true)\n element.removeEventListener('pointerup', handlePointerUp, true)\n }\n }, [stopPropagation, controls])\n\n return (\n <motion.div\n ref={ref}\n data-touchable=\"true\"\n className=\"flex w-full\"\n animate={stopPropagation ? controls : undefined}\n whileTap={stopPropagation ? undefined : {opacity: 0.7}}\n transition={{\n opacity: {type: 'tween', duration: 0.08, ease: 'linear'},\n }}\n onClick={handleClick}\n style={{\n touchAction: stopPropagation ? 'manipulation' : undefined,\n }}\n {...motionProps}\n >\n {children}\n </motion.div>\n )\n}\n"],"names":["Touchable","children","onClick","stopPropagation","props","ref","React","controls","useAnimationControls","_","motionProps","handleClick","event","element","handlePointerDown","handlePointerUp","jsx","motion"],"mappings":";;;;AAkBO,MAAMA,IAAY,CAAC;AAAA,EACxB,UAAAC;AAAA,EACA,SAAAC;AAAA,EACA,iBAAAC,IAAkB;AAAA,EAClB,GAAGC;AACL,MAAsB;AACd,QAAAC,IAAMC,EAAM,OAAuB,IAAI,GACvCC,IAAWC,EAAqB,GAIhC,EAAC,KAAKC,GAAG,GAAGC,EAAe,IAAAN,GAE3BO,IAAcL,EAAM;AAAA,IACxB,CAACM,MAA4C;AACvC,MAAAT,OAAuB,gBAAgB,GAC3CD,IAAUU,CAAK;AAAA,IACjB;AAAA,IACA,CAACT,GAAiBD,CAAO;AAAA,EAC3B;AAGA,SAAAI,EAAM,UAAU,MAAM;AACpB,QAAI,CAACH,KAAmB,CAACE,EAAI,QAAS;AAEtC,UAAMQ,IAAUR,EAAI,SAEdS,IAAoB,CAACF,MAAwB;AACjD,MAAAA,EAAM,yBAAyB,GAC/BA,EAAM,gBAAgB,GAGtBL,EAAS,MAAM;AAAA,QACb,SAAS;AAAA,QACT,YAAY;AAAA,UACV,SAAS,EAAC,MAAM,SAAS,UAAU,MAAM,MAAM,SAAQ;AAAA,QAAA;AAAA,MACzD,CACD;AAAA,IACH,GAEMQ,IAAkB,CAACH,MAAwB;AAC/C,MAAAA,EAAM,yBAAyB,GAC/BA,EAAM,gBAAgB,GAGtBL,EAAS,MAAM;AAAA,QACb,SAAS;AAAA,QACT,YAAY;AAAA,UACV,SAAS,EAAC,MAAM,SAAS,UAAU,MAAM,MAAM,SAAQ;AAAA,QAAA;AAAA,MACzD,CACD;AAAA,IACH;AAGQ,WAAAM,EAAA,iBAAiB,eAAeC,GAAmB,EAAI,GACvDD,EAAA,iBAAiB,aAAaE,GAAiB,EAAI,GAEpD,MAAM;AACH,MAAAF,EAAA,oBAAoB,eAAeC,GAAmB,EAAI,GAC1DD,EAAA,oBAAoB,aAAaE,GAAiB,EAAI;AAAA,IAChE;AAAA,EAAA,GACC,CAACZ,GAAiBI,CAAQ,CAAC,GAG5B,gBAAAS;AAAA,IAACC,EAAO;AAAA,IAAP;AAAA,MACC,KAAAZ;AAAA,MACA,kBAAe;AAAA,MACf,WAAU;AAAA,MACV,SAASF,IAAkBI,IAAW;AAAA,MACtC,UAAUJ,IAAkB,SAAY,EAAC,SAAS,IAAG;AAAA,MACrD,YAAY;AAAA,QACV,SAAS,EAAC,MAAM,SAAS,UAAU,MAAM,MAAM,SAAQ;AAAA,MACzD;AAAA,MACA,SAASQ;AAAA,MACT,OAAO;AAAA,QACL,aAAaR,IAAkB,iBAAiB;AAAA,MAClD;AAAA,MACC,GAAGO;AAAA,MAEH,UAAAT;AAAA,IAAA;AAAA,EACH;AAEJ;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video-player.js","sources":["../../../src/components/atoms/video-player.tsx"],"sourcesContent":["import {\n useRef,\n useEffect,\n useState,\n useCallback,\n forwardRef,\n useImperativeHandle,\n useMemo,\n} from 'react'\n\nimport videojs from 'video.js'\nimport Player from 'video.js/dist/types/player'\nimport 'video.js/dist/video-js.css'\n\nexport interface VideoPlayerRef {\n play: () => Promise<void>\n pause: () => void\n}\n\
|
|
1
|
+
{"version":3,"file":"video-player.js","sources":["../../../src/components/atoms/video-player.tsx"],"sourcesContent":["import {\n useRef,\n useEffect,\n useState,\n useCallback,\n forwardRef,\n useImperativeHandle,\n useMemo,\n} from 'react'\n\nimport videojs from 'video.js'\nimport Player from 'video.js/dist/types/player'\nimport 'video.js/dist/video-js.css'\n\nexport interface VideoPlayerRef {\n play: () => Promise<void>\n pause: () => void\n}\n\nexport interface VideoPlayerProps {\n /** The video source URL */\n src: string\n /** The format/MIME type of the video (default: 'video/mp4') */\n format?: string\n /** Whether the video should be muted */\n muted?: boolean\n /** URL for the poster image shown before playback */\n poster?: string\n /** Whether the video should autoplay */\n autoplay?: boolean\n /** Preload behavior: 'none', 'metadata', or 'auto' */\n preload?: 'none' | 'metadata' | 'auto'\n /** Whether the video should loop */\n loop?: boolean\n /** Video width in pixels */\n width?: number\n /** Video height in pixels */\n height?: number\n /** Custom play button component */\n playButtonComponent?: React.ReactNode\n /** Callback when video starts playing */\n onPlay?: () => void\n /** Callback when video is paused */\n onPause?: () => void\n /** Callback when video ends */\n onEnded?: () => void\n /** Callback when video player is ready */\n onReady?: () => void\n}\n\nexport const VideoPlayer: React.ForwardRefExoticComponent<\n VideoPlayerProps & React.RefAttributes<VideoPlayerRef>\n> = forwardRef<VideoPlayerRef, VideoPlayerProps>(\n (\n {\n src,\n format = 'video/mp4',\n poster,\n muted,\n autoplay,\n preload = 'auto',\n loop = false,\n width,\n height,\n playButtonComponent,\n onPlay,\n onPause,\n onEnded,\n onReady,\n },\n ref\n ) => {\n const videoContainerRef = useRef<HTMLDivElement>(null)\n const playerRef = useRef<Player | null>(null)\n\n const [isPlaying, setIsPlaying] = useState(false)\n\n // Expose imperative methods to parent components\n useImperativeHandle(\n ref,\n () => ({\n play: async () => {\n if (playerRef.current) {\n try {\n await playerRef.current.play()\n setIsPlaying(true)\n } catch (error) {\n console.error('Error playing video:', error)\n }\n }\n },\n pause: () => {\n if (playerRef.current) {\n playerRef.current.pause()\n setIsPlaying(false)\n }\n },\n }),\n []\n )\n\n const options = useMemo(\n () => ({\n controls: false,\n controlBar: {\n volumePanel: {\n inline: false,\n },\n },\n preload,\n loop,\n muted,\n // This makes sure that the video player does not take over the whole screen\n preferFullWindow: false,\n playsinline: true,\n poster,\n height,\n width,\n sources: [\n {\n src,\n type: format,\n },\n ],\n }),\n [muted, poster, height, width, src, format, preload, loop]\n )\n\n useEffect(() => {\n const player = playerRef.current\n\n return () => {\n if (player && !player.isDisposed()) {\n player.dispose()\n playerRef.current = null\n }\n }\n }, [playerRef])\n\n useEffect(() => {\n if (!playerRef.current) return\n\n const handlePlay = () => {\n onPlay?.()\n setIsPlaying(true)\n }\n const handlePause = () => {\n onPause?.()\n setIsPlaying(false)\n }\n const handleEnded = () => {\n onEnded?.()\n setIsPlaying(false)\n }\n\n playerRef.current.on('play', handlePlay)\n playerRef.current.on('pause', handlePause)\n playerRef.current.on('ended', handleEnded)\n\n return () => {\n if (playerRef.current) {\n playerRef.current.off('play', handlePlay)\n playerRef.current.off('pause', handlePause)\n playerRef.current.off('ended', handleEnded)\n }\n }\n }, [onEnded, onPause, onPlay])\n\n const togglePlayPause = useCallback(() => {\n if (isPlaying) {\n playerRef.current?.pause()\n setIsPlaying(false)\n } else {\n playerRef.current?.play()\n setIsPlaying(true)\n }\n }, [isPlaying])\n\n useEffect(() => {\n if (!playerRef.current) {\n const videoElement = document.createElement('video-js')\n\n // The Video.js player needs to be _inside_ the component element for React 18 Strict Mode.\n videoContainerRef.current?.appendChild(videoElement)\n\n playerRef.current = videojs(videoElement, options, () => {\n onReady && onReady()\n\n if (autoplay) {\n togglePlayPause()\n }\n })\n }\n }, [options, videoContainerRef, autoplay, onReady, togglePlayPause])\n\n // Update muted state when prop changes after initial render\n useEffect(() => {\n if (playerRef.current && !playerRef.current.isDisposed()) {\n playerRef.current.muted(muted ?? false)\n }\n }, [muted])\n\n const containerClassName = [\n width ? `w-${width}` : undefined,\n 'relative',\n ].join(' ')\n\n return (\n <div className=\"flex\">\n <div data-vjs-player className={containerClassName}>\n <div ref={videoContainerRef} />\n <div\n className=\"absolute top-0 left-0 w-full h-full flex items-center justify-center cursor-pointer\"\n onClick={togglePlayPause}\n aria-hidden\n >\n {isPlaying ? null : (playButtonComponent ?? <DefaultPlayIcon />)}\n </div>\n </div>\n </div>\n )\n }\n)\n\nconst DefaultPlayIcon = () => (\n <div className=\"absolute inset-0 flex items-center justify-center bg-black/20 cursor-pointer animate-in fade-in duration-200\">\n <svg\n viewBox=\"0 0 24 24\"\n className=\"w-10 h-10 text-white\"\n fill=\"currentColor\"\n >\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n </div>\n)\n"],"names":["VideoPlayer","forwardRef","src","format","poster","muted","autoplay","preload","loop","width","height","playButtonComponent","onPlay","onPause","onEnded","onReady","ref","videoContainerRef","useRef","playerRef","isPlaying","setIsPlaying","useState","useImperativeHandle","error","options","useMemo","useEffect","player","handlePlay","handlePause","handleEnded","togglePlayPause","useCallback","videoElement","videojs","containerClassName","jsx","DefaultPlayIcon"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add-to-cart.js","sources":["../../../src/components/commerce/add-to-cart.tsx"],"sourcesContent":["import * as React from 'react'\nimport {useState, useCallback} from 'react'\n\nimport {Product} from '@shopify/shop-minis-platform'\nimport {CheckIcon} from 'lucide-react'\nimport {motion, AnimatePresence} from 'motion/react'\n\nimport {useErrorToast, useShopNavigation} from '../../hooks'\nimport {useShopCartActions} from '../../internal/useShopCartActions'\nimport {cn} from '../../lib/utils'\nimport {Button} from '../atoms/button'\n\
|
|
1
|
+
{"version":3,"file":"add-to-cart.js","sources":["../../../src/components/commerce/add-to-cart.tsx"],"sourcesContent":["import * as React from 'react'\nimport {useState, useCallback} from 'react'\n\nimport {Product} from '@shopify/shop-minis-platform'\nimport {CheckIcon} from 'lucide-react'\nimport {motion, AnimatePresence} from 'motion/react'\n\nimport {useErrorToast, useShopNavigation} from '../../hooks'\nimport {useShopCartActions} from '../../internal/useShopCartActions'\nimport {cn} from '../../lib/utils'\nimport {Button} from '../atoms/button'\n\nexport interface AddToCartButtonProps {\n /** Whether the button is disabled */\n disabled?: boolean\n /** CSS class name */\n className?: string\n /** Button size variant */\n size?: 'default' | 'sm' | 'lg'\n /** The discount codes to apply to the cart */\n discountCodes?: string[]\n /** The GID of the product variant. E.g. `gid://shopify/ProductVariant/456` */\n productVariantId: string\n /** The product to add to the cart */\n product?: Product\n}\n\nexport function AddToCartButton({\n disabled = false,\n className,\n size = 'default',\n productVariantId,\n discountCodes,\n product,\n}: AddToCartButtonProps) {\n const {addToCart} = useShopCartActions()\n const {navigateToProduct} = useShopNavigation()\n const [isAdded, setIsAdded] = useState(false)\n const timeoutRef = React.useRef<number | undefined>(undefined)\n const {id, referral, variants} = product ?? {}\n\n const variantImageUrl = variants?.find(\n variant => variant.id === productVariantId\n )?.image?.url\n\n const {showErrorToast} = useErrorToast()\n\n const handleClick = useCallback(async () => {\n if (disabled) return\n\n if (id && referral) {\n navigateToProduct({\n productId: id,\n })\n\n return\n }\n\n if (isAdded) return\n\n try {\n if (id && productVariantId) {\n addToCart({\n productId: id,\n productVariantId,\n quantity: 1,\n discountCodes,\n variantImageUrl,\n })\n .then(() => {})\n .catch(() => {\n showErrorToast({message: 'Failed to add to cart'})\n })\n }\n\n // Show success state\n setIsAdded(true)\n\n // Clear any existing timeout\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current)\n }\n\n // Reset to initial state after delay\n timeoutRef.current = window.setTimeout(() => {\n setIsAdded(false)\n }, 2000)\n } catch (error) {\n // Handle error - reset to initial state\n setIsAdded(false)\n console.error('Failed to add to cart:', error)\n }\n }, [\n disabled,\n id,\n referral,\n isAdded,\n navigateToProduct,\n productVariantId,\n addToCart,\n discountCodes,\n variantImageUrl,\n showErrorToast,\n ])\n\n // Cleanup timeout on unmount\n React.useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current)\n }\n }\n }, [])\n\n const addToCartText = isAdded ? 'Added to cart' : 'Add to cart'\n const buttonText = referral ? 'View product' : addToCartText\n\n return (\n <Button\n onClick={handleClick}\n disabled={disabled}\n className={cn(\n 'relative overflow-hidden transition-all duration-300',\n className\n )}\n size={size}\n >\n <div className=\"relative flex items-center justify-center\">\n <AnimatePresence>\n {isAdded && (\n <motion.div\n initial={{scale: 0, rotate: -180}}\n animate={{scale: 1, rotate: 0}}\n exit={{scale: 0, rotate: 180}}\n transition={{\n duration: 0.4,\n ease: [0.175, 0.885, 0.32, 1.275], // bounce effect\n }}\n className=\"absolute left-2\"\n style={{x: -8}}\n >\n <CheckIcon className=\"size-4\" />\n </motion.div>\n )}\n </AnimatePresence>\n <span className={cn(isAdded && 'pl-5', 'transition-all duration-300')}>\n {buttonText}\n </span>\n </div>\n </Button>\n )\n}\n"],"names":["AddToCartButton","disabled","className","size","productVariantId","discountCodes","product","addToCart","useShopCartActions","navigateToProduct","useShopNavigation","isAdded","setIsAdded","useState","timeoutRef","React","id","referral","variants","variantImageUrl","variant","showErrorToast","useErrorToast","handleClick","useCallback","error","buttonText","jsx","Button","cn","jsxs","AnimatePresence","motion","CheckIcon"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buy-now.js","sources":["../../../src/components/commerce/buy-now.tsx"],"sourcesContent":["import {useState, useCallback} from 'react'\n\nimport {Product} from '@shopify/shop-minis-platform'\nimport {motion, AnimatePresence} from 'motion/react'\n\nimport {useErrorToast, useShopNavigation} from '../../hooks'\nimport {useShopCartActions} from '../../internal/useShopCartActions'\nimport {cn} from '../../lib/utils'\nimport {Button} from '../atoms/button'\n\
|
|
1
|
+
{"version":3,"file":"buy-now.js","sources":["../../../src/components/commerce/buy-now.tsx"],"sourcesContent":["import {useState, useCallback} from 'react'\n\nimport {Product} from '@shopify/shop-minis-platform'\nimport {motion, AnimatePresence} from 'motion/react'\n\nimport {useErrorToast, useShopNavigation} from '../../hooks'\nimport {useShopCartActions} from '../../internal/useShopCartActions'\nimport {cn} from '../../lib/utils'\nimport {Button} from '../atoms/button'\n\nexport interface BuyNowButtonProps {\n /** Whether the button is disabled */\n disabled?: boolean\n /** CSS class name */\n className?: string\n /** Button size variant */\n size?: 'default' | 'sm' | 'lg'\n /** The discount code to apply to the purchase */\n discountCode?: string\n /** The GID of the product variant. E.g. `gid://shopify/ProductVariant/456` */\n productVariantId: string\n /** The product to buy now */\n product?: Product\n}\n\nexport function BuyNowButton({\n disabled = false,\n className,\n size = 'default',\n productVariantId,\n discountCode,\n product,\n}: BuyNowButtonProps) {\n const {buyProduct} = useShopCartActions()\n const {navigateToProduct} = useShopNavigation()\n const [isPurchasing, setIsPurchasing] = useState(false)\n const {id, referral} = product ?? {}\n\n const {showErrorToast} = useErrorToast()\n\n const handleClick = useCallback(async () => {\n if (disabled) return\n\n if (id && referral) {\n navigateToProduct({\n productId: id,\n })\n\n return\n }\n\n if (isPurchasing) return\n\n try {\n if (id && productVariantId) {\n setIsPurchasing(true)\n\n await buyProduct({\n productId: id,\n productVariantId,\n quantity: 1,\n discountCode,\n })\n\n setIsPurchasing(false)\n }\n } catch (error) {\n showErrorToast({message: 'Failed to complete purchase'})\n setIsPurchasing(false)\n }\n }, [\n disabled,\n id,\n referral,\n isPurchasing,\n navigateToProduct,\n productVariantId,\n buyProduct,\n discountCode,\n showErrorToast,\n ])\n\n return (\n <Button\n onClick={handleClick}\n disabled={disabled || isPurchasing}\n className={cn('relative overflow-hidden', className)}\n size={size}\n aria-live=\"polite\"\n aria-busy={isPurchasing}\n >\n <AnimatePresence mode=\"wait\">\n <motion.span\n key=\"text\"\n initial={{opacity: 0, y: 10}}\n animate={{opacity: 1, y: 0}}\n exit={{opacity: 0, y: -10}}\n transition={{duration: 0.2}}\n >\n {referral ? 'View product' : 'Buy now'}\n </motion.span>\n </AnimatePresence>\n </Button>\n )\n}\n"],"names":["BuyNowButton","disabled","className","size","productVariantId","discountCode","product","buyProduct","useShopCartActions","navigateToProduct","useShopNavigation","isPurchasing","setIsPurchasing","useState","id","referral","showErrorToast","useErrorToast","handleClick","useCallback","jsx","Button","cn","AnimatePresence","motion"],"mappings":";;;;;;;;;AAyBO,SAASA,EAAa;AAAA,EAC3B,UAAAC,IAAW;AAAA,EACX,WAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,kBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,SAAAC;AACF,GAAsB;AACd,QAAA,EAAC,YAAAC,EAAU,IAAIC,EAAmB,GAClC,EAAC,mBAAAC,EAAiB,IAAIC,EAAkB,GACxC,CAACC,GAAcC,CAAe,IAAIC,EAAS,EAAK,GAChD,EAAC,IAAAC,GAAI,UAAAC,EAAQ,IAAIT,KAAW,CAAC,GAE7B,EAAC,gBAAAU,EAAc,IAAIC,EAAc,GAEjCC,IAAcC,EAAY,YAAY;AAC1C,QAAI,CAAAlB,GAEJ;AAAA,UAAIa,KAAMC,GAAU;AACA,QAAAN,EAAA;AAAA,UAChB,WAAWK;AAAA,QAAA,CACZ;AAED;AAAA,MAAA;AAGF,UAAI,CAAAH;AAEA,YAAA;AACF,UAAIG,KAAMV,MACRQ,EAAgB,EAAI,GAEpB,MAAML,EAAW;AAAA,YACf,WAAWO;AAAA,YACX,kBAAAV;AAAA,YACA,UAAU;AAAA,YACV,cAAAC;AAAA,UAAA,CACD,GAEDO,EAAgB,EAAK;AAAA,gBAET;AACC,UAAAI,EAAA,EAAC,SAAS,+BAA8B,GACvDJ,EAAgB,EAAK;AAAA,QAAA;AAAA;AAAA,EACvB,GACC;AAAA,IACDX;AAAA,IACAa;AAAA,IACAC;AAAA,IACAJ;AAAA,IACAF;AAAA,IACAL;AAAA,IACAG;AAAA,IACAF;AAAA,IACAW;AAAA,EAAA,CACD;AAGC,SAAA,gBAAAI;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,SAASH;AAAA,MACT,UAAUjB,KAAYU;AAAA,MACtB,WAAWW,EAAG,4BAA4BpB,CAAS;AAAA,MACnD,MAAAC;AAAA,MACA,aAAU;AAAA,MACV,aAAWQ;AAAA,MAEX,UAAA,gBAAAS,EAACG,GAAgB,EAAA,MAAK,QACpB,UAAA,gBAAAH;AAAA,QAACI,EAAO;AAAA,QAAP;AAAA,UAEC,SAAS,EAAC,SAAS,GAAG,GAAG,GAAE;AAAA,UAC3B,SAAS,EAAC,SAAS,GAAG,GAAG,EAAC;AAAA,UAC1B,MAAM,EAAC,SAAS,GAAG,GAAG,IAAG;AAAA,UACzB,YAAY,EAAC,UAAU,IAAG;AAAA,UAEzB,cAAW,iBAAiB;AAAA,QAAA;AAAA,QANzB;AAAA,MAAA,EAQR,CAAA;AAAA,IAAA;AAAA,EACF;AAEJ;"}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { jsx as r } from "react/jsx-runtime";
|
|
2
2
|
import { IconButton as n } from "../atoms/icon-button.js";
|
|
3
3
|
import m from "../../shop-minis-react/node_modules/.pnpm/lucide-react@0.513.0_react@19.1.0/node_modules/lucide-react/dist/esm/icons/heart.js";
|
|
4
|
-
function e({
|
|
5
|
-
onClick: t,
|
|
6
|
-
filled: o = !1
|
|
7
|
-
}) {
|
|
4
|
+
function e({ onClick: t, filled: o = !1 }) {
|
|
8
5
|
return /* @__PURE__ */ r(
|
|
9
6
|
n,
|
|
10
7
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"favorite-button.js","sources":["../../../src/components/commerce/favorite-button.tsx"],"sourcesContent":["import {Heart} from 'lucide-react'\n\nimport {IconButton} from '../atoms/icon-button'\n\nexport
|
|
1
|
+
{"version":3,"file":"favorite-button.js","sources":["../../../src/components/commerce/favorite-button.tsx"],"sourcesContent":["import {Heart} from 'lucide-react'\n\nimport {IconButton} from '../atoms/icon-button'\n\nexport interface FavoriteButtonProps {\n /** Click handler for toggling favorite state */\n onClick?: () => void\n /** Whether the product is currently favorited */\n filled?: boolean\n}\n\nexport function FavoriteButton({onClick, filled = false}: FavoriteButtonProps) {\n return (\n <IconButton\n Icon={Heart}\n filled={filled}\n onClick={onClick}\n buttonStyles={\n filled ? 'bg-primary' : 'bg-button-overlay/30 backdrop-blur-sm'\n }\n />\n )\n}\n"],"names":["FavoriteButton","onClick","filled","jsx","IconButton","Heart"],"mappings":";;;AAWO,SAASA,EAAe,EAAC,SAAAC,GAAS,QAAAC,IAAS,MAA6B;AAE3E,SAAA,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,MAAMC;AAAA,MACN,QAAAH;AAAA,MACA,SAAAD;AAAA,MACA,cACEC,IAAS,eAAe;AAAA,IAAA;AAAA,EAE5B;AAEJ;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merchant-card.js","sources":["../../../src/components/commerce/merchant-card.tsx"],"sourcesContent":["import * as React from 'react'\nimport {createContext, useCallback, useContext, useMemo} from 'react'\n\nimport {type Shop} from '@shopify/shop-minis-platform'\nimport {Star} from 'lucide-react'\n\nimport {useShopNavigation} from '../../hooks/navigation/useShopNavigation'\nimport {cn} from '../../lib/utils'\nimport {\n type ExtractedBrandTheme,\n extractBrandTheme,\n formatReviewCount,\n getFeaturedImages,\n normalizeRating,\n} from '../../utils'\nimport {isDarkColor} from '../../utils/colors'\nimport {Image} from '../atoms/image'\nimport {Touchable} from '../atoms/touchable'\n\ninterface MerchantCardContextValue {\n // Core data\n shop: Shop\n\n // Derived data\n cardTheme: ExtractedBrandTheme\n\n // UI configuration\n touchable: boolean\n featuredImagesLimit: number\n\n // Actions\n onClick: () => void\n}\n\nconst MerchantCardContext = createContext<MerchantCardContextValue | undefined>(\n undefined\n)\n\nfunction useMerchantCardContext() {\n const context = useContext(MerchantCardContext)\n if (!context) {\n throw new Error(\n 'useMerchantCardContext must be used within a MerchantCardProvider'\n )\n }\n return context\n}\n\nfunction MerchantCardContainer({\n className,\n ...props\n}: React.ComponentProps<'div'>) {\n const {touchable, cardTheme, onClick} = useMerchantCardContext()\n\n const content = (\n <div\n style={{\n backgroundColor: cardTheme.backgroundColor,\n }}\n className={cn(\n 'relative w-full overflow-hidden rounded-xl bg-white flex flex-col border border-gray-200 aspect-square isolate',\n\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 MerchantCardImage({\n className,\n src,\n alt,\n thumbhash,\n ...props\n}: React.ComponentProps<'img'> & {\n src?: string\n alt?: string\n thumbhash?: string\n}) {\n if (!src) {\n return <div className=\"w-full h-full bg-gray-100\" />\n }\n\n if (thumbhash) {\n return (\n <Image\n data-slot=\"merchant-card-image\"\n src={src}\n alt={alt}\n thumbhash={thumbhash}\n className={cn(className)}\n {...props}\n />\n )\n }\n\n return (\n <img\n data-slot=\"merchant-card-image\"\n src={src}\n alt={alt}\n className={cn('size-full object-cover', className)}\n {...props}\n />\n )\n}\n\nfunction MerchantCardLogo({className, ...props}: React.ComponentProps<'div'>) {\n const {shop} = useMerchantCardContext()\n const {name, visualTheme} = shop\n\n const logoAverageColor = visualTheme?.brandSettings?.colors?.logoAverage\n const logoDominantColor = visualTheme?.brandSettings?.colors?.logoDominant\n const logoColor = logoAverageColor || logoDominantColor\n\n const logoBackgroundClassName = useMemo(\n () => (logoColor && isDarkColor(logoColor) ? 'bg-white' : 'bg-gray-800'),\n [logoColor]\n )\n\n const logoUrl = visualTheme?.logoImage?.url\n const altText = `${name} logo`\n\n return (\n <div\n data-slot=\"merchant-card-logo\"\n className={cn(\n 'absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-10',\n 'w-16 h-16 rounded-xl bg-white border-2 border-white shadow-sm',\n 'flex items-center justify-center overflow-hidden',\n logoBackgroundClassName,\n className\n )}\n {...props}\n >\n {logoUrl ? (\n <img\n src={logoUrl}\n alt={altText}\n className=\"w-full h-full object-cover\"\n />\n ) : (\n <div className=\"w-full h-full bg-gray-200 flex items-center justify-center\">\n <span className=\"text-gray-600 font-semibold text-lg\">\n {name?.slice(0, 1)}\n </span>\n </div>\n )}\n </div>\n )\n}\n\nfunction MerchantCardInfo({className, ...props}: React.ComponentProps<'div'>) {\n const {cardTheme} = useMerchantCardContext()\n\n const isDarkTheme = useMemo(() => {\n return (\n cardTheme.backgroundColor !== 'white' &&\n isDarkColor(cardTheme.backgroundColor)\n )\n }, [cardTheme.backgroundColor])\n\n const textColor = isDarkTheme ? 'text-primary-foreground' : 'text-foreground'\n\n return (\n <div\n data-slot=\"merchant-card-info\"\n className={cn(\n 'p-3 flex-shrink-0 flex flex-col min-w-0',\n textColor,\n className\n )}\n {...props}\n />\n )\n}\n\nfunction MerchantCardName({\n className,\n children,\n ...props\n}: React.ComponentProps<'h3'>) {\n const {shop} = useMerchantCardContext()\n const {name} = shop\n const nameContent = children ?? name\n\n return (\n <h3\n data-slot=\"merchant-card-name\"\n className={cn('text-sm font-medium truncate', className)}\n {...props}\n >\n {nameContent}\n </h3>\n )\n}\n\nfunction MerchantCardRating({\n className,\n\n ...props\n}: React.ComponentProps<'div'> & {\n rating?: number | null\n reviewCount?: number\n}) {\n const {shop} = useMerchantCardContext()\n\n const {\n reviewAnalytics: {averageRating, reviewCount},\n } = shop\n\n if (!averageRating || !reviewCount) return null\n\n return (\n <div\n data-slot=\"merchant-card-rating\"\n className={cn('flex items-center gap-1 text-xs', className)}\n {...props}\n >\n <Star className=\"h-3 w-3 fill-current\" />\n <span className=\"text-xs\">\n {normalizeRating(averageRating)} ({formatReviewCount(reviewCount)})\n </span>\n </div>\n )\n}\n\nfunction MerchantCardDefaultHeader({withLogo = false}: {withLogo?: boolean}) {\n const {shop, cardTheme, featuredImagesLimit} = useMerchantCardContext()\n const {visualTheme} = shop\n\n const featuredImages = useMemo(\n () => getFeaturedImages(visualTheme, featuredImagesLimit),\n [visualTheme, featuredImagesLimit]\n )\n\n const numberOfFeaturedImages = featuredImages?.length ?? 0\n\n const displayDefaultCover = () => {\n if (numberOfFeaturedImages > 0) {\n const heightClass = numberOfFeaturedImages === 2 ? 'h-full' : 'h-1/2'\n return featuredImages?.map((image, index) => (\n <div className={`z-0 w-1/2 ${heightClass}`} key={image.url || index}>\n <MerchantCardImage\n src={image.url}\n alt={image.altText ?? undefined}\n thumbhash={image.thumbhash ?? undefined}\n className=\"aspect-square\"\n />\n </div>\n ))\n } else if (cardTheme.type === 'coverImage') {\n return (\n <MerchantCardImage\n src={cardTheme.coverImageUrl}\n thumbhash={cardTheme.coverImageThumbhash}\n />\n )\n }\n\n return null\n }\n\n return (\n <div className=\"w-full h-full bg-muted relative flex flex-wrap overflow-hidden\">\n {withLogo && (\n <div className=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-10\">\n <MerchantCardLogo />\n </div>\n )}\n\n {displayDefaultCover()}\n </div>\n )\n}\n\nfunction MerchantCardBrandedHeader({withLogo = false}: {withLogo?: boolean}) {\n const {shop, cardTheme} = useMerchantCardContext()\n const wordmarkImage = shop.visualTheme?.brandSettings?.headerTheme?.wordmark\n\n return (\n <div className=\"size-full relative\">\n {cardTheme.type === 'coverImage' && (\n <>\n <MerchantCardImage\n src={cardTheme.coverImageUrl}\n alt={shop.name}\n thumbhash={cardTheme.coverImageThumbhash ?? undefined}\n />\n\n <div className=\"absolute inset-0 z-[1] bg-black/20\" />\n\n <div\n className=\"absolute bottom-0 z-[1] size-full\"\n style={{\n background: `linear-gradient(to top, ${cardTheme.backgroundColor} 0%, ${cardTheme.backgroundColor}00 40%)`,\n }}\n />\n </>\n )}\n\n {withLogo && (\n <div className=\"absolute inset-0 z-[1] flex items-center justify-center\">\n {wordmarkImage ? (\n <img\n src={wordmarkImage.url}\n alt={wordmarkImage.altText || shop.name}\n className=\"max-h-16 min-h-10 max-w-28 object-contain\"\n data-testid=\"store-data-wordmark\"\n />\n ) : (\n <MerchantCardLogo />\n )}\n </div>\n )}\n </div>\n )\n}\n\ninterface MerchantCardHeaderProps {\n isDefault?: boolean\n withLogo?: boolean\n}\n\nfunction MerchantCardHeader({\n isDefault,\n withLogo,\n className,\n ...props\n}: React.ComponentProps<'div'> & MerchantCardHeaderProps) {\n const {cardTheme} = useMerchantCardContext()\n\n const isBranded =\n cardTheme.type === 'coverImage' || cardTheme.type === 'brandColor'\n\n return (\n <div\n className={cn('relative overflow-hidden flex-1 flex-wrap', className)}\n {...props}\n >\n {isBranded && !isDefault ? (\n <MerchantCardBrandedHeader withLogo={withLogo} />\n ) : (\n <MerchantCardDefaultHeader withLogo={withLogo} />\n )}\n </div>\n )\n}\n\nexport interface MerchantCardProps {\n shop: Shop\n touchable?: boolean\n featuredImagesLimit?: number\n children?: React.ReactNode\n}\n\nfunction MerchantCard({\n shop,\n touchable = true,\n featuredImagesLimit = 4,\n children,\n}: MerchantCardProps) {\n const {navigateToShop} = useShopNavigation()\n\n const {id, visualTheme} = shop\n\n const handleClick = useCallback(() => {\n if (!touchable) return\n navigateToShop({shopId: id})\n }, [navigateToShop, id, touchable])\n\n const cardTheme = useMemo(\n () => extractBrandTheme(visualTheme?.brandSettings),\n [visualTheme?.brandSettings]\n )\n\n const contextValue = useMemo<MerchantCardContextValue>(\n () => ({\n shop,\n cardTheme,\n touchable,\n featuredImagesLimit,\n onClick: handleClick,\n }),\n [shop, cardTheme, touchable, featuredImagesLimit, handleClick]\n )\n\n return (\n <MerchantCardContext.Provider value={contextValue}>\n {children ?? (\n <MerchantCardContainer>\n <MerchantCardHeader withLogo />\n <MerchantCardInfo>\n <MerchantCardName />\n <MerchantCardRating />\n </MerchantCardInfo>\n </MerchantCardContainer>\n )}\n </MerchantCardContext.Provider>\n )\n}\n\nexport {\n MerchantCard,\n MerchantCardContainer,\n MerchantCardHeader,\n MerchantCardInfo,\n MerchantCardName,\n MerchantCardRating,\n}\n"],"names":["MerchantCardContext","createContext","useMerchantCardContext","context","useContext","MerchantCardContainer","className","props","touchable","cardTheme","onClick","content","jsx","cn","Touchable","MerchantCardImage","src","alt","thumbhash","Image","MerchantCardLogo","shop","name","visualTheme","logoAverageColor","logoDominantColor","logoColor","logoBackgroundClassName","useMemo","isDarkColor","logoUrl","altText","MerchantCardInfo","textColor","MerchantCardName","children","nameContent","MerchantCardRating","averageRating","reviewCount","jsxs","Star","normalizeRating","formatReviewCount","MerchantCardDefaultHeader","withLogo","featuredImagesLimit","featuredImages","getFeaturedImages","numberOfFeaturedImages","heightClass","image","index","MerchantCardBrandedHeader","wordmarkImage","Fragment","MerchantCardHeader","isDefault","isBranded","MerchantCard","navigateToShop","useShopNavigation","id","handleClick","useCallback","extractBrandTheme","contextValue"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"merchant-card.js","sources":["../../../src/components/commerce/merchant-card.tsx"],"sourcesContent":["import * as React from 'react'\nimport {createContext, useCallback, useContext, useMemo} from 'react'\n\nimport {type Shop} from '@shopify/shop-minis-platform'\nimport {Star} from 'lucide-react'\n\nimport {useShopNavigation} from '../../hooks/navigation/useShopNavigation'\nimport {cn} from '../../lib/utils'\nimport {\n type ExtractedBrandTheme,\n extractBrandTheme,\n formatReviewCount,\n getFeaturedImages,\n normalizeRating,\n} from '../../utils'\nimport {isDarkColor} from '../../utils/colors'\nimport {Image} from '../atoms/image'\nimport {Touchable} from '../atoms/touchable'\n\ninterface MerchantCardContextValue {\n // Core data\n shop: Shop\n\n // Derived data\n cardTheme: ExtractedBrandTheme\n\n // UI configuration\n touchable: boolean\n featuredImagesLimit: number\n\n // Actions\n onClick: () => void\n}\n\nconst MerchantCardContext = createContext<MerchantCardContextValue | undefined>(\n undefined\n)\n\nfunction useMerchantCardContext() {\n const context = useContext(MerchantCardContext)\n if (!context) {\n throw new Error(\n 'useMerchantCardContext must be used within a MerchantCardProvider'\n )\n }\n return context\n}\n\nfunction MerchantCardContainer({\n className,\n ...props\n}: React.ComponentProps<'div'>) {\n const {touchable, cardTheme, onClick} = useMerchantCardContext()\n\n const content = (\n <div\n style={{\n backgroundColor: cardTheme.backgroundColor,\n }}\n className={cn(\n 'relative w-full overflow-hidden rounded-xl bg-white flex flex-col border border-gray-200 aspect-square isolate',\n\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 MerchantCardImage({\n className,\n src,\n alt,\n thumbhash,\n ...props\n}: React.ComponentProps<'img'> & {\n src?: string\n alt?: string\n thumbhash?: string\n}) {\n if (!src) {\n return <div className=\"w-full h-full bg-gray-100\" />\n }\n\n if (thumbhash) {\n return (\n <Image\n data-slot=\"merchant-card-image\"\n src={src}\n alt={alt}\n thumbhash={thumbhash}\n className={cn(className)}\n {...props}\n />\n )\n }\n\n return (\n <img\n data-slot=\"merchant-card-image\"\n src={src}\n alt={alt}\n className={cn('size-full object-cover', className)}\n {...props}\n />\n )\n}\n\nfunction MerchantCardLogo({className, ...props}: React.ComponentProps<'div'>) {\n const {shop} = useMerchantCardContext()\n const {name, visualTheme} = shop\n\n const logoAverageColor = visualTheme?.brandSettings?.colors?.logoAverage\n const logoDominantColor = visualTheme?.brandSettings?.colors?.logoDominant\n const logoColor = logoAverageColor || logoDominantColor\n\n const logoBackgroundClassName = useMemo(\n () => (logoColor && isDarkColor(logoColor) ? 'bg-white' : 'bg-gray-800'),\n [logoColor]\n )\n\n const logoUrl = visualTheme?.logoImage?.url\n const altText = `${name} logo`\n\n return (\n <div\n data-slot=\"merchant-card-logo\"\n className={cn(\n 'absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-10',\n 'w-16 h-16 rounded-xl bg-white border-2 border-white shadow-sm',\n 'flex items-center justify-center overflow-hidden',\n logoBackgroundClassName,\n className\n )}\n {...props}\n >\n {logoUrl ? (\n <img\n src={logoUrl}\n alt={altText}\n className=\"w-full h-full object-cover\"\n />\n ) : (\n <div className=\"w-full h-full bg-gray-200 flex items-center justify-center\">\n <span className=\"text-gray-600 font-semibold text-lg\">\n {name?.slice(0, 1)}\n </span>\n </div>\n )}\n </div>\n )\n}\n\nfunction MerchantCardInfo({className, ...props}: React.ComponentProps<'div'>) {\n const {cardTheme} = useMerchantCardContext()\n\n const isDarkTheme = useMemo(() => {\n return (\n cardTheme.backgroundColor !== 'white' &&\n isDarkColor(cardTheme.backgroundColor)\n )\n }, [cardTheme.backgroundColor])\n\n const textColor = isDarkTheme ? 'text-primary-foreground' : 'text-foreground'\n\n return (\n <div\n data-slot=\"merchant-card-info\"\n className={cn(\n 'p-3 flex-shrink-0 flex flex-col min-w-0',\n textColor,\n className\n )}\n {...props}\n />\n )\n}\n\nfunction MerchantCardName({\n className,\n children,\n ...props\n}: React.ComponentProps<'h3'>) {\n const {shop} = useMerchantCardContext()\n const {name} = shop\n const nameContent = children ?? name\n\n return (\n <h3\n data-slot=\"merchant-card-name\"\n className={cn('text-sm font-medium truncate', className)}\n {...props}\n >\n {nameContent}\n </h3>\n )\n}\n\nfunction MerchantCardRating({\n className,\n\n ...props\n}: React.ComponentProps<'div'> & {\n rating?: number | null\n reviewCount?: number\n}) {\n const {shop} = useMerchantCardContext()\n\n const {\n reviewAnalytics: {averageRating, reviewCount},\n } = shop\n\n if (!averageRating || !reviewCount) return null\n\n return (\n <div\n data-slot=\"merchant-card-rating\"\n className={cn('flex items-center gap-1 text-xs', className)}\n {...props}\n >\n <Star className=\"h-3 w-3 fill-current\" />\n <span className=\"text-xs\">\n {normalizeRating(averageRating)} ({formatReviewCount(reviewCount)})\n </span>\n </div>\n )\n}\n\nfunction MerchantCardDefaultHeader({withLogo = false}: {withLogo?: boolean}) {\n const {shop, cardTheme, featuredImagesLimit} = useMerchantCardContext()\n const {visualTheme} = shop\n\n const featuredImages = useMemo(\n () => getFeaturedImages(visualTheme, featuredImagesLimit),\n [visualTheme, featuredImagesLimit]\n )\n\n const numberOfFeaturedImages = featuredImages?.length ?? 0\n\n const displayDefaultCover = () => {\n if (numberOfFeaturedImages > 0) {\n const heightClass = numberOfFeaturedImages === 2 ? 'h-full' : 'h-1/2'\n return featuredImages?.map((image, index) => (\n <div className={`z-0 w-1/2 ${heightClass}`} key={image.url || index}>\n <MerchantCardImage\n src={image.url}\n alt={image.altText ?? undefined}\n thumbhash={image.thumbhash ?? undefined}\n className=\"aspect-square\"\n />\n </div>\n ))\n } else if (cardTheme.type === 'coverImage') {\n return (\n <MerchantCardImage\n src={cardTheme.coverImageUrl}\n thumbhash={cardTheme.coverImageThumbhash}\n />\n )\n }\n\n return null\n }\n\n return (\n <div className=\"w-full h-full bg-muted relative flex flex-wrap overflow-hidden\">\n {withLogo && (\n <div className=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-10\">\n <MerchantCardLogo />\n </div>\n )}\n\n {displayDefaultCover()}\n </div>\n )\n}\n\nfunction MerchantCardBrandedHeader({withLogo = false}: {withLogo?: boolean}) {\n const {shop, cardTheme} = useMerchantCardContext()\n const wordmarkImage = shop.visualTheme?.brandSettings?.headerTheme?.wordmark\n\n return (\n <div className=\"size-full relative\">\n {cardTheme.type === 'coverImage' && (\n <>\n <MerchantCardImage\n src={cardTheme.coverImageUrl}\n alt={shop.name}\n thumbhash={cardTheme.coverImageThumbhash ?? undefined}\n />\n\n <div className=\"absolute inset-0 z-[1] bg-black/20\" />\n\n <div\n className=\"absolute bottom-0 z-[1] size-full\"\n style={{\n background: `linear-gradient(to top, ${cardTheme.backgroundColor} 0%, ${cardTheme.backgroundColor}00 40%)`,\n }}\n />\n </>\n )}\n\n {withLogo && (\n <div className=\"absolute inset-0 z-[1] flex items-center justify-center\">\n {wordmarkImage ? (\n <img\n src={wordmarkImage.url}\n alt={wordmarkImage.altText || shop.name}\n className=\"max-h-16 min-h-10 max-w-28 object-contain\"\n data-testid=\"store-data-wordmark\"\n />\n ) : (\n <MerchantCardLogo />\n )}\n </div>\n )}\n </div>\n )\n}\n\ninterface MerchantCardHeaderProps {\n isDefault?: boolean\n withLogo?: boolean\n}\n\nfunction MerchantCardHeader({\n isDefault,\n withLogo,\n className,\n ...props\n}: React.ComponentProps<'div'> & MerchantCardHeaderProps) {\n const {cardTheme} = useMerchantCardContext()\n\n const isBranded =\n cardTheme.type === 'coverImage' || cardTheme.type === 'brandColor'\n\n return (\n <div\n className={cn('relative overflow-hidden flex-1 flex-wrap', className)}\n {...props}\n >\n {isBranded && !isDefault ? (\n <MerchantCardBrandedHeader withLogo={withLogo} />\n ) : (\n <MerchantCardDefaultHeader withLogo={withLogo} />\n )}\n </div>\n )\n}\n\nexport interface MerchantCardProps {\n /** The shop/merchant to display */\n shop: Shop\n /** Whether the card is tappable to navigate to shop (default: true) */\n touchable?: boolean\n /** Maximum number of featured product images to show (default: 4) */\n featuredImagesLimit?: number\n /** Custom content to render inside the card */\n children?: React.ReactNode\n}\n\nfunction MerchantCard({\n shop,\n touchable = true,\n featuredImagesLimit = 4,\n children,\n}: MerchantCardProps) {\n const {navigateToShop} = useShopNavigation()\n\n const {id, visualTheme} = shop\n\n const handleClick = useCallback(() => {\n if (!touchable) return\n navigateToShop({shopId: id})\n }, [navigateToShop, id, touchable])\n\n const cardTheme = useMemo(\n () => extractBrandTheme(visualTheme?.brandSettings),\n [visualTheme?.brandSettings]\n )\n\n const contextValue = useMemo<MerchantCardContextValue>(\n () => ({\n shop,\n cardTheme,\n touchable,\n featuredImagesLimit,\n onClick: handleClick,\n }),\n [shop, cardTheme, touchable, featuredImagesLimit, handleClick]\n )\n\n return (\n <MerchantCardContext.Provider value={contextValue}>\n {children ?? (\n <MerchantCardContainer>\n <MerchantCardHeader withLogo />\n <MerchantCardInfo>\n <MerchantCardName />\n <MerchantCardRating />\n </MerchantCardInfo>\n </MerchantCardContainer>\n )}\n </MerchantCardContext.Provider>\n )\n}\n\nexport {\n MerchantCard,\n MerchantCardContainer,\n MerchantCardHeader,\n MerchantCardInfo,\n MerchantCardName,\n MerchantCardRating,\n}\n"],"names":["MerchantCardContext","createContext","useMerchantCardContext","context","useContext","MerchantCardContainer","className","props","touchable","cardTheme","onClick","content","jsx","cn","Touchable","MerchantCardImage","src","alt","thumbhash","Image","MerchantCardLogo","shop","name","visualTheme","logoAverageColor","logoDominantColor","logoColor","logoBackgroundClassName","useMemo","isDarkColor","logoUrl","altText","MerchantCardInfo","textColor","MerchantCardName","children","nameContent","MerchantCardRating","averageRating","reviewCount","jsxs","Star","normalizeRating","formatReviewCount","MerchantCardDefaultHeader","withLogo","featuredImagesLimit","featuredImages","getFeaturedImages","numberOfFeaturedImages","heightClass","image","index","MerchantCardBrandedHeader","wordmarkImage","Fragment","MerchantCardHeader","isDefault","isBranded","MerchantCard","navigateToShop","useShopNavigation","id","handleClick","useCallback","extractBrandTheme","contextValue"],"mappings":"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"}
|