react-intersection-observer
Advanced tools
Comparing version 0.2.0 to 0.2.1
127
lib/index.js
@@ -7,10 +7,129 @@ 'use strict'; | ||
require('./window'); | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _Observer = require('./Observer'); | ||
var _react = require('react'); | ||
var _Observer2 = _interopRequireDefault(_Observer); | ||
var _react2 = _interopRequireDefault(_react); | ||
var _propTypes = require('prop-types'); | ||
var _propTypes2 = _interopRequireDefault(_propTypes); | ||
var _intersection = require('./intersection'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
exports.default = _Observer2.default; | ||
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } 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; } // eslint-disable-line no-unused-vars | ||
var isFunction = function isFunction(func) { | ||
return typeof func === 'function'; | ||
}; | ||
/** | ||
* Monitors scroll, and triggers the children function with updated props | ||
* | ||
<Observer> | ||
{inView => ( | ||
<h1>{`${inView}`}</h1> | ||
)} | ||
</Observer> | ||
*/ | ||
var Observer = function (_Component) { | ||
_inherits(Observer, _Component); | ||
function Observer() { | ||
var _ref; | ||
var _temp, _this, _ret; | ||
_classCallCheck(this, Observer); | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = Observer.__proto__ || Object.getPrototypeOf(Observer)).call.apply(_ref, [this].concat(args))), _this), _this.state = { | ||
inView: false | ||
}, _this.node = null, _this.handleNode = function (node) { | ||
if (_this.node) (0, _intersection.unobserve)(_this.node); | ||
if (node) { | ||
(0, _intersection.observe)(node, _this.handleChange, _this.props.triggerOnce, _this.props.threshold); | ||
} | ||
_this.node = node; | ||
}, _this.handleChange = function (inView) { | ||
return _this.setState({ inView: inView }); | ||
}, _temp), _possibleConstructorReturn(_this, _ret); | ||
} | ||
_createClass(Observer, [{ | ||
key: 'componentWillUpdate', | ||
value: function componentWillUpdate(nextProps, nextState) { | ||
if (!!this.props.onChange && nextState.inView !== this.state.inView) { | ||
this.props.onChange(nextState.inView); | ||
} | ||
} | ||
}, { | ||
key: 'componentWillUnmount', | ||
value: function componentWillUnmount() { | ||
if (this.node) { | ||
(0, _intersection.unobserve)(this.node); | ||
this.node = null; | ||
} | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render() { | ||
var _props = this.props; | ||
var children = _props.children; | ||
var render = _props.render; | ||
var tag = _props.tag; | ||
var triggerOnce = _props.triggerOnce; | ||
var threshold = _props.threshold; | ||
var props = _objectWithoutProperties(_props, ['children', 'render', 'tag', 'triggerOnce', 'threshold']); | ||
var inView = this.state.inView; | ||
return (0, _react.createElement)(tag, Object.assign({}, props, { | ||
ref: this.handleNode | ||
}), | ||
// If render is a function, use it to render content when in view | ||
inView && isFunction(render) ? render() : null, | ||
// If children is a function, render it with the current inView status. | ||
// Otherwise always render children. Assume onChange is being used outside, to control the the state of children. | ||
isFunction(children) ? children(inView) : children); | ||
} | ||
}]); | ||
return Observer; | ||
}(_react.Component); | ||
Observer.propTypes = { | ||
/** Element tag to use for the wrapping */ | ||
tag: _propTypes2.default.node, | ||
/** Children should be either a function or a node */ | ||
children: _propTypes2.default.oneOfType([_propTypes2.default.func, _propTypes2.default.node]), | ||
/** Only trigger this method once */ | ||
triggerOnce: _propTypes2.default.bool, | ||
/** Number between 0 and 1 indicating the the percentage that should be visible before triggering */ | ||
threshold: _propTypes2.default.number, | ||
/** Call this function whenever the in view state changes */ | ||
onChange: _propTypes2.default.func, | ||
/** Use render method to only render content when inView */ | ||
render: _propTypes2.default.func | ||
}; | ||
Observer.defaultProps = { | ||
tag: 'div', | ||
threshold: 0, | ||
triggerOnce: false | ||
}; | ||
exports.default = Observer; |
@@ -8,5 +8,7 @@ 'use strict'; | ||
exports.unobserve = unobserve; | ||
if (global.window && !process.env.SERVER) { | ||
// eslint-disable-next-line global-require | ||
require('intersection-observer'); | ||
} | ||
require('intersection-observer'); | ||
var INSTANCE_MAP = new Map(); | ||
@@ -13,0 +15,0 @@ var OBSERVER_MAP = new Map(); |
{ | ||
"name": "react-intersection-observer", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "Monitor if a component is inside the viewport, using IntersectionObserver API", | ||
@@ -23,3 +23,2 @@ "main": "lib/index.js", | ||
"build:storybook": "build-storybook --output-dir example", | ||
"deploy": "npm run build:storybook && git-directory-deploy --directory example --branch gh-pages", | ||
"lint": "eslint src/.", | ||
@@ -75,7 +74,6 @@ "precommit": "lint-staged", | ||
"eslint-config-prettier": "1.7.0", | ||
"git-directory-deploy": "1.5.1", | ||
"husky": "0.13.3", | ||
"jest": "19.0.2", | ||
"lint-staged": "3.4.1", | ||
"prettier": "1.2.2", | ||
"prettier": "1.3.0", | ||
"prop-types": "15.5.8", | ||
@@ -82,0 +80,0 @@ "react": "15.5.4", |
# react-intersection-observer | ||
[![Travis](https://travis-ci.org/thebuilder/react-intersection-observer.svg?branch=master)](https://travis-ci.org/thebuilder/react-intersection-observer) | ||
[![Dependency Status](https://david-dm.org/thebuilder/react-intersection-observer.svg)](https://david-dm.org/thebuilder/react-intersection-observer) | ||
[![npm version](https://badge.fury.io/js/react-intersection-observer.svg)](https://www.npmjs.com/package/react-intersection-observer) | ||
[![npm](https://img.shields.io/npm/v/react-intersection-observer.svg)](https://www.npmjs.com/package/react-intersection-observer) | ||
@@ -96,6 +98,2 @@ React component that allows triggers a function when the component enters or leaves the viewport. | ||
The IntersectionObserver polyfill requires `window` and `document`, and will crash if you try to import it outside the browser. | ||
To allow the Observer to be rendered universally, it sets `global.window` and `global.document` to empty objects if they are not defined. | ||
Ideally you would **noop** the IntersectionObserver when rendering outside the browser, but to make integration easier i've included the hack in the module. | ||
It could potentially conflict with other modules that checks for the existence of `window` and `document`. You can always require `lib/Observer.js` directly, to skip the window check. `lib/Observer.js` is also set as the `"browser"` field. | ||
To allow the Observer to be rendered universally, it only loads the IntersectionObserver polyfill if `window` exists. |
@@ -1,4 +0,98 @@ | ||
import './window' | ||
import Observer from './Observer' | ||
import React, { Component, createElement } from 'react' // eslint-disable-line no-unused-vars | ||
import PropTypes from 'prop-types' | ||
import { observe, unobserve } from './intersection' | ||
const isFunction = func => typeof func === 'function' | ||
/** | ||
* Monitors scroll, and triggers the children function with updated props | ||
* | ||
<Observer> | ||
{inView => ( | ||
<h1>{`${inView}`}</h1> | ||
)} | ||
</Observer> | ||
*/ | ||
class Observer extends Component { | ||
static propTypes = { | ||
/** Element tag to use for the wrapping */ | ||
tag: PropTypes.node, | ||
/** Children should be either a function or a node */ | ||
children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]), | ||
/** Only trigger this method once */ | ||
triggerOnce: PropTypes.bool, | ||
/** Number between 0 and 1 indicating the the percentage that should be visible before triggering */ | ||
threshold: PropTypes.number, | ||
/** Call this function whenever the in view state changes */ | ||
onChange: PropTypes.func, | ||
/** Use render method to only render content when inView */ | ||
render: PropTypes.func, | ||
} | ||
static defaultProps = { | ||
tag: 'div', | ||
threshold: 0, | ||
triggerOnce: false, | ||
} | ||
state = { | ||
inView: false, | ||
} | ||
componentWillUpdate(nextProps, nextState) { | ||
if (!!this.props.onChange && nextState.inView !== this.state.inView) { | ||
this.props.onChange(nextState.inView) | ||
} | ||
} | ||
componentWillUnmount() { | ||
if (this.node) { | ||
unobserve(this.node) | ||
this.node = null | ||
} | ||
} | ||
node = null | ||
handleNode = node => { | ||
if (this.node) unobserve(this.node) | ||
if (node) { | ||
observe( | ||
node, | ||
this.handleChange, | ||
this.props.triggerOnce, | ||
this.props.threshold, | ||
) | ||
} | ||
this.node = node | ||
} | ||
handleChange = inView => this.setState({ inView }) | ||
render() { | ||
const { | ||
children, | ||
render, | ||
tag, | ||
triggerOnce, | ||
threshold, | ||
...props | ||
} = this.props | ||
const { inView } = this.state | ||
return createElement( | ||
tag, | ||
{ | ||
...props, | ||
ref: this.handleNode, | ||
}, | ||
// If render is a function, use it to render content when in view | ||
inView && isFunction(render) ? render() : null, | ||
// If children is a function, render it with the current inView status. | ||
// Otherwise always render children. Assume onChange is being used outside, to control the the state of children. | ||
isFunction(children) ? children(inView) : children, | ||
) | ||
} | ||
} | ||
export default Observer |
@@ -1,2 +0,5 @@ | ||
import 'intersection-observer' | ||
if (global.window && !process.env.SERVER) { | ||
// eslint-disable-next-line global-require | ||
require('intersection-observer') | ||
} | ||
@@ -3,0 +6,0 @@ const INSTANCE_MAP = new Map() |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18
1834706
18
7318
98
2