Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / packages / components / hooks / useActiveBreakpoint.ts
blob31dac17e6f94fdc17099d1aa2998e16b8d80cc56
1 import { useEffect, useMemo, useState } from 'react';
3 import debounce from '@proton/utils/debounce';
5 type ActiveBreakpoint = 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | '2xlarge';
7 const getActiveBreakpoint = (): ActiveBreakpoint | '' => {
8     const bodyEl = document.querySelector('body');
9     if (!bodyEl) {
10         return '';
11     }
12     return window
13         .getComputedStyle(bodyEl, ':before')
14         .getPropertyValue('content')
15         .replace(/['"]+/g, '') as ActiveBreakpoint;
18 /** Contains React state setter of each instantiated hooks */
19 const callbackStack: Set<Function> = new Set();
20 const onResize = () => {
21     const result = getActiveBreakpoint();
22     for (let callback of callbackStack.values()) {
23         callback(result);
24     }
26 const onResizeDebounced = debounce(onResize, 250, { leading: true });
28 export interface Breakpoints {
29     activeBreakpoint: ActiveBreakpoint;
30     viewportWidth: {
31         // Defined in CSS
32         xsmall: boolean;
33         small: boolean;
34         medium: boolean;
35         large: boolean;
36         xlarge: boolean;
37         '2xlarge': boolean;
39         // Custom ones
40         '<=small': boolean;
41         '<=medium': boolean;
42         '>=large': boolean;
43     };
46 const useActiveBreakpoint = () => {
47     const [activeBreakpoint, setActiveBreakpoint] = useState(() => getActiveBreakpoint() as ActiveBreakpoint);
49     useEffect(() => {
50         if (callbackStack.size === 0) {
51             window.addEventListener('load', onResize);
52             window.addEventListener('resize', onResizeDebounced);
53         }
54         callbackStack.add(setActiveBreakpoint);
55         return () => {
56             callbackStack.delete(setActiveBreakpoint);
57             if (callbackStack.size === 0) {
58                 window.removeEventListener('load', onResize);
59                 window.removeEventListener('resize', onResizeDebounced);
60             }
61         };
62     }, []);
64     return useMemo((): Breakpoints => {
65         /*
66             isLargeDesktop  = 2xlarge
67             isMediumDesktop = xlarge
68             isSmallDesktop  = large
69             isTablet        = medium
70             isMobile        = small
71             isTinyMobile    = xsmall
72             --
73             isDesktop = >=large
74             isNarrow  = <=small
75         */
76         const viewportWidth = {
77             // Defined in CSS
78             xsmall: activeBreakpoint === 'xsmall',
79             small: activeBreakpoint === 'small',
80             medium: activeBreakpoint === 'medium',
81             large: activeBreakpoint === 'large',
82             xlarge: activeBreakpoint === 'xlarge',
83             '2xlarge': activeBreakpoint === '2xlarge',
85             // Custom ones
86             '<=small': false,
87             '<=medium': false,
88             '>=large': false,
89         };
91         viewportWidth['<=small'] = viewportWidth.small || viewportWidth.xsmall;
92         viewportWidth['<=medium'] = viewportWidth.small || viewportWidth.xsmall || viewportWidth.medium;
93         viewportWidth['>=large'] = viewportWidth['2xlarge'] || viewportWidth.xlarge || viewportWidth.large;
95         return {
96             activeBreakpoint,
97             viewportWidth,
98         };
99     }, [activeBreakpoint]);
102 export default useActiveBreakpoint;