@medialane/ui 0.301.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.
@@ -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 border border-border/50 bg-card transition-colors hover:border-border",
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 border border-border/50 bg-card", children: [
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 border border-border/50 bg-card transition-colors hover:border-border\",\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 border border-border/50 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,mFACb;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"]}
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 border border-border/50 bg-card transition-colors hover:border-border",
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 border border-border/50 bg-card", children: [
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 border border-border/50 bg-card transition-colors hover:border-border\",\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 border border-border/50 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,mFACb;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":[]}
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":[]}
@@ -86,80 +86,95 @@ 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
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "relative pl-12 pb-6 last:pb-0", children: [
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
- "absolute left-0 top-0 flex h-8 w-8 items-center justify-center rounded-full ring-4 ring-background",
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-4 w-4", config?.colorClass ?? "text-muted-foreground") })
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
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-start gap-3", children: [
102
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "min-w-0 flex-1", children: [
103
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-sm font-semibold leading-8 sm:leading-8", children: [
104
- EVENT_TITLE[event.type] ?? event.type,
105
- amount ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "ml-1.5 text-xs font-medium text-muted-foreground", children: [
106
- "\xD7",
107
- amount
108
- ] }) : null,
109
- actor ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "font-normal text-muted-foreground", children: [
110
- " by ",
111
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
112
- import_link.default,
113
- {
114
- href: (0, import_sdk.profileHref)({ address: actor }),
115
- className: "hover:text-primary transition-colors",
116
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_address_display.AddressDisplay, { address: actor, chars: 4, showCopy: false, className: "text-xs" })
117
- }
118
- )
119
- ] }) : null
120
- ] }),
121
- showAsset && name ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
122
- import_link.default,
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: [
134
+ "\xD7",
135
+ amount
136
+ ] }) : null,
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
+ ] }) }),
147
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex shrink-0 flex-col items-end gap-1", children: [
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: [
149
+ event.price.currency ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_currency_icon.CurrencyIcon, { symbol: event.price.currency, size: 15, "aria-hidden": true }) : null,
150
+ (0, import_format.formatDisplayPrice)(event.price.formatted),
151
+ event.price.currency ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs font-medium text-muted-foreground", children: event.price.currency }) : null
152
+ ] }) : null,
153
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
154
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("time", { dateTime: event.timestamp, title: new Date(event.timestamp).toLocaleString(), children: (0, import_time.timeAgo)(event.timestamp) }),
155
+ event.txHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
156
+ "a",
123
157
  {
124
- href: contract && tokenId ? (0, import_sdk.assetHref)(event.chain ?? "STARKNET", contract, tokenId) : "#",
125
- className: "mt-1 inline-flex max-w-full items-center gap-2 rounded-lg bg-muted/40 py-1 pl-1 pr-3 hover:bg-muted transition-colors",
126
- children: [
127
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "relative h-8 w-8 shrink-0 overflow-hidden rounded-md bg-muted", children: image ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_image.default, { src: image, alt: "", width: 32, height: 32, 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
- ]
158
+ href: `${import_explorer_url.EXPLORER_URL}/tx/${event.txHash}`,
159
+ target: "_blank",
160
+ rel: "noopener noreferrer",
161
+ className: "rounded-md p-1 hover:bg-muted hover:text-foreground transition-colors",
162
+ "aria-label": "View transaction",
163
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ExternalLink, { className: "h-3.5 w-3.5", "aria-hidden": true })
130
164
  }
131
165
  ) : null
132
- ] }),
133
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex shrink-0 flex-col items-end gap-0.5 pt-1.5", children: [
134
- event.price?.formatted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1.5 text-sm font-bold tabular-nums", children: [
135
- event.price.currency ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_currency_icon.CurrencyIcon, { symbol: event.price.currency, size: 13, "aria-hidden": true }) : null,
136
- (0, import_format.formatDisplayPrice)(event.price.formatted)
137
- ] }) : null,
138
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
139
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("time", { dateTime: event.timestamp, title: new Date(event.timestamp).toLocaleString(), children: (0, import_time.timeAgo)(event.timestamp) }),
140
- event.txHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
141
- "a",
142
- {
143
- href: `${import_explorer_url.EXPLORER_URL}/tx/${event.txHash}`,
144
- target: "_blank",
145
- rel: "noopener noreferrer",
146
- className: "rounded p-0.5 hover:bg-muted hover:text-foreground transition-colors",
147
- "aria-label": "View transaction",
148
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ExternalLink, { className: "h-3 w-3", "aria-hidden": true })
149
- }
150
- ) : null
151
- ] })
152
166
  ] })
153
167
  ] })
154
168
  ] });
155
169
  }
156
170
  function ProvenanceSkeleton() {
157
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "space-y-6", "aria-hidden": true, children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-start gap-4", children: [
158
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-8 w-8 shrink-0 rounded-full bg-muted animate-pulse" }),
159
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 space-y-2 pt-1", children: [
160
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-3.5 w-40 rounded bg-muted animate-pulse" }),
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: [
172
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-11 w-11 shrink-0 rounded-xl bg-muted animate-pulse" }),
173
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 space-y-2", children: [
174
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-4 w-44 rounded bg-muted animate-pulse" }),
161
175
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-3 w-24 rounded bg-muted animate-pulse" })
162
- ] })
176
+ ] }),
177
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-4 w-16 rounded bg-muted animate-pulse" })
163
178
  ] }, i)) });
164
179
  }
165
180
  function CollectionProvenanceTab({ contract }) {
@@ -184,10 +199,10 @@ function CollectionProvenanceTab({ contract }) {
184
199
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-muted-foreground/70 max-w-xs", children: "Mints, transfers, listings and sales will appear here as they happen." })
185
200
  ] });
186
201
  }
187
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mx-auto max-w-2xl", children: [
188
- groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "mb-8 last:mb-0", children: [
189
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "mb-4 pl-12 text-xs font-medium text-muted-foreground", children: group.label }),
190
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "relative before:absolute before:left-4 before:top-4 before:bottom-4 before:w-px before:bg-border", children: group.events.map((event, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
202
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-8", children: [
203
+ groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [
204
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "mb-3 font-display text-lg font-bold", children: group.label }),
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)(
191
206
  ProvenanceEvent,
192
207
  {
193
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=\"relative pl-12 pb-6 last:pb-0\">\n <span\n className={cn(\n \"absolute left-0 top-0 flex h-8 w-8 items-center justify-center rounded-full ring-4 ring-background\",\n config?.bgClass ?? \"bg-muted\"\n )}\n aria-hidden\n >\n <Icon className={cn(\"h-4 w-4\", config?.colorClass ?? \"text-muted-foreground\")} />\n </span>\n\n <div className=\"flex items-start gap-3\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-semibold leading-8 sm:leading-8\">\n {EVENT_TITLE[event.type] ?? event.type}\n {amount ? <span className=\"ml-1.5 text-xs font-medium text-muted-foreground\">×{amount}</span> : null}\n {actor ? (\n <span className=\"font-normal text-muted-foreground\">\n {\" by \"}\n <Link\n href={profileHref({ address: actor })}\n className=\"hover:text-primary transition-colors\"\n >\n <AddressDisplay address={actor} chars={4} showCopy={false} className=\"text-xs\" />\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-1 inline-flex max-w-full items-center gap-2 rounded-lg bg-muted/40 py-1 pl-1 pr-3 hover:bg-muted transition-colors\"\n >\n <span className=\"relative h-8 w-8 shrink-0 overflow-hidden rounded-md bg-muted\">\n {image ? (\n <Image src={image} alt=\"\" width={32} height={32} 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-0.5 pt-1.5\">\n {event.price?.formatted ? (\n <span className=\"flex items-center gap-1.5 text-sm font-bold tabular-nums\">\n {event.price.currency ? <CurrencyIcon symbol={event.price.currency} size={13} aria-hidden /> : null}\n {formatDisplayPrice(event.price.formatted)}\n </span>\n ) : null}\n <span className=\"flex items-center gap-1.5 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 p-0.5 hover:bg-muted hover:text-foreground transition-colors\"\n aria-label=\"View transaction\"\n >\n <ExternalLink className=\"h-3 w-3\" aria-hidden />\n </a>\n ) : null}\n </span>\n </div>\n </div>\n </li>\n );\n}\n\nfunction ProvenanceSkeleton() {\n return (\n <div className=\"space-y-6\" aria-hidden>\n {Array.from({ length: 6 }).map((_, i) => (\n <div key={i} className=\"flex items-start gap-4\">\n <div className=\"h-8 w-8 shrink-0 rounded-full bg-muted animate-pulse\" />\n <div className=\"flex-1 space-y-2 pt-1\">\n <div className=\"h-3.5 w-40 rounded bg-muted animate-pulse\" />\n <div className=\"h-3 w-24 rounded bg-muted animate-pulse\" />\n </div>\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=\"mx-auto max-w-2xl\">\n {groups.map((group) => (\n <section key={group.label} className=\"mb-8 last:mb-0\">\n <h3 className=\"mb-4 pl-12 text-xs font-medium text-muted-foreground\">{group.label}</h3>\n <ol className=\"relative before:absolute before:left-4 before:top-4 before:bottom-4 before:w-px before:bg-border\">\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
+ {"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,80 +53,95 @@ 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
- return /* @__PURE__ */ jsxs("li", { className: "relative pl-12 pb-6 last:pb-0", children: [
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
- "absolute left-0 top-0 flex h-8 w-8 items-center justify-center rounded-full ring-4 ring-background",
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-4 w-4", config?.colorClass ?? "text-muted-foreground") })
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
- /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
69
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
70
- /* @__PURE__ */ jsxs("p", { className: "text-sm font-semibold leading-8 sm:leading-8", children: [
71
- EVENT_TITLE[event.type] ?? event.type,
72
- amount ? /* @__PURE__ */ jsxs("span", { className: "ml-1.5 text-xs font-medium text-muted-foreground", children: [
73
- "\xD7",
74
- amount
75
- ] }) : null,
76
- actor ? /* @__PURE__ */ jsxs("span", { className: "font-normal text-muted-foreground", children: [
77
- " by ",
78
- /* @__PURE__ */ jsx(
79
- Link,
80
- {
81
- href: profileHref({ address: actor }),
82
- className: "hover:text-primary transition-colors",
83
- children: /* @__PURE__ */ jsx(AddressDisplay, { address: actor, chars: 4, showCopy: false, className: "text-xs" })
84
- }
85
- )
86
- ] }) : null
87
- ] }),
88
- showAsset && name ? /* @__PURE__ */ jsxs(
89
- Link,
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: [
101
+ "\xD7",
102
+ amount
103
+ ] }) : null,
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
+ ] }) }),
114
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col items-end gap-1", children: [
115
+ event.price?.formatted ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-base font-bold tabular-nums", children: [
116
+ event.price.currency ? /* @__PURE__ */ jsx(CurrencyIcon, { symbol: event.price.currency, size: 15, "aria-hidden": true }) : null,
117
+ formatDisplayPrice(event.price.formatted),
118
+ event.price.currency ? /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground", children: event.price.currency }) : null
119
+ ] }) : null,
120
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
121
+ /* @__PURE__ */ jsx("time", { dateTime: event.timestamp, title: new Date(event.timestamp).toLocaleString(), children: timeAgo(event.timestamp) }),
122
+ event.txHash ? /* @__PURE__ */ jsx(
123
+ "a",
90
124
  {
91
- href: contract && tokenId ? assetHref(event.chain ?? "STARKNET", contract, tokenId) : "#",
92
- className: "mt-1 inline-flex max-w-full items-center gap-2 rounded-lg bg-muted/40 py-1 pl-1 pr-3 hover:bg-muted transition-colors",
93
- children: [
94
- /* @__PURE__ */ jsx("span", { className: "relative h-8 w-8 shrink-0 overflow-hidden rounded-md bg-muted", children: image ? /* @__PURE__ */ jsx(Image, { src: image, alt: "", width: 32, height: 32, className: "h-full w-full object-cover", unoptimized: true }) : null }),
95
- /* @__PURE__ */ jsx("span", { className: "truncate text-xs font-medium", children: name })
96
- ]
125
+ href: `${EXPLORER_URL}/tx/${event.txHash}`,
126
+ target: "_blank",
127
+ rel: "noopener noreferrer",
128
+ className: "rounded-md p-1 hover:bg-muted hover:text-foreground transition-colors",
129
+ "aria-label": "View transaction",
130
+ children: /* @__PURE__ */ jsx(ExternalLink, { className: "h-3.5 w-3.5", "aria-hidden": true })
97
131
  }
98
132
  ) : null
