@medialane/ui 0.78.2 → 0.79.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.
@@ -19,17 +19,25 @@ var __copyProps = (to, from, except, desc) => {
19
19
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
20
  var license_terms_builder_exports = {};
21
21
  __export(license_terms_builder_exports, {
22
+ DURATION_UNITS: () => DURATION_UNITS,
22
23
  EMPTY_SPONSORSHIP_TERMS: () => EMPTY_SPONSORSHIP_TERMS,
23
24
  LicenseTermsBuilder: () => LicenseTermsBuilder,
24
25
  MEDIA_TYPES: () => MEDIA_TYPES,
26
+ toDurationDays: () => toDurationDays,
25
27
  toLicenseMetadata: () => toLicenseMetadata
26
28
  });
27
29
  module.exports = __toCommonJS(license_terms_builder_exports);
28
30
  var import_jsx_runtime = require("react/jsx-runtime");
29
- var import_lucide_react = require("lucide-react");
30
31
  var import_cn = require("../utils/cn.js");
31
32
  var import_currency_icon = require("./currency-icon.js");
32
33
  var import_ip = require("../data/ip.js");
34
+ const DURATION_UNITS = ["Days", "Weeks", "Months", "Years"];
35
+ const DURATION_UNIT_DAYS = { Days: 1, Weeks: 7, Months: 30, Years: 365 };
36
+ function toDurationDays(terms) {
37
+ const raw = Number(terms.durationValue || "0");
38
+ if (!raw || raw <= 0) return 0;
39
+ return Math.round(raw * DURATION_UNIT_DAYS[terms.durationUnit]);
40
+ }
33
41
  const MEDIA_TYPES = [
34
42
  "Social Media",
35
43
  "Video",
@@ -43,7 +51,8 @@ const MEDIA_TYPES = [
43
51
  const EMPTY_SPONSORSHIP_TERMS = {
44
52
  amount: "",
45
53
  paymentTokenSymbol: "",
46
- durationDays: "",
54
+ durationValue: "",
55
+ durationUnit: "Days",
47
56
  transferable: true,
48
57
  royaltyPercent: "0",
49
58
  licenseText: "",
@@ -183,193 +192,203 @@ function LicenseTermsBuilder({
183
192
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: (0, import_cn.cn)(FIELD_HELP, "block"), children: "Off means it's meant to stay with the sponsor who accepts it \u2014 resale still isn't blocked on-chain, this is just the stated intent." })
184
193
  ] })
185
194
  ] }),
186
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-xl border border-border overflow-hidden bg-card/40", 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: [
192
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
193
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "License length (days)" }),
194
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
195
- "input",
196
- {
197
- type: "number",
198
- min: 1,
199
- disabled,
200
- value: value.durationDays,
201
- onChange: (e) => set("durationDays", e.target.value),
202
- placeholder: "e.g. 30",
203
- className: INPUT_BASE
204
- }
205
- ),
206
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: FIELD_HELP, children: "Counted from the moment the deal is accepted, not from today." })
207
- ] }),
208
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
209
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "License type" }),
210
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
211
- "select",
212
- {
213
- disabled,
214
- value: value.licenseType,
215
- onChange: (e) => handleLicenseTypeChange(e.target.value),
216
- className: INPUT_BASE,
217
- children: import_ip.LICENSE_TYPES.map((l) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: l.value, children: l.label }, l.value))
218
- }
219
- ),
220
- selectedLicense ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: FIELD_HELP, children: selectedLicense.description }) : null
221
- ] }),
222
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
223
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "Commercial use" }),
224
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToggleGroup, { value: value.commercialUse, options: ["Yes", "No"], onChange: (v) => set("commercialUse", v), disabled })
225
- ] }),
226
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
227
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "Derivatives" }),
228
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToggleGroup, { value: value.derivatives, options: ["Allowed", "Not Allowed", "Share-Alike"], onChange: (v) => set("derivatives", v), disabled })
229
- ] }),
230
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
231
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "Attribution" }),
232
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToggleGroup, { value: value.attribution, options: ["Required", "Not Required"], onChange: (v) => set("attribution", v), disabled })
233
- ] }),
234
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
235
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "Territory" }),
236
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
237
- "select",
238
- {
239
- disabled,
240
- value: value.territory,
241
- onChange: (e) => set("territory", e.target.value),
242
- className: INPUT_BASE,
243
- children: import_ip.GEOGRAPHIC_SCOPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: t, children: t }, t))
244
- }
245
- )
246
- ] }),
247
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
248
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "AI policy" }),
249
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
250
- "select",
251
- {
252
- disabled,
253
- value: value.aiPolicy,
254
- onChange: (e) => set("aiPolicy", e.target.value),
255
- className: INPUT_BASE,
256
- children: import_ip.AI_POLICIES.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: p, children: p }, p))
257
- }
258
- ),
259
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: FIELD_HELP, children: "Whether this work can be used to train AI models." })
260
- ] }),
261
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
262
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: FIELD_LABEL, children: [
263
- "Scope ",
264
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
265
- ] }),
266
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
267
- "input",
268
- {
269
- type: "text",
270
- disabled,
271
- value: value.scope,
272
- onChange: (e) => set("scope", e.target.value),
273
- placeholder: "e.g. Instagram + YouTube only",
274
- className: INPUT_BASE
275
- }
276
- )
277
- ] }),
278
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
279
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: FIELD_LABEL, children: [
280
- "Deliverables ",
281
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
282
- ] }),
283
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
284
- "textarea",
285
- {
286
- disabled,
287
- value: value.deliverables,
288
- onChange: (e) => set("deliverables", e.target.value),
289
- placeholder: "e.g. 3 posts, 1 video",
290
- rows: 2,
291
- className: (0, import_cn.cn)(INPUT_BASE, "h-auto py-2.5 resize-y")
292
- }
293
- )
294
- ] }),
195
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
196
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "License length" }),
197
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid grid-cols-[1fr_auto] gap-2", children: [
295
198
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
296
- YesNoToggle,
199
+ "input",
297
200
  {
298
- label: "Exclusive to this sponsor",
299
- help: "No other sponsors during the license term.",
300
- checked: value.exclusive,
301
- onChange: (v) => set("exclusive", v),
302
- disabled
201
+ type: "number",
202
+ min: 1,
203
+ disabled,
204
+ value: value.durationValue,
205
+ onChange: (e) => set("durationValue", e.target.value),
206
+ placeholder: "e.g. 30",
207
+ className: INPUT_BASE
303
208
  }
