// Copyright (C) 2017-2025 Smart code 203358507 import { useEffect } from 'react'; import { useGamepad } from '../GamepadContext'; const useContentGamepadNavigation = ( sectionRef: React.RefObject, gamepadHandlerId: string ) => { const gamepad = useGamepad(); useEffect(() => { const handleGamepadNavigation = ( direction: 'left' | 'right' | 'up' | 'down' ) => { const elements = Array.from( sectionRef.current?.querySelectorAll('[tabindex="0"]') || [] ); if (elements.length === 0) return; const activeElement = sectionRef.current?.querySelector(':focus'); if (!activeElement) { elements[0].focus(); return; } let closestElement: HTMLDivElement | null = null; const currentRect = activeElement.getBoundingClientRect(); let closestDistance = Infinity; elements.forEach((el) => { if (el === activeElement) return; const rect = el.getBoundingClientRect(); let distance = Infinity; switch (direction) { case 'left': if ( rect.right <= currentRect.left && (rect.top === currentRect.top || (rect.top < currentRect.top && rect.bottom > currentRect.top) ) ) { distance = currentRect.left - rect.right; } break; case 'right': if ( currentRect.right <= rect.left && (rect.top === currentRect.top || (rect.top < currentRect.top && rect.bottom > currentRect.top) ) ) { distance = rect.left - currentRect.right; } break; case 'up': if ( rect.bottom <= currentRect.top && (rect.left === currentRect.left || (rect.left < currentRect.left && rect.right > currentRect.left) ) ) { distance = currentRect.top - rect.bottom; } break; case 'down': if ( rect.top >= currentRect.bottom && (rect.left === currentRect.left || (rect.left < currentRect.left && rect.right > currentRect.left) ) ) { distance = rect.top - currentRect.bottom; } break; } if (distance < closestDistance) { closestDistance = distance; closestElement = el; } }); if (closestElement) { closestElement.focus(); } }; const onSelect = () => { const elements = Array.from( sectionRef.current?.querySelectorAll('[tabindex="0"]') || [] ); if (elements.length === 0) return; const activeElement = sectionRef.current?.querySelector(':focus'); if (!activeElement) { elements[0].focus(); return; } const isActiveSelectElement = [activeElement.classList].some((className) => /^select-input/.test(className.toString())); if (!isActiveSelectElement) { activeElement?.click(); } }; gamepad?.on('analog', gamepadHandlerId, handleGamepadNavigation); gamepad?.on('buttonA', gamepadHandlerId, onSelect); return () => { gamepad?.off('analog', gamepadHandlerId); gamepad?.off('buttonA', gamepadHandlerId); }; }, [gamepad, gamepadHandlerId, sectionRef]); }; export default useContentGamepadNavigation;