@penaprieto/design-system
Version:
Multi-brand React design system with design tokens from Figma
105 lines (104 loc) • 5.8 kB
JavaScript
;
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;