@medialane/ui 0.4.0 → 0.4.2

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.
Files changed (36) hide show
  1. package/README.md +219 -0
  2. package/dist/components/activity-ticker.cjs +1 -2
  3. package/dist/components/activity-ticker.cjs.map +1 -1
  4. package/dist/components/activity-ticker.d.cts +2 -1
  5. package/dist/components/activity-ticker.d.ts +2 -1
  6. package/dist/components/activity-ticker.js +1 -2
  7. package/dist/components/activity-ticker.js.map +1 -1
  8. package/dist/components/discover-collections-strip.cjs +5 -3
  9. package/dist/components/discover-collections-strip.cjs.map +1 -1
  10. package/dist/components/discover-collections-strip.d.cts +3 -1
  11. package/dist/components/discover-collections-strip.d.ts +3 -1
  12. package/dist/components/discover-collections-strip.js +5 -3
  13. package/dist/components/discover-collections-strip.js.map +1 -1
  14. package/dist/components/discover-creators-strip.cjs +7 -5
  15. package/dist/components/discover-creators-strip.cjs.map +1 -1
  16. package/dist/components/discover-creators-strip.d.cts +3 -1
  17. package/dist/components/discover-creators-strip.d.ts +3 -1
  18. package/dist/components/discover-creators-strip.js +7 -5
  19. package/dist/components/discover-creators-strip.js.map +1 -1
  20. package/dist/components/discover-hero.cjs +3 -2
  21. package/dist/components/discover-hero.cjs.map +1 -1
  22. package/dist/components/discover-hero.d.cts +2 -1
  23. package/dist/components/discover-hero.d.ts +2 -1
  24. package/dist/components/discover-hero.js +3 -2
  25. package/dist/components/discover-hero.js.map +1 -1
  26. package/dist/components/hero-slider.cjs +8 -11
  27. package/dist/components/hero-slider.cjs.map +1 -1
  28. package/dist/components/hero-slider.d.cts +6 -1
  29. package/dist/components/hero-slider.d.ts +6 -1
  30. package/dist/components/hero-slider.js +7 -10
  31. package/dist/components/hero-slider.js.map +1 -1
  32. package/dist/data/launchpad-services.cjs +38 -38
  33. package/dist/data/launchpad-services.cjs.map +1 -1
  34. package/dist/data/launchpad-services.js +38 -38
  35. package/dist/data/launchpad-services.js.map +1 -1
  36. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/discover-creators-strip.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Users, ArrowRight, AtSign } from \"lucide-react\";\nimport { FadeIn } from \"./motion-primitives.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport type { ApiCreatorProfile } from \"@medialane/sdk\";\n\nexport interface DiscoverCreatorsStripProps {\n creators: ApiCreatorProfile[];\n isLoading: boolean;\n getHref: (creator: ApiCreatorProfile) => string;\n allCreatorsHref?: string;\n}\n\nfunction CreatorChipSkeleton() {\n return (\n <div className=\"shrink-0 w-64 aspect-[3/4] rounded-xl bg-muted animate-pulse\" />\n );\n}\n\nfunction CreatorChip({\n creator,\n href,\n}: {\n creator: ApiCreatorProfile;\n href: string;\n}) {\n const [avatarError, setAvatarError] = useState(false);\n const [bannerError, setBannerError] = useState(false);\n\n const bannerSrc = creator.bannerImage ?? creator.collectionImage ?? null;\n const avatarSrc = creator.avatarImage ?? creator.collectionImage ?? null;\n\n const bannerUrl = bannerSrc && !bannerError ? ipfsToHttp(bannerSrc) : null;\n const avatarUrl = avatarSrc && !avatarError ? ipfsToHttp(avatarSrc) : null;\n\n const displayName = creator.displayName || `@${creator.username}`;\n\n return (\n <a\n href={href}\n className=\"block shrink-0 w-64 snap-start active:scale-[0.97] transition-transform duration-150 select-none\"\n >\n <div className=\"relative aspect-[3/4] rounded-xl overflow-hidden bg-muted\">\n {bannerUrl && (\n <img\n src={bannerUrl}\n alt=\"\"\n aria-hidden\n loading=\"lazy\"\n className=\"absolute inset-0 w-full h-full object-cover\"\n onError={() => setBannerError(true)}\n />\n )}\n <div className=\"absolute inset-0 bg-gradient-to-t from-black/80 via-black/10 to-transparent\" />\n <div className=\"absolute bottom-0 inset-x-0 p-2.5 space-y-1.5\">\n <div className=\"h-8 w-8 rounded-full ring-2 ring-white/20 overflow-hidden bg-muted flex items-center justify-center\">\n {avatarUrl ? (\n <img\n src={avatarUrl}\n alt={displayName ?? \"\"}\n loading=\"lazy\"\n className=\"h-full w-full object-cover\"\n onError={() => setAvatarError(true)}\n />\n ) : (\n <span className=\"text-xs font-black text-white/60\">\n {(displayName ?? \"?\").charAt(0).toUpperCase()}\n </span>\n )}\n </div>\n <div>\n <p className=\"font-bold text-white text-xs truncate\">{displayName}</p>\n <p className=\"text-[10px] text-white/55 flex items-center gap-0.5\">\n <AtSign className=\"h-2 w-2 shrink-0\" />\n <span className=\"truncate\">{creator.username}</span>\n </p>\n </div>\n </div>\n </div>\n </a>\n );\n}\n\nexport function DiscoverCreatorsStrip({\n creators,\n isLoading,\n getHref,\n allCreatorsHref = \"/creators\",\n}: DiscoverCreatorsStripProps) {\n if (!isLoading && creators.length === 0) return null;\n\n return (\n <FadeIn>\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"section-label\">Creator network</p>\n <div className=\"flex items-center gap-2 mt-0.5\">\n <Users className=\"h-4 w-4 text-brand-purple\" />\n <h2 className=\"text-lg font-bold\">Creators</h2>\n </div>\n </div>\n <a\n href={allCreatorsHref}\n className=\"inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md hover:bg-accent transition-colors\"\n >\n View all <ArrowRight className=\"h-3.5 w-3.5\" />\n </a>\n </div>\n <div className=\"overflow-x-auto scrollbar-hide snap-x snap-mandatory -mx-4 px-4 md:mx-0 md:px-0\">\n <div className=\"flex gap-3 w-max pb-1\">\n {isLoading\n ? Array.from({ length: 6 }).map((_, i) => <CreatorChipSkeleton key={i} />)\n : creators.map((c) => (\n <CreatorChip key={c.walletAddress} creator={c} href={getHref(c)} />\n ))}\n </div>\n </div>\n </div>\n </FadeIn>\n );\n}\n"],"mappings":";AAiBI,cAyDQ,YAzDR;AAfJ,SAAS,gBAAgB;AACzB,SAAS,OAAO,YAAY,cAAc;AAC1C,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAU3B,SAAS,sBAAsB;AAC7B,SACE,oBAAC,SAAI,WAAU,gEAA+D;AAElF;AAEA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AACF,GAGG;AACD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AAEpD,QAAM,YAAY,QAAQ,eAAe,QAAQ,mBAAmB;AACpE,QAAM,YAAY,QAAQ,eAAe,QAAQ,mBAAmB;AAEpE,QAAM,YAAY,aAAa,CAAC,cAAc,WAAW,SAAS,IAAI;AACtE,QAAM,YAAY,aAAa,CAAC,cAAc,WAAW,SAAS,IAAI;AAEtE,QAAM,cAAc,QAAQ,eAAe,IAAI,QAAQ,QAAQ;AAE/D,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAU;AAAA,MAEV,+BAAC,SAAI,WAAU,6DACZ;AAAA,qBACC;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,KAAI;AAAA,YACJ,eAAW;AAAA,YACX,SAAQ;AAAA,YACR,WAAU;AAAA,YACV,SAAS,MAAM,eAAe,IAAI;AAAA;AAAA,QACpC;AAAA,QAEF,oBAAC,SAAI,WAAU,+EAA8E;AAAA,QAC7F,qBAAC,SAAI,WAAU,iDACb;AAAA,8BAAC,SAAI,WAAU,uGACZ,sBACC;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,KAAK,eAAe;AAAA,cACpB,SAAQ;AAAA,cACR,WAAU;AAAA,cACV,SAAS,MAAM,eAAe,IAAI;AAAA;AAAA,UACpC,IAEA,oBAAC,UAAK,WAAU,oCACZ,0BAAe,KAAK,OAAO,CAAC,EAAE,YAAY,GAC9C,GAEJ;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,OAAE,WAAU,yCAAyC,uBAAY;AAAA,YAClE,qBAAC,OAAE,WAAU,uDACX;AAAA,kCAAC,UAAO,WAAU,oBAAmB;AAAA,cACrC,oBAAC,UAAK,WAAU,YAAY,kBAAQ,UAAS;AAAA,eAC/C;AAAA,aACF;AAAA,WACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB;AACpB,GAA+B;AAC7B,MAAI,CAAC,aAAa,SAAS,WAAW,EAAG,QAAO;AAEhD,SACE,oBAAC,UACC,+BAAC,SAAI,WAAU,aACb;AAAA,yBAAC,SAAI,WAAU,qCACb;AAAA,2BAAC,SACC;AAAA,4BAAC,OAAE,WAAU,iBAAgB,6BAAe;AAAA,QAC5C,qBAAC,SAAI,WAAU,kCACb;AAAA,8BAAC,SAAM,WAAU,6BAA4B;AAAA,UAC7C,oBAAC,QAAG,WAAU,qBAAoB,sBAAQ;AAAA,WAC5C;AAAA,SACF;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAM;AAAA,UACN,WAAU;AAAA,UACX;AAAA;AAAA,YACU,oBAAC,cAAW,WAAU,eAAc;AAAA;AAAA;AAAA,MAC/C;AAAA,OACF;AAAA,IACA,oBAAC,SAAI,WAAU,mFACb,8BAAC,SAAI,WAAU,yBACZ,sBACG,MAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,oBAAC,yBAAyB,CAAG,CAAE,IACvE,SAAS,IAAI,CAAC,MACZ,oBAAC,eAAkC,SAAS,GAAG,MAAM,QAAQ,CAAC,KAA5C,EAAE,aAA6C,CAClE,GACP,GACF;AAAA,KACF,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/discover-creators-strip.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Users, ArrowRight, AtSign } from \"lucide-react\";\nimport { FadeIn } from \"./motion-primitives.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport type { ApiCreatorProfile } from \"@medialane/sdk\";\n\nexport interface DiscoverCreatorsStripProps {\n creators: ApiCreatorProfile[];\n isLoading: boolean;\n getHref: (creator: ApiCreatorProfile) => string;\n allCreatorsHref?: string;\n sectionLabel?: string;\n title?: string;\n}\n\nfunction CreatorChipSkeleton() {\n return (\n <div className=\"shrink-0 w-64 aspect-[3/4] rounded-xl bg-muted animate-pulse\" />\n );\n}\n\nfunction CreatorChip({\n creator,\n href,\n}: {\n creator: ApiCreatorProfile;\n href: string;\n}) {\n const [avatarError, setAvatarError] = useState(false);\n const [bannerError, setBannerError] = useState(false);\n\n const bannerSrc = creator.bannerImage ?? null;\n const avatarSrc = creator.avatarImage ?? creator.bannerImage ?? null;\n\n const bannerUrl = bannerSrc && !bannerError ? ipfsToHttp(bannerSrc) : null;\n const avatarUrl = avatarSrc && !avatarError ? ipfsToHttp(avatarSrc) : null;\n\n const displayName = creator.displayName || `@${creator.username}`;\n\n return (\n <a\n href={href}\n className=\"block shrink-0 w-64 snap-start active:scale-[0.97] transition-transform duration-150 select-none\"\n >\n <div className=\"relative aspect-[3/4] rounded-xl overflow-hidden bg-muted\">\n {bannerUrl && (\n <img\n src={bannerUrl}\n alt=\"\"\n aria-hidden\n loading=\"lazy\"\n className=\"absolute inset-0 w-full h-full object-cover\"\n onError={() => setBannerError(true)}\n />\n )}\n <div className=\"absolute inset-0 bg-gradient-to-t from-black/80 via-black/10 to-transparent\" />\n <div className=\"absolute bottom-0 inset-x-0 p-2.5 space-y-1.5\">\n <div className=\"h-8 w-8 rounded-full ring-2 ring-white/20 overflow-hidden bg-muted flex items-center justify-center\">\n {avatarUrl ? (\n <img\n src={avatarUrl}\n alt={displayName ?? \"\"}\n loading=\"lazy\"\n className=\"h-full w-full object-cover\"\n onError={() => setAvatarError(true)}\n />\n ) : (\n <span className=\"text-xs font-black text-white/60\">\n {(displayName ?? \"?\").charAt(0).toUpperCase()}\n </span>\n )}\n </div>\n <div>\n <p className=\"font-bold text-white text-xs truncate\">{displayName}</p>\n <p className=\"text-[10px] text-white/55 flex items-center gap-0.5\">\n <AtSign className=\"h-2 w-2 shrink-0\" />\n <span className=\"truncate\">{creator.username}</span>\n </p>\n </div>\n </div>\n </div>\n </a>\n );\n}\n\nexport function DiscoverCreatorsStrip({\n creators,\n isLoading,\n getHref,\n allCreatorsHref = \"/creators\",\n sectionLabel = \"Creator network\",\n title = \"Creators\",\n}: DiscoverCreatorsStripProps) {\n if (!isLoading && creators.length === 0) return null;\n\n return (\n <FadeIn>\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"section-label\">{sectionLabel}</p>\n <div className=\"flex items-center gap-2 mt-0.5\">\n <Users className=\"h-4 w-4 text-brand-purple\" />\n <h2 className=\"text-lg font-bold\">{title}</h2>\n </div>\n </div>\n <a\n href={allCreatorsHref}\n className=\"inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md hover:bg-accent transition-colors\"\n >\n View all <ArrowRight className=\"h-3.5 w-3.5\" />\n </a>\n </div>\n <div className=\"overflow-x-auto scrollbar-hide snap-x snap-mandatory -mx-4 px-4 md:mx-0 md:px-0\">\n <div className=\"flex gap-3 w-max pb-1\">\n {isLoading\n ? Array.from({ length: 6 }).map((_, i) => <CreatorChipSkeleton key={i} />)\n : creators.map((c) => (\n <CreatorChip key={c.walletAddress} creator={c} href={getHref(c)} />\n ))}\n </div>\n </div>\n </div>\n </FadeIn>\n );\n}\n"],"mappings":";AAmBI,cAyDQ,YAzDR;AAjBJ,SAAS,gBAAgB;AACzB,SAAS,OAAO,YAAY,cAAc;AAC1C,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAY3B,SAAS,sBAAsB;AAC7B,SACE,oBAAC,SAAI,WAAU,gEAA+D;AAElF;AAEA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AACF,GAGG;AACD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AAEpD,QAAM,YAAY,QAAQ,eAAe;AACzC,QAAM,YAAY,QAAQ,eAAe,QAAQ,eAAe;AAEhE,QAAM,YAAY,aAAa,CAAC,cAAc,WAAW,SAAS,IAAI;AACtE,QAAM,YAAY,aAAa,CAAC,cAAc,WAAW,SAAS,IAAI;AAEtE,QAAM,cAAc,QAAQ,eAAe,IAAI,QAAQ,QAAQ;AAE/D,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAU;AAAA,MAEV,+BAAC,SAAI,WAAU,6DACZ;AAAA,qBACC;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,KAAI;AAAA,YACJ,eAAW;AAAA,YACX,SAAQ;AAAA,YACR,WAAU;AAAA,YACV,SAAS,MAAM,eAAe,IAAI;AAAA;AAAA,QACpC;AAAA,QAEF,oBAAC,SAAI,WAAU,+EAA8E;AAAA,QAC7F,qBAAC,SAAI,WAAU,iDACb;AAAA,8BAAC,SAAI,WAAU,uGACZ,sBACC;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,KAAK,eAAe;AAAA,cACpB,SAAQ;AAAA,cACR,WAAU;AAAA,cACV,SAAS,MAAM,eAAe,IAAI;AAAA;AAAA,UACpC,IAEA,oBAAC,UAAK,WAAU,oCACZ,0BAAe,KAAK,OAAO,CAAC,EAAE,YAAY,GAC9C,GAEJ;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,OAAE,WAAU,yCAAyC,uBAAY;AAAA,YAClE,qBAAC,OAAE,WAAU,uDACX;AAAA,kCAAC,UAAO,WAAU,oBAAmB;AAAA,cACrC,oBAAC,UAAK,WAAU,YAAY,kBAAQ,UAAS;AAAA,eAC/C;AAAA,aACF;AAAA,WACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,QAAQ;AACV,GAA+B;AAC7B,MAAI,CAAC,aAAa,SAAS,WAAW,EAAG,QAAO;AAEhD,SACE,oBAAC,UACC,+BAAC,SAAI,WAAU,aACb;AAAA,yBAAC,SAAI,WAAU,qCACb;AAAA,2BAAC,SACC;AAAA,4BAAC,OAAE,WAAU,iBAAiB,wBAAa;AAAA,QAC3C,qBAAC,SAAI,WAAU,kCACb;AAAA,8BAAC,SAAM,WAAU,6BAA4B;AAAA,UAC7C,oBAAC,QAAG,WAAU,qBAAqB,iBAAM;AAAA,WAC3C;AAAA,SACF;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAM;AAAA,UACN,WAAU;AAAA,UACX;AAAA;AAAA,YACU,oBAAC,cAAW,WAAU,eAAc;AAAA;AAAA;AAAA,MAC/C;AAAA,OACF;AAAA,IACA,oBAAC,SAAI,WAAU,mFACb,8BAAC,SAAI,WAAU,yBACZ,sBACG,MAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,oBAAC,yBAAyB,CAAG,CAAE,IACvE,SAAS,IAAI,CAAC,MACZ,oBAAC,eAAkC,SAAS,GAAG,MAAM,QAAQ,CAAC,KAA5C,EAAE,aAA6C,CAClE,GACP,GACF;AAAA,KACF,GACF;AAEJ;","names":[]}
