@medialane/ui 0.12.1 → 0.13.1
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/asset-markets-tab.cjs +111 -0
- package/dist/components/asset-markets-tab.cjs.map +1 -0
- package/dist/components/asset-markets-tab.d.cts +16 -0
- package/dist/components/asset-markets-tab.d.ts +16 -0
- package/dist/components/asset-markets-tab.js +87 -0
- package/dist/components/asset-markets-tab.js.map +1 -0
- package/dist/components/asset-overview-content.cjs +102 -0
- package/dist/components/asset-overview-content.cjs.map +1 -0
- package/dist/components/asset-overview-content.d.cts +14 -0
- package/dist/components/asset-overview-content.d.ts +14 -0
- package/dist/components/asset-overview-content.js +78 -0
- package/dist/components/asset-overview-content.js.map +1 -0
- package/dist/components/asset-top-sections.cjs +147 -0
- package/dist/components/asset-top-sections.cjs.map +1 -0
- package/dist/components/asset-top-sections.d.cts +34 -0
- package/dist/components/asset-top-sections.d.ts +34 -0
- package/dist/components/asset-top-sections.js +111 -0
- package/dist/components/asset-top-sections.js.map +1 -0
- package/dist/components/ip-type-display.cjs +201 -0
- package/dist/components/ip-type-display.cjs.map +1 -0
- package/dist/components/ip-type-display.d.cts +12 -0
- package/dist/components/ip-type-display.d.ts +12 -0
- package/dist/components/ip-type-display.js +181 -0
- package/dist/components/ip-type-display.js.map +1 -0
- package/dist/components/parent-attribution-banner.cjs +57 -0
- package/dist/components/parent-attribution-banner.cjs.map +1 -0
- package/dist/components/parent-attribution-banner.d.cts +11 -0
- package/dist/components/parent-attribution-banner.d.ts +11 -0
- package/dist/components/parent-attribution-banner.js +23 -0
- package/dist/components/parent-attribution-banner.js.map +1 -0
- package/dist/data/ip-templates.cjs +206 -0
- package/dist/data/ip-templates.cjs.map +1 -0
- package/dist/data/ip-templates.d.cts +45 -0
- package/dist/data/ip-templates.d.ts +45 -0
- package/dist/data/ip-templates.js +200 -0
- package/dist/data/ip-templates.js.map +1 -0
- package/dist/data/ip.cjs +163 -0
- package/dist/data/ip.cjs.map +1 -0
- package/dist/data/ip.d.cts +18 -0
- package/dist/data/ip.d.ts +18 -0
- package/dist/data/ip.js +134 -0
- package/dist/data/ip.js.map +1 -0
- package/dist/index.cjs +43 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +38 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/time.cjs +15 -2
- package/dist/utils/time.cjs.map +1 -1
- package/dist/utils/time.d.cts +3 -1
- package/dist/utils/time.d.ts +3 -1
- package/dist/utils/time.js +13 -1
- package/dist/utils/time.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var asset_top_sections_exports = {};
|
|
31
|
+
__export(asset_top_sections_exports, {
|
|
32
|
+
AssetHeaderBlock: () => AssetHeaderBlock,
|
|
33
|
+
AssetMediaColumn: () => AssetMediaColumn,
|
|
34
|
+
buildEditionStats: () => buildEditionStats
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(asset_top_sections_exports);
|
|
37
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
38
|
+
var import_image = __toESM(require("next/image"), 1);
|
|
39
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
40
|
+
var import_framer_motion = require("framer-motion");
|
|
41
|
+
var import_ip_type_badge = require("./ip-type-badge.js");
|
|
42
|
+
var import_address_display = require("./address-display.js");
|
|
43
|
+
var import_parent_attribution_banner = require("./parent-attribution-banner.js");
|
|
44
|
+
var import_lucide_react = require("lucide-react");
|
|
45
|
+
function AssetMediaColumn({
|
|
46
|
+
shouldReduce,
|
|
47
|
+
image,
|
|
48
|
+
imageAlt,
|
|
49
|
+
imgError,
|
|
50
|
+
onImageError,
|
|
51
|
+
fallback,
|
|
52
|
+
stats
|
|
53
|
+
}) {
|
|
54
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
55
|
+
import_framer_motion.motion.div,
|
|
56
|
+
{
|
|
57
|
+
initial: shouldReduce ? false : { scale: 1, opacity: 0 },
|
|
58
|
+
animate: { scale: 1.02, opacity: 1 },
|
|
59
|
+
transition: { duration: 0.6, ease: "easeOut" },
|
|
60
|
+
className: "overflow-hidden rounded-xl lg:sticky lg:top-16",
|
|
61
|
+
children: [
|
|
62
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rounded-2xl overflow-hidden border border-border bg-muted", children: image && !imgError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
63
|
+
import_image.default,
|
|
64
|
+
{
|
|
65
|
+
src: image,
|
|
66
|
+
alt: imageAlt,
|
|
67
|
+
width: 0,
|
|
68
|
+
height: 0,
|
|
69
|
+
sizes: "(max-width: 1024px) 100vw, 66vw",
|
|
70
|
+
className: "w-full h-auto",
|
|
71
|
+
onError: onImageError,
|
|
72
|
+
crossOrigin: "anonymous",
|
|
73
|
+
priority: true
|
|
74
|
+
}
|
|
75
|
+
) : fallback }),
|
|
76
|
+
stats && stats.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `grid gap-3 mt-4 ${stats.length === 2 ? "grid-cols-2" : "grid-cols-1"}`, children: stats.map((stat) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-xl border border-border bg-muted/20 p-4 text-center", children: [
|
|
77
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-2xl font-black", children: stat.value }),
|
|
78
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-center gap-1 text-xs text-muted-foreground mt-1", children: [
|
|
79
|
+
stat.icon,
|
|
80
|
+
stat.label
|
|
81
|
+
] })
|
|
82
|
+
] }, stat.label)) }) : null
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
function AssetHeaderBlock({
|
|
88
|
+
name,
|
|
89
|
+
description,
|
|
90
|
+
ipType,
|
|
91
|
+
showMultiEditionBadge = false,
|
|
92
|
+
parentContract,
|
|
93
|
+
parentTokenId,
|
|
94
|
+
ownerAddress
|
|
95
|
+
}) {
|
|
96
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
97
|
+
parentContract && parentTokenId ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
98
|
+
import_parent_attribution_banner.ParentAttributionBanner,
|
|
99
|
+
{
|
|
100
|
+
parentContract,
|
|
101
|
+
parentTokenId,
|
|
102
|
+
parentName: `Token #${parentTokenId}`
|
|
103
|
+
}
|
|
104
|
+
) }) : null,
|
|
105
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 flex-wrap mb-2", children: [
|
|
106
|
+
ipType ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ip_type_badge.IpTypeBadge, { ipType, size: "md" }) : null,
|
|
107
|
+
showMultiEditionBadge ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "inline-flex items-center gap-1 text-[11px] font-semibold px-2.5 py-1 rounded-full border border-violet-500/30 bg-violet-500/10 text-violet-500", children: [
|
|
108
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Layers, { className: "h-3 w-3" }),
|
|
109
|
+
"Multi-edition"
|
|
110
|
+
] }) : null
|
|
111
|
+
] }),
|
|
112
|
+
ownerAddress ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mb-1 flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
113
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-semibold uppercase tracking-wider", children: "Owner" }),
|
|
114
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
115
|
+
import_link.default,
|
|
116
|
+
{
|
|
117
|
+
href: `/creator/${ownerAddress}`,
|
|
118
|
+
className: "hover:text-primary transition-colors font-medium",
|
|
119
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_address_display.AddressDisplay, { address: ownerAddress })
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
] }) : null,
|
|
123
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "text-3xl lg:text-5xl font-bold", children: name }),
|
|
124
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground leading-relaxed mt-1", children: description }) : null
|
|
125
|
+
] });
|
|
126
|
+
}
|
|
127
|
+
function buildEditionStats(totalEditions, uniqueOwners) {
|
|
128
|
+
return [
|
|
129
|
+
{
|
|
130
|
+
value: totalEditions.toLocaleString(),
|
|
131
|
+
label: "editions minted",
|
|
132
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Layers, { className: "h-3 w-3" })
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
value: uniqueOwners.toLocaleString(),
|
|
136
|
+
label: "unique owners",
|
|
137
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Users, { className: "h-3 w-3" })
|
|
138
|
+
}
|
|
139
|
+
];
|
|
140
|
+
}
|
|
141
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
142
|
+
0 && (module.exports = {
|
|
143
|
+
AssetHeaderBlock,
|
|
144
|
+
AssetMediaColumn,
|
|
145
|
+
buildEditionStats
|
|
146
|
+
});
|
|
147
|
+
//# sourceMappingURL=asset-top-sections.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/asset-top-sections.tsx"],"sourcesContent":["\"use client\";\n\nimport Image from \"next/image\";\nimport Link from \"next/link\";\nimport { motion } from \"framer-motion\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { ParentAttributionBanner } from \"./parent-attribution-banner.js\";\nimport type { IPType } from \"../data/ip.js\";\nimport { Layers, Users } from \"lucide-react\";\n\ninterface AssetMediaColumnProps {\n shouldReduce: boolean;\n image: string;\n imageAlt: string;\n imgError: boolean;\n onImageError: () => void;\n fallback: React.ReactNode;\n stats?: Array<{\n value: string;\n label: string;\n icon: React.ReactNode;\n }>;\n}\n\nexport function AssetMediaColumn({\n shouldReduce,\n image,\n imageAlt,\n imgError,\n onImageError,\n fallback,\n stats,\n}: AssetMediaColumnProps) {\n return (\n <motion.div\n initial={shouldReduce ? false : { scale: 1.0, opacity: 0 }}\n animate={{ scale: 1.02, opacity: 1 }}\n transition={{ duration: 0.6, ease: \"easeOut\" }}\n className=\"overflow-hidden rounded-xl lg:sticky lg:top-16\"\n >\n <div className=\"rounded-2xl overflow-hidden border border-border bg-muted\">\n {image && !imgError ? (\n <Image\n src={image}\n alt={imageAlt}\n width={0}\n height={0}\n sizes=\"(max-width: 1024px) 100vw, 66vw\"\n className=\"w-full h-auto\"\n onError={onImageError}\n crossOrigin=\"anonymous\"\n priority\n />\n ) : (\n fallback\n )}\n </div>\n\n {stats && stats.length > 0 ? (\n <div className={`grid gap-3 mt-4 ${stats.length === 2 ? \"grid-cols-2\" : \"grid-cols-1\"}`}>\n {stats.map((stat) => (\n <div key={stat.label} className=\"rounded-xl border border-border bg-muted/20 p-4 text-center\">\n <p className=\"text-2xl font-black\">{stat.value}</p>\n <div className=\"flex items-center justify-center gap-1 text-xs text-muted-foreground mt-1\">\n {stat.icon}\n {stat.label}\n </div>\n </div>\n ))}\n </div>\n ) : null}\n </motion.div>\n );\n}\n\ninterface AssetHeaderBlockProps {\n name: string;\n description?: string | null;\n ipType?: IPType | string | null;\n showMultiEditionBadge?: boolean;\n parentContract?: string | null;\n parentTokenId?: string | null;\n ownerAddress?: string | null;\n}\n\nexport function AssetHeaderBlock({\n name,\n description,\n ipType,\n showMultiEditionBadge = false,\n parentContract,\n parentTokenId,\n ownerAddress,\n}: AssetHeaderBlockProps) {\n return (\n <div>\n {parentContract && parentTokenId ? (\n <div className=\"mb-3\">\n <ParentAttributionBanner\n parentContract={parentContract}\n parentTokenId={parentTokenId}\n parentName={`Token #${parentTokenId}`}\n />\n </div>\n ) : null}\n <div className=\"flex items-center gap-2 flex-wrap mb-2\">\n {ipType ? <IpTypeBadge ipType={ipType} size=\"md\" /> : null}\n {showMultiEditionBadge ? (\n <span className=\"inline-flex items-center gap-1 text-[11px] font-semibold px-2.5 py-1 rounded-full border border-violet-500/30 bg-violet-500/10 text-violet-500\">\n <Layers className=\"h-3 w-3\" />\n Multi-edition\n </span>\n ) : null}\n </div>\n {ownerAddress ? (\n <div className=\"mb-1 flex items-center gap-1.5 text-xs text-muted-foreground\">\n <span className=\"font-semibold uppercase tracking-wider\">Owner</span>\n <Link\n href={`/creator/${ownerAddress}`}\n className=\"hover:text-primary transition-colors font-medium\"\n >\n <AddressDisplay address={ownerAddress} />\n </Link>\n </div>\n ) : null}\n <h1 className=\"text-3xl lg:text-5xl font-bold\">{name}</h1>\n {description ? (\n <p className=\"text-sm text-muted-foreground leading-relaxed mt-1\">{description}</p>\n ) : null}\n </div>\n );\n}\n\nexport function buildEditionStats(totalEditions: number, uniqueOwners: number) {\n return [\n {\n value: totalEditions.toLocaleString(),\n label: \"editions minted\",\n icon: <Layers className=\"h-3 w-3\" />,\n },\n {\n value: uniqueOwners.toLocaleString(),\n label: \"unique owners\",\n icon: <Users className=\"h-3 w-3\" />,\n },\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2CU;AAzCV,mBAAkB;AAClB,kBAAiB;AACjB,2BAAuB;AACvB,2BAA4B;AAC5B,6BAA+B;AAC/B,uCAAwC;AAExC,0BAA8B;AAgBvB,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,SACE;AAAA,IAAC,4BAAO;AAAA,IAAP;AAAA,MACC,SAAS,eAAe,QAAQ,EAAE,OAAO,GAAK,SAAS,EAAE;AAAA,MACzD,SAAS,EAAE,OAAO,MAAM,SAAS,EAAE;AAAA,MACnC,YAAY,EAAE,UAAU,KAAK,MAAM,UAAU;AAAA,MAC7C,WAAU;AAAA,MAEV;AAAA,oDAAC,SAAI,WAAU,6DACZ,mBAAS,CAAC,WACT;AAAA,UAAC,aAAAA;AAAA,UAAA;AAAA,YACC,KAAK;AAAA,YACL,KAAK;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,OAAM;AAAA,YACN,WAAU;AAAA,YACV,SAAS;AAAA,YACT,aAAY;AAAA,YACZ,UAAQ;AAAA;AAAA,QACV,IAEA,UAEJ;AAAA,QAEC,SAAS,MAAM,SAAS,IACvB,4CAAC,SAAI,WAAW,mBAAmB,MAAM,WAAW,IAAI,gBAAgB,aAAa,IAClF,gBAAM,IAAI,CAAC,SACV,6CAAC,SAAqB,WAAU,+DAC9B;AAAA,sDAAC,OAAE,WAAU,uBAAuB,eAAK,OAAM;AAAA,UAC/C,6CAAC,SAAI,WAAU,6EACZ;AAAA,iBAAK;AAAA,YACL,KAAK;AAAA,aACR;AAAA,aALQ,KAAK,KAMf,CACD,GACH,IACE;AAAA;AAAA;AAAA,EACN;AAEJ;AAYO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA,wBAAwB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,SACE,6CAAC,SACE;AAAA,sBAAkB,gBACjB,4CAAC,SAAI,WAAU,QACb;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,YAAY,UAAU,aAAa;AAAA;AAAA,IACrC,GACF,IACE;AAAA,IACJ,6CAAC,SAAI,WAAU,0CACZ;AAAA,eAAS,4CAAC,oCAAY,QAAgB,MAAK,MAAK,IAAK;AAAA,MACrD,wBACC,6CAAC,UAAK,WAAU,kJACd;AAAA,oDAAC,8BAAO,WAAU,WAAU;AAAA,QAAE;AAAA,SAEhC,IACE;AAAA,OACN;AAAA,IACC,eACC,6CAAC,SAAI,WAAU,gEACb;AAAA,kDAAC,UAAK,WAAU,0CAAyC,mBAAK;AAAA,MAC9D;AAAA,QAAC,YAAAC;AAAA,QAAA;AAAA,UACC,MAAM,YAAY,YAAY;AAAA,UAC9B,WAAU;AAAA,UAEV,sDAAC,yCAAe,SAAS,cAAc;AAAA;AAAA,MACzC;AAAA,OACF,IACE;AAAA,IACJ,4CAAC,QAAG,WAAU,kCAAkC,gBAAK;AAAA,IACpD,cACC,4CAAC,OAAE,WAAU,sDAAsD,uBAAY,IAC7E;AAAA,KACN;AAEJ;AAEO,SAAS,kBAAkB,eAAuB,cAAsB;AAC7E,SAAO;AAAA,IACL;AAAA,MACE,OAAO,cAAc,eAAe;AAAA,MACpC,OAAO;AAAA,MACP,MAAM,4CAAC,8BAAO,WAAU,WAAU;AAAA,IACpC;AAAA,IACA;AAAA,MACE,OAAO,aAAa,eAAe;AAAA,MACnC,OAAO;AAAA,MACP,MAAM,4CAAC,6BAAM,WAAU,WAAU;AAAA,IACnC;AAAA,EACF;AACF;","names":["Image","Link"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { IPType } from '../data/ip.cjs';
|
|
3
|
+
|
|
4
|
+
interface AssetMediaColumnProps {
|
|
5
|
+
shouldReduce: boolean;
|
|
6
|
+
image: string;
|
|
7
|
+
imageAlt: string;
|
|
8
|
+
imgError: boolean;
|
|
9
|
+
onImageError: () => void;
|
|
10
|
+
fallback: React.ReactNode;
|
|
11
|
+
stats?: Array<{
|
|
12
|
+
value: string;
|
|
13
|
+
label: string;
|
|
14
|
+
icon: React.ReactNode;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
declare function AssetMediaColumn({ shouldReduce, image, imageAlt, imgError, onImageError, fallback, stats, }: AssetMediaColumnProps): react_jsx_runtime.JSX.Element;
|
|
18
|
+
interface AssetHeaderBlockProps {
|
|
19
|
+
name: string;
|
|
20
|
+
description?: string | null;
|
|
21
|
+
ipType?: IPType | string | null;
|
|
22
|
+
showMultiEditionBadge?: boolean;
|
|
23
|
+
parentContract?: string | null;
|
|
24
|
+
parentTokenId?: string | null;
|
|
25
|
+
ownerAddress?: string | null;
|
|
26
|
+
}
|
|
27
|
+
declare function AssetHeaderBlock({ name, description, ipType, showMultiEditionBadge, parentContract, parentTokenId, ownerAddress, }: AssetHeaderBlockProps): react_jsx_runtime.JSX.Element;
|
|
28
|
+
declare function buildEditionStats(totalEditions: number, uniqueOwners: number): {
|
|
29
|
+
value: string;
|
|
30
|
+
label: string;
|
|
31
|
+
icon: react_jsx_runtime.JSX.Element;
|
|
32
|
+
}[];
|
|
33
|
+
|
|
34
|
+
export { AssetHeaderBlock, AssetMediaColumn, buildEditionStats };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { IPType } from '../data/ip.js';
|
|
3
|
+
|
|
4
|
+
interface AssetMediaColumnProps {
|
|
5
|
+
shouldReduce: boolean;
|
|
6
|
+
image: string;
|
|
7
|
+
imageAlt: string;
|
|
8
|
+
imgError: boolean;
|
|
9
|
+
onImageError: () => void;
|
|
10
|
+
fallback: React.ReactNode;
|
|
11
|
+
stats?: Array<{
|
|
12
|
+
value: string;
|
|
13
|
+
label: string;
|
|
14
|
+
icon: React.ReactNode;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
declare function AssetMediaColumn({ shouldReduce, image, imageAlt, imgError, onImageError, fallback, stats, }: AssetMediaColumnProps): react_jsx_runtime.JSX.Element;
|
|
18
|
+
interface AssetHeaderBlockProps {
|
|
19
|
+
name: string;
|
|
20
|
+
description?: string | null;
|
|
21
|
+
ipType?: IPType | string | null;
|
|
22
|
+
showMultiEditionBadge?: boolean;
|
|
23
|
+
parentContract?: string | null;
|
|
24
|
+
parentTokenId?: string | null;
|
|
25
|
+
ownerAddress?: string | null;
|
|
26
|
+
}
|
|
27
|
+
declare function AssetHeaderBlock({ name, description, ipType, showMultiEditionBadge, parentContract, parentTokenId, ownerAddress, }: AssetHeaderBlockProps): react_jsx_runtime.JSX.Element;
|
|
28
|
+
declare function buildEditionStats(totalEditions: number, uniqueOwners: number): {
|
|
29
|
+
value: string;
|
|
30
|
+
label: string;
|
|
31
|
+
icon: react_jsx_runtime.JSX.Element;
|
|
32
|
+
}[];
|
|
33
|
+
|
|
34
|
+
export { AssetHeaderBlock, AssetMediaColumn, buildEditionStats };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import Image from "next/image";
|
|
4
|
+
import Link from "next/link";
|
|
5
|
+
import { motion } from "framer-motion";
|
|
6
|
+
import { IpTypeBadge } from "./ip-type-badge.js";
|
|
7
|
+
import { AddressDisplay } from "./address-display.js";
|
|
8
|
+
import { ParentAttributionBanner } from "./parent-attribution-banner.js";
|
|
9
|
+
import { Layers, Users } from "lucide-react";
|
|
10
|
+
function AssetMediaColumn({
|
|
11
|
+
shouldReduce,
|
|
12
|
+
image,
|
|
13
|
+
imageAlt,
|
|
14
|
+
imgError,
|
|
15
|
+
onImageError,
|
|
16
|
+
fallback,
|
|
17
|
+
stats
|
|
18
|
+
}) {
|
|
19
|
+
return /* @__PURE__ */ jsxs(
|
|
20
|
+
motion.div,
|
|
21
|
+
{
|
|
22
|
+
initial: shouldReduce ? false : { scale: 1, opacity: 0 },
|
|
23
|
+
animate: { scale: 1.02, opacity: 1 },
|
|
24
|
+
transition: { duration: 0.6, ease: "easeOut" },
|
|
25
|
+
className: "overflow-hidden rounded-xl lg:sticky lg:top-16",
|
|
26
|
+
children: [
|
|
27
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-2xl overflow-hidden border border-border bg-muted", children: image && !imgError ? /* @__PURE__ */ jsx(
|
|
28
|
+
Image,
|
|
29
|
+
{
|
|
30
|
+
src: image,
|
|
31
|
+
alt: imageAlt,
|
|
32
|
+
width: 0,
|
|
33
|
+
height: 0,
|
|
34
|
+
sizes: "(max-width: 1024px) 100vw, 66vw",
|
|
35
|
+
className: "w-full h-auto",
|
|
36
|
+
onError: onImageError,
|
|
37
|
+
crossOrigin: "anonymous",
|
|
38
|
+
priority: true
|
|
39
|
+
}
|
|
40
|
+
) : fallback }),
|
|
41
|
+
stats && stats.length > 0 ? /* @__PURE__ */ jsx("div", { className: `grid gap-3 mt-4 ${stats.length === 2 ? "grid-cols-2" : "grid-cols-1"}`, children: stats.map((stat) => /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border bg-muted/20 p-4 text-center", children: [
|
|
42
|
+
/* @__PURE__ */ jsx("p", { className: "text-2xl font-black", children: stat.value }),
|
|
43
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1 text-xs text-muted-foreground mt-1", children: [
|
|
44
|
+
stat.icon,
|
|
45
|
+
stat.label
|
|
46
|
+
] })
|
|
47
|
+
] }, stat.label)) }) : null
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
function AssetHeaderBlock({
|
|
53
|
+
name,
|
|
54
|
+
description,
|
|
55
|
+
ipType,
|
|
56
|
+
showMultiEditionBadge = false,
|
|
57
|
+
parentContract,
|
|
58
|
+
parentTokenId,
|
|
59
|
+
ownerAddress
|
|
60
|
+
}) {
|
|
61
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
62
|
+
parentContract && parentTokenId ? /* @__PURE__ */ jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsx(
|
|
63
|
+
ParentAttributionBanner,
|
|
64
|
+
{
|
|
65
|
+
parentContract,
|
|
66
|
+
parentTokenId,
|
|
67
|
+
parentName: `Token #${parentTokenId}`
|
|
68
|
+
}
|
|
69
|
+
) }) : null,
|
|
70
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap mb-2", children: [
|
|
71
|
+
ipType ? /* @__PURE__ */ jsx(IpTypeBadge, { ipType, size: "md" }) : null,
|
|
72
|
+
showMultiEditionBadge ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-[11px] font-semibold px-2.5 py-1 rounded-full border border-violet-500/30 bg-violet-500/10 text-violet-500", children: [
|
|
73
|
+
/* @__PURE__ */ jsx(Layers, { className: "h-3 w-3" }),
|
|
74
|
+
"Multi-edition"
|
|
75
|
+
] }) : null
|
|
76
|
+
] }),
|
|
77
|
+
ownerAddress ? /* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
78
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold uppercase tracking-wider", children: "Owner" }),
|
|
79
|
+
/* @__PURE__ */ jsx(
|
|
80
|
+
Link,
|
|
81
|
+
{
|
|
82
|
+
href: `/creator/${ownerAddress}`,
|
|
83
|
+
className: "hover:text-primary transition-colors font-medium",
|
|
84
|
+
children: /* @__PURE__ */ jsx(AddressDisplay, { address: ownerAddress })
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
] }) : null,
|
|
88
|
+
/* @__PURE__ */ jsx("h1", { className: "text-3xl lg:text-5xl font-bold", children: name }),
|
|
89
|
+
description ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground leading-relaxed mt-1", children: description }) : null
|
|
90
|
+
] });
|
|
91
|
+
}
|
|
92
|
+
function buildEditionStats(totalEditions, uniqueOwners) {
|
|
93
|
+
return [
|
|
94
|
+
{
|
|
95
|
+
value: totalEditions.toLocaleString(),
|
|
96
|
+
label: "editions minted",
|
|
97
|
+
icon: /* @__PURE__ */ jsx(Layers, { className: "h-3 w-3" })
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
value: uniqueOwners.toLocaleString(),
|
|
101
|
+
label: "unique owners",
|
|
102
|
+
icon: /* @__PURE__ */ jsx(Users, { className: "h-3 w-3" })
|
|
103
|
+
}
|
|
104
|
+
];
|
|
105
|
+
}
|
|
106
|
+
export {
|
|
107
|
+
AssetHeaderBlock,
|
|
108
|
+
AssetMediaColumn,
|
|
109
|
+
buildEditionStats
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=asset-top-sections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/asset-top-sections.tsx"],"sourcesContent":["\"use client\";\n\nimport Image from \"next/image\";\nimport Link from \"next/link\";\nimport { motion } from \"framer-motion\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { ParentAttributionBanner } from \"./parent-attribution-banner.js\";\nimport type { IPType } from \"../data/ip.js\";\nimport { Layers, Users } from \"lucide-react\";\n\ninterface AssetMediaColumnProps {\n shouldReduce: boolean;\n image: string;\n imageAlt: string;\n imgError: boolean;\n onImageError: () => void;\n fallback: React.ReactNode;\n stats?: Array<{\n value: string;\n label: string;\n icon: React.ReactNode;\n }>;\n}\n\nexport function AssetMediaColumn({\n shouldReduce,\n image,\n imageAlt,\n imgError,\n onImageError,\n fallback,\n stats,\n}: AssetMediaColumnProps) {\n return (\n <motion.div\n initial={shouldReduce ? false : { scale: 1.0, opacity: 0 }}\n animate={{ scale: 1.02, opacity: 1 }}\n transition={{ duration: 0.6, ease: \"easeOut\" }}\n className=\"overflow-hidden rounded-xl lg:sticky lg:top-16\"\n >\n <div className=\"rounded-2xl overflow-hidden border border-border bg-muted\">\n {image && !imgError ? (\n <Image\n src={image}\n alt={imageAlt}\n width={0}\n height={0}\n sizes=\"(max-width: 1024px) 100vw, 66vw\"\n className=\"w-full h-auto\"\n onError={onImageError}\n crossOrigin=\"anonymous\"\n priority\n />\n ) : (\n fallback\n )}\n </div>\n\n {stats && stats.length > 0 ? (\n <div className={`grid gap-3 mt-4 ${stats.length === 2 ? \"grid-cols-2\" : \"grid-cols-1\"}`}>\n {stats.map((stat) => (\n <div key={stat.label} className=\"rounded-xl border border-border bg-muted/20 p-4 text-center\">\n <p className=\"text-2xl font-black\">{stat.value}</p>\n <div className=\"flex items-center justify-center gap-1 text-xs text-muted-foreground mt-1\">\n {stat.icon}\n {stat.label}\n </div>\n </div>\n ))}\n </div>\n ) : null}\n </motion.div>\n );\n}\n\ninterface AssetHeaderBlockProps {\n name: string;\n description?: string | null;\n ipType?: IPType | string | null;\n showMultiEditionBadge?: boolean;\n parentContract?: string | null;\n parentTokenId?: string | null;\n ownerAddress?: string | null;\n}\n\nexport function AssetHeaderBlock({\n name,\n description,\n ipType,\n showMultiEditionBadge = false,\n parentContract,\n parentTokenId,\n ownerAddress,\n}: AssetHeaderBlockProps) {\n return (\n <div>\n {parentContract && parentTokenId ? (\n <div className=\"mb-3\">\n <ParentAttributionBanner\n parentContract={parentContract}\n parentTokenId={parentTokenId}\n parentName={`Token #${parentTokenId}`}\n />\n </div>\n ) : null}\n <div className=\"flex items-center gap-2 flex-wrap mb-2\">\n {ipType ? <IpTypeBadge ipType={ipType} size=\"md\" /> : null}\n {showMultiEditionBadge ? (\n <span className=\"inline-flex items-center gap-1 text-[11px] font-semibold px-2.5 py-1 rounded-full border border-violet-500/30 bg-violet-500/10 text-violet-500\">\n <Layers className=\"h-3 w-3\" />\n Multi-edition\n </span>\n ) : null}\n </div>\n {ownerAddress ? (\n <div className=\"mb-1 flex items-center gap-1.5 text-xs text-muted-foreground\">\n <span className=\"font-semibold uppercase tracking-wider\">Owner</span>\n <Link\n href={`/creator/${ownerAddress}`}\n className=\"hover:text-primary transition-colors font-medium\"\n >\n <AddressDisplay address={ownerAddress} />\n </Link>\n </div>\n ) : null}\n <h1 className=\"text-3xl lg:text-5xl font-bold\">{name}</h1>\n {description ? (\n <p className=\"text-sm text-muted-foreground leading-relaxed mt-1\">{description}</p>\n ) : null}\n </div>\n );\n}\n\nexport function buildEditionStats(totalEditions: number, uniqueOwners: number) {\n return [\n {\n value: totalEditions.toLocaleString(),\n label: \"editions minted\",\n icon: <Layers className=\"h-3 w-3\" />,\n },\n {\n value: uniqueOwners.toLocaleString(),\n label: \"unique owners\",\n icon: <Users className=\"h-3 w-3\" />,\n },\n ];\n}\n"],"mappings":";AA2CU,cAqBI,YArBJ;AAzCV,OAAO,WAAW;AAClB,OAAO,UAAU;AACjB,SAAS,cAAc;AACvB,SAAS,mBAAmB;AAC5B,SAAS,sBAAsB;AAC/B,SAAS,+BAA+B;AAExC,SAAS,QAAQ,aAAa;AAgBvB,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,SACE;AAAA,IAAC,OAAO;AAAA,IAAP;AAAA,MACC,SAAS,eAAe,QAAQ,EAAE,OAAO,GAAK,SAAS,EAAE;AAAA,MACzD,SAAS,EAAE,OAAO,MAAM,SAAS,EAAE;AAAA,MACnC,YAAY,EAAE,UAAU,KAAK,MAAM,UAAU;AAAA,MAC7C,WAAU;AAAA,MAEV;AAAA,4BAAC,SAAI,WAAU,6DACZ,mBAAS,CAAC,WACT;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,KAAK;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,OAAM;AAAA,YACN,WAAU;AAAA,YACV,SAAS;AAAA,YACT,aAAY;AAAA,YACZ,UAAQ;AAAA;AAAA,QACV,IAEA,UAEJ;AAAA,QAEC,SAAS,MAAM,SAAS,IACvB,oBAAC,SAAI,WAAW,mBAAmB,MAAM,WAAW,IAAI,gBAAgB,aAAa,IAClF,gBAAM,IAAI,CAAC,SACV,qBAAC,SAAqB,WAAU,+DAC9B;AAAA,8BAAC,OAAE,WAAU,uBAAuB,eAAK,OAAM;AAAA,UAC/C,qBAAC,SAAI,WAAU,6EACZ;AAAA,iBAAK;AAAA,YACL,KAAK;AAAA,aACR;AAAA,aALQ,KAAK,KAMf,CACD,GACH,IACE;AAAA;AAAA;AAAA,EACN;AAEJ;AAYO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA,wBAAwB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,SACE,qBAAC,SACE;AAAA,sBAAkB,gBACjB,oBAAC,SAAI,WAAU,QACb;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,YAAY,UAAU,aAAa;AAAA;AAAA,IACrC,GACF,IACE;AAAA,IACJ,qBAAC,SAAI,WAAU,0CACZ;AAAA,eAAS,oBAAC,eAAY,QAAgB,MAAK,MAAK,IAAK;AAAA,MACrD,wBACC,qBAAC,UAAK,WAAU,kJACd;AAAA,4BAAC,UAAO,WAAU,WAAU;AAAA,QAAE;AAAA,SAEhC,IACE;AAAA,OACN;AAAA,IACC,eACC,qBAAC,SAAI,WAAU,gEACb;AAAA,0BAAC,UAAK,WAAU,0CAAyC,mBAAK;AAAA,MAC9D;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,YAAY,YAAY;AAAA,UAC9B,WAAU;AAAA,UAEV,8BAAC,kBAAe,SAAS,cAAc;AAAA;AAAA,MACzC;AAAA,OACF,IACE;AAAA,IACJ,oBAAC,QAAG,WAAU,kCAAkC,gBAAK;AAAA,IACpD,cACC,oBAAC,OAAE,WAAU,sDAAsD,uBAAY,IAC7E;AAAA,KACN;AAEJ;AAEO,SAAS,kBAAkB,eAAuB,cAAsB;AAC7E,SAAO;AAAA,IACL;AAAA,MACE,OAAO,cAAc,eAAe;AAAA,MACpC,OAAO;AAAA,MACP,MAAM,oBAAC,UAAO,WAAU,WAAU;AAAA,IACpC;AAAA,IACA;AAAA,MACE,OAAO,aAAa,eAAe;AAAA,MACnC,OAAO;AAAA,MACP,MAAM,oBAAC,SAAM,WAAU,WAAU;AAAA,IACnC;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var ip_type_display_exports = {};
|
|
21
|
+
__export(ip_type_display_exports, {
|
|
22
|
+
IPTypeDisplay: () => IPTypeDisplay
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(ip_type_display_exports);
|
|
25
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
26
|
+
var import_ip_templates = require("../data/ip-templates.js");
|
|
27
|
+
var import_lucide_react = require("lucide-react");
|
|
28
|
+
function parseYouTubeEmbed(url) {
|
|
29
|
+
try {
|
|
30
|
+
const u = new URL(url);
|
|
31
|
+
let id = null;
|
|
32
|
+
if (u.hostname.includes("youtu.be")) {
|
|
33
|
+
id = u.pathname.slice(1);
|
|
34
|
+
} else if (u.hostname.includes("youtube.com")) {
|
|
35
|
+
id = u.searchParams.get("v");
|
|
36
|
+
}
|
|
37
|
+
if (!id) return null;
|
|
38
|
+
return `https://www.youtube.com/embed/${id}`;
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function parseSpotifyEmbed(url) {
|
|
44
|
+
try {
|
|
45
|
+
const u = new URL(url);
|
|
46
|
+
if (!u.hostname.includes("spotify.com")) return null;
|
|
47
|
+
const match = u.pathname.match(
|
|
48
|
+
/(track|album|playlist|episode|show|artist)\/([A-Za-z0-9]+)/
|
|
49
|
+
);
|
|
50
|
+
if (!match) return null;
|
|
51
|
+
return `https://open.spotify.com/embed/${match[1]}/${match[2]}`;
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function parseSoundCloudEmbed(url) {
|
|
57
|
+
try {
|
|
58
|
+
new URL(url);
|
|
59
|
+
if (!url.includes("soundcloud.com")) return null;
|
|
60
|
+
const encoded = encodeURIComponent(url);
|
|
61
|
+
return `https://w.soundcloud.com/player/?url=${encoded}&color=%23ff5500&auto_play=false&hide_related=true&show_comments=false&show_user=true&show_reposts=false`;
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function parseTikTokEmbed(url) {
|
|
67
|
+
try {
|
|
68
|
+
const u = new URL(url);
|
|
69
|
+
if (!u.hostname.includes("tiktok.com")) return null;
|
|
70
|
+
const match = u.pathname.match(/\/video\/(\d+)/);
|
|
71
|
+
if (!match) return null;
|
|
72
|
+
return `https://www.tiktok.com/embed/v2/${match[1]}`;
|
|
73
|
+
} catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function parseVimeoEmbed(url) {
|
|
78
|
+
try {
|
|
79
|
+
const u = new URL(url);
|
|
80
|
+
if (!u.hostname.includes("vimeo.com")) return null;
|
|
81
|
+
const match = u.pathname.match(/(\d+)/);
|
|
82
|
+
if (!match) return null;
|
|
83
|
+
return `https://player.vimeo.com/video/${match[1]}`;
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function getEmbedSrc(platform, value) {
|
|
89
|
+
switch (platform) {
|
|
90
|
+
case "youtube":
|
|
91
|
+
return parseYouTubeEmbed(value);
|
|
92
|
+
case "spotify":
|
|
93
|
+
return parseSpotifyEmbed(value);
|
|
94
|
+
case "soundcloud":
|
|
95
|
+
return parseSoundCloudEmbed(value);
|
|
96
|
+
case "tiktok":
|
|
97
|
+
return parseTikTokEmbed(value);
|
|
98
|
+
case "vimeo":
|
|
99
|
+
return parseVimeoEmbed(value);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const COMPACT = {
|
|
103
|
+
spotify: true,
|
|
104
|
+
soundcloud: true,
|
|
105
|
+
youtube: false,
|
|
106
|
+
tiktok: false,
|
|
107
|
+
vimeo: false
|
|
108
|
+
};
|
|
109
|
+
function IPTypeDisplay({ attributes }) {
|
|
110
|
+
const attrs = attributes ?? [];
|
|
111
|
+
const ipType = attrs.find(
|
|
112
|
+
(a) => a.trait_type?.toLowerCase() === "ip type"
|
|
113
|
+
)?.value;
|
|
114
|
+
if (!ipType) return null;
|
|
115
|
+
const template = import_ip_templates.IP_TEMPLATES[ipType];
|
|
116
|
+
if (!template) return null;
|
|
117
|
+
const getAttr = (key) => attrs.find((a) => a.trait_type === key)?.value ?? null;
|
|
118
|
+
const embeds = (template.embeds ?? []).flatMap((platform) => {
|
|
119
|
+
const meta = import_ip_templates.EMBED_PLATFORM_META[platform];
|
|
120
|
+
const value = getAttr(meta.traitKey);
|
|
121
|
+
return value ? [{ platform, meta, value }] : [];
|
|
122
|
+
});
|
|
123
|
+
const socials = (template.socials ?? []).flatMap((platform) => {
|
|
124
|
+
const meta = import_ip_templates.SOCIAL_PLATFORM_META[platform];
|
|
125
|
+
const value = getAttr(meta.traitKey);
|
|
126
|
+
return value ? [{ platform, meta, value }] : [];
|
|
127
|
+
});
|
|
128
|
+
if (embeds.length === 0 && socials.length === 0) return null;
|
|
129
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-5", children: [
|
|
130
|
+
embeds.map(({ platform, meta, value }) => {
|
|
131
|
+
const src = getEmbedSrc(platform, value);
|
|
132
|
+
if (src) {
|
|
133
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
|
|
134
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs font-semibold uppercase tracking-wider text-muted-foreground", children: meta.label }),
|
|
135
|
+
COMPACT[platform] ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
136
|
+
"iframe",
|
|
137
|
+
{
|
|
138
|
+
src,
|
|
139
|
+
className: "w-full rounded-xl border-0",
|
|
140
|
+
height: 166,
|
|
141
|
+
allow: "autoplay",
|
|
142
|
+
loading: "lazy",
|
|
143
|
+
title: meta.label
|
|
144
|
+
}
|
|
145
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "relative w-full aspect-video rounded-xl overflow-hidden bg-muted/20", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
146
|
+
"iframe",
|
|
147
|
+
{
|
|
148
|
+
src,
|
|
149
|
+
className: "absolute inset-0 w-full h-full",
|
|
150
|
+
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
|
|
151
|
+
allowFullScreen: true,
|
|
152
|
+
loading: "lazy",
|
|
153
|
+
title: meta.label
|
|
154
|
+
}
|
|
155
|
+
) })
|
|
156
|
+
] }, platform);
|
|
157
|
+
}
|
|
158
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
159
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-1", children: meta.label }),
|
|
160
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
161
|
+
"a",
|
|
162
|
+
{
|
|
163
|
+
href: value,
|
|
164
|
+
target: "_blank",
|
|
165
|
+
rel: "noopener noreferrer",
|
|
166
|
+
className: "inline-flex items-center gap-1.5 text-sm text-primary hover:underline",
|
|
167
|
+
children: [
|
|
168
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ExternalLink, { className: "h-3.5 w-3.5" }),
|
|
169
|
+
"Open link"
|
|
170
|
+
]
|
|
171
|
+
}
|
|
172
|
+
)
|
|
173
|
+
] }, platform);
|
|
174
|
+
}),
|
|
175
|
+
socials.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
|
|
176
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs font-semibold uppercase tracking-wider text-muted-foreground", children: "Links" }),
|
|
177
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-wrap gap-2", children: socials.map(({ platform, meta, value }) => {
|
|
178
|
+
const SIcon = meta.icon;
|
|
179
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
180
|
+
"a",
|
|
181
|
+
{
|
|
182
|
+
href: value,
|
|
183
|
+
target: "_blank",
|
|
184
|
+
rel: "noopener noreferrer",
|
|
185
|
+
className: "inline-flex items-center gap-1.5 rounded-full border border-border bg-muted/30 px-3 py-1.5 text-xs font-medium text-muted-foreground transition-colors hover:border-primary/40 hover:text-foreground",
|
|
186
|
+
children: [
|
|
187
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SIcon, { className: "h-3.5 w-3.5" }),
|
|
188
|
+
meta.label
|
|
189
|
+
]
|
|
190
|
+
},
|
|
191
|
+
platform
|
|
192
|
+
);
|
|
193
|
+
}) })
|
|
194
|
+
] })
|
|
195
|
+
] });
|
|
196
|
+
}
|
|
197
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
198
|
+
0 && (module.exports = {
|
|
199
|
+
IPTypeDisplay
|
|
200
|
+
});
|
|
201
|
+
//# sourceMappingURL=ip-type-display.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/ip-type-display.tsx"],"sourcesContent":["\"use client\";\n\nimport type { IPType } from \"../data/ip.js\";\nimport {\n IP_TEMPLATES,\n EMBED_PLATFORM_META,\n SOCIAL_PLATFORM_META,\n type EmbedPlatform,\n} from \"../data/ip-templates.js\";\nimport { ExternalLink } from \"lucide-react\";\n\ninterface Attr {\n trait_type?: string | null;\n value?: string | null;\n}\n\ninterface IPTypeDisplayProps {\n attributes: Attr[] | null | undefined;\n}\n\n// ── Embed URL parsers ────────────────────────────────────────────────────────\n\nfunction parseYouTubeEmbed(url: string): string | null {\n try {\n const u = new URL(url);\n let id: string | null = null;\n if (u.hostname.includes(\"youtu.be\")) {\n id = u.pathname.slice(1);\n } else if (u.hostname.includes(\"youtube.com\")) {\n id = u.searchParams.get(\"v\");\n }\n if (!id) return null;\n return `https://www.youtube.com/embed/${id}`;\n } catch {\n return null;\n }\n}\n\nfunction parseSpotifyEmbed(url: string): string | null {\n try {\n const u = new URL(url);\n if (!u.hostname.includes(\"spotify.com\")) return null;\n // Spotify's embed endpoint only accepts /embed/{type}/{id}. Isolate the\n // resource type + id so locale prefixes (e.g. /intl-pt) and trailing query\n // params don't leak through — `/embed/intl-pt/album/…` 404s on Spotify.\n const match = u.pathname.match(\n /(track|album|playlist|episode|show|artist)\\/([A-Za-z0-9]+)/\n );\n if (!match) return null;\n return `https://open.spotify.com/embed/${match[1]}/${match[2]}`;\n } catch {\n return null;\n }\n}\n\nfunction parseSoundCloudEmbed(url: string): string | null {\n try {\n new URL(url); // validate\n if (!url.includes(\"soundcloud.com\")) return null;\n const encoded = encodeURIComponent(url);\n return `https://w.soundcloud.com/player/?url=${encoded}&color=%23ff5500&auto_play=false&hide_related=true&show_comments=false&show_user=true&show_reposts=false`;\n } catch {\n return null;\n }\n}\n\nfunction parseTikTokEmbed(url: string): string | null {\n try {\n const u = new URL(url);\n if (!u.hostname.includes(\"tiktok.com\")) return null;\n const match = u.pathname.match(/\\/video\\/(\\d+)/);\n if (!match) return null;\n return `https://www.tiktok.com/embed/v2/${match[1]}`;\n } catch {\n return null;\n }\n}\n\nfunction parseVimeoEmbed(url: string): string | null {\n try {\n const u = new URL(url);\n if (!u.hostname.includes(\"vimeo.com\")) return null;\n const match = u.pathname.match(/(\\d+)/);\n if (!match) return null;\n return `https://player.vimeo.com/video/${match[1]}`;\n } catch {\n return null;\n }\n}\n\nfunction getEmbedSrc(platform: EmbedPlatform, value: string): string | null {\n switch (platform) {\n case \"youtube\": return parseYouTubeEmbed(value);\n case \"spotify\": return parseSpotifyEmbed(value);\n case \"soundcloud\": return parseSoundCloudEmbed(value);\n case \"tiktok\": return parseTikTokEmbed(value);\n case \"vimeo\": return parseVimeoEmbed(value);\n }\n}\n\n// Compact iframe (fixed height) vs 16:9 video frame.\nconst COMPACT: Record<EmbedPlatform, boolean> = {\n spotify: true,\n soundcloud: true,\n youtube: false,\n tiktok: false,\n vimeo: false,\n};\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport function IPTypeDisplay({ attributes }: IPTypeDisplayProps) {\n const attrs = attributes ?? [];\n\n const ipType = attrs.find(\n (a) => a.trait_type?.toLowerCase() === \"ip type\"\n )?.value as IPType | undefined;\n if (!ipType) return null;\n\n const template = IP_TEMPLATES[ipType];\n if (!template) return null;\n\n const getAttr = (key: string) =>\n attrs.find((a) => a.trait_type === key)?.value ?? null;\n\n const embeds = (template.embeds ?? []).flatMap((platform) => {\n const meta = EMBED_PLATFORM_META[platform];\n const value = getAttr(meta.traitKey);\n return value ? [{ platform, meta, value }] : [];\n });\n\n const socials = (template.socials ?? []).flatMap((platform) => {\n const meta = SOCIAL_PLATFORM_META[platform];\n const value = getAttr(meta.traitKey);\n return value ? [{ platform, meta, value }] : [];\n });\n\n if (embeds.length === 0 && socials.length === 0) return null;\n\n return (\n <div className=\"space-y-5\">\n {embeds.map(({ platform, meta, value }) => {\n const src = getEmbedSrc(platform, value);\n if (src) {\n return (\n <div key={platform} className=\"space-y-1.5\">\n <p className=\"text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n {meta.label}\n </p>\n {COMPACT[platform] ? (\n <iframe\n src={src}\n className=\"w-full rounded-xl border-0\"\n height={166}\n allow=\"autoplay\"\n loading=\"lazy\"\n title={meta.label}\n />\n ) : (\n <div className=\"relative w-full aspect-video rounded-xl overflow-hidden bg-muted/20\">\n <iframe\n src={src}\n className=\"absolute inset-0 w-full h-full\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n loading=\"lazy\"\n title={meta.label}\n />\n </div>\n )}\n </div>\n );\n }\n // Fallback: plain external link if URL parsing failed\n return (\n <div key={platform}>\n <p className=\"text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-1\">\n {meta.label}\n </p>\n <a\n href={value}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-1.5 text-sm text-primary hover:underline\"\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n Open link\n </a>\n </div>\n );\n })}\n\n {socials.length > 0 && (\n <div className=\"space-y-1.5\">\n <p className=\"text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n Links\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {socials.map(({ platform, meta, value }) => {\n const SIcon = meta.icon;\n return (\n <a\n key={platform}\n href={value}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-1.5 rounded-full border border-border bg-muted/30 px-3 py-1.5 text-xs font-medium text-muted-foreground transition-colors hover:border-primary/40 hover:text-foreground\"\n >\n <SIcon className=\"h-3.5 w-3.5\" />\n {meta.label}\n </a>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface Attr {
|
|
4
|
+
trait_type?: string | null;
|
|
5
|
+
value?: string | null;
|
|
6
|
+
}
|
|
7
|
+
interface IPTypeDisplayProps {
|
|
8
|
+
attributes: Attr[] | null | undefined;
|
|
9
|
+
}
|
|
10
|
+
declare function IPTypeDisplay({ attributes }: IPTypeDisplayProps): react_jsx_runtime.JSX.Element | null;
|
|
11
|
+
|
|
12
|
+
export { IPTypeDisplay };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface Attr {
|
|
4
|
+
trait_type?: string | null;
|
|
5
|
+
value?: string | null;
|
|
6
|
+
}
|
|
7
|
+
interface IPTypeDisplayProps {
|
|
8
|
+
attributes: Attr[] | null | undefined;
|
|
9
|
+
}
|
|
10
|
+
declare function IPTypeDisplay({ attributes }: IPTypeDisplayProps): react_jsx_runtime.JSX.Element | null;
|
|
11
|
+
|
|
12
|
+
export { IPTypeDisplay };
|