react-intersection-observer
Advanced tools
Comparing version 9.4.3 to 9.4.4
@@ -5,4 +5,4 @@ import * as React from 'react'; | ||
export { observe, defaultFallbackInView } from './observe'; | ||
declare type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; | ||
export declare type ObserverInstanceCallback = (inView: boolean, entry: IntersectionObserverEntry) => void; | ||
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; | ||
export type ObserverInstanceCallback = (inView: boolean, entry: IntersectionObserverEntry) => void; | ||
interface RenderProps { | ||
@@ -46,3 +46,3 @@ inView: boolean; | ||
* */ | ||
export declare type PlainChildrenProps = IntersectionOptions & { | ||
export type PlainChildrenProps = IntersectionOptions & { | ||
children?: React.ReactNode; | ||
@@ -63,3 +63,3 @@ /** | ||
*/ | ||
export declare type InViewHookResponse = [ | ||
export type InViewHookResponse = [ | ||
(node?: Element | null) => void, | ||
@@ -66,0 +66,0 @@ boolean, |
import * as React from 'react'; | ||
import type { IntersectionObserverProps, PlainChildrenProps } from './index'; | ||
declare type State = { | ||
type State = { | ||
inView: boolean; | ||
@@ -5,0 +5,0 @@ entry?: IntersectionObserverEntry; |
{ | ||
"name": "react-intersection-observer", | ||
"version": "9.4.3", | ||
"version": "9.4.4", | ||
"description": "Monitor if a component is inside the viewport, using IntersectionObserver API", | ||
@@ -82,3 +82,18 @@ "source": "./src/index.tsx", | ||
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" | ||
}, | ||
"pnpm": { | ||
"peerDependencyRules": { | ||
"allowedVersions": { | ||
"react": "18" | ||
} | ||
}, | ||
"allowedDeprecatedVersions": { | ||
"rollup-plugin-terser": "*", | ||
"sourcemap-codec": "*", | ||
"source-map-resolve": "*", | ||
"source-map-url": "*", | ||
"stable": "*", | ||
"urix": "*" | ||
} | ||
} | ||
} |
import * as React from 'react'; | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
_extends = Object.assign ? Object.assign.bind() : function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
@@ -14,25 +13,18 @@ if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
function _inheritsLoose(subClass, superClass) { | ||
subClass.prototype = Object.create(superClass.prototype); | ||
subClass.prototype.constructor = subClass; | ||
_setPrototypeOf(subClass, superClass); | ||
} | ||
function _setPrototypeOf(o, p) { | ||
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { | ||
_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { | ||
o.__proto__ = p; | ||
return o; | ||
}; | ||
return _setPrototypeOf(o, p); | ||
} | ||
function _objectWithoutPropertiesLoose(source, excluded) { | ||
@@ -43,3 +35,2 @@ if (source == null) return {}; | ||
var key, i; | ||
for (i = 0; i < sourceKeys.length; i++) { | ||
@@ -50,3 +41,2 @@ key = sourceKeys[i]; | ||
} | ||
return target; | ||
@@ -65,3 +55,2 @@ } | ||
* **/ | ||
function defaultFallbackInView(inView) { | ||
@@ -74,3 +63,2 @@ unsupportedValue = inView; | ||
*/ | ||
function getRootId(root) { | ||
@@ -88,4 +76,2 @@ if (!root) return '0'; | ||
*/ | ||
function optionsToId(options) { | ||
@@ -98,3 +84,2 @@ return Object.keys(options).sort().filter(function (key) { | ||
} | ||
function createObserver(options) { | ||
@@ -104,3 +89,2 @@ // Create a unique ID for this observer instance, based on the root, root margin and threshold. | ||
var instance = observerMap.get(id); | ||
if (!instance) { | ||
@@ -113,3 +97,2 @@ // Create a map of elements this observer is going to observe. Each element has a list of callbacks that should be triggered, once it comes into view. | ||
var _elements$get; | ||
// While it would be nice if you could just look at isIntersecting to determine if the component is inside the viewport, browsers can't agree on how to use it. | ||
@@ -119,4 +102,4 @@ // -Firefox ignores `threshold` when considering `isIntersecting`, so it will never be false again if `threshold` is > 0 | ||
return entry.intersectionRatio >= threshold; | ||
}); // @ts-ignore support IntersectionObserver v2 | ||
}); | ||
// @ts-ignore support IntersectionObserver v2 | ||
if (options.trackVisibility && typeof entry.isVisible === 'undefined') { | ||
@@ -127,3 +110,2 @@ // The browser doesn't support Intersection Observer v2, falling back to v1 behavior. | ||
} | ||
(_elements$get = elements.get(entry.target)) == null ? void 0 : _elements$get.forEach(function (callback) { | ||
@@ -133,4 +115,4 @@ callback(inView, entry); | ||
}); | ||
}, options); // Ensure we have a valid thresholds array. If not, use the threshold from the options | ||
}, options); | ||
// Ensure we have a valid thresholds array. If not, use the threshold from the options | ||
thresholds = observer.thresholds || (Array.isArray(options.threshold) ? options.threshold : [options.threshold || 0]); | ||
@@ -144,3 +126,2 @@ instance = { | ||
} | ||
return instance; | ||
@@ -155,4 +136,2 @@ } | ||
*/ | ||
function observe(element, callback, options, fallbackInView) { | ||
@@ -162,7 +141,5 @@ if (options === void 0) { | ||
} | ||
if (fallbackInView === void 0) { | ||
fallbackInView = unsupportedValue; | ||
} | ||
if (typeof window.IntersectionObserver === 'undefined' && fallbackInView !== undefined) { | ||
@@ -179,19 +156,16 @@ var bounds = element.getBoundingClientRect(); | ||
}); | ||
return function () {// Nothing to cleanup | ||
return function () { | ||
// Nothing to cleanup | ||
}; | ||
} // An observer with the same options can be reused, so lets use this fact | ||
} | ||
// An observer with the same options can be reused, so lets use this fact | ||
var _createObserver = createObserver(options), | ||
id = _createObserver.id, | ||
observer = _createObserver.observer, | ||
elements = _createObserver.elements; // Register the callback listener for this element | ||
id = _createObserver.id, | ||
observer = _createObserver.observer, | ||
elements = _createObserver.elements; | ||
// Register the callback listener for this element | ||
var callbacks = elements.get(element) || []; | ||
if (!elements.has(element)) { | ||
elements.set(element, callbacks); | ||
} | ||
callbacks.push(callback); | ||
@@ -202,3 +176,2 @@ observer.observe(element); | ||
callbacks.splice(callbacks.indexOf(callback), 1); | ||
if (callbacks.length === 0) { | ||
@@ -209,3 +182,2 @@ // No more callback exists for element, so destroy it | ||
} | ||
if (elements.size === 0) { | ||
@@ -220,3 +192,2 @@ // No more elements are being observer by this instance, so destroy it | ||
var _excluded = ["children", "as", "triggerOnce", "threshold", "root", "rootMargin", "onChange", "skip", "trackVisibility", "delay", "initialInView", "fallbackInView"]; | ||
function isPlainChildren(props) { | ||
@@ -274,14 +245,9 @@ return typeof props.children !== 'function'; | ||
*/ | ||
var InView = /*#__PURE__*/function (_React$Component) { | ||
_inheritsLoose(InView, _React$Component); | ||
function InView(props) { | ||
var _this; | ||
_this = _React$Component.call(this, props) || this; | ||
_this.node = null; | ||
_this._unobserveCb = null; | ||
_this.handleNode = function (node) { | ||
@@ -291,3 +257,2 @@ if (_this.node) { | ||
_this.unobserve(); | ||
if (!node && !_this.props.triggerOnce && !_this.props.skip) { | ||
@@ -301,8 +266,5 @@ // Reset the state if we get a new node, and we aren't ignoring updates | ||
} | ||
_this.node = node ? node : null; | ||
_this.observeNode(); | ||
}; | ||
_this.handleChange = function (inView, entry) { | ||
@@ -313,3 +275,2 @@ if (inView && _this.props.triggerOnce) { | ||
} | ||
if (!isPlainChildren(_this.props)) { | ||
@@ -323,3 +284,2 @@ // Store the current State, so we can pass it to the children in the next render update | ||
} | ||
if (_this.props.onChange) { | ||
@@ -330,3 +290,2 @@ // If the user is actively listening for onChange, always trigger it | ||
}; | ||
_this.state = { | ||
@@ -338,5 +297,3 @@ inView: !!props.initialInView, | ||
} | ||
var _proto = InView.prototype; | ||
_proto.componentDidUpdate = function componentDidUpdate(prevProps) { | ||
@@ -349,3 +306,2 @@ // If a IntersectionObserver option changed, reinit the observer | ||
}; | ||
_proto.componentWillUnmount = function componentWillUnmount() { | ||
@@ -355,12 +311,11 @@ this.unobserve(); | ||
}; | ||
_proto.observeNode = function observeNode() { | ||
if (!this.node || this.props.skip) return; | ||
var _this$props = this.props, | ||
threshold = _this$props.threshold, | ||
root = _this$props.root, | ||
rootMargin = _this$props.rootMargin, | ||
trackVisibility = _this$props.trackVisibility, | ||
delay = _this$props.delay, | ||
fallbackInView = _this$props.fallbackInView; | ||
threshold = _this$props.threshold, | ||
root = _this$props.root, | ||
rootMargin = _this$props.rootMargin, | ||
trackVisibility = _this$props.trackVisibility, | ||
delay = _this$props.delay, | ||
fallbackInView = _this$props.fallbackInView; | ||
this._unobserveCb = observe(this.node, this.handleChange, { | ||
@@ -376,16 +331,13 @@ threshold: threshold, | ||
}; | ||
_proto.unobserve = function unobserve() { | ||
if (this._unobserveCb) { | ||
this._unobserveCb(); | ||
this._unobserveCb = null; | ||
} | ||
}; | ||
_proto.render = function render() { | ||
if (!isPlainChildren(this.props)) { | ||
var _this$state = this.state, | ||
inView = _this$state.inView, | ||
entry = _this$state.entry; | ||
inView = _this$state.inView, | ||
entry = _this$state.entry; | ||
return this.props.children({ | ||
@@ -397,8 +349,6 @@ inView: inView, | ||
} | ||
var _this$props2 = this.props, | ||
children = _this$props2.children, | ||
as = _this$props2.as, | ||
props = _objectWithoutPropertiesLoose(_this$props2, _excluded); | ||
children = _this$props2.children, | ||
as = _this$props2.as, | ||
props = _objectWithoutPropertiesLoose(_this$props2, _excluded); | ||
return React.createElement(as || 'div', _extends({ | ||
@@ -408,3 +358,2 @@ ref: this.handleNode | ||
}; | ||
return InView; | ||
@@ -439,33 +388,27 @@ }(React.Component); | ||
*/ | ||
function useInView(_temp) { | ||
var _state$entry; | ||
var _ref = _temp === void 0 ? {} : _temp, | ||
threshold = _ref.threshold, | ||
delay = _ref.delay, | ||
trackVisibility = _ref.trackVisibility, | ||
rootMargin = _ref.rootMargin, | ||
root = _ref.root, | ||
triggerOnce = _ref.triggerOnce, | ||
skip = _ref.skip, | ||
initialInView = _ref.initialInView, | ||
fallbackInView = _ref.fallbackInView, | ||
onChange = _ref.onChange; | ||
threshold = _ref.threshold, | ||
delay = _ref.delay, | ||
trackVisibility = _ref.trackVisibility, | ||
rootMargin = _ref.rootMargin, | ||
root = _ref.root, | ||
triggerOnce = _ref.triggerOnce, | ||
skip = _ref.skip, | ||
initialInView = _ref.initialInView, | ||
fallbackInView = _ref.fallbackInView, | ||
onChange = _ref.onChange; | ||
var _React$useState = React.useState(null), | ||
ref = _React$useState[0], | ||
setRef = _React$useState[1]; | ||
ref = _React$useState[0], | ||
setRef = _React$useState[1]; | ||
var callback = React.useRef(); | ||
var _React$useState2 = React.useState({ | ||
inView: !!initialInView, | ||
entry: undefined | ||
}), | ||
state = _React$useState2[0], | ||
setState = _React$useState2[1]; // Store the onChange callback in a `ref`, so we can access the latest instance | ||
inView: !!initialInView, | ||
entry: undefined | ||
}), | ||
state = _React$useState2[0], | ||
setState = _React$useState2[1]; | ||
// Store the onChange callback in a `ref`, so we can access the latest instance | ||
// inside the `useEffect`, but without triggering a rerender. | ||
callback.current = onChange; | ||
@@ -482,3 +425,2 @@ React.useEffect(function () { | ||
if (callback.current) callback.current(inView, entry); | ||
if (entry.isIntersecting && triggerOnce && unobserve) { | ||
@@ -503,5 +445,7 @@ // If it should only trigger once, unobserve the element after it's inView | ||
}; | ||
}, // We break the rule here, because we aren't including the actual `threshold` variable | ||
}, | ||
// We break the rule here, because we aren't including the actual `threshold` variable | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
[// If the threshold is an array, convert it to a string, so it won't change between renders. | ||
[ | ||
// If the threshold is an array, convert it to a string, so it won't change between renders. | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
@@ -511,3 +455,2 @@ Array.isArray(threshold) ? threshold.toString() : threshold, ref, root, rootMargin, triggerOnce, skip, trackVisibility, fallbackInView, delay]); | ||
var previousEntryTarget = React.useRef(); | ||
if (!ref && entryTarget && !triggerOnce && !skip && previousEntryTarget.current !== entryTarget) { | ||
@@ -522,5 +465,4 @@ // If we don't have a node ref, then reset the state (unless the hook is set to only `triggerOnce` or `skip`) | ||
} | ||
var result = [setRef, state.inView, state.entry]; // Support object destructuring, by adding the specific values. | ||
var result = [setRef, state.inView, state.entry]; | ||
// Support object destructuring, by adding the specific values. | ||
result.ref = result[0]; | ||
@@ -527,0 +469,0 @@ result.inView = result[1]; |
@@ -24,6 +24,5 @@ var React = require('react'); | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
_extends = Object.assign ? Object.assign.bind() : function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
@@ -35,25 +34,18 @@ if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
function _inheritsLoose(subClass, superClass) { | ||
subClass.prototype = Object.create(superClass.prototype); | ||
subClass.prototype.constructor = subClass; | ||
_setPrototypeOf(subClass, superClass); | ||
} | ||
function _setPrototypeOf(o, p) { | ||
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { | ||
_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { | ||
o.__proto__ = p; | ||
return o; | ||
}; | ||
return _setPrototypeOf(o, p); | ||
} | ||
function _objectWithoutPropertiesLoose(source, excluded) { | ||
@@ -64,3 +56,2 @@ if (source == null) return {}; | ||
var key, i; | ||
for (i = 0; i < sourceKeys.length; i++) { | ||
@@ -71,3 +62,2 @@ key = sourceKeys[i]; | ||
} | ||
return target; | ||
@@ -86,3 +76,2 @@ } | ||
* **/ | ||
function defaultFallbackInView(inView) { | ||
@@ -95,3 +84,2 @@ unsupportedValue = inView; | ||
*/ | ||
function getRootId(root) { | ||
@@ -109,4 +97,2 @@ if (!root) return '0'; | ||
*/ | ||
function optionsToId(options) { | ||
@@ -119,3 +105,2 @@ return Object.keys(options).sort().filter(function (key) { | ||
} | ||
function createObserver(options) { | ||
@@ -125,3 +110,2 @@ // Create a unique ID for this observer instance, based on the root, root margin and threshold. | ||
var instance = observerMap.get(id); | ||
if (!instance) { | ||
@@ -134,3 +118,2 @@ // Create a map of elements this observer is going to observe. Each element has a list of callbacks that should be triggered, once it comes into view. | ||
var _elements$get; | ||
// While it would be nice if you could just look at isIntersecting to determine if the component is inside the viewport, browsers can't agree on how to use it. | ||
@@ -140,4 +123,4 @@ // -Firefox ignores `threshold` when considering `isIntersecting`, so it will never be false again if `threshold` is > 0 | ||
return entry.intersectionRatio >= threshold; | ||
}); // @ts-ignore support IntersectionObserver v2 | ||
}); | ||
// @ts-ignore support IntersectionObserver v2 | ||
if (options.trackVisibility && typeof entry.isVisible === 'undefined') { | ||
@@ -148,3 +131,2 @@ // The browser doesn't support Intersection Observer v2, falling back to v1 behavior. | ||
} | ||
(_elements$get = elements.get(entry.target)) == null ? void 0 : _elements$get.forEach(function (callback) { | ||
@@ -154,4 +136,4 @@ callback(inView, entry); | ||
}); | ||
}, options); // Ensure we have a valid thresholds array. If not, use the threshold from the options | ||
}, options); | ||
// Ensure we have a valid thresholds array. If not, use the threshold from the options | ||
thresholds = observer.thresholds || (Array.isArray(options.threshold) ? options.threshold : [options.threshold || 0]); | ||
@@ -165,3 +147,2 @@ instance = { | ||
} | ||
return instance; | ||
@@ -176,4 +157,2 @@ } | ||
*/ | ||
function observe(element, callback, options, fallbackInView) { | ||
@@ -183,7 +162,5 @@ if (options === void 0) { | ||
} | ||
if (fallbackInView === void 0) { | ||
fallbackInView = unsupportedValue; | ||
} | ||
if (typeof window.IntersectionObserver === 'undefined' && fallbackInView !== undefined) { | ||
@@ -200,19 +177,16 @@ var bounds = element.getBoundingClientRect(); | ||
}); | ||
return function () {// Nothing to cleanup | ||
return function () { | ||
// Nothing to cleanup | ||
}; | ||
} // An observer with the same options can be reused, so lets use this fact | ||
} | ||
// An observer with the same options can be reused, so lets use this fact | ||
var _createObserver = createObserver(options), | ||
id = _createObserver.id, | ||
observer = _createObserver.observer, | ||
elements = _createObserver.elements; // Register the callback listener for this element | ||
id = _createObserver.id, | ||
observer = _createObserver.observer, | ||
elements = _createObserver.elements; | ||
// Register the callback listener for this element | ||
var callbacks = elements.get(element) || []; | ||
if (!elements.has(element)) { | ||
elements.set(element, callbacks); | ||
} | ||
callbacks.push(callback); | ||
@@ -223,3 +197,2 @@ observer.observe(element); | ||
callbacks.splice(callbacks.indexOf(callback), 1); | ||
if (callbacks.length === 0) { | ||
@@ -230,3 +203,2 @@ // No more callback exists for element, so destroy it | ||
} | ||
if (elements.size === 0) { | ||
@@ -241,3 +213,2 @@ // No more elements are being observer by this instance, so destroy it | ||
var _excluded = ["children", "as", "triggerOnce", "threshold", "root", "rootMargin", "onChange", "skip", "trackVisibility", "delay", "initialInView", "fallbackInView"]; | ||
function isPlainChildren(props) { | ||
@@ -295,14 +266,9 @@ return typeof props.children !== 'function'; | ||
*/ | ||
var InView = /*#__PURE__*/function (_React$Component) { | ||
_inheritsLoose(InView, _React$Component); | ||
function InView(props) { | ||
var _this; | ||
_this = _React$Component.call(this, props) || this; | ||
_this.node = null; | ||
_this._unobserveCb = null; | ||
_this.handleNode = function (node) { | ||
@@ -312,3 +278,2 @@ if (_this.node) { | ||
_this.unobserve(); | ||
if (!node && !_this.props.triggerOnce && !_this.props.skip) { | ||
@@ -322,8 +287,5 @@ // Reset the state if we get a new node, and we aren't ignoring updates | ||
} | ||
_this.node = node ? node : null; | ||
_this.observeNode(); | ||
}; | ||
_this.handleChange = function (inView, entry) { | ||
@@ -334,3 +296,2 @@ if (inView && _this.props.triggerOnce) { | ||
} | ||
if (!isPlainChildren(_this.props)) { | ||
@@ -344,3 +305,2 @@ // Store the current State, so we can pass it to the children in the next render update | ||
} | ||
if (_this.props.onChange) { | ||
@@ -351,3 +311,2 @@ // If the user is actively listening for onChange, always trigger it | ||
}; | ||
_this.state = { | ||
@@ -359,5 +318,3 @@ inView: !!props.initialInView, | ||
} | ||
var _proto = InView.prototype; | ||
_proto.componentDidUpdate = function componentDidUpdate(prevProps) { | ||
@@ -370,3 +327,2 @@ // If a IntersectionObserver option changed, reinit the observer | ||
}; | ||
_proto.componentWillUnmount = function componentWillUnmount() { | ||
@@ -376,12 +332,11 @@ this.unobserve(); | ||
}; | ||
_proto.observeNode = function observeNode() { | ||
if (!this.node || this.props.skip) return; | ||
var _this$props = this.props, | ||
threshold = _this$props.threshold, | ||
root = _this$props.root, | ||
rootMargin = _this$props.rootMargin, | ||
trackVisibility = _this$props.trackVisibility, | ||
delay = _this$props.delay, | ||
fallbackInView = _this$props.fallbackInView; | ||
threshold = _this$props.threshold, | ||
root = _this$props.root, | ||
rootMargin = _this$props.rootMargin, | ||
trackVisibility = _this$props.trackVisibility, | ||
delay = _this$props.delay, | ||
fallbackInView = _this$props.fallbackInView; | ||
this._unobserveCb = observe(this.node, this.handleChange, { | ||
@@ -397,16 +352,13 @@ threshold: threshold, | ||
}; | ||
_proto.unobserve = function unobserve() { | ||
if (this._unobserveCb) { | ||
this._unobserveCb(); | ||
this._unobserveCb = null; | ||
} | ||
}; | ||
_proto.render = function render() { | ||
if (!isPlainChildren(this.props)) { | ||
var _this$state = this.state, | ||
inView = _this$state.inView, | ||
entry = _this$state.entry; | ||
inView = _this$state.inView, | ||
entry = _this$state.entry; | ||
return this.props.children({ | ||
@@ -418,8 +370,6 @@ inView: inView, | ||
} | ||
var _this$props2 = this.props, | ||
children = _this$props2.children, | ||
as = _this$props2.as, | ||
props = _objectWithoutPropertiesLoose(_this$props2, _excluded); | ||
children = _this$props2.children, | ||
as = _this$props2.as, | ||
props = _objectWithoutPropertiesLoose(_this$props2, _excluded); | ||
return React__namespace.createElement(as || 'div', _extends({ | ||
@@ -429,3 +379,2 @@ ref: this.handleNode | ||
}; | ||
return InView; | ||
@@ -460,33 +409,27 @@ }(React__namespace.Component); | ||
*/ | ||
function useInView(_temp) { | ||
var _state$entry; | ||
var _ref = _temp === void 0 ? {} : _temp, | ||
threshold = _ref.threshold, | ||
delay = _ref.delay, | ||
trackVisibility = _ref.trackVisibility, | ||
rootMargin = _ref.rootMargin, | ||
root = _ref.root, | ||
triggerOnce = _ref.triggerOnce, | ||
skip = _ref.skip, | ||
initialInView = _ref.initialInView, | ||
fallbackInView = _ref.fallbackInView, | ||
onChange = _ref.onChange; | ||
threshold = _ref.threshold, | ||
delay = _ref.delay, | ||
trackVisibility = _ref.trackVisibility, | ||
rootMargin = _ref.rootMargin, | ||
root = _ref.root, | ||
triggerOnce = _ref.triggerOnce, | ||
skip = _ref.skip, | ||
initialInView = _ref.initialInView, | ||
fallbackInView = _ref.fallbackInView, | ||
onChange = _ref.onChange; | ||
var _React$useState = React__namespace.useState(null), | ||
ref = _React$useState[0], | ||
setRef = _React$useState[1]; | ||
ref = _React$useState[0], | ||
setRef = _React$useState[1]; | ||
var callback = React__namespace.useRef(); | ||
var _React$useState2 = React__namespace.useState({ | ||
inView: !!initialInView, | ||
entry: undefined | ||
}), | ||
state = _React$useState2[0], | ||
setState = _React$useState2[1]; // Store the onChange callback in a `ref`, so we can access the latest instance | ||
inView: !!initialInView, | ||
entry: undefined | ||
}), | ||
state = _React$useState2[0], | ||
setState = _React$useState2[1]; | ||
// Store the onChange callback in a `ref`, so we can access the latest instance | ||
// inside the `useEffect`, but without triggering a rerender. | ||
callback.current = onChange; | ||
@@ -503,3 +446,2 @@ React__namespace.useEffect(function () { | ||
if (callback.current) callback.current(inView, entry); | ||
if (entry.isIntersecting && triggerOnce && unobserve) { | ||
@@ -524,5 +466,7 @@ // If it should only trigger once, unobserve the element after it's inView | ||
}; | ||
}, // We break the rule here, because we aren't including the actual `threshold` variable | ||
}, | ||
// We break the rule here, because we aren't including the actual `threshold` variable | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
[// If the threshold is an array, convert it to a string, so it won't change between renders. | ||
[ | ||
// If the threshold is an array, convert it to a string, so it won't change between renders. | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
@@ -532,3 +476,2 @@ Array.isArray(threshold) ? threshold.toString() : threshold, ref, root, rootMargin, triggerOnce, skip, trackVisibility, fallbackInView, delay]); | ||
var previousEntryTarget = React__namespace.useRef(); | ||
if (!ref && entryTarget && !triggerOnce && !skip && previousEntryTarget.current !== entryTarget) { | ||
@@ -543,5 +486,4 @@ // If we don't have a node ref, then reset the state (unless the hook is set to only `triggerOnce` or `skip`) | ||
} | ||
var result = [setRef, state.inView, state.entry]; // Support object destructuring, by adding the specific values. | ||
var result = [setRef, state.inView, state.entry]; | ||
// Support object destructuring, by adding the specific values. | ||
result.ref = result[0]; | ||
@@ -548,0 +490,0 @@ result.inView = result[1]; |
@@ -27,6 +27,5 @@ (function (global, factory) { | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
_extends = Object.assign ? Object.assign.bind() : function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
@@ -38,25 +37,18 @@ if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
function _inheritsLoose(subClass, superClass) { | ||
subClass.prototype = Object.create(superClass.prototype); | ||
subClass.prototype.constructor = subClass; | ||
_setPrototypeOf(subClass, superClass); | ||
} | ||
function _setPrototypeOf(o, p) { | ||
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { | ||
_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { | ||
o.__proto__ = p; | ||
return o; | ||
}; | ||
return _setPrototypeOf(o, p); | ||
} | ||
function _objectWithoutPropertiesLoose(source, excluded) { | ||
@@ -67,3 +59,2 @@ if (source == null) return {}; | ||
var key, i; | ||
for (i = 0; i < sourceKeys.length; i++) { | ||
@@ -74,3 +65,2 @@ key = sourceKeys[i]; | ||
} | ||
return target; | ||
@@ -89,3 +79,2 @@ } | ||
* **/ | ||
function defaultFallbackInView(inView) { | ||
@@ -98,3 +87,2 @@ unsupportedValue = inView; | ||
*/ | ||
function getRootId(root) { | ||
@@ -112,4 +100,2 @@ if (!root) return '0'; | ||
*/ | ||
function optionsToId(options) { | ||
@@ -122,3 +108,2 @@ return Object.keys(options).sort().filter(function (key) { | ||
} | ||
function createObserver(options) { | ||
@@ -128,3 +113,2 @@ // Create a unique ID for this observer instance, based on the root, root margin and threshold. | ||
var instance = observerMap.get(id); | ||
if (!instance) { | ||
@@ -137,3 +121,2 @@ // Create a map of elements this observer is going to observe. Each element has a list of callbacks that should be triggered, once it comes into view. | ||
var _elements$get; | ||
// While it would be nice if you could just look at isIntersecting to determine if the component is inside the viewport, browsers can't agree on how to use it. | ||
@@ -143,4 +126,4 @@ // -Firefox ignores `threshold` when considering `isIntersecting`, so it will never be false again if `threshold` is > 0 | ||
return entry.intersectionRatio >= threshold; | ||
}); // @ts-ignore support IntersectionObserver v2 | ||
}); | ||
// @ts-ignore support IntersectionObserver v2 | ||
if (options.trackVisibility && typeof entry.isVisible === 'undefined') { | ||
@@ -151,3 +134,2 @@ // The browser doesn't support Intersection Observer v2, falling back to v1 behavior. | ||
} | ||
(_elements$get = elements.get(entry.target)) == null ? void 0 : _elements$get.forEach(function (callback) { | ||
@@ -157,4 +139,4 @@ callback(inView, entry); | ||
}); | ||
}, options); // Ensure we have a valid thresholds array. If not, use the threshold from the options | ||
}, options); | ||
// Ensure we have a valid thresholds array. If not, use the threshold from the options | ||
thresholds = observer.thresholds || (Array.isArray(options.threshold) ? options.threshold : [options.threshold || 0]); | ||
@@ -168,3 +150,2 @@ instance = { | ||
} | ||
return instance; | ||
@@ -179,4 +160,2 @@ } | ||
*/ | ||
function observe(element, callback, options, fallbackInView) { | ||
@@ -186,7 +165,5 @@ if (options === void 0) { | ||
} | ||
if (fallbackInView === void 0) { | ||
fallbackInView = unsupportedValue; | ||
} | ||
if (typeof window.IntersectionObserver === 'undefined' && fallbackInView !== undefined) { | ||
@@ -203,19 +180,16 @@ var bounds = element.getBoundingClientRect(); | ||
}); | ||
return function () {// Nothing to cleanup | ||
return function () { | ||
// Nothing to cleanup | ||
}; | ||
} // An observer with the same options can be reused, so lets use this fact | ||
} | ||
// An observer with the same options can be reused, so lets use this fact | ||
var _createObserver = createObserver(options), | ||
id = _createObserver.id, | ||
observer = _createObserver.observer, | ||
elements = _createObserver.elements; // Register the callback listener for this element | ||
id = _createObserver.id, | ||
observer = _createObserver.observer, | ||
elements = _createObserver.elements; | ||
// Register the callback listener for this element | ||
var callbacks = elements.get(element) || []; | ||
if (!elements.has(element)) { | ||
elements.set(element, callbacks); | ||
} | ||
callbacks.push(callback); | ||
@@ -226,3 +200,2 @@ observer.observe(element); | ||
callbacks.splice(callbacks.indexOf(callback), 1); | ||
if (callbacks.length === 0) { | ||
@@ -233,3 +206,2 @@ // No more callback exists for element, so destroy it | ||
} | ||
if (elements.size === 0) { | ||
@@ -244,3 +216,2 @@ // No more elements are being observer by this instance, so destroy it | ||
var _excluded = ["children", "as", "triggerOnce", "threshold", "root", "rootMargin", "onChange", "skip", "trackVisibility", "delay", "initialInView", "fallbackInView"]; | ||
function isPlainChildren(props) { | ||
@@ -298,14 +269,9 @@ return typeof props.children !== 'function'; | ||
*/ | ||
var InView = /*#__PURE__*/function (_React$Component) { | ||
_inheritsLoose(InView, _React$Component); | ||
function InView(props) { | ||
var _this; | ||
_this = _React$Component.call(this, props) || this; | ||
_this.node = null; | ||
_this._unobserveCb = null; | ||
_this.handleNode = function (node) { | ||
@@ -315,3 +281,2 @@ if (_this.node) { | ||
_this.unobserve(); | ||
if (!node && !_this.props.triggerOnce && !_this.props.skip) { | ||
@@ -325,8 +290,5 @@ // Reset the state if we get a new node, and we aren't ignoring updates | ||
} | ||
_this.node = node ? node : null; | ||
_this.observeNode(); | ||
}; | ||
_this.handleChange = function (inView, entry) { | ||
@@ -337,3 +299,2 @@ if (inView && _this.props.triggerOnce) { | ||
} | ||
if (!isPlainChildren(_this.props)) { | ||
@@ -347,3 +308,2 @@ // Store the current State, so we can pass it to the children in the next render update | ||
} | ||
if (_this.props.onChange) { | ||
@@ -354,3 +314,2 @@ // If the user is actively listening for onChange, always trigger it | ||
}; | ||
_this.state = { | ||
@@ -362,5 +321,3 @@ inView: !!props.initialInView, | ||
} | ||
var _proto = InView.prototype; | ||
_proto.componentDidUpdate = function componentDidUpdate(prevProps) { | ||
@@ -373,3 +330,2 @@ // If a IntersectionObserver option changed, reinit the observer | ||
}; | ||
_proto.componentWillUnmount = function componentWillUnmount() { | ||
@@ -379,12 +335,11 @@ this.unobserve(); | ||
}; | ||
_proto.observeNode = function observeNode() { | ||
if (!this.node || this.props.skip) return; | ||
var _this$props = this.props, | ||
threshold = _this$props.threshold, | ||
root = _this$props.root, | ||
rootMargin = _this$props.rootMargin, | ||
trackVisibility = _this$props.trackVisibility, | ||
delay = _this$props.delay, | ||
fallbackInView = _this$props.fallbackInView; | ||
threshold = _this$props.threshold, | ||
root = _this$props.root, | ||
rootMargin = _this$props.rootMargin, | ||
trackVisibility = _this$props.trackVisibility, | ||
delay = _this$props.delay, | ||
fallbackInView = _this$props.fallbackInView; | ||
this._unobserveCb = observe(this.node, this.handleChange, { | ||
@@ -400,16 +355,13 @@ threshold: threshold, | ||
}; | ||
_proto.unobserve = function unobserve() { | ||
if (this._unobserveCb) { | ||
this._unobserveCb(); | ||
this._unobserveCb = null; | ||
} | ||
}; | ||
_proto.render = function render() { | ||
if (!isPlainChildren(this.props)) { | ||
var _this$state = this.state, | ||
inView = _this$state.inView, | ||
entry = _this$state.entry; | ||
inView = _this$state.inView, | ||
entry = _this$state.entry; | ||
return this.props.children({ | ||
@@ -421,8 +373,6 @@ inView: inView, | ||
} | ||
var _this$props2 = this.props, | ||
children = _this$props2.children, | ||
as = _this$props2.as, | ||
props = _objectWithoutPropertiesLoose(_this$props2, _excluded); | ||
children = _this$props2.children, | ||
as = _this$props2.as, | ||
props = _objectWithoutPropertiesLoose(_this$props2, _excluded); | ||
return React__namespace.createElement(as || 'div', _extends({ | ||
@@ -432,3 +382,2 @@ ref: this.handleNode | ||
}; | ||
return InView; | ||
@@ -463,33 +412,27 @@ }(React__namespace.Component); | ||
*/ | ||
function useInView(_temp) { | ||
var _state$entry; | ||
var _ref = _temp === void 0 ? {} : _temp, | ||
threshold = _ref.threshold, | ||
delay = _ref.delay, | ||
trackVisibility = _ref.trackVisibility, | ||
rootMargin = _ref.rootMargin, | ||
root = _ref.root, | ||
triggerOnce = _ref.triggerOnce, | ||
skip = _ref.skip, | ||
initialInView = _ref.initialInView, | ||
fallbackInView = _ref.fallbackInView, | ||
onChange = _ref.onChange; | ||
threshold = _ref.threshold, | ||
delay = _ref.delay, | ||
trackVisibility = _ref.trackVisibility, | ||
rootMargin = _ref.rootMargin, | ||
root = _ref.root, | ||
triggerOnce = _ref.triggerOnce, | ||
skip = _ref.skip, | ||
initialInView = _ref.initialInView, | ||
fallbackInView = _ref.fallbackInView, | ||
onChange = _ref.onChange; | ||
var _React$useState = React__namespace.useState(null), | ||
ref = _React$useState[0], | ||
setRef = _React$useState[1]; | ||
ref = _React$useState[0], | ||
setRef = _React$useState[1]; | ||
var callback = React__namespace.useRef(); | ||
var _React$useState2 = React__namespace.useState({ | ||
inView: !!initialInView, | ||
entry: undefined | ||
}), | ||
state = _React$useState2[0], | ||
setState = _React$useState2[1]; // Store the onChange callback in a `ref`, so we can access the latest instance | ||
inView: !!initialInView, | ||
entry: undefined | ||
}), | ||
state = _React$useState2[0], | ||
setState = _React$useState2[1]; | ||
// Store the onChange callback in a `ref`, so we can access the latest instance | ||
// inside the `useEffect`, but without triggering a rerender. | ||
callback.current = onChange; | ||
@@ -506,3 +449,2 @@ React__namespace.useEffect(function () { | ||
if (callback.current) callback.current(inView, entry); | ||
if (entry.isIntersecting && triggerOnce && unobserve) { | ||
@@ -527,5 +469,7 @@ // If it should only trigger once, unobserve the element after it's inView | ||
}; | ||
}, // We break the rule here, because we aren't including the actual `threshold` variable | ||
}, | ||
// We break the rule here, because we aren't including the actual `threshold` variable | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
[// If the threshold is an array, convert it to a string, so it won't change between renders. | ||
[ | ||
// If the threshold is an array, convert it to a string, so it won't change between renders. | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
@@ -535,3 +479,2 @@ Array.isArray(threshold) ? threshold.toString() : threshold, ref, root, rootMargin, triggerOnce, skip, trackVisibility, fallbackInView, delay]); | ||
var previousEntryTarget = React__namespace.useRef(); | ||
if (!ref && entryTarget && !triggerOnce && !skip && previousEntryTarget.current !== entryTarget) { | ||
@@ -546,5 +489,4 @@ // If we don't have a node ref, then reset the state (unless the hook is set to only `triggerOnce` or `skip`) | ||
} | ||
var result = [setRef, state.inView, state.entry]; // Support object destructuring, by adding the specific values. | ||
var result = [setRef, state.inView, state.entry]; | ||
// Support object destructuring, by adding the specific values. | ||
result.ref = result[0]; | ||
@@ -551,0 +493,0 @@ result.inView = result[1]; |
@@ -356,3 +356,3 @@ # react-intersection-observer | ||
return ( | ||
<div ref={ref} id="wrapper"> | ||
<div ref={ref} data-testid="wrapper"> | ||
{inView.toString()} | ||
@@ -359,0 +359,0 @@ </div> |
@@ -13,4 +13,6 @@ "use strict"; | ||
setupIntersectionMocking(jest.fn); | ||
else if (typeof vi !== 'undefined') | ||
else if (typeof vi !== 'undefined') { | ||
// Cast the `vi.fn` to `jest.fn` - The returned `Mock` type has a different signature than `jest.fn` | ||
setupIntersectionMocking(vi.fn); | ||
} | ||
}); | ||
@@ -24,13 +26,15 @@ afterEach(() => { | ||
return; | ||
console.error('React Intersection Observer was not configured to handle mocking.\n' + | ||
'Outside Jest, you might need to manually configure it by calling setupIntersectionMocking() and resetIntersectionMocking() in your test setup file.', +`\n// test-setup.js | ||
import { resetIntersectionMocking, setupIntersectionMocking } from 'react-intersection-observer/test-utils'; | ||
beforeEach(() => { | ||
setupIntersectionMocking(vi.fn); | ||
}); | ||
console.error(`React Intersection Observer was not configured to handle mocking. | ||
Outside Jest and Vitest, you might need to manually configure it by calling setupIntersectionMocking() and resetIntersectionMocking() in your test setup file. | ||
afterEach(() => { | ||
resetIntersectionMocking(); | ||
});`); | ||
// test-setup.js | ||
import { resetIntersectionMocking, setupIntersectionMocking } from 'react-intersection-observer/test-utils'; | ||
beforeEach(() => { | ||
setupIntersectionMocking(vi.fn); | ||
}); | ||
afterEach(() => { | ||
resetIntersectionMocking(); | ||
});`); | ||
} | ||
@@ -37,0 +41,0 @@ /** |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
2101
214578