@@ -30,7 +30,8 @@ function DiscoverHero({
30
30
  stats,
31
31
  orders,
32
32
  badgeText = "Creative Works",
33
- headlineText = "Create, share & explore"
33
+ headlineText = "Create, share & explore",
34
+ getTickerHref
34
35
  }) {
35
36
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-6 pt-2 pb-6 border-b border-border/50", children: [
36
37
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -77,7 +78,7 @@ function DiscoverHero({
77
78
  ))
78
79
  }
79
80
  ),
80
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_activity_ticker.ActivityTicker, { orders })
81
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_activity_ticker.ActivityTicker, { orders, getHref: getTickerHref })
81
82
  ] });
82
83
  }
83
84
  // Annotate the CommonJS export names for ESM import in node:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/discover-hero.tsx"],"sourcesContent":["\"use client\";\n\nimport { motion } from \"framer-motion\";\nimport { KineticWords, EASE_OUT } from \"./motion-primitives.js\";\nimport { ActivityTicker } from \"./activity-ticker.js\";\nimport type { ApiOrder } from \"@medialane/sdk\";\n\nexport interface DiscoverHeroProps {\n stats: { collections: number; tokens: number; sales: number } | null;\n orders: ApiOrder[];\n badgeText?: string;\n headlineText?: string;\n}\n\nexport function DiscoverHero({\n stats,\n orders,\n badgeText = \"Creative Works\",\n headlineText = \"Create, share & explore\",\n}: DiscoverHeroProps) {\n return (\n <div className=\"space-y-6 pt-2 pb-6 border-b border-border/50\">\n {/* Badge */}\n <motion.div\n initial={{ opacity: 0, y: 12 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.4, ease: EASE_OUT }}\n >\n <span className=\"pill-badge\">{badgeText}</span>\n </motion.div>\n\n {/* Headline */}\n <motion.div\n className=\"text-3xl sm:text-4xl lg:text-5xl font-black leading-[1.1]\"\n style={{ perspective: \"800px\" }}\n initial={{ opacity: 0, y: 16 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.5, delay: 0.1, ease: EASE_OUT }}\n >\n <span className=\"gradient-text\">\n <KineticWords text={headlineText} />\n </span>\n </motion.div>\n\n {/* Stats chips */}\n {stats && (\n <motion.div\n className=\"flex flex-wrap gap-2\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.4, delay: 0.35, ease: EASE_OUT }}\n >\n {[\n { label: \"Collections\", value: stats.collections },\n { label: \"Assets\", value: stats.tokens },\n { label: \"Sales\", value: stats.sales },\n ].map(({ label, value }) => (\n <div\n key={label}\n className=\"flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm\"\n >\n <span className=\"font-bold tabular-nums\">{value?.toLocaleString() ?? \"—\"}</span>\n <span className=\"text-muted-foreground\">{label}</span>\n </div>\n ))}\n </motion.div>\n )}\n\n {/* Scrolling ticker */}\n <ActivityTicker orders={orders} />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BQ;AA1BR,2BAAuB;AACvB,+BAAuC;AACvC,6BAA+B;AAUxB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,eAAe;AACjB,GAAsB;AACpB,SACE,6CAAC,SAAI,WAAU,iDAEb;AAAA;AAAA,MAAC,4BAAO;AAAA,MAAP;AAAA,QACC,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,QAC7B,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,QAC5B,YAAY,EAAE,UAAU,KAAK,MAAM,kCAAS;AAAA,QAE5C,sDAAC,UAAK,WAAU,cAAc,qBAAU;AAAA;AAAA,IAC1C;AAAA,IAGA;AAAA,MAAC,4BAAO;AAAA,MAAP;AAAA,QACC,WAAU;AAAA,QACV,OAAO,EAAE,aAAa,QAAQ;AAAA,QAC9B,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,QAC7B,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,QAC5B,YAAY,EAAE,UAAU,KAAK,OAAO,KAAK,MAAM,kCAAS;AAAA,QAExD,sDAAC,UAAK,WAAU,iBACd,sDAAC,yCAAa,MAAM,cAAc,GACpC;AAAA;AAAA,IACF;AAAA,IAGC,SACC;AAAA,MAAC,4BAAO;AAAA,MAAP;AAAA,QACC,WAAU;AAAA,QACV,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,YAAY,EAAE,UAAU,KAAK,OAAO,MAAM,MAAM,kCAAS;AAAA,QAExD;AAAA,UACC,EAAE,OAAO,eAAe,OAAO,MAAM,YAAY;AAAA,UACjD,EAAE,OAAO,UAAU,OAAO,MAAM,OAAO;AAAA,UACvC,EAAE,OAAO,SAAS,OAAO,MAAM,MAAM;AAAA,QACvC,EAAE,IAAI,CAAC,EAAE,OAAO,MAAM,MACpB;AAAA,UAAC;AAAA;AAAA,YAEC,WAAU;AAAA,YAEV;AAAA,0DAAC,UAAK,WAAU,0BAA0B,iBAAO,eAAe,KAAK,UAAI;AAAA,cACzE,4CAAC,UAAK,WAAU,yBAAyB,iBAAM;AAAA;AAAA;AAAA,UAJ1C;AAAA,QAKP,CACD;AAAA;AAAA,IACH;AAAA,IAIF,4CAAC,yCAAe,QAAgB;AAAA,KAClC;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/discover-hero.tsx"],"sourcesContent":["\"use client\";\n\nimport { motion } from \"framer-motion\";\nimport { KineticWords, EASE_OUT } from \"./motion-primitives.js\";\nimport { ActivityTicker } from \"./activity-ticker.js\";\nimport type { ApiOrder } from \"@medialane/sdk\";\n\nexport interface DiscoverHeroProps {\n stats: { collections: number; tokens: number; sales: number } | null;\n orders: ApiOrder[];\n badgeText?: string;\n headlineText?: string;\n getTickerHref?: (order: ApiOrder) => string;\n}\n\nexport function DiscoverHero({\n stats,\n orders,\n badgeText = \"Creative Works\",\n headlineText = \"Create, share & explore\",\n getTickerHref,\n}: DiscoverHeroProps) {\n return (\n <div className=\"space-y-6 pt-2 pb-6 border-b border-border/50\">\n {/* Badge */}\n <motion.div\n initial={{ opacity: 0, y: 12 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.4, ease: EASE_OUT }}\n >\n <span className=\"pill-badge\">{badgeText}</span>\n </motion.div>\n\n {/* Headline */}\n <motion.div\n className=\"text-3xl sm:text-4xl lg:text-5xl font-black leading-[1.1]\"\n style={{ perspective: \"800px\" }}\n initial={{ opacity: 0, y: 16 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.5, delay: 0.1, ease: EASE_OUT }}\n >\n <span className=\"gradient-text\">\n <KineticWords text={headlineText} />\n </span>\n </motion.div>\n\n {/* Stats chips */}\n {stats && (\n <motion.div\n className=\"flex flex-wrap gap-2\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.4, delay: 0.35, ease: EASE_OUT }}\n >\n {[\n { label: \"Collections\", value: stats.collections },\n { label: \"Assets\", value: stats.tokens },\n { label: \"Sales\", value: stats.sales },\n ].map(({ label, value }) => (\n <div\n key={label}\n className=\"flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm\"\n >\n <span className=\"font-bold tabular-nums\">{value?.toLocaleString() ?? \"—\"}</span>\n <span className=\"text-muted-foreground\">{label}</span>\n </div>\n ))}\n </motion.div>\n )}\n\n {/* Scrolling ticker */}\n <ActivityTicker orders={orders} getHref={getTickerHref} />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BQ;AA5BR,2BAAuB;AACvB,+BAAuC;AACvC,6BAA+B;AAWxB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,eAAe;AAAA,EACf;AACF,GAAsB;AACpB,SACE,6CAAC,SAAI,WAAU,iDAEb;AAAA;AAAA,MAAC,4BAAO;AAAA,MAAP;AAAA,QACC,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,QAC7B,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,QAC5B,YAAY,EAAE,UAAU,KAAK,MAAM,kCAAS;AAAA,QAE5C,sDAAC,UAAK,WAAU,cAAc,qBAAU;AAAA;AAAA,IAC1C;AAAA,IAGA;AAAA,MAAC,4BAAO;AAAA,MAAP;AAAA,QACC,WAAU;AAAA,QACV,OAAO,EAAE,aAAa,QAAQ;AAAA,QAC9B,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,QAC7B,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,QAC5B,YAAY,EAAE,UAAU,KAAK,OAAO,KAAK,MAAM,kCAAS;AAAA,QAExD,sDAAC,UAAK,WAAU,iBACd,sDAAC,yCAAa,MAAM,cAAc,GACpC;AAAA;AAAA,IACF;AAAA,IAGC,SACC;AAAA,MAAC,4BAAO;AAAA,MAAP;AAAA,QACC,WAAU;AAAA,QACV,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,YAAY,EAAE,UAAU,KAAK,OAAO,MAAM,MAAM,kCAAS;AAAA,QAExD;AAAA,UACC,EAAE,OAAO,eAAe,OAAO,MAAM,YAAY;AAAA,UACjD,EAAE,OAAO,UAAU,OAAO,MAAM,OAAO;AAAA,UACvC,EAAE,OAAO,SAAS,OAAO,MAAM,MAAM;AAAA,QACvC,EAAE,IAAI,CAAC,EAAE,OAAO,MAAM,MACpB;AAAA,UAAC;AAAA;AAAA,YAEC,WAAU;AAAA,YAEV;AAAA,0DAAC,UAAK,WAAU,0BAA0B,iBAAO,eAAe,KAAK,UAAI;AAAA,cACzE,4CAAC,UAAK,WAAU,yBAAyB,iBAAM;AAAA;AAAA;AAAA,UAJ1C;AAAA,QAKP,CACD;AAAA;AAAA,IACH;AAAA,IAIF,4CAAC,yCAAe,QAAgB,SAAS,eAAe;AAAA,KAC1D;AAEJ;","names":[]}
