@medialane/ui 0.142.1 → 0.144.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.
@@ -32,7 +32,7 @@ var import_select = require("./select.js");
32
32
  var import_lucide_react = require("lucide-react");
33
33
  const createId = () => globalThis.crypto?.randomUUID?.() ?? `trait-${Date.now()}-${Math.random().toString(36).slice(2)}`;
34
34
  const looksLikeUrl = (v) => /^https?:\/\/\S+/i.test(v.trim());
35
- function IPTypeFields({ ipType, onChange, uploadDocument }) {
35
+ function IPTypeFields({ ipType, onChange, uploadDocument, existingDocument }) {
36
36
  const template = ipType ? import_ip_templates.IP_TEMPLATES[ipType] : null;
37
37
  const [embedValues, setEmbedValues] = (0, import_react.useState)({});
38
38
  const [socialValues, setSocialValues] = (0, import_react.useState)({});
@@ -49,6 +49,8 @@ function IPTypeFields({ ipType, onChange, uploadDocument }) {
49
49
  setDocName(null);
50
50
  setDocError(null);
51
51
  }, [ipType]);
52
+ const effectiveDocUri = existingDocument?.uri ?? docUri;
53
+ const effectiveDocName = existingDocument?.name ?? docName;
52
54
  const docTraitType = template?.docUpload?.traitType ?? null;
53
55
  const metadataFields = (0, import_react.useMemo)(() => {
54
56
  const fields = [];
@@ -61,12 +63,12 @@ function IPTypeFields({ ipType, onChange, uploadDocument }) {
61
63
  seen.add(k);
62
64
  fields.push({ traitType: t, value: v });
63
65
  };
64
- if (docTraitType && docUri) add(docTraitType, docUri);
66
+ if (docTraitType && effectiveDocUri) add(docTraitType, effectiveDocUri);
65
67
  Object.entries(embedValues).forEach(([key, value]) => add(key, value));
66
68
  Object.entries(socialValues).forEach(([key, value]) => add(key, value));
67
69
  traits.forEach((row) => add(row.key, row.value));
68
70
  return fields;
69
- }, [embedValues, socialValues, traits, docTraitType, docUri]);
71
+ }, [embedValues, socialValues, traits, docTraitType, effectiveDocUri]);
70
72
  (0, import_react.useEffect)(() => {
71
73
  onChange(metadataFields);
72
74
  }, [metadataFields, onChange]);
@@ -118,9 +120,15 @@ function IPTypeFields({ ipType, onChange, uploadDocument }) {
118
120
  " Details"
119
121
  ] })
120
122
  ] }),
