@medialane/ui 0.1.5 → 0.2.0
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/brand-icon.cjs +0 -9
- package/dist/components/brand-icon.cjs.map +1 -1
- package/dist/components/brand-icon.js +0 -9
- package/dist/components/brand-icon.js.map +1 -1
- package/dist/components/collection-card.cjs +124 -0
- package/dist/components/collection-card.cjs.map +1 -0
- package/dist/components/collection-card.d.cts +13 -0
- package/dist/components/collection-card.d.ts +13 -0
- package/dist/components/collection-card.js +89 -0
- package/dist/components/collection-card.js.map +1 -0
- package/dist/components/motion-primitives.cjs +126 -0
- package/dist/components/motion-primitives.cjs.map +1 -0
- package/dist/components/motion-primitives.d.cts +36 -0
- package/dist/components/motion-primitives.d.ts +36 -0
- package/dist/components/motion-primitives.js +96 -0
- package/dist/components/motion-primitives.js.map +1 -0
- package/dist/components/scroll-section.cjs +72 -0
- package/dist/components/scroll-section.cjs.map +1 -0
- package/dist/components/scroll-section.d.cts +18 -0
- package/dist/components/scroll-section.d.ts +18 -0
- package/dist/components/scroll-section.js +38 -0
- package/dist/components/scroll-section.js.map +1 -0
- package/dist/components/share-button.cjs +86 -0
- package/dist/components/share-button.cjs.map +1 -0
- package/dist/components/share-button.d.cts +12 -0
- package/dist/components/share-button.d.ts +12 -0
- package/dist/components/share-button.js +62 -0
- package/dist/components/share-button.js.map +1 -0
- package/dist/components/token-card.cjs +281 -0
- package/dist/components/token-card.cjs.map +1 -0
- package/dist/components/token-card.d.cts +31 -0
- package/dist/components/token-card.d.ts +31 -0
- package/dist/components/token-card.js +256 -0
- package/dist/components/token-card.js.map +1 -0
- package/dist/index.cjs +31 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/package.json +15 -9
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
"use client";
|
|
3
2
|
var __create = Object.create;
|
|
4
3
|
var __defProp = Object.defineProperty;
|
|
5
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -35,15 +34,7 @@ module.exports = __toCommonJS(brand_icon_exports);
|
|
|
35
34
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
36
35
|
var import_image = __toESM(require("next/image"), 1);
|
|
37
36
|
var import_link = __toESM(require("next/link"), 1);
|
|
38
|
-
var import_react = require("react");
|
|
39
37
|
function MedialaneIcon({ size = 256, href = "/", className }) {
|
|
40
|
-
const [mounted, setMounted] = (0, import_react.useState)(false);
|
|
41
|
-
(0, import_react.useEffect)(() => {
|
|
42
|
-
setMounted(true);
|
|
43
|
-
}, []);
|
|
44
|
-
if (!mounted) {
|
|
45
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href, className, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { width: size, height: size } }) });
|
|
46
|
-
}
|
|
47
38
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
48
39
|
import_link.default,
|
|
49
40
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/brand-icon.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../src/components/brand-icon.tsx"],"sourcesContent":["import Image from \"next/image\";\nimport Link from \"next/link\";\n\nexport interface MedialaneIconProps {\n size?: number;\n href?: string;\n className?: string;\n}\n\nexport function MedialaneIcon({ size = 256, href = \"/\", className }: MedialaneIconProps) {\n return (\n <Link\n href={href}\n className={`transition-opacity hover:opacity-80 drop-shadow-md ${className ?? \"\"}`}\n >\n <Image\n src=\"/icon.png\"\n alt=\"Medialane\"\n width={size}\n height={size}\n priority\n />\n </Link>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAeM;AAfN,mBAAkB;AAClB,kBAAiB;AAQV,SAAS,cAAc,EAAE,OAAO,KAAK,OAAO,KAAK,UAAU,GAAuB;AACvF,SACE;AAAA,IAAC,YAAAA;AAAA,IAAA;AAAA,MACC;AAAA,MACA,WAAW,sDAAsD,aAAa,EAAE;AAAA,MAEhF;AAAA,QAAC,aAAAC;AAAA,QAAA;AAAA,UACC,KAAI;AAAA,UACJ,KAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,UAAQ;AAAA;AAAA,MACV;AAAA;AAAA,EACF;AAEJ;","names":["Link","Image"]}
|
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
"use client";
|
|
2
1
|
import { jsx } from "react/jsx-runtime";
|
|
3
2
|
import Image from "next/image";
|
|
4
3
|
import Link from "next/link";
|
|
5
|
-
import { useEffect, useState } from "react";
|
|
6
4
|
function MedialaneIcon({ size = 256, href = "/", className }) {
|
|
7
|
-
const [mounted, setMounted] = useState(false);
|
|
8
|
-
useEffect(() => {
|
|
9
|
-
setMounted(true);
|
|
10
|
-
}, []);
|
|
11
|
-
if (!mounted) {
|
|
12
|
-
return /* @__PURE__ */ jsx(Link, { href, className, children: /* @__PURE__ */ jsx("div", { style: { width: size, height: size } }) });
|
|
13
|
-
}
|
|
14
5
|
return /* @__PURE__ */ jsx(
|
|
15
6
|
Link,
|
|
16
7
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/brand-icon.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../src/components/brand-icon.tsx"],"sourcesContent":["import Image from \"next/image\";\nimport Link from \"next/link\";\n\nexport interface MedialaneIconProps {\n size?: number;\n href?: string;\n className?: string;\n}\n\nexport function MedialaneIcon({ size = 256, href = \"/\", className }: MedialaneIconProps) {\n return (\n <Link\n href={href}\n className={`transition-opacity hover:opacity-80 drop-shadow-md ${className ?? \"\"}`}\n >\n <Image\n src=\"/icon.png\"\n alt=\"Medialane\"\n width={size}\n height={size}\n priority\n />\n </Link>\n );\n}\n"],"mappings":"AAeM;AAfN,OAAO,WAAW;AAClB,OAAO,UAAU;AAQV,SAAS,cAAc,EAAE,OAAO,KAAK,OAAO,KAAK,UAAU,GAAuB;AACvF,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,sDAAsD,aAAa,EAAE;AAAA,MAEhF;AAAA,QAAC;AAAA;AAAA,UACC,KAAI;AAAA,UACJ,KAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,UAAQ;AAAA;AAAA,MACV;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var collection_card_exports = {};
|
|
31
|
+
__export(collection_card_exports, {
|
|
32
|
+
CollectionCard: () => CollectionCard,
|
|
33
|
+
CollectionCardSkeleton: () => CollectionCardSkeleton
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(collection_card_exports);
|
|
36
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
37
|
+
var import_react = require("react");
|
|
38
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
39
|
+
var import_image = __toESM(require("next/image"), 1);
|
|
40
|
+
var import_lucide_react = require("lucide-react");
|
|
41
|
+
var import_cn = require("../utils/cn.js");
|
|
42
|
+
var import_ipfs = require("../utils/ipfs.js");
|
|
43
|
+
var import_format = require("../utils/format.js");
|
|
44
|
+
var import_motion_primitives = require("./motion-primitives.js");
|
|
45
|
+
function FloorTooltip({ children, label }) {
|
|
46
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "relative inline-flex items-center gap-0.5 group/tip cursor-default", children: [
|
|
47
|
+
children,
|
|
48
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.HelpCircle, { className: "h-2.5 w-2.5 text-white/50 group-hover/tip:text-white/80 transition-colors shrink-0" }),
|
|
49
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "pointer-events-none absolute bottom-full left-1/2 -translate-x-1/2 mb-1.5 px-2 py-1 text-[10px] font-normal bg-popover text-popover-foreground border border-border rounded-md shadow-md whitespace-nowrap opacity-0 group-hover/tip:opacity-100 transition-opacity z-50", children: label })
|
|
50
|
+
] });
|
|
51
|
+
}
|
|
52
|
+
function CollectionCard({ collection, settingsHref, className }) {
|
|
53
|
+
const [imgError, setImgError] = (0, import_react.useState)(false);
|
|
54
|
+
const imageUrl = collection.image ? (0, import_ipfs.ipfsToHttp)(collection.image) : null;
|
|
55
|
+
const showImage = imageUrl && !imgError;
|
|
56
|
+
const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();
|
|
57
|
+
const hasFloor = !!collection.floorPrice;
|
|
58
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_motion_primitives.MotionCard, { className: (0, import_cn.cn)("card-base group relative", className), children: [
|
|
59
|
+
settingsHref && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
60
|
+
import_link.default,
|
|
61
|
+
{
|
|
62
|
+
href: settingsHref,
|
|
63
|
+
onClick: (e) => e.stopPropagation(),
|
|
64
|
+
className: "absolute top-2 right-2 z-10 h-7 w-7 rounded-full bg-black/40 backdrop-blur-sm flex items-center justify-center text-white/70 hover:text-white hover:bg-black/60 transition-colors",
|
|
65
|
+
"aria-label": "Collection settings",
|
|
66
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Settings2, { className: "h-3.5 w-3.5" })
|
|
67
|
+
}
|
|
68
|
+
),
|
|
69
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: `/collections/${collection.contractAddress}`, className: "block relative h-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative aspect-[3/4] w-full overflow-hidden bg-muted", children: [
|
|
70
|
+
showImage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
71
|
+
import_image.default,
|
|
72
|
+
{
|
|
73
|
+
src: imageUrl,
|
|
74
|
+
alt: collection.name ?? "Collection",
|
|
75
|
+
fill: true,
|
|
76
|
+
className: "object-cover transition-transform duration-500 group-hover:scale-105",
|
|
77
|
+
onError: () => setImgError(true),
|
|
78
|
+
unoptimized: true
|
|
79
|
+
}
|
|
80
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/40 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-8xl font-black text-white/10 select-none tracking-tighter", children: initial }) }),
|
|
81
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "absolute bottom-0 left-0 right-0 px-2.5 pb-2.5 flex flex-col gap-1.5 items-start", children: [
|
|
82
|
+
!collection.name && collection.metadataStatus === "PENDING" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1 text-[10px] text-white/60 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5", children: [
|
|
83
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Loader2, { className: "h-2.5 w-2.5 animate-spin" }),
|
|
84
|
+
"Indexing\u2026"
|
|
85
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
86
|
+
"p",
|
|
87
|
+
{
|
|
88
|
+
className: "font-bold text-sm text-white leading-tight backdrop-blur-md bg-black/30 rounded-lg px-2.5 py-1 max-w-full truncate",
|
|
89
|
+
style: { textShadow: "0 1px 6px rgba(0,0,0,0.5)" },
|
|
90
|
+
children: [
|
|
91
|
+
collection.name ?? "Unnamed Collection",
|
|
92
|
+
collection.isKnown && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.CheckCircle2, { className: "inline-block h-3 w-3 text-blue-400 ml-1.5 shrink-0 align-middle" })
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
),
|
|
96
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-1.5 flex-wrap", children: [
|
|
97
|
+
collection.totalSupply != null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "text-[10px] font-medium text-white/80 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5", children: [
|
|
98
|
+
collection.totalSupply.toLocaleString(),
|
|
99
|
+
" items"
|
|
100
|
+
] }),
|
|
101
|
+
hasFloor && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[10px] font-bold text-white/90 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FloorTooltip, { label: "Lowest active listing price in this collection", children: [
|
|
102
|
+
"Floor ",
|
|
103
|
+
(0, import_format.formatDisplayPrice)(collection.floorPrice)
|
|
104
|
+
] }) })
|
|
105
|
+
] })
|
|
106
|
+
] })
|
|
107
|
+
] }) })
|
|
108
|
+
] });
|
|
109
|
+
}
|
|
110
|
+
function CollectionCardSkeleton() {
|
|
111
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "card-base overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative aspect-[3/4] w-full overflow-hidden bg-muted", children: [
|
|
112
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-0 animate-pulse bg-muted" }),
|
|
113
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "absolute bottom-3 left-3 right-3 space-y-1.5", children: [
|
|
114
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-4 w-2/3 rounded-md bg-muted-foreground/20 animate-pulse" }),
|
|
115
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-3 w-1/3 rounded-md bg-muted-foreground/20 animate-pulse" })
|
|
116
|
+
] })
|
|
117
|
+
] }) });
|
|
118
|
+
}
|
|
119
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
120
|
+
0 && (module.exports = {
|
|
121
|
+
CollectionCard,
|
|
122
|
+
CollectionCardSkeleton
|
|
123
|
+
});
|
|
124
|
+
//# sourceMappingURL=collection-card.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { Loader2, Settings2, CheckCircle2, HelpCircle } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { MotionCard } from \"./motion-primitives.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\n// Pure CSS tooltip — no Radix/shadcn dependency\nfunction FloorTooltip({ children, label }: { children: React.ReactNode; label: string }) {\n return (\n <span className=\"relative inline-flex items-center gap-0.5 group/tip cursor-default\">\n {children}\n <HelpCircle className=\"h-2.5 w-2.5 text-white/50 group-hover/tip:text-white/80 transition-colors shrink-0\" />\n <span className=\"pointer-events-none absolute bottom-full left-1/2 -translate-x-1/2 mb-1.5 px-2 py-1 text-[10px] font-normal bg-popover text-popover-foreground border border-border rounded-md shadow-md whitespace-nowrap opacity-0 group-hover/tip:opacity-100 transition-opacity z-50\">\n {label}\n </span>\n </span>\n );\n}\n\nexport interface CollectionCardProps {\n collection: ApiCollection;\n /** Shows settings gear icon linking to this path — used in portfolio pages */\n settingsHref?: string;\n className?: string;\n}\n\nexport function CollectionCard({ collection, settingsHref, className }: CollectionCardProps) {\n const [imgError, setImgError] = useState(false);\n const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;\n const showImage = imageUrl && !imgError;\n const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();\n const hasFloor = !!collection.floorPrice;\n\n return (\n <MotionCard className={cn(\"card-base group relative\", className)}>\n {settingsHref && (\n <Link\n href={settingsHref}\n onClick={(e) => e.stopPropagation()}\n className=\"absolute top-2 right-2 z-10 h-7 w-7 rounded-full bg-black/40 backdrop-blur-sm flex items-center justify-center text-white/70 hover:text-white hover:bg-black/60 transition-colors\"\n aria-label=\"Collection settings\"\n >\n <Settings2 className=\"h-3.5 w-3.5\" />\n </Link>\n )}\n\n <Link href={`/collections/${collection.contractAddress}`} className=\"block relative h-full\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n {showImage ? (\n <Image\n src={imageUrl}\n alt={collection.name ?? \"Collection\"}\n fill\n className=\"object-cover transition-transform duration-500 group-hover:scale-105\"\n onError={() => setImgError(true)}\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/40 flex items-center justify-center\">\n <span className=\"text-8xl font-black text-white/10 select-none tracking-tighter\">\n {initial}\n </span>\n </div>\n )}\n\n <div className=\"absolute bottom-0 left-0 right-0 px-2.5 pb-2.5 flex flex-col gap-1.5 items-start\">\n {!collection.name && collection.metadataStatus === \"PENDING\" ? (\n <span className=\"flex items-center gap-1 text-[10px] text-white/60 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n <Loader2 className=\"h-2.5 w-2.5 animate-spin\" />\n Indexing…\n </span>\n ) : (\n <p\n className=\"font-bold text-sm text-white leading-tight backdrop-blur-md bg-black/30 rounded-lg px-2.5 py-1 max-w-full truncate\"\n style={{ textShadow: \"0 1px 6px rgba(0,0,0,0.5)\" }}\n >\n {collection.name ?? \"Unnamed Collection\"}\n {collection.isKnown && (\n <CheckCircle2 className=\"inline-block h-3 w-3 text-blue-400 ml-1.5 shrink-0 align-middle\" />\n )}\n </p>\n )}\n\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n {collection.totalSupply != null && (\n <span className=\"text-[10px] font-medium text-white/80 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n {collection.totalSupply.toLocaleString()} items\n </span>\n )}\n {hasFloor && (\n <span className=\"text-[10px] font-bold text-white/90 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n <FloorTooltip label=\"Lowest active listing price in this collection\">\n Floor {formatDisplayPrice(collection.floorPrice)}\n </FloorTooltip>\n </span>\n )}\n </div>\n </div>\n </div>\n </Link>\n </MotionCard>\n );\n}\n\nexport function CollectionCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n <div className=\"absolute inset-0 animate-pulse bg-muted\" />\n <div className=\"absolute bottom-3 left-3 right-3 space-y-1.5\">\n <div className=\"h-4 w-2/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n <div className=\"h-3 w-1/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeI;AAbJ,mBAAyB;AACzB,kBAAiB;AACjB,mBAAkB;AAClB,0BAA6D;AAC7D,gBAAmB;AACnB,kBAA2B;AAC3B,oBAAmC;AACnC,+BAA2B;AAI3B,SAAS,aAAa,EAAE,UAAU,MAAM,GAAiD;AACvF,SACE,6CAAC,UAAK,WAAU,sEACb;AAAA;AAAA,IACD,4CAAC,kCAAW,WAAU,sFAAqF;AAAA,IAC3G,4CAAC,UAAK,WAAU,4QACb,iBACH;AAAA,KACF;AAEJ;AASO,SAAS,eAAe,EAAE,YAAY,cAAc,UAAU,GAAwB;AAC3F,QAAM,CAAC,UAAU,WAAW,QAAI,uBAAS,KAAK;AAC9C,QAAM,WAAW,WAAW,YAAQ,wBAAW,WAAW,KAAK,IAAI;AACnE,QAAM,YAAY,YAAY,CAAC;AAC/B,QAAM,WAAW,WAAW,QAAQ,WAAW,iBAAiB,OAAO,CAAC,EAAE,YAAY;AACtF,QAAM,WAAW,CAAC,CAAC,WAAW;AAE9B,SACE,6CAAC,uCAAW,eAAW,cAAG,4BAA4B,SAAS,GAC5D;AAAA,oBACC;AAAA,MAAC,YAAAA;AAAA,MAAA;AAAA,QACC,MAAM;AAAA,QACN,SAAS,CAAC,MAAM,EAAE,gBAAgB;AAAA,QAClC,WAAU;AAAA,QACV,cAAW;AAAA,QAEX,sDAAC,iCAAU,WAAU,eAAc;AAAA;AAAA,IACrC;AAAA,IAGF,4CAAC,YAAAA,SAAA,EAAK,MAAM,gBAAgB,WAAW,eAAe,IAAI,WAAU,yBAClE,uDAAC,SAAI,WAAU,yDACZ;AAAA,kBACC;AAAA,QAAC,aAAAC;AAAA,QAAA;AAAA,UACC,KAAK;AAAA,UACL,KAAK,WAAW,QAAQ;AAAA,UACxB,MAAI;AAAA,UACJ,WAAU;AAAA,UACV,SAAS,MAAM,YAAY,IAAI;AAAA,UAC/B,aAAW;AAAA;AAAA,MACb,IAEA,4CAAC,SAAI,WAAU,+HACb,sDAAC,UAAK,WAAU,kEACb,mBACH,GACF;AAAA,MAGF,6CAAC,SAAI,WAAU,oFACZ;AAAA,SAAC,WAAW,QAAQ,WAAW,mBAAmB,YACjD,6CAAC,UAAK,WAAU,2GACd;AAAA,sDAAC,+BAAQ,WAAU,4BAA2B;AAAA,UAAE;AAAA,WAElD,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,YAAY,4BAA4B;AAAA,YAEhD;AAAA,yBAAW,QAAQ;AAAA,cACnB,WAAW,WACV,4CAAC,oCAAa,WAAU,mEAAkE;AAAA;AAAA;AAAA,QAE9F;AAAA,QAGF,6CAAC,SAAI,WAAU,uCACZ;AAAA,qBAAW,eAAe,QACzB,6CAAC,UAAK,WAAU,+FACb;AAAA,uBAAW,YAAY,eAAe;AAAA,YAAE;AAAA,aAC3C;AAAA,UAED,YACC,4CAAC,UAAK,WAAU,6FACd,uDAAC,gBAAa,OAAM,kDAAiD;AAAA;AAAA,gBAC5D,kCAAmB,WAAW,UAAU;AAAA,aACjD,GACF;AAAA,WAEJ;AAAA,SACF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;AAEO,SAAS,yBAAyB;AACvC,SACE,4CAAC,SAAI,WAAU,6BACb,uDAAC,SAAI,WAAU,yDACb;AAAA,gDAAC,SAAI,WAAU,2CAA0C;AAAA,IACzD,6CAAC,SAAI,WAAU,gDACb;AAAA,kDAAC,SAAI,WAAU,6DAA4D;AAAA,MAC3E,4CAAC,SAAI,WAAU,6DAA4D;AAAA,OAC7E;AAAA,KACF,GACF;AAEJ;","names":["Link","Image"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ApiCollection } from '@medialane/sdk';
|
|
3
|
+
|
|
4
|
+
interface CollectionCardProps {
|
|
5
|
+
collection: ApiCollection;
|
|
6
|
+
/** Shows settings gear icon linking to this path — used in portfolio pages */
|
|
7
|
+
settingsHref?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
declare function CollectionCard({ collection, settingsHref, className }: CollectionCardProps): react_jsx_runtime.JSX.Element;
|
|
11
|
+
declare function CollectionCardSkeleton(): react_jsx_runtime.JSX.Element;
|
|
12
|
+
|
|
13
|
+
export { CollectionCard, type CollectionCardProps, CollectionCardSkeleton };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ApiCollection } from '@medialane/sdk';
|
|
3
|
+
|
|
4
|
+
interface CollectionCardProps {
|
|
5
|
+
collection: ApiCollection;
|
|
6
|
+
/** Shows settings gear icon linking to this path — used in portfolio pages */
|
|
7
|
+
settingsHref?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
declare function CollectionCard({ collection, settingsHref, className }: CollectionCardProps): react_jsx_runtime.JSX.Element;
|
|
11
|
+
declare function CollectionCardSkeleton(): react_jsx_runtime.JSX.Element;
|
|
12
|
+
|
|
13
|
+
export { CollectionCard, type CollectionCardProps, CollectionCardSkeleton };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import Link from "next/link";
|
|
5
|
+
import Image from "next/image";
|
|
6
|
+
import { Loader2, Settings2, CheckCircle2, HelpCircle } from "lucide-react";
|
|
7
|
+
import { cn } from "../utils/cn.js";
|
|
8
|
+
import { ipfsToHttp } from "../utils/ipfs.js";
|
|
9
|
+
import { formatDisplayPrice } from "../utils/format.js";
|
|
10
|
+
import { MotionCard } from "./motion-primitives.js";
|
|
11
|
+
function FloorTooltip({ children, label }) {
|
|
12
|
+
return /* @__PURE__ */ jsxs("span", { className: "relative inline-flex items-center gap-0.5 group/tip cursor-default", children: [
|
|
13
|
+
children,
|
|
14
|
+
/* @__PURE__ */ jsx(HelpCircle, { className: "h-2.5 w-2.5 text-white/50 group-hover/tip:text-white/80 transition-colors shrink-0" }),
|
|
15
|
+
/* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute bottom-full left-1/2 -translate-x-1/2 mb-1.5 px-2 py-1 text-[10px] font-normal bg-popover text-popover-foreground border border-border rounded-md shadow-md whitespace-nowrap opacity-0 group-hover/tip:opacity-100 transition-opacity z-50", children: label })
|
|
16
|
+
] });
|
|
17
|
+
}
|
|
18
|
+
function CollectionCard({ collection, settingsHref, className }) {
|
|
19
|
+
const [imgError, setImgError] = useState(false);
|
|
20
|
+
const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;
|
|
21
|
+
const showImage = imageUrl && !imgError;
|
|
22
|
+
const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();
|
|
23
|
+
const hasFloor = !!collection.floorPrice;
|
|
24
|
+
return /* @__PURE__ */ jsxs(MotionCard, { className: cn("card-base group relative", className), children: [
|
|
25
|
+
settingsHref && /* @__PURE__ */ jsx(
|
|
26
|
+
Link,
|
|
27
|
+
{
|
|
28
|
+
href: settingsHref,
|
|
29
|
+
onClick: (e) => e.stopPropagation(),
|
|
30
|
+
className: "absolute top-2 right-2 z-10 h-7 w-7 rounded-full bg-black/40 backdrop-blur-sm flex items-center justify-center text-white/70 hover:text-white hover:bg-black/60 transition-colors",
|
|
31
|
+
"aria-label": "Collection settings",
|
|
32
|
+
children: /* @__PURE__ */ jsx(Settings2, { className: "h-3.5 w-3.5" })
|
|
33
|
+
}
|
|
34
|
+
),
|
|
35
|
+
/* @__PURE__ */ jsx(Link, { href: `/collections/${collection.contractAddress}`, className: "block relative h-full", children: /* @__PURE__ */ jsxs("div", { className: "relative aspect-[3/4] w-full overflow-hidden bg-muted", children: [
|
|
36
|
+
showImage ? /* @__PURE__ */ jsx(
|
|
37
|
+
Image,
|
|
38
|
+
{
|
|
39
|
+
src: imageUrl,
|
|
40
|
+
alt: collection.name ?? "Collection",
|
|
41
|
+
fill: true,
|
|
42
|
+
className: "object-cover transition-transform duration-500 group-hover:scale-105",
|
|
43
|
+
onError: () => setImgError(true),
|
|
44
|
+
unoptimized: true
|
|
45
|
+
}
|
|
46
|
+
) : /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/40 flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "text-8xl font-black text-white/10 select-none tracking-tighter", children: initial }) }),
|
|
47
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute bottom-0 left-0 right-0 px-2.5 pb-2.5 flex flex-col gap-1.5 items-start", children: [
|
|
48
|
+
!collection.name && collection.metadataStatus === "PENDING" ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-[10px] text-white/60 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5", children: [
|
|
49
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-2.5 w-2.5 animate-spin" }),
|
|
50
|
+
"Indexing\u2026"
|
|
51
|
+
] }) : /* @__PURE__ */ jsxs(
|
|
52
|
+
"p",
|
|
53
|
+
{
|
|
54
|
+
className: "font-bold text-sm text-white leading-tight backdrop-blur-md bg-black/30 rounded-lg px-2.5 py-1 max-w-full truncate",
|
|
55
|
+
style: { textShadow: "0 1px 6px rgba(0,0,0,0.5)" },
|
|
56
|
+
children: [
|
|
57
|
+
collection.name ?? "Unnamed Collection",
|
|
58
|
+
collection.isKnown && /* @__PURE__ */ jsx(CheckCircle2, { className: "inline-block h-3 w-3 text-blue-400 ml-1.5 shrink-0 align-middle" })
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
),
|
|
62
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 flex-wrap", children: [
|
|
63
|
+
collection.totalSupply != null && /* @__PURE__ */ jsxs("span", { className: "text-[10px] font-medium text-white/80 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5", children: [
|
|
64
|
+
collection.totalSupply.toLocaleString(),
|
|
65
|
+
" items"
|
|
66
|
+
] }),
|
|
67
|
+
hasFloor && /* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold text-white/90 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5", children: /* @__PURE__ */ jsxs(FloorTooltip, { label: "Lowest active listing price in this collection", children: [
|
|
68
|
+
"Floor ",
|
|
69
|
+
formatDisplayPrice(collection.floorPrice)
|
|
70
|
+
] }) })
|
|
71
|
+
] })
|
|
72
|
+
] })
|
|
73
|
+
] }) })
|
|
74
|
+
] });
|
|
75
|
+
}
|
|
76
|
+
function CollectionCardSkeleton() {
|
|
77
|
+
return /* @__PURE__ */ jsx("div", { className: "card-base overflow-hidden", children: /* @__PURE__ */ jsxs("div", { className: "relative aspect-[3/4] w-full overflow-hidden bg-muted", children: [
|
|
78
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 animate-pulse bg-muted" }),
|
|
79
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute bottom-3 left-3 right-3 space-y-1.5", children: [
|
|
80
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 w-2/3 rounded-md bg-muted-foreground/20 animate-pulse" }),
|
|
81
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-1/3 rounded-md bg-muted-foreground/20 animate-pulse" })
|
|
82
|
+
] })
|
|
83
|
+
] }) });
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
CollectionCard,
|
|
87
|
+
CollectionCardSkeleton
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=collection-card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { Loader2, Settings2, CheckCircle2, HelpCircle } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { MotionCard } from \"./motion-primitives.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\n// Pure CSS tooltip — no Radix/shadcn dependency\nfunction FloorTooltip({ children, label }: { children: React.ReactNode; label: string }) {\n return (\n <span className=\"relative inline-flex items-center gap-0.5 group/tip cursor-default\">\n {children}\n <HelpCircle className=\"h-2.5 w-2.5 text-white/50 group-hover/tip:text-white/80 transition-colors shrink-0\" />\n <span className=\"pointer-events-none absolute bottom-full left-1/2 -translate-x-1/2 mb-1.5 px-2 py-1 text-[10px] font-normal bg-popover text-popover-foreground border border-border rounded-md shadow-md whitespace-nowrap opacity-0 group-hover/tip:opacity-100 transition-opacity z-50\">\n {label}\n </span>\n </span>\n );\n}\n\nexport interface CollectionCardProps {\n collection: ApiCollection;\n /** Shows settings gear icon linking to this path — used in portfolio pages */\n settingsHref?: string;\n className?: string;\n}\n\nexport function CollectionCard({ collection, settingsHref, className }: CollectionCardProps) {\n const [imgError, setImgError] = useState(false);\n const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;\n const showImage = imageUrl && !imgError;\n const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();\n const hasFloor = !!collection.floorPrice;\n\n return (\n <MotionCard className={cn(\"card-base group relative\", className)}>\n {settingsHref && (\n <Link\n href={settingsHref}\n onClick={(e) => e.stopPropagation()}\n className=\"absolute top-2 right-2 z-10 h-7 w-7 rounded-full bg-black/40 backdrop-blur-sm flex items-center justify-center text-white/70 hover:text-white hover:bg-black/60 transition-colors\"\n aria-label=\"Collection settings\"\n >\n <Settings2 className=\"h-3.5 w-3.5\" />\n </Link>\n )}\n\n <Link href={`/collections/${collection.contractAddress}`} className=\"block relative h-full\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n {showImage ? (\n <Image\n src={imageUrl}\n alt={collection.name ?? \"Collection\"}\n fill\n className=\"object-cover transition-transform duration-500 group-hover:scale-105\"\n onError={() => setImgError(true)}\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/40 flex items-center justify-center\">\n <span className=\"text-8xl font-black text-white/10 select-none tracking-tighter\">\n {initial}\n </span>\n </div>\n )}\n\n <div className=\"absolute bottom-0 left-0 right-0 px-2.5 pb-2.5 flex flex-col gap-1.5 items-start\">\n {!collection.name && collection.metadataStatus === \"PENDING\" ? (\n <span className=\"flex items-center gap-1 text-[10px] text-white/60 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n <Loader2 className=\"h-2.5 w-2.5 animate-spin\" />\n Indexing…\n </span>\n ) : (\n <p\n className=\"font-bold text-sm text-white leading-tight backdrop-blur-md bg-black/30 rounded-lg px-2.5 py-1 max-w-full truncate\"\n style={{ textShadow: \"0 1px 6px rgba(0,0,0,0.5)\" }}\n >\n {collection.name ?? \"Unnamed Collection\"}\n {collection.isKnown && (\n <CheckCircle2 className=\"inline-block h-3 w-3 text-blue-400 ml-1.5 shrink-0 align-middle\" />\n )}\n </p>\n )}\n\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n {collection.totalSupply != null && (\n <span className=\"text-[10px] font-medium text-white/80 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n {collection.totalSupply.toLocaleString()} items\n </span>\n )}\n {hasFloor && (\n <span className=\"text-[10px] font-bold text-white/90 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n <FloorTooltip label=\"Lowest active listing price in this collection\">\n Floor {formatDisplayPrice(collection.floorPrice)}\n </FloorTooltip>\n </span>\n )}\n </div>\n </div>\n </div>\n </Link>\n </MotionCard>\n );\n}\n\nexport function CollectionCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n <div className=\"absolute inset-0 animate-pulse bg-muted\" />\n <div className=\"absolute bottom-3 left-3 right-3 space-y-1.5\">\n <div className=\"h-4 w-2/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n <div className=\"h-3 w-1/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";AAeI,SAEE,KAFF;AAbJ,SAAS,gBAAgB;AACzB,OAAO,UAAU;AACjB,OAAO,WAAW;AAClB,SAAS,SAAS,WAAW,cAAc,kBAAkB;AAC7D,SAAS,UAAU;AACnB,SAAS,kBAAkB;AAC3B,SAAS,0BAA0B;AACnC,SAAS,kBAAkB;AAI3B,SAAS,aAAa,EAAE,UAAU,MAAM,GAAiD;AACvF,SACE,qBAAC,UAAK,WAAU,sEACb;AAAA;AAAA,IACD,oBAAC,cAAW,WAAU,sFAAqF;AAAA,IAC3G,oBAAC,UAAK,WAAU,4QACb,iBACH;AAAA,KACF;AAEJ;AASO,SAAS,eAAe,EAAE,YAAY,cAAc,UAAU,GAAwB;AAC3F,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,WAAW,WAAW,QAAQ,WAAW,WAAW,KAAK,IAAI;AACnE,QAAM,YAAY,YAAY,CAAC;AAC/B,QAAM,WAAW,WAAW,QAAQ,WAAW,iBAAiB,OAAO,CAAC,EAAE,YAAY;AACtF,QAAM,WAAW,CAAC,CAAC,WAAW;AAE9B,SACE,qBAAC,cAAW,WAAW,GAAG,4BAA4B,SAAS,GAC5D;AAAA,oBACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,SAAS,CAAC,MAAM,EAAE,gBAAgB;AAAA,QAClC,WAAU;AAAA,QACV,cAAW;AAAA,QAEX,8BAAC,aAAU,WAAU,eAAc;AAAA;AAAA,IACrC;AAAA,IAGF,oBAAC,QAAK,MAAM,gBAAgB,WAAW,eAAe,IAAI,WAAU,yBAClE,+BAAC,SAAI,WAAU,yDACZ;AAAA,kBACC;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,KAAK,WAAW,QAAQ;AAAA,UACxB,MAAI;AAAA,UACJ,WAAU;AAAA,UACV,SAAS,MAAM,YAAY,IAAI;AAAA,UAC/B,aAAW;AAAA;AAAA,MACb,IAEA,oBAAC,SAAI,WAAU,+HACb,8BAAC,UAAK,WAAU,kEACb,mBACH,GACF;AAAA,MAGF,qBAAC,SAAI,WAAU,oFACZ;AAAA,SAAC,WAAW,QAAQ,WAAW,mBAAmB,YACjD,qBAAC,UAAK,WAAU,2GACd;AAAA,8BAAC,WAAQ,WAAU,4BAA2B;AAAA,UAAE;AAAA,WAElD,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,YAAY,4BAA4B;AAAA,YAEhD;AAAA,yBAAW,QAAQ;AAAA,cACnB,WAAW,WACV,oBAAC,gBAAa,WAAU,mEAAkE;AAAA;AAAA;AAAA,QAE9F;AAAA,QAGF,qBAAC,SAAI,WAAU,uCACZ;AAAA,qBAAW,eAAe,QACzB,qBAAC,UAAK,WAAU,+FACb;AAAA,uBAAW,YAAY,eAAe;AAAA,YAAE;AAAA,aAC3C;AAAA,UAED,YACC,oBAAC,UAAK,WAAU,6FACd,+BAAC,gBAAa,OAAM,kDAAiD;AAAA;AAAA,YAC5D,mBAAmB,WAAW,UAAU;AAAA,aACjD,GACF;AAAA,WAEJ;AAAA,SACF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;AAEO,SAAS,yBAAyB;AACvC,SACE,oBAAC,SAAI,WAAU,6BACb,+BAAC,SAAI,WAAU,yDACb;AAAA,wBAAC,SAAI,WAAU,2CAA0C;AAAA,IACzD,qBAAC,SAAI,WAAU,gDACb;AAAA,0BAAC,SAAI,WAAU,6DAA4D;AAAA,MAC3E,oBAAC,SAAI,WAAU,6DAA4D;AAAA,OAC7E;AAAA,KACF,GACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var motion_primitives_exports = {};
|
|
21
|
+
__export(motion_primitives_exports, {
|
|
22
|
+
EASE_OUT: () => EASE_OUT,
|
|
23
|
+
FadeIn: () => FadeIn,
|
|
24
|
+
KineticWords: () => KineticWords,
|
|
25
|
+
MotionCard: () => MotionCard,
|
|
26
|
+
SPRING: () => SPRING,
|
|
27
|
+
Stagger: () => Stagger,
|
|
28
|
+
StaggerItem: () => StaggerItem
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(motion_primitives_exports);
|
|
31
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
32
|
+
var import_framer_motion = require("framer-motion");
|
|
33
|
+
const SPRING = { type: "spring", stiffness: 400, damping: 28 };
|
|
34
|
+
const EASE_OUT = [0.25, 0.46, 0.45, 0.94];
|
|
35
|
+
function MotionCard({ children, className, ...props }) {
|
|
36
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
37
|
+
import_framer_motion.motion.div,
|
|
38
|
+
{
|
|
39
|
+
className,
|
|
40
|
+
whileTap: { scale: 0.96 },
|
|
41
|
+
transition: SPRING,
|
|
42
|
+
...props,
|
|
43
|
+
children
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
function FadeIn({ children, className, delay = 0, y = 20 }) {
|
|
48
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
49
|
+
import_framer_motion.motion.div,
|
|
50
|
+
{
|
|
51
|
+
className,
|
|
52
|
+
initial: { opacity: 0, y },
|
|
53
|
+
whileInView: { opacity: 1, y: 0 },
|
|
54
|
+
viewport: { once: true, margin: "-60px" },
|
|
55
|
+
transition: { duration: 0.5, delay, ease: EASE_OUT },
|
|
56
|
+
children
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
function Stagger({ children, className, staggerDelay = 0.07 }) {
|
|
61
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
62
|
+
import_framer_motion.motion.div,
|
|
63
|
+
{
|
|
64
|
+
className,
|
|
65
|
+
initial: "hidden",
|
|
66
|
+
whileInView: "show",
|
|
67
|
+
viewport: { once: true, margin: "-60px" },
|
|
68
|
+
variants: {
|
|
69
|
+
hidden: {},
|
|
70
|
+
show: { transition: { staggerChildren: staggerDelay } }
|
|
71
|
+
},
|
|
72
|
+
children
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
function StaggerItem({ children, className }) {
|
|
77
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
78
|
+
import_framer_motion.motion.div,
|
|
79
|
+
{
|
|
80
|
+
className,
|
|
81
|
+
variants: {
|
|
82
|
+
hidden: { opacity: 0, y: 20 },
|
|
83
|
+
show: { opacity: 1, y: 0, transition: { duration: 0.45, ease: EASE_OUT } }
|
|
84
|
+
},
|
|
85
|
+
children
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
function KineticWords({ text, className }) {
|
|
90
|
+
const words = text.split(" ");
|
|
91
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
92
|
+
import_framer_motion.motion.span,
|
|
93
|
+
{
|
|
94
|
+
className,
|
|
95
|
+
initial: "hidden",
|
|
96
|
+
animate: "show",
|
|
97
|
+
variants: {
|
|
98
|
+
hidden: {},
|
|
99
|
+
show: { transition: { staggerChildren: 0.08, delayChildren: 0.1 } }
|
|
100
|
+
},
|
|
101
|
+
children: words.map((word, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
102
|
+
import_framer_motion.motion.span,
|
|
103
|
+
{
|
|
104
|
+
className: "inline-block mr-[0.25em]",
|
|
105
|
+
variants: {
|
|
106
|
+
hidden: { opacity: 0, y: 24, rotateX: -20 },
|
|
107
|
+
show: { opacity: 1, y: 0, rotateX: 0, transition: { duration: 0.5, ease: EASE_OUT } }
|
|
108
|
+
},
|
|
109
|
+
children: word
|
|
110
|
+
},
|
|
111
|
+
i
|
|
112
|
+
))
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
117
|
+
0 && (module.exports = {
|
|
118
|
+
EASE_OUT,
|
|
119
|
+
FadeIn,
|
|
120
|
+
KineticWords,
|
|
121
|
+
MotionCard,
|
|
122
|
+
SPRING,
|
|
123
|
+
Stagger,
|
|
124
|
+
StaggerItem
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=motion-primitives.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/motion-primitives.tsx"],"sourcesContent":["\"use client\";\n\nimport { motion, type HTMLMotionProps } from \"framer-motion\";\n\nexport const SPRING = { type: \"spring\", stiffness: 400, damping: 28 } as const;\nexport const EASE_OUT = [0.25, 0.46, 0.45, 0.94] as const;\n\n// ─── Press-able card wrapper ──────────────────────────────────────────────────\n\ninterface MotionCardProps extends HTMLMotionProps<\"div\"> {\n children: React.ReactNode;\n}\n\nexport function MotionCard({ children, className, ...props }: MotionCardProps) {\n return (\n <motion.div\n className={className}\n whileTap={{ scale: 0.96 }}\n transition={SPRING}\n {...props}\n >\n {children}\n </motion.div>\n );\n}\n\n// ─── Scroll-triggered fade-in ─────────────────────────────────────────────────\n\ninterface FadeInProps {\n children: React.ReactNode;\n className?: string;\n delay?: number;\n y?: number;\n}\n\nexport function FadeIn({ children, className, delay = 0, y = 20 }: FadeInProps) {\n return (\n <motion.div\n className={className}\n initial={{ opacity: 0, y }}\n whileInView={{ opacity: 1, y: 0 }}\n viewport={{ once: true, margin: \"-60px\" }}\n transition={{ duration: 0.5, delay, ease: EASE_OUT }}\n >\n {children}\n </motion.div>\n );\n}\n\n// ─── Stagger container ────────────────────────────────────────────────────────\n\ninterface StaggerProps {\n children: React.ReactNode;\n className?: string;\n staggerDelay?: number;\n}\n\nexport function Stagger({ children, className, staggerDelay = 0.07 }: StaggerProps) {\n return (\n <motion.div\n className={className}\n initial=\"hidden\"\n whileInView=\"show\"\n viewport={{ once: true, margin: \"-60px\" }}\n variants={{\n hidden: {},\n show: { transition: { staggerChildren: staggerDelay } },\n }}\n >\n {children}\n </motion.div>\n );\n}\n\nexport function StaggerItem({ children, className }: { children: React.ReactNode; className?: string }) {\n return (\n <motion.div\n className={className}\n variants={{\n hidden: { opacity: 0, y: 20 },\n show: { opacity: 1, y: 0, transition: { duration: 0.45, ease: EASE_OUT } },\n }}\n >\n {children}\n </motion.div>\n );\n}\n\n// ─── Kinetic headline words ───────────────────────────────────────────────────\n\nexport function KineticWords({ text, className }: { text: string; className?: string }) {\n const words = text.split(\" \");\n return (\n <motion.span\n className={className}\n initial=\"hidden\"\n animate=\"show\"\n variants={{\n hidden: {},\n show: { transition: { staggerChildren: 0.08, delayChildren: 0.1 } },\n }}\n >\n {words.map((word, i) => (\n <motion.span\n key={i}\n className=\"inline-block mr-[0.25em]\"\n variants={{\n hidden: { opacity: 0, y: 24, rotateX: -20 },\n show: { opacity: 1, y: 0, rotateX: 0, transition: { duration: 0.5, ease: EASE_OUT } },\n }}\n >\n {word}\n </motion.span>\n ))}\n </motion.span>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeI;AAbJ,2BAA6C;AAEtC,MAAM,SAAS,EAAE,MAAM,UAAU,WAAW,KAAK,SAAS,GAAG;AAC7D,MAAM,WAAW,CAAC,MAAM,MAAM,MAAM,IAAI;AAQxC,SAAS,WAAW,EAAE,UAAU,WAAW,GAAG,MAAM,GAAoB;AAC7E,SACE;AAAA,IAAC,4BAAO;AAAA,IAAP;AAAA,MACC;AAAA,MACA,UAAU,EAAE,OAAO,KAAK;AAAA,MACxB,YAAY;AAAA,MACX,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAWO,SAAS,OAAO,EAAE,UAAU,WAAW,QAAQ,GAAG,IAAI,GAAG,GAAgB;AAC9E,SACE;AAAA,IAAC,4BAAO;AAAA,IAAP;AAAA,MACC;AAAA,MACA,SAAS,EAAE,SAAS,GAAG,EAAE;AAAA,MACzB,aAAa,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,MAChC,UAAU,EAAE,MAAM,MAAM,QAAQ,QAAQ;AAAA,MACxC,YAAY,EAAE,UAAU,KAAK,OAAO,MAAM,SAAS;AAAA,MAElD;AAAA;AAAA,EACH;AAEJ;AAUO,SAAS,QAAQ,EAAE,UAAU,WAAW,eAAe,KAAK,GAAiB;AAClF,SACE;AAAA,IAAC,4BAAO;AAAA,IAAP;AAAA,MACC;AAAA,MACA,SAAQ;AAAA,MACR,aAAY;AAAA,MACZ,UAAU,EAAE,MAAM,MAAM,QAAQ,QAAQ;AAAA,MACxC,UAAU;AAAA,QACR,QAAQ,CAAC;AAAA,QACT,MAAM,EAAE,YAAY,EAAE,iBAAiB,aAAa,EAAE;AAAA,MACxD;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAEO,SAAS,YAAY,EAAE,UAAU,UAAU,GAAsD;AACtG,SACE;AAAA,IAAC,4BAAO;AAAA,IAAP;AAAA,MACC;AAAA,MACA,UAAU;AAAA,QACR,QAAQ,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,QAC5B,MAAM,EAAE,SAAS,GAAG,GAAG,GAAG,YAAY,EAAE,UAAU,MAAM,MAAM,SAAS,EAAE;AAAA,MAC3E;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAIO,SAAS,aAAa,EAAE,MAAM,UAAU,GAAyC;AACtF,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,SACE;AAAA,IAAC,4BAAO;AAAA,IAAP;AAAA,MACC;AAAA,MACA,SAAQ;AAAA,MACR,SAAQ;AAAA,MACR,UAAU;AAAA,QACR,QAAQ,CAAC;AAAA,QACT,MAAM,EAAE,YAAY,EAAE,iBAAiB,MAAM,eAAe,IAAI,EAAE;AAAA,MACpE;AAAA,MAEC,gBAAM,IAAI,CAAC,MAAM,MAChB;AAAA,QAAC,4BAAO;AAAA,QAAP;AAAA,UAEC,WAAU;AAAA,UACV,UAAU;AAAA,YACR,QAAQ,EAAE,SAAS,GAAG,GAAG,IAAI,SAAS,IAAI;AAAA,YAC1C,MAAM,EAAE,SAAS,GAAG,GAAG,GAAG,SAAS,GAAG,YAAY,EAAE,UAAU,KAAK,MAAM,SAAS,EAAE;AAAA,UACtF;AAAA,UAEC;AAAA;AAAA,QAPI;AAAA,MAQP,CACD;AAAA;AAAA,EACH;AAEJ;","names":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { HTMLMotionProps } from 'framer-motion';
|
|
3
|
+
|
|
4
|
+
declare const SPRING: {
|
|
5
|
+
readonly type: "spring";
|
|
6
|
+
readonly stiffness: 400;
|
|
7
|
+
readonly damping: 28;
|
|
8
|
+
};
|
|
9
|
+
declare const EASE_OUT: readonly [0.25, 0.46, 0.45, 0.94];
|
|
10
|
+
interface MotionCardProps extends HTMLMotionProps<"div"> {
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
declare function MotionCard({ children, className, ...props }: MotionCardProps): react_jsx_runtime.JSX.Element;
|
|
14
|
+
interface FadeInProps {
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
className?: string;
|
|
17
|
+
delay?: number;
|
|
18
|
+
y?: number;
|
|
19
|
+
}
|
|
20
|
+
declare function FadeIn({ children, className, delay, y }: FadeInProps): react_jsx_runtime.JSX.Element;
|
|
21
|
+
interface StaggerProps {
|
|
22
|
+
children: React.ReactNode;
|
|
23
|
+
className?: string;
|
|
24
|
+
staggerDelay?: number;
|
|
25
|
+
}
|
|
26
|
+
declare function Stagger({ children, className, staggerDelay }: StaggerProps): react_jsx_runtime.JSX.Element;
|
|
27
|
+
declare function StaggerItem({ children, className }: {
|
|
28
|
+
children: React.ReactNode;
|
|
29
|
+
className?: string;
|
|
30
|
+
}): react_jsx_runtime.JSX.Element;
|
|
31
|
+
declare function KineticWords({ text, className }: {
|
|
32
|
+
text: string;
|
|
33
|
+
className?: string;
|
|
34
|
+
}): react_jsx_runtime.JSX.Element;
|
|
35
|
+
|
|
36
|
+
export { EASE_OUT, FadeIn, KineticWords, MotionCard, SPRING, Stagger, StaggerItem };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { HTMLMotionProps } from 'framer-motion';
|
|
3
|
+
|
|
4
|
+
declare const SPRING: {
|
|
5
|
+
readonly type: "spring";
|
|
6
|
+
readonly stiffness: 400;
|
|
7
|
+
readonly damping: 28;
|
|
8
|
+
};
|
|
9
|
+
declare const EASE_OUT: readonly [0.25, 0.46, 0.45, 0.94];
|
|
10
|
+
interface MotionCardProps extends HTMLMotionProps<"div"> {
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
declare function MotionCard({ children, className, ...props }: MotionCardProps): react_jsx_runtime.JSX.Element;
|
|
14
|
+
interface FadeInProps {
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
className?: string;
|
|
17
|
+
delay?: number;
|
|
18
|
+
y?: number;
|
|
19
|
+
}
|
|
20
|
+
declare function FadeIn({ children, className, delay, y }: FadeInProps): react_jsx_runtime.JSX.Element;
|
|
21
|
+
interface StaggerProps {
|
|
22
|
+
children: React.ReactNode;
|
|
23
|
+
className?: string;
|
|
24
|
+
staggerDelay?: number;
|
|
25
|
+
}
|
|
26
|
+
declare function Stagger({ children, className, staggerDelay }: StaggerProps): react_jsx_runtime.JSX.Element;
|
|
27
|
+
declare function StaggerItem({ children, className }: {
|
|
28
|
+
children: React.ReactNode;
|
|
29
|
+
className?: string;
|
|
30
|
+
}): react_jsx_runtime.JSX.Element;
|
|
31
|
+
declare function KineticWords({ text, className }: {
|
|
32
|
+
text: string;
|
|
33
|
+
className?: string;
|
|
34
|
+
}): react_jsx_runtime.JSX.Element;
|
|
35
|
+
|
|
36
|
+
export { EASE_OUT, FadeIn, KineticWords, MotionCard, SPRING, Stagger, StaggerItem };
|