@medialane/ui 0.50.1 → 0.52.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.
@@ -23,31 +23,37 @@ __export(claim_rail_exports, {
23
23
  module.exports = __toCommonJS(claim_rail_exports);
24
24
  var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_lucide_react = require("lucide-react");
26
- const LABEL = "text-xs font-semibold uppercase tracking-wider text-white/70";
27
- const CHIP = "h-8 w-8 rounded-lg bg-white/20 backdrop-blur-sm flex items-center justify-center shrink-0";
26
+ const MONO = '"Geist Mono", ui-monospace, SFMono-Regular, monospace';
28
27
  function ClaimRail({ included, steps, trustLead, trust, trustIcon: TrustIcon = import_lucide_react.ShieldCheck }) {
29
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
30
- included && included.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-2xl p-5 bg-gradient-to-br from-blue-600 to-indigo-700 text-white", children: [
31
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: LABEL, children: "What's included" }),
28
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-2xl border border-border/60 bg-card divide-y divide-border/60 overflow-hidden", children: [
29
+ included && included.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "p-5", children: [
30
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "section-label", children: "What's included" }),
32
31
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "mt-4 space-y-4", children: included.map(({ icon: Icon, title, desc }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "flex items-start gap-3", children: [
33
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: CHIP, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: "h-4 w-4 text-white" }) }),
32
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-8 w-8 rounded-lg bg-brand-blue/10 flex items-center justify-center shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: "h-4 w-4 text-brand-blue" }) }),
34
33
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "min-w-0", children: [
35
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-semibold", children: title }),
36
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-white/80 leading-relaxed mt-0.5", children: desc })
34
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-semibold text-foreground", children: title }),
35
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground leading-relaxed mt-0.5", children: desc })
37
36
  ] })
38
37
  ] }, title)) })
39
38
  ] }),
40
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-2xl p-5 bg-gradient-to-br from-violet-600 to-fuchsia-700 text-white", children: [
41
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: LABEL, children: "How it works" }),
39
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "p-5", children: [
40
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "section-label", children: "How it works" }),
42
41
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "mt-4 space-y-3", children: steps.map((label, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "flex items-center gap-3", children: [
43
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `${CHIP} text-sm font-bold`, children: i + 1 }),
44
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-sm text-white/90", children: label })
42
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43
+ "span",
44
+ {
45
+ className: "h-8 w-8 rounded-lg bg-brand-purple/10 text-brand-purple flex items-center justify-center shrink-0 text-[13px] font-bold",
46
+ style: { fontFamily: MONO },
47
+ children: i + 1
48
+ }
49
+ ),
50
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-sm text-foreground/90", children: label })
45
51
  ] }, label)) })
46
52
  ] }),
47
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-2xl p-5 bg-gradient-to-br from-rose-600 to-orange-600 text-white flex items-start gap-3", children: [
48
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TrustIcon, { className: "h-5 w-5 text-white shrink-0 mt-0.5" }),
49
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-sm text-white/90 leading-relaxed", children: [
50
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-semibold", children: trustLead }),
53
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "p-5 bg-muted/40 flex items-start gap-3", children: [
54
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TrustIcon, { className: "h-5 w-5 text-brand-orange shrink-0 mt-0.5" }),
55
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-sm text-muted-foreground leading-relaxed", children: [
56
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-semibold text-foreground", children: trustLead }),
51
57
  " ",
52
58
  trust
53
59
  ] })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/claim-rail.tsx"],"sourcesContent":["import { ShieldCheck, type LucideIcon } from \"lucide-react\";\n\nexport interface ClaimRailProps {\n /** \"What's included\" benefits. Omit to hide that panel (e.g. when a live\n * preview is the rail's first panel instead). */\n included?: { icon: LucideIcon; title: string; desc: string }[];\n /** \"How it works\" ordered steps. */\n steps: string[];\n /** Trust/assurance note: bold lead + the rest of the sentence. */\n trustLead: string;\n trust: string;\n /** Trust glyph — defaults to a shield. */\n trustIcon?: LucideIcon;\n}\n\nconst LABEL = \"text-xs font-semibold uppercase tracking-wider text-white/70\";\nconst CHIP = \"h-8 w-8 rounded-lg bg-white/20 backdrop-blur-sm flex items-center justify-center shrink-0\";\n\n/** Vivid right-rail for launchpad/claim pages — three \"good vibes\" gradient\n * panels (What's included · How it works · trust) flowing as a spectrum.\n * Pure presentation; the consuming app passes the per-surface content. */\nexport function ClaimRail({ included, steps, trustLead, trust, trustIcon: TrustIcon = ShieldCheck }: ClaimRailProps) {\n return (\n <>\n {included && included.length > 0 && (\n <div className=\"rounded-2xl p-5 bg-gradient-to-br from-blue-600 to-indigo-700 text-white\">\n <p className={LABEL}>What&apos;s included</p>\n <ul className=\"mt-4 space-y-4\">\n {included.map(({ icon: Icon, title, desc }) => (\n <li key={title} className=\"flex items-start gap-3\">\n <div className={CHIP}>\n <Icon className=\"h-4 w-4 text-white\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold\">{title}</p>\n <p className=\"text-sm text-white/80 leading-relaxed mt-0.5\">{desc}</p>\n </div>\n </li>\n ))}\n </ul>\n </div>\n )}\n\n <div className=\"rounded-2xl p-5 bg-gradient-to-br from-violet-600 to-fuchsia-700 text-white\">\n <p className={LABEL}>How it works</p>\n <ol className=\"mt-4 space-y-3\">\n {steps.map((label, i) => (\n <li key={label} className=\"flex items-center gap-3\">\n <span className={`${CHIP} text-sm font-bold`}>{i + 1}</span>\n <span className=\"text-sm text-white/90\">{label}</span>\n </li>\n ))}\n </ol>\n </div>\n\n <div className=\"rounded-2xl p-5 bg-gradient-to-br from-rose-600 to-orange-600 text-white flex items-start gap-3\">\n <TrustIcon className=\"h-5 w-5 text-white shrink-0 mt-0.5\" />\n <p className=\"text-sm text-white/90 leading-relaxed\">\n <span className=\"font-semibold\">{trustLead}</span> {trust}\n </p>\n </div>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBI;AAvBJ,0BAA6C;AAe7C,MAAM,QAAQ;AACd,MAAM,OAAO;AAKN,SAAS,UAAU,EAAE,UAAU,OAAO,WAAW,OAAO,WAAW,YAAY,gCAAY,GAAmB;AACnH,SACE,4EACG;AAAA,gBAAY,SAAS,SAAS,KAC7B,6CAAC,SAAI,WAAU,4EACb;AAAA,kDAAC,OAAE,WAAW,OAAO,6BAAoB;AAAA,MACzC,4CAAC,QAAG,WAAU,kBACX,mBAAS,IAAI,CAAC,EAAE,MAAM,MAAM,OAAO,KAAK,MACvC,6CAAC,QAAe,WAAU,0BACxB;AAAA,oDAAC,SAAI,WAAW,MACd,sDAAC,QAAK,WAAU,sBAAqB,GACvC;AAAA,QACA,6CAAC,SAAI,WAAU,WACb;AAAA,sDAAC,OAAE,WAAU,yBAAyB,iBAAM;AAAA,UAC5C,4CAAC,OAAE,WAAU,gDAAgD,gBAAK;AAAA,WACpE;AAAA,WAPO,KAQT,CACD,GACH;AAAA,OACF;AAAA,IAGF,6CAAC,SAAI,WAAU,+EACb;AAAA,kDAAC,OAAE,WAAW,OAAO,0BAAY;AAAA,MACjC,4CAAC,QAAG,WAAU,kBACX,gBAAM,IAAI,CAAC,OAAO,MACjB,6CAAC,QAAe,WAAU,2BACxB;AAAA,oDAAC,UAAK,WAAW,GAAG,IAAI,sBAAuB,cAAI,GAAE;AAAA,QACrD,4CAAC,UAAK,WAAU,yBAAyB,iBAAM;AAAA,WAFxC,KAGT,CACD,GACH;AAAA,OACF;AAAA,IAEA,6CAAC,SAAI,WAAU,mGACb;AAAA,kDAAC,aAAU,WAAU,sCAAqC;AAAA,MAC1D,6CAAC,OAAE,WAAU,yCACX;AAAA,oDAAC,UAAK,WAAU,iBAAiB,qBAAU;AAAA,QAAO;AAAA,QAAE;AAAA,SACtD;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/claim-rail.tsx"],"sourcesContent":["import { ShieldCheck, type LucideIcon } from \"lucide-react\";\n\nexport interface ClaimRailProps {\n /** \"What's included\" benefits. Omit to hide that panel (e.g. when a live\n * preview is the rail's first panel instead). */\n included?: { icon: LucideIcon; title: string; desc: string }[];\n /** \"How it works\" ordered steps. */\n steps: string[];\n /** Trust/assurance note: bold lead + the rest of the sentence. */\n trustLead: string;\n trust: string;\n /** Trust glyph — defaults to a shield. */\n trustIcon?: LucideIcon;\n}\n\nconst MONO = '\"Geist Mono\", ui-monospace, SFMono-Regular, monospace';\n\n/** Right-rail for launchpad/claim pages — one quiet sectioned card\n * (What's included · How it works · trust). The brand spectrum appears only\n * as tints: blue benefit chips → purple step numerals → orange trust glyph.\n * Pure presentation; the consuming app passes the per-surface content. */\nexport function ClaimRail({ included, steps, trustLead, trust, trustIcon: TrustIcon = ShieldCheck }: ClaimRailProps) {\n return (\n <div className=\"rounded-2xl border border-border/60 bg-card divide-y divide-border/60 overflow-hidden\">\n {included && included.length > 0 && (\n <section className=\"p-5\">\n <p className=\"section-label\">What&apos;s included</p>\n <ul className=\"mt-4 space-y-4\">\n {included.map(({ icon: Icon, title, desc }) => (\n <li key={title} className=\"flex items-start gap-3\">\n <div className=\"h-8 w-8 rounded-lg bg-brand-blue/10 flex items-center justify-center shrink-0\">\n <Icon className=\"h-4 w-4 text-brand-blue\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-foreground\">{title}</p>\n <p className=\"text-sm text-muted-foreground leading-relaxed mt-0.5\">{desc}</p>\n </div>\n </li>\n ))}\n </ul>\n </section>\n )}\n\n <section className=\"p-5\">\n <p className=\"section-label\">How it works</p>\n <ol className=\"mt-4 space-y-3\">\n {steps.map((label, i) => (\n <li key={label} className=\"flex items-center gap-3\">\n <span\n className=\"h-8 w-8 rounded-lg bg-brand-purple/10 text-brand-purple flex items-center justify-center shrink-0 text-[13px] font-bold\"\n style={{ fontFamily: MONO }}\n >\n {i + 1}\n </span>\n <span className=\"text-sm text-foreground/90\">{label}</span>\n </li>\n ))}\n </ol>\n </section>\n\n <section className=\"p-5 bg-muted/40 flex items-start gap-3\">\n <TrustIcon className=\"h-5 w-5 text-brand-orange shrink-0 mt-0.5\" />\n <p className=\"text-sm text-muted-foreground leading-relaxed\">\n <span className=\"font-semibold text-foreground\">{trustLead}</span> {trust}\n </p>\n </section>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BU;AA1BV,0BAA6C;AAe7C,MAAM,OAAO;AAMN,SAAS,UAAU,EAAE,UAAU,OAAO,WAAW,OAAO,WAAW,YAAY,gCAAY,GAAmB;AACnH,SACE,6CAAC,SAAI,WAAU,yFACZ;AAAA,gBAAY,SAAS,SAAS,KAC7B,6CAAC,aAAQ,WAAU,OACjB;AAAA,kDAAC,OAAE,WAAU,iBAAgB,6BAAoB;AAAA,MACjD,4CAAC,QAAG,WAAU,kBACX,mBAAS,IAAI,CAAC,EAAE,MAAM,MAAM,OAAO,KAAK,MACvC,6CAAC,QAAe,WAAU,0BACxB;AAAA,oDAAC,SAAI,WAAU,iFACb,sDAAC,QAAK,WAAU,2BAA0B,GAC5C;AAAA,QACA,6CAAC,SAAI,WAAU,WACb;AAAA,sDAAC,OAAE,WAAU,yCAAyC,iBAAM;AAAA,UAC5D,4CAAC,OAAE,WAAU,wDAAwD,gBAAK;AAAA,WAC5E;AAAA,WAPO,KAQT,CACD,GACH;AAAA,OACF;AAAA,IAGF,6CAAC,aAAQ,WAAU,OACjB;AAAA,kDAAC,OAAE,WAAU,iBAAgB,0BAAY;AAAA,MACzC,4CAAC,QAAG,WAAU,kBACX,gBAAM,IAAI,CAAC,OAAO,MACjB,6CAAC,QAAe,WAAU,2BACxB;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,YAAY,KAAK;AAAA,YAEzB,cAAI;AAAA;AAAA,QACP;AAAA,QACA,4CAAC,UAAK,WAAU,8BAA8B,iBAAM;AAAA,WAP7C,KAQT,CACD,GACH;AAAA,OACF;AAAA,IAEA,6CAAC,aAAQ,WAAU,0CACjB;AAAA,kDAAC,aAAU,WAAU,6CAA4C;AAAA,MACjE,6CAAC,OAAE,WAAU,iDACX;AAAA,oDAAC,UAAK,WAAU,iCAAiC,qBAAU;AAAA,QAAO;AAAA,QAAE;AAAA,SACtE;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
@@ -17,8 +17,9 @@ interface ClaimRailProps {
17
17
  /** Trust glyph — defaults to a shield. */
18
18
  trustIcon?: LucideIcon;
19
19
  }
20
- /** Vivid right-rail for launchpad/claim pages — three "good vibes" gradient
21
- * panels (What's included · How it works · trust) flowing as a spectrum.
20
+ /** Right-rail for launchpad/claim pages — one quiet sectioned card
21
+ * (What's included · How it works · trust). The brand spectrum appears only
22
+ * as tints: blue benefit chips → purple step numerals → orange trust glyph.
22
23
  * Pure presentation; the consuming app passes the per-surface content. */
23
24
  declare function ClaimRail({ included, steps, trustLead, trust, trustIcon: TrustIcon }: ClaimRailProps): react_jsx_runtime.JSX.Element;
24
25
 
@@ -17,8 +17,9 @@ interface ClaimRailProps {
17
17
  /** Trust glyph — defaults to a shield. */
18
18
  trustIcon?: LucideIcon;
19
19
  }
20
- /** Vivid right-rail for launchpad/claim pages — three "good vibes" gradient
21
- * panels (What's included · How it works · trust) flowing as a spectrum.
20
+ /** Right-rail for launchpad/claim pages — one quiet sectioned card
21
+ * (What's included · How it works · trust). The brand spectrum appears only
22
+ * as tints: blue benefit chips → purple step numerals → orange trust glyph.
22
23
  * Pure presentation; the consuming app passes the per-surface content. */
23
24
  declare function ClaimRail({ included, steps, trustLead, trust, trustIcon: TrustIcon }: ClaimRailProps): react_jsx_runtime.JSX.Element;
24
25
 
@@ -1,30 +1,36 @@
1
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { ShieldCheck } from "lucide-react";
3
- const LABEL = "text-xs font-semibold uppercase tracking-wider text-white/70";
4
- const CHIP = "h-8 w-8 rounded-lg bg-white/20 backdrop-blur-sm flex items-center justify-center shrink-0";
3
+ const MONO = '"Geist Mono", ui-monospace, SFMono-Regular, monospace';
5
4
  function ClaimRail({ included, steps, trustLead, trust, trustIcon: TrustIcon = ShieldCheck }) {
6
- return /* @__PURE__ */ jsxs(Fragment, { children: [
7
- included && included.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-2xl p-5 bg-gradient-to-br from-blue-600 to-indigo-700 text-white", children: [
8
- /* @__PURE__ */ jsx("p", { className: LABEL, children: "What's included" }),
5
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-border/60 bg-card divide-y divide-border/60 overflow-hidden", children: [
6
+ included && included.length > 0 && /* @__PURE__ */ jsxs("section", { className: "p-5", children: [
7
+ /* @__PURE__ */ jsx("p", { className: "section-label", children: "What's included" }),
9
8
  /* @__PURE__ */ jsx("ul", { className: "mt-4 space-y-4", children: included.map(({ icon: Icon, title, desc }) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-3", children: [
10
- /* @__PURE__ */ jsx("div", { className: CHIP, children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 text-white" }) }),
9
+ /* @__PURE__ */ jsx("div", { className: "h-8 w-8 rounded-lg bg-brand-blue/10 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 text-brand-blue" }) }),
11
10
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
12
- /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: title }),
13
- /* @__PURE__ */ jsx("p", { className: "text-sm text-white/80 leading-relaxed mt-0.5", children: desc })
11
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: title }),
12
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground leading-relaxed mt-0.5", children: desc })
14
13
  ] })
15
14
  ] }, title)) })
