// components/Fileinput.js import { $, Tag, If, For } from "sigpro"; export const Fileinput = (props) => { const selectedFiles = $([]); const isDragging = $(false); const error = $(null); const maxBytes = (props.max || 2) * 1024 * 1024; const handleFiles = (files) => { const fileList = Array.from(files); error(null); if (fileList.find(f => f.size > maxBytes)) { error(`Máx ${props.max || 2}MB`); return; } selectedFiles([...selectedFiles(), ...fileList]); props.onselect?.(selectedFiles()); }; const removeFile = (idx) => { const updated = selectedFiles().filter((_, i) => i !== idx); selectedFiles(updated); props.onselect?.(updated); }; return Tag("div", { ...props, class: `fieldset w-full p-0 ${props.class ?? ''}` }, [ Tag("label", { class: () => `relative flex items-center justify-between w-full h-12 px-4 border-2 border-dashed rounded-lg cursor-pointer transition-all duration-200 ${isDragging() ? "border-primary bg-primary/10" : "border-base-content/20 bg-base-100 hover:bg-base-200"}`, ondragover: (e) => { e.preventDefault(); isDragging(true); }, ondragleave: () => isDragging(false), ondrop: (e) => { e.preventDefault(); isDragging(false); handleFiles(e.dataTransfer.files); } }, [ Tag("div", { class: "flex items-center gap-3 w-full" }, [ Tag("span", { class: "icon-[lucide--upload]" }), Tag("span", { class: "text-sm opacity-70 truncate grow text-left" }, "Arrastra o selecciona archivos..."), Tag("span", { class: "text-[10px] opacity-40 shrink-0" }, `Máx ${props.max || 2}MB`) ]), Tag("input", { type: "file", multiple: true, accept: props.accept || "*", class: "hidden", onchange: (e) => handleFiles(e.target.files) }) ]), () => error() && Tag("span", { class: "text-[10px] text-error mt-1 px-1 font-medium" }, error()), If(() => selectedFiles().length > 0, () => Tag("ul", { class: "mt-2 space-y-1" }, [ For(selectedFiles, (file, idx) => Tag("li", { class: "flex items-center justify-between p-1.5 pl-3 text-xs bg-base-200/50 rounded-md border border-base-300" }, [ Tag("div", { class: "flex items-center gap-2 truncate" }, [ Tag("span", { class: "opacity-50" }, "📄"), Tag("span", { class: "truncate font-medium max-w-[200px]" }, file.name), Tag("span", { class: "text-[9px] opacity-40" }, `(${(file.size / 1024).toFixed(0)} KB)`) ]), Tag("button", { type: "button", class: "btn btn-ghost btn-xs btn-circle", onclick: (e) => { e.preventDefault(); removeFile(idx); } }, Tag("span", { class: "icon-[lucide--x]" })) ]), (file) => file.name + file.lastModified ) ]) ) ]); };