304
209
  ),
305
210
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
306
- YesNoToggle,
211
+ "select",
307
212
  {
308
- label: "Content approval required",
309
- help: "Sponsor reviews content before it's published.",
310
- checked: value.approvalRequired,
311
- onChange: (v) => set("approvalRequired", v),
312
- disabled
213
+ disabled,
214
+ value: value.durationUnit,
215
+ onChange: (e) => set("durationUnit", e.target.value),
216
+ className: (0, import_cn.cn)(INPUT_BASE, "w-28"),
217
+ children: DURATION_UNITS.map((u) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: u, children: u }, u))
313
218
  }
314
- ),
315
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
316
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: FIELD_LABEL, children: [
317
- "Media ",
318
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
319
- ] }),
320
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-wrap gap-1.5", children: MEDIA_TYPES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
321
- "button",
322
- {
323
- type: "button",
324
- disabled,
325
- onClick: () => toggleMedia(m),
326
- className: (0, import_cn.cn)(
327
- "h-8 px-2.5 rounded-full border text-xs font-medium transition-colors disabled:opacity-50",
328
- value.media.includes(m) ? "border-brand-purple bg-brand-purple/10 text-foreground" : "border-border bg-card text-muted-foreground hover:text-foreground"
329
- ),
330
- children: m
331
- },
332
- m
333
- )) }),
334
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
335
- "input",
336
- {
337
- type: "text",
338
- disabled,
339
- value: value.mediaOther,
340
- onChange: (e) => set("mediaOther", e.target.value),
341
- placeholder: "Other media type",
342
- className: (0, import_cn.cn)(INPUT_BASE, "mt-1.5")
343
- }
344
- )
345
- ] }),
346
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
347
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: FIELD_LABEL, children: [
348
- "Additional terms ",
349
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
350
- ] }),
351
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
352
- "textarea",
353
- {
354
- disabled,
355
- value: value.licenseText,
356
- onChange: (e) => set("licenseText", e.target.value),
357
- placeholder: "Anything else worth spelling out.",
358
- rows: 3,
359
- className: (0, import_cn.cn)(INPUT_BASE, "h-auto py-2.5 resize-y")
360
- }
219
+ )
220
+ ] }),
221
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: FIELD_HELP, children: "Counted from the moment the deal is accepted, not from today." })
222
+ ] }),
223
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
224
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "License type" }),
225
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
226
+ "select",
227
+ {
228
+ disabled,
229
+ value: value.licenseType,
230
+ onChange: (e) => handleLicenseTypeChange(e.target.value),
231
+ className: INPUT_BASE,
232
+ children: import_ip.LICENSE_TYPES.map((l) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: l.value, children: l.label }, l.value))
233
+ }
234
+ ),
235
+ selectedLicense ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: FIELD_HELP, children: selectedLicense.description }) : null
236
+ ] }),
237
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
238
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "Commercial use" }),
239
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToggleGroup, { value: value.commercialUse, options: ["Yes", "No"], onChange: (v) => set("commercialUse", v), disabled })
240
+ ] }),
241
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
242
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "Derivatives" }),
243
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToggleGroup, { value: value.derivatives, options: ["Allowed", "Not Allowed", "Share-Alike"], onChange: (v) => set("derivatives", v), disabled })
244
+ ] }),
245
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
246
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "Attribution" }),
247
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToggleGroup, { value: value.attribution, options: ["Required", "Not Required"], onChange: (v) => set("attribution", v), disabled })
248
+ ] }),
249
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
250
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: FIELD_LABEL, children: [
251
+ "Territory ",
252
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
253
+ ] }),
254
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
255
+ "input",
256
+ {
257
+ type: "text",
258
+ disabled,
259
+ value: value.territory,
260
+ onChange: (e) => set("territory", e.target.value),
261
+ placeholder: "e.g. Worldwide, Brazil only, excluding China",
262
+ className: INPUT_BASE
263
+ }
264
+ )
265
+ ] }),
266
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
267
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: FIELD_LABEL, children: "AI policy" }),
268
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
269
+ "select",
270
+ {
271
+ disabled,
272
+ value: value.aiPolicy,
273
+ onChange: (e) => set("aiPolicy", e.target.value),
274
+ className: INPUT_BASE,
275
+ children: import_ip.AI_POLICIES.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: p, children: p }, p))
276
+ }
277
+ ),
278
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: FIELD_HELP, children: "Whether this work can be used to train AI models." })
279
+ ] }),
280
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
281
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: FIELD_LABEL, children: [
282
+ "Scope ",
283
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
284
+ ] }),
285
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
286
+ "input",
287
+ {
288
+ type: "text",
289
+ disabled,
290
+ value: value.scope,
291
+ onChange: (e) => set("scope", e.target.value),
292
+ placeholder: "e.g. Instagram + YouTube only",
293
+ className: INPUT_BASE
294
+ }
295
+ )
296
+ ] }),
297
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
298
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: FIELD_LABEL, children: [
299
+ "Deliverables ",
300
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
301
+ ] }),
302
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
303
+ "textarea",
304
+ {
305
+ disabled,
306
+ value: value.deliverables,
307
+ onChange: (e) => set("deliverables", e.target.value),
308
+ placeholder: "e.g. 3 posts, 1 video",
309
+ rows: 2,
310
+ className: (0, import_cn.cn)(INPUT_BASE, "h-auto py-2.5 resize-y")
311
+ }
312
+ )
313
+ ] }),
314
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
315
+ YesNoToggle,
316
+ {
317
+ label: "Exclusive to this sponsor",
318
+ help: "No other sponsors during the license term.",
319
+ checked: value.exclusive,
320
+ onChange: (v) => set("exclusive", v),
321
+ disabled
322
+ }
323
+ ),
324
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
325
+ YesNoToggle,
326
+ {
327
+ label: "Content approval required",
328
+ help: "Sponsor reviews content before it's published.",
329
+ checked: value.approvalRequired,
330
+ onChange: (v) => set("approvalRequired", v),
331
+ disabled
332
+ }
333
+ ),
334
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
335
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: FIELD_LABEL, children: [
336
+ "Media ",
337
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
338
+ ] }),
339
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-wrap gap-1.5", children: MEDIA_TYPES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
340
+ "button",
341
+ {
342
+ type: "button",
343
+ disabled,
344
+ onClick: () => toggleMedia(m),
345
+ className: (0, import_cn.cn)(
346
+ "h-8 px-2.5 rounded-full border text-xs font-medium transition-colors disabled:opacity-50",
347
+ value.media.includes(m) ? "border-brand-purple bg-brand-purple/10 text-foreground" : "border-border bg-card text-muted-foreground hover:text-foreground"
361
348
  ),
362
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: FIELD_HELP, children: "Saved permanently and shown to anyone who holds the license." })
363
- ] })
364
- ] })
349
+ children: m
350
+ },
351
+ m
352
+ )) }),
353
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
354
+ "input",
355
+ {
356
+ type: "text",
357
+ disabled,
358
+ value: value.mediaOther,
359
+ onChange: (e) => set("mediaOther", e.target.value),
360
+ placeholder: "Other media type",
361
+ className: (0, import_cn.cn)(INPUT_BASE, "mt-1.5")
362
+ }
363
+ )
364
+ ] }),
365
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
366
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: FIELD_LABEL, children: [
367
+ "Additional terms ",
368
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
369
+ ] }),
370
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
371
+ "textarea",
372
+ {
373
+ disabled,
374
+ value: value.licenseText,
375
+ onChange: (e) => set("licenseText", e.target.value),
376
+ placeholder: "Anything else worth spelling out.",
377
+ rows: 3,
378
+ className: (0, import_cn.cn)(INPUT_BASE, "h-auto py-2.5 resize-y")
379
+ }
380
+ ),
381
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: FIELD_HELP, children: "Saved permanently and shown to anyone who holds the license." })
365
382
  ] })