@@ -10,7 +10,8 @@ interface DiscoverHeroProps {
10
10
  orders: ApiOrder[];
11
11
  badgeText?: string;
12
12
  headlineText?: string;
13
+ getTickerHref?: (order: ApiOrder) => string;
13
14
  }
14
- declare function DiscoverHero({ stats, orders, badgeText, headlineText, }: DiscoverHeroProps): react_jsx_runtime.JSX.Element;
15
+ declare function DiscoverHero({ stats, orders, badgeText, headlineText, getTickerHref, }: DiscoverHeroProps): react_jsx_runtime.JSX.Element;
15
16
 
16
17
  export { DiscoverHero, type DiscoverHeroProps };
@@ -10,7 +10,8 @@ interface DiscoverHeroProps {
10
10
  orders: ApiOrder[];
11
11
  badgeText?: string;
12
12
  headlineText?: string;
13
+ getTickerHref?: (order: ApiOrder) => string;
13
14
  }
14
- declare function DiscoverHero({ stats, orders, badgeText, headlineText, }: DiscoverHeroProps): react_jsx_runtime.JSX.Element;
15
+ declare function DiscoverHero({ stats, orders, badgeText, headlineText, getTickerHref, }: DiscoverHeroProps): react_jsx_runtime.JSX.Element;
15
16
 
16
17
  export { DiscoverHero, type DiscoverHeroProps };
@@ -7,7 +7,8 @@ function DiscoverHero({
7
7
  stats,
8
8
  orders,
9
9
  badgeText = "Creative Works",
10
- headlineText = "Create, share & explore"
10
+ headlineText = "Create, share & explore",
11
+ getTickerHref
11
12
  }) {
12
13
  return /* @__PURE__ */ jsxs("div", { className: "space-y-6 pt-2 pb-6 border-b border-border/50", children: [
13
14
  /* @__PURE__ */ jsx(
@@ -54,7 +55,7 @@ function DiscoverHero({
54
55
  ))
55
56
  }
56
57
  ),
57
- /* @__PURE__ */ jsx(ActivityTicker, { orders })
58
+ /* @__PURE__ */ jsx(ActivityTicker, { orders, getHref: getTickerHref })
58
59
  ] });
59
60
  }
60
61
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/discover-hero.tsx"],"sourcesContent":["\"use client\";\n\nimport { motion } from \"framer-motion\";\nimport { KineticWords, EASE_OUT } from \"./motion-primitives.js\";\nimport { ActivityTicker } from \"./activity-ticker.js\";\nimport type { ApiOrder } from \"@medialane/sdk\";\n\nexport interface DiscoverHeroProps {\n stats: { collections: number; tokens: number; sales: number } | null;\n orders: ApiOrder[];\n badgeText?: string;\n headlineText?: string;\n}\n\nexport function DiscoverHero({\n stats,\n orders,\n badgeText = \"Creative Works\",\n headlineText = \"Create, share & explore\",\n}: DiscoverHeroProps) {\n return (\n <div className=\"space-y-6 pt-2 pb-6 border-b border-border/50\">\n {/* Badge */}\n <motion.div\n initial={{ opacity: 0, y: 12 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.4, ease: EASE_OUT }}\n >\n <span className=\"pill-badge\">{badgeText}</span>\n </motion.div>\n\n {/* Headline */}\n <motion.div\n className=\"text-3xl sm:text-4xl lg:text-5xl font-black leading-[1.1]\"\n style={{ perspective: \"800px\" }}\n initial={{ opacity: 0, y: 16 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.5, delay: 0.1, ease: EASE_OUT }}\n >\n <span className=\"gradient-text\">\n <KineticWords text={headlineText} />\n </span>\n </motion.div>\n\n {/* Stats chips */}\n {stats && (\n <motion.div\n className=\"flex flex-wrap gap-2\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.4, delay: 0.35, ease: EASE_OUT }}\n >\n {[\n { label: \"Collections\", value: stats.collections },\n { label: \"Assets\", value: stats.tokens },\n { label: \"Sales\", value: stats.sales },\n ].map(({ label, value }) => (\n <div\n key={label}\n className=\"flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm\"\n >\n <span className=\"font-bold tabular-nums\">{value?.toLocaleString() ?? \"—\"}</span>\n <span className=\"text-muted-foreground\">{label}</span>\n </div>\n ))}\n </motion.div>\n )}\n\n {/* Scrolling ticker */}\n <ActivityTicker orders={orders} />\n </div>\n );\n}\n"],"mappings":";AA4BQ,cA6BI,YA7BJ;AA1BR,SAAS,cAAc;AACvB,SAAS,cAAc,gBAAgB;AACvC,SAAS,sBAAsB;AAUxB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,eAAe;AACjB,GAAsB;AACpB,SACE,qBAAC,SAAI,WAAU,iDAEb;AAAA;AAAA,MAAC,OAAO;AAAA,MAAP;AAAA,QACC,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,QAC7B,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,QAC5B,YAAY,EAAE,UAAU,KAAK,MAAM,SAAS;AAAA,QAE5C,8BAAC,UAAK,WAAU,cAAc,qBAAU;AAAA;AAAA,IAC1C;AAAA,IAGA;AAAA,MAAC,OAAO;AAAA,MAAP;AAAA,QACC,WAAU;AAAA,QACV,OAAO,EAAE,aAAa,QAAQ;AAAA,QAC9B,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,QAC7B,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,QAC5B,YAAY,EAAE,UAAU,KAAK,OAAO,KAAK,MAAM,SAAS;AAAA,QAExD,8BAAC,UAAK,WAAU,iBACd,8BAAC,gBAAa,MAAM,cAAc,GACpC;AAAA;AAAA,IACF;AAAA,IAGC,SACC;AAAA,MAAC,OAAO;AAAA,MAAP;AAAA,QACC,WAAU;AAAA,QACV,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,YAAY,EAAE,UAAU,KAAK,OAAO,MAAM,MAAM,SAAS;AAAA,QAExD;AAAA,UACC,EAAE,OAAO,eAAe,OAAO,MAAM,YAAY;AAAA,UACjD,EAAE,OAAO,UAAU,OAAO,MAAM,OAAO;AAAA,UACvC,EAAE,OAAO,SAAS,OAAO,MAAM,MAAM;AAAA,QACvC,EAAE,IAAI,CAAC,EAAE,OAAO,MAAM,MACpB;AAAA,UAAC;AAAA;AAAA,YAEC,WAAU;AAAA,YAEV;AAAA,kCAAC,UAAK,WAAU,0BAA0B,iBAAO,eAAe,KAAK,UAAI;AAAA,cACzE,oBAAC,UAAK,WAAU,yBAAyB,iBAAM;AAAA;AAAA;AAAA,UAJ1C;AAAA,QAKP,CACD;AAAA;AAAA,IACH;AAAA,IAIF,oBAAC,kBAAe,QAAgB;AAAA,KAClC;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/discover-hero.tsx"],"sourcesContent":["\"use client\";\n\nimport { motion } from \"framer-motion\";\nimport { KineticWords, EASE_OUT } from \"./motion-primitives.js\";\nimport { ActivityTicker } from \"./activity-ticker.js\";\nimport type { ApiOrder } from \"@medialane/sdk\";\n\nexport interface DiscoverHeroProps {\n stats: { collections: number; tokens: number; sales: number } | null;\n orders: ApiOrder[];\n badgeText?: string;\n headlineText?: string;\n getTickerHref?: (order: ApiOrder) => string;\n}\n\nexport function DiscoverHero({\n stats,\n orders,\n badgeText = \"Creative Works\",\n headlineText = \"Create, share & explore\",\n getTickerHref,\n}: DiscoverHeroProps) {\n return (\n <div className=\"space-y-6 pt-2 pb-6 border-b border-border/50\">\n {/* Badge */}\n <motion.div\n initial={{ opacity: 0, y: 12 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.4, ease: EASE_OUT }}\n >\n <span className=\"pill-badge\">{badgeText}</span>\n </motion.div>\n\n {/* Headline */}\n <motion.div\n className=\"text-3xl sm:text-4xl lg:text-5xl font-black leading-[1.1]\"\n style={{ perspective: \"800px\" }}\n initial={{ opacity: 0, y: 16 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.5, delay: 0.1, ease: EASE_OUT }}\n >\n <span className=\"gradient-text\">\n <KineticWords text={headlineText} />\n </span>\n </motion.div>\n\n {/* Stats chips */}\n {stats && (\n <motion.div\n className=\"flex flex-wrap gap-2\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.4, delay: 0.35, ease: EASE_OUT }}\n >\n {[\n { label: \"Collections\", value: stats.collections },\n { label: \"Assets\", value: stats.tokens },\n { label: \"Sales\", value: stats.sales },\n ].map(({ label, value }) => (\n <div\n key={label}\n className=\"flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm\"\n >\n <span className=\"font-bold tabular-nums\">{value?.toLocaleString() ?? \"—\"}</span>\n <span className=\"text-muted-foreground\">{label}</span>\n </div>\n ))}\n </motion.div>\n )}\n\n {/* Scrolling ticker */}\n <ActivityTicker orders={orders} getHref={getTickerHref} />\n </div>\n );\n}\n"],"mappings":";AA8BQ,cA6BI,YA7BJ;AA5BR,SAAS,cAAc;AACvB,SAAS,cAAc,gBAAgB;AACvC,SAAS,sBAAsB;AAWxB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,eAAe;AAAA,EACf;AACF,GAAsB;AACpB,SACE,qBAAC,SAAI,WAAU,iDAEb;AAAA;AAAA,MAAC,OAAO;AAAA,MAAP;AAAA,QACC,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,QAC7B,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,QAC5B,YAAY,EAAE,UAAU,KAAK,MAAM,SAAS;AAAA,QAE5C,8BAAC,UAAK,WAAU,cAAc,qBAAU;AAAA;AAAA,IAC1C;AAAA,IAGA;AAAA,MAAC,OAAO;AAAA,MAAP;AAAA,QACC,WAAU;AAAA,QACV,OAAO,EAAE,aAAa,QAAQ;AAAA,QAC9B,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,QAC7B,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,QAC5B,YAAY,EAAE,UAAU,KAAK,OAAO,KAAK,MAAM,SAAS;AAAA,QAExD,8BAAC,UAAK,WAAU,iBACd,8BAAC,gBAAa,MAAM,cAAc,GACpC;AAAA;AAAA,IACF;AAAA,IAGC,SACC;AAAA,MAAC,OAAO;AAAA,MAAP;AAAA,QACC,WAAU;AAAA,QACV,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,YAAY,EAAE,UAAU,KAAK,OAAO,MAAM,MAAM,SAAS;AAAA,QAExD;AAAA,UACC,EAAE,OAAO,eAAe,OAAO,MAAM,YAAY;AAAA,UACjD,EAAE,OAAO,UAAU,OAAO,MAAM,OAAO;AAAA,UACvC,EAAE,OAAO,SAAS,OAAO,MAAM,MAAM;AAAA,QACvC,EAAE,IAAI,CAAC,EAAE,OAAO,MAAM,MACpB;AAAA,UAAC;AAAA;AAAA,YAEC,WAAU;AAAA,YAEV;AAAA,kCAAC,UAAK,WAAU,0BAA0B,iBAAO,eAAe,KAAK,UAAI;AAAA,cACzE,oBAAC,UAAK,WAAU,yBAAyB,iBAAM;AAAA;AAAA;AAAA,UAJ1C;AAAA,QAKP,CACD;AAAA;AAAA,IACH;AAAA,IAIF,oBAAC,kBAAe,QAAgB,SAAS,eAAe;AAAA,KAC1D;AAEJ;","names":[]}
@@ -39,6 +39,7 @@ var import_link = __toESM(require("next/link"), 1);
39
39
  var import_image = __toESM(require("next/image"), 1);
