UNPKG

@penaprieto/design-system

Version:

Multi-brand React design system with design tokens from Figma

105 lines (104 loc) 5.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FileUpload = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); require("./FileUpload.css"); const Icon_1 = require("../Icon"); const Button_1 = require("../Button"); const FileUpload = ({ label, helperText, accept, multiple = false, maxSize, disabled = false, error = false, onChange, className = '', }) => { const [isDragging, setIsDragging] = (0, react_1.useState)(false); const [files, setFiles] = (0, react_1.useState)([]); const [errorMessage, setErrorMessage] = (0, react_1.useState)(''); const inputRef = (0, react_1.useRef)(null); const validateFiles = (fileList) => { if (!fileList) return []; const validFiles = []; const errors = []; Array.from(fileList).forEach((file) => { if (maxSize && file.size > maxSize) { errors.push(`${file.name} excede el tamaño máximo`); } else { validFiles.push(file); } }); if (errors.length > 0) { setErrorMessage(errors.join(', ')); } else { setErrorMessage(''); } return validFiles; }; const handleFiles = (fileList) => { const validFiles = validateFiles(fileList); if (validFiles.length > 0) { setFiles(validFiles); onChange === null || onChange === void 0 ? void 0 : onChange(validFiles); } }; const handleDragEnter = (e) => { e.preventDefault(); e.stopPropagation(); if (!disabled) { setIsDragging(true); } }; const handleDragLeave = (e) => { e.preventDefault(); e.stopPropagation(); setIsDragging(false); }; const handleDragOver = (e) => { e.preventDefault(); e.stopPropagation(); }; const handleDrop = (e) => { e.preventDefault(); e.stopPropagation(); setIsDragging(false); if (!disabled) { handleFiles(e.dataTransfer.files); } }; const handleInputChange = (e) => { handleFiles(e.target.files); }; const handleClick = () => { var _a; if (!disabled) { (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.click(); } }; const handleRemoveFile = (index) => { const newFiles = files.filter((_, i) => i !== index); setFiles(newFiles); onChange === null || onChange === void 0 ? void 0 : onChange(newFiles); }; const formatFileSize = (bytes) => { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]; }; const rootClassName = [ 'ds-file-upload', disabled && 'ds-file-upload--disabled', error && 'ds-file-upload--error', className, ] .filter(Boolean) .join(' '); const dropzoneClassName = [ 'ds-file-upload__dropzone', isDragging && 'ds-file-upload__dropzone--dragging', ] .filter(Boolean) .join(' '); return ((0, jsx_runtime_1.jsxs)("div", { className: rootClassName, children: [label && (0, jsx_runtime_1.jsx)("div", { className: "ds-file-upload__label", children: label }), (0, jsx_runtime_1.jsxs)("div", { className: dropzoneClassName, onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, onClick: handleClick, children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, type: "file", className: "ds-file-upload__input", accept: accept, multiple: multiple, disabled: disabled, onChange: handleInputChange }), (0, jsx_runtime_1.jsx)("div", { className: "ds-file-upload__icon", children: (0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: "upload", size: 32 }) }), (0, jsx_runtime_1.jsxs)("div", { className: "ds-file-upload__text", children: [(0, jsx_runtime_1.jsx)("span", { className: "ds-file-upload__primary-text", children: isDragging ? 'Suelta los archivos aquí' : 'Arrastra archivos aquí o haz clic para' }), (0, jsx_runtime_1.jsx)("span", { className: "ds-file-upload__link-text", children: "seleccionar archivos" })] }), accept && ((0, jsx_runtime_1.jsxs)("div", { className: "ds-file-upload__hint", children: ["Formatos aceptados: ", accept] })), maxSize && ((0, jsx_runtime_1.jsxs)("div", { className: "ds-file-upload__hint", children: ["Tama\u00F1o m\u00E1ximo: ", formatFileSize(maxSize)] }))] }), files.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "ds-file-upload__files", children: files.map((file, index) => ((0, jsx_runtime_1.jsxs)("div", { className: "ds-file-upload__file", children: [(0, jsx_runtime_1.jsx)("div", { className: "ds-file-upload__file-icon", children: (0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: "file", size: 20 }) }), (0, jsx_runtime_1.jsxs)("div", { className: "ds-file-upload__file-info", children: [(0, jsx_runtime_1.jsx)("div", { className: "ds-file-upload__file-name", children: file.name }), (0, jsx_runtime_1.jsx)("div", { className: "ds-file-upload__file-size", children: formatFileSize(file.size) })] }), (0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "ghost", shape: "icon", size: "small", onClick: () => handleRemoveFile(index), "aria-label": "Eliminar archivo", children: (0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: "x", size: 16 }) })] }, index))) })), (helperText || errorMessage) && ((0, jsx_runtime_1.jsx)("div", { className: "ds-file-upload__helper", children: errorMessage || helperText }))] })); }; exports.FileUpload = FileUpload;