1 | import React from 'react';
|
2 | import { useToken } from '../theme/internal';
|
3 | export const responsiveArray = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs'];
|
4 | const getResponsiveMap = token => ({
|
5 | xs: `(max-width: ${token.screenXSMax}px)`,
|
6 | sm: `(min-width: ${token.screenSM}px)`,
|
7 | md: `(min-width: ${token.screenMD}px)`,
|
8 | lg: `(min-width: ${token.screenLG}px)`,
|
9 | xl: `(min-width: ${token.screenXL}px)`,
|
10 | xxl: `(min-width: ${token.screenXXL}px)`
|
11 | });
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | const validateBreakpoints = token => {
|
17 | const indexableToken = token;
|
18 | const revBreakpoints = [].concat(responsiveArray).reverse();
|
19 | revBreakpoints.forEach((breakpoint, i) => {
|
20 | const breakpointUpper = breakpoint.toUpperCase();
|
21 | const screenMin = `screen${breakpointUpper}Min`;
|
22 | const screen = `screen${breakpointUpper}`;
|
23 | if (!(indexableToken[screenMin] <= indexableToken[screen])) {
|
24 | throw new Error(`${screenMin}<=${screen} fails : !(${indexableToken[screenMin]}<=${indexableToken[screen]})`);
|
25 | }
|
26 | if (i < revBreakpoints.length - 1) {
|
27 | const screenMax = `screen${breakpointUpper}Max`;
|
28 | if (!(indexableToken[screen] <= indexableToken[screenMax])) {
|
29 | throw new Error(`${screen}<=${screenMax} fails : !(${indexableToken[screen]}<=${indexableToken[screenMax]})`);
|
30 | }
|
31 | const nextBreakpointUpperMin = revBreakpoints[i + 1].toUpperCase();
|
32 | const nextScreenMin = `screen${nextBreakpointUpperMin}Min`;
|
33 | if (!(indexableToken[screenMax] <= indexableToken[nextScreenMin])) {
|
34 | throw new Error(`${screenMax}<=${nextScreenMin} fails : !(${indexableToken[screenMax]}<=${indexableToken[nextScreenMin]})`);
|
35 | }
|
36 | }
|
37 | });
|
38 | return token;
|
39 | };
|
40 | export default function useResponsiveObserver() {
|
41 | const [, token] = useToken();
|
42 | const responsiveMap = getResponsiveMap(validateBreakpoints(token));
|
43 |
|
44 | return React.useMemo(() => {
|
45 | const subscribers = new Map();
|
46 | let subUid = -1;
|
47 | let screens = {};
|
48 | return {
|
49 | matchHandlers: {},
|
50 | dispatch(pointMap) {
|
51 | screens = pointMap;
|
52 | subscribers.forEach(func => func(screens));
|
53 | return subscribers.size >= 1;
|
54 | },
|
55 | subscribe(func) {
|
56 | if (!subscribers.size) this.register();
|
57 | subUid += 1;
|
58 | subscribers.set(subUid, func);
|
59 | func(screens);
|
60 | return subUid;
|
61 | },
|
62 | unsubscribe(paramToken) {
|
63 | subscribers.delete(paramToken);
|
64 | if (!subscribers.size) this.unregister();
|
65 | },
|
66 | unregister() {
|
67 | Object.keys(responsiveMap).forEach(screen => {
|
68 | const matchMediaQuery = responsiveMap[screen];
|
69 | const handler = this.matchHandlers[matchMediaQuery];
|
70 | handler === null || handler === void 0 ? void 0 : handler.mql.removeListener(handler === null || handler === void 0 ? void 0 : handler.listener);
|
71 | });
|
72 | subscribers.clear();
|
73 | },
|
74 | register() {
|
75 | Object.keys(responsiveMap).forEach(screen => {
|
76 | const matchMediaQuery = responsiveMap[screen];
|
77 | const listener = _ref => {
|
78 | let {
|
79 | matches
|
80 | } = _ref;
|
81 | this.dispatch(Object.assign(Object.assign({}, screens), {
|
82 | [screen]: matches
|
83 | }));
|
84 | };
|
85 | const mql = window.matchMedia(matchMediaQuery);
|
86 | mql.addListener(listener);
|
87 | this.matchHandlers[matchMediaQuery] = {
|
88 | mql,
|
89 | listener
|
90 | };
|
91 | listener(mql);
|
92 | });
|
93 | },
|
94 | responsiveMap
|
95 | };
|
96 | }, [token]);
|
97 | }
|
98 | export const matchScreen = (screens, screenSizes) => {
|
99 | if (screenSizes && typeof screenSizes === 'object') {
|
100 | for (let i = 0; i < responsiveArray.length; i++) {
|
101 | const breakpoint = responsiveArray[i];
|
102 | if (screens[breakpoint] && screenSizes[breakpoint] !== undefined) {
|
103 | return screenSizes[breakpoint];
|
104 | }
|
105 | }
|
106 | }
|
107 | }; |
\ | No newline at end of file |