40
40
  var import_lucide_react = require("lucide-react");
41
41
  var import_cn = require("../utils/cn.js");
42
+ var import_ipfs = require("../utils/ipfs.js");
42
43
  function formatFloorPrice(price) {
43
44
  if (!price) return "";
44
45
  const n = parseFloat(price);
@@ -47,25 +48,20 @@ function formatFloorPrice(price) {
47
48
  if (n >= 1) return n.toFixed(2);
48
49
  return n.toPrecision(3);
49
50
  }
50
- function ipfsToHttp(uri) {
51
- if (!uri) return "";
52
- if (uri.startsWith("ipfs://")) return uri.replace("ipfs://", "https://gateway.pinata.cloud/ipfs/");
53
- return uri;
54
- }
55
- function HeroPlaceholder() {
51
+ function HeroPlaceholder({ hrefs }) {
56
52
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/50 flex flex-col items-center justify-center gap-4 text-center px-6 overflow-hidden", children: [
57
53
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute aurora-purple w-[600px] h-[600px] opacity-20 -top-24 -left-24" }),
58
54
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute aurora-blue w-[400px] h-[400px] opacity-15 -bottom-16 -right-16" }),
59
55
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-4xl sm:text-6xl font-black gradient-text relative z-10", children: "Medialane" }),
60
56
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-muted-foreground text-lg relative z-10 max-w-md", children: "New monetization revenues for creative works" }),
61
57
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex gap-3 relative z-10", children: [
62
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: "/marketplace", className: "inline-flex items-center justify-center rounded-[11px] bg-brand-blue px-4 py-2 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all", children: "Markets" }),
63
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: "/create/asset", className: "inline-flex items-center justify-center rounded-[11px] border border-white/20 bg-background/20 backdrop-blur-sm px-4 py-2 text-sm font-semibold text-white hover:bg-white/10 transition-all", children: "Create" })
58
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: hrefs.markets, className: "inline-flex items-center justify-center rounded-[11px] bg-brand-blue px-4 py-2 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all", children: "Markets" }),
59
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: hrefs.create, className: "inline-flex items-center justify-center rounded-[11px] border border-white/20 bg-background/20 backdrop-blur-sm px-4 py-2 text-sm font-semibold text-white hover:bg-white/10 transition-all", children: "Create" })
64
60
  ] })
65
61
  ] });
66
62
  }
67
63
  function HeroSlide({ collection, active, getHref }) {
68
- const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;
64
+ const imageUrl = collection.image ? (0, import_ipfs.ipfsToHttp)(collection.image) : null;
69
65
  const name = collection.name ?? "Collection";
70
66
  const floor = collection.floorPrice;
71
67
  const supply = collection.totalSupply;
@@ -101,7 +97,8 @@ function HeroSlide({ collection, active, getHref }) {
101
97
  function HeroSliderSkeleton() {
102
98
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", { className: "relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] bg-muted animate-pulse" });
103
99
  }
104
- function HeroSlider({ collections, isLoading, getHref }) {
100
+ function HeroSlider({ collections, isLoading, getHref, placeholderHrefs = {} }) {
101
+ const hrefs = { markets: "/marketplace", create: "/create/asset", ...placeholderHrefs };
105
102
  const [current, setCurrent] = (0, import_react.useState)(0);
106
103
  const count = collections.length;
107
104
  const next = (0, import_react.useCallback)(() => {
@@ -116,7 +113,7 @@ function HeroSlider({ collections, isLoading, getHref }) {
116
113
  return () => clearInterval(id);
117
114
  }, [count, next]);
118
115
  if (isLoading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HeroSliderSkeleton, {});
119
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", { className: "relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] overflow-hidden bg-muted", children: count === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HeroPlaceholder, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
116
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", { className: "relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] overflow-hidden bg-muted", children: count === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HeroPlaceholder, { hrefs }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
120
117
  collections.map((col, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HeroSlide, { collection: col, active: i === current, getHref }, col.contractAddress)),
121
118
  count > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
122
119
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: prev, "aria-label": "Previous slide", className: "absolute left-3 top-1/2 -translate-y-1/2 z-10 h-9 w-9 rounded-full bg-black/40 hover:bg-black/60 backdrop-blur-sm flex items-center justify-center transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ChevronLeft, { className: "h-5 w-5 text-white" }) }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/hero-slider.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { ChevronLeft, ChevronRight, ArrowRight } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\nexport interface HeroSliderProps {\n collections: ApiCollection[];\n isLoading: boolean;\n getHref: (collection: ApiCollection) => string;\n}\n\nfunction formatFloorPrice(price: string | null | undefined): string {\n if (!price) return \"\";\n const n = parseFloat(price);\n if (isNaN(n)) return price;\n if (n >= 1000) return `${(n / 1000).toFixed(1)}K`;\n if (n >= 1) return n.toFixed(2);\n return n.toPrecision(3);\n}\n\nfunction ipfsToHttp(uri: string): string {\n if (!uri) return \"\";\n if (uri.startsWith(\"ipfs://\")) return uri.replace(\"ipfs://\", \"https://gateway.pinata.cloud/ipfs/\");\n return uri;\n}\n\nfunction HeroPlaceholder() {\n return (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/50 flex flex-col items-center justify-center gap-4 text-center px-6 overflow-hidden\">\n <div className=\"absolute aurora-purple w-[600px] h-[600px] opacity-20 -top-24 -left-24\" />\n <div className=\"absolute aurora-blue w-[400px] h-[400px] opacity-15 -bottom-16 -right-16\" />\n <h2 className=\"text-4xl sm:text-6xl font-black gradient-text relative z-10\">Medialane</h2>\n <p className=\"text-muted-foreground text-lg relative z-10 max-w-md\">\n New monetization revenues for creative works\n </p>\n <div className=\"flex gap-3 relative z-10\">\n <Link href=\"/marketplace\" className=\"inline-flex items-center justify-center rounded-[11px] bg-brand-blue px-4 py-2 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all\">\n Markets\n </Link>\n <Link href=\"/create/asset\" className=\"inline-flex items-center justify-center rounded-[11px] border border-white/20 bg-background/20 backdrop-blur-sm px-4 py-2 text-sm font-semibold text-white hover:bg-white/10 transition-all\">\n Create\n </Link>\n </div>\n </div>\n );\n}\n\nfunction HeroSlide({ collection, active, getHref }: { collection: ApiCollection; active: boolean; getHref: (col: ApiCollection) => string }) {\n const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;\n const name = collection.name ?? \"Collection\";\n const floor = collection.floorPrice;\n const supply = collection.totalSupply;\n\n return (\n <div className={cn(\"absolute inset-0 transition-opacity duration-700\", active ? \"opacity-100\" : \"opacity-0 pointer-events-none\")}>\n {imageUrl ? (\n <div className=\"absolute inset-0 overflow-hidden\">\n <div className=\"animate-kenburns absolute inset-0\">\n <Image src={imageUrl} alt={name} fill className=\"object-cover\" priority={active} unoptimized />\n </div>\n </div>\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/40 via-brand-blue/20 to-brand-navy/60\" />\n )}\n <div className=\"absolute inset-0 bg-gradient-to-t from-black/40 via-black/30 to-black/0\" />\n <div className=\"absolute bottom-0 left-0 right-0 p-6 sm:p-10 flex flex-col gap-3\">\n <h2 className=\"text-4xl lg:text-5xl font-semibold text-white leading-tight\">{name}</h2>\n <div className=\"flex items-center gap-4 text-sm text-white/70\">\n {supply != null && <span>{supply.toLocaleString()} items</span>}\n {floor && <span className=\"text-white font-semibold\">Floor {formatFloorPrice(floor)}</span>}\n </div>\n <Link\n href={getHref(collection)}\n className=\"self-start mt-2 inline-flex items-center gap-1.5 bg-white text-black hover:bg-white/90 font-semibold px-4 py-2 rounded-[11px] text-sm transition-all active:scale-[0.98]\"\n >\n View Collection <ArrowRight className=\"h-4 w-4\" />\n </Link>\n </div>\n </div>\n );\n}\n\nexport function HeroSliderSkeleton() {\n return <section className=\"relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] bg-muted animate-pulse\" />;\n}\n\nexport function HeroSlider({ collections, isLoading, getHref }: HeroSliderProps) {\n const [current, setCurrent] = useState(0);\n const count = collections.length;\n\n const next = useCallback(() => { if (count > 1) setCurrent((c) => (c + 1) % count); }, [count]);\n const prev = useCallback(() => { if (count > 1) setCurrent((c) => (c - 1 + count) % count); }, [count]);\n\n useEffect(() => {\n if (count <= 1) return;\n const id = setInterval(next, 7000);\n return () => clearInterval(id);\n }, [count, next]);\n\n if (isLoading) return <HeroSliderSkeleton />;\n\n return (\n <section className=\"relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] overflow-hidden bg-muted\">\n {count === 0 ? (\n <HeroPlaceholder />\n ) : (\n <>\n {collections.map((col, i) => (\n <HeroSlide key={col.contractAddress} collection={col} active={i === current} getHref={getHref} />\n ))}\n {count > 1 && (\n <>\n <button onClick={prev} aria-label=\"Previous slide\" className=\"absolute left-3 top-1/2 -translate-y-1/2 z-10 h-9 w-9 rounded-full bg-black/40 hover:bg-black/60 backdrop-blur-sm flex items-center justify-center transition-colors\">\n <ChevronLeft className=\"h-5 w-5 text-white\" />\n </button>\n <button onClick={next} aria-label=\"Next slide\" className=\"absolute right-3 top-1/2 -translate-y-1/2 z-10 h-9 w-9 rounded-full bg-black/40 hover:bg-black/60 backdrop-blur-sm flex items-center justify-center transition-colors\">\n <ChevronRight className=\"h-5 w-5 text-white\" />\n </button>\n <div className=\"absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-1.5 z-10\">\n {collections.map((_, i) => (\n <button key={i} onClick={() => setCurrent(i)} aria-label={`Go to slide ${i + 1}`} className={cn(\"h-1.5 rounded-full transition-all\", i === current ? \"w-6 bg-white\" : \"w-1.5 bg-white/40\")} />\n ))}\n </div>\n </>\n )}\n </>\n )}\n </section>\n );\n}\n"],"mappings":"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","names":["Link","Image"]}
1
+ {"version":3,"sources":["../../src/components/hero-slider.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { ChevronLeft, ChevronRight, ArrowRight } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\nexport interface HeroSliderProps {\n collections: ApiCollection[];\n isLoading: boolean;\n getHref: (collection: ApiCollection) => string;\n /** Optional placeholder CTA hrefs — defaults to \"/marketplace\" and \"/create/asset\" */\n placeholderHrefs?: { markets?: string; create?: string };\n}\n\nfunction formatFloorPrice(price: string | null | undefined): string {\n if (!price) return \"\";\n const n = parseFloat(price);\n if (isNaN(n)) return price;\n if (n >= 1000) return `${(n / 1000).toFixed(1)}K`;\n if (n >= 1) return n.toFixed(2);\n return n.toPrecision(3);\n}\n\nfunction HeroPlaceholder({ hrefs }: { hrefs: Required<HeroSliderProps>[\"placeholderHrefs\"] }) {\n return (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/50 flex flex-col items-center justify-center gap-4 text-center px-6 overflow-hidden\">\n <div className=\"absolute aurora-purple w-[600px] h-[600px] opacity-20 -top-24 -left-24\" />\n <div className=\"absolute aurora-blue w-[400px] h-[400px] opacity-15 -bottom-16 -right-16\" />\n <h2 className=\"text-4xl sm:text-6xl font-black gradient-text relative z-10\">Medialane</h2>\n <p className=\"text-muted-foreground text-lg relative z-10 max-w-md\">\n New monetization revenues for creative works\n </p>\n <div className=\"flex gap-3 relative z-10\">\n <Link href={hrefs.markets!} className=\"inline-flex items-center justify-center rounded-[11px] bg-brand-blue px-4 py-2 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all\">\n Markets\n </Link>\n <Link href={hrefs.create!} className=\"inline-flex items-center justify-center rounded-[11px] border border-white/20 bg-background/20 backdrop-blur-sm px-4 py-2 text-sm font-semibold text-white hover:bg-white/10 transition-all\">\n Create\n </Link>\n </div>\n </div>\n );\n}\n\nfunction HeroSlide({ collection, active, getHref }: { collection: ApiCollection; active: boolean; getHref: (col: ApiCollection) => string }) {\n const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;\n const name = collection.name ?? \"Collection\";\n const floor = collection.floorPrice;\n const supply = collection.totalSupply;\n\n return (\n <div className={cn(\"absolute inset-0 transition-opacity duration-700\", active ? \"opacity-100\" : \"opacity-0 pointer-events-none\")}>\n {imageUrl ? (\n <div className=\"absolute inset-0 overflow-hidden\">\n <div className=\"animate-kenburns absolute inset-0\">\n <Image src={imageUrl} alt={name} fill className=\"object-cover\" priority={active} unoptimized />\n </div>\n </div>\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/40 via-brand-blue/20 to-brand-navy/60\" />\n )}\n <div className=\"absolute inset-0 bg-gradient-to-t from-black/40 via-black/30 to-black/0\" />\n <div className=\"absolute bottom-0 left-0 right-0 p-6 sm:p-10 flex flex-col gap-3\">\n <h2 className=\"text-4xl lg:text-5xl font-semibold text-white leading-tight\">{name}</h2>\n <div className=\"flex items-center gap-4 text-sm text-white/70\">\n {supply != null && <span>{supply.toLocaleString()} items</span>}\n {floor && <span className=\"text-white font-semibold\">Floor {formatFloorPrice(floor)}</span>}\n </div>\n <Link\n href={getHref(collection)}\n className=\"self-start mt-2 inline-flex items-center gap-1.5 bg-white text-black hover:bg-white/90 font-semibold px-4 py-2 rounded-[11px] text-sm transition-all active:scale-[0.98]\"\n >\n View Collection <ArrowRight className=\"h-4 w-4\" />\n </Link>\n </div>\n </div>\n );\n}\n\nexport function HeroSliderSkeleton() {\n return <section className=\"relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] bg-muted animate-pulse\" />;\n}\n\nexport function HeroSlider({ collections, isLoading, getHref, placeholderHrefs = {} }: HeroSliderProps) {\n const hrefs = { markets: \"/marketplace\", create: \"/create/asset\", ...placeholderHrefs };\n const [current, setCurrent] = useState(0);\n const count = collections.length;\n\n const next = useCallback(() => { if (count > 1) setCurrent((c) => (c + 1) % count); }, [count]);\n const prev = useCallback(() => { if (count > 1) setCurrent((c) => (c - 1 + count) % count); }, [count]);\n\n useEffect(() => {\n if (count <= 1) return;\n const id = setInterval(next, 7000);\n return () => clearInterval(id);\n }, [count, next]);\n\n if (isLoading) return <HeroSliderSkeleton />;\n\n return (\n <section className=\"relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] overflow-hidden bg-muted\">\n {count === 0 ? (\n <HeroPlaceholder hrefs={hrefs} />\n ) : (\n <>\n {collections.map((col, i) => (\n <HeroSlide key={col.contractAddress} collection={col} active={i === current} getHref={getHref} />\n ))}\n {count > 1 && (\n <>\n <button onClick={prev} aria-label=\"Previous slide\" className=\"absolute left-3 top-1/2 -translate-y-1/2 z-10 h-9 w-9 rounded-full bg-black/40 hover:bg-black/60 backdrop-blur-sm flex items-center justify-center transition-colors\">\n <ChevronLeft className=\"h-5 w-5 text-white\" />\n </button>\n <button onClick={next} aria-label=\"Next slide\" className=\"absolute right-3 top-1/2 -translate-y-1/2 z-10 h-9 w-9 rounded-full bg-black/40 hover:bg-black/60 backdrop-blur-sm flex items-center justify-center transition-colors\">\n <ChevronRight className=\"h-5 w-5 text-white\" />\n </button>\n <div className=\"absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-1.5 z-10\">\n {collections.map((_, i) => (\n <button key={i} onClick={() => setCurrent(i)} aria-label={`Go to slide ${i + 1}`} className={cn(\"h-1.5 rounded-full transition-all\", i === current ? \"w-6 bg-white\" : \"w-1.5 bg-white/40\")} />\n ))}\n </div>\n </>\n )}\n </>\n )}\n </section>\n );\n}\n"],"mappings":"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","names":["Link","Image"]}
@@ -5,8 +5,13 @@ interface HeroSliderProps {
5
5
  collections: ApiCollection[];
6
6
  isLoading: boolean;
7
7
  getHref: (collection: ApiCollection) => string;
8
+ /** Optional placeholder CTA hrefs — defaults to "/marketplace" and "/create/asset" */
9
+ placeholderHrefs?: {
10
+ markets?: string;
11
+ create?: string;
12
+ };
8
13
  }
