@medialane/ui 0.286.0 → 0.287.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/button.d.cts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/components/collection-settings.cjs +350 -0
- package/dist/components/collection-settings.cjs.map +1 -0
- package/dist/components/collection-settings.d.cts +7 -0
- package/dist/components/collection-settings.d.ts +7 -0
- package/dist/components/collection-settings.js +335 -0
- package/dist/components/collection-settings.js.map +1 -0
- package/dist/components/collection-slug-claim.cjs +219 -0
- package/dist/components/collection-slug-claim.cjs.map +1 -0
- package/dist/components/collection-slug-claim.d.cts +10 -0
- package/dist/components/collection-slug-claim.d.ts +10 -0
- package/dist/components/collection-slug-claim.js +185 -0
- package/dist/components/collection-slug-claim.js.map +1 -0
- package/dist/components/fast-mint/fast-mint.d.cts +2 -2
- package/dist/components/fast-mint/fast-mint.d.ts +2 -2
- package/dist/components/medialane-app.cjs.map +1 -1
- package/dist/components/medialane-app.d.cts +1 -0
- package/dist/components/medialane-app.d.ts +1 -0
- package/dist/components/medialane-app.js.map +1 -1
- package/dist/components/settings-section.cjs +65 -0
- package/dist/components/settings-section.cjs.map +1 -0
- package/dist/components/settings-section.d.cts +24 -0
- package/dist/components/settings-section.d.ts +24 -0
- package/dist/components/settings-section.js +38 -0
- package/dist/components/settings-section.js.map +1 -0
- package/dist/components/sheet.d.cts +1 -1
- package/dist/components/sheet.d.ts +1 -1
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/collection-settings-form.cjs +77 -0
- package/dist/utils/collection-settings-form.cjs.map +1 -0
- package/dist/utils/collection-settings-form.d.cts +21 -0
- package/dist/utils/collection-settings-form.d.ts +21 -0
- package/dist/utils/collection-settings-form.js +51 -0
- package/dist/utils/collection-settings-form.js.map +1 -0
- package/dist/utils/use-collection-settings.cjs +83 -0
- package/dist/utils/use-collection-settings.cjs.map +1 -0
- package/dist/utils/use-collection-settings.d.cts +58 -0
- package/dist/utils/use-collection-settings.d.ts +58 -0
- package/dist/utils/use-collection-settings.js +59 -0
- package/dist/utils/use-collection-settings.js.map +1 -0
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
|
|
7
7
|
size?: "default" | "icon" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
|
|
7
7
|
size?: "default" | "icon" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -0,0 +1,350 @@
|
|
|
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 collection_settings_exports = {};
|
|
31
|
+
__export(collection_settings_exports, {
|
|
32
|
+
CollectionSettings: () => CollectionSettings
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(collection_settings_exports);
|
|
35
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
36
|
+
var import_lucide_react = require("lucide-react");
|
|
37
|
+
var import_sdk = require("@medialane/sdk");
|
|
38
|
+
var import_button = require("./button.js");
|
|
39
|
+
var import_input = require("./input.js");
|
|
40
|
+
var import_label = require("./label.js");
|
|
41
|
+
var import_textarea = require("./textarea.js");
|
|
42
|
+
var import_switch = require("./switch.js");
|
|
43
|
+
var import_select = require("./select.js");
|
|
44
|
+
var import_badge = require("./badge.js");
|
|
45
|
+
var import_link = __toESM(require("./link.js"), 1);
|
|
46
|
+
var import_cn = require("../utils/cn.js");
|
|
47
|
+
var import_settings_section = require("./settings-section.js");
|
|
48
|
+
var import_collection_slug_claim = require("./collection-slug-claim.js");
|
|
49
|
+
var import_use_collection_settings = require("../utils/use-collection-settings.js");
|
|
50
|
+
const DESC_MAX = 500;
|
|
51
|
+
const CONTENT_TYPES = [
|
|
52
|
+
{ value: "VIDEO", label: "Video", icon: import_lucide_react.Video, hint: "YouTube, Vimeo, or any video URL" },
|
|
53
|
+
{ value: "AUDIO", label: "Audio", icon: import_lucide_react.Music, hint: "Spotify, SoundCloud, MP3 link\u2026" },
|
|
54
|
+
{ value: "STREAM", label: "Live stream", icon: import_lucide_react.Radio, hint: "Twitch, YouTube Live, etc." },
|
|
55
|
+
{ value: "DOCUMENT", label: "Document", icon: import_lucide_react.FileText, hint: "PDF, Notion, Google Doc\u2026" },
|
|
56
|
+
{ value: "LINK", label: "Link", icon: import_lucide_react.Link2, hint: "Any URL" }
|
|
57
|
+
];
|
|
58
|
+
function CollectionSettings({ contract }) {
|
|
59
|
+
const {
|
|
60
|
+
collection,
|
|
61
|
+
profile,
|
|
62
|
+
collectionLoading,
|
|
63
|
+
isLoading,
|
|
64
|
+
isOwner,
|
|
65
|
+
form,
|
|
66
|
+
set,
|
|
67
|
+
update,
|
|
68
|
+
saving,
|
|
69
|
+
saveStatus,
|
|
70
|
+
saveError,
|
|
71
|
+
save
|
|
72
|
+
} = (0, import_use_collection_settings.useCollectionSettings)(contract);
|
|
73
|
+
const descLen = form.description.length;
|
|
74
|
+
if (!collectionLoading && collection && !isOwner) {
|
|
75
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "py-12 flex flex-col items-center gap-3 text-center", children: [
|
|
76
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-12 w-12 rounded-full bg-muted flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Lock, { className: "h-5 w-5 text-muted-foreground" }) }),
|
|
77
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-medium", children: "Owner access only" }),
|
|
78
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-muted-foreground max-w-xs", children: "Only the collection owner can access settings. If you believe this is yours, visit your portfolio to claim it." }),
|
|
79
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { variant: "outline", size: "sm", asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: "/portfolio/collections", children: "Go to my collections" }) })
|
|
80
|
+
] });
|
|
81
|
+
}
|
|
82
|
+
const selectedContentType = CONTENT_TYPES.find((t) => t.value === form.gatedContentType);
|
|
83
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-6 max-w-2xl pb-16", children: [
|
|
84
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
85
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "text-xl font-semibold", children: "Collection Settings" }),
|
|
86
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground mt-1", children: "Customize how your collection appears on Medialane and manage exclusive content for your community." }),
|
|
87
|
+
collection && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
88
|
+
import_link.default,
|
|
89
|
+
{
|
|
90
|
+
href: (0, import_sdk.collectionHref)("STARKNET", contract),
|
|
91
|
+
className: "inline-flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground mt-2 transition-colors",
|
|
92
|
+
children: [
|
|
93
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ExternalLink, { className: "h-3 w-3" }),
|
|
94
|
+
"View collection page"
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
] }),
|
|
99
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_settings_section.SectionCard, { id: "identity", children: [
|
|
100
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
101
|
+
import_settings_section.SectionHeader,
|
|
102
|
+
{
|
|
103
|
+
icon: import_lucide_react.User,
|
|
104
|
+
title: "Identity",
|
|
105
|
+
description: "Your collection's public name and description. A complete profile builds trust with collectors.",
|
|
106
|
+
badge: profile?.displayName ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_badge.Badge, { variant: "outline", className: "text-2xs h-4 px-1.5 gap-1 text-emerald-500 border-emerald-500/30", children: [
|
|
107
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.CheckCircle2, { className: "h-2.5 w-2.5" }),
|
|
108
|
+
"Named"
|
|
109
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_badge.Badge, { variant: "outline", className: "text-2xs h-4 px-1.5 gap-1 text-amber-500 border-amber-500/30", children: [
|
|
110
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Info, { className: "h-2.5 w-2.5" }),
|
|
111
|
+
"Add a name"
|
|
112
|
+
] })
|
|
113
|
+
}
|
|
114
|
+
),
|
|
115
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-4 pt-1 border-t border-border", children: [
|
|
116
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_settings_section.FieldRow, { children: [
|
|
117
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.Label, { htmlFor: "displayName", children: "Display name" }),
|
|
118
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
119
|
+
import_input.Input,
|
|
120
|
+
{
|
|
121
|
+
id: "displayName",
|
|
122
|
+
placeholder: collection?.name ?? "My Collection",
|
|
123
|
+
value: form.displayName,
|
|
124
|
+
onChange: set("displayName"),
|
|
125
|
+
disabled: isLoading
|
|
126
|
+
}
|
|
127
|
+
),
|
|
128
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_settings_section.HelperText, { children: "Shown on your collection page and search results. Uses the on-chain name by default." })
|
|
129
|
+
] }),
|
|
130
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_settings_section.FieldRow, { children: [
|
|
131
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
132
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.Label, { htmlFor: "description", children: "Description" }),
|
|
133
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: (0, import_cn.cn)("text-2xs tabular-nums", descLen > DESC_MAX ? "text-destructive" : "text-muted-foreground"), children: [
|
|
134
|
+
descLen,
|
|
135
|
+
"/",
|
|
136
|
+
DESC_MAX
|
|
137
|
+
] })
|
|
138
|
+
] }),
|
|
139
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
140
|
+
import_textarea.Textarea,
|
|
141
|
+
{
|
|
142
|
+
id: "description",
|
|
143
|
+
value: form.description,
|
|
144
|
+
onChange: (e) => {
|
|
145
|
+
if (e.target.value.length <= DESC_MAX) set("description")(e);
|
|
146
|
+
},
|
|
147
|
+
rows: 4,
|
|
148
|
+
placeholder: "Tell collectors what makes this collection special \u2014 the story, the art style, the community\u2026",
|
|
149
|
+
disabled: isLoading
|
|
150
|
+
}
|
|
151
|
+
)
|
|
152
|
+
] })
|
|
153
|
+
] })
|
|
154
|
+
] }),
|
|
155
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_settings_section.SectionCard, { id: "media", children: [
|
|
156
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
157
|
+
import_settings_section.SectionHeader,
|
|
158
|
+
{
|
|
159
|
+
icon: import_lucide_react.Image,
|
|
160
|
+
title: "Media",
|
|
161
|
+
description: "Images shown on your collection page. Use IPFS URIs (ipfs://Qm\u2026) or direct HTTPS URLs."
|
|
162
|
+
}
|
|
163
|
+
),
|
|
164
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-4 pt-1 border-t border-border", children: [
|
|
165
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_settings_section.FieldRow, { children: [
|
|
166
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.Label, { htmlFor: "image", children: "Cover image" }),
|
|
167
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
168
|
+
import_input.Input,
|
|
169
|
+
{
|
|
170
|
+
id: "image",
|
|
171
|
+
placeholder: "ipfs://Qm\u2026 or https://\u2026",
|
|
172
|
+
value: form.image,
|
|
173
|
+
onChange: set("image"),
|
|
174
|
+
disabled: isLoading
|
|
175
|
+
}
|
|
176
|
+
),
|
|
177
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_settings_section.HelperText, { children: "Square or portrait image shown on collection cards across the marketplace." })
|
|
178
|
+
] }),
|
|
179
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_settings_section.FieldRow, { children: [
|
|
180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.Label, { htmlFor: "bannerImage", children: "Banner image" }),
|
|
181
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
182
|
+
import_input.Input,
|
|
183
|
+
{
|
|
184
|
+
id: "bannerImage",
|
|
185
|
+
placeholder: "ipfs://Qm\u2026 or https://\u2026",
|
|
186
|
+
value: form.bannerImage,
|
|
187
|
+
onChange: set("bannerImage"),
|
|
188
|
+
disabled: isLoading
|
|
189
|
+
}
|
|
190
|
+
),
|
|
191
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_settings_section.HelperText, { children: "Wide image displayed as the hero banner at the top of your collection page. Recommended 1500\xD7500 px." })
|
|
192
|
+
] })
|
|
193
|
+
] })
|
|
194
|
+
] }),
|
|
195
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_settings_section.SectionCard, { id: "exclusive", className: form.gatedEnabled ? "border-emerald-500/30 bg-emerald-500/[0.03]" : "", children: [
|
|
196
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
197
|
+
import_settings_section.SectionHeader,
|
|
198
|
+
{
|
|
199
|
+
icon: import_lucide_react.Lock,
|
|
200
|
+
title: "Exclusive Content",
|
|
201
|
+
description: "Reward your holders with exclusive content \u2014 only wallets that own a token from this collection can access it.",
|
|
202
|
+
iconClass: form.gatedEnabled ? "text-emerald-500" : "text-muted-foreground",
|
|
203
|
+
bgClass: form.gatedEnabled ? "bg-emerald-500/15" : "bg-muted",
|
|
204
|
+
badge: form.gatedEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_badge.Badge, { variant: "outline", className: "text-2xs h-4 px-1.5 gap-1 text-emerald-500 border-emerald-500/30", children: [
|
|
205
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Unlock, { className: "h-2.5 w-2.5" }),
|
|
206
|
+
"Active"
|
|
207
|
+
] }) : void 0
|
|
208
|
+
}
|
|
209
|
+
),
|
|
210
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "pt-1 border-t border-border space-y-5", children: [
|
|
211
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
212
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
213
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-medium", children: form.gatedEnabled ? "Exclusive content is enabled" : "Enable exclusive content" }),
|
|
214
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-muted-foreground mt-0.5", children: form.gatedEnabled ? "Holders will see and unlock your exclusive content on the collection page." : "Add exclusive content that only token holders can access \u2014 video, audio, links, or documents." })
|
|
215
|
+
] }),
|
|
216
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
217
|
+
import_switch.Switch,
|
|
218
|
+
{
|
|
219
|
+
checked: form.gatedEnabled,
|
|
220
|
+
onCheckedChange: (v) => update({ gatedEnabled: v }),
|
|
221
|
+
disabled: isLoading
|
|
222
|
+
}
|
|
223
|
+
)
|
|
224
|
+
] }),
|
|
225
|
+
form.gatedEnabled && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-4", children: [
|
|
226
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_settings_section.FieldRow, { children: [
|
|
227
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.Label, { htmlFor: "gatedContentTitle", children: "Content title" }),
|
|
228
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
229
|
+
import_input.Input,
|
|
230
|
+
{
|
|
231
|
+
id: "gatedContentTitle",
|
|
232
|
+
placeholder: "e.g. Exclusive Track, Behind the Scenes, Holders Chat\u2026",
|
|
233
|
+
value: form.gatedContentTitle,
|
|
234
|
+
onChange: set("gatedContentTitle")
|
|
235
|
+
}
|
|
236
|
+
),
|
|
237
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_settings_section.HelperText, { children: "Displayed publicly as a teaser on your collection page \u2014 this title is visible to everyone, but the actual content is only accessible to verified holders." })
|
|
238
|
+
] }),
|
|
239
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_settings_section.FieldRow, { children: [
|
|
240
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.Label, { htmlFor: "gatedContentUrl", children: "Content URL" }),
|
|
241
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
242
|
+
import_input.Input,
|
|
243
|
+
{
|
|
244
|
+
id: "gatedContentUrl",
|
|
245
|
+
placeholder: "https://\u2026",
|
|
246
|
+
value: form.gatedContentUrl,
|
|
247
|
+
onChange: set("gatedContentUrl")
|
|
248
|
+
}
|
|
249
|
+
),
|
|
250
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_settings_section.HelperText, { children: "The link holders will receive. This is kept private by the backend and never exposed publicly. Works with any URL \u2014 video, audio, document, community link, etc." })
|
|
251
|
+
] }),
|
|
252
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_settings_section.FieldRow, { children: [
|
|
253
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.Label, { children: "Content type" }),
|
|
254
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
255
|
+
import_select.Select,
|
|
256
|
+
{
|
|
257
|
+
value: form.gatedContentType,
|
|
258
|
+
onValueChange: (v) => update({ gatedContentType: v }),
|
|
259
|
+
children: [
|
|
260
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.SelectTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.SelectValue, { placeholder: "What kind of content is this?" }) }),
|
|
261
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.SelectContent, { children: CONTENT_TYPES.map(({ value, label, icon: Icon }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.SelectItem, { value, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
262
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
263
|
+
label
|
|
264
|
+
] }) }, value)) })
|
|
265
|
+
]
|
|
266
|
+
}
|
|
267
|
+
),
|
|
268
|
+
selectedContentType && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_settings_section.HelperText, { children: selectedContentType.hint })
|
|
269
|
+
] }),
|
|
270
|
+
form.gatedContentTitle && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-lg border border-emerald-500/20 bg-emerald-500/5 p-4 space-y-1.5", children: [
|
|
271
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-2xs font-semibold text-emerald-500 uppercase tracking-widest", children: "Preview \u2014 what holders see" }),
|
|
272
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-semibold", children: form.gatedContentTitle || "\u2014" }),
|
|
273
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-muted-foreground", children: "Verified holders can access this content on your collection page." })
|
|
274
|
+
] })
|
|
275
|
+
] }),
|
|
276
|
+
!form.gatedEnabled && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-lg bg-muted/50 border border-border p-4 space-y-2", children: [
|
|
277
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs font-semibold text-foreground", children: "How it works" }),
|
|
278
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("ul", { className: "text-xs text-muted-foreground space-y-1.5", children: [
|
|
279
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "flex items-start gap-2", children: [
|
|
280
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Sparkles, { className: "h-3 w-3 text-emerald-500 mt-0.5 shrink-0" }),
|
|
281
|
+
"Set a URL \u2014 a private video, Discord invite, audio file, or any link."
|
|
282
|
+
] }),
|
|
283
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "flex items-start gap-2", children: [
|
|
284
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ShieldCheck, { className: "h-3 w-3 text-emerald-500 mt-0.5 shrink-0" }),
|
|
285
|
+
"Medialane verifies on-chain ownership before granting access. No spoofing."
|
|
286
|
+
] }),
|
|
287
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "flex items-start gap-2", children: [
|
|
288
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Lock, { className: "h-3 w-3 text-emerald-500 mt-0.5 shrink-0" }),
|
|
289
|
+
"The content URL is never exposed publicly \u2014 only verified holders receive it."
|
|
290
|
+
] })
|
|
291
|
+
] })
|
|
292
|
+
] })
|
|
293
|
+
] })
|
|
294
|
+
] }),
|
|
295
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_settings_section.SectionCard, { id: "links", children: [
|
|
296
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
297
|
+
import_settings_section.SectionHeader,
|
|
298
|
+
{
|
|
299
|
+
icon: import_lucide_react.Globe,
|
|
300
|
+
title: "Links",
|
|
301
|
+
description: "Social and community links shown to collectors visiting your page."
|
|
302
|
+
}
|
|
303
|
+
),
|
|
304
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "space-y-4 pt-1 border-t border-border", children: [
|
|
305
|
+
{ key: "websiteUrl", icon: import_lucide_react.Globe, label: "Website", placeholder: "https://myproject.xyz" },
|
|
306
|
+
{ key: "twitterUrl", icon: import_lucide_react.Twitter, label: "Twitter / X", placeholder: "https://twitter.com/\u2026" },
|
|
307
|
+
{ key: "discordUrl", icon: import_lucide_react.MessageCircle, label: "Discord", placeholder: "https://discord.gg/\u2026" },
|
|
308
|
+
{ key: "telegramUrl", icon: import_lucide_react.Send, label: "Telegram", placeholder: "https://t.me/\u2026" }
|
|
309
|
+
].map(({ key, icon: Icon, label, placeholder }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_settings_section.FieldRow, { children: [
|
|
310
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_label.Label, { htmlFor: key, className: "flex items-center gap-1.5", children: [
|
|
311
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
312
|
+
label
|
|
313
|
+
] }),
|
|
314
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
315
|
+
import_input.Input,
|
|
316
|
+
{
|
|
317
|
+
id: key,
|
|
318
|
+
placeholder,
|
|
319
|
+
value: form[key],
|
|
320
|
+
onChange: set(key),
|
|
321
|
+
disabled: isLoading
|
|
322
|
+
}
|
|
323
|
+
)
|
|
324
|
+
] }, key)) })
|
|
325
|
+
] }),
|
|
326
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_slug_claim.CollectionSlugClaimSection, { contract, profile }),
|
|
327
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3 pt-2", children: [
|
|
328
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
329
|
+
import_button.Button,
|
|
330
|
+
{
|
|
331
|
+
onClick: save,
|
|
332
|
+
disabled: saving || isLoading || descLen > DESC_MAX,
|
|
333
|
+
className: "min-w-[120px]",
|
|
334
|
+
children: saving ? "Saving\u2026" : "Save changes"
|
|
335
|
+
}
|
|
336
|
+
),
|
|
337
|
+
saveStatus === "saved" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1.5 text-sm text-emerald-500", children: [
|
|
338
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.CheckCircle2, { className: "h-4 w-4" }),
|
|
339
|
+
" Saved"
|
|
340
|
+
] }),
|
|
341
|
+
saveStatus === "error" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-sm text-destructive", children: saveError }),
|
|
342
|
+
descLen > DESC_MAX && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-destructive", children: "Description is too long." })
|
|
343
|
+
] })
|
|
344
|
+
] });
|
|
345
|
+
}
|
|
346
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
347
|
+
0 && (module.exports = {
|
|
348
|
+
CollectionSettings
|
|
349
|
+
});
|
|
350
|
+
//# sourceMappingURL=collection-settings.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/collection-settings.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n User, Image as ImageIcon, Globe, Twitter, MessageCircle, Send,\n Lock, Unlock, Sparkles, ShieldCheck, CheckCircle2, ExternalLink,\n Video, Music, Radio, FileText, Link2, Info,\n} from \"lucide-react\";\nimport { collectionHref } from \"@medialane/sdk\";\nimport { Button } from \"./button.js\";\nimport { Input } from \"./input.js\";\nimport { Label } from \"./label.js\";\nimport { Textarea } from \"./textarea.js\";\nimport { Switch } from \"./switch.js\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"./select.js\";\nimport { Badge } from \"./badge.js\";\nimport Link from \"./link.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { SectionCard, SectionHeader, FieldRow, HelperText } from \"./settings-section.js\";\nimport { CollectionSlugClaimSection } from \"./collection-slug-claim.js\";\nimport { useCollectionSettings } from \"../utils/use-collection-settings.js\";\n\nconst DESC_MAX = 500;\n\nconst CONTENT_TYPES = [\n { value: \"VIDEO\", label: \"Video\", icon: Video, hint: \"YouTube, Vimeo, or any video URL\" },\n { value: \"AUDIO\", label: \"Audio\", icon: Music, hint: \"Spotify, SoundCloud, MP3 link…\" },\n { value: \"STREAM\", label: \"Live stream\", icon: Radio, hint: \"Twitch, YouTube Live, etc.\" },\n { value: \"DOCUMENT\", label: \"Document\", icon: FileText, hint: \"PDF, Notion, Google Doc…\" },\n { value: \"LINK\", label: \"Link\", icon: Link2, hint: \"Any URL\" },\n];\n\nexport function CollectionSettings({ contract }: { contract: string }) {\n const {\n collection, profile, collectionLoading, isLoading, isOwner,\n form, set, update, saving, saveStatus, saveError, save,\n } = useCollectionSettings(contract);\n const descLen = form.description.length;\n\n if (!collectionLoading && collection && !isOwner) {\n return (\n <div className=\"py-12 flex flex-col items-center gap-3 text-center\">\n <div className=\"h-12 w-12 rounded-full bg-muted flex items-center justify-center\">\n <Lock className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <p className=\"text-sm font-medium\">Owner access only</p>\n <p className=\"text-xs text-muted-foreground max-w-xs\">\n Only the collection owner can access settings. If you believe this is yours,\n visit your portfolio to claim it.\n </p>\n <Button variant=\"outline\" size=\"sm\" asChild>\n <Link href=\"/portfolio/collections\">Go to my collections</Link>\n </Button>\n </div>\n );\n }\n\n const selectedContentType = CONTENT_TYPES.find(t => t.value === form.gatedContentType);\n\n return (\n <div className=\"space-y-6 max-w-2xl pb-16\">\n\n <div>\n <h1 className=\"text-xl font-semibold\">Collection Settings</h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Customize how your collection appears on Medialane and manage exclusive content for your community.\n </p>\n {collection && (\n <Link\n href={collectionHref(\"STARKNET\", contract)}\n className=\"inline-flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground mt-2 transition-colors\"\n >\n <ExternalLink className=\"h-3 w-3\" />\n View collection page\n </Link>\n )}\n </div>\n\n <SectionCard id=\"identity\">\n <SectionHeader\n icon={User}\n title=\"Identity\"\n description=\"Your collection's public name and description. A complete profile builds trust with collectors.\"\n badge={\n profile?.displayName ? (\n <Badge variant=\"outline\" className=\"text-2xs h-4 px-1.5 gap-1 text-emerald-500 border-emerald-500/30\">\n <CheckCircle2 className=\"h-2.5 w-2.5\" />\n Named\n </Badge>\n ) : (\n <Badge variant=\"outline\" className=\"text-2xs h-4 px-1.5 gap-1 text-amber-500 border-amber-500/30\">\n <Info className=\"h-2.5 w-2.5\" />\n Add a name\n </Badge>\n )\n }\n />\n <div className=\"space-y-4 pt-1 border-t border-border\">\n <FieldRow>\n <Label htmlFor=\"displayName\">Display name</Label>\n <Input\n id=\"displayName\"\n placeholder={collection?.name ?? \"My Collection\"}\n value={form.displayName}\n onChange={set(\"displayName\")}\n disabled={isLoading}\n />\n <HelperText>\n Shown on your collection page and search results. Uses the on-chain name by default.\n </HelperText>\n </FieldRow>\n <FieldRow>\n <div className=\"flex items-center justify-between\">\n <Label htmlFor=\"description\">Description</Label>\n <span className={cn(\"text-2xs tabular-nums\", descLen > DESC_MAX ? \"text-destructive\" : \"text-muted-foreground\")}>\n {descLen}/{DESC_MAX}\n </span>\n </div>\n <Textarea\n id=\"description\"\n value={form.description}\n onChange={(e) => {\n if (e.target.value.length <= DESC_MAX) set(\"description\")(e);\n }}\n rows={4}\n placeholder=\"Tell collectors what makes this collection special — the story, the art style, the community…\"\n disabled={isLoading}\n />\n </FieldRow>\n </div>\n </SectionCard>\n\n <SectionCard id=\"media\">\n <SectionHeader\n icon={ImageIcon}\n title=\"Media\"\n description=\"Images shown on your collection page. Use IPFS URIs (ipfs://Qm…) or direct HTTPS URLs.\"\n />\n <div className=\"space-y-4 pt-1 border-t border-border\">\n <FieldRow>\n <Label htmlFor=\"image\">Cover image</Label>\n <Input\n id=\"image\"\n placeholder=\"ipfs://Qm… or https://…\"\n value={form.image}\n onChange={set(\"image\")}\n disabled={isLoading}\n />\n <HelperText>Square or portrait image shown on collection cards across the marketplace.</HelperText>\n </FieldRow>\n <FieldRow>\n <Label htmlFor=\"bannerImage\">Banner image</Label>\n <Input\n id=\"bannerImage\"\n placeholder=\"ipfs://Qm… or https://…\"\n value={form.bannerImage}\n onChange={set(\"bannerImage\")}\n disabled={isLoading}\n />\n <HelperText>Wide image displayed as the hero banner at the top of your collection page. Recommended 1500×500 px.</HelperText>\n </FieldRow>\n </div>\n </SectionCard>\n\n <SectionCard id=\"exclusive\" className={form.gatedEnabled ? \"border-emerald-500/30 bg-emerald-500/[0.03]\" : \"\"}>\n <SectionHeader\n icon={Lock}\n title=\"Exclusive Content\"\n description=\"Reward your holders with exclusive content — only wallets that own a token from this collection can access it.\"\n iconClass={form.gatedEnabled ? \"text-emerald-500\" : \"text-muted-foreground\"}\n bgClass={form.gatedEnabled ? \"bg-emerald-500/15\" : \"bg-muted\"}\n badge={\n form.gatedEnabled ? (\n <Badge variant=\"outline\" className=\"text-2xs h-4 px-1.5 gap-1 text-emerald-500 border-emerald-500/30\">\n <Unlock className=\"h-2.5 w-2.5\" />\n Active\n </Badge>\n ) : undefined\n }\n />\n\n <div className=\"pt-1 border-t border-border space-y-5\">\n\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-sm font-medium\">\n {form.gatedEnabled ? \"Exclusive content is enabled\" : \"Enable exclusive content\"}\n </p>\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n {form.gatedEnabled\n ? \"Holders will see and unlock your exclusive content on the collection page.\"\n : \"Add exclusive content that only token holders can access — video, audio, links, or documents.\"}\n </p>\n </div>\n <Switch\n checked={form.gatedEnabled}\n onCheckedChange={(v) => update({ gatedEnabled: v })}\n disabled={isLoading}\n />\n </div>\n\n {form.gatedEnabled && (\n <div className=\"space-y-4\">\n\n <FieldRow>\n <Label htmlFor=\"gatedContentTitle\">Content title</Label>\n <Input\n id=\"gatedContentTitle\"\n placeholder=\"e.g. Exclusive Track, Behind the Scenes, Holders Chat…\"\n value={form.gatedContentTitle}\n onChange={set(\"gatedContentTitle\")}\n />\n <HelperText>\n Displayed publicly as a teaser on your collection page — this title is visible to everyone,\n but the actual content is only accessible to verified holders.\n </HelperText>\n </FieldRow>\n\n <FieldRow>\n <Label htmlFor=\"gatedContentUrl\">Content URL</Label>\n <Input\n id=\"gatedContentUrl\"\n placeholder=\"https://…\"\n value={form.gatedContentUrl}\n onChange={set(\"gatedContentUrl\")}\n />\n <HelperText>\n The link holders will receive. This is kept private by the backend and never exposed publicly.\n Works with any URL — video, audio, document, community link, etc.\n </HelperText>\n </FieldRow>\n\n <FieldRow>\n <Label>Content type</Label>\n <Select\n value={form.gatedContentType}\n onValueChange={(v) => update({ gatedContentType: v })}\n >\n <SelectTrigger>\n <SelectValue placeholder=\"What kind of content is this?\" />\n </SelectTrigger>\n <SelectContent>\n {CONTENT_TYPES.map(({ value, label, icon: Icon }) => (\n <SelectItem key={value} value={value}>\n <div className=\"flex items-center gap-2\">\n <Icon className=\"h-3.5 w-3.5 text-muted-foreground\" />\n {label}\n </div>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {selectedContentType && (\n <HelperText>{selectedContentType.hint}</HelperText>\n )}\n </FieldRow>\n\n {form.gatedContentTitle && (\n <div className=\"rounded-lg border border-emerald-500/20 bg-emerald-500/5 p-4 space-y-1.5\">\n <p className=\"text-2xs font-semibold text-emerald-500 uppercase tracking-widest\">\n Preview — what holders see\n </p>\n <p className=\"text-sm font-semibold\">{form.gatedContentTitle || \"—\"}</p>\n <p className=\"text-xs text-muted-foreground\">\n Verified holders can access this content on your collection page.\n </p>\n </div>\n )}\n </div>\n )}\n\n {!form.gatedEnabled && (\n <div className=\"rounded-lg bg-muted/50 border border-border p-4 space-y-2\">\n <p className=\"text-xs font-semibold text-foreground\">How it works</p>\n <ul className=\"text-xs text-muted-foreground space-y-1.5\">\n <li className=\"flex items-start gap-2\">\n <Sparkles className=\"h-3 w-3 text-emerald-500 mt-0.5 shrink-0\" />\n Set a URL — a private video, Discord invite, audio file, or any link.\n </li>\n <li className=\"flex items-start gap-2\">\n <ShieldCheck className=\"h-3 w-3 text-emerald-500 mt-0.5 shrink-0\" />\n Medialane verifies on-chain ownership before granting access. No spoofing.\n </li>\n <li className=\"flex items-start gap-2\">\n <Lock className=\"h-3 w-3 text-emerald-500 mt-0.5 shrink-0\" />\n The content URL is never exposed publicly — only verified holders receive it.\n </li>\n </ul>\n </div>\n )}\n </div>\n </SectionCard>\n\n <SectionCard id=\"links\">\n <SectionHeader\n icon={Globe}\n title=\"Links\"\n description=\"Social and community links shown to collectors visiting your page.\"\n />\n <div className=\"space-y-4 pt-1 border-t border-border\">\n {([\n { key: \"websiteUrl\" as const, icon: Globe, label: \"Website\", placeholder: \"https://myproject.xyz\" },\n { key: \"twitterUrl\" as const, icon: Twitter, label: \"Twitter / X\", placeholder: \"https://twitter.com/…\" },\n { key: \"discordUrl\" as const, icon: MessageCircle, label: \"Discord\", placeholder: \"https://discord.gg/…\" },\n { key: \"telegramUrl\" as const, icon: Send, label: \"Telegram\", placeholder: \"https://t.me/…\" },\n ] as const).map(({ key, icon: Icon, label, placeholder }) => (\n <FieldRow key={key}>\n <Label htmlFor={key} className=\"flex items-center gap-1.5\">\n <Icon className=\"h-3.5 w-3.5 text-muted-foreground\" />\n {label}\n </Label>\n <Input\n id={key}\n placeholder={placeholder}\n value={form[key]}\n onChange={set(key)}\n disabled={isLoading}\n />\n </FieldRow>\n ))}\n </div>\n </SectionCard>\n\n <CollectionSlugClaimSection contract={contract} profile={profile} />\n\n <div className=\"flex items-center gap-3 pt-2\">\n <Button\n onClick={save}\n disabled={saving || isLoading || descLen > DESC_MAX}\n className=\"min-w-[120px]\"\n >\n {saving ? \"Saving…\" : \"Save changes\"}\n </Button>\n {saveStatus === \"saved\" && (\n <span className=\"flex items-center gap-1.5 text-sm text-emerald-500\">\n <CheckCircle2 className=\"h-4 w-4\" /> Saved\n </span>\n )}\n {saveStatus === \"error\" && (\n <span className=\"text-sm text-destructive\">{saveError}</span>\n )}\n {descLen > DESC_MAX && (\n <p className=\"text-xs text-destructive\">Description is too long.</p>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["Link","ImageIcon"]}
|