@legendapp/list 0.5.7 → 0.5.9

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
@@ -77,6 +77,7 @@ interface InternalState {
77
77
  scroll: number;
78
78
  time: number;
79
79
  }>;
80
+ scrollTimer: Timer | undefined;
80
81
  }
81
82
  interface ViewableRange<T> {
82
83
  startBuffered: number;
package/index.d.ts CHANGED
@@ -77,6 +77,7 @@ interface InternalState {
77
77
  scroll: number;
78
78
  time: number;
79
79
  }>;
80
+ scrollTimer: Timer | undefined;
80
81
  }
81
82
  interface ViewableRange<T> {
82
83
  startBuffered: number;
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var React7 = require('react');
3
+ var React5 = require('react');
4
4
  var reactNative = require('react-native');
5
5
 
6
6
  function _interopNamespace(e) {
@@ -21,14 +21,13 @@ function _interopNamespace(e) {
21
21
  return Object.freeze(n);
22
22
  }
23
23
 
24
- var React7__namespace = /*#__PURE__*/_interopNamespace(React7);
24
+ var React5__namespace = /*#__PURE__*/_interopNamespace(React5);
25
25
 
26
26
  // src/LegendList.tsx
27
27
  var USE_CONTENT_INSET = reactNative.Platform.OS === "ios";
28
- var ContextState = React7__namespace.createContext(null);
28
+ var ContextState = React5__namespace.createContext(null);
29
29
  function StateProvider({ children }) {
30
- const [value] = React7__namespace.useState(() => ({
31
- hooks: /* @__PURE__ */ new Map(),
30
+ const [value] = React5__namespace.useState(() => ({
32
31
  listeners: /* @__PURE__ */ new Map(),
33
32
  values: /* @__PURE__ */ new Map(),
34
33
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
@@ -36,16 +35,18 @@ function StateProvider({ children }) {
36
35
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
37
36
  mapViewabilityAmountValues: /* @__PURE__ */ new Map()
38
37
  }));
39
- return /* @__PURE__ */ React7__namespace.createElement(ContextState.Provider, { value }, children);
38
+ return /* @__PURE__ */ React5__namespace.createElement(ContextState.Provider, { value }, children);
40
39
  }
41
40
  function useStateContext() {
42
- return React7__namespace.useContext(ContextState);
41
+ return React5__namespace.useContext(ContextState);
43
42
  }
44
43
  function use$(signalName) {
45
- const { hooks, values } = React7__namespace.useContext(ContextState);
46
- const [, forceUpdate] = React7__namespace.useReducer((x) => x + 1, 0);
47
- hooks.set(signalName, forceUpdate);
48
- return values.get(signalName);
44
+ const ctx = React5__namespace.useContext(ContextState);
45
+ const value = React5.useSyncExternalStore(
46
+ (onStoreChange) => listen$(ctx, signalName, onStoreChange),
47
+ () => ctx.values.get(signalName)
48
+ );
49
+ return value;
49
50
  }
50
51
  function listen$(ctx, signalName, cb) {
51
52
  const { listeners } = ctx;
@@ -62,11 +63,9 @@ function peek$(ctx, signalName) {
62
63
  return values.get(signalName);
63
64
  }
64
65
  function set$(ctx, signalName, value) {
65
- var _a;
66
- const { listeners, hooks, values } = ctx;
66
+ const { listeners, values } = ctx;
67
67
  if (values.get(signalName) !== value) {
68
68
  values.set(signalName, value);
69
- (_a = hooks.get(signalName)) == null ? void 0 : _a();
70
69
  const setListeners = listeners.get(signalName);
71
70
  if (setListeners) {
72
71
  for (const listener of setListeners) {
@@ -78,7 +77,7 @@ function set$(ctx, signalName, value) {
78
77
 
79
78
  // src/$ScrollView.tsx
80
79
  var OFFSET_TEST = 0;
81
- var $ScrollView = React7__namespace.forwardRef(function $ScrollView2(props, ref) {
80
+ var $ScrollView = React5__namespace.forwardRef(function $ScrollView2(props, ref) {
82
81
  const { style, horizontal, ...rest } = props;
83
82
  const scrollAdjust = use$("scrollAdjust");
84
83
  const adjustProps = {};
@@ -92,77 +91,51 @@ var $ScrollView = React7__namespace.forwardRef(function $ScrollView2(props, ref)
92
91
  }
93
92
  }
94
93
  }
95
- return /* @__PURE__ */ React7__namespace.createElement(reactNative.ScrollView, { ...rest, style, horizontal, ...adjustProps, ref });
94
+ return /* @__PURE__ */ React5__namespace.createElement(reactNative.ScrollView, { ...rest, style, horizontal, ...adjustProps, ref });
96
95
  });
97
- var LeanView = React7__namespace.forwardRef((props, ref) => {
98
- return React7__namespace.createElement("RCTView", { ...props, ref });
99
- });
100
- LeanView.displayName = "RCTView";
101
-
102
- // src/$View.tsx
103
- function $View({ $key, $key2, $key3, $key4, $style, ...rest }) {
104
- use$($key);
105
- $key2 && use$($key2);
106
- $key3 && use$($key3);
107
- $key4 && use$($key4);
108
- const style = $style();
109
- return /* @__PURE__ */ React7__namespace.createElement(LeanView, { style, ...rest });
110
- }
111
- function InnerContainer({ containerId, getRenderedItem, recycleItems, ItemSeparatorComponent }) {
112
- const lastItemKey = use$("lastItemKey");
113
- const itemKey = use$(`containerItemKey${containerId}`);
114
- if (itemKey === void 0) {
115
- return null;
116
- }
117
- const renderedItem = getRenderedItem(itemKey, containerId);
118
- return /* @__PURE__ */ React7__namespace.default.createElement(React7__namespace.default.Fragment, { key: recycleItems ? void 0 : itemKey }, renderedItem, ItemSeparatorComponent && itemKey !== lastItemKey && ItemSeparatorComponent);
119
- }
120
96
  var Container = ({
121
97
  id,
122
98
  recycleItems,
123
99
  horizontal,
124
100
  getRenderedItem,
125
- onLayout,
101
+ updateItemSize,
126
102
  ItemSeparatorComponent
127
103
  }) => {
128
104
  const ctx = useStateContext();
129
- const createStyle = () => {
130
- const position = peek$(ctx, `containerPosition${id}`);
131
- const column = peek$(ctx, `containerColumn${id}`) || 0;
132
- const visible = peek$(ctx, `containerDidLayout${id}`);
133
- const numColumns = peek$(ctx, "numColumns");
134
- const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
135
- const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
136
- return horizontal ? {
137
- flexDirection: "row",
138
- position: "absolute",
139
- top: visible ? otherAxisPos : -1e7,
140
- bottom: numColumns > 1 ? null : 0,
141
- height: otherAxisSize,
142
- left: position
143
- } : {
144
- position: "absolute",
145
- left: visible ? otherAxisPos : -1e7,
146
- right: numColumns > 1 ? null : 0,
147
- width: otherAxisSize,
148
- top: position
149
- };
105
+ const position = use$(`containerPosition${id}`);
106
+ const column = use$(`containerColumn${id}`) || 0;
107
+ const visible = use$(`containerDidLayout${id}`);
108
+ const numColumns = use$("numColumns");
109
+ const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
110
+ const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
111
+ const style = horizontal ? {
112
+ flexDirection: "row",
113
+ position: "absolute",
114
+ top: visible ? otherAxisPos : -1e7,
115
+ bottom: numColumns > 1 ? null : 0,
116
+ height: otherAxisSize,
117
+ left: position
118
+ } : {
119
+ position: "absolute",
120
+ left: visible ? otherAxisPos : -1e7,
121
+ right: numColumns > 1 ? null : 0,
122
+ width: otherAxisSize,
123
+ top: position
150
124
  };
151
- return /* @__PURE__ */ React7__namespace.default.createElement(
152
- $View,
125
+ const lastItemKey = use$("lastItemKey");
126
+ const itemKey = use$(`containerItemKey${id}`);
127
+ const renderedItem = React5.useMemo(() => itemKey !== void 0 && getRenderedItem(itemKey, id), [itemKey]);
128
+ return /* @__PURE__ */ React5__namespace.default.createElement(
129
+ reactNative.View,
153
130
  {
154
- $key: `containerPosition${id}`,
155
- $key2: `containerDidLayout${id}`,
156
- $key3: `containerColumn${id}`,
157
- $key4: "numColumns",
158
- $style: createStyle,
131
+ style,
159
132
  onLayout: (event) => {
160
133
  const key = peek$(ctx, `containerItemKey${id}`);
161
134
  if (key !== void 0) {
162
135
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
163
- onLayout(key, size);
164
- const otherAxisSize = horizontal ? event.nativeEvent.layout.width : event.nativeEvent.layout.height;
165
- set$(ctx, "otherAxisSize", Math.max(otherAxisSize, peek$(ctx, "otherAxisSize") || 0));
136
+ updateItemSize(id, key, size);
137
+ const otherAxisSize2 = horizontal ? event.nativeEvent.layout.width : event.nativeEvent.layout.height;
138
+ set$(ctx, "otherAxisSize", Math.max(otherAxisSize2, peek$(ctx, "otherAxisSize") || 0));
166
139
  const measured = peek$(ctx, `containerDidLayout${id}`);
167
140
  if (!measured) {
168
141
  requestAnimationFrame(() => {
@@ -172,20 +145,24 @@ var Container = ({
172
145
  }
173
146
  }
174
147
  },
175
- /* @__PURE__ */ React7__namespace.default.createElement(
176
- InnerContainer,
177
- {
178
- containerId: id,
179
- getRenderedItem,
180
- recycleItems,
181
- ItemSeparatorComponent
182
- }
183
- )
148
+ /* @__PURE__ */ React5__namespace.default.createElement(React5__namespace.default.Fragment, { key: recycleItems ? void 0 : itemKey }, renderedItem, renderedItem && ItemSeparatorComponent && itemKey !== lastItemKey && ItemSeparatorComponent)
184
149
  );
185
150
  };
151
+ var useAnimatedValue = reactNative.useAnimatedValue || ((initialValue) => {
152
+ return React5.useRef(new reactNative.Animated.Value(initialValue)).current;
153
+ });
154
+ function useValue$(key, getValue, key2) {
155
+ var _a;
156
+ const ctx = useStateContext();
157
+ const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
158
+ React5.useMemo(() => {
159
+ listen$(ctx, key, (v) => animValue.setValue(getValue ? getValue(v) : v));
160
+ }, []);
161
+ return animValue;
162
+ }
186
163
 
187
164
  // src/Containers.tsx
188
- var Containers = React7__namespace.memo(function Containers2({
165
+ var Containers = React5__namespace.memo(function Containers2({
189
166
  horizontal,
190
167
  recycleItems,
191
168
  ItemSeparatorComponent,
@@ -194,10 +171,11 @@ var Containers = React7__namespace.memo(function Containers2({
194
171
  }) {
195
172
  const ctx = useStateContext();
196
173
  const numContainers = use$("numContainersPooled");
174
+ const animSize = useValue$("totalSize", (v) => v + peek$(ctx, "scrollAdjust"));
197
175
  const containers = [];
198
176
  for (let i = 0; i < numContainers; i++) {
199
177
  containers.push(
200
- /* @__PURE__ */ React7__namespace.createElement(
178
+ /* @__PURE__ */ React5__namespace.createElement(
201
179
  Container,
202
180
  {
203
181
  id: i,
@@ -205,41 +183,27 @@ var Containers = React7__namespace.memo(function Containers2({
205
183
  recycleItems,
206
184
  horizontal,
207
185
  getRenderedItem,
208
- onLayout: updateItemSize,
186
+ updateItemSize,
209
187
  ItemSeparatorComponent
210
188
  }
211
189
  )
212
190
  );
213
191
  }
214
- return /* @__PURE__ */ React7__namespace.createElement(
215
- $View,
216
- {
217
- $key: "totalSize",
218
- $key2: "scrollAdjust",
219
- $style: () => {
220
- const size = peek$(ctx, "totalSize") + peek$(ctx, "scrollAdjust");
221
- return horizontal ? {
222
- width: size
223
- } : {
224
- height: size
225
- };
226
- }
227
- },
228
- containers
229
- );
192
+ const style = horizontal ? { width: animSize } : { height: animSize };
193
+ return /* @__PURE__ */ React5__namespace.createElement(reactNative.Animated.View, { style }, containers);
230
194
  });
231
195
 
232
196
  // src/ListComponent.tsx
233
197
  var getComponent = (Component) => {
234
- if (React7__namespace.isValidElement(Component)) {
198
+ if (React5__namespace.isValidElement(Component)) {
235
199
  return Component;
236
200
  }
237
201
  if (Component) {
238
- return /* @__PURE__ */ React7__namespace.createElement(Component, null);
202
+ return /* @__PURE__ */ React5__namespace.createElement(Component, null);
239
203
  }
240
204
  return null;
241
205
  };
242
- var ListComponent = React7__namespace.memo(function ListComponent2({
206
+ var ListComponent = React5__namespace.memo(function ListComponent2({
243
207
  style,
244
208
  contentContainerStyle,
245
209
  horizontal,
@@ -262,8 +226,9 @@ var ListComponent = React7__namespace.memo(function ListComponent2({
262
226
  ...rest
263
227
  }) {
264
228
  const ctx = useStateContext();
265
- use$("otherAxisSize") || 0;
266
- return /* @__PURE__ */ React7__namespace.createElement(
229
+ const animPaddingTop = useValue$("paddingTop");
230
+ const animScrollAdjust = useValue$("scrollAdjust");
231
+ return /* @__PURE__ */ React5__namespace.createElement(
267
232
  $ScrollView,
268
233
  {
269
234
  ...rest,
@@ -280,12 +245,13 @@ var ListComponent = React7__namespace.memo(function ListComponent2({
280
245
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
281
246
  ref: refScroller
282
247
  },
283
- alignItemsAtEnd && /* @__PURE__ */ React7__namespace.createElement($View, { $key: "paddingTop", $style: () => ({ height: peek$(ctx, "paddingTop") }) }),
284
- ListHeaderComponent && /* @__PURE__ */ React7__namespace.createElement(
285
- $View,
248
+ alignItemsAtEnd && /* @__PURE__ */ React5__namespace.createElement(reactNative.Animated.View, { style: { height: animPaddingTop } }),
249
+ ListHeaderComponent && /* @__PURE__ */ React5__namespace.createElement(
250
+ reactNative.Animated.View,
286
251
  {
287
- $key: "scrollAdjust",
288
- $style: () => reactNative.StyleSheet.compose(ListHeaderComponentStyle, { top: peek$(ctx, "scrollAdjust") }),
252
+ style: reactNative.StyleSheet.compose(ListHeaderComponentStyle, {
253
+ top: animScrollAdjust
254
+ }),
289
255
  onLayout: (event) => {
290
256
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
291
257
  const prevSize = peek$(ctx, "headerSize") || 0;
@@ -296,15 +262,16 @@ var ListComponent = React7__namespace.memo(function ListComponent2({
296
262
  },
297
263
  getComponent(ListHeaderComponent)
298
264
  ),
299
- ListEmptyComponent && /* @__PURE__ */ React7__namespace.createElement(
300
- $View,
265
+ ListEmptyComponent && /* @__PURE__ */ React5__namespace.createElement(
266
+ reactNative.Animated.View,
301
267
  {
302
- $key: "scrollAdjust",
303
- $style: () => reactNative.StyleSheet.compose(ListEmptyComponentStyle, { top: peek$(ctx, "scrollAdjust") })
268
+ style: reactNative.StyleSheet.compose(ListEmptyComponentStyle, {
269
+ top: animScrollAdjust
270
+ })
304
271
  },
305
272
  getComponent(ListEmptyComponent)
306
273
  ),
307
- /* @__PURE__ */ React7__namespace.createElement(
274
+ /* @__PURE__ */ React5__namespace.createElement(
308
275
  Containers,
309
276
  {
310
277
  horizontal,
@@ -314,12 +281,12 @@ var ListComponent = React7__namespace.memo(function ListComponent2({
314
281
  updateItemSize
315
282
  }
316
283
  ),
317
- ListFooterComponent && /* @__PURE__ */ React7__namespace.createElement(reactNative.View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
284
+ ListFooterComponent && /* @__PURE__ */ React5__namespace.createElement(reactNative.View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
318
285
  );
319
286
  });
320
287
  var symbolFirst = Symbol();
321
288
  function useInit(cb) {
322
- const refValue = React7.useRef(symbolFirst);
289
+ const refValue = React5.useRef(symbolFirst);
323
290
  if (refValue.current === symbolFirst) {
324
291
  refValue.current = cb();
325
292
  }
@@ -478,11 +445,11 @@ var DEFAULT_DRAW_DISTANCE = 250;
478
445
  var INITIAL_SCROLL_ADJUST = 1e4;
479
446
  var POSITION_OUT_OF_VIEW = -1e7;
480
447
  var DEFAULT_ITEM_SIZE = 100;
481
- var LegendList = React7.forwardRef(function LegendList2(props, forwardedRef) {
482
- return /* @__PURE__ */ React7__namespace.createElement(StateProvider, null, /* @__PURE__ */ React7__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
448
+ var LegendList = React5.forwardRef(function LegendList2(props, forwardedRef) {
449
+ return /* @__PURE__ */ React5__namespace.createElement(StateProvider, null, /* @__PURE__ */ React5__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
483
450
  });
484
- var LegendListInner = React7.forwardRef(function LegendListInner2(props, forwardedRef) {
485
- var _a, _b, _c, _d, _e;
451
+ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forwardedRef) {
452
+ var _a, _b, _c, _d, _e, _f;
486
453
  const {
487
454
  data,
488
455
  initialScrollIndex,
@@ -499,7 +466,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
499
466
  maintainVisibleContentPosition = false,
500
467
  onScroll: onScrollProp,
501
468
  numColumns: numColumnsProp = 1,
502
- keyExtractor,
469
+ keyExtractor: keyExtractorProp,
503
470
  renderItem,
504
471
  estimatedItemSize,
505
472
  getEstimatedItemSize,
@@ -510,10 +477,11 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
510
477
  } = props;
511
478
  const { style, contentContainerStyle } = props;
512
479
  const ctx = useStateContext();
513
- const internalRef = React7.useRef(null);
480
+ const internalRef = React5.useRef(null);
514
481
  const refScroller = internalRef;
515
482
  const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE;
516
- const refState = React7.useRef();
483
+ const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
484
+ const refState = React5.useRef();
517
485
  const getId = (index) => {
518
486
  var _a2;
519
487
  const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
@@ -547,7 +515,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
547
515
  }
548
516
  return void 0;
549
517
  };
550
- const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React7.useMemo(calculateInitialOffset, []);
518
+ const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React5.useMemo(calculateInitialOffset, []);
551
519
  if (!refState.current) {
552
520
  refState.current = {
553
521
  sizes: /* @__PURE__ */ new Map(),
@@ -583,7 +551,8 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
583
551
  scrollVelocity: 0,
584
552
  contentSize: { width: 0, height: 0 },
585
553
  sizesLaidOut: __DEV__ ? /* @__PURE__ */ new Map() : void 0,
586
- timeoutSizeMessage: 0
554
+ timeoutSizeMessage: 0,
555
+ scrollTimer: void 0
587
556
  };
588
557
  refState.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
589
558
  set$(ctx, "scrollAdjust", refState.current.scrollAdjustPending);
@@ -593,7 +562,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
593
562
  refState.current.scrollAdjustPending -= diff;
594
563
  }
595
564
  };
596
- const addTotalSize = React7.useCallback((key, add) => {
565
+ const addTotalSize = React5.useCallback((key, add) => {
597
566
  const state = refState.current;
598
567
  const index = key === null ? 0 : state.indexByKey.get(key);
599
568
  const isAbove = key !== null && index < (state.startNoBuffer || 0);
@@ -620,7 +589,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
620
589
  state.animFrameTotalSize = requestAnimationFrame(doAdd);
621
590
  }
622
591
  }, []);
623
- const calculateItemsInView = React7.useCallback((speed = 0) => {
592
+ const calculateItemsInView = React5.useCallback((speed = 0) => {
624
593
  var _a2, _b2, _c2;
625
594
  const state = refState.current;
626
595
  const {
@@ -641,7 +610,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
641
610
  }
642
611
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
643
612
  const scrollAdjustPending = (_a2 = state.scrollAdjustPending) != null ? _a2 : 0;
644
- const scrollExtra = Math.max(-16, Math.min(16, speed)) * 32;
613
+ const scrollExtra = Math.max(-16, Math.min(16, speed)) * 16;
645
614
  const scroll = Math.max(
646
615
  0,
647
616
  scrollState - topPad - (USE_CONTENT_INSET ? scrollAdjustPending : 0) + scrollExtra
@@ -835,19 +804,22 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
835
804
  return;
836
805
  }
837
806
  const { scrollLength, scroll, contentSize } = refState.current;
838
- const distanceFromEnd = contentSize[horizontal ? "width" : "height"] - scroll - scrollLength;
839
- if (refState.current) {
840
- refState.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
841
- }
842
- if (onEndReached) {
843
- if (!refState.current.isEndReached) {
844
- if (distanceFromEnd < onEndReachedThreshold * scrollLength) {
845
- refState.current.isEndReached = true;
846
- onEndReached({ distanceFromEnd });
847
- }
848
- } else {
849
- if (distanceFromEnd >= onEndReachedThreshold * scrollLength) {
850
- refState.current.isEndReached = false;
807
+ const contentLength = contentSize[horizontal ? "width" : "height"];
808
+ if (scroll > 0 && contentLength > 0) {
809
+ const distanceFromEnd = contentLength - scroll - scrollLength;
810
+ if (refState.current) {
811
+ refState.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
812
+ }
813
+ if (onEndReached) {
814
+ if (!refState.current.isEndReached) {
815
+ if (distanceFromEnd < onEndReachedThreshold * scrollLength) {
816
+ refState.current.isEndReached = true;
817
+ onEndReached({ distanceFromEnd });
818
+ }
819
+ } else {
820
+ if (distanceFromEnd >= onEndReachedThreshold * scrollLength) {
821
+ refState.current.isEndReached = false;
822
+ }
851
823
  }
852
824
  }
853
825
  }
@@ -875,7 +847,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
875
847
  };
876
848
  const isFirst = !refState.current.renderItem;
877
849
  if (isFirst || data !== refState.current.data || numColumnsProp !== peek$(ctx, "numColumns")) {
878
- if (!keyExtractor && !isFirst && data !== refState.current.data) {
850
+ if (!keyExtractorProp && !isFirst && data !== refState.current.data) {
879
851
  refState.current.sizes.clear();
880
852
  refState.current.positions.clear();
881
853
  }
@@ -916,11 +888,14 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
916
888
  refState.current.isEndReached = false;
917
889
  const numContainers = peek$(ctx, "numContainers");
918
890
  for (let i = 0; i < numContainers; i++) {
919
- set$(ctx, `containerItemKey${i}`, void 0);
920
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
921
- set$(ctx, `containerColumn${i}`, -1);
891
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
892
+ if (!keyExtractorProp || itemKey && ((_b = refState.current) == null ? void 0 : _b.indexByKey.get(itemKey)) === void 0) {
893
+ set$(ctx, `containerItemKey${i}`, void 0);
894
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
895
+ set$(ctx, `containerColumn${i}`, -1);
896
+ }
922
897
  }
923
- if (!keyExtractor) {
898
+ if (!keyExtractorProp) {
924
899
  refState.current.sizes.clear();
925
900
  refState.current.positions;
926
901
  }
@@ -936,9 +911,9 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
936
911
  set$(
937
912
  ctx,
938
913
  "stylePaddingTop",
939
- (_e = (_d = (_b = reactNative.StyleSheet.flatten(style)) == null ? void 0 : _b.paddingTop) != null ? _d : (_c = reactNative.StyleSheet.flatten(contentContainerStyle)) == null ? void 0 : _c.paddingTop) != null ? _e : 0
914
+ (_f = (_e = (_c = reactNative.StyleSheet.flatten(style)) == null ? void 0 : _c.paddingTop) != null ? _e : (_d = reactNative.StyleSheet.flatten(contentContainerStyle)) == null ? void 0 : _d.paddingTop) != null ? _f : 0
940
915
  );
941
- const getRenderedItem = React7.useCallback((key, containerId) => {
916
+ const getRenderedItem = React5.useCallback((key, containerId) => {
942
917
  var _a2, _b2;
943
918
  const state = refState.current;
944
919
  if (!state) {
@@ -958,7 +933,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
958
933
  }
959
934
  });
960
935
  ctx.mapViewabilityCallbacks.set(key2, callback);
961
- React7.useEffect(
936
+ React5.useEffect(
962
937
  () => () => {
963
938
  ctx.mapViewabilityCallbacks.delete(key2);
964
939
  },
@@ -973,7 +948,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
973
948
  }
974
949
  });
975
950
  ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
976
- React7.useEffect(
951
+ React5.useEffect(
977
952
  () => () => {
978
953
  ctx.mapViewabilityAmountCallbacks.delete(containerId);
979
954
  },
@@ -981,7 +956,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
981
956
  );
982
957
  };
983
958
  const useRecyclingEffect = (effect) => {
984
- React7.useEffect(() => {
959
+ React5.useEffect(() => {
985
960
  const state2 = refState.current;
986
961
  let prevIndex = index;
987
962
  let prevItem = state2.data[index];
@@ -1009,7 +984,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
1009
984
  }, []);
1010
985
  };
1011
986
  const useRecyclingState = (valueOrFun) => {
1012
- const stateInfo = React7.useState(
987
+ const stateInfo = React5.useState(
1013
988
  () => typeof valueOrFun === "function" ? valueOrFun({
1014
989
  index,
1015
990
  item: refState.current.data[index],
@@ -1047,7 +1022,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
1047
1022
  set$(ctx, "numContainersPooled", numContainers * 2);
1048
1023
  calculateItemsInView();
1049
1024
  });
1050
- const updateItemSize = React7.useCallback((key, size) => {
1025
+ const updateItemSize = React5.useCallback((containerId, itemKey, size) => {
1051
1026
  var _a2;
1052
1027
  const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
1053
1028
  if (!data2) {
@@ -1055,14 +1030,14 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
1055
1030
  }
1056
1031
  const state = refState.current;
1057
1032
  const { sizes, indexByKey, idsInFirstRender, columns, sizesLaidOut } = state;
1058
- const index = indexByKey.get(key);
1059
- const wasInFirstRender = idsInFirstRender.has(key);
1060
- const prevSize = sizes.get(key) || (wasInFirstRender ? getItemSize(key, index, data2[index]) : 0);
1033
+ const index = indexByKey.get(itemKey);
1034
+ const wasInFirstRender = idsInFirstRender.has(itemKey);
1035
+ const prevSize = sizes.get(itemKey) || (wasInFirstRender ? getItemSize(itemKey, index, data2[index]) : 0);
1061
1036
  if (!prevSize || Math.abs(prevSize - size) > 0.5) {
1062
1037
  let diff;
1063
1038
  const numColumns = peek$(ctx, "numColumns");
1064
1039
  if (numColumns > 1) {
1065
- const column = columns.get(key);
1040
+ const column = columns.get(itemKey);
1066
1041
  const loopStart = index - (column - 1);
1067
1042
  let prevMaxSizeInRow = 0;
1068
1043
  for (let i = loopStart; i < loopStart + numColumns; i++) {
@@ -1070,7 +1045,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
1070
1045
  const size2 = getItemSize(id, i, data2[i]);
1071
1046
  prevMaxSizeInRow = Math.max(prevMaxSizeInRow, size2);
1072
1047
  }
1073
- sizes.set(key, size);
1048
+ sizes.set(itemKey, size);
1074
1049
  let nextMaxSizeInRow = 0;
1075
1050
  for (let i = loopStart; i < loopStart + numColumns; i++) {
1076
1051
  const id = getId(i);
@@ -1079,11 +1054,11 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
1079
1054
  }
1080
1055
  diff = nextMaxSizeInRow - prevMaxSizeInRow;
1081
1056
  } else {
1082
- sizes.set(key, size);
1057
+ sizes.set(itemKey, size);
1083
1058
  diff = size - prevSize;
1084
1059
  }
1085
1060
  if (__DEV__ && !estimatedItemSize && !getEstimatedItemSize) {
1086
- sizesLaidOut.set(key, size);
1061
+ sizesLaidOut.set(itemKey, size);
1087
1062
  if (state.timeoutSizeMessage) {
1088
1063
  clearTimeout(state.timeoutSizeMessage);
1089
1064
  }
@@ -1091,7 +1066,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
1091
1066
  state.timeoutSizeMessage = void 0;
1092
1067
  let total = 0;
1093
1068
  let num = 0;
1094
- for (const [key2, size2] of sizesLaidOut) {
1069
+ for (const [key, size2] of sizesLaidOut) {
1095
1070
  num++;
1096
1071
  total += size2;
1097
1072
  }
@@ -1101,18 +1076,22 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
1101
1076
  );
1102
1077
  }, 1e3);
1103
1078
  }
1104
- addTotalSize(key, diff);
1079
+ addTotalSize(itemKey, diff);
1105
1080
  doMaintainScrollAtEnd(true);
1106
1081
  const scrollVelocity = state.scrollVelocity;
1107
1082
  if (!state.animFrameLayout && (Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1)) {
1108
- state.animFrameLayout = requestAnimationFrame(() => {
1109
- state.animFrameLayout = null;
1083
+ if (!peek$(ctx, `containerDidLayout${containerId}`)) {
1084
+ state.animFrameLayout = requestAnimationFrame(() => {
1085
+ state.animFrameLayout = null;
1086
+ calculateItemsInView(state.scrollVelocity);
1087
+ });
1088
+ } else {
1110
1089
  calculateItemsInView(state.scrollVelocity);
1111
- });
1090
+ }
1112
1091
  }
1113
1092
  }
1114
1093
  }, []);
1115
- const handleScrollDebounced = React7.useCallback((velocity) => {
1094
+ const handleScrollDebounced = React5.useCallback((velocity) => {
1116
1095
  var _a2, _b2;
1117
1096
  const scrollAdjustPending = (_b2 = (_a2 = refState.current) == null ? void 0 : _a2.scrollAdjustPending) != null ? _b2 : 0;
1118
1097
  set$(ctx, "scrollAdjust", scrollAdjustPending);
@@ -1120,7 +1099,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
1120
1099
  checkAtBottom();
1121
1100
  checkAtTop();
1122
1101
  }, []);
1123
- const onLayout = React7.useCallback((event) => {
1102
+ const onLayout = React5.useCallback((event) => {
1124
1103
  let scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
1125
1104
  if (!USE_CONTENT_INSET) {
1126
1105
  scrollLength += event.nativeEvent.layout[horizontal ? "x" : "y"];
@@ -1142,7 +1121,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
1142
1121
  }
1143
1122
  }
1144
1123
  }, []);
1145
- const handleScroll = React7.useCallback(
1124
+ const handleScroll = React5.useCallback(
1146
1125
  (event, fromSelf) => {
1147
1126
  var _a2, _b2, _c2;
1148
1127
  if (((_b2 = (_a2 = event.nativeEvent) == null ? void 0 : _a2.contentSize) == null ? void 0 : _b2.height) === 0 && ((_c2 = event.nativeEvent.contentSize) == null ? void 0 : _c2.width) === 0) {
@@ -1153,10 +1132,18 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
1153
1132
  state.contentSize = event.nativeEvent.contentSize;
1154
1133
  const currentTime = performance.now();
1155
1134
  const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
1156
- state.scrollHistory.push({ scroll: newScroll, time: currentTime });
1135
+ if (!(state.scrollHistory.length === 0 && newScroll === initialContentOffset)) {
1136
+ state.scrollHistory.push({ scroll: newScroll, time: currentTime });
1137
+ }
1157
1138
  if (state.scrollHistory.length > 5) {
1158
1139
  state.scrollHistory.shift();
1159
1140
  }
1141
+ if (state.scrollTimer !== void 0) {
1142
+ clearTimeout(state.scrollTimer);
1143
+ }
1144
+ state.scrollTimer = setTimeout(() => {
1145
+ state.scrollVelocity = 0;
1146
+ }, 500);
1160
1147
  let velocity = 0;
1161
1148
  if (state.scrollHistory.length >= 2) {
1162
1149
  const newest = state.scrollHistory[state.scrollHistory.length - 1];
@@ -1177,7 +1164,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
1177
1164
  },
1178
1165
  []
1179
1166
  );
1180
- React7.useImperativeHandle(
1167
+ React5.useImperativeHandle(
1181
1168
  forwardedRef,
1182
1169
  () => {
1183
1170
  const scrollToIndex = ({ index, animated }) => {
@@ -1206,7 +1193,7 @@ var LegendListInner = React7.forwardRef(function LegendListInner2(props, forward
1206
1193
  },
1207
1194
  []
1208
1195
  );
1209
- return /* @__PURE__ */ React7__namespace.createElement(
1196
+ return /* @__PURE__ */ React5__namespace.createElement(
1210
1197
  ListComponent,
1211
1198
  {
1212
1199
  ...rest,
package/index.mjs CHANGED
@@ -1,13 +1,12 @@
1
- import * as React7 from 'react';
2
- import React7__default, { forwardRef, useRef, useMemo, useCallback, useImperativeHandle, useEffect, useState } from 'react';
3
- import { Platform, StyleSheet, ScrollView, View, Dimensions } from 'react-native';
1
+ import * as React5 from 'react';
2
+ import React5__default, { forwardRef, useRef, useMemo, useCallback, useImperativeHandle, useSyncExternalStore, useEffect, useState } from 'react';
3
+ import { Platform, StyleSheet, ScrollView, Animated, View, Dimensions, useAnimatedValue as useAnimatedValue$1 } from 'react-native';
4
4
 
5
5
  // src/LegendList.tsx
6
6
  var USE_CONTENT_INSET = Platform.OS === "ios";
7
- var ContextState = React7.createContext(null);
7
+ var ContextState = React5.createContext(null);
8
8
  function StateProvider({ children }) {
9
- const [value] = React7.useState(() => ({
10
- hooks: /* @__PURE__ */ new Map(),
9
+ const [value] = React5.useState(() => ({
11
10
  listeners: /* @__PURE__ */ new Map(),
12
11
  values: /* @__PURE__ */ new Map(),
13
12
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
@@ -15,16 +14,18 @@ function StateProvider({ children }) {
15
14
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
16
15
  mapViewabilityAmountValues: /* @__PURE__ */ new Map()
17
16
  }));
18
- return /* @__PURE__ */ React7.createElement(ContextState.Provider, { value }, children);
17
+ return /* @__PURE__ */ React5.createElement(ContextState.Provider, { value }, children);
19
18
  }
20
19
  function useStateContext() {
21
- return React7.useContext(ContextState);
20
+ return React5.useContext(ContextState);
22
21
  }
23
22
  function use$(signalName) {
24
- const { hooks, values } = React7.useContext(ContextState);
25
- const [, forceUpdate] = React7.useReducer((x) => x + 1, 0);
26
- hooks.set(signalName, forceUpdate);
27
- return values.get(signalName);
23
+ const ctx = React5.useContext(ContextState);
24
+ const value = useSyncExternalStore(
25
+ (onStoreChange) => listen$(ctx, signalName, onStoreChange),
26
+ () => ctx.values.get(signalName)
27
+ );
28
+ return value;
28
29
  }
29
30
  function listen$(ctx, signalName, cb) {
30
31
  const { listeners } = ctx;
@@ -41,11 +42,9 @@ function peek$(ctx, signalName) {
41
42
  return values.get(signalName);
42
43
  }
43
44
  function set$(ctx, signalName, value) {
44
- var _a;
45
- const { listeners, hooks, values } = ctx;
45
+ const { listeners, values } = ctx;
46
46
  if (values.get(signalName) !== value) {
47
47
  values.set(signalName, value);
48
- (_a = hooks.get(signalName)) == null ? void 0 : _a();
49
48
  const setListeners = listeners.get(signalName);
50
49
  if (setListeners) {
51
50
  for (const listener of setListeners) {
@@ -57,7 +56,7 @@ function set$(ctx, signalName, value) {
57
56
 
58
57
  // src/$ScrollView.tsx
59
58
  var OFFSET_TEST = 0;
60
- var $ScrollView = React7.forwardRef(function $ScrollView2(props, ref) {
59
+ var $ScrollView = React5.forwardRef(function $ScrollView2(props, ref) {
61
60
  const { style, horizontal, ...rest } = props;
62
61
  const scrollAdjust = use$("scrollAdjust");
63
62
  const adjustProps = {};
@@ -71,77 +70,51 @@ var $ScrollView = React7.forwardRef(function $ScrollView2(props, ref) {
71
70
  }
72
71
  }
73
72
  }
74
- return /* @__PURE__ */ React7.createElement(ScrollView, { ...rest, style, horizontal, ...adjustProps, ref });
73
+ return /* @__PURE__ */ React5.createElement(ScrollView, { ...rest, style, horizontal, ...adjustProps, ref });
75
74
  });
76
- var LeanView = React7.forwardRef((props, ref) => {
77
- return React7.createElement("RCTView", { ...props, ref });
78
- });
79
- LeanView.displayName = "RCTView";
80
-
81
- // src/$View.tsx
82
- function $View({ $key, $key2, $key3, $key4, $style, ...rest }) {
83
- use$($key);
84
- $key2 && use$($key2);
85
- $key3 && use$($key3);
86
- $key4 && use$($key4);
87
- const style = $style();
88
- return /* @__PURE__ */ React7.createElement(LeanView, { style, ...rest });
89
- }
90
- function InnerContainer({ containerId, getRenderedItem, recycleItems, ItemSeparatorComponent }) {
91
- const lastItemKey = use$("lastItemKey");
92
- const itemKey = use$(`containerItemKey${containerId}`);
93
- if (itemKey === void 0) {
94
- return null;
95
- }
96
- const renderedItem = getRenderedItem(itemKey, containerId);
97
- return /* @__PURE__ */ React7__default.createElement(React7__default.Fragment, { key: recycleItems ? void 0 : itemKey }, renderedItem, ItemSeparatorComponent && itemKey !== lastItemKey && ItemSeparatorComponent);
98
- }
99
75
  var Container = ({
100
76
  id,
101
77
  recycleItems,
102
78
  horizontal,
103
79
  getRenderedItem,
104
- onLayout,
80
+ updateItemSize,
105
81
  ItemSeparatorComponent
106
82
  }) => {
107
83
  const ctx = useStateContext();
108
- const createStyle = () => {
109
- const position = peek$(ctx, `containerPosition${id}`);
110
- const column = peek$(ctx, `containerColumn${id}`) || 0;
111
- const visible = peek$(ctx, `containerDidLayout${id}`);
112
- const numColumns = peek$(ctx, "numColumns");
113
- const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
114
- const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
115
- return horizontal ? {
116
- flexDirection: "row",
117
- position: "absolute",
118
- top: visible ? otherAxisPos : -1e7,
119
- bottom: numColumns > 1 ? null : 0,
120
- height: otherAxisSize,
121
- left: position
122
- } : {
123
- position: "absolute",
124
- left: visible ? otherAxisPos : -1e7,
125
- right: numColumns > 1 ? null : 0,
126
- width: otherAxisSize,
127
- top: position
128
- };
84
+ const position = use$(`containerPosition${id}`);
85
+ const column = use$(`containerColumn${id}`) || 0;
86
+ const visible = use$(`containerDidLayout${id}`);
87
+ const numColumns = use$("numColumns");
88
+ const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
89
+ const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
90
+ const style = horizontal ? {
91
+ flexDirection: "row",
92
+ position: "absolute",
93
+ top: visible ? otherAxisPos : -1e7,
94
+ bottom: numColumns > 1 ? null : 0,
95
+ height: otherAxisSize,
96
+ left: position
97
+ } : {
98
+ position: "absolute",
99
+ left: visible ? otherAxisPos : -1e7,
100
+ right: numColumns > 1 ? null : 0,
101
+ width: otherAxisSize,
102
+ top: position
129
103
  };
130
- return /* @__PURE__ */ React7__default.createElement(
131
- $View,
104
+ const lastItemKey = use$("lastItemKey");
105
+ const itemKey = use$(`containerItemKey${id}`);
106
+ const renderedItem = useMemo(() => itemKey !== void 0 && getRenderedItem(itemKey, id), [itemKey]);
107
+ return /* @__PURE__ */ React5__default.createElement(
108
+ View,
132
109
  {
133
- $key: `containerPosition${id}`,
134
- $key2: `containerDidLayout${id}`,
135
- $key3: `containerColumn${id}`,
136
- $key4: "numColumns",
137
- $style: createStyle,
110
+ style,
138
111
  onLayout: (event) => {
139
112
  const key = peek$(ctx, `containerItemKey${id}`);
140
113
  if (key !== void 0) {
141
114
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
142
- onLayout(key, size);
143
- const otherAxisSize = horizontal ? event.nativeEvent.layout.width : event.nativeEvent.layout.height;
144
- set$(ctx, "otherAxisSize", Math.max(otherAxisSize, peek$(ctx, "otherAxisSize") || 0));
115
+ updateItemSize(id, key, size);
116
+ const otherAxisSize2 = horizontal ? event.nativeEvent.layout.width : event.nativeEvent.layout.height;
117
+ set$(ctx, "otherAxisSize", Math.max(otherAxisSize2, peek$(ctx, "otherAxisSize") || 0));
145
118
  const measured = peek$(ctx, `containerDidLayout${id}`);
146
119
  if (!measured) {
147
120
  requestAnimationFrame(() => {
@@ -151,20 +124,24 @@ var Container = ({
151
124
  }
152
125
  }
153
126
  },
154
- /* @__PURE__ */ React7__default.createElement(
155
- InnerContainer,
156
- {
157
- containerId: id,
158
- getRenderedItem,
159
- recycleItems,
160
- ItemSeparatorComponent
161
- }
162
- )
127
+ /* @__PURE__ */ React5__default.createElement(React5__default.Fragment, { key: recycleItems ? void 0 : itemKey }, renderedItem, renderedItem && ItemSeparatorComponent && itemKey !== lastItemKey && ItemSeparatorComponent)
163
128
  );
164
129
  };
130
+ var useAnimatedValue = useAnimatedValue$1 || ((initialValue) => {
131
+ return useRef(new Animated.Value(initialValue)).current;
132
+ });
133
+ function useValue$(key, getValue, key2) {
134
+ var _a;
135
+ const ctx = useStateContext();
136
+ const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
137
+ useMemo(() => {
138
+ listen$(ctx, key, (v) => animValue.setValue(getValue ? getValue(v) : v));
139
+ }, []);
140
+ return animValue;
141
+ }
165
142
 
166
143
  // src/Containers.tsx
167
- var Containers = React7.memo(function Containers2({
144
+ var Containers = React5.memo(function Containers2({
168
145
  horizontal,
169
146
  recycleItems,
170
147
  ItemSeparatorComponent,
@@ -173,10 +150,11 @@ var Containers = React7.memo(function Containers2({
173
150
  }) {
174
151
  const ctx = useStateContext();
175
152
  const numContainers = use$("numContainersPooled");
153
+ const animSize = useValue$("totalSize", (v) => v + peek$(ctx, "scrollAdjust"));
176
154
  const containers = [];
177
155
  for (let i = 0; i < numContainers; i++) {
178
156
  containers.push(
179
- /* @__PURE__ */ React7.createElement(
157
+ /* @__PURE__ */ React5.createElement(
180
158
  Container,
181
159
  {
182
160
  id: i,
@@ -184,41 +162,27 @@ var Containers = React7.memo(function Containers2({
184
162
  recycleItems,
185
163
  horizontal,
186
164
  getRenderedItem,
187
- onLayout: updateItemSize,
165
+ updateItemSize,
188
166
  ItemSeparatorComponent
189
167
  }
190
168
  )
191
169
  );
192
170
  }
193
- return /* @__PURE__ */ React7.createElement(
194
- $View,
195
- {
196
- $key: "totalSize",
197
- $key2: "scrollAdjust",
198
- $style: () => {
199
- const size = peek$(ctx, "totalSize") + peek$(ctx, "scrollAdjust");
200
- return horizontal ? {
201
- width: size
202
- } : {
203
- height: size
204
- };
205
- }
206
- },
207
- containers
208
- );
171
+ const style = horizontal ? { width: animSize } : { height: animSize };
172
+ return /* @__PURE__ */ React5.createElement(Animated.View, { style }, containers);
209
173
  });
210
174
 
211
175
  // src/ListComponent.tsx
212
176
  var getComponent = (Component) => {
213
- if (React7.isValidElement(Component)) {
177
+ if (React5.isValidElement(Component)) {
214
178
  return Component;
215
179
  }
216
180
  if (Component) {
217
- return /* @__PURE__ */ React7.createElement(Component, null);
181
+ return /* @__PURE__ */ React5.createElement(Component, null);
218
182
  }
219
183
  return null;
220
184
  };
221
- var ListComponent = React7.memo(function ListComponent2({
185
+ var ListComponent = React5.memo(function ListComponent2({
222
186
  style,
223
187
  contentContainerStyle,
224
188
  horizontal,
@@ -241,8 +205,9 @@ var ListComponent = React7.memo(function ListComponent2({
241
205
  ...rest
242
206
  }) {
243
207
  const ctx = useStateContext();
244
- use$("otherAxisSize") || 0;
245
- return /* @__PURE__ */ React7.createElement(
208
+ const animPaddingTop = useValue$("paddingTop");
209
+ const animScrollAdjust = useValue$("scrollAdjust");
210
+ return /* @__PURE__ */ React5.createElement(
246
211
  $ScrollView,
247
212
  {
248
213
  ...rest,
@@ -259,12 +224,13 @@ var ListComponent = React7.memo(function ListComponent2({
259
224
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
260
225
  ref: refScroller
261
226
  },
262
- alignItemsAtEnd && /* @__PURE__ */ React7.createElement($View, { $key: "paddingTop", $style: () => ({ height: peek$(ctx, "paddingTop") }) }),
263
- ListHeaderComponent && /* @__PURE__ */ React7.createElement(
264
- $View,
227
+ alignItemsAtEnd && /* @__PURE__ */ React5.createElement(Animated.View, { style: { height: animPaddingTop } }),
228
+ ListHeaderComponent && /* @__PURE__ */ React5.createElement(
229
+ Animated.View,
265
230
  {
266
- $key: "scrollAdjust",
267
- $style: () => StyleSheet.compose(ListHeaderComponentStyle, { top: peek$(ctx, "scrollAdjust") }),
231
+ style: StyleSheet.compose(ListHeaderComponentStyle, {
232
+ top: animScrollAdjust
233
+ }),
268
234
  onLayout: (event) => {
269
235
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
270
236
  const prevSize = peek$(ctx, "headerSize") || 0;
@@ -275,15 +241,16 @@ var ListComponent = React7.memo(function ListComponent2({
275
241
  },
276
242
  getComponent(ListHeaderComponent)
277
243
  ),
278
- ListEmptyComponent && /* @__PURE__ */ React7.createElement(
279
- $View,
244
+ ListEmptyComponent && /* @__PURE__ */ React5.createElement(
245
+ Animated.View,
280
246
  {
281
- $key: "scrollAdjust",
282
- $style: () => StyleSheet.compose(ListEmptyComponentStyle, { top: peek$(ctx, "scrollAdjust") })
247
+ style: StyleSheet.compose(ListEmptyComponentStyle, {
248
+ top: animScrollAdjust
249
+ })
283
250
  },
284
251
  getComponent(ListEmptyComponent)
285
252
  ),
286
- /* @__PURE__ */ React7.createElement(
253
+ /* @__PURE__ */ React5.createElement(
287
254
  Containers,
288
255
  {
289
256
  horizontal,
@@ -293,7 +260,7 @@ var ListComponent = React7.memo(function ListComponent2({
293
260
  updateItemSize
294
261
  }
295
262
  ),
296
- ListFooterComponent && /* @__PURE__ */ React7.createElement(View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
263
+ ListFooterComponent && /* @__PURE__ */ React5.createElement(View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
297
264
  );
298
265
  });
299
266
  var symbolFirst = Symbol();
@@ -458,10 +425,10 @@ var INITIAL_SCROLL_ADJUST = 1e4;
458
425
  var POSITION_OUT_OF_VIEW = -1e7;
459
426
  var DEFAULT_ITEM_SIZE = 100;
460
427
  var LegendList = forwardRef(function LegendList2(props, forwardedRef) {
461
- return /* @__PURE__ */ React7.createElement(StateProvider, null, /* @__PURE__ */ React7.createElement(LegendListInner, { ...props, ref: forwardedRef }));
428
+ return /* @__PURE__ */ React5.createElement(StateProvider, null, /* @__PURE__ */ React5.createElement(LegendListInner, { ...props, ref: forwardedRef }));
462
429
  });
463
430
  var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef) {
464
- var _a, _b, _c, _d, _e;
431
+ var _a, _b, _c, _d, _e, _f;
465
432
  const {
466
433
  data,
467
434
  initialScrollIndex,
@@ -478,7 +445,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
478
445
  maintainVisibleContentPosition = false,
479
446
  onScroll: onScrollProp,
480
447
  numColumns: numColumnsProp = 1,
481
- keyExtractor,
448
+ keyExtractor: keyExtractorProp,
482
449
  renderItem,
483
450
  estimatedItemSize,
484
451
  getEstimatedItemSize,
@@ -492,6 +459,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
492
459
  const internalRef = useRef(null);
493
460
  const refScroller = internalRef;
494
461
  const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE;
462
+ const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
495
463
  const refState = useRef();
496
464
  const getId = (index) => {
497
465
  var _a2;
@@ -562,7 +530,8 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
562
530
  scrollVelocity: 0,
563
531
  contentSize: { width: 0, height: 0 },
564
532
  sizesLaidOut: __DEV__ ? /* @__PURE__ */ new Map() : void 0,
565
- timeoutSizeMessage: 0
533
+ timeoutSizeMessage: 0,
534
+ scrollTimer: void 0
566
535
  };
567
536
  refState.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
568
537
  set$(ctx, "scrollAdjust", refState.current.scrollAdjustPending);
@@ -620,7 +589,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
620
589
  }
621
590
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
622
591
  const scrollAdjustPending = (_a2 = state.scrollAdjustPending) != null ? _a2 : 0;
623
- const scrollExtra = Math.max(-16, Math.min(16, speed)) * 32;
592
+ const scrollExtra = Math.max(-16, Math.min(16, speed)) * 16;
624
593
  const scroll = Math.max(
625
594
  0,
626
595
  scrollState - topPad - (USE_CONTENT_INSET ? scrollAdjustPending : 0) + scrollExtra
@@ -814,19 +783,22 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
814
783
  return;
815
784
  }
816
785
  const { scrollLength, scroll, contentSize } = refState.current;
817
- const distanceFromEnd = contentSize[horizontal ? "width" : "height"] - scroll - scrollLength;
818
- if (refState.current) {
819
- refState.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
820
- }
821
- if (onEndReached) {
822
- if (!refState.current.isEndReached) {
823
- if (distanceFromEnd < onEndReachedThreshold * scrollLength) {
824
- refState.current.isEndReached = true;
825
- onEndReached({ distanceFromEnd });
826
- }
827
- } else {
828
- if (distanceFromEnd >= onEndReachedThreshold * scrollLength) {
829
- refState.current.isEndReached = false;
786
+ const contentLength = contentSize[horizontal ? "width" : "height"];
787
+ if (scroll > 0 && contentLength > 0) {
788
+ const distanceFromEnd = contentLength - scroll - scrollLength;
789
+ if (refState.current) {
790
+ refState.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
791
+ }
792
+ if (onEndReached) {
793
+ if (!refState.current.isEndReached) {
794
+ if (distanceFromEnd < onEndReachedThreshold * scrollLength) {
795
+ refState.current.isEndReached = true;
796
+ onEndReached({ distanceFromEnd });
797
+ }
798
+ } else {
799
+ if (distanceFromEnd >= onEndReachedThreshold * scrollLength) {
800
+ refState.current.isEndReached = false;
801
+ }
830
802
  }
831
803
  }
832
804
  }
@@ -854,7 +826,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
854
826
  };
855
827
  const isFirst = !refState.current.renderItem;
856
828
  if (isFirst || data !== refState.current.data || numColumnsProp !== peek$(ctx, "numColumns")) {
857
- if (!keyExtractor && !isFirst && data !== refState.current.data) {
829
+ if (!keyExtractorProp && !isFirst && data !== refState.current.data) {
858
830
  refState.current.sizes.clear();
859
831
  refState.current.positions.clear();
860
832
  }
@@ -895,11 +867,14 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
895
867
  refState.current.isEndReached = false;
896
868
  const numContainers = peek$(ctx, "numContainers");
897
869
  for (let i = 0; i < numContainers; i++) {
898
- set$(ctx, `containerItemKey${i}`, void 0);
899
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
900
- set$(ctx, `containerColumn${i}`, -1);
870
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
871
+ if (!keyExtractorProp || itemKey && ((_b = refState.current) == null ? void 0 : _b.indexByKey.get(itemKey)) === void 0) {
872
+ set$(ctx, `containerItemKey${i}`, void 0);
873
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
874
+ set$(ctx, `containerColumn${i}`, -1);
875
+ }
901
876
  }
902
- if (!keyExtractor) {
877
+ if (!keyExtractorProp) {
903
878
  refState.current.sizes.clear();
904
879
  refState.current.positions;
905
880
  }
@@ -915,7 +890,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
915
890
  set$(
916
891
  ctx,
917
892
  "stylePaddingTop",
918
- (_e = (_d = (_b = StyleSheet.flatten(style)) == null ? void 0 : _b.paddingTop) != null ? _d : (_c = StyleSheet.flatten(contentContainerStyle)) == null ? void 0 : _c.paddingTop) != null ? _e : 0
893
+ (_f = (_e = (_c = StyleSheet.flatten(style)) == null ? void 0 : _c.paddingTop) != null ? _e : (_d = StyleSheet.flatten(contentContainerStyle)) == null ? void 0 : _d.paddingTop) != null ? _f : 0
919
894
  );
920
895
  const getRenderedItem = useCallback((key, containerId) => {
921
896
  var _a2, _b2;
@@ -1026,7 +1001,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1026
1001
  set$(ctx, "numContainersPooled", numContainers * 2);
1027
1002
  calculateItemsInView();
1028
1003
  });
1029
- const updateItemSize = useCallback((key, size) => {
1004
+ const updateItemSize = useCallback((containerId, itemKey, size) => {
1030
1005
  var _a2;
1031
1006
  const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
1032
1007
  if (!data2) {
@@ -1034,14 +1009,14 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1034
1009
  }
1035
1010
  const state = refState.current;
1036
1011
  const { sizes, indexByKey, idsInFirstRender, columns, sizesLaidOut } = state;
1037
- const index = indexByKey.get(key);
1038
- const wasInFirstRender = idsInFirstRender.has(key);
1039
- const prevSize = sizes.get(key) || (wasInFirstRender ? getItemSize(key, index, data2[index]) : 0);
1012
+ const index = indexByKey.get(itemKey);
1013
+ const wasInFirstRender = idsInFirstRender.has(itemKey);
1014
+ const prevSize = sizes.get(itemKey) || (wasInFirstRender ? getItemSize(itemKey, index, data2[index]) : 0);
1040
1015
  if (!prevSize || Math.abs(prevSize - size) > 0.5) {
1041
1016
  let diff;
1042
1017
  const numColumns = peek$(ctx, "numColumns");
1043
1018
  if (numColumns > 1) {
1044
- const column = columns.get(key);
1019
+ const column = columns.get(itemKey);
1045
1020
  const loopStart = index - (column - 1);
1046
1021
  let prevMaxSizeInRow = 0;
1047
1022
  for (let i = loopStart; i < loopStart + numColumns; i++) {
@@ -1049,7 +1024,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1049
1024
  const size2 = getItemSize(id, i, data2[i]);
1050
1025
  prevMaxSizeInRow = Math.max(prevMaxSizeInRow, size2);
1051
1026
  }
1052
- sizes.set(key, size);
1027
+ sizes.set(itemKey, size);
1053
1028
  let nextMaxSizeInRow = 0;
1054
1029
  for (let i = loopStart; i < loopStart + numColumns; i++) {
1055
1030
  const id = getId(i);
@@ -1058,11 +1033,11 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1058
1033
  }
1059
1034
  diff = nextMaxSizeInRow - prevMaxSizeInRow;
1060
1035
  } else {
1061
- sizes.set(key, size);
1036
+ sizes.set(itemKey, size);
1062
1037
  diff = size - prevSize;
1063
1038
  }
1064
1039
  if (__DEV__ && !estimatedItemSize && !getEstimatedItemSize) {
1065
- sizesLaidOut.set(key, size);
1040
+ sizesLaidOut.set(itemKey, size);
1066
1041
  if (state.timeoutSizeMessage) {
1067
1042
  clearTimeout(state.timeoutSizeMessage);
1068
1043
  }
@@ -1070,7 +1045,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1070
1045
  state.timeoutSizeMessage = void 0;
1071
1046
  let total = 0;
1072
1047
  let num = 0;
1073
- for (const [key2, size2] of sizesLaidOut) {
1048
+ for (const [key, size2] of sizesLaidOut) {
1074
1049
  num++;
1075
1050
  total += size2;
1076
1051
  }
@@ -1080,14 +1055,18 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1080
1055
  );
1081
1056
  }, 1e3);
1082
1057
  }
1083
- addTotalSize(key, diff);
1058
+ addTotalSize(itemKey, diff);
1084
1059
  doMaintainScrollAtEnd(true);
1085
1060
  const scrollVelocity = state.scrollVelocity;
1086
1061
  if (!state.animFrameLayout && (Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1)) {
1087
- state.animFrameLayout = requestAnimationFrame(() => {
1088
- state.animFrameLayout = null;
1062
+ if (!peek$(ctx, `containerDidLayout${containerId}`)) {
1063
+ state.animFrameLayout = requestAnimationFrame(() => {
1064
+ state.animFrameLayout = null;
1065
+ calculateItemsInView(state.scrollVelocity);
1066
+ });
1067
+ } else {
1089
1068
  calculateItemsInView(state.scrollVelocity);
1090
- });
1069
+ }
1091
1070
  }
1092
1071
  }
1093
1072
  }, []);
@@ -1132,10 +1111,18 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1132
1111
  state.contentSize = event.nativeEvent.contentSize;
1133
1112
  const currentTime = performance.now();
1134
1113
  const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
1135
- state.scrollHistory.push({ scroll: newScroll, time: currentTime });
1114
+ if (!(state.scrollHistory.length === 0 && newScroll === initialContentOffset)) {
1115
+ state.scrollHistory.push({ scroll: newScroll, time: currentTime });
1116
+ }
1136
1117
  if (state.scrollHistory.length > 5) {
1137
1118
  state.scrollHistory.shift();
1138
1119
  }
1120
+ if (state.scrollTimer !== void 0) {
1121
+ clearTimeout(state.scrollTimer);
1122
+ }
1123
+ state.scrollTimer = setTimeout(() => {
1124
+ state.scrollVelocity = 0;
1125
+ }, 500);
1139
1126
  let velocity = 0;
1140
1127
  if (state.scrollHistory.length >= 2) {
1141
1128
  const newest = state.scrollHistory[state.scrollHistory.length - 1];
@@ -1185,7 +1172,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1185
1172
  },
1186
1173
  []
1187
1174
  );
1188
- return /* @__PURE__ */ React7.createElement(
1175
+ return /* @__PURE__ */ React5.createElement(
1189
1176
  ListComponent,
1190
1177
  {
1191
1178
  ...rest,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "0.5.7",
3
+ "version": "0.5.9",
4
4
  "description": "legend-list",
5
5
  "sideEffects": false,
6
6
  "private": false,