@medialane/ui 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,163 +29,200 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
30
  var launchpad_services_exports = {};
31
31
  __export(launchpad_services_exports, {
32
- LaunchpadServicesGrid: () => LaunchpadServicesGrid
32
+ LaunchpadGroupedSections: () => LaunchpadGroupedSections,
33
+ LaunchpadServiceCard: () => LaunchpadServiceCard,
34
+ SERVICE_CARD_COLORS: () => SERVICE_CARD_COLORS
33
35
  });
34
36
  module.exports = __toCommonJS(launchpad_services_exports);
35
37
  var import_jsx_runtime = require("react/jsx-runtime");
36
38
  var import_link = __toESM(require("next/link"), 1);
39
+ var import_framer_motion = require("framer-motion");
37
40
  var import_lucide_react = require("lucide-react");
38
41
  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
- }) {
42
+ var import_launchpad_services = require("../data/launchpad-services.js");
43
+ const DEFAULT_COLORS = {
44
+ icon: "text-brand-blue",
45
+ button: "bg-brand-blue",
46
+ chip: "border-border/50 text-muted-foreground bg-muted/30",
47
+ gradient: "from-border/40 to-border/20"
48
+ };
49
+ const SERVICE_CARD_COLORS = {
50
+ "mint-ip-asset": { icon: "text-brand-blue", button: "bg-brand-blue", chip: "border-blue-500/30 text-blue-400 bg-blue-500/10", gradient: "from-blue-500/50 via-cyan-400/20 to-blue-600/30" },
51
+ "create-collection": { icon: "text-brand-purple", button: "bg-brand-purple", chip: "border-purple-500/30 text-purple-400 bg-purple-500/10", gradient: "from-purple-500/50 via-violet-400/20 to-purple-700/30" },
52
+ "ip-collection-1155": { icon: "text-brand-rose", button: "bg-brand-rose", chip: "border-rose-500/30 text-rose-400 bg-rose-500/10", gradient: "from-rose-500/50 via-pink-400/20 to-rose-700/30" },
53
+ "mint-editions": { icon: "text-brand-orange", button: "bg-brand-orange", chip: "border-orange-500/30 text-orange-400 bg-orange-500/10", gradient: "from-orange-500/50 via-amber-400/20 to-orange-700/30" },
54
+ "remix-asset": { icon: "text-brand-navy", button: "bg-brand-navy", chip: "border-indigo-700/30 text-indigo-300 bg-indigo-900/20", gradient: "from-blue-900/60 via-indigo-700/20 to-blue-800/30" },
55
+ "pop-protocol": { icon: "text-brand-orange", button: "bg-brand-orange", chip: "border-orange-500/30 text-orange-400 bg-orange-500/10", gradient: "from-orange-500/50 via-amber-400/20 to-orange-700/30" },
56
+ "collection-drop": { icon: "text-brand-rose", button: "bg-brand-rose", chip: "border-rose-500/30 text-rose-400 bg-rose-500/10", gradient: "from-rose-500/50 via-red-400/20 to-rose-700/30" },
57
+ "ip-tickets": { icon: "text-brand-blue", button: "bg-brand-blue", chip: "border-blue-500/30 text-blue-400 bg-blue-500/10", gradient: "from-blue-500/50 via-cyan-400/20 to-blue-600/30" },
58
+ "membership": { icon: "text-brand-purple", button: "bg-brand-purple", chip: "border-purple-500/30 text-purple-400 bg-purple-500/10", gradient: "from-purple-500/50 via-violet-400/20 to-purple-700/30" },
59
+ "subscriptions": { icon: "text-brand-blue", button: "bg-brand-blue", chip: "border-blue-500/30 text-blue-400 bg-blue-500/10", gradient: "from-blue-500/50 via-cyan-400/20 to-blue-600/30" },
60
+ "ip-coins": { icon: "text-brand-orange", button: "bg-brand-orange", chip: "border-orange-500/30 text-orange-400 bg-orange-500/10", gradient: "from-orange-500/50 via-amber-400/20 to-orange-700/30" },
61
+ "creator-coins": { icon: "text-brand-rose", button: "bg-brand-rose", chip: "border-rose-500/30 text-rose-400 bg-rose-500/10", gradient: "from-rose-500/50 via-pink-400/20 to-rose-700/30" },
62
+ "claim-memecoin": { icon: "text-brand-orange", button: "bg-brand-orange", chip: "border-orange-500/30 text-orange-400 bg-orange-500/10", gradient: "from-orange-500/50 via-amber-400/20 to-orange-700/30" },
63
+ "claim-username": { icon: "text-brand-purple", button: "bg-brand-purple", chip: "border-purple-500/30 text-purple-400 bg-purple-500/10", gradient: "from-purple-500/50 via-violet-400/20 to-purple-700/30" },
64
+ "claim-collection": { icon: "text-brand-blue", button: "bg-brand-blue", chip: "border-blue-500/30 text-blue-400 bg-blue-500/10", gradient: "from-blue-500/50 via-cyan-400/20 to-blue-600/30" }
65
+ };
66
+ function LaunchpadServiceCard({ def, override = {} }) {
67
+ const { key, icon: Icon, browseLinkLabel } = def;
68
+ const status = override.status ?? def.status;
69
+ const badge = override.badge ?? def.badge;
70
+ const subtitle = override.subtitle ?? def.subtitle;
71
+ const description = override.description ?? def.description;
72
+ const features = override.features ?? def.features;
73
+ const { href, buttonLabel, browseHref } = override;
56
74
  const live = status === "live";
57
75
  const building = status === "building";
58
76
  const active = live || building;
59
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
77
+ const colors = SERVICE_CARD_COLORS[key] ?? DEFAULT_COLORS;
78
+ const card = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
60
79
  "div",
61
80
  {
62
81
  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"
82
+ "relative rounded-[15px] bg-card flex flex-col overflow-hidden",
83
+ "transition-all duration-200 flex-1",
84
+ !active && "opacity-80"
68
85
  ),
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
- ] }),
86
+ children: [
118
87
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
119
- "p",
88
+ "div",
120
89
  {
90
+ "aria-hidden": true,
121
91
  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
92
+ "absolute inset-0 bg-gradient-to-br pointer-events-none",
93
+ colors.gradient,
94
+ active ? "opacity-[0.13]" : "opacity-[0.05]"
95
+ )
126
96
  }