366
383
  ] });
367
384
  }
368
385
  // Annotate the CommonJS export names for ESM import in node:
369
386
  0 && (module.exports = {
387
+ DURATION_UNITS,
370
388
  EMPTY_SPONSORSHIP_TERMS,
371
389
  LicenseTermsBuilder,
372
390
  MEDIA_TYPES,
391
+ toDurationDays,
373
392
  toLicenseMetadata
374
393
  });
375
394
  //# sourceMappingURL=license-terms-builder.cjs.map
@@ -1 +1 @@
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":[]}
1
+ {"version":3,"sources":["../../src/components/license-terms-builder.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"../utils/cn.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { LICENSE_TYPES, AI_POLICIES } from \"../data/ip.js\";\n\n/** Duration units — the on-chain `duration` arg is seconds, but nobody\n * should be forced to think in days for a multi-year deal (or forced into\n * days at all — this is declarative, not contract-enforced). */\nexport const DURATION_UNITS = [\"Days\", \"Weeks\", \"Months\", \"Years\"] as const;\nexport type DurationUnit = (typeof DURATION_UNITS)[number];\nconst DURATION_UNIT_DAYS: Record<DurationUnit, number> = { Days: 1, Weeks: 7, Months: 30, Years: 365 };\n\n/** Converts the user-entered value + unit into whole days for the contract's\n * `duration` arg (seconds = days * 86400, done by the caller). */\nexport function toDurationDays(terms: SponsorshipTerms): number {\n const raw = Number(terms.durationValue || \"0\");\n if (!raw || raw <= 0) return 0;\n return Math.round(raw * DURATION_UNIT_DAYS[terms.durationUnit]);\n}\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 * Paired with `durationUnit`; convert with `toDurationDays()`. */\n durationValue: string;\n durationUnit: DurationUnit;\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 /** Free text — \"Worldwide\" is a fine default, but real deals often name a\n * specific country or an exclusion, which a fixed list can't cover. */\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 durationValue: \"\",\n durationUnit: \"Days\",\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=\"space-y-1.5\">\n <label className={FIELD_LABEL}>License length</label>\n <div className=\"grid grid-cols-[1fr_auto] gap-2\">\n <input\n type=\"number\"\n min={1}\n disabled={disabled}\n value={value.durationValue}\n onChange={(e) => set(\"durationValue\", e.target.value)}\n placeholder=\"e.g. 30\"\n className={INPUT_BASE}\n />\n <select\n disabled={disabled}\n value={value.durationUnit}\n onChange={(e) => set(\"durationUnit\", e.target.value as DurationUnit)}\n className={cn(INPUT_BASE, \"w-28\")}\n >\n {DURATION_UNITS.map((u) => (\n <option key={u} value={u}>{u}</option>\n ))}\n </select>\n </div>\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 <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <input\n type=\"text\"\n disabled={disabled}\n value={value.territory}\n onChange={(e) => set(\"territory\", e.target.value)}\n placeholder=\"e.g. Worldwide, Brazil only, excluding China\"\n className={INPUT_BASE}\n />\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 );\n}\n"],"mappings":"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","names":[]}
@@ -1,5 +1,13 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
 