121
- docUpload && uploadDocument && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "space-y-2", children: [
123
+ docUpload && (uploadDocument || existingDocument) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "space-y-2", children: [
122
124
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-[11px] font-semibold text-muted-foreground", children: "Document" }),
123
- docUri ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3", children: [
125
+ existingDocument ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3", children: [
126
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.FileText, { className: "h-5 w-5 text-emerald-500 shrink-0" }),
127
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "min-w-0 flex-1", children: [
128
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-medium truncate", children: effectiveDocName }),
129
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-muted-foreground", children: "Already attached as your uploaded file" })
130
+ ] })
131
+ ] }) : docUri ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3", children: [
124
132
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.FileText, { className: "h-5 w-5 text-emerald-500 shrink-0" }),
125
133
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "min-w-0 flex-1", children: [
126
134
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-medium truncate", children: docName }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/ip-type-fields.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport type { IPType } from \"../data/ip.js\";\nimport {\n IP_TEMPLATES,\n EMBED_PLATFORM_META,\n SOCIAL_PLATFORM_META,\n type TraitSuggestion,\n} from \"../data/ip-templates.js\";\nimport { Label } from \"./label.js\";\nimport { Input } from \"./input.js\";\nimport { Button } from \"./button.js\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"./select.js\";\nimport { Check, FileText, FileUp, Loader2, Plus, Trash2, X } from \"lucide-react\";\n\nexport type MetadataField = {\n traitType: string;\n value: string;\n};\n\ntype TraitRow = {\n id: string;\n key: string;\n value: string;\n options?: string[];\n};\n\nconst createId = () =>\n globalThis.crypto?.randomUUID?.() ?? `trait-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n\nconst looksLikeUrl = (v: string) => /^https?:\\/\\/\\S+/i.test(v.trim());\n\nexport interface IPTypeFieldsProps {\n ipType: IPType | null;\n onChange: (fields: MetadataField[]) => void;\n\n uploadDocument?: (file: File) => Promise<string>;\n}\n\nexport function IPTypeFields({ ipType, onChange, uploadDocument }: IPTypeFieldsProps) {\n const template = ipType ? IP_TEMPLATES[ipType] : null;\n\n const [embedValues, setEmbedValues] = useState<Record<string, string>>({});\n const [socialValues, setSocialValues] = useState<Record<string, string>>({});\n\n const [traits, setTraits] = useState<TraitRow[]>([]);\n\n const [docUri, setDocUri] = useState<string | null>(null);\n const [docName, setDocName] = useState<string | null>(null);\n const [docUploading, setDocUploading] = useState(false);\n const [docError, setDocError] = useState<string | null>(null);\n const docInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n setEmbedValues({});\n setSocialValues({});\n setDocUri(null);\n setDocName(null);\n setDocError(null);\n }, [ipType]);\n\n const docTraitType = template?.docUpload?.traitType ?? null;\n\n const metadataFields = useMemo(() => {\n const fields: MetadataField[] = [];\n const seen = new Set<string>();\n const add = (traitType: string, value: string) => {\n const t = traitType.trim();\n const v = value.trim();\n const k = t.toLowerCase();\n if (!t || !v || seen.has(k)) return;\n seen.add(k);\n fields.push({ traitType: t, value: v });\n };\n if (docTraitType && docUri) add(docTraitType, docUri);\n Object.entries(embedValues).forEach(([key, value]) => add(key, value));\n Object.entries(socialValues).forEach(([key, value]) => add(key, value));\n traits.forEach((row) => add(row.key, row.value));\n return fields;\n }, [embedValues, socialValues, traits, docTraitType, docUri]);\n\n useEffect(() => {\n onChange(metadataFields);\n }, [metadataFields, onChange]);\n\n const addedKeys = useMemo(\n () => new Set(traits.map((t) => t.key.trim().toLowerCase())),\n [traits]\n );\n\n const addSuggestion = (s: TraitSuggestion) => {\n setTraits((cur) => [\n ...cur,\n { id: createId(), key: s.key, value: \"\", options: s.options },\n ]);\n };\n const addCustomTrait = () =>\n setTraits((cur) => [...cur, { id: createId(), key: \"\", value: \"\" }]);\n const updateTrait = (id: string, patch: Partial<TraitRow>) =>\n setTraits((cur) => cur.map((t) => (t.id === id ? { ...t, ...patch } : t)));\n const removeTrait = (id: string) =>\n setTraits((cur) => cur.filter((t) => t.id !== id));\n\n if (!template) return null;\n\n const Icon = template.icon;\n const docUpload = template.docUpload;\n\n const handleDocPick = async (file: File) => {\n if (!uploadDocument || !docUpload) return;\n if (file.size > docUpload.maxMb * 1024 * 1024) {\n setDocError(`File must be under ${docUpload.maxMb} MB`);\n return;\n }\n setDocError(null);\n setDocUploading(true);\n try {\n const uri = await uploadDocument(file);\n setDocUri(uri);\n setDocName(file.name);\n } catch (err) {\n setDocError(err instanceof Error ? err.message : \"Document upload failed\");\n } finally {\n setDocUploading(false);\n if (docInputRef.current) docInputRef.current.value = \"\";\n }\n };\n\n const clearDoc = () => {\n setDocUri(null);\n setDocName(null);\n setDocError(null);\n };\n\n return (\n <div className=\"space-y-5\">\n <div className=\"flex items-center gap-2\">\n <Icon className={`h-4 w-4 ${template.color.text}`} />\n <p className=\"text-sm font-semibold\">{template.label} Details</p>\n </div>\n\n {docUpload && uploadDocument && (\n <section className=\"space-y-2\">\n <p className=\"text-[11px] font-semibold text-muted-foreground\">\n Document\n </p>\n {docUri ? (\n <div className=\"flex items-center gap-3 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3\">\n <FileText className=\"h-5 w-5 text-emerald-500 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\">{docName}</p>\n <p className=\"text-xs text-muted-foreground truncate\">{docUri}</p>\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 shrink-0 text-muted-foreground hover:text-destructive\"\n onClick={clearDoc}\n aria-label=\"Remove document\"\n >\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n ) : (\n <div className=\"space-y-1.5\">\n <input\n ref={docInputRef}\n type=\"file\"\n accept={docUpload.accept}\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) void handleDocPick(f);\n }}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={docUploading}\n onClick={() => docInputRef.current?.click()}\n >\n {docUploading ? (\n <>\n <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" />\n Uploading…\n </>\n ) : (\n <>\n <FileUp className=\"mr-1.5 h-3.5 w-3.5\" />\n Upload document\n </>\n )}\n </Button>\n {docError && <p className=\"text-xs text-destructive\">{docError}</p>}\n <p className=\"text-xs text-muted-foreground leading-relaxed\">{docUpload.hint}</p>\n </div>\n )}\n </section>\n )}\n\n {template.embeds && template.embeds.length > 0 && (\n <section className=\"space-y-3\">\n <p className=\"text-[11px] font-semibold text-muted-foreground\">Embeds</p>\n {template.embeds.map((platform) => {\n const meta = EMBED_PLATFORM_META[platform];\n const PIcon = meta.icon;\n const value = embedValues[meta.traitKey] ?? \"\";\n return (\n <div key={platform} className=\"space-y-1.5\">\n <Label className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <PIcon className=\"h-3.5 w-3.5\" />\n {meta.label}\n {looksLikeUrl(value) && (\n <span className=\"ml-1 inline-flex items-center gap-0.5 text-[10px] font-medium text-emerald-400\">\n <Check className=\"h-3 w-3\" /> connected\n </span>\n )}\n </Label>\n <Input\n type=\"url\"\n inputMode=\"url\"\n placeholder={meta.placeholder}\n value={value}\n onChange={(e) =>\n setEmbedValues((cur) => ({ ...cur, [meta.traitKey]: e.target.value }))\n }\n className=\"h-10 text-sm\"\n />\n </div>\n );\n })}\n </section>\n )}\n\n {template.socials && template.socials.length > 0 && (\n <section className=\"space-y-3\">\n <p className=\"text-[11px] font-semibold text-muted-foreground\">Social links</p>\n {template.socials.map((platform) => {\n const meta = SOCIAL_PLATFORM_META[platform];\n const PIcon = meta.icon;\n const value = socialValues[meta.traitKey] ?? \"\";\n return (\n <div key={platform} className=\"space-y-1.5\">\n <Label className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <PIcon className=\"h-3.5 w-3.5\" />\n {meta.label}\n </Label>\n <Input\n type=\"url\"\n inputMode=\"url\"\n placeholder={meta.placeholder}\n value={value}\n onChange={(e) =>\n setSocialValues((cur) => ({ ...cur, [meta.traitKey]: e.target.value }))\n }\n className=\"h-10 text-sm\"\n />\n </div>\n );\n })}\n </section>\n )}\n\n <section className=\"space-y-3 border-t border-border/60 pt-4\">\n <p className=\"text-sm font-semibold\">Traits</p>\n\n {template.traitSuggestions && template.traitSuggestions.length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {template.traitSuggestions\n .filter((s) => !addedKeys.has(s.key.toLowerCase()))\n .map((s) => (\n <button\n key={s.key}\n type=\"button\"\n onClick={() => addSuggestion(s)}\n className=\"inline-flex items-center gap-1 rounded-full border border-border bg-muted/40 px-3 py-1 text-xs font-medium text-muted-foreground transition-colors hover:border-primary/40 hover:text-foreground\"\n >\n <Plus className=\"h-3 w-3\" />\n {s.key}\n </button>\n ))}\n </div>\n )}\n\n {traits.length > 0 && (\n <div className=\"space-y-2\">\n {traits.map((row) => (\n <div\n key={row.id}\n className=\"grid grid-cols-[1fr_1fr_auto] items-center gap-2\"\n >\n <Input\n value={row.key}\n onChange={(e) => updateTrait(row.id, { key: e.target.value })}\n placeholder=\"Trait name\"\n className=\"h-9 text-sm\"\n maxLength={64}\n />\n {row.options ? (\n <Select\n value={row.value}\n onValueChange={(v) => updateTrait(row.id, { value: v })}\n >\n <SelectTrigger className=\"h-9 text-sm\">\n <SelectValue placeholder=\"Value\" />\n </SelectTrigger>\n <SelectContent>\n {row.options.map((opt) => (\n <SelectItem key={opt} value={opt}>{opt}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : (\n <Input\n value={row.value}\n onChange={(e) => updateTrait(row.id, { value: e.target.value })}\n placeholder=\"Value\"\n className=\"h-9 text-sm\"\n maxLength={512}\n />\n )}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-9 w-9 shrink-0 text-muted-foreground hover:text-destructive\"\n onClick={() => removeTrait(row.id)}\n aria-label=\"Remove trait\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n ))}\n </div>\n )}\n\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={addCustomTrait}>\n <Plus className=\"mr-1.5 h-3.5 w-3.5\" />\n Add custom trait\n </Button>\n </section>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/ip-type-fields.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport type { IPType } from \"../data/ip.js\";\nimport {\n IP_TEMPLATES,\n EMBED_PLATFORM_META,\n SOCIAL_PLATFORM_META,\n type TraitSuggestion,\n} from \"../data/ip-templates.js\";\nimport { Label } from \"./label.js\";\nimport { Input } from \"./input.js\";\nimport { Button } from \"./button.js\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"./select.js\";\nimport { Check, FileText, FileUp, Loader2, Plus, Trash2, X } from \"lucide-react\";\n\nexport type MetadataField = {\n traitType: string;\n value: string;\n};\n\ntype TraitRow = {\n id: string;\n key: string;\n value: string;\n options?: string[];\n};\n\nconst createId = () =>\n globalThis.crypto?.randomUUID?.() ?? `trait-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n\nconst looksLikeUrl = (v: string) => /^https?:\\/\\/\\S+/i.test(v.trim());\n\nexport interface IPTypeFieldsProps {\n ipType: IPType | null;\n onChange: (fields: MetadataField[]) => void;\n\n uploadDocument?: (file: File) => Promise<string>;\n\n /**\n * When the primary asset being minted is already the document this IP\n * type would otherwise ask to upload (e.g. a Documents/Publications type\n * whose main file is a PDF), pass it here to skip the redundant picker\n * and show it as already attached instead.\n */\n existingDocument?: { uri: string; name: string } | null;\n}\n\nexport function IPTypeFields({ ipType, onChange, uploadDocument, existingDocument }: IPTypeFieldsProps) {\n const template = ipType ? IP_TEMPLATES[ipType] : null;\n\n const [embedValues, setEmbedValues] = useState<Record<string, string>>({});\n const [socialValues, setSocialValues] = useState<Record<string, string>>({});\n\n const [traits, setTraits] = useState<TraitRow[]>([]);\n\n const [docUri, setDocUri] = useState<string | null>(null);\n const [docName, setDocName] = useState<string | null>(null);\n const [docUploading, setDocUploading] = useState(false);\n const [docError, setDocError] = useState<string | null>(null);\n const docInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n setEmbedValues({});\n setSocialValues({});\n setDocUri(null);\n setDocName(null);\n setDocError(null);\n }, [ipType]);\n\n const effectiveDocUri = existingDocument?.uri ?? docUri;\n const effectiveDocName = existingDocument?.name ?? docName;\n\n const docTraitType = template?.docUpload?.traitType ?? null;\n\n const metadataFields = useMemo(() => {\n const fields: MetadataField[] = [];\n const seen = new Set<string>();\n const add = (traitType: string, value: string) => {\n const t = traitType.trim();\n const v = value.trim();\n const k = t.toLowerCase();\n if (!t || !v || seen.has(k)) return;\n seen.add(k);\n fields.push({ traitType: t, value: v });\n };\n if (docTraitType && effectiveDocUri) add(docTraitType, effectiveDocUri);\n Object.entries(embedValues).forEach(([key, value]) => add(key, value));\n Object.entries(socialValues).forEach(([key, value]) => add(key, value));\n traits.forEach((row) => add(row.key, row.value));\n return fields;\n }, [embedValues, socialValues, traits, docTraitType, effectiveDocUri]);\n\n useEffect(() => {\n onChange(metadataFields);\n }, [metadataFields, onChange]);\n\n const addedKeys = useMemo(\n () => new Set(traits.map((t) => t.key.trim().toLowerCase())),\n [traits]\n );\n\n const addSuggestion = (s: TraitSuggestion) => {\n setTraits((cur) => [\n ...cur,\n { id: createId(), key: s.key, value: \"\", options: s.options },\n ]);\n };\n const addCustomTrait = () =>\n setTraits((cur) => [...cur, { id: createId(), key: \"\", value: \"\" }]);\n const updateTrait = (id: string, patch: Partial<TraitRow>) =>\n setTraits((cur) => cur.map((t) => (t.id === id ? { ...t, ...patch } : t)));\n const removeTrait = (id: string) =>\n setTraits((cur) => cur.filter((t) => t.id !== id));\n\n if (!template) return null;\n\n const Icon = template.icon;\n const docUpload = template.docUpload;\n\n const handleDocPick = async (file: File) => {\n if (!uploadDocument || !docUpload) return;\n if (file.size > docUpload.maxMb * 1024 * 1024) {\n setDocError(`File must be under ${docUpload.maxMb} MB`);\n return;\n }\n setDocError(null);\n setDocUploading(true);\n try {\n const uri = await uploadDocument(file);\n setDocUri(uri);\n setDocName(file.name);\n } catch (err) {\n setDocError(err instanceof Error ? err.message : \"Document upload failed\");\n } finally {\n setDocUploading(false);\n if (docInputRef.current) docInputRef.current.value = \"\";\n }\n };\n\n const clearDoc = () => {\n setDocUri(null);\n setDocName(null);\n setDocError(null);\n };\n\n return (\n <div className=\"space-y-5\">\n <div className=\"flex items-center gap-2\">\n <Icon className={`h-4 w-4 ${template.color.text}`} />\n <p className=\"text-sm font-semibold\">{template.label} Details</p>\n </div>\n\n {docUpload && (uploadDocument || existingDocument) && (\n <section className=\"space-y-2\">\n <p className=\"text-[11px] font-semibold text-muted-foreground\">\n Document\n </p>\n {existingDocument ? (\n <div className=\"flex items-center gap-3 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3\">\n <FileText className=\"h-5 w-5 text-emerald-500 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\">{effectiveDocName}</p>\n <p className=\"text-xs text-muted-foreground\">Already attached as your uploaded file</p>\n </div>\n </div>\n ) : docUri ? (\n <div className=\"flex items-center gap-3 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3\">\n <FileText className=\"h-5 w-5 text-emerald-500 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\">{docName}</p>\n <p className=\"text-xs text-muted-foreground truncate\">{docUri}</p>\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 shrink-0 text-muted-foreground hover:text-destructive\"\n onClick={clearDoc}\n aria-label=\"Remove document\"\n >\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n ) : (\n <div className=\"space-y-1.5\">\n <input\n ref={docInputRef}\n type=\"file\"\n accept={docUpload.accept}\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) void handleDocPick(f);\n }}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={docUploading}\n onClick={() => docInputRef.current?.click()}\n >\n {docUploading ? (\n <>\n <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" />\n Uploading…\n </>\n ) : (\n <>\n <FileUp className=\"mr-1.5 h-3.5 w-3.5\" />\n Upload document\n </>\n )}\n </Button>\n {docError && <p className=\"text-xs text-destructive\">{docError}</p>}\n <p className=\"text-xs text-muted-foreground leading-relaxed\">{docUpload.hint}</p>\n </div>\n )}\n </section>\n )}\n\n {template.embeds && template.embeds.length > 0 && (\n <section className=\"space-y-3\">\n <p className=\"text-[11px] font-semibold text-muted-foreground\">Embeds</p>\n {template.embeds.map((platform) => {\n const meta = EMBED_PLATFORM_META[platform];\n const PIcon = meta.icon;\n const value = embedValues[meta.traitKey] ?? \"\";\n return (\n <div key={platform} className=\"space-y-1.5\">\n <Label className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <PIcon className=\"h-3.5 w-3.5\" />\n {meta.label}\n {looksLikeUrl(value) && (\n <span className=\"ml-1 inline-flex items-center gap-0.5 text-[10px] font-medium text-emerald-400\">\n <Check className=\"h-3 w-3\" /> connected\n </span>\n )}\n </Label>\n <Input\n type=\"url\"\n inputMode=\"url\"\n placeholder={meta.placeholder}\n value={value}\n onChange={(e) =>\n setEmbedValues((cur) => ({ ...cur, [meta.traitKey]: e.target.value }))\n }\n className=\"h-10 text-sm\"\n />\n </div>\n );\n })}\n </section>\n )}\n\n {template.socials && template.socials.length > 0 && (\n <section className=\"space-y-3\">\n <p className=\"text-[11px] font-semibold text-muted-foreground\">Social links</p>\n {template.socials.map((platform) => {\n const meta = SOCIAL_PLATFORM_META[platform];\n const PIcon = meta.icon;\n const value = socialValues[meta.traitKey] ?? \"\";\n return (\n <div key={platform} className=\"space-y-1.5\">\n <Label className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <PIcon className=\"h-3.5 w-3.5\" />\n {meta.label}\n </Label>\n <Input\n type=\"url\"\n inputMode=\"url\"\n placeholder={meta.placeholder}\n value={value}\n onChange={(e) =>\n setSocialValues((cur) => ({ ...cur, [meta.traitKey]: e.target.value }))\n }\n className=\"h-10 text-sm\"\n />\n </div>\n );\n })}\n </section>\n )}\n\n <section className=\"space-y-3 border-t border-border/60 pt-4\">\n <p className=\"text-sm font-semibold\">Traits</p>\n\n {template.traitSuggestions && template.traitSuggestions.length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {template.traitSuggestions\n .filter((s) => !addedKeys.has(s.key.toLowerCase()))\n .map((s) => (\n <button\n key={s.key}\n type=\"button\"\n onClick={() => addSuggestion(s)}\n className=\"inline-flex items-center gap-1 rounded-full border border-border bg-muted/40 px-3 py-1 text-xs font-medium text-muted-foreground transition-colors hover:border-primary/40 hover:text-foreground\"\n >\n <Plus className=\"h-3 w-3\" />\n {s.key}\n </button>\n ))}\n </div>\n )}\n\n {traits.length > 0 && (\n <div className=\"space-y-2\">\n {traits.map((row) => (\n <div\n key={row.id}\n className=\"grid grid-cols-[1fr_1fr_auto] items-center gap-2\"\n >\n <Input\n value={row.key}\n onChange={(e) => updateTrait(row.id, { key: e.target.value })}\n placeholder=\"Trait name\"\n className=\"h-9 text-sm\"\n maxLength={64}\n />\n {row.options ? (\n <Select\n value={row.value}\n onValueChange={(v) => updateTrait(row.id, { value: v })}\n >\n <SelectTrigger className=\"h-9 text-sm\">\n <SelectValue placeholder=\"Value\" />\n </SelectTrigger>\n <SelectContent>\n {row.options.map((opt) => (\n <SelectItem key={opt} value={opt}>{opt}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : (\n <Input\n value={row.value}\n onChange={(e) => updateTrait(row.id, { value: e.target.value })}\n placeholder=\"Value\"\n className=\"h-9 text-sm\"\n maxLength={512}\n />\n )}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-9 w-9 shrink-0 text-muted-foreground hover:text-destructive\"\n onClick={() => removeTrait(row.id)}\n aria-label=\"Remove trait\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n ))}\n </div>\n )}\n\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={addCustomTrait}>\n <Plus className=\"mr-1.5 h-3.5 w-3.5\" />\n Add custom trait\n </Button>\n </section>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -9,7 +9,17 @@ interface IPTypeFieldsProps {
9
9
  ipType: IPType | null;
10
10
  onChange: (fields: MetadataField[]) => void;
11
11
  uploadDocument?: (file: File) => Promise<string>;
12
+ /**
13
+ * When the primary asset being minted is already the document this IP
14
+ * type would otherwise ask to upload (e.g. a Documents/Publications type
15
+ * whose main file is a PDF), pass it here to skip the redundant picker
16
+ * and show it as already attached instead.
17
+ */
18
+ existingDocument?: {
19
+ uri: string;
20
+ name: string;
21
+ } | null;
12
22
  }