127
97
  ),
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,
98
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative flex flex-col flex-1 p-6 gap-4", children: [
99
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-start justify-between", children: [
100
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative", children: [
101
+ active && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "aria-hidden": true, className: (0, import_cn.cn)("absolute -inset-3 rounded-full blur-2xl opacity-30", colors.button) }),
102
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: (0, import_cn.cn)("relative h-10 w-10 transition-transform duration-300", active ? colors.icon : "text-muted-foreground/45") })
103
+ ] }),
104
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
105
+ "span",
106
+ {
107
+ className: (0, import_cn.cn)(
108
+ "text-[10px] font-semibold tracking-widest uppercase rounded-full px-2.5 py-1 flex items-center gap-1.5",
109
+ live ? "text-emerald-500 bg-emerald-500/10" : building ? "text-amber-500 bg-amber-500/10" : "text-muted-foreground/40 bg-muted/30"
110
+ ),
111
+ children: [
112
+ live && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse" }),
113
+ !active && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Lock, { className: "h-2.5 w-2.5" }),
114
+ badge
115
+ ]
116
+ }
117
+ )
118
+ ] }),
119
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1", children: [
120
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: (0, import_cn.cn)("text-2xl font-bold leading-snug tracking-tight", !active && "text-foreground/60"), children: def.title }),
121
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: (0, import_cn.cn)("text-[13px] leading-relaxed", active ? "text-muted-foreground" : "text-muted-foreground/50"), children: subtitle })
122
+ ] }),
123
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-2", children: [
124
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: (0, import_cn.cn)("text-sm leading-relaxed", active ? "text-muted-foreground" : "text-muted-foreground/50"), children: description }),
125
+ def.example && active && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-muted-foreground/60 italic", children: def.example })
126
+ ] }),
127
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-wrap gap-1.5", children: features.map((f) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
128
+ "span",
142
129
  {
143
- href,
144
130
  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
131
+ "text-[11px] px-2.5 py-1 rounded-full border font-medium",
132
+ active ? colors.chip : "bg-muted/10 border-border/15 text-muted-foreground/45"
149
133
  ),
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"
134
+ children: f
135
+ },
136
+ f
137
+ )) }),
138
+ live && href ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-2 mt-auto pt-2", children: [
139
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
140
+ import_link.default,
141
+ {
142
+ href,
143
+ className: (0, import_cn.cn)(
144
+ "flex items-center justify-between w-full h-10 px-4 rounded-xl",
145
+ "text-sm font-semibold text-white",
146
+ "transition-all hover:brightness-110 active:scale-[0.98]",
147
+ colors.button
148
+ ),
149
+ children: [
150
+ buttonLabel ?? "Get started",
151
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ArrowRight, { className: "h-3.5 w-3.5" })
152
+ ]
153
+ }
154
+ ),
155
+ browseHref && browseLinkLabel && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
156
+ import_link.default,
157
+ {
158
+ href: browseHref,
159
+ className: "flex items-center justify-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors py-1",
160
+ children: [
161
+ browseLinkLabel,
162
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ArrowRight, { className: "h-3 w-3" })
163
+ ]
164
+ }
165
+ )
166
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 h-10 mt-auto pt-2 text-sm text-muted-foreground/50 font-medium", children: [
167
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Lock, { className: "h-3.5 w-3.5" }),
168
+ building ? "In development" : "Coming soon"
169
+ ] })
170
170
  ] })
