@tamagui/react-native-web-lite
Version:
React Native for Web
200 lines (199 loc) • 9.18 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: !0 });
}, __copyProps = (to, from, except, desc) => {
if (from && typeof from == "object" || typeof from == "function")
for (let key of __getOwnPropNames(from))
!__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0 }), mod);
var ViewabilityHelper_exports = {};
__export(ViewabilityHelper_exports, {
default: () => ViewabilityHelper_default
});
module.exports = __toCommonJS(ViewabilityHelper_exports);
var import_react_native_web_internals = require("@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;
(0, import_react_native_web_internals.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;
//# sourceMappingURL=ViewabilityHelper.js.map