@tamagui/react-native-web-lite
Version:
React Native for Web
117 lines (116 loc) • 4.32 kB
JavaScript
function elementsThatOverlapOffsets(offsets, props, getFrameMetrics, zoomScale = 1) {
const itemCount = props.getItemCount(props.data);
const result = [];
for (let offsetIndex = 0; offsetIndex < offsets.length; offsetIndex++) {
const currentOffset = offsets[offsetIndex];
let left = 0;
let right = itemCount - 1;
while (left <= right) {
const mid = left + (right - left >>> 1);
const frame = getFrameMetrics(mid, props);
const scaledOffsetStart = frame.offset * zoomScale;
const scaledOffsetEnd = (frame.offset + frame.length) * zoomScale;
if (mid === 0 && currentOffset < scaledOffsetStart || mid !== 0 && currentOffset <= scaledOffsetStart) {
right = mid - 1;
} else if (currentOffset > scaledOffsetEnd) {
left = mid + 1;
} else {
result[offsetIndex] = mid;
break;
}
}
}
return result;
}
function newRangeCount(prev, next) {
return next.last - next.first + 1 - Math.max(0, 1 + Math.min(next.last, prev.last) - Math.max(next.first, prev.first));
}
function computeWindowedRenderLimits(props, maxToRenderPerBatch, windowSize, prev, getFrameMetricsApprox, scrollMetrics) {
const itemCount = props.getItemCount(props.data);
if (itemCount === 0) {
return {
first: 0,
last: -1
};
}
const {
offset,
velocity,
visibleLength,
zoomScale = 1
} = scrollMetrics;
const visibleBegin = Math.max(0, offset);
const visibleEnd = visibleBegin + visibleLength;
const overscanLength = (windowSize - 1) * visibleLength;
const leadFactor = 0.5;
const fillPreference = velocity > 1 ? "after" : velocity < -1 ? "before" : "none";
const overscanBegin = Math.max(0, visibleBegin - (1 - leadFactor) * overscanLength);
const overscanEnd = Math.max(0, visibleEnd + leadFactor * overscanLength);
const lastItemOffset = getFrameMetricsApprox(itemCount - 1, props).offset * zoomScale;
if (lastItemOffset < overscanBegin) {
return {
first: Math.max(0, itemCount - 1 - maxToRenderPerBatch),
last: itemCount - 1
};
}
let [overscanFirst, first, last, overscanLast] = elementsThatOverlapOffsets([overscanBegin, visibleBegin, visibleEnd, overscanEnd], props, getFrameMetricsApprox, zoomScale);
overscanFirst = overscanFirst == null ? 0 : overscanFirst;
first = first == null ? Math.max(0, overscanFirst) : first;
overscanLast = overscanLast == null ? itemCount - 1 : overscanLast;
last = last == null ? Math.min(overscanLast, first + maxToRenderPerBatch - 1) : last;
const visible = {
first,
last
};
let newCellCount = newRangeCount(prev, visible);
while (true) {
if (first <= overscanFirst && last >= overscanLast) {
break;
}
const maxNewCells = newCellCount >= maxToRenderPerBatch;
const firstWillAddMore = first <= prev.first || first > prev.last;
const firstShouldIncrement = first > overscanFirst && (!maxNewCells || !firstWillAddMore);
const lastWillAddMore = last >= prev.last || last < prev.first;
const lastShouldIncrement = last < overscanLast && (!maxNewCells || !lastWillAddMore);
if (maxNewCells && !firstShouldIncrement && !lastShouldIncrement) {
break;
}
if (firstShouldIncrement && !(fillPreference === "after" && lastShouldIncrement && lastWillAddMore)) {
if (firstWillAddMore) {
newCellCount++;
}
first--;
}
if (lastShouldIncrement && !(fillPreference === "before" && firstShouldIncrement && firstWillAddMore)) {
if (lastWillAddMore) {
newCellCount++;
}
last++;
}
}
if (!(last >= first && first >= 0 && last < itemCount && first >= overscanFirst && last <= overscanLast && first <= visible.first && last >= visible.last)) {
throw new Error("Bad window calculation " + JSON.stringify({
first,
last,
itemCount,
overscanFirst,
overscanLast,
visible
}));
}
return {
first,
last
};
}
function keyExtractor(item, index) {
if (typeof item === "object" && item?.key != null) {
return item.key;
}
if (typeof item === "object" && item?.id != null) {
return item.id;
}
return String(index);
}
export { computeWindowedRenderLimits, elementsThatOverlapOffsets, keyExtractor, newRangeCount };
//# sourceMappingURL=index.mjs.map