@tamagui/react-native-web-lite
Version:
React Native for Web
1,006 lines (1,004 loc) • 54.3 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { invariant, StyleSheet } from "@tamagui/react-native-web-internals";
import ViewabilityHelper from "../ViewabilityHelper.native.js";
import { CellRenderMask } from "./CellRenderMask.native.js";
import StateSafePureComponent from "./StateSafePureComponent.native.js";
import { VirtualizedListCellContextProvider, VirtualizedListContext, VirtualizedListContextProvider } from "./VirtualizedListContext.native.js";
import ScrollView from "../../../ScrollView/ScrollViewBase.native.js";
import View from "../../../View";
import CellRenderer from "./VirtualizedListCellRenderer.native.js";
import FillRateHelper from "../FillRateHelper";
import ChildListCollection from "./ChildListCollection.native.js";
import React from "react";
import clamp from "../Utilities/clamp.native.js";
import { keyExtractor as defaultKeyExtractor } from "../VirtualizeUtils";
import Batchinator from "../../../Batchinator";
import RefreshControl from "../../../RefreshControl";
function _assert_this_initialized(self) {
if (self === void 0) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
return self;
}
function _call_super(_this, derived, args) {
return derived = _get_prototype_of(derived), _possible_constructor_return(_this, _is_native_reflect_construct() ? Reflect.construct(derived, args || [], _get_prototype_of(_this).constructor) : derived.apply(_this, args));
}
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;
}
function _get_prototype_of(o) {
return _get_prototype_of = Object.setPrototypeOf ? Object.getPrototypeOf : function (o2) {
return o2.__proto__ || Object.getPrototypeOf(o2);
}, _get_prototype_of(o);
}
function _inherits(subClass, superClass) {
if (typeof superClass != "function" && superClass !== null) throw new TypeError("Super expression must either be null or a function");
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: !0,
configurable: !0
}
}), superClass && _set_prototype_of(subClass, superClass);
}
function _possible_constructor_return(self, call) {
return call && (_type_of(call) === "object" || typeof call == "function") ? call : _assert_this_initialized(self);
}
function _set_prototype_of(o, p) {
return _set_prototype_of = Object.setPrototypeOf || function (o2, p2) {
return o2.__proto__ = p2, o2;
}, _set_prototype_of(o, p);
}
function _type_of(obj) {
"@swc/helpers - typeof";
return obj && typeof Symbol < "u" && obj.constructor === Symbol ? "symbol" : typeof obj;
}
function _is_native_reflect_construct() {
try {
var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
} catch {}
return (_is_native_reflect_construct = function () {
return !!result;
})();
}
var __DEV__ = process.env.NODE_ENV !== "production",
ON_EDGE_REACHED_EPSILON = 1e-3,
_usedIndexForKey = !1,
_keylessItemComponentName = "";
function horizontalOrDefault(horizontal) {
return horizontal ?? !1;
}
function initialNumToRenderOrDefault(initialNumToRender) {
return initialNumToRender ?? 10;
}
function maxToRenderPerBatchOrDefault(maxToRenderPerBatch) {
return maxToRenderPerBatch ?? 10;
}
function onStartReachedThresholdOrDefault(onStartReachedThreshold) {
return onStartReachedThreshold ?? 2;
}
function onEndReachedThresholdOrDefault(onEndReachedThreshold) {
return onEndReachedThreshold ?? 2;
}
function getScrollingThreshold(threshold, visibleLength) {
return threshold * visibleLength / 2;
}
function scrollEventThrottleOrDefault(scrollEventThrottle) {
return scrollEventThrottle ?? 50;
}
function windowSizeOrDefault(windowSize) {
return windowSize ?? 21;
}
function findLastWhere(arr, predicate) {
for (var i = arr.length - 1; i >= 0; i--) if (predicate(arr[i])) return arr[i];
return null;
}
var VirtualizedList = /* @__PURE__ */function (StateSafePureComponent2) {
"use strict";
_inherits(VirtualizedList2, StateSafePureComponent2);
function VirtualizedList2(props) {
_class_call_check(this, VirtualizedList2);
var _this;
_this = _call_super(this, VirtualizedList2, [props]), _define_property(_this, "_getScrollMetrics", function () {
return _this._scrollMetrics;
}), _define_property(_this, "_getOutermostParentListRef", function () {
return _this._isNestedWithSameOrientation() ? _this.context.getOutermostParentListRef() : _this;
}), _define_property(_this, "_registerAsNestedChild", function (childList) {
_this._nestedChildLists.add(childList.ref, childList.cellKey), _this._hasInteracted && childList.ref.recordInteraction();
}), _define_property(_this, "_unregisterAsNestedChild", function (childList) {
_this._nestedChildLists.remove(childList.ref);
}), _define_property(_this, "invertedWheelEventHandler", void 0), _define_property(_this, "_onUpdateSeparators", function (keys, newProps) {
keys.forEach(function (key) {
var ref = key != null && _this._cellRefs[key];
ref && ref.updateSeparatorProps(newProps);
});
}), _define_property(_this, "_getSpacerKey", function (isVertical) {
return isVertical ? "height" : "width";
}), _define_property(_this, "_averageCellLength", 0), _define_property(_this, "_cellRefs", {}), _define_property(_this, "_fillRateHelper", void 0), _define_property(_this, "_frames", {}), _define_property(_this, "_footerLength", 0), _define_property(_this, "_hasTriggeredInitialScrollToIndex", !1), _define_property(_this, "_hasInteracted", !1), _define_property(_this, "_hasMore", !1), _define_property(_this, "_hasWarned", {}), _define_property(_this, "_headerLength", 0), _define_property(_this, "_hiPriInProgress", !1), _define_property(_this, "_highestMeasuredFrameIndex", 0), _define_property(_this, "_indicesToKeys", /* @__PURE__ */new Map()), _define_property(_this, "_lastFocusedCellKey", null), _define_property(_this, "_nestedChildLists", new ChildListCollection()), _define_property(_this, "_offsetFromParentVirtualizedList", 0), _define_property(_this, "_prevParentOffset", 0), _define_property(_this, "_scrollMetrics", {
contentLength: 0,
dOffset: 0,
dt: 10,
offset: 0,
timestamp: 0,
velocity: 0,
visibleLength: 0,
zoomScale: 1
}), _define_property(_this, "_scrollRef", null), _define_property(_this, "_sentStartForContentLength", 0), _define_property(_this, "_sentEndForContentLength", 0), _define_property(_this, "_totalCellLength", 0), _define_property(_this, "_totalCellsMeasured", 0), _define_property(_this, "_updateCellsToRenderBatcher", void 0), _define_property(_this, "_viewabilityTuples", []), _define_property(_this, "_captureScrollRef", function (ref) {
_this._scrollRef = ref;
}), _define_property(_this, "_defaultRenderScrollComponent", function (props2) {
var onRefresh = props2.onRefresh;
if (_this._isNestedWithSameOrientation()) return /* @__PURE__ */_jsx(View, {
...props2
});
if (onRefresh) {
var _props_refreshing;
return invariant(typeof props2.refreshing == "boolean", "`refreshing` prop must be set as a boolean in order to use `onRefresh`, but got `" + JSON.stringify((_props_refreshing = props2.refreshing) !== null && _props_refreshing !== void 0 ? _props_refreshing : "undefined") + "`"), /* @__PURE__ */_jsx(ScrollView, {
...props2,
refreshControl: props2.refreshControl == null ? /* @__PURE__ */_jsx(RefreshControl, {
refreshing: props2.refreshing,
onRefresh,
progressViewOffset: props2.progressViewOffset
}) : props2.refreshControl
});
} else return /* @__PURE__ */_jsx(ScrollView, {
...props2
});
}), _define_property(_this, "_onCellLayout", function (e, cellKey, index) {
var layout = e.nativeEvent.layout,
next = {
offset: _this._selectOffset(layout),
length: _this._selectLength(layout),
index,
inLayout: !0
},
curr = _this._frames[cellKey];
!curr || next.offset !== curr.offset || next.length !== curr.length || index !== curr.index ? (_this._totalCellLength += next.length - (curr ? curr.length : 0), _this._totalCellsMeasured += curr ? 0 : 1, _this._averageCellLength = _this._totalCellLength / _this._totalCellsMeasured, _this._frames[cellKey] = next, _this._highestMeasuredFrameIndex = Math.max(_this._highestMeasuredFrameIndex, index), _this._scheduleCellsToRenderUpdate()) : _this._frames[cellKey].inLayout = !0, _this._triggerRemeasureForChildListsInCell(cellKey), _this._computeBlankness(), _this._updateViewableItems(
// @ts-ignore
_this.props, _this.state.cellsAroundViewport);
}), _define_property(_this, "_onCellUnmount", function (cellKey) {
delete _this._cellRefs[cellKey];
var curr = _this._frames[cellKey];
curr && (_this._frames[cellKey] = {
...curr,
inLayout: !1
});
}), _define_property(_this, "_onLayout", function (e) {
_this._isNestedWithSameOrientation() ? _this.measureLayoutRelativeToContainingList() : _this._scrollMetrics.visibleLength = _this._selectLength(e.nativeEvent.layout), _this.props.onLayout && _this.props.onLayout(e), _this._scheduleCellsToRenderUpdate(), _this._maybeCallOnEdgeReached();
}), _define_property(_this, "_onLayoutEmpty", function (e) {
_this.props.onLayout && _this.props.onLayout(e);
}), _define_property(_this, "_onLayoutFooter", function (e) {
_this._triggerRemeasureForChildListsInCell(_this._getFooterCellKey()), _this._footerLength = _this._selectLength(e.nativeEvent.layout);
}), _define_property(_this, "_onLayoutHeader", function (e) {
_this._headerLength = _this._selectLength(e.nativeEvent.layout);
}), _define_property(_this, "_onContentSizeChange", function (width, height) {
width > 0 && height > 0 && _this.props.initialScrollIndex != null && _this.props.initialScrollIndex > 0 && !_this._hasTriggeredInitialScrollToIndex && (_this.props.contentOffset == null && (_this.props.initialScrollIndex < _this.props.getItemCount(_this.props.data) ? _this.scrollToIndex({
animated: !1,
index: nullthrows(_this.props.initialScrollIndex)
}) : _this.scrollToEnd({
animated: !1
})), _this._hasTriggeredInitialScrollToIndex = !0), _this.props.onContentSizeChange && _this.props.onContentSizeChange(width, height), _this._scrollMetrics.contentLength = _this._selectLength({
height,
width
}), _this._scheduleCellsToRenderUpdate(), _this._maybeCallOnEdgeReached();
}), _define_property(_this, "_convertParentScrollMetrics", function (metrics) {
var offset = metrics.offset - _this._offsetFromParentVirtualizedList,
visibleLength = metrics.visibleLength,
dOffset = offset - _this._scrollMetrics.offset,
contentLength = _this._scrollMetrics.contentLength;
return {
visibleLength,
contentLength,
offset,
dOffset
};
}), _define_property(_this, "_onScroll", function (e) {
_this._nestedChildLists.forEach(function (childList) {
childList._onScroll(e);
}), _this.props.onScroll && _this.props.onScroll(e);
var timestamp = e.timeStamp,
visibleLength = _this._selectLength(e.nativeEvent.layoutMeasurement),
contentLength = _this._selectLength(e.nativeEvent.contentSize),
offset = _this._selectOffset(e.nativeEvent.contentOffset),
dOffset = offset - _this._scrollMetrics.offset;
if (_this._isNestedWithSameOrientation()) {
if (_this._scrollMetrics.contentLength === 0) return;
({
visibleLength,
contentLength,
offset,
dOffset
} = _this._convertParentScrollMetrics({
visibleLength,
offset
}));
}
var dt = _this._scrollMetrics.timestamp ? Math.max(1, timestamp - _this._scrollMetrics.timestamp) : 1,
velocity = dOffset / dt;
dt > 500 && _this._scrollMetrics.dt > 500 && contentLength > 5 * visibleLength && !_this._hasWarned.perf && (infoLog("VirtualizedList: You have a large list that is slow to update - make sure your renderItem function renders components that follow React performance best practices like PureComponent, shouldComponentUpdate, etc.", {
dt,
prevDt: _this._scrollMetrics.dt,
contentLength
}), _this._hasWarned.perf = !0);
var zoomScale = e.nativeEvent.zoomScale < 0 ? 1 : e.nativeEvent.zoomScale;
_this._scrollMetrics = {
contentLength,
dt,
dOffset,
offset,
timestamp,
velocity,
visibleLength,
zoomScale
}, _this._updateViewableItems(_this.props, _this.state.cellsAroundViewport), _this.props && (_this._maybeCallOnEdgeReached(), velocity !== 0 && _this._fillRateHelper.activate(), _this._computeBlankness(), _this._scheduleCellsToRenderUpdate());
}), _define_property(_this, "_onScrollBeginDrag", function (e) {
_this._nestedChildLists.forEach(function (childList) {
childList._onScrollBeginDrag(e);
}), _this._viewabilityTuples.forEach(function (tuple) {
tuple.viewabilityHelper.recordInteraction();
}), _this._hasInteracted = !0, _this.props.onScrollBeginDrag && _this.props.onScrollBeginDrag(e);
}), _define_property(_this, "_onScrollEndDrag", function (e) {
_this._nestedChildLists.forEach(function (childList) {
childList._onScrollEndDrag(e);
});
var {
velocity
} = e.nativeEvent;
velocity && (_this._scrollMetrics.velocity = _this._selectOffset(velocity)), _this._computeBlankness(), _this.props.onScrollEndDrag && _this.props.onScrollEndDrag(e);
}), _define_property(_this, "_onMomentumScrollBegin", function (e) {
_this._nestedChildLists.forEach(function (childList) {
childList._onMomentumScrollBegin(e);
}), _this.props.onMomentumScrollBegin && _this.props.onMomentumScrollBegin(e);
}), _define_property(_this, "_onMomentumScrollEnd", function (e) {
_this._nestedChildLists.forEach(function (childList) {
childList._onMomentumScrollEnd(e);
}), _this._scrollMetrics.velocity = 0, _this._computeBlankness(), _this.props.onMomentumScrollEnd && _this.props.onMomentumScrollEnd(e);
}), _define_property(_this, "_updateCellsToRender", function () {
_this._updateViewableItems(_this.props, _this.state.cellsAroundViewport), _this.setState(function (state, props2) {
var cellsAroundViewport = _this._adjustCellsAroundViewport(props2, state.cellsAroundViewport),
renderMask = VirtualizedList2._createRenderMask(props2, cellsAroundViewport, _this._getNonViewportRenderRegions(props2));
return cellsAroundViewport.first === state.cellsAroundViewport.first && cellsAroundViewport.last === state.cellsAroundViewport.last && renderMask.equals(state.renderMask) ? null : {
cellsAroundViewport,
renderMask
};
});
}), _define_property(_this, "_createViewToken", function (index, isViewable, props2) {
var {
data,
getItem
} = props2,
item = getItem(data, index);
return {
index,
item,
key: _this._keyExtractor(item, index, props2),
isViewable
};
}), _define_property(_this, "_getOffsetApprox", function (index, props2) {
if (Number.isInteger(index)) return _this.__getFrameMetricsApprox(index, props2).offset;
var frameMetrics = _this.__getFrameMetricsApprox(Math.floor(index), props2),
remainder = index - Math.floor(index);
return frameMetrics.offset + remainder * frameMetrics.length;
}), _define_property(_this, "__getFrameMetricsApprox", function (index, props2) {
var frame = _this._getFrameMetrics(index, props2);
if (frame && frame.index === index) return frame;
var {
data,
getItemCount,
getItemLayout
} = props2;
return invariant(index >= 0 && index < getItemCount(data), "Tried to get frame for out of range index " + index), invariant(!getItemLayout, "Should not have to estimate frames when a measurement metrics function is provided"), {
length: _this._averageCellLength,
offset: _this._averageCellLength * index
};
}), _define_property(_this, "_getFrameMetrics", function (index, props2) {
var {
data,
getItem,
getItemCount,
getItemLayout
} = props2;
invariant(index >= 0 && index < getItemCount(data), "Tried to get frame for out of range index " + index);
var item = getItem(data, index),
frame = _this._frames[_this._keyExtractor(item, index, props2)];
return (!frame || frame.index !== index) && getItemLayout ? getItemLayout(data, index) : frame;
}), _define_property(_this, "_getNonViewportRenderRegions", function (props2) {
if (!(_this._lastFocusedCellKey && _this._cellRefs[_this._lastFocusedCellKey])) return [];
var lastFocusedCellRenderer = _this._cellRefs[_this._lastFocusedCellKey],
focusedCellIndex = lastFocusedCellRenderer.props.index,
itemCount = props2.getItemCount(props2.data);
if (focusedCellIndex >= itemCount || _this._keyExtractor(props2.getItem(props2.data, focusedCellIndex), focusedCellIndex, props2) !== _this._lastFocusedCellKey) return [];
for (var first = focusedCellIndex, heightOfCellsBeforeFocused = 0, i = first - 1; i >= 0 && heightOfCellsBeforeFocused < _this._scrollMetrics.visibleLength; i--) first--, heightOfCellsBeforeFocused += _this.__getFrameMetricsApprox(i, props2).length;
for (var last = focusedCellIndex, heightOfCellsAfterFocused = 0, i1 = last + 1; i1 < itemCount && heightOfCellsAfterFocused < _this._scrollMetrics.visibleLength; i1++) last++, heightOfCellsAfterFocused += _this.__getFrameMetricsApprox(i1, props2).length;
return [{
first,
last
}];
}), _this._checkProps(props), _this._fillRateHelper = new FillRateHelper(_this._getFrameMetrics);
var _this_props_updateCellsBatchingPeriod;
if (_this._updateCellsToRenderBatcher = new Batchinator(_this._updateCellsToRender, (_this_props_updateCellsBatchingPeriod = _this.props.updateCellsBatchingPeriod) !== null && _this_props_updateCellsBatchingPeriod !== void 0 ? _this_props_updateCellsBatchingPeriod : 50), _this.props.viewabilityConfigCallbackPairs) _this._viewabilityTuples = _this.props.viewabilityConfigCallbackPairs.map(function (pair) {
return {
viewabilityHelper: new ViewabilityHelper(pair.viewabilityConfig),
onViewableItemsChanged: pair.onViewableItemsChanged
};
});else {
var {
onViewableItemsChanged,
viewabilityConfig
} = _this.props;
onViewableItemsChanged && _this._viewabilityTuples.push({
viewabilityHelper: new ViewabilityHelper(viewabilityConfig),
onViewableItemsChanged
});
}
var initialRenderRegion = VirtualizedList2._initialRenderRegion(props);
return _this.state = {
cellsAroundViewport: initialRenderRegion,
renderMask: VirtualizedList2._createRenderMask(props, initialRenderRegion)
}, _this.invertedWheelEventHandler = function (ev) {
var scrollOffset = _this.props.horizontal ? ev.target.scrollLeft : ev.target.scrollTop,
scrollLength = _this.props.horizontal ? ev.target.scrollWidth : ev.target.scrollHeight,
clientLength = _this.props.horizontal ? ev.target.clientWidth : ev.target.clientHeight,
isEventTargetScrollable = scrollLength > clientLength,
delta = _this.props.horizontal ? ev.deltaX || ev.wheelDeltaX : ev.deltaY || ev.wheelDeltaY,
leftoverDelta = delta;
isEventTargetScrollable && (leftoverDelta = delta < 0 ? Math.min(delta + scrollOffset, 0) : Math.max(delta - (scrollLength - clientLength - scrollOffset), 0));
var targetDelta = delta - leftoverDelta;
if (_this.props.inverted && _this._scrollRef && _this._scrollRef.getScrollableNode) {
var node = _this._scrollRef.getScrollableNode();
if (_this.props.horizontal) {
ev.target.scrollLeft += targetDelta;
var nextScrollLeft = node.scrollLeft - leftoverDelta;
node.scrollLeft = _this.props.getItemLayout ? nextScrollLeft : Math.min(nextScrollLeft, _this._totalCellLength);
} else {
ev.target.scrollTop += targetDelta;
var nextScrollTop = node.scrollTop - leftoverDelta;
node.scrollTop = _this.props.getItemLayout ? nextScrollTop : Math.min(nextScrollTop, _this._totalCellLength);
}
ev.preventDefault();
}
}, _this;
}
return _create_class(VirtualizedList2, [{
// scrollToEnd may be janky without getItemLayout prop
key: "scrollToEnd",
value: function (params) {
var animated = params ? params.animated : !0,
veryLast = this.props.getItemCount(this.props.data) - 1;
if (!(veryLast < 0)) {
var frame = this.__getFrameMetricsApprox(veryLast, this.props),
offset = Math.max(0, frame.offset + frame.length + this._footerLength - this._scrollMetrics.visibleLength);
if (this._scrollRef != null) {
if (this._scrollRef.scrollTo == null) {
console.warn("No scrollTo method provided. This may be because you have two nested VirtualizedLists with the same orientation, or because you are using a custom component that does not implement scrollTo.");
return;
}
this._scrollRef.scrollTo(horizontalOrDefault(this.props.horizontal) ? {
x: offset,
animated
} : {
y: offset,
animated
});
}
}
}
}, {
// scrollToIndex may be janky without getItemLayout prop
key: "scrollToIndex",
value: function (params) {
var {
data,
horizontal,
getItemCount,
getItemLayout,
onScrollToIndexFailed
} = this.props,
{
animated,
index,
viewOffset,
viewPosition
} = params;
if (invariant(index >= 0, `scrollToIndex out of range: requested index ${index} but minimum is 0`), invariant(getItemCount(data) >= 1, `scrollToIndex out of range: item length ${getItemCount(data)} but minimum is 1`), invariant(index < getItemCount(data), `scrollToIndex out of range: requested index ${index} is out of 0 to ${getItemCount(data) - 1}`), !getItemLayout && index > this._highestMeasuredFrameIndex) {
invariant(!!onScrollToIndexFailed, "scrollToIndex should be used in conjunction with getItemLayout or onScrollToIndexFailed, otherwise there is no way to know the location of offscreen indices or handle failures."), onScrollToIndexFailed({
averageItemLength: this._averageCellLength,
highestMeasuredFrameIndex: this._highestMeasuredFrameIndex,
index
});
return;
}
var frame = this.__getFrameMetricsApprox(Math.floor(index), this.props),
offset = Math.max(0,
// @ts-ignore
this._getOffsetApprox(index, this.props) - (viewPosition || 0) * (this._scrollMetrics.visibleLength - frame.length)) - (viewOffset || 0);
if (this._scrollRef != null) {
if (this._scrollRef.scrollTo == null) {
console.warn("No scrollTo method provided. This may be because you have two nested VirtualizedLists with the same orientation, or because you are using a custom component that does not implement scrollTo.");
return;
}
this._scrollRef.scrollTo(horizontal ? {
x: offset,
animated
} : {
y: offset,
animated
});
}
}
}, {
// scrollToItem may be janky without getItemLayout prop. Required linear scan through items -
// use scrollToIndex instead if possible.
key: "scrollToItem",
value: function (params) {
for (var {
item
} = params, {
data,
getItem,
getItemCount
} = this.props, itemCount = getItemCount(data), index = 0; index < itemCount; index++) if (getItem(data, index) === item) {
this.scrollToIndex({
...params,
index
});
break;
}
}
}, {
/**
* Scroll to a specific content pixel offset in the list.
*
* Param `offset` expects the offset to scroll to.
* In case of `horizontal` is true, the offset is the x-value,
* in any other case the offset is the y-value.
*
* Param `animated` (`true` by default) defines whether the list
* should do an animation while scrolling.
*/
key: "scrollToOffset",
value: function (params) {
var {
animated,
offset
} = params;
if (this._scrollRef != null) {
if (this._scrollRef.scrollTo == null) {
console.warn("No scrollTo method provided. This may be because you have two nested VirtualizedLists with the same orientation, or because you are using a custom component that does not implement scrollTo.");
return;
}
this._scrollRef.scrollTo(horizontalOrDefault(this.props.horizontal) ? {
x: offset,
animated
} : {
y: offset,
animated
});
}
}
}, {
key: "recordInteraction",
value: function () {
this._nestedChildLists.forEach(function (childList) {
childList.recordInteraction();
}), this._viewabilityTuples.forEach(function (t) {
t.viewabilityHelper.recordInteraction();
}), this._updateViewableItems(this.props, this.state.cellsAroundViewport);
}
}, {
key: "flashScrollIndicators",
value: function () {
this._scrollRef != null && this._scrollRef.flashScrollIndicators();
}
}, {
/**
* Provides a handle to the underlying scroll responder.
* Note that `this._scrollRef` might not be a `ScrollView`, so we
* need to check that it responds to `getScrollResponder` before calling it.
*/
key: "getScrollResponder",
value: function () {
return this._scrollRef && this._scrollRef.getScrollResponder ? this._scrollRef.getScrollResponder() : null;
}
}, {
key: "getScrollableNode",
value: function () {
return this._scrollRef && this._scrollRef.getScrollableNode ? this._scrollRef.getScrollableNode() : this._scrollRef;
}
}, {
key: "getScrollRef",
value: function () {
return this._scrollRef && this._scrollRef.getScrollRef ? this._scrollRef.getScrollRef() : this._scrollRef;
}
}, {
key: "_getCellKey",
value: function () {
var _this_context;
return ((_this_context = this.context) === null || _this_context === void 0 ? void 0 : _this_context.cellKey) || "rootList";
}
}, {
key: "hasMore",
value: function () {
return this._hasMore;
}
}, {
key: "_checkProps",
value: function (props) {
var {
onScroll,
windowSize,
getItemCount,
data,
initialScrollIndex
} = props;
invariant(!(onScroll && onScroll.__isNative), "Components based on VirtualizedList must be wrapped with Animated.createAnimatedComponent to support native onScroll events with useNativeDriver"), invariant(windowSizeOrDefault(windowSize) > 0, "VirtualizedList: The windowSize prop must be present and set to a value greater than 0."), invariant(getItemCount, 'VirtualizedList: The "getItemCount" prop must be provided');
var itemCount = getItemCount(data);
if (initialScrollIndex != null && !this._hasTriggeredInitialScrollToIndex && (initialScrollIndex < 0 || itemCount > 0 && initialScrollIndex >= itemCount) && !this._hasWarned.initialScrollIndex && (console.warn(`initialScrollIndex "${initialScrollIndex}" is not valid (list has ${itemCount} items)`), this._hasWarned.initialScrollIndex = !0), __DEV__ && !this._hasWarned.flexWrap) {
var flatStyles = StyleSheet.flatten(this.props.contentContainerStyle);
flatStyles != null && flatStyles.flexWrap === "wrap" && (console.warn("`flexWrap: `wrap`` is not supported with the `VirtualizedList` components.Consider using `numColumns` with `FlatList` instead."), this._hasWarned.flexWrap = !0);
}
}
}, {
key: "_adjustCellsAroundViewport",
value: function (props, cellsAroundViewport) {
var {
data,
getItemCount
} = props,
onEndReachedThreshold = onEndReachedThresholdOrDefault(props.onEndReachedThreshold),
{
contentLength,
offset,
visibleLength
} = this._scrollMetrics,
distanceFromEnd = contentLength - visibleLength - offset;
if (visibleLength <= 0 || contentLength <= 0) return cellsAroundViewport.last >= getItemCount(data) ? VirtualizedList2._constrainToItemCount(cellsAroundViewport, props) : cellsAroundViewport;
var newCellsAroundViewport;
if (props.disableVirtualization) {
var renderAhead = distanceFromEnd < onEndReachedThreshold * visibleLength ? maxToRenderPerBatchOrDefault(props.maxToRenderPerBatch) : 0;
newCellsAroundViewport = {
first: 0,
last: Math.min(cellsAroundViewport.last + renderAhead, getItemCount(data) - 1)
};
} else {
if (props.initialScrollIndex && !this._scrollMetrics.offset && Math.abs(distanceFromEnd) >= Number.EPSILON) return cellsAroundViewport.last >= getItemCount(data) ? VirtualizedList2._constrainToItemCount(cellsAroundViewport, props) : cellsAroundViewport;
newCellsAroundViewport = computeWindowedRenderLimits(props, maxToRenderPerBatchOrDefault(props.maxToRenderPerBatch), windowSizeOrDefault(props.windowSize), cellsAroundViewport, this.__getFrameMetricsApprox, this._scrollMetrics), invariant(newCellsAroundViewport.last < getItemCount(data), "computeWindowedRenderLimits() should return range in-bounds");
}
if (this._nestedChildLists.size() > 0) {
var childIdx = this._findFirstChildWithMore(newCellsAroundViewport.first, newCellsAroundViewport.last);
newCellsAroundViewport.last = childIdx ?? newCellsAroundViewport.last;
}
return newCellsAroundViewport;
}
}, {
key: "_findFirstChildWithMore",
value: function (first, last) {
for (var ii = first; ii <= last; ii++) {
var cellKeyForIndex = this._indicesToKeys.get(ii);
if (cellKeyForIndex != null && this._nestedChildLists.anyInCell(cellKeyForIndex, function (childList) {
return childList.hasMore();
})) return ii;
}
return null;
}
}, {
key: "componentDidMount",
value: function () {
this._isNestedWithSameOrientation() && this.context.registerAsNestedChild({
ref: this,
cellKey: this.context.cellKey
}), this.setupWebWheelHandler();
}
}, {
key: "componentWillUnmount",
value: function () {
this._isNestedWithSameOrientation() && this.context.unregisterAsNestedChild({
ref: this
}), this._updateCellsToRenderBatcher.dispose({
abort: !0
}), this._viewabilityTuples.forEach(function (tuple) {
tuple.viewabilityHelper.dispose();
}), this._fillRateHelper.deactivateAndFlush(), this.teardownWebWheelHandler();
}
}, {
key: "setupWebWheelHandler",
value: function () {
var _this = this;
if (this._scrollRef && this._scrollRef.getScrollableNode) this._scrollRef.getScrollableNode().addEventListener("wheel", this.invertedWheelEventHandler);else {
setTimeout(function () {
return _this.setupWebWheelHandler();
}, 50);
return;
}
}
}, {
key: "teardownWebWheelHandler",
value: function () {
this._scrollRef && this._scrollRef.getScrollableNode && this._scrollRef.getScrollableNode().removeEventListener("wheel", this.invertedWheelEventHandler);
}
}, {
key: "_pushCells",
value: function (cells, stickyHeaderIndices, stickyIndicesFromProps, first, last, inversionStyle) {
var _this,
_loop = function (ii2) {
var item = getItem(data, ii2),
key = _this._keyExtractor(item, ii2, _this.props);
_this._indicesToKeys.set(ii2, key), stickyIndicesFromProps.has(ii2 + stickyOffset) && stickyHeaderIndices.push(cells.length);
var shouldListenForLayout = getItemLayout == null || debug || _this._fillRateHelper.enabled();
cells.push(/* @__PURE__ */_jsx(CellRenderer, {
CellRendererComponent,
ItemSeparatorComponent: ii2 < end ? ItemSeparatorComponent : void 0,
ListItemComponent,
cellKey: key,
horizontal,
index: ii2,
inversionStyle,
item,
prevCellKey,
onUpdateSeparators: _this._onUpdateSeparators,
onCellFocusCapture: function (e) {
return _this1._onCellFocusCapture(key);
},
onUnmount: _this._onCellUnmount,
ref: function (ref) {
_this1._cellRefs[key] = ref;
},
renderItem,
...(shouldListenForLayout && {
onCellLayout: _this._onCellLayout
})
}, key)), prevCellKey = key;
},
_this1 = this,
{
CellRendererComponent,
ItemSeparatorComponent,
ListHeaderComponent,
ListItemComponent,
data,
debug,
getItem,
getItemCount,
getItemLayout,
horizontal,
renderItem
} = this.props,
stickyOffset = ListHeaderComponent ? 1 : 0,
end = getItemCount(data) - 1,
prevCellKey;
last = Math.min(end, last);
for (var ii = first; ii <= last; ii++) _this = this, _loop(ii);
}
}, {
key: "_isNestedWithSameOrientation",
value: function () {
var nestedContext = this.context;
return !!(nestedContext && !!nestedContext.horizontal === horizontalOrDefault(this.props.horizontal));
}
}, {
key: "_keyExtractor",
value: function (item, index, props) {
if (props.keyExtractor != null) return props.keyExtractor(item, index);
var key = defaultKeyExtractor(item, index);
return key === String(index) && (_usedIndexForKey = !0, item.type && item.type.displayName && (_keylessItemComponentName = item.type.displayName)), key;
}
}, {
key: "render",
value: function () {
var _this = this;
this._checkProps(this.props);
var {
ListEmptyComponent,
ListFooterComponent,
ListHeaderComponent
} = this.props,
{
data,
horizontal
} = this.props,
inversionStyle = this.props.inverted ? horizontalOrDefault(this.props.horizontal) ? styles.horizontallyInverted : styles.verticallyInverted : null,
cells = [],
stickyIndicesFromProps = new Set(this.props.stickyHeaderIndices),
stickyHeaderIndices = [];
if (ListHeaderComponent) {
stickyIndicesFromProps.has(0) && stickyHeaderIndices.push(0);
var element = /* @__PURE__ */React.isValidElement(ListHeaderComponent) ? ListHeaderComponent : /* @__PURE__ */_jsx(ListHeaderComponent, {});
cells.push(/* @__PURE__ */_jsx(VirtualizedListCellContextProvider, {
cellKey: this._getCellKey() + "-header",
children: /* @__PURE__ */_jsx(View, {
onLayout: this._onLayoutHeader,
style: [inversionStyle, this.props.ListHeaderComponentStyle],
children: element
})
}, "$header"));
}
var itemCount = this.props.getItemCount(data);
if (itemCount === 0 && ListEmptyComponent) {
var element1 = /* @__PURE__ */React.isValidElement(ListEmptyComponent) ? ListEmptyComponent : /* @__PURE__ */_jsx(ListEmptyComponent, {});
cells.push(/* @__PURE__ */_jsx(VirtualizedListCellContextProvider, {
cellKey: this._getCellKey() + "-empty",
children: /* @__PURE__ */React.cloneElement(element1, {
onLayout: function (event) {
_this._onLayoutEmpty(event), element1.props.onLayout && element1.props.onLayout(event);
},
style: [inversionStyle, element1.props.style]
})
}, "$empty"));
}
if (itemCount > 0) {
_usedIndexForKey = !1, _keylessItemComponentName = "";
var spacerKey = this._getSpacerKey(!horizontal),
renderRegions = this.state.renderMask.enumerateRegions(),
lastSpacer = findLastWhere(renderRegions, function (r) {
return r.isSpacer;
}),
_iteratorNormalCompletion = !0,
_didIteratorError = !1,
_iteratorError = void 0;
try {
for (var _iterator = renderRegions[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = !0) {
var section = _step.value;
if (section.isSpacer) {
if (this.props.disableVirtualization) continue;
var isLastSpacer = section === lastSpacer,
constrainToMeasured = isLastSpacer && !this.props.getItemLayout,
last = constrainToMeasured ? clamp(section.first - 1, section.last, this._highestMeasuredFrameIndex) : section.last,
firstMetrics = this.__getFrameMetricsApprox(section.first, this.props),
lastMetrics = this.__getFrameMetricsApprox(last, this.props),
spacerSize = lastMetrics.offset + lastMetrics.length - firstMetrics.offset;
cells.push(/* @__PURE__ */_jsx(View, {
style: {
[spacerKey]: spacerSize
}
}, `$spacer-${section.first}`));
} else this._pushCells(cells, stickyHeaderIndices, stickyIndicesFromProps, section.first, section.last, inversionStyle);
}
} catch (err) {
_didIteratorError = !0, _iteratorError = err;
} finally {
try {
!_iteratorNormalCompletion && _iterator.return != null && _iterator.return();
} finally {
if (_didIteratorError) throw _iteratorError;
}
}
!this._hasWarned.keys && _usedIndexForKey && (console.warn("VirtualizedList: missing keys for items, make sure to specify a key or id property on each item or provide a custom keyExtractor.", _keylessItemComponentName), this._hasWarned.keys = !0);
}
if (ListFooterComponent) {
var element2 = /* @__PURE__ */React.isValidElement(ListFooterComponent) ? ListFooterComponent : /* @__PURE__ */_jsx(ListFooterComponent, {});
cells.push(/* @__PURE__ */_jsx(VirtualizedListCellContextProvider, {
cellKey: this._getFooterCellKey(),
children: /* @__PURE__ */_jsx(View, {
onLayout: this._onLayoutFooter,
style: [inversionStyle, this.props.ListFooterComponentStyle],
children: element2
})
}, "$footer"));
}
var scrollProps = {
...this.props,
onContentSizeChange: this._onContentSizeChange,
onLayout: this._onLayout,
onScroll: this._onScroll,
onScrollBeginDrag: this._onScrollBeginDrag,
onScrollEndDrag: this._onScrollEndDrag,
onMomentumScrollBegin: this._onMomentumScrollBegin,
onMomentumScrollEnd: this._onMomentumScrollEnd,
scrollEventThrottle: scrollEventThrottleOrDefault(this.props.scrollEventThrottle),
invertStickyHeaders: this.props.invertStickyHeaders !== void 0 ? this.props.invertStickyHeaders : this.props.inverted,
stickyHeaderIndices,
style: inversionStyle ? [inversionStyle, this.props.style] : this.props.style
};
this._hasMore = this.state.cellsAroundViewport.last < itemCount - 1;
var innerRet = /* @__PURE__ */_jsx(VirtualizedListContextProvider, {
value: {
cellKey: null,
getScrollMetrics: this._getScrollMetrics,
horizontal: horizontalOrDefault(this.props.horizontal),
getOutermostParentListRef: this._getOutermostParentListRef,
registerAsNestedChild: this._registerAsNestedChild,
unregisterAsNestedChild: this._unregisterAsNestedChild
},
children: /* @__PURE__ */React.cloneElement((this.props.renderScrollComponent || this._defaultRenderScrollComponent)(scrollProps), {
ref: this._captureScrollRef
}, cells)
}),
ret = innerRet;
return ret;
}
}, {
key: "componentDidUpdate",
value: function (prevProps) {
var {
data,
extraData
} = this.props;
(data !== prevProps.data || extraData !== prevProps.extraData) && this._viewabilityTuples.forEach(function (tuple) {
tuple.viewabilityHelper.resetViewableIndices();
});
var hiPriInProgress = this._hiPriInProgress;
this._scheduleCellsToRenderUpdate(), hiPriInProgress && (this._hiPriInProgress = !1);
}
}, {
key: "_computeBlankness",
value: function () {
this._fillRateHelper.computeBlankness(
// @ts-ignore
this.props, this.state.cellsAroundViewport, this._scrollMetrics);
}
}, {
key: "_onCellFocusCapture",
value: function (cellKey) {
this._lastFocusedCellKey = cellKey, this._updateCellsToRender();
}
}, {
key: "_triggerRemeasureForChildListsInCell",
value: function (cellKey) {
this._nestedChildLists.forEachInCell(cellKey, function (childList) {
childList.measureLayoutRelativeToContainingList();
});
}
}, {
key: "measureLayoutRelativeToContainingList",
value: function () {
var _this = this;
try {
if (!this._scrollRef) return;
this._scrollRef.measureLayout(this.context.getOutermostParentListRef().getScrollRef(), function (x, y, width, height) {
_this._offsetFromParentVirtualizedList = _this._selectOffset({
x,
y
}), _this._scrollMetrics.contentLength = _this._selectLength({
width,
height
});
var scrollMetrics = _this._convertParentScrollMetrics(_this.context.getScrollMetrics()),
metricsChanged = _this._scrollMetrics.visibleLength !== scrollMetrics.visibleLength || _this._scrollMetrics.offset !== scrollMetrics.offset;
metricsChanged && (_this._scrollMetrics.visibleLength = scrollMetrics.visibleLength, _this._scrollMetrics.offset = scrollMetrics.offset, _this._nestedChildLists.forEach(function (childList) {
childList.measureLayoutRelativeToContainingList();
}));
}, function (error) {
console.warn("VirtualizedList: Encountered an error while measuring a list's offset from its containing VirtualizedList.");
});
} catch (error) {
console.warn("measureLayoutRelativeToContainingList threw an error", error.stack);
}
}
}, {
key: "_getFooterCellKey",
value: function () {
return this._getCellKey() + "-footer";
}
}, {
key: "_renderDebugOverlay",
value: function () {
for (var normalize = this._scrollMetrics.visibleLength / (this._scrollMetrics.contentLength || 1), framesInLayout = [], itemCount = this.props.getItemCount(this.props.data), ii = 0; ii < itemCount; ii++) {
var frame = this.__getFrameMetricsApprox(ii, this.props);
frame.inLayout && framesInLayout.push(frame);
}
var windowTop = this.__getFrameMetricsApprox(this.state.cellsAroundViewport.first, this.props).offset,
frameLast = this.__getFrameMetricsApprox(this.state.cellsAroundViewport.last, this.props),
windowLen = frameLast.offset + frameLast.length - windowTop,
visTop = this._scrollMetrics.offset,
visLen = this._scrollMetrics.visibleLength;
return /* @__PURE__ */_jsxs(View, {
style: [styles.debugOverlayBase, styles.debugOverlay],
children: [framesInLayout.map(function (f, ii2) {
return /* @__PURE__ */_jsx(View, {
style: [styles.debugOverlayBase, styles.debugOverlayFrame, {
top: f.offset * normalize,
height: f.length * normalize
}]
}, "f" + ii2);
}), /* @__PURE__ */_jsx(View, {
style: [styles.debugOverlayBase, styles.debugOverlayFrameLast, {
top: windowTop * normalize,
height: windowLen * normalize
}]
}), /* @__PURE__ */_jsx(View, {
style: [styles.debugOverlayBase, styles.debugOverlayFrameVis, {
top: visTop * normalize,
height: visLen * normalize
}]
})]
});
}
}, {
key: "_selectLength",
value: function (metrics) {
return horizontalOrDefault(this.props.horizontal) ? metrics.width : metrics.height;
}
}, {
key: "_selectOffset",
value: function (metrics) {
return horizontalOrDefault(this.props.horizontal) ? metrics.x : metrics.y;
}
}, {
key: "_maybeCallOnEdgeReached",
value: function () {
var {
data,
getItemCount,
onStartReached,
onStartReachedThreshold,
onEndReached,
onEndReachedThreshold,
initialScrollIndex
} = this.props,
{
contentLength,
visibleLength,
offset
} = this._scrollMetrics,
distanceFromStart = offset,
distanceFromEnd = contentLength - visibleLength - offset;
distanceFromStart < ON_EDGE_REACHED_EPSILON && (distanceFromStart = 0), distanceFromEnd < ON_EDGE_REACHED_EPSILON && (distanceFromEnd = 0);
var DEFAULT_THRESHOLD_PX = 2,
startThreshold = onStartReachedThreshold != null ? onStartReachedThreshold * visibleLength : DEFAULT_THRESHOLD_PX,
endThreshold = onEndReachedThreshold != null ? onEndReachedThreshold * visibleLength : DEFAULT_THRESHOLD_PX,
isWithinStartThreshold = distanceFromStart <= startThreshold,
isWithinEndThreshold = distanceFromEnd <= endThreshold;
onEndReached && this.state.cellsAroundViewport.last === getItemCount(data) - 1 && isWithinEndThreshold && this._scrollMetrics.contentLength !== this._sentEndForContentLength ? (this._sentEndForContentLength = this._scrollMetrics.contentLength, onEndReached({
distanceFromEnd
})) : onStartReached != null && this.state.cellsAroundViewport.first === 0 && isWithinStartThreshold && this._scrollMetrics.contentLength !== this._sentStartForContentLength ? (!initialScrollIndex || this._scrollMetrics.timestamp !== 0) && (this._sentStartForContentLength = this._scrollMetrics.contentLength, onStartReached({
distanceFromStart
})) : (this._sentStartForContentLength = isWithinStartThreshold ? this._sentStartForContentLength : 0, this._sentEndForContentLength = isWithinEndThreshold ? this._sentEndForContentLength : 0);
}
}, {
key: "_scheduleCellsToRenderUpdate",
value: function () {
var {
first,
last
} = this.state.cellsAroundViewport,
{
offset,
visibleLength,
velocity
} = this._scrollMetrics,
itemCount = this.props.getItemCount(this.props.data),
hiPri = !1,
onStartReachedThreshold = onStartReachedThresholdOrDefault(this.props.onStartReachedThreshold),
onEndReachedThreshold = onEndReachedThresholdOrDefault(this.props.onEndReachedThreshold);
if (first > 0) {
var distTop = offset - this.__getFrameMetricsApprox(first, this.props).offset;
hiPri = distTop < 0 || velocity < -2 && distTop < getScrollingThreshold(onStartReachedThreshold, visibleLength);
}
if (!hiPri && last >= 0 && last < itemCount - 1) {
var distBottom = this.__getFrameMetricsApprox(last, this.props).offset - (offset + visibleLength);
hiPri = distBottom < 0 || velocity > 2 && distBottom < getScrollingThreshold(onEndReachedThreshold, visibleLength);
}
if (hiPri && (this._averageCellLength || this.props.getItemLayout) && !this._hiPriInProgress) {
this._hiPriInProgress = !0, this._updateCellsToRenderBatcher.dispose({
abort: !0
}), this._updateCellsToRender();
return;
} else this._updateCellsToRenderBatcher.schedule();
}
}, {
key: "_updateViewableItems",
value: function (props, cellsAroundViewport) {
var _this = this;
this._viewabilityTuples.forEach(function (tuple) {
tuple.viewabilityHelper.onUpdate(props, _this._scrollMetrics.offset, _this._scrollMetrics.visibleLength, _this._getFrameMetrics, _this._createViewToken, tuple.onViewableItemsChanged, cellsAroundViewport);
});
}
}], [{
key: "_createRenderMask",
value: function (props, cellsAroundViewport, additionalRegions) {
var itemCount = props.getItemCount(props.data);
invariant(cellsAroundViewport.first >= 0 && cellsAroundViewport.last >= cellsAr