@medialane/ui 0.78.1 → 0.78.2

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.
@@ -26,7 +26,6 @@ __export(license_terms_builder_exports, {
26
26
  });
27
27
  module.exports = __toCommonJS(license_terms_builder_exports);
28
28
  var import_jsx_runtime = require("react/jsx-runtime");
29
- var import_react = require("react");
30
29
  var import_lucide_react = require("lucide-react");
31
30
  var import_cn = require("../utils/cn.js");
32
31
  var import_currency_icon = require("./currency-icon.js");
@@ -44,9 +43,9 @@ const MEDIA_TYPES = [
44
43
  const EMPTY_SPONSORSHIP_TERMS = {
45
44
  amount: "",
46
45
  paymentTokenSymbol: "",
47
- durationDays: "30",
46
+ durationDays: "",
48
47
  transferable: true,
49
- royaltyPercent: "5",
48
+ royaltyPercent: "0",
50
49
  licenseText: "",
51
50
  licenseType: "CC BY-SA",
52
51
  commercialUse: "Yes",
@@ -115,7 +114,6 @@ function LicenseTermsBuilder({
115
114
  disabled,
116
115
  className
117
116
  }) {
118
- const [panelOpen, setPanelOpen] = (0, import_react.useState)(false);
119
117
  const set = (key, v) => onChange({ ...value, [key]: v });
120
118
  const handleLicenseTypeChange = (licenseType) => {
121
119
  const def = import_ip.LICENSE_TYPES.find((l) => l.value === licenseType);
@@ -169,23 +167,6 @@ function LicenseTermsBuilder({
169
167
  symbol
170
168
  )) })
171
169
  ] }),
172
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
173
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "Resale royalty (%)" }),
174
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
175
- "input",
176
- {
177
- type: "number",
178
- min: 0,
179
- max: 100,
180
- step: "0.1",
181
- disabled,
182
- value: value.royaltyPercent,
183
- onChange: (e) => set("royaltyPercent", e.target.value),
184
- className: INPUT_BASE
185
- }
186
- ),
187
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: FIELD_HELP, children: "You get this share automatically if the license is ever resold." })
188
- ] }),
189
170
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "flex items-start gap-2.5 cursor-pointer select-none", children: [
190
171
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
191
172
  "input",
@@ -203,31 +184,11 @@ function LicenseTermsBuilder({
203
184
  ] })
204
185
  ] }),
205
186
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-xl border border-border overflow-hidden bg-card/40", children: [
206
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
207
- "button",
208
- {
209
- type: "button",
210
- onClick: () => setPanelOpen((o) => !o),
211
- className: "w-full flex items-center justify-between gap-3 px-4 py-3 text-left transition-colors hover:bg-card/80",
212
- children: [
213
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-2.5 min-w-0", children: [
214
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ScrollText, { className: "h-4 w-4 text-brand-purple shrink-0" }),
215
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "min-w-0", children: [
216
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "block text-sm font-semibold", children: "How long, where, and what for" }),
217
- !panelOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "block text-xs text-muted-foreground truncate", children: [
218
- value.durationDays || "30",
219
- " days \xB7 ",
220
- value.territory,
221
- " \xB7 ",
222
- value.licenseType
223
- ] }) : null
224
- ] })
225
- ] }),
226
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ChevronDown, { className: (0, import_cn.cn)("h-4 w-4 transition-transform text-muted-foreground shrink-0", panelOpen && "rotate-180") })
227
- ]
228
- }
229
- ),
230
- panelOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "px-4 pb-4 space-y-4 border-t border-border pt-4", children: [
187
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2.5 px-4 py-3 border-b border-border", children: [
188
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ScrollText, { className: "h-4 w-4 text-brand-purple shrink-0" }),
189
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-sm font-semibold", children: "How long, where, and what for" })
190
+ ] }),
191
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "px-4 pb-4 space-y-4 pt-4", children: [
231
192
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
232
193
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "License length (days)" }),
233
194
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -238,6 +199,7 @@ function LicenseTermsBuilder({
238
199
  disabled,
239
200
  value: value.durationDays,
240
201
  onChange: (e) => set("durationDays", e.target.value),
202
+ placeholder: "e.g. 30",
241
203
  className: INPUT_BASE
242
204
  }
243
205
  ),
@@ -399,7 +361,7 @@ function LicenseTermsBuilder({
399
361
  ),
400
362
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: FIELD_HELP, children: "Saved permanently and shown to anyone who holds the license." })
401
363
  ] })
402
- ] }) : null
364
+ ] })
403
365
  ] })
404
366
  ] });
