@legendapp/list 0.1.1 → 0.1.2

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/README.md CHANGED
@@ -70,3 +70,11 @@ There's not a lot of code here so hopefully it's easy to contribute. If you want
70
70
  - Other important missing features from FlatList or other lists libraries
71
71
  - Optimizations:
72
72
  - Loop over only potentially changed items when adjusting heights rather than data array
73
+
74
+ ## Community
75
+
76
+ Join us on [Discord](https://discord.gg/tuW2pAffjA) to get involved with the Legend community.
77
+
78
+ ## 👩‍⚖️ License
79
+
80
+ [MIT](LICENSE)
package/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { ComponentProps, ReactNode } from 'react';
3
- import { ScrollView } from 'react-native';
3
+ import * as react_native from 'react-native';
4
+ import { ScrollView, StyleProp, ViewStyle } from 'react-native';
4
5
 
5
6
  type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset'> & {
6
7
  data: ArrayLike<any> & T[];
@@ -19,6 +20,10 @@ type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset
19
20
  keyExtractor?: (item: T, index: number) => string;
20
21
  renderItem?: (props: LegendListRenderItemInfo<T>) => ReactNode;
21
22
  onViewableRangeChanged?: (range: ViewableRange<T>) => void;
23
+ ListHeaderComponent?: ReactNode;
24
+ ListHeaderComponentStyle?: StyleProp<ViewStyle> | undefined;
25
+ ListFooterComponent?: ReactNode;
26
+ ListFooterComponentStyle?: StyleProp<ViewStyle> | undefined;
22
27
  };
23
28
  interface ViewableRange<T> {
24
29
  startBuffered: number;
@@ -32,6 +37,27 @@ interface LegendListRenderItemInfo<ItemT> {
32
37
  index: number;
33
38
  }
34
39
 
35
- declare function LegendList<T>(props: LegendListProps<T>): React.JSX.Element;
40
+ declare const LegendList: React.ForwardRefExoticComponent<Omit<react_native.ScrollViewProps, "contentOffset"> & {
41
+ data: ArrayLike<any> & unknown[];
42
+ initialScrollOffset?: number;
43
+ initialScrollIndex?: number;
44
+ drawDistance?: number;
45
+ initialContainers?: number;
46
+ recycleItems?: boolean;
47
+ onEndReachedThreshold?: number | null | undefined;
48
+ autoScrollToBottom?: boolean;
49
+ autoScrollToBottomThreshold?: number;
50
+ estimatedItemLength: (index: number) => number;
51
+ onEndReached?: ((info: {
52
+ distanceFromEnd: number;
53
+ }) => void) | null | undefined;
54
+ keyExtractor?: ((item: unknown, index: number) => string) | undefined;
55
+ renderItem?: ((props: LegendListRenderItemInfo<unknown>) => React.ReactNode) | undefined;
56
+ onViewableRangeChanged?: ((range: ViewableRange<unknown>) => void) | undefined;
57
+ ListHeaderComponent?: React.ReactNode;
58
+ ListHeaderComponentStyle?: react_native.StyleProp<react_native.ViewStyle> | undefined;
59
+ ListFooterComponent?: React.ReactNode;
60
+ ListFooterComponentStyle?: react_native.StyleProp<react_native.ViewStyle> | undefined;
61
+ } & React.RefAttributes<ScrollView>>;
36
62
 
37
63
  export { LegendList, type LegendListProps, type LegendListRenderItemInfo, type ViewableRange };
package/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { ComponentProps, ReactNode } from 'react';
3
- import { ScrollView } from 'react-native';
3
+ import * as react_native from 'react-native';
4
+ import { ScrollView, StyleProp, ViewStyle } from 'react-native';
4
5
 
5
6
  type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset'> & {
6
7
  data: ArrayLike<any> & T[];
@@ -19,6 +20,10 @@ type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset
19
20
  keyExtractor?: (item: T, index: number) => string;
20
21
  renderItem?: (props: LegendListRenderItemInfo<T>) => ReactNode;
21
22
  onViewableRangeChanged?: (range: ViewableRange<T>) => void;
23
+ ListHeaderComponent?: ReactNode;
24
+ ListHeaderComponentStyle?: StyleProp<ViewStyle> | undefined;
25
+ ListFooterComponent?: ReactNode;
26
+ ListFooterComponentStyle?: StyleProp<ViewStyle> | undefined;
22
27
  };
