37 lines
1.1 KiB
TypeScript
37 lines
1.1 KiB
TypeScript
|
|
import { useSyncExternalStore } from "react"
|
|||
|
|
|
|||
|
|
const subscribeMediaQuery = (query: string) => (callback: () => void) => {
|
|||
|
|
if (typeof window === "undefined") return () => {}
|
|||
|
|
const mql = window.matchMedia(query)
|
|||
|
|
mql.addEventListener("change", callback)
|
|||
|
|
return () => mql.removeEventListener("change", callback)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const getMediaQuerySnapshot = (query: string) => () => {
|
|||
|
|
if (typeof window === "undefined") return false
|
|||
|
|
return window.matchMedia(query).matches
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function useMediaQuery(query: string): boolean {
|
|||
|
|
return useSyncExternalStore(
|
|||
|
|
subscribeMediaQuery(query),
|
|||
|
|
getMediaQuerySnapshot(query),
|
|||
|
|
() => false,
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 移动端:< 768px(对应 Tailwind md 断点以下)
|
|||
|
|
export function useIsMobile(): boolean {
|
|||
|
|
return useMediaQuery("(max-width: 47.999rem)")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 桌面端:>= 768px
|
|||
|
|
export function useIsDesktop(): boolean {
|
|||
|
|
return useMediaQuery("(min-width: 48rem)")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 窄桌面/平板横屏:< 1280px(对应 Tailwind xl 断点以下)
|
|||
|
|
export function useIsNarrowDesktop(): boolean {
|
|||
|
|
return useMediaQuery("(max-width: 79.999rem)")
|
|||
|
|
}
|