@legendapp/list 1.0.0-beta.8 → 1.0.0
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/CHANGELOG.md +5 -0
- package/README.md +96 -43
- package/animated.d.mts +54 -4
- package/animated.d.ts +54 -4
- package/index.d.mts +341 -63
- package/index.d.ts +341 -63
- package/index.js +1139 -434
- package/index.mjs +1117 -412
- package/keyboard-controller.d.mts +401 -0
- package/keyboard-controller.d.ts +401 -0
- package/keyboard-controller.js +69 -0
- package/keyboard-controller.mjs +48 -0
- package/package.json +3 -6
- package/reanimated.d.mts +12 -11
- package/reanimated.d.ts +12 -11
- package/reanimated.js +27 -16
- package/reanimated.mjs +28 -17
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -1,76 +1,129 @@
|
|
|
1
1
|
# Legend List
|
|
2
2
|
|
|
3
|
-
Legend List
|
|
3
|
+
**Legend List** is a high-performance list component for **React Native**, written purely in Typescript with no native dependencies. It is a drop-in replacement for `FlatList` and `FlashList` with better performance, especially when handling dynamically sized items.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## 🤔 Why Legend List?
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
* **Performance:** Designed from the ground up and heavily optimized for performance, it is faster than FlatList and other list libraries in most scenarios.
|
|
10
|
+
* **Dynamic Item Sizes:** Natively supports items with varying heights without performance hits.
|
|
11
|
+
* **Drop-in Replacement:** API compatibility with `FlatList` and `FlashList` for easier migration.
|
|
12
|
+
* **100% JS:** No native module linking required, ensuring easy integration and compatibility across platforms.
|
|
13
|
+
* **Lightweight:** Our goal is to keep LegendList as small of a dependency as possible. For more advanced use cases, we plan on supporting optional plugins. This ensures that we keep the package size as small as possible.
|
|
14
|
+
* **Bidirectional infinite lists:** Supports infinite scrolling in both directions with no flashes or scroll jumping
|
|
15
|
+
* **Chat UIs without inverted:** Chat UIs can align their content to the bottom and maintain scroll at end, so that the list doesn't need to be inverted, which causes weird behavior (in animations, etc...)
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
For more information, listen to the Legend List episode of the [React Native Radio Podcast](https://infinite.red/react-native-radio/rnr-325-legend-list-with-jay-meistrich) and the [livestream with Expo](https://www.youtube.com/watch?v=XpZMveUCke8).
|
|
12
18
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- `recycleItems` prop enables toggling recycling of list items. If enabled it will reuse item components for improved performance, but it will reuse any local state in items. So if you have local state in items you likely want this disabled.
|
|
19
|
+
---
|
|
20
|
+
## ✨ Additional Features
|
|
16
21
|
|
|
17
|
-
|
|
22
|
+
Beyond standard `FlatList` capabilities:
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
* `recycleItems`: (boolean) Toggles item component recycling.
|
|
25
|
+
* `true`: Reuses item components for optimal performance. Be cautious if your item components contain local state, as it might be reused unexpectedly.
|
|
26
|
+
* `false` (default): Creates new item components every time. Less performant but safer if items have complex internal state.
|
|
27
|
+
* `maintainScrollAtEnd`: (boolean) If `true` and the user is scrolled near the bottom (within `maintainScrollAtEndThreshold * screen height`), the list automatically scrolls to the end when items are added or heights change. Useful for chat interfaces.
|
|
28
|
+
* `alignItemsAtEnd`: (boolean) Useful for chat UIs, content smaller than the View will be aligned to the bottom of the list.
|
|
20
29
|
|
|
21
|
-
|
|
30
|
+
---
|
|
22
31
|
|
|
23
|
-
##
|
|
32
|
+
## 📚 Documentation
|
|
24
33
|
|
|
25
|
-
|
|
34
|
+
For comprehensive documentation, guides, and the full API reference, please visit:
|
|
26
35
|
|
|
27
|
-
|
|
36
|
+
➡️ **[Legend List Documentation Site](https://www.legendapp.com/open-source/list)**
|
|
28
37
|
|
|
29
|
-
|
|
38
|
+
---
|
|
30
39
|
|
|
31
|
-
|
|
40
|
+
## 💻 Usage
|
|
32
41
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
### Installation
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Using Bun
|
|
46
|
+
bun add @legendapp/list
|
|
47
|
+
|
|
48
|
+
# Using npm
|
|
49
|
+
npm install @legendapp/list
|
|
50
|
+
|
|
51
|
+
# Using Yarn
|
|
52
|
+
yarn add @legendapp/list
|
|
39
53
|
```
|
|
40
54
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
onEndReached?: ((info: { distanceFromEnd: number }) => void) | null | undefined;
|
|
53
|
-
keyExtractor?: (item: T, index: number) => string;
|
|
55
|
+
### Example
|
|
56
|
+
```tsx
|
|
57
|
+
import React, { useRef } from "react"
|
|
58
|
+
import { View, Image, Text, StyleSheet } from "react-native"
|
|
59
|
+
import { LegendList, LegendListRef, LegendListRenderItemProps } from "@legendapp/list"
|
|
60
|
+
|
|
61
|
+
// Define the type for your data items
|
|
62
|
+
interface UserData {
|
|
63
|
+
id: string;
|
|
64
|
+
name: string;
|
|
65
|
+
photoUri: string;
|
|
54
66
|
}
|
|
67
|
+
|
|
68
|
+
const LegendListExample = () => {
|
|
69
|
+
// Optional: Ref for accessing list methods (e.g., scrollTo)
|
|
70
|
+
const listRef = useRef<LegendListRef | null>(null)
|
|
71
|
+
|
|
72
|
+
const data = []
|
|
73
|
+
|
|
74
|
+
const renderItem = ({ item }: LegendListRenderItemProps<UserData>) => {
|
|
75
|
+
return (
|
|
76
|
+
<View>
|
|
77
|
+
<Image source={{ uri: item.photoUri }} />
|
|
78
|
+
<Text>{item.name}</Text>
|
|
79
|
+
</View>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<LegendList
|
|
85
|
+
// Required Props
|
|
86
|
+
data={data}
|
|
87
|
+
renderItem={renderItem}
|
|
88
|
+
|
|
89
|
+
// Recommended props (Improves performance)
|
|
90
|
+
keyExtractor={(item) => item.id}
|
|
91
|
+
recycleItems={true}
|
|
92
|
+
|
|
93
|
+
ref={listRef}
|
|
94
|
+
/>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export default LegendListExample
|
|
99
|
+
|
|
55
100
|
```
|
|
56
101
|
|
|
57
|
-
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## How to Build
|
|
58
105
|
|
|
59
|
-
|
|
106
|
+
1. `bun i`
|
|
107
|
+
2. `bun run build` will build the package to the `dist` folder.
|
|
60
108
|
|
|
61
|
-
##
|
|
109
|
+
## Running the Example
|
|
62
110
|
|
|
63
111
|
1. `cd example`
|
|
64
|
-
2. `
|
|
65
|
-
3. `
|
|
112
|
+
2. `bun i`
|
|
113
|
+
3. `bun run ios`
|
|
66
114
|
|
|
67
115
|
## PRs gladly accepted!
|
|
68
116
|
|
|
69
|
-
There's not a
|
|
117
|
+
There's not a ton of code so hopefully it's easy to contribute. If you want to add a missing feature or fix a bug please post an issue to see if development is already in progress so we can make sure to not duplicate work 😀.
|
|
70
118
|
|
|
71
|
-
##
|
|
119
|
+
## Upcoming Roadmap
|
|
72
120
|
|
|
73
|
-
|
|
121
|
+
- [] Column spans
|
|
122
|
+
- [] overrideItemLayout
|
|
123
|
+
- [] Sticky headers
|
|
124
|
+
- [] Masonry layout
|
|
125
|
+
- [] getItemType
|
|
126
|
+
- [] React DOM implementation
|
|
74
127
|
|
|
75
128
|
## Community
|
|
76
129
|
|
package/animated.d.mts
CHANGED
|
@@ -1,9 +1,59 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React$1 from 'react';
|
|
2
2
|
import * as _legendapp_list from '@legendapp/list';
|
|
3
|
+
import * as react_native from 'react-native';
|
|
3
4
|
import { Animated } from 'react-native';
|
|
4
5
|
|
|
5
|
-
declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props:
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
|
|
7
|
+
alignItemsAtEnd?: boolean;
|
|
8
|
+
columnWrapperStyle?: _legendapp_list.ColumnWrapperStyle;
|
|
9
|
+
data: readonly T[];
|
|
10
|
+
drawDistance?: number;
|
|
11
|
+
estimatedItemSize?: number;
|
|
12
|
+
extraData?: any;
|
|
13
|
+
getEstimatedItemSize?: ((index: number, item: T) => number) | undefined;
|
|
14
|
+
initialContainerPoolRatio?: number | undefined;
|
|
15
|
+
initialScrollOffset?: number;
|
|
16
|
+
initialScrollIndex?: number;
|
|
17
|
+
ItemSeparatorComponent?: React$1.ComponentType<{
|
|
18
|
+
leadingItem: T;
|
|
19
|
+
}> | undefined;
|
|
20
|
+
keyExtractor?: ((item: T, index: number) => string) | undefined;
|
|
21
|
+
ListEmptyComponent?: React.ComponentType<any> | React.ReactElement | null | undefined;
|
|
22
|
+
ListFooterComponent?: React.ComponentType<any> | React.ReactElement | null | undefined;
|
|
23
|
+
ListFooterComponentStyle?: react_native.StyleProp<react_native.ViewStyle> | undefined;
|
|
24
|
+
ListHeaderComponent?: React.ComponentType<any> | React.ReactElement | null | undefined;
|
|
25
|
+
ListHeaderComponentStyle?: react_native.StyleProp<react_native.ViewStyle> | undefined;
|
|
26
|
+
maintainScrollAtEnd?: boolean;
|
|
27
|
+
maintainScrollAtEndThreshold?: number;
|
|
28
|
+
maintainVisibleContentPosition?: boolean;
|
|
29
|
+
numColumns?: number;
|
|
30
|
+
onEndReached?: ((info: {
|
|
31
|
+
distanceFromEnd: number;
|
|
32
|
+
}) => void) | null | undefined;
|
|
33
|
+
onEndReachedThreshold?: number | null | undefined;
|
|
34
|
+
onItemSizeChanged?: ((info: {
|
|
35
|
+
size: number;
|
|
36
|
+
previous: number;
|
|
37
|
+
index: number;
|
|
38
|
+
itemKey: string;
|
|
39
|
+
itemData: T;
|
|
40
|
+
}) => void) | undefined;
|
|
41
|
+
onRefresh?: () => void;
|
|
42
|
+
onStartReached?: ((info: {
|
|
43
|
+
distanceFromStart: number;
|
|
44
|
+
}) => void) | null | undefined;
|
|
45
|
+
onStartReachedThreshold?: number | null | undefined;
|
|
46
|
+
onViewableItemsChanged?: _legendapp_list.OnViewableItemsChanged | undefined;
|
|
47
|
+
progressViewOffset?: number;
|
|
48
|
+
recycleItems?: boolean;
|
|
49
|
+
refScrollView?: React.Ref<react_native.ScrollView>;
|
|
50
|
+
refreshing?: boolean;
|
|
51
|
+
renderItem?: ((props: _legendapp_list.LegendListRenderItemProps<T>) => React$1.ReactNode) | undefined;
|
|
52
|
+
renderScrollComponent?: (props: react_native.ScrollViewProps) => React.ReactElement<react_native.ScrollViewProps>;
|
|
53
|
+
suggestEstimatedItemSize?: boolean;
|
|
54
|
+
viewabilityConfig?: _legendapp_list.ViewabilityConfig;
|
|
55
|
+
viewabilityConfigCallbackPairs?: _legendapp_list.ViewabilityConfigCallbackPairs | undefined;
|
|
56
|
+
waitForInitialLayout?: boolean;
|
|
57
|
+
} & React$1.RefAttributes<_legendapp_list.LegendListRef>) => React.ReactNode)>;
|
|
8
58
|
|
|
9
59
|
export { AnimatedLegendList };
|
package/animated.d.ts
CHANGED
|
@@ -1,9 +1,59 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React$1 from 'react';
|
|
2
2
|
import * as _legendapp_list from '@legendapp/list';
|
|
3
|
+
import * as react_native from 'react-native';
|
|
3
4
|
import { Animated } from 'react-native';
|
|
4
5
|
|
|
5
|
-
declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props:
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<Omit<react_native.ScrollViewProps, "scrollEventThrottle">, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
|
|
7
|
+
alignItemsAtEnd?: boolean;
|
|
8
|
+
columnWrapperStyle?: _legendapp_list.ColumnWrapperStyle;
|
|
9
|
+
data: readonly T[];
|
|
10
|
+
drawDistance?: number;
|
|
11
|
+
estimatedItemSize?: number;
|
|
12
|
+
extraData?: any;
|
|
13
|
+
getEstimatedItemSize?: ((index: number, item: T) => number) | undefined;
|
|
14
|
+
initialContainerPoolRatio?: number | undefined;
|
|
15
|
+
initialScrollOffset?: number;
|
|
16
|
+
initialScrollIndex?: number;
|
|
17
|
+
ItemSeparatorComponent?: React$1.ComponentType<{
|
|
18
|
+
leadingItem: T;
|
|
19
|
+
}> | undefined;
|
|
20
|
+
keyExtractor?: ((item: T, index: number) => string) | undefined;
|
|
21
|
+
ListEmptyComponent?: React.ComponentType<any> | React.ReactElement | null | undefined;
|
|
22
|
+
ListFooterComponent?: React.ComponentType<any> | React.ReactElement | null | undefined;
|
|
23
|
+
ListFooterComponentStyle?: react_native.StyleProp<react_native.ViewStyle> | undefined;
|
|
24
|
+
ListHeaderComponent?: React.ComponentType<any> | React.ReactElement | null | undefined;
|
|
25
|
+
ListHeaderComponentStyle?: react_native.StyleProp<react_native.ViewStyle> | undefined;
|
|
26
|
+
maintainScrollAtEnd?: boolean;
|
|
27
|
+
maintainScrollAtEndThreshold?: number;
|
|
28
|
+
maintainVisibleContentPosition?: boolean;
|
|
29
|
+
numColumns?: number;
|
|
30
|
+
onEndReached?: ((info: {
|
|
31
|
+
distanceFromEnd: number;
|
|
32
|
+
}) => void) | null | undefined;
|
|
33
|
+
onEndReachedThreshold?: number | null | undefined;
|
|
34
|
+
onItemSizeChanged?: ((info: {
|
|
35
|
+
size: number;
|
|
36
|
+
previous: number;
|
|
37
|
+
index: number;
|
|
38
|
+
itemKey: string;
|
|
39
|
+
itemData: T;
|
|
40
|
+
}) => void) | undefined;
|
|
41
|
+
onRefresh?: () => void;
|
|
42
|
+
onStartReached?: ((info: {
|
|
43
|
+
distanceFromStart: number;
|
|
44
|
+
}) => void) | null | undefined;
|
|
45
|
+
onStartReachedThreshold?: number | null | undefined;
|
|
46
|
+
onViewableItemsChanged?: _legendapp_list.OnViewableItemsChanged | undefined;
|
|
47
|
+
progressViewOffset?: number;
|
|
48
|
+
recycleItems?: boolean;
|
|
49
|
+
refScrollView?: React.Ref<react_native.ScrollView>;
|
|
50
|
+
refreshing?: boolean;
|
|
51
|
+
renderItem?: ((props: _legendapp_list.LegendListRenderItemProps<T>) => React$1.ReactNode) | undefined;
|
|
52
|
+
renderScrollComponent?: (props: react_native.ScrollViewProps) => React.ReactElement<react_native.ScrollViewProps>;
|
|
53
|
+
suggestEstimatedItemSize?: boolean;
|
|
54
|
+
viewabilityConfig?: _legendapp_list.ViewabilityConfig;
|
|
55
|
+
viewabilityConfigCallbackPairs?: _legendapp_list.ViewabilityConfigCallbackPairs | undefined;
|
|
56
|
+
waitForInitialLayout?: boolean;
|
|
57
|
+
} & React$1.RefAttributes<_legendapp_list.LegendListRef>) => React.ReactNode)>;
|
|
8
58
|
|
|
9
59
|
export { AnimatedLegendList };
|