-
Notifications
You must be signed in to change notification settings - Fork 4
/
ContainerQuery.js
76 lines (59 loc) · 1.76 KB
/
ContainerQuery.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import React, { Component } from "react";
import PropTypes from "prop-types";
import Container from "@zeecoder/container-query";
class ContainerQuery extends Component {
constructor(props) {
super(props);
this.options = { ...this.props.options };
// Listen to size changes only if needed
if (typeof this.props.children === "function") {
this.options.handleResize = this.handleResize;
}
}
state = { width: 1, height: 1 };
ref = React.createRef();
handleResize = size => {
if (this.__willUnmount) {
return;
}
this.setState(size);
};
componentDidMount() {
new Container(this.ref.current, this.props.meta, this.options);
}
componentWillUnmount() {
this.__willUnmount = true;
}
render() {
// Removing all props only used by this component, and only passing
// through the rest that was supposedly meant for the wrapped child
const { options, as, meta, children, ...props } = this.props;
// Needs to start with a capital letter for the jsx compiler.
// @see https://stackoverflow.com/a/38823404
const TagName = as;
return (
<TagName {...props} ref={this.ref}>
{this.doRender()}
</TagName>
);
}
doRender() {
if (typeof this.props.children === "function") {
return this.props.children(this.state.width, this.state.height);
} else if (this.props.children) {
return this.props.children;
}
return null;
}
}
ContainerQuery.defaultProps = {
options: {},
as: "div"
};
ContainerQuery.propTypes = {
options: PropTypes.object,
as: PropTypes.string,
meta: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired,
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired
};
export default ContainerQuery;