mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 08:33:36 +00:00
59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
import { useState, useEffect, useRef } from 'react';
|
|
|
|
/**
|
|
* Hook to detect if a media query matches
|
|
* @param query - The media query string (e.g., '(max-width: 768px)')
|
|
* @returns boolean indicating if the media query matches
|
|
*/
|
|
export function useMediaQuery(query: string): boolean {
|
|
const [matches, setMatches] = useState(() => {
|
|
if (typeof window === 'undefined') return false;
|
|
return window.matchMedia(query).matches;
|
|
});
|
|
|
|
// Track if this is the initial mount to avoid redundant setMatches call
|
|
const isInitialMount = useRef(true);
|
|
|
|
useEffect(() => {
|
|
if (typeof window === 'undefined') return;
|
|
|
|
const mediaQuery = window.matchMedia(query);
|
|
const handleChange = (e: MediaQueryListEvent) => {
|
|
setMatches(e.matches);
|
|
};
|
|
|
|
// Only sync state when query changes after initial mount
|
|
// (initial mount already has correct value from useState initializer)
|
|
if (isInitialMount.current) {
|
|
isInitialMount.current = false;
|
|
} else {
|
|
setMatches(mediaQuery.matches);
|
|
}
|
|
|
|
// Listen for changes
|
|
mediaQuery.addEventListener('change', handleChange);
|
|
|
|
return () => {
|
|
mediaQuery.removeEventListener('change', handleChange);
|
|
};
|
|
}, [query]);
|
|
|
|
return matches;
|
|
}
|
|
|
|
/**
|
|
* Hook to detect if the device is mobile (screen width <= 768px)
|
|
* @returns boolean indicating if the device is mobile
|
|
*/
|
|
export function useIsMobile(): boolean {
|
|
return useMediaQuery('(max-width: 768px)');
|
|
}
|
|
|
|
/**
|
|
* Hook to detect if the device is tablet or smaller (screen width <= 1024px)
|
|
* @returns boolean indicating if the device is tablet or smaller
|
|
*/
|
|
export function useIsTablet(): boolean {
|
|
return useMediaQuery('(max-width: 1024px)');
|
|
}
|