import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { CalendarRange, X } from 'lucide-react'; import { useTranslation } from 'react-i18next'; interface Props { from: string; to: string; onChange: (from: string, to: string) => void; } const CURRENT_YEAR = new Date().getFullYear(); export default function YearFilterButton({ from, to, onChange }: Props) { const { t } = useTranslation(); const [open, setOpen] = useState(false); const [popStyle, setPopStyle] = useState({}); const triggerRef = useRef(null); const popRef = useRef(null); const fromRef = useRef(null); const fromNum = parseInt(from, 10); const toNum = parseInt(to, 10); const active = !isNaN(fromNum) && !isNaN(toNum) && fromNum >= 1 && toNum >= 1; const updatePopStyle = () => { if (!triggerRef.current) return; const rect = triggerRef.current.getBoundingClientRect(); const MARGIN = 6; const WIDTH = 260; const MAX_H = 200; const spaceBelow = window.innerHeight - rect.bottom - MARGIN; const spaceAbove = rect.top - MARGIN; const useAbove = spaceBelow < 160 && spaceAbove > spaceBelow; const left = Math.min( Math.max(rect.left, 8), window.innerWidth - WIDTH - 8, ); setPopStyle({ position: 'fixed', left, width: WIDTH, ...(useAbove ? { bottom: window.innerHeight - rect.top + MARGIN } : { top: rect.bottom + MARGIN }), maxHeight: Math.min(MAX_H, useAbove ? spaceAbove : spaceBelow), zIndex: 99998, }); }; useLayoutEffect(() => { if (!open) return; updatePopStyle(); setTimeout(() => fromRef.current?.focus(), 0); }, [open]); useEffect(() => { if (!open) return; const onResize = () => updatePopStyle(); window.addEventListener('resize', onResize); window.addEventListener('scroll', onResize, true); return () => { window.removeEventListener('resize', onResize); window.removeEventListener('scroll', onResize, true); }; }, [open]); useEffect(() => { if (!open) return; const onDown = (e: MouseEvent) => { if ( !triggerRef.current?.contains(e.target as Node) && !popRef.current?.contains(e.target as Node) ) setOpen(false); }; const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false); }; document.addEventListener('mousedown', onDown); document.addEventListener('keydown', onKey); return () => { document.removeEventListener('mousedown', onDown); document.removeEventListener('keydown', onKey); }; }, [open]); const clear = () => { onChange('', ''); }; return ( <> {open && createPortal(
onChange(e.target.value, to)} />
onChange(from, e.target.value)} />
{active && (
)}
, document.body, )} ); }