Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-intersection-observer

Package Overview
Dependencies
Maintainers
1
Versions
160
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-intersection-observer - npm Package Compare versions

Comparing version 1.2.1 to 1.2.2-0

.flowconfig

13

.babelrc.js
module.exports = {
presets: [
[
'env',
process.env.BABEL_ENV === 'es'
? {
modules: false,
}
: {},
],
'react',
'stage-2',
],
presets: ['env', 'react', 'stage-2'],
}

@@ -13,11 +13,7 @@ 'use strict';

var _react2 = _interopRequireDefault(_react);
var React = _interopRequireWildcard(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _intersection = require('./intersection');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

@@ -30,9 +26,4 @@ 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 _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
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; }
var isFunction = function isFunction(func) {
return typeof func === 'function';
};
/**

@@ -47,6 +38,5 @@ * Monitors scroll, and triggers the children function with updated props

*/
var Observer = function (_React$Component) {
_inherits(Observer, _React$Component);
var Observer = function (_Component) {
_inherits(Observer, _Component);
function Observer() {

@@ -138,10 +128,10 @@ var _ref;

return (0, _react.createElement)(tag, _extends({}, props, {
return React.createElement(tag, _extends({}, 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);
inView && typeof render === 'function' ? 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.
typeof children === 'function' ? children(inView) : children);
}

@@ -151,25 +141,4 @@ }]);

return Observer;
}(_react.Component);
}(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 the inView callback once */
triggerOnce: _propTypes2.default.bool,
/** Number between 0 and 1 indicating the the percentage that should be visible before triggering. Can also be an array of numbers, to create multiple trigger points. */
threshold: _propTypes2.default.oneOfType([_propTypes2.default.arrayOf(_propTypes2.default.number), _propTypes2.default.number]),
/** The HTMLElement that is used as the viewport for checking visibility of the target. Defaults to the browser viewport if not specified or if null.*/
root: _propTypes2.default.object,
/** Margin around the root. Can have values similar to the CSS margin property, e.g. "10px 20px 30px 40px" (top, right, bottom, left). */
rootMargin: _propTypes2.default.string,
/** Unique identifier for the root element - This is used to identify the IntersectionObserver instance, so it can be reused.
* If you defined a root element, without adding an id, it will create a new instance for all components. */
rootId: _propTypes2.default.string,
/** 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 = {

@@ -176,0 +145,0 @@ tag: 'div',

@@ -26,9 +26,9 @@ "use strict";

};
var rootId = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
var threshold = options.threshold,
root = options.root,
var rootId = arguments[3];
var root = options.root,
rootMargin = options.rootMargin;
var threshold = options.threshold || 0;
if (!element || !callback) return;
var observerId = rootMargin ? threshold + "_" + rootMargin : "" + threshold;
var observerId = rootMargin ? threshold.toString() + "_" + rootMargin : "" + threshold.toString();

@@ -67,11 +67,12 @@ if (root) {

if (!element) return;
var instance = INSTANCE_MAP.get(element);
if (INSTANCE_MAP.has(element)) {
var _INSTANCE_MAP$get = INSTANCE_MAP.get(element),
observerId = _INSTANCE_MAP$get.observerId,
observer = _INSTANCE_MAP$get.observer;
if (instance) {
var _observerId = instance.observerId,
_observer = instance.observer;
var observerInstance = observerId ? OBSERVER_MAP.get(observerId) : observer;
var observerInstance = _observerId ? OBSERVER_MAP.get(_observerId) : _observer;
if (observerInstance) {
// $FlowFixMe - the interface in bom.js is wrong. Spec should accept the element.
observerInstance.unobserve(element);

@@ -82,5 +83,5 @@ }

var itemsLeft = false;
if (observerId) {
if (_observerId) {
INSTANCE_MAP.forEach(function (item, key) {
if (item && item.observerId === observerId && key !== element) {
if (item && item.observerId === _observerId && key !== element) {
itemsLeft = true;

@@ -94,3 +95,3 @@ }

observerInstance.disconnect();
OBSERVER_MAP.delete(observerId);
OBSERVER_MAP.delete(_observerId);
}

@@ -117,20 +118,20 @@

changes.forEach(function (intersection) {
if (INSTANCE_MAP.has(intersection.target)) {
var isIntersecting = intersection.isIntersecting,
intersectionRatio = intersection.intersectionRatio,
target = intersection.target;
var isIntersecting = intersection.isIntersecting,
intersectionRatio = intersection.intersectionRatio,
target = intersection.target;
var instance = INSTANCE_MAP.get(target);
var options = instance.options;
var instance = INSTANCE_MAP.get(target);
if (instance) {
var _options = instance.options;
var inView = void 0;
var _inView = false;
if (Array.isArray(options.threshold)) {
if (Array.isArray(_options.threshold)) {
// If threshold is an array, check if any of them intersects. This just triggers the onChange event multiple times.
inView = options.threshold.some(function (threshold) {
_inView = _options.threshold.some(function (threshold) {
return instance.visible ? intersectionRatio > threshold : intersectionRatio >= threshold;
});
} else {
} else if (_options.threshold !== undefined) {
// Trigger on 0 ratio only when not visible. This is fallback for browsers without isIntersecting support
inView = instance.visible ? intersectionRatio > options.threshold : intersectionRatio >= options.threshold;
_inView = instance.visible ? intersectionRatio > _options.threshold : intersectionRatio >= _options.threshold;
}

@@ -141,10 +142,10 @@

// Otherwise it reports a threshold of 0
inView = inView && isIntersecting;
_inView = _inView && isIntersecting;
}
// Update the visible value on the instance
instance.visible = inView;
instance.visible = _inView;
if (instance.callback) {
instance.callback(inView);
instance.callback(_inView);
}

@@ -151,0 +152,0 @@ }

{
"name": "react-intersection-observer",
"version": "1.2.1",
"version": "1.2.2-0",
"description": "Monitor if a component is inside the viewport, using IntersectionObserver API",
"main": "lib/index.js",
"module": "es/index.js",
"jsnext:main": "es/index.js",
"author": "Daniel Schmidt",

@@ -22,9 +20,9 @@ "repository": {

"scripts": {
"build": "rm -rf lib && npm run build:lib && npm run build:es",
"build:es": "BABEL_ENV=es babel src --out-dir es --ignore __*,*.story.js,*.test.js",
"build": "rm -rf lib es && npm run build:lib && npm run build:flow",
"build:lib": "babel src --out-dir lib --ignore __*,*.story.js,*.test.js",
"build:storybook": "build-storybook --output-dir example",
"build:flow": "flow-copy-source -v src lib",
"dev": "concurrently -k -r 'jest --watch' 'npm run storybook'",
"lint": "eslint {src,stories,tests}/. ",
"precommit": "lint-staged",
"precommit": "flow && lint-staged",
"postcommit": "git reset",

@@ -62,5 +60,3 @@ "prepublish": "npm run build",

},
"dependencies": {
"prop-types": "^15.6.0"
},
"dependencies": {},
"peerDependencies": {

@@ -85,2 +81,4 @@ "react": "^15.0.0 || ^16.0.0 || ^17.0.0"

"eslint-config-insilico": "^5.0.1",
"flow-bin": "^0.57.3",
"flow-copy-source": "^1.2.1",
"husky": "^0.14.3",

@@ -87,0 +85,0 @@ "intersection-observer": "^0.4.0",

@@ -1,7 +0,31 @@

import React, { Component, createElement } from 'react' // eslint-disable-line no-unused-vars
import PropTypes from 'prop-types'
// @flow
import * as React from 'react'
import { observe, unobserve } from './intersection'
const isFunction = func => typeof func === 'function'
type Props = {
/** Element tag to use for the wrapping */
tag: string,
/** Only trigger the inView callback once */
triggerOnce: boolean,
/** Children should be either a function or a node */
children?: ((inView: boolean) => React.Node) | React.Node,
/** Number between 0 and 1 indicating the the percentage that should be visible before triggering. Can also be an array of numbers, to create multiple trigger points. */
threshold?: number | Array<number>,
/** The HTMLElement that is used as the viewport for checking visibility of the target. Defaults to the browser viewport if not specified or if null.*/
root?: HTMLElement,
/** Margin around the root. Can have values similar to the CSS margin property, e.g. "10px 20px 30px 40px" (top, right, bottom, left). */
rootMargin?: string,
/** Unique identifier for the root element - This is used to identify the IntersectionObserver instance, so it can be reused.
* If you defined a root element, without adding an id, it will create a new instance for all components. */
rootId?: string,
/** Call this function whenever the in view state changes */
onChange?: (inView: boolean) => void,
/** Use render method to only render content when inView */
render?: () => React.Node,
}
type State = {
inView: boolean,
}
/**

@@ -16,28 +40,3 @@ * Monitors scroll, and triggers the children function with updated props

*/
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 the inView callback once */
triggerOnce: PropTypes.bool,
/** Number between 0 and 1 indicating the the percentage that should be visible before triggering. Can also be an array of numbers, to create multiple trigger points. */
threshold: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.number),
PropTypes.number,
]),
/** The HTMLElement that is used as the viewport for checking visibility of the target. Defaults to the browser viewport if not specified or if null.*/
root: PropTypes.object,
/** Margin around the root. Can have values similar to the CSS margin property, e.g. "10px 20px 30px 40px" (top, right, bottom, left). */
rootMargin: PropTypes.string,
/** Unique identifier for the root element - This is used to identify the IntersectionObserver instance, so it can be reused.
* If you defined a root element, without adding an id, it will create a new instance for all components. */
rootId: PropTypes.string,
/** Call this function whenever the in view state changes */
onChange: PropTypes.func,
/** Use render method to only render content when inView */
render: PropTypes.func,
}
class Observer extends React.Component<Props, State> {
static defaultProps = {

@@ -53,3 +52,3 @@ tag: 'div',

componentWillUpdate(nextProps, nextState) {
componentWillUpdate(nextProps: Props, nextState: State) {
if (!!this.props.onChange && nextState !== this.state) {

@@ -60,3 +59,3 @@ this.props.onChange(nextState.inView)

componentDidUpdate(prevProps, prevState) {
componentDidUpdate(prevProps: Props, prevState: State) {
// If a IntersectionObserver option changed, reinit the observer

@@ -87,3 +86,3 @@ if (

node = null
node: ?HTMLElement = null

@@ -105,3 +104,3 @@ observeNode() {

handleNode = node => {
handleNode = (node: ?HTMLElement) => {
if (this.node) unobserve(this.node)

@@ -112,3 +111,3 @@ this.node = node

handleChange = inView => this.setState({ inView })
handleChange = (inView: boolean) => this.setState({ inView })

@@ -130,3 +129,3 @@ render() {

return createElement(
return React.createElement(
tag,

@@ -138,6 +137,6 @@ {

// 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,
inView && typeof render === 'function' ? 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.
typeof children === 'function' ? children(inView) : children,
)

@@ -144,0 +143,0 @@ }

@@ -1,4 +0,15 @@

const INSTANCE_MAP = new Map()
const OBSERVER_MAP = new Map()
// @flow
type Callback = (inView: boolean) => void
type Instance = {
callback: Callback,
visible: boolean,
options: IntersectionObserverOptions,
observerId: ?string,
observer: ?IntersectionObserver,
}
const INSTANCE_MAP: Map<HTMLElement, Instance> = new Map()
const OBSERVER_MAP: Map<?string, IntersectionObserver> = new Map()
/**

@@ -15,12 +26,15 @@ * Monitor element, and trigger callback when element becomes visible

export function observe(
element,
callback,
options = {
element: HTMLElement,
callback: Callback,
options: IntersectionObserverOptions = {
threshold: 0,
},
rootId = null,
rootId?: string,
) {
const { threshold, root, rootMargin } = options
const { root, rootMargin } = options
const threshold = options.threshold || 0
if (!element || !callback) return
let observerId = rootMargin ? `${threshold}_${rootMargin}` : `${threshold}`
let observerId = rootMargin
? `${threshold.toString()}_${rootMargin}`
: `${threshold.toString()}`

@@ -37,3 +51,3 @@ if (root) {

const instance = {
const instance: Instance = {
callback,

@@ -58,7 +72,8 @@ visible: false,

*/
export function unobserve(element) {
export function unobserve(element: ?HTMLElement) {
if (!element) return
const instance = INSTANCE_MAP.get(element)
if (INSTANCE_MAP.has(element)) {
const { observerId, observer } = INSTANCE_MAP.get(element)
if (instance) {
const { observerId, observer } = instance
const observerInstance = observerId

@@ -69,2 +84,3 @@ ? OBSERVER_MAP.get(observerId)

if (observerInstance) {
// $FlowFixMe - the interface in bom.js is wrong. Spec should accept the element.
observerInstance.unobserve(element)

@@ -108,8 +124,8 @@ }

changes.forEach(intersection => {
if (INSTANCE_MAP.has(intersection.target)) {
const { isIntersecting, intersectionRatio, target } = intersection
const instance = INSTANCE_MAP.get(target)
const { isIntersecting, intersectionRatio, target } = intersection
const instance = INSTANCE_MAP.get(target)
if (instance) {
const options = instance.options
let inView
let inView = false

@@ -123,3 +139,3 @@ if (Array.isArray(options.threshold)) {

})
} else {
} else if (options.threshold !== undefined) {
// Trigger on 0 ratio only when not visible. This is fallback for browsers without isIntersecting support

@@ -126,0 +142,0 @@ inView = instance.visible

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc