@legendapp/list 0.1.2 → 0.2.1

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 CHANGED
@@ -1,6 +1,4 @@
1
- import * as React from 'react';
2
- import { ComponentProps, ReactNode } from 'react';
3
- import * as react_native from 'react-native';
1
+ import { ComponentProps, ReactNode, ForwardedRef, ReactElement } from 'react';
4
2
  import { ScrollView, StyleProp, ViewStyle } from 'react-native';
5
3
 
6
4
  type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset'> & {
@@ -13,6 +11,7 @@ type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset
13
11
  onEndReachedThreshold?: number | null | undefined;
14
12
  autoScrollToBottom?: boolean;
15
13
  autoScrollToBottomThreshold?: number;
14
+ startAtBottom?: boolean;
16
15
  estimatedItemLength: (index: number) => number;
17
16
  onEndReached?: ((info: {
18
17
  distanceFromEnd: number;
@@ -24,6 +23,7 @@ type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset
24
23
  ListHeaderComponentStyle?: StyleProp<ViewStyle> | undefined;
25
24
  ListFooterComponent?: ReactNode;
26
25
  ListFooterComponentStyle?: StyleProp<ViewStyle> | undefined;
26
+ ItemSeparatorComponent?: ReactNode;
27
27
  };
28
28
  interface ViewableRange<T> {
29
29
  startBuffered: number;
@@ -37,27 +37,8 @@ interface LegendListRenderItemInfo<ItemT> {
37
37
  index: number;
38
38
  }
39
39
 
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>>;
40
+ declare const LegendList: <T>(props: LegendListProps<T> & {
41
+ ref?: ForwardedRef<ScrollView>;
42
+ }) => ReactElement;
62
43
 
63
44
  export { LegendList, type LegendListProps, type LegendListRenderItemInfo, type ViewableRange };
package/index.d.ts CHANGED
@@ -1,6 +1,4 @@
1
- import * as React from 'react';
2
- import { ComponentProps, ReactNode } from 'react';
3
- import * as react_native from 'react-native';
1
+ import { ComponentProps, ReactNode, ForwardedRef, ReactElement } from 'react';
4
2
  import { ScrollView, StyleProp, ViewStyle } from 'react-native';
5
3
 
6
4
  type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset'> & {
@@ -13,6 +11,7 @@ type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset
13
11
  onEndReachedThreshold?: number | null | undefined;
14
12
  autoScrollToBottom?: boolean;
15
13
  autoScrollToBottomThreshold?: number;
14
+ startAtBottom?: boolean;
16
15
  estimatedItemLength: (index: number) => number;
17
16
  onEndReached?: ((info: {
18
17
  distanceFromEnd: number;
@@ -24,6 +23,7 @@ type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset
24
23
  ListHeaderComponentStyle?: StyleProp<ViewStyle> | undefined;
25
24
  ListFooterComponent?: ReactNode;
26
25
  ListFooterComponentStyle?: StyleProp<ViewStyle> | undefined;
26
+ ItemSeparatorComponent?: ReactNode;
27
27
  };
28
28
  interface ViewableRange<T> {
29
29
  startBuffered: number;
@@ -37,27 +37,8 @@ interface LegendListRenderItemInfo<ItemT> {
37
37
  index: number;
38
38
  }
39
39
 
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>>;
40
+ declare const LegendList: <T>(props: LegendListProps<T> & {
41
+ ref?: ForwardedRef<ScrollView>;
42
+ }) => ReactElement;
62
43
 
63
44
  export { LegendList, type LegendListProps, type LegendListRenderItemInfo, type ViewableRange };
package/index.js CHANGED
@@ -33,13 +33,15 @@ var Container = ({
33
33
  recycleItems,
34
34
  listProps,
35
35
  getRenderedItem,
36
- onLayout
36
+ onLayout,
37
+ ItemSeparatorComponent
37
38
  }) => {
38
39
  const { horizontal } = listProps;
39
40
  const { id } = $container.peek();
40
41
  const itemIndex = react.use$($container.itemIndex);
41
42
  const key = recycleItems ? void 0 : itemIndex;
42
43
  const createStyle = () => horizontal ? {
44
+ flexDirection: "row",
43
45
  position: "absolute",
44
46
  top: 0,
45
47
  bottom: 0,
@@ -63,7 +65,8 @@ var Container = ({
63
65
  onLayout(index, length);
64
66
  }
65
67
  },
66
- /* @__PURE__ */ React2__namespace.createElement(reactNative.View, { key }, getRenderedItem(itemIndex))
68
+ /* @__PURE__ */ React2__namespace.createElement(reactNative.View, { key }, getRenderedItem(itemIndex)),
69
+ ItemSeparatorComponent && itemIndex !== listProps.data.length - 1 && /* @__PURE__ */ React2__namespace.createElement(react.Reactive.View, null, ItemSeparatorComponent)
67
70
  );
68
71
  };
69
72
 
@@ -71,7 +74,7 @@ var Container = ({
71
74
  enableReactNativeComponents.enableReactNativeComponents();
72
75
  var DEFAULT_SCROLL_BUFFER = 0;
73
76
  var POSITION_OUT_OF_VIEW = -1e4;
74
- var LegendList = React2.forwardRef((props, forwardedRef) => {
77
+ var LegendList = React2.forwardRef(function LegendList2(props, forwardedRef) {
75
78
  const {
76
79
  data,
77
80
  initialScrollIndex,
@@ -85,6 +88,7 @@ var LegendList = React2.forwardRef((props, forwardedRef) => {
85
88
  onEndReachedThreshold,
86
89
  autoScrollToBottom = false,
87
90
  autoScrollToBottomThreshold = 0.1,
91
+ startAtBottom = false,
88
92
  keyExtractor,
89
93
  renderItem,
90
94
  estimatedItemLength,
@@ -94,11 +98,13 @@ var LegendList = React2.forwardRef((props, forwardedRef) => {
94
98
  ListHeaderComponentStyle,
95
99
  ListFooterComponent,
96
100
  ListFooterComponentStyle,
101
+ ItemSeparatorComponent,
97
102
  ...rest
98
103
  } = props;
99
104
  const internalRef = React2.useRef(null);
100
105
  const refScroller = forwardedRef || internalRef;
101
106
  const containers$ = react.useObservable(() => []);
107
+ const paddingTop$ = react.useObservable(0);
102
108
  const visibleRange$ = react.useObservable(() => ({
103
109
  start: 0,
104
110
  end: 0,
@@ -128,15 +134,24 @@ var LegendList = React2.forwardRef((props, forwardedRef) => {
128
134
  isAtBottom: false,
129
135
  data,
130
136
  idsInFirstRender: void 0,
131
- hasScrolled: false
137
+ hasScrolled: false,
138
+ scrollLength: reactNative.Dimensions.get("window")[horizontal ? "width" : "height"]
132
139
  };
133
140
  refPositions.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
134
141
  }
135
142
  refPositions.current.data = data;
136
- const SCREEN_LENGTH = reactNative.Dimensions.get("window")[horizontal ? "width" : "height"];
137
143
  const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : initialScrollIndex ? initialScrollIndex * estimatedItemLength(initialScrollIndex) : void 0;
144
+ const setTotalLength = (length) => {
145
+ visibleRange$.totalLength.set(length);
146
+ const screenLength = refPositions.current.scrollLength;
147
+ if (startAtBottom) {
148
+ const listPaddingTop = ((style == null ? void 0 : style.paddingTop) || 0) + ((contentContainerStyle == null ? void 0 : contentContainerStyle.paddingTop) || 0);
149
+ paddingTop$.set(Math.max(0, screenLength - length - listPaddingTop));
150
+ }
151
+ };
138
152
  const allocateContainers = React2.useCallback(() => {
139
- const numContainers = initialContainers || Math.ceil((SCREEN_LENGTH + scrollBuffer * 2) / estimatedItemLength(0)) + 4;
153
+ const scrollLength = refPositions.current.scrollLength;
154
+ const numContainers = initialContainers || Math.ceil((scrollLength + scrollBuffer * 2) / estimatedItemLength(0)) + 4;
140
155
  const containers2 = [];
141
156
  for (let i = 0; i < numContainers; i++) {
142
157
  containers2.push({
@@ -164,7 +179,7 @@ var LegendList = React2.forwardRef((props, forwardedRef) => {
164
179
  );
165
180
  const calculateItemsInView = React2.useCallback(() => {
166
181
  var _a, _b;
167
- const data2 = refPositions.current.data;
182
+ const { data: data2, scrollLength } = refPositions.current;
168
183
  if (!data2) {
169
184
  return;
170
185
  }
@@ -190,10 +205,10 @@ var LegendList = React2.forwardRef((props, forwardedRef) => {
190
205
  startBuffered = i;
191
206
  }
192
207
  if (startNoBuffer !== null) {
193
- if (top <= scroll + SCREEN_LENGTH) {
208
+ if (top <= scroll + scrollLength) {
194
209
  endNoBuffer = i;
195
210
  }
196
- if (top <= scroll + SCREEN_LENGTH + scrollBuffer) {
211
+ if (top <= scroll + scrollLength + scrollBuffer) {
197
212
  endBuffered = i;
198
213
  } else {
199
214
  break;
@@ -282,12 +297,34 @@ var LegendList = React2.forwardRef((props, forwardedRef) => {
282
297
  const id = getId(i);
283
298
  totalLength += (_b = lengths.get(id)) != null ? _b : estimatedItemLength(i);
284
299
  }
285
- visibleRange$.totalLength.set(totalLength);
300
+ setTotalLength(totalLength);
286
301
  }, []);
302
+ const checkAtBottom = () => {
303
+ var _a;
304
+ const scrollLength = refPositions.current.scrollLength;
305
+ const newScroll = visibleRange$.scroll.peek();
306
+ const distanceFromEnd = visibleRange$.totalLength.peek() - newScroll - scrollLength;
307
+ if (refPositions.current) {
308
+ refPositions.current.isAtBottom = distanceFromEnd < scrollLength * autoScrollToBottomThreshold;
309
+ }
310
+ if (onEndReached && !((_a = refPositions.current) == null ? void 0 : _a.isEndReached)) {
311
+ if (distanceFromEnd < (onEndReachedThreshold || 0.5) * scrollLength) {
312
+ if (refPositions.current) {
313
+ refPositions.current.isEndReached = true;
314
+ }
315
+ onEndReached({ distanceFromEnd });
316
+ }
317
+ }
318
+ };
287
319
  React2.useMemo(() => {
320
+ var _a;
288
321
  if (refPositions.current) {
289
- refPositions.current.isEndReached = false;
322
+ if (!((_a = refPositions.current) == null ? void 0 : _a.isAtBottom)) {
323
+ refPositions.current.isEndReached = false;
324
+ }
290
325
  }
326
+ calculateItemsInView();
327
+ checkAtBottom();
291
328
  }, [data]);
292
329
  const containers = react.use$(containers$, { shallow: true });
293
330
  const updateItemLength = React2.useCallback((index, length) => {
@@ -303,7 +340,7 @@ var LegendList = React2.forwardRef((props, forwardedRef) => {
303
340
  if (!prevLength || prevLength !== length) {
304
341
  state.beginBatch();
305
342
  lengths.set(id, length);
306
- visibleRange$.totalLength.set((prevTotal) => prevTotal + (length - prevLength));
343
+ setTotalLength(visibleRange$.totalLength.peek() + (length - prevLength));
307
344
  if (((_d = refPositions.current) == null ? void 0 : _d.isAtBottom) && autoScrollToBottom) {
308
345
  requestAnimationFrame(() => {
309
346
  var _a2;
@@ -319,25 +356,16 @@ var LegendList = React2.forwardRef((props, forwardedRef) => {
319
356
  }
320
357
  }, []);
321
358
  const handleScrollDebounced = React2.useCallback(() => {
322
- var _a;
323
- const newScroll = visibleRange$.scroll.peek();
324
359
  calculateItemsInView();
325
- const distanceFromEnd = visibleRange$.totalLength.peek() - newScroll - SCREEN_LENGTH;
326
- if (refPositions.current) {
327
- refPositions.current.isAtBottom = distanceFromEnd < SCREEN_LENGTH * autoScrollToBottomThreshold;
328
- }
329
- if (onEndReached && !((_a = refPositions.current) == null ? void 0 : _a.isEndReached)) {
330
- if (distanceFromEnd < (onEndReachedThreshold || 0.5) * SCREEN_LENGTH) {
331
- if (refPositions.current) {
332
- refPositions.current.isEndReached = true;
333
- }
334
- onEndReached({ distanceFromEnd });
335
- }
336
- }
360
+ checkAtBottom();
337
361
  if (refPositions.current) {
338
362
  refPositions.current.animFrame = null;
339
363
  }
340
364
  }, []);
365
+ const onLayout = (event) => {
366
+ const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
367
+ refPositions.current.scrollLength = scrollLength;
368
+ };
341
369
  const handleScroll = React2.useCallback((event) => {
342
370
  refPositions.current.hasScrolled = true;
343
371
  const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
@@ -365,12 +393,14 @@ var LegendList = React2.forwardRef((props, forwardedRef) => {
365
393
  } : {}
366
394
  ],
367
395
  onScroll: handleScroll,
396
+ onLayout,
368
397
  scrollEventThrottle: 32,
369
398
  horizontal,
370
399
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
371
400
  ...rest,
372
401
  ref: refScroller
373
402
  },
403
+ startAtBottom && /* @__PURE__ */ React2__namespace.createElement(react.Reactive.View, { $style: () => ({ height: paddingTop$.get() }) }),
374
404
  ListHeaderComponent && /* @__PURE__ */ React2__namespace.createElement(react.Reactive.View, { $style: ListHeaderComponentStyle }, ListHeaderComponent),
375
405
  /* @__PURE__ */ React2__namespace.createElement(
376
406
  react.Reactive.View,
@@ -389,7 +419,8 @@ var LegendList = React2.forwardRef((props, forwardedRef) => {
389
419
  $container: containers$[i],
390
420
  listProps: props,
391
421
  getRenderedItem,
392
- onLayout: updateItemLength
422
+ onLayout: updateItemLength,
423
+ ItemSeparatorComponent
393
424
  }
394
425
  ))
395
426
  ),
package/index.mjs CHANGED
@@ -12,13 +12,15 @@ var Container = ({
12
12
  recycleItems,
13
13
  listProps,
14
14
  getRenderedItem,
15
- onLayout
15
+ onLayout,
16
+ ItemSeparatorComponent
16
17
  }) => {
17
18
  const { horizontal } = listProps;
18
19
  const { id } = $container.peek();
19
20
  const itemIndex = use$($container.itemIndex);
20
21
  const key = recycleItems ? void 0 : itemIndex;
21
22
  const createStyle = () => horizontal ? {
23
+ flexDirection: "row",
22
24
  position: "absolute",
23
25
  top: 0,
24
26
  bottom: 0,
@@ -42,7 +44,8 @@ var Container = ({
42
44
  onLayout(index, length);
43
45
  }
44
46
  },
45
- /* @__PURE__ */ React2.createElement(View, { key }, getRenderedItem(itemIndex))
47
+ /* @__PURE__ */ React2.createElement(View, { key }, getRenderedItem(itemIndex)),
48
+ ItemSeparatorComponent && itemIndex !== listProps.data.length - 1 && /* @__PURE__ */ React2.createElement(Reactive.View, null, ItemSeparatorComponent)
46
49
  );
47
50
  };
48
51
 
@@ -50,7 +53,7 @@ var Container = ({
50
53
  enableReactNativeComponents();
51
54
  var DEFAULT_SCROLL_BUFFER = 0;
52
55
  var POSITION_OUT_OF_VIEW = -1e4;
53
- var LegendList = forwardRef((props, forwardedRef) => {
56
+ var LegendList = forwardRef(function LegendList2(props, forwardedRef) {
54
57
  const {
55
58
  data,
56
59
  initialScrollIndex,
@@ -64,6 +67,7 @@ var LegendList = forwardRef((props, forwardedRef) => {
64
67
  onEndReachedThreshold,
65
68
  autoScrollToBottom = false,
66
69
  autoScrollToBottomThreshold = 0.1,
70
+ startAtBottom = false,
67
71
  keyExtractor,
68
72
  renderItem,
69
73
  estimatedItemLength,
@@ -73,11 +77,13 @@ var LegendList = forwardRef((props, forwardedRef) => {
73
77
  ListHeaderComponentStyle,
74
78
  ListFooterComponent,
75
79
  ListFooterComponentStyle,
80
+ ItemSeparatorComponent,
76
81
  ...rest
77
82
  } = props;
78
83
  const internalRef = useRef(null);
79
84
  const refScroller = forwardedRef || internalRef;
80
85
  const containers$ = useObservable(() => []);
86
+ const paddingTop$ = useObservable(0);
81
87
  const visibleRange$ = useObservable(() => ({
82
88
  start: 0,
83
89
  end: 0,
@@ -107,15 +113,24 @@ var LegendList = forwardRef((props, forwardedRef) => {
107
113
  isAtBottom: false,
108
114
  data,
109
115
  idsInFirstRender: void 0,
110
- hasScrolled: false
116
+ hasScrolled: false,
117
+ scrollLength: Dimensions.get("window")[horizontal ? "width" : "height"]
111
118
  };
112
119
  refPositions.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
113
120
  }
114
121
  refPositions.current.data = data;
115
- const SCREEN_LENGTH = Dimensions.get("window")[horizontal ? "width" : "height"];
116
122
  const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : initialScrollIndex ? initialScrollIndex * estimatedItemLength(initialScrollIndex) : void 0;
123
+ const setTotalLength = (length) => {
124
+ visibleRange$.totalLength.set(length);
125
+ const screenLength = refPositions.current.scrollLength;
126
+ if (startAtBottom) {
127
+ const listPaddingTop = ((style == null ? void 0 : style.paddingTop) || 0) + ((contentContainerStyle == null ? void 0 : contentContainerStyle.paddingTop) || 0);
128
+ paddingTop$.set(Math.max(0, screenLength - length - listPaddingTop));
129
+ }
130
+ };
117
131
  const allocateContainers = useCallback(() => {
118
- const numContainers = initialContainers || Math.ceil((SCREEN_LENGTH + scrollBuffer * 2) / estimatedItemLength(0)) + 4;
132
+ const scrollLength = refPositions.current.scrollLength;
133
+ const numContainers = initialContainers || Math.ceil((scrollLength + scrollBuffer * 2) / estimatedItemLength(0)) + 4;
119
134
  const containers2 = [];
120
135
  for (let i = 0; i < numContainers; i++) {
121
136
  containers2.push({
@@ -143,7 +158,7 @@ var LegendList = forwardRef((props, forwardedRef) => {
143
158
  );
144
159
  const calculateItemsInView = useCallback(() => {
145
160
  var _a, _b;
146
- const data2 = refPositions.current.data;
161
+ const { data: data2, scrollLength } = refPositions.current;
147
162
  if (!data2) {
148
163
  return;
149
164
  }
@@ -169,10 +184,10 @@ var LegendList = forwardRef((props, forwardedRef) => {
169
184
  startBuffered = i;
170
185
  }
171
186
  if (startNoBuffer !== null) {
172
- if (top <= scroll + SCREEN_LENGTH) {
187
+ if (top <= scroll + scrollLength) {
173
188
  endNoBuffer = i;
174
189
  }
175
- if (top <= scroll + SCREEN_LENGTH + scrollBuffer) {
190
+ if (top <= scroll + scrollLength + scrollBuffer) {
176
191
  endBuffered = i;
177
192
  } else {
178
193
  break;
@@ -261,12 +276,34 @@ var LegendList = forwardRef((props, forwardedRef) => {
261
276
  const id = getId(i);
262
277
  totalLength += (_b = lengths.get(id)) != null ? _b : estimatedItemLength(i);
263
278
  }
264
- visibleRange$.totalLength.set(totalLength);
279
+ setTotalLength(totalLength);
265
280
  }, []);
281
+ const checkAtBottom = () => {
282
+ var _a;
283
+ const scrollLength = refPositions.current.scrollLength;
284
+ const newScroll = visibleRange$.scroll.peek();
285
+ const distanceFromEnd = visibleRange$.totalLength.peek() - newScroll - scrollLength;
286
+ if (refPositions.current) {
287
+ refPositions.current.isAtBottom = distanceFromEnd < scrollLength * autoScrollToBottomThreshold;
288
+ }
289
+ if (onEndReached && !((_a = refPositions.current) == null ? void 0 : _a.isEndReached)) {
290
+ if (distanceFromEnd < (onEndReachedThreshold || 0.5) * scrollLength) {
291
+ if (refPositions.current) {
292
+ refPositions.current.isEndReached = true;
293
+ }
294
+ onEndReached({ distanceFromEnd });
295
+ }
296
+ }
297
+ };
266
298
  useMemo(() => {
299
+ var _a;
267
300
  if (refPositions.current) {
268
- refPositions.current.isEndReached = false;
301
+ if (!((_a = refPositions.current) == null ? void 0 : _a.isAtBottom)) {
302
+ refPositions.current.isEndReached = false;
303
+ }
269
304
  }
305
+ calculateItemsInView();
306
+ checkAtBottom();
270
307
  }, [data]);
271
308
  const containers = use$(containers$, { shallow: true });
272
309
  const updateItemLength = useCallback((index, length) => {
@@ -282,7 +319,7 @@ var LegendList = forwardRef((props, forwardedRef) => {
282
319
  if (!prevLength || prevLength !== length) {
283
320
  beginBatch();
284
321
  lengths.set(id, length);
285
- visibleRange$.totalLength.set((prevTotal) => prevTotal + (length - prevLength));
322
+ setTotalLength(visibleRange$.totalLength.peek() + (length - prevLength));
286
323
  if (((_d = refPositions.current) == null ? void 0 : _d.isAtBottom) && autoScrollToBottom) {
287
324
  requestAnimationFrame(() => {
288
325
  var _a2;
@@ -298,25 +335,16 @@ var LegendList = forwardRef((props, forwardedRef) => {
298
335
  }
299
336
  }, []);
300
337
  const handleScrollDebounced = useCallback(() => {
301
- var _a;
302
- const newScroll = visibleRange$.scroll.peek();
303
338
  calculateItemsInView();
304
- const distanceFromEnd = visibleRange$.totalLength.peek() - newScroll - SCREEN_LENGTH;
305
- if (refPositions.current) {
306
- refPositions.current.isAtBottom = distanceFromEnd < SCREEN_LENGTH * autoScrollToBottomThreshold;
307
- }
308
- if (onEndReached && !((_a = refPositions.current) == null ? void 0 : _a.isEndReached)) {
309
- if (distanceFromEnd < (onEndReachedThreshold || 0.5) * SCREEN_LENGTH) {
310
- if (refPositions.current) {
311
- refPositions.current.isEndReached = true;
312
- }
313
- onEndReached({ distanceFromEnd });
314
- }
315
- }
339
+ checkAtBottom();
316
340
  if (refPositions.current) {
317
341
  refPositions.current.animFrame = null;
318
342
  }
319
343
  }, []);
344
+ const onLayout = (event) => {
345
+ const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
346
+ refPositions.current.scrollLength = scrollLength;
347
+ };
320
348
  const handleScroll = useCallback((event) => {
321
349
  refPositions.current.hasScrolled = true;
322
350
  const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
@@ -344,12 +372,14 @@ var LegendList = forwardRef((props, forwardedRef) => {
344
372
  } : {}
345
373
  ],
346
374
  onScroll: handleScroll,
375
+ onLayout,
347
376
  scrollEventThrottle: 32,
348
377
  horizontal,
349
378
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
350
379
  ...rest,
351
380
  ref: refScroller
352
381
  },
382
+ startAtBottom && /* @__PURE__ */ React2.createElement(Reactive.View, { $style: () => ({ height: paddingTop$.get() }) }),
353
383
  ListHeaderComponent && /* @__PURE__ */ React2.createElement(Reactive.View, { $style: ListHeaderComponentStyle }, ListHeaderComponent),
354
384
  /* @__PURE__ */ React2.createElement(
355
385
  Reactive.View,
@@ -368,7 +398,8 @@ var LegendList = forwardRef((props, forwardedRef) => {
368
398
  $container: containers$[i],
369
399
  listProps: props,
370
400
  getRenderedItem,
371
- onLayout: updateItemLength
401
+ onLayout: updateItemLength,
402
+ ItemSeparatorComponent
372
403
  }
373
404
  ))
374
405
  ),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "description": "legend-list",
5
5
  "sideEffects": false,
6
6
  "private": false,