| | import { useEffect, RefObject, useState } from 'react'; |
| |
|
| | export function useOutsideAlerter<T extends HTMLElement>( |
| | ref: RefObject<T>, |
| | handler: () => void, |
| | additionalDeps: unknown[], |
| | handleEscapeKey?: boolean, |
| | ) { |
| | useEffect(() => { |
| | function handleClickOutside(event: MouseEvent) { |
| | if (ref.current && !ref.current.contains(event.target as Node)) { |
| | handler(); |
| | } |
| | } |
| |
|
| | function handleEscape(event: KeyboardEvent) { |
| | if (event.key === 'Escape') { |
| | handler(); |
| | } |
| | } |
| |
|
| | document.addEventListener('mousedown', handleClickOutside); |
| | if (handleEscapeKey) { |
| | document.addEventListener('keydown', handleEscape); |
| | } |
| |
|
| | return () => { |
| | document.removeEventListener('mousedown', handleClickOutside); |
| | if (handleEscapeKey) { |
| | document.removeEventListener('keydown', handleEscape); |
| | } |
| | }; |
| | }, [ref, ...additionalDeps]); |
| | } |
| |
|
| | export function useMediaQuery() { |
| | const mobileQuery = '(max-width: 768px)'; |
| | const darkModeQuery = '(prefers-color-scheme: dark)'; |
| | const desktopQuery = '(min-width: 960px)'; |
| | const [isMobile, setIsMobile] = useState(false); |
| | const [isDesktop, setIsDesktop] = useState(false); |
| | const [isDarkMode, setIsDarkMode] = useState(false); |
| |
|
| | useEffect(() => { |
| | const mobileMedia = window.matchMedia(mobileQuery); |
| | const desktopMedia = window.matchMedia(desktopQuery); |
| | const darkModeMedia = window.matchMedia(darkModeQuery); |
| |
|
| | const updateMediaQueries = () => { |
| | setIsMobile(mobileMedia.matches); |
| | setIsDesktop(desktopMedia.matches); |
| | setIsDarkMode(darkModeMedia.matches); |
| | }; |
| |
|
| | updateMediaQueries(); |
| |
|
| | const listener = () => updateMediaQueries(); |
| | window.addEventListener('resize', listener); |
| |
|
| | return () => { |
| | window.removeEventListener('resize', listener); |
| | }; |
| | }, [mobileQuery, desktopQuery, darkModeQuery]); |
| |
|
| | return { isMobile, isDesktop, isDarkMode }; |
| | } |
| |
|