/
useBreakpoint.ts
36 lines (29 loc) · 1.25 KB
/
useBreakpoint.ts
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
import { DefaultTheme, useTheme } from 'styled-components';
import { useMediaQuery } from './useMediaQuery';
export type BreakpointKey = keyof DefaultTheme['breakpoints'] | 'base';
export type BreakPointFilter = (keyof DefaultTheme['breakpoints'])[];
/**
* Returns the name of the current breakpoint. If `breakpointFilter` is given,
* returns the name of the largest breakpoint that matches the current window.
*/
export function useBreakpoint(
breakpointFilter?: BreakPointFilter
): BreakpointKey {
const { breakpoints } = useTheme();
const givenBreakpointNames = breakpointFilter ?? Object.keys(breakpoints);
// Get names/widths of breakpoints in descending order
const breakpointNames = Object.keys(breakpoints)
.filter(name => givenBreakpointNames.includes(name))
.reverse();
const breakpointWidths = Object.entries(breakpoints)
.filter(([name]) => breakpointNames.includes(name))
.map(bps => bps[1])
.reverse();
const listeners = breakpointWidths.map(v =>
// eslint-disable-next-line react-hooks/rules-of-hooks
useMediaQuery(`(min-width: ${v}px)`)
);
// Return the first breakpoint that's active
const activeIndex = listeners.findIndex(Boolean);
return (breakpointNames[activeIndex] ?? 'base') as BreakpointKey;
}