99
- ] }),
100
- /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col items-end gap-0.5 pt-1.5", children: [
101
- event.price?.formatted ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-sm font-bold tabular-nums", children: [
102
- event.price.currency ? /* @__PURE__ */ jsx(CurrencyIcon, { symbol: event.price.currency, size: 13, "aria-hidden": true }) : null,
103
- formatDisplayPrice(event.price.formatted)
104
- ] }) : null,
105
- /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
106
- /* @__PURE__ */ jsx("time", { dateTime: event.timestamp, title: new Date(event.timestamp).toLocaleString(), children: timeAgo(event.timestamp) }),
107
- event.txHash ? /* @__PURE__ */ jsx(
108
- "a",
109
- {
110
- href: `${EXPLORER_URL}/tx/${event.txHash}`,
111
- target: "_blank",
112
- rel: "noopener noreferrer",
113
- className: "rounded p-0.5 hover:bg-muted hover:text-foreground transition-colors",
114
- "aria-label": "View transaction",
115
- children: /* @__PURE__ */ jsx(ExternalLink, { className: "h-3 w-3", "aria-hidden": true })
116
- }
117
- ) : null
118
- ] })
119
133
  ] })
120
134
  ] })
121
135
  ] });
122
136
  }
123
137
  function ProvenanceSkeleton() {
124
- return /* @__PURE__ */ jsx("div", { className: "space-y-6", "aria-hidden": true, children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-4", children: [
125
- /* @__PURE__ */ jsx("div", { className: "h-8 w-8 shrink-0 rounded-full bg-muted animate-pulse" }),
126
- /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2 pt-1", children: [
127
- /* @__PURE__ */ jsx("div", { className: "h-3.5 w-40 rounded bg-muted animate-pulse" }),
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: [
139
+ /* @__PURE__ */ jsx("div", { className: "h-11 w-11 shrink-0 rounded-xl bg-muted animate-pulse" }),
140
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2", children: [
141
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-44 rounded bg-muted animate-pulse" }),
128
142
  /* @__PURE__ */ jsx("div", { className: "h-3 w-24 rounded bg-muted animate-pulse" })
129
- ] })
143
+ ] }),
144
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-16 rounded bg-muted animate-pulse" })
130
145
  ] }, i)) });
