@dust-tt/sparkle 0.2.481-rc2 → 0.2.481-rc4
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/cjs/index.js +1 -1
- package/dist/esm/components/InteractiveImage.d.ts.map +1 -1
- package/dist/esm/components/InteractiveImage.js +42 -34
- package/dist/esm/components/InteractiveImage.js.map +1 -1
- package/dist/sparkle.css +33 -9
- package/package.json +1 -1
- package/src/components/InteractiveImage.tsx +78 -30
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InteractiveImage.d.ts","sourceRoot":"","sources":["../../../src/components/InteractiveImage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"InteractiveImage.d.ts","sourceRoot":"","sources":["../../../src/components/InteractiveImage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAqD1B,UAAU,qBAAqB;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,GAAG,EACH,SAAiB,EACjB,GAAG,EACH,GAAG,KAAK,EACT,EAAE,qBAAqB,qBAsDvB"}
|
|
@@ -3,9 +3,41 @@ import React from "react";
|
|
|
3
3
|
import { Dialog, DialogContent, DialogTrigger, IconButton, Spinner, } from "../components";
|
|
4
4
|
import { ArrowDownOnSquareIcon } from "../icons/app";
|
|
5
5
|
import { cn } from "../lib/utils";
|
|
6
|
+
function DownloadButton(_a) {
|
|
7
|
+
var _this = this;
|
|
8
|
+
var className = _a.className, _b = _a.size, size = _b === void 0 ? "xs" : _b, src = _a.src, title = _a.title;
|
|
9
|
+
var handleDownload = React.useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
10
|
+
var link;
|
|
11
|
+
return __generator(this, function (_a) {
|
|
12
|
+
if (!src) {
|
|
13
|
+
return [2 /*return*/];
|
|
14
|
+
}
|
|
15
|
+
link = document.createElement("a");
|
|
16
|
+
link.href = src;
|
|
17
|
+
link.download = title;
|
|
18
|
+
document.body.appendChild(link);
|
|
19
|
+
link.click();
|
|
20
|
+
document.body.removeChild(link);
|
|
21
|
+
return [2 /*return*/];
|
|
22
|
+
});
|
|
23
|
+
}); }, [src, title]);
|
|
24
|
+
return (React.createElement(IconButton, { icon: ArrowDownOnSquareIcon, className: cn("s-text-white", className), tooltip: "Download", size: size, onClick: function (e) { return __awaiter(_this, void 0, void 0, function () {
|
|
25
|
+
return __generator(this, function (_a) {
|
|
26
|
+
switch (_a.label) {
|
|
27
|
+
case 0:
|
|
28
|
+
e.stopPropagation(); // Prevent image zoom.
|
|
29
|
+
return [4 /*yield*/, handleDownload()];
|
|
30
|
+
case 1:
|
|
31
|
+
_a.sent();
|
|
32
|
+
return [2 /*return*/];
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}); } }));
|
|
36
|
+
}
|
|
6
37
|
export function InteractiveImage(_a) {
|
|
7
38
|
var alt = _a.alt, _b = _a.isLoading, isLoading = _b === void 0 ? false : _b, src = _a.src, props = __rest(_a, ["alt", "isLoading", "src"]);
|
|
8
39
|
var _c = __read(React.useState(false), 2), isZoomed = _c[0], setIsZoomed = _c[1];
|
|
40
|
+
var _d = __read(React.useState(false), 2), imageLoaded = _d[0], setImageLoaded = _d[1];
|
|
9
41
|
var handleZoomToggle = React.useCallback(function () {
|
|
10
42
|
setIsZoomed(!isZoomed);
|
|
11
43
|
}, [isZoomed]);
|
|
@@ -20,46 +52,22 @@ export function InteractiveImage(_a) {
|
|
|
20
52
|
}
|
|
21
53
|
handleZoomToggle();
|
|
22
54
|
}, src: src }, props)))),
|
|
23
|
-
React.createElement(DialogContent, { className: cn("s-w-auto s-max-w-none s-border-0 s-outline-none s-ring-0", "focus:s-outline-none focus:s-ring-0"), size: "xl" },
|
|
24
|
-
React.createElement("
|
|
55
|
+
React.createElement(DialogContent, { className: cn("s-w-auto s-max-w-none s-border-0 s-outline-none s-ring-0", "focus:s-outline-none focus:s-ring-0", "s-rounded-none s-bg-transparent s-shadow-none"), size: "xl" },
|
|
56
|
+
React.createElement("div", { className: "s-flex s-flex-col" },
|
|
57
|
+
React.createElement("div", { className: "s-flex s-justify-end" }, imageLoaded && (React.createElement(DownloadButton, { src: src, title: props.title, size: "sm" }))),
|
|
58
|
+
React.createElement("div", { className: "s-relative s-w-full" },
|
|
59
|
+
React.createElement("img", { src: src, alt: alt, className: "s-w-full s-object-contain", onLoad: function () { return setImageLoaded(true); } }))))));
|
|
25
60
|
}
|
|
26
61
|
function LoadingImage() {
|
|
27
62
|
return (React.createElement("div", { className: "s-flex s-h-full s-w-full s-items-center s-justify-center" },
|
|
28
|
-
React.createElement(Spinner, { variant: "dark", size: "
|
|
63
|
+
React.createElement(Spinner, { variant: "dark", size: "md" })));
|
|
29
64
|
}
|
|
30
65
|
function ImagePreview(_a) {
|
|
31
|
-
var _this = this;
|
|
32
66
|
var isLoading = _a.isLoading, onClick = _a.onClick, alt = _a.alt, src = _a.src, title = _a.title;
|
|
33
|
-
|
|
34
|
-
var link;
|
|
35
|
-
return __generator(this, function (_a) {
|
|
36
|
-
if (!src) {
|
|
37
|
-
return [2 /*return*/];
|
|
38
|
-
}
|
|
39
|
-
link = document.createElement("a");
|
|
40
|
-
link.href = src;
|
|
41
|
-
link.download = title;
|
|
42
|
-
document.body.appendChild(link);
|
|
43
|
-
link.click();
|
|
44
|
-
document.body.removeChild(link);
|
|
45
|
-
return [2 /*return*/];
|
|
46
|
-
});
|
|
47
|
-
}); }, [src, title]);
|
|
48
|
-
return (React.createElement("div", { onClick: onClick, className: cn("s-group/preview s-relative s-h-full s-w-full s-overflow-hidden s-rounded-2xl s-bg-muted-background dark:s-bg-muted-background-night", !isLoading && "s-cursor-pointer") }, isLoading ? (React.createElement(LoadingImage, null)) : (React.createElement(React.Fragment, null,
|
|
67
|
+
return (React.createElement("div", { onClick: onClick, className: cn("s-group/preview s-relative s-h-full s-w-full s-overflow-hidden s-rounded-2xl", "s-bg-muted-background dark:s-bg-muted-background-night", !isLoading && "s-cursor-pointer") }, isLoading ? (React.createElement(LoadingImage, null)) : (React.createElement(React.Fragment, null,
|
|
49
68
|
React.createElement("img", { src: src, alt: alt, className: "s-h-full s-w-full s-rounded-2xl s-object-cover" }),
|
|
50
|
-
React.createElement("div", { className: "s-absolute s-inset-0 s-bg-black s-opacity-0 s-transition-opacity s-duration-200 group-hover/preview:s-opacity-
|
|
51
|
-
React.createElement("div", { className: "s-absolute s-right-3 s-top-3 s-z-10 s-flex s-opacity-0 s-transition-opacity s-duration-200 group-hover/preview:s-opacity-100" },
|
|
52
|
-
React.createElement(
|
|
53
|
-
return __generator(this, function (_a) {
|
|
54
|
-
switch (_a.label) {
|
|
55
|
-
case 0:
|
|
56
|
-
e.stopPropagation(); // Prevent image zoom.
|
|
57
|
-
return [4 /*yield*/, handleDownload()];
|
|
58
|
-
case 1:
|
|
59
|
-
_a.sent();
|
|
60
|
-
return [2 /*return*/];
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
}); } }))))));
|
|
69
|
+
React.createElement("div", { className: cn("s-absolute s-inset-0 s-bg-gradient-to-b", "s-from-black/40 s-via-transparent s-to-black/40", "s-opacity-0 s-transition-opacity s-duration-200", "group-hover/preview:s-opacity-100") }),
|
|
70
|
+
React.createElement("div", { className: cn("s-absolute s-right-3 s-top-3 s-z-10 s-flex", "s-opacity-0 s-transition-opacity s-duration-200", "group-hover/preview:s-opacity-100") },
|
|
71
|
+
React.createElement(DownloadButton, { src: src, title: title, size: "xs" }))))));
|
|
64
72
|
}
|
|
65
73
|
//# sourceMappingURL=InteractiveImage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InteractiveImage.js","sourceRoot":"","sources":["../../../src/components/InteractiveImage.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EACL,MAAM,EACN,aAAa,EACb,aAAa,EACb,UAAU,EACV,OAAO,GACR,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AASxC,MAAM,UAAU,gBAAgB,CAAC,EAKT;IAJtB,IAAA,GAAG,SAAA,EACH,iBAAiB,EAAjB,SAAS,mBAAG,KAAK,KAAA,EACjB,GAAG,SAAA,EACA,KAAK,cAJuB,2BAKhC,CADS;IAEF,IAAA,KAAA,OAA0B,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAA,EAA9C,QAAQ,QAAA,EAAE,WAAW,QAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"InteractiveImage.js","sourceRoot":"","sources":["../../../src/components/InteractiveImage.tsx"],"names":[],"mappings":"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"}
|
package/dist/sparkle.css
CHANGED
|
@@ -2311,6 +2311,10 @@ select {
|
|
|
2311
2311
|
border-radius: 0.375rem;
|
|
2312
2312
|
}
|
|
2313
2313
|
|
|
2314
|
+
.s-rounded-none {
|
|
2315
|
+
border-radius: 0px;
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2314
2318
|
.s-rounded-sm {
|
|
2315
2319
|
border-radius: 0.125rem;
|
|
2316
2320
|
}
|
|
@@ -2674,11 +2678,6 @@ select {
|
|
|
2674
2678
|
background-color: rgb(255 255 255 / 0.8);
|
|
2675
2679
|
}
|
|
2676
2680
|
|
|
2677
|
-
.s-bg-black {
|
|
2678
|
-
--tw-bg-opacity: 1;
|
|
2679
|
-
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
|
|
2680
|
-
}
|
|
2681
|
-
|
|
2682
2681
|
.s-bg-blue-100 {
|
|
2683
2682
|
--tw-bg-opacity: 1;
|
|
2684
2683
|
background-color: rgb(202 235 255 / var(--tw-bg-opacity));
|
|
@@ -3563,6 +3562,10 @@ select {
|
|
|
3563
3562
|
background-color: rgb(169 184 169 / var(--tw-bg-opacity));
|
|
3564
3563
|
}
|
|
3565
3564
|
|
|
3565
|
+
.s-bg-transparent {
|
|
3566
|
+
background-color: transparent;
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3566
3569
|
.s-bg-violet-100 {
|
|
3567
3570
|
--tw-bg-opacity: 1;
|
|
3568
3571
|
background-color: rgb(237 233 254 / var(--tw-bg-opacity));
|
|
@@ -3697,6 +3700,10 @@ select {
|
|
|
3697
3700
|
background-color: rgb(254 240 138 / var(--tw-bg-opacity));
|
|
3698
3701
|
}
|
|
3699
3702
|
|
|
3703
|
+
.s-bg-gradient-to-b {
|
|
3704
|
+
background-image: linear-gradient(to bottom, var(--tw-gradient-stops));
|
|
3705
|
+
}
|
|
3706
|
+
|
|
3700
3707
|
.s-bg-gradient-to-r {
|
|
3701
3708
|
background-image: linear-gradient(to right, var(--tw-gradient-stops));
|
|
3702
3709
|
}
|
|
@@ -3709,6 +3716,12 @@ select {
|
|
|
3709
3716
|
background-image: linear-gradient(90deg, #7AC6FF, #1C91FF, #a855f7, #4BABFF, #0A6CC6);
|
|
3710
3717
|
}
|
|
3711
3718
|
|
|
3719
|
+
.s-from-black\/40 {
|
|
3720
|
+
--tw-gradient-from: rgb(0 0 0 / 0.4) var(--tw-gradient-from-position);
|
|
3721
|
+
--tw-gradient-to: rgb(0 0 0 / 0) var(--tw-gradient-to-position);
|
|
3722
|
+
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
|
3723
|
+
}
|
|
3724
|
+
|
|
3712
3725
|
.s-from-cyan-500 {
|
|
3713
3726
|
--tw-gradient-from: #06b6d4 var(--tw-gradient-from-position);
|
|
3714
3727
|
--tw-gradient-to: rgb(6 182 212 / 0) var(--tw-gradient-to-position);
|
|
@@ -3826,6 +3839,11 @@ select {
|
|
|
3826
3839
|
--tw-gradient-stops: var(--tw-gradient-from), #04140A var(--tw-gradient-via-position), var(--tw-gradient-to);
|
|
3827
3840
|
}
|
|
3828
3841
|
|
|
3842
|
+
.s-via-transparent {
|
|
3843
|
+
--tw-gradient-to: rgb(0 0 0 / 0) var(--tw-gradient-to-position);
|
|
3844
|
+
--tw-gradient-stops: var(--tw-gradient-from), transparent var(--tw-gradient-via-position), var(--tw-gradient-to);
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3829
3847
|
.s-via-warning-950 {
|
|
3830
3848
|
--tw-gradient-to: rgb(34 10 4 / 0) var(--tw-gradient-to-position);
|
|
3831
3849
|
--tw-gradient-stops: var(--tw-gradient-from), #220A04 var(--tw-gradient-via-position), var(--tw-gradient-to);
|
|
@@ -3835,6 +3853,10 @@ select {
|
|
|
3835
3853
|
--tw-gradient-via-position: 50%;
|
|
3836
3854
|
}
|
|
3837
3855
|
|
|
3856
|
+
.s-to-black\/40 {
|
|
3857
|
+
--tw-gradient-to: rgb(0 0 0 / 0.4) var(--tw-gradient-to-position);
|
|
3858
|
+
}
|
|
3859
|
+
|
|
3838
3860
|
.s-to-blue-500 {
|
|
3839
3861
|
--tw-gradient-to: #1C91FF var(--tw-gradient-to-position);
|
|
3840
3862
|
}
|
|
@@ -4899,6 +4921,12 @@ select {
|
|
|
4899
4921
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
|
4900
4922
|
}
|
|
4901
4923
|
|
|
4924
|
+
.s-shadow-none {
|
|
4925
|
+
--tw-shadow: 0 0 #0000;
|
|
4926
|
+
--tw-shadow-colored: 0 0 #0000;
|
|
4927
|
+
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
|
4928
|
+
}
|
|
4929
|
+
|
|
4902
4930
|
.s-shadow-sm {
|
|
4903
4931
|
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
4904
4932
|
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
|
@@ -5811,10 +5839,6 @@ select {
|
|
|
5811
5839
|
opacity: 1;
|
|
5812
5840
|
}
|
|
5813
5841
|
|
|
5814
|
-
.s-group\/preview:hover .group-hover\/preview\:s-opacity-40 {
|
|
5815
|
-
opacity: 0.4;
|
|
5816
|
-
}
|
|
5817
|
-
|
|
5818
5842
|
.s-group\/tree:hover .group-hover\/tree\:s-opacity-100 {
|
|
5819
5843
|
opacity: 1;
|
|
5820
5844
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dust-tt/sparkle",
|
|
3
|
-
"version": "0.2.481-
|
|
3
|
+
"version": "0.2.481-rc4",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"build": "rm -rf dist && npm run tailwind && npm run build:esm && npm run build:cjs",
|
|
6
6
|
"tailwind": "tailwindcss -i ./src/styles/tailwind.css -o dist/sparkle.css",
|
|
@@ -10,6 +10,47 @@ import {
|
|
|
10
10
|
import { ArrowDownOnSquareIcon } from "@sparkle/icons/app";
|
|
11
11
|
import { cn } from "@sparkle/lib/utils";
|
|
12
12
|
|
|
13
|
+
interface DownloadButtonProps {
|
|
14
|
+
className?: string;
|
|
15
|
+
size?: "xs" | "sm";
|
|
16
|
+
src?: string;
|
|
17
|
+
title: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function DownloadButton({
|
|
21
|
+
className,
|
|
22
|
+
size = "xs",
|
|
23
|
+
src,
|
|
24
|
+
title,
|
|
25
|
+
}: DownloadButtonProps) {
|
|
26
|
+
const handleDownload = React.useCallback(async () => {
|
|
27
|
+
if (!src) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Create a hidden link and click it.
|
|
32
|
+
const link = document.createElement("a");
|
|
33
|
+
link.href = src;
|
|
34
|
+
link.download = title;
|
|
35
|
+
document.body.appendChild(link);
|
|
36
|
+
link.click();
|
|
37
|
+
document.body.removeChild(link);
|
|
38
|
+
}, [src, title]);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<IconButton
|
|
42
|
+
icon={ArrowDownOnSquareIcon}
|
|
43
|
+
className={cn("s-text-white", className)}
|
|
44
|
+
tooltip="Download"
|
|
45
|
+
size={size}
|
|
46
|
+
onClick={async (e) => {
|
|
47
|
+
e.stopPropagation(); // Prevent image zoom.
|
|
48
|
+
await handleDownload();
|
|
49
|
+
}}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
13
54
|
interface InteractiveImageProps {
|
|
14
55
|
alt: string;
|
|
15
56
|
isLoading?: boolean;
|
|
@@ -24,6 +65,7 @@ export function InteractiveImage({
|
|
|
24
65
|
...props
|
|
25
66
|
}: InteractiveImageProps) {
|
|
26
67
|
const [isZoomed, setIsZoomed] = React.useState(false);
|
|
68
|
+
const [imageLoaded, setImageLoaded] = React.useState(false);
|
|
27
69
|
|
|
28
70
|
const handleZoomToggle = React.useCallback(() => {
|
|
29
71
|
setIsZoomed(!isZoomed);
|
|
@@ -52,11 +94,26 @@ export function InteractiveImage({
|
|
|
52
94
|
<DialogContent
|
|
53
95
|
className={cn(
|
|
54
96
|
"s-w-auto s-max-w-none s-border-0 s-outline-none s-ring-0",
|
|
55
|
-
"focus:s-outline-none focus:s-ring-0"
|
|
97
|
+
"focus:s-outline-none focus:s-ring-0",
|
|
98
|
+
"s-rounded-none s-bg-transparent s-shadow-none"
|
|
56
99
|
)}
|
|
57
100
|
size="xl"
|
|
58
101
|
>
|
|
59
|
-
<
|
|
102
|
+
<div className="s-flex s-flex-col">
|
|
103
|
+
<div className="s-flex s-justify-end">
|
|
104
|
+
{imageLoaded && (
|
|
105
|
+
<DownloadButton src={src} title={props.title} size="sm" />
|
|
106
|
+
)}
|
|
107
|
+
</div>
|
|
108
|
+
<div className="s-relative s-w-full">
|
|
109
|
+
<img
|
|
110
|
+
src={src}
|
|
111
|
+
alt={alt}
|
|
112
|
+
className="s-w-full s-object-contain"
|
|
113
|
+
onLoad={() => setImageLoaded(true)}
|
|
114
|
+
/>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
60
117
|
</DialogContent>
|
|
61
118
|
</Dialog>
|
|
62
119
|
);
|
|
@@ -65,7 +122,7 @@ export function InteractiveImage({
|
|
|
65
122
|
function LoadingImage() {
|
|
66
123
|
return (
|
|
67
124
|
<div className="s-flex s-h-full s-w-full s-items-center s-justify-center">
|
|
68
|
-
<Spinner variant="dark" size="
|
|
125
|
+
<Spinner variant="dark" size="md" />
|
|
69
126
|
</div>
|
|
70
127
|
);
|
|
71
128
|
}
|
|
@@ -81,25 +138,12 @@ function ImagePreview({
|
|
|
81
138
|
src,
|
|
82
139
|
title,
|
|
83
140
|
}: ImagePreviewProps) {
|
|
84
|
-
const handleDownload = React.useCallback(async () => {
|
|
85
|
-
if (!src) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Create a hidden link and click it.
|
|
90
|
-
const link = document.createElement("a");
|
|
91
|
-
link.href = src;
|
|
92
|
-
link.download = title;
|
|
93
|
-
document.body.appendChild(link);
|
|
94
|
-
link.click();
|
|
95
|
-
document.body.removeChild(link);
|
|
96
|
-
}, [src, title]);
|
|
97
|
-
|
|
98
141
|
return (
|
|
99
142
|
<div
|
|
100
143
|
onClick={onClick}
|
|
101
144
|
className={cn(
|
|
102
|
-
"s-group/preview s-relative s-h-full s-w-full s-overflow-hidden s-rounded-2xl
|
|
145
|
+
"s-group/preview s-relative s-h-full s-w-full s-overflow-hidden s-rounded-2xl",
|
|
146
|
+
"s-bg-muted-background dark:s-bg-muted-background-night",
|
|
103
147
|
!isLoading && "s-cursor-pointer"
|
|
104
148
|
)}
|
|
105
149
|
>
|
|
@@ -113,19 +157,23 @@ function ImagePreview({
|
|
|
113
157
|
className="s-h-full s-w-full s-rounded-2xl s-object-cover"
|
|
114
158
|
/>
|
|
115
159
|
{/* Dark overlay on hover */}
|
|
116
|
-
<div
|
|
160
|
+
<div
|
|
161
|
+
className={cn(
|
|
162
|
+
"s-absolute s-inset-0 s-bg-gradient-to-b",
|
|
163
|
+
"s-from-black/40 s-via-transparent s-to-black/40",
|
|
164
|
+
"s-opacity-0 s-transition-opacity s-duration-200",
|
|
165
|
+
"group-hover/preview:s-opacity-100"
|
|
166
|
+
)}
|
|
167
|
+
/>
|
|
117
168
|
{/* Icon container - only visible on hover */}
|
|
118
|
-
<div
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
await handleDownload();
|
|
127
|
-
}}
|
|
128
|
-
/>
|
|
169
|
+
<div
|
|
170
|
+
className={cn(
|
|
171
|
+
"s-absolute s-right-3 s-top-3 s-z-10 s-flex",
|
|
172
|
+
"s-opacity-0 s-transition-opacity s-duration-200",
|
|
173
|
+
"group-hover/preview:s-opacity-100"
|
|
174
|
+
)}
|
|
175
|
+
>
|
|
176
|
+
<DownloadButton src={src} title={title} size="xs" />
|
|
129
177
|
</div>
|
|
130
178
|
</>
|
|
131
179
|
)}
|