23
28
  interface ViewableRange<T> {
24
29
  startBuffered: number;
@@ -32,6 +37,27 @@ interface LegendListRenderItemInfo<ItemT> {
32
37
  index: number;
33
38
  }
34
39
 
35
- declare function LegendList<T>(props: LegendListProps<T>): React.JSX.Element;
40
+ declare const LegendList: React.ForwardRefExoticComponent<Omit<react_native.ScrollViewProps, "contentOffset"> & {
41
+ data: ArrayLike<any> & unknown[];
42
+ initialScrollOffset?: number;
43
+ initialScrollIndex?: number;
44
+ drawDistance?: number;
45
+ initialContainers?: number;
46
+ recycleItems?: boolean;
47
+ onEndReachedThreshold?: number | null | undefined;
48
+ autoScrollToBottom?: boolean;
49
+ autoScrollToBottomThreshold?: number;
50
+ estimatedItemLength: (index: number) => number;
51
+ onEndReached?: ((info: {
52
+ distanceFromEnd: number;
53
+ }) => void) | null | undefined;
54
+ keyExtractor?: ((item: unknown, index: number) => string) | undefined;
55
+ renderItem?: ((props: LegendListRenderItemInfo<unknown>) => React.ReactNode) | undefined;
56
+ onViewableRangeChanged?: ((range: ViewableRange<unknown>) => void) | undefined;
57
+ ListHeaderComponent?: React.ReactNode;
58
+ ListHeaderComponentStyle?: react_native.StyleProp<react_native.ViewStyle> | undefined;
59
+ ListFooterComponent?: React.ReactNode;
60
+ ListFooterComponentStyle?: react_native.StyleProp<react_native.ViewStyle> | undefined;
61
+ } & React.RefAttributes<ScrollView>>;
36
62
 
37
63
  export { LegendList, type LegendListProps, type LegendListRenderItemInfo, type ViewableRange };
package/index.js CHANGED
@@ -71,7 +71,7 @@ var Container = ({
71
71
  enableReactNativeComponents.enableReactNativeComponents();
72
72
  var DEFAULT_SCROLL_BUFFER = 0;
73
73
  var POSITION_OUT_OF_VIEW = -1e4;
74
- function LegendList(props) {
74
+ var LegendList = React2.forwardRef((props, forwardedRef) => {
75
75
  const {
76
76
  data,
77
77
  initialScrollIndex,
@@ -81,7 +81,7 @@ function LegendList(props) {
81
81
  contentContainerStyle,
82
82
  initialContainers,
83
83
  drawDistance,
84
- recycleItems = false,
84
+ recycleItems = true,
85
85
  onEndReachedThreshold,
86
86
  autoScrollToBottom = false,
87
87
  autoScrollToBottomThreshold = 0.1,
@@ -90,11 +90,14 @@ function LegendList(props) {
90
90
  estimatedItemLength,
91
91
  onEndReached,
92
92
  onViewableRangeChanged,
93
- children,
93
+ ListHeaderComponent,
94
+ ListHeaderComponentStyle,
95
+ ListFooterComponent,
96
+ ListFooterComponentStyle,
94
97
  ...rest
95
98
  } = props;
96
- const childrenArray = children && !data ? React2__namespace.Children.toArray(children) : void 0;
97
- const refScroller = React2.useRef(null);
99
+ const internalRef = React2.useRef(null);
100
+ const refScroller = forwardedRef || internalRef;
98
101
  const containers$ = react.useObservable(() => []);
99
102
  const visibleRange$ = react.useObservable(() => ({
100
103
  start: 0,
@@ -111,7 +114,7 @@ function LegendList(props) {
111
114
  if (!data2) {
112
115
  return "";
113
116
  }
114
- const ret = index < (data2 || childrenArray).length ? data2 ? keyExtractor ? keyExtractor(data2[index], index) : index : index : null;
117
+ const ret = index < data2.length ? keyExtractor ? keyExtractor(data2[index], index) : index : null;
115
118
  return ret + "";
116
119
  };
117
120
  if (!refPositions.current) {
@@ -125,13 +128,11 @@ function LegendList(props) {
125
128
  isAtBottom: false,
126
129
  data,
127
130
  idsInFirstRender: void 0,
128
- hasScrolled: false,
129
- childrenArray
131
+ hasScrolled: false
130
132
  };
131
- refPositions.current.idsInFirstRender = new Set((data || childrenArray).map((_, i) => getId(i)));
133
+ refPositions.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
132
134
  }
133
135
  refPositions.current.data = data;
134
- refPositions.current.childrenArray = childrenArray;
135
136
  const SCREEN_LENGTH = reactNative.Dimensions.get("window")[horizontal ? "width" : "height"];
136
137
  const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : initialScrollIndex ? initialScrollIndex * estimatedItemLength(initialScrollIndex) : void 0;
137
138
  const allocateContainers = React2.useCallback(() => {
@@ -148,15 +149,10 @@ function LegendList(props) {
148
149
  }, []);
149
150
  const getRenderedItem = React2.useCallback(
150
151
  (index) => {
151
- var _a, _b;
152
+ var _a;
152
153
  const data2 = (_a = refPositions.current) == null ? void 0 : _a.data;
153
154
  if (!data2) {
154
- const childrenArray2 = (_b = refPositions.current) == null ? void 0 : _b.childrenArray;
155
- if (childrenArray2) {
156
- return childrenArray2[index];
157
- } else {
158
- return null;
159
- }
155
+ return null;
160
156
  }
161
157
  const renderedItem = renderItem == null ? void 0 : renderItem({
162
158
  item: data2[index],
@@ -375,6 +371,7 @@ function LegendList(props) {
375
371
  ...rest,
376
372
  ref: refScroller
377
373
  },
374
+ ListHeaderComponent && /* @__PURE__ */ React2__namespace.createElement(react.Reactive.View, { $style: ListHeaderComponentStyle }, ListHeaderComponent),
378
375
  /* @__PURE__ */ React2__namespace.createElement(
379
376
  react.Reactive.View,
380
377
  {
@@ -395,8 +392,9 @@ function LegendList(props) {
395
392
  onLayout: updateItemLength
396
393
  }
397
394
  ))
398
- )
395
+ ),
396
+ ListFooterComponent && /* @__PURE__ */ React2__namespace.createElement(react.Reactive.View, { $style: ListFooterComponentStyle }, ListFooterComponent)
399
397
  );
400
- }
398
+ });
401
399
 
402
400
  exports.LegendList = LegendList;
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React2 from 'react';
2
- import { useRef, useCallback, useMemo, useEffect } from 'react';
2
+ import { forwardRef, useRef, useCallback, useMemo, useEffect } from 'react';
3
3
  import { beginBatch, endBatch } from '@legendapp/state';
4
4
  import { enableReactNativeComponents } from '@legendapp/state/config/enableReactNativeComponents';
5
5
  import { useObservable, use$, Reactive } from '@legendapp/state/react';
@@ -50,7 +50,7 @@ var Container = ({
50
50
  enableReactNativeComponents();
51
51
  var DEFAULT_SCROLL_BUFFER = 0;
52
52
  var POSITION_OUT_OF_VIEW = -1e4;
53
- function LegendList(props) {
53
+ var LegendList = forwardRef((props, forwardedRef) => {
54
54
  const {
55
55
  data,
56
56
  initialScrollIndex,
@@ -60,7 +60,7 @@ function LegendList(props) {
60
60
  contentContainerStyle,
61
61
  initialContainers,
62
62
  drawDistance,
63
- recycleItems = false,
63
+ recycleItems = true,
64
64
  onEndReachedThreshold,
65
65
  autoScrollToBottom = false,
66
66
  autoScrollToBottomThreshold = 0.1,
@@ -69,11 +69,14 @@ function LegendList(props) {
69
69
  estimatedItemLength,
70
70
  onEndReached,
71
71
  onViewableRangeChanged,
72
- children,
72
+ ListHeaderComponent,
73
+ ListHeaderComponentStyle,
74
+ ListFooterComponent,
75
+ ListFooterComponentStyle,
73
76
  ...rest
74
77
  } = props;
75
- const childrenArray = children && !data ? React2.Children.toArray(children) : void 0;
76
- const refScroller = useRef(null);
78
+ const internalRef = useRef(null);
79
+ const refScroller = forwardedRef || internalRef;
77
80
  const containers$ = useObservable(() => []);
78
81
  const visibleRange$ = useObservable(() => ({
79
82
  start: 0,
@@ -90,7 +93,7 @@ function LegendList(props) {
90
93
  if (!data2) {
91
94
  return "";
92
95
  }
93
- const ret = index < (data2 || childrenArray).length ? data2 ? keyExtractor ? keyExtractor(data2[index], index) : index : index : null;
96
+ const ret = index < data2.length ? keyExtractor ? keyExtractor(data2[index], index) : index : null;
94
97
  return ret + "";
95
98
  };
96
99
  if (!refPositions.current) {
@@ -104,13 +107,11 @@ function LegendList(props) {
104
107
  isAtBottom: false,
105
108
  data,
106
109
  idsInFirstRender: void 0,
107
- hasScrolled: false,
108
- childrenArray
110
+ hasScrolled: false
109
111
  };
110
- refPositions.current.idsInFirstRender = new Set((data || childrenArray).map((_, i) => getId(i)));
112
+ refPositions.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
111
113
  }
112
114
  refPositions.current.data = data;
113
- refPositions.current.childrenArray = childrenArray;
114
115
  const SCREEN_LENGTH = Dimensions.get("window")[horizontal ? "width" : "height"];
115
116
  const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : initialScrollIndex ? initialScrollIndex * estimatedItemLength(initialScrollIndex) : void 0;
116
117
  const allocateContainers = useCallback(() => {
@@ -127,15 +128,10 @@ function LegendList(props) {
127
128
  }, []);
128
129
  const getRenderedItem = useCallback(
129
130
  (index) => {
130
- var _a, _b;
131
+ var _a;
131
132
  const data2 = (_a = refPositions.current) == null ? void 0 : _a.data;
132
133
  if (!data2) {
133
- const childrenArray2 = (_b = refPositions.current) == null ? void 0 : _b.childrenArray;
134
- if (childrenArray2) {
135
- return childrenArray2[index];
136
- } else {
137
- return null;
138
- }
134
+ return null;
139
135
  }
140
136
  const renderedItem = renderItem == null ? void 0 : renderItem({
141
137
  item: data2[index],
@@ -354,6 +350,7 @@ function LegendList(props) {
354
350
  ...rest,
355
351
  ref: refScroller
356
352
  },
353
+ ListHeaderComponent && /* @__PURE__ */ React2.createElement(Reactive.View, { $style: ListHeaderComponentStyle }, ListHeaderComponent),
357
354
  /* @__PURE__ */ React2.createElement(
358
355
  Reactive.View,
359
356
  {
@@ -374,8 +371,9 @@ function LegendList(props) {
374
371
  onLayout: updateItemLength
375
372
  }
376
373
  ))
377
- )
374
+ ),
375
+ ListFooterComponent && /* @__PURE__ */ React2.createElement(Reactive.View, { $style: ListFooterComponentStyle }, ListFooterComponent)
378
376
  );
379
- }
377
+ });
380
378
 
381
379
  export { LegendList };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "legend-list",
5
5
  "sideEffects": false,
6
6
  "private": false,