@legendapp/list 2.0.0-next.2 → 2.0.0-next.20
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/{dist/animated.d.mts → animated.d.mts} +7 -2
- package/{dist/animated.d.ts → animated.d.ts} +7 -2
- package/{dist/animated.js → animated.js} +2 -2
- package/{dist/animated.mjs → animated.mjs} +2 -2
- package/{dist/index.d.mts → index.d.mts} +106 -56
- package/{dist/index.d.ts → index.d.ts} +106 -56
- package/{dist/index.js → index.js} +1589 -1095
- package/{dist/index.mjs → index.mjs} +1591 -1097
- package/{dist/keyboard-controller.d.mts → keyboard-controller.d.mts} +28 -8
- package/{dist/keyboard-controller.d.ts → keyboard-controller.d.ts} +28 -8
- package/{dist/keyboard-controller.js → keyboard-controller.js} +4 -4
- package/{dist/keyboard-controller.mjs → keyboard-controller.mjs} +4 -4
- package/package.json +34 -88
- package/{dist/reanimated.d.mts → reanimated.d.mts} +2 -2
- package/{dist/reanimated.d.ts → reanimated.d.ts} +2 -2
- package/{dist/reanimated.js → reanimated.js} +7 -7
- package/{dist/reanimated.mjs → reanimated.mjs} +7 -7
- package/.claude/settings.local.json +0 -8
- package/.cursor/rules/changelog.mdc +0 -60
- package/.github/FUNDING.yml +0 -15
- package/.gitignore +0 -5
- package/.prettierrc.json +0 -5
- package/.vscode/settings.json +0 -14
- package/CLAUDE.md +0 -126
- package/biome.json +0 -46
- package/bun.lock +0 -1289
- package/bunfig.toml +0 -2
- package/dist/CHANGELOG.md +0 -119
- package/dist/LICENSE +0 -21
- package/dist/README.md +0 -139
- package/dist/package.json +0 -35
- package/example/README.md +0 -40
- package/example/api/data/genres.json +0 -23
- package/example/api/data/playlist/10402-10749.json +0 -1
- package/example/api/data/playlist/10402-10770.json +0 -1
- package/example/api/data/playlist/10402-37.json +0 -1
- package/example/api/data/playlist/10749-10752.json +0 -1
- package/example/api/data/playlist/10749-10770.json +0 -1
- package/example/api/data/playlist/10749-37.json +0 -1
- package/example/api/data/playlist/10749-878.json +0 -1
- package/example/api/data/playlist/10751-10402.json +0 -1
- package/example/api/data/playlist/10751-10752.json +0 -1
- package/example/api/data/playlist/10751-37.json +0 -1
- package/example/api/data/playlist/10751-53.json +0 -1
- package/example/api/data/playlist/10751-878.json +0 -1
- package/example/api/data/playlist/10751-9648.json +0 -1
- package/example/api/data/playlist/10752-37.json +0 -1
- package/example/api/data/playlist/12-10402.json +0 -1
- package/example/api/data/playlist/12-10749.json +0 -1
- package/example/api/data/playlist/12-18.json +0 -1
- package/example/api/data/playlist/12-27.json +0 -1
- package/example/api/data/playlist/12-35.json +0 -1
- package/example/api/data/playlist/14-36.json +0 -1
- package/example/api/data/playlist/14-878.json +0 -1
- package/example/api/data/playlist/16-10751.json +0 -1
- package/example/api/data/playlist/16-10770.json +0 -1
- package/example/api/data/playlist/16-35.json +0 -1
- package/example/api/data/playlist/16-36.json +0 -1
- package/example/api/data/playlist/16-53.json +0 -1
- package/example/api/data/playlist/18-10751.json +0 -1
- package/example/api/data/playlist/18-10752.json +0 -1
- package/example/api/data/playlist/18-37.json +0 -1
- package/example/api/data/playlist/18-53.json +0 -1
- package/example/api/data/playlist/18-878.json +0 -1
- package/example/api/data/playlist/27-10749.json +0 -1
- package/example/api/data/playlist/27-10770.json +0 -1
- package/example/api/data/playlist/28-10749.json +0 -1
- package/example/api/data/playlist/28-10751.json +0 -1
- package/example/api/data/playlist/28-10770.json +0 -1
- package/example/api/data/playlist/28-16.json +0 -1
- package/example/api/data/playlist/28-18.json +0 -1
- package/example/api/data/playlist/28-36.json +0 -1
- package/example/api/data/playlist/28-37.json +0 -1
- package/example/api/data/playlist/28-53.json +0 -1
- package/example/api/data/playlist/28-80.json +0 -1
- package/example/api/data/playlist/28-99.json +0 -1
- package/example/api/data/playlist/35-10749.json +0 -1
- package/example/api/data/playlist/35-10751.json +0 -1
- package/example/api/data/playlist/35-10752.json +0 -1
- package/example/api/data/playlist/35-27.json +0 -1
- package/example/api/data/playlist/35-36.json +0 -1
- package/example/api/data/playlist/35-53.json +0 -1
- package/example/api/data/playlist/35-80.json +0 -1
- package/example/api/data/playlist/36-37.json +0 -1
- package/example/api/data/playlist/36-878.json +0 -1
- package/example/api/data/playlist/36-9648.json +0 -1
- package/example/api/data/playlist/53-10752.json +0 -1
- package/example/api/data/playlist/80-10770.json +0 -1
- package/example/api/data/playlist/80-14.json +0 -1
- package/example/api/data/playlist/80-18.json +0 -1
- package/example/api/data/playlist/80-37.json +0 -1
- package/example/api/data/playlist/878-37.json +0 -1
- package/example/api/data/playlist/9648-10770.json +0 -1
- package/example/api/data/playlist/9648-37.json +0 -1
- package/example/api/data/playlist/9648-53.json +0 -1
- package/example/api/data/playlist/9648-878.json +0 -1
- package/example/api/data/playlist/99-10749.json +0 -1
- package/example/api/data/playlist/99-14.json +0 -1
- package/example/api/data/playlist/99-18.json +0 -1
- package/example/api/data/playlist/99-27.json +0 -1
- package/example/api/data/playlist/99-53.json +0 -1
- package/example/api/data/playlist/99-9648.json +0 -1
- package/example/api/data/playlist/index.ts +0 -73
- package/example/api/data/rows.json +0 -1
- package/example/api/index.ts +0 -36
- package/example/app/(tabs)/_layout.tsx +0 -60
- package/example/app/(tabs)/cards.tsx +0 -81
- package/example/app/(tabs)/index.tsx +0 -205
- package/example/app/(tabs)/moviesL.tsx +0 -7
- package/example/app/(tabs)/moviesLR.tsx +0 -7
- package/example/app/+not-found.tsx +0 -32
- package/example/app/_layout.tsx +0 -34
- package/example/app/accurate-scrollto/index.tsx +0 -125
- package/example/app/accurate-scrollto-2/index.tsx +0 -52
- package/example/app/accurate-scrollto-huge/index.tsx +0 -128
- package/example/app/add-to-end/index.tsx +0 -82
- package/example/app/ai-chat/index.tsx +0 -236
- package/example/app/bidirectional-infinite-list/index.tsx +0 -133
- package/example/app/cards-columns/index.tsx +0 -37
- package/example/app/cards-flashlist/index.tsx +0 -122
- package/example/app/cards-flatlist/index.tsx +0 -94
- package/example/app/cards-no-recycle/index.tsx +0 -110
- package/example/app/cards-renderItem.tsx +0 -354
- package/example/app/chat-example/index.tsx +0 -167
- package/example/app/chat-infinite/index.tsx +0 -239
- package/example/app/chat-keyboard/index.tsx +0 -248
- package/example/app/chat-resize-outer/index.tsx +0 -247
- package/example/app/columns/index.tsx +0 -78
- package/example/app/countries/index.tsx +0 -182
- package/example/app/countries-flashlist/index.tsx +0 -163
- package/example/app/countries-reorder/index.tsx +0 -187
- package/example/app/extra-data/index.tsx +0 -86
- package/example/app/filter-elements/filter-data-provider.tsx +0 -55
- package/example/app/filter-elements/index.tsx +0 -118
- package/example/app/initial-scroll-index/index.tsx +0 -106
- package/example/app/initial-scroll-index/renderFixedItem.tsx +0 -215
- package/example/app/initial-scroll-index-free-height/index.tsx +0 -70
- package/example/app/initial-scroll-index-keyed/index.tsx +0 -62
- package/example/app/lazy-list/index.tsx +0 -123
- package/example/app/movies-flashlist/index.tsx +0 -7
- package/example/app/mutable-cells/index.tsx +0 -104
- package/example/app/video-feed/index.tsx +0 -119
- package/example/app.config.js +0 -22
- package/example/app.json +0 -45
- package/example/assets/fonts/SpaceMono-Regular.ttf +0 -0
- package/example/assets/images/adaptive-icon.png +0 -0
- package/example/assets/images/favicon.png +0 -0
- package/example/assets/images/icon.png +0 -0
- package/example/assets/images/partial-react-logo.png +0 -0
- package/example/assets/images/react-logo.png +0 -0
- package/example/assets/images/react-logo@2x.png +0 -0
- package/example/assets/images/react-logo@3x.png +0 -0
- package/example/assets/images/splash-icon.png +0 -0
- package/example/autoscroll.sh +0 -101
- package/example/bun.lock +0 -2266
- package/example/bunfig.toml +0 -2
- package/example/components/Breathe.tsx +0 -54
- package/example/components/Circle.tsx +0 -69
- package/example/components/Collapsible.tsx +0 -44
- package/example/components/ExternalLink.tsx +0 -24
- package/example/components/HapticTab.tsx +0 -18
- package/example/components/HelloWave.tsx +0 -37
- package/example/components/Movies.tsx +0 -179
- package/example/components/ParallaxScrollView.tsx +0 -81
- package/example/components/ThemedText.tsx +0 -60
- package/example/components/ThemedView.tsx +0 -14
- package/example/components/__tests__/ThemedText-test.tsx +0 -10
- package/example/components/__tests__/__snapshots__/ThemedText-test.tsx.snap +0 -24
- package/example/components/ui/IconSymbol.ios.tsx +0 -32
- package/example/components/ui/IconSymbol.tsx +0 -43
- package/example/components/ui/TabBarBackground.ios.tsx +0 -22
- package/example/components/ui/TabBarBackground.tsx +0 -6
- package/example/constants/Colors.ts +0 -26
- package/example/constants/constants.ts +0 -5
- package/example/constants/useScrollTest.ts +0 -19
- package/example/hooks/useColorScheme.ts +0 -1
- package/example/hooks/useColorScheme.web.ts +0 -8
- package/example/hooks/useThemeColor.ts +0 -22
- package/example/ios/.xcode.env +0 -11
- package/example/ios/Podfile +0 -64
- package/example/ios/Podfile.lock +0 -2767
- package/example/ios/Podfile.properties.json +0 -5
- package/example/ios/listtest/AppDelegate.swift +0 -70
- package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png +0 -0
- package/example/ios/listtest/Images.xcassets/AppIcon.appiconset/Contents.json +0 -14
- package/example/ios/listtest/Images.xcassets/Contents.json +0 -6
- package/example/ios/listtest/Images.xcassets/SplashScreenBackground.colorset/Contents.json +0 -20
- package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/Contents.json +0 -23
- package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image.png +0 -0
- package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@2x.png +0 -0
- package/example/ios/listtest/Images.xcassets/SplashScreenLogo.imageset/image@3x.png +0 -0
- package/example/ios/listtest/Info.plist +0 -85
- package/example/ios/listtest/PrivacyInfo.xcprivacy +0 -48
- package/example/ios/listtest/SplashScreen.storyboard +0 -42
- package/example/ios/listtest/Supporting/Expo.plist +0 -12
- package/example/ios/listtest/listtest-Bridging-Header.h +0 -3
- package/example/ios/listtest/listtest.entitlements +0 -5
- package/example/ios/listtest.xcodeproj/project.pbxproj +0 -547
- package/example/ios/listtest.xcodeproj/xcshareddata/xcschemes/listtest.xcscheme +0 -88
- package/example/ios/listtest.xcworkspace/contents.xcworkspacedata +0 -10
- package/example/metro.config.js +0 -16
- package/example/package.json +0 -73
- package/example/scripts/reset-project.js +0 -84
- package/example/tsconfig.json +0 -26
- package/posttsup.ts +0 -24
- package/src/Container.tsx +0 -176
- package/src/Containers.tsx +0 -85
- package/src/ContextContainer.ts +0 -145
- package/src/DebugView.tsx +0 -83
- package/src/LazyLegendList.tsx +0 -41
- package/src/LeanView.tsx +0 -18
- package/src/LegendList.tsx +0 -558
- package/src/ListComponent.tsx +0 -191
- package/src/ScrollAdjust.tsx +0 -24
- package/src/ScrollAdjustHandler.ts +0 -26
- package/src/Separator.tsx +0 -14
- package/src/animated.tsx +0 -6
- package/src/calculateItemsInView.ts +0 -363
- package/src/calculateOffsetForIndex.ts +0 -23
- package/src/calculateOffsetWithOffsetPosition.ts +0 -26
- package/src/checkAllSizesKnown.ts +0 -17
- package/src/checkAtBottom.ts +0 -36
- package/src/checkAtTop.ts +0 -27
- package/src/checkThreshold.ts +0 -30
- package/src/constants.ts +0 -11
- package/src/createColumnWrapperStyle.ts +0 -16
- package/src/doInitialAllocateContainers.ts +0 -40
- package/src/doMaintainScrollAtEnd.ts +0 -34
- package/src/findAvailableContainers.ts +0 -98
- package/src/finishScrollTo.ts +0 -8
- package/src/getId.ts +0 -21
- package/src/getItemSize.ts +0 -52
- package/src/getRenderedItem.ts +0 -34
- package/src/getScrollVelocity.ts +0 -47
- package/src/handleLayout.ts +0 -70
- package/src/helpers.ts +0 -39
- package/src/index.ts +0 -11
- package/src/keyboard-controller.tsx +0 -63
- package/src/onScroll.ts +0 -66
- package/src/prepareMVCP.ts +0 -50
- package/src/reanimated.tsx +0 -63
- package/src/requestAdjust.ts +0 -41
- package/src/scrollTo.ts +0 -40
- package/src/scrollToIndex.ts +0 -34
- package/src/setDidLayout.ts +0 -25
- package/src/setPaddingTop.ts +0 -28
- package/src/state.tsx +0 -304
- package/src/types.ts +0 -610
- package/src/updateAlignItemsPaddingTop.ts +0 -18
- package/src/updateAllPositions.ts +0 -130
- package/src/updateItemSize.ts +0 -203
- package/src/updateTotalSize.ts +0 -44
- package/src/useAnimatedValue.ts +0 -6
- package/src/useCombinedRef.ts +0 -22
- package/src/useInit.ts +0 -17
- package/src/useSyncLayout.tsx +0 -68
- package/src/useValue$.ts +0 -53
- package/src/viewability.ts +0 -279
- package/tsconfig.json +0 -59
- package/tsup.config.ts +0 -21
package/src/ListComponent.tsx
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { useMemo } from "react";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
import {
|
|
4
|
-
Animated,
|
|
5
|
-
type LayoutChangeEvent,
|
|
6
|
-
type LayoutRectangle,
|
|
7
|
-
type NativeScrollEvent,
|
|
8
|
-
type NativeSyntheticEvent,
|
|
9
|
-
ScrollView,
|
|
10
|
-
type ScrollViewProps,
|
|
11
|
-
View,
|
|
12
|
-
type ViewStyle,
|
|
13
|
-
} from "react-native";
|
|
14
|
-
import { Containers } from "./Containers";
|
|
15
|
-
import { ScrollAdjust } from "./ScrollAdjust";
|
|
16
|
-
import type { ScrollAdjustHandler } from "./ScrollAdjustHandler";
|
|
17
|
-
import { ENABLE_DEVMODE } from "./constants";
|
|
18
|
-
import { set$, useStateContext } from "./state";
|
|
19
|
-
import { type GetRenderedItem, type LegendListProps, typedMemo } from "./types";
|
|
20
|
-
import { useSyncLayout } from "./useSyncLayout";
|
|
21
|
-
import { useValue$ } from "./useValue$";
|
|
22
|
-
|
|
23
|
-
interface ListComponentProps<ItemT>
|
|
24
|
-
extends Omit<
|
|
25
|
-
LegendListProps<ItemT> & { scrollEventThrottle: number | undefined },
|
|
26
|
-
| "data"
|
|
27
|
-
| "estimatedItemSize"
|
|
28
|
-
| "drawDistance"
|
|
29
|
-
| "maintainScrollAtEnd"
|
|
30
|
-
| "maintainScrollAtEndThreshold"
|
|
31
|
-
| "maintainVisibleContentPosition"
|
|
32
|
-
| "style"
|
|
33
|
-
> {
|
|
34
|
-
horizontal: boolean;
|
|
35
|
-
initialContentOffset: number | undefined;
|
|
36
|
-
refScrollView: React.Ref<ScrollView>;
|
|
37
|
-
getRenderedItem: GetRenderedItem;
|
|
38
|
-
updateItemSize: (itemKey: string, size: { width: number; height: number }) => void;
|
|
39
|
-
onScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
40
|
-
onLayout: (event: LayoutChangeEvent) => void;
|
|
41
|
-
onLayoutHeader: (rect: LayoutRectangle, fromLayoutEffect: boolean) => void;
|
|
42
|
-
maintainVisibleContentPosition: boolean;
|
|
43
|
-
renderScrollComponent?: (props: ScrollViewProps) => React.ReactElement<ScrollViewProps>;
|
|
44
|
-
style: ViewStyle;
|
|
45
|
-
canRender: boolean;
|
|
46
|
-
scrollAdjustHandler: ScrollAdjustHandler;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const getComponent = (Component: React.ComponentType<any> | React.ReactElement) => {
|
|
50
|
-
if (React.isValidElement<any>(Component)) {
|
|
51
|
-
return Component;
|
|
52
|
-
}
|
|
53
|
-
if (Component) {
|
|
54
|
-
return <Component />;
|
|
55
|
-
}
|
|
56
|
-
return null;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const Padding = () => {
|
|
60
|
-
const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
|
|
61
|
-
|
|
62
|
-
return <Animated.View style={{ paddingTop: animPaddingTop }} />;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const PaddingDevMode = () => {
|
|
66
|
-
const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
|
|
67
|
-
|
|
68
|
-
return (
|
|
69
|
-
<>
|
|
70
|
-
<Animated.View style={{ paddingTop: animPaddingTop }} />
|
|
71
|
-
<Animated.View
|
|
72
|
-
style={{
|
|
73
|
-
position: "absolute",
|
|
74
|
-
top: 0,
|
|
75
|
-
height: animPaddingTop,
|
|
76
|
-
left: 0,
|
|
77
|
-
right: 0,
|
|
78
|
-
backgroundColor: "green",
|
|
79
|
-
}}
|
|
80
|
-
/>
|
|
81
|
-
</>
|
|
82
|
-
);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
export const ListComponent = typedMemo(function ListComponent<ItemT>({
|
|
86
|
-
canRender,
|
|
87
|
-
style,
|
|
88
|
-
contentContainerStyle,
|
|
89
|
-
horizontal,
|
|
90
|
-
initialContentOffset,
|
|
91
|
-
recycleItems,
|
|
92
|
-
ItemSeparatorComponent,
|
|
93
|
-
alignItemsAtEnd,
|
|
94
|
-
waitForInitialLayout,
|
|
95
|
-
onScroll,
|
|
96
|
-
onLayout,
|
|
97
|
-
ListHeaderComponent,
|
|
98
|
-
ListHeaderComponentStyle,
|
|
99
|
-
ListFooterComponent,
|
|
100
|
-
ListFooterComponentStyle,
|
|
101
|
-
ListEmptyComponent,
|
|
102
|
-
getRenderedItem,
|
|
103
|
-
updateItemSize,
|
|
104
|
-
refScrollView,
|
|
105
|
-
maintainVisibleContentPosition,
|
|
106
|
-
renderScrollComponent,
|
|
107
|
-
scrollAdjustHandler,
|
|
108
|
-
onLayoutHeader,
|
|
109
|
-
...rest
|
|
110
|
-
}: ListComponentProps<ItemT>) {
|
|
111
|
-
const ctx = useStateContext();
|
|
112
|
-
const { onLayout: onLayoutHeaderSync, ref: refHeader } = useSyncLayout({
|
|
113
|
-
onChange: onLayoutHeader,
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// Use renderScrollComponent if provided, otherwise a regular ScrollView
|
|
117
|
-
const ScrollComponent = renderScrollComponent
|
|
118
|
-
? useMemo(
|
|
119
|
-
() => React.forwardRef((props, ref) => renderScrollComponent({ ...props, ref } as any)),
|
|
120
|
-
[renderScrollComponent],
|
|
121
|
-
)
|
|
122
|
-
: ScrollView;
|
|
123
|
-
|
|
124
|
-
React.useEffect(() => {
|
|
125
|
-
if (canRender) {
|
|
126
|
-
setTimeout(() => {
|
|
127
|
-
scrollAdjustHandler.setMounted();
|
|
128
|
-
}, 0);
|
|
129
|
-
}
|
|
130
|
-
}, [canRender]);
|
|
131
|
-
|
|
132
|
-
return (
|
|
133
|
-
<ScrollComponent
|
|
134
|
-
{...rest}
|
|
135
|
-
style={style}
|
|
136
|
-
maintainVisibleContentPosition={
|
|
137
|
-
maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : undefined
|
|
138
|
-
}
|
|
139
|
-
contentContainerStyle={[
|
|
140
|
-
contentContainerStyle,
|
|
141
|
-
horizontal
|
|
142
|
-
? {
|
|
143
|
-
height: "100%",
|
|
144
|
-
}
|
|
145
|
-
: {},
|
|
146
|
-
]}
|
|
147
|
-
onScroll={onScroll}
|
|
148
|
-
onLayout={onLayout}
|
|
149
|
-
horizontal={horizontal}
|
|
150
|
-
contentOffset={
|
|
151
|
-
initialContentOffset
|
|
152
|
-
? horizontal
|
|
153
|
-
? { x: initialContentOffset, y: 0 }
|
|
154
|
-
: { x: 0, y: initialContentOffset }
|
|
155
|
-
: undefined
|
|
156
|
-
}
|
|
157
|
-
ref={refScrollView as any}
|
|
158
|
-
>
|
|
159
|
-
{maintainVisibleContentPosition && <ScrollAdjust />}
|
|
160
|
-
{ENABLE_DEVMODE ? <PaddingDevMode /> : <Padding />}
|
|
161
|
-
{ListHeaderComponent && (
|
|
162
|
-
<View style={ListHeaderComponentStyle} onLayout={onLayoutHeaderSync} ref={refHeader}>
|
|
163
|
-
{getComponent(ListHeaderComponent)}
|
|
164
|
-
</View>
|
|
165
|
-
)}
|
|
166
|
-
{ListEmptyComponent && getComponent(ListEmptyComponent)}
|
|
167
|
-
|
|
168
|
-
{canRender && (
|
|
169
|
-
<Containers
|
|
170
|
-
horizontal={horizontal!}
|
|
171
|
-
recycleItems={recycleItems!}
|
|
172
|
-
waitForInitialLayout={waitForInitialLayout}
|
|
173
|
-
getRenderedItem={getRenderedItem}
|
|
174
|
-
ItemSeparatorComponent={ItemSeparatorComponent}
|
|
175
|
-
updateItemSize={updateItemSize}
|
|
176
|
-
/>
|
|
177
|
-
)}
|
|
178
|
-
{ListFooterComponent && (
|
|
179
|
-
<View
|
|
180
|
-
style={ListFooterComponentStyle}
|
|
181
|
-
onLayout={(event) => {
|
|
182
|
-
const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
|
|
183
|
-
set$(ctx, "footerSize", size);
|
|
184
|
-
}}
|
|
185
|
-
>
|
|
186
|
-
{getComponent(ListFooterComponent)}
|
|
187
|
-
</View>
|
|
188
|
-
)}
|
|
189
|
-
</ScrollComponent>
|
|
190
|
-
);
|
|
191
|
-
});
|
package/src/ScrollAdjust.tsx
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// biome-ignore lint/correctness/noUnusedImports: Leaving this out makes it crash in some environments
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
import { View } from "react-native";
|
|
4
|
-
import { useArr$ } from "./state";
|
|
5
|
-
|
|
6
|
-
export function ScrollAdjust() {
|
|
7
|
-
// Use a large bias to ensure this value never goes negative
|
|
8
|
-
const bias = 10_000_000;
|
|
9
|
-
const [scrollAdjust, scrollAdjustUserOffset] = useArr$(["scrollAdjust", "scrollAdjustUserOffset"]);
|
|
10
|
-
const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0) + bias;
|
|
11
|
-
const horizontal = false;
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<View
|
|
15
|
-
style={{
|
|
16
|
-
position: "absolute",
|
|
17
|
-
height: 0,
|
|
18
|
-
width: 0,
|
|
19
|
-
top: horizontal ? 0 : scrollOffset,
|
|
20
|
-
left: horizontal ? scrollOffset : 0,
|
|
21
|
-
}}
|
|
22
|
-
/>
|
|
23
|
-
);
|
|
24
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { type StateContext, peek$, set$ } from "./state";
|
|
2
|
-
|
|
3
|
-
export class ScrollAdjustHandler {
|
|
4
|
-
private appliedAdjust = 0;
|
|
5
|
-
private context: StateContext;
|
|
6
|
-
private mounted = false;
|
|
7
|
-
|
|
8
|
-
constructor(ctx: StateContext) {
|
|
9
|
-
this.context = ctx;
|
|
10
|
-
}
|
|
11
|
-
requestAdjust(add: number) {
|
|
12
|
-
const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
|
|
13
|
-
|
|
14
|
-
this.appliedAdjust = add + oldAdjustTop;
|
|
15
|
-
|
|
16
|
-
const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
|
|
17
|
-
if (this.mounted) {
|
|
18
|
-
set();
|
|
19
|
-
} else {
|
|
20
|
-
requestAnimationFrame(set);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
setMounted() {
|
|
24
|
-
this.mounted = true;
|
|
25
|
-
}
|
|
26
|
-
}
|
package/src/Separator.tsx
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { useArr$ } from "./state";
|
|
2
|
-
|
|
3
|
-
export interface SeparatorProps<ItemT> {
|
|
4
|
-
ItemSeparatorComponent: React.ComponentType<{ leadingItem: ItemT }>;
|
|
5
|
-
itemKey: string;
|
|
6
|
-
leadingItem: ItemT;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function Separator<ItemT>({ ItemSeparatorComponent, itemKey, leadingItem }: SeparatorProps<ItemT>) {
|
|
10
|
-
const [lastItemKeys] = useArr$(["lastItemKeys"]);
|
|
11
|
-
const isALastItem = lastItemKeys.includes(itemKey);
|
|
12
|
-
|
|
13
|
-
return isALastItem ? null : <ItemSeparatorComponent leadingItem={leadingItem} />;
|
|
14
|
-
}
|
package/src/animated.tsx
DELETED
|
@@ -1,363 +0,0 @@
|
|
|
1
|
-
import { calculateOffsetForIndex } from "./calculateOffsetForIndex";
|
|
2
|
-
import { calculateOffsetWithOffsetPosition } from "./calculateOffsetWithOffsetPosition";
|
|
3
|
-
import { checkAllSizesKnown } from "./checkAllSizesKnown";
|
|
4
|
-
import { ENABLE_DEBUG_VIEW, POSITION_OUT_OF_VIEW } from "./constants";
|
|
5
|
-
import { findAvailableContainers } from "./findAvailableContainers";
|
|
6
|
-
import { getId } from "./getId";
|
|
7
|
-
import { getItemSize } from "./getItemSize";
|
|
8
|
-
import { getScrollVelocity } from "./getScrollVelocity";
|
|
9
|
-
import { prepareMVCP } from "./prepareMVCP";
|
|
10
|
-
import { setDidLayout } from "./setDidLayout";
|
|
11
|
-
import { type StateContext, peek$, set$ } from "./state";
|
|
12
|
-
import type { InternalState } from "./types";
|
|
13
|
-
import { updateAllPositions } from "./updateAllPositions";
|
|
14
|
-
import { updateViewableItems } from "./viewability";
|
|
15
|
-
|
|
16
|
-
export function calculateItemsInView(
|
|
17
|
-
ctx: StateContext,
|
|
18
|
-
state: InternalState,
|
|
19
|
-
params: { doMVCP?: boolean; dataChanged?: boolean } = {},
|
|
20
|
-
) {
|
|
21
|
-
const {
|
|
22
|
-
scrollLength,
|
|
23
|
-
startBufferedId: startBufferedIdOrig,
|
|
24
|
-
positions,
|
|
25
|
-
columns,
|
|
26
|
-
containerItemKeys,
|
|
27
|
-
idCache,
|
|
28
|
-
sizes,
|
|
29
|
-
indexByKey,
|
|
30
|
-
scrollForNextCalculateItemsInView,
|
|
31
|
-
enableScrollForNextCalculateItemsInView,
|
|
32
|
-
minIndexSizeChanged,
|
|
33
|
-
} = state;
|
|
34
|
-
const data = state.props.data;
|
|
35
|
-
if (!data || scrollLength === 0) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const totalSize = peek$(ctx, "totalSize");
|
|
40
|
-
const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
|
|
41
|
-
const numColumns = peek$(ctx, "numColumns");
|
|
42
|
-
const previousScrollAdjust = 0;
|
|
43
|
-
const { dataChanged, doMVCP } = params;
|
|
44
|
-
const speed = getScrollVelocity(state);
|
|
45
|
-
|
|
46
|
-
if (doMVCP || dataChanged) {
|
|
47
|
-
// TODO: This should only run if a size changed or items changed
|
|
48
|
-
// Handle maintainVisibleContentPosition adjustment early
|
|
49
|
-
const checkMVCP = doMVCP ? prepareMVCP(ctx, state) : undefined;
|
|
50
|
-
|
|
51
|
-
// Update all positions upfront so we can assume they're correct
|
|
52
|
-
updateAllPositions(ctx, state, dataChanged);
|
|
53
|
-
|
|
54
|
-
checkMVCP?.();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const scrollExtra = 0;
|
|
58
|
-
// Disabled this optimization for now because it was causing blanks to appear sometimes
|
|
59
|
-
// We may need to control speed calculation better, or not have a 5 item history to avoid this issue
|
|
60
|
-
// const scrollExtra = Math.max(-16, Math.min(16, speed)) * 24;
|
|
61
|
-
|
|
62
|
-
const { queuedInitialLayout } = state;
|
|
63
|
-
let { scroll: scrollState } = state;
|
|
64
|
-
|
|
65
|
-
// If this is before the initial layout, and we have an initialScrollIndex,
|
|
66
|
-
// then ignore the actual scroll which might be shifting due to scrollAdjustHandler
|
|
67
|
-
// and use the calculated offset of the initialScrollIndex instead.
|
|
68
|
-
const initialScroll = state.props.initialScroll;
|
|
69
|
-
if (!queuedInitialLayout && initialScroll) {
|
|
70
|
-
const updatedOffset = calculateOffsetWithOffsetPosition(
|
|
71
|
-
state,
|
|
72
|
-
calculateOffsetForIndex(ctx, state, initialScroll.index),
|
|
73
|
-
initialScroll,
|
|
74
|
-
);
|
|
75
|
-
scrollState = updatedOffset;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const scrollAdjustPad = -previousScrollAdjust - topPad;
|
|
79
|
-
let scroll = scrollState + scrollExtra + scrollAdjustPad;
|
|
80
|
-
|
|
81
|
-
// Sometimes we may have scrolled past the visible area which can make items at the top of the
|
|
82
|
-
// screen not render. So make sure we clamp scroll to the end.
|
|
83
|
-
if (scroll + scrollLength > totalSize) {
|
|
84
|
-
scroll = totalSize - scrollLength;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (ENABLE_DEBUG_VIEW) {
|
|
88
|
-
set$(ctx, "debugRawScroll", scrollState);
|
|
89
|
-
set$(ctx, "debugComputedScroll", scroll);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const scrollBuffer = state.props.scrollBuffer;
|
|
93
|
-
let scrollBufferTop = scrollBuffer;
|
|
94
|
-
let scrollBufferBottom = scrollBuffer;
|
|
95
|
-
|
|
96
|
-
if (speed > 0) {
|
|
97
|
-
scrollBufferTop = scrollBuffer * 0.5;
|
|
98
|
-
scrollBufferBottom = scrollBuffer * 1.5;
|
|
99
|
-
} else {
|
|
100
|
-
scrollBufferTop = scrollBuffer * 1.5;
|
|
101
|
-
scrollBufferBottom = scrollBuffer * 0.5;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const scrollTopBuffered = scroll - scrollBufferTop;
|
|
105
|
-
const scrollBottom = scroll + scrollLength;
|
|
106
|
-
const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
|
|
107
|
-
|
|
108
|
-
// Check precomputed scroll range to see if we can skip this check
|
|
109
|
-
if (scrollForNextCalculateItemsInView) {
|
|
110
|
-
const { top, bottom } = scrollForNextCalculateItemsInView;
|
|
111
|
-
if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
let startNoBuffer: number | null = null;
|
|
117
|
-
let startBuffered: number | null = null;
|
|
118
|
-
let startBufferedId: string | null = null;
|
|
119
|
-
let endNoBuffer: number | null = null;
|
|
120
|
-
let endBuffered: number | null = null;
|
|
121
|
-
|
|
122
|
-
let loopStart: number = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
|
|
123
|
-
|
|
124
|
-
if (minIndexSizeChanged !== undefined) {
|
|
125
|
-
loopStart = Math.min(minIndexSizeChanged, loopStart);
|
|
126
|
-
state.minIndexSizeChanged = undefined;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Go backwards from the last start position to find the first item that is in view
|
|
130
|
-
// This is an optimization to avoid looping through all items, which could slow down
|
|
131
|
-
// when scrolling at the end of a long list.
|
|
132
|
-
for (let i = loopStart; i >= 0; i--) {
|
|
133
|
-
const id = idCache.get(i) ?? getId(state, i)!;
|
|
134
|
-
const top = positions.get(id)!;
|
|
135
|
-
const size = sizes.get(id) ?? getItemSize(state, id, i, data[i]);
|
|
136
|
-
const bottom = top + size;
|
|
137
|
-
|
|
138
|
-
if (bottom > scroll - scrollBuffer) {
|
|
139
|
-
loopStart = i;
|
|
140
|
-
} else {
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const loopStartMod = loopStart % numColumns;
|
|
146
|
-
if (loopStartMod > 0) {
|
|
147
|
-
loopStart -= loopStartMod;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
let foundEnd = false;
|
|
151
|
-
let nextTop: number | undefined;
|
|
152
|
-
let nextBottom: number | undefined;
|
|
153
|
-
|
|
154
|
-
// TODO PERF: Could cache this while looping through numContainers at the end of this function
|
|
155
|
-
// This takes 0.03 ms in an example in the ios simulator
|
|
156
|
-
const prevNumContainers = ctx.values.get("numContainers") as number;
|
|
157
|
-
let maxIndexRendered = 0;
|
|
158
|
-
for (let i = 0; i < prevNumContainers; i++) {
|
|
159
|
-
const key = peek$(ctx, `containerItemKey${i}`);
|
|
160
|
-
if (key !== undefined) {
|
|
161
|
-
const index = indexByKey.get(key)!;
|
|
162
|
-
maxIndexRendered = Math.max(maxIndexRendered, index);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
let firstFullyOnScreenIndex: number | undefined;
|
|
167
|
-
|
|
168
|
-
// scan data forwards
|
|
169
|
-
// Continue until we've found the end and we've updated positions of all items that were previously in view
|
|
170
|
-
const dataLength = data!.length;
|
|
171
|
-
for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
|
|
172
|
-
const id = idCache.get(i) ?? getId(state, i)!;
|
|
173
|
-
const size = sizes.get(id) ?? getItemSize(state, id, i, data[i]);
|
|
174
|
-
const top = positions.get(id)!;
|
|
175
|
-
|
|
176
|
-
if (!foundEnd) {
|
|
177
|
-
if (startNoBuffer === null && top + size > scroll) {
|
|
178
|
-
startNoBuffer = i;
|
|
179
|
-
}
|
|
180
|
-
// Subtract 10px for a little buffer so it can be slightly off screen
|
|
181
|
-
if (firstFullyOnScreenIndex === undefined && top >= scroll - 10) {
|
|
182
|
-
firstFullyOnScreenIndex = i;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (startBuffered === null && top + size > scrollTopBuffered) {
|
|
186
|
-
startBuffered = i;
|
|
187
|
-
startBufferedId = id;
|
|
188
|
-
nextTop = top;
|
|
189
|
-
}
|
|
190
|
-
if (startNoBuffer !== null) {
|
|
191
|
-
if (top <= scrollBottom) {
|
|
192
|
-
endNoBuffer = i;
|
|
193
|
-
}
|
|
194
|
-
if (top <= scrollBottomBuffered) {
|
|
195
|
-
endBuffered = i;
|
|
196
|
-
nextBottom = top + size;
|
|
197
|
-
} else {
|
|
198
|
-
foundEnd = true;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const idsInView: string[] = [];
|
|
205
|
-
for (let i = firstFullyOnScreenIndex!; i <= endNoBuffer!; i++) {
|
|
206
|
-
const id = idCache.get(i) ?? getId(state, i)!;
|
|
207
|
-
idsInView.push(id);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
Object.assign(state, {
|
|
211
|
-
startBuffered,
|
|
212
|
-
startBufferedId,
|
|
213
|
-
startNoBuffer,
|
|
214
|
-
endBuffered,
|
|
215
|
-
endNoBuffer,
|
|
216
|
-
idsInView,
|
|
217
|
-
firstFullyOnScreenIndex,
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
// Precompute the scroll that will be needed for the range to change
|
|
221
|
-
// so it can be skipped if not needed
|
|
222
|
-
if (enableScrollForNextCalculateItemsInView && nextTop !== undefined && nextBottom !== undefined) {
|
|
223
|
-
state.scrollForNextCalculateItemsInView =
|
|
224
|
-
nextTop !== undefined && nextBottom !== undefined
|
|
225
|
-
? {
|
|
226
|
-
top: nextTop,
|
|
227
|
-
bottom: nextBottom,
|
|
228
|
-
}
|
|
229
|
-
: undefined;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const numContainers = peek$(ctx, "numContainers");
|
|
233
|
-
// Reset containers that aren't used anymore because the data has changed
|
|
234
|
-
const pendingRemoval: number[] = [];
|
|
235
|
-
if (dataChanged) {
|
|
236
|
-
for (let i = 0; i < numContainers; i++) {
|
|
237
|
-
const itemKey = peek$(ctx, `containerItemKey${i}`);
|
|
238
|
-
if (!state.props.keyExtractor || (itemKey && indexByKey.get(itemKey) === undefined)) {
|
|
239
|
-
pendingRemoval.push(i);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Place newly added items into containers
|
|
245
|
-
if (startBuffered !== null && endBuffered !== null) {
|
|
246
|
-
let numContainers = prevNumContainers;
|
|
247
|
-
const needNewContainers: number[] = [];
|
|
248
|
-
|
|
249
|
-
for (let i = startBuffered!; i <= endBuffered; i++) {
|
|
250
|
-
const id = idCache.get(i) ?? getId(state, i)!;
|
|
251
|
-
if (!containerItemKeys.has(id)) {
|
|
252
|
-
needNewContainers.push(i);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (needNewContainers.length > 0) {
|
|
257
|
-
const availableContainers = findAvailableContainers(
|
|
258
|
-
ctx,
|
|
259
|
-
state,
|
|
260
|
-
needNewContainers.length,
|
|
261
|
-
startBuffered,
|
|
262
|
-
endBuffered,
|
|
263
|
-
pendingRemoval,
|
|
264
|
-
);
|
|
265
|
-
for (let idx = 0; idx < needNewContainers.length; idx++) {
|
|
266
|
-
const i = needNewContainers[idx];
|
|
267
|
-
const containerIndex = availableContainers[idx];
|
|
268
|
-
const id = idCache.get(i) ?? getId(state, i)!;
|
|
269
|
-
|
|
270
|
-
// Remove old key from cache
|
|
271
|
-
const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
|
|
272
|
-
if (oldKey && oldKey !== id) {
|
|
273
|
-
containerItemKeys!.delete(oldKey);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
set$(ctx, `containerItemKey${containerIndex}`, id);
|
|
277
|
-
set$(ctx, `containerItemData${containerIndex}`, data[i]);
|
|
278
|
-
|
|
279
|
-
// Update cache when adding new item
|
|
280
|
-
containerItemKeys!.add(id);
|
|
281
|
-
|
|
282
|
-
if (containerIndex >= numContainers) {
|
|
283
|
-
numContainers = containerIndex + 1;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
if (numContainers !== prevNumContainers) {
|
|
288
|
-
set$(ctx, "numContainers", numContainers);
|
|
289
|
-
if (numContainers > peek$(ctx, "numContainersPooled")) {
|
|
290
|
-
set$(ctx, "numContainersPooled", Math.ceil(numContainers * 1.5));
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// Update top positions of all containers
|
|
297
|
-
for (let i = 0; i < numContainers; i++) {
|
|
298
|
-
const itemKey = peek$(ctx, `containerItemKey${i}`);
|
|
299
|
-
|
|
300
|
-
// If it was
|
|
301
|
-
if (pendingRemoval.includes(i)) {
|
|
302
|
-
// Update cache when removing item
|
|
303
|
-
if (itemKey) {
|
|
304
|
-
containerItemKeys!.delete(itemKey);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
set$(ctx, `containerItemKey${i}`, undefined);
|
|
308
|
-
set$(ctx, `containerItemData${i}`, undefined);
|
|
309
|
-
set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
|
|
310
|
-
set$(ctx, `containerColumn${i}`, -1);
|
|
311
|
-
} else {
|
|
312
|
-
const itemIndex = indexByKey.get(itemKey)!;
|
|
313
|
-
const item = data[itemIndex];
|
|
314
|
-
if (item !== undefined) {
|
|
315
|
-
const id = idCache.get(itemIndex) ?? getId(state, itemIndex);
|
|
316
|
-
const position = positions.get(id);
|
|
317
|
-
|
|
318
|
-
if (position === undefined) {
|
|
319
|
-
// This item may have been in view before data changed and positions were reset
|
|
320
|
-
// so we need to set it to out of view
|
|
321
|
-
set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
|
|
322
|
-
} else {
|
|
323
|
-
const pos = positions.get(id)!;
|
|
324
|
-
const column = columns.get(id) || 1;
|
|
325
|
-
|
|
326
|
-
const prevPos = peek$(ctx, `containerPosition${i}`);
|
|
327
|
-
const prevColumn = peek$(ctx, `containerColumn${i}`);
|
|
328
|
-
const prevData = peek$(ctx, `containerItemData${i}`);
|
|
329
|
-
|
|
330
|
-
if (!prevPos || (pos > POSITION_OUT_OF_VIEW && pos !== prevPos)) {
|
|
331
|
-
set$(ctx, `containerPosition${i}`, pos);
|
|
332
|
-
}
|
|
333
|
-
if (column >= 0 && column !== prevColumn) {
|
|
334
|
-
set$(ctx, `containerColumn${i}`, column);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (prevData !== item) {
|
|
338
|
-
set$(ctx, `containerItemData${i}`, data[itemIndex]);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
if (!queuedInitialLayout && endBuffered !== null) {
|
|
346
|
-
// If waiting for initial layout and all items in view have a known size then
|
|
347
|
-
// initial layout is complete
|
|
348
|
-
if (checkAllSizesKnown(state)) {
|
|
349
|
-
setDidLayout(ctx, state);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
if (state.props.viewabilityConfigCallbackPairs) {
|
|
354
|
-
updateViewableItems(
|
|
355
|
-
state,
|
|
356
|
-
ctx,
|
|
357
|
-
state.props.viewabilityConfigCallbackPairs,
|
|
358
|
-
scrollLength,
|
|
359
|
-
startNoBuffer!,
|
|
360
|
-
endNoBuffer!,
|
|
361
|
-
);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { getId } from "./getId";
|
|
2
|
-
import { type StateContext, peek$ } from "./state";
|
|
3
|
-
import type { InternalState } from "./types";
|
|
4
|
-
|
|
5
|
-
export function calculateOffsetForIndex(ctx: StateContext, state: InternalState, index: number | undefined) {
|
|
6
|
-
let position = 0;
|
|
7
|
-
|
|
8
|
-
if (index !== undefined) {
|
|
9
|
-
position = state?.positions.get(getId(state, index)) || 0;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const paddingTop = peek$(ctx, "stylePaddingTop");
|
|
13
|
-
if (paddingTop) {
|
|
14
|
-
position += paddingTop;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const headerSize = peek$(ctx, "headerSize");
|
|
18
|
-
if (headerSize) {
|
|
19
|
-
position += headerSize;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return position;
|
|
23
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { getId } from "./getId";
|
|
2
|
-
import { getItemSize } from "./getItemSize";
|
|
3
|
-
import type { InternalState, ScrollIndexWithOffsetPosition } from "./types";
|
|
4
|
-
|
|
5
|
-
export function calculateOffsetWithOffsetPosition(
|
|
6
|
-
state: InternalState,
|
|
7
|
-
offsetParam: number,
|
|
8
|
-
params: Partial<ScrollIndexWithOffsetPosition>,
|
|
9
|
-
) {
|
|
10
|
-
const { index, viewOffset, viewPosition } = params;
|
|
11
|
-
let offset = offsetParam;
|
|
12
|
-
|
|
13
|
-
if (viewOffset) {
|
|
14
|
-
offset -= viewOffset;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (viewPosition !== undefined && index !== undefined) {
|
|
18
|
-
// TODO: This can be inaccurate if the item size is very different from the estimatedItemSize
|
|
19
|
-
// In the future we can improve this by listening for the item size change and then updating the scroll position
|
|
20
|
-
offset -=
|
|
21
|
-
viewPosition *
|
|
22
|
-
(state.scrollLength - getItemSize(state, getId(state, index), index, state.props.data[index]!));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return offset;
|
|
26
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { getId } from "./getId";
|
|
2
|
-
import type { InternalState } from "./types";
|
|
3
|
-
|
|
4
|
-
export function checkAllSizesKnown(state: InternalState) {
|
|
5
|
-
const { startBuffered, endBuffered, sizesKnown } = state;
|
|
6
|
-
if (endBuffered !== null) {
|
|
7
|
-
// If waiting for initial layout and all items in view have a known size then
|
|
8
|
-
// initial layout is complete
|
|
9
|
-
let areAllKnown = true;
|
|
10
|
-
for (let i = startBuffered!; areAllKnown && i <= endBuffered!; i++) {
|
|
11
|
-
const key = getId(state, i)!;
|
|
12
|
-
areAllKnown &&= sizesKnown.has(key);
|
|
13
|
-
}
|
|
14
|
-
return areAllKnown;
|
|
15
|
-
}
|
|
16
|
-
return false;
|
|
17
|
-
}
|