@medialane/ui 0.141.1 → 0.142.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/asset-card.cjs +1 -1
- package/dist/components/asset-card.cjs.map +1 -1
- package/dist/components/asset-card.js +1 -1
- package/dist/components/asset-card.js.map +1 -1
- package/dist/components/collection-card.cjs +1 -1
- package/dist/components/collection-card.cjs.map +1 -1
- package/dist/components/collection-card.js +1 -1
- package/dist/components/collection-card.js.map +1 -1
- package/dist/components/fast-mint/dropzone.cjs +120 -0
- package/dist/components/fast-mint/dropzone.cjs.map +1 -0
- package/dist/components/fast-mint/dropzone.d.cts +17 -0
- package/dist/components/fast-mint/dropzone.d.ts +17 -0
- package/dist/components/fast-mint/dropzone.js +96 -0
- package/dist/components/fast-mint/dropzone.js.map +1 -0
- package/dist/components/fast-mint/fast-mint.cjs +887 -0
- package/dist/components/fast-mint/fast-mint.cjs.map +1 -0
- package/dist/components/fast-mint/fast-mint.d.cts +10 -0
- package/dist/components/fast-mint/fast-mint.d.ts +10 -0
- package/dist/components/fast-mint/fast-mint.js +873 -0
- package/dist/components/fast-mint/fast-mint.js.map +1 -0
- package/dist/components/fast-mint/success-view.cjs +113 -0
- package/dist/components/fast-mint/success-view.cjs.map +1 -0
- package/dist/components/fast-mint/success-view.d.cts +17 -0
- package/dist/components/fast-mint/success-view.d.ts +17 -0
- package/dist/components/fast-mint/success-view.js +79 -0
- package/dist/components/fast-mint/success-view.js.map +1 -0
- package/dist/components/listing-card.cjs +1 -1
- package/dist/components/listing-card.cjs.map +1 -1
- package/dist/components/listing-card.js +1 -1
- package/dist/components/listing-card.js.map +1 -1
- package/dist/components/token-card.cjs +1 -1
- package/dist/components/token-card.cjs.map +1 -1
- package/dist/components/token-card.js +1 -1
- package/dist/components/token-card.js.map +1 -1
- package/dist/data/drop-create-schema.d.cts +2 -2
- package/dist/data/drop-create-schema.d.ts +2 -2
- package/dist/index.cjs +18 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/types-7TZuHZVP.d.cts +35 -0
- package/dist/types-7TZuHZVP.d.ts +35 -0
- package/dist/utils/ipfs-upload.cjs +87 -0
- package/dist/utils/ipfs-upload.cjs.map +1 -0
- package/dist/utils/ipfs-upload.d.cts +13 -0
- package/dist/utils/ipfs-upload.d.ts +13 -0
- package/dist/utils/ipfs-upload.js +60 -0
- package/dist/utils/ipfs-upload.js.map +1 -0
- package/dist/utils/ipfs.cjs +11 -3
- package/dist/utils/ipfs.cjs.map +1 -1
- package/dist/utils/ipfs.d.cts +4 -1
- package/dist/utils/ipfs.d.ts +4 -1
- package/dist/utils/ipfs.js +11 -3
- package/dist/utils/ipfs.js.map +1 -1
- package/package.json +5 -3
|
@@ -55,7 +55,7 @@ function AssetCard({
|
|
|
55
55
|
ipTypeBaseUrl = "",
|
|
56
56
|
className
|
|
57
57
|
}) {
|
|
58
|
-
const resolved = image ? (0, import_ipfs.ipfsToHttp)(image) : null;
|
|
58
|
+
const resolved = image ? (0, import_ipfs.ipfsToHttp)(image, { width: 480 }) : null;
|
|
59
59
|
const hasPrice = !!price?.formatted;
|
|
60
60
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
61
61
|
"div",
|
|
@@ -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 { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.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 resolved = image ? ipfsToHttp(image) : null;\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 <Link href={href} className=\"block relative aspect-[4/5] 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 {ipType && (\n <div className=\"absolute top-2 right-2\">\n <IpTypeBadge ipType={ipType} size=\"sm\" baseUrl={ipTypeBaseUrl} />\n </div>\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-bold line-clamp-1 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-[4/5] 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;AA8EY;AA5EZ,kBAAiB;AACjB,0BAAwB;AACxB,gBAAmB;AACnB,kBAA2B;AAC3B,wBAAiC;AACjC,2BAA4B;AAC5B,kCAAmC;AAmC5B,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,WAAW,YAAQ,wBAAW,
|
|
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 { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.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 resolved = image ? ipfsToHttp(image, { width: 480 }) : null;\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 <Link href={href} className=\"block relative aspect-[4/5] 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 {ipType && (\n <div className=\"absolute top-2 right-2\">\n <IpTypeBadge ipType={ipType} size=\"sm\" baseUrl={ipTypeBaseUrl} />\n </div>\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-bold line-clamp-1 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-[4/5] 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;AA8EY;AA5EZ,kBAAiB;AACjB,0BAAwB;AACxB,gBAAmB;AACnB,kBAA2B;AAC3B,wBAAiC;AACjC,2BAA4B;AAC5B,kCAAmC;AAmC5B,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,WAAW,YAAQ,wBAAW,OAAO,EAAE,OAAO,IAAI,CAAC,IAAI;AAC7D,QAAM,WAAW,CAAC,CAAC,OAAO;AAE1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAGA;AAAA,qDAAC,YAAAA,SAAA,EAAK,MAAY,WAAU,wDAC1B;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,UACC,4CAAC,SAAI,WAAU,0BACb,sDAAC,oCAAY,QAAgB,MAAK,MAAK,SAAS,eAAe,GACjE;AAAA,UAGD,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,iDACV,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,8CAA6C;AAAA,IAC5D,6CAAC,SAAI,WAAU,yBACb;AAAA,kDAAC,SAAI,WAAU,+CAA8C;AAAA,MAC7D,4CAAC,SAAI,WAAU,iDAAgD;AAAA,OACjE;AAAA,KACF;AAEJ;","names":["Link"]}
|
|
@@ -21,7 +21,7 @@ function AssetCard({
|
|
|
21
21
|
ipTypeBaseUrl = "",
|
|
22
22
|
className
|
|
23
23
|
}) {
|
|
24
|
-
const resolved = image ? ipfsToHttp(image) : null;
|
|
24
|
+
const resolved = image ? ipfsToHttp(image, { width: 480 }) : null;
|
|
25
25
|
const hasPrice = !!price?.formatted;
|
|
26
26
|
return /* @__PURE__ */ jsxs(
|
|
27
27
|
"div",
|
|
@@ -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 { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.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 resolved = image ? ipfsToHttp(image) : null;\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 <Link href={href} className=\"block relative aspect-[4/5] 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 {ipType && (\n <div className=\"absolute top-2 right-2\">\n <IpTypeBadge ipType={ipType} size=\"sm\" baseUrl={ipTypeBaseUrl} />\n </div>\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-bold line-clamp-1 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-[4/5] 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":";AA8EY,cACE,YADF;AA5EZ,OAAO,UAAU;AACjB,SAAS,eAAe;AACxB,SAAS,UAAU;AACnB,SAAS,kBAAkB;AAC3B,SAAS,wBAAwB;AACjC,SAAS,mBAAmB;AAC5B,SAAS,0BAA0B;AAmC5B,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,WAAW,QAAQ,WAAW,
|
|
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 { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.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 resolved = image ? ipfsToHttp(image, { width: 480 }) : null;\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 <Link href={href} className=\"block relative aspect-[4/5] 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 {ipType && (\n <div className=\"absolute top-2 right-2\">\n <IpTypeBadge ipType={ipType} size=\"sm\" baseUrl={ipTypeBaseUrl} />\n </div>\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-bold line-clamp-1 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-[4/5] 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":";AA8EY,cACE,YADF;AA5EZ,OAAO,UAAU;AACjB,SAAS,eAAe;AACxB,SAAS,UAAU;AACnB,SAAS,kBAAkB;AAC3B,SAAS,wBAAwB;AACjC,SAAS,mBAAmB;AAC5B,SAAS,0BAA0B;AAmC5B,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,WAAW,QAAQ,WAAW,OAAO,EAAE,OAAO,IAAI,CAAC,IAAI;AAC7D,QAAM,WAAW,CAAC,CAAC,OAAO;AAE1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAGA;AAAA,6BAAC,QAAK,MAAY,WAAU,wDAC1B;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,UACC,oBAAC,SAAI,WAAU,0BACb,8BAAC,eAAY,QAAgB,MAAK,MAAK,SAAS,eAAe,GACjE;AAAA,UAGD,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,iDACV,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,8CAA6C;AAAA,IAC5D,qBAAC,SAAI,WAAU,yBACb;AAAA,0BAAC,SAAI,WAAU,+CAA8C;AAAA,MAC7D,oBAAC,SAAI,WAAU,iDAAgD;AAAA,OACjE;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -54,7 +54,7 @@ function parseFloorPrice(floor) {
|
|
|
54
54
|
}
|
|
55
55
|
function CollectionCard({ collection, href, settingsHref, className }) {
|
|
56
56
|
const [imgError, setImgError] = (0, import_react.useState)(false);
|
|
57
|
-
const imageUrl = collection.image ? (0, import_ipfs.ipfsToHttp)(collection.image) : null;
|
|
57
|
+
const imageUrl = collection.image ? (0, import_ipfs.ipfsToHttp)(collection.image, { width: 480 }) : null;
|
|
58
58
|
const showImage = imageUrl && !imgError;
|
|
59
59
|
const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();
|
|
60
60
|
const floor = parseFloorPrice(collection.floorPrice);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"./link.js\";\nimport Image from \"./image.js\";\nimport { Loader2, Settings2 } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { MotionCard } from \"./motion-primitives.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\nfunction parseFloorPrice(floor: string | null | undefined): { amount: string; symbol: string } | null {\n if (!floor) return null;\n const formatted = formatDisplayPrice(floor);\n const parts = formatted.trim().split(/\\s+/);\n if (parts.length < 2) return null;\n const symbol = parts[parts.length - 1];\n const amount = parts.slice(0, -1).join(\" \");\n return { amount, symbol };\n}\n\ntype CollectionWithProfile = ApiCollection & {\n profile?: { hasGatedContent?: boolean } | null;\n};\n\nexport interface CollectionCardProps {\n collection: ApiCollection;\n\n href?: string;\n\n settingsHref?: string;\n className?: string;\n}\n\nexport function CollectionCard({ collection, href, settingsHref, className }: CollectionCardProps) {\n const [imgError, setImgError] = useState(false);\n const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;\n const showImage = imageUrl && !imgError;\n const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();\n const floor = parseFloorPrice(collection.floorPrice);\n const hasExclusiveContent = !!(collection as CollectionWithProfile).profile?.hasGatedContent;\n\n return (\n <div className={cn(hasExclusiveContent && \"card-exclusive-wrapper btn-border-animated\")}>\n <MotionCard className={cn(\"card-base group relative\", className)}>\n {settingsHref && (\n <Link\n href={settingsHref}\n onClick={(e) => e.stopPropagation()}\n className=\"absolute top-2 right-2 z-10 min-h-11 min-w-11 rounded-full flex items-center justify-center\"\n aria-label=\"Collection settings\"\n >\n <span className=\"flex h-7 w-7 items-center justify-center rounded-full bg-black/40 backdrop-blur-sm text-white/70 hover:text-white hover:bg-black/60 transition-colors\">\n <Settings2 className=\"h-3.5 w-3.5\" />\n </span>\n </Link>\n )}\n\n <Link href={href ?? `/collections/${collection.contractAddress}`} className=\"block relative h-full\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n {showImage ? (\n <Image\n src={imageUrl}\n alt={collection.name ?? \"Collection\"}\n fill\n className=\"object-cover transition-transform duration-500 group-hover:scale-105\"\n onError={() => setImgError(true)}\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/40 flex items-center justify-center\">\n <span className=\"text-8xl font-black text-white/10 select-none tracking-tighter\">\n {initial}\n </span>\n </div>\n )}\n\n <div className=\"absolute bottom-0 left-0 right-0 px-3 pb-3 flex flex-col gap-1.5 items-start\">\n {!collection.name && collection.metadataStatus === \"PENDING\" ? (\n <span className=\"flex items-center gap-1 text-2xs text-white/60 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n <Loader2 className=\"h-2.5 w-2.5 animate-spin\" />\n Indexing…\n </span>\n ) : (\n <p\n className=\"font-bold text-sm text-white leading-tight backdrop-blur-md bg-black/30 rounded-lg px-2.5 py-1 max-w-full truncate\"\n style={{ textShadow: \"0 1px 6px rgba(0,0,0,0.5)\" }}\n >\n {collection.name ?? \"Unnamed Collection\"}\n </p>\n )}\n\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n {collection.totalSupply != null && (\n <span className=\"text-2xs font-medium text-white/80 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n {collection.totalSupply.toLocaleString()} items\n </span>\n )}\n {floor && (\n <span className=\"inline-flex items-center gap-1 text-2xs font-bold text-white/90 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n Floor\n <CurrencyIcon symbol={floor.symbol} size={10} />\n {floor.amount}\n </span>\n )}\n {hasExclusiveContent && (\n <span className=\"inline-flex items-center gap-1 text-2xs font-bold text-white backdrop-blur-md bg-black/50 rounded-full px-2 py-0.5\">\n ✦ Exclusive\n </span>\n )}\n </div>\n </div>\n </div>\n </Link>\n </MotionCard>\n </div>\n );\n}\n\nexport function CollectionCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n <div className=\"absolute inset-0 animate-pulse bg-muted\" />\n <div className=\"absolute bottom-3 left-3 right-3 space-y-1.5\">\n <div className=\"h-4 w-2/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n <div className=\"h-3 w-1/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuDc;AArDd,mBAAyB;AACzB,kBAAiB;AACjB,mBAAkB;AAClB,0BAAmC;AACnC,gBAAmB;AACnB,kBAA2B;AAC3B,oBAAmC;AACnC,+BAA2B;AAC3B,2BAA6B;AAG7B,SAAS,gBAAgB,OAA6E;AACpG,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,gBAAY,kCAAmB,KAAK;AAC1C,QAAM,QAAQ,UAAU,KAAK,EAAE,MAAM,KAAK;AAC1C,MAAI,MAAM,SAAS,EAAG,QAAO;AAC7B,QAAM,SAAS,MAAM,MAAM,SAAS,CAAC;AACrC,QAAM,SAAS,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG;AAC1C,SAAO,EAAE,QAAQ,OAAO;AAC1B;AAeO,SAAS,eAAe,EAAE,YAAY,MAAM,cAAc,UAAU,GAAwB;AACjG,QAAM,CAAC,UAAU,WAAW,QAAI,uBAAS,KAAK;AAC9C,QAAM,WAAW,WAAW,YAAQ,wBAAW,WAAW,
|
|
1
|
+
{"version":3,"sources":["../../src/components/collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"./link.js\";\nimport Image from \"./image.js\";\nimport { Loader2, Settings2 } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { MotionCard } from \"./motion-primitives.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\nfunction parseFloorPrice(floor: string | null | undefined): { amount: string; symbol: string } | null {\n if (!floor) return null;\n const formatted = formatDisplayPrice(floor);\n const parts = formatted.trim().split(/\\s+/);\n if (parts.length < 2) return null;\n const symbol = parts[parts.length - 1];\n const amount = parts.slice(0, -1).join(\" \");\n return { amount, symbol };\n}\n\ntype CollectionWithProfile = ApiCollection & {\n profile?: { hasGatedContent?: boolean } | null;\n};\n\nexport interface CollectionCardProps {\n collection: ApiCollection;\n\n href?: string;\n\n settingsHref?: string;\n className?: string;\n}\n\nexport function CollectionCard({ collection, href, settingsHref, className }: CollectionCardProps) {\n const [imgError, setImgError] = useState(false);\n const imageUrl = collection.image ? ipfsToHttp(collection.image, { width: 480 }) : null;\n const showImage = imageUrl && !imgError;\n const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();\n const floor = parseFloorPrice(collection.floorPrice);\n const hasExclusiveContent = !!(collection as CollectionWithProfile).profile?.hasGatedContent;\n\n return (\n <div className={cn(hasExclusiveContent && \"card-exclusive-wrapper btn-border-animated\")}>\n <MotionCard className={cn(\"card-base group relative\", className)}>\n {settingsHref && (\n <Link\n href={settingsHref}\n onClick={(e) => e.stopPropagation()}\n className=\"absolute top-2 right-2 z-10 min-h-11 min-w-11 rounded-full flex items-center justify-center\"\n aria-label=\"Collection settings\"\n >\n <span className=\"flex h-7 w-7 items-center justify-center rounded-full bg-black/40 backdrop-blur-sm text-white/70 hover:text-white hover:bg-black/60 transition-colors\">\n <Settings2 className=\"h-3.5 w-3.5\" />\n </span>\n </Link>\n )}\n\n <Link href={href ?? `/collections/${collection.contractAddress}`} className=\"block relative h-full\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n {showImage ? (\n <Image\n src={imageUrl}\n alt={collection.name ?? \"Collection\"}\n fill\n className=\"object-cover transition-transform duration-500 group-hover:scale-105\"\n onError={() => setImgError(true)}\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/40 flex items-center justify-center\">\n <span className=\"text-8xl font-black text-white/10 select-none tracking-tighter\">\n {initial}\n </span>\n </div>\n )}\n\n <div className=\"absolute bottom-0 left-0 right-0 px-3 pb-3 flex flex-col gap-1.5 items-start\">\n {!collection.name && collection.metadataStatus === \"PENDING\" ? (\n <span className=\"flex items-center gap-1 text-2xs text-white/60 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n <Loader2 className=\"h-2.5 w-2.5 animate-spin\" />\n Indexing…\n </span>\n ) : (\n <p\n className=\"font-bold text-sm text-white leading-tight backdrop-blur-md bg-black/30 rounded-lg px-2.5 py-1 max-w-full truncate\"\n style={{ textShadow: \"0 1px 6px rgba(0,0,0,0.5)\" }}\n >\n {collection.name ?? \"Unnamed Collection\"}\n </p>\n )}\n\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n {collection.totalSupply != null && (\n <span className=\"text-2xs font-medium text-white/80 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n {collection.totalSupply.toLocaleString()} items\n </span>\n )}\n {floor && (\n <span className=\"inline-flex items-center gap-1 text-2xs font-bold text-white/90 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n Floor\n <CurrencyIcon symbol={floor.symbol} size={10} />\n {floor.amount}\n </span>\n )}\n {hasExclusiveContent && (\n <span className=\"inline-flex items-center gap-1 text-2xs font-bold text-white backdrop-blur-md bg-black/50 rounded-full px-2 py-0.5\">\n ✦ Exclusive\n </span>\n )}\n </div>\n </div>\n </div>\n </Link>\n </MotionCard>\n </div>\n );\n}\n\nexport function CollectionCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n <div className=\"absolute inset-0 animate-pulse bg-muted\" />\n <div className=\"absolute bottom-3 left-3 right-3 space-y-1.5\">\n <div className=\"h-4 w-2/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n <div className=\"h-3 w-1/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["Link","Image"]}
|
|
@@ -20,7 +20,7 @@ function parseFloorPrice(floor) {
|
|
|
20
20
|
}
|
|
21
21
|
function CollectionCard({ collection, href, settingsHref, className }) {
|
|
22
22
|
const [imgError, setImgError] = useState(false);
|
|
23
|
-
const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;
|
|
23
|
+
const imageUrl = collection.image ? ipfsToHttp(collection.image, { width: 480 }) : null;
|
|
24
24
|
const showImage = imageUrl && !imgError;
|
|
25
25
|
const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();
|
|
26
26
|
const floor = parseFloorPrice(collection.floorPrice);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"./link.js\";\nimport Image from \"./image.js\";\nimport { Loader2, Settings2 } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { MotionCard } from \"./motion-primitives.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\nfunction parseFloorPrice(floor: string | null | undefined): { amount: string; symbol: string } | null {\n if (!floor) return null;\n const formatted = formatDisplayPrice(floor);\n const parts = formatted.trim().split(/\\s+/);\n if (parts.length < 2) return null;\n const symbol = parts[parts.length - 1];\n const amount = parts.slice(0, -1).join(\" \");\n return { amount, symbol };\n}\n\ntype CollectionWithProfile = ApiCollection & {\n profile?: { hasGatedContent?: boolean } | null;\n};\n\nexport interface CollectionCardProps {\n collection: ApiCollection;\n\n href?: string;\n\n settingsHref?: string;\n className?: string;\n}\n\nexport function CollectionCard({ collection, href, settingsHref, className }: CollectionCardProps) {\n const [imgError, setImgError] = useState(false);\n const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;\n const showImage = imageUrl && !imgError;\n const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();\n const floor = parseFloorPrice(collection.floorPrice);\n const hasExclusiveContent = !!(collection as CollectionWithProfile).profile?.hasGatedContent;\n\n return (\n <div className={cn(hasExclusiveContent && \"card-exclusive-wrapper btn-border-animated\")}>\n <MotionCard className={cn(\"card-base group relative\", className)}>\n {settingsHref && (\n <Link\n href={settingsHref}\n onClick={(e) => e.stopPropagation()}\n className=\"absolute top-2 right-2 z-10 min-h-11 min-w-11 rounded-full flex items-center justify-center\"\n aria-label=\"Collection settings\"\n >\n <span className=\"flex h-7 w-7 items-center justify-center rounded-full bg-black/40 backdrop-blur-sm text-white/70 hover:text-white hover:bg-black/60 transition-colors\">\n <Settings2 className=\"h-3.5 w-3.5\" />\n </span>\n </Link>\n )}\n\n <Link href={href ?? `/collections/${collection.contractAddress}`} className=\"block relative h-full\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n {showImage ? (\n <Image\n src={imageUrl}\n alt={collection.name ?? \"Collection\"}\n fill\n className=\"object-cover transition-transform duration-500 group-hover:scale-105\"\n onError={() => setImgError(true)}\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/40 flex items-center justify-center\">\n <span className=\"text-8xl font-black text-white/10 select-none tracking-tighter\">\n {initial}\n </span>\n </div>\n )}\n\n <div className=\"absolute bottom-0 left-0 right-0 px-3 pb-3 flex flex-col gap-1.5 items-start\">\n {!collection.name && collection.metadataStatus === \"PENDING\" ? (\n <span className=\"flex items-center gap-1 text-2xs text-white/60 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n <Loader2 className=\"h-2.5 w-2.5 animate-spin\" />\n Indexing…\n </span>\n ) : (\n <p\n className=\"font-bold text-sm text-white leading-tight backdrop-blur-md bg-black/30 rounded-lg px-2.5 py-1 max-w-full truncate\"\n style={{ textShadow: \"0 1px 6px rgba(0,0,0,0.5)\" }}\n >\n {collection.name ?? \"Unnamed Collection\"}\n </p>\n )}\n\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n {collection.totalSupply != null && (\n <span className=\"text-2xs font-medium text-white/80 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n {collection.totalSupply.toLocaleString()} items\n </span>\n )}\n {floor && (\n <span className=\"inline-flex items-center gap-1 text-2xs font-bold text-white/90 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n Floor\n <CurrencyIcon symbol={floor.symbol} size={10} />\n {floor.amount}\n </span>\n )}\n {hasExclusiveContent && (\n <span className=\"inline-flex items-center gap-1 text-2xs font-bold text-white backdrop-blur-md bg-black/50 rounded-full px-2 py-0.5\">\n ✦ Exclusive\n </span>\n )}\n </div>\n </div>\n </div>\n </Link>\n </MotionCard>\n </div>\n );\n}\n\nexport function CollectionCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n <div className=\"absolute inset-0 animate-pulse bg-muted\" />\n <div className=\"absolute bottom-3 left-3 right-3 space-y-1.5\">\n <div className=\"h-4 w-2/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n <div className=\"h-3 w-1/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";AAuDc,cA0BE,YA1BF;AArDd,SAAS,gBAAgB;AACzB,OAAO,UAAU;AACjB,OAAO,WAAW;AAClB,SAAS,SAAS,iBAAiB;AACnC,SAAS,UAAU;AACnB,SAAS,kBAAkB;AAC3B,SAAS,0BAA0B;AACnC,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAG7B,SAAS,gBAAgB,OAA6E;AACpG,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,YAAY,mBAAmB,KAAK;AAC1C,QAAM,QAAQ,UAAU,KAAK,EAAE,MAAM,KAAK;AAC1C,MAAI,MAAM,SAAS,EAAG,QAAO;AAC7B,QAAM,SAAS,MAAM,MAAM,SAAS,CAAC;AACrC,QAAM,SAAS,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG;AAC1C,SAAO,EAAE,QAAQ,OAAO;AAC1B;AAeO,SAAS,eAAe,EAAE,YAAY,MAAM,cAAc,UAAU,GAAwB;AACjG,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,WAAW,WAAW,QAAQ,WAAW,WAAW,
|
|
1
|
+
{"version":3,"sources":["../../src/components/collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"./link.js\";\nimport Image from \"./image.js\";\nimport { Loader2, Settings2 } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { MotionCard } from \"./motion-primitives.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\nfunction parseFloorPrice(floor: string | null | undefined): { amount: string; symbol: string } | null {\n if (!floor) return null;\n const formatted = formatDisplayPrice(floor);\n const parts = formatted.trim().split(/\\s+/);\n if (parts.length < 2) return null;\n const symbol = parts[parts.length - 1];\n const amount = parts.slice(0, -1).join(\" \");\n return { amount, symbol };\n}\n\ntype CollectionWithProfile = ApiCollection & {\n profile?: { hasGatedContent?: boolean } | null;\n};\n\nexport interface CollectionCardProps {\n collection: ApiCollection;\n\n href?: string;\n\n settingsHref?: string;\n className?: string;\n}\n\nexport function CollectionCard({ collection, href, settingsHref, className }: CollectionCardProps) {\n const [imgError, setImgError] = useState(false);\n const imageUrl = collection.image ? ipfsToHttp(collection.image, { width: 480 }) : null;\n const showImage = imageUrl && !imgError;\n const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();\n const floor = parseFloorPrice(collection.floorPrice);\n const hasExclusiveContent = !!(collection as CollectionWithProfile).profile?.hasGatedContent;\n\n return (\n <div className={cn(hasExclusiveContent && \"card-exclusive-wrapper btn-border-animated\")}>\n <MotionCard className={cn(\"card-base group relative\", className)}>\n {settingsHref && (\n <Link\n href={settingsHref}\n onClick={(e) => e.stopPropagation()}\n className=\"absolute top-2 right-2 z-10 min-h-11 min-w-11 rounded-full flex items-center justify-center\"\n aria-label=\"Collection settings\"\n >\n <span className=\"flex h-7 w-7 items-center justify-center rounded-full bg-black/40 backdrop-blur-sm text-white/70 hover:text-white hover:bg-black/60 transition-colors\">\n <Settings2 className=\"h-3.5 w-3.5\" />\n </span>\n </Link>\n )}\n\n <Link href={href ?? `/collections/${collection.contractAddress}`} className=\"block relative h-full\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n {showImage ? (\n <Image\n src={imageUrl}\n alt={collection.name ?? \"Collection\"}\n fill\n className=\"object-cover transition-transform duration-500 group-hover:scale-105\"\n onError={() => setImgError(true)}\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/40 flex items-center justify-center\">\n <span className=\"text-8xl font-black text-white/10 select-none tracking-tighter\">\n {initial}\n </span>\n </div>\n )}\n\n <div className=\"absolute bottom-0 left-0 right-0 px-3 pb-3 flex flex-col gap-1.5 items-start\">\n {!collection.name && collection.metadataStatus === \"PENDING\" ? (\n <span className=\"flex items-center gap-1 text-2xs text-white/60 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n <Loader2 className=\"h-2.5 w-2.5 animate-spin\" />\n Indexing…\n </span>\n ) : (\n <p\n className=\"font-bold text-sm text-white leading-tight backdrop-blur-md bg-black/30 rounded-lg px-2.5 py-1 max-w-full truncate\"\n style={{ textShadow: \"0 1px 6px rgba(0,0,0,0.5)\" }}\n >\n {collection.name ?? \"Unnamed Collection\"}\n </p>\n )}\n\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n {collection.totalSupply != null && (\n <span className=\"text-2xs font-medium text-white/80 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n {collection.totalSupply.toLocaleString()} items\n </span>\n )}\n {floor && (\n <span className=\"inline-flex items-center gap-1 text-2xs font-bold text-white/90 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n Floor\n <CurrencyIcon symbol={floor.symbol} size={10} />\n {floor.amount}\n </span>\n )}\n {hasExclusiveContent && (\n <span className=\"inline-flex items-center gap-1 text-2xs font-bold text-white backdrop-blur-md bg-black/50 rounded-full px-2 py-0.5\">\n ✦ Exclusive\n </span>\n )}\n </div>\n </div>\n </div>\n </Link>\n </MotionCard>\n </div>\n );\n}\n\nexport function CollectionCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n <div className=\"absolute inset-0 animate-pulse bg-muted\" />\n <div className=\"absolute bottom-3 left-3 right-3 space-y-1.5\">\n <div className=\"h-4 w-2/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n <div className=\"h-3 w-1/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var dropzone_exports = {};
|
|
21
|
+
__export(dropzone_exports, {
|
|
22
|
+
Dropzone: () => Dropzone
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(dropzone_exports);
|
|
25
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
26
|
+
var import_react = require("react");
|
|
27
|
+
var import_lucide_react = require("lucide-react");
|
|
28
|
+
var import_cn = require("../../utils/cn.js");
|
|
29
|
+
var import_button = require("../button.js");
|
|
30
|
+
function Dropzone({
|
|
31
|
+
mediaKindLock,
|
|
32
|
+
presentation = "inline",
|
|
33
|
+
hasWallet,
|
|
34
|
+
onRequireWallet,
|
|
35
|
+
onFileSelected,
|
|
36
|
+
connectLabel = "Sign in"
|
|
37
|
+
}) {
|
|
38
|
+
const mediaInputRef = (0, import_react.useRef)(null);
|
|
39
|
+
const openMediaPicker = () => {
|
|
40
|
+
if (!hasWallet) {
|
|
41
|
+
onRequireWallet();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
mediaInputRef.current?.click();
|
|
45
|
+
};
|
|
46
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
47
|
+
"section",
|
|
48
|
+
{
|
|
49
|
+
role: "button",
|
|
50
|
+
tabIndex: 0,
|
|
51
|
+
"aria-label": hasWallet ? "Upload media" : `${connectLabel} to upload media`,
|
|
52
|
+
onClick: openMediaPicker,
|
|
53
|
+
onKeyDown: (e) => {
|
|
54
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
openMediaPicker();
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
onDragOver: (e) => e.preventDefault(),
|
|
60
|
+
onDrop: (e) => {
|
|
61
|
+
e.preventDefault();
|
|
62
|
+
if (!hasWallet) {
|
|
63
|
+
onRequireWallet();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const f = e.dataTransfer.files?.[0];
|
|
67
|
+
if (f) onFileSelected(f);
|
|
68
|
+
},
|
|
69
|
+
className: (0, import_cn.cn)(
|
|
70
|
+
"relative flex flex-col items-center justify-center gap-4 cursor-pointer transition-colors text-center rounded-3xl border-[3px] border-dashed border-brand-blue/40 hover:border-brand-blue/70 hover:bg-brand-blue/[0.04] p-6",
|
|
71
|
+
presentation === "dialog" ? "min-h-[16rem] sm:min-h-[18rem]" : "min-h-[20rem] sm:min-h-[24rem]"
|
|
72
|
+
),
|
|
73
|
+
children: [
|
|
74
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-14 w-14 rounded-2xl bg-muted flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ImagePlus, { className: "h-6 w-6 text-muted-foreground" }) }),
|
|
75
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5 px-6", children: [
|
|
76
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-2xl sm:text-3xl font-bold tracking-tight", children: mediaKindLock ? `Drop or upload an ${mediaKindLock}` : "Drop or upload your media" }),
|
|
77
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-base text-muted-foreground max-w-sm mx-auto", children: mediaKindLock === "image" ? "It becomes your avatar and app theme." : "Protect your creation and monetize it worldwide." })
|
|
78
|
+
] }),
|
|
79
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
80
|
+
import_button.Button,
|
|
81
|
+
{
|
|
82
|
+
type: "button",
|
|
83
|
+
variant: "outline",
|
|
84
|
+
className: "rounded-full mt-1 bg-card",
|
|
85
|
+
onClick: (e) => {
|
|
86
|
+
e.stopPropagation();
|
|
87
|
+
openMediaPicker();
|
|
88
|
+
},
|
|
89
|
+
children: hasWallet ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
90
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Upload, { className: "h-3.5 w-3.5 mr-1.5" }),
|
|
91
|
+
"Browse files"
|
|
92
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
93
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.LogIn, { className: "h-3.5 w-3.5 mr-1.5" }),
|
|
94
|
+
connectLabel
|
|
95
|
+
] })
|
|
96
|
+
}
|
|
97
|
+
),
|
|
98
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-2xs text-muted-foreground/70", children: mediaKindLock === "image" ? "JPG, PNG, GIF, WebP, or SVG up to 100 MB" : "Images, audio, video, and PDFs up to 100 MB; other documents up to 20 MB" }),
|
|
99
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
100
|
+
"input",
|
|
101
|
+
{
|
|
102
|
+
ref: mediaInputRef,
|
|
103
|
+
type: "file",
|
|
104
|
+
accept: mediaKindLock === "image" ? "image/*" : void 0,
|
|
105
|
+
className: "hidden",
|
|
106
|
+
onChange: (e) => {
|
|
107
|
+
const f = e.target.files?.[0];
|
|
108
|
+
if (f) onFileSelected(f);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
117
|
+
0 && (module.exports = {
|
|
118
|
+
Dropzone
|
|
119
|
+
});
|
|
120
|
+
//# sourceMappingURL=dropzone.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/fast-mint/dropzone.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRef } from \"react\";\nimport { ImagePlus, Upload, LogIn } from \"lucide-react\";\nimport { cn } from \"../../utils/cn.js\";\nimport { Button } from \"../button.js\";\nimport type { MediaKind } from \"./types.js\";\n\nexport interface DropzoneProps {\n mediaKindLock?: MediaKind;\n presentation?: \"inline\" | \"dialog\";\n hasWallet: boolean;\n onRequireWallet: () => void;\n onFileSelected: (file: File) => void;\n connectLabel?: string;\n}\n\nexport function Dropzone({\n mediaKindLock,\n presentation = \"inline\",\n hasWallet,\n onRequireWallet,\n onFileSelected,\n connectLabel = \"Sign in\",\n}: DropzoneProps) {\n const mediaInputRef = useRef<HTMLInputElement>(null);\n\n const openMediaPicker = () => {\n if (!hasWallet) { onRequireWallet(); return; }\n mediaInputRef.current?.click();\n };\n\n return (\n <section\n role=\"button\"\n tabIndex={0}\n aria-label={hasWallet ? \"Upload media\" : `${connectLabel} to upload media`}\n onClick={openMediaPicker}\n onKeyDown={(e) => { if (e.key === \"Enter\" || e.key === \" \") { e.preventDefault(); openMediaPicker(); } }}\n onDragOver={(e) => e.preventDefault()}\n onDrop={(e) => { e.preventDefault(); if (!hasWallet) { onRequireWallet(); return; } const f = e.dataTransfer.files?.[0]; if (f) onFileSelected(f); }}\n className={cn(\n \"relative flex flex-col items-center justify-center gap-4 cursor-pointer transition-colors text-center rounded-3xl border-[3px] border-dashed border-brand-blue/40 hover:border-brand-blue/70 hover:bg-brand-blue/[0.04] p-6\",\n presentation === \"dialog\" ? \"min-h-[16rem] sm:min-h-[18rem]\" : \"min-h-[20rem] sm:min-h-[24rem]\"\n )}\n >\n <div className=\"h-14 w-14 rounded-2xl bg-muted flex items-center justify-center\">\n <ImagePlus className=\"h-6 w-6 text-muted-foreground\" />\n </div>\n <div className=\"space-y-1.5 px-6\">\n <h2 className=\"text-2xl sm:text-3xl font-bold tracking-tight\">\n {mediaKindLock ? `Drop or upload an ${mediaKindLock}` : \"Drop or upload your media\"}\n </h2>\n <p className=\"text-base text-muted-foreground max-w-sm mx-auto\">\n {mediaKindLock === \"image\" ? \"It becomes your avatar and app theme.\" : \"Protect your creation and monetize it worldwide.\"}\n </p>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"rounded-full mt-1 bg-card\"\n onClick={(e) => { e.stopPropagation(); openMediaPicker(); }}\n >\n {hasWallet ? (\n <>\n <Upload className=\"h-3.5 w-3.5 mr-1.5\" />\n Browse files\n </>\n ) : (\n <>\n <LogIn className=\"h-3.5 w-3.5 mr-1.5\" />\n {connectLabel}\n </>\n )}\n </Button>\n <p className=\"text-2xs text-muted-foreground/70\">\n {mediaKindLock === \"image\" ? \"JPG, PNG, GIF, WebP, or SVG up to 100 MB\" : \"Images, audio, video, and PDFs up to 100 MB; other documents up to 20 MB\"}\n </p>\n <input\n ref={mediaInputRef}\n type=\"file\"\n accept={mediaKindLock === \"image\" ? \"image/*\" : undefined}\n className=\"hidden\"\n onChange={(e) => { const f = e.target.files?.[0]; if (f) onFileSelected(f); }}\n />\n </section>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA+CQ;AA7CR,mBAAuB;AACvB,0BAAyC;AACzC,gBAAmB;AACnB,oBAAuB;AAYhB,SAAS,SAAS;AAAA,EACvB;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AACjB,GAAkB;AAChB,QAAM,oBAAgB,qBAAyB,IAAI;AAEnD,QAAM,kBAAkB,MAAM;AAC5B,QAAI,CAAC,WAAW;AAAE,sBAAgB;AAAG;AAAA,IAAQ;AAC7C,kBAAc,SAAS,MAAM;AAAA,EAC/B;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,UAAU;AAAA,MACV,cAAY,YAAY,iBAAiB,GAAG,YAAY;AAAA,MACxD,SAAS;AAAA,MACT,WAAW,CAAC,MAAM;AAAE,YAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AAAE,YAAE,eAAe;AAAG,0BAAgB;AAAA,QAAG;AAAA,MAAE;AAAA,MACvG,YAAY,CAAC,MAAM,EAAE,eAAe;AAAA,MACpC,QAAQ,CAAC,MAAM;AAAE,UAAE,eAAe;AAAG,YAAI,CAAC,WAAW;AAAE,0BAAgB;AAAG;AAAA,QAAQ;AAAE,cAAM,IAAI,EAAE,aAAa,QAAQ,CAAC;AAAG,YAAI,EAAG,gBAAe,CAAC;AAAA,MAAG;AAAA,MACnJ,eAAW;AAAA,QACT;AAAA,QACA,iBAAiB,WAAW,mCAAmC;AAAA,MACjE;AAAA,MAEA;AAAA,oDAAC,SAAI,WAAU,mEACb,sDAAC,iCAAU,WAAU,iCAAgC,GACvD;AAAA,QACA,6CAAC,SAAI,WAAU,oBACb;AAAA,sDAAC,QAAG,WAAU,iDACX,0BAAgB,qBAAqB,aAAa,KAAK,6BAC1D;AAAA,UACA,4CAAC,OAAE,WAAU,oDACV,4BAAkB,UAAU,0CAA0C,oDACzE;AAAA,WACF;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,WAAU;AAAA,YACV,SAAS,CAAC,MAAM;AAAE,gBAAE,gBAAgB;AAAG,8BAAgB;AAAA,YAAG;AAAA,YAEzD,sBACC,4EACE;AAAA,0DAAC,8BAAO,WAAU,sBAAqB;AAAA,cAAE;AAAA,eAE3C,IAEA,4EACE;AAAA,0DAAC,6BAAM,WAAU,sBAAqB;AAAA,cACrC;AAAA,eACH;AAAA;AAAA,QAEJ;AAAA,QACA,4CAAC,OAAE,WAAU,qCACV,4BAAkB,UAAU,6CAA6C,4EAC5E;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YACL,QAAQ,kBAAkB,UAAU,YAAY;AAAA,YAChD,WAAU;AAAA,YACV,UAAU,CAAC,MAAM;AAAE,oBAAM,IAAI,EAAE,OAAO,QAAQ,CAAC;AAAG,kBAAI,EAAG,gBAAe,CAAC;AAAA,YAAG;AAAA;AAAA,QAC9E;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { M as MediaKind } from '../../types-7TZuHZVP.cjs';
|
|
3
|
+
import 'starknet';
|
|
4
|
+
import '@medialane/sdk';
|
|
5
|
+
import '@medialane/sdk/starknet';
|
|
6
|
+
|
|
7
|
+
interface DropzoneProps {
|
|
8
|
+
mediaKindLock?: MediaKind;
|
|
9
|
+
presentation?: "inline" | "dialog";
|
|
10
|
+
hasWallet: boolean;
|
|
11
|
+
onRequireWallet: () => void;
|
|
12
|
+
onFileSelected: (file: File) => void;
|
|
13
|
+
connectLabel?: string;
|
|
14
|
+
}
|
|
15
|
+
declare function Dropzone({ mediaKindLock, presentation, hasWallet, onRequireWallet, onFileSelected, connectLabel, }: DropzoneProps): react_jsx_runtime.JSX.Element;
|
|
16
|
+
|
|
17
|
+
export { Dropzone, type DropzoneProps };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { M as MediaKind } from '../../types-7TZuHZVP.js';
|
|
3
|
+
import 'starknet';
|
|
4
|
+
import '@medialane/sdk';
|
|
5
|
+
import '@medialane/sdk/starknet';
|
|
6
|
+
|
|
7
|
+
interface DropzoneProps {
|
|
8
|
+
mediaKindLock?: MediaKind;
|
|
9
|
+
presentation?: "inline" | "dialog";
|
|
10
|
+
hasWallet: boolean;
|
|
11
|
+
onRequireWallet: () => void;
|
|
12
|
+
onFileSelected: (file: File) => void;
|
|
13
|
+
connectLabel?: string;
|
|
14
|
+
}
|
|
15
|
+
declare function Dropzone({ mediaKindLock, presentation, hasWallet, onRequireWallet, onFileSelected, connectLabel, }: DropzoneProps): react_jsx_runtime.JSX.Element;
|
|
16
|
+
|
|
17
|
+
export { Dropzone, type DropzoneProps };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useRef } from "react";
|
|
4
|
+
import { ImagePlus, Upload, LogIn } from "lucide-react";
|
|
5
|
+
import { cn } from "../../utils/cn.js";
|
|
6
|
+
import { Button } from "../button.js";
|
|
7
|
+
function Dropzone({
|
|
8
|
+
mediaKindLock,
|
|
9
|
+
presentation = "inline",
|
|
10
|
+
hasWallet,
|
|
11
|
+
onRequireWallet,
|
|
12
|
+
onFileSelected,
|
|
13
|
+
connectLabel = "Sign in"
|
|
14
|
+
}) {
|
|
15
|
+
const mediaInputRef = useRef(null);
|
|
16
|
+
const openMediaPicker = () => {
|
|
17
|
+
if (!hasWallet) {
|
|
18
|
+
onRequireWallet();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
mediaInputRef.current?.click();
|
|
22
|
+
};
|
|
23
|
+
return /* @__PURE__ */ jsxs(
|
|
24
|
+
"section",
|
|
25
|
+
{
|
|
26
|
+
role: "button",
|
|
27
|
+
tabIndex: 0,
|
|
28
|
+
"aria-label": hasWallet ? "Upload media" : `${connectLabel} to upload media`,
|
|
29
|
+
onClick: openMediaPicker,
|
|
30
|
+
onKeyDown: (e) => {
|
|
31
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
openMediaPicker();
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
onDragOver: (e) => e.preventDefault(),
|
|
37
|
+
onDrop: (e) => {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
if (!hasWallet) {
|
|
40
|
+
onRequireWallet();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const f = e.dataTransfer.files?.[0];
|
|
44
|
+
if (f) onFileSelected(f);
|
|
45
|
+
},
|
|
46
|
+
className: cn(
|
|
47
|
+
"relative flex flex-col items-center justify-center gap-4 cursor-pointer transition-colors text-center rounded-3xl border-[3px] border-dashed border-brand-blue/40 hover:border-brand-blue/70 hover:bg-brand-blue/[0.04] p-6",
|
|
48
|
+
presentation === "dialog" ? "min-h-[16rem] sm:min-h-[18rem]" : "min-h-[20rem] sm:min-h-[24rem]"
|
|
49
|
+
),
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ jsx("div", { className: "h-14 w-14 rounded-2xl bg-muted flex items-center justify-center", children: /* @__PURE__ */ jsx(ImagePlus, { className: "h-6 w-6 text-muted-foreground" }) }),
|
|
52
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5 px-6", children: [
|
|
53
|
+
/* @__PURE__ */ jsx("h2", { className: "text-2xl sm:text-3xl font-bold tracking-tight", children: mediaKindLock ? `Drop or upload an ${mediaKindLock}` : "Drop or upload your media" }),
|
|
54
|
+
/* @__PURE__ */ jsx("p", { className: "text-base text-muted-foreground max-w-sm mx-auto", children: mediaKindLock === "image" ? "It becomes your avatar and app theme." : "Protect your creation and monetize it worldwide." })
|
|
55
|
+
] }),
|
|
56
|
+
/* @__PURE__ */ jsx(
|
|
57
|
+
Button,
|
|
58
|
+
{
|
|
59
|
+
type: "button",
|
|
60
|
+
variant: "outline",
|
|
61
|
+
className: "rounded-full mt-1 bg-card",
|
|
62
|
+
onClick: (e) => {
|
|
63
|
+
e.stopPropagation();
|
|
64
|
+
openMediaPicker();
|
|
65
|
+
},
|
|
66
|
+
children: hasWallet ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
67
|
+
/* @__PURE__ */ jsx(Upload, { className: "h-3.5 w-3.5 mr-1.5" }),
|
|
68
|
+
"Browse files"
|
|
69
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
70
|
+
/* @__PURE__ */ jsx(LogIn, { className: "h-3.5 w-3.5 mr-1.5" }),
|
|
71
|
+
connectLabel
|
|
72
|
+
] })
|
|
73
|
+
}
|
|
74
|
+
),
|
|
75
|
+
/* @__PURE__ */ jsx("p", { className: "text-2xs text-muted-foreground/70", children: mediaKindLock === "image" ? "JPG, PNG, GIF, WebP, or SVG up to 100 MB" : "Images, audio, video, and PDFs up to 100 MB; other documents up to 20 MB" }),
|
|
76
|
+
/* @__PURE__ */ jsx(
|
|
77
|
+
"input",
|
|
78
|
+
{
|
|
79
|
+
ref: mediaInputRef,
|
|
80
|
+
type: "file",
|
|
81
|
+
accept: mediaKindLock === "image" ? "image/*" : void 0,
|
|
82
|
+
className: "hidden",
|
|
83
|
+
onChange: (e) => {
|
|
84
|
+
const f = e.target.files?.[0];
|
|
85
|
+
if (f) onFileSelected(f);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
Dropzone
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=dropzone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/fast-mint/dropzone.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRef } from \"react\";\nimport { ImagePlus, Upload, LogIn } from \"lucide-react\";\nimport { cn } from \"../../utils/cn.js\";\nimport { Button } from \"../button.js\";\nimport type { MediaKind } from \"./types.js\";\n\nexport interface DropzoneProps {\n mediaKindLock?: MediaKind;\n presentation?: \"inline\" | \"dialog\";\n hasWallet: boolean;\n onRequireWallet: () => void;\n onFileSelected: (file: File) => void;\n connectLabel?: string;\n}\n\nexport function Dropzone({\n mediaKindLock,\n presentation = \"inline\",\n hasWallet,\n onRequireWallet,\n onFileSelected,\n connectLabel = \"Sign in\",\n}: DropzoneProps) {\n const mediaInputRef = useRef<HTMLInputElement>(null);\n\n const openMediaPicker = () => {\n if (!hasWallet) { onRequireWallet(); return; }\n mediaInputRef.current?.click();\n };\n\n return (\n <section\n role=\"button\"\n tabIndex={0}\n aria-label={hasWallet ? \"Upload media\" : `${connectLabel} to upload media`}\n onClick={openMediaPicker}\n onKeyDown={(e) => { if (e.key === \"Enter\" || e.key === \" \") { e.preventDefault(); openMediaPicker(); } }}\n onDragOver={(e) => e.preventDefault()}\n onDrop={(e) => { e.preventDefault(); if (!hasWallet) { onRequireWallet(); return; } const f = e.dataTransfer.files?.[0]; if (f) onFileSelected(f); }}\n className={cn(\n \"relative flex flex-col items-center justify-center gap-4 cursor-pointer transition-colors text-center rounded-3xl border-[3px] border-dashed border-brand-blue/40 hover:border-brand-blue/70 hover:bg-brand-blue/[0.04] p-6\",\n presentation === \"dialog\" ? \"min-h-[16rem] sm:min-h-[18rem]\" : \"min-h-[20rem] sm:min-h-[24rem]\"\n )}\n >\n <div className=\"h-14 w-14 rounded-2xl bg-muted flex items-center justify-center\">\n <ImagePlus className=\"h-6 w-6 text-muted-foreground\" />\n </div>\n <div className=\"space-y-1.5 px-6\">\n <h2 className=\"text-2xl sm:text-3xl font-bold tracking-tight\">\n {mediaKindLock ? `Drop or upload an ${mediaKindLock}` : \"Drop or upload your media\"}\n </h2>\n <p className=\"text-base text-muted-foreground max-w-sm mx-auto\">\n {mediaKindLock === \"image\" ? \"It becomes your avatar and app theme.\" : \"Protect your creation and monetize it worldwide.\"}\n </p>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"rounded-full mt-1 bg-card\"\n onClick={(e) => { e.stopPropagation(); openMediaPicker(); }}\n >\n {hasWallet ? (\n <>\n <Upload className=\"h-3.5 w-3.5 mr-1.5\" />\n Browse files\n </>\n ) : (\n <>\n <LogIn className=\"h-3.5 w-3.5 mr-1.5\" />\n {connectLabel}\n </>\n )}\n </Button>\n <p className=\"text-2xs text-muted-foreground/70\">\n {mediaKindLock === \"image\" ? \"JPG, PNG, GIF, WebP, or SVG up to 100 MB\" : \"Images, audio, video, and PDFs up to 100 MB; other documents up to 20 MB\"}\n </p>\n <input\n ref={mediaInputRef}\n type=\"file\"\n accept={mediaKindLock === \"image\" ? \"image/*\" : undefined}\n className=\"hidden\"\n onChange={(e) => { const f = e.target.files?.[0]; if (f) onFileSelected(f); }}\n />\n </section>\n );\n}\n"],"mappings":";AA+CQ,SAiBE,UAjBF,KAEF,YAFE;AA7CR,SAAS,cAAc;AACvB,SAAS,WAAW,QAAQ,aAAa;AACzC,SAAS,UAAU;AACnB,SAAS,cAAc;AAYhB,SAAS,SAAS;AAAA,EACvB;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AACjB,GAAkB;AAChB,QAAM,gBAAgB,OAAyB,IAAI;AAEnD,QAAM,kBAAkB,MAAM;AAC5B,QAAI,CAAC,WAAW;AAAE,sBAAgB;AAAG;AAAA,IAAQ;AAC7C,kBAAc,SAAS,MAAM;AAAA,EAC/B;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,UAAU;AAAA,MACV,cAAY,YAAY,iBAAiB,GAAG,YAAY;AAAA,MACxD,SAAS;AAAA,MACT,WAAW,CAAC,MAAM;AAAE,YAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AAAE,YAAE,eAAe;AAAG,0BAAgB;AAAA,QAAG;AAAA,MAAE;AAAA,MACvG,YAAY,CAAC,MAAM,EAAE,eAAe;AAAA,MACpC,QAAQ,CAAC,MAAM;AAAE,UAAE,eAAe;AAAG,YAAI,CAAC,WAAW;AAAE,0BAAgB;AAAG;AAAA,QAAQ;AAAE,cAAM,IAAI,EAAE,aAAa,QAAQ,CAAC;AAAG,YAAI,EAAG,gBAAe,CAAC;AAAA,MAAG;AAAA,MACnJ,WAAW;AAAA,QACT;AAAA,QACA,iBAAiB,WAAW,mCAAmC;AAAA,MACjE;AAAA,MAEA;AAAA,4BAAC,SAAI,WAAU,mEACb,8BAAC,aAAU,WAAU,iCAAgC,GACvD;AAAA,QACA,qBAAC,SAAI,WAAU,oBACb;AAAA,8BAAC,QAAG,WAAU,iDACX,0BAAgB,qBAAqB,aAAa,KAAK,6BAC1D;AAAA,UACA,oBAAC,OAAE,WAAU,oDACV,4BAAkB,UAAU,0CAA0C,oDACzE;AAAA,WACF;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,WAAU;AAAA,YACV,SAAS,CAAC,MAAM;AAAE,gBAAE,gBAAgB;AAAG,8BAAgB;AAAA,YAAG;AAAA,YAEzD,sBACC,iCACE;AAAA,kCAAC,UAAO,WAAU,sBAAqB;AAAA,cAAE;AAAA,eAE3C,IAEA,iCACE;AAAA,kCAAC,SAAM,WAAU,sBAAqB;AAAA,cACrC;AAAA,eACH;AAAA;AAAA,QAEJ;AAAA,QACA,oBAAC,OAAE,WAAU,qCACV,4BAAkB,UAAU,6CAA6C,4EAC5E;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YACL,QAAQ,kBAAkB,UAAU,YAAY;AAAA,YAChD,WAAU;AAAA,YACV,UAAU,CAAC,MAAM;AAAE,oBAAM,IAAI,EAAE,OAAO,QAAQ,CAAC;AAAG,kBAAI,EAAG,gBAAe,CAAC;AAAA,YAAG;AAAA;AAAA,QAC9E;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|