171
- ] })
171
+ ]
172
172
  }
173
173
  );
174
+ return live ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_cn.cn)("p-[1px] rounded-2xl bg-gradient-to-br", colors.gradient, "transition-all duration-200 hover:-translate-y-0.5 hover:shadow-lg hover:shadow-black/25 flex flex-col"), children: card }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rounded-2xl border border-border/25 flex flex-col", children: card });
174
175
  }
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))
176
+ function GroupHeader({ group }) {
177
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1", children: [
178
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
179
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-xl font-bold tracking-tight", children: group.title }),
180
+ group.badge ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[10px] font-semibold tracking-widest uppercase rounded-full px-2 py-0.5 bg-muted/40 text-muted-foreground", children: group.badge }) : null
181
+ ] }),
182
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground", children: group.tagline })
183
+ ] });
184
+ }
185
+ function ComingSoonStrip({ group, defs }) {
186
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-2xl border border-border/25 p-5", children: [
187
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "section-label", children: group.title }),
188
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground mt-1", children: group.tagline }),
189
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-wrap gap-2 mt-4", children: defs.map(({ key, icon: Icon, title, subtitle }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 px-3 py-2 rounded-full bg-muted/30 border border-border/25", children: [
190
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: "h-3.5 w-3.5 text-muted-foreground/60" }),
191
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs font-semibold text-muted-foreground", children: title }),
192
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "hidden sm:inline text-xs text-muted-foreground/50", children: [
193
+ "\u2014 ",
194
+ subtitle
195
+ ] })
196
+ ] }, key)) })
197
+ ] });
198
+ }
199
+ function LaunchpadGroupedSections({ overrides, className }) {
200
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_cn.cn)("space-y-10", className), children: import_launchpad_services.LAUNCHPAD_SERVICE_GROUPS.map((group) => {
201
+ const defs = import_launchpad_services.LAUNCHPAD_SERVICE_DEFINITIONS.filter((d) => d.group === group.key);
202
+ if (defs.length === 0) return null;
203
+ if (group.key === "coming-soon") {
204
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComingSoonStrip, { group, defs }, group.key);
184
205
  }
185
- );
206
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
207
+ import_framer_motion.motion.div,
208
+ {
209
+ initial: { opacity: 0, y: 8 },
210
+ animate: { opacity: 1, y: 0 },
211
+ transition: { duration: 0.3, ease: [0.25, 0.46, 0.45, 0.94] },
212
+ className: "space-y-4",
213
+ children: [
214
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GroupHeader, { group }),
215
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-5", children: defs.map((def) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LaunchpadServiceCard, { def, override: overrides[def.key] }, def.key)) })
216
+ ]
217
+ },
218
+ group.key
219
+ );
220
+ }) });
186
221
  }
