File size: 1,938 Bytes
fed832e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
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)'; // Detect dark mode
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 };
}
|