405
367
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/license-terms-builder.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { ChevronDown, ScrollText } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { LICENSE_TYPES, GEOGRAPHIC_SCOPES, AI_POLICIES } from \"../data/ip.js\";\n\n/** Common sponsorship media/channel types — deliberately not part of the\n * general IP taxonomy in `data/ip.ts` (that's about the asset itself;\n * this is about the sponsorship deal's channels), so it stays local here. */\nexport const MEDIA_TYPES = [\n \"Social Media\", \"Video\", \"Photo\", \"Article/Blog\", \"Print\", \"Broadcast\", \"Podcast/Audio\", \"Livestream\",\n] as const;\n\n/**\n * The deal terms a sponsorship offer/proposal needs, in plain-language shape\n * — no bps, no IPFS, no ByteArray. `royaltyPercent` is a plain 0–100 number\n * (multiply by 100 for the contract's basis-points argument). Every field\n * here is declarative metadata carried in the pinned IPFS document (see\n * `toLicenseMetadata`) — the contract never reads any of it, so none of it\n * is enforced beyond the atomic accept-and-mint payment itself. This\n * component only collects and validates the data, it never fetches or\n * uploads anything itself.\n */\nexport interface SponsorshipTerms {\n amount: string;\n paymentTokenSymbol: string;\n durationDays: string;\n transferable: boolean;\n royaltyPercent: string;\n /** Free-text notes that don't fit any structured field below. */\n licenseText: string;\n licenseType: string;\n commercialUse: \"Yes\" | \"No\";\n derivatives: \"Allowed\" | \"Not Allowed\" | \"Share-Alike\";\n attribution: \"Required\" | \"Not Required\";\n territory: string;\n aiPolicy: string;\n /** e.g. \"Instagram + YouTube only\" — too deal-specific to bound into an enum. */\n scope: string;\n /** e.g. \"3 posts, 1 video\" */\n deliverables: string;\n exclusive: boolean;\n approvalRequired: boolean;\n media: string[];\n mediaOther: string;\n}\n\nexport const EMPTY_SPONSORSHIP_TERMS: SponsorshipTerms = {\n amount: \"\",\n paymentTokenSymbol: \"\",\n durationDays: \"30\",\n transferable: true,\n royaltyPercent: \"5\",\n licenseText: \"\",\n licenseType: \"CC BY-SA\",\n commercialUse: \"Yes\",\n derivatives: \"Share-Alike\",\n attribution: \"Required\",\n territory: \"Worldwide\",\n aiPolicy: \"Allowed\",\n scope: \"\",\n deliverables: \"\",\n exclusive: false,\n approvalRequired: false,\n media: [],\n mediaOther: \"\",\n};\n\n/** Shapes the pinned-IPFS-JSON payload — the single place both apps build\n * this object, so it can't drift across call sites. Purely additive; the\n * contract never reads any of it. */\nexport function toLicenseMetadata(terms: SponsorshipTerms): Record<string, unknown> {\n return {\n terms: terms.licenseText,\n transferable: terms.transferable,\n royaltyPercent: Number(terms.royaltyPercent || \"0\"),\n licenseType: terms.licenseType,\n commercialUse: terms.commercialUse,\n derivatives: terms.derivatives,\n attribution: terms.attribution,\n territory: terms.territory,\n aiPolicy: terms.aiPolicy,\n scope: terms.scope,\n deliverables: terms.deliverables,\n exclusive: terms.exclusive,\n approvalRequired: terms.approvalRequired,\n media: terms.media,\n mediaOther: terms.mediaOther,\n };\n}\n\nexport interface LicenseTermsBuilderProps {\n value: SponsorshipTerms;\n onChange: (next: SponsorshipTerms) => void;\n /** Payment token symbols to offer — e.g. from SUPPORTED_TOKENS. */\n tokenOptions: string[];\n /** Copy override for the amount field — \"Minimum bid\" for an owner's\n * offer, \"Amount you'll pay\" for a sponsor's proposal. Default: \"Amount\". */\n amountLabel?: string;\n disabled?: boolean;\n className?: string;\n}\n\nconst FIELD_LABEL = \"text-xs font-semibold text-foreground\";\nconst FIELD_HELP = \"text-xs text-muted-foreground\";\nconst INPUT_BASE =\n \"w-full h-10 rounded-xl border border-border bg-card px-3 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-brand-purple/40 focus:border-brand-purple/40 disabled:opacity-50\";\n\nfunction ToggleGroup({ value, options, onChange, disabled }: { value: string; options: readonly string[]; onChange: (v: string) => void; disabled?: boolean }) {\n return (\n <div className=\"flex rounded-lg border border-border overflow-hidden w-full\">\n {options.map((opt, i) => (\n <button\n key={opt}\n type=\"button\"\n disabled={disabled}\n onClick={() => onChange(opt)}\n className={cn(\n \"flex-1 px-3 py-2 text-xs sm:text-sm transition-colors disabled:opacity-50\",\n i > 0 && \"border-l border-border\",\n value === opt\n ? \"bg-primary text-primary-foreground font-medium\"\n : \"bg-background hover:bg-muted text-muted-foreground\",\n )}\n >\n {opt}\n </button>\n ))}\n </div>\n );\n}\n\nfunction YesNoToggle({ label, help, checked, onChange, disabled }: { label: string; help: string; checked: boolean; onChange: (v: boolean) => void; disabled?: boolean }) {\n return (\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>{label}</label>\n <ToggleGroup value={checked ? \"Yes\" : \"No\"} options={[\"Yes\", \"No\"]} onChange={(v) => onChange(v === \"Yes\")} disabled={disabled} />\n <p className={FIELD_HELP}>{help}</p>\n </div>\n );\n}\n\nexport function LicenseTermsBuilder({\n value, onChange, tokenOptions, amountLabel = \"Amount\", disabled, className,\n}: LicenseTermsBuilderProps) {\n const [panelOpen, setPanelOpen] = useState(false);\n const set = <K extends keyof SponsorshipTerms>(key: K, v: SponsorshipTerms[K]) =>\n onChange({ ...value, [key]: v });\n\n const handleLicenseTypeChange = (licenseType: string) => {\n const def = LICENSE_TYPES.find((l) => l.value === licenseType);\n onChange({\n ...value,\n licenseType,\n ...(def ? { commercialUse: def.commercialUse, derivatives: def.derivatives, attribution: def.attribution } : {}),\n });\n };\n\n const selectedLicense = LICENSE_TYPES.find((l) => l.value === value.licenseType);\n const toggleMedia = (m: string) => {\n const next = value.media.includes(m) ? value.media.filter((x) => x !== m) : [...value.media, m];\n set(\"media\", next);\n };\n\n return (\n <div className={cn(\"space-y-4\", className)}>\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>{amountLabel}</label>\n <input\n type=\"number\"\n min={0}\n step=\"0.01\"\n inputMode=\"decimal\"\n disabled={disabled}\n value={value.amount}\n onChange={(e) => set(\"amount\", e.target.value)}\n placeholder=\"0.00\"\n className={INPUT_BASE}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Currency</label>\n <div className=\"grid grid-cols-3 sm:grid-cols-5 gap-1.5\">\n {tokenOptions.map((symbol) => (\n <button\n key={symbol}\n type=\"button\"\n disabled={disabled}\n onClick={() => set(\"paymentTokenSymbol\", symbol)}\n aria-pressed={value.paymentTokenSymbol === symbol}\n className={cn(\n \"h-10 px-2 rounded-xl border text-xs font-semibold flex items-center justify-center gap-1.5 transition-colors disabled:opacity-50\",\n value.paymentTokenSymbol === symbol\n ? \"border-brand-purple bg-brand-purple/10 text-foreground\"\n : \"border-border bg-card text-muted-foreground hover:text-foreground\",\n )}\n >\n <CurrencyIcon symbol={symbol} size={14} />\n {symbol}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Resale royalty (%)</label>\n <input\n type=\"number\"\n min={0}\n max={100}\n step=\"0.1\"\n disabled={disabled}\n value={value.royaltyPercent}\n onChange={(e) => set(\"royaltyPercent\", e.target.value)}\n className={INPUT_BASE}\n />\n <p className={FIELD_HELP}>You get this share automatically if the license is ever resold.</p>\n </div>\n\n <label className=\"flex items-start gap-2.5 cursor-pointer select-none\">\n <input\n type=\"checkbox\"\n disabled={disabled}\n checked={value.transferable}\n onChange={(e) => set(\"transferable\", e.target.checked)}\n className=\"mt-0.5 h-4 w-4 rounded border-border text-brand-purple focus:ring-brand-purple/40\"\n />\n <span className=\"text-sm\">\n <span className=\"font-medium\">Sponsor can resell this license</span>\n <span className={cn(FIELD_HELP, \"block\")}>Off means it&apos;s meant to stay with the sponsor who accepts it — resale still isn&apos;t blocked on-chain, this is just the stated intent.</span>\n </span>\n </label>\n\n <div className=\"rounded-xl border border-border overflow-hidden bg-card/40\">\n <button\n type=\"button\"\n onClick={() => setPanelOpen((o) => !o)}\n className=\"w-full flex items-center justify-between gap-3 px-4 py-3 text-left transition-colors hover:bg-card/80\"\n >\n <span className=\"flex items-center gap-2.5 min-w-0\">\n <ScrollText className=\"h-4 w-4 text-brand-purple shrink-0\" />\n <span className=\"min-w-0\">\n <span className=\"block text-sm font-semibold\">How long, where, and what for</span>\n {!panelOpen ? (\n <span className=\"block text-xs text-muted-foreground truncate\">\n {value.durationDays || \"30\"} days · {value.territory} · {value.licenseType}\n </span>\n ) : null}\n </span>\n </span>\n <ChevronDown className={cn(\"h-4 w-4 transition-transform text-muted-foreground shrink-0\", panelOpen && \"rotate-180\")} />\n </button>\n\n {panelOpen ? (\n <div className=\"px-4 pb-4 space-y-4 border-t border-border pt-4\">\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>License length (days)</label>\n <input\n type=\"number\"\n min={1}\n disabled={disabled}\n value={value.durationDays}\n onChange={(e) => set(\"durationDays\", e.target.value)}\n className={INPUT_BASE}\n />\n <p className={FIELD_HELP}>Counted from the moment the deal is accepted, not from today.</p>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>License type</label>\n <select\n disabled={disabled}\n value={value.licenseType}\n onChange={(e) => handleLicenseTypeChange(e.target.value)}\n className={INPUT_BASE}\n >\n {LICENSE_TYPES.map((l) => (\n <option key={l.value} value={l.value}>{l.label}</option>\n ))}\n </select>\n {selectedLicense ? <p className={FIELD_HELP}>{selectedLicense.description}</p> : null}\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Commercial use</label>\n <ToggleGroup value={value.commercialUse} options={[\"Yes\", \"No\"]} onChange={(v) => set(\"commercialUse\", v as SponsorshipTerms[\"commercialUse\"])} disabled={disabled} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Derivatives</label>\n <ToggleGroup value={value.derivatives} options={[\"Allowed\", \"Not Allowed\", \"Share-Alike\"]} onChange={(v) => set(\"derivatives\", v as SponsorshipTerms[\"derivatives\"])} disabled={disabled} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Attribution</label>\n <ToggleGroup value={value.attribution} options={[\"Required\", \"Not Required\"]} onChange={(v) => set(\"attribution\", v as SponsorshipTerms[\"attribution\"])} disabled={disabled} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Territory</label>\n <select\n disabled={disabled}\n value={value.territory}\n onChange={(e) => set(\"territory\", e.target.value)}\n className={INPUT_BASE}\n >\n {GEOGRAPHIC_SCOPES.map((t) => (\n <option key={t} value={t}>{t}</option>\n ))}\n </select>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>AI policy</label>\n <select\n disabled={disabled}\n value={value.aiPolicy}\n onChange={(e) => set(\"aiPolicy\", e.target.value)}\n className={INPUT_BASE}\n >\n {AI_POLICIES.map((p) => (\n <option key={p} value={p}>{p}</option>\n ))}\n </select>\n <p className={FIELD_HELP}>Whether this work can be used to train AI models.</p>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Scope <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <input\n type=\"text\"\n disabled={disabled}\n value={value.scope}\n onChange={(e) => set(\"scope\", e.target.value)}\n placeholder=\"e.g. Instagram + YouTube only\"\n className={INPUT_BASE}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Deliverables <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <textarea\n disabled={disabled}\n value={value.deliverables}\n onChange={(e) => set(\"deliverables\", e.target.value)}\n placeholder=\"e.g. 3 posts, 1 video\"\n rows={2}\n className={cn(INPUT_BASE, \"h-auto py-2.5 resize-y\")}\n />\n </div>\n\n <YesNoToggle\n label=\"Exclusive to this sponsor\"\n help=\"No other sponsors during the license term.\"\n checked={value.exclusive}\n onChange={(v) => set(\"exclusive\", v)}\n disabled={disabled}\n />\n\n <YesNoToggle\n label=\"Content approval required\"\n help=\"Sponsor reviews content before it's published.\"\n checked={value.approvalRequired}\n onChange={(v) => set(\"approvalRequired\", v)}\n disabled={disabled}\n />\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Media <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <div className=\"flex flex-wrap gap-1.5\">\n {MEDIA_TYPES.map((m) => (\n <button\n key={m}\n type=\"button\"\n disabled={disabled}\n onClick={() => toggleMedia(m)}\n className={cn(\n \"h-8 px-2.5 rounded-full border text-xs font-medium transition-colors disabled:opacity-50\",\n value.media.includes(m)\n ? \"border-brand-purple bg-brand-purple/10 text-foreground\"\n : \"border-border bg-card text-muted-foreground hover:text-foreground\",\n )}\n >\n {m}\n </button>\n ))}\n </div>\n <input\n type=\"text\"\n disabled={disabled}\n value={value.mediaOther}\n onChange={(e) => set(\"mediaOther\", e.target.value)}\n placeholder=\"Other media type\"\n className={cn(INPUT_BASE, \"mt-1.5\")}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Additional terms <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <textarea\n disabled={disabled}\n value={value.licenseText}\n onChange={(e) => set(\"licenseText\", e.target.value)}\n placeholder=\"Anything else worth spelling out.\"\n rows={3}\n className={cn(INPUT_BASE, \"h-auto py-2.5 resize-y\")}\n />\n <p className={FIELD_HELP}>Saved permanently and shown to anyone who holds the license.</p>\n </div>\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/license-terms-builder.tsx"],"sourcesContent":["\"use client\";\n\nimport { ScrollText } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { LICENSE_TYPES, GEOGRAPHIC_SCOPES, AI_POLICIES } from \"../data/ip.js\";\n\n/** Common sponsorship media/channel types — deliberately not part of the\n * general IP taxonomy in `data/ip.ts` (that's about the asset itself;\n * this is about the sponsorship deal's channels), so it stays local here. */\nexport const MEDIA_TYPES = [\n \"Social Media\", \"Video\", \"Photo\", \"Article/Blog\", \"Print\", \"Broadcast\", \"Podcast/Audio\", \"Livestream\",\n] as const;\n\n/**\n * The deal terms a sponsorship offer/proposal needs, in plain-language shape\n * — no bps, no IPFS, no ByteArray. `royaltyPercent` is a plain 0–100 number\n * (multiply by 100 for the contract's basis-points argument). Every field\n * here is declarative metadata carried in the pinned IPFS document (see\n * `toLicenseMetadata`) — the contract never reads any of it, so none of it\n * is enforced beyond the atomic accept-and-mint payment itself. This\n * component only collects and validates the data, it never fetches or\n * uploads anything itself.\n */\nexport interface SponsorshipTerms {\n amount: string;\n paymentTokenSymbol: string;\n /** No default — the user must explicitly set this, never silently inherit one. */\n durationDays: string;\n transferable: boolean;\n /** Not surfaced in the UI (no resale-royalty concept here) — always \"0\". Kept\n * on the type because `create_offer`/`propose_sponsorship` still take a\n * `royaltyBps` argument. */\n royaltyPercent: string;\n /** Free-text notes that don't fit any structured field below. */\n licenseText: string;\n licenseType: string;\n commercialUse: \"Yes\" | \"No\";\n derivatives: \"Allowed\" | \"Not Allowed\" | \"Share-Alike\";\n attribution: \"Required\" | \"Not Required\";\n territory: string;\n aiPolicy: string;\n /** e.g. \"Instagram + YouTube only\" — too deal-specific to bound into an enum. */\n scope: string;\n /** e.g. \"3 posts, 1 video\" */\n deliverables: string;\n exclusive: boolean;\n approvalRequired: boolean;\n media: string[];\n mediaOther: string;\n}\n\nexport const EMPTY_SPONSORSHIP_TERMS: SponsorshipTerms = {\n amount: \"\",\n paymentTokenSymbol: \"\",\n durationDays: \"\",\n transferable: true,\n royaltyPercent: \"0\",\n licenseText: \"\",\n licenseType: \"CC BY-SA\",\n commercialUse: \"Yes\",\n derivatives: \"Share-Alike\",\n attribution: \"Required\",\n territory: \"Worldwide\",\n aiPolicy: \"Allowed\",\n scope: \"\",\n deliverables: \"\",\n exclusive: false,\n approvalRequired: false,\n media: [],\n mediaOther: \"\",\n};\n\n/** Shapes the pinned-IPFS-JSON payload — the single place both apps build\n * this object, so it can't drift across call sites. Purely additive; the\n * contract never reads any of it. */\nexport function toLicenseMetadata(terms: SponsorshipTerms): Record<string, unknown> {\n return {\n terms: terms.licenseText,\n transferable: terms.transferable,\n royaltyPercent: Number(terms.royaltyPercent || \"0\"),\n licenseType: terms.licenseType,\n commercialUse: terms.commercialUse,\n derivatives: terms.derivatives,\n attribution: terms.attribution,\n territory: terms.territory,\n aiPolicy: terms.aiPolicy,\n scope: terms.scope,\n deliverables: terms.deliverables,\n exclusive: terms.exclusive,\n approvalRequired: terms.approvalRequired,\n media: terms.media,\n mediaOther: terms.mediaOther,\n };\n}\n\nexport interface LicenseTermsBuilderProps {\n value: SponsorshipTerms;\n onChange: (next: SponsorshipTerms) => void;\n /** Payment token symbols to offer — e.g. from SUPPORTED_TOKENS. */\n tokenOptions: string[];\n /** Copy override for the amount field — \"Minimum bid\" for an owner's\n * offer, \"Amount you'll pay\" for a sponsor's proposal. Default: \"Amount\". */\n amountLabel?: string;\n disabled?: boolean;\n className?: string;\n}\n\nconst FIELD_LABEL = \"text-xs font-semibold text-foreground\";\nconst FIELD_HELP = \"text-xs text-muted-foreground\";\nconst INPUT_BASE =\n \"w-full h-10 rounded-xl border border-border bg-card px-3 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-brand-purple/40 focus:border-brand-purple/40 disabled:opacity-50\";\n\nfunction ToggleGroup({ value, options, onChange, disabled }: { value: string; options: readonly string[]; onChange: (v: string) => void; disabled?: boolean }) {\n return (\n <div className=\"flex rounded-lg border border-border overflow-hidden w-full\">\n {options.map((opt, i) => (\n <button\n key={opt}\n type=\"button\"\n disabled={disabled}\n onClick={() => onChange(opt)}\n className={cn(\n \"flex-1 px-3 py-2 text-xs sm:text-sm transition-colors disabled:opacity-50\",\n i > 0 && \"border-l border-border\",\n value === opt\n ? \"bg-primary text-primary-foreground font-medium\"\n : \"bg-background hover:bg-muted text-muted-foreground\",\n )}\n >\n {opt}\n </button>\n ))}\n </div>\n );\n}\n\nfunction YesNoToggle({ label, help, checked, onChange, disabled }: { label: string; help: string; checked: boolean; onChange: (v: boolean) => void; disabled?: boolean }) {\n return (\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>{label}</label>\n <ToggleGroup value={checked ? \"Yes\" : \"No\"} options={[\"Yes\", \"No\"]} onChange={(v) => onChange(v === \"Yes\")} disabled={disabled} />\n <p className={FIELD_HELP}>{help}</p>\n </div>\n );\n}\n\nexport function LicenseTermsBuilder({\n value, onChange, tokenOptions, amountLabel = \"Amount\", disabled, className,\n}: LicenseTermsBuilderProps) {\n const set = <K extends keyof SponsorshipTerms>(key: K, v: SponsorshipTerms[K]) =>\n onChange({ ...value, [key]: v });\n\n const handleLicenseTypeChange = (licenseType: string) => {\n const def = LICENSE_TYPES.find((l) => l.value === licenseType);\n onChange({\n ...value,\n licenseType,\n ...(def ? { commercialUse: def.commercialUse, derivatives: def.derivatives, attribution: def.attribution } : {}),\n });\n };\n\n const selectedLicense = LICENSE_TYPES.find((l) => l.value === value.licenseType);\n const toggleMedia = (m: string) => {\n const next = value.media.includes(m) ? value.media.filter((x) => x !== m) : [...value.media, m];\n set(\"media\", next);\n };\n\n return (\n <div className={cn(\"space-y-4\", className)}>\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>{amountLabel}</label>\n <input\n type=\"number\"\n min={0}\n step=\"0.01\"\n inputMode=\"decimal\"\n disabled={disabled}\n value={value.amount}\n onChange={(e) => set(\"amount\", e.target.value)}\n placeholder=\"0.00\"\n className={INPUT_BASE}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Currency</label>\n <div className=\"grid grid-cols-3 sm:grid-cols-5 gap-1.5\">\n {tokenOptions.map((symbol) => (\n <button\n key={symbol}\n type=\"button\"\n disabled={disabled}\n onClick={() => set(\"paymentTokenSymbol\", symbol)}\n aria-pressed={value.paymentTokenSymbol === symbol}\n className={cn(\n \"h-10 px-2 rounded-xl border text-xs font-semibold flex items-center justify-center gap-1.5 transition-colors disabled:opacity-50\",\n value.paymentTokenSymbol === symbol\n ? \"border-brand-purple bg-brand-purple/10 text-foreground\"\n : \"border-border bg-card text-muted-foreground hover:text-foreground\",\n )}\n >\n <CurrencyIcon symbol={symbol} size={14} />\n {symbol}\n </button>\n ))}\n </div>\n </div>\n\n <label className=\"flex items-start gap-2.5 cursor-pointer select-none\">\n <input\n type=\"checkbox\"\n disabled={disabled}\n checked={value.transferable}\n onChange={(e) => set(\"transferable\", e.target.checked)}\n className=\"mt-0.5 h-4 w-4 rounded border-border text-brand-purple focus:ring-brand-purple/40\"\n />\n <span className=\"text-sm\">\n <span className=\"font-medium\">Sponsor can resell this license</span>\n <span className={cn(FIELD_HELP, \"block\")}>Off means it&apos;s meant to stay with the sponsor who accepts it — resale still isn&apos;t blocked on-chain, this is just the stated intent.</span>\n </span>\n </label>\n\n <div className=\"rounded-xl border border-border overflow-hidden bg-card/40\">\n <div className=\"flex items-center gap-2.5 px-4 py-3 border-b border-border\">\n <ScrollText className=\"h-4 w-4 text-brand-purple shrink-0\" />\n <span className=\"text-sm font-semibold\">How long, where, and what for</span>\n </div>\n\n <div className=\"px-4 pb-4 space-y-4 pt-4\">\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>License length (days)</label>\n <input\n type=\"number\"\n min={1}\n disabled={disabled}\n value={value.durationDays}\n onChange={(e) => set(\"durationDays\", e.target.value)}\n placeholder=\"e.g. 30\"\n className={INPUT_BASE}\n />\n <p className={FIELD_HELP}>Counted from the moment the deal is accepted, not from today.</p>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>License type</label>\n <select\n disabled={disabled}\n value={value.licenseType}\n onChange={(e) => handleLicenseTypeChange(e.target.value)}\n className={INPUT_BASE}\n >\n {LICENSE_TYPES.map((l) => (\n <option key={l.value} value={l.value}>{l.label}</option>\n ))}\n </select>\n {selectedLicense ? <p className={FIELD_HELP}>{selectedLicense.description}</p> : null}\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Commercial use</label>\n <ToggleGroup value={value.commercialUse} options={[\"Yes\", \"No\"]} onChange={(v) => set(\"commercialUse\", v as SponsorshipTerms[\"commercialUse\"])} disabled={disabled} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Derivatives</label>\n <ToggleGroup value={value.derivatives} options={[\"Allowed\", \"Not Allowed\", \"Share-Alike\"]} onChange={(v) => set(\"derivatives\", v as SponsorshipTerms[\"derivatives\"])} disabled={disabled} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Attribution</label>\n <ToggleGroup value={value.attribution} options={[\"Required\", \"Not Required\"]} onChange={(v) => set(\"attribution\", v as SponsorshipTerms[\"attribution\"])} disabled={disabled} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Territory</label>\n <select\n disabled={disabled}\n value={value.territory}\n onChange={(e) => set(\"territory\", e.target.value)}\n className={INPUT_BASE}\n >\n {GEOGRAPHIC_SCOPES.map((t) => (\n <option key={t} value={t}>{t}</option>\n ))}\n </select>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>AI policy</label>\n <select\n disabled={disabled}\n value={value.aiPolicy}\n onChange={(e) => set(\"aiPolicy\", e.target.value)}\n className={INPUT_BASE}\n >\n {AI_POLICIES.map((p) => (\n <option key={p} value={p}>{p}</option>\n ))}\n </select>\n <p className={FIELD_HELP}>Whether this work can be used to train AI models.</p>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Scope <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <input\n type=\"text\"\n disabled={disabled}\n value={value.scope}\n onChange={(e) => set(\"scope\", e.target.value)}\n placeholder=\"e.g. Instagram + YouTube only\"\n className={INPUT_BASE}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Deliverables <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <textarea\n disabled={disabled}\n value={value.deliverables}\n onChange={(e) => set(\"deliverables\", e.target.value)}\n placeholder=\"e.g. 3 posts, 1 video\"\n rows={2}\n className={cn(INPUT_BASE, \"h-auto py-2.5 resize-y\")}\n />\n </div>\n\n <YesNoToggle\n label=\"Exclusive to this sponsor\"\n help=\"No other sponsors during the license term.\"\n checked={value.exclusive}\n onChange={(v) => set(\"exclusive\", v)}\n disabled={disabled}\n />\n\n <YesNoToggle\n label=\"Content approval required\"\n help=\"Sponsor reviews content before it's published.\"\n checked={value.approvalRequired}\n onChange={(v) => set(\"approvalRequired\", v)}\n disabled={disabled}\n />\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Media <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <div className=\"flex flex-wrap gap-1.5\">\n {MEDIA_TYPES.map((m) => (\n <button\n key={m}\n type=\"button\"\n disabled={disabled}\n onClick={() => toggleMedia(m)}\n className={cn(\n \"h-8 px-2.5 rounded-full border text-xs font-medium transition-colors disabled:opacity-50\",\n value.media.includes(m)\n ? \"border-brand-purple bg-brand-purple/10 text-foreground\"\n : \"border-border bg-card text-muted-foreground hover:text-foreground\",\n )}\n >\n {m}\n </button>\n ))}\n </div>\n <input\n type=\"text\"\n disabled={disabled}\n value={value.mediaOther}\n onChange={(e) => set(\"mediaOther\", e.target.value)}\n placeholder=\"Other media type\"\n className={cn(INPUT_BASE, \"mt-1.5\")}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Additional terms <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <textarea\n disabled={disabled}\n value={value.licenseText}\n onChange={(e) => set(\"licenseText\", e.target.value)}\n placeholder=\"Anything else worth spelling out.\"\n rows={3}\n className={cn(INPUT_BASE, \"h-auto py-2.5 resize-y\")}\n />\n <p className={FIELD_HELP}>Saved permanently and shown to anyone who holds the license.</p>\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -17,8 +17,12 @@ declare const MEDIA_TYPES: readonly ["Social Media", "Video", "Photo", "Article/
17
17
  interface SponsorshipTerms {
18
18
  amount: string;
19
19
  paymentTokenSymbol: string;
20
+ /** No default — the user must explicitly set this, never silently inherit one. */
20
21
  durationDays: string;
21
22
  transferable: boolean;
23
+ /** Not surfaced in the UI (no resale-royalty concept here) — always "0". Kept
24
+ * on the type because `create_offer`/`propose_sponsorship` still take a
25
+ * `royaltyBps` argument. */
22
26
  royaltyPercent: string;
23
27
  /** Free-text notes that don't fit any structured field below. */
24
28
  licenseText: string;
@@ -17,8 +17,12 @@ declare const MEDIA_TYPES: readonly ["Social Media", "Video", "Photo", "Article/
17
17
  interface SponsorshipTerms {
18
18
  amount: string;
19
19
  paymentTokenSymbol: string;
20
+ /** No default — the user must explicitly set this, never silently inherit one. */
20
21
  durationDays: string;
21
22
  transferable: boolean;
23
+ /** Not surfaced in the UI (no resale-royalty concept here) — always "0". Kept
24
+ * on the type because `create_offer`/`propose_sponsorship` still take a
25
+ * `royaltyBps` argument. */
22
26
  royaltyPercent: string;
23
27
  /** Free-text notes that don't fit any structured field below. */
24
28
  licenseText: string;
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useState } from "react";
4
- import { ChevronDown, ScrollText } from "lucide-react";
3
+ import { ScrollText } from "lucide-react";
5
4
  import { cn } from "../utils/cn.js";
6
5
  import { CurrencyIcon } from "./currency-icon.js";
7
6
  import { LICENSE_TYPES, GEOGRAPHIC_SCOPES, AI_POLICIES } from "../data/ip.js";
@@ -18,9 +17,9 @@ const MEDIA_TYPES = [
18
17
  const EMPTY_SPONSORSHIP_TERMS = {
19
18
  amount: "",
20
19
  paymentTokenSymbol: "",
21
- durationDays: "30",
20
+ durationDays: "",
22
21
  transferable: true,
23
- royaltyPercent: "5",
22
+ royaltyPercent: "0",
24
23
  licenseText: "",
25
24
  licenseType: "CC BY-SA",
26
25
  commercialUse: "Yes",
@@ -89,7 +88,6 @@ function LicenseTermsBuilder({
89
88
  disabled,
90
89
  className
91
90
  }) {
92
- const [panelOpen, setPanelOpen] = useState(false);
93
91
  const set = (key, v) => onChange({ ...value, [key]: v });
94
92
  const handleLicenseTypeChange = (licenseType) => {
95
93
  const def = LICENSE_TYPES.find((l) => l.value === licenseType);
@@ -143,23 +141,6 @@ function LicenseTermsBuilder({
143
141
  symbol
144
142
  )) })
145
143
  ] }),
146
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
147
- /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "Resale royalty (%)" }),
148
- /* @__PURE__ */ jsx(
149
- "input",
150
- {
151
- type: "number",
152
- min: 0,
153
- max: 100,
154
- step: "0.1",
155
- disabled,
156
- value: value.royaltyPercent,
157
- onChange: (e) => set("royaltyPercent", e.target.value),
158
- className: INPUT_BASE
159
- }
160
- ),
161
- /* @__PURE__ */ jsx("p", { className: FIELD_HELP, children: "You get this share automatically if the license is ever resold." })
162
- ] }),
163
144
  /* @__PURE__ */ jsxs("label", { className: "flex items-start gap-2.5 cursor-pointer select-none", children: [
164
145
  /* @__PURE__ */ jsx(
165
146
  "input",
@@ -177,31 +158,11 @@ function LicenseTermsBuilder({
177
158
  ] })
178
159
  ] }),