3
+ /** Duration units — the on-chain `duration` arg is seconds, but nobody
4
+ * should be forced to think in days for a multi-year deal (or forced into
5
+ * days at all — this is declarative, not contract-enforced). */
6
+ declare const DURATION_UNITS: readonly ["Days", "Weeks", "Months", "Years"];
7
+ type DurationUnit = (typeof DURATION_UNITS)[number];
8
+ /** Converts the user-entered value + unit into whole days for the contract's
9
+ * `duration` arg (seconds = days * 86400, done by the caller). */
10
+ declare function toDurationDays(terms: SponsorshipTerms): number;
3
11
  /** Common sponsorship media/channel types — deliberately not part of the
4
12
  * general IP taxonomy in `data/ip.ts` (that's about the asset itself;
5
13
  * this is about the sponsorship deal's channels), so it stays local here. */
@@ -17,8 +25,10 @@ declare const MEDIA_TYPES: readonly ["Social Media", "Video", "Photo", "Article/
17
25
  interface SponsorshipTerms {
18
26
  amount: string;
19
27
  paymentTokenSymbol: string;
20
- /** No default — the user must explicitly set this, never silently inherit one. */
21
- durationDays: string;
28
+ /** No default — the user must explicitly set this, never silently inherit one.
29
+ * Paired with `durationUnit`; convert with `toDurationDays()`. */
30
+ durationValue: string;
31
+ durationUnit: DurationUnit;
22
32
  transferable: boolean;
23
33
  /** Not surfaced in the UI (no resale-royalty concept here) — always "0". Kept
24
34
  * on the type because `create_offer`/`propose_sponsorship` still take a
@@ -30,6 +40,8 @@ interface SponsorshipTerms {
30
40
  commercialUse: "Yes" | "No";
31
41
  derivatives: "Allowed" | "Not Allowed" | "Share-Alike";
32
42
  attribution: "Required" | "Not Required";
43
+ /** Free text — "Worldwide" is a fine default, but real deals often name a
44
+ * specific country or an exclusion, which a fixed list can't cover. */
33
45
  territory: string;
34
46
  aiPolicy: string;
35
47
  /** e.g. "Instagram + YouTube only" — too deal-specific to bound into an enum. */
@@ -59,4 +71,4 @@ interface LicenseTermsBuilderProps {
59
71
  }
60
72
  declare function LicenseTermsBuilder({ value, onChange, tokenOptions, amountLabel, disabled, className, }: LicenseTermsBuilderProps): react_jsx_runtime.JSX.Element;
61
73
 
62
- export { EMPTY_SPONSORSHIP_TERMS, LicenseTermsBuilder, type LicenseTermsBuilderProps, MEDIA_TYPES, type SponsorshipTerms, toLicenseMetadata };
74
+ export { DURATION_UNITS, type DurationUnit, EMPTY_SPONSORSHIP_TERMS, LicenseTermsBuilder, type LicenseTermsBuilderProps, MEDIA_TYPES, type SponsorshipTerms, toDurationDays, toLicenseMetadata };
@@ -1,5 +1,13 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
 
3
+ /** Duration units — the on-chain `duration` arg is seconds, but nobody
4
+ * should be forced to think in days for a multi-year deal (or forced into
5
+ * days at all — this is declarative, not contract-enforced). */
6
+ declare const DURATION_UNITS: readonly ["Days", "Weeks", "Months", "Years"];
7
+ type DurationUnit = (typeof DURATION_UNITS)[number];
8
+ /** Converts the user-entered value + unit into whole days for the contract's
9
+ * `duration` arg (seconds = days * 86400, done by the caller). */
10
+ declare function toDurationDays(terms: SponsorshipTerms): number;
3
11
  /** Common sponsorship media/channel types — deliberately not part of the
4
12
  * general IP taxonomy in `data/ip.ts` (that's about the asset itself;
5
13
  * this is about the sponsorship deal's channels), so it stays local here. */
@@ -17,8 +25,10 @@ declare const MEDIA_TYPES: readonly ["Social Media", "Video", "Photo", "Article/
17
25
  interface SponsorshipTerms {
18
26
  amount: string;
19
27
  paymentTokenSymbol: string;
20
- /** No default — the user must explicitly set this, never silently inherit one. */
21
- durationDays: string;
28
+ /** No default — the user must explicitly set this, never silently inherit one.
29
+ * Paired with `durationUnit`; convert with `toDurationDays()`. */
30
+ durationValue: string;
31
+ durationUnit: DurationUnit;
22
32
  transferable: boolean;
23
33
  /** Not surfaced in the UI (no resale-royalty concept here) — always "0". Kept
24
34
  * on the type because `create_offer`/`propose_sponsorship` still take a
@@ -30,6 +40,8 @@ interface SponsorshipTerms {
30
40
  commercialUse: "Yes" | "No";
31
41
  derivatives: "Allowed" | "Not Allowed" | "Share-Alike";
32
42
  attribution: "Required" | "Not Required";
43
+ /** Free text — "Worldwide" is a fine default, but real deals often name a
44
+ * specific country or an exclusion, which a fixed list can't cover. */
33
45
  territory: string;
34
46
  aiPolicy: string;
35
47
  /** e.g. "Instagram + YouTube only" — too deal-specific to bound into an enum. */
@@ -59,4 +71,4 @@ interface LicenseTermsBuilderProps {
59
71
  }
60
72
  declare function LicenseTermsBuilder({ value, onChange, tokenOptions, amountLabel, disabled, className, }: LicenseTermsBuilderProps): react_jsx_runtime.JSX.Element;
61
73
 
62
- export { EMPTY_SPONSORSHIP_TERMS, LicenseTermsBuilder, type LicenseTermsBuilderProps, MEDIA_TYPES, type SponsorshipTerms, toLicenseMetadata };
74
+ export { DURATION_UNITS, type DurationUnit, EMPTY_SPONSORSHIP_TERMS, LicenseTermsBuilder, type LicenseTermsBuilderProps, MEDIA_TYPES, type SponsorshipTerms, toDurationDays, toLicenseMetadata };
@@ -1,9 +1,15 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { ScrollText } from "lucide-react";
4
3
  import { cn } from "../utils/cn.js";
5
4
  import { CurrencyIcon } from "./currency-icon.js";
6
- import { LICENSE_TYPES, GEOGRAPHIC_SCOPES, AI_POLICIES } from "../data/ip.js";
5
+ import { LICENSE_TYPES, AI_POLICIES } from "../data/ip.js";
6
+ const DURATION_UNITS = ["Days", "Weeks", "Months", "Years"];
7
+ const DURATION_UNIT_DAYS = { Days: 1, Weeks: 7, Months: 30, Years: 365 };
8
+ function toDurationDays(terms) {
9
+ const raw = Number(terms.durationValue || "0");
10
+ if (!raw || raw <= 0) return 0;
11
+ return Math.round(raw * DURATION_UNIT_DAYS[terms.durationUnit]);
12
+ }
7
13
  const MEDIA_TYPES = [
8
14
  "Social Media",
9
15
  "Video",
@@ -17,7 +23,8 @@ const MEDIA_TYPES = [
17
23
  const EMPTY_SPONSORSHIP_TERMS = {
18
24
  amount: "",
19
25
  paymentTokenSymbol: "",
20
- durationDays: "",
26
+ durationValue: "",
27
+ durationUnit: "Days",
21
28
  transferable: true,
22
29
  royaltyPercent: "0",
23
30
  licenseText: "",
@@ -157,192 +164,202 @@ function LicenseTermsBuilder({
157
164
  /* @__PURE__ */ jsx("span", { className: cn(FIELD_HELP, "block"), children: "Off means it's meant to stay with the sponsor who accepts it \u2014 resale still isn't blocked on-chain, this is just the stated intent." })
158
165
  ] })
159
166
  ] }),
160
- /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border overflow-hidden bg-card/40", 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: [
166
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
167
- /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "License length (days)" }),
168
- /* @__PURE__ */ jsx(
169
- "input",
170
- {
171
- type: "number",
172
- min: 1,
173
- disabled,
174
- value: value.durationDays,
175
- onChange: (e) => set("durationDays", e.target.value),
176
- placeholder: "e.g. 30",
177
- className: INPUT_BASE
178
- }
179
- ),
180
- /* @__PURE__ */ jsx("p", { className: FIELD_HELP, children: "Counted from the moment the deal is accepted, not from today." })
181
- ] }),
182
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
183
- /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "License type" }),
184
- /* @__PURE__ */ jsx(
185
- "select",
186
- {
187
- disabled,
188
- value: value.licenseType,
189
- onChange: (e) => handleLicenseTypeChange(e.target.value),
190
- className: INPUT_BASE,
191
- children: LICENSE_TYPES.map((l) => /* @__PURE__ */ jsx("option", { value: l.value, children: l.label }, l.value))
192
- }
193
- ),
194
- selectedLicense ? /* @__PURE__ */ jsx("p", { className: FIELD_HELP, children: selectedLicense.description }) : null
195
- ] }),
196
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
197
- /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "Commercial use" }),
198
- /* @__PURE__ */ jsx(ToggleGroup, { value: value.commercialUse, options: ["Yes", "No"], onChange: (v) => set("commercialUse", v), disabled })
199
- ] }),
200
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
201
- /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "Derivatives" }),
202
- /* @__PURE__ */ jsx(ToggleGroup, { value: value.derivatives, options: ["Allowed", "Not Allowed", "Share-Alike"], onChange: (v) => set("derivatives", v), disabled })
203
- ] }),
204
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
205
- /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "Attribution" }),
206
- /* @__PURE__ */ jsx(ToggleGroup, { value: value.attribution, options: ["Required", "Not Required"], onChange: (v) => set("attribution", v), disabled })
207
- ] }),
208
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
209
- /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "Territory" }),
210
- /* @__PURE__ */ jsx(
211
- "select",
212
- {
213
- disabled,
214
- value: value.territory,
215
- onChange: (e) => set("territory", e.target.value),
216
- className: INPUT_BASE,
217
- children: GEOGRAPHIC_SCOPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children: t }, t))
218
- }
219
- )
220
- ] }),
221
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
222
- /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "AI policy" }),
223
- /* @__PURE__ */ jsx(
224
- "select",
225
- {
226
- disabled,
227
- value: value.aiPolicy,
228
- onChange: (e) => set("aiPolicy", e.target.value),
229
- className: INPUT_BASE,
230
- children: AI_POLICIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: p }, p))
231
- }
232
- ),
233
- /* @__PURE__ */ jsx("p", { className: FIELD_HELP, children: "Whether this work can be used to train AI models." })
234
- ] }),
235
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
236
- /* @__PURE__ */ jsxs("label", { className: FIELD_LABEL, children: [
237
- "Scope ",
238
- /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
239
- ] }),
240
- /* @__PURE__ */ jsx(
241
- "input",
242
- {
243
- type: "text",
244
- disabled,
245
- value: value.scope,
246
- onChange: (e) => set("scope", e.target.value),
247
- placeholder: "e.g. Instagram + YouTube only",
248
- className: INPUT_BASE
249
- }
250
- )
251
- ] }),
252
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
253
- /* @__PURE__ */ jsxs("label", { className: FIELD_LABEL, children: [
254
- "Deliverables ",
255
- /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
256
- ] }),
257
- /* @__PURE__ */ jsx(
258
- "textarea",
259
- {
260
- disabled,
261
- value: value.deliverables,
262
- onChange: (e) => set("deliverables", e.target.value),
263
- placeholder: "e.g. 3 posts, 1 video",
264
- rows: 2,
265
- className: cn(INPUT_BASE, "h-auto py-2.5 resize-y")
266
- }
267
- )
268
- ] }),
167
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
168
+ /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "License length" }),
169
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_auto] gap-2", children: [
269
170
  /* @__PURE__ */ jsx(
270
- YesNoToggle,
171
+ "input",
271
172
  {
272
- label: "Exclusive to this sponsor",
273
- help: "No other sponsors during the license term.",
274
- checked: value.exclusive,
275
- onChange: (v) => set("exclusive", v),
276
- disabled
173
+ type: "number",
174
+ min: 1,
175
+ disabled,
176
+ value: value.durationValue,
177
+ onChange: (e) => set("durationValue", e.target.value),
178
+ placeholder: "e.g. 30",
179
+ className: INPUT_BASE
277
180
  }
278
181
  ),
