amis-rpc-design/node_modules/antd/es/_util/responsiveObserver.js
2023-10-07 19:42:30 +08:00

107 lines
3.9 KiB
JavaScript

import React from 'react';
import { useToken } from '../theme/internal';
export const responsiveArray = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs'];
const getResponsiveMap = token => ({
xs: `(max-width: ${token.screenXSMax}px)`,
sm: `(min-width: ${token.screenSM}px)`,
md: `(min-width: ${token.screenMD}px)`,
lg: `(min-width: ${token.screenLG}px)`,
xl: `(min-width: ${token.screenXL}px)`,
xxl: `(min-width: ${token.screenXXL}px)`
});
/**
* Ensures that the breakpoints token are valid, in good order
* For each breakpoint : screenMin <= screen <= screenMax and screenMax <= nextScreenMin
*/
const validateBreakpoints = token => {
const indexableToken = token;
const revBreakpoints = [].concat(responsiveArray).reverse();
revBreakpoints.forEach((breakpoint, i) => {
const breakpointUpper = breakpoint.toUpperCase();
const screenMin = `screen${breakpointUpper}Min`;
const screen = `screen${breakpointUpper}`;
if (!(indexableToken[screenMin] <= indexableToken[screen])) {
throw new Error(`${screenMin}<=${screen} fails : !(${indexableToken[screenMin]}<=${indexableToken[screen]})`);
}
if (i < revBreakpoints.length - 1) {
const screenMax = `screen${breakpointUpper}Max`;
if (!(indexableToken[screen] <= indexableToken[screenMax])) {
throw new Error(`${screen}<=${screenMax} fails : !(${indexableToken[screen]}<=${indexableToken[screenMax]})`);
}
const nextBreakpointUpperMin = revBreakpoints[i + 1].toUpperCase();
const nextScreenMin = `screen${nextBreakpointUpperMin}Min`;
if (!(indexableToken[screenMax] <= indexableToken[nextScreenMin])) {
throw new Error(`${screenMax}<=${nextScreenMin} fails : !(${indexableToken[screenMax]}<=${indexableToken[nextScreenMin]})`);
}
}
});
return token;
};
export default function useResponsiveObserver() {
const [, token] = useToken();
const responsiveMap = getResponsiveMap(validateBreakpoints(token));
// To avoid repeat create instance, we add `useMemo` here.
return React.useMemo(() => {
const subscribers = new Map();
let subUid = -1;
let screens = {};
return {
matchHandlers: {},
dispatch(pointMap) {
screens = pointMap;
subscribers.forEach(func => func(screens));
return subscribers.size >= 1;
},
subscribe(func) {
if (!subscribers.size) this.register();
subUid += 1;
subscribers.set(subUid, func);
func(screens);
return subUid;
},
unsubscribe(paramToken) {
subscribers.delete(paramToken);
if (!subscribers.size) this.unregister();
},
unregister() {
Object.keys(responsiveMap).forEach(screen => {
const matchMediaQuery = responsiveMap[screen];
const handler = this.matchHandlers[matchMediaQuery];
handler === null || handler === void 0 ? void 0 : handler.mql.removeListener(handler === null || handler === void 0 ? void 0 : handler.listener);
});
subscribers.clear();
},
register() {
Object.keys(responsiveMap).forEach(screen => {
const matchMediaQuery = responsiveMap[screen];
const listener = _ref => {
let {
matches
} = _ref;
this.dispatch(Object.assign(Object.assign({}, screens), {
[screen]: matches
}));
};
const mql = window.matchMedia(matchMediaQuery);
mql.addListener(listener);
this.matchHandlers[matchMediaQuery] = {
mql,
listener
};
listener(mql);
});
},
responsiveMap
};
}, [token]);
}
export const matchScreen = (screens, screenSizes) => {
if (screenSizes && typeof screenSizes === 'object') {
for (let i = 0; i < responsiveArray.length; i++) {
const breakpoint = responsiveArray[i];
if (screens[breakpoint] && screenSizes[breakpoint] !== undefined) {
return screenSizes[breakpoint];
}
}
}
};