"use client"; import { Menu as MenuIcon, X as CloseIcon } from "lucide-react"; import Link from "next/link"; import { ChangeEvent, useEffect, useRef, useState } from "react"; import { usePathname } from "next/navigation"; import { DEFAULT_LOCALE, I18nKey, LOCALE_LABELS, Locale, SUPPORTED_LOCALES, translateText, } from "@/shared/config/i18n"; import { resolveInitialLocale, saveManualLocale, } from "@/features/i18n/model/resolveInitialLocale"; import { I18nProvider } from "@/features/i18n/model/useI18n"; export function I18nLayoutShell({ children, }: { children: React.ReactNode; }) { const pathname = usePathname(); const isLobby = pathname === "/"; const [locale, setLocale] = useState(DEFAULT_LOCALE); const [isMenuOpen, setIsMenuOpen] = useState(false); const menuRef = useRef(null); const menuButtonRef = useRef(null); useEffect(() => { const initialLocale = resolveInitialLocale(); setLocale(initialLocale); document.documentElement.lang = initialLocale; }, []); const handleSetLocale = (nextLocale: Locale) => { if (!SUPPORTED_LOCALES.includes(nextLocale)) return; setLocale(nextLocale); saveManualLocale(nextLocale); document.documentElement.lang = nextLocale; }; const handleLocaleChange = (event: ChangeEvent) => { const nextLocale = event.target.value as Locale; handleSetLocale(nextLocale); }; const t = (key: I18nKey) => translateText(locale, key); useEffect(() => { setIsMenuOpen(false); }, [pathname]); useEffect(() => { if (!isMenuOpen) return; const handlePointerDown = (event: PointerEvent) => { if (!menuRef.current) return; const target = event.target as Node | null; if (target && !menuRef.current.contains(target)) { setIsMenuOpen(false); } }; const handleEscape = (event: KeyboardEvent) => { if (event.key !== "Escape") return; setIsMenuOpen(false); menuButtonRef.current?.focus(); }; document.addEventListener("pointerdown", handlePointerDown); document.addEventListener("keydown", handleEscape); return () => { document.removeEventListener("pointerdown", handlePointerDown); document.removeEventListener("keydown", handleEscape); }; }, [isMenuOpen]); return (
FOCUSTELLA
{ if (!isMenuOpen) return; const nextFocused = event.relatedTarget as Node | null; if (nextFocused && event.currentTarget.contains(nextFocused)) { return; } setIsMenuOpen(false); }} > {isMenuOpen && (
)}
{children}
); }