react-mqls
Version:
Javascript media query match for React.js
118 lines (117 loc) • 4.35 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = require("react");
const prop_types_1 = __importDefault(require("prop-types"));
const pull_1 = __importDefault(require("lodash/pull"));
;
const queryPreset = {
xs: '(max-width: 575px)',
sm: '(min-width: 576px)',
md: '(min-width: 768px)',
lg: '(min-width: 992px)',
xl: '(min-width: 1200px)',
xxl: '(min-width: 1600px)',
};
class MediaQuery extends react_1.Component {
constructor() {
super(...arguments);
this.mediaQueryList = {};
this.state = {
matchedQuery: this.props.queries.reduce((prev, curr) => {
return prev.concat(curr.query || queryPreset[curr.preset]);
}, []),
};
this.getMatched = (targetQuery) => {
const { queries } = this.props;
if (typeof targetQuery === 'undefined') {
return null;
}
return queries.filter(q => {
if (q.query === targetQuery) {
return true;
}
else if (queryPreset[q.preset] === targetQuery) {
return true;
}
return false;
})[0];
};
this.cancellableListener = (originQuery, mql) => {
if (mql.matches) {
const matchedQuery = this.state.matchedQuery.concat(originQuery);
this.setState({
matchedQuery,
});
}
else {
const matchedQuery = pull_1.default(this.state.matchedQuery, originQuery);
this.setState({
matchedQuery,
});
}
};
this.cancel = () => {
const { queries } = this.props;
if (Array.isArray(queries)) {
queries.forEach((mql) => {
if (this.mediaQueryList[mql.query]) {
this.mediaQueryList[mql.query].removeListener(this.cancellableListener);
}
});
}
};
}
componentDidMount() {
const { targetWindow = window } = this.props;
if (typeof targetWindow !== 'object') {
return;
}
if (typeof targetWindow.matchMedia !== 'function') {
console.error('Does not support matchMedia');
return;
}
const { queries } = this.props;
if (Array.isArray(queries)) {
queries.forEach((mql) => {
const { query, preset } = mql;
if (query && query.length) {
this.mediaQueryList[query] = targetWindow.matchMedia(query);
this.cancellableListener(query, this.mediaQueryList[query]);
this.mediaQueryList[query].addListener(this.cancellableListener.bind(this, query));
}
else if (preset && queryPreset[preset]) {
const querySet = queryPreset[preset];
this.mediaQueryList[querySet] = targetWindow.matchMedia(querySet);
this.cancellableListener(querySet, this.mediaQueryList[querySet]);
this.mediaQueryList[querySet].addListener(this.cancellableListener.bind(this, querySet));
}
});
}
else {
console.error('Does not support type');
return;
}
}
componentWillUnmount() {
this.cancel();
}
render() {
const { matchedQuery } = this.state;
const matched = this.getMatched(matchedQuery[matchedQuery.length - 1]);
if (matched) {
if (typeof matched.component === 'function') {
return matched.component();
}
return matched.component;
}
return null;
}
}
MediaQuery.propTypes = {
queries: prop_types_1.default.arrayOf(prop_types_1.default.object.isRequired),
targetWindow: prop_types_1.default.object,
};
exports.default = MediaQuery;