131
146
  }
132
147
  function CollectionProvenanceTab({ contract }) {
@@ -151,10 +166,10 @@ function CollectionProvenanceTab({ contract }) {
151
166
  /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground/70 max-w-xs", children: "Mints, transfers, listings and sales will appear here as they happen." })
152
167
  ] });
153
168
  }
154
- return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-2xl", children: [
155
- groups.map((group) => /* @__PURE__ */ jsxs("section", { className: "mb-8 last:mb-0", children: [
156
- /* @__PURE__ */ jsx("h3", { className: "mb-4 pl-12 text-xs font-medium text-muted-foreground", children: group.label }),
157
- /* @__PURE__ */ jsx("ol", { className: "relative before:absolute before:left-4 before:top-4 before:bottom-4 before:w-px before:bg-border", children: group.events.map((event, i) => /* @__PURE__ */ jsx(
169
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-8", children: [
170
+ groups.map((group) => /* @__PURE__ */ jsxs("section", { children: [
171
+ /* @__PURE__ */ jsx("h3", { className: "mb-3 font-display text-lg font-bold", children: group.label }),
172
+ /* @__PURE__ */ jsx("ol", { className: "grid gap-2.5 lg:grid-cols-2", children: group.events.map((event, i) => /* @__PURE__ */ jsx(
158
173
  ProvenanceEvent,
159
174
  {
160
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=\"relative pl-12 pb-6 last:pb-0\">\n <span\n className={cn(\n \"absolute left-0 top-0 flex h-8 w-8 items-center justify-center rounded-full ring-4 ring-background\",\n config?.bgClass ?? \"bg-muted\"\n )}\n aria-hidden\n >\n <Icon className={cn(\"h-4 w-4\", config?.colorClass ?? \"text-muted-foreground\")} />\n </span>\n\n <div className=\"flex items-start gap-3\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-semibold leading-8 sm:leading-8\">\n {EVENT_TITLE[event.type] ?? event.type}\n {amount ? <span className=\"ml-1.5 text-xs font-medium text-muted-foreground\">×{amount}</span> : null}\n {actor ? (\n <span className=\"font-normal text-muted-foreground\">\n {\" by \"}\n <Link\n href={profileHref({ address: actor })}\n className=\"hover:text-primary transition-colors\"\n >\n <AddressDisplay address={actor} chars={4} showCopy={false} className=\"text-xs\" />\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-1 inline-flex max-w-full items-center gap-2 rounded-lg bg-muted/40 py-1 pl-1 pr-3 hover:bg-muted transition-colors\"\n >\n <span className=\"relative h-8 w-8 shrink-0 overflow-hidden rounded-md bg-muted\">\n {image ? (\n <Image src={image} alt=\"\" width={32} height={32} 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-0.5 pt-1.5\">\n {event.price?.formatted ? (\n <span className=\"flex items-center gap-1.5 text-sm font-bold tabular-nums\">\n {event.price.currency ? <CurrencyIcon symbol={event.price.currency} size={13} aria-hidden /> : null}\n {formatDisplayPrice(event.price.formatted)}\n </span>\n ) : null}\n <span className=\"flex items-center gap-1.5 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 p-0.5 hover:bg-muted hover:text-foreground transition-colors\"\n aria-label=\"View transaction\"\n >\n <ExternalLink className=\"h-3 w-3\" aria-hidden />\n </a>\n ) : null}\n </span>\n </div>\n </div>\n </li>\n );\n}\n\nfunction ProvenanceSkeleton() {\n return (\n <div className=\"space-y-6\" aria-hidden>\n {Array.from({ length: 6 }).map((_, i) => (\n <div key={i} className=\"flex items-start gap-4\">\n <div className=\"h-8 w-8 shrink-0 rounded-full bg-muted animate-pulse\" />\n <div className=\"flex-1 space-y-2 pt-1\">\n <div className=\"h-3.5 w-40 rounded bg-muted animate-pulse\" />\n <div className=\"h-3 w-24 rounded bg-muted animate-pulse\" />\n </div>\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=\"mx-auto max-w-2xl\">\n {groups.map((group) => (\n <section key={group.label} className=\"mb-8 last:mb-0\">\n <h3 className=\"mb-4 pl-12 text-xs font-medium text-muted-foreground\">{group.label}</h3>\n <ol className=\"relative before:absolute before:left-4 before:top-4 before:bottom-4 before:w-px before:bg-border\">\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":[]}
@@ -24,12 +24,12 @@ __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-emerald-400", bgClass: "bg-emerald-500/10" },
28
- transfer: { label: "Transfer", variant: "secondary", icon: import_lucide_react.ArrowRightLeft, colorClass: "text-slate-400", bgClass: "bg-slate-500/10" },
29
- listing: { label: "Listed", variant: "default", icon: import_lucide_react.Tag, colorClass: "text-sky-400", bgClass: "bg-sky-500/10" },
30
- sale: { label: "Sale", variant: "default", icon: import_lucide_react.ShoppingCart, colorClass: "text-violet-400", bgClass: "bg-violet-500/10" },
31
- offer: { label: "Offer", variant: "outline", icon: import_lucide_react.HandCoins, colorClass: "text-amber-400", bgClass: "bg-amber-500/10" },
32
- cancelled: { label: "Cancelled", variant: "outline", icon: import_lucide_react.X, colorClass: "text-rose-400", bgClass: "bg-rose-500/10" }
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
+ cancelled: { label: "Cancelled", variant: "outline", icon: import_lucide_react.X, colorClass: "text-muted-foreground", bgClass: "bg-muted" }
33
33
  };
34
34
  const TYPE_FILTERS = [
35
35
  { label: "All", value: "" },
@@ -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-emerald-400\", bgClass: \"bg-emerald-500/10\" },\n transfer: { label: \"Transfer\", variant: \"secondary\", icon: ArrowRightLeft, colorClass: \"text-slate-400\", bgClass: \"bg-slate-500/10\" },\n listing: { label: \"Listed\", variant: \"default\", icon: Tag, colorClass: \"text-sky-400\", bgClass: \"bg-sky-500/10\" },\n sale: { label: \"Sale\", variant: \"default\", icon: ShoppingCart, colorClass: \"text-violet-400\", bgClass: \"bg-violet-500/10\" },\n offer: { label: \"Offer\", variant: \"outline\", icon: HandCoins, colorClass: \"text-amber-400\", bgClass: \"bg-amber-500/10\" },\n cancelled: { label: \"Cancelled\", variant: \"outline\", icon: X, colorClass: \"text-rose-400\", bgClass: \"bg-rose-500/10\" },\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,oBAAoB,SAAS,oBAAoB;AAAA,EAC1I,UAAW,EAAE,OAAO,YAAa,SAAS,aAAa,MAAM,oCAAgB,YAAY,kBAAoB,SAAS,kBAAkB;AAAA,EACxI,SAAW,EAAE,OAAO,UAAa,SAAS,WAAa,MAAM,yBAAgB,YAAY,gBAAoB,SAAS,gBAAgB;AAAA,EACtI,MAAW,EAAE,OAAO,QAAa,SAAS,WAAa,MAAM,kCAAgB,YAAY,mBAAoB,SAAS,mBAAmB;AAAA,EACzI,OAAW,EAAE,OAAO,SAAa,SAAS,WAAa,MAAM,+BAAgB,YAAY,kBAAoB,SAAS,kBAAkB;AAAA,EACxI,WAAW,EAAE,OAAO,aAAa,SAAS,WAAa,MAAM,uBAAgB,YAAY,iBAAoB,SAAS,iBAAiB;AACzI;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":[]}
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":[]}
@@ -1,11 +1,11 @@
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-emerald-400", bgClass: "bg-emerald-500/10" },
4
- transfer: { label: "Transfer", variant: "secondary", icon: ArrowRightLeft, colorClass: "text-slate-400", bgClass: "bg-slate-500/10" },
5
- listing: { label: "Listed", variant: "default", icon: Tag, colorClass: "text-sky-400", bgClass: "bg-sky-500/10" },
6
- sale: { label: "Sale", variant: "default", icon: ShoppingCart, colorClass: "text-violet-400", bgClass: "bg-violet-500/10" },
7
- offer: { label: "Offer", variant: "outline", icon: HandCoins, colorClass: "text-amber-400", bgClass: "bg-amber-500/10" },
8
- cancelled: { label: "Cancelled", variant: "outline", icon: X, colorClass: "text-rose-400", bgClass: "bg-rose-500/10" }
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
+ cancelled: { label: "Cancelled", variant: "outline", icon: X, colorClass: "text-muted-foreground", bgClass: "bg-muted" }
9
9
  };
10
10
  const TYPE_FILTERS = [
11
11
  { label: "All", value: "" },
@@ -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-emerald-400\", bgClass: \"bg-emerald-500/10\" },\n transfer: { label: \"Transfer\", variant: \"secondary\", icon: ArrowRightLeft, colorClass: \"text-slate-400\", bgClass: \"bg-slate-500/10\" },\n listing: { label: \"Listed\", variant: \"default\", icon: Tag, colorClass: \"text-sky-400\", bgClass: \"bg-sky-500/10\" },\n sale: { label: \"Sale\", variant: \"default\", icon: ShoppingCart, colorClass: \"text-violet-400\", bgClass: \"bg-violet-500/10\" },\n offer: { label: \"Offer\", variant: \"outline\", icon: HandCoins, colorClass: \"text-amber-400\", bgClass: \"bg-amber-500/10\" },\n cancelled: { label: \"Cancelled\", variant: \"outline\", icon: X, colorClass: \"text-rose-400\", bgClass: \"bg-rose-500/10\" },\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,oBAAoB,SAAS,oBAAoB;AAAA,EAC1I,UAAW,EAAE,OAAO,YAAa,SAAS,aAAa,MAAM,gBAAgB,YAAY,kBAAoB,SAAS,kBAAkB;AAAA,EACxI,SAAW,EAAE,OAAO,UAAa,SAAS,WAAa,MAAM,KAAgB,YAAY,gBAAoB,SAAS,gBAAgB;AAAA,EACtI,MAAW,EAAE,OAAO,QAAa,SAAS,WAAa,MAAM,cAAgB,YAAY,mBAAoB,SAAS,mBAAmB;AAAA,EACzI,OAAW,EAAE,OAAO,SAAa,SAAS,WAAa,MAAM,WAAgB,YAAY,kBAAoB,SAAS,kBAAkB;AAAA,EACxI,WAAW,EAAE,OAAO,aAAa,SAAS,WAAa,MAAM,GAAgB,YAAY,iBAAoB,SAAS,iBAAiB;AACzI;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":[]}
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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medialane/ui",
3
- "version": "0.301.0",
3
+ "version": "0.303.0",
4
4
  "description": "Shared UI components for Medialane apps",
5
5
  "type": "module",
6
6
  "sideEffects": false,