<ElementQuery
import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import isNumber from 'lodash/isNumber';
import elementResizeDetector from 'element-resize-detector';
let erd;
if (__CLIENT__) {
erd = elementResizeDetector({
strategy: 'scroll'
});
}
export default class ElementQuery extends Component {
static propTypes = {
minWidth: PropTypes.number,
maxWidth: PropTypes.number,
minHeight: PropTypes.number,
maxHeight: PropTypes.number,
children: PropTypes.any,
// "values" are used for server-side rendering
values: PropTypes.shape({
width: PropTypes.number,
height: PropTypes.number
})
};
componentDidMount() {
this.$parent = ReactDOM.findDOMNode(this).parentElement;
erd.listenTo(this.$parent, this.onResize.bind(this));
}
componentWillUnmount() {
erd.removeAllListeners(this.$parent);
erd.uninstall(this.$parent);
}
onResize() {
this.forceUpdate();
}
isInsideRange(value, min, max) {
return (isNumber(min) ? value >= min : true) &&
(isNumber(max) ? value <= max : true);
}
matchesRules() {
const { values, minWidth, maxWidth, minHeight, maxHeight } = this.props;
if (__SERVER__ && values) {
return this.isInsideRange(values.width, minWidth, maxWidth) &&
this.isInsideRange(values.height, minHeight, maxHeight);
}
// TODO: should we always show the elements by default on the server?
if (!this.$parent) {
return true;
}
const width = this.$parent.offsetWidth;
const height = this.$parent.offsetHeight;
return this.isInsideRange(width, minWidth, maxWidth) &&
this.isInsideRange(height, minHeight, maxHeight);
}
render() {
if (this.matchesRules()) {
return this.props.children;
}
return <span />;
}
}