@medialane/ui 0.3.4 → 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.
- package/README.md +219 -0
- package/dist/components/activity-ticker.cjs +1 -2
- package/dist/components/activity-ticker.cjs.map +1 -1
- package/dist/components/activity-ticker.d.cts +2 -1
- package/dist/components/activity-ticker.d.ts +2 -1
- package/dist/components/activity-ticker.js +1 -2
- package/dist/components/activity-ticker.js.map +1 -1
- package/dist/components/discover-collections-strip.cjs +5 -3
- package/dist/components/discover-collections-strip.cjs.map +1 -1
- package/dist/components/discover-collections-strip.d.cts +3 -1
- package/dist/components/discover-collections-strip.d.ts +3 -1
- package/dist/components/discover-collections-strip.js +5 -3
- package/dist/components/discover-collections-strip.js.map +1 -1
- package/dist/components/discover-creators-strip.cjs +7 -5
- package/dist/components/discover-creators-strip.cjs.map +1 -1
- package/dist/components/discover-creators-strip.d.cts +3 -1
- package/dist/components/discover-creators-strip.d.ts +3 -1
- package/dist/components/discover-creators-strip.js +7 -5
- package/dist/components/discover-creators-strip.js.map +1 -1
- package/dist/components/discover-hero.cjs +3 -2
- package/dist/components/discover-hero.cjs.map +1 -1
- package/dist/components/discover-hero.d.cts +2 -1
- package/dist/components/discover-hero.d.ts +2 -1
- package/dist/components/discover-hero.js +3 -2
- package/dist/components/discover-hero.js.map +1 -1
- package/dist/components/hero-slider.cjs +8 -11
- package/dist/components/hero-slider.cjs.map +1 -1
- package/dist/components/hero-slider.d.cts +6 -1
- package/dist/components/hero-slider.d.ts +6 -1
- package/dist/components/hero-slider.js +7 -10
- package/dist/components/hero-slider.js.map +1 -1
- package/dist/components/launchpad-services.cjs +191 -0
- package/dist/components/launchpad-services.cjs.map +1 -0
- package/dist/components/launchpad-services.d.cts +20 -0
- package/dist/components/launchpad-services.d.ts +20 -0
- package/dist/components/launchpad-services.js +157 -0
- package/dist/components/launchpad-services.js.map +1 -0
- package/dist/data/launchpad-services.cjs +211 -0
- package/dist/data/launchpad-services.cjs.map +1 -0
- package/dist/data/launchpad-services.d.cts +24 -0
- package/dist/data/launchpad-services.d.ts +24 -0
- package/dist/data/launchpad-services.js +199 -0
- package/dist/data/launchpad-services.js.map +1 -0
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- 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 ??
|
|
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;
|
|
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":";
|
|
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
|
|
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:
|
|
63
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href:
|
|
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
|
|
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
|
|
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:
|
|
29
|
-
/* @__PURE__ */ jsx(Link, { href:
|
|
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
|
|
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":[]}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var launchpad_services_exports = {};
|
|
31
|
+
__export(launchpad_services_exports, {
|
|
32
|
+
LaunchpadServicesGrid: () => LaunchpadServicesGrid
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(launchpad_services_exports);
|
|
35
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
36
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
37
|
+
var import_lucide_react = require("lucide-react");
|
|
38
|
+
var import_cn = require("../utils/cn.js");
|
|
39
|
+
function ServiceCard({
|
|
40
|
+
title,
|
|
41
|
+
subtitle,
|
|
42
|
+
description,
|
|
43
|
+
features,
|
|
44
|
+
icon: Icon,
|
|
45
|
+
gradient,
|
|
46
|
+
borderColor,
|
|
47
|
+
iconColor,
|
|
48
|
+
buttonColor,
|
|
49
|
+
badge,
|
|
50
|
+
status,
|
|
51
|
+
href,
|
|
52
|
+
buttonLabel,
|
|
53
|
+
browseHref,
|
|
54
|
+
browseLinkLabel
|
|
55
|
+
}) {
|
|
56
|
+
const live = status === "live";
|
|
57
|
+
const building = status === "building";
|
|
58
|
+
const active = live || building;
|
|
59
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
60
|
+
"div",
|
|
61
|
+
{
|
|
62
|
+
className: (0, import_cn.cn)(
|
|
63
|
+
"group relative rounded-2xl border overflow-hidden transition-all duration-300 flex flex-col",
|
|
64
|
+
`bg-gradient-to-br ${gradient}`,
|
|
65
|
+
active ? borderColor : "border-border/20",
|
|
66
|
+
live && "hover:-translate-y-[3px] hover:shadow-lg hover:shadow-black/5 dark:hover:shadow-black/20",
|
|
67
|
+
!active && "opacity-60"
|
|
68
|
+
),
|
|
69
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col flex-1 p-7 gap-6", children: [
|
|
70
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-start justify-between", children: [
|
|
71
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
72
|
+
Icon,
|
|
73
|
+
{
|
|
74
|
+
className: (0, import_cn.cn)(
|
|
75
|
+
"h-9 w-9 transition-transform duration-300",
|
|
76
|
+
active ? iconColor : "text-muted-foreground/25",
|
|
77
|
+
live && "group-hover:scale-110"
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
82
|
+
"span",
|
|
83
|
+
{
|
|
84
|
+
className: (0, import_cn.cn)(
|
|
85
|
+
"text-[10px] font-semibold tracking-widest uppercase rounded-full px-2.5 py-1 flex items-center gap-1.5",
|
|
86
|
+
live ? "text-emerald-600 dark:text-emerald-400 bg-emerald-500/10" : building ? "text-amber-600 dark:text-amber-400 bg-amber-500/10" : "text-muted-foreground/40 bg-muted/30"
|
|
87
|
+
),
|
|
88
|
+
children: [
|
|
89
|
+
live && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse" }),
|
|
90
|
+
!active && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Lock, { className: "h-2.5 w-2.5" }),
|
|
91
|
+
badge
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
] }),
|
|
96
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
|
|
97
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
98
|
+
"p",
|
|
99
|
+
{
|
|
100
|
+
className: (0, import_cn.cn)(
|
|
101
|
+
"text-xl sm:text-2xl font-bold leading-snug tracking-tight",
|
|
102
|
+
!active && "text-foreground/40"
|
|
103
|
+
),
|
|
104
|
+
children: title
|
|
105
|
+
}
|
|
106
|
+
),
|
|
107
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
108
|
+
"p",
|
|
109
|
+
{
|
|
110
|
+
className: (0, import_cn.cn)(
|
|
111
|
+
"text-xs leading-relaxed",
|
|
112
|
+
active ? "text-muted-foreground" : "text-muted-foreground/30"
|
|
113
|
+
),
|
|
114
|
+
children: subtitle
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
] }),
|
|
118
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
119
|
+
"p",
|
|
120
|
+
{
|
|
121
|
+
className: (0, import_cn.cn)(
|
|
122
|
+
"text-sm leading-relaxed flex-1",
|
|
123
|
+
active ? "text-muted-foreground" : "text-muted-foreground/30"
|
|
124
|
+
),
|
|
125
|
+
children: description
|
|
126
|
+
}
|
|
127
|
+
),
|
|
128
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-wrap gap-1.5", children: features.map((f) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
129
|
+
"span",
|
|
130
|
+
{
|
|
131
|
+
className: (0, import_cn.cn)(
|
|
132
|
+
"text-[11px] px-2.5 py-1 rounded-full border font-medium",
|
|
133
|
+
active ? "bg-background/50 border-border/50 text-muted-foreground" : "bg-muted/10 border-border/15 text-muted-foreground/25"
|
|
134
|
+
),
|
|
135
|
+
children: f
|
|
136
|
+
},
|
|
137
|
+
f
|
|
138
|
+
)) }),
|
|
139
|
+
live && href ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-2", children: [
|
|
140
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
141
|
+
import_link.default,
|
|
142
|
+
{
|
|
143
|
+
href,
|
|
144
|
+
className: (0, import_cn.cn)(
|
|
145
|
+
"flex items-center justify-between w-full h-10 px-4 rounded-xl",
|
|
146
|
+
"text-sm font-semibold text-white",
|
|
147
|
+
"transition-all duration-200 active:scale-[0.98]",
|
|
148
|
+
buttonColor
|
|
149
|
+
),
|
|
150
|
+
children: [
|
|
151
|
+
buttonLabel ?? "Get started",
|
|
152
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ArrowRight, { className: "h-3.5 w-3.5" })
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
),
|
|
156
|
+
browseHref && browseLinkLabel && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
157
|
+
import_link.default,
|
|
158
|
+
{
|
|
159
|
+
href: browseHref,
|
|
160
|
+
className: "flex items-center justify-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors py-1",
|
|
161
|
+
children: [
|
|
162
|
+
browseLinkLabel,
|
|
163
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ArrowRight, { className: "h-3 w-3" })
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
)
|
|
167
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 h-10 text-sm text-muted-foreground/30 font-medium", children: [
|
|
168
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Lock, { className: "h-3.5 w-3.5" }),
|
|
169
|
+
building ? "In development" : "Coming soon"
|
|
170
|
+
] })
|
|
171
|
+
] })
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
function LaunchpadServicesGrid({ services, className }) {
|
|
176
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
177
|
+
"div",
|
|
178
|
+
{
|
|
179
|
+
className: (0, import_cn.cn)(
|
|
180
|
+
"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",
|
|
181
|
+
className
|
|
182
|
+
),
|
|
183
|
+
children: services.map(({ key, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ServiceCard, { ...rest }, key))
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
188
|
+
0 && (module.exports = {
|
|
189
|
+
LaunchpadServicesGrid
|
|
190
|
+
});
|
|
191
|
+
//# sourceMappingURL=launchpad-services.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/launchpad-services.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"next/link\";\nimport { Lock, ArrowRight } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport type { ServiceDefinition } from \"../data/launchpad-services.js\";\n\nexport type { ServiceStatus, ServiceCategory, ServiceDefinition } from \"../data/launchpad-services.js\";\n\nexport interface ServiceCardProps extends ServiceDefinition {\n /** Primary CTA href — required for live services */\n href?: string;\n /** Primary CTA button label */\n buttonLabel?: string;\n /** Secondary browse link href */\n browseHref?: string;\n}\n\nfunction ServiceCard({\n title,\n subtitle,\n description,\n features,\n icon: Icon,\n gradient,\n borderColor,\n iconColor,\n buttonColor,\n badge,\n status,\n href,\n buttonLabel,\n browseHref,\n browseLinkLabel,\n}: ServiceCardProps) {\n const live = status === \"live\";\n const building = status === \"building\";\n const active = live || building;\n\n return (\n <div\n className={cn(\n \"group relative rounded-2xl border overflow-hidden transition-all duration-300 flex flex-col\",\n `bg-gradient-to-br ${gradient}`,\n active ? borderColor : \"border-border/20\",\n live && \"hover:-translate-y-[3px] hover:shadow-lg hover:shadow-black/5 dark:hover:shadow-black/20\",\n !active && \"opacity-60\"\n )}\n >\n <div className=\"flex flex-col flex-1 p-7 gap-6\">\n\n {/* Icon + status badge */}\n <div className=\"flex items-start justify-between\">\n <Icon\n className={cn(\n \"h-9 w-9 transition-transform duration-300\",\n active ? iconColor : \"text-muted-foreground/25\",\n live && \"group-hover:scale-110\"\n )}\n />\n <span\n className={cn(\n \"text-[10px] font-semibold tracking-widest uppercase rounded-full px-2.5 py-1 flex items-center gap-1.5\",\n live\n ? \"text-emerald-600 dark:text-emerald-400 bg-emerald-500/10\"\n : building\n ? \"text-amber-600 dark:text-amber-400 bg-amber-500/10\"\n : \"text-muted-foreground/40 bg-muted/30\"\n )}\n >\n {live && <span className=\"h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse\" />}\n {!active && <Lock className=\"h-2.5 w-2.5\" />}\n {badge}\n </span>\n </div>\n\n {/* Title + subtitle */}\n <div className=\"space-y-1.5\">\n <p\n className={cn(\n \"text-xl sm:text-2xl font-bold leading-snug tracking-tight\",\n !active && \"text-foreground/40\"\n )}\n >\n {title}\n </p>\n <p\n className={cn(\n \"text-xs leading-relaxed\",\n active ? \"text-muted-foreground\" : \"text-muted-foreground/30\"\n )}\n >\n {subtitle}\n </p>\n </div>\n\n {/* Description */}\n <p\n className={cn(\n \"text-sm leading-relaxed flex-1\",\n active ? \"text-muted-foreground\" : \"text-muted-foreground/30\"\n )}\n >\n {description}\n </p>\n\n {/* Feature chips */}\n <div className=\"flex flex-wrap gap-1.5\">\n {features.map((f) => (\n <span\n key={f}\n className={cn(\n \"text-[11px] px-2.5 py-1 rounded-full border font-medium\",\n active\n ? \"bg-background/50 border-border/50 text-muted-foreground\"\n : \"bg-muted/10 border-border/15 text-muted-foreground/25\"\n )}\n >\n {f}\n </span>\n ))}\n </div>\n\n {/* CTA */}\n {live && href ? (\n <div className=\"space-y-2\">\n <Link\n href={href}\n className={cn(\n \"flex items-center justify-between w-full h-10 px-4 rounded-xl\",\n \"text-sm font-semibold text-white\",\n \"transition-all duration-200 active:scale-[0.98]\",\n buttonColor\n )}\n >\n {buttonLabel ?? \"Get started\"}\n <ArrowRight className=\"h-3.5 w-3.5\" />\n </Link>\n {browseHref && browseLinkLabel && (\n <Link\n href={browseHref}\n className=\"flex items-center justify-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors py-1\"\n >\n {browseLinkLabel}\n <ArrowRight className=\"h-3 w-3\" />\n </Link>\n )}\n </div>\n ) : (\n <div className=\"flex items-center gap-2 h-10 text-sm text-muted-foreground/30 font-medium\">\n <Lock className=\"h-3.5 w-3.5\" />\n {building ? \"In development\" : \"Coming soon\"}\n </div>\n )}\n\n </div>\n </div>\n );\n}\n\nexport interface LaunchpadServicesGridProps {\n services: ServiceCardProps[];\n className?: string;\n}\n\nexport function LaunchpadServicesGrid({ services, className }: LaunchpadServicesGridProps) {\n return (\n <div\n className={cn(\n \"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\",\n className\n )}\n >\n {services.map(({ key, ...rest }) => (\n <ServiceCard key={key} {...rest} />\n ))}\n </div>\n );\n}\n"],"mappings":"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","names":["Link"]}
|