react-in-viewport
Advanced tools
Comparing version
@@ -5,2 +5,8 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
if (typeof window !== 'undefined') { | ||
@@ -15,27 +21,37 @@ // Polyfills for intersection-observer | ||
const isStateless = Component => !Component.prototype.render; | ||
var isStateless = function isStateless(Component) { | ||
return !Component.prototype.render; | ||
}; | ||
function handleViewport(Component, options, config = { disconnectOnLeave: false }) { | ||
class InViewport extends PureComponent { | ||
constructor(props) { | ||
super(props); | ||
this.observer = null; | ||
this.node = null; | ||
this.state = { | ||
function handleViewport(Component, options) { | ||
var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { disconnectOnLeave: false }; | ||
var InViewport = function (_PureComponent) { | ||
_inherits(InViewport, _PureComponent); | ||
function InViewport(props) { | ||
_classCallCheck(this, InViewport); | ||
var _this = _possibleConstructorReturn(this, _PureComponent.call(this, props)); | ||
_this.observer = null; | ||
_this.node = null; | ||
_this.state = { | ||
inViewport: false | ||
}; | ||
this.intersected = false; | ||
this.handleIntersection = this.handleIntersection.bind(this); | ||
this.initIntersectionObserver = this.initIntersectionObserver.bind(this); | ||
this.setRef = this.setRef.bind(this); | ||
this.setInnerRef = this.setInnerRef.bind(this); | ||
_this.intersected = false; | ||
_this.handleIntersection = _this.handleIntersection.bind(_this); | ||
_this.initIntersectionObserver = _this.initIntersectionObserver.bind(_this); | ||
_this.setRef = _this.setRef.bind(_this); | ||
_this.setInnerRef = _this.setInnerRef.bind(_this); | ||
return _this; | ||
} | ||
componentDidMount() { | ||
InViewport.prototype.componentDidMount = function componentDidMount() { | ||
// https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API | ||
this.initIntersectionObserver(); | ||
this.startObserver(this.node, this.observer); | ||
} | ||
}; | ||
componentDidUpdate(prevProps, prevState) { | ||
InViewport.prototype.componentDidUpdate = function componentDidUpdate(prevProps, prevState) { | ||
// reset observer on update, to fix race condition that when observer init, | ||
@@ -49,21 +65,21 @@ // the element is not in viewport, such as in animation | ||
} | ||
} | ||
}; | ||
initIntersectionObserver() { | ||
InViewport.prototype.initIntersectionObserver = function initIntersectionObserver() { | ||
if (!this.observer) { | ||
this.observer = new IntersectionObserver(this.handleIntersection, options); | ||
} | ||
} | ||
}; | ||
componentWillUnmount() { | ||
InViewport.prototype.componentWillUnmount = function componentWillUnmount() { | ||
this.stopObserver(this.node, this.observer); | ||
} | ||
}; | ||
startObserver(node, observer) { | ||
InViewport.prototype.startObserver = function startObserver(node, observer) { | ||
if (node && observer) { | ||
observer.observe(node); | ||
} | ||
} | ||
}; | ||
stopObserver(node, observer) { | ||
InViewport.prototype.stopObserver = function stopObserver(node, observer) { | ||
if (node && observer) { | ||
@@ -74,10 +90,15 @@ observer.unobserve(node); | ||
} | ||
} | ||
}; | ||
handleIntersection(entries) { | ||
const { onEnterViewport, onLeaveViewport } = this.props; | ||
const entry = entries[0] || {}; | ||
const { isIntersecting, intersectionRatio } = entry; | ||
const inViewport = typeof isIntersecting !== 'undefined' ? isIntersecting : intersectionRatio > 0; | ||
InViewport.prototype.handleIntersection = function handleIntersection(entries) { | ||
var _props = this.props, | ||
onEnterViewport = _props.onEnterViewport, | ||
onLeaveViewport = _props.onLeaveViewport; | ||
var entry = entries[0] || {}; | ||
var isIntersecting = entry.isIntersecting, | ||
intersectionRatio = entry.intersectionRatio; | ||
var inViewport = typeof isIntersecting !== 'undefined' ? isIntersecting : intersectionRatio > 0; | ||
// enter | ||
@@ -88,3 +109,3 @@ if (!this.intersected && inViewport) { | ||
this.setState({ | ||
inViewport | ||
inViewport: inViewport | ||
}); | ||
@@ -103,12 +124,12 @@ return; | ||
this.setState({ | ||
inViewport | ||
inViewport: inViewport | ||
}); | ||
} | ||
} | ||
}; | ||
setRef(node) { | ||
InViewport.prototype.setRef = function setRef(node) { | ||
this.node = ReactDOM.findDOMNode(node); | ||
} | ||
}; | ||
setInnerRef(node) { | ||
InViewport.prototype.setInnerRef = function setInnerRef(node) { | ||
if (node && !this.node) { | ||
@@ -120,16 +141,20 @@ // handle stateless | ||
} | ||
} | ||
}; | ||
render() { | ||
const _props = this.props, | ||
{ onEnterViewport, onLeaveViewport } = _props, | ||
others = _objectWithoutProperties(_props, ['onEnterViewport', 'onLeaveViewport']); | ||
InViewport.prototype.render = function render() { | ||
var _props2 = this.props, | ||
onEnterViewport = _props2.onEnterViewport, | ||
onLeaveViewport = _props2.onLeaveViewport, | ||
others = _objectWithoutProperties(_props2, ['onEnterViewport', 'onLeaveViewport']); | ||
// pass ref to class and innerRef for stateless component | ||
const refProps = isStateless(Component) ? { innerRef: this.setInnerRef } : { ref: this.setRef }; | ||
var refProps = isStateless(Component) ? { innerRef: this.setInnerRef } : { ref: this.setRef }; | ||
return React.createElement(Component, _extends({}, others, { | ||
inViewport: this.state.inViewport | ||
}, refProps)); | ||
} | ||
} | ||
}; | ||
return InViewport; | ||
}(PureComponent); | ||
return hoistNonReactStatic(InViewport, Component); | ||
@@ -136,0 +161,0 @@ } |
{ | ||
"name": "react-in-viewport", | ||
"version": "0.0.24", | ||
"version": "0.0.25", | ||
"description": "Track React component in viewport", | ||
@@ -5,0 +5,0 @@ "author": "Roderick Hsiao <roderickhsiao@gmail.com>", |
335742
0.57%618
2.49%