9
14
  declare function HeroSliderSkeleton(): react_jsx_runtime.JSX.Element;
10
- declare function HeroSlider({ collections, isLoading, getHref }: HeroSliderProps): react_jsx_runtime.JSX.Element;
15
+ declare function HeroSlider({ collections, isLoading, getHref, placeholderHrefs }: HeroSliderProps): react_jsx_runtime.JSX.Element;
11
16
 
12
17
  export { HeroSlider, type HeroSliderProps, HeroSliderSkeleton };
@@ -5,8 +5,13 @@ interface HeroSliderProps {
5
5
  collections: ApiCollection[];
6
6
  isLoading: boolean;
7
7
  getHref: (collection: ApiCollection) => string;
8
+ /** Optional placeholder CTA hrefs — defaults to "/marketplace" and "/create/asset" */
9
+ placeholderHrefs?: {
10
+ markets?: string;
11
+ create?: string;
12
+ };
8
13
  }
9
14
  declare function HeroSliderSkeleton(): react_jsx_runtime.JSX.Element;
10
- declare function HeroSlider({ collections, isLoading, getHref }: HeroSliderProps): react_jsx_runtime.JSX.Element;
15
+ declare function HeroSlider({ collections, isLoading, getHref, placeholderHrefs }: HeroSliderProps): react_jsx_runtime.JSX.Element;
11
16
 
12
17
  export { HeroSlider, type HeroSliderProps, HeroSliderSkeleton };
@@ -5,6 +5,7 @@ import Link from "next/link";
5
5
  import Image from "next/image";
6
6
  import { ChevronLeft, ChevronRight, ArrowRight } from "lucide-react";
7
7
  import { cn } from "../utils/cn.js";
8
+ import { ipfsToHttp } from "../utils/ipfs.js";
8
9
  function formatFloorPrice(price) {
9
10
  if (!price) return "";
10
11
  const n = parseFloat(price);
@@ -13,20 +14,15 @@ function formatFloorPrice(price) {
13
14
  if (n >= 1) return n.toFixed(2);
14
15
  return n.toPrecision(3);
15
16
  }
16
- function ipfsToHttp(uri) {
17
- if (!uri) return "";
18
- if (uri.startsWith("ipfs://")) return uri.replace("ipfs://", "https://gateway.pinata.cloud/ipfs/");
19
- return uri;
20
- }
21
- function HeroPlaceholder() {
17
+ function HeroPlaceholder({ hrefs }) {
22
18
  return /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/50 flex flex-col items-center justify-center gap-4 text-center px-6 overflow-hidden", children: [
23
19
  /* @__PURE__ */ jsx("div", { className: "absolute aurora-purple w-[600px] h-[600px] opacity-20 -top-24 -left-24" }),
24
20
  /* @__PURE__ */ jsx("div", { className: "absolute aurora-blue w-[400px] h-[400px] opacity-15 -bottom-16 -right-16" }),
25
21
  /* @__PURE__ */ jsx("h2", { className: "text-4xl sm:text-6xl font-black gradient-text relative z-10", children: "Medialane" }),
26
22
  /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-lg relative z-10 max-w-md", children: "New monetization revenues for creative works" }),
27
23
  /* @__PURE__ */ jsxs("div", { className: "flex gap-3 relative z-10", children: [
28
- /* @__PURE__ */ jsx(Link, { href: "/marketplace", className: "inline-flex items-center justify-center rounded-[11px] bg-brand-blue px-4 py-2 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all", children: "Markets" }),
29
- /* @__PURE__ */ jsx(Link, { href: "/create/asset", className: "inline-flex items-center justify-center rounded-[11px] border border-white/20 bg-background/20 backdrop-blur-sm px-4 py-2 text-sm font-semibold text-white hover:bg-white/10 transition-all", children: "Create" })
24
+ /* @__PURE__ */ jsx(Link, { href: hrefs.markets, className: "inline-flex items-center justify-center rounded-[11px] bg-brand-blue px-4 py-2 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all", children: "Markets" }),
25
+ /* @__PURE__ */ jsx(Link, { href: hrefs.create, className: "inline-flex items-center justify-center rounded-[11px] border border-white/20 bg-background/20 backdrop-blur-sm px-4 py-2 text-sm font-semibold text-white hover:bg-white/10 transition-all", children: "Create" })
30
26
  ] })
31
27
  ] });
32
28
  }
