From 131ac29789c51bccb08ce1becac2a1e7c940a94c Mon Sep 17 00:00:00 2001 From: Serhat Kaya <59228830+serhatkaya@users.noreply.github.com> Date: Tue, 10 Dec 2024 13:09:58 +0300 Subject: [PATCH 1/2] feature: provide support for object breakpoints --- src/create.ts | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/create.ts b/src/create.ts index ff6e2d1..643a46c 100644 --- a/src/create.ts +++ b/src/create.ts @@ -2,15 +2,29 @@ import { useMemo, useState } from "react"; import { isBrowser, useIsomorphicEffect } from "./utils"; -export function create>(screens: TScreens) { - function useBreakpoint(breakpoint: keyof TScreens, defaultValue: boolean = false) { +export function create(screens: TScreens) { + function useBreakpoint( + breakpoint: keyof TScreens, + defaultValue: boolean = false + ) { const [match, setMatch] = useState(() => defaultValue); useIsomorphicEffect(() => { - if (!(isBrowser && "matchMedia" in window && window.matchMedia)) return undefined; + if (!(isBrowser && 'matchMedia' in window && window.matchMedia)) + return undefined; - const value = screens[breakpoint] ?? "999999px"; - const query = window.matchMedia(`(min-width: ${value})`); + const value = screens[breakpoint]; + let queryStr = ''; + + if (typeof value === 'string') { + queryStr = `(min-width: ${value})`; + } else if (typeof value === 'object') { + const { min, max } = value; + if (min) queryStr += `(min-width: ${min})`; + if (max) queryStr += `${min ? ' and ' : ''}(max-width: ${max})`; + } + + const query = window.matchMedia(queryStr); function listener(event: MediaQueryListEvent) { setMatch(event.matches); @@ -18,22 +32,32 @@ export function create>(screens: TScreen setMatch(query.matches); - query.addEventListener("change", listener); - return () => query.removeEventListener("change", listener); + query.addEventListener('change', listener); + return () => query.removeEventListener('change', listener); }, [breakpoint, defaultValue]); return match; } - function useBreakpointEffect(breakpoint: keyof TScreens, effect: (match: boolean) => void) { + function useBreakpointEffect( + breakpoint: keyof TScreens, + effect: (match: boolean) => void + ) { const match = useBreakpoint(breakpoint); useIsomorphicEffect(() => effect(match), [breakpoint, effect]); return null; } - function useBreakpointValue(breakpoint: keyof TScreens, valid: T, invalid: U) { + function useBreakpointValue( + breakpoint: keyof TScreens, + valid: T, + invalid: U + ) { const match = useBreakpoint(breakpoint); - const value = useMemo(() => (match ? valid : invalid), [invalid, match, valid]); + const value = useMemo( + () => (match ? valid : invalid), + [invalid, match, valid] + ); return value; } From d80b44a74285a53a0546ba976c2cedb1f35ba2e2 Mon Sep 17 00:00:00 2001 From: serhatkaya Date: Tue, 10 Dec 2024 13:11:48 +0300 Subject: [PATCH 2/2] fix: fix breakpoint type --- src/create.ts | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/src/create.ts b/src/create.ts index 643a46c..554ca5b 100644 --- a/src/create.ts +++ b/src/create.ts @@ -2,26 +2,22 @@ import { useMemo, useState } from "react"; import { isBrowser, useIsomorphicEffect } from "./utils"; -export function create(screens: TScreens) { - function useBreakpoint( - breakpoint: keyof TScreens, - defaultValue: boolean = false - ) { +export function create>(screens: TScreens) { + function useBreakpoint(breakpoint: keyof TScreens, defaultValue: boolean = false) { const [match, setMatch] = useState(() => defaultValue); useIsomorphicEffect(() => { - if (!(isBrowser && 'matchMedia' in window && window.matchMedia)) - return undefined; + if (!(isBrowser && "matchMedia" in window && window.matchMedia)) return undefined; const value = screens[breakpoint]; - let queryStr = ''; + let queryStr = ""; - if (typeof value === 'string') { + if (typeof value === "string") { queryStr = `(min-width: ${value})`; - } else if (typeof value === 'object') { + } else if (typeof value === "object") { const { min, max } = value; if (min) queryStr += `(min-width: ${min})`; - if (max) queryStr += `${min ? ' and ' : ''}(max-width: ${max})`; + if (max) queryStr += `${min ? " and " : ""}(max-width: ${max})`; } const query = window.matchMedia(queryStr); @@ -32,32 +28,22 @@ export function create(screens: TScreens) { setMatch(query.matches); - query.addEventListener('change', listener); - return () => query.removeEventListener('change', listener); + query.addEventListener("change", listener); + return () => query.removeEventListener("change", listener); }, [breakpoint, defaultValue]); return match; } - function useBreakpointEffect( - breakpoint: keyof TScreens, - effect: (match: boolean) => void - ) { + function useBreakpointEffect(breakpoint: keyof TScreens, effect: (match: boolean) => void) { const match = useBreakpoint(breakpoint); useIsomorphicEffect(() => effect(match), [breakpoint, effect]); return null; } - function useBreakpointValue( - breakpoint: keyof TScreens, - valid: T, - invalid: U - ) { + function useBreakpointValue(breakpoint: keyof TScreens, valid: T, invalid: U) { const match = useBreakpoint(breakpoint); - const value = useMemo( - () => (match ? valid : invalid), - [invalid, match, valid] - ); + const value = useMemo(() => (match ? valid : invalid), [invalid, match, valid]); return value; }