279
182
  /* @__PURE__ */ jsx(
280
- YesNoToggle,
183
+ "select",
281
184
  {
282
- label: "Content approval required",
283
- help: "Sponsor reviews content before it's published.",
284
- checked: value.approvalRequired,
285
- onChange: (v) => set("approvalRequired", v),
286
- disabled
185
+ disabled,
186
+ value: value.durationUnit,
187
+ onChange: (e) => set("durationUnit", e.target.value),
188
+ className: cn(INPUT_BASE, "w-28"),
189
+ children: DURATION_UNITS.map((u) => /* @__PURE__ */ jsx("option", { value: u, children: u }, u))
287
190
  }
288
- ),
289
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
290
- /* @__PURE__ */ jsxs("label", { className: FIELD_LABEL, children: [
291
- "Media ",
292
- /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
293
- ] }),
294
- /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: MEDIA_TYPES.map((m) => /* @__PURE__ */ jsx(
295
- "button",
296
- {
297
- type: "button",
298
- disabled,
299
- onClick: () => toggleMedia(m),
300
- className: cn(
301
- "h-8 px-2.5 rounded-full border text-xs font-medium transition-colors disabled:opacity-50",
302
- value.media.includes(m) ? "border-brand-purple bg-brand-purple/10 text-foreground" : "border-border bg-card text-muted-foreground hover:text-foreground"
303
- ),
304
- children: m
305
- },
306
- m
307
- )) }),
308
- /* @__PURE__ */ jsx(
309
- "input",
310
- {
311
- type: "text",
312
- disabled,
313
- value: value.mediaOther,
314
- onChange: (e) => set("mediaOther", e.target.value),
315
- placeholder: "Other media type",
316
- className: cn(INPUT_BASE, "mt-1.5")
317
- }
318
- )
319
- ] }),
320
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
321
- /* @__PURE__ */ jsxs("label", { className: FIELD_LABEL, children: [
322
- "Additional terms ",
323
- /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
324
- ] }),
325
- /* @__PURE__ */ jsx(
326
- "textarea",
327
- {
328
- disabled,
329
- value: value.licenseText,
330
- onChange: (e) => set("licenseText", e.target.value),
331
- placeholder: "Anything else worth spelling out.",
332
- rows: 3,
333
- className: cn(INPUT_BASE, "h-auto py-2.5 resize-y")
334
- }
191
+ )
192
+ ] }),
193
+ /* @__PURE__ */ jsx("p", { className: FIELD_HELP, children: "Counted from the moment the deal is accepted, not from today." })
194
+ ] }),
195
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
196
+ /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "License type" }),
197
+ /* @__PURE__ */ jsx(
198
+ "select",
199
+ {
200
+ disabled,
201
+ value: value.licenseType,
202
+ onChange: (e) => handleLicenseTypeChange(e.target.value),
203
+ className: INPUT_BASE,
204
+ children: LICENSE_TYPES.map((l) => /* @__PURE__ */ jsx("option", { value: l.value, children: l.label }, l.value))
205
+ }
206
+ ),
207
+ selectedLicense ? /* @__PURE__ */ jsx("p", { className: FIELD_HELP, children: selectedLicense.description }) : null
208
+ ] }),
209
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
210
+ /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "Commercial use" }),
211
+ /* @__PURE__ */ jsx(ToggleGroup, { value: value.commercialUse, options: ["Yes", "No"], onChange: (v) => set("commercialUse", v), disabled })
212
+ ] }),
213
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
214
+ /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "Derivatives" }),
215
+ /* @__PURE__ */ jsx(ToggleGroup, { value: value.derivatives, options: ["Allowed", "Not Allowed", "Share-Alike"], onChange: (v) => set("derivatives", v), disabled })
216
+ ] }),
217
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
218
+ /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "Attribution" }),
219
+ /* @__PURE__ */ jsx(ToggleGroup, { value: value.attribution, options: ["Required", "Not Required"], onChange: (v) => set("attribution", v), disabled })
220
+ ] }),
221
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
222
+ /* @__PURE__ */ jsxs("label", { className: FIELD_LABEL, children: [
223
+ "Territory ",
224
+ /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
225
+ ] }),
226
+ /* @__PURE__ */ jsx(
227
+ "input",
228
+ {
229
+ type: "text",
230
+ disabled,
231
+ value: value.territory,
232
+ onChange: (e) => set("territory", e.target.value),
233
+ placeholder: "e.g. Worldwide, Brazil only, excluding China",
234
+ className: INPUT_BASE
235
+ }
236
+ )
237
+ ] }),
238
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
239
+ /* @__PURE__ */ jsx("label", { className: FIELD_LABEL, children: "AI policy" }),
240
+ /* @__PURE__ */ jsx(
241
+ "select",
242
+ {
243
+ disabled,
244
+ value: value.aiPolicy,
245
+ onChange: (e) => set("aiPolicy", e.target.value),
246
+ className: INPUT_BASE,
247
+ children: AI_POLICIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: p }, p))
248
+ }
249
+ ),
250
+ /* @__PURE__ */ jsx("p", { className: FIELD_HELP, children: "Whether this work can be used to train AI models." })
251
+ ] }),
252
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
253
+ /* @__PURE__ */ jsxs("label", { className: FIELD_LABEL, children: [
254
+ "Scope ",
255
+ /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
256
+ ] }),
257
+ /* @__PURE__ */ jsx(
258
+ "input",
259
+ {
260
+ type: "text",
261
+ disabled,
262
+ value: value.scope,
263
+ onChange: (e) => set("scope", e.target.value),
264
+ placeholder: "e.g. Instagram + YouTube only",
265
+ className: INPUT_BASE
266
+ }
267
+ )
268
+ ] }),
269
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
270
+ /* @__PURE__ */ jsxs("label", { className: FIELD_LABEL, children: [
271
+ "Deliverables ",
272
+ /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
273
+ ] }),
274
+ /* @__PURE__ */ jsx(
275
+ "textarea",
276
+ {
277
+ disabled,
278
+ value: value.deliverables,
279
+ onChange: (e) => set("deliverables", e.target.value),
280
+ placeholder: "e.g. 3 posts, 1 video",
281
+ rows: 2,
282
+ className: cn(INPUT_BASE, "h-auto py-2.5 resize-y")
283
+ }
284
+ )
285
+ ] }),
286
+ /* @__PURE__ */ jsx(
287
+ YesNoToggle,
288
+ {
289
+ label: "Exclusive to this sponsor",
290
+ help: "No other sponsors during the license term.",
291
+ checked: value.exclusive,
292
+ onChange: (v) => set("exclusive", v),
293
+ disabled
294
+ }
295
+ ),
296
+ /* @__PURE__ */ jsx(
297
+ YesNoToggle,
298
+ {
299
+ label: "Content approval required",
300
+ help: "Sponsor reviews content before it's published.",
301
+ checked: value.approvalRequired,
302
+ onChange: (v) => set("approvalRequired", v),
303
+ disabled
304
+ }
305
+ ),
306
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
307
+ /* @__PURE__ */ jsxs("label", { className: FIELD_LABEL, children: [
308
+ "Media ",
309
+ /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
310
+ ] }),
311
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: MEDIA_TYPES.map((m) => /* @__PURE__ */ jsx(
312
+ "button",
313
+ {
314
+ type: "button",
315
+ disabled,
316
+ onClick: () => toggleMedia(m),
317
+ className: cn(
318
+ "h-8 px-2.5 rounded-full border text-xs font-medium transition-colors disabled:opacity-50",
319
+ value.media.includes(m) ? "border-brand-purple bg-brand-purple/10 text-foreground" : "border-border bg-card text-muted-foreground hover:text-foreground"
335
320
  ),
336
- /* @__PURE__ */ jsx("p", { className: FIELD_HELP, children: "Saved permanently and shown to anyone who holds the license." })
337
- ] })
338
- ] })
321
+ children: m
322
+ },
323
+ m
324
+ )) }),
325
+ /* @__PURE__ */ jsx(
326
+ "input",
327
+ {
328
+ type: "text",
329
+ disabled,
330
+ value: value.mediaOther,
331
+ onChange: (e) => set("mediaOther", e.target.value),
332
+ placeholder: "Other media type",
333
+ className: cn(INPUT_BASE, "mt-1.5")
334
+ }
335
+ )
336
+ ] }),
337
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
338
+ /* @__PURE__ */ jsxs("label", { className: FIELD_LABEL, children: [
339
+ "Additional terms ",
340
+ /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: "(optional)" })
341
+ ] }),
342
+ /* @__PURE__ */ jsx(
343
+ "textarea",
344
+ {
345
+ disabled,
346
+ value: value.licenseText,
347
+ onChange: (e) => set("licenseText", e.target.value),
348
+ placeholder: "Anything else worth spelling out.",
349
+ rows: 3,
350
+ className: cn(INPUT_BASE, "h-auto py-2.5 resize-y")
351
+ }
352
+ ),
353
+ /* @__PURE__ */ jsx("p", { className: FIELD_HELP, children: "Saved permanently and shown to anyone who holds the license." })
339
354
  ] })
