@medialane/ui 0.302.0 → 0.303.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/asset-card.cjs +2 -2
- package/dist/components/asset-card.cjs.map +1 -1
- package/dist/components/asset-card.js +2 -2
- package/dist/components/asset-card.js.map +1 -1
- package/dist/components/button.d.cts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/components/collection-provenance-tab.cjs +50 -36
- package/dist/components/collection-provenance-tab.cjs.map +1 -1
- package/dist/components/collection-provenance-tab.js +51 -37
- package/dist/components/collection-provenance-tab.js.map +1 -1
- package/dist/components/fast-mint/fast-mint.d.cts +2 -2
- package/dist/components/fast-mint/fast-mint.d.ts +2 -2
- package/dist/data/activity.cjs +5 -5
- package/dist/data/activity.cjs.map +1 -1
- package/dist/data/activity.js +5 -5
- package/dist/data/activity.js.map +1 -1
- package/dist/utils/media-wallet/use-erc20-balance.d.cts +1 -1
- package/dist/utils/media-wallet/use-erc20-balance.d.ts +1 -1
- package/package.json +1 -1
|
@@ -62,7 +62,7 @@ function AssetCard({
|
|
|
62
62
|
"div",
|
|
63
63
|
{
|
|
64
64
|
className: (0, import_cn.cn)(
|
|
65
|
-
"group relative flex flex-col w-full overflow-hidden rounded-xl
|
|
65
|
+
"group relative flex flex-col w-full overflow-hidden rounded-xl bg-card",
|
|
66
66
|
className
|
|
67
67
|
),
|
|
68
68
|
children: [
|
|
@@ -109,7 +109,7 @@ function AssetCard({
|
|
|
109
109
|
);
|
|
110
110
|
}
|
|
111
111
|
function AssetCardSkeleton() {
|
|
112
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col w-full overflow-hidden rounded-xl
|
|
112
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col w-full overflow-hidden rounded-xl bg-card", children: [
|
|
113
113
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "aspect-square w-full animate-pulse bg-muted" }),
|
|
114
114
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "px-3 py-3 space-y-1.5", children: [
|
|
115
115
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-4 w-3/4 rounded-md animate-pulse bg-muted" }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/asset-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport { Loader2 } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\n\nexport interface AssetCardPrice {\n formatted?: string | null;\n currency?: string | null;\n\n usdValue?: string | null;\n}\n\nexport interface AssetCardProps {\n\n href: string;\n\n name: string;\n\n image?: string | null;\n\n animationUrl?: string | null;\n\n live?: boolean;\n\n subtitle?: string | null;\n\n ipType?: string | null;\n\n price?: AssetCardPrice | null;\n\n fallbackId?: string | null;\n\n indexing?: boolean;\n\n ipTypeBaseUrl?: string;\n className?: string;\n}\n\nexport function AssetCard({\n href,\n name,\n image,\n animationUrl,\n live = false,\n subtitle,\n ipType,\n price,\n fallbackId,\n indexing = false,\n ipTypeBaseUrl = \"\",\n className,\n}: AssetCardProps) {\n const resolveImage = useImageUrl();\n const resolved = resolveImage(image, { width: 480 });\n const hasPrice = !!price?.formatted;\n\n return (\n <div\n className={cn(\n \"group relative flex flex-col w-full overflow-hidden rounded-xl
|
|
1
|
+
{"version":3,"sources":["../../src/components/asset-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport { Loader2 } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\n\nexport interface AssetCardPrice {\n formatted?: string | null;\n currency?: string | null;\n\n usdValue?: string | null;\n}\n\nexport interface AssetCardProps {\n\n href: string;\n\n name: string;\n\n image?: string | null;\n\n animationUrl?: string | null;\n\n live?: boolean;\n\n subtitle?: string | null;\n\n ipType?: string | null;\n\n price?: AssetCardPrice | null;\n\n fallbackId?: string | null;\n\n indexing?: boolean;\n\n ipTypeBaseUrl?: string;\n className?: string;\n}\n\nexport function AssetCard({\n href,\n name,\n image,\n animationUrl,\n live = false,\n subtitle,\n ipType,\n price,\n fallbackId,\n indexing = false,\n ipTypeBaseUrl = \"\",\n className,\n}: AssetCardProps) {\n const resolveImage = useImageUrl();\n const resolved = resolveImage(image, { width: 480 });\n const hasPrice = !!price?.formatted;\n\n return (\n <div\n className={cn(\n \"group relative flex flex-col w-full overflow-hidden rounded-xl bg-card\",\n className\n )}\n >\n\n {ipType && (\n <div className=\"absolute top-2 right-2 z-10\">\n <IpTypeBadge ipType={ipType} size=\"sm\" baseUrl={ipTypeBaseUrl} />\n </div>\n )}\n\n <Link href={href} className=\"block relative aspect-square bg-muted overflow-hidden\">\n <AnimatedTokenMedia\n image={resolved}\n animationUrl={animationUrl}\n live={live}\n alt={name}\n mode=\"fill\"\n sizes=\"(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 22vw\"\n className=\"object-cover transition-transform duration-700 ease-out group-hover:scale-[1.03]\"\n fallback={\n <div className=\"absolute inset-0 flex items-center justify-center bg-gradient-to-br from-brand-blue/25 via-brand-purple/25 to-brand-rose/25\">\n <span className=\"text-sm font-semibold text-muted-foreground tabular-nums\">\n #{fallbackId ?? \"?\"}\n </span>\n </div>\n }\n />\n\n {indexing && (\n <div className=\"absolute bottom-0 inset-x-0 flex items-center justify-center gap-1.5 bg-black/50 backdrop-blur-sm py-1.5\">\n <Loader2 className=\"h-3 w-3 animate-spin text-white/70\" />\n <span className=\"text-2xs text-white/70\">Indexing…</span>\n </div>\n )}\n </Link>\n\n <div className=\"px-3 py-3 space-y-1\">\n <Link href={href} className=\"block min-w-0\">\n <p className=\"text-base font-semibold tracking-tight line-clamp-2 break-words leading-snug\">\n {name}\n </p>\n {subtitle && (\n <p className=\"text-xs text-muted-foreground line-clamp-1 leading-snug\">\n {subtitle}\n </p>\n )}\n </Link>\n\n {hasPrice && !indexing && (\n <div className=\"flex items-center gap-1.5 text-sm font-bold tabular-nums pt-0.5\">\n <PriceChipContent\n amountFormatted={price!.formatted}\n currency={price!.currency}\n usdValue={price!.usdValue}\n tone=\"solid\"\n />\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport function AssetCardSkeleton() {\n return (\n <div className=\"flex flex-col w-full overflow-hidden rounded-xl bg-card\">\n <div className=\"aspect-square w-full animate-pulse bg-muted\" />\n <div className=\"px-3 py-3 space-y-1.5\">\n <div className=\"h-4 w-3/4 rounded-md animate-pulse bg-muted\" />\n <div className=\"h-3.5 w-2/5 rounded-md animate-pulse bg-muted\" />\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuEU;AArEV,kBAAiB;AACjB,0BAAwB;AACxB,gBAAmB;AACnB,wBAAiC;AACjC,2BAA4B;AAC5B,kCAAmC;AACnC,2BAA4B;AAmCrB,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,gBAAgB;AAAA,EAChB;AACF,GAAmB;AACjB,QAAM,mBAAe,kCAAY;AACjC,QAAM,WAAW,aAAa,OAAO,EAAE,OAAO,IAAI,CAAC;AACnD,QAAM,WAAW,CAAC,CAAC,OAAO;AAE1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAGC;AAAA,kBACC,4CAAC,SAAI,WAAU,+BACb,sDAAC,oCAAY,QAAgB,MAAK,MAAK,SAAS,eAAe,GACjE;AAAA,QAGF,6CAAC,YAAAA,SAAA,EAAK,MAAY,WAAU,yDAC1B;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,cACP;AAAA,cACA;AAAA,cACA,KAAK;AAAA,cACL,MAAK;AAAA,cACL,OAAM;AAAA,cACN,WAAU;AAAA,cACV,UACE,4CAAC,SAAI,WAAU,+HACb,uDAAC,UAAK,WAAU,4DAA2D;AAAA;AAAA,gBACvE,cAAc;AAAA,iBAClB,GACF;AAAA;AAAA,UAEJ;AAAA,UAEC,YACC,6CAAC,SAAI,WAAU,4GACb;AAAA,wDAAC,+BAAQ,WAAU,sCAAqC;AAAA,YACxD,4CAAC,UAAK,WAAU,0BAAyB,4BAAS;AAAA,aACpD;AAAA,WAEJ;AAAA,QAEA,6CAAC,SAAI,WAAU,uBACb;AAAA,uDAAC,YAAAA,SAAA,EAAK,MAAY,WAAU,iBAC1B;AAAA,wDAAC,OAAE,WAAU,gFACV,gBACH;AAAA,YACC,YACC,4CAAC,OAAE,WAAU,2DACV,oBACH;AAAA,aAEJ;AAAA,UAEC,YAAY,CAAC,YACZ,4CAAC,SAAI,WAAU,mEACb;AAAA,YAAC;AAAA;AAAA,cACC,iBAAiB,MAAO;AAAA,cACxB,UAAU,MAAO;AAAA,cACjB,UAAU,MAAO;AAAA,cACjB,MAAK;AAAA;AAAA,UACP,GACF;AAAA,WAEJ;AAAA;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,oBAAoB;AAClC,SACE,6CAAC,SAAI,WAAU,2DACb;AAAA,gDAAC,SAAI,WAAU,+CAA8C;AAAA,IAC7D,6CAAC,SAAI,WAAU,yBACb;AAAA,kDAAC,SAAI,WAAU,+CAA8C;AAAA,MAC7D,4CAAC,SAAI,WAAU,iDAAgD;AAAA,OACjE;AAAA,KACF;AAEJ;","names":["Link"]}
|
|
@@ -28,7 +28,7 @@ function AssetCard({
|
|
|
28
28
|
"div",
|
|
29
29
|
{
|
|
30
30
|
className: cn(
|
|
31
|
-
"group relative flex flex-col w-full overflow-hidden rounded-xl
|
|
31
|
+
"group relative flex flex-col w-full overflow-hidden rounded-xl bg-card",
|
|
32
32
|
className
|
|
33
33
|
),
|
|
34
34
|
children: [
|
|
@@ -75,7 +75,7 @@ function AssetCard({
|
|
|
75
75
|
);
|
|
76
76
|
}
|
|
77
77
|
function AssetCardSkeleton() {
|
|
78
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col w-full overflow-hidden rounded-xl
|
|
78
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col w-full overflow-hidden rounded-xl bg-card", children: [
|
|
79
79
|
/* @__PURE__ */ jsx("div", { className: "aspect-square w-full animate-pulse bg-muted" }),
|
|
80
80
|
/* @__PURE__ */ jsxs("div", { className: "px-3 py-3 space-y-1.5", children: [
|
|
81
81
|
/* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 rounded-md animate-pulse bg-muted" }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/asset-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport { Loader2 } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\n\nexport interface AssetCardPrice {\n formatted?: string | null;\n currency?: string | null;\n\n usdValue?: string | null;\n}\n\nexport interface AssetCardProps {\n\n href: string;\n\n name: string;\n\n image?: string | null;\n\n animationUrl?: string | null;\n\n live?: boolean;\n\n subtitle?: string | null;\n\n ipType?: string | null;\n\n price?: AssetCardPrice | null;\n\n fallbackId?: string | null;\n\n indexing?: boolean;\n\n ipTypeBaseUrl?: string;\n className?: string;\n}\n\nexport function AssetCard({\n href,\n name,\n image,\n animationUrl,\n live = false,\n subtitle,\n ipType,\n price,\n fallbackId,\n indexing = false,\n ipTypeBaseUrl = \"\",\n className,\n}: AssetCardProps) {\n const resolveImage = useImageUrl();\n const resolved = resolveImage(image, { width: 480 });\n const hasPrice = !!price?.formatted;\n\n return (\n <div\n className={cn(\n \"group relative flex flex-col w-full overflow-hidden rounded-xl
|
|
1
|
+
{"version":3,"sources":["../../src/components/asset-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport { Loader2 } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\n\nexport interface AssetCardPrice {\n formatted?: string | null;\n currency?: string | null;\n\n usdValue?: string | null;\n}\n\nexport interface AssetCardProps {\n\n href: string;\n\n name: string;\n\n image?: string | null;\n\n animationUrl?: string | null;\n\n live?: boolean;\n\n subtitle?: string | null;\n\n ipType?: string | null;\n\n price?: AssetCardPrice | null;\n\n fallbackId?: string | null;\n\n indexing?: boolean;\n\n ipTypeBaseUrl?: string;\n className?: string;\n}\n\nexport function AssetCard({\n href,\n name,\n image,\n animationUrl,\n live = false,\n subtitle,\n ipType,\n price,\n fallbackId,\n indexing = false,\n ipTypeBaseUrl = \"\",\n className,\n}: AssetCardProps) {\n const resolveImage = useImageUrl();\n const resolved = resolveImage(image, { width: 480 });\n const hasPrice = !!price?.formatted;\n\n return (\n <div\n className={cn(\n \"group relative flex flex-col w-full overflow-hidden rounded-xl bg-card\",\n className\n )}\n >\n\n {ipType && (\n <div className=\"absolute top-2 right-2 z-10\">\n <IpTypeBadge ipType={ipType} size=\"sm\" baseUrl={ipTypeBaseUrl} />\n </div>\n )}\n\n <Link href={href} className=\"block relative aspect-square bg-muted overflow-hidden\">\n <AnimatedTokenMedia\n image={resolved}\n animationUrl={animationUrl}\n live={live}\n alt={name}\n mode=\"fill\"\n sizes=\"(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 22vw\"\n className=\"object-cover transition-transform duration-700 ease-out group-hover:scale-[1.03]\"\n fallback={\n <div className=\"absolute inset-0 flex items-center justify-center bg-gradient-to-br from-brand-blue/25 via-brand-purple/25 to-brand-rose/25\">\n <span className=\"text-sm font-semibold text-muted-foreground tabular-nums\">\n #{fallbackId ?? \"?\"}\n </span>\n </div>\n }\n />\n\n {indexing && (\n <div className=\"absolute bottom-0 inset-x-0 flex items-center justify-center gap-1.5 bg-black/50 backdrop-blur-sm py-1.5\">\n <Loader2 className=\"h-3 w-3 animate-spin text-white/70\" />\n <span className=\"text-2xs text-white/70\">Indexing…</span>\n </div>\n )}\n </Link>\n\n <div className=\"px-3 py-3 space-y-1\">\n <Link href={href} className=\"block min-w-0\">\n <p className=\"text-base font-semibold tracking-tight line-clamp-2 break-words leading-snug\">\n {name}\n </p>\n {subtitle && (\n <p className=\"text-xs text-muted-foreground line-clamp-1 leading-snug\">\n {subtitle}\n </p>\n )}\n </Link>\n\n {hasPrice && !indexing && (\n <div className=\"flex items-center gap-1.5 text-sm font-bold tabular-nums pt-0.5\">\n <PriceChipContent\n amountFormatted={price!.formatted}\n currency={price!.currency}\n usdValue={price!.usdValue}\n tone=\"solid\"\n />\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport function AssetCardSkeleton() {\n return (\n <div className=\"flex flex-col w-full overflow-hidden rounded-xl bg-card\">\n <div className=\"aspect-square w-full animate-pulse bg-muted\" />\n <div className=\"px-3 py-3 space-y-1.5\">\n <div className=\"h-4 w-3/4 rounded-md animate-pulse bg-muted\" />\n <div className=\"h-3.5 w-2/5 rounded-md animate-pulse bg-muted\" />\n </div>\n </div>\n );\n}\n"],"mappings":";AAuEU,cAeI,YAfJ;AArEV,OAAO,UAAU;AACjB,SAAS,eAAe;AACxB,SAAS,UAAU;AACnB,SAAS,wBAAwB;AACjC,SAAS,mBAAmB;AAC5B,SAAS,0BAA0B;AACnC,SAAS,mBAAmB;AAmCrB,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,gBAAgB;AAAA,EAChB;AACF,GAAmB;AACjB,QAAM,eAAe,YAAY;AACjC,QAAM,WAAW,aAAa,OAAO,EAAE,OAAO,IAAI,CAAC;AACnD,QAAM,WAAW,CAAC,CAAC,OAAO;AAE1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAGC;AAAA,kBACC,oBAAC,SAAI,WAAU,+BACb,8BAAC,eAAY,QAAgB,MAAK,MAAK,SAAS,eAAe,GACjE;AAAA,QAGF,qBAAC,QAAK,MAAY,WAAU,yDAC1B;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,cACP;AAAA,cACA;AAAA,cACA,KAAK;AAAA,cACL,MAAK;AAAA,cACL,OAAM;AAAA,cACN,WAAU;AAAA,cACV,UACE,oBAAC,SAAI,WAAU,+HACb,+BAAC,UAAK,WAAU,4DAA2D;AAAA;AAAA,gBACvE,cAAc;AAAA,iBAClB,GACF;AAAA;AAAA,UAEJ;AAAA,UAEC,YACC,qBAAC,SAAI,WAAU,4GACb;AAAA,gCAAC,WAAQ,WAAU,sCAAqC;AAAA,YACxD,oBAAC,UAAK,WAAU,0BAAyB,4BAAS;AAAA,aACpD;AAAA,WAEJ;AAAA,QAEA,qBAAC,SAAI,WAAU,uBACb;AAAA,+BAAC,QAAK,MAAY,WAAU,iBAC1B;AAAA,gCAAC,OAAE,WAAU,gFACV,gBACH;AAAA,YACC,YACC,oBAAC,OAAE,WAAU,2DACV,oBACH;AAAA,aAEJ;AAAA,UAEC,YAAY,CAAC,YACZ,oBAAC,SAAI,WAAU,mEACb;AAAA,YAAC;AAAA;AAAA,cACC,iBAAiB,MAAO;AAAA,cACxB,UAAU,MAAO;AAAA,cACjB,UAAU,MAAO;AAAA,cACjB,MAAK;AAAA;AAAA,UACP,GACF;AAAA,WAEJ;AAAA;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,oBAAoB;AAClC,SACE,qBAAC,SAAI,WAAU,2DACb;AAAA,wBAAC,SAAI,WAAU,+CAA8C;AAAA,IAC7D,qBAAC,SAAI,WAAU,yBACb;AAAA,0BAAC,SAAI,WAAU,+CAA8C;AAAA,MAC7D,oBAAC,SAAI,WAAU,iDAAgD;AAAA,OACjE;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
|
|
7
7
|
size?: "default" | "icon" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
|
|
7
7
|
size?: "default" | "icon" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -86,50 +86,64 @@ function ProvenanceEvent({ event, showAsset }) {
|
|
|
86
86
|
const amount = event.amount && Number(event.amount) > 1 ? event.amount : null;
|
|
87
87
|
const name = event.token?.name ?? (tokenId ? `#${tokenId}` : null);
|
|
88
88
|
const image = resolveImage(event.token?.image ?? null);
|
|
89
|
-
|
|
89
|
+
const leadWithAsset = showAsset && !!name;
|
|
90
|
+
const assetLink = contract && tokenId ? (0, import_sdk.assetHref)(event.chain ?? "STARKNET", contract, tokenId) : null;
|
|
91
|
+
const actorLink = actor ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "text-sm font-normal text-muted-foreground", children: [
|
|
92
|
+
"by",
|
|
93
|
+
" ",
|
|
94
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
95
|
+
import_link.default,
|
|
96
|
+
{
|
|
97
|
+
href: (0, import_sdk.profileHref)({ address: actor }),
|
|
98
|
+
className: "font-medium text-foreground/80 hover:text-primary transition-colors",
|
|
99
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_address_display.AddressDisplay, { address: actor, chars: 6, showCopy: false, className: "text-sm" })
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
] }) : null;
|
|
103
|
+
const tile = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
104
|
+
"span",
|
|
105
|
+
{
|
|
106
|
+
className: (0, import_cn.cn)(
|
|
107
|
+
"flex h-11 w-11 shrink-0 items-center justify-center rounded-xl",
|
|
108
|
+
config?.bgClass ?? "bg-muted"
|
|
109
|
+
),
|
|
110
|
+
"aria-hidden": true,
|
|
111
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: (0, import_cn.cn)("h-5 w-5", config?.colorClass ?? "text-muted-foreground") })
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
const thumb = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "relative h-14 w-14 shrink-0", children: [
|
|
115
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "block h-full w-full overflow-hidden rounded-xl bg-gradient-to-br from-brand-blue/25 via-brand-purple/25 to-brand-rose/25", children: image ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_image.default, { src: image, alt: "", width: 56, height: 56, className: "h-full w-full object-cover", unoptimized: true }) : null }),
|
|
90
116
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
91
117
|
"span",
|
|
92
118
|
{
|
|
93
119
|
className: (0, import_cn.cn)(
|
|
94
|
-
"flex h-
|
|
95
|
-
config?.bgClass ?? "bg-muted"
|
|
120
|
+
"absolute -bottom-1 -right-1 flex h-6 w-6 items-center justify-center rounded-full bg-card ring-2 ring-card"
|
|
96
121
|
),
|
|
97
122
|
"aria-hidden": true,
|
|
98
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: (0, import_cn.cn)("h-
|
|
123
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: (0, import_cn.cn)("flex h-full w-full items-center justify-center rounded-full", config?.bgClass ?? "bg-muted"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: (0, import_cn.cn)("h-3 w-3", config?.colorClass ?? "text-muted-foreground") }) })
|
|
99
124
|
}
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
125
|
+
)
|
|
126
|
+
] });
|
|
127
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "flex items-center gap-4 rounded-2xl border border-border/50 bg-card/60 p-4 backdrop-blur-sm transition-colors hover:bg-card/90", children: [
|
|
128
|
+
leadWithAsset ? assetLink ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: assetLink, className: "shrink-0", children: thumb }) : thumb : tile,
|
|
129
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "min-w-0 flex-1", children: leadWithAsset ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
130
|
+
assetLink ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: assetLink, className: "block truncate text-base font-semibold leading-tight hover:text-primary transition-colors", children: name }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "truncate text-base font-semibold leading-tight", children: name }),
|
|
131
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "mt-1 flex flex-wrap items-baseline gap-x-1.5 text-sm", children: [
|
|
132
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: (0, import_cn.cn)("font-medium", config?.colorClass), children: EVENT_TITLE[event.type] ?? event.type }),
|
|
133
|
+
amount ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
105
134
|
"\xD7",
|
|
106
135
|
amount
|
|
107
136
|
] }) : null,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
)
|
|
119
|
-
] }) : null
|
|
120
|
-
] }),
|
|
121
|
-
showAsset && name ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
122
|
-
import_link.default,
|
|
123
|
-
{
|
|
124
|
-
href: contract && tokenId ? (0, import_sdk.assetHref)(event.chain ?? "STARKNET", contract, tokenId) : "#",
|
|
125
|
-
className: "mt-2 inline-flex max-w-full items-center gap-2 rounded-full bg-muted/70 py-1 pl-1 pr-3 hover:bg-muted transition-colors",
|
|
126
|
-
children: [
|
|
127
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "relative h-6 w-6 shrink-0 overflow-hidden rounded-full bg-muted", children: image ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_image.default, { src: image, alt: "", width: 24, height: 24, className: "h-full w-full object-cover", unoptimized: true }) : null }),
|
|
128
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate text-xs font-medium", children: name })
|
|
129
|
-
]
|
|
130
|
-
}
|
|
131
|
-
) : null
|
|
132
|
-
] }),
|
|
137
|
+
actorLink
|
|
138
|
+
] })
|
|
139
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "flex flex-wrap items-baseline gap-x-1.5 text-base font-semibold leading-tight", children: [
|
|
140
|
+
EVENT_TITLE[event.type] ?? event.type,
|
|
141
|
+
amount ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "text-sm font-medium text-muted-foreground", children: [
|
|
142
|
+
"\xD7",
|
|
143
|
+
amount
|
|
144
|
+
] }) : null,
|
|
145
|
+
actorLink
|
|
146
|
+
] }) }),
|
|
133
147
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex shrink-0 flex-col items-end gap-1", children: [
|
|
134
148
|
event.price?.formatted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1.5 text-base font-bold tabular-nums", children: [
|
|
135
149
|
event.price.currency ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_currency_icon.CurrencyIcon, { symbol: event.price.currency, size: 15, "aria-hidden": true }) : null,
|
|
@@ -154,7 +168,7 @@ function ProvenanceEvent({ event, showAsset }) {
|
|
|
154
168
|
] });
|
|
155
169
|
}
|
|
156
170
|
function ProvenanceSkeleton() {
|
|
157
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "
|
|
171
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid gap-2.5 lg:grid-cols-2", "aria-hidden": true, children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-4 rounded-2xl border border-border/50 bg-card/60 p-4", children: [
|
|
158
172
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-11 w-11 shrink-0 rounded-xl bg-muted animate-pulse" }),
|
|
159
173
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 space-y-2", children: [
|
|
160
174
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-4 w-44 rounded bg-muted animate-pulse" }),
|
|
@@ -188,7 +202,7 @@ function CollectionProvenanceTab({ contract }) {
|
|
|
188
202
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-8", children: [
|
|
189
203
|
groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [
|
|
190
204
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "mb-3 font-display text-lg font-bold", children: group.label }),
|
|
191
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "
|
|
205
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "grid gap-2.5 lg:grid-cols-2", children: group.events.map((event, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
192
206
|
ProvenanceEvent,
|
|
193
207
|
{
|
|
194
208
|
event,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/collection-provenance-tab.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useMemo } from \"react\";\nimport type { ApiActivity } from \"@medialane/sdk\";\nimport { assetHref, profileHref } from \"@medialane/sdk\";\nimport { ExternalLink, Inbox } from \"lucide-react\";\nimport Image from \"./image.js\";\nimport Link from \"./link.js\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { useActivities } from \"../utils/use-activities.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\nimport { ACTIVITY_TYPE_CONFIG } from \"../data/activity.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { cn } from \"../utils/cn.js\";\n\nconst PAGE_SIZE = 30;\n\nconst EVENT_TITLE: Record<string, string> = {\n mint: \"Minted\",\n listing: \"Listed for sale\",\n sale: \"Purchased\",\n offer: \"Offer made\",\n transfer: \"Transferred\",\n cancelled: \"Listing cancelled\",\n};\n\nfunction dayLabel(iso: string): string {\n const date = new Date(iso);\n const today = new Date();\n const yesterday = new Date();\n yesterday.setDate(today.getDate() - 1);\n if (date.toDateString() === today.toDateString()) return \"Today\";\n if (date.toDateString() === yesterday.toDateString()) return \"Yesterday\";\n return date.toLocaleDateString(undefined, { day: \"numeric\", month: \"long\", year: \"numeric\" });\n}\n\nfunction groupByDay(events: ApiActivity[]) {\n const groups: { label: string; events: ApiActivity[] }[] = [];\n for (const event of events) {\n const label = dayLabel(event.timestamp);\n const last = groups[groups.length - 1];\n if (last && last.label === label) last.events.push(event);\n else groups.push({ label, events: [event] });\n }\n return groups;\n}\n\nfunction ProvenanceEvent({ event, showAsset }: { event: ApiActivity; showAsset: boolean }) {\n const resolveImage = useImageUrl();\n const config = ACTIVITY_TYPE_CONFIG[event.type];\n const Icon = config?.icon ?? ExternalLink;\n const contract = event.nftContract ?? event.contractAddress ?? null;\n const tokenId = event.nftTokenId ?? event.tokenId ?? null;\n const actor =\n event.offerer ?? event.fulfiller ?? (event.type === \"mint\" ? event.to : event.from) ?? null;\n const amount = event.amount && Number(event.amount) > 1 ? event.amount : null;\n const name = event.token?.name ?? (tokenId ? `#${tokenId}` : null);\n const image = resolveImage(event.token?.image ?? null);\n\n return (\n <li className=\"flex items-center gap-4 rounded-2xl border border-border/50 bg-card/60 p-4 backdrop-blur-sm transition-colors hover:bg-card/90\">\n <span\n className={cn(\n \"flex h-11 w-11 shrink-0 items-center justify-center rounded-xl\",\n config?.bgClass ?? \"bg-muted\"\n )}\n aria-hidden\n >\n <Icon className={cn(\"h-5 w-5\", config?.colorClass ?? \"text-muted-foreground\")} />\n </span>\n\n <div className=\"min-w-0 flex-1\">\n <p className=\"flex flex-wrap items-baseline gap-x-1.5 text-base font-semibold leading-tight\">\n {EVENT_TITLE[event.type] ?? event.type}\n {amount ? <span className=\"text-sm font-medium text-muted-foreground\">×{amount}</span> : null}\n {actor ? (\n <span className=\"text-sm font-normal text-muted-foreground\">\n by{\" \"}\n <Link\n href={profileHref({ address: actor })}\n className=\"font-medium text-foreground/80 hover:text-primary transition-colors\"\n >\n <AddressDisplay address={actor} chars={6} showCopy={false} className=\"text-sm\" />\n </Link>\n </span>\n ) : null}\n </p>\n\n {showAsset && name ? (\n <Link\n href={contract && tokenId ? assetHref(event.chain ?? \"STARKNET\", contract, tokenId) : \"#\"}\n className=\"mt-2 inline-flex max-w-full items-center gap-2 rounded-full bg-muted/70 py-1 pl-1 pr-3 hover:bg-muted transition-colors\"\n >\n <span className=\"relative h-6 w-6 shrink-0 overflow-hidden rounded-full bg-muted\">\n {image ? (\n <Image src={image} alt=\"\" width={24} height={24} className=\"h-full w-full object-cover\" unoptimized />\n ) : null}\n </span>\n <span className=\"truncate text-xs font-medium\">{name}</span>\n </Link>\n ) : null}\n </div>\n\n <div className=\"flex shrink-0 flex-col items-end gap-1\">\n {event.price?.formatted ? (\n <span className=\"flex items-center gap-1.5 text-base font-bold tabular-nums\">\n {event.price.currency ? <CurrencyIcon symbol={event.price.currency} size={15} aria-hidden /> : null}\n {formatDisplayPrice(event.price.formatted)}\n {event.price.currency ? (\n <span className=\"text-xs font-medium text-muted-foreground\">{event.price.currency}</span>\n ) : null}\n </span>\n ) : null}\n <span className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n <time dateTime={event.timestamp} title={new Date(event.timestamp).toLocaleString()}>\n {timeAgo(event.timestamp)}\n </time>\n {event.txHash ? (\n <a\n href={`${EXPLORER_URL}/tx/${event.txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"rounded-md p-1 hover:bg-muted hover:text-foreground transition-colors\"\n aria-label=\"View transaction\"\n >\n <ExternalLink className=\"h-3.5 w-3.5\" aria-hidden />\n </a>\n ) : null}\n </span>\n </div>\n </li>\n );\n}\n\nfunction ProvenanceSkeleton() {\n return (\n <div className=\"space-y-2.5\" aria-hidden>\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-4 rounded-2xl border border-border/50 bg-card/60 p-4\">\n <div className=\"h-11 w-11 shrink-0 rounded-xl bg-muted animate-pulse\" />\n <div className=\"flex-1 space-y-2\">\n <div className=\"h-4 w-44 rounded bg-muted animate-pulse\" />\n <div className=\"h-3 w-24 rounded bg-muted animate-pulse\" />\n </div>\n <div className=\"h-4 w-16 rounded bg-muted animate-pulse\" />\n </div>\n ))}\n </div>\n );\n}\n\nexport interface CollectionProvenanceTabProps {\n contract: string;\n}\n\nexport function CollectionProvenanceTab({ contract }: CollectionProvenanceTabProps) {\n const [page, setPage] = useState(1);\n const [all, setAll] = useState<ApiActivity[]>([]);\n const { activities, meta, isLoading } = useActivities({ contract, page, limit: PAGE_SIZE });\n\n useEffect(() => {\n if (activities.length === 0) return;\n setAll((prev) => (page === 1 ? activities : [...prev, ...activities]));\n }, [activities, page]);\n\n const groups = useMemo(() => groupByDay(all), [all]);\n const showAsset = useMemo(\n () => new Set(all.map((e) => e.nftTokenId ?? e.tokenId ?? \"\")).size > 1,\n [all]\n );\n const hasMore = meta ? all.length < (meta.total ?? 0) : false;\n\n if (isLoading && all.length === 0) return <ProvenanceSkeleton />;\n\n if (all.length === 0) {\n return (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <Inbox className=\"h-10 w-10 text-muted-foreground/40\" />\n <p className=\"text-sm font-medium text-muted-foreground\">No history yet</p>\n <p className=\"text-xs text-muted-foreground/70 max-w-xs\">\n Mints, transfers, listings and sales will appear here as they happen.\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-8\">\n {groups.map((group) => (\n <section key={group.label}>\n <h3 className=\"mb-3 font-display text-lg font-bold\">{group.label}</h3>\n <ol className=\"space-y-2.5\">\n {group.events.map((event, i) => (\n <ProvenanceEvent\n key={`${event.txHash ?? event.orderHash}-${event.type}-${i}`}\n event={event}\n showAsset={showAsset}\n />\n ))}\n </ol>\n </section>\n ))}\n <LoadMoreSentinel hasMore={hasMore} isLoading={isLoading} onLoadMore={() => setPage((p) => p + 1)} />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwEQ;AAtER,mBAA6C;AAE7C,iBAAuC;AACvC,0BAAoC;AACpC,mBAAkB;AAClB,kBAAiB;AACjB,6BAA+B;AAC/B,2BAA6B;AAC7B,gCAAiC;AACjC,4BAA8B;AAC9B,2BAA4B;AAC5B,sBAAqC;AACrC,0BAA6B;AAC7B,oBAAmC;AACnC,kBAAwB;AACxB,gBAAmB;AAEnB,MAAM,YAAY;AAElB,MAAM,cAAsC;AAAA,EAC1C,MAAM;AAAA,EACN,SAAS;AAAA,EACT,MAAM;AAAA,EACN,OAAO;AAAA,EACP,UAAU;AAAA,EACV,WAAW;AACb;AAEA,SAAS,SAAS,KAAqB;AACrC,QAAM,OAAO,IAAI,KAAK,GAAG;AACzB,QAAM,QAAQ,oBAAI,KAAK;AACvB,QAAM,YAAY,oBAAI,KAAK;AAC3B,YAAU,QAAQ,MAAM,QAAQ,IAAI,CAAC;AACrC,MAAI,KAAK,aAAa,MAAM,MAAM,aAAa,EAAG,QAAO;AACzD,MAAI,KAAK,aAAa,MAAM,UAAU,aAAa,EAAG,QAAO;AAC7D,SAAO,KAAK,mBAAmB,QAAW,EAAE,KAAK,WAAW,OAAO,QAAQ,MAAM,UAAU,CAAC;AAC9F;AAEA,SAAS,WAAW,QAAuB;AACzC,QAAM,SAAqD,CAAC;AAC5D,aAAW,SAAS,QAAQ;AAC1B,UAAM,QAAQ,SAAS,MAAM,SAAS;AACtC,UAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,QAAI,QAAQ,KAAK,UAAU,MAAO,MAAK,OAAO,KAAK,KAAK;AAAA,QACnD,QAAO,KAAK,EAAE,OAAO,QAAQ,CAAC,KAAK,EAAE,CAAC;AAAA,EAC7C;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,EAAE,OAAO,UAAU,GAA+C;AACzF,QAAM,mBAAe,kCAAY;AACjC,QAAM,SAAS,qCAAqB,MAAM,IAAI;AAC9C,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,WAAW,MAAM,eAAe,MAAM,mBAAmB;AAC/D,QAAM,UAAU,MAAM,cAAc,MAAM,WAAW;AACrD,QAAM,QACJ,MAAM,WAAW,MAAM,cAAc,MAAM,SAAS,SAAS,MAAM,KAAK,MAAM,SAAS;AACzF,QAAM,SAAS,MAAM,UAAU,OAAO,MAAM,MAAM,IAAI,IAAI,MAAM,SAAS;AACzE,QAAM,OAAO,MAAM,OAAO,SAAS,UAAU,IAAI,OAAO,KAAK;AAC7D,QAAM,QAAQ,aAAa,MAAM,OAAO,SAAS,IAAI;AAErD,SACE,6CAAC,QAAG,WAAU,kIACZ;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,eAAW;AAAA,UACT;AAAA,UACA,QAAQ,WAAW;AAAA,QACrB;AAAA,QACA,eAAW;AAAA,QAEX,sDAAC,QAAK,eAAW,cAAG,WAAW,QAAQ,cAAc,uBAAuB,GAAG;AAAA;AAAA,IACjF;AAAA,IAEA,6CAAC,SAAI,WAAU,kBACb;AAAA,mDAAC,OAAE,WAAU,iFACV;AAAA,oBAAY,MAAM,IAAI,KAAK,MAAM;AAAA,QACjC,SAAS,6CAAC,UAAK,WAAU,6CAA4C;AAAA;AAAA,UAAE;AAAA,WAAO,IAAU;AAAA,QACxF,QACC,6CAAC,UAAK,WAAU,6CAA4C;AAAA;AAAA,UACvD;AAAA,UACH;AAAA,YAAC,YAAAA;AAAA,YAAA;AAAA,cACC,UAAM,wBAAY,EAAE,SAAS,MAAM,CAAC;AAAA,cACpC,WAAU;AAAA,cAEV,sDAAC,yCAAe,SAAS,OAAO,OAAO,GAAG,UAAU,OAAO,WAAU,WAAU;AAAA;AAAA,UACjF;AAAA,WACF,IACE;AAAA,SACN;AAAA,MAEC,aAAa,OACZ;AAAA,QAAC,YAAAA;AAAA,QAAA;AAAA,UACC,MAAM,YAAY,cAAU,sBAAU,MAAM,SAAS,YAAY,UAAU,OAAO,IAAI;AAAA,UACtF,WAAU;AAAA,UAEV;AAAA,wDAAC,UAAK,WAAU,mEACb,kBACC,4CAAC,aAAAC,SAAA,EAAM,KAAK,OAAO,KAAI,IAAG,OAAO,IAAI,QAAQ,IAAI,WAAU,8BAA6B,aAAW,MAAC,IAClG,MACN;AAAA,YACA,4CAAC,UAAK,WAAU,gCAAgC,gBAAK;AAAA;AAAA;AAAA,MACvD,IACE;AAAA,OACN;AAAA,IAEA,6CAAC,SAAI,WAAU,0CACZ;AAAA,YAAM,OAAO,YACZ,6CAAC,UAAK,WAAU,8DACb;AAAA,cAAM,MAAM,WAAW,4CAAC,qCAAa,QAAQ,MAAM,MAAM,UAAU,MAAM,IAAI,eAAW,MAAC,IAAK;AAAA,YAC9F,kCAAmB,MAAM,MAAM,SAAS;AAAA,QACxC,MAAM,MAAM,WACX,4CAAC,UAAK,WAAU,6CAA6C,gBAAM,MAAM,UAAS,IAChF;AAAA,SACN,IACE;AAAA,MACJ,6CAAC,UAAK,WAAU,yDACd;AAAA,oDAAC,UAAK,UAAU,MAAM,WAAW,OAAO,IAAI,KAAK,MAAM,SAAS,EAAE,eAAe,GAC9E,mCAAQ,MAAM,SAAS,GAC1B;AAAA,QACC,MAAM,SACL;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,GAAG,gCAAY,OAAO,MAAM,MAAM;AAAA,YACxC,QAAO;AAAA,YACP,KAAI;AAAA,YACJ,WAAU;AAAA,YACV,cAAW;AAAA,YAEX,sDAAC,oCAAa,WAAU,eAAc,eAAW,MAAC;AAAA;AAAA,QACpD,IACE;AAAA,SACN;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,SAAS,qBAAqB;AAC5B,SACE,4CAAC,SAAI,WAAU,eAAc,eAAW,MACrC,gBAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,MACjC,6CAAC,SAAY,WAAU,8EACrB;AAAA,gDAAC,SAAI,WAAU,wDAAuD;AAAA,IACtE,6CAAC,SAAI,WAAU,oBACb;AAAA,kDAAC,SAAI,WAAU,2CAA0C;AAAA,MACzD,4CAAC,SAAI,WAAU,2CAA0C;AAAA,OAC3D;AAAA,IACA,4CAAC,SAAI,WAAU,2CAA0C;AAAA,OANjD,CAOV,CACD,GACH;AAEJ;AAMO,SAAS,wBAAwB,EAAE,SAAS,GAAiC;AAClF,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAS,CAAC;AAClC,QAAM,CAAC,KAAK,MAAM,QAAI,uBAAwB,CAAC,CAAC;AAChD,QAAM,EAAE,YAAY,MAAM,UAAU,QAAI,qCAAc,EAAE,UAAU,MAAM,OAAO,UAAU,CAAC;AAE1F,8BAAU,MAAM;AACd,QAAI,WAAW,WAAW,EAAG;AAC7B,WAAO,CAAC,SAAU,SAAS,IAAI,aAAa,CAAC,GAAG,MAAM,GAAG,UAAU,CAAE;AAAA,EACvE,GAAG,CAAC,YAAY,IAAI,CAAC;AAErB,QAAM,aAAS,sBAAQ,MAAM,WAAW,GAAG,GAAG,CAAC,GAAG,CAAC;AACnD,QAAM,gBAAY;AAAA,IAChB,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO;AAAA,IACtE,CAAC,GAAG;AAAA,EACN;AACA,QAAM,UAAU,OAAO,IAAI,UAAU,KAAK,SAAS,KAAK;AAExD,MAAI,aAAa,IAAI,WAAW,EAAG,QAAO,4CAAC,sBAAmB;AAE9D,MAAI,IAAI,WAAW,GAAG;AACpB,WACE,6CAAC,SAAI,WAAU,sDACb;AAAA,kDAAC,6BAAM,WAAU,sCAAqC;AAAA,MACtD,4CAAC,OAAE,WAAU,6CAA4C,4BAAc;AAAA,MACvE,4CAAC,OAAE,WAAU,6CAA4C,mFAEzD;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,6CAAC,SAAI,WAAU,aACZ;AAAA,WAAO,IAAI,CAAC,UACX,6CAAC,aACC;AAAA,kDAAC,QAAG,WAAU,uCAAuC,gBAAM,OAAM;AAAA,MACjE,4CAAC,QAAG,WAAU,eACX,gBAAM,OAAO,IAAI,CAAC,OAAO,MACxB;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA;AAAA;AAAA,QAFK,GAAG,MAAM,UAAU,MAAM,SAAS,IAAI,MAAM,IAAI,IAAI,CAAC;AAAA,MAG5D,CACD,GACH;AAAA,SAVY,MAAM,KAWpB,CACD;AAAA,IACD,4CAAC,8CAAiB,SAAkB,WAAsB,YAAY,MAAM,QAAQ,CAAC,MAAM,IAAI,CAAC,GAAG;AAAA,KACrG;AAEJ;","names":["Link","Image"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/collection-provenance-tab.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useMemo } from \"react\";\nimport type { ApiActivity } from \"@medialane/sdk\";\nimport { assetHref, profileHref } from \"@medialane/sdk\";\nimport { ExternalLink, Inbox } from \"lucide-react\";\nimport Image from \"./image.js\";\nimport Link from \"./link.js\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { useActivities } from \"../utils/use-activities.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\nimport { ACTIVITY_TYPE_CONFIG } from \"../data/activity.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { cn } from \"../utils/cn.js\";\n\nconst PAGE_SIZE = 30;\n\nconst EVENT_TITLE: Record<string, string> = {\n mint: \"Minted\",\n listing: \"Listed for sale\",\n sale: \"Purchased\",\n offer: \"Offer made\",\n transfer: \"Transferred\",\n cancelled: \"Listing cancelled\",\n};\n\nfunction dayLabel(iso: string): string {\n const date = new Date(iso);\n const today = new Date();\n const yesterday = new Date();\n yesterday.setDate(today.getDate() - 1);\n if (date.toDateString() === today.toDateString()) return \"Today\";\n if (date.toDateString() === yesterday.toDateString()) return \"Yesterday\";\n return date.toLocaleDateString(undefined, { day: \"numeric\", month: \"long\", year: \"numeric\" });\n}\n\nfunction groupByDay(events: ApiActivity[]) {\n const groups: { label: string; events: ApiActivity[] }[] = [];\n for (const event of events) {\n const label = dayLabel(event.timestamp);\n const last = groups[groups.length - 1];\n if (last && last.label === label) last.events.push(event);\n else groups.push({ label, events: [event] });\n }\n return groups;\n}\n\nfunction ProvenanceEvent({ event, showAsset }: { event: ApiActivity; showAsset: boolean }) {\n const resolveImage = useImageUrl();\n const config = ACTIVITY_TYPE_CONFIG[event.type];\n const Icon = config?.icon ?? ExternalLink;\n const contract = event.nftContract ?? event.contractAddress ?? null;\n const tokenId = event.nftTokenId ?? event.tokenId ?? null;\n const actor =\n event.offerer ?? event.fulfiller ?? (event.type === \"mint\" ? event.to : event.from) ?? null;\n const amount = event.amount && Number(event.amount) > 1 ? event.amount : null;\n const name = event.token?.name ?? (tokenId ? `#${tokenId}` : null);\n const image = resolveImage(event.token?.image ?? null);\n const leadWithAsset = showAsset && !!name;\n const assetLink = contract && tokenId ? assetHref(event.chain ?? \"STARKNET\", contract, tokenId) : null;\n\n const actorLink = actor ? (\n <span className=\"text-sm font-normal text-muted-foreground\">\n by{\" \"}\n <Link\n href={profileHref({ address: actor })}\n className=\"font-medium text-foreground/80 hover:text-primary transition-colors\"\n >\n <AddressDisplay address={actor} chars={6} showCopy={false} className=\"text-sm\" />\n </Link>\n </span>\n ) : null;\n\n const tile = (\n <span\n className={cn(\n \"flex h-11 w-11 shrink-0 items-center justify-center rounded-xl\",\n config?.bgClass ?? \"bg-muted\"\n )}\n aria-hidden\n >\n <Icon className={cn(\"h-5 w-5\", config?.colorClass ?? \"text-muted-foreground\")} />\n </span>\n );\n\n const thumb = (\n <span className=\"relative h-14 w-14 shrink-0\">\n <span className=\"block h-full w-full overflow-hidden rounded-xl bg-gradient-to-br from-brand-blue/25 via-brand-purple/25 to-brand-rose/25\">\n {image ? (\n <Image src={image} alt=\"\" width={56} height={56} className=\"h-full w-full object-cover\" unoptimized />\n ) : null}\n </span>\n <span\n className={cn(\n \"absolute -bottom-1 -right-1 flex h-6 w-6 items-center justify-center rounded-full bg-card ring-2 ring-card\"\n )}\n aria-hidden\n >\n <span className={cn(\"flex h-full w-full items-center justify-center rounded-full\", config?.bgClass ?? \"bg-muted\")}>\n <Icon className={cn(\"h-3 w-3\", config?.colorClass ?? \"text-muted-foreground\")} />\n </span>\n </span>\n </span>\n );\n\n return (\n <li className=\"flex items-center gap-4 rounded-2xl border border-border/50 bg-card/60 p-4 backdrop-blur-sm transition-colors hover:bg-card/90\">\n {leadWithAsset ? (assetLink ? <Link href={assetLink} className=\"shrink-0\">{thumb}</Link> : thumb) : tile}\n\n <div className=\"min-w-0 flex-1\">\n {leadWithAsset ? (\n <>\n {assetLink ? (\n <Link href={assetLink} className=\"block truncate text-base font-semibold leading-tight hover:text-primary transition-colors\">\n {name}\n </Link>\n ) : (\n <p className=\"truncate text-base font-semibold leading-tight\">{name}</p>\n )}\n <p className=\"mt-1 flex flex-wrap items-baseline gap-x-1.5 text-sm\">\n <span className={cn(\"font-medium\", config?.colorClass)}>{EVENT_TITLE[event.type] ?? event.type}</span>\n {amount ? <span className=\"text-muted-foreground\">×{amount}</span> : null}\n {actorLink}\n </p>\n </>\n ) : (\n <p className=\"flex flex-wrap items-baseline gap-x-1.5 text-base font-semibold leading-tight\">\n {EVENT_TITLE[event.type] ?? event.type}\n {amount ? <span className=\"text-sm font-medium text-muted-foreground\">×{amount}</span> : null}\n {actorLink}\n </p>\n )}\n </div>\n\n <div className=\"flex shrink-0 flex-col items-end gap-1\">\n {event.price?.formatted ? (\n <span className=\"flex items-center gap-1.5 text-base font-bold tabular-nums\">\n {event.price.currency ? <CurrencyIcon symbol={event.price.currency} size={15} aria-hidden /> : null}\n {formatDisplayPrice(event.price.formatted)}\n {event.price.currency ? (\n <span className=\"text-xs font-medium text-muted-foreground\">{event.price.currency}</span>\n ) : null}\n </span>\n ) : null}\n <span className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n <time dateTime={event.timestamp} title={new Date(event.timestamp).toLocaleString()}>\n {timeAgo(event.timestamp)}\n </time>\n {event.txHash ? (\n <a\n href={`${EXPLORER_URL}/tx/${event.txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"rounded-md p-1 hover:bg-muted hover:text-foreground transition-colors\"\n aria-label=\"View transaction\"\n >\n <ExternalLink className=\"h-3.5 w-3.5\" aria-hidden />\n </a>\n ) : null}\n </span>\n </div>\n </li>\n );\n}\n\nfunction ProvenanceSkeleton() {\n return (\n <div className=\"grid gap-2.5 lg:grid-cols-2\" aria-hidden>\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-4 rounded-2xl border border-border/50 bg-card/60 p-4\">\n <div className=\"h-11 w-11 shrink-0 rounded-xl bg-muted animate-pulse\" />\n <div className=\"flex-1 space-y-2\">\n <div className=\"h-4 w-44 rounded bg-muted animate-pulse\" />\n <div className=\"h-3 w-24 rounded bg-muted animate-pulse\" />\n </div>\n <div className=\"h-4 w-16 rounded bg-muted animate-pulse\" />\n </div>\n ))}\n </div>\n );\n}\n\nexport interface CollectionProvenanceTabProps {\n contract: string;\n}\n\nexport function CollectionProvenanceTab({ contract }: CollectionProvenanceTabProps) {\n const [page, setPage] = useState(1);\n const [all, setAll] = useState<ApiActivity[]>([]);\n const { activities, meta, isLoading } = useActivities({ contract, page, limit: PAGE_SIZE });\n\n useEffect(() => {\n if (activities.length === 0) return;\n setAll((prev) => (page === 1 ? activities : [...prev, ...activities]));\n }, [activities, page]);\n\n const groups = useMemo(() => groupByDay(all), [all]);\n const showAsset = useMemo(\n () => new Set(all.map((e) => e.nftTokenId ?? e.tokenId ?? \"\")).size > 1,\n [all]\n );\n const hasMore = meta ? all.length < (meta.total ?? 0) : false;\n\n if (isLoading && all.length === 0) return <ProvenanceSkeleton />;\n\n if (all.length === 0) {\n return (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <Inbox className=\"h-10 w-10 text-muted-foreground/40\" />\n <p className=\"text-sm font-medium text-muted-foreground\">No history yet</p>\n <p className=\"text-xs text-muted-foreground/70 max-w-xs\">\n Mints, transfers, listings and sales will appear here as they happen.\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-8\">\n {groups.map((group) => (\n <section key={group.label}>\n <h3 className=\"mb-3 font-display text-lg font-bold\">{group.label}</h3>\n <ol className=\"grid gap-2.5 lg:grid-cols-2\">\n {group.events.map((event, i) => (\n <ProvenanceEvent\n key={`${event.txHash ?? event.orderHash}-${event.type}-${i}`}\n event={event}\n showAsset={showAsset}\n />\n ))}\n </ol>\n </section>\n ))}\n <LoadMoreSentinel hasMore={hasMore} isLoading={isLoading} onLoadMore={() => setPage((p) => p + 1)} />\n </div>\n );\n}\n"],"mappings":"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","names":["Link","Image"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useEffect, useMemo } from "react";
|
|
4
4
|
import { assetHref, profileHref } from "@medialane/sdk";
|
|
5
5
|
import { ExternalLink, Inbox } from "lucide-react";
|
|
@@ -53,50 +53,64 @@ function ProvenanceEvent({ event, showAsset }) {
|
|
|
53
53
|
const amount = event.amount && Number(event.amount) > 1 ? event.amount : null;
|
|
54
54
|
const name = event.token?.name ?? (tokenId ? `#${tokenId}` : null);
|
|
55
55
|
const image = resolveImage(event.token?.image ?? null);
|
|
56
|
-
|
|
56
|
+
const leadWithAsset = showAsset && !!name;
|
|
57
|
+
const assetLink = contract && tokenId ? assetHref(event.chain ?? "STARKNET", contract, tokenId) : null;
|
|
58
|
+
const actorLink = actor ? /* @__PURE__ */ jsxs("span", { className: "text-sm font-normal text-muted-foreground", children: [
|
|
59
|
+
"by",
|
|
60
|
+
" ",
|
|
61
|
+
/* @__PURE__ */ jsx(
|
|
62
|
+
Link,
|
|
63
|
+
{
|
|
64
|
+
href: profileHref({ address: actor }),
|
|
65
|
+
className: "font-medium text-foreground/80 hover:text-primary transition-colors",
|
|
66
|
+
children: /* @__PURE__ */ jsx(AddressDisplay, { address: actor, chars: 6, showCopy: false, className: "text-sm" })
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
] }) : null;
|
|
70
|
+
const tile = /* @__PURE__ */ jsx(
|
|
71
|
+
"span",
|
|
72
|
+
{
|
|
73
|
+
className: cn(
|
|
74
|
+
"flex h-11 w-11 shrink-0 items-center justify-center rounded-xl",
|
|
75
|
+
config?.bgClass ?? "bg-muted"
|
|
76
|
+
),
|
|
77
|
+
"aria-hidden": true,
|
|
78
|
+
children: /* @__PURE__ */ jsx(Icon, { className: cn("h-5 w-5", config?.colorClass ?? "text-muted-foreground") })
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
const thumb = /* @__PURE__ */ jsxs("span", { className: "relative h-14 w-14 shrink-0", children: [
|
|
82
|
+
/* @__PURE__ */ jsx("span", { className: "block h-full w-full overflow-hidden rounded-xl bg-gradient-to-br from-brand-blue/25 via-brand-purple/25 to-brand-rose/25", children: image ? /* @__PURE__ */ jsx(Image, { src: image, alt: "", width: 56, height: 56, className: "h-full w-full object-cover", unoptimized: true }) : null }),
|
|
57
83
|
/* @__PURE__ */ jsx(
|
|
58
84
|
"span",
|
|
59
85
|
{
|
|
60
86
|
className: cn(
|
|
61
|
-
"flex h-
|
|
62
|
-
config?.bgClass ?? "bg-muted"
|
|
87
|
+
"absolute -bottom-1 -right-1 flex h-6 w-6 items-center justify-center rounded-full bg-card ring-2 ring-card"
|
|
63
88
|
),
|
|
64
89
|
"aria-hidden": true,
|
|
65
|
-
children: /* @__PURE__ */ jsx(Icon, { className: cn("h-
|
|
90
|
+
children: /* @__PURE__ */ jsx("span", { className: cn("flex h-full w-full items-center justify-center rounded-full", config?.bgClass ?? "bg-muted"), children: /* @__PURE__ */ jsx(Icon, { className: cn("h-3 w-3", config?.colorClass ?? "text-muted-foreground") }) })
|
|
66
91
|
}
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
92
|
+
)
|
|
93
|
+
] });
|
|
94
|
+
return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-4 rounded-2xl border border-border/50 bg-card/60 p-4 backdrop-blur-sm transition-colors hover:bg-card/90", children: [
|
|
95
|
+
leadWithAsset ? assetLink ? /* @__PURE__ */ jsx(Link, { href: assetLink, className: "shrink-0", children: thumb }) : thumb : tile,
|
|
96
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: leadWithAsset ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
97
|
+
assetLink ? /* @__PURE__ */ jsx(Link, { href: assetLink, className: "block truncate text-base font-semibold leading-tight hover:text-primary transition-colors", children: name }) : /* @__PURE__ */ jsx("p", { className: "truncate text-base font-semibold leading-tight", children: name }),
|
|
98
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-1 flex flex-wrap items-baseline gap-x-1.5 text-sm", children: [
|
|
99
|
+
/* @__PURE__ */ jsx("span", { className: cn("font-medium", config?.colorClass), children: EVENT_TITLE[event.type] ?? event.type }),
|
|
100
|
+
amount ? /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
72
101
|
"\xD7",
|
|
73
102
|
amount
|
|
74
103
|
] }) : null,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
)
|
|
86
|
-
] }) : null
|
|
87
|
-
] }),
|
|
88
|
-
showAsset && name ? /* @__PURE__ */ jsxs(
|
|
89
|
-
Link,
|
|
90
|
-
{
|
|
91
|
-
href: contract && tokenId ? assetHref(event.chain ?? "STARKNET", contract, tokenId) : "#",
|
|
92
|
-
className: "mt-2 inline-flex max-w-full items-center gap-2 rounded-full bg-muted/70 py-1 pl-1 pr-3 hover:bg-muted transition-colors",
|
|
93
|
-
children: [
|
|
94
|
-
/* @__PURE__ */ jsx("span", { className: "relative h-6 w-6 shrink-0 overflow-hidden rounded-full bg-muted", children: image ? /* @__PURE__ */ jsx(Image, { src: image, alt: "", width: 24, height: 24, className: "h-full w-full object-cover", unoptimized: true }) : null }),
|
|
95
|
-
/* @__PURE__ */ jsx("span", { className: "truncate text-xs font-medium", children: name })
|
|
96
|
-
]
|
|
97
|
-
}
|
|
98
|
-
) : null
|
|
99
|
-
] }),
|
|
104
|
+
actorLink
|
|
105
|
+
] })
|
|
106
|
+
] }) : /* @__PURE__ */ jsxs("p", { className: "flex flex-wrap items-baseline gap-x-1.5 text-base font-semibold leading-tight", children: [
|
|
107
|
+
EVENT_TITLE[event.type] ?? event.type,
|
|
108
|
+
amount ? /* @__PURE__ */ jsxs("span", { className: "text-sm font-medium text-muted-foreground", children: [
|
|
109
|
+
"\xD7",
|
|
110
|
+
amount
|
|
111
|
+
] }) : null,
|
|
112
|
+
actorLink
|
|
113
|
+
] }) }),
|
|
100
114
|
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col items-end gap-1", children: [
|
|
101
115
|
event.price?.formatted ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-base font-bold tabular-nums", children: [
|
|
102
116
|
event.price.currency ? /* @__PURE__ */ jsx(CurrencyIcon, { symbol: event.price.currency, size: 15, "aria-hidden": true }) : null,
|
|
@@ -121,7 +135,7 @@ function ProvenanceEvent({ event, showAsset }) {
|
|
|
121
135
|
] });
|
|
122
136
|
}
|
|
123
137
|
function ProvenanceSkeleton() {
|
|
124
|
-
return /* @__PURE__ */ jsx("div", { className: "
|
|
138
|
+
return /* @__PURE__ */ jsx("div", { className: "grid gap-2.5 lg:grid-cols-2", "aria-hidden": true, children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 rounded-2xl border border-border/50 bg-card/60 p-4", children: [
|
|
125
139
|
/* @__PURE__ */ jsx("div", { className: "h-11 w-11 shrink-0 rounded-xl bg-muted animate-pulse" }),
|
|
126
140
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2", children: [
|
|
127
141
|
/* @__PURE__ */ jsx("div", { className: "h-4 w-44 rounded bg-muted animate-pulse" }),
|
|
@@ -155,7 +169,7 @@ function CollectionProvenanceTab({ contract }) {
|
|
|
155
169
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-8", children: [
|
|
156
170
|
groups.map((group) => /* @__PURE__ */ jsxs("section", { children: [
|
|
157
171
|
/* @__PURE__ */ jsx("h3", { className: "mb-3 font-display text-lg font-bold", children: group.label }),
|
|
158
|
-
/* @__PURE__ */ jsx("ol", { className: "
|
|
172
|
+
/* @__PURE__ */ jsx("ol", { className: "grid gap-2.5 lg:grid-cols-2", children: group.events.map((event, i) => /* @__PURE__ */ jsx(
|
|
159
173
|
ProvenanceEvent,
|
|
160
174
|
{
|
|
161
175
|
event,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/collection-provenance-tab.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useMemo } from \"react\";\nimport type { ApiActivity } from \"@medialane/sdk\";\nimport { assetHref, profileHref } from \"@medialane/sdk\";\nimport { ExternalLink, Inbox } from \"lucide-react\";\nimport Image from \"./image.js\";\nimport Link from \"./link.js\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { useActivities } from \"../utils/use-activities.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\nimport { ACTIVITY_TYPE_CONFIG } from \"../data/activity.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { cn } from \"../utils/cn.js\";\n\nconst PAGE_SIZE = 30;\n\nconst EVENT_TITLE: Record<string, string> = {\n mint: \"Minted\",\n listing: \"Listed for sale\",\n sale: \"Purchased\",\n offer: \"Offer made\",\n transfer: \"Transferred\",\n cancelled: \"Listing cancelled\",\n};\n\nfunction dayLabel(iso: string): string {\n const date = new Date(iso);\n const today = new Date();\n const yesterday = new Date();\n yesterday.setDate(today.getDate() - 1);\n if (date.toDateString() === today.toDateString()) return \"Today\";\n if (date.toDateString() === yesterday.toDateString()) return \"Yesterday\";\n return date.toLocaleDateString(undefined, { day: \"numeric\", month: \"long\", year: \"numeric\" });\n}\n\nfunction groupByDay(events: ApiActivity[]) {\n const groups: { label: string; events: ApiActivity[] }[] = [];\n for (const event of events) {\n const label = dayLabel(event.timestamp);\n const last = groups[groups.length - 1];\n if (last && last.label === label) last.events.push(event);\n else groups.push({ label, events: [event] });\n }\n return groups;\n}\n\nfunction ProvenanceEvent({ event, showAsset }: { event: ApiActivity; showAsset: boolean }) {\n const resolveImage = useImageUrl();\n const config = ACTIVITY_TYPE_CONFIG[event.type];\n const Icon = config?.icon ?? ExternalLink;\n const contract = event.nftContract ?? event.contractAddress ?? null;\n const tokenId = event.nftTokenId ?? event.tokenId ?? null;\n const actor =\n event.offerer ?? event.fulfiller ?? (event.type === \"mint\" ? event.to : event.from) ?? null;\n const amount = event.amount && Number(event.amount) > 1 ? event.amount : null;\n const name = event.token?.name ?? (tokenId ? `#${tokenId}` : null);\n const image = resolveImage(event.token?.image ?? null);\n\n return (\n <li className=\"flex items-center gap-4 rounded-2xl border border-border/50 bg-card/60 p-4 backdrop-blur-sm transition-colors hover:bg-card/90\">\n <span\n className={cn(\n \"flex h-11 w-11 shrink-0 items-center justify-center rounded-xl\",\n config?.bgClass ?? \"bg-muted\"\n )}\n aria-hidden\n >\n <Icon className={cn(\"h-5 w-5\", config?.colorClass ?? \"text-muted-foreground\")} />\n </span>\n\n <div className=\"min-w-0 flex-1\">\n <p className=\"flex flex-wrap items-baseline gap-x-1.5 text-base font-semibold leading-tight\">\n {EVENT_TITLE[event.type] ?? event.type}\n {amount ? <span className=\"text-sm font-medium text-muted-foreground\">×{amount}</span> : null}\n {actor ? (\n <span className=\"text-sm font-normal text-muted-foreground\">\n by{\" \"}\n <Link\n href={profileHref({ address: actor })}\n className=\"font-medium text-foreground/80 hover:text-primary transition-colors\"\n >\n <AddressDisplay address={actor} chars={6} showCopy={false} className=\"text-sm\" />\n </Link>\n </span>\n ) : null}\n </p>\n\n {showAsset && name ? (\n <Link\n href={contract && tokenId ? assetHref(event.chain ?? \"STARKNET\", contract, tokenId) : \"#\"}\n className=\"mt-2 inline-flex max-w-full items-center gap-2 rounded-full bg-muted/70 py-1 pl-1 pr-3 hover:bg-muted transition-colors\"\n >\n <span className=\"relative h-6 w-6 shrink-0 overflow-hidden rounded-full bg-muted\">\n {image ? (\n <Image src={image} alt=\"\" width={24} height={24} className=\"h-full w-full object-cover\" unoptimized />\n ) : null}\n </span>\n <span className=\"truncate text-xs font-medium\">{name}</span>\n </Link>\n ) : null}\n </div>\n\n <div className=\"flex shrink-0 flex-col items-end gap-1\">\n {event.price?.formatted ? (\n <span className=\"flex items-center gap-1.5 text-base font-bold tabular-nums\">\n {event.price.currency ? <CurrencyIcon symbol={event.price.currency} size={15} aria-hidden /> : null}\n {formatDisplayPrice(event.price.formatted)}\n {event.price.currency ? (\n <span className=\"text-xs font-medium text-muted-foreground\">{event.price.currency}</span>\n ) : null}\n </span>\n ) : null}\n <span className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n <time dateTime={event.timestamp} title={new Date(event.timestamp).toLocaleString()}>\n {timeAgo(event.timestamp)}\n </time>\n {event.txHash ? (\n <a\n href={`${EXPLORER_URL}/tx/${event.txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"rounded-md p-1 hover:bg-muted hover:text-foreground transition-colors\"\n aria-label=\"View transaction\"\n >\n <ExternalLink className=\"h-3.5 w-3.5\" aria-hidden />\n </a>\n ) : null}\n </span>\n </div>\n </li>\n );\n}\n\nfunction ProvenanceSkeleton() {\n return (\n <div className=\"space-y-2.5\" aria-hidden>\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-4 rounded-2xl border border-border/50 bg-card/60 p-4\">\n <div className=\"h-11 w-11 shrink-0 rounded-xl bg-muted animate-pulse\" />\n <div className=\"flex-1 space-y-2\">\n <div className=\"h-4 w-44 rounded bg-muted animate-pulse\" />\n <div className=\"h-3 w-24 rounded bg-muted animate-pulse\" />\n </div>\n <div className=\"h-4 w-16 rounded bg-muted animate-pulse\" />\n </div>\n ))}\n </div>\n );\n}\n\nexport interface CollectionProvenanceTabProps {\n contract: string;\n}\n\nexport function CollectionProvenanceTab({ contract }: CollectionProvenanceTabProps) {\n const [page, setPage] = useState(1);\n const [all, setAll] = useState<ApiActivity[]>([]);\n const { activities, meta, isLoading } = useActivities({ contract, page, limit: PAGE_SIZE });\n\n useEffect(() => {\n if (activities.length === 0) return;\n setAll((prev) => (page === 1 ? activities : [...prev, ...activities]));\n }, [activities, page]);\n\n const groups = useMemo(() => groupByDay(all), [all]);\n const showAsset = useMemo(\n () => new Set(all.map((e) => e.nftTokenId ?? e.tokenId ?? \"\")).size > 1,\n [all]\n );\n const hasMore = meta ? all.length < (meta.total ?? 0) : false;\n\n if (isLoading && all.length === 0) return <ProvenanceSkeleton />;\n\n if (all.length === 0) {\n return (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <Inbox className=\"h-10 w-10 text-muted-foreground/40\" />\n <p className=\"text-sm font-medium text-muted-foreground\">No history yet</p>\n <p className=\"text-xs text-muted-foreground/70 max-w-xs\">\n Mints, transfers, listings and sales will appear here as they happen.\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-8\">\n {groups.map((group) => (\n <section key={group.label}>\n <h3 className=\"mb-3 font-display text-lg font-bold\">{group.label}</h3>\n <ol className=\"space-y-2.5\">\n {group.events.map((event, i) => (\n <ProvenanceEvent\n key={`${event.txHash ?? event.orderHash}-${event.type}-${i}`}\n event={event}\n showAsset={showAsset}\n />\n ))}\n </ol>\n </section>\n ))}\n <LoadMoreSentinel hasMore={hasMore} isLoading={isLoading} onLoadMore={() => setPage((p) => p + 1)} />\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/collection-provenance-tab.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useMemo } from \"react\";\nimport type { ApiActivity } from \"@medialane/sdk\";\nimport { assetHref, profileHref } from \"@medialane/sdk\";\nimport { ExternalLink, Inbox } from \"lucide-react\";\nimport Image from \"./image.js\";\nimport Link from \"./link.js\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { useActivities } from \"../utils/use-activities.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\nimport { ACTIVITY_TYPE_CONFIG } from \"../data/activity.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { cn } from \"../utils/cn.js\";\n\nconst PAGE_SIZE = 30;\n\nconst EVENT_TITLE: Record<string, string> = {\n mint: \"Minted\",\n listing: \"Listed for sale\",\n sale: \"Purchased\",\n offer: \"Offer made\",\n transfer: \"Transferred\",\n cancelled: \"Listing cancelled\",\n};\n\nfunction dayLabel(iso: string): string {\n const date = new Date(iso);\n const today = new Date();\n const yesterday = new Date();\n yesterday.setDate(today.getDate() - 1);\n if (date.toDateString() === today.toDateString()) return \"Today\";\n if (date.toDateString() === yesterday.toDateString()) return \"Yesterday\";\n return date.toLocaleDateString(undefined, { day: \"numeric\", month: \"long\", year: \"numeric\" });\n}\n\nfunction groupByDay(events: ApiActivity[]) {\n const groups: { label: string; events: ApiActivity[] }[] = [];\n for (const event of events) {\n const label = dayLabel(event.timestamp);\n const last = groups[groups.length - 1];\n if (last && last.label === label) last.events.push(event);\n else groups.push({ label, events: [event] });\n }\n return groups;\n}\n\nfunction ProvenanceEvent({ event, showAsset }: { event: ApiActivity; showAsset: boolean }) {\n const resolveImage = useImageUrl();\n const config = ACTIVITY_TYPE_CONFIG[event.type];\n const Icon = config?.icon ?? ExternalLink;\n const contract = event.nftContract ?? event.contractAddress ?? null;\n const tokenId = event.nftTokenId ?? event.tokenId ?? null;\n const actor =\n event.offerer ?? event.fulfiller ?? (event.type === \"mint\" ? event.to : event.from) ?? null;\n const amount = event.amount && Number(event.amount) > 1 ? event.amount : null;\n const name = event.token?.name ?? (tokenId ? `#${tokenId}` : null);\n const image = resolveImage(event.token?.image ?? null);\n const leadWithAsset = showAsset && !!name;\n const assetLink = contract && tokenId ? assetHref(event.chain ?? \"STARKNET\", contract, tokenId) : null;\n\n const actorLink = actor ? (\n <span className=\"text-sm font-normal text-muted-foreground\">\n by{\" \"}\n <Link\n href={profileHref({ address: actor })}\n className=\"font-medium text-foreground/80 hover:text-primary transition-colors\"\n >\n <AddressDisplay address={actor} chars={6} showCopy={false} className=\"text-sm\" />\n </Link>\n </span>\n ) : null;\n\n const tile = (\n <span\n className={cn(\n \"flex h-11 w-11 shrink-0 items-center justify-center rounded-xl\",\n config?.bgClass ?? \"bg-muted\"\n )}\n aria-hidden\n >\n <Icon className={cn(\"h-5 w-5\", config?.colorClass ?? \"text-muted-foreground\")} />\n </span>\n );\n\n const thumb = (\n <span className=\"relative h-14 w-14 shrink-0\">\n <span className=\"block h-full w-full overflow-hidden rounded-xl bg-gradient-to-br from-brand-blue/25 via-brand-purple/25 to-brand-rose/25\">\n {image ? (\n <Image src={image} alt=\"\" width={56} height={56} className=\"h-full w-full object-cover\" unoptimized />\n ) : null}\n </span>\n <span\n className={cn(\n \"absolute -bottom-1 -right-1 flex h-6 w-6 items-center justify-center rounded-full bg-card ring-2 ring-card\"\n )}\n aria-hidden\n >\n <span className={cn(\"flex h-full w-full items-center justify-center rounded-full\", config?.bgClass ?? \"bg-muted\")}>\n <Icon className={cn(\"h-3 w-3\", config?.colorClass ?? \"text-muted-foreground\")} />\n </span>\n </span>\n </span>\n );\n\n return (\n <li className=\"flex items-center gap-4 rounded-2xl border border-border/50 bg-card/60 p-4 backdrop-blur-sm transition-colors hover:bg-card/90\">\n {leadWithAsset ? (assetLink ? <Link href={assetLink} className=\"shrink-0\">{thumb}</Link> : thumb) : tile}\n\n <div className=\"min-w-0 flex-1\">\n {leadWithAsset ? (\n <>\n {assetLink ? (\n <Link href={assetLink} className=\"block truncate text-base font-semibold leading-tight hover:text-primary transition-colors\">\n {name}\n </Link>\n ) : (\n <p className=\"truncate text-base font-semibold leading-tight\">{name}</p>\n )}\n <p className=\"mt-1 flex flex-wrap items-baseline gap-x-1.5 text-sm\">\n <span className={cn(\"font-medium\", config?.colorClass)}>{EVENT_TITLE[event.type] ?? event.type}</span>\n {amount ? <span className=\"text-muted-foreground\">×{amount}</span> : null}\n {actorLink}\n </p>\n </>\n ) : (\n <p className=\"flex flex-wrap items-baseline gap-x-1.5 text-base font-semibold leading-tight\">\n {EVENT_TITLE[event.type] ?? event.type}\n {amount ? <span className=\"text-sm font-medium text-muted-foreground\">×{amount}</span> : null}\n {actorLink}\n </p>\n )}\n </div>\n\n <div className=\"flex shrink-0 flex-col items-end gap-1\">\n {event.price?.formatted ? (\n <span className=\"flex items-center gap-1.5 text-base font-bold tabular-nums\">\n {event.price.currency ? <CurrencyIcon symbol={event.price.currency} size={15} aria-hidden /> : null}\n {formatDisplayPrice(event.price.formatted)}\n {event.price.currency ? (\n <span className=\"text-xs font-medium text-muted-foreground\">{event.price.currency}</span>\n ) : null}\n </span>\n ) : null}\n <span className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n <time dateTime={event.timestamp} title={new Date(event.timestamp).toLocaleString()}>\n {timeAgo(event.timestamp)}\n </time>\n {event.txHash ? (\n <a\n href={`${EXPLORER_URL}/tx/${event.txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"rounded-md p-1 hover:bg-muted hover:text-foreground transition-colors\"\n aria-label=\"View transaction\"\n >\n <ExternalLink className=\"h-3.5 w-3.5\" aria-hidden />\n </a>\n ) : null}\n </span>\n </div>\n </li>\n );\n}\n\nfunction ProvenanceSkeleton() {\n return (\n <div className=\"grid gap-2.5 lg:grid-cols-2\" aria-hidden>\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-4 rounded-2xl border border-border/50 bg-card/60 p-4\">\n <div className=\"h-11 w-11 shrink-0 rounded-xl bg-muted animate-pulse\" />\n <div className=\"flex-1 space-y-2\">\n <div className=\"h-4 w-44 rounded bg-muted animate-pulse\" />\n <div className=\"h-3 w-24 rounded bg-muted animate-pulse\" />\n </div>\n <div className=\"h-4 w-16 rounded bg-muted animate-pulse\" />\n </div>\n ))}\n </div>\n );\n}\n\nexport interface CollectionProvenanceTabProps {\n contract: string;\n}\n\nexport function CollectionProvenanceTab({ contract }: CollectionProvenanceTabProps) {\n const [page, setPage] = useState(1);\n const [all, setAll] = useState<ApiActivity[]>([]);\n const { activities, meta, isLoading } = useActivities({ contract, page, limit: PAGE_SIZE });\n\n useEffect(() => {\n if (activities.length === 0) return;\n setAll((prev) => (page === 1 ? activities : [...prev, ...activities]));\n }, [activities, page]);\n\n const groups = useMemo(() => groupByDay(all), [all]);\n const showAsset = useMemo(\n () => new Set(all.map((e) => e.nftTokenId ?? e.tokenId ?? \"\")).size > 1,\n [all]\n );\n const hasMore = meta ? all.length < (meta.total ?? 0) : false;\n\n if (isLoading && all.length === 0) return <ProvenanceSkeleton />;\n\n if (all.length === 0) {\n return (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <Inbox className=\"h-10 w-10 text-muted-foreground/40\" />\n <p className=\"text-sm font-medium text-muted-foreground\">No history yet</p>\n <p className=\"text-xs text-muted-foreground/70 max-w-xs\">\n Mints, transfers, listings and sales will appear here as they happen.\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-8\">\n {groups.map((group) => (\n <section key={group.label}>\n <h3 className=\"mb-3 font-display text-lg font-bold\">{group.label}</h3>\n <ol className=\"grid gap-2.5 lg:grid-cols-2\">\n {group.events.map((event, i) => (\n <ProvenanceEvent\n key={`${event.txHash ?? event.orderHash}-${event.type}-${i}`}\n event={event}\n showAsset={showAsset}\n />\n ))}\n </ol>\n </section>\n ))}\n <LoadMoreSentinel hasMore={hasMore} isLoading={isLoading} onLoadMore={() => setPage((p) => p + 1)} />\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
3
|
import { FastMintProps } from './types.cjs';
|
|
4
4
|
import 'starknet';
|
|
5
5
|
import '@medialane/sdk';
|
|
6
6
|
import '@medialane/sdk/starknet';
|
|
7
7
|
|
|
8
|
-
declare function FastMint(props: FastMintProps): string | number | bigint | boolean |
|
|
8
|
+
declare function FastMint(props: FastMintProps): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
9
9
|
|
|
10
10
|
export { FastMint };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
3
|
import { FastMintProps } from './types.js';
|
|
4
4
|
import 'starknet';
|
|
5
5
|
import '@medialane/sdk';
|
|
6
6
|
import '@medialane/sdk/starknet';
|
|
7
7
|
|
|
8
|
-
declare function FastMint(props: FastMintProps): string | number | bigint | boolean |
|
|
8
|
+
declare function FastMint(props: FastMintProps): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
9
9
|
|
|
10
10
|
export { FastMint };
|
package/dist/data/activity.cjs
CHANGED
|
@@ -24,11 +24,11 @@ __export(activity_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(activity_exports);
|
|
25
25
|
var import_lucide_react = require("lucide-react");
|
|
26
26
|
const ACTIVITY_TYPE_CONFIG = {
|
|
27
|
-
mint: { label: "Mint", variant: "default", icon: import_lucide_react.Sparkles, colorClass: "text-brand-purple", bgClass: "bg-brand-purple/
|
|
28
|
-
transfer: { label: "Transfer", variant: "secondary", icon: import_lucide_react.ArrowRightLeft, colorClass: "text-brand-blue", bgClass: "bg-brand-blue/
|
|
29
|
-
listing: { label: "Listed", variant: "default", icon: import_lucide_react.Tag, colorClass: "text-brand-orange", bgClass: "bg-brand-orange/
|
|
30
|
-
sale: { label: "Sale", variant: "default", icon: import_lucide_react.ShoppingCart, colorClass: "text-brand-rose", bgClass: "bg-brand-rose/
|
|
31
|
-
offer: { label: "Offer", variant: "outline", icon: import_lucide_react.HandCoins, colorClass: "text-brand-maeve", bgClass: "bg-brand-maeve/
|
|
27
|
+
mint: { label: "Mint", variant: "default", icon: import_lucide_react.Sparkles, colorClass: "text-brand-purple", bgClass: "bg-brand-purple/15 dark:bg-brand-purple/25" },
|
|
28
|
+
transfer: { label: "Transfer", variant: "secondary", icon: import_lucide_react.ArrowRightLeft, colorClass: "text-brand-blue", bgClass: "bg-brand-blue/15 dark:bg-brand-blue/25" },
|
|
29
|
+
listing: { label: "Listed", variant: "default", icon: import_lucide_react.Tag, colorClass: "text-brand-orange", bgClass: "bg-brand-orange/15 dark:bg-brand-orange/25" },
|
|
30
|
+
sale: { label: "Sale", variant: "default", icon: import_lucide_react.ShoppingCart, colorClass: "text-brand-rose", bgClass: "bg-brand-rose/15 dark:bg-brand-rose/25" },
|
|
31
|
+
offer: { label: "Offer", variant: "outline", icon: import_lucide_react.HandCoins, colorClass: "text-brand-maeve", bgClass: "bg-brand-maeve/15 dark:bg-brand-maeve/25" },
|
|
32
32
|
cancelled: { label: "Cancelled", variant: "outline", icon: import_lucide_react.X, colorClass: "text-muted-foreground", bgClass: "bg-muted" }
|
|
33
33
|
};
|
|
34
34
|
const TYPE_FILTERS = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/data/activity.ts"],"sourcesContent":["import { ArrowRightLeft, Tag, ShoppingCart, HandCoins, X, Sparkles } from \"lucide-react\";\nimport type { ElementType } from \"react\";\n\nexport interface ActivityTypeConfig {\n label: string;\n variant: \"default\" | \"secondary\" | \"outline\";\n icon: ElementType;\n colorClass: string;\n bgClass: string;\n}\n\nexport const ACTIVITY_TYPE_CONFIG: Record<string, ActivityTypeConfig> = {\n mint: { label: \"Mint\", variant: \"default\", icon: Sparkles, colorClass: \"text-brand-purple\", bgClass: \"bg-brand-purple/
|
|
1
|
+
{"version":3,"sources":["../../src/data/activity.ts"],"sourcesContent":["import { ArrowRightLeft, Tag, ShoppingCart, HandCoins, X, Sparkles } from \"lucide-react\";\nimport type { ElementType } from \"react\";\n\nexport interface ActivityTypeConfig {\n label: string;\n variant: \"default\" | \"secondary\" | \"outline\";\n icon: ElementType;\n colorClass: string;\n bgClass: string;\n}\n\nexport const ACTIVITY_TYPE_CONFIG: Record<string, ActivityTypeConfig> = {\n mint: { label: \"Mint\", variant: \"default\", icon: Sparkles, colorClass: \"text-brand-purple\", bgClass: \"bg-brand-purple/15 dark:bg-brand-purple/25\" },\n transfer: { label: \"Transfer\", variant: \"secondary\", icon: ArrowRightLeft, colorClass: \"text-brand-blue\", bgClass: \"bg-brand-blue/15 dark:bg-brand-blue/25\" },\n listing: { label: \"Listed\", variant: \"default\", icon: Tag, colorClass: \"text-brand-orange\", bgClass: \"bg-brand-orange/15 dark:bg-brand-orange/25\" },\n sale: { label: \"Sale\", variant: \"default\", icon: ShoppingCart, colorClass: \"text-brand-rose\", bgClass: \"bg-brand-rose/15 dark:bg-brand-rose/25\" },\n offer: { label: \"Offer\", variant: \"outline\", icon: HandCoins, colorClass: \"text-brand-maeve\", bgClass: \"bg-brand-maeve/15 dark:bg-brand-maeve/25\" },\n cancelled: { label: \"Cancelled\", variant: \"outline\", icon: X, colorClass: \"text-muted-foreground\", bgClass: \"bg-muted\" },\n};\n\nexport const TYPE_FILTERS = [\n { label: \"All\", value: \"\" },\n { label: \"Mints\", value: \"mint\" },\n { label: \"Sales\", value: \"sale\" },\n { label: \"Listings\", value: \"listing\" },\n { label: \"Offers\", value: \"offer\" },\n { label: \"Transfers\", value: \"transfer\" },\n { label: \"Cancelled\", value: \"cancelled\" },\n];\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAA0E;AAWnE,MAAM,uBAA2D;AAAA,EACtE,MAAW,EAAE,OAAO,QAAa,SAAS,WAAa,MAAM,8BAAgB,YAAY,qBAAqB,SAAS,6CAA6C;AAAA,EACpK,UAAW,EAAE,OAAO,YAAa,SAAS,aAAa,MAAM,oCAAgB,YAAY,mBAAqB,SAAS,yCAAyC;AAAA,EAChK,SAAW,EAAE,OAAO,UAAa,SAAS,WAAa,MAAM,yBAAgB,YAAY,qBAAqB,SAAS,6CAA6C;AAAA,EACpK,MAAW,EAAE,OAAO,QAAa,SAAS,WAAa,MAAM,kCAAgB,YAAY,mBAAqB,SAAS,yCAAyC;AAAA,EAChK,OAAW,EAAE,OAAO,SAAa,SAAS,WAAa,MAAM,+BAAgB,YAAY,oBAAqB,SAAS,2CAA2C;AAAA,EAClK,WAAW,EAAE,OAAO,aAAa,SAAS,WAAa,MAAM,uBAAgB,YAAY,yBAAyB,SAAS,WAAW;AACxI;AAEO,MAAM,eAAe;AAAA,EAC1B,EAAE,OAAO,OAAa,OAAO,GAAG;AAAA,EAChC,EAAE,OAAO,SAAa,OAAO,OAAO;AAAA,EACpC,EAAE,OAAO,SAAa,OAAO,OAAO;AAAA,EACpC,EAAE,OAAO,YAAa,OAAO,UAAU;AAAA,EACvC,EAAE,OAAO,UAAa,OAAO,QAAQ;AAAA,EACrC,EAAE,OAAO,aAAa,OAAO,WAAW;AAAA,EACxC,EAAE,OAAO,aAAa,OAAO,YAAY;AAC3C;","names":[]}
|
package/dist/data/activity.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ArrowRightLeft, Tag, ShoppingCart, HandCoins, X, Sparkles } from "lucide-react";
|
|
2
2
|
const ACTIVITY_TYPE_CONFIG = {
|
|
3
|
-
mint: { label: "Mint", variant: "default", icon: Sparkles, colorClass: "text-brand-purple", bgClass: "bg-brand-purple/
|
|
4
|
-
transfer: { label: "Transfer", variant: "secondary", icon: ArrowRightLeft, colorClass: "text-brand-blue", bgClass: "bg-brand-blue/
|
|
5
|
-
listing: { label: "Listed", variant: "default", icon: Tag, colorClass: "text-brand-orange", bgClass: "bg-brand-orange/
|
|
6
|
-
sale: { label: "Sale", variant: "default", icon: ShoppingCart, colorClass: "text-brand-rose", bgClass: "bg-brand-rose/
|
|
7
|
-
offer: { label: "Offer", variant: "outline", icon: HandCoins, colorClass: "text-brand-maeve", bgClass: "bg-brand-maeve/
|
|
3
|
+
mint: { label: "Mint", variant: "default", icon: Sparkles, colorClass: "text-brand-purple", bgClass: "bg-brand-purple/15 dark:bg-brand-purple/25" },
|
|
4
|
+
transfer: { label: "Transfer", variant: "secondary", icon: ArrowRightLeft, colorClass: "text-brand-blue", bgClass: "bg-brand-blue/15 dark:bg-brand-blue/25" },
|
|
5
|
+
listing: { label: "Listed", variant: "default", icon: Tag, colorClass: "text-brand-orange", bgClass: "bg-brand-orange/15 dark:bg-brand-orange/25" },
|
|
6
|
+
sale: { label: "Sale", variant: "default", icon: ShoppingCart, colorClass: "text-brand-rose", bgClass: "bg-brand-rose/15 dark:bg-brand-rose/25" },
|
|
7
|
+
offer: { label: "Offer", variant: "outline", icon: HandCoins, colorClass: "text-brand-maeve", bgClass: "bg-brand-maeve/15 dark:bg-brand-maeve/25" },
|
|
8
8
|
cancelled: { label: "Cancelled", variant: "outline", icon: X, colorClass: "text-muted-foreground", bgClass: "bg-muted" }
|
|
9
9
|
};
|
|
10
10
|
const TYPE_FILTERS = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/data/activity.ts"],"sourcesContent":["import { ArrowRightLeft, Tag, ShoppingCart, HandCoins, X, Sparkles } from \"lucide-react\";\nimport type { ElementType } from \"react\";\n\nexport interface ActivityTypeConfig {\n label: string;\n variant: \"default\" | \"secondary\" | \"outline\";\n icon: ElementType;\n colorClass: string;\n bgClass: string;\n}\n\nexport const ACTIVITY_TYPE_CONFIG: Record<string, ActivityTypeConfig> = {\n mint: { label: \"Mint\", variant: \"default\", icon: Sparkles, colorClass: \"text-brand-purple\", bgClass: \"bg-brand-purple/
|
|
1
|
+
{"version":3,"sources":["../../src/data/activity.ts"],"sourcesContent":["import { ArrowRightLeft, Tag, ShoppingCart, HandCoins, X, Sparkles } from \"lucide-react\";\nimport type { ElementType } from \"react\";\n\nexport interface ActivityTypeConfig {\n label: string;\n variant: \"default\" | \"secondary\" | \"outline\";\n icon: ElementType;\n colorClass: string;\n bgClass: string;\n}\n\nexport const ACTIVITY_TYPE_CONFIG: Record<string, ActivityTypeConfig> = {\n mint: { label: \"Mint\", variant: \"default\", icon: Sparkles, colorClass: \"text-brand-purple\", bgClass: \"bg-brand-purple/15 dark:bg-brand-purple/25\" },\n transfer: { label: \"Transfer\", variant: \"secondary\", icon: ArrowRightLeft, colorClass: \"text-brand-blue\", bgClass: \"bg-brand-blue/15 dark:bg-brand-blue/25\" },\n listing: { label: \"Listed\", variant: \"default\", icon: Tag, colorClass: \"text-brand-orange\", bgClass: \"bg-brand-orange/15 dark:bg-brand-orange/25\" },\n sale: { label: \"Sale\", variant: \"default\", icon: ShoppingCart, colorClass: \"text-brand-rose\", bgClass: \"bg-brand-rose/15 dark:bg-brand-rose/25\" },\n offer: { label: \"Offer\", variant: \"outline\", icon: HandCoins, colorClass: \"text-brand-maeve\", bgClass: \"bg-brand-maeve/15 dark:bg-brand-maeve/25\" },\n cancelled: { label: \"Cancelled\", variant: \"outline\", icon: X, colorClass: \"text-muted-foreground\", bgClass: \"bg-muted\" },\n};\n\nexport const TYPE_FILTERS = [\n { label: \"All\", value: \"\" },\n { label: \"Mints\", value: \"mint\" },\n { label: \"Sales\", value: \"sale\" },\n { label: \"Listings\", value: \"listing\" },\n { label: \"Offers\", value: \"offer\" },\n { label: \"Transfers\", value: \"transfer\" },\n { label: \"Cancelled\", value: \"cancelled\" },\n];\n"],"mappings":"AAAA,SAAS,gBAAgB,KAAK,cAAc,WAAW,GAAG,gBAAgB;AAWnE,MAAM,uBAA2D;AAAA,EACtE,MAAW,EAAE,OAAO,QAAa,SAAS,WAAa,MAAM,UAAgB,YAAY,qBAAqB,SAAS,6CAA6C;AAAA,EACpK,UAAW,EAAE,OAAO,YAAa,SAAS,aAAa,MAAM,gBAAgB,YAAY,mBAAqB,SAAS,yCAAyC;AAAA,EAChK,SAAW,EAAE,OAAO,UAAa,SAAS,WAAa,MAAM,KAAgB,YAAY,qBAAqB,SAAS,6CAA6C;AAAA,EACpK,MAAW,EAAE,OAAO,QAAa,SAAS,WAAa,MAAM,cAAgB,YAAY,mBAAqB,SAAS,yCAAyC;AAAA,EAChK,OAAW,EAAE,OAAO,SAAa,SAAS,WAAa,MAAM,WAAgB,YAAY,oBAAqB,SAAS,2CAA2C;AAAA,EAClK,WAAW,EAAE,OAAO,aAAa,SAAS,WAAa,MAAM,GAAgB,YAAY,yBAAyB,SAAS,WAAW;AACxI;AAEO,MAAM,eAAe;AAAA,EAC1B,EAAE,OAAO,OAAa,OAAO,GAAG;AAAA,EAChC,EAAE,OAAO,SAAa,OAAO,OAAO;AAAA,EACpC,EAAE,OAAO,SAAa,OAAO,OAAO;AAAA,EACpC,EAAE,OAAO,YAAa,OAAO,UAAU;AAAA,EACvC,EAAE,OAAO,UAAa,OAAO,QAAQ;AAAA,EACrC,EAAE,OAAO,aAAa,OAAO,WAAW;AAAA,EACxC,EAAE,OAAO,aAAa,OAAO,YAAY;AAC3C;","names":[]}
|
|
@@ -7,7 +7,7 @@ declare function useTokenBalance(symbol: string | null, holderAddress: string |
|
|
|
7
7
|
rawBalance: bigint | null;
|
|
8
8
|
isLoading: boolean;
|
|
9
9
|
error: any;
|
|
10
|
-
decimals:
|
|
10
|
+
decimals: 6 | 8 | 18;
|
|
11
11
|
};
|
|
12
12
|
declare function hasSufficientBalance(rawBalance: bigint | null, requiredHuman: string, decimals: number): boolean | null;
|
|
13
13
|
|
|
@@ -7,7 +7,7 @@ declare function useTokenBalance(symbol: string | null, holderAddress: string |
|
|
|
7
7
|
rawBalance: bigint | null;
|
|
8
8
|
isLoading: boolean;
|
|
9
9
|
error: any;
|
|
10
|
-
decimals:
|
|
10
|
+
decimals: 6 | 8 | 18;
|
|
11
11
|
};
|
|
12
12
|
declare function hasSufficientBalance(rawBalance: bigint | null, requiredHuman: string, decimals: number): boolean | null;
|
|
13
13
|
|