187
222
  // Annotate the CommonJS export names for ESM import in node:
188
223
  0 && (module.exports = {
189
- LaunchpadServicesGrid
224
+ LaunchpadGroupedSections,
225
+ LaunchpadServiceCard,
226
+ SERVICE_CARD_COLORS
190
227
  });
191
228
  //# sourceMappingURL=launchpad-services.cjs.map
@@ -1 +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"]}
1
+ {"version":3,"sources":["../../src/components/launchpad-services.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * Launchpad grouped services — the single source for the /launchpad page UI\n * in medialane-io and medialane-dapp (consolidated 2026-06-10; replaces the\n * old flat LaunchpadServicesGrid).\n *\n * Apps own: hrefs, button labels, per-app status/badge flips (rollout), and\n * any copy overrides (e.g. the gasless-rail chip wording). Everything else —\n * card design, group order, colors, copy — lives here.\n */\n\nimport Link from \"next/link\";\nimport { motion } from \"framer-motion\";\nimport { Lock, ArrowRight } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport {\n LAUNCHPAD_SERVICE_DEFINITIONS,\n LAUNCHPAD_SERVICE_GROUPS,\n type ServiceDefinition,\n type ServiceGroupDefinition,\n type ServiceStatus,\n} from \"../data/launchpad-services.js\";\n\n// ── Per-app injection points ─────────────────────────────────────────────────\n\nexport interface ServiceOverride {\n /** Primary CTA href — required for live services */\n href?: string;\n buttonLabel?: string;\n /** Secondary browse link href (pairs with the def's browseLinkLabel) */\n browseHref?: string;\n /** Per-app rollout flips (e.g. coins live on one app first) */\n status?: ServiceStatus;\n badge?: string;\n /** Per-app copy overrides (e.g. \"Gasless via ChipiPay\" vs \"Gasless transactions\") */\n features?: string[];\n description?: string;\n subtitle?: string;\n}\n\nexport type ServiceOverrides = Record<string, ServiceOverride>;\n\n// ── Brand color map per service key ──────────────────────────────────────────\n\ninterface ServiceCardColors {\n icon: string;\n button: string;\n chip: string;\n gradient: string;\n}\n\nconst DEFAULT_COLORS: ServiceCardColors = {\n icon: \"text-brand-blue\",\n button: \"bg-brand-blue\",\n chip: \"border-border/50 text-muted-foreground bg-muted/30\",\n gradient: \"from-border/40 to-border/20\",\n};\n\nexport const SERVICE_CARD_COLORS: Record<string, ServiceCardColors> = {\n \"mint-ip-asset\": { icon: \"text-brand-blue\", button: \"bg-brand-blue\", chip: \"border-blue-500/30 text-blue-400 bg-blue-500/10\", gradient: \"from-blue-500/50 via-cyan-400/20 to-blue-600/30\" },\n \"create-collection\": { icon: \"text-brand-purple\", button: \"bg-brand-purple\", chip: \"border-purple-500/30 text-purple-400 bg-purple-500/10\", gradient: \"from-purple-500/50 via-violet-400/20 to-purple-700/30\" },\n \"ip-collection-1155\": { icon: \"text-brand-rose\", button: \"bg-brand-rose\", chip: \"border-rose-500/30 text-rose-400 bg-rose-500/10\", gradient: \"from-rose-500/50 via-pink-400/20 to-rose-700/30\" },\n \"mint-editions\": { icon: \"text-brand-orange\", button: \"bg-brand-orange\", chip: \"border-orange-500/30 text-orange-400 bg-orange-500/10\", gradient: \"from-orange-500/50 via-amber-400/20 to-orange-700/30\" },\n \"remix-asset\": { icon: \"text-brand-navy\", button: \"bg-brand-navy\", chip: \"border-indigo-700/30 text-indigo-300 bg-indigo-900/20\", gradient: \"from-blue-900/60 via-indigo-700/20 to-blue-800/30\" },\n \"pop-protocol\": { icon: \"text-brand-orange\", button: \"bg-brand-orange\", chip: \"border-orange-500/30 text-orange-400 bg-orange-500/10\", gradient: \"from-orange-500/50 via-amber-400/20 to-orange-700/30\" },\n \"collection-drop\": { icon: \"text-brand-rose\", button: \"bg-brand-rose\", chip: \"border-rose-500/30 text-rose-400 bg-rose-500/10\", gradient: \"from-rose-500/50 via-red-400/20 to-rose-700/30\" },\n \"ip-tickets\": { icon: \"text-brand-blue\", button: \"bg-brand-blue\", chip: \"border-blue-500/30 text-blue-400 bg-blue-500/10\", gradient: \"from-blue-500/50 via-cyan-400/20 to-blue-600/30\" },\n \"membership\": { icon: \"text-brand-purple\", button: \"bg-brand-purple\", chip: \"border-purple-500/30 text-purple-400 bg-purple-500/10\", gradient: \"from-purple-500/50 via-violet-400/20 to-purple-700/30\" },\n \"subscriptions\": { icon: \"text-brand-blue\", button: \"bg-brand-blue\", chip: \"border-blue-500/30 text-blue-400 bg-blue-500/10\", gradient: \"from-blue-500/50 via-cyan-400/20 to-blue-600/30\" },\n \"ip-coins\": { icon: \"text-brand-orange\", button: \"bg-brand-orange\", chip: \"border-orange-500/30 text-orange-400 bg-orange-500/10\", gradient: \"from-orange-500/50 via-amber-400/20 to-orange-700/30\" },\n \"creator-coins\": { icon: \"text-brand-rose\", button: \"bg-brand-rose\", chip: \"border-rose-500/30 text-rose-400 bg-rose-500/10\", gradient: \"from-rose-500/50 via-pink-400/20 to-rose-700/30\" },\n \"claim-memecoin\": { icon: \"text-brand-orange\", button: \"bg-brand-orange\", chip: \"border-orange-500/30 text-orange-400 bg-orange-500/10\", gradient: \"from-orange-500/50 via-amber-400/20 to-orange-700/30\" },\n \"claim-username\": { icon: \"text-brand-purple\", button: \"bg-brand-purple\", chip: \"border-purple-500/30 text-purple-400 bg-purple-500/10\", gradient: \"from-purple-500/50 via-violet-400/20 to-purple-700/30\" },\n \"claim-collection\": { icon: \"text-brand-blue\", button: \"bg-brand-blue\", chip: \"border-blue-500/30 text-blue-400 bg-blue-500/10\", gradient: \"from-blue-500/50 via-cyan-400/20 to-blue-600/30\" },\n};\n\n// ── Service card ─────────────────────────────────────────────────────────────\n\nexport interface LaunchpadServiceCardProps {\n def: ServiceDefinition;\n override?: ServiceOverride;\n}\n\nexport function LaunchpadServiceCard({ def, override = {} }: LaunchpadServiceCardProps) {\n const { key, icon: Icon, browseLinkLabel } = def;\n const status = override.status ?? def.status;\n const badge = override.badge ?? def.badge;\n const subtitle = override.subtitle ?? def.subtitle;\n const description = override.description ?? def.description;\n const features = override.features ?? def.features;\n const { href, buttonLabel, browseHref } = override;\n\n const live = status === \"live\";\n const building = status === \"building\";\n const active = live || building;\n const colors = SERVICE_CARD_COLORS[key] ?? DEFAULT_COLORS;\n\n const card = (\n <div\n className={cn(\n \"relative rounded-[15px] bg-card flex flex-col overflow-hidden\",\n \"transition-all duration-200 flex-1\",\n !active && \"opacity-80\",\n )}\n >\n {/* Atmospheric wash — per-service color, fades to nothing */}\n <div\n aria-hidden\n className={cn(\n \"absolute inset-0 bg-gradient-to-br pointer-events-none\",\n colors.gradient,\n active ? \"opacity-[0.13]\" : \"opacity-[0.05]\",\n )}\n />\n <div className=\"relative flex flex-col flex-1 p-6 gap-4\">\n {/* Icon (soft glow) + status badge */}\n <div className=\"flex items-start justify-between\">\n <div className=\"relative\">\n {active && (\n <div aria-hidden className={cn(\"absolute -inset-3 rounded-full blur-2xl opacity-30\", colors.button)} />\n )}\n <Icon className={cn(\"relative h-10 w-10 transition-transform duration-300\", active ? colors.icon : \"text-muted-foreground/45\")} />\n </div>\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-500 bg-emerald-500/10\"\n : building\n ? \"text-amber-500 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\">\n <p className={cn(\"text-2xl font-bold leading-snug tracking-tight\", !active && \"text-foreground/60\")}>\n {def.title}\n </p>\n <p className={cn(\"text-[13px] leading-relaxed\", active ? \"text-muted-foreground\" : \"text-muted-foreground/50\")}>\n {subtitle}\n </p>\n </div>\n\n {/* Description */}\n <div className=\"space-y-2\">\n <p className={cn(\"text-sm leading-relaxed\", active ? \"text-muted-foreground\" : \"text-muted-foreground/50\")}>\n {description}\n </p>\n {def.example && active && (\n <p className=\"text-xs text-muted-foreground/60 italic\">{def.example}</p>\n )}\n </div>\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 ? colors.chip : \"bg-muted/10 border-border/15 text-muted-foreground/45\",\n )}\n >\n {f}\n </span>\n ))}\n </div>\n\n {/* CTA — pinned to the card bottom */}\n {live && href ? (\n <div className=\"space-y-2 mt-auto pt-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 hover:brightness-110 active:scale-[0.98]\",\n colors.button,\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 mt-auto pt-2 text-sm text-muted-foreground/50 font-medium\">\n <Lock className=\"h-3.5 w-3.5\" />\n {building ? \"In development\" : \"Coming soon\"}\n </div>\n )}\n </div>\n </div>\n );\n\n return live ? (\n <div className={cn(\"p-[1px] rounded-2xl bg-gradient-to-br\", colors.gradient, \"transition-all duration-200 hover:-translate-y-0.5 hover:shadow-lg hover:shadow-black/25 flex flex-col\")}>\n {card}\n </div>\n ) : (\n <div className=\"rounded-2xl border border-border/25 flex flex-col\">{card}</div>\n );\n}\n\n// ── Group sections ───────────────────────────────────────────────────────────\n\nfunction GroupHeader({ group }: { group: ServiceGroupDefinition }) {\n return (\n <div className=\"space-y-1\">\n <div className=\"flex items-center gap-2\">\n <h2 className=\"text-xl font-bold tracking-tight\">{group.title}</h2>\n {group.badge ? (\n <span className=\"text-[10px] font-semibold tracking-widest uppercase rounded-full px-2 py-0.5 bg-muted/40 text-muted-foreground\">\n {group.badge}\n </span>\n ) : null}\n </div>\n <p className=\"text-sm text-muted-foreground\">{group.tagline}</p>\n </div>\n );\n}\n\nfunction ComingSoonStrip({ group, defs }: { group: ServiceGroupDefinition; defs: ServiceDefinition[] }) {\n return (\n <div className=\"rounded-2xl border border-border/25 p-5\">\n <p className=\"section-label\">{group.title}</p>\n <p className=\"text-sm text-muted-foreground mt-1\">{group.tagline}</p>\n <div className=\"flex flex-wrap gap-2 mt-4\">\n {defs.map(({ key, icon: Icon, title, subtitle }) => (\n <div key={key} className=\"flex items-center gap-2 px-3 py-2 rounded-full bg-muted/30 border border-border/25\">\n <Icon className=\"h-3.5 w-3.5 text-muted-foreground/60\" />\n <span className=\"text-xs font-semibold text-muted-foreground\">{title}</span>\n <span className=\"hidden sm:inline text-xs text-muted-foreground/50\">— {subtitle}</span>\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nexport interface LaunchpadGroupedSectionsProps {\n /** Per-app hrefs / labels / rollout flips / copy overrides, keyed by service key. */\n overrides: ServiceOverrides;\n className?: string;\n}\n\n/** The full grouped launchpad services block — section order comes from\n * LAUNCHPAD_SERVICE_GROUPS; cards from LAUNCHPAD_SERVICE_DEFINITIONS. */\nexport function LaunchpadGroupedSections({ overrides, className }: LaunchpadGroupedSectionsProps) {\n return (\n <div className={cn(\"space-y-10\", className)}>\n {LAUNCHPAD_SERVICE_GROUPS.map((group) => {\n const defs = LAUNCHPAD_SERVICE_DEFINITIONS.filter((d) => d.group === group.key);\n if (defs.length === 0) return null;\n if (group.key === \"coming-soon\") {\n return <ComingSoonStrip key={group.key} group={group} defs={defs} />;\n }\n return (\n <motion.div\n key={group.key}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.3, ease: [0.25, 0.46, 0.45, 0.94] }}\n className=\"space-y-4\"\n >\n <GroupHeader group={group} />\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-5\">\n {defs.map((def) => (\n <LaunchpadServiceCard key={def.key} def={def} override={overrides[def.key]} />\n ))}\n </div>\n </motion.div>\n );\n })}\n </div>\n );\n}\n"],"mappings":"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","names":["Link"]}
@@ -1,20 +1,41 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ServiceDefinition } from '../data/launchpad-services.cjs';
3
- export { ServiceCategory, ServiceStatus } from '../data/launchpad-services.cjs';
2
+ import { ServiceStatus, ServiceDefinition } from '../data/launchpad-services.cjs';
4
3
  import 'lucide-react';
