@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
JavaScript
;
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