@legendapp/list 1.0.0-beta.34 → 1.0.0-beta.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.mts +1 -5
- package/index.d.ts +1 -5
- package/index.js +129 -80
- package/index.mjs +130 -81
- package/package.json +1 -1
package/index.d.mts
CHANGED
|
@@ -286,10 +286,6 @@ interface LegendListRenderItemProps<ItemT> {
|
|
|
286
286
|
item: ItemT;
|
|
287
287
|
index: number;
|
|
288
288
|
extraData: any;
|
|
289
|
-
useViewability: (configId: string, callback: ViewabilityCallback) => void;
|
|
290
|
-
useViewabilityAmount: (callback: ViewabilityAmountCallback) => void;
|
|
291
|
-
useRecyclingEffect: (effect: (info: LegendListRecyclingState<ItemT>) => void | (() => void)) => void;
|
|
292
|
-
useRecyclingState: <T>(updateState: ((info: LegendListRecyclingState<ItemT>) => T) | T) => [T, React.Dispatch<T>];
|
|
293
289
|
}
|
|
294
290
|
type ScrollState = {
|
|
295
291
|
contentLength: number;
|
|
@@ -395,13 +391,13 @@ interface ViewToken<ItemT = any> {
|
|
|
395
391
|
key: string;
|
|
396
392
|
index: number;
|
|
397
393
|
isViewable: boolean;
|
|
394
|
+
containerId: number;
|
|
398
395
|
}
|
|
399
396
|
interface ViewAmountToken<ItemT = any> extends ViewToken<ItemT> {
|
|
400
397
|
sizeVisible: number;
|
|
401
398
|
size: number;
|
|
402
399
|
percentVisible: number;
|
|
403
400
|
percentOfScroller: number;
|
|
404
|
-
position: number;
|
|
405
401
|
scrollSize: number;
|
|
406
402
|
}
|
|
407
403
|
interface ViewabilityConfigCallbackPair {
|
package/index.d.ts
CHANGED
|
@@ -286,10 +286,6 @@ interface LegendListRenderItemProps<ItemT> {
|
|
|
286
286
|
item: ItemT;
|
|
287
287
|
index: number;
|
|
288
288
|
extraData: any;
|
|
289
|
-
useViewability: (configId: string, callback: ViewabilityCallback) => void;
|
|
290
|
-
useViewabilityAmount: (callback: ViewabilityAmountCallback) => void;
|
|
291
|
-
useRecyclingEffect: (effect: (info: LegendListRecyclingState<ItemT>) => void | (() => void)) => void;
|
|
292
|
-
useRecyclingState: <T>(updateState: ((info: LegendListRecyclingState<ItemT>) => T) | T) => [T, React.Dispatch<T>];
|
|
293
289
|
}
|
|
294
290
|
type ScrollState = {
|
|
295
291
|
contentLength: number;
|
|
@@ -395,13 +391,13 @@ interface ViewToken<ItemT = any> {
|
|
|
395
391
|
key: string;
|
|
396
392
|
index: number;
|
|
397
393
|
isViewable: boolean;
|
|
394
|
+
containerId: number;
|
|
398
395
|
}
|
|
399
396
|
interface ViewAmountToken<ItemT = any> extends ViewToken<ItemT> {
|
|
400
397
|
sizeVisible: number;
|
|
401
398
|
size: number;
|
|
402
399
|
percentVisible: number;
|
|
403
400
|
percentOfScroller: number;
|
|
404
|
-
position: number;
|
|
405
401
|
scrollSize: number;
|
|
406
402
|
}
|
|
407
403
|
interface ViewabilityConfigCallbackPair {
|
package/index.js
CHANGED
|
@@ -86,6 +86,58 @@ function getContentSize(ctx) {
|
|
|
86
86
|
const totalSize = values.get("totalSize") || 0;
|
|
87
87
|
return headerSize + footerSize + totalSize + stylePaddingTop;
|
|
88
88
|
}
|
|
89
|
+
|
|
90
|
+
// src/DebugView.tsx
|
|
91
|
+
var DebugRow = ({ children }) => {
|
|
92
|
+
return /* @__PURE__ */ React.createElement(reactNative.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" } }, children);
|
|
93
|
+
};
|
|
94
|
+
var DebugView = React6.memo(function DebugView2({ state }) {
|
|
95
|
+
const ctx = useStateContext();
|
|
96
|
+
const totalSize = use$("totalSize") || 0;
|
|
97
|
+
const totalSizeWithScrollAdjust = use$("totalSizeWithScrollAdjust") || 0;
|
|
98
|
+
const scrollAdjust = use$("scrollAdjust") || 0;
|
|
99
|
+
const rawScroll = use$("debugRawScroll") || 0;
|
|
100
|
+
const scroll = use$("debugComputedScroll") || 0;
|
|
101
|
+
const contentSize = getContentSize(ctx);
|
|
102
|
+
const [, forceUpdate] = React6.useReducer((x) => x + 1, 0);
|
|
103
|
+
use$("numContainers");
|
|
104
|
+
use$("numContainersPooled");
|
|
105
|
+
useInterval(() => {
|
|
106
|
+
forceUpdate();
|
|
107
|
+
}, 100);
|
|
108
|
+
return /* @__PURE__ */ React.createElement(
|
|
109
|
+
reactNative.View,
|
|
110
|
+
{
|
|
111
|
+
style: {
|
|
112
|
+
position: "absolute",
|
|
113
|
+
top: 0,
|
|
114
|
+
right: 0,
|
|
115
|
+
paddingLeft: 4,
|
|
116
|
+
paddingBottom: 4,
|
|
117
|
+
// height: 100,
|
|
118
|
+
backgroundColor: "#FFFFFFCC",
|
|
119
|
+
padding: 4,
|
|
120
|
+
borderRadius: 4
|
|
121
|
+
},
|
|
122
|
+
pointerEvents: "none"
|
|
123
|
+
},
|
|
124
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "TotalSize:"), /* @__PURE__ */ React.createElement(reactNative.Text, null, totalSize.toFixed(2))),
|
|
125
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "ContentSize:"), /* @__PURE__ */ React.createElement(reactNative.Text, null, contentSize.toFixed(2))),
|
|
126
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "At end:"), /* @__PURE__ */ React.createElement(reactNative.Text, null, String(state.isAtBottom))),
|
|
127
|
+
/* @__PURE__ */ React.createElement(reactNative.Text, null),
|
|
128
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "ScrollAdjust:"), /* @__PURE__ */ React.createElement(reactNative.Text, null, scrollAdjust.toFixed(2))),
|
|
129
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "TotalSizeReal: "), /* @__PURE__ */ React.createElement(reactNative.Text, null, totalSizeWithScrollAdjust.toFixed(2))),
|
|
130
|
+
/* @__PURE__ */ React.createElement(reactNative.Text, null),
|
|
131
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "RawScroll: "), /* @__PURE__ */ React.createElement(reactNative.Text, null, rawScroll.toFixed(2))),
|
|
132
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "ComputedScroll: "), /* @__PURE__ */ React.createElement(reactNative.Text, null, scroll.toFixed(2)))
|
|
133
|
+
);
|
|
134
|
+
});
|
|
135
|
+
function useInterval(callback, delay) {
|
|
136
|
+
React6.useEffect(() => {
|
|
137
|
+
const interval = setInterval(callback, delay);
|
|
138
|
+
return () => clearInterval(interval);
|
|
139
|
+
}, [delay]);
|
|
140
|
+
}
|
|
89
141
|
var symbolFirst = Symbol();
|
|
90
142
|
function useInit(cb) {
|
|
91
143
|
const refValue = React6.useRef(symbolFirst);
|
|
@@ -171,56 +223,6 @@ function useRecyclingState(valueOrFun) {
|
|
|
171
223
|
});
|
|
172
224
|
return stateInfo;
|
|
173
225
|
}
|
|
174
|
-
var DebugRow = ({ children }) => {
|
|
175
|
-
return /* @__PURE__ */ React.createElement(reactNative.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" } }, children);
|
|
176
|
-
};
|
|
177
|
-
var DebugView = React6.memo(function DebugView2({ state }) {
|
|
178
|
-
const ctx = useStateContext();
|
|
179
|
-
const totalSize = use$("totalSize") || 0;
|
|
180
|
-
const totalSizeWithScrollAdjust = use$("totalSizeWithScrollAdjust") || 0;
|
|
181
|
-
const scrollAdjust = use$("scrollAdjust") || 0;
|
|
182
|
-
const rawScroll = use$("debugRawScroll") || 0;
|
|
183
|
-
const scroll = use$("debugComputedScroll") || 0;
|
|
184
|
-
const contentSize = getContentSize(ctx);
|
|
185
|
-
const [, forceUpdate] = React6.useReducer((x) => x + 1, 0);
|
|
186
|
-
use$("numContainers");
|
|
187
|
-
use$("numContainersPooled");
|
|
188
|
-
useInterval(() => {
|
|
189
|
-
forceUpdate();
|
|
190
|
-
}, 100);
|
|
191
|
-
return /* @__PURE__ */ React.createElement(
|
|
192
|
-
reactNative.View,
|
|
193
|
-
{
|
|
194
|
-
style: {
|
|
195
|
-
position: "absolute",
|
|
196
|
-
top: 0,
|
|
197
|
-
right: 0,
|
|
198
|
-
paddingLeft: 4,
|
|
199
|
-
paddingBottom: 4,
|
|
200
|
-
// height: 100,
|
|
201
|
-
backgroundColor: "#FFFFFFCC",
|
|
202
|
-
padding: 4,
|
|
203
|
-
borderRadius: 4
|
|
204
|
-
},
|
|
205
|
-
pointerEvents: "none"
|
|
206
|
-
},
|
|
207
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "TotalSize:"), /* @__PURE__ */ React.createElement(reactNative.Text, null, totalSize.toFixed(2))),
|
|
208
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "ContentSize:"), /* @__PURE__ */ React.createElement(reactNative.Text, null, contentSize.toFixed(2))),
|
|
209
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "At end:"), /* @__PURE__ */ React.createElement(reactNative.Text, null, String(state.isAtBottom))),
|
|
210
|
-
/* @__PURE__ */ React.createElement(reactNative.Text, null),
|
|
211
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "ScrollAdjust:"), /* @__PURE__ */ React.createElement(reactNative.Text, null, scrollAdjust.toFixed(2))),
|
|
212
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "TotalSizeReal: "), /* @__PURE__ */ React.createElement(reactNative.Text, null, totalSizeWithScrollAdjust.toFixed(2))),
|
|
213
|
-
/* @__PURE__ */ React.createElement(reactNative.Text, null),
|
|
214
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "RawScroll: "), /* @__PURE__ */ React.createElement(reactNative.Text, null, rawScroll.toFixed(2))),
|
|
215
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "ComputedScroll: "), /* @__PURE__ */ React.createElement(reactNative.Text, null, scroll.toFixed(2)))
|
|
216
|
-
);
|
|
217
|
-
});
|
|
218
|
-
function useInterval(callback, delay) {
|
|
219
|
-
React6.useEffect(() => {
|
|
220
|
-
const interval = setInterval(callback, delay);
|
|
221
|
-
return () => clearInterval(interval);
|
|
222
|
-
}, [delay]);
|
|
223
|
-
}
|
|
224
226
|
var LeanViewComponent = React6__namespace.forwardRef((props, ref) => {
|
|
225
227
|
return React6__namespace.createElement("RCTView", { ...props, ref });
|
|
226
228
|
});
|
|
@@ -678,11 +680,37 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
|
|
|
678
680
|
const { viewabilityConfig, onViewableItemsChanged } = viewabilityConfigCallbackPair;
|
|
679
681
|
const configId = viewabilityConfig.id;
|
|
680
682
|
const viewabilityState = mapViewabilityConfigCallbackPairs.get(configId);
|
|
681
|
-
const { viewableItems: previousViewableItems, start,
|
|
683
|
+
const { viewableItems: previousViewableItems, start, end } = viewabilityState;
|
|
684
|
+
const viewabilityTokens = /* @__PURE__ */ new Map();
|
|
685
|
+
for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
|
|
686
|
+
viewabilityTokens.set(
|
|
687
|
+
containerId,
|
|
688
|
+
computeViewability(
|
|
689
|
+
state,
|
|
690
|
+
ctx,
|
|
691
|
+
viewabilityConfig,
|
|
692
|
+
containerId,
|
|
693
|
+
value.key,
|
|
694
|
+
scrollSize,
|
|
695
|
+
value.item,
|
|
696
|
+
value.index
|
|
697
|
+
)
|
|
698
|
+
);
|
|
699
|
+
}
|
|
682
700
|
const changed = [];
|
|
683
701
|
if (previousViewableItems) {
|
|
684
702
|
for (const viewToken of previousViewableItems) {
|
|
685
|
-
|
|
703
|
+
const containerId = findContainerId(ctx, viewToken.key);
|
|
704
|
+
if (!isViewable(
|
|
705
|
+
state,
|
|
706
|
+
ctx,
|
|
707
|
+
viewabilityConfig,
|
|
708
|
+
containerId,
|
|
709
|
+
viewToken.key,
|
|
710
|
+
scrollSize,
|
|
711
|
+
viewToken.item,
|
|
712
|
+
viewToken.index
|
|
713
|
+
)) {
|
|
686
714
|
viewToken.isViewable = false;
|
|
687
715
|
changed.push(viewToken);
|
|
688
716
|
}
|
|
@@ -693,12 +721,14 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
|
|
|
693
721
|
const item = data[i];
|
|
694
722
|
if (item) {
|
|
695
723
|
const key = getId(i);
|
|
696
|
-
|
|
724
|
+
const containerId = findContainerId(ctx, key);
|
|
725
|
+
if (isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
|
|
697
726
|
const viewToken = {
|
|
698
727
|
item,
|
|
699
728
|
key,
|
|
700
729
|
index: i,
|
|
701
|
-
isViewable: true
|
|
730
|
+
isViewable: true,
|
|
731
|
+
containerId
|
|
702
732
|
};
|
|
703
733
|
viewableItems.push(viewToken);
|
|
704
734
|
if (!(previousViewableItems == null ? void 0 : previousViewableItems.find((v) => v.key === viewToken.key))) {
|
|
@@ -716,14 +746,19 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
|
|
|
716
746
|
viewabilityState.viewableItems = viewableItems;
|
|
717
747
|
for (let i = 0; i < changed.length; i++) {
|
|
718
748
|
const change = changed[i];
|
|
719
|
-
maybeUpdateViewabilityCallback(ctx, configId, change);
|
|
749
|
+
maybeUpdateViewabilityCallback(ctx, configId, change.containerId, change);
|
|
720
750
|
}
|
|
721
751
|
if (onViewableItemsChanged) {
|
|
722
752
|
onViewableItemsChanged({ viewableItems, changed });
|
|
723
753
|
}
|
|
724
754
|
}
|
|
755
|
+
for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
|
|
756
|
+
if (value.sizeVisible < 0) {
|
|
757
|
+
ctx.mapViewabilityAmountValues.delete(containerId);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
725
760
|
}
|
|
726
|
-
function
|
|
761
|
+
function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
|
|
727
762
|
const { sizes, positions, scroll: scrollState, scrollAdjustHandler } = state;
|
|
728
763
|
const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
|
|
729
764
|
const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
|
|
@@ -731,7 +766,7 @@ function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index)
|
|
|
731
766
|
const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
|
|
732
767
|
const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
|
|
733
768
|
const scroll = scrollState - previousScrollAdjust - topPad;
|
|
734
|
-
const top = positions.get(key) - scroll
|
|
769
|
+
const top = positions.get(key) - scroll;
|
|
735
770
|
const size = sizes.get(key) || 0;
|
|
736
771
|
const bottom = top + size;
|
|
737
772
|
const isEntirelyVisible = top >= 0 && bottom <= scrollSize && bottom > top;
|
|
@@ -740,7 +775,6 @@ function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index)
|
|
|
740
775
|
const percentOfScroller = size ? 100 * (sizeVisible / scrollSize) : 0;
|
|
741
776
|
const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
|
|
742
777
|
const isViewable2 = percent >= viewablePercentThreshold;
|
|
743
|
-
const containerId = findContainerId(ctx, key);
|
|
744
778
|
const value = {
|
|
745
779
|
index,
|
|
746
780
|
isViewable: isViewable2,
|
|
@@ -750,15 +784,21 @@ function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index)
|
|
|
750
784
|
percentOfScroller,
|
|
751
785
|
sizeVisible,
|
|
752
786
|
size,
|
|
753
|
-
|
|
754
|
-
|
|
787
|
+
scrollSize,
|
|
788
|
+
containerId
|
|
755
789
|
};
|
|
756
|
-
ctx.mapViewabilityAmountValues.
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
cb
|
|
790
|
+
if (JSON.stringify(value) !== JSON.stringify(ctx.mapViewabilityAmountValues.get(containerId))) {
|
|
791
|
+
ctx.mapViewabilityAmountValues.set(containerId, value);
|
|
792
|
+
const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
|
|
793
|
+
if (cb) {
|
|
794
|
+
cb(value);
|
|
795
|
+
}
|
|
760
796
|
}
|
|
761
|
-
return
|
|
797
|
+
return value;
|
|
798
|
+
}
|
|
799
|
+
function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
|
|
800
|
+
const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
|
|
801
|
+
return value.isViewable;
|
|
762
802
|
}
|
|
763
803
|
function findContainerId(ctx, key) {
|
|
764
804
|
const numContainers = peek$(ctx, "numContainers");
|
|
@@ -770,8 +810,8 @@ function findContainerId(ctx, key) {
|
|
|
770
810
|
}
|
|
771
811
|
return -1;
|
|
772
812
|
}
|
|
773
|
-
function maybeUpdateViewabilityCallback(ctx, configId, viewToken) {
|
|
774
|
-
const key =
|
|
813
|
+
function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
|
|
814
|
+
const key = containerId + configId;
|
|
775
815
|
ctx.mapViewabilityValues.set(key, viewToken);
|
|
776
816
|
const cb = ctx.mapViewabilityCallbacks.get(key);
|
|
777
817
|
cb == null ? void 0 : cb(viewToken);
|
|
@@ -799,7 +839,7 @@ var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
|
|
|
799
839
|
var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
|
|
800
840
|
var _a, _b, _c, _d;
|
|
801
841
|
const {
|
|
802
|
-
data: dataProp,
|
|
842
|
+
data: dataProp = [],
|
|
803
843
|
initialScrollIndex,
|
|
804
844
|
initialScrollOffset,
|
|
805
845
|
horizontal,
|
|
@@ -1633,22 +1673,31 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1633
1673
|
if (index === void 0) {
|
|
1634
1674
|
return null;
|
|
1635
1675
|
}
|
|
1636
|
-
const useViewability2 = (configId, callback) => {
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1676
|
+
const useViewability2 = __DEV__ ? (configId, callback) => {
|
|
1677
|
+
console.warn(
|
|
1678
|
+
`[legend-list] useViewability has been moved from a render prop to a regular import: import { useViewability } from "@legendapp/list";`
|
|
1679
|
+
);
|
|
1680
|
+
} : void 0;
|
|
1681
|
+
const useViewabilityAmount2 = __DEV__ ? (callback) => {
|
|
1682
|
+
console.warn(
|
|
1683
|
+
`[legend-list] useViewabilityAmount has been moved from a render prop to a regular import: import { useViewabilityAmount } from "@legendapp/list";`
|
|
1684
|
+
);
|
|
1685
|
+
} : void 0;
|
|
1686
|
+
const useRecyclingEffect2 = __DEV__ ? (effect) => {
|
|
1687
|
+
console.warn(
|
|
1688
|
+
`[legend-list] useRecyclingEffect has been moved from a render prop to a regular import: import { useRecyclingEffect } from "@legendapp/list";`
|
|
1689
|
+
);
|
|
1690
|
+
} : void 0;
|
|
1691
|
+
const useRecyclingState2 = __DEV__ ? (valueOrFun) => {
|
|
1692
|
+
console.warn(
|
|
1693
|
+
`[legend-list] useRecyclingState has been moved from a render prop to a regular import: import { useRecyclingState } from "@legendapp/list";`
|
|
1694
|
+
);
|
|
1695
|
+
} : void 0;
|
|
1648
1696
|
const renderedItem = (_b2 = (_a2 = refState.current).renderItem) == null ? void 0 : _b2.call(_a2, {
|
|
1649
1697
|
item: data[index],
|
|
1650
1698
|
index,
|
|
1651
1699
|
extraData: peek$(ctx, "extraData"),
|
|
1700
|
+
// @ts-expect-error TODO: Remove these before 1.0
|
|
1652
1701
|
useViewability: useViewability2,
|
|
1653
1702
|
useViewabilityAmount: useViewabilityAmount2,
|
|
1654
1703
|
useRecyclingEffect: useRecyclingEffect2,
|
package/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React6 from 'react';
|
|
2
|
-
import React6__default, {
|
|
2
|
+
import React6__default, { memo, useReducer, useEffect, createContext, useMemo, useRef, useCallback, useImperativeHandle, useSyncExternalStore, useContext, useState, forwardRef, useLayoutEffect } from 'react';
|
|
3
3
|
import { View, Text, Platform, Animated, ScrollView, StyleSheet, Dimensions, RefreshControl } from 'react-native';
|
|
4
4
|
|
|
5
5
|
// src/LegendList.tsx
|
|
@@ -65,6 +65,58 @@ function getContentSize(ctx) {
|
|
|
65
65
|
const totalSize = values.get("totalSize") || 0;
|
|
66
66
|
return headerSize + footerSize + totalSize + stylePaddingTop;
|
|
67
67
|
}
|
|
68
|
+
|
|
69
|
+
// src/DebugView.tsx
|
|
70
|
+
var DebugRow = ({ children }) => {
|
|
71
|
+
return /* @__PURE__ */ React.createElement(View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" } }, children);
|
|
72
|
+
};
|
|
73
|
+
var DebugView = memo(function DebugView2({ state }) {
|
|
74
|
+
const ctx = useStateContext();
|
|
75
|
+
const totalSize = use$("totalSize") || 0;
|
|
76
|
+
const totalSizeWithScrollAdjust = use$("totalSizeWithScrollAdjust") || 0;
|
|
77
|
+
const scrollAdjust = use$("scrollAdjust") || 0;
|
|
78
|
+
const rawScroll = use$("debugRawScroll") || 0;
|
|
79
|
+
const scroll = use$("debugComputedScroll") || 0;
|
|
80
|
+
const contentSize = getContentSize(ctx);
|
|
81
|
+
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
82
|
+
use$("numContainers");
|
|
83
|
+
use$("numContainersPooled");
|
|
84
|
+
useInterval(() => {
|
|
85
|
+
forceUpdate();
|
|
86
|
+
}, 100);
|
|
87
|
+
return /* @__PURE__ */ React.createElement(
|
|
88
|
+
View,
|
|
89
|
+
{
|
|
90
|
+
style: {
|
|
91
|
+
position: "absolute",
|
|
92
|
+
top: 0,
|
|
93
|
+
right: 0,
|
|
94
|
+
paddingLeft: 4,
|
|
95
|
+
paddingBottom: 4,
|
|
96
|
+
// height: 100,
|
|
97
|
+
backgroundColor: "#FFFFFFCC",
|
|
98
|
+
padding: 4,
|
|
99
|
+
borderRadius: 4
|
|
100
|
+
},
|
|
101
|
+
pointerEvents: "none"
|
|
102
|
+
},
|
|
103
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React.createElement(Text, null, totalSize.toFixed(2))),
|
|
104
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React.createElement(Text, null, contentSize.toFixed(2))),
|
|
105
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "At end:"), /* @__PURE__ */ React.createElement(Text, null, String(state.isAtBottom))),
|
|
106
|
+
/* @__PURE__ */ React.createElement(Text, null),
|
|
107
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React.createElement(Text, null, scrollAdjust.toFixed(2))),
|
|
108
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "TotalSizeReal: "), /* @__PURE__ */ React.createElement(Text, null, totalSizeWithScrollAdjust.toFixed(2))),
|
|
109
|
+
/* @__PURE__ */ React.createElement(Text, null),
|
|
110
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React.createElement(Text, null, rawScroll.toFixed(2))),
|
|
111
|
+
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React.createElement(Text, null, scroll.toFixed(2)))
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
function useInterval(callback, delay) {
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
const interval = setInterval(callback, delay);
|
|
117
|
+
return () => clearInterval(interval);
|
|
118
|
+
}, [delay]);
|
|
119
|
+
}
|
|
68
120
|
var symbolFirst = Symbol();
|
|
69
121
|
function useInit(cb) {
|
|
70
122
|
const refValue = useRef(symbolFirst);
|
|
@@ -150,56 +202,6 @@ function useRecyclingState(valueOrFun) {
|
|
|
150
202
|
});
|
|
151
203
|
return stateInfo;
|
|
152
204
|
}
|
|
153
|
-
var DebugRow = ({ children }) => {
|
|
154
|
-
return /* @__PURE__ */ React.createElement(View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" } }, children);
|
|
155
|
-
};
|
|
156
|
-
var DebugView = memo(function DebugView2({ state }) {
|
|
157
|
-
const ctx = useStateContext();
|
|
158
|
-
const totalSize = use$("totalSize") || 0;
|
|
159
|
-
const totalSizeWithScrollAdjust = use$("totalSizeWithScrollAdjust") || 0;
|
|
160
|
-
const scrollAdjust = use$("scrollAdjust") || 0;
|
|
161
|
-
const rawScroll = use$("debugRawScroll") || 0;
|
|
162
|
-
const scroll = use$("debugComputedScroll") || 0;
|
|
163
|
-
const contentSize = getContentSize(ctx);
|
|
164
|
-
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
165
|
-
use$("numContainers");
|
|
166
|
-
use$("numContainersPooled");
|
|
167
|
-
useInterval(() => {
|
|
168
|
-
forceUpdate();
|
|
169
|
-
}, 100);
|
|
170
|
-
return /* @__PURE__ */ React.createElement(
|
|
171
|
-
View,
|
|
172
|
-
{
|
|
173
|
-
style: {
|
|
174
|
-
position: "absolute",
|
|
175
|
-
top: 0,
|
|
176
|
-
right: 0,
|
|
177
|
-
paddingLeft: 4,
|
|
178
|
-
paddingBottom: 4,
|
|
179
|
-
// height: 100,
|
|
180
|
-
backgroundColor: "#FFFFFFCC",
|
|
181
|
-
padding: 4,
|
|
182
|
-
borderRadius: 4
|
|
183
|
-
},
|
|
184
|
-
pointerEvents: "none"
|
|
185
|
-
},
|
|
186
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React.createElement(Text, null, totalSize.toFixed(2))),
|
|
187
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React.createElement(Text, null, contentSize.toFixed(2))),
|
|
188
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "At end:"), /* @__PURE__ */ React.createElement(Text, null, String(state.isAtBottom))),
|
|
189
|
-
/* @__PURE__ */ React.createElement(Text, null),
|
|
190
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React.createElement(Text, null, scrollAdjust.toFixed(2))),
|
|
191
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "TotalSizeReal: "), /* @__PURE__ */ React.createElement(Text, null, totalSizeWithScrollAdjust.toFixed(2))),
|
|
192
|
-
/* @__PURE__ */ React.createElement(Text, null),
|
|
193
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React.createElement(Text, null, rawScroll.toFixed(2))),
|
|
194
|
-
/* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React.createElement(Text, null, scroll.toFixed(2)))
|
|
195
|
-
);
|
|
196
|
-
});
|
|
197
|
-
function useInterval(callback, delay) {
|
|
198
|
-
useEffect(() => {
|
|
199
|
-
const interval = setInterval(callback, delay);
|
|
200
|
-
return () => clearInterval(interval);
|
|
201
|
-
}, [delay]);
|
|
202
|
-
}
|
|
203
205
|
var LeanViewComponent = React6.forwardRef((props, ref) => {
|
|
204
206
|
return React6.createElement("RCTView", { ...props, ref });
|
|
205
207
|
});
|
|
@@ -657,11 +659,37 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
|
|
|
657
659
|
const { viewabilityConfig, onViewableItemsChanged } = viewabilityConfigCallbackPair;
|
|
658
660
|
const configId = viewabilityConfig.id;
|
|
659
661
|
const viewabilityState = mapViewabilityConfigCallbackPairs.get(configId);
|
|
660
|
-
const { viewableItems: previousViewableItems, start,
|
|
662
|
+
const { viewableItems: previousViewableItems, start, end } = viewabilityState;
|
|
663
|
+
const viewabilityTokens = /* @__PURE__ */ new Map();
|
|
664
|
+
for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
|
|
665
|
+
viewabilityTokens.set(
|
|
666
|
+
containerId,
|
|
667
|
+
computeViewability(
|
|
668
|
+
state,
|
|
669
|
+
ctx,
|
|
670
|
+
viewabilityConfig,
|
|
671
|
+
containerId,
|
|
672
|
+
value.key,
|
|
673
|
+
scrollSize,
|
|
674
|
+
value.item,
|
|
675
|
+
value.index
|
|
676
|
+
)
|
|
677
|
+
);
|
|
678
|
+
}
|
|
661
679
|
const changed = [];
|
|
662
680
|
if (previousViewableItems) {
|
|
663
681
|
for (const viewToken of previousViewableItems) {
|
|
664
|
-
|
|
682
|
+
const containerId = findContainerId(ctx, viewToken.key);
|
|
683
|
+
if (!isViewable(
|
|
684
|
+
state,
|
|
685
|
+
ctx,
|
|
686
|
+
viewabilityConfig,
|
|
687
|
+
containerId,
|
|
688
|
+
viewToken.key,
|
|
689
|
+
scrollSize,
|
|
690
|
+
viewToken.item,
|
|
691
|
+
viewToken.index
|
|
692
|
+
)) {
|
|
665
693
|
viewToken.isViewable = false;
|
|
666
694
|
changed.push(viewToken);
|
|
667
695
|
}
|
|
@@ -672,12 +700,14 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
|
|
|
672
700
|
const item = data[i];
|
|
673
701
|
if (item) {
|
|
674
702
|
const key = getId(i);
|
|
675
|
-
|
|
703
|
+
const containerId = findContainerId(ctx, key);
|
|
704
|
+
if (isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
|
|
676
705
|
const viewToken = {
|
|
677
706
|
item,
|
|
678
707
|
key,
|
|
679
708
|
index: i,
|
|
680
|
-
isViewable: true
|
|
709
|
+
isViewable: true,
|
|
710
|
+
containerId
|
|
681
711
|
};
|
|
682
712
|
viewableItems.push(viewToken);
|
|
683
713
|
if (!(previousViewableItems == null ? void 0 : previousViewableItems.find((v) => v.key === viewToken.key))) {
|
|
@@ -695,14 +725,19 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
|
|
|
695
725
|
viewabilityState.viewableItems = viewableItems;
|
|
696
726
|
for (let i = 0; i < changed.length; i++) {
|
|
697
727
|
const change = changed[i];
|
|
698
|
-
maybeUpdateViewabilityCallback(ctx, configId, change);
|
|
728
|
+
maybeUpdateViewabilityCallback(ctx, configId, change.containerId, change);
|
|
699
729
|
}
|
|
700
730
|
if (onViewableItemsChanged) {
|
|
701
731
|
onViewableItemsChanged({ viewableItems, changed });
|
|
702
732
|
}
|
|
703
733
|
}
|
|
734
|
+
for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
|
|
735
|
+
if (value.sizeVisible < 0) {
|
|
736
|
+
ctx.mapViewabilityAmountValues.delete(containerId);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
704
739
|
}
|
|
705
|
-
function
|
|
740
|
+
function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
|
|
706
741
|
const { sizes, positions, scroll: scrollState, scrollAdjustHandler } = state;
|
|
707
742
|
const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
|
|
708
743
|
const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
|
|
@@ -710,7 +745,7 @@ function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index)
|
|
|
710
745
|
const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
|
|
711
746
|
const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
|
|
712
747
|
const scroll = scrollState - previousScrollAdjust - topPad;
|
|
713
|
-
const top = positions.get(key) - scroll
|
|
748
|
+
const top = positions.get(key) - scroll;
|
|
714
749
|
const size = sizes.get(key) || 0;
|
|
715
750
|
const bottom = top + size;
|
|
716
751
|
const isEntirelyVisible = top >= 0 && bottom <= scrollSize && bottom > top;
|
|
@@ -719,7 +754,6 @@ function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index)
|
|
|
719
754
|
const percentOfScroller = size ? 100 * (sizeVisible / scrollSize) : 0;
|
|
720
755
|
const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
|
|
721
756
|
const isViewable2 = percent >= viewablePercentThreshold;
|
|
722
|
-
const containerId = findContainerId(ctx, key);
|
|
723
757
|
const value = {
|
|
724
758
|
index,
|
|
725
759
|
isViewable: isViewable2,
|
|
@@ -729,15 +763,21 @@ function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index)
|
|
|
729
763
|
percentOfScroller,
|
|
730
764
|
sizeVisible,
|
|
731
765
|
size,
|
|
732
|
-
|
|
733
|
-
|
|
766
|
+
scrollSize,
|
|
767
|
+
containerId
|
|
734
768
|
};
|
|
735
|
-
ctx.mapViewabilityAmountValues.
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
cb
|
|
769
|
+
if (JSON.stringify(value) !== JSON.stringify(ctx.mapViewabilityAmountValues.get(containerId))) {
|
|
770
|
+
ctx.mapViewabilityAmountValues.set(containerId, value);
|
|
771
|
+
const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
|
|
772
|
+
if (cb) {
|
|
773
|
+
cb(value);
|
|
774
|
+
}
|
|
739
775
|
}
|
|
740
|
-
return
|
|
776
|
+
return value;
|
|
777
|
+
}
|
|
778
|
+
function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
|
|
779
|
+
const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
|
|
780
|
+
return value.isViewable;
|
|
741
781
|
}
|
|
742
782
|
function findContainerId(ctx, key) {
|
|
743
783
|
const numContainers = peek$(ctx, "numContainers");
|
|
@@ -749,8 +789,8 @@ function findContainerId(ctx, key) {
|
|
|
749
789
|
}
|
|
750
790
|
return -1;
|
|
751
791
|
}
|
|
752
|
-
function maybeUpdateViewabilityCallback(ctx, configId, viewToken) {
|
|
753
|
-
const key =
|
|
792
|
+
function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
|
|
793
|
+
const key = containerId + configId;
|
|
754
794
|
ctx.mapViewabilityValues.set(key, viewToken);
|
|
755
795
|
const cb = ctx.mapViewabilityCallbacks.get(key);
|
|
756
796
|
cb == null ? void 0 : cb(viewToken);
|
|
@@ -778,7 +818,7 @@ var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
|
|
|
778
818
|
var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
|
|
779
819
|
var _a, _b, _c, _d;
|
|
780
820
|
const {
|
|
781
|
-
data: dataProp,
|
|
821
|
+
data: dataProp = [],
|
|
782
822
|
initialScrollIndex,
|
|
783
823
|
initialScrollOffset,
|
|
784
824
|
horizontal,
|
|
@@ -1612,22 +1652,31 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
1612
1652
|
if (index === void 0) {
|
|
1613
1653
|
return null;
|
|
1614
1654
|
}
|
|
1615
|
-
const useViewability2 = (configId, callback) => {
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1655
|
+
const useViewability2 = __DEV__ ? (configId, callback) => {
|
|
1656
|
+
console.warn(
|
|
1657
|
+
`[legend-list] useViewability has been moved from a render prop to a regular import: import { useViewability } from "@legendapp/list";`
|
|
1658
|
+
);
|
|
1659
|
+
} : void 0;
|
|
1660
|
+
const useViewabilityAmount2 = __DEV__ ? (callback) => {
|
|
1661
|
+
console.warn(
|
|
1662
|
+
`[legend-list] useViewabilityAmount has been moved from a render prop to a regular import: import { useViewabilityAmount } from "@legendapp/list";`
|
|
1663
|
+
);
|
|
1664
|
+
} : void 0;
|
|
1665
|
+
const useRecyclingEffect2 = __DEV__ ? (effect) => {
|
|
1666
|
+
console.warn(
|
|
1667
|
+
`[legend-list] useRecyclingEffect has been moved from a render prop to a regular import: import { useRecyclingEffect } from "@legendapp/list";`
|
|
1668
|
+
);
|
|
1669
|
+
} : void 0;
|
|
1670
|
+
const useRecyclingState2 = __DEV__ ? (valueOrFun) => {
|
|
1671
|
+
console.warn(
|
|
1672
|
+
`[legend-list] useRecyclingState has been moved from a render prop to a regular import: import { useRecyclingState } from "@legendapp/list";`
|
|
1673
|
+
);
|
|
1674
|
+
} : void 0;
|
|
1627
1675
|
const renderedItem = (_b2 = (_a2 = refState.current).renderItem) == null ? void 0 : _b2.call(_a2, {
|
|
1628
1676
|
item: data[index],
|
|
1629
1677
|
index,
|
|
1630
1678
|
extraData: peek$(ctx, "extraData"),
|
|
1679
|
+
// @ts-expect-error TODO: Remove these before 1.0
|
|
1631
1680
|
useViewability: useViewability2,
|
|
1632
1681
|
useViewabilityAmount: useViewabilityAmount2,
|
|
1633
1682
|
useRecyclingEffect: useRecyclingEffect2,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@legendapp/list",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.35",
|
|
4
4
|
"description": "Legend List aims to be a drop-in replacement for FlatList with much better performance and supporting dynamically sized items.",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"private": false,
|