179
160
  /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border overflow-hidden bg-card/40", children: [
180
- /* @__PURE__ */ jsxs(
181
- "button",
182
- {
183
- type: "button",
184
- onClick: () => setPanelOpen((o) => !o),
185
- className: "w-full flex items-center justify-between gap-3 px-4 py-3 text-left transition-colors hover:bg-card/80",
186
- children: [
187
- /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2.5 min-w-0", children: [
188
- /* @__PURE__ */ jsx(ScrollText, { className: "h-4 w-4 text-brand-purple shrink-0" }),
189
- /* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
190
- /* @__PURE__ */ jsx("span", { className: "block text-sm font-semibold", children: "How long, where, and what for" }),
191
- !panelOpen ? /* @__PURE__ */ jsxs("span", { className: "block text-xs text-muted-foreground truncate", children: [
192
- value.durationDays || "30",
193
- " days \xB7 ",
194
- value.territory,
195
- " \xB7 ",
196
- value.licenseType
197
- ] }) : null
198
- ] })
199
- ] }),
200
- /* @__PURE__ */ jsx(ChevronDown, { className: cn("h-4 w-4 transition-transform text-muted-foreground shrink-0", panelOpen && "rotate-180") })
201
- ]
202
- }
203
- ),
204
- panelOpen ? /* @__PURE__ */ jsxs("div", { className: "px-4 pb-4 space-y-4 border-t border-border pt-4", children: [
161
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 px-4 py-3 border-b border-border", children: [
162
+ /* @__PURE__ */ jsx(ScrollText, { className: "h-4 w-4 text-brand-purple shrink-0" }),
163
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: "How long, where, and what for" })
164
+ ] }),
165
+ /* @__PURE__ */ jsxs("div", { className: "px-4 pb-4 space-y-4 pt-4", children: [
205
166
  /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
206
167
  /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "License length (days)" }),
207
168
  /* @__PURE__ */ jsx(
@@ -212,6 +173,7 @@ function LicenseTermsBuilder({
212
173
  disabled,
213
174
  value: value.durationDays,
214
175
  onChange: (e) => set("durationDays", e.target.value),
176
+ placeholder: "e.g. 30",
215
177
  className: INPUT_BASE
216
178
  }
217
179
  ),
@@ -373,7 +335,7 @@ function LicenseTermsBuilder({
373
335
  ),
374
336
  /* @__PURE__ */ jsx("p", { className: FIELD_HELP, children: "Saved permanently and shown to anyone who holds the license." })
375
337
  ] })