16
15
  ] }),
17
- /* @__PURE__ */ jsxs("div", { className: "rounded-2xl p-5 bg-gradient-to-br from-violet-600 to-fuchsia-700 text-white", children: [
18
- /* @__PURE__ */ jsx("p", { className: LABEL, children: "How it works" }),
16
+ /* @__PURE__ */ jsxs("section", { className: "p-5", children: [
17
+ /* @__PURE__ */ jsx("p", { className: "section-label", children: "How it works" }),
19
18
  /* @__PURE__ */ jsx("ol", { className: "mt-4 space-y-3", children: steps.map((label, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-3", children: [
20
- /* @__PURE__ */ jsx("span", { className: `${CHIP} text-sm font-bold`, children: i + 1 }),
21
- /* @__PURE__ */ jsx("span", { className: "text-sm text-white/90", children: label })
19
+ /* @__PURE__ */ jsx(
20
+ "span",
21
+ {
22
+ className: "h-8 w-8 rounded-lg bg-brand-purple/10 text-brand-purple flex items-center justify-center shrink-0 text-[13px] font-bold",
23
+ style: { fontFamily: MONO },
24
+ children: i + 1
25
+ }
26
+ ),
27
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground/90", children: label })
22
28
  ] }, label)) })
23
29
  ] }),
24
- /* @__PURE__ */ jsxs("div", { className: "rounded-2xl p-5 bg-gradient-to-br from-rose-600 to-orange-600 text-white flex items-start gap-3", children: [
25
- /* @__PURE__ */ jsx(TrustIcon, { className: "h-5 w-5 text-white shrink-0 mt-0.5" }),
26
- /* @__PURE__ */ jsxs("p", { className: "text-sm text-white/90 leading-relaxed", children: [
27
- /* @__PURE__ */ jsx("span", { className: "font-semibold", children: trustLead }),
30
+ /* @__PURE__ */ jsxs("section", { className: "p-5 bg-muted/40 flex items-start gap-3", children: [
31
+ /* @__PURE__ */ jsx(TrustIcon, { className: "h-5 w-5 text-brand-orange shrink-0 mt-0.5" }),
32
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground leading-relaxed", children: [
33
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: trustLead }),
28
34
  " ",
29
35
  trust
30
36
  ] })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/claim-rail.tsx"],"sourcesContent":["import { ShieldCheck, type LucideIcon } from \"lucide-react\";\n\nexport interface ClaimRailProps {\n /** \"What's included\" benefits. Omit to hide that panel (e.g. when a live\n * preview is the rail's first panel instead). */\n included?: { icon: LucideIcon; title: string; desc: string }[];\n /** \"How it works\" ordered steps. */\n steps: string[];\n /** Trust/assurance note: bold lead + the rest of the sentence. */\n trustLead: string;\n trust: string;\n /** Trust glyph — defaults to a shield. */\n trustIcon?: LucideIcon;\n}\n\nconst LABEL = \"text-xs font-semibold uppercase tracking-wider text-white/70\";\nconst CHIP = \"h-8 w-8 rounded-lg bg-white/20 backdrop-blur-sm flex items-center justify-center shrink-0\";\n\n/** Vivid right-rail for launchpad/claim pages — three \"good vibes\" gradient\n * panels (What's included · How it works · trust) flowing as a spectrum.\n * Pure presentation; the consuming app passes the per-surface content. */\nexport function ClaimRail({ included, steps, trustLead, trust, trustIcon: TrustIcon = ShieldCheck }: ClaimRailProps) {\n return (\n <>\n {included && included.length > 0 && (\n <div className=\"rounded-2xl p-5 bg-gradient-to-br from-blue-600 to-indigo-700 text-white\">\n <p className={LABEL}>What&apos;s included</p>\n <ul className=\"mt-4 space-y-4\">\n {included.map(({ icon: Icon, title, desc }) => (\n <li key={title} className=\"flex items-start gap-3\">\n <div className={CHIP}>\n <Icon className=\"h-4 w-4 text-white\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold\">{title}</p>\n <p className=\"text-sm text-white/80 leading-relaxed mt-0.5\">{desc}</p>\n </div>\n </li>\n ))}\n </ul>\n </div>\n )}\n\n <div className=\"rounded-2xl p-5 bg-gradient-to-br from-violet-600 to-fuchsia-700 text-white\">\n <p className={LABEL}>How it works</p>\n <ol className=\"mt-4 space-y-3\">\n {steps.map((label, i) => (\n <li key={label} className=\"flex items-center gap-3\">\n <span className={`${CHIP} text-sm font-bold`}>{i + 1}</span>\n <span className=\"text-sm text-white/90\">{label}</span>\n </li>\n ))}\n </ol>\n </div>\n\n <div className=\"rounded-2xl p-5 bg-gradient-to-br from-rose-600 to-orange-600 text-white flex items-start gap-3\">\n <TrustIcon className=\"h-5 w-5 text-white shrink-0 mt-0.5\" />\n <p className=\"text-sm text-white/90 leading-relaxed\">\n <span className=\"font-semibold\">{trustLead}</span> {trust}\n </p>\n </div>\n </>\n );\n}\n"],"mappings":"AAuBI,mBAGM,KAOM,YAVZ;AAvBJ,SAAS,mBAAoC;AAe7C,MAAM,QAAQ;AACd,MAAM,OAAO;AAKN,SAAS,UAAU,EAAE,UAAU,OAAO,WAAW,OAAO,WAAW,YAAY,YAAY,GAAmB;AACnH,SACE,iCACG;AAAA,gBAAY,SAAS,SAAS,KAC7B,qBAAC,SAAI,WAAU,4EACb;AAAA,0BAAC,OAAE,WAAW,OAAO,6BAAoB;AAAA,MACzC,oBAAC,QAAG,WAAU,kBACX,mBAAS,IAAI,CAAC,EAAE,MAAM,MAAM,OAAO,KAAK,MACvC,qBAAC,QAAe,WAAU,0BACxB;AAAA,4BAAC,SAAI,WAAW,MACd,8BAAC,QAAK,WAAU,sBAAqB,GACvC;AAAA,QACA,qBAAC,SAAI,WAAU,WACb;AAAA,8BAAC,OAAE,WAAU,yBAAyB,iBAAM;AAAA,UAC5C,oBAAC,OAAE,WAAU,gDAAgD,gBAAK;AAAA,WACpE;AAAA,WAPO,KAQT,CACD,GACH;AAAA,OACF;AAAA,IAGF,qBAAC,SAAI,WAAU,+EACb;AAAA,0BAAC,OAAE,WAAW,OAAO,0BAAY;AAAA,MACjC,oBAAC,QAAG,WAAU,kBACX,gBAAM,IAAI,CAAC,OAAO,MACjB,qBAAC,QAAe,WAAU,2BACxB;AAAA,4BAAC,UAAK,WAAW,GAAG,IAAI,sBAAuB,cAAI,GAAE;AAAA,QACrD,oBAAC,UAAK,WAAU,yBAAyB,iBAAM;AAAA,WAFxC,KAGT,CACD,GACH;AAAA,OACF;AAAA,IAEA,qBAAC,SAAI,WAAU,mGACb;AAAA,0BAAC,aAAU,WAAU,sCAAqC;AAAA,MAC1D,qBAAC,OAAE,WAAU,yCACX;AAAA,4BAAC,UAAK,WAAU,iBAAiB,qBAAU;AAAA,QAAO;AAAA,QAAE;AAAA,SACtD;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/claim-rail.tsx"],"sourcesContent":["import { ShieldCheck, type LucideIcon } from \"lucide-react\";\n\nexport interface ClaimRailProps {\n /** \"What's included\" benefits. Omit to hide that panel (e.g. when a live\n * preview is the rail's first panel instead). */\n included?: { icon: LucideIcon; title: string; desc: string }[];\n /** \"How it works\" ordered steps. */\n steps: string[];\n /** Trust/assurance note: bold lead + the rest of the sentence. */\n trustLead: string;\n trust: string;\n /** Trust glyph — defaults to a shield. */\n trustIcon?: LucideIcon;\n}\n\nconst MONO = '\"Geist Mono\", ui-monospace, SFMono-Regular, monospace';\n\n/** Right-rail for launchpad/claim pages — one quiet sectioned card\n * (What's included · How it works · trust). The brand spectrum appears only\n * as tints: blue benefit chips → purple step numerals → orange trust glyph.\n * Pure presentation; the consuming app passes the per-surface content. */\nexport function ClaimRail({ included, steps, trustLead, trust, trustIcon: TrustIcon = ShieldCheck }: ClaimRailProps) {\n return (\n <div className=\"rounded-2xl border border-border/60 bg-card divide-y divide-border/60 overflow-hidden\">\n {included && included.length > 0 && (\n <section className=\"p-5\">\n <p className=\"section-label\">What&apos;s included</p>\n <ul className=\"mt-4 space-y-4\">\n {included.map(({ icon: Icon, title, desc }) => (\n <li key={title} className=\"flex items-start gap-3\">\n <div className=\"h-8 w-8 rounded-lg bg-brand-blue/10 flex items-center justify-center shrink-0\">\n <Icon className=\"h-4 w-4 text-brand-blue\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-foreground\">{title}</p>\n <p className=\"text-sm text-muted-foreground leading-relaxed mt-0.5\">{desc}</p>\n </div>\n </li>\n ))}\n </ul>\n </section>\n )}\n\n <section className=\"p-5\">\n <p className=\"section-label\">How it works</p>\n <ol className=\"mt-4 space-y-3\">\n {steps.map((label, i) => (\n <li key={label} className=\"flex items-center gap-3\">\n <span\n className=\"h-8 w-8 rounded-lg bg-brand-purple/10 text-brand-purple flex items-center justify-center shrink-0 text-[13px] font-bold\"\n style={{ fontFamily: MONO }}\n >\n {i + 1}\n </span>\n <span className=\"text-sm text-foreground/90\">{label}</span>\n </li>\n ))}\n </ol>\n </section>\n\n <section className=\"p-5 bg-muted/40 flex items-start gap-3\">\n <TrustIcon className=\"h-5 w-5 text-brand-orange shrink-0 mt-0.5\" />\n <p className=\"text-sm text-muted-foreground leading-relaxed\">\n <span className=\"font-semibold text-foreground\">{trustLead}</span> {trust}\n </p>\n </section>\n </div>\n );\n}\n"],"mappings":"AA0BU,cAOM,YAPN;AA1BV,SAAS,mBAAoC;AAe7C,MAAM,OAAO;AAMN,SAAS,UAAU,EAAE,UAAU,OAAO,WAAW,OAAO,WAAW,YAAY,YAAY,GAAmB;AACnH,SACE,qBAAC,SAAI,WAAU,yFACZ;AAAA,gBAAY,SAAS,SAAS,KAC7B,qBAAC,aAAQ,WAAU,OACjB;AAAA,0BAAC,OAAE,WAAU,iBAAgB,6BAAoB;AAAA,MACjD,oBAAC,QAAG,WAAU,kBACX,mBAAS,IAAI,CAAC,EAAE,MAAM,MAAM,OAAO,KAAK,MACvC,qBAAC,QAAe,WAAU,0BACxB;AAAA,4BAAC,SAAI,WAAU,iFACb,8BAAC,QAAK,WAAU,2BAA0B,GAC5C;AAAA,QACA,qBAAC,SAAI,WAAU,WACb;AAAA,8BAAC,OAAE,WAAU,yCAAyC,iBAAM;AAAA,UAC5D,oBAAC,OAAE,WAAU,wDAAwD,gBAAK;AAAA,WAC5E;AAAA,WAPO,KAQT,CACD,GACH;AAAA,OACF;AAAA,IAGF,qBAAC,aAAQ,WAAU,OACjB;AAAA,0BAAC,OAAE,WAAU,iBAAgB,0BAAY;AAAA,MACzC,oBAAC,QAAG,WAAU,kBACX,gBAAM,IAAI,CAAC,OAAO,MACjB,qBAAC,QAAe,WAAU,2BACxB;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,YAAY,KAAK;AAAA,YAEzB,cAAI;AAAA;AAAA,QACP;AAAA,QACA,oBAAC,UAAK,WAAU,8BAA8B,iBAAM;AAAA,WAP7C,KAQT,CACD,GACH;AAAA,OACF;AAAA,IAEA,qBAAC,aAAQ,WAAU,0CACjB;AAAA,0BAAC,aAAU,WAAU,6CAA4C;AAAA,MACjE,qBAAC,OAAE,WAAU,iDACX;AAAA,4BAAC,UAAK,WAAU,iCAAiC,qBAAU;AAAA,QAAO;AAAA,QAAE;AAAA,SACtE;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
@@ -52,7 +52,7 @@ function parseFloorPrice(floor) {
52
52
  const amount = parts.slice(0, -1).join(" ");
53
53
  return { amount, symbol };
54
54
  }
55
- function CollectionCard({ collection, settingsHref, className }) {
55
+ function CollectionCard({ collection, href, settingsHref, className }) {
56
56
  const [imgError, setImgError] = (0, import_react.useState)(false);
57
57
  const imageUrl = collection.image ? (0, import_ipfs.ipfsToHttp)(collection.image) : null;
58
58
  const showImage = imageUrl && !imgError;
@@ -70,7 +70,7 @@ function CollectionCard({ collection, settingsHref, className }) {
70
70
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Settings2, { className: "h-3.5 w-3.5" })
71
71
  }
72
72
  ),
73
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: `/collections/${collection.contractAddress}`, className: "block relative h-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative aspect-[3/4] w-full overflow-hidden bg-muted", children: [
73
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: href ?? `/collections/${collection.contractAddress}`, className: "block relative h-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative aspect-[3/4] w-full overflow-hidden bg-muted", children: [
74
74
  showImage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
75
75
  import_image.default,
76
76
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { Loader2, Settings2 } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { MotionCard } from \"./motion-primitives.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\n/** \"0.990000 USDC\" → { amount: \"0.99\", symbol: \"USDC\" } */\nfunction parseFloorPrice(floor: string | null | undefined): { amount: string; symbol: string } | null {\n if (!floor) return null;\n const formatted = formatDisplayPrice(floor);\n const parts = formatted.trim().split(/\\s+/);\n if (parts.length < 2) return null;\n const symbol = parts[parts.length - 1];\n const amount = parts.slice(0, -1).join(\" \");\n return { amount, symbol };\n}\n\n/** ui's pinned SDK lags the apps — extend structurally for newer fields. */\ntype CollectionWithProfile = ApiCollection & {\n profile?: { hasGatedContent?: boolean } | null;\n};\n\nexport interface CollectionCardProps {\n collection: ApiCollection;\n /** Shows settings gear icon linking to this path — used in portfolio pages */\n settingsHref?: string;\n className?: string;\n}\n\nexport function CollectionCard({ collection, settingsHref, className }: CollectionCardProps) {\n const [imgError, setImgError] = useState(false);\n const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;\n const showImage = imageUrl && !imgError;\n const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();\n const floor = parseFloorPrice(collection.floorPrice);\n const hasExclusiveContent = !!(collection as CollectionWithProfile).profile?.hasGatedContent;\n\n return (\n <div className={cn(hasExclusiveContent && \"card-exclusive-wrapper btn-border-animated\")}>\n <MotionCard className={cn(\"card-base group relative\", className)}>\n {settingsHref && (\n <Link\n href={settingsHref}\n onClick={(e) => e.stopPropagation()}\n className=\"absolute top-2 right-2 z-10 h-7 w-7 rounded-full bg-black/40 backdrop-blur-sm flex items-center justify-center text-white/70 hover:text-white hover:bg-black/60 transition-colors\"\n aria-label=\"Collection settings\"\n >\n <Settings2 className=\"h-3.5 w-3.5\" />\n </Link>\n )}\n\n <Link href={`/collections/${collection.contractAddress}`} className=\"block relative h-full\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n {showImage ? (\n <Image\n src={imageUrl}\n alt={collection.name ?? \"Collection\"}\n fill\n className=\"object-cover transition-transform duration-500 group-hover:scale-105\"\n onError={() => setImgError(true)}\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/40 flex items-center justify-center\">\n <span className=\"text-8xl font-black text-white/10 select-none tracking-tighter\">\n {initial}\n </span>\n </div>\n )}\n\n <div className=\"absolute bottom-0 left-0 right-0 px-3 pb-3 flex flex-col gap-1.5 items-start\">\n {!collection.name && collection.metadataStatus === \"PENDING\" ? (\n <span className=\"flex items-center gap-1 text-[10px] text-white/60 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n <Loader2 className=\"h-2.5 w-2.5 animate-spin\" />\n Indexing…\n </span>\n ) : (\n <p\n className=\"font-bold text-sm text-white leading-tight backdrop-blur-md bg-black/30 rounded-lg px-2.5 py-1 max-w-full truncate\"\n style={{ textShadow: \"0 1px 6px rgba(0,0,0,0.5)\" }}\n >\n {collection.name ?? \"Unnamed Collection\"}\n </p>\n )}\n\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n {collection.totalSupply != null && (\n <span className=\"text-[10px] font-medium text-white/80 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n {collection.totalSupply.toLocaleString()} items\n </span>\n )}\n {floor && (\n <span className=\"inline-flex items-center gap-1 text-[10px] font-bold text-white/90 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n Floor\n <CurrencyIcon symbol={floor.symbol} size={10} />\n {floor.amount}\n </span>\n )}\n {hasExclusiveContent && (\n <span className=\"inline-flex items-center gap-1 text-[10px] font-bold text-white backdrop-blur-md bg-black/50 rounded-full px-2 py-0.5\">\n ✦ Exclusive\n </span>\n )}\n </div>\n </div>\n </div>\n </Link>\n </MotionCard>\n </div>\n );\n}\n\nexport function CollectionCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n <div className=\"absolute inset-0 animate-pulse bg-muted\" />\n <div className=\"absolute bottom-3 left-3 right-3 space-y-1.5\">\n <div className=\"h-4 w-2/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n <div className=\"h-3 w-1/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["Link","Image"]}
1
+ {"version":3,"sources":["../../src/components/collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { Loader2, Settings2 } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { MotionCard } from \"./motion-primitives.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\n/** \"0.990000 USDC\" → { amount: \"0.99\", symbol: \"USDC\" } */\nfunction parseFloorPrice(floor: string | null | undefined): { amount: string; symbol: string } | null {\n if (!floor) return null;\n const formatted = formatDisplayPrice(floor);\n const parts = formatted.trim().split(/\\s+/);\n if (parts.length < 2) return null;\n const symbol = parts[parts.length - 1];\n const amount = parts.slice(0, -1).join(\" \");\n return { amount, symbol };\n}\n\n/** ui's pinned SDK lags the apps — extend structurally for newer fields. */\ntype CollectionWithProfile = ApiCollection & {\n profile?: { hasGatedContent?: boolean } | null;\n};\n\nexport interface CollectionCardProps {\n collection: ApiCollection;\n /** Override the card link destination. Defaults to /collections/:contractAddress. */\n href?: string;\n /** Shows settings gear icon linking to this path — used in portfolio pages */\n settingsHref?: string;\n className?: string;\n}\n\nexport function CollectionCard({ collection, href, settingsHref, className }: CollectionCardProps) {\n const [imgError, setImgError] = useState(false);\n const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;\n const showImage = imageUrl && !imgError;\n const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();\n const floor = parseFloorPrice(collection.floorPrice);\n const hasExclusiveContent = !!(collection as CollectionWithProfile).profile?.hasGatedContent;\n\n return (\n <div className={cn(hasExclusiveContent && \"card-exclusive-wrapper btn-border-animated\")}>\n <MotionCard className={cn(\"card-base group relative\", className)}>\n {settingsHref && (\n <Link\n href={settingsHref}\n onClick={(e) => e.stopPropagation()}\n className=\"absolute top-2 right-2 z-10 h-7 w-7 rounded-full bg-black/40 backdrop-blur-sm flex items-center justify-center text-white/70 hover:text-white hover:bg-black/60 transition-colors\"\n aria-label=\"Collection settings\"\n >\n <Settings2 className=\"h-3.5 w-3.5\" />\n </Link>\n )}\n\n <Link href={href ?? `/collections/${collection.contractAddress}`} className=\"block relative h-full\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n {showImage ? (\n <Image\n src={imageUrl}\n alt={collection.name ?? \"Collection\"}\n fill\n className=\"object-cover transition-transform duration-500 group-hover:scale-105\"\n onError={() => setImgError(true)}\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/40 flex items-center justify-center\">\n <span className=\"text-8xl font-black text-white/10 select-none tracking-tighter\">\n {initial}\n </span>\n </div>\n )}\n\n <div className=\"absolute bottom-0 left-0 right-0 px-3 pb-3 flex flex-col gap-1.5 items-start\">\n {!collection.name && collection.metadataStatus === \"PENDING\" ? (\n <span className=\"flex items-center gap-1 text-[10px] text-white/60 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n <Loader2 className=\"h-2.5 w-2.5 animate-spin\" />\n Indexing…\n </span>\n ) : (\n <p\n className=\"font-bold text-sm text-white leading-tight backdrop-blur-md bg-black/30 rounded-lg px-2.5 py-1 max-w-full truncate\"\n style={{ textShadow: \"0 1px 6px rgba(0,0,0,0.5)\" }}\n >\n {collection.name ?? \"Unnamed Collection\"}\n </p>\n )}\n\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n {collection.totalSupply != null && (\n <span className=\"text-[10px] font-medium text-white/80 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n {collection.totalSupply.toLocaleString()} items\n </span>\n )}\n {floor && (\n <span className=\"inline-flex items-center gap-1 text-[10px] font-bold text-white/90 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n Floor\n <CurrencyIcon symbol={floor.symbol} size={10} />\n {floor.amount}\n </span>\n )}\n {hasExclusiveContent && (\n <span className=\"inline-flex items-center gap-1 text-[10px] font-bold text-white backdrop-blur-md bg-black/50 rounded-full px-2 py-0.5\">\n ✦ Exclusive\n </span>\n )}\n </div>\n </div>\n </div>\n </Link>\n </MotionCard>\n </div>\n );\n}\n\nexport function CollectionCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n <div className=\"absolute inset-0 animate-pulse bg-muted\" />\n <div className=\"absolute bottom-3 left-3 right-3 space-y-1.5\">\n <div className=\"h-4 w-2/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n <div className=\"h-3 w-1/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwDY;AAtDZ,mBAAyB;AACzB,kBAAiB;AACjB,mBAAkB;AAClB,0BAAmC;AACnC,gBAAmB;AACnB,kBAA2B;AAC3B,oBAAmC;AACnC,+BAA2B;AAC3B,2BAA6B;AAI7B,SAAS,gBAAgB,OAA6E;AACpG,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,gBAAY,kCAAmB,KAAK;AAC1C,QAAM,QAAQ,UAAU,KAAK,EAAE,MAAM,KAAK;AAC1C,MAAI,MAAM,SAAS,EAAG,QAAO;AAC7B,QAAM,SAAS,MAAM,MAAM,SAAS,CAAC;AACrC,QAAM,SAAS,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG;AAC1C,SAAO,EAAE,QAAQ,OAAO;AAC1B;AAgBO,SAAS,eAAe,EAAE,YAAY,MAAM,cAAc,UAAU,GAAwB;AACjG,QAAM,CAAC,UAAU,WAAW,QAAI,uBAAS,KAAK;AAC9C,QAAM,WAAW,WAAW,YAAQ,wBAAW,WAAW,KAAK,IAAI;AACnE,QAAM,YAAY,YAAY,CAAC;AAC/B,QAAM,WAAW,WAAW,QAAQ,WAAW,iBAAiB,OAAO,CAAC,EAAE,YAAY;AACtF,QAAM,QAAQ,gBAAgB,WAAW,UAAU;AACnD,QAAM,sBAAsB,CAAC,CAAE,WAAqC,SAAS;AAE7E,SACE,4CAAC,SAAI,eAAW,cAAG,uBAAuB,4CAA4C,GACpF,uDAAC,uCAAW,eAAW,cAAG,4BAA4B,SAAS,GAC5D;AAAA,oBACC;AAAA,MAAC,YAAAA;AAAA,MAAA;AAAA,QACC,MAAM;AAAA,QACN,SAAS,CAAC,MAAM,EAAE,gBAAgB;AAAA,QAClC,WAAU;AAAA,QACV,cAAW;AAAA,QAEX,sDAAC,iCAAU,WAAU,eAAc;AAAA;AAAA,IACrC;AAAA,IAGF,4CAAC,YAAAA,SAAA,EAAK,MAAM,QAAQ,gBAAgB,WAAW,eAAe,IAAI,WAAU,yBAC1E,uDAAC,SAAI,WAAU,yDACZ;AAAA,kBACC;AAAA,QAAC,aAAAC;AAAA,QAAA;AAAA,UACC,KAAK;AAAA,UACL,KAAK,WAAW,QAAQ;AAAA,UACxB,MAAI;AAAA,UACJ,WAAU;AAAA,UACV,SAAS,MAAM,YAAY,IAAI;AAAA,UAC/B,aAAW;AAAA;AAAA,MACb,IAEA,4CAAC,SAAI,WAAU,+HACb,sDAAC,UAAK,WAAU,kEACb,mBACH,GACF;AAAA,MAGF,6CAAC,SAAI,WAAU,gFACZ;AAAA,SAAC,WAAW,QAAQ,WAAW,mBAAmB,YACjD,6CAAC,UAAK,WAAU,2GACd;AAAA,sDAAC,+BAAQ,WAAU,4BAA2B;AAAA,UAAE;AAAA,WAElD,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,YAAY,4BAA4B;AAAA,YAEhD,qBAAW,QAAQ;AAAA;AAAA,QACtB;AAAA,QAGF,6CAAC,SAAI,WAAU,uCACZ;AAAA,qBAAW,eAAe,QACzB,6CAAC,UAAK,WAAU,+FACb;AAAA,uBAAW,YAAY,eAAe;AAAA,YAAE;AAAA,aAC3C;AAAA,UAED,SACC,6CAAC,UAAK,WAAU,4HAA2H;AAAA;AAAA,YAEzI,4CAAC,qCAAa,QAAQ,MAAM,QAAQ,MAAM,IAAI;AAAA,YAC7C,MAAM;AAAA,aACT;AAAA,UAED,uBACC,4CAAC,UAAK,WAAU,yHAAwH,8BAExI;AAAA,WAEJ;AAAA,SACF;AAAA,OACF,GACF;AAAA,KACF,GACF;AAEJ;AAEO,SAAS,yBAAyB;AACvC,SACE,4CAAC,SAAI,WAAU,6BACb,uDAAC,SAAI,WAAU,yDACb;AAAA,gDAAC,SAAI,WAAU,2CAA0C;AAAA,IACzD,6CAAC,SAAI,WAAU,gDACb;AAAA,kDAAC,SAAI,WAAU,6DAA4D;AAAA,MAC3E,4CAAC,SAAI,WAAU,6DAA4D;AAAA,OAC7E;AAAA,KACF,GACF;AAEJ;","names":["Link","Image"]}
@@ -3,11 +3,13 @@ import { ApiCollection } from '@medialane/sdk';
3
3
 
4
4
  interface CollectionCardProps {
5
5
  collection: ApiCollection;
6
+ /** Override the card link destination. Defaults to /collections/:contractAddress. */
7
+ href?: string;
6
8
  /** Shows settings gear icon linking to this path — used in portfolio pages */
7
9
  settingsHref?: string;
8
10
  className?: string;
9
11
  }
10
- declare function CollectionCard({ collection, settingsHref, className }: CollectionCardProps): react_jsx_runtime.JSX.Element;
12
+ declare function CollectionCard({ collection, href, settingsHref, className }: CollectionCardProps): react_jsx_runtime.JSX.Element;
11
13
  declare function CollectionCardSkeleton(): react_jsx_runtime.JSX.Element;
12
14
 
13
15
  export { CollectionCard, type CollectionCardProps, CollectionCardSkeleton };
@@ -3,11 +3,13 @@ import { ApiCollection } from '@medialane/sdk';
3
3
 
4
4
  interface CollectionCardProps {
5
5
  collection: ApiCollection;
6
+ /** Override the card link destination. Defaults to /collections/:contractAddress. */
7
+ href?: string;
6
8
  /** Shows settings gear icon linking to this path — used in portfolio pages */
7
9
  settingsHref?: string;
8
10
  className?: string;
9
11
  }
10
- declare function CollectionCard({ collection, settingsHref, className }: CollectionCardProps): react_jsx_runtime.JSX.Element;
12
+ declare function CollectionCard({ collection, href, settingsHref, className }: CollectionCardProps): react_jsx_runtime.JSX.Element;
11
13
  declare function CollectionCardSkeleton(): react_jsx_runtime.JSX.Element;
12
14
 
13
15
  export { CollectionCard, type CollectionCardProps, CollectionCardSkeleton };
@@ -18,7 +18,7 @@ function parseFloorPrice(floor) {
18
18
  const amount = parts.slice(0, -1).join(" ");
19
19
  return { amount, symbol };
20
20
  }
21
- function CollectionCard({ collection, settingsHref, className }) {
21
+ function CollectionCard({ collection, href, settingsHref, className }) {
22
22
  const [imgError, setImgError] = useState(false);
23
23
  const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;
24
24
  const showImage = imageUrl && !imgError;
@@ -36,7 +36,7 @@ function CollectionCard({ collection, settingsHref, className }) {
36
36
  children: /* @__PURE__ */ jsx(Settings2, { className: "h-3.5 w-3.5" })
37
37
  }
38
38
  ),
39
- /* @__PURE__ */ jsx(Link, { href: `/collections/${collection.contractAddress}`, className: "block relative h-full", children: /* @__PURE__ */ jsxs("div", { className: "relative aspect-[3/4] w-full overflow-hidden bg-muted", children: [
39
+ /* @__PURE__ */ jsx(Link, { href: href ?? `/collections/${collection.contractAddress}`, className: "block relative h-full", children: /* @__PURE__ */ jsxs("div", { className: "relative aspect-[3/4] w-full overflow-hidden bg-muted", children: [
40
40
  showImage ? /* @__PURE__ */ jsx(
41
41
  Image,
42
42
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { Loader2, Settings2 } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { MotionCard } from \"./motion-primitives.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\n/** \"0.990000 USDC\" → { amount: \"0.99\", symbol: \"USDC\" } */\nfunction parseFloorPrice(floor: string | null | undefined): { amount: string; symbol: string } | null {\n if (!floor) return null;\n const formatted = formatDisplayPrice(floor);\n const parts = formatted.trim().split(/\\s+/);\n if (parts.length < 2) return null;\n const symbol = parts[parts.length - 1];\n const amount = parts.slice(0, -1).join(\" \");\n return { amount, symbol };\n}\n\n/** ui's pinned SDK lags the apps — extend structurally for newer fields. */\ntype CollectionWithProfile = ApiCollection & {\n profile?: { hasGatedContent?: boolean } | null;\n};\n\nexport interface CollectionCardProps {\n collection: ApiCollection;\n /** Shows settings gear icon linking to this path — used in portfolio pages */\n settingsHref?: string;\n className?: string;\n}\n\nexport function CollectionCard({ collection, settingsHref, className }: CollectionCardProps) {\n const [imgError, setImgError] = useState(false);\n const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;\n const showImage = imageUrl && !imgError;\n const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();\n const floor = parseFloorPrice(collection.floorPrice);\n const hasExclusiveContent = !!(collection as CollectionWithProfile).profile?.hasGatedContent;\n\n return (\n <div className={cn(hasExclusiveContent && \"card-exclusive-wrapper btn-border-animated\")}>\n <MotionCard className={cn(\"card-base group relative\", className)}>\n {settingsHref && (\n <Link\n href={settingsHref}\n onClick={(e) => e.stopPropagation()}\n className=\"absolute top-2 right-2 z-10 h-7 w-7 rounded-full bg-black/40 backdrop-blur-sm flex items-center justify-center text-white/70 hover:text-white hover:bg-black/60 transition-colors\"\n aria-label=\"Collection settings\"\n >\n <Settings2 className=\"h-3.5 w-3.5\" />\n </Link>\n )}\n\n <Link href={`/collections/${collection.contractAddress}`} className=\"block relative h-full\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n {showImage ? (\n <Image\n src={imageUrl}\n alt={collection.name ?? \"Collection\"}\n fill\n className=\"object-cover transition-transform duration-500 group-hover:scale-105\"\n onError={() => setImgError(true)}\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/40 flex items-center justify-center\">\n <span className=\"text-8xl font-black text-white/10 select-none tracking-tighter\">\n {initial}\n </span>\n </div>\n )}\n\n <div className=\"absolute bottom-0 left-0 right-0 px-3 pb-3 flex flex-col gap-1.5 items-start\">\n {!collection.name && collection.metadataStatus === \"PENDING\" ? (\n <span className=\"flex items-center gap-1 text-[10px] text-white/60 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n <Loader2 className=\"h-2.5 w-2.5 animate-spin\" />\n Indexing…\n </span>\n ) : (\n <p\n className=\"font-bold text-sm text-white leading-tight backdrop-blur-md bg-black/30 rounded-lg px-2.5 py-1 max-w-full truncate\"\n style={{ textShadow: \"0 1px 6px rgba(0,0,0,0.5)\" }}\n >\n {collection.name ?? \"Unnamed Collection\"}\n </p>\n )}\n\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n {collection.totalSupply != null && (\n <span className=\"text-[10px] font-medium text-white/80 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n {collection.totalSupply.toLocaleString()} items\n </span>\n )}\n {floor && (\n <span className=\"inline-flex items-center gap-1 text-[10px] font-bold text-white/90 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n Floor\n <CurrencyIcon symbol={floor.symbol} size={10} />\n {floor.amount}\n </span>\n )}\n {hasExclusiveContent && (\n <span className=\"inline-flex items-center gap-1 text-[10px] font-bold text-white backdrop-blur-md bg-black/50 rounded-full px-2 py-0.5\">\n ✦ Exclusive\n </span>\n )}\n </div>\n </div>\n </div>\n </Link>\n </MotionCard>\n </div>\n );\n}\n\nexport function CollectionCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n <div className=\"absolute inset-0 animate-pulse bg-muted\" />\n <div className=\"absolute bottom-3 left-3 right-3 space-y-1.5\">\n <div className=\"h-4 w-2/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n <div className=\"h-3 w-1/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { Loader2, Settings2 } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { MotionCard } from \"./motion-primitives.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\n/** \"0.990000 USDC\" → { amount: \"0.99\", symbol: \"USDC\" } */\nfunction parseFloorPrice(floor: string | null | undefined): { amount: string; symbol: string } | null {\n if (!floor) return null;\n const formatted = formatDisplayPrice(floor);\n const parts = formatted.trim().split(/\\s+/);\n if (parts.length < 2) return null;\n const symbol = parts[parts.length - 1];\n const amount = parts.slice(0, -1).join(\" \");\n return { amount, symbol };\n}\n\n/** ui's pinned SDK lags the apps — extend structurally for newer fields. */\ntype CollectionWithProfile = ApiCollection & {\n profile?: { hasGatedContent?: boolean } | null;\n};\n\nexport interface CollectionCardProps {\n collection: ApiCollection;\n /** Override the card link destination. Defaults to /collections/:contractAddress. */\n href?: string;\n /** Shows settings gear icon linking to this path — used in portfolio pages */\n settingsHref?: string;\n className?: string;\n}\n\nexport function CollectionCard({ collection, href, settingsHref, className }: CollectionCardProps) {\n const [imgError, setImgError] = useState(false);\n const imageUrl = collection.image ? ipfsToHttp(collection.image) : null;\n const showImage = imageUrl && !imgError;\n const initial = (collection.name ?? collection.contractAddress).charAt(0).toUpperCase();\n const floor = parseFloorPrice(collection.floorPrice);\n const hasExclusiveContent = !!(collection as CollectionWithProfile).profile?.hasGatedContent;\n\n return (\n <div className={cn(hasExclusiveContent && \"card-exclusive-wrapper btn-border-animated\")}>\n <MotionCard className={cn(\"card-base group relative\", className)}>\n {settingsHref && (\n <Link\n href={settingsHref}\n onClick={(e) => e.stopPropagation()}\n className=\"absolute top-2 right-2 z-10 h-7 w-7 rounded-full bg-black/40 backdrop-blur-sm flex items-center justify-center text-white/70 hover:text-white hover:bg-black/60 transition-colors\"\n aria-label=\"Collection settings\"\n >\n <Settings2 className=\"h-3.5 w-3.5\" />\n </Link>\n )}\n\n <Link href={href ?? `/collections/${collection.contractAddress}`} className=\"block relative h-full\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n {showImage ? (\n <Image\n src={imageUrl}\n alt={collection.name ?? \"Collection\"}\n fill\n className=\"object-cover transition-transform duration-500 group-hover:scale-105\"\n onError={() => setImgError(true)}\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/30 via-brand-blue/20 to-brand-navy/40 flex items-center justify-center\">\n <span className=\"text-8xl font-black text-white/10 select-none tracking-tighter\">\n {initial}\n </span>\n </div>\n )}\n\n <div className=\"absolute bottom-0 left-0 right-0 px-3 pb-3 flex flex-col gap-1.5 items-start\">\n {!collection.name && collection.metadataStatus === \"PENDING\" ? (\n <span className=\"flex items-center gap-1 text-[10px] text-white/60 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n <Loader2 className=\"h-2.5 w-2.5 animate-spin\" />\n Indexing…\n </span>\n ) : (\n <p\n className=\"font-bold text-sm text-white leading-tight backdrop-blur-md bg-black/30 rounded-lg px-2.5 py-1 max-w-full truncate\"\n style={{ textShadow: \"0 1px 6px rgba(0,0,0,0.5)\" }}\n >\n {collection.name ?? \"Unnamed Collection\"}\n </p>\n )}\n\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n {collection.totalSupply != null && (\n <span className=\"text-[10px] font-medium text-white/80 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n {collection.totalSupply.toLocaleString()} items\n </span>\n )}\n {floor && (\n <span className=\"inline-flex items-center gap-1 text-[10px] font-bold text-white/90 backdrop-blur-md bg-black/30 rounded-full px-2 py-0.5\">\n Floor\n <CurrencyIcon symbol={floor.symbol} size={10} />\n {floor.amount}\n </span>\n )}\n {hasExclusiveContent && (\n <span className=\"inline-flex items-center gap-1 text-[10px] font-bold text-white backdrop-blur-md bg-black/50 rounded-full px-2 py-0.5\">\n ✦ Exclusive\n </span>\n )}\n </div>\n </div>\n </div>\n </Link>\n </MotionCard>\n </div>\n );\n}\n\nexport function CollectionCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"relative aspect-[3/4] w-full overflow-hidden bg-muted\">\n <div className=\"absolute inset-0 animate-pulse bg-muted\" />\n <div className=\"absolute bottom-3 left-3 right-3 space-y-1.5\">\n <div className=\"h-4 w-2/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n <div className=\"h-3 w-1/3 rounded-md bg-muted-foreground/20 animate-pulse\" />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";AAwDY,cAyBI,YAzBJ;AAtDZ,SAAS,gBAAgB;AACzB,OAAO,UAAU;AACjB,OAAO,WAAW;AAClB,SAAS,SAAS,iBAAiB;AACnC,SAAS,UAAU;AACnB,SAAS,kBAAkB;AAC3B,SAAS,0BAA0B;AACnC,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAI7B,SAAS,gBAAgB,OAA6E;AACpG,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,YAAY,mBAAmB,KAAK;AAC1C,QAAM,QAAQ,UAAU,KAAK,EAAE,MAAM,KAAK;AAC1C,MAAI,MAAM,SAAS,EAAG,QAAO;AAC7B,QAAM,SAAS,MAAM,MAAM,SAAS,CAAC;AACrC,QAAM,SAAS,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG;AAC1C,SAAO,EAAE,QAAQ,OAAO;AAC1B;AAgBO,SAAS,eAAe,EAAE,YAAY,MAAM,cAAc,UAAU,GAAwB;AACjG,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,WAAW,WAAW,QAAQ,WAAW,WAAW,KAAK,IAAI;AACnE,QAAM,YAAY,YAAY,CAAC;AAC/B,QAAM,WAAW,WAAW,QAAQ,WAAW,iBAAiB,OAAO,CAAC,EAAE,YAAY;AACtF,QAAM,QAAQ,gBAAgB,WAAW,UAAU;AACnD,QAAM,sBAAsB,CAAC,CAAE,WAAqC,SAAS;AAE7E,SACE,oBAAC,SAAI,WAAW,GAAG,uBAAuB,4CAA4C,GACpF,+BAAC,cAAW,WAAW,GAAG,4BAA4B,SAAS,GAC5D;AAAA,oBACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,SAAS,CAAC,MAAM,EAAE,gBAAgB;AAAA,QAClC,WAAU;AAAA,QACV,cAAW;AAAA,QAEX,8BAAC,aAAU,WAAU,eAAc;AAAA;AAAA,IACrC;AAAA,IAGF,oBAAC,QAAK,MAAM,QAAQ,gBAAgB,WAAW,eAAe,IAAI,WAAU,yBAC1E,+BAAC,SAAI,WAAU,yDACZ;AAAA,kBACC;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,KAAK,WAAW,QAAQ;AAAA,UACxB,MAAI;AAAA,UACJ,WAAU;AAAA,UACV,SAAS,MAAM,YAAY,IAAI;AAAA,UAC/B,aAAW;AAAA;AAAA,MACb,IAEA,oBAAC,SAAI,WAAU,+HACb,8BAAC,UAAK,WAAU,kEACb,mBACH,GACF;AAAA,MAGF,qBAAC,SAAI,WAAU,gFACZ;AAAA,SAAC,WAAW,QAAQ,WAAW,mBAAmB,YACjD,qBAAC,UAAK,WAAU,2GACd;AAAA,8BAAC,WAAQ,WAAU,4BAA2B;AAAA,UAAE;AAAA,WAElD,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,YAAY,4BAA4B;AAAA,YAEhD,qBAAW,QAAQ;AAAA;AAAA,QACtB;AAAA,QAGF,qBAAC,SAAI,WAAU,uCACZ;AAAA,qBAAW,eAAe,QACzB,qBAAC,UAAK,WAAU,+FACb;AAAA,uBAAW,YAAY,eAAe;AAAA,YAAE;AAAA,aAC3C;AAAA,UAED,SACC,qBAAC,UAAK,WAAU,4HAA2H;AAAA;AAAA,YAEzI,oBAAC,gBAAa,QAAQ,MAAM,QAAQ,MAAM,IAAI;AAAA,YAC7C,MAAM;AAAA,aACT;AAAA,UAED,uBACC,oBAAC,UAAK,WAAU,yHAAwH,8BAExI;AAAA,WAEJ;AAAA,SACF;AAAA,OACF,GACF;AAAA,KACF,GACF;AAEJ;AAEO,SAAS,yBAAyB;AACvC,SACE,oBAAC,SAAI,WAAU,6BACb,+BAAC,SAAI,WAAU,yDACb;AAAA,wBAAC,SAAI,WAAU,2CAA0C;AAAA,IACzD,qBAAC,SAAI,WAAU,gDACb;AAAA,0BAAC,SAAI,WAAU,6DAA4D;AAAA,MAC3E,oBAAC,SAAI,WAAU,6DAA4D;AAAA,OAC7E;AAAA,KACF,GACF;AAEJ;","names":[]}
@@ -25,8 +25,8 @@ var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_cn = require("../utils/cn.js");
26
26
  var import_service_header = require("./service-header.js");
27
27
  function ServiceFormShell({ icon, title, subtitle, headerAccessory, backSlot, aside, aboveForm, children }) {
28
- const header = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_service_header.ServiceHeader, { plain: true, icon, title, subtitle, headerAccessory });
29
- const form = aside ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "btn-border-animated p-[1.5px] rounded-2xl", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rounded-[15px] bg-card p-5 sm:p-6", children }) }) : children;
28
+ const header = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_service_header.ServiceHeader, { bare: true, icon, title, subtitle, headerAccessory });
29
+ const form = aside ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rounded-2xl border border-border/60 bg-card p-5 sm:p-6", children }) : children;
30
30
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: (0, import_cn.cn)("container mx-auto px-4 sm:px-6 py-10 space-y-6 pb-20", aside ? "max-w-5xl" : "max-w-3xl"), children: [
31
31
  backSlot,
32
32
  aside ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid gap-4 lg:grid-cols-12 lg:items-start", children: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/service-form-shell.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ServiceHeader } from \"./service-header.js\";\n\nexport interface ServiceFormShellProps {\n /** Rendered icon element for the header, e.g. <Coins className=\"h-4 w-4 text-white\" />. */\n icon: ReactNode;\n title: string;\n subtitle: string;\n /** Optional element under the header subtitle (e.g. a URL pill). */\n headerAccessory?: ReactNode;\n /** Rendered above the header — the app's own back button (router-specific). */\n backSlot?: ReactNode;\n /** Right-rail panels (e.g. <ClaimRail/>). When present, lays out an 8/4 bento. */\n aside?: ReactNode;\n /** Rendered in the left column between the header and the form — e.g. a\n * <StepNav/> for multi-step flows. Only used in the aside (8/4) layout. */\n aboveForm?: ReactNode;\n /** The form. **Already gated by the app** — wrap it in your own auth/wallet\n * gate before passing. This component stays presentation-only (no auth,\n * no router) so both apps can share it. */\n children: ReactNode;\n}\n\n/** Shared launchpad/claim form layout: back slot + gradient header, then the\n * form inside the animated full-spectrum border (`.btn-border-animated`, from\n * @medialane/ui/styles). With an `aside` it lays out an 8/4 bento (form left,\n * rail right); without, a single centered column. */\nexport function ServiceFormShell({ icon, title, subtitle, headerAccessory, backSlot, aside, aboveForm, children }: ServiceFormShellProps) {\n // Plain header: the form below already carries the animated gradient border,\n // so the header drops its gradient frame to keep a single focal accent.\n const header = <ServiceHeader plain icon={icon} title={title} subtitle={subtitle} headerAccessory={headerAccessory} />;\n\n // The form is the focus: animated gradient border around the dark card.\n const form = aside ? (\n <div className=\"btn-border-animated p-[1.5px] rounded-2xl\">\n <div className=\"rounded-[15px] bg-card p-5 sm:p-6\">{children}</div>\n </div>\n ) : (\n children\n );\n\n return (\n <div className={cn(\"container mx-auto px-4 sm:px-6 py-10 space-y-6 pb-20\", aside ? \"max-w-5xl\" : \"max-w-3xl\")}>\n {backSlot}\n {aside ? (\n <div className=\"grid gap-4 lg:grid-cols-12 lg:items-start\">\n <div className=\"space-y-4 lg:col-span-8\">\n {header}\n {aboveForm}\n {form}\n </div>\n <div className=\"space-y-4 lg:col-span-4 lg:sticky lg:top-24\">{aside}</div>\n </div>\n ) : (\n <div className=\"space-y-6\">\n {header}\n {form}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA+BiB;AA9BjB,gBAAmB;AACnB,4BAA8B;AA0BvB,SAAS,iBAAiB,EAAE,MAAM,OAAO,UAAU,iBAAiB,UAAU,OAAO,WAAW,SAAS,GAA0B;AAGxI,QAAM,SAAS,4CAAC,uCAAc,OAAK,MAAC,MAAY,OAAc,UAAoB,iBAAkC;AAGpH,QAAM,OAAO,QACX,4CAAC,SAAI,WAAU,6CACb,sDAAC,SAAI,WAAU,qCAAqC,UAAS,GAC/D,IAEA;AAGF,SACE,6CAAC,SAAI,eAAW,cAAG,wDAAwD,QAAQ,cAAc,WAAW,GACzG;AAAA;AAAA,IACA,QACC,6CAAC,SAAI,WAAU,6CACb;AAAA,mDAAC,SAAI,WAAU,2BACZ;AAAA;AAAA,QACA;AAAA,QACA;AAAA,SACH;AAAA,MACA,4CAAC,SAAI,WAAU,+CAA+C,iBAAM;AAAA,OACtE,IAEA,6CAAC,SAAI,WAAU,aACZ;AAAA;AAAA,MACA;AAAA,OACH;AAAA,KAEJ;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/service-form-shell.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ServiceHeader } from \"./service-header.js\";\n\nexport interface ServiceFormShellProps {\n /** Rendered icon element for the header, e.g. <Coins className=\"h-4 w-4 text-white\" />. */\n icon: ReactNode;\n title: string;\n subtitle: string;\n /** Optional element under the header subtitle (e.g. a URL pill). */\n headerAccessory?: ReactNode;\n /** Rendered above the header — the app's own back button (router-specific). */\n backSlot?: ReactNode;\n /** Right-rail panels (e.g. <ClaimRail/>). When present, lays out an 8/4 bento. */\n aside?: ReactNode;\n /** Rendered in the left column between the header and the form — e.g. a\n * <StepNav/> for multi-step flows. Only used in the aside (8/4) layout. */\n aboveForm?: ReactNode;\n /** The form. **Already gated by the app** — wrap it in your own auth/wallet\n * gate before passing. This component stays presentation-only (no auth,\n * no router) so both apps can share it. */\n children: ReactNode;\n}\n\n/** Shared launchpad/claim form layout: back slot + bare header (no card), then\n * the form in a quiet hairline card. With an `aside` it lays out an 8/4 bento\n * (form left, rail right); without, a single centered column. The brand\n * gradient belongs to the form's action button, not to any container. */\nexport function ServiceFormShell({ icon, title, subtitle, headerAccessory, backSlot, aside, aboveForm, children }: ServiceFormShellProps) {\n // Bare header: the form card is the page's only panel.\n const header = <ServiceHeader bare icon={icon} title={title} subtitle={subtitle} headerAccessory={headerAccessory} />;\n\n const form = aside ? (\n <div className=\"rounded-2xl border border-border/60 bg-card p-5 sm:p-6\">{children}</div>\n ) : (\n children\n );\n\n return (\n <div className={cn(\"container mx-auto px-4 sm:px-6 py-10 space-y-6 pb-20\", aside ? \"max-w-5xl\" : \"max-w-3xl\")}>\n {backSlot}\n {aside ? (\n <div className=\"grid gap-4 lg:grid-cols-12 lg:items-start\">\n <div className=\"space-y-4 lg:col-span-8\">\n {header}\n {aboveForm}\n {form}\n </div>\n <div className=\"space-y-4 lg:col-span-4 lg:sticky lg:top-24\">{aside}</div>\n </div>\n ) : (\n <div className=\"space-y-6\">\n {header}\n {form}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BiB;AA7BjB,gBAAmB;AACnB,4BAA8B;AA0BvB,SAAS,iBAAiB,EAAE,MAAM,OAAO,UAAU,iBAAiB,UAAU,OAAO,WAAW,SAAS,GAA0B;AAExI,QAAM,SAAS,4CAAC,uCAAc,MAAI,MAAC,MAAY,OAAc,UAAoB,iBAAkC;AAEnH,QAAM,OAAO,QACX,4CAAC,SAAI,WAAU,0DAA0D,UAAS,IAElF;AAGF,SACE,6CAAC,SAAI,eAAW,cAAG,wDAAwD,QAAQ,cAAc,WAAW,GACzG;AAAA;AAAA,IACA,QACC,6CAAC,SAAI,WAAU,6CACb;AAAA,mDAAC,SAAI,WAAU,2BACZ;AAAA;AAAA,QACA;AAAA,QACA;AAAA,SACH;AAAA,MACA,4CAAC,SAAI,WAAU,+CAA+C,iBAAM;AAAA,OACtE,IAEA,6CAAC,SAAI,WAAU,aACZ;AAAA;AAAA,MACA;AAAA,OACH;AAAA,KAEJ;AAEJ;","names":[]}
@@ -20,10 +20,10 @@ interface ServiceFormShellProps {
20
20
  * no router) so both apps can share it. */
21
21
  children: ReactNode;
22
22
  }
23
- /** Shared launchpad/claim form layout: back slot + gradient header, then the
24
- * form inside the animated full-spectrum border (`.btn-border-animated`, from
25
- * @medialane/ui/styles). With an `aside` it lays out an 8/4 bento (form left,
26
- * rail right); without, a single centered column. */
23
+ /** Shared launchpad/claim form layout: back slot + bare header (no card), then
24
+ * the form in a quiet hairline card. With an `aside` it lays out an 8/4 bento
25
+ * (form left, rail right); without, a single centered column. The brand
26
+ * gradient belongs to the form's action button, not to any container. */
27
27
  declare function ServiceFormShell({ icon, title, subtitle, headerAccessory, backSlot, aside, aboveForm, children }: ServiceFormShellProps): react_jsx_runtime.JSX.Element;
28
28
 
29
29
  export { ServiceFormShell, type ServiceFormShellProps };
@@ -20,10 +20,10 @@ interface ServiceFormShellProps {
20
20
  * no router) so both apps can share it. */
21
21
  children: ReactNode;
22
22
  }
23
- /** Shared launchpad/claim form layout: back slot + gradient header, then the
24
- * form inside the animated full-spectrum border (`.btn-border-animated`, from
25
- * @medialane/ui/styles). With an `aside` it lays out an 8/4 bento (form left,
26
- * rail right); without, a single centered column. */
23
+ /** Shared launchpad/claim form layout: back slot + bare header (no card), then
24
+ * the form in a quiet hairline card. With an `aside` it lays out an 8/4 bento
25
+ * (form left, rail right); without, a single centered column. The brand
26
+ * gradient belongs to the form's action button, not to any container. */
27
27
  declare function ServiceFormShell({ icon, title, subtitle, headerAccessory, backSlot, aside, aboveForm, children }: ServiceFormShellProps): react_jsx_runtime.JSX.Element;
28
28
 
29
29
  export { ServiceFormShell, type ServiceFormShellProps };
@@ -2,8 +2,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { cn } from "../utils/cn.js";
3
3
  import { ServiceHeader } from "./service-header.js";
4
4
  function ServiceFormShell({ icon, title, subtitle, headerAccessory, backSlot, aside, aboveForm, children }) {
5
- const header = /* @__PURE__ */ jsx(ServiceHeader, { plain: true, icon, title, subtitle, headerAccessory });
6
- const form = aside ? /* @__PURE__ */ jsx("div", { className: "btn-border-animated p-[1.5px] rounded-2xl", children: /* @__PURE__ */ jsx("div", { className: "rounded-[15px] bg-card p-5 sm:p-6", children }) }) : children;
5
+ const header = /* @__PURE__ */ jsx(ServiceHeader, { bare: true, icon, title, subtitle, headerAccessory });
6
+ const form = aside ? /* @__PURE__ */ jsx("div", { className: "rounded-2xl border border-border/60 bg-card p-5 sm:p-6", children }) : children;
7
7
  return /* @__PURE__ */ jsxs("div", { className: cn("container mx-auto px-4 sm:px-6 py-10 space-y-6 pb-20", aside ? "max-w-5xl" : "max-w-3xl"), children: [
8
8
  backSlot,
9
9
  aside ? /* @__PURE__ */ jsxs("div", { className: "grid gap-4 lg:grid-cols-12 lg:items-start", children: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/service-form-shell.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ServiceHeader } from \"./service-header.js\";\n\nexport interface ServiceFormShellProps {\n /** Rendered icon element for the header, e.g. <Coins className=\"h-4 w-4 text-white\" />. */\n icon: ReactNode;\n title: string;\n subtitle: string;\n /** Optional element under the header subtitle (e.g. a URL pill). */\n headerAccessory?: ReactNode;\n /** Rendered above the header — the app's own back button (router-specific). */\n backSlot?: ReactNode;\n /** Right-rail panels (e.g. <ClaimRail/>). When present, lays out an 8/4 bento. */\n aside?: ReactNode;\n /** Rendered in the left column between the header and the form — e.g. a\n * <StepNav/> for multi-step flows. Only used in the aside (8/4) layout. */\n aboveForm?: ReactNode;\n /** The form. **Already gated by the app** — wrap it in your own auth/wallet\n * gate before passing. This component stays presentation-only (no auth,\n * no router) so both apps can share it. */\n children: ReactNode;\n}\n\n/** Shared launchpad/claim form layout: back slot + gradient header, then the\n * form inside the animated full-spectrum border (`.btn-border-animated`, from\n * @medialane/ui/styles). With an `aside` it lays out an 8/4 bento (form left,\n * rail right); without, a single centered column. */\nexport function ServiceFormShell({ icon, title, subtitle, headerAccessory, backSlot, aside, aboveForm, children }: ServiceFormShellProps) {\n // Plain header: the form below already carries the animated gradient border,\n // so the header drops its gradient frame to keep a single focal accent.\n const header = <ServiceHeader plain icon={icon} title={title} subtitle={subtitle} headerAccessory={headerAccessory} />;\n\n // The form is the focus: animated gradient border around the dark card.\n const form = aside ? (\n <div className=\"btn-border-animated p-[1.5px] rounded-2xl\">\n <div className=\"rounded-[15px] bg-card p-5 sm:p-6\">{children}</div>\n </div>\n ) : (\n children\n );\n\n return (\n <div className={cn(\"container mx-auto px-4 sm:px-6 py-10 space-y-6 pb-20\", aside ? \"max-w-5xl\" : \"max-w-3xl\")}>\n {backSlot}\n {aside ? (\n <div className=\"grid gap-4 lg:grid-cols-12 lg:items-start\">\n <div className=\"space-y-4 lg:col-span-8\">\n {header}\n {aboveForm}\n {form}\n </div>\n <div className=\"space-y-4 lg:col-span-4 lg:sticky lg:top-24\">{aside}</div>\n </div>\n ) : (\n <div className=\"space-y-6\">\n {header}\n {form}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"AA+BiB,cAgBP,YAhBO;AA9BjB,SAAS,UAAU;AACnB,SAAS,qBAAqB;AA0BvB,SAAS,iBAAiB,EAAE,MAAM,OAAO,UAAU,iBAAiB,UAAU,OAAO,WAAW,SAAS,GAA0B;AAGxI,QAAM,SAAS,oBAAC,iBAAc,OAAK,MAAC,MAAY,OAAc,UAAoB,iBAAkC;AAGpH,QAAM,OAAO,QACX,oBAAC,SAAI,WAAU,6CACb,8BAAC,SAAI,WAAU,qCAAqC,UAAS,GAC/D,IAEA;AAGF,SACE,qBAAC,SAAI,WAAW,GAAG,wDAAwD,QAAQ,cAAc,WAAW,GACzG;AAAA;AAAA,IACA,QACC,qBAAC,SAAI,WAAU,6CACb;AAAA,2BAAC,SAAI,WAAU,2BACZ;AAAA;AAAA,QACA;AAAA,QACA;AAAA,SACH;AAAA,MACA,oBAAC,SAAI,WAAU,+CAA+C,iBAAM;AAAA,OACtE,IAEA,qBAAC,SAAI,WAAU,aACZ;AAAA;AAAA,MACA;AAAA,OACH;AAAA,KAEJ;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/service-form-shell.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn.js\";\nimport { ServiceHeader } from \"./service-header.js\";\n\nexport interface ServiceFormShellProps {\n /** Rendered icon element for the header, e.g. <Coins className=\"h-4 w-4 text-white\" />. */\n icon: ReactNode;\n title: string;\n subtitle: string;\n /** Optional element under the header subtitle (e.g. a URL pill). */\n headerAccessory?: ReactNode;\n /** Rendered above the header — the app's own back button (router-specific). */\n backSlot?: ReactNode;\n /** Right-rail panels (e.g. <ClaimRail/>). When present, lays out an 8/4 bento. */\n aside?: ReactNode;\n /** Rendered in the left column between the header and the form — e.g. a\n * <StepNav/> for multi-step flows. Only used in the aside (8/4) layout. */\n aboveForm?: ReactNode;\n /** The form. **Already gated by the app** — wrap it in your own auth/wallet\n * gate before passing. This component stays presentation-only (no auth,\n * no router) so both apps can share it. */\n children: ReactNode;\n}\n\n/** Shared launchpad/claim form layout: back slot + bare header (no card), then\n * the form in a quiet hairline card. With an `aside` it lays out an 8/4 bento\n * (form left, rail right); without, a single centered column. The brand\n * gradient belongs to the form's action button, not to any container. */\nexport function ServiceFormShell({ icon, title, subtitle, headerAccessory, backSlot, aside, aboveForm, children }: ServiceFormShellProps) {\n // Bare header: the form card is the page's only panel.\n const header = <ServiceHeader bare icon={icon} title={title} subtitle={subtitle} headerAccessory={headerAccessory} />;\n\n const form = aside ? (\n <div className=\"rounded-2xl border border-border/60 bg-card p-5 sm:p-6\">{children}</div>\n ) : (\n children\n );\n\n return (\n <div className={cn(\"container mx-auto px-4 sm:px-6 py-10 space-y-6 pb-20\", aside ? \"max-w-5xl\" : \"max-w-3xl\")}>\n {backSlot}\n {aside ? (\n <div className=\"grid gap-4 lg:grid-cols-12 lg:items-start\">\n <div className=\"space-y-4 lg:col-span-8\">\n {header}\n {aboveForm}\n {form}\n </div>\n <div className=\"space-y-4 lg:col-span-4 lg:sticky lg:top-24\">{aside}</div>\n </div>\n ) : (\n <div className=\"space-y-6\">\n {header}\n {form}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"AA8BiB,cAaP,YAbO;AA7BjB,SAAS,UAAU;AACnB,SAAS,qBAAqB;AA0BvB,SAAS,iBAAiB,EAAE,MAAM,OAAO,UAAU,iBAAiB,UAAU,OAAO,WAAW,SAAS,GAA0B;AAExI,QAAM,SAAS,oBAAC,iBAAc,MAAI,MAAC,MAAY,OAAc,UAAoB,iBAAkC;AAEnH,QAAM,OAAO,QACX,oBAAC,SAAI,WAAU,0DAA0D,UAAS,IAElF;AAGF,SACE,qBAAC,SAAI,WAAW,GAAG,wDAAwD,QAAQ,cAAc,WAAW,GACzG;AAAA;AAAA,IACA,QACC,qBAAC,SAAI,WAAU,6CACb;AAAA,2BAAC,SAAI,WAAU,2BACZ;AAAA;AAAA,QACA;AAAA,QACA;AAAA,SACH;AAAA,MACA,oBAAC,SAAI,WAAU,+CAA+C,iBAAM;AAAA,OACtE,IAEA,qBAAC,SAAI,WAAU,aACZ;AAAA;AAAA,MACA;AAAA,OACH;AAAA,KAEJ;AAEJ;","names":[]}
@@ -23,15 +23,18 @@ __export(service_header_exports, {
23
23
  module.exports = __toCommonJS(service_header_exports);
24
24
  var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_cn = require("../utils/cn.js");
26
- function ServiceHeader({ icon, title, subtitle, headerAccessory, className, plain = false }) {
26
+ function ServiceHeader({ icon, title, subtitle, headerAccessory, className, plain = false, bare = false }) {
27
27
  const body = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
28
28
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2.5", children: [
29
29
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-9 w-9 rounded-xl bg-primary flex items-center justify-center shrink-0", children: icon }),
30
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "text-2xl sm:text-3xl font-black", children: title })
30
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "text-2xl sm:text-3xl font-black tracking-tight", children: title })
31
31
  ] }),
32
32
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mt-1.5 text-sm text-muted-foreground max-w-xl", children: subtitle }),
33
33
  headerAccessory && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-4", children: headerAccessory })
34
34
  ] });
35
+ if (bare) {
36
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, children: body });
37
+ }
35
38
  if (plain) {
36
39
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_cn.cn)("rounded-2xl border border-border/60 bg-card p-6 sm:p-7", className), children: body });
37
40
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/service-header.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn.js\";\n\nexport interface ServiceHeaderProps {\n /** Rendered icon element, e.g. <Coins className=\"h-4 w-4 text-white\" />. */\n icon: ReactNode;\n title: string;\n subtitle: string;\n /** Optional element shown under the subtitle (e.g. a URL pill). */\n headerAccessory?: ReactNode;\n className?: string;\n /** Drop the brand gradient border for a plain neutral-bordered card. Used by\n * ServiceFormShell (create/mint form pages) where the form already carries\n * the animated gradient border, so the header shouldn't compete. Standalone\n * headers (browse pages, coin page, /claim hub) keep the gradient. */\n plain?: boolean;\n}\n\n/** Shared launchpad/claim page header: a dark card with a solid primary icon\n * chip, title + subtitle. By default it sits on a static brand gradient\n * border; pass `plain` for a neutral-bordered card. Pure presentation —\n * consuming app supplies the icon and (optionally) a header accessory. */\nexport function ServiceHeader({ icon, title, subtitle, headerAccessory, className, plain = false }: ServiceHeaderProps) {\n const body = (\n <>\n <div className=\"flex items-center gap-2.5\">\n <div className=\"h-9 w-9 rounded-xl bg-primary flex items-center justify-center shrink-0\">\n {icon}\n </div>\n <h1 className=\"text-2xl sm:text-3xl font-black\">{title}</h1>\n </div>\n <p className=\"mt-1.5 text-sm text-muted-foreground max-w-xl\">{subtitle}</p>\n {headerAccessory && <div className=\"mt-4\">{headerAccessory}</div>}\n </>\n );\n\n if (plain) {\n return <div className={cn(\"rounded-2xl border border-border/60 bg-card p-6 sm:p-7\", className)}>{body}</div>;\n }\n\n return (\n <div className={cn(\"rounded-2xl p-[1.5px] bg-gradient-to-br from-brand-blue via-brand-purple to-brand-rose\", className)}>\n <div className=\"rounded-[15px] bg-card p-6 sm:p-7\">{body}</div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBI;AAvBJ,gBAAmB;AAqBZ,SAAS,cAAc,EAAE,MAAM,OAAO,UAAU,iBAAiB,WAAW,QAAQ,MAAM,GAAuB;AACtH,QAAM,OACJ,4EACE;AAAA,iDAAC,SAAI,WAAU,6BACb;AAAA,kDAAC,SAAI,WAAU,2EACZ,gBACH;AAAA,MACA,4CAAC,QAAG,WAAU,mCAAmC,iBAAM;AAAA,OACzD;AAAA,IACA,4CAAC,OAAE,WAAU,iDAAiD,oBAAS;AAAA,IACtE,mBAAmB,4CAAC,SAAI,WAAU,QAAQ,2BAAgB;AAAA,KAC7D;AAGF,MAAI,OAAO;AACT,WAAO,4CAAC,SAAI,eAAW,cAAG,0DAA0D,SAAS,GAAI,gBAAK;AAAA,EACxG;AAEA,SACE,4CAAC,SAAI,eAAW,cAAG,0FAA0F,SAAS,GACpH,sDAAC,SAAI,WAAU,qCAAqC,gBAAK,GAC3D;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/service-header.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn.js\";\n\nexport interface ServiceHeaderProps {\n /** Rendered icon element, e.g. <Coins className=\"h-4 w-4 text-white\" />. */\n icon: ReactNode;\n title: string;\n subtitle: string;\n /** Optional element shown under the subtitle (e.g. a URL pill). */\n headerAccessory?: ReactNode;\n className?: string;\n /** Drop the brand gradient border for a plain neutral-bordered card.\n * Standalone headers (browse pages, coin page, /claim hub) keep the\n * gradient by default. */\n plain?: boolean;\n /** No card at all — icon chip + title + subtitle on the page background.\n * Used by ServiceFormShell so the form card is the page's only panel. */\n bare?: boolean;\n}\n\n/** Shared launchpad/claim page header: a dark card with a solid primary icon\n * chip, title + subtitle. By default it sits on a static brand gradient\n * border; pass `plain` for a neutral-bordered card. Pure presentation —\n * consuming app supplies the icon and (optionally) a header accessory. */\nexport function ServiceHeader({ icon, title, subtitle, headerAccessory, className, plain = false, bare = false }: ServiceHeaderProps) {\n const body = (\n <>\n <div className=\"flex items-center gap-2.5\">\n <div className=\"h-9 w-9 rounded-xl bg-primary flex items-center justify-center shrink-0\">\n {icon}\n </div>\n <h1 className=\"text-2xl sm:text-3xl font-black tracking-tight\">{title}</h1>\n </div>\n <p className=\"mt-1.5 text-sm text-muted-foreground max-w-xl\">{subtitle}</p>\n {headerAccessory && <div className=\"mt-4\">{headerAccessory}</div>}\n </>\n );\n\n if (bare) {\n return <div className={className}>{body}</div>;\n }\n\n if (plain) {\n return <div className={cn(\"rounded-2xl border border-border/60 bg-card p-6 sm:p-7\", className)}>{body}</div>;\n }\n\n return (\n <div className={cn(\"rounded-2xl p-[1.5px] bg-gradient-to-br from-brand-blue via-brand-purple to-brand-rose\", className)}>\n <div className=\"rounded-[15px] bg-card p-6 sm:p-7\">{body}</div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BI;AAzBJ,gBAAmB;AAuBZ,SAAS,cAAc,EAAE,MAAM,OAAO,UAAU,iBAAiB,WAAW,QAAQ,OAAO,OAAO,MAAM,GAAuB;AACpI,QAAM,OACJ,4EACE;AAAA,iDAAC,SAAI,WAAU,6BACb;AAAA,kDAAC,SAAI,WAAU,2EACZ,gBACH;AAAA,MACA,4CAAC,QAAG,WAAU,kDAAkD,iBAAM;AAAA,OACxE;AAAA,IACA,4CAAC,OAAE,WAAU,iDAAiD,oBAAS;AAAA,IACtE,mBAAmB,4CAAC,SAAI,WAAU,QAAQ,2BAAgB;AAAA,KAC7D;AAGF,MAAI,MAAM;AACR,WAAO,4CAAC,SAAI,WAAuB,gBAAK;AAAA,EAC1C;AAEA,MAAI,OAAO;AACT,WAAO,4CAAC,SAAI,eAAW,cAAG,0DAA0D,SAAS,GAAI,gBAAK;AAAA,EACxG;AAEA,SACE,4CAAC,SAAI,eAAW,cAAG,0FAA0F,SAAS,GACpH,sDAAC,SAAI,WAAU,qCAAqC,gBAAK,GAC3D;AAEJ;","names":[]}
@@ -9,16 +9,18 @@ interface ServiceHeaderProps {
9
9
  /** Optional element shown under the subtitle (e.g. a URL pill). */
10
10
  headerAccessory?: ReactNode;
11
11
  className?: string;
12
- /** Drop the brand gradient border for a plain neutral-bordered card. Used by
13
- * ServiceFormShell (create/mint form pages) where the form already carries
14
- * the animated gradient border, so the header shouldn't compete. Standalone
15
- * headers (browse pages, coin page, /claim hub) keep the gradient. */
12
+ /** Drop the brand gradient border for a plain neutral-bordered card.
13
+ * Standalone headers (browse pages, coin page, /claim hub) keep the
14
+ * gradient by default. */
16
15
  plain?: boolean;
16
+ /** No card at all — icon chip + title + subtitle on the page background.
17
+ * Used by ServiceFormShell so the form card is the page's only panel. */
18
+ bare?: boolean;
17
19
  }
18
20
  /** Shared launchpad/claim page header: a dark card with a solid primary icon
19
21
  * chip, title + subtitle. By default it sits on a static brand gradient
20
22
  * border; pass `plain` for a neutral-bordered card. Pure presentation —
21
23
  * consuming app supplies the icon and (optionally) a header accessory. */
22
- declare function ServiceHeader({ icon, title, subtitle, headerAccessory, className, plain }: ServiceHeaderProps): react_jsx_runtime.JSX.Element;
24
+ declare function ServiceHeader({ icon, title, subtitle, headerAccessory, className, plain, bare }: ServiceHeaderProps): react_jsx_runtime.JSX.Element;
23
25
 
24
26
  export { ServiceHeader, type ServiceHeaderProps };
@@ -9,16 +9,18 @@ interface ServiceHeaderProps {
9
9
  /** Optional element shown under the subtitle (e.g. a URL pill). */
10
10
  headerAccessory?: ReactNode;
11
11
  className?: string;
12
- /** Drop the brand gradient border for a plain neutral-bordered card. Used by
13
- * ServiceFormShell (create/mint form pages) where the form already carries
14
- * the animated gradient border, so the header shouldn't compete. Standalone
15
- * headers (browse pages, coin page, /claim hub) keep the gradient. */
12
+ /** Drop the brand gradient border for a plain neutral-bordered card.
13
+ * Standalone headers (browse pages, coin page, /claim hub) keep the
14
+ * gradient by default. */
16
15
  plain?: boolean;
16
+ /** No card at all — icon chip + title + subtitle on the page background.
17
+ * Used by ServiceFormShell so the form card is the page's only panel. */
18
+ bare?: boolean;
17
19
  }
18
20
  /** Shared launchpad/claim page header: a dark card with a solid primary icon
19
21
  * chip, title + subtitle. By default it sits on a static brand gradient
20
22
  * border; pass `plain` for a neutral-bordered card. Pure presentation —
21
23
  * consuming app supplies the icon and (optionally) a header accessory. */
22
- declare function ServiceHeader({ icon, title, subtitle, headerAccessory, className, plain }: ServiceHeaderProps): react_jsx_runtime.JSX.Element;
24
+ declare function ServiceHeader({ icon, title, subtitle, headerAccessory, className, plain, bare }: ServiceHeaderProps): react_jsx_runtime.JSX.Element;
23
25
 
24
26
  export { ServiceHeader, type ServiceHeaderProps };
@@ -1,14 +1,17 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { cn } from "../utils/cn.js";
3
- function ServiceHeader({ icon, title, subtitle, headerAccessory, className, plain = false }) {
3
+ function ServiceHeader({ icon, title, subtitle, headerAccessory, className, plain = false, bare = false }) {
4
4
  const body = /* @__PURE__ */ jsxs(Fragment, { children: [
5
5
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
6
6
  /* @__PURE__ */ jsx("div", { className: "h-9 w-9 rounded-xl bg-primary flex items-center justify-center shrink-0", children: icon }),
7
- /* @__PURE__ */ jsx("h1", { className: "text-2xl sm:text-3xl font-black", children: title })
7
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl sm:text-3xl font-black tracking-tight", children: title })
8
8
  ] }),
9
9
  /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-sm text-muted-foreground max-w-xl", children: subtitle }),
10
10
  headerAccessory && /* @__PURE__ */ jsx("div", { className: "mt-4", children: headerAccessory })
11
11
  ] });
12
+ if (bare) {
13
+ return /* @__PURE__ */ jsx("div", { className, children: body });
14
+ }
12
15
  if (plain) {
13
16
  return /* @__PURE__ */ jsx("div", { className: cn("rounded-2xl border border-border/60 bg-card p-6 sm:p-7", className), children: body });
14
17
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/service-header.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn.js\";\n\nexport interface ServiceHeaderProps {\n /** Rendered icon element, e.g. <Coins className=\"h-4 w-4 text-white\" />. */\n icon: ReactNode;\n title: string;\n subtitle: string;\n /** Optional element shown under the subtitle (e.g. a URL pill). */\n headerAccessory?: ReactNode;\n className?: string;\n /** Drop the brand gradient border for a plain neutral-bordered card. Used by\n * ServiceFormShell (create/mint form pages) where the form already carries\n * the animated gradient border, so the header shouldn't compete. Standalone\n * headers (browse pages, coin page, /claim hub) keep the gradient. */\n plain?: boolean;\n}\n\n/** Shared launchpad/claim page header: a dark card with a solid primary icon\n * chip, title + subtitle. By default it sits on a static brand gradient\n * border; pass `plain` for a neutral-bordered card. Pure presentation —\n * consuming app supplies the icon and (optionally) a header accessory. */\nexport function ServiceHeader({ icon, title, subtitle, headerAccessory, className, plain = false }: ServiceHeaderProps) {\n const body = (\n <>\n <div className=\"flex items-center gap-2.5\">\n <div className=\"h-9 w-9 rounded-xl bg-primary flex items-center justify-center shrink-0\">\n {icon}\n </div>\n <h1 className=\"text-2xl sm:text-3xl font-black\">{title}</h1>\n </div>\n <p className=\"mt-1.5 text-sm text-muted-foreground max-w-xl\">{subtitle}</p>\n {headerAccessory && <div className=\"mt-4\">{headerAccessory}</div>}\n </>\n );\n\n if (plain) {\n return <div className={cn(\"rounded-2xl border border-border/60 bg-card p-6 sm:p-7\", className)}>{body}</div>;\n }\n\n return (\n <div className={cn(\"rounded-2xl p-[1.5px] bg-gradient-to-br from-brand-blue via-brand-purple to-brand-rose\", className)}>\n <div className=\"rounded-[15px] bg-card p-6 sm:p-7\">{body}</div>\n </div>\n );\n}\n"],"mappings":"AAwBI,mBAEI,KADF,YADF;AAvBJ,SAAS,UAAU;AAqBZ,SAAS,cAAc,EAAE,MAAM,OAAO,UAAU,iBAAiB,WAAW,QAAQ,MAAM,GAAuB;AACtH,QAAM,OACJ,iCACE;AAAA,yBAAC,SAAI,WAAU,6BACb;AAAA,0BAAC,SAAI,WAAU,2EACZ,gBACH;AAAA,MACA,oBAAC,QAAG,WAAU,mCAAmC,iBAAM;AAAA,OACzD;AAAA,IACA,oBAAC,OAAE,WAAU,iDAAiD,oBAAS;AAAA,IACtE,mBAAmB,oBAAC,SAAI,WAAU,QAAQ,2BAAgB;AAAA,KAC7D;AAGF,MAAI,OAAO;AACT,WAAO,oBAAC,SAAI,WAAW,GAAG,0DAA0D,SAAS,GAAI,gBAAK;AAAA,EACxG;AAEA,SACE,oBAAC,SAAI,WAAW,GAAG,0FAA0F,SAAS,GACpH,8BAAC,SAAI,WAAU,qCAAqC,gBAAK,GAC3D;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/service-header.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn.js\";\n\nexport interface ServiceHeaderProps {\n /** Rendered icon element, e.g. <Coins className=\"h-4 w-4 text-white\" />. */\n icon: ReactNode;\n title: string;\n subtitle: string;\n /** Optional element shown under the subtitle (e.g. a URL pill). */\n headerAccessory?: ReactNode;\n className?: string;\n /** Drop the brand gradient border for a plain neutral-bordered card.\n * Standalone headers (browse pages, coin page, /claim hub) keep the\n * gradient by default. */\n plain?: boolean;\n /** No card at all — icon chip + title + subtitle on the page background.\n * Used by ServiceFormShell so the form card is the page's only panel. */\n bare?: boolean;\n}\n\n/** Shared launchpad/claim page header: a dark card with a solid primary icon\n * chip, title + subtitle. By default it sits on a static brand gradient\n * border; pass `plain` for a neutral-bordered card. Pure presentation —\n * consuming app supplies the icon and (optionally) a header accessory. */\nexport function ServiceHeader({ icon, title, subtitle, headerAccessory, className, plain = false, bare = false }: ServiceHeaderProps) {\n const body = (\n <>\n <div className=\"flex items-center gap-2.5\">\n <div className=\"h-9 w-9 rounded-xl bg-primary flex items-center justify-center shrink-0\">\n {icon}\n </div>\n <h1 className=\"text-2xl sm:text-3xl font-black tracking-tight\">{title}</h1>\n </div>\n <p className=\"mt-1.5 text-sm text-muted-foreground max-w-xl\">{subtitle}</p>\n {headerAccessory && <div className=\"mt-4\">{headerAccessory}</div>}\n </>\n );\n\n if (bare) {\n return <div className={className}>{body}</div>;\n }\n\n if (plain) {\n return <div className={cn(\"rounded-2xl border border-border/60 bg-card p-6 sm:p-7\", className)}>{body}</div>;\n }\n\n return (\n <div className={cn(\"rounded-2xl p-[1.5px] bg-gradient-to-br from-brand-blue via-brand-purple to-brand-rose\", className)}>\n <div className=\"rounded-[15px] bg-card p-6 sm:p-7\">{body}</div>\n </div>\n );\n}\n"],"mappings":"AA0BI,mBAEI,KADF,YADF;AAzBJ,SAAS,UAAU;AAuBZ,SAAS,cAAc,EAAE,MAAM,OAAO,UAAU,iBAAiB,WAAW,QAAQ,OAAO,OAAO,MAAM,GAAuB;AACpI,QAAM,OACJ,iCACE;AAAA,yBAAC,SAAI,WAAU,6BACb;AAAA,0BAAC,SAAI,WAAU,2EACZ,gBACH;AAAA,MACA,oBAAC,QAAG,WAAU,kDAAkD,iBAAM;AAAA,OACxE;AAAA,IACA,oBAAC,OAAE,WAAU,iDAAiD,oBAAS;AAAA,IACtE,mBAAmB,oBAAC,SAAI,WAAU,QAAQ,2BAAgB;AAAA,KAC7D;AAGF,MAAI,MAAM;AACR,WAAO,oBAAC,SAAI,WAAuB,gBAAK;AAAA,EAC1C;AAEA,MAAI,OAAO;AACT,WAAO,oBAAC,SAAI,WAAW,GAAG,0DAA0D,SAAS,GAAI,gBAAK;AAAA,EACxG;AAEA,SACE,oBAAC,SAAI,WAAW,GAAG,0FAA0F,SAAS,GACpH,8BAAC,SAAI,WAAU,qCAAqC,gBAAK,GAC3D;AAEJ;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medialane/ui",
3
- "version": "0.50.1",
3
+ "version": "0.52.0",
4
4
  "description": "Shared UI components for Medialane apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",