5
4
 
6
- interface ServiceCardProps extends ServiceDefinition {
5
+ interface ServiceOverride {
7
6
  /** Primary CTA href — required for live services */
8
7
  href?: string;
9
- /** Primary CTA button label */
10
8
  buttonLabel?: string;
11
- /** Secondary browse link href */
9
+ /** Secondary browse link href (pairs with the def's browseLinkLabel) */
12
10
  browseHref?: string;
11
+ /** Per-app rollout flips (e.g. coins live on one app first) */
12
+ status?: ServiceStatus;
13
+ badge?: string;
14
+ /** Per-app copy overrides (e.g. "Gasless via ChipiPay" vs "Gasless transactions") */
15
+ features?: string[];
16
+ description?: string;
17
+ subtitle?: string;
13
18
  }
14
- interface LaunchpadServicesGridProps {
15
- services: ServiceCardProps[];
19
+ type ServiceOverrides = Record<string, ServiceOverride>;
20
+ interface ServiceCardColors {
21
+ icon: string;
22
+ button: string;
23
+ chip: string;
24
+ gradient: string;
25
+ }
26
+ declare const SERVICE_CARD_COLORS: Record<string, ServiceCardColors>;
27
+ interface LaunchpadServiceCardProps {
28
+ def: ServiceDefinition;
29
+ override?: ServiceOverride;
30
+ }
31
+ declare function LaunchpadServiceCard({ def, override }: LaunchpadServiceCardProps): react_jsx_runtime.JSX.Element;
32
+ interface LaunchpadGroupedSectionsProps {
33
+ /** Per-app hrefs / labels / rollout flips / copy overrides, keyed by service key. */
34
+ overrides: ServiceOverrides;
16
35
  className?: string;
17
36
  }
18
- declare function LaunchpadServicesGrid({ services, className }: LaunchpadServicesGridProps): react_jsx_runtime.JSX.Element;
37
+ /** The full grouped launchpad services block section order comes from
38
+ * LAUNCHPAD_SERVICE_GROUPS; cards from LAUNCHPAD_SERVICE_DEFINITIONS. */
39
+ declare function LaunchpadGroupedSections({ overrides, className }: LaunchpadGroupedSectionsProps): react_jsx_runtime.JSX.Element;
19
40
 
20
- export { LaunchpadServicesGrid, type LaunchpadServicesGridProps, type ServiceCardProps, ServiceDefinition };
41
+ export { LaunchpadGroupedSections, type LaunchpadGroupedSectionsProps, LaunchpadServiceCard, type LaunchpadServiceCardProps, SERVICE_CARD_COLORS, type ServiceOverride, type ServiceOverrides };
@@ -1,20 +1,41 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ServiceDefinition } from '../data/launchpad-services.js';
3
- export { ServiceCategory, ServiceStatus } from '../data/launchpad-services.js';
2
+ import { ServiceStatus, ServiceDefinition } from '../data/launchpad-services.js';
4
3
  import 'lucide-react';
5
4
 
6
- interface ServiceCardProps extends ServiceDefinition {
5
+ interface ServiceOverride {
7
6
  /** Primary CTA href — required for live services */
8
7
  href?: string;
9
- /** Primary CTA button label */
10
8
  buttonLabel?: string;
11
- /** Secondary browse link href */
9
+ /** Secondary browse link href (pairs with the def's browseLinkLabel) */
12
10
  browseHref?: string;
11
+ /** Per-app rollout flips (e.g. coins live on one app first) */
12
+ status?: ServiceStatus;
13
+ badge?: string;
14
+ /** Per-app copy overrides (e.g. "Gasless via ChipiPay" vs "Gasless transactions") */
15
+ features?: string[];
16
+ description?: string;
17
+ subtitle?: string;
13
18
  }
14
- interface LaunchpadServicesGridProps {
15
- services: ServiceCardProps[];
19
+ type ServiceOverrides = Record<string, ServiceOverride>;
20
+ interface ServiceCardColors {
21
+ icon: string;
22
+ button: string;
23
+ chip: string;
24
+ gradient: string;
25
+ }
26
+ declare const SERVICE_CARD_COLORS: Record<string, ServiceCardColors>;
27
+ interface LaunchpadServiceCardProps {
28
+ def: ServiceDefinition;
29
+ override?: ServiceOverride;
30
+ }
31
+ declare function LaunchpadServiceCard({ def, override }: LaunchpadServiceCardProps): react_jsx_runtime.JSX.Element;
32
+ interface LaunchpadGroupedSectionsProps {
33
+ /** Per-app hrefs / labels / rollout flips / copy overrides, keyed by service key. */
34
+ overrides: ServiceOverrides;
16
35
  className?: string;
17
36
  }
18
- declare function LaunchpadServicesGrid({ services, className }: LaunchpadServicesGridProps): react_jsx_runtime.JSX.Element;
37
+ /** The full grouped launchpad services block section order comes from
38
+ * LAUNCHPAD_SERVICE_GROUPS; cards from LAUNCHPAD_SERVICE_DEFINITIONS. */
39
+ declare function LaunchpadGroupedSections({ overrides, className }: LaunchpadGroupedSectionsProps): react_jsx_runtime.JSX.Element;
19
40
 
20
- export { LaunchpadServicesGrid, type LaunchpadServicesGridProps, type ServiceCardProps, ServiceDefinition };
41
+ export { LaunchpadGroupedSections, type LaunchpadGroupedSectionsProps, LaunchpadServiceCard, type LaunchpadServiceCardProps, SERVICE_CARD_COLORS, type ServiceOverride, type ServiceOverrides };