import { useCallback, useEffect, useLayoutEffect, useRef, useState, type ReactNode } from 'react' import { createPortal } from 'react-dom' import { Link, useLocation } from 'react-router-dom' import { AnimatePresence, motion } from 'framer-motion' import { Cast, ChevronDown, Clock, Heart, ListMusic, LogOut, Settings, UserCog } from 'lucide-react' import clsx from 'clsx' import type { PlayProfile } from '../types' import { LayoutThemeToggle } from './LayoutThemeToggle' import type { ThemeMode } from './useThemeMode' type MenuPosition = { top: number right: number } type LayoutUser = { username?: string role?: string } type LayoutUserMenuProps = { user: LayoutUser | null | undefined isOpen: boolean profiles: PlayProfile[] activeProfileId: string | null activeProfile: PlayProfile | null onToggle: () => void onClose: () => void onUseDefaultProfile: () => void onSwitchProfile: (profile: PlayProfile) => void onLogout: () => void themeMode?: ThemeMode onThemeChange?: (mode: ThemeMode) => void } export function LayoutUserMenu({ user, isOpen, profiles, activeProfileId, activeProfile, onToggle, onClose, onUseDefaultProfile, onSwitchProfile, onLogout, themeMode, onThemeChange, }: LayoutUserMenuProps) { const location = useLocation() const triggerRef = useRef(null) const onCloseRef = useRef(onClose) const [menuPosition, setMenuPosition] = useState(null) onCloseRef.current = onClose const updateMenuPosition = useCallback(() => { const trigger = triggerRef.current if (!trigger) return const rect = trigger.getBoundingClientRect() setMenuPosition({ top: rect.bottom + 12, right: Math.max(8, window.innerWidth - rect.right), }) }, []) useLayoutEffect(() => { if (!isOpen) { setMenuPosition(null) return undefined } updateMenuPosition() window.addEventListener('resize', updateMenuPosition) window.addEventListener('scroll', updateMenuPosition, true) return () => { window.removeEventListener('resize', updateMenuPosition) window.removeEventListener('scroll', updateMenuPosition, true) } }, [isOpen, updateMenuPosition]) useEffect(() => { if (!isOpen) return undefined const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Escape') onCloseRef.current() } document.addEventListener('keydown', handleKeyDown) return () => { document.removeEventListener('keydown', handleKeyDown) } }, [isOpen]) useEffect(() => { onCloseRef.current() }, [location.pathname, location.search]) const menuPortal = isOpen && menuPosition && typeof document !== 'undefined' ? createPortal(