340
355
  ] });
341
356
  }
342
357
  export {
358
+ DURATION_UNITS,
343
359
  EMPTY_SPONSORSHIP_TERMS,
344
360
  LicenseTermsBuilder,
345
361
  MEDIA_TYPES,
362
+ toDurationDays,
346
363
  toLicenseMetadata
347
364
  };
348
365
  //# sourceMappingURL=license-terms-builder.js.map
@@ -1 +1 @@
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":[]}
1
+ {"version":3,"sources":["../../src/components/license-terms-builder.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"../utils/cn.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { LICENSE_TYPES, AI_POLICIES } from \"../data/ip.js\";\n\n/** Duration units — the on-chain `duration` arg is seconds, but nobody\n * should be forced to think in days for a multi-year deal (or forced into\n * days at all — this is declarative, not contract-enforced). */\nexport const DURATION_UNITS = [\"Days\", \"Weeks\", \"Months\", \"Years\"] as const;\nexport type DurationUnit = (typeof DURATION_UNITS)[number];\nconst DURATION_UNIT_DAYS: Record<DurationUnit, number> = { Days: 1, Weeks: 7, Months: 30, Years: 365 };\n\n/** Converts the user-entered value + unit into whole days for the contract's\n * `duration` arg (seconds = days * 86400, done by the caller). */\nexport function toDurationDays(terms: SponsorshipTerms): number {\n const raw = Number(terms.durationValue || \"0\");\n if (!raw || raw <= 0) return 0;\n return Math.round(raw * DURATION_UNIT_DAYS[terms.durationUnit]);\n}\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 * Paired with `durationUnit`; convert with `toDurationDays()`. */\n durationValue: string;\n durationUnit: DurationUnit;\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 /** Free text — \"Worldwide\" is a fine default, but real deals often name a\n * specific country or an exclusion, which a fixed list can't cover. */\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 durationValue: \"\",\n durationUnit: \"Days\",\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=\"space-y-1.5\">\n <label className={FIELD_LABEL}>License length</label>\n <div className=\"grid grid-cols-[1fr_auto] gap-2\">\n <input\n type=\"number\"\n min={1}\n disabled={disabled}\n value={value.durationValue}\n onChange={(e) => set(\"durationValue\", e.target.value)}\n placeholder=\"e.g. 30\"\n className={INPUT_BASE}\n />\n <select\n disabled={disabled}\n value={value.durationUnit}\n onChange={(e) => set(\"durationUnit\", e.target.value as DurationUnit)}\n className={cn(INPUT_BASE, \"w-28\")}\n >\n {DURATION_UNITS.map((u) => (\n <option key={u} value={u}>{u}</option>\n ))}\n </select>\n </div>\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 <span className=\"font-normal text-muted-foreground\">(optional)</span></label>\n <input\n type=\"text\"\n disabled={disabled}\n value={value.territory}\n onChange={(e) => set(\"territory\", e.target.value)}\n placeholder=\"e.g. Worldwide, Brazil only, excluding China\"\n className={INPUT_BASE}\n />\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 );\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.2",
3
+ "version": "0.79.0",
4
4
  "description": "Shared UI components for Medialane apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",