@tamagui/react-native-web-lite
Version:
React Native for Web
181 lines (179 loc) • 7.98 kB
JavaScript
import { invariant } from "@tamagui/react-native-web-internals";
function _class_call_check(instance, Constructor) {
if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || !1, descriptor.configurable = !0, "value" in descriptor && (descriptor.writable = !0), Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _create_class(Constructor, protoProps, staticProps) {
return protoProps && _defineProperties(Constructor.prototype, protoProps), staticProps && _defineProperties(Constructor, staticProps), Constructor;
}
function _define_property(obj, key, value) {
return key in obj ? Object.defineProperty(obj, key, {
value,
enumerable: !0,
configurable: !0,
writable: !0
}) : obj[key] = value, obj;
}
var ViewabilityHelper = /* @__PURE__ */function () {
"use strict";
function ViewabilityHelper2() {
var config = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {
viewAreaCoveragePercentThreshold: 0
};
_class_call_check(this, ViewabilityHelper2), _define_property(this, "_config", void 0), _define_property(this, "_hasInteracted", !1), _define_property(this, "_timers", /* @__PURE__ */new Set()), _define_property(this, "_viewableIndices", []), _define_property(this, "_viewableItems", /* @__PURE__ */new Map()), this._config = config;
}
return _create_class(ViewabilityHelper2, [{
/**
* Cleanup, e.g. on unmount. Clears any pending timers.
*/
key: "dispose",
value: function () {
this._timers.forEach(clearTimeout);
}
}, {
/**
* Determines which items are viewable based on the current metrics and config.
*/
key: "computeViewableItems",
value: function (props, scrollOffset, viewportHeight, getFrameMetrics, renderRange) {
var itemCount = props.getItemCount(props.data),
{
itemVisiblePercentThreshold,
viewAreaCoveragePercentThreshold
} = this._config,
viewAreaMode = viewAreaCoveragePercentThreshold != null,
viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
invariant(viewablePercentThreshold != null && itemVisiblePercentThreshold != null != (viewAreaCoveragePercentThreshold != null), "Must set exactly one of itemVisiblePercentThreshold or viewAreaCoveragePercentThreshold");
var viewableIndices = [];
if (itemCount === 0) return viewableIndices;
var firstVisible = -1,
{
first,
last
} = renderRange || {
first: 0,
last: itemCount - 1
};
if (last >= itemCount) return console.warn("Invalid render range computing viewability " + JSON.stringify({
renderRange,
itemCount
})), [];
for (var idx = first; idx <= last; idx++) {
var metrics = getFrameMetrics(idx, props);
if (metrics) {
var top = metrics.offset - scrollOffset,
bottom = top + metrics.length;
if (top < viewportHeight && bottom > 0) firstVisible = idx, _isViewable(viewAreaMode, viewablePercentThreshold, top, bottom, viewportHeight, metrics.length) && viewableIndices.push(idx);else if (firstVisible >= 0) break;
}
}
return viewableIndices;
}
}, {
/**
* Figures out which items are viewable and how that has changed from before and calls
* `onViewableItemsChanged` as appropriate.
*/
key: "onUpdate",
value: function (props, scrollOffset, viewportHeight, getFrameMetrics, createViewToken, onViewableItemsChanged, renderRange) {
var _this = this,
itemCount = props.getItemCount(props.data);
if (!(this._config.waitForInteraction && !this._hasInteracted || itemCount === 0 || !getFrameMetrics(0, props))) {
var viewableIndices = [];
if (itemCount && (viewableIndices = this.computeViewableItems(props, scrollOffset, viewportHeight, getFrameMetrics, renderRange)), !(this._viewableIndices.length === viewableIndices.length && this._viewableIndices.every(function (v, ii) {
return v === viewableIndices[ii];
}))) if (this._viewableIndices = viewableIndices, this._config.minimumViewTime) {
var handle = setTimeout(function () {
_this._timers.delete(handle), _this._onUpdateSync(props, viewableIndices, onViewableItemsChanged, createViewToken);
}, this._config.minimumViewTime);
this._timers.add(handle);
} else this._onUpdateSync(props, viewableIndices, onViewableItemsChanged, createViewToken);
}
}
}, {
key: "resetViewableIndices",
value: function () {
this._viewableIndices = [];
}
}, {
key: "recordInteraction",
value: function () {
this._hasInteracted = !0;
}
}, {
key: "_onUpdateSync",
value: function (props, viewableIndicesToCheck, onViewableItemsChanged, createViewToken) {
var _this = this;
viewableIndicesToCheck = viewableIndicesToCheck.filter(function (ii) {
return _this._viewableIndices.includes(ii);
});
var prevItems = this._viewableItems,
nextItems = new Map(viewableIndicesToCheck.map(function (ii) {
var viewable2 = createViewToken(ii, !0, props);
return [viewable2.key, viewable2];
})),
changed = [],
_iteratorNormalCompletion = !0,
_didIteratorError = !1,
_iteratorError = void 0;
try {
for (var _iterator = nextItems[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = !0) {
var [key, viewable] = _step.value;
prevItems.has(key) || changed.push(viewable);
}
} catch (err) {
_didIteratorError = !0, _iteratorError = err;
} finally {
try {
!_iteratorNormalCompletion && _iterator.return != null && _iterator.return();
} finally {
if (_didIteratorError) throw _iteratorError;
}
}
var _iteratorNormalCompletion1 = !0,
_didIteratorError1 = !1,
_iteratorError1 = void 0;
try {
for (var _iterator1 = prevItems[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = !0) {
var [key1, viewable1] = _step1.value;
nextItems.has(key1) || changed.push({
...viewable1,
isViewable: !1
});
}
} catch (err) {
_didIteratorError1 = !0, _iteratorError1 = err;
} finally {
try {
!_iteratorNormalCompletion1 && _iterator1.return != null && _iterator1.return();
} finally {
if (_didIteratorError1) throw _iteratorError1;
}
}
changed.length > 0 && (this._viewableItems = nextItems, onViewableItemsChanged({
viewableItems: Array.from(nextItems.values()),
changed
}));
}
}]), ViewabilityHelper2;
}();
function _isViewable(viewAreaMode, viewablePercentThreshold, top, bottom, viewportHeight, itemLength) {
if (_isEntirelyVisible(top, bottom, viewportHeight)) return !0;
var pixels = _getPixelsVisible(top, bottom, viewportHeight),
percent = 100 * (viewAreaMode ? pixels / viewportHeight : pixels / itemLength);
return percent >= viewablePercentThreshold;
}
function _getPixelsVisible(top, bottom, viewportHeight) {
var visibleHeight = Math.min(bottom, viewportHeight) - Math.max(top, 0);
return Math.max(0, visibleHeight);
}
function _isEntirelyVisible(top, bottom, viewportHeight) {
return top >= 0 && bottom <= viewportHeight && bottom > top;
}
var ViewabilityHelper_default = ViewabilityHelper;
export { ViewabilityHelper_default as default };
//# sourceMappingURL=ViewabilityHelper.native.js.map