@@ -67,7 +63,8 @@ function HeroSlide({ collection, active, getHref }) {
67
63
  function HeroSliderSkeleton() {
68
64
  return /* @__PURE__ */ jsx("section", { className: "relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] bg-muted animate-pulse" });
69
65
  }
70
- function HeroSlider({ collections, isLoading, getHref }) {
66
+ function HeroSlider({ collections, isLoading, getHref, placeholderHrefs = {} }) {
67
+ const hrefs = { markets: "/marketplace", create: "/create/asset", ...placeholderHrefs };
71
68
  const [current, setCurrent] = useState(0);
72
69
  const count = collections.length;
73
70
  const next = useCallback(() => {
@@ -82,7 +79,7 @@ function HeroSlider({ collections, isLoading, getHref }) {
82
79
  return () => clearInterval(id);
83
80
  }, [count, next]);
84
81
  if (isLoading) return /* @__PURE__ */ jsx(HeroSliderSkeleton, {});
85
- return /* @__PURE__ */ jsx("section", { className: "relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] overflow-hidden bg-muted", children: count === 0 ? /* @__PURE__ */ jsx(HeroPlaceholder, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
82
+ return /* @__PURE__ */ jsx("section", { className: "relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] overflow-hidden bg-muted", children: count === 0 ? /* @__PURE__ */ jsx(HeroPlaceholder, { hrefs }) : /* @__PURE__ */ jsxs(Fragment, { children: [
86
83
  collections.map((col, i) => /* @__PURE__ */ jsx(HeroSlide, { collection: col, active: i === current, getHref }, col.contractAddress)),
87
84
  count > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
88
85
  /* @__PURE__ */ jsx("button", { onClick: prev, "aria-label": "Previous slide", className: "absolute left-3 top-1/2 -translate-y-1/2 z-10 h-9 w-9 rounded-full bg-black/40 hover:bg-black/60 backdrop-blur-sm flex items-center justify-center transition-colors", children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-5 w-5 text-white" }) }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/hero-slider.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { ChevronLeft, ChevronRight, ArrowRight } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\nexport interface HeroSliderProps {\n collections: ApiCollection[];\n isLoading: boolean;\n getHref: (collection: ApiCollection) => string;\n}\n\nfunction formatFloorPrice(price: string | null | undefined): string {\n if (!price) return \"\";\n const n = parseFloat(price);\n if (isNaN(n)) return price;\n if (n >= 1000) return `${(n / 1000).toFixed(1)}K`;\n if (n >= 1) return n.toFixed(2);\n return n.toPrecision(3);\n}\n\nfunction ipfsToHttp(uri: string): string {\n if (!uri) return \"\";\n if (uri.startsWith(\"ipfs://\")) return uri.replace(\"ipfs://\", \"https://gateway.pinata.cloud/ipfs/\");\n return uri;\n}\n\nfunction HeroPlaceholder() {\n return (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/50 flex flex-col items-center justify-center gap-4 text-center px-6 overflow-hidden\">\n <div className=\"absolute aurora-purple w-[600px] h-[600px] opacity-20 -top-24 -left-24\" />\n <div className=\"absolute aurora-blue w-[400px] h-[400px] opacity-15 -bottom-16 -right-16\" />\n <h2 className=\"text-4xl sm:text-6xl font-black gradient-text relative z-10\">Medialane</h2>\n <p className=\"text-muted-foreground text-lg relative z-10 max-w-md\">\n New monetization revenues for creative works\n </p>\n <div className=\"flex gap-3 relative z-10\">\n <Link href=\"/marketplace\" className=\"inline-flex items-center justify-center rounded-[11px] bg-brand-blue px-4 py-2 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all\">\n Markets\n </Link>\n <Link href=\"/create/asset\" className=\"inline-flex items-center justify-center rounded-[11px] border border-white/20 bg-background/20 backdrop-blur-sm px-4 py-2 text-sm font-semibold text-white hover:bg-white/10 transition-all\">\n Create\n </Link>\n </div>\n </div>\n );\n}\n\nfunction HeroSlide({ collection, active, getHref }: { collection: ApiCollection; active: boolean; getHref: (col: ApiCollection) => string }) {\n const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;\n const name = collection.name ?? \"Collection\";\n const floor = collection.floorPrice;\n const supply = collection.totalSupply;\n\n return (\n <div className={cn(\"absolute inset-0 transition-opacity duration-700\", active ? \"opacity-100\" : \"opacity-0 pointer-events-none\")}>\n {imageUrl ? (\n <div className=\"absolute inset-0 overflow-hidden\">\n <div className=\"animate-kenburns absolute inset-0\">\n <Image src={imageUrl} alt={name} fill className=\"object-cover\" priority={active} unoptimized />\n </div>\n </div>\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/40 via-brand-blue/20 to-brand-navy/60\" />\n )}\n <div className=\"absolute inset-0 bg-gradient-to-t from-black/40 via-black/30 to-black/0\" />\n <div className=\"absolute bottom-0 left-0 right-0 p-6 sm:p-10 flex flex-col gap-3\">\n <h2 className=\"text-4xl lg:text-5xl font-semibold text-white leading-tight\">{name}</h2>\n <div className=\"flex items-center gap-4 text-sm text-white/70\">\n {supply != null && <span>{supply.toLocaleString()} items</span>}\n {floor && <span className=\"text-white font-semibold\">Floor {formatFloorPrice(floor)}</span>}\n </div>\n <Link\n href={getHref(collection)}\n className=\"self-start mt-2 inline-flex items-center gap-1.5 bg-white text-black hover:bg-white/90 font-semibold px-4 py-2 rounded-[11px] text-sm transition-all active:scale-[0.98]\"\n >\n View Collection <ArrowRight className=\"h-4 w-4\" />\n </Link>\n </div>\n </div>\n );\n}\n\nexport function HeroSliderSkeleton() {\n return <section className=\"relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] bg-muted animate-pulse\" />;\n}\n\nexport function HeroSlider({ collections, isLoading, getHref }: HeroSliderProps) {\n const [current, setCurrent] = useState(0);\n const count = collections.length;\n\n const next = useCallback(() => { if (count > 1) setCurrent((c) => (c + 1) % count); }, [count]);\n const prev = useCallback(() => { if (count > 1) setCurrent((c) => (c - 1 + count) % count); }, [count]);\n\n useEffect(() => {\n if (count <= 1) return;\n const id = setInterval(next, 7000);\n return () => clearInterval(id);\n }, [count, next]);\n\n if (isLoading) return <HeroSliderSkeleton />;\n\n return (\n <section className=\"relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] overflow-hidden bg-muted\">\n {count === 0 ? (\n <HeroPlaceholder />\n ) : (\n <>\n {collections.map((col, i) => (\n <HeroSlide key={col.contractAddress} collection={col} active={i === current} getHref={getHref} />\n ))}\n {count > 1 && (\n <>\n <button onClick={prev} aria-label=\"Previous slide\" className=\"absolute left-3 top-1/2 -translate-y-1/2 z-10 h-9 w-9 rounded-full bg-black/40 hover:bg-black/60 backdrop-blur-sm flex items-center justify-center transition-colors\">\n <ChevronLeft className=\"h-5 w-5 text-white\" />\n </button>\n <button onClick={next} aria-label=\"Next slide\" className=\"absolute right-3 top-1/2 -translate-y-1/2 z-10 h-9 w-9 rounded-full bg-black/40 hover:bg-black/60 backdrop-blur-sm flex items-center justify-center transition-colors\">\n <ChevronRight className=\"h-5 w-5 text-white\" />\n </button>\n <div className=\"absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-1.5 z-10\">\n {collections.map((_, i) => (\n <button key={i} onClick={() => setCurrent(i)} aria-label={`Go to slide ${i + 1}`} className={cn(\"h-1.5 rounded-full transition-all\", i === current ? \"w-6 bg-white\" : \"w-1.5 bg-white/40\")} />\n ))}\n </div>\n </>\n )}\n </>\n )}\n </section>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/hero-slider.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { ChevronLeft, ChevronRight, ArrowRight } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\nexport interface HeroSliderProps {\n collections: ApiCollection[];\n isLoading: boolean;\n getHref: (collection: ApiCollection) => string;\n /** Optional placeholder CTA hrefs — defaults to \"/marketplace\" and \"/create/asset\" */\n placeholderHrefs?: { markets?: string; create?: string };\n}\n\nfunction formatFloorPrice(price: string | null | undefined): string {\n if (!price) return \"\";\n const n = parseFloat(price);\n if (isNaN(n)) return price;\n if (n >= 1000) return `${(n / 1000).toFixed(1)}K`;\n if (n >= 1) return n.toFixed(2);\n return n.toPrecision(3);\n}\n\nfunction HeroPlaceholder({ hrefs }: { hrefs: Required<HeroSliderProps>[\"placeholderHrefs\"] }) {\n return (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/50 flex flex-col items-center justify-center gap-4 text-center px-6 overflow-hidden\">\n <div className=\"absolute aurora-purple w-[600px] h-[600px] opacity-20 -top-24 -left-24\" />\n <div className=\"absolute aurora-blue w-[400px] h-[400px] opacity-15 -bottom-16 -right-16\" />\n <h2 className=\"text-4xl sm:text-6xl font-black gradient-text relative z-10\">Medialane</h2>\n <p className=\"text-muted-foreground text-lg relative z-10 max-w-md\">\n New monetization revenues for creative works\n </p>\n <div className=\"flex gap-3 relative z-10\">\n <Link href={hrefs.markets!} className=\"inline-flex items-center justify-center rounded-[11px] bg-brand-blue px-4 py-2 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all\">\n Markets\n </Link>\n <Link href={hrefs.create!} className=\"inline-flex items-center justify-center rounded-[11px] border border-white/20 bg-background/20 backdrop-blur-sm px-4 py-2 text-sm font-semibold text-white hover:bg-white/10 transition-all\">\n Create\n </Link>\n </div>\n </div>\n );\n}\n\nfunction HeroSlide({ collection, active, getHref }: { collection: ApiCollection; active: boolean; getHref: (col: ApiCollection) => string }) {\n const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;\n const name = collection.name ?? \"Collection\";\n const floor = collection.floorPrice;\n const supply = collection.totalSupply;\n\n return (\n <div className={cn(\"absolute inset-0 transition-opacity duration-700\", active ? \"opacity-100\" : \"opacity-0 pointer-events-none\")}>\n {imageUrl ? (\n <div className=\"absolute inset-0 overflow-hidden\">\n <div className=\"animate-kenburns absolute inset-0\">\n <Image src={imageUrl} alt={name} fill className=\"object-cover\" priority={active} unoptimized />\n </div>\n </div>\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/40 via-brand-blue/20 to-brand-navy/60\" />\n )}\n <div className=\"absolute inset-0 bg-gradient-to-t from-black/40 via-black/30 to-black/0\" />\n <div className=\"absolute bottom-0 left-0 right-0 p-6 sm:p-10 flex flex-col gap-3\">\n <h2 className=\"text-4xl lg:text-5xl font-semibold text-white leading-tight\">{name}</h2>\n <div className=\"flex items-center gap-4 text-sm text-white/70\">\n {supply != null && <span>{supply.toLocaleString()} items</span>}\n {floor && <span className=\"text-white font-semibold\">Floor {formatFloorPrice(floor)}</span>}\n </div>\n <Link\n href={getHref(collection)}\n className=\"self-start mt-2 inline-flex items-center gap-1.5 bg-white text-black hover:bg-white/90 font-semibold px-4 py-2 rounded-[11px] text-sm transition-all active:scale-[0.98]\"\n >\n View Collection <ArrowRight className=\"h-4 w-4\" />\n </Link>\n </div>\n </div>\n );\n}\n\nexport function HeroSliderSkeleton() {\n return <section className=\"relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] bg-muted animate-pulse\" />;\n}\n\nexport function HeroSlider({ collections, isLoading, getHref, placeholderHrefs = {} }: HeroSliderProps) {\n const hrefs = { markets: \"/marketplace\", create: \"/create/asset\", ...placeholderHrefs };\n const [current, setCurrent] = useState(0);\n const count = collections.length;\n\n const next = useCallback(() => { if (count > 1) setCurrent((c) => (c + 1) % count); }, [count]);\n const prev = useCallback(() => { if (count > 1) setCurrent((c) => (c - 1 + count) % count); }, [count]);\n\n useEffect(() => {\n if (count <= 1) return;\n const id = setInterval(next, 7000);\n return () => clearInterval(id);\n }, [count, next]);\n\n if (isLoading) return <HeroSliderSkeleton />;\n\n return (\n <section className=\"relative w-full h-[78vw] min-h-[420px] max-h-[768px] sm:h-[72vh] sm:max-h-[816px] overflow-hidden bg-muted\">\n {count === 0 ? (\n <HeroPlaceholder hrefs={hrefs} />\n ) : (\n <>\n {collections.map((col, i) => (\n <HeroSlide key={col.contractAddress} collection={col} active={i === current} getHref={getHref} />\n ))}\n {count > 1 && (\n <>\n <button onClick={prev} aria-label=\"Previous slide\" className=\"absolute left-3 top-1/2 -translate-y-1/2 z-10 h-9 w-9 rounded-full bg-black/40 hover:bg-black/60 backdrop-blur-sm flex items-center justify-center transition-colors\">\n <ChevronLeft className=\"h-5 w-5 text-white\" />\n </button>\n <button onClick={next} aria-label=\"Next slide\" className=\"absolute right-3 top-1/2 -translate-y-1/2 z-10 h-9 w-9 rounded-full bg-black/40 hover:bg-black/60 backdrop-blur-sm flex items-center justify-center transition-colors\">\n <ChevronRight className=\"h-5 w-5 text-white\" />\n </button>\n <div className=\"absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-1.5 z-10\">\n {collections.map((_, i) => (\n <button key={i} onClick={() => setCurrent(i)} aria-label={`Go to slide ${i + 1}`} className={cn(\"h-1.5 rounded-full transition-all\", i === current ? \"w-6 bg-white\" : \"w-1.5 bg-white/40\")} />\n ))}\n </div>\n </>\n )}\n </>\n )}\n </section>\n );\n}\n"],"mappings":"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","names":[]}
@@ -26,9 +26,9 @@ const LAUNCHPAD_SERVICE_DEFINITIONS = [
26
26
  // ── Create ────────────────────────────────────────────────────────────────
27
27
  {
28
28
  key: "mint-ip-asset",
29
- title: "Mint IP Asset",
30
- subtitle: "Register any creative work onchain",
31
- description: "Turn any creative file into a programmable IP NFT. Gasless, permanent, and immediately tradeable.",
29
+ title: "Mint IP NFT",
30
+ subtitle: "Publish any creative work on Starknet",
31
+ description: "Turn any photo, video, or audio file into a programmable IP NFT. Gasless, permanent, and immediately tradeable on Medialane.",
32
32
  features: ["Gasless via ChipiPay", "IPFS metadata", "Programmable licensing"],
33
33
  icon: import_lucide_react.ImagePlus,
34
34
  gradient: "from-blue-500/10 via-sky-400/4 to-transparent",
@@ -42,8 +42,8 @@ const LAUNCHPAD_SERVICE_DEFINITIONS = [
42
42
  {
43
43
  key: "create-collection",
44
44
  title: "Create Collection",
45
- subtitle: "Deploy a named ERC-721 catalog",
46
- description: "Deploy a branded collection with its own page, metadata, and on-chain identity \u2014 ready to populate with assets.",
45
+ subtitle: "Group your NFTs under a shared identity",
46
+ description: "Deploy a branded ERC-721 collection with its own page, metadata, and on-chain identity \u2014 ready to populate with assets at any time.",
47
47
  features: ["Factory-deployed ERC-721", "Branded collection page", "Add assets at any time"],
48
48
  icon: import_lucide_react.Layers,
49
49
  gradient: "from-violet-500/10 via-purple-400/4 to-transparent",
@@ -54,6 +54,36 @@ const LAUNCHPAD_SERVICE_DEFINITIONS = [
54
54
  status: "live",
55
55
  category: "create"
56
56
  },
57
+ {
58
+ key: "ip-collection-1155",
59
+ title: "Edition Collection",
60
+ subtitle: "Deploy a contract for multi-copy NFT releases",
61
+ description: "Launch a collection for music tracks, art prints, or any IP you want to release in multiples. Each edition token is numbered and tradeable on Medialane.",
62
+ features: ["Multi-edition ERC-1155", "Immutable provenance", "Tradeable on Medialane"],
63
+ icon: import_lucide_react.Layers,
64
+ gradient: "from-violet-500/10 via-purple-400/4 to-transparent",
65
+ borderColor: "border-violet-500/20",
66
+ iconColor: "text-violet-500",
67
+ buttonColor: "bg-violet-600 hover:bg-violet-700",
68
+ badge: "Create",
69
+ status: "live",
70
+ category: "create"
71
+ },
72
+ {
73
+ key: "mint-editions",
74
+ title: "Mint NFT Editions",
75
+ subtitle: "Add new editions to an existing collection",
76
+ description: "Select one of your Edition Collection contracts and mint new token editions into it \u2014 set supply, upload artwork, and release to collectors.",
77
+ features: ["Choose any edition collection", "Set edition supply", "IPFS metadata"],
78
+ icon: import_lucide_react.PlusCircle,
79
+ gradient: "from-fuchsia-500/10 via-violet-400/4 to-transparent",
80
+ borderColor: "border-fuchsia-500/20",
81
+ iconColor: "text-fuchsia-500",
82
+ buttonColor: "bg-fuchsia-600 hover:bg-fuchsia-700",
83
+ badge: "Create",
84
+ status: "live",
85
+ category: "create"
86
+ },
57
87
  {
58
88
  key: "remix-asset",
59
89
  title: "Remix Asset",
@@ -65,7 +95,7 @@ const LAUNCHPAD_SERVICE_DEFINITIONS = [
65
95
  borderColor: "border-rose-500/20",
66
96
  iconColor: "text-rose-500",
67
97
  buttonColor: "bg-brand-rose hover:bg-brand-rose/90",
68
- badge: "Remix",
98
+ badge: "Create",
69
99
  status: "live",
70
100
  category: "create"
71
101
  },
@@ -73,8 +103,8 @@ const LAUNCHPAD_SERVICE_DEFINITIONS = [
73
103
  {
74
104
  key: "pop-protocol",
75
105
  title: "POP Protocol",
76
- subtitle: "Soulbound credentials for events & education",
77
- description: "Issue non-transferable on-chain credentials for bootcamps, hackathons, and conferences. Each attendee claims one soulbound badge \u2014 permanently tied to their wallet.",
106
+ subtitle: "Proof-of-participation for events & communities",
107
+ description: "Give every attendee proof they were there. Issue soulbound credentials to your community \u2014 one non-transferable badge per wallet, permanently on-chain. Works for bootcamps, hackathons, and conferences.",
78
108
  features: ["Soulbound \xB7 non-transferable", "One credential per wallet", "Optional allowlist gating"],
79
109
  icon: import_lucide_react.Award,
80
110
  gradient: "from-emerald-500/10 via-green-400/4 to-transparent",
@@ -102,36 +132,6 @@ const LAUNCHPAD_SERVICE_DEFINITIONS = [
102
132
  status: "live",
103
133
  category: "launch"
104
134
  },
105
- {
106
- key: "ip-collection-1155",
107
- title: "IP Collection 1155",
108
- subtitle: "Multi-edition ERC-1155 collections",
109
- description: "Deploy a multi-edition collection for music tracks, art series, or any IP with multiple copies. Mint unlimited editions in a single transaction.",
110
- features: ["Multi-edition ERC-1155", "Immutable provenance", "Tradeable on Medialane"],
111
- icon: import_lucide_react.Layers,
112
- gradient: "from-violet-500/10 via-purple-400/4 to-transparent",
113
- borderColor: "border-violet-500/20",
114
- iconColor: "text-violet-500",
115
- buttonColor: "bg-violet-600 hover:bg-violet-700",
116
- badge: "Launch",
117
- status: "live",
118
- category: "launch"
119
- },
120
- {
121
- key: "mint-editions",
122
- title: "Mint Editions",
123
- subtitle: "Add new tokens to an existing collection",
124
- description: "Select one of your IP Collection 1155 contracts and mint new token editions into it \u2014 set supply, upload artwork, and release to collectors.",
125
- features: ["Choose any 1155 collection", "Set edition supply", "IPFS metadata"],
126
- icon: import_lucide_react.PlusCircle,
127
- gradient: "from-fuchsia-500/10 via-violet-400/4 to-transparent",
128
- borderColor: "border-fuchsia-500/20",
129
- iconColor: "text-fuchsia-500",
130
- buttonColor: "bg-fuchsia-600 hover:bg-fuchsia-700",
131
- badge: "Launch",
132
- status: "live",
133
- category: "launch"
134
- },
135
135
  {
136
136
  key: "ip-tickets",
137
137
  title: "IP Tickets",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/data/launchpad-services.ts"],"sourcesContent":["import type { LucideIcon } from \"lucide-react\";\nimport {\n ImagePlus, Layers, GitBranch,\n Award, Package, PlusCircle,\n Ticket, Users,\n RefreshCw, Coins, TrendingUp,\n} from \"lucide-react\";\n\nexport type ServiceStatus = \"live\" | \"building\" | \"soon\";\nexport type ServiceCategory = \"create\" | \"launch\" | \"monetize\";\n\nexport interface ServiceDefinition {\n key: string;\n title: string;\n subtitle: string;\n description: string;\n features: string[];\n icon: LucideIcon;\n gradient: string;\n borderColor: string;\n iconColor: string;\n buttonColor?: string;\n badge: string;\n status: ServiceStatus;\n category: ServiceCategory;\n /** Secondary browse link label — injected app adds the href */\n browseLinkLabel?: string;\n}\n\nexport const LAUNCHPAD_SERVICE_DEFINITIONS: ServiceDefinition[] = [\n // ── Create ────────────────────────────────────────────────────────────────\n {\n key: \"mint-ip-asset\",\n title: \"Mint IP Asset\",\n subtitle: \"Register any creative work onchain\",\n description:\n \"Turn any creative file into a programmable IP NFT. Gasless, permanent, and immediately tradeable.\",\n features: [\"Gasless via ChipiPay\", \"IPFS metadata\", \"Programmable licensing\"],\n icon: ImagePlus,\n gradient: \"from-blue-500/10 via-sky-400/4 to-transparent\",\n borderColor: \"border-blue-500/20\",\n iconColor: \"text-blue-500\",\n buttonColor: \"bg-brand-blue hover:bg-brand-blue/90\",\n badge: \"Create\",\n status: \"live\",\n category: \"create\",\n },\n {\n key: \"create-collection\",\n title: \"Create Collection\",\n subtitle: \"Deploy a named ERC-721 catalog\",\n description:\n \"Deploy a branded collection with its own page, metadata, and on-chain identity — ready to populate with assets.\",\n features: [\"Factory-deployed ERC-721\", \"Branded collection page\", \"Add assets at any time\"],\n icon: Layers,\n gradient: \"from-violet-500/10 via-purple-400/4 to-transparent\",\n borderColor: \"border-violet-500/20\",\n iconColor: \"text-violet-500\",\n buttonColor: \"bg-brand-purple hover:bg-brand-purple/90\",\n badge: \"Create\",\n status: \"live\",\n category: \"create\",\n },\n {\n key: \"remix-asset\",\n title: \"Remix Asset\",\n subtitle: \"Derivative works with on-chain attribution\",\n description:\n \"Create a licensed derivative of any IP asset with full provenance and attribution flowing back to the original creator.\",\n features: [\"On-chain attribution\", \"License-enforced at mint\", \"Royalties to original creator\"],\n icon: GitBranch,\n gradient: \"from-rose-500/10 via-pink-400/4 to-transparent\",\n borderColor: \"border-rose-500/20\",\n iconColor: \"text-rose-500\",\n buttonColor: \"bg-brand-rose hover:bg-brand-rose/90\",\n badge: \"Remix\",\n status: \"live\",\n category: \"create\",\n },\n\n // ── Launch ────────────────────────────────────────────────────────────────\n {\n key: \"pop-protocol\",\n title: \"POP Protocol\",\n subtitle: \"Soulbound credentials for events & education\",\n description:\n \"Issue non-transferable on-chain credentials for bootcamps, hackathons, and conferences. Each attendee claims one soulbound badge — permanently tied to their wallet.\",\n features: [\"Soulbound · non-transferable\", \"One credential per wallet\", \"Optional allowlist gating\"],\n icon: Award,\n gradient: \"from-emerald-500/10 via-green-400/4 to-transparent\",\n borderColor: \"border-emerald-500/20\",\n iconColor: \"text-emerald-500\",\n buttonColor: \"bg-green-600 hover:bg-green-700\",\n badge: \"Launch\",\n browseLinkLabel: \"Browse events\",\n status: \"live\",\n category: \"launch\",\n },\n {\n key: \"collection-drop\",\n title: \"Collection Drop\",\n subtitle: \"Limited-edition timed releases\",\n description:\n \"Launch a fixed-supply ERC-721 drop with a defined mint window and per-wallet limit. Set your open date and let your community race to collect.\",\n features: [\"Fixed supply cap\", \"Timed mint window\", \"Free or paid mint\"],\n icon: Package,\n gradient: \"from-orange-500/10 via-amber-400/4 to-transparent\",\n borderColor: \"border-orange-500/20\",\n iconColor: \"text-orange-500\",\n buttonColor: \"bg-orange-600 hover:bg-orange-700\",\n badge: \"Launch\",\n browseLinkLabel: \"Browse drops\",\n status: \"live\",\n category: \"launch\",\n },\n {\n key: \"ip-collection-1155\",\n title: \"IP Collection 1155\",\n subtitle: \"Multi-edition ERC-1155 collections\",\n description:\n \"Deploy a multi-edition collection for music tracks, art series, or any IP with multiple copies. Mint unlimited editions in a single transaction.\",\n features: [\"Multi-edition ERC-1155\", \"Immutable provenance\", \"Tradeable on Medialane\"],\n icon: Layers,\n gradient: \"from-violet-500/10 via-purple-400/4 to-transparent\",\n borderColor: \"border-violet-500/20\",\n iconColor: \"text-violet-500\",\n buttonColor: \"bg-violet-600 hover:bg-violet-700\",\n badge: \"Launch\",\n status: \"live\",\n category: \"launch\",\n },\n {\n key: \"mint-editions\",\n title: \"Mint Editions\",\n subtitle: \"Add new tokens to an existing collection\",\n description:\n \"Select one of your IP Collection 1155 contracts and mint new token editions into it — set supply, upload artwork, and release to collectors.\",\n features: [\"Choose any 1155 collection\", \"Set edition supply\", \"IPFS metadata\"],\n icon: PlusCircle,\n gradient: \"from-fuchsia-500/10 via-violet-400/4 to-transparent\",\n borderColor: \"border-fuchsia-500/20\",\n iconColor: \"text-fuchsia-500\",\n buttonColor: \"bg-fuchsia-600 hover:bg-fuchsia-700\",\n badge: \"Launch\",\n status: \"live\",\n category: \"launch\",\n },\n {\n key: \"ip-tickets\",\n title: \"IP Tickets\",\n subtitle: \"Gate real-world experiences with NFTs\",\n description:\n \"Distribute tickets for concerts, workshops, and events. Each ticket is verifiable on-chain proof of attendance.\",\n features: [\"NFT-based event gating\", \"Proof of attendance\", \"Transferable or soulbound\"],\n icon: Ticket,\n gradient: \"from-teal-500/7 via-cyan-400/3 to-transparent\",\n borderColor: \"border-teal-500/15\",\n iconColor: \"text-teal-500\",\n badge: \"Soon\",\n status: \"building\",\n category: \"launch\",\n },\n {\n key: \"membership\",\n title: \"Membership\",\n subtitle: \"Token-gated access passes\",\n description:\n \"Create tiered membership passes that unlock exclusive content, private communities, and experiences for your most loyal fans.\",\n features: [\"Token-gated content\", \"Tiered access levels\", \"Community alignment\"],\n icon: Users,\n gradient: \"from-indigo-500/6 via-violet-400/2 to-transparent\",\n borderColor: \"border-indigo-500/10\",\n iconColor: \"text-indigo-400\",\n badge: \"Soon\",\n status: \"soon\",\n category: \"launch\",\n },\n\n // ── Monetize ─────────────────────────────────────────────────────────────\n {\n key: \"subscriptions\",\n title: \"Subscriptions\",\n subtitle: \"Recurring on-chain revenue\",\n description:\n \"Monthly licensing, creator support tiers, and access passes — all auto-renewed without intermediaries.\",\n features: [\"Recurring revenue\", \"Auto-renewal protocol\", \"No middlemen\"],\n icon: RefreshCw,\n gradient: \"from-sky-500/6 via-blue-400/2 to-transparent\",\n borderColor: \"border-sky-500/10\",\n iconColor: \"text-sky-400\",\n badge: \"Soon\",\n status: \"soon\",\n category: \"monetize\",\n },\n {\n key: \"ip-coins\",\n title: \"IP Coins\",\n subtitle: \"Fractional ownership of intellectual property\",\n description:\n \"Tokenize your IP catalog as fungible tokens. Enable fractional ownership and liquid markets around your creative work.\",\n features: [\"Fungible IP tokens\", \"Fractional ownership\", \"Liquid secondary markets\"],\n icon: Coins,\n gradient: \"from-amber-500/6 via-yellow-400/2 to-transparent\",\n borderColor: \"border-amber-500/10\",\n iconColor: \"text-amber-400\",\n badge: \"Soon\",\n status: \"soon\",\n category: \"monetize\",\n },\n {\n key: \"creator-coins\",\n title: \"Creator Coins\",\n subtitle: \"Personal social token for fans\",\n description:\n \"Launch a social token tied to your creative career. Let fans invest directly in your work — full economic alignment between creator and community.\",\n features: [\"Personal social token\", \"Fan investment\", \"Creator-community alignment\"],\n icon: TrendingUp,\n gradient: \"from-pink-500/6 via-rose-400/2 to-transparent\",\n borderColor: \"border-pink-500/10\",\n iconColor: \"text-pink-400\",\n badge: \"Soon\",\n status: \"soon\",\n category: \"monetize\",\n },\n];\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/data/launchpad-services.ts"],"sourcesContent":["import type { LucideIcon } from \"lucide-react\";\nimport {\n ImagePlus, Layers, GitBranch,\n Award, Package, PlusCircle,\n Ticket, Users,\n RefreshCw, Coins, TrendingUp,\n} from \"lucide-react\";\n\nexport type ServiceStatus = \"live\" | \"building\" | \"soon\";\nexport type ServiceCategory = \"create\" | \"launch\" | \"monetize\";\n\nexport interface ServiceDefinition {\n key: string;\n title: string;\n subtitle: string;\n description: string;\n features: string[];\n icon: LucideIcon;\n gradient: string;\n borderColor: string;\n iconColor: string;\n buttonColor?: string;\n badge: string;\n status: ServiceStatus;\n category: ServiceCategory;\n /** Secondary browse link label — injected app adds the href */\n browseLinkLabel?: string;\n}\n\nexport const LAUNCHPAD_SERVICE_DEFINITIONS: ServiceDefinition[] = [\n // ── Create ────────────────────────────────────────────────────────────────\n {\n key: \"mint-ip-asset\",\n title: \"Mint IP NFT\",\n subtitle: \"Publish any creative work on Starknet\",\n description:\n \"Turn any photo, video, or audio file into a programmable IP NFT. Gasless, permanent, and immediately tradeable on Medialane.\",\n features: [\"Gasless via ChipiPay\", \"IPFS metadata\", \"Programmable licensing\"],\n icon: ImagePlus,\n gradient: \"from-blue-500/10 via-sky-400/4 to-transparent\",\n borderColor: \"border-blue-500/20\",\n iconColor: \"text-blue-500\",\n buttonColor: \"bg-brand-blue hover:bg-brand-blue/90\",\n badge: \"Create\",\n status: \"live\",\n category: \"create\",\n },\n {\n key: \"create-collection\",\n title: \"Create Collection\",\n subtitle: \"Group your NFTs under a shared identity\",\n description:\n \"Deploy a branded ERC-721 collection with its own page, metadata, and on-chain identity — ready to populate with assets at any time.\",\n features: [\"Factory-deployed ERC-721\", \"Branded collection page\", \"Add assets at any time\"],\n icon: Layers,\n gradient: \"from-violet-500/10 via-purple-400/4 to-transparent\",\n borderColor: \"border-violet-500/20\",\n iconColor: \"text-violet-500\",\n buttonColor: \"bg-brand-purple hover:bg-brand-purple/90\",\n badge: \"Create\",\n status: \"live\",\n category: \"create\",\n },\n {\n key: \"ip-collection-1155\",\n title: \"Edition Collection\",\n subtitle: \"Deploy a contract for multi-copy NFT releases\",\n description:\n \"Launch a collection for music tracks, art prints, or any IP you want to release in multiples. Each edition token is numbered and tradeable on Medialane.\",\n features: [\"Multi-edition ERC-1155\", \"Immutable provenance\", \"Tradeable on Medialane\"],\n icon: Layers,\n gradient: \"from-violet-500/10 via-purple-400/4 to-transparent\",\n borderColor: \"border-violet-500/20\",\n iconColor: \"text-violet-500\",\n buttonColor: \"bg-violet-600 hover:bg-violet-700\",\n badge: \"Create\",\n status: \"live\",\n category: \"create\",\n },\n {\n key: \"mint-editions\",\n title: \"Mint NFT Editions\",\n subtitle: \"Add new editions to an existing collection\",\n description:\n \"Select one of your Edition Collection contracts and mint new token editions into it — set supply, upload artwork, and release to collectors.\",\n features: [\"Choose any edition collection\", \"Set edition supply\", \"IPFS metadata\"],\n icon: PlusCircle,\n gradient: \"from-fuchsia-500/10 via-violet-400/4 to-transparent\",\n borderColor: \"border-fuchsia-500/20\",\n iconColor: \"text-fuchsia-500\",\n buttonColor: \"bg-fuchsia-600 hover:bg-fuchsia-700\",\n badge: \"Create\",\n status: \"live\",\n category: \"create\",\n },\n {\n key: \"remix-asset\",\n title: \"Remix Asset\",\n subtitle: \"Derivative works with on-chain attribution\",\n description:\n \"Create a licensed derivative of any IP asset with full provenance and attribution flowing back to the original creator.\",\n features: [\"On-chain attribution\", \"License-enforced at mint\", \"Royalties to original creator\"],\n icon: GitBranch,\n gradient: \"from-rose-500/10 via-pink-400/4 to-transparent\",\n borderColor: \"border-rose-500/20\",\n iconColor: \"text-rose-500\",\n buttonColor: \"bg-brand-rose hover:bg-brand-rose/90\",\n badge: \"Create\",\n status: \"live\",\n category: \"create\",\n },\n\n // ── Launch ────────────────────────────────────────────────────────────────\n {\n key: \"pop-protocol\",\n title: \"POP Protocol\",\n subtitle: \"Proof-of-participation for events & communities\",\n description:\n \"Give every attendee proof they were there. Issue soulbound credentials to your community — one non-transferable badge per wallet, permanently on-chain. Works for bootcamps, hackathons, and conferences.\",\n features: [\"Soulbound · non-transferable\", \"One credential per wallet\", \"Optional allowlist gating\"],\n icon: Award,\n gradient: \"from-emerald-500/10 via-green-400/4 to-transparent\",\n borderColor: \"border-emerald-500/20\",\n iconColor: \"text-emerald-500\",\n buttonColor: \"bg-green-600 hover:bg-green-700\",\n badge: \"Launch\",\n browseLinkLabel: \"Browse events\",\n status: \"live\",\n category: \"launch\",\n },\n {\n key: \"collection-drop\",\n title: \"Collection Drop\",\n subtitle: \"Limited-edition timed releases\",\n description:\n \"Launch a fixed-supply ERC-721 drop with a defined mint window and per-wallet limit. Set your open date and let your community race to collect.\",\n features: [\"Fixed supply cap\", \"Timed mint window\", \"Free or paid mint\"],\n icon: Package,\n gradient: \"from-orange-500/10 via-amber-400/4 to-transparent\",\n borderColor: \"border-orange-500/20\",\n iconColor: \"text-orange-500\",\n buttonColor: \"bg-orange-600 hover:bg-orange-700\",\n badge: \"Launch\",\n browseLinkLabel: \"Browse drops\",\n status: \"live\",\n category: \"launch\",\n },\n {\n key: \"ip-tickets\",\n title: \"IP Tickets\",\n subtitle: \"Gate real-world experiences with NFTs\",\n description:\n \"Distribute tickets for concerts, workshops, and events. Each ticket is verifiable on-chain proof of attendance.\",\n features: [\"NFT-based event gating\", \"Proof of attendance\", \"Transferable or soulbound\"],\n icon: Ticket,\n gradient: \"from-teal-500/7 via-cyan-400/3 to-transparent\",\n borderColor: \"border-teal-500/15\",\n iconColor: \"text-teal-500\",\n badge: \"Soon\",\n status: \"building\",\n category: \"launch\",\n },\n {\n key: \"membership\",\n title: \"Membership\",\n subtitle: \"Token-gated access passes\",\n description:\n \"Create tiered membership passes that unlock exclusive content, private communities, and experiences for your most loyal fans.\",\n features: [\"Token-gated content\", \"Tiered access levels\", \"Community alignment\"],\n icon: Users,\n gradient: \"from-indigo-500/6 via-violet-400/2 to-transparent\",\n borderColor: \"border-indigo-500/10\",\n iconColor: \"text-indigo-400\",\n badge: \"Soon\",\n status: \"soon\",\n category: \"launch\",\n },\n\n // ── Monetize ─────────────────────────────────────────────────────────────\n {\n key: \"subscriptions\",\n title: \"Subscriptions\",\n subtitle: \"Recurring on-chain revenue\",\n description:\n \"Monthly licensing, creator support tiers, and access passes — all auto-renewed without intermediaries.\",\n features: [\"Recurring revenue\", \"Auto-renewal protocol\", \"No middlemen\"],\n icon: RefreshCw,\n gradient: \"from-sky-500/6 via-blue-400/2 to-transparent\",\n borderColor: \"border-sky-500/10\",\n iconColor: \"text-sky-400\",\n badge: \"Soon\",\n status: \"soon\",\n category: \"monetize\",\n },\n {\n key: \"ip-coins\",\n title: \"IP Coins\",\n subtitle: \"Fractional ownership of intellectual property\",\n description:\n \"Tokenize your IP catalog as fungible tokens. Enable fractional ownership and liquid markets around your creative work.\",\n features: [\"Fungible IP tokens\", \"Fractional ownership\", \"Liquid secondary markets\"],\n icon: Coins,\n gradient: \"from-amber-500/6 via-yellow-400/2 to-transparent\",\n borderColor: \"border-amber-500/10\",\n iconColor: \"text-amber-400\",\n badge: \"Soon\",\n status: \"soon\",\n category: \"monetize\",\n },\n {\n key: \"creator-coins\",\n title: \"Creator Coins\",\n subtitle: \"Personal social token for fans\",\n description:\n \"Launch a social token tied to your creative career. Let fans invest directly in your work — full economic alignment between creator and community.\",\n features: [\"Personal social token\", \"Fan investment\", \"Creator-community alignment\"],\n icon: TrendingUp,\n gradient: \"from-pink-500/6 via-rose-400/2 to-transparent\",\n borderColor: \"border-pink-500/10\",\n iconColor: \"text-pink-400\",\n badge: \"Soon\",\n status: \"soon\",\n category: \"monetize\",\n },\n];\n"],"mappings":"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","names":[]}