Skip to content
Permalink
Browse files

feat(InView): Added an InView component

  • Loading branch information...
HHogg committed Feb 17, 2019
1 parent 8c630e8 commit 2fbd355c84785d399163d915000d6cb38176e956
Showing with 1,730 additions and 0 deletions.
  1. +94 −0 src/InView/InView.js
  2. +1 −0 src/index.js
  3. +1,635 −0 yarn.lock
@@ -0,0 +1,94 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import debounce from 'lodash.debounce';

const BUFFER = 20;

function isElementInViewport(el) {
const rect = el.getBoundingClientRect();

return rect.bottom > -BUFFER && rect.bottom < window.innerHeight + BUFFER &&
rect.right > -BUFFER && rect.right < window.innerWidth + BUFFER &&
rect.left > -BUFFER && rect.left < window.innerWidth + BUFFER &&
rect.top > -BUFFER && rect.top < window.innerHeight + BUFFER;
}

export default class InView extends PureComponent {
static propTypes = {
children: PropTypes.func.isRequired,
enabled: PropTypes.bool.isRequired,
};

static defaultProps = {
enabled: true,
};

constructor(props) {
super(props);
this.setRef = this.setRef.bind(this);
this.updateIsInView = debounce(this.updateIsInView.bind(this), 100);
this.state = {
isInView: false,
};
}

componentDidMount() {
const { enabled } = this.props;

if (enabled) {
this.updateIsInView();
this.addEventListeners();
}
}

componentDidUpdate(prevProps) {
const { enabled } = this.props;

if (enabled !== prevProps.enabled) {
if (enabled) {
this.updateIsInView();
this.addEventListeners();
} else {
this.removeEventListeners();
}
}
}

componentWillUnmount() {
this.removeEventListeners();
}

addEventListeners() {
document.addEventListener('scroll', this.updateIsInView);
document.addEventListener('resize', this.updateIsInView);
}

removeEventListeners() {
document.removeEventListener('scroll', this.updateIsInView);
document.removeEventListener('resize', this.updateIsInView);
}

updateIsInView() {
if (this.element) {
const isInView = isElementInViewport(this.element);

if (this.state.isInView !== isInView) {
this.setState({ isInView });
}
}
}

setRef(element) {
this.element = element;
}

render() {
const { children } = this.props;
const { isInView } = this.state;

return children({
isInView: isInView,
ref: this.setRef,
});
}
}
@@ -29,6 +29,7 @@ export { default as GridItem } from './Grid/GridItem';
export { default as Icon } from './Icon/Icon';
export { default as Image } from './Image/Image';
export { default as Input } from './Input/Input';
export { default as InView } from './InView/InView';
export { default as Label } from './Label/Label';
export { default as Labels } from './Label/Labels';
export { default as Link } from './Link/Link';
Oops, something went wrong.

0 comments on commit 2fbd355

Please sign in to comment.
You can’t perform that action at this time.