import clsx from 'clsx'; import React, { ReactNode, useEffect, useState } from 'react'; import { MdArrowBackIosNew } from 'react-icons/md'; import { useEnv } from '@/context/EnvContext'; import { useDrag } from '@/hooks/useDrag'; import { useResponsiveSize } from '@/hooks/useResponsiveSize'; import { impactFeedback } from '@tauri-apps/plugin-haptics'; const DISMISS_THRESHOLD = 100; const VELOCITY_THRESHOLD = 0.5; interface DialogProps { id?: string; isOpen: boolean; children: ReactNode; header?: ReactNode; title?: string; className?: string; boxClassName?: string; contentClassName?: string; onClose: () => void; } const Dialog: React.FC = ({ id, isOpen, children, header, title, className, boxClassName, contentClassName, onClose, }) => { const { appService } = useEnv(); const [translateY, setTranslateY] = useState(0); const iconSize22 = useResponsiveSize(22); const isMobile = window.innerWidth < 640; const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Escape') { onClose(); } }; useEffect(() => { window.addEventListener('keydown', handleKeyDown); return () => { window.removeEventListener('keydown', handleKeyDown); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleDragMove = (data: { clientY: number; deltaY: number }) => { if (!isMobile) return; const modal = document.querySelector('.modal-box') as HTMLElement; const overlay = document.querySelector('.overlay') as HTMLElement; if (modal && overlay) { modal.style.transition = ''; overlay.style.opacity = `${1 - data.clientY / window.innerHeight}`; } setTranslateY((prev) => Math.max(prev + data.deltaY, 0)); }; const handleDragEnd = (velocity: number) => { const modal = document.querySelector('.modal-box') as HTMLElement; if (!modal) return; if (translateY > DISMISS_THRESHOLD || velocity > VELOCITY_THRESHOLD) { modal.style.transition = `transform ${0.15 / velocity}s ease-out`; onClose(); setTimeout(() => setTranslateY(0), 300); if (appService?.hasHaptics) { impactFeedback('medium'); } } else { modal.style.transition = `transform 0.3s ease-out`; setTranslateY(0); if (appService?.hasHaptics) { impactFeedback('medium'); } } }; const { handleDragStart } = useDrag(handleDragMove, handleDragEnd); return (
{window.innerWidth < 640 && (
)}
{header ? ( header ) : (
{title ?? ''}
)}
{children}
); }; export default Dialog;