376
- ] }) : null
338
+ ] })
377
339
  ] })
378
340
  ] });
379
341
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/license-terms-builder.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { ChevronDown, ScrollText } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { LICENSE_TYPES, GEOGRAPHIC_SCOPES, AI_POLICIES } from \"../data/ip.js\";\n\n/** Common sponsorship media/channel types — deliberately not part of the\n * general IP taxonomy in `data/ip.ts` (that's about the asset itself;\n * this is about the sponsorship deal's channels), so it stays local here. */\nexport const MEDIA_TYPES = [\n \"Social Media\", \"Video\", \"Photo\", \"Article/Blog\", \"Print\", \"Broadcast\", \"Podcast/Audio\", \"Livestream\",\n] as const;\n\n/**\n * The deal terms a sponsorship offer/proposal needs, in plain-language shape\n * — no bps, no IPFS, no ByteArray. `royaltyPercent` is a plain 0–100 number\n * (multiply by 100 for the contract's basis-points argument). Every field\n * here is declarative metadata carried in the pinned IPFS document (see\n * `toLicenseMetadata`) — the contract never reads any of it, so none of it\n * is enforced beyond the atomic accept-and-mint payment itself. This\n * component only collects and validates the data, it never fetches or\n * uploads anything itself.\n */\nexport interface SponsorshipTerms {\n amount: string;\n paymentTokenSymbol: string;\n durationDays: string;\n transferable: boolean;\n royaltyPercent: string;\n /** Free-text notes that don't fit any structured field below. */\n licenseText: string;\n licenseType: string;\n commercialUse: \"Yes\" | \"No\";\n derivatives: \"Allowed\" | \"Not Allowed\" | \"Share-Alike\";\n attribution: \"Required\" | \"Not Required\";\n territory: string;\n aiPolicy: string;\n /** e.g. \"Instagram + YouTube only\" — too deal-specific to bound into an enum. */\n scope: string;\n /** e.g. \"3 posts, 1 video\" */\n deliverables: string;\n exclusive: boolean;\n approvalRequired: boolean;\n media: string[];\n mediaOther: string;\n}\n\nexport const EMPTY_SPONSORSHIP_TERMS: SponsorshipTerms = {\n amount: \"\",\n paymentTokenSymbol: \"\",\n durationDays: \"30\",\n transferable: true,\n royaltyPercent: \"5\",\n licenseText: \"\",\n licenseType: \"CC BY-SA\",\n commercialUse: \"Yes\",\n derivatives: \"Share-Alike\",\n attribution: \"Required\",\n territory: \"Worldwide\",\n aiPolicy: \"Allowed\",\n scope: \"\",\n deliverables: \"\",\n exclusive: false,\n approvalRequired: false,\n media: [],\n mediaOther: \"\",\n};\n\n/** Shapes the pinned-IPFS-JSON payload — the single place both apps build\n * this object, so it can't drift across call sites. Purely additive; the\n * contract never reads any of it. */\nexport function toLicenseMetadata(terms: SponsorshipTerms): Record<string, unknown> {\n return {\n terms: terms.licenseText,\n transferable: terms.transferable,\n royaltyPercent: Number(terms.royaltyPercent || \"0\"),\n licenseType: terms.licenseType,\n commercialUse: terms.commercialUse,\n derivatives: terms.derivatives,\n attribution: terms.attribution,\n territory: terms.territory,\n aiPolicy: terms.aiPolicy,\n scope: terms.scope,\n deliverables: terms.deliverables,\n exclusive: terms.exclusive,\n approvalRequired: terms.approvalRequired,\n media: terms.media,\n mediaOther: terms.mediaOther,\n };\n}\n\nexport interface LicenseTermsBuilderProps {\n value: SponsorshipTerms;\n onChange: (next: SponsorshipTerms) => void;\n /** Payment token symbols to offer — e.g. from SUPPORTED_TOKENS. */\n tokenOptions: string[];\n /** Copy override for the amount field — \"Minimum bid\" for an owner's\n * offer, \"Amount you'll pay\" for a sponsor's proposal. Default: \"Amount\". */\n amountLabel?: string;\n disabled?: boolean;\n className?: string;\n}\n\nconst FIELD_LABEL = \"text-xs font-semibold text-foreground\";\nconst FIELD_HELP = \"text-xs text-muted-foreground\";\nconst INPUT_BASE =\n \"w-full h-10 rounded-xl border border-border bg-card px-3 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-brand-purple/40 focus:border-brand-purple/40 disabled:opacity-50\";\n\nfunction ToggleGroup({ value, options, onChange, disabled }: { value: string; options: readonly string[]; onChange: (v: string) => void; disabled?: boolean }) {\n return (\n <div className=\"flex rounded-lg border border-border overflow-hidden w-full\">\n {options.map((opt, i) => (\n <button\n key={opt}\n type=\"button\"\n disabled={disabled}\n onClick={() => onChange(opt)}\n className={cn(\n \"flex-1 px-3 py-2 text-xs sm:text-sm transition-colors disabled:opacity-50\",\n i > 0 && \"border-l border-border\",\n value === opt\n ? \"bg-primary text-primary-foreground font-medium\"\n : \"bg-background hover:bg-muted text-muted-foreground\",\n )}\n >\n {opt}\n </button>\n ))}\n </div>\n );\n}\n\nfunction YesNoToggle({ label, help, checked, onChange, disabled }: { label: string; help: string; checked: boolean; onChange: (v: boolean) => void; disabled?: boolean }) {\n return (\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>{label}</label>\n <ToggleGroup value={checked ? \"Yes\" : \"No\"} options={[\"Yes\", \"No\"]} onChange={(v) => onChange(v === \"Yes\")} disabled={disabled} />\n <p className={FIELD_HELP}>{help}</p>\n </div>\n );\n}\n\nexport function LicenseTermsBuilder({\n value, onChange, tokenOptions, amountLabel = \"Amount\", disabled, className,\n}: LicenseTermsBuilderProps) {\n const [panelOpen, setPanelOpen] = useState(false);\n const set = <K extends keyof SponsorshipTerms>(key: K, v: SponsorshipTerms[K]) =>\n onChange({ ...value, [key]: v });\n\n const handleLicenseTypeChange = (licenseType: string) => {\n const def = LICENSE_TYPES.find((l) => l.value === licenseType);\n onChange({\n ...value,\n licenseType,\n ...(def ? { commercialUse: def.commercialUse, derivatives: def.derivatives, attribution: def.attribution } : {}),\n });\n };\n\n const selectedLicense = LICENSE_TYPES.find((l) => l.value === value.licenseType);\n const toggleMedia = (m: string) => {\n const next = value.media.includes(m) ? value.media.filter((x) => x !== m) : [...value.media, m];\n set(\"media\", next);\n };\n\n return (\n <div className={cn(\"space-y-4\", className)}>\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>{amountLabel}</label>\n <input\n type=\"number\"\n min={0}\n step=\"0.01\"\n inputMode=\"decimal\"\n disabled={disabled}\n value={value.amount}\n onChange={(e) => set(\"amount\", e.target.value)}\n placeholder=\"0.00\"\n className={INPUT_BASE}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Currency</label>\n <div className=\"grid grid-cols-3 sm:grid-cols-5 gap-1.5\">\n {tokenOptions.map((symbol) => (\n <button\n key={symbol}\n type=\"button\"\n disabled={disabled}\n onClick={() => set(\"paymentTokenSymbol\", symbol)}\n aria-pressed={value.paymentTokenSymbol === symbol}\n className={cn(\n \"h-10 px-2 rounded-xl border text-xs font-semibold flex items-center justify-center gap-1.5 transition-colors disabled:opacity-50\",\n value.paymentTokenSymbol === symbol\n ? \"border-brand-purple bg-brand-purple/10 text-foreground\"\n : \"border-border bg-card text-muted-foreground hover:text-foreground\",\n )}\n >\n <CurrencyIcon symbol={symbol} size={14} />\n {symbol}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Resale royalty (%)</label>\n <input\n type=\"number\"\n min={0}\n max={100}\n step=\"0.1\"\n disabled={disabled}\n value={value.royaltyPercent}\n onChange={(e) => set(\"royaltyPercent\", e.target.value)}\n className={INPUT_BASE}\n />\n <p className={FIELD_HELP}>You get this share automatically if the license is ever resold.</p>\n </div>\n\n <label className=\"flex items-start gap-2.5 cursor-pointer select-none\">\n <input\n type=\"checkbox\"\n disabled={disabled}\n checked={value.transferable}\n onChange={(e) => set(\"transferable\", e.target.checked)}\n className=\"mt-0.5 h-4 w-4 rounded border-border text-brand-purple focus:ring-brand-purple/40\"\n />\n <span className=\"text-sm\">\n <span className=\"font-medium\">Sponsor can resell this license</span>\n <span className={cn(FIELD_HELP, \"block\")}>Off means it&apos;s meant to stay with the sponsor who accepts it — resale still isn&apos;t blocked on-chain, this is just the stated intent.</span>\n </span>\n </label>\n\n <div className=\"rounded-xl border border-border overflow-hidden bg-card/40\">\n <button\n type=\"button\"\n onClick={() => setPanelOpen((o) => !o)}\n className=\"w-full flex items-center justify-between gap-3 px-4 py-3 text-left transition-colors hover:bg-card/80\"\n >\n <span className=\"flex items-center gap-2.5 min-w-0\">\n <ScrollText className=\"h-4 w-4 text-brand-purple shrink-0\" />\n <span className=\"min-w-0\">\n <span className=\"block text-sm font-semibold\">How long, where, and what for</span>\n {!panelOpen ? (\n <span className=\"block text-xs text-muted-foreground truncate\">\n {value.durationDays || \"30\"} days · {value.territory} · {value.licenseType}\n </span>\n ) : null}\n </span>\n </span>\n <ChevronDown className={cn(\"h-4 w-4 transition-transform text-muted-foreground shrink-0\", panelOpen && \"rotate-180\")} />\n </button>\n\n {panelOpen ? (\n <div className=\"px-4 pb-4 space-y-4 border-t border-border pt-4\">\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>License length (days)</label>\n <input\n type=\"number\"\n min={1}\n disabled={disabled}\n value={value.durationDays}\n onChange={(e) => set(\"durationDays\", e.target.value)}\n className={INPUT_BASE}\n />\n <p className={FIELD_HELP}>Counted from the moment the deal is accepted, not from today.</p>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>License type</label>\n <select\n disabled={disabled}\n value={value.licenseType}\n onChange={(e) => handleLicenseTypeChange(e.target.value)}\n className={INPUT_BASE}\n >\n {LICENSE_TYPES.map((l) => (\n <option key={l.value} value={l.value}>{l.label}</option>\n ))}\n </select>\n {selectedLicense ? <p className={FIELD_HELP}>{selectedLicense.description}</p> : null}\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Commercial use</label>\n <ToggleGroup value={value.commercialUse} options={[\"Yes\", \"No\"]} onChange={(v) => set(\"commercialUse\", v as SponsorshipTerms[\"commercialUse\"])} disabled={disabled} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Derivatives</label>\n <ToggleGroup value={value.derivatives} options={[\"Allowed\", \"Not Allowed\", \"Share-Alike\"]} onChange={(v) => set(\"derivatives\", v as SponsorshipTerms[\"derivatives\"])} disabled={disabled} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Attribution</label>\n <ToggleGroup value={value.attribution} options={[\"Required\", \"Not Required\"]} onChange={(v) => set(\"attribution\", v as SponsorshipTerms[\"attribution\"])} disabled={disabled} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Territory</label>\n <select\n disabled={disabled}\n value={value.territory}\n onChange={(e) => set(\"territory\", e.target.value)}\n className={INPUT_BASE}\n >\n {GEOGRAPHIC_SCOPES.map((t) => (\n <option key={t} value={t}>{t}</option>\n ))}\n </select>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>AI policy</label>\n <select\n disabled={disabled}\n value={value.aiPolicy}\n onChange={(e) => set(\"aiPolicy\", e.target.value)}\n className={INPUT_BASE}\n >\n {AI_POLICIES.map((p) => (\n <option key={p} value={p}>{p}</option>\n ))}\n </select>\n <p className={FIELD_HELP}>Whether this work can be used to train AI models.</p>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Scope <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <input\n type=\"text\"\n disabled={disabled}\n value={value.scope}\n onChange={(e) => set(\"scope\", e.target.value)}\n placeholder=\"e.g. Instagram + YouTube only\"\n className={INPUT_BASE}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Deliverables <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <textarea\n disabled={disabled}\n value={value.deliverables}\n onChange={(e) => set(\"deliverables\", e.target.value)}\n placeholder=\"e.g. 3 posts, 1 video\"\n rows={2}\n className={cn(INPUT_BASE, \"h-auto py-2.5 resize-y\")}\n />\n </div>\n\n <YesNoToggle\n label=\"Exclusive to this sponsor\"\n help=\"No other sponsors during the license term.\"\n checked={value.exclusive}\n onChange={(v) => set(\"exclusive\", v)}\n disabled={disabled}\n />\n\n <YesNoToggle\n label=\"Content approval required\"\n help=\"Sponsor reviews content before it's published.\"\n checked={value.approvalRequired}\n onChange={(v) => set(\"approvalRequired\", v)}\n disabled={disabled}\n />\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Media <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <div className=\"flex flex-wrap gap-1.5\">\n {MEDIA_TYPES.map((m) => (\n <button\n key={m}\n type=\"button\"\n disabled={disabled}\n onClick={() => toggleMedia(m)}\n className={cn(\n \"h-8 px-2.5 rounded-full border text-xs font-medium transition-colors disabled:opacity-50\",\n value.media.includes(m)\n ? \"border-brand-purple bg-brand-purple/10 text-foreground\"\n : \"border-border bg-card text-muted-foreground hover:text-foreground\",\n )}\n >\n {m}\n </button>\n ))}\n </div>\n <input\n type=\"text\"\n disabled={disabled}\n value={value.mediaOther}\n onChange={(e) => set(\"mediaOther\", e.target.value)}\n placeholder=\"Other media type\"\n className={cn(INPUT_BASE, \"mt-1.5\")}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Additional terms <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <textarea\n disabled={disabled}\n value={value.licenseText}\n onChange={(e) => set(\"licenseText\", e.target.value)}\n placeholder=\"Anything else worth spelling out.\"\n rows={3}\n className={cn(INPUT_BASE, \"h-auto py-2.5 resize-y\")}\n />\n <p className={FIELD_HELP}>Saved permanently and shown to anyone who holds the license.</p>\n </div>\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n"],"mappings":";AAkHQ,cAsBJ,YAtBI;AAhHR,SAAS,gBAAgB;AACzB,SAAS,aAAa,kBAAkB;AACxC,SAAS,UAAU;AACnB,SAAS,oBAAoB;AAC7B,SAAS,eAAe,mBAAmB,mBAAmB;AAKvD,MAAM,cAAc;AAAA,EACzB;AAAA,EAAgB;AAAA,EAAS;AAAA,EAAS;AAAA,EAAgB;AAAA,EAAS;AAAA,EAAa;AAAA,EAAiB;AAC3F;AAoCO,MAAM,0BAA4C;AAAA,EACvD,QAAQ;AAAA,EACR,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe;AAAA,EACf,aAAa;AAAA,EACb,aAAa;AAAA,EACb,WAAW;AAAA,EACX,UAAU;AAAA,EACV,OAAO;AAAA,EACP,cAAc;AAAA,EACd,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,OAAO,CAAC;AAAA,EACR,YAAY;AACd;AAKO,SAAS,kBAAkB,OAAkD;AAClF,SAAO;AAAA,IACL,OAAO,MAAM;AAAA,IACb,cAAc,MAAM;AAAA,IACpB,gBAAgB,OAAO,MAAM,kBAAkB,GAAG;AAAA,IAClD,aAAa,MAAM;AAAA,IACnB,eAAe,MAAM;AAAA,IACrB,aAAa,MAAM;AAAA,IACnB,aAAa,MAAM;AAAA,IACnB,WAAW,MAAM;AAAA,IACjB,UAAU,MAAM;AAAA,IAChB,OAAO,MAAM;AAAA,IACb,cAAc,MAAM;AAAA,IACpB,WAAW,MAAM;AAAA,IACjB,kBAAkB,MAAM;AAAA,IACxB,OAAO,MAAM;AAAA,IACb,YAAY,MAAM;AAAA,EACpB;AACF;AAcA,MAAM,cAAc;AACpB,MAAM,aAAa;AACnB,MAAM,aACJ;AAEF,SAAS,YAAY,EAAE,OAAO,SAAS,UAAU,SAAS,GAAqG;AAC7J,SACE,oBAAC,SAAI,WAAU,+DACZ,kBAAQ,IAAI,CAAC,KAAK,MACjB;AAAA,IAAC;AAAA;AAAA,MAEC,MAAK;AAAA,MACL;AAAA,MACA,SAAS,MAAM,SAAS,GAAG;AAAA,MAC3B,WAAW;AAAA,QACT;AAAA,QACA,IAAI,KAAK;AAAA,QACT,UAAU,MACN,mDACA;AAAA,MACN;AAAA,MAEC;AAAA;AAAA,IAZI;AAAA,EAaP,CACD,GACH;AAEJ;AAEA,SAAS,YAAY,EAAE,OAAO,MAAM,SAAS,UAAU,SAAS,GAA0G;AACxK,SACE,qBAAC,SAAI,WAAU,eACb;AAAA,wBAAC,WAAM,WAAW,aAAc,iBAAM;AAAA,IACtC,oBAAC,eAAY,OAAO,UAAU,QAAQ,MAAM,SAAS,CAAC,OAAO,IAAI,GAAG,UAAU,CAAC,MAAM,SAAS,MAAM,KAAK,GAAG,UAAoB;AAAA,IAChI,oBAAC,OAAE,WAAW,YAAa,gBAAK;AAAA,KAClC;AAEJ;AAEO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EAAO;AAAA,EAAU;AAAA,EAAc,cAAc;AAAA,EAAU;AAAA,EAAU;AACnE,GAA6B;AAC3B,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,MAAM,CAAmC,KAAQ,MACrD,SAAS,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,EAAE,CAAC;AAEjC,QAAM,0BAA0B,CAAC,gBAAwB;AACvD,UAAM,MAAM,cAAc,KAAK,CAAC,MAAM,EAAE,UAAU,WAAW;AAC7D,aAAS;AAAA,MACP,GAAG;AAAA,MACH;AAAA,MACA,GAAI,MAAM,EAAE,eAAe,IAAI,eAAe,aAAa,IAAI,aAAa,aAAa,IAAI,YAAY,IAAI,CAAC;AAAA,IAChH,CAAC;AAAA,EACH;AAEA,QAAM,kBAAkB,cAAc,KAAK,CAAC,MAAM,EAAE,UAAU,MAAM,WAAW;AAC/E,QAAM,cAAc,CAAC,MAAc;AACjC,UAAM,OAAO,MAAM,MAAM,SAAS,CAAC,IAAI,MAAM,MAAM,OAAO,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC;AAC9F,QAAI,SAAS,IAAI;AAAA,EACnB;AAEA,SACE,qBAAC,SAAI,WAAW,GAAG,aAAa,SAAS,GACvC;AAAA,yBAAC,SAAI,WAAU,eACb;AAAA,0BAAC,WAAM,WAAW,aAAc,uBAAY;AAAA,MAC5C;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAK;AAAA,UACL,WAAU;AAAA,UACV;AAAA,UACA,OAAO,MAAM;AAAA,UACb,UAAU,CAAC,MAAM,IAAI,UAAU,EAAE,OAAO,KAAK;AAAA,UAC7C,aAAY;AAAA,UACZ,WAAW;AAAA;AAAA,MACb;AAAA,OACF;AAAA,IAEA,qBAAC,SAAI,WAAU,eACb;AAAA,0BAAC,WAAM,WAAW,aAAa,sBAAQ;AAAA,MACvC,oBAAC,SAAI,WAAU,2CACZ,uBAAa,IAAI,CAAC,WACjB;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL;AAAA,UACA,SAAS,MAAM,IAAI,sBAAsB,MAAM;AAAA,UAC/C,gBAAc,MAAM,uBAAuB;AAAA,UAC3C,WAAW;AAAA,YACT;AAAA,YACA,MAAM,uBAAuB,SACzB,2DACA;AAAA,UACN;AAAA,UAEA;AAAA,gCAAC,gBAAa,QAAgB,MAAM,IAAI;AAAA,YACvC;AAAA;AAAA;AAAA,QAbI;AAAA,MAcP,CACD,GACH;AAAA,OACF;AAAA,IAEA,qBAAC,SAAI,WAAU,eACb;AAAA,0BAAC,WAAM,WAAW,aAAa,gCAAkB;AAAA,MACjD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAK;AAAA,UACL;AAAA,UACA,OAAO,MAAM;AAAA,UACb,UAAU,CAAC,MAAM,IAAI,kBAAkB,EAAE,OAAO,KAAK;AAAA,UACrD,WAAW;AAAA;AAAA,MACb;AAAA,MACA,oBAAC,OAAE,WAAW,YAAY,6EAA+D;AAAA,OAC3F;AAAA,IAEA,qBAAC,WAAM,WAAU,uDACf;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL;AAAA,UACA,SAAS,MAAM;AAAA,UACf,UAAU,CAAC,MAAM,IAAI,gBAAgB,EAAE,OAAO,OAAO;AAAA,UACrD,WAAU;AAAA;AAAA,MACZ;AAAA,MACA,qBAAC,UAAK,WAAU,WACd;AAAA,4BAAC,UAAK,WAAU,eAAc,6CAA+B;AAAA,QAC7D,oBAAC,UAAK,WAAW,GAAG,YAAY,OAAO,GAAG,sJAA6I;AAAA,SACzL;AAAA,OACF;AAAA,IAEA,qBAAC,SAAI,WAAU,8DACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC;AAAA,UACrC,WAAU;AAAA,UAEV;AAAA,iCAAC,UAAK,WAAU,qCACd;AAAA,kCAAC,cAAW,WAAU,sCAAqC;AAAA,cAC3D,qBAAC,UAAK,WAAU,WACd;AAAA,oCAAC,UAAK,WAAU,+BAA8B,2CAA6B;AAAA,gBAC1E,CAAC,YACA,qBAAC,UAAK,WAAU,gDACb;AAAA,wBAAM,gBAAgB;AAAA,kBAAK;AAAA,kBAAS,MAAM;AAAA,kBAAU;AAAA,kBAAI,MAAM;AAAA,mBACjE,IACE;AAAA,iBACN;AAAA,eACF;AAAA,YACA,oBAAC,eAAY,WAAW,GAAG,+DAA+D,aAAa,YAAY,GAAG;AAAA;AAAA;AAAA,MACxH;AAAA,MAEC,YACC,qBAAC,SAAI,WAAU,mDACb;AAAA,6BAAC,SAAI,WAAU,eACb;AAAA,8BAAC,WAAM,WAAW,aAAa,mCAAqB;AAAA,UACpD;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,KAAK;AAAA,cACL;AAAA,cACA,OAAO,MAAM;AAAA,cACb,UAAU,CAAC,MAAM,IAAI,gBAAgB,EAAE,OAAO,KAAK;AAAA,cACnD,WAAW;AAAA;AAAA,UACb;AAAA,UACA,oBAAC,OAAE,WAAW,YAAY,2EAA6D;AAAA,WACzF;AAAA,QAEA,qBAAC,SAAI,WAAU,eACb;AAAA,8BAAC,WAAM,WAAW,aAAa,0BAAY;AAAA,UAC3C;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,OAAO,MAAM;AAAA,cACb,UAAU,CAAC,MAAM,wBAAwB,EAAE,OAAO,KAAK;AAAA,cACvD,WAAW;AAAA,cAEV,wBAAc,IAAI,CAAC,MAClB,oBAAC,YAAqB,OAAO,EAAE,OAAQ,YAAE,SAA5B,EAAE,KAAgC,CAChD;AAAA;AAAA,UACH;AAAA,UACC,kBAAkB,oBAAC,OAAE,WAAW,YAAa,0BAAgB,aAAY,IAAO;AAAA,WACnF;AAAA,QAEA,qBAAC,SAAI,WAAU,eACb;AAAA,8BAAC,WAAM,WAAW,aAAa,4BAAc;AAAA,UAC7C,oBAAC,eAAY,OAAO,MAAM,eAAe,SAAS,CAAC,OAAO,IAAI,GAAG,UAAU,CAAC,MAAM,IAAI,iBAAiB,CAAsC,GAAG,UAAoB;AAAA,WACtK;AAAA,QAEA,qBAAC,SAAI,WAAU,eACb;AAAA,8BAAC,WAAM,WAAW,aAAa,yBAAW;AAAA,UAC1C,oBAAC,eAAY,OAAO,MAAM,aAAa,SAAS,CAAC,WAAW,eAAe,aAAa,GAAG,UAAU,CAAC,MAAM,IAAI,eAAe,CAAoC,GAAG,UAAoB;AAAA,WAC5L;AAAA,QAEA,qBAAC,SAAI,WAAU,eACb;AAAA,8BAAC,WAAM,WAAW,aAAa,yBAAW;AAAA,UAC1C,oBAAC,eAAY,OAAO,MAAM,aAAa,SAAS,CAAC,YAAY,cAAc,GAAG,UAAU,CAAC,MAAM,IAAI,eAAe,CAAoC,GAAG,UAAoB;AAAA,WAC/K;AAAA,QAEA,qBAAC,SAAI,WAAU,eACb;AAAA,8BAAC,WAAM,WAAW,aAAa,uBAAS;AAAA,UACxC;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,OAAO,MAAM;AAAA,cACb,UAAU,CAAC,MAAM,IAAI,aAAa,EAAE,OAAO,KAAK;AAAA,cAChD,WAAW;AAAA,cAEV,4BAAkB,IAAI,CAAC,MACtB,oBAAC,YAAe,OAAO,GAAI,eAAd,CAAgB,CAC9B;AAAA;AAAA,UACH;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,eACb;AAAA,8BAAC,WAAM,WAAW,aAAa,uBAAS;AAAA,UACxC;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,OAAO,MAAM;AAAA,cACb,UAAU,CAAC,MAAM,IAAI,YAAY,EAAE,OAAO,KAAK;AAAA,cAC/C,WAAW;AAAA,cAEV,sBAAY,IAAI,CAAC,MAChB,oBAAC,YAAe,OAAO,GAAI,eAAd,CAAgB,CAC9B;AAAA;AAAA,UACH;AAAA,UACA,oBAAC,OAAE,WAAW,YAAY,+DAAiD;AAAA,WAC7E;AAAA,QAEA,qBAAC,SAAI,WAAU,eACb;AAAA,+BAAC,WAAM,WAAW,aAAa;AAAA;AAAA,YAAM,oBAAC,UAAK,WAAU,qCAAoC,wBAAU;AAAA,aAAO;AAAA,UAC1G;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL;AAAA,cACA,OAAO,MAAM;AAAA,cACb,UAAU,CAAC,MAAM,IAAI,SAAS,EAAE,OAAO,KAAK;AAAA,cAC5C,aAAY;AAAA,cACZ,WAAW;AAAA;AAAA,UACb;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,eACb;AAAA,+BAAC,WAAM,WAAW,aAAa;AAAA;AAAA,YAAa,oBAAC,UAAK,WAAU,qCAAoC,wBAAU;AAAA,aAAO;AAAA,UACjH;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,OAAO,MAAM;AAAA,cACb,UAAU,CAAC,MAAM,IAAI,gBAAgB,EAAE,OAAO,KAAK;AAAA,cACnD,aAAY;AAAA,cACZ,MAAM;AAAA,cACN,WAAW,GAAG,YAAY,wBAAwB;AAAA;AAAA,UACpD;AAAA,WACF;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,OAAM;AAAA,YACN,MAAK;AAAA,YACL,SAAS,MAAM;AAAA,YACf,UAAU,CAAC,MAAM,IAAI,aAAa,CAAC;AAAA,YACnC;AAAA;AAAA,QACF;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,OAAM;AAAA,YACN,MAAK;AAAA,YACL,SAAS,MAAM;AAAA,YACf,UAAU,CAAC,MAAM,IAAI,oBAAoB,CAAC;AAAA,YAC1C;AAAA;AAAA,QACF;AAAA,QAEA,qBAAC,SAAI,WAAU,eACb;AAAA,+BAAC,WAAM,WAAW,aAAa;AAAA;AAAA,YAAM,oBAAC,UAAK,WAAU,qCAAoC,wBAAU;AAAA,aAAO;AAAA,UAC1G,oBAAC,SAAI,WAAU,0BACZ,sBAAY,IAAI,CAAC,MAChB;AAAA,YAAC;AAAA;AAAA,cAEC,MAAK;AAAA,cACL;AAAA,cACA,SAAS,MAAM,YAAY,CAAC;AAAA,cAC5B,WAAW;AAAA,gBACT;AAAA,gBACA,MAAM,MAAM,SAAS,CAAC,IAClB,2DACA;AAAA,cACN;AAAA,cAEC;AAAA;AAAA,YAXI;AAAA,UAYP,CACD,GACH;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL;AAAA,cACA,OAAO,MAAM;AAAA,cACb,UAAU,CAAC,MAAM,IAAI,cAAc,EAAE,OAAO,KAAK;AAAA,cACjD,aAAY;AAAA,cACZ,WAAW,GAAG,YAAY,QAAQ;AAAA;AAAA,UACpC;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,eACb;AAAA,+BAAC,WAAM,WAAW,aAAa;AAAA;AAAA,YAAiB,oBAAC,UAAK,WAAU,qCAAoC,wBAAU;AAAA,aAAO;AAAA,UACrH;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,OAAO,MAAM;AAAA,cACb,UAAU,CAAC,MAAM,IAAI,eAAe,EAAE,OAAO,KAAK;AAAA,cAClD,aAAY;AAAA,cACZ,MAAM;AAAA,cACN,WAAW,GAAG,YAAY,wBAAwB;AAAA;AAAA,UACpD;AAAA,UACA,oBAAC,OAAE,WAAW,YAAY,0EAA4D;AAAA,WACxF;AAAA,SACF,IACE;AAAA,OACN;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/license-terms-builder.tsx"],"sourcesContent":["\"use client\";\n\nimport { ScrollText } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { LICENSE_TYPES, GEOGRAPHIC_SCOPES, AI_POLICIES } from \"../data/ip.js\";\n\n/** Common sponsorship media/channel types — deliberately not part of the\n * general IP taxonomy in `data/ip.ts` (that's about the asset itself;\n * this is about the sponsorship deal's channels), so it stays local here. */\nexport const MEDIA_TYPES = [\n \"Social Media\", \"Video\", \"Photo\", \"Article/Blog\", \"Print\", \"Broadcast\", \"Podcast/Audio\", \"Livestream\",\n] as const;\n\n/**\n * The deal terms a sponsorship offer/proposal needs, in plain-language shape\n * — no bps, no IPFS, no ByteArray. `royaltyPercent` is a plain 0–100 number\n * (multiply by 100 for the contract's basis-points argument). Every field\n * here is declarative metadata carried in the pinned IPFS document (see\n * `toLicenseMetadata`) — the contract never reads any of it, so none of it\n * is enforced beyond the atomic accept-and-mint payment itself. This\n * component only collects and validates the data, it never fetches or\n * uploads anything itself.\n */\nexport interface SponsorshipTerms {\n amount: string;\n paymentTokenSymbol: string;\n /** No default — the user must explicitly set this, never silently inherit one. */\n durationDays: string;\n transferable: boolean;\n /** Not surfaced in the UI (no resale-royalty concept here) — always \"0\". Kept\n * on the type because `create_offer`/`propose_sponsorship` still take a\n * `royaltyBps` argument. */\n royaltyPercent: string;\n /** Free-text notes that don't fit any structured field below. */\n licenseText: string;\n licenseType: string;\n commercialUse: \"Yes\" | \"No\";\n derivatives: \"Allowed\" | \"Not Allowed\" | \"Share-Alike\";\n attribution: \"Required\" | \"Not Required\";\n territory: string;\n aiPolicy: string;\n /** e.g. \"Instagram + YouTube only\" — too deal-specific to bound into an enum. */\n scope: string;\n /** e.g. \"3 posts, 1 video\" */\n deliverables: string;\n exclusive: boolean;\n approvalRequired: boolean;\n media: string[];\n mediaOther: string;\n}\n\nexport const EMPTY_SPONSORSHIP_TERMS: SponsorshipTerms = {\n amount: \"\",\n paymentTokenSymbol: \"\",\n durationDays: \"\",\n transferable: true,\n royaltyPercent: \"0\",\n licenseText: \"\",\n licenseType: \"CC BY-SA\",\n commercialUse: \"Yes\",\n derivatives: \"Share-Alike\",\n attribution: \"Required\",\n territory: \"Worldwide\",\n aiPolicy: \"Allowed\",\n scope: \"\",\n deliverables: \"\",\n exclusive: false,\n approvalRequired: false,\n media: [],\n mediaOther: \"\",\n};\n\n/** Shapes the pinned-IPFS-JSON payload — the single place both apps build\n * this object, so it can't drift across call sites. Purely additive; the\n * contract never reads any of it. */\nexport function toLicenseMetadata(terms: SponsorshipTerms): Record<string, unknown> {\n return {\n terms: terms.licenseText,\n transferable: terms.transferable,\n royaltyPercent: Number(terms.royaltyPercent || \"0\"),\n licenseType: terms.licenseType,\n commercialUse: terms.commercialUse,\n derivatives: terms.derivatives,\n attribution: terms.attribution,\n territory: terms.territory,\n aiPolicy: terms.aiPolicy,\n scope: terms.scope,\n deliverables: terms.deliverables,\n exclusive: terms.exclusive,\n approvalRequired: terms.approvalRequired,\n media: terms.media,\n mediaOther: terms.mediaOther,\n };\n}\n\nexport interface LicenseTermsBuilderProps {\n value: SponsorshipTerms;\n onChange: (next: SponsorshipTerms) => void;\n /** Payment token symbols to offer — e.g. from SUPPORTED_TOKENS. */\n tokenOptions: string[];\n /** Copy override for the amount field — \"Minimum bid\" for an owner's\n * offer, \"Amount you'll pay\" for a sponsor's proposal. Default: \"Amount\". */\n amountLabel?: string;\n disabled?: boolean;\n className?: string;\n}\n\nconst FIELD_LABEL = \"text-xs font-semibold text-foreground\";\nconst FIELD_HELP = \"text-xs text-muted-foreground\";\nconst INPUT_BASE =\n \"w-full h-10 rounded-xl border border-border bg-card px-3 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-brand-purple/40 focus:border-brand-purple/40 disabled:opacity-50\";\n\nfunction ToggleGroup({ value, options, onChange, disabled }: { value: string; options: readonly string[]; onChange: (v: string) => void; disabled?: boolean }) {\n return (\n <div className=\"flex rounded-lg border border-border overflow-hidden w-full\">\n {options.map((opt, i) => (\n <button\n key={opt}\n type=\"button\"\n disabled={disabled}\n onClick={() => onChange(opt)}\n className={cn(\n \"flex-1 px-3 py-2 text-xs sm:text-sm transition-colors disabled:opacity-50\",\n i > 0 && \"border-l border-border\",\n value === opt\n ? \"bg-primary text-primary-foreground font-medium\"\n : \"bg-background hover:bg-muted text-muted-foreground\",\n )}\n >\n {opt}\n </button>\n ))}\n </div>\n );\n}\n\nfunction YesNoToggle({ label, help, checked, onChange, disabled }: { label: string; help: string; checked: boolean; onChange: (v: boolean) => void; disabled?: boolean }) {\n return (\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>{label}</label>\n <ToggleGroup value={checked ? \"Yes\" : \"No\"} options={[\"Yes\", \"No\"]} onChange={(v) => onChange(v === \"Yes\")} disabled={disabled} />\n <p className={FIELD_HELP}>{help}</p>\n </div>\n );\n}\n\nexport function LicenseTermsBuilder({\n value, onChange, tokenOptions, amountLabel = \"Amount\", disabled, className,\n}: LicenseTermsBuilderProps) {\n const set = <K extends keyof SponsorshipTerms>(key: K, v: SponsorshipTerms[K]) =>\n onChange({ ...value, [key]: v });\n\n const handleLicenseTypeChange = (licenseType: string) => {\n const def = LICENSE_TYPES.find((l) => l.value === licenseType);\n onChange({\n ...value,\n licenseType,\n ...(def ? { commercialUse: def.commercialUse, derivatives: def.derivatives, attribution: def.attribution } : {}),\n });\n };\n\n const selectedLicense = LICENSE_TYPES.find((l) => l.value === value.licenseType);\n const toggleMedia = (m: string) => {\n const next = value.media.includes(m) ? value.media.filter((x) => x !== m) : [...value.media, m];\n set(\"media\", next);\n };\n\n return (\n <div className={cn(\"space-y-4\", className)}>\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>{amountLabel}</label>\n <input\n type=\"number\"\n min={0}\n step=\"0.01\"\n inputMode=\"decimal\"\n disabled={disabled}\n value={value.amount}\n onChange={(e) => set(\"amount\", e.target.value)}\n placeholder=\"0.00\"\n className={INPUT_BASE}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Currency</label>\n <div className=\"grid grid-cols-3 sm:grid-cols-5 gap-1.5\">\n {tokenOptions.map((symbol) => (\n <button\n key={symbol}\n type=\"button\"\n disabled={disabled}\n onClick={() => set(\"paymentTokenSymbol\", symbol)}\n aria-pressed={value.paymentTokenSymbol === symbol}\n className={cn(\n \"h-10 px-2 rounded-xl border text-xs font-semibold flex items-center justify-center gap-1.5 transition-colors disabled:opacity-50\",\n value.paymentTokenSymbol === symbol\n ? \"border-brand-purple bg-brand-purple/10 text-foreground\"\n : \"border-border bg-card text-muted-foreground hover:text-foreground\",\n )}\n >\n <CurrencyIcon symbol={symbol} size={14} />\n {symbol}\n </button>\n ))}\n </div>\n </div>\n\n <label className=\"flex items-start gap-2.5 cursor-pointer select-none\">\n <input\n type=\"checkbox\"\n disabled={disabled}\n checked={value.transferable}\n onChange={(e) => set(\"transferable\", e.target.checked)}\n className=\"mt-0.5 h-4 w-4 rounded border-border text-brand-purple focus:ring-brand-purple/40\"\n />\n <span className=\"text-sm\">\n <span className=\"font-medium\">Sponsor can resell this license</span>\n <span className={cn(FIELD_HELP, \"block\")}>Off means it&apos;s meant to stay with the sponsor who accepts it — resale still isn&apos;t blocked on-chain, this is just the stated intent.</span>\n </span>\n </label>\n\n <div className=\"rounded-xl border border-border overflow-hidden bg-card/40\">\n <div className=\"flex items-center gap-2.5 px-4 py-3 border-b border-border\">\n <ScrollText className=\"h-4 w-4 text-brand-purple shrink-0\" />\n <span className=\"text-sm font-semibold\">How long, where, and what for</span>\n </div>\n\n <div className=\"px-4 pb-4 space-y-4 pt-4\">\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>License length (days)</label>\n <input\n type=\"number\"\n min={1}\n disabled={disabled}\n value={value.durationDays}\n onChange={(e) => set(\"durationDays\", e.target.value)}\n placeholder=\"e.g. 30\"\n className={INPUT_BASE}\n />\n <p className={FIELD_HELP}>Counted from the moment the deal is accepted, not from today.</p>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>License type</label>\n <select\n disabled={disabled}\n value={value.licenseType}\n onChange={(e) => handleLicenseTypeChange(e.target.value)}\n className={INPUT_BASE}\n >\n {LICENSE_TYPES.map((l) => (\n <option key={l.value} value={l.value}>{l.label}</option>\n ))}\n </select>\n {selectedLicense ? <p className={FIELD_HELP}>{selectedLicense.description}</p> : null}\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Commercial use</label>\n <ToggleGroup value={value.commercialUse} options={[\"Yes\", \"No\"]} onChange={(v) => set(\"commercialUse\", v as SponsorshipTerms[\"commercialUse\"])} disabled={disabled} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Derivatives</label>\n <ToggleGroup value={value.derivatives} options={[\"Allowed\", \"Not Allowed\", \"Share-Alike\"]} onChange={(v) => set(\"derivatives\", v as SponsorshipTerms[\"derivatives\"])} disabled={disabled} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Attribution</label>\n <ToggleGroup value={value.attribution} options={[\"Required\", \"Not Required\"]} onChange={(v) => set(\"attribution\", v as SponsorshipTerms[\"attribution\"])} disabled={disabled} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Territory</label>\n <select\n disabled={disabled}\n value={value.territory}\n onChange={(e) => set(\"territory\", e.target.value)}\n className={INPUT_BASE}\n >\n {GEOGRAPHIC_SCOPES.map((t) => (\n <option key={t} value={t}>{t}</option>\n ))}\n </select>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>AI policy</label>\n <select\n disabled={disabled}\n value={value.aiPolicy}\n onChange={(e) => set(\"aiPolicy\", e.target.value)}\n className={INPUT_BASE}\n >\n {AI_POLICIES.map((p) => (\n <option key={p} value={p}>{p}</option>\n ))}\n </select>\n <p className={FIELD_HELP}>Whether this work can be used to train AI models.</p>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Scope <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <input\n type=\"text\"\n disabled={disabled}\n value={value.scope}\n onChange={(e) => set(\"scope\", e.target.value)}\n placeholder=\"e.g. Instagram + YouTube only\"\n className={INPUT_BASE}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Deliverables <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <textarea\n disabled={disabled}\n value={value.deliverables}\n onChange={(e) => set(\"deliverables\", e.target.value)}\n placeholder=\"e.g. 3 posts, 1 video\"\n rows={2}\n className={cn(INPUT_BASE, \"h-auto py-2.5 resize-y\")}\n />\n </div>\n\n <YesNoToggle\n label=\"Exclusive to this sponsor\"\n help=\"No other sponsors during the license term.\"\n checked={value.exclusive}\n onChange={(v) => set(\"exclusive\", v)}\n disabled={disabled}\n />\n\n <YesNoToggle\n label=\"Content approval required\"\n help=\"Sponsor reviews content before it's published.\"\n checked={value.approvalRequired}\n onChange={(v) => set(\"approvalRequired\", v)}\n disabled={disabled}\n />\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Media <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <div className=\"flex flex-wrap gap-1.5\">\n {MEDIA_TYPES.map((m) => (\n <button\n key={m}\n type=\"button\"\n disabled={disabled}\n onClick={() => toggleMedia(m)}\n className={cn(\n \"h-8 px-2.5 rounded-full border text-xs font-medium transition-colors disabled:opacity-50\",\n value.media.includes(m)\n ? \"border-brand-purple bg-brand-purple/10 text-foreground\"\n : \"border-border bg-card text-muted-foreground hover:text-foreground\",\n )}\n >\n {m}\n </button>\n ))}\n </div>\n <input\n type=\"text\"\n disabled={disabled}\n value={value.mediaOther}\n onChange={(e) => set(\"mediaOther\", e.target.value)}\n placeholder=\"Other media type\"\n className={cn(INPUT_BASE, \"mt-1.5\")}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className={FIELD_LABEL}>Additional terms <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <textarea\n disabled={disabled}\n value={value.licenseText}\n onChange={(e) => set(\"licenseText\", e.target.value)}\n placeholder=\"Anything else worth spelling out.\"\n rows={3}\n className={cn(INPUT_BASE, \"h-auto py-2.5 resize-y\")}\n />\n <p className={FIELD_HELP}>Saved permanently and shown to anyone who holds the license.</p>\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medialane/ui",
3
- "version": "0.78.1",
3
+ "version": "0.78.2",
4
4
  "description": "Shared UI components for Medialane apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",