From 1c9d7348ed92de0c2deeb1efaeb957611064be52 Mon Sep 17 00:00:00 2001 From: gitea Date: Thu, 27 Nov 2025 16:52:35 -0300 Subject: [PATCH] =?UTF-8?q?=E2=9C=85=20Auto-Scroll=20Implementado=20en=20D?= =?UTF-8?q?rag=20&=20Drop=20Frontend=20v1.0.75=20Nueva=20Funcionalidad:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ Auto-scroll automático cuando arrastras cerca de los bordes del modal ✅ Zona de activación: 100 pixeles desde arriba/abajo ✅ Scroll suave: 10 pixeles cada 16ms (~60fps) ✅ Limpieza automática: Detiene el scroll cuando sueltas o sales del área Cómo Funciona: Arrastras una pregunta cerca del borde superior → scroll automático hacia arriba Arrastras cerca del borde inferior → scroll automático hacia abajo Alejas del borde → scroll se detiene Sueltas la pregunta → scroll se limpia --- frontend/package.json | 2 +- frontend/src/App.jsx | 56 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index 44da8bc..20cabf4 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "checklist-frontend", "private": true, - "version": "1.0.74", + "version": "1.0.75", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 6933f57..586d9e5 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -930,6 +930,8 @@ function QuestionsManagerModal({ checklist, onClose }) { const [loadingAudit, setLoadingAudit] = useState(false) const [draggedQuestion, setDraggedQuestion] = useState(null) const [dragOverQuestion, setDragOverQuestion] = useState(null) + const scrollContainerRef = useRef(null) + const autoScrollIntervalRef = useRef(null) const [formData, setFormData] = useState({ section: '', text: '', @@ -1225,6 +1227,12 @@ function QuestionsManagerModal({ checklist, onClose }) { e.currentTarget.style.opacity = '1' setDraggedQuestion(null) setDragOverQuestion(null) + + // Limpiar auto-scroll + if (autoScrollIntervalRef.current) { + clearInterval(autoScrollIntervalRef.current) + autoScrollIntervalRef.current = null + } } const handleDragOver = (e, question) => { @@ -1250,10 +1258,58 @@ function QuestionsManagerModal({ checklist, onClose }) { e.dataTransfer.dropEffect = 'move' setDragOverQuestion(question) + + // Auto-scroll cuando está cerca de los bordes + if (scrollContainerRef.current) { + const container = scrollContainerRef.current + const rect = container.getBoundingClientRect() + const scrollThreshold = 100 // Pixeles desde el borde para activar scroll + const scrollSpeed = 10 // Velocidad de scroll + + const mouseY = e.clientY + const distanceFromTop = mouseY - rect.top + const distanceFromBottom = rect.bottom - mouseY + + // Limpiar intervalo anterior si existe + if (autoScrollIntervalRef.current) { + clearInterval(autoScrollIntervalRef.current) + autoScrollIntervalRef.current = null + } + + // Scroll hacia arriba + if (distanceFromTop < scrollThreshold && container.scrollTop > 0) { + autoScrollIntervalRef.current = setInterval(() => { + if (container.scrollTop > 0) { + container.scrollTop -= scrollSpeed + } else { + clearInterval(autoScrollIntervalRef.current) + autoScrollIntervalRef.current = null + } + }, 16) // ~60fps + } + // Scroll hacia abajo + else if (distanceFromBottom < scrollThreshold && + container.scrollTop < container.scrollHeight - container.clientHeight) { + autoScrollIntervalRef.current = setInterval(() => { + if (container.scrollTop < container.scrollHeight - container.clientHeight) { + container.scrollTop += scrollSpeed + } else { + clearInterval(autoScrollIntervalRef.current) + autoScrollIntervalRef.current = null + } + }, 16) // ~60fps + } + } } const handleDragLeave = (e) => { setDragOverQuestion(null) + + // Limpiar auto-scroll si sale del área + if (autoScrollIntervalRef.current) { + clearInterval(autoScrollIntervalRef.current) + autoScrollIntervalRef.current = null + } } const handleDrop = async (e, targetQuestion) => {