UNPKG

@futurejj/react-native-visibility-sensor

Version:

A React Native wrapper to check whether a component is in the view port to track impressions and clicks

106 lines (104 loc) 4.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _jsxRuntime = require("react/jsx-runtime"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function useInterval(callback, delay) { const savedCallback = (0, _react.useRef)(callback); (0, _react.useEffect)(() => { savedCallback.current = callback; }, [callback]); (0, _react.useEffect)(() => { if (delay === null || delay === undefined) { return; } const id = setInterval(() => savedCallback.current(), delay); return () => clearInterval(id); }, [delay]); } const VisibilitySensor = /*#__PURE__*/(0, _react.forwardRef)((props, ref) => { const { onChange, disabled = false, triggerOnce = false, delay, threshold = {}, children, ...rest } = props; const localRef = (0, _react.useRef)(null); (0, _react.useImperativeHandle)(ref, () => ({ getInnerRef: () => localRef.current })); const [rectDimensions, setRectDimensions] = (0, _react.useState)({ rectTop: 0, rectBottom: 0, rectLeft: 0, rectRight: 0, rectWidth: 0, rectHeight: 0 }); const [lastValue, setLastValue] = (0, _react.useState)(undefined); const [active, setActive] = (0, _react.useState)(false); const measureInnerView = () => { if (!active) return; localRef.current?.measure((_x, _y, width, height, pageX, pageY) => { const dimensions = { rectTop: pageY, rectBottom: pageY + height, rectLeft: pageX, rectRight: pageX + width, rectWidth: width, rectHeight: height }; if (rectDimensions.rectTop !== dimensions.rectTop || rectDimensions.rectBottom !== dimensions.rectBottom || rectDimensions.rectLeft !== dimensions.rectLeft || rectDimensions.rectRight !== dimensions.rectRight || rectDimensions.rectWidth !== dimensions.rectWidth || rectDimensions.rectHeight !== dimensions.rectHeight) { setRectDimensions(dimensions); } }); }; useInterval(measureInnerView, delay || 100); const startWatching = (0, _react.useCallback)(() => { if (!active) setActive(true); }, [active]); const stopWatching = (0, _react.useCallback)(() => { if (active) setActive(false); }, [active]); (0, _react.useEffect)(() => { if (!disabled) { startWatching(); } return () => { stopWatching(); }; }, [disabled, startWatching, stopWatching]); (0, _react.useEffect)(() => { const window = _reactNative.Dimensions.get('window'); const isVisible = rectDimensions.rectTop + (threshold.top || 0) <= window.height && // Top edge is within the bottom of the window rectDimensions.rectBottom - (threshold.bottom || 0) >= 0 && // Bottom edge is within the top of the window rectDimensions.rectLeft + (threshold.left || 0) <= window.width && // Left edge is within the right of the window rectDimensions.rectRight - (threshold.right || 0) >= 0; // Right edge is within the left of the window if (lastValue !== isVisible) { setLastValue(isVisible); onChange(isVisible); if (isVisible && triggerOnce) { stopWatching(); } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [rectDimensions, lastValue]); return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { ref: localRef, ...rest, children: children }); }); var _default = exports.default = VisibilitySensor; //# sourceMappingURL=VisibilitySensor.js.map