13
- declare function IPTypeFields({ ipType, onChange, uploadDocument }: IPTypeFieldsProps): react_jsx_runtime.JSX.Element | null;
23
+ declare function IPTypeFields({ ipType, onChange, uploadDocument, existingDocument }: IPTypeFieldsProps): react_jsx_runtime.JSX.Element | null;
14
24
 
15
25
  export { IPTypeFields, type IPTypeFieldsProps, type MetadataField };
@@ -9,7 +9,17 @@ interface IPTypeFieldsProps {
9
9
  ipType: IPType | null;
10
10
  onChange: (fields: MetadataField[]) => void;
11
11
  uploadDocument?: (file: File) => Promise<string>;
12
+ /**
13
+ * When the primary asset being minted is already the document this IP
14
+ * type would otherwise ask to upload (e.g. a Documents/Publications type
15
+ * whose main file is a PDF), pass it here to skip the redundant picker
16
+ * and show it as already attached instead.
17
+ */
18
+ existingDocument?: {
19
+ uri: string;
20
+ name: string;
21
+ } | null;
12
22
  }
13
- declare function IPTypeFields({ ipType, onChange, uploadDocument }: IPTypeFieldsProps): react_jsx_runtime.JSX.Element | null;
23
+ declare function IPTypeFields({ ipType, onChange, uploadDocument, existingDocument }: IPTypeFieldsProps): react_jsx_runtime.JSX.Element | null;
14
24
 
