@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 CHANGED
@@ -0,0 +1,5 @@
1
+ # 1.0.0
2
+
3
+ Initial release! Major changes if you're coming from a beta version:
4
+
5
+ - Item hooks like `useRecyclingState` are no longer render props, but can be imported from `@legendapp/list`
package/README.md CHANGED
@@ -1,76 +1,129 @@
1
1
  # Legend List
2
2
 
3
- Legend List aims to be a drop-in replacement for FlatList with much better performance and supporting dynamically sized items.
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
- ## Caution: Experimental
5
+ ---
6
6
 
7
- This is an early release to test and gather feedback. It's not used in production yet and needs more work to reach parity with FlatList features.
7
+ ## 🤔 Why Legend List?
8
8
 
9
- ## Features
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
- In addition to normal FlatList features:
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
- - Dynamic layouts supported. Just use the `estimatedItemSize` prop to give a close estimate so that layouts aren't too far off, and positions will adjust while rendering.
14
- - `maintainScrollAtEnd`: If true and scroll is within `maintainScrollAtEndThreshold * screen height` then changing items or heights will scroll to the bottom. This can be useful for chat interfaces.
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
- ## Documentation
22
+ Beyond standard `FlatList` capabilities:
18
23
 
19
- See the [documentation site](https://www.legendapp.com/open-source/list) for the full documentation.
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
- ## Usage
30
+ ---
22
31
 
23
- ## Install
32
+ ## 📚 Documentation
24
33
 
25
- `bun add @legendapp/list` or `npm install @legendapp/list` or `yarn add @legendapp/list`
34
+ For comprehensive documentation, guides, and the full API reference, please visit:
26
35
 
27
- ### Props
36
+ ➡️ **[Legend List Documentation Site](https://www.legendapp.com/open-source/list)**
28
37
 
29
- We suggest using all of the required props and additionally `keyExtractor` to improve performance when adding/removing items.
38
+ ---
30
39
 
31
- #### Required
40
+ ## 💻 Usage
32
41
 
33
- ```ts
34
- interface PropsRequired {
35
- data: ArrayLike<any> & T[];
36
- renderItem: (props: LegendListRenderItemInfo<T>) => ReactNode;
37
- estimatedItemSize: number;
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
- #### Optional
42
-
43
- ```ts
44
- interface PropsOptional {
45
- initialScrollOffset?: number;
46
- initialScrollIndex?: number;
47
- drawDistance?: number;
48
- recycleItems?: boolean;
49
- onEndReachedThreshold?: number | null | undefined;
50
- maintainScrollAtEnd?: boolean;
51
- maintainScrollAtEndThreshold?: number;
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
- ## How to build
102
+ ---
103
+
104
+ ## How to Build
58
105
 
59
- `npm run build` will build the package to the `dist` folder.
106
+ 1. `bun i`
107
+ 2. `bun run build` will build the package to the `dist` folder.
60
108
 
61
- ## How to run example
109
+ ## Running the Example
62
110
 
63
111
  1. `cd example`
64
- 2. `npm i`
65
- 3. `npm run bootstrap-start`
112
+ 2. `bun i`
113
+ 3. `bun run ios`
66
114
 
67
115
  ## PRs gladly accepted!
68
116
 
69
- There's not a lot of code here 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 😀.
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
- ## TODO list
119
+ ## Upcoming Roadmap
72
120
 
73
- See [Road to v1](https://github.com/LegendApp/legend-list/issues/28)
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 react from 'react';
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: _legendapp_list.LegendListProps<T> & {
6
- ref?: react.ForwardedRef<_legendapp_list.LegendListRef>;
7
- }) => react.ReactElement)>;
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 react from 'react';
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: _legendapp_list.LegendListProps<T> & {
6
- ref?: react.ForwardedRef<_legendapp_list.LegendListRef>;
7
- }) => react.ReactElement)>;
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 };