@medialane/ui 0.73.3 → 0.73.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/medialane-collection-card.cjs +8 -17
- package/dist/components/medialane-collection-card.cjs.map +1 -1
- package/dist/components/medialane-collection-card.d.cts +7 -5
- package/dist/components/medialane-collection-card.d.ts +7 -5
- package/dist/components/medialane-collection-card.js +8 -17
- package/dist/components/medialane-collection-card.js.map +1 -1
- package/dist/components/nav-shell.cjs +1 -1
- package/dist/components/nav-shell.cjs.map +1 -1
- package/dist/components/nav-shell.js +1 -1
- package/dist/components/nav-shell.js.map +1 -1
- package/dist/medialane.css +32 -0
- package/package.json +1 -1
|
@@ -26,9 +26,6 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
26
26
|
var import_react = require("react");
|
|
27
27
|
var import_cn = require("../utils/cn.js");
|
|
28
28
|
const FRAME_GRADIENT = "linear-gradient(135deg, #3b7bff, #8a5cf6 38%, #f6608f 70%, #fb8b46)";
|
|
29
|
-
const MATERIAL = `radial-gradient(120% 90% at 0% 0%, rgba(59,123,255,0.14), transparent 55%),
|
|
30
|
-
radial-gradient(120% 90% at 100% 100%, rgba(251,139,70,0.10), transparent 55%),
|
|
31
|
-
#0a0e1f`;
|
|
32
29
|
function MedialaneCollectionCard({
|
|
33
30
|
image,
|
|
34
31
|
name,
|
|
@@ -74,10 +71,9 @@ function MedialaneCollectionCard({
|
|
|
74
71
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
75
72
|
"div",
|
|
76
73
|
{
|
|
77
|
-
className: "relative rounded-[22.5px] overflow-hidden text-white ring-1 ring-inset ring-white/[0.06]",
|
|
78
|
-
style: { background: MATERIAL },
|
|
74
|
+
className: "ml-card-material relative rounded-[22.5px] overflow-hidden text-[#0a0e1f] dark:text-white ring-1 ring-inset ring-black/[0.06] dark:ring-white/[0.06]",
|
|
79
75
|
children: [
|
|
80
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "p-2.5 pb-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative aspect-[4/5] w-full overflow-hidden rounded-[16px] ring-1 ring-white/10", children: [
|
|
76
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "p-2.5 pb-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative aspect-[4/5] w-full overflow-hidden rounded-[16px] ring-1 ring-black/10 dark:ring-white/10", children: [
|
|
81
77
|
image ? (
|
|
82
78
|
// eslint-disable-next-line @next/next/no-img-element
|
|
83
79
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: image, alt: displayName, className: "h-full w-full object-cover" })
|
|
@@ -101,21 +97,16 @@ function MedialaneCollectionCard({
|
|
|
101
97
|
"div",
|
|
102
98
|
{
|
|
103
99
|
"aria-hidden": true,
|
|
104
|
-
className: "pointer-events-none absolute inset-0 opacity-40 group-hover:opacity-100 transition-opacity duration-300"
|
|
105
|
-
style: {
|
|
106
|
-
background: `radial-gradient(420px circle at var(--mx, 70%) var(--my, 20%), rgba(255,255,255,0.20), transparent 45%),
|
|
107
|
-
linear-gradient(115deg, rgba(59,123,255,0.14), rgba(138,92,246,0.14) 35%, rgba(246,96,143,0.14) 65%, rgba(251,139,70,0.14))`,
|
|
108
|
-
mixBlendMode: "screen"
|
|
109
|
-
}
|
|
100
|
+
className: "ml-card-sheen pointer-events-none absolute inset-0 opacity-40 group-hover:opacity-100 transition-opacity duration-300"
|
|
110
101
|
}
|
|
111
102
|
),
|
|
112
103
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative px-4 pt-3 pb-4", children: [
|
|
113
104
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-start gap-2", children: [
|
|
114
105
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "min-w-0 flex-1 text-[18px] font-bold leading-snug truncate", children: displayName }),
|
|
115
|
-
serial && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mt-0.5 shrink-0 rounded-full bg-white/10 px-2 py-0.5 text-[11px] font-semibold text-white/80 tabular-nums", children: serial })
|
|
106
|
+
serial && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mt-0.5 shrink-0 rounded-full bg-black/5 dark:bg-white/10 px-2 py-0.5 text-[11px] font-semibold text-[#0a0e1f]/80 dark:text-white/80 tabular-nums", children: serial })
|
|
116
107
|
] }),
|
|
117
|
-
collection && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mt-0.5 text-[12.5px] text-white/55 truncate", children: collection }),
|
|
118
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "my-3 h-px bg-white/10" }),
|
|
108
|
+
collection && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mt-0.5 text-[12.5px] text-[#0a0e1f]/55 dark:text-white/55 truncate", children: collection }),
|
|
109
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "my-3 h-px bg-black/10 dark:bg-white/10" }),
|
|
119
110
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
120
111
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
121
112
|
"span",
|
|
@@ -125,8 +116,8 @@ function MedialaneCollectionCard({
|
|
|
125
116
|
style: { background: FRAME_GRADIENT }
|
|
126
117
|
}
|
|
127
118
|
),
|
|
128
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[9px] font-bold tracking-[0.18em] text-white/50", children: "MEDIALANE" }),
|
|
129
|
-
creator && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ml-auto min-w-0 truncate text-[11px] text-white/55 tabular-nums", children: creator })
|
|
119
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[9px] font-bold tracking-[0.18em] text-[#0a0e1f]/50 dark:text-white/50", children: "MEDIALANE" }),
|
|
120
|
+
creator && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ml-auto min-w-0 truncate text-[11px] text-[#0a0e1f]/55 dark:text-white/55 tabular-nums", children: creator })
|
|
130
121
|
] })
|
|
131
122
|
] })
|
|
132
123
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/medialane-collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRef } from \"react\";\nimport { cn } from \"../utils/cn.js\";\n\nexport interface MedialaneCollectionCardProps {\n /** Resolved, browser-loadable image URL. Empty → brand-gradient placeholder. */\n image?: string | null;\n /** Asset or collection name. */\n name?: string;\n /** Secondary line under the name (collection name, symbol, ticker…). */\n collection?: string;\n /** Edition or serial shown as a pill, e.g. \"#42\" or \"1 / 300\". */\n serial?: string;\n /** Creator display name or shortened address. */\n creator?: string;\n className?: string;\n}\n\nconst FRAME_GRADIENT =\n \"linear-gradient(135deg, #3b7bff, #8a5cf6 38%, #f6608f 70%, #fb8b46)\";\n\n/**
|
|
1
|
+
{"version":3,"sources":["../../src/components/medialane-collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRef } from \"react\";\nimport { cn } from \"../utils/cn.js\";\n\nexport interface MedialaneCollectionCardProps {\n /** Resolved, browser-loadable image URL. Empty → brand-gradient placeholder. */\n image?: string | null;\n /** Asset or collection name. */\n name?: string;\n /** Secondary line under the name (collection name, symbol, ticker…). */\n collection?: string;\n /** Edition or serial shown as a pill, e.g. \"#42\" or \"1 / 300\". */\n serial?: string;\n /** Creator display name or shortened address. */\n creator?: string;\n className?: string;\n}\n\nconst FRAME_GRADIENT =\n \"linear-gradient(135deg, #3b7bff, #8a5cf6 38%, #f6608f 70%, #fb8b46)\";\n\n/** The Medialane Collection Card — a branded collectors-card preview of an\n * asset or collection. A self-contained collectible object: brand-spectrum\n * frame, inset artwork on foil-tinted material, pointer-tracked 3D tilt +\n * holographic sheen, display-face name, serial pill, Medialane maker's mark.\n * Follows the app's light/dark theme automatically (`.ml-card-material` /\n * `.ml-card-sheen` in medialane.css carry the `.dark` overrides — light is\n * the default, no `.dark` ancestor needed). Fluid width — size it with the\n * parent container. Pure presentation. */\nexport function MedialaneCollectionCard({\n image,\n name,\n collection,\n serial,\n creator,\n className,\n}: MedialaneCollectionCardProps) {\n const frameRef = useRef<HTMLDivElement>(null);\n\n const handleMove = (e: React.PointerEvent<HTMLDivElement>) => {\n const el = frameRef.current;\n if (!el || e.pointerType !== \"mouse\") return;\n if (window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches) return;\n const rect = el.getBoundingClientRect();\n const x = (e.clientX - rect.left) / rect.width;\n const y = (e.clientY - rect.top) / rect.height;\n el.style.setProperty(\"--rx\", `${(0.5 - y) * 9}deg`);\n el.style.setProperty(\"--ry\", `${(x - 0.5) * 9}deg`);\n el.style.setProperty(\"--mx\", `${x * 100}%`);\n el.style.setProperty(\"--my\", `${y * 100}%`);\n el.style.setProperty(\"--pop\", \"1.015\");\n };\n\n const handleLeave = () => {\n const el = frameRef.current;\n if (!el) return;\n el.style.setProperty(\"--rx\", \"0deg\");\n el.style.setProperty(\"--ry\", \"0deg\");\n el.style.setProperty(\"--pop\", \"1\");\n };\n\n const displayName = name?.trim() || \"Untitled\";\n\n return (\n <div className={cn(\"group\", className)} style={{ perspective: \"1000px\" }}>\n <div\n ref={frameRef}\n onPointerMove={handleMove}\n onPointerLeave={handleLeave}\n className=\"rounded-[24px] p-[1.5px] transition-transform duration-200 ease-out will-change-transform shadow-[0_16px_40px_-16px_rgba(91,76,230,0.45)]\"\n style={{\n background: FRAME_GRADIENT,\n transform:\n \"rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) scale(var(--pop, 1))\",\n transformStyle: \"preserve-3d\",\n }}\n >\n <div\n className=\"ml-card-material relative rounded-[22.5px] overflow-hidden text-[#0a0e1f] dark:text-white ring-1 ring-inset ring-black/[0.06] dark:ring-white/[0.06]\"\n >\n {/* Artwork — inset like a printed trading card */}\n <div className=\"p-2.5 pb-0\">\n <div className=\"relative aspect-[4/5] w-full overflow-hidden rounded-[16px] ring-1 ring-black/10 dark:ring-white/10\">\n {image ? (\n // eslint-disable-next-line @next/next/no-img-element\n <img src={image} alt={displayName} className=\"h-full w-full object-cover\" />\n ) : (\n <div\n className=\"h-full w-full\"\n style={{ background: FRAME_GRADIENT, opacity: 0.9 }}\n />\n )}\n {/* Bottom scrim for depth against the meta block */}\n <div\n aria-hidden\n className=\"pointer-events-none absolute inset-x-0 bottom-0 h-16\"\n style={{ background: \"linear-gradient(to top, rgba(10,14,31,0.45), transparent)\" }}\n />\n </div>\n </div>\n\n {/* Holographic sheen — visible at rest, blooms and tracks on hover */}\n <div\n aria-hidden\n className=\"ml-card-sheen pointer-events-none absolute inset-0 opacity-40 group-hover:opacity-100 transition-opacity duration-300\"\n />\n\n {/* Meta */}\n <div className=\"relative px-4 pt-3 pb-4\">\n <div className=\"flex items-start gap-2\">\n <p className=\"min-w-0 flex-1 text-[18px] font-bold leading-snug truncate\">\n {displayName}\n </p>\n {serial && (\n <span className=\"mt-0.5 shrink-0 rounded-full bg-black/5 dark:bg-white/10 px-2 py-0.5 text-[11px] font-semibold text-[#0a0e1f]/80 dark:text-white/80 tabular-nums\">\n {serial}\n </span>\n )}\n </div>\n {collection && (\n <p className=\"mt-0.5 text-[12.5px] text-[#0a0e1f]/55 dark:text-white/55 truncate\">{collection}</p>\n )}\n <div className=\"my-3 h-px bg-black/10 dark:bg-white/10\" />\n <div className=\"flex items-center gap-2\">\n <span\n aria-hidden\n className=\"h-3.5 w-3.5 rounded-full shrink-0\"\n style={{ background: FRAME_GRADIENT }}\n />\n <span className=\"text-[9px] font-bold tracking-[0.18em] text-[#0a0e1f]/50 dark:text-white/50\">\n MEDIALANE\n </span>\n {creator && (\n <span className=\"ml-auto min-w-0 truncate text-[11px] text-[#0a0e1f]/55 dark:text-white/55 tabular-nums\">\n {creator}\n </span>\n )}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -14,11 +14,13 @@ interface MedialaneCollectionCardProps {
|
|
|
14
14
|
className?: string;
|
|
15
15
|
}
|
|
16
16
|
/** The Medialane Collection Card — a branded collectors-card preview of an
|
|
17
|
-
* asset or collection. A self-contained
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
17
|
+
* asset or collection. A self-contained collectible object: brand-spectrum
|
|
18
|
+
* frame, inset artwork on foil-tinted material, pointer-tracked 3D tilt +
|
|
19
|
+
* holographic sheen, display-face name, serial pill, Medialane maker's mark.
|
|
20
|
+
* Follows the app's light/dark theme automatically (`.ml-card-material` /
|
|
21
|
+
* `.ml-card-sheen` in medialane.css carry the `.dark` overrides — light is
|
|
22
|
+
* the default, no `.dark` ancestor needed). Fluid width — size it with the
|
|
23
|
+
* parent container. Pure presentation. */
|
|
22
24
|
declare function MedialaneCollectionCard({ image, name, collection, serial, creator, className, }: MedialaneCollectionCardProps): react_jsx_runtime.JSX.Element;
|
|
23
25
|
|
|
24
26
|
export { MedialaneCollectionCard, type MedialaneCollectionCardProps };
|
|
@@ -14,11 +14,13 @@ interface MedialaneCollectionCardProps {
|
|
|
14
14
|
className?: string;
|
|
15
15
|
}
|
|
16
16
|
/** The Medialane Collection Card — a branded collectors-card preview of an
|
|
17
|
-
* asset or collection. A self-contained
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
17
|
+
* asset or collection. A self-contained collectible object: brand-spectrum
|
|
18
|
+
* frame, inset artwork on foil-tinted material, pointer-tracked 3D tilt +
|
|
19
|
+
* holographic sheen, display-face name, serial pill, Medialane maker's mark.
|
|
20
|
+
* Follows the app's light/dark theme automatically (`.ml-card-material` /
|
|
21
|
+
* `.ml-card-sheen` in medialane.css carry the `.dark` overrides — light is
|
|
22
|
+
* the default, no `.dark` ancestor needed). Fluid width — size it with the
|
|
23
|
+
* parent container. Pure presentation. */
|
|
22
24
|
declare function MedialaneCollectionCard({ image, name, collection, serial, creator, className, }: MedialaneCollectionCardProps): react_jsx_runtime.JSX.Element;
|
|
23
25
|
|
|
24
26
|
export { MedialaneCollectionCard, type MedialaneCollectionCardProps };
|
|
@@ -3,9 +3,6 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useRef } from "react";
|
|
4
4
|
import { cn } from "../utils/cn.js";
|
|
5
5
|
const FRAME_GRADIENT = "linear-gradient(135deg, #3b7bff, #8a5cf6 38%, #f6608f 70%, #fb8b46)";
|
|
6
|
-
const MATERIAL = `radial-gradient(120% 90% at 0% 0%, rgba(59,123,255,0.14), transparent 55%),
|
|
7
|
-
radial-gradient(120% 90% at 100% 100%, rgba(251,139,70,0.10), transparent 55%),
|
|
8
|
-
#0a0e1f`;
|
|
9
6
|
function MedialaneCollectionCard({
|
|
10
7
|
image,
|
|
11
8
|
name,
|
|
@@ -51,10 +48,9 @@ function MedialaneCollectionCard({
|
|
|
51
48
|
children: /* @__PURE__ */ jsxs(
|
|
52
49
|
"div",
|
|
53
50
|
{
|
|
54
|
-
className: "relative rounded-[22.5px] overflow-hidden text-white ring-1 ring-inset ring-white/[0.06]",
|
|
55
|
-
style: { background: MATERIAL },
|
|
51
|
+
className: "ml-card-material relative rounded-[22.5px] overflow-hidden text-[#0a0e1f] dark:text-white ring-1 ring-inset ring-black/[0.06] dark:ring-white/[0.06]",
|
|
56
52
|
children: [
|
|
57
|
-
/* @__PURE__ */ jsx("div", { className: "p-2.5 pb-0", children: /* @__PURE__ */ jsxs("div", { className: "relative aspect-[4/5] w-full overflow-hidden rounded-[16px] ring-1 ring-white/10", children: [
|
|
53
|
+
/* @__PURE__ */ jsx("div", { className: "p-2.5 pb-0", children: /* @__PURE__ */ jsxs("div", { className: "relative aspect-[4/5] w-full overflow-hidden rounded-[16px] ring-1 ring-black/10 dark:ring-white/10", children: [
|
|
58
54
|
image ? (
|
|
59
55
|
// eslint-disable-next-line @next/next/no-img-element
|
|
60
56
|
/* @__PURE__ */ jsx("img", { src: image, alt: displayName, className: "h-full w-full object-cover" })
|
|
@@ -78,21 +74,16 @@ function MedialaneCollectionCard({
|
|
|
78
74
|
"div",
|
|
79
75
|
{
|
|
80
76
|
"aria-hidden": true,
|
|
81
|
-
className: "pointer-events-none absolute inset-0 opacity-40 group-hover:opacity-100 transition-opacity duration-300"
|
|
82
|
-
style: {
|
|
83
|
-
background: `radial-gradient(420px circle at var(--mx, 70%) var(--my, 20%), rgba(255,255,255,0.20), transparent 45%),
|
|
84
|
-
linear-gradient(115deg, rgba(59,123,255,0.14), rgba(138,92,246,0.14) 35%, rgba(246,96,143,0.14) 65%, rgba(251,139,70,0.14))`,
|
|
85
|
-
mixBlendMode: "screen"
|
|
86
|
-
}
|
|
77
|
+
className: "ml-card-sheen pointer-events-none absolute inset-0 opacity-40 group-hover:opacity-100 transition-opacity duration-300"
|
|
87
78
|
}
|
|
88
79
|
),
|
|
89
80
|
/* @__PURE__ */ jsxs("div", { className: "relative px-4 pt-3 pb-4", children: [
|
|
90
81
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
91
82
|
/* @__PURE__ */ jsx("p", { className: "min-w-0 flex-1 text-[18px] font-bold leading-snug truncate", children: displayName }),
|
|
92
|
-
serial && /* @__PURE__ */ jsx("span", { className: "mt-0.5 shrink-0 rounded-full bg-white/10 px-2 py-0.5 text-[11px] font-semibold text-white/80 tabular-nums", children: serial })
|
|
83
|
+
serial && /* @__PURE__ */ jsx("span", { className: "mt-0.5 shrink-0 rounded-full bg-black/5 dark:bg-white/10 px-2 py-0.5 text-[11px] font-semibold text-[#0a0e1f]/80 dark:text-white/80 tabular-nums", children: serial })
|
|
93
84
|
] }),
|
|
94
|
-
collection && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-[12.5px] text-white/55 truncate", children: collection }),
|
|
95
|
-
/* @__PURE__ */ jsx("div", { className: "my-3 h-px bg-white/10" }),
|
|
85
|
+
collection && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-[12.5px] text-[#0a0e1f]/55 dark:text-white/55 truncate", children: collection }),
|
|
86
|
+
/* @__PURE__ */ jsx("div", { className: "my-3 h-px bg-black/10 dark:bg-white/10" }),
|
|
96
87
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
97
88
|
/* @__PURE__ */ jsx(
|
|
98
89
|
"span",
|
|
@@ -102,8 +93,8 @@ function MedialaneCollectionCard({
|
|
|
102
93
|
style: { background: FRAME_GRADIENT }
|
|
103
94
|
}
|
|
104
95
|
),
|
|
105
|
-
/* @__PURE__ */ jsx("span", { className: "text-[9px] font-bold tracking-[0.18em] text-white/50", children: "MEDIALANE" }),
|
|
106
|
-
creator && /* @__PURE__ */ jsx("span", { className: "ml-auto min-w-0 truncate text-[11px] text-white/55 tabular-nums", children: creator })
|
|
96
|
+
/* @__PURE__ */ jsx("span", { className: "text-[9px] font-bold tracking-[0.18em] text-[#0a0e1f]/50 dark:text-white/50", children: "MEDIALANE" }),
|
|
97
|
+
creator && /* @__PURE__ */ jsx("span", { className: "ml-auto min-w-0 truncate text-[11px] text-[#0a0e1f]/55 dark:text-white/55 tabular-nums", children: creator })
|
|
107
98
|
] })
|
|
108
99
|
] })
|
|
109
100
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/medialane-collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRef } from \"react\";\nimport { cn } from \"../utils/cn.js\";\n\nexport interface MedialaneCollectionCardProps {\n /** Resolved, browser-loadable image URL. Empty → brand-gradient placeholder. */\n image?: string | null;\n /** Asset or collection name. */\n name?: string;\n /** Secondary line under the name (collection name, symbol, ticker…). */\n collection?: string;\n /** Edition or serial shown as a pill, e.g. \"#42\" or \"1 / 300\". */\n serial?: string;\n /** Creator display name or shortened address. */\n creator?: string;\n className?: string;\n}\n\nconst FRAME_GRADIENT =\n \"linear-gradient(135deg, #3b7bff, #8a5cf6 38%, #f6608f 70%, #fb8b46)\";\n\n/**
|
|
1
|
+
{"version":3,"sources":["../../src/components/medialane-collection-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRef } from \"react\";\nimport { cn } from \"../utils/cn.js\";\n\nexport interface MedialaneCollectionCardProps {\n /** Resolved, browser-loadable image URL. Empty → brand-gradient placeholder. */\n image?: string | null;\n /** Asset or collection name. */\n name?: string;\n /** Secondary line under the name (collection name, symbol, ticker…). */\n collection?: string;\n /** Edition or serial shown as a pill, e.g. \"#42\" or \"1 / 300\". */\n serial?: string;\n /** Creator display name or shortened address. */\n creator?: string;\n className?: string;\n}\n\nconst FRAME_GRADIENT =\n \"linear-gradient(135deg, #3b7bff, #8a5cf6 38%, #f6608f 70%, #fb8b46)\";\n\n/** The Medialane Collection Card — a branded collectors-card preview of an\n * asset or collection. A self-contained collectible object: brand-spectrum\n * frame, inset artwork on foil-tinted material, pointer-tracked 3D tilt +\n * holographic sheen, display-face name, serial pill, Medialane maker's mark.\n * Follows the app's light/dark theme automatically (`.ml-card-material` /\n * `.ml-card-sheen` in medialane.css carry the `.dark` overrides — light is\n * the default, no `.dark` ancestor needed). Fluid width — size it with the\n * parent container. Pure presentation. */\nexport function MedialaneCollectionCard({\n image,\n name,\n collection,\n serial,\n creator,\n className,\n}: MedialaneCollectionCardProps) {\n const frameRef = useRef<HTMLDivElement>(null);\n\n const handleMove = (e: React.PointerEvent<HTMLDivElement>) => {\n const el = frameRef.current;\n if (!el || e.pointerType !== \"mouse\") return;\n if (window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches) return;\n const rect = el.getBoundingClientRect();\n const x = (e.clientX - rect.left) / rect.width;\n const y = (e.clientY - rect.top) / rect.height;\n el.style.setProperty(\"--rx\", `${(0.5 - y) * 9}deg`);\n el.style.setProperty(\"--ry\", `${(x - 0.5) * 9}deg`);\n el.style.setProperty(\"--mx\", `${x * 100}%`);\n el.style.setProperty(\"--my\", `${y * 100}%`);\n el.style.setProperty(\"--pop\", \"1.015\");\n };\n\n const handleLeave = () => {\n const el = frameRef.current;\n if (!el) return;\n el.style.setProperty(\"--rx\", \"0deg\");\n el.style.setProperty(\"--ry\", \"0deg\");\n el.style.setProperty(\"--pop\", \"1\");\n };\n\n const displayName = name?.trim() || \"Untitled\";\n\n return (\n <div className={cn(\"group\", className)} style={{ perspective: \"1000px\" }}>\n <div\n ref={frameRef}\n onPointerMove={handleMove}\n onPointerLeave={handleLeave}\n className=\"rounded-[24px] p-[1.5px] transition-transform duration-200 ease-out will-change-transform shadow-[0_16px_40px_-16px_rgba(91,76,230,0.45)]\"\n style={{\n background: FRAME_GRADIENT,\n transform:\n \"rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) scale(var(--pop, 1))\",\n transformStyle: \"preserve-3d\",\n }}\n >\n <div\n className=\"ml-card-material relative rounded-[22.5px] overflow-hidden text-[#0a0e1f] dark:text-white ring-1 ring-inset ring-black/[0.06] dark:ring-white/[0.06]\"\n >\n {/* Artwork — inset like a printed trading card */}\n <div className=\"p-2.5 pb-0\">\n <div className=\"relative aspect-[4/5] w-full overflow-hidden rounded-[16px] ring-1 ring-black/10 dark:ring-white/10\">\n {image ? (\n // eslint-disable-next-line @next/next/no-img-element\n <img src={image} alt={displayName} className=\"h-full w-full object-cover\" />\n ) : (\n <div\n className=\"h-full w-full\"\n style={{ background: FRAME_GRADIENT, opacity: 0.9 }}\n />\n )}\n {/* Bottom scrim for depth against the meta block */}\n <div\n aria-hidden\n className=\"pointer-events-none absolute inset-x-0 bottom-0 h-16\"\n style={{ background: \"linear-gradient(to top, rgba(10,14,31,0.45), transparent)\" }}\n />\n </div>\n </div>\n\n {/* Holographic sheen — visible at rest, blooms and tracks on hover */}\n <div\n aria-hidden\n className=\"ml-card-sheen pointer-events-none absolute inset-0 opacity-40 group-hover:opacity-100 transition-opacity duration-300\"\n />\n\n {/* Meta */}\n <div className=\"relative px-4 pt-3 pb-4\">\n <div className=\"flex items-start gap-2\">\n <p className=\"min-w-0 flex-1 text-[18px] font-bold leading-snug truncate\">\n {displayName}\n </p>\n {serial && (\n <span className=\"mt-0.5 shrink-0 rounded-full bg-black/5 dark:bg-white/10 px-2 py-0.5 text-[11px] font-semibold text-[#0a0e1f]/80 dark:text-white/80 tabular-nums\">\n {serial}\n </span>\n )}\n </div>\n {collection && (\n <p className=\"mt-0.5 text-[12.5px] text-[#0a0e1f]/55 dark:text-white/55 truncate\">{collection}</p>\n )}\n <div className=\"my-3 h-px bg-black/10 dark:bg-white/10\" />\n <div className=\"flex items-center gap-2\">\n <span\n aria-hidden\n className=\"h-3.5 w-3.5 rounded-full shrink-0\"\n style={{ background: FRAME_GRADIENT }}\n />\n <span className=\"text-[9px] font-bold tracking-[0.18em] text-[#0a0e1f]/50 dark:text-white/50\">\n MEDIALANE\n </span>\n {creator && (\n <span className=\"ml-auto min-w-0 truncate text-[11px] text-[#0a0e1f]/55 dark:text-white/55 tabular-nums\">\n {creator}\n </span>\n )}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -48,7 +48,7 @@ function NavBrandButton({ onClick, className, iconSrc = "/icon.png", ...rest })
|
|
|
48
48
|
"aria-label": rest["aria-label"] ?? "Open navigation",
|
|
49
49
|
className: (0, import_cn.cn)(
|
|
50
50
|
"group flex h-11 items-center gap-2 rounded-full",
|
|
51
|
-
"bg-background/10 pl-
|
|
51
|
+
"bg-background/10 pl-2.5 pr-3 backdrop-blur-xl backdrop-saturate-150",
|
|
52
52
|
"transition-colors hover:bg-background/20 active:scale-[0.97]",
|
|
53
53
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60",
|
|
54
54
|
className
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/nav-shell.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { cn } from \"../utils/cn.js\";\n\n// ── Header buttons ────────────────────────────────────────────────────────────\n\nexport interface NavBrandButtonProps {\n /** Defaults to opening the nav command menu (`ml:nav-open`). */\n onClick?: () => void;\n className?: string;\n \"aria-label\"?: string;\n /** Path to the brand icon image (the app's real icon asset). */\n iconSrc?: string;\n}\n\n/**\n * The main header trigger: brand mark + menu glyph in one quiet glass pill.\n * Mobile-first — a single ≥44px tap target instead of two small adjacent icons.\n * With no `onClick`, it opens the NavCommandMenu mounted elsewhere in the app.\n */\nexport function NavBrandButton({ onClick, className, iconSrc = \"/icon.png\", ...rest }: NavBrandButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick ?? (() => document.dispatchEvent(new CustomEvent(ML_NAV_OPEN)))}\n aria-label={rest[\"aria-label\"] ?? \"Open navigation\"}\n className={cn(\n \"group flex h-11 items-center gap-2 rounded-full\",\n \"bg-background/10 pl-1.5 pr-3 backdrop-blur-xl backdrop-saturate-150\",\n \"transition-colors hover:bg-background/20 active:scale-[0.97]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60\",\n className\n )}\n >\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img src={iconSrc} alt=\"Medialane\" width={30} height={30} className=\"h-[30px] w-[30px] shrink-0\" />\n <span className=\"flex flex-col gap-[5px]\" aria-hidden=\"true\">\n <span className=\"h-[1.5px] w-4 rounded-full bg-muted-foreground transition-all group-hover:w-4 group-hover:bg-foreground\" />\n <span className=\"h-[1.5px] w-2.5 rounded-full bg-muted-foreground transition-all group-hover:w-4 group-hover:bg-foreground\" />\n </span>\n </button>\n );\n}\n\nexport interface NavIconButtonProps {\n onClick?: () => void;\n className?: string;\n \"aria-label\": string;\n /** Show a small brand-colored status dot (e.g. wallet connected). */\n indicator?: boolean;\n children: React.ReactNode;\n}\n\n/**\n * Circular glass header button — the right-side counterpart to NavBrandButton\n * (wallet / account trigger).\n */\nexport function NavIconButton({ onClick, className, indicator, children, ...rest }: NavIconButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={rest[\"aria-label\"]}\n className={cn(\n \"relative flex h-11 w-11 items-center justify-center rounded-full\",\n \"bg-background/10 text-muted-foreground backdrop-blur-xl backdrop-saturate-150\",\n \"transition-colors hover:bg-background/20 hover:text-foreground active:scale-[0.97]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60\",\n className\n )}\n >\n {children}\n {indicator && (\n <span className=\"absolute right-[3px] top-[3px] h-2.5 w-2.5 rounded-full border-2 border-background bg-brand-blue\" />\n )}\n </button>\n );\n}\n\n// ── Account sheet ─────────────────────────────────────────────────────────────\n\nconst ML_ACCOUNT_OPEN = \"ml:account-open\";\nconst ML_ACCOUNT_CLOSE = \"ml:account-close\";\nconst ML_NAV_OPEN = \"ml:nav-open\";\nconst ML_NAV_CLOSE = \"ml:nav-close\";\n\nexport function useNavAccountSheet() {\n return {\n open: () => document.dispatchEvent(new CustomEvent(ML_ACCOUNT_OPEN)),\n close: () => document.dispatchEvent(new CustomEvent(ML_ACCOUNT_CLOSE)),\n };\n}\n\nexport interface NavAccountSheetProps {\n /** The app's account/connect panel (Clerk, wallet connectors, …). */\n children: React.ReactNode;\n /** Optional heading above the panel. */\n title?: string;\n}\n\n/**\n * The wallet-side surface: a compact glass sheet anchored to the top-right\n * header button (bottom sheet on mobile). Content is app-owned — pass the same\n * account panel the command menu uses in its accountSlot.\n *\n * Opens via `useNavAccountSheet().open()`. Mutually exclusive with the command\n * menu: opening one closes the other, and the shared `ml:nav-close` event\n * (fired by `useNavCommandMenu().close()`) closes this sheet too, so account\n * panels behave identically in both hosts.\n */\nexport function NavAccountSheet({ children, title = \"Account\" }: NavAccountSheetProps) {\n const [open, setOpen] = React.useState(false);\n\n React.useEffect(() => {\n const onOpen = () => {\n document.dispatchEvent(new CustomEvent(ML_NAV_CLOSE));\n setOpen(true);\n };\n const onClose = () => setOpen(false);\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(ML_ACCOUNT_OPEN, onOpen);\n document.addEventListener(ML_ACCOUNT_CLOSE, onClose);\n document.addEventListener(ML_NAV_OPEN, onClose);\n document.addEventListener(ML_NAV_CLOSE, onClose);\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(ML_ACCOUNT_OPEN, onOpen);\n document.removeEventListener(ML_ACCOUNT_CLOSE, onClose);\n document.removeEventListener(ML_NAV_OPEN, onClose);\n document.removeEventListener(ML_NAV_CLOSE, onClose);\n document.removeEventListener(\"keydown\", onKey);\n };\n }, []);\n\n return (\n <AnimatePresence>\n {open && (\n <>\n <motion.div\n className=\"nav-canvas-overlay\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15 }}\n onClick={() => setOpen(false)}\n />\n <motion.div\n className=\"fixed inset-x-3 bottom-3 z-[101] sm:inset-auto sm:right-4 sm:top-4 sm:w-[360px] lg:right-8\"\n initial={{ opacity: 0, y: 24 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 24 }}\n transition={{ duration: 0.18, ease: \"easeOut\" }}\n >\n <div className=\"overflow-hidden rounded-[20px] border border-border/40 bg-background/90 shadow-2xl backdrop-blur-2xl backdrop-saturate-150\">\n <div className=\"flex justify-center pt-2.5 sm:hidden\" aria-hidden=\"true\">\n <span className=\"h-1 w-9 rounded-full bg-muted-foreground/30\" />\n </div>\n <div className=\"flex items-center justify-between px-4 pb-1 pt-2 sm:pt-3\">\n <span className=\"text-[11px] font-semibold uppercase tracking-wider text-muted-foreground/70\">\n {title}\n </span>\n <button\n onClick={() => setOpen(false)}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted/50\"\n aria-label=\"Close\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <div className=\"px-3 pb-4 pt-1 sm:pb-3\">{children}</div>\n </div>\n </motion.div>\n </>\n )}\n </AnimatePresence>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/nav-shell.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { cn } from \"../utils/cn.js\";\n\n// ── Header buttons ────────────────────────────────────────────────────────────\n\nexport interface NavBrandButtonProps {\n /** Defaults to opening the nav command menu (`ml:nav-open`). */\n onClick?: () => void;\n className?: string;\n \"aria-label\"?: string;\n /** Path to the brand icon image (the app's real icon asset). */\n iconSrc?: string;\n}\n\n/**\n * The main header trigger: brand mark + menu glyph in one quiet glass pill.\n * Mobile-first — a single ≥44px tap target instead of two small adjacent icons.\n * With no `onClick`, it opens the NavCommandMenu mounted elsewhere in the app.\n */\nexport function NavBrandButton({ onClick, className, iconSrc = \"/icon.png\", ...rest }: NavBrandButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick ?? (() => document.dispatchEvent(new CustomEvent(ML_NAV_OPEN)))}\n aria-label={rest[\"aria-label\"] ?? \"Open navigation\"}\n className={cn(\n \"group flex h-11 items-center gap-2 rounded-full\",\n \"bg-background/10 pl-2.5 pr-3 backdrop-blur-xl backdrop-saturate-150\",\n \"transition-colors hover:bg-background/20 active:scale-[0.97]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60\",\n className\n )}\n >\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img src={iconSrc} alt=\"Medialane\" width={30} height={30} className=\"h-[30px] w-[30px] shrink-0\" />\n <span className=\"flex flex-col gap-[5px]\" aria-hidden=\"true\">\n <span className=\"h-[1.5px] w-4 rounded-full bg-muted-foreground transition-all group-hover:w-4 group-hover:bg-foreground\" />\n <span className=\"h-[1.5px] w-2.5 rounded-full bg-muted-foreground transition-all group-hover:w-4 group-hover:bg-foreground\" />\n </span>\n </button>\n );\n}\n\nexport interface NavIconButtonProps {\n onClick?: () => void;\n className?: string;\n \"aria-label\": string;\n /** Show a small brand-colored status dot (e.g. wallet connected). */\n indicator?: boolean;\n children: React.ReactNode;\n}\n\n/**\n * Circular glass header button — the right-side counterpart to NavBrandButton\n * (wallet / account trigger).\n */\nexport function NavIconButton({ onClick, className, indicator, children, ...rest }: NavIconButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={rest[\"aria-label\"]}\n className={cn(\n \"relative flex h-11 w-11 items-center justify-center rounded-full\",\n \"bg-background/10 text-muted-foreground backdrop-blur-xl backdrop-saturate-150\",\n \"transition-colors hover:bg-background/20 hover:text-foreground active:scale-[0.97]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60\",\n className\n )}\n >\n {children}\n {indicator && (\n <span className=\"absolute right-[3px] top-[3px] h-2.5 w-2.5 rounded-full border-2 border-background bg-brand-blue\" />\n )}\n </button>\n );\n}\n\n// ── Account sheet ─────────────────────────────────────────────────────────────\n\nconst ML_ACCOUNT_OPEN = \"ml:account-open\";\nconst ML_ACCOUNT_CLOSE = \"ml:account-close\";\nconst ML_NAV_OPEN = \"ml:nav-open\";\nconst ML_NAV_CLOSE = \"ml:nav-close\";\n\nexport function useNavAccountSheet() {\n return {\n open: () => document.dispatchEvent(new CustomEvent(ML_ACCOUNT_OPEN)),\n close: () => document.dispatchEvent(new CustomEvent(ML_ACCOUNT_CLOSE)),\n };\n}\n\nexport interface NavAccountSheetProps {\n /** The app's account/connect panel (Clerk, wallet connectors, …). */\n children: React.ReactNode;\n /** Optional heading above the panel. */\n title?: string;\n}\n\n/**\n * The wallet-side surface: a compact glass sheet anchored to the top-right\n * header button (bottom sheet on mobile). Content is app-owned — pass the same\n * account panel the command menu uses in its accountSlot.\n *\n * Opens via `useNavAccountSheet().open()`. Mutually exclusive with the command\n * menu: opening one closes the other, and the shared `ml:nav-close` event\n * (fired by `useNavCommandMenu().close()`) closes this sheet too, so account\n * panels behave identically in both hosts.\n */\nexport function NavAccountSheet({ children, title = \"Account\" }: NavAccountSheetProps) {\n const [open, setOpen] = React.useState(false);\n\n React.useEffect(() => {\n const onOpen = () => {\n document.dispatchEvent(new CustomEvent(ML_NAV_CLOSE));\n setOpen(true);\n };\n const onClose = () => setOpen(false);\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(ML_ACCOUNT_OPEN, onOpen);\n document.addEventListener(ML_ACCOUNT_CLOSE, onClose);\n document.addEventListener(ML_NAV_OPEN, onClose);\n document.addEventListener(ML_NAV_CLOSE, onClose);\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(ML_ACCOUNT_OPEN, onOpen);\n document.removeEventListener(ML_ACCOUNT_CLOSE, onClose);\n document.removeEventListener(ML_NAV_OPEN, onClose);\n document.removeEventListener(ML_NAV_CLOSE, onClose);\n document.removeEventListener(\"keydown\", onKey);\n };\n }, []);\n\n return (\n <AnimatePresence>\n {open && (\n <>\n <motion.div\n className=\"nav-canvas-overlay\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15 }}\n onClick={() => setOpen(false)}\n />\n <motion.div\n className=\"fixed inset-x-3 bottom-3 z-[101] sm:inset-auto sm:right-4 sm:top-4 sm:w-[360px] lg:right-8\"\n initial={{ opacity: 0, y: 24 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 24 }}\n transition={{ duration: 0.18, ease: \"easeOut\" }}\n >\n <div className=\"overflow-hidden rounded-[20px] border border-border/40 bg-background/90 shadow-2xl backdrop-blur-2xl backdrop-saturate-150\">\n <div className=\"flex justify-center pt-2.5 sm:hidden\" aria-hidden=\"true\">\n <span className=\"h-1 w-9 rounded-full bg-muted-foreground/30\" />\n </div>\n <div className=\"flex items-center justify-between px-4 pb-1 pt-2 sm:pt-3\">\n <span className=\"text-[11px] font-semibold uppercase tracking-wider text-muted-foreground/70\">\n {title}\n </span>\n <button\n onClick={() => setOpen(false)}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted/50\"\n aria-label=\"Close\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <div className=\"px-3 pb-4 pt-1 sm:pb-3\">{children}</div>\n </div>\n </motion.div>\n </>\n )}\n </AnimatePresence>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -12,7 +12,7 @@ function NavBrandButton({ onClick, className, iconSrc = "/icon.png", ...rest })
|
|
|
12
12
|
"aria-label": rest["aria-label"] ?? "Open navigation",
|
|
13
13
|
className: cn(
|
|
14
14
|
"group flex h-11 items-center gap-2 rounded-full",
|
|
15
|
-
"bg-background/10 pl-
|
|
15
|
+
"bg-background/10 pl-2.5 pr-3 backdrop-blur-xl backdrop-saturate-150",
|
|
16
16
|
"transition-colors hover:bg-background/20 active:scale-[0.97]",
|
|
17
17
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60",
|
|
18
18
|
className
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/nav-shell.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { cn } from \"../utils/cn.js\";\n\n// ── Header buttons ────────────────────────────────────────────────────────────\n\nexport interface NavBrandButtonProps {\n /** Defaults to opening the nav command menu (`ml:nav-open`). */\n onClick?: () => void;\n className?: string;\n \"aria-label\"?: string;\n /** Path to the brand icon image (the app's real icon asset). */\n iconSrc?: string;\n}\n\n/**\n * The main header trigger: brand mark + menu glyph in one quiet glass pill.\n * Mobile-first — a single ≥44px tap target instead of two small adjacent icons.\n * With no `onClick`, it opens the NavCommandMenu mounted elsewhere in the app.\n */\nexport function NavBrandButton({ onClick, className, iconSrc = \"/icon.png\", ...rest }: NavBrandButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick ?? (() => document.dispatchEvent(new CustomEvent(ML_NAV_OPEN)))}\n aria-label={rest[\"aria-label\"] ?? \"Open navigation\"}\n className={cn(\n \"group flex h-11 items-center gap-2 rounded-full\",\n \"bg-background/10 pl-1.5 pr-3 backdrop-blur-xl backdrop-saturate-150\",\n \"transition-colors hover:bg-background/20 active:scale-[0.97]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60\",\n className\n )}\n >\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img src={iconSrc} alt=\"Medialane\" width={30} height={30} className=\"h-[30px] w-[30px] shrink-0\" />\n <span className=\"flex flex-col gap-[5px]\" aria-hidden=\"true\">\n <span className=\"h-[1.5px] w-4 rounded-full bg-muted-foreground transition-all group-hover:w-4 group-hover:bg-foreground\" />\n <span className=\"h-[1.5px] w-2.5 rounded-full bg-muted-foreground transition-all group-hover:w-4 group-hover:bg-foreground\" />\n </span>\n </button>\n );\n}\n\nexport interface NavIconButtonProps {\n onClick?: () => void;\n className?: string;\n \"aria-label\": string;\n /** Show a small brand-colored status dot (e.g. wallet connected). */\n indicator?: boolean;\n children: React.ReactNode;\n}\n\n/**\n * Circular glass header button — the right-side counterpart to NavBrandButton\n * (wallet / account trigger).\n */\nexport function NavIconButton({ onClick, className, indicator, children, ...rest }: NavIconButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={rest[\"aria-label\"]}\n className={cn(\n \"relative flex h-11 w-11 items-center justify-center rounded-full\",\n \"bg-background/10 text-muted-foreground backdrop-blur-xl backdrop-saturate-150\",\n \"transition-colors hover:bg-background/20 hover:text-foreground active:scale-[0.97]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60\",\n className\n )}\n >\n {children}\n {indicator && (\n <span className=\"absolute right-[3px] top-[3px] h-2.5 w-2.5 rounded-full border-2 border-background bg-brand-blue\" />\n )}\n </button>\n );\n}\n\n// ── Account sheet ─────────────────────────────────────────────────────────────\n\nconst ML_ACCOUNT_OPEN = \"ml:account-open\";\nconst ML_ACCOUNT_CLOSE = \"ml:account-close\";\nconst ML_NAV_OPEN = \"ml:nav-open\";\nconst ML_NAV_CLOSE = \"ml:nav-close\";\n\nexport function useNavAccountSheet() {\n return {\n open: () => document.dispatchEvent(new CustomEvent(ML_ACCOUNT_OPEN)),\n close: () => document.dispatchEvent(new CustomEvent(ML_ACCOUNT_CLOSE)),\n };\n}\n\nexport interface NavAccountSheetProps {\n /** The app's account/connect panel (Clerk, wallet connectors, …). */\n children: React.ReactNode;\n /** Optional heading above the panel. */\n title?: string;\n}\n\n/**\n * The wallet-side surface: a compact glass sheet anchored to the top-right\n * header button (bottom sheet on mobile). Content is app-owned — pass the same\n * account panel the command menu uses in its accountSlot.\n *\n * Opens via `useNavAccountSheet().open()`. Mutually exclusive with the command\n * menu: opening one closes the other, and the shared `ml:nav-close` event\n * (fired by `useNavCommandMenu().close()`) closes this sheet too, so account\n * panels behave identically in both hosts.\n */\nexport function NavAccountSheet({ children, title = \"Account\" }: NavAccountSheetProps) {\n const [open, setOpen] = React.useState(false);\n\n React.useEffect(() => {\n const onOpen = () => {\n document.dispatchEvent(new CustomEvent(ML_NAV_CLOSE));\n setOpen(true);\n };\n const onClose = () => setOpen(false);\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(ML_ACCOUNT_OPEN, onOpen);\n document.addEventListener(ML_ACCOUNT_CLOSE, onClose);\n document.addEventListener(ML_NAV_OPEN, onClose);\n document.addEventListener(ML_NAV_CLOSE, onClose);\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(ML_ACCOUNT_OPEN, onOpen);\n document.removeEventListener(ML_ACCOUNT_CLOSE, onClose);\n document.removeEventListener(ML_NAV_OPEN, onClose);\n document.removeEventListener(ML_NAV_CLOSE, onClose);\n document.removeEventListener(\"keydown\", onKey);\n };\n }, []);\n\n return (\n <AnimatePresence>\n {open && (\n <>\n <motion.div\n className=\"nav-canvas-overlay\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15 }}\n onClick={() => setOpen(false)}\n />\n <motion.div\n className=\"fixed inset-x-3 bottom-3 z-[101] sm:inset-auto sm:right-4 sm:top-4 sm:w-[360px] lg:right-8\"\n initial={{ opacity: 0, y: 24 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 24 }}\n transition={{ duration: 0.18, ease: \"easeOut\" }}\n >\n <div className=\"overflow-hidden rounded-[20px] border border-border/40 bg-background/90 shadow-2xl backdrop-blur-2xl backdrop-saturate-150\">\n <div className=\"flex justify-center pt-2.5 sm:hidden\" aria-hidden=\"true\">\n <span className=\"h-1 w-9 rounded-full bg-muted-foreground/30\" />\n </div>\n <div className=\"flex items-center justify-between px-4 pb-1 pt-2 sm:pt-3\">\n <span className=\"text-[11px] font-semibold uppercase tracking-wider text-muted-foreground/70\">\n {title}\n </span>\n <button\n onClick={() => setOpen(false)}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted/50\"\n aria-label=\"Close\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <div className=\"px-3 pb-4 pt-1 sm:pb-3\">{children}</div>\n </div>\n </motion.div>\n </>\n )}\n </AnimatePresence>\n );\n}\n"],"mappings":";AAqCM,SAwGE,UAxGF,KACA,YADA;AAnCN,YAAY,WAAW;AACvB,SAAS,iBAAiB,cAAc;AACxC,SAAS,UAAU;AAkBZ,SAAS,eAAe,EAAE,SAAS,WAAW,UAAU,aAAa,GAAG,KAAK,GAAwB;AAC1G,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS,YAAY,MAAM,SAAS,cAAc,IAAI,YAAY,WAAW,CAAC;AAAA,MAC9E,cAAY,KAAK,YAAY,KAAK;AAAA,MAClC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MAGA;AAAA,4BAAC,SAAI,KAAK,SAAS,KAAI,aAAY,OAAO,IAAI,QAAQ,IAAI,WAAU,8BAA6B;AAAA,QACjG,qBAAC,UAAK,WAAU,2BAA0B,eAAY,QACpD;AAAA,8BAAC,UAAK,WAAU,2GAA0G;AAAA,UAC1H,oBAAC,UAAK,WAAU,6GAA4G;AAAA,WAC9H;AAAA;AAAA;AAAA,EACF;AAEJ;AAeO,SAAS,cAAc,EAAE,SAAS,WAAW,WAAW,UAAU,GAAG,KAAK,GAAuB;AACtG,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL;AAAA,MACA,cAAY,KAAK,YAAY;AAAA,MAC7B,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,QACA,aACC,oBAAC,UAAK,WAAU,oGAAmG;AAAA;AAAA;AAAA,EAEvH;AAEJ;AAIA,MAAM,kBAAkB;AACxB,MAAM,mBAAmB;AACzB,MAAM,cAAc;AACpB,MAAM,eAAe;AAEd,SAAS,qBAAqB;AACnC,SAAO;AAAA,IACL,MAAM,MAAM,SAAS,cAAc,IAAI,YAAY,eAAe,CAAC;AAAA,IACnE,OAAO,MAAM,SAAS,cAAc,IAAI,YAAY,gBAAgB,CAAC;AAAA,EACvE;AACF;AAmBO,SAAS,gBAAgB,EAAE,UAAU,QAAQ,UAAU,GAAyB;AACrF,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAS,KAAK;AAE5C,QAAM,UAAU,MAAM;AACpB,UAAM,SAAS,MAAM;AACnB,eAAS,cAAc,IAAI,YAAY,YAAY,CAAC;AACpD,cAAQ,IAAI;AAAA,IACd;AACA,UAAM,UAAU,MAAM,QAAQ,KAAK;AACnC,UAAM,QAAQ,CAAC,MAAqB;AAClC,UAAI,EAAE,QAAQ,SAAU,SAAQ,KAAK;AAAA,IACvC;AACA,aAAS,iBAAiB,iBAAiB,MAAM;AACjD,aAAS,iBAAiB,kBAAkB,OAAO;AACnD,aAAS,iBAAiB,aAAa,OAAO;AAC9C,aAAS,iBAAiB,cAAc,OAAO;AAC/C,aAAS,iBAAiB,WAAW,KAAK;AAC1C,WAAO,MAAM;AACX,eAAS,oBAAoB,iBAAiB,MAAM;AACpD,eAAS,oBAAoB,kBAAkB,OAAO;AACtD,eAAS,oBAAoB,aAAa,OAAO;AACjD,eAAS,oBAAoB,cAAc,OAAO;AAClD,eAAS,oBAAoB,WAAW,KAAK;AAAA,IAC/C;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SACE,oBAAC,mBACE,kBACC,iCACE;AAAA;AAAA,MAAC,OAAO;AAAA,MAAP;AAAA,QACC,WAAU;AAAA,QACV,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,SAAS,EAAE,SAAS,EAAE;AAAA,QACtB,MAAM,EAAE,SAAS,EAAE;AAAA,QACnB,YAAY,EAAE,UAAU,KAAK;AAAA,QAC7B,SAAS,MAAM,QAAQ,KAAK;AAAA;AAAA,IAC9B;AAAA,IACA;AAAA,MAAC,OAAO;AAAA,MAAP;AAAA,QACC,WAAU;AAAA,QACV,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,QAC7B,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,QAC5B,MAAM,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,QAC1B,YAAY,EAAE,UAAU,MAAM,MAAM,UAAU;AAAA,QAE9C,+BAAC,SAAI,WAAU,8HACb;AAAA,8BAAC,SAAI,WAAU,wCAAuC,eAAY,QAChE,8BAAC,UAAK,WAAU,+CAA8C,GAChE;AAAA,UACA,qBAAC,SAAI,WAAU,4DACb;AAAA,gCAAC,UAAK,WAAU,+EACb,iBACH;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS,MAAM,QAAQ,KAAK;AAAA,gBAC5B,WAAU;AAAA,gBACV,cAAW;AAAA,gBAEX,8BAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAC9G,8BAAC,UAAK,GAAE,wBAAuB,GACjC;AAAA;AAAA,YACF;AAAA,aACF;AAAA,UACA,oBAAC,SAAI,WAAU,0BAA0B,UAAS;AAAA,WACpD;AAAA;AAAA,IACF;AAAA,KACF,GAEJ;AAEJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/nav-shell.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { cn } from \"../utils/cn.js\";\n\n// ── Header buttons ────────────────────────────────────────────────────────────\n\nexport interface NavBrandButtonProps {\n /** Defaults to opening the nav command menu (`ml:nav-open`). */\n onClick?: () => void;\n className?: string;\n \"aria-label\"?: string;\n /** Path to the brand icon image (the app's real icon asset). */\n iconSrc?: string;\n}\n\n/**\n * The main header trigger: brand mark + menu glyph in one quiet glass pill.\n * Mobile-first — a single ≥44px tap target instead of two small adjacent icons.\n * With no `onClick`, it opens the NavCommandMenu mounted elsewhere in the app.\n */\nexport function NavBrandButton({ onClick, className, iconSrc = \"/icon.png\", ...rest }: NavBrandButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick ?? (() => document.dispatchEvent(new CustomEvent(ML_NAV_OPEN)))}\n aria-label={rest[\"aria-label\"] ?? \"Open navigation\"}\n className={cn(\n \"group flex h-11 items-center gap-2 rounded-full\",\n \"bg-background/10 pl-2.5 pr-3 backdrop-blur-xl backdrop-saturate-150\",\n \"transition-colors hover:bg-background/20 active:scale-[0.97]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60\",\n className\n )}\n >\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img src={iconSrc} alt=\"Medialane\" width={30} height={30} className=\"h-[30px] w-[30px] shrink-0\" />\n <span className=\"flex flex-col gap-[5px]\" aria-hidden=\"true\">\n <span className=\"h-[1.5px] w-4 rounded-full bg-muted-foreground transition-all group-hover:w-4 group-hover:bg-foreground\" />\n <span className=\"h-[1.5px] w-2.5 rounded-full bg-muted-foreground transition-all group-hover:w-4 group-hover:bg-foreground\" />\n </span>\n </button>\n );\n}\n\nexport interface NavIconButtonProps {\n onClick?: () => void;\n className?: string;\n \"aria-label\": string;\n /** Show a small brand-colored status dot (e.g. wallet connected). */\n indicator?: boolean;\n children: React.ReactNode;\n}\n\n/**\n * Circular glass header button — the right-side counterpart to NavBrandButton\n * (wallet / account trigger).\n */\nexport function NavIconButton({ onClick, className, indicator, children, ...rest }: NavIconButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={rest[\"aria-label\"]}\n className={cn(\n \"relative flex h-11 w-11 items-center justify-center rounded-full\",\n \"bg-background/10 text-muted-foreground backdrop-blur-xl backdrop-saturate-150\",\n \"transition-colors hover:bg-background/20 hover:text-foreground active:scale-[0.97]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60\",\n className\n )}\n >\n {children}\n {indicator && (\n <span className=\"absolute right-[3px] top-[3px] h-2.5 w-2.5 rounded-full border-2 border-background bg-brand-blue\" />\n )}\n </button>\n );\n}\n\n// ── Account sheet ─────────────────────────────────────────────────────────────\n\nconst ML_ACCOUNT_OPEN = \"ml:account-open\";\nconst ML_ACCOUNT_CLOSE = \"ml:account-close\";\nconst ML_NAV_OPEN = \"ml:nav-open\";\nconst ML_NAV_CLOSE = \"ml:nav-close\";\n\nexport function useNavAccountSheet() {\n return {\n open: () => document.dispatchEvent(new CustomEvent(ML_ACCOUNT_OPEN)),\n close: () => document.dispatchEvent(new CustomEvent(ML_ACCOUNT_CLOSE)),\n };\n}\n\nexport interface NavAccountSheetProps {\n /** The app's account/connect panel (Clerk, wallet connectors, …). */\n children: React.ReactNode;\n /** Optional heading above the panel. */\n title?: string;\n}\n\n/**\n * The wallet-side surface: a compact glass sheet anchored to the top-right\n * header button (bottom sheet on mobile). Content is app-owned — pass the same\n * account panel the command menu uses in its accountSlot.\n *\n * Opens via `useNavAccountSheet().open()`. Mutually exclusive with the command\n * menu: opening one closes the other, and the shared `ml:nav-close` event\n * (fired by `useNavCommandMenu().close()`) closes this sheet too, so account\n * panels behave identically in both hosts.\n */\nexport function NavAccountSheet({ children, title = \"Account\" }: NavAccountSheetProps) {\n const [open, setOpen] = React.useState(false);\n\n React.useEffect(() => {\n const onOpen = () => {\n document.dispatchEvent(new CustomEvent(ML_NAV_CLOSE));\n setOpen(true);\n };\n const onClose = () => setOpen(false);\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(ML_ACCOUNT_OPEN, onOpen);\n document.addEventListener(ML_ACCOUNT_CLOSE, onClose);\n document.addEventListener(ML_NAV_OPEN, onClose);\n document.addEventListener(ML_NAV_CLOSE, onClose);\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(ML_ACCOUNT_OPEN, onOpen);\n document.removeEventListener(ML_ACCOUNT_CLOSE, onClose);\n document.removeEventListener(ML_NAV_OPEN, onClose);\n document.removeEventListener(ML_NAV_CLOSE, onClose);\n document.removeEventListener(\"keydown\", onKey);\n };\n }, []);\n\n return (\n <AnimatePresence>\n {open && (\n <>\n <motion.div\n className=\"nav-canvas-overlay\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15 }}\n onClick={() => setOpen(false)}\n />\n <motion.div\n className=\"fixed inset-x-3 bottom-3 z-[101] sm:inset-auto sm:right-4 sm:top-4 sm:w-[360px] lg:right-8\"\n initial={{ opacity: 0, y: 24 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 24 }}\n transition={{ duration: 0.18, ease: \"easeOut\" }}\n >\n <div className=\"overflow-hidden rounded-[20px] border border-border/40 bg-background/90 shadow-2xl backdrop-blur-2xl backdrop-saturate-150\">\n <div className=\"flex justify-center pt-2.5 sm:hidden\" aria-hidden=\"true\">\n <span className=\"h-1 w-9 rounded-full bg-muted-foreground/30\" />\n </div>\n <div className=\"flex items-center justify-between px-4 pb-1 pt-2 sm:pt-3\">\n <span className=\"text-[11px] font-semibold uppercase tracking-wider text-muted-foreground/70\">\n {title}\n </span>\n <button\n onClick={() => setOpen(false)}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted/50\"\n aria-label=\"Close\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <div className=\"px-3 pb-4 pt-1 sm:pb-3\">{children}</div>\n </div>\n </motion.div>\n </>\n )}\n </AnimatePresence>\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/medialane.css
CHANGED
|
@@ -236,6 +236,38 @@ input[type="number"] { -moz-appearance: textfield; }
|
|
|
236
236
|
100% { background-position: 220% 50%; }
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
+
/* ── Collector card material (MedialaneCollectionCard) ────────────────── */
|
|
240
|
+
/* Light by default (matches the app's light-theme root, no .dark ancestor);
|
|
241
|
+
.dark overrides restore the original always-dark foil-on-navy look. The
|
|
242
|
+
frame gradient + tilt/sheen mechanics stay identical in both themes — only
|
|
243
|
+
the material color and the sheen's blend mode/highlight change, since a
|
|
244
|
+
bright white "screen" bloom that reads as a premium highlight on navy
|
|
245
|
+
would just wash out invisibly on a near-white card. */
|
|
246
|
+
.ml-card-material {
|
|
247
|
+
background:
|
|
248
|
+
radial-gradient(120% 90% at 0% 0%, rgba(59,123,255,0.07), transparent 55%),
|
|
249
|
+
radial-gradient(120% 90% at 100% 100%, rgba(251,139,70,0.06), transparent 55%),
|
|
250
|
+
#f8f9fc;
|
|
251
|
+
}
|
|
252
|
+
.dark .ml-card-material {
|
|
253
|
+
background:
|
|
254
|
+
radial-gradient(120% 90% at 0% 0%, rgba(59,123,255,0.14), transparent 55%),
|
|
255
|
+
radial-gradient(120% 90% at 100% 100%, rgba(251,139,70,0.10), transparent 55%),
|
|
256
|
+
#0a0e1f;
|
|
257
|
+
}
|
|
258
|
+
.ml-card-sheen {
|
|
259
|
+
background:
|
|
260
|
+
radial-gradient(420px circle at var(--mx, 70%) var(--my, 20%), rgba(91,76,230,0.10), transparent 45%),
|
|
261
|
+
linear-gradient(115deg, rgba(59,123,255,0.05), rgba(138,92,246,0.05) 35%, rgba(246,96,143,0.05) 65%, rgba(251,139,70,0.05));
|
|
262
|
+
mix-blend-mode: multiply;
|
|
263
|
+
}
|
|
264
|
+
.dark .ml-card-sheen {
|
|
265
|
+
background:
|
|
266
|
+
radial-gradient(420px circle at var(--mx, 70%) var(--my, 20%), rgba(255,255,255,0.20), transparent 45%),
|
|
267
|
+
linear-gradient(115deg, rgba(59,123,255,0.14), rgba(138,92,246,0.14) 35%, rgba(246,96,143,0.14) 65%, rgba(251,139,70,0.14));
|
|
268
|
+
mix-blend-mode: screen;
|
|
269
|
+
}
|
|
270
|
+
|
|
239
271
|
/* ── Action dialog keyframes ──────────────────────────────────────────── */
|
|
240
272
|
@keyframes mlFade {
|
|
241
273
|
from { opacity: 0; }
|