15
25
  export { IPTypeFields, type IPTypeFieldsProps, type MetadataField };
@@ -19,7 +19,7 @@ import {
19
19
  import { Check, FileText, FileUp, Loader2, Plus, Trash2, X } from "lucide-react";
20
20
  const createId = () => globalThis.crypto?.randomUUID?.() ?? `trait-${Date.now()}-${Math.random().toString(36).slice(2)}`;
21
21
  const looksLikeUrl = (v) => /^https?:\/\/\S+/i.test(v.trim());
22
- function IPTypeFields({ ipType, onChange, uploadDocument }) {
22
+ function IPTypeFields({ ipType, onChange, uploadDocument, existingDocument }) {
23
23
  const template = ipType ? IP_TEMPLATES[ipType] : null;
24
24
  const [embedValues, setEmbedValues] = useState({});
25
25
  const [socialValues, setSocialValues] = useState({});
@@ -36,6 +36,8 @@ function IPTypeFields({ ipType, onChange, uploadDocument }) {
36
36
  setDocName(null);
37
37
  setDocError(null);
38
38
  }, [ipType]);
39
+ const effectiveDocUri = existingDocument?.uri ?? docUri;
40
+ const effectiveDocName = existingDocument?.name ?? docName;
39
41
  const docTraitType = template?.docUpload?.traitType ?? null;
40
42
  const metadataFields = useMemo(() => {
41
43
  const fields = [];
@@ -48,12 +50,12 @@ function IPTypeFields({ ipType, onChange, uploadDocument }) {
48
50
  seen.add(k);
49
51
  fields.push({ traitType: t, value: v });
50
52
  };
51
- if (docTraitType && docUri) add(docTraitType, docUri);
53
+ if (docTraitType && effectiveDocUri) add(docTraitType, effectiveDocUri);
52
54
  Object.entries(embedValues).forEach(([key, value]) => add(key, value));
53
55
  Object.entries(socialValues).forEach(([key, value]) => add(key, value));
54
56
  traits.forEach((row) => add(row.key, row.value));
55
57
  return fields;
56
- }, [embedValues, socialValues, traits, docTraitType, docUri]);
58
+ }, [embedValues, socialValues, traits, docTraitType, effectiveDocUri]);
57
59
  useEffect(() => {
58
60
  onChange(metadataFields);
59
61
  }, [metadataFields, onChange]);
@@ -105,9 +107,15 @@ function IPTypeFields({ ipType, onChange, uploadDocument }) {
105
107
  " Details"
106
108
  ] })
107
109
  ] }),
108
- docUpload && uploadDocument && /* @__PURE__ */ jsxs("section", { className: "space-y-2", children: [
110
+ docUpload && (uploadDocument || existingDocument) && /* @__PURE__ */ jsxs("section", { className: "space-y-2", children: [
109
111
  /* @__PURE__ */ jsx("p", { className: "text-[11px] font-semibold text-muted-foreground", children: "Document" }),
110
- docUri ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3", children: [
112
+ existingDocument ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3", children: [
113
+ /* @__PURE__ */ jsx(FileText, { className: "h-5 w-5 text-emerald-500 shrink-0" }),
114
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
115
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium truncate", children: effectiveDocName }),
116
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Already attached as your uploaded file" })
117
+ ] })
118
+ ] }) : docUri ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3", children: [
111
119
  /* @__PURE__ */ jsx(FileText, { className: "h-5 w-5 text-emerald-500 shrink-0" }),
112
120
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
113
121
  /* @__PURE__ */ jsx("p", { className: "text-sm font-medium truncate", children: docName }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/ip-type-fields.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport type { IPType } from \"../data/ip.js\";\nimport {\n IP_TEMPLATES,\n EMBED_PLATFORM_META,\n SOCIAL_PLATFORM_META,\n type TraitSuggestion,\n} from \"../data/ip-templates.js\";\nimport { Label } from \"./label.js\";\nimport { Input } from \"./input.js\";\nimport { Button } from \"./button.js\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"./select.js\";\nimport { Check, FileText, FileUp, Loader2, Plus, Trash2, X } from \"lucide-react\";\n\nexport type MetadataField = {\n traitType: string;\n value: string;\n};\n\ntype TraitRow = {\n id: string;\n key: string;\n value: string;\n options?: string[];\n};\n\nconst createId = () =>\n globalThis.crypto?.randomUUID?.() ?? `trait-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n\nconst looksLikeUrl = (v: string) => /^https?:\\/\\/\\S+/i.test(v.trim());\n\nexport interface IPTypeFieldsProps {\n ipType: IPType | null;\n onChange: (fields: MetadataField[]) => void;\n\n uploadDocument?: (file: File) => Promise<string>;\n}\n\nexport function IPTypeFields({ ipType, onChange, uploadDocument }: IPTypeFieldsProps) {\n const template = ipType ? IP_TEMPLATES[ipType] : null;\n\n const [embedValues, setEmbedValues] = useState<Record<string, string>>({});\n const [socialValues, setSocialValues] = useState<Record<string, string>>({});\n\n const [traits, setTraits] = useState<TraitRow[]>([]);\n\n const [docUri, setDocUri] = useState<string | null>(null);\n const [docName, setDocName] = useState<string | null>(null);\n const [docUploading, setDocUploading] = useState(false);\n const [docError, setDocError] = useState<string | null>(null);\n const docInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n setEmbedValues({});\n setSocialValues({});\n setDocUri(null);\n setDocName(null);\n setDocError(null);\n }, [ipType]);\n\n const docTraitType = template?.docUpload?.traitType ?? null;\n\n const metadataFields = useMemo(() => {\n const fields: MetadataField[] = [];\n const seen = new Set<string>();\n const add = (traitType: string, value: string) => {\n const t = traitType.trim();\n const v = value.trim();\n const k = t.toLowerCase();\n if (!t || !v || seen.has(k)) return;\n seen.add(k);\n fields.push({ traitType: t, value: v });\n };\n if (docTraitType && docUri) add(docTraitType, docUri);\n Object.entries(embedValues).forEach(([key, value]) => add(key, value));\n Object.entries(socialValues).forEach(([key, value]) => add(key, value));\n traits.forEach((row) => add(row.key, row.value));\n return fields;\n }, [embedValues, socialValues, traits, docTraitType, docUri]);\n\n useEffect(() => {\n onChange(metadataFields);\n }, [metadataFields, onChange]);\n\n const addedKeys = useMemo(\n () => new Set(traits.map((t) => t.key.trim().toLowerCase())),\n [traits]\n );\n\n const addSuggestion = (s: TraitSuggestion) => {\n setTraits((cur) => [\n ...cur,\n { id: createId(), key: s.key, value: \"\", options: s.options },\n ]);\n };\n const addCustomTrait = () =>\n setTraits((cur) => [...cur, { id: createId(), key: \"\", value: \"\" }]);\n const updateTrait = (id: string, patch: Partial<TraitRow>) =>\n setTraits((cur) => cur.map((t) => (t.id === id ? { ...t, ...patch } : t)));\n const removeTrait = (id: string) =>\n setTraits((cur) => cur.filter((t) => t.id !== id));\n\n if (!template) return null;\n\n const Icon = template.icon;\n const docUpload = template.docUpload;\n\n const handleDocPick = async (file: File) => {\n if (!uploadDocument || !docUpload) return;\n if (file.size > docUpload.maxMb * 1024 * 1024) {\n setDocError(`File must be under ${docUpload.maxMb} MB`);\n return;\n }\n setDocError(null);\n setDocUploading(true);\n try {\n const uri = await uploadDocument(file);\n setDocUri(uri);\n setDocName(file.name);\n } catch (err) {\n setDocError(err instanceof Error ? err.message : \"Document upload failed\");\n } finally {\n setDocUploading(false);\n if (docInputRef.current) docInputRef.current.value = \"\";\n }\n };\n\n const clearDoc = () => {\n setDocUri(null);\n setDocName(null);\n setDocError(null);\n };\n\n return (\n <div className=\"space-y-5\">\n <div className=\"flex items-center gap-2\">\n <Icon className={`h-4 w-4 ${template.color.text}`} />\n <p className=\"text-sm font-semibold\">{template.label} Details</p>\n </div>\n\n {docUpload && uploadDocument && (\n <section className=\"space-y-2\">\n <p className=\"text-[11px] font-semibold text-muted-foreground\">\n Document\n </p>\n {docUri ? (\n <div className=\"flex items-center gap-3 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3\">\n <FileText className=\"h-5 w-5 text-emerald-500 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\">{docName}</p>\n <p className=\"text-xs text-muted-foreground truncate\">{docUri}</p>\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 shrink-0 text-muted-foreground hover:text-destructive\"\n onClick={clearDoc}\n aria-label=\"Remove document\"\n >\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n ) : (\n <div className=\"space-y-1.5\">\n <input\n ref={docInputRef}\n type=\"file\"\n accept={docUpload.accept}\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) void handleDocPick(f);\n }}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={docUploading}\n onClick={() => docInputRef.current?.click()}\n >\n {docUploading ? (\n <>\n <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" />\n Uploading…\n </>\n ) : (\n <>\n <FileUp className=\"mr-1.5 h-3.5 w-3.5\" />\n Upload document\n </>\n )}\n </Button>\n {docError && <p className=\"text-xs text-destructive\">{docError}</p>}\n <p className=\"text-xs text-muted-foreground leading-relaxed\">{docUpload.hint}</p>\n </div>\n )}\n </section>\n )}\n\n {template.embeds && template.embeds.length > 0 && (\n <section className=\"space-y-3\">\n <p className=\"text-[11px] font-semibold text-muted-foreground\">Embeds</p>\n {template.embeds.map((platform) => {\n const meta = EMBED_PLATFORM_META[platform];\n const PIcon = meta.icon;\n const value = embedValues[meta.traitKey] ?? \"\";\n return (\n <div key={platform} className=\"space-y-1.5\">\n <Label className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <PIcon className=\"h-3.5 w-3.5\" />\n {meta.label}\n {looksLikeUrl(value) && (\n <span className=\"ml-1 inline-flex items-center gap-0.5 text-[10px] font-medium text-emerald-400\">\n <Check className=\"h-3 w-3\" /> connected\n </span>\n )}\n </Label>\n <Input\n type=\"url\"\n inputMode=\"url\"\n placeholder={meta.placeholder}\n value={value}\n onChange={(e) =>\n setEmbedValues((cur) => ({ ...cur, [meta.traitKey]: e.target.value }))\n }\n className=\"h-10 text-sm\"\n />\n </div>\n );\n })}\n </section>\n )}\n\n {template.socials && template.socials.length > 0 && (\n <section className=\"space-y-3\">\n <p className=\"text-[11px] font-semibold text-muted-foreground\">Social links</p>\n {template.socials.map((platform) => {\n const meta = SOCIAL_PLATFORM_META[platform];\n const PIcon = meta.icon;\n const value = socialValues[meta.traitKey] ?? \"\";\n return (\n <div key={platform} className=\"space-y-1.5\">\n <Label className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <PIcon className=\"h-3.5 w-3.5\" />\n {meta.label}\n </Label>\n <Input\n type=\"url\"\n inputMode=\"url\"\n placeholder={meta.placeholder}\n value={value}\n onChange={(e) =>\n setSocialValues((cur) => ({ ...cur, [meta.traitKey]: e.target.value }))\n }\n className=\"h-10 text-sm\"\n />\n </div>\n );\n })}\n </section>\n )}\n\n <section className=\"space-y-3 border-t border-border/60 pt-4\">\n <p className=\"text-sm font-semibold\">Traits</p>\n\n {template.traitSuggestions && template.traitSuggestions.length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {template.traitSuggestions\n .filter((s) => !addedKeys.has(s.key.toLowerCase()))\n .map((s) => (\n <button\n key={s.key}\n type=\"button\"\n onClick={() => addSuggestion(s)}\n className=\"inline-flex items-center gap-1 rounded-full border border-border bg-muted/40 px-3 py-1 text-xs font-medium text-muted-foreground transition-colors hover:border-primary/40 hover:text-foreground\"\n >\n <Plus className=\"h-3 w-3\" />\n {s.key}\n </button>\n ))}\n </div>\n )}\n\n {traits.length > 0 && (\n <div className=\"space-y-2\">\n {traits.map((row) => (\n <div\n key={row.id}\n className=\"grid grid-cols-[1fr_1fr_auto] items-center gap-2\"\n >\n <Input\n value={row.key}\n onChange={(e) => updateTrait(row.id, { key: e.target.value })}\n placeholder=\"Trait name\"\n className=\"h-9 text-sm\"\n maxLength={64}\n />\n {row.options ? (\n <Select\n value={row.value}\n onValueChange={(v) => updateTrait(row.id, { value: v })}\n >\n <SelectTrigger className=\"h-9 text-sm\">\n <SelectValue placeholder=\"Value\" />\n </SelectTrigger>\n <SelectContent>\n {row.options.map((opt) => (\n <SelectItem key={opt} value={opt}>{opt}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : (\n <Input\n value={row.value}\n onChange={(e) => updateTrait(row.id, { value: e.target.value })}\n placeholder=\"Value\"\n className=\"h-9 text-sm\"\n maxLength={512}\n />\n )}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-9 w-9 shrink-0 text-muted-foreground hover:text-destructive\"\n onClick={() => removeTrait(row.id)}\n aria-label=\"Remove trait\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n ))}\n </div>\n )}\n\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={addCustomTrait}>\n <Plus className=\"mr-1.5 h-3.5 w-3.5\" />\n Add custom trait\n </Button>\n </section>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/ip-type-fields.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport type { IPType } from \"../data/ip.js\";\nimport {\n IP_TEMPLATES,\n EMBED_PLATFORM_META,\n SOCIAL_PLATFORM_META,\n type TraitSuggestion,\n} from \"../data/ip-templates.js\";\nimport { Label } from \"./label.js\";\nimport { Input } from \"./input.js\";\nimport { Button } from \"./button.js\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"./select.js\";\nimport { Check, FileText, FileUp, Loader2, Plus, Trash2, X } from \"lucide-react\";\n\nexport type MetadataField = {\n traitType: string;\n value: string;\n};\n\ntype TraitRow = {\n id: string;\n key: string;\n value: string;\n options?: string[];\n};\n\nconst createId = () =>\n globalThis.crypto?.randomUUID?.() ?? `trait-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n\nconst looksLikeUrl = (v: string) => /^https?:\\/\\/\\S+/i.test(v.trim());\n\nexport interface IPTypeFieldsProps {\n ipType: IPType | null;\n onChange: (fields: MetadataField[]) => void;\n\n uploadDocument?: (file: File) => Promise<string>;\n\n /**\n * When the primary asset being minted is already the document this IP\n * type would otherwise ask to upload (e.g. a Documents/Publications type\n * whose main file is a PDF), pass it here to skip the redundant picker\n * and show it as already attached instead.\n */\n existingDocument?: { uri: string; name: string } | null;\n}\n\nexport function IPTypeFields({ ipType, onChange, uploadDocument, existingDocument }: IPTypeFieldsProps) {\n const template = ipType ? IP_TEMPLATES[ipType] : null;\n\n const [embedValues, setEmbedValues] = useState<Record<string, string>>({});\n const [socialValues, setSocialValues] = useState<Record<string, string>>({});\n\n const [traits, setTraits] = useState<TraitRow[]>([]);\n\n const [docUri, setDocUri] = useState<string | null>(null);\n const [docName, setDocName] = useState<string | null>(null);\n const [docUploading, setDocUploading] = useState(false);\n const [docError, setDocError] = useState<string | null>(null);\n const docInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n setEmbedValues({});\n setSocialValues({});\n setDocUri(null);\n setDocName(null);\n setDocError(null);\n }, [ipType]);\n\n const effectiveDocUri = existingDocument?.uri ?? docUri;\n const effectiveDocName = existingDocument?.name ?? docName;\n\n const docTraitType = template?.docUpload?.traitType ?? null;\n\n const metadataFields = useMemo(() => {\n const fields: MetadataField[] = [];\n const seen = new Set<string>();\n const add = (traitType: string, value: string) => {\n const t = traitType.trim();\n const v = value.trim();\n const k = t.toLowerCase();\n if (!t || !v || seen.has(k)) return;\n seen.add(k);\n fields.push({ traitType: t, value: v });\n };\n if (docTraitType && effectiveDocUri) add(docTraitType, effectiveDocUri);\n Object.entries(embedValues).forEach(([key, value]) => add(key, value));\n Object.entries(socialValues).forEach(([key, value]) => add(key, value));\n traits.forEach((row) => add(row.key, row.value));\n return fields;\n }, [embedValues, socialValues, traits, docTraitType, effectiveDocUri]);\n\n useEffect(() => {\n onChange(metadataFields);\n }, [metadataFields, onChange]);\n\n const addedKeys = useMemo(\n () => new Set(traits.map((t) => t.key.trim().toLowerCase())),\n [traits]\n );\n\n const addSuggestion = (s: TraitSuggestion) => {\n setTraits((cur) => [\n ...cur,\n { id: createId(), key: s.key, value: \"\", options: s.options },\n ]);\n };\n const addCustomTrait = () =>\n setTraits((cur) => [...cur, { id: createId(), key: \"\", value: \"\" }]);\n const updateTrait = (id: string, patch: Partial<TraitRow>) =>\n setTraits((cur) => cur.map((t) => (t.id === id ? { ...t, ...patch } : t)));\n const removeTrait = (id: string) =>\n setTraits((cur) => cur.filter((t) => t.id !== id));\n\n if (!template) return null;\n\n const Icon = template.icon;\n const docUpload = template.docUpload;\n\n const handleDocPick = async (file: File) => {\n if (!uploadDocument || !docUpload) return;\n if (file.size > docUpload.maxMb * 1024 * 1024) {\n setDocError(`File must be under ${docUpload.maxMb} MB`);\n return;\n }\n setDocError(null);\n setDocUploading(true);\n try {\n const uri = await uploadDocument(file);\n setDocUri(uri);\n setDocName(file.name);\n } catch (err) {\n setDocError(err instanceof Error ? err.message : \"Document upload failed\");\n } finally {\n setDocUploading(false);\n if (docInputRef.current) docInputRef.current.value = \"\";\n }\n };\n\n const clearDoc = () => {\n setDocUri(null);\n setDocName(null);\n setDocError(null);\n };\n\n return (\n <div className=\"space-y-5\">\n <div className=\"flex items-center gap-2\">\n <Icon className={`h-4 w-4 ${template.color.text}`} />\n <p className=\"text-sm font-semibold\">{template.label} Details</p>\n </div>\n\n {docUpload && (uploadDocument || existingDocument) && (\n <section className=\"space-y-2\">\n <p className=\"text-[11px] font-semibold text-muted-foreground\">\n Document\n </p>\n {existingDocument ? (\n <div className=\"flex items-center gap-3 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3\">\n <FileText className=\"h-5 w-5 text-emerald-500 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\">{effectiveDocName}</p>\n <p className=\"text-xs text-muted-foreground\">Already attached as your uploaded file</p>\n </div>\n </div>\n ) : docUri ? (\n <div className=\"flex items-center gap-3 rounded-xl border border-emerald-500/30 bg-emerald-500/5 px-4 py-3\">\n <FileText className=\"h-5 w-5 text-emerald-500 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium truncate\">{docName}</p>\n <p className=\"text-xs text-muted-foreground truncate\">{docUri}</p>\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 shrink-0 text-muted-foreground hover:text-destructive\"\n onClick={clearDoc}\n aria-label=\"Remove document\"\n >\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n ) : (\n <div className=\"space-y-1.5\">\n <input\n ref={docInputRef}\n type=\"file\"\n accept={docUpload.accept}\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) void handleDocPick(f);\n }}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={docUploading}\n onClick={() => docInputRef.current?.click()}\n >\n {docUploading ? (\n <>\n <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" />\n Uploading…\n </>\n ) : (\n <>\n <FileUp className=\"mr-1.5 h-3.5 w-3.5\" />\n Upload document\n </>\n )}\n </Button>\n {docError && <p className=\"text-xs text-destructive\">{docError}</p>}\n <p className=\"text-xs text-muted-foreground leading-relaxed\">{docUpload.hint}</p>\n </div>\n )}\n </section>\n )}\n\n {template.embeds && template.embeds.length > 0 && (\n <section className=\"space-y-3\">\n <p className=\"text-[11px] font-semibold text-muted-foreground\">Embeds</p>\n {template.embeds.map((platform) => {\n const meta = EMBED_PLATFORM_META[platform];\n const PIcon = meta.icon;\n const value = embedValues[meta.traitKey] ?? \"\";\n return (\n <div key={platform} className=\"space-y-1.5\">\n <Label className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <PIcon className=\"h-3.5 w-3.5\" />\n {meta.label}\n {looksLikeUrl(value) && (\n <span className=\"ml-1 inline-flex items-center gap-0.5 text-[10px] font-medium text-emerald-400\">\n <Check className=\"h-3 w-3\" /> connected\n </span>\n )}\n </Label>\n <Input\n type=\"url\"\n inputMode=\"url\"\n placeholder={meta.placeholder}\n value={value}\n onChange={(e) =>\n setEmbedValues((cur) => ({ ...cur, [meta.traitKey]: e.target.value }))\n }\n className=\"h-10 text-sm\"\n />\n </div>\n );\n })}\n </section>\n )}\n\n {template.socials && template.socials.length > 0 && (\n <section className=\"space-y-3\">\n <p className=\"text-[11px] font-semibold text-muted-foreground\">Social links</p>\n {template.socials.map((platform) => {\n const meta = SOCIAL_PLATFORM_META[platform];\n const PIcon = meta.icon;\n const value = socialValues[meta.traitKey] ?? \"\";\n return (\n <div key={platform} className=\"space-y-1.5\">\n <Label className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <PIcon className=\"h-3.5 w-3.5\" />\n {meta.label}\n </Label>\n <Input\n type=\"url\"\n inputMode=\"url\"\n placeholder={meta.placeholder}\n value={value}\n onChange={(e) =>\n setSocialValues((cur) => ({ ...cur, [meta.traitKey]: e.target.value }))\n }\n className=\"h-10 text-sm\"\n />\n </div>\n );\n })}\n </section>\n )}\n\n <section className=\"space-y-3 border-t border-border/60 pt-4\">\n <p className=\"text-sm font-semibold\">Traits</p>\n\n {template.traitSuggestions && template.traitSuggestions.length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {template.traitSuggestions\n .filter((s) => !addedKeys.has(s.key.toLowerCase()))\n .map((s) => (\n <button\n key={s.key}\n type=\"button\"\n onClick={() => addSuggestion(s)}\n className=\"inline-flex items-center gap-1 rounded-full border border-border bg-muted/40 px-3 py-1 text-xs font-medium text-muted-foreground transition-colors hover:border-primary/40 hover:text-foreground\"\n >\n <Plus className=\"h-3 w-3\" />\n {s.key}\n </button>\n ))}\n </div>\n )}\n\n {traits.length > 0 && (\n <div className=\"space-y-2\">\n {traits.map((row) => (\n <div\n key={row.id}\n className=\"grid grid-cols-[1fr_1fr_auto] items-center gap-2\"\n >\n <Input\n value={row.key}\n onChange={(e) => updateTrait(row.id, { key: e.target.value })}\n placeholder=\"Trait name\"\n className=\"h-9 text-sm\"\n maxLength={64}\n />\n {row.options ? (\n <Select\n value={row.value}\n onValueChange={(v) => updateTrait(row.id, { value: v })}\n >\n <SelectTrigger className=\"h-9 text-sm\">\n <SelectValue placeholder=\"Value\" />\n </SelectTrigger>\n <SelectContent>\n {row.options.map((opt) => (\n <SelectItem key={opt} value={opt}>{opt}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : (\n <Input\n value={row.value}\n onChange={(e) => updateTrait(row.id, { value: e.target.value })}\n placeholder=\"Value\"\n className=\"h-9 text-sm\"\n maxLength={512}\n />\n )}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-9 w-9 shrink-0 text-muted-foreground hover:text-destructive\"\n onClick={() => removeTrait(row.id)}\n aria-label=\"Remove trait\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n ))}\n </div>\n )}\n\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={addCustomTrait}>\n <Plus className=\"mr-1.5 h-3.5 w-3.5\" />\n Add custom trait\n </Button>\n </section>\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.142.1",
3
+ "version": "0.144.0",
4
4
  "description": "Shared UI components for Medialane apps",
5
5
  "type": "module",
6
6
  "sideEffects": false,