@legendapp/list 3.0.0-beta.32 → 3.0.0-beta.33

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.
Files changed (54) hide show
  1. package/README.md +7 -1
  2. package/animated.d.ts +600 -6
  3. package/animated.js +2 -2
  4. package/animated.mjs +1 -1
  5. package/index.d.ts +454 -108
  6. package/index.js +81 -32
  7. package/index.mjs +81 -32
  8. package/index.native.js +89 -44
  9. package/index.native.mjs +88 -43
  10. package/keyboard-controller.d.ts +611 -6
  11. package/keyboard-controller.js +2 -2
  12. package/keyboard-controller.mjs +1 -1
  13. package/keyboard.d.ts +204 -8
  14. package/keyboard.js +66 -52
  15. package/keyboard.mjs +69 -54
  16. package/{index.d.mts → list-react-native.d.ts} +95 -32
  17. package/list-react-native.js +4234 -0
  18. package/list-react-native.mjs +4204 -0
  19. package/{index.native.d.mts → list-react.d.ts} +355 -40
  20. package/list-react.js +4426 -0
  21. package/list-react.mjs +4396 -0
  22. package/package.json +52 -1
  23. package/reanimated.d.ts +595 -7
  24. package/reanimated.js +156 -11
  25. package/reanimated.mjs +153 -8
  26. package/section-list.d.ts +610 -14
  27. package/section-list.js +6 -6
  28. package/section-list.mjs +1 -1
  29. package/animated.d.mts +0 -9
  30. package/animated.native.d.mts +0 -9
  31. package/animated.native.d.ts +0 -9
  32. package/animated.native.js +0 -9
  33. package/animated.native.mjs +0 -7
  34. package/index.native.d.ts +0 -817
  35. package/keyboard-controller.d.mts +0 -12
  36. package/keyboard-controller.native.d.mts +0 -12
  37. package/keyboard-controller.native.d.ts +0 -12
  38. package/keyboard-controller.native.js +0 -69
  39. package/keyboard-controller.native.mjs +0 -48
  40. package/keyboard.d.mts +0 -13
  41. package/keyboard.native.d.mts +0 -13
  42. package/keyboard.native.d.ts +0 -13
  43. package/keyboard.native.js +0 -399
  44. package/keyboard.native.mjs +0 -377
  45. package/reanimated.d.mts +0 -18
  46. package/reanimated.native.d.mts +0 -18
  47. package/reanimated.native.d.ts +0 -18
  48. package/reanimated.native.js +0 -89
  49. package/reanimated.native.mjs +0 -65
  50. package/section-list.d.mts +0 -112
  51. package/section-list.native.d.mts +0 -112
  52. package/section-list.native.d.ts +0 -112
  53. package/section-list.native.js +0 -293
  54. package/section-list.native.mjs +0 -271
package/keyboard.d.ts CHANGED
@@ -1,13 +1,209 @@
1
- import * as React from 'react';
2
- import { Insets } from 'react-native';
3
- import { ReanimatedScrollEvent } from 'react-native-reanimated/lib/typescript/hook/commonTypes';
4
- import { LegendListRef } from '@legendapp/list';
1
+ import * as React$1 from 'react';
2
+ import { ScrollViewComponent, ScrollResponderMixin, Insets as Insets$1 } from 'react-native';
3
+ import { ScrollEvent, ScrollHandlerProcessed } from 'react-native-reanimated';
5
4
  import { AnimatedLegendListProps } from '@legendapp/list/reanimated';
6
5
 
6
+ type ListenerType = "activeStickyIndex" | "debugComputedScroll" | "debugRawScroll" | "extraData" | "footerSize" | "headerSize" | "lastItemKeys" | "lastPositionUpdate" | "maintainVisibleContentPosition" | "numColumns" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "scrollAdjust" | "scrollAdjustPending" | "scrollAdjustUserOffset" | "scrollSize" | "snapToOffsets" | "stylePaddingTop" | "totalSize" | `containerColumn${number}` | `containerSpan${number}` | `containerItemData${number}` | `containerItemKey${number}` | `containerPosition${number}` | `containerSticky${number}`;
7
+ type LegendListListenerType = Extract<ListenerType, "activeStickyIndex" | "footerSize" | "headerSize" | "lastItemKeys" | "lastPositionUpdate" | "numContainers" | "numContainersPooled" | "otherAxisSize" | "readyToRender" | "snapToOffsets" | "totalSize">;
8
+ type ListenerTypeValueMap = {
9
+ activeStickyIndex: number;
10
+ animatedScrollY: any;
11
+ debugComputedScroll: number;
12
+ debugRawScroll: number;
13
+ extraData: any;
14
+ footerSize: number;
15
+ headerSize: number;
16
+ lastItemKeys: string[];
17
+ lastPositionUpdate: number;
18
+ maintainVisibleContentPosition: MaintainVisibleContentPositionNormalized;
19
+ numColumns: number;
20
+ numContainers: number;
21
+ numContainersPooled: number;
22
+ otherAxisSize: number;
23
+ readyToRender: boolean;
24
+ scrollAdjust: number;
25
+ scrollAdjustPending: number;
26
+ scrollAdjustUserOffset: number;
27
+ scrollSize: {
28
+ width: number;
29
+ height: number;
30
+ };
31
+ snapToOffsets: number[];
32
+ stylePaddingTop: number;
33
+ totalSize: number;
34
+ } & {
35
+ [K in ListenerType as K extends `containerItemKey${number}` ? K : never]: string;
36
+ } & {
37
+ [K in ListenerType as K extends `containerItemData${number}` ? K : never]: any;
38
+ } & {
39
+ [K in ListenerType as K extends `containerPosition${number}` ? K : never]: number;
40
+ } & {
41
+ [K in ListenerType as K extends `containerColumn${number}` ? K : never]: number;
42
+ } & {
43
+ [K in ListenerType as K extends `containerSpan${number}` ? K : never]: number;
44
+ } & {
45
+ [K in ListenerType as K extends `containerSticky${number}` ? K : never]: boolean;
46
+ };
47
+
48
+ interface Insets {
49
+ top: number;
50
+ left: number;
51
+ bottom: number;
52
+ right: number;
53
+ }
54
+ interface MaintainVisibleContentPositionNormalized<ItemT = any> {
55
+ data: boolean;
56
+ size: boolean;
57
+ shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
58
+ }
59
+ type LegendListState = {
60
+ activeStickyIndex: number;
61
+ contentLength: number;
62
+ data: readonly any[];
63
+ elementAtIndex: (index: number) => any;
64
+ end: number;
65
+ endBuffered: number;
66
+ isAtEnd: boolean;
67
+ isAtStart: boolean;
68
+ listen: <T extends LegendListListenerType>(listenerType: T, callback: (value: ListenerTypeValueMap[T]) => void) => () => void;
69
+ listenToPosition: (key: string, callback: (value: number) => void) => () => void;
70
+ positionAtIndex: (index: number) => number;
71
+ positions: Map<string, number>;
72
+ scroll: number;
73
+ scrollLength: number;
74
+ scrollVelocity: number;
75
+ sizeAtIndex: (index: number) => number;
76
+ sizes: Map<string, number>;
77
+ start: number;
78
+ startBuffered: number;
79
+ };
80
+ type LegendListRef$1 = {
81
+ /**
82
+ * Displays the scroll indicators momentarily.
83
+ */
84
+ flashScrollIndicators(): void;
85
+ /**
86
+ * Returns the native ScrollView component reference.
87
+ */
88
+ getNativeScrollRef(): any;
89
+ /**
90
+ * Returns the scroll responder instance for handling scroll events.
91
+ */
92
+ getScrollableNode(): any;
93
+ /**
94
+ * Returns the ScrollResponderMixin for advanced scroll handling.
95
+ */
96
+ getScrollResponder(): any;
97
+ /**
98
+ * Returns the internal state of the scroll virtualization.
99
+ */
100
+ getState(): LegendListState;
101
+ /**
102
+ * Scrolls a specific index into view.
103
+ * @param params - Parameters for scrolling.
104
+ * @param params.animated - If true, animates the scroll. Default: true.
105
+ * @param params.index - The index to scroll to.
106
+ */
107
+ scrollIndexIntoView(params: {
108
+ animated?: boolean | undefined;
109
+ index: number;
110
+ }): void;
111
+ /**
112
+ * Scrolls a specific index into view.
113
+ * @param params - Parameters for scrolling.
114
+ * @param params.animated - If true, animates the scroll. Default: true.
115
+ * @param params.item - The item to scroll to.
116
+ */
117
+ scrollItemIntoView(params: {
118
+ animated?: boolean | undefined;
119
+ item: any;
120
+ }): void;
121
+ /**
122
+ * Scrolls to the end of the list.
123
+ * @param options - Options for scrolling.
124
+ * @param options.animated - If true, animates the scroll. Default: true.
125
+ * @param options.viewOffset - Offset from the target position.
126
+ */
127
+ scrollToEnd(options?: {
128
+ animated?: boolean | undefined;
129
+ viewOffset?: number | undefined;
130
+ }): void;
131
+ /**
132
+ * Scrolls to a specific index in the list.
133
+ * @param params - Parameters for scrolling.
134
+ * @param params.animated - If true, animates the scroll. Default: true.
135
+ * @param params.index - The index to scroll to.
136
+ * @param params.viewOffset - Offset from the target position.
137
+ * @param params.viewPosition - Position of the item in the viewport (0 to 1).
138
+ */
139
+ scrollToIndex(params: {
140
+ animated?: boolean | undefined;
141
+ index: number;
142
+ viewOffset?: number | undefined;
143
+ viewPosition?: number | undefined;
144
+ }): void;
145
+ /**
146
+ * Scrolls to a specific item in the list.
147
+ * @param params - Parameters for scrolling.
148
+ * @param params.animated - If true, animates the scroll. Default: true.
149
+ * @param params.item - The item to scroll to.
150
+ * @param params.viewOffset - Offset from the target position.
151
+ * @param params.viewPosition - Position of the item in the viewport (0 to 1).
152
+ */
153
+ scrollToItem(params: {
154
+ animated?: boolean | undefined;
155
+ item: any;
156
+ viewOffset?: number | undefined;
157
+ viewPosition?: number | undefined;
158
+ }): void;
159
+ /**
160
+ * Scrolls to a specific offset in pixels.
161
+ * @param params - Parameters for scrolling.
162
+ * @param params.offset - The pixel offset to scroll to.
163
+ * @param params.animated - If true, animates the scroll. Default: true.
164
+ */
165
+ scrollToOffset(params: {
166
+ offset: number;
167
+ animated?: boolean | undefined;
168
+ }): void;
169
+ /**
170
+ * Sets or adds to the offset of the visible content anchor.
171
+ * @param value - The offset to set or add.
172
+ * @param animated - If true, uses Animated to animate the change.
173
+ */
174
+ setVisibleContentAnchorOffset(value: number | ((val: number) => number)): void;
175
+ /**
176
+ * Sets whether scroll processing is enabled.
177
+ * @param enabled - If true, scroll processing is enabled.
178
+ */
179
+ setScrollProcessingEnabled(enabled: boolean): void;
180
+ /**
181
+ * Clears internal virtualization caches.
182
+ * @param options - Cache clearing options.
183
+ * @param options.mode - `sizes` clears measurement caches. `full` also clears key/position caches.
184
+ */
185
+ clearCaches(options?: {
186
+ mode?: "sizes" | "full";
187
+ }): void;
188
+ /**
189
+ * Reports an externally measured content inset. Pass null/undefined to clear.
190
+ * Values are merged on top of props/animated/native insets.
191
+ */
192
+ reportContentInset(inset?: Partial<Insets> | null): void;
193
+ };
194
+
195
+ type LegendListRef = Omit<LegendListRef$1, "getNativeScrollRef" | "getScrollResponder" | "reportContentInset"> & {
196
+ getNativeScrollRef(): React.ElementRef<typeof ScrollViewComponent>;
197
+ getScrollResponder(): ScrollResponderMixin;
198
+ reportContentInset(inset?: Partial<Insets$1> | null): void;
199
+ };
200
+
201
+ type KeyboardOnScrollCallback = (event: ScrollEvent) => void;
202
+ type KeyboardOnScrollHandler = KeyboardOnScrollCallback | ScrollHandlerProcessed<Record<string, unknown>>;
7
203
  declare const KeyboardAvoidingLegendList: <ItemT>(props: Omit<AnimatedLegendListProps<ItemT>, "onScroll" | "automaticallyAdjustContentInsets" | "contentInset"> & {
8
- onScroll?: (event: ReanimatedScrollEvent) => void;
9
- contentInset?: Insets | undefined;
204
+ onScroll?: KeyboardOnScrollHandler;
205
+ contentInset?: Insets$1 | undefined;
10
206
  safeAreaInsetBottom?: number;
11
- } & React.RefAttributes<LegendListRef>) => React.ReactNode;
207
+ } & React$1.RefAttributes<LegendListRef>) => React$1.ReactNode;
12
208
 
13
- export { KeyboardAvoidingLegendList, KeyboardAvoidingLegendList as LegendList };
209
+ export { KeyboardAvoidingLegendList };
package/keyboard.js CHANGED
@@ -95,7 +95,7 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
95
95
  const scrollOffsetY = reactNativeReanimated.useSharedValue(0);
96
96
  const animatedOffsetY = reactNativeReanimated.useSharedValue(null);
97
97
  const scrollOffsetAtKeyboardStart = reactNativeReanimated.useSharedValue(0);
98
- const mode = reactNativeReanimated.useSharedValue("idle");
98
+ const animationMode = reactNativeReanimated.useSharedValue("idle");
99
99
  const keyboardInset = reactNativeReanimated.useSharedValue(0);
100
100
  const keyboardHeight = reactNativeReanimated.useSharedValue(0);
101
101
  const contentLength = reactNativeReanimated.useSharedValue(0);
@@ -106,17 +106,33 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
106
106
  const isKeyboardOpen = reactNativeReanimated.useSharedValue(false);
107
107
  const keyboardInsetRef = React.useRef(0);
108
108
  const [alignItemsAtEndMinSize, setAlignItemsAtEndMinSize] = React.useState(void 0);
109
+ const onScrollValue = onScrollProp;
110
+ const onScrollCallback = typeof onScrollValue === "function" ? onScrollValue : void 0;
111
+ const onScrollProcessed = onScrollValue && typeof onScrollValue === "object" && "workletEventHandler" in onScrollValue ? onScrollValue : null;
112
+ const onScrollCallbackIsWorklet = React.useMemo(
113
+ () => onScrollCallback ? reactNativeReanimated.isWorkletFunction(onScrollCallback) : false,
114
+ [onScrollCallback]
115
+ );
109
116
  const scrollHandler = reactNativeReanimated.useAnimatedScrollHandler(
110
117
  (event) => {
111
- if (mode.get() !== "running" || didInteractive.get()) {
118
+ if (animationMode.get() !== "running" || didInteractive.get()) {
112
119
  scrollOffsetY.set(event.contentOffset[horizontal ? "x" : "y"]);
113
120
  }
114
- if (onScrollProp) {
115
- reactNativeReanimated.runOnJS(onScrollProp)(event);
121
+ if (onScrollCallback) {
122
+ if (onScrollCallbackIsWorklet) {
123
+ onScrollCallback(event);
124
+ } else {
125
+ reactNativeReanimated.runOnJS(onScrollCallback)(event);
126
+ }
116
127
  }
117
128
  },
118
- [onScrollProp, horizontal]
129
+ [horizontal, onScrollCallback, onScrollCallbackIsWorklet]
119
130
  );
131
+ const composedScrollHandler = reactNativeReanimated.useComposedEventHandler([
132
+ scrollHandler,
133
+ onScrollProcessed
134
+ ]);
135
+ const finalScrollHandler = onScrollProcessed ? composedScrollHandler : scrollHandler;
120
136
  const setScrollProcessingEnabled = React.useCallback(
121
137
  (enabled) => {
122
138
  var _a;
@@ -184,19 +200,39 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
184
200
  React.useEffect(() => {
185
201
  updateAlignItemsAtEndMinSize();
186
202
  }, [updateAlignItemsAtEndMinSize]);
203
+ const getEffectiveKeyboardHeightFromInset = React.useCallback(
204
+ (nextKeyboardInset) => {
205
+ "worklet";
206
+ return calculateEffectiveKeyboardHeight(
207
+ nextKeyboardInset,
208
+ contentLength.get(),
209
+ scrollLength.get(),
210
+ alignItemsAtEnd
211
+ );
212
+ },
213
+ [alignItemsAtEnd, contentLength, scrollLength]
214
+ );
215
+ const getEffectiveKeyboardHeightFromEvent = React.useCallback(
216
+ (eventHeight) => {
217
+ "worklet";
218
+ const nextKeyboardInset = calculateKeyboardInset(eventHeight, safeAreaInsetBottom);
219
+ return getEffectiveKeyboardHeightFromInset(nextKeyboardInset);
220
+ },
221
+ [getEffectiveKeyboardHeightFromInset, safeAreaInsetBottom]
222
+ );
187
223
  reactNativeKeyboardController.useKeyboardHandler(
188
224
  // biome-ignore assist/source/useSortedKeys: prefer start/move/end
189
225
  {
190
226
  onStart: (event) => {
191
227
  "worklet";
192
- mode.set("running");
228
+ animationMode.set("running");
193
229
  const progress = clampProgress(event.progress);
194
230
  if (isKeyboardOpen.get() && progress >= 1 && event.height > 0) {
195
231
  return;
196
232
  }
197
233
  if (!didInteractive.get()) {
198
234
  if (event.height > 0) {
199
- keyboardHeight.set(event.height - safeAreaInsetBottom);
235
+ keyboardHeight.set(calculateKeyboardInset(event.height, safeAreaInsetBottom));
200
236
  }
201
237
  const vIsOpening = progress > 0;
202
238
  isOpening.set(vIsOpening);
@@ -209,15 +245,7 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
209
245
  const vScrollOffset = scrollOffsetY.get();
210
246
  scrollOffsetAtKeyboardStart.set(vScrollOffset);
211
247
  if (isIos) {
212
- const vContentLength = contentLength.get();
213
- const vScrollLength = scrollLength.get();
214
- const vKeyboardHeight = keyboardHeight.get();
215
- const vEffectiveKeyboardHeight = calculateEffectiveKeyboardHeight(
216
- vKeyboardHeight,
217
- vContentLength,
218
- vScrollLength,
219
- alignItemsAtEnd
220
- );
248
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromInset(keyboardHeight.get());
221
249
  const targetOffset = Math.max(
222
250
  0,
223
251
  vIsOpening ? vScrollOffset + vEffectiveKeyboardHeight : vScrollOffset - vEffectiveKeyboardHeight
@@ -234,10 +262,10 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
234
262
  },
235
263
  onInteractive: (event) => {
236
264
  "worklet";
237
- if (mode.get() !== "running") {
265
+ if (animationMode.get() !== "running") {
238
266
  reactNativeReanimated.runOnJS(setScrollProcessingEnabled)(false);
239
267
  }
240
- mode.set("running");
268
+ animationMode.set("running");
241
269
  if (!didInteractive.get()) {
242
270
  didInteractive.set(true);
243
271
  }
@@ -246,13 +274,7 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
246
274
  keyboardInset.set(newInset);
247
275
  }
248
276
  if (shouldUpdateAlignItemsAtEndMinSize.get() && !horizontal && alignItemsAtEnd) {
249
- const vKeyboardHeight = calculateKeyboardInset(event.height, safeAreaInsetBottom);
250
- const vEffectiveKeyboardHeight = calculateEffectiveKeyboardHeight(
251
- vKeyboardHeight,
252
- contentLength.get(),
253
- scrollLength.get(),
254
- alignItemsAtEnd
255
- );
277
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromEvent(event.height);
256
278
  reactNativeReanimated.runOnJS(updateAlignItemsAtEndMinSize)(vEffectiveKeyboardHeight);
257
279
  }
258
280
  },
@@ -262,13 +284,7 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
262
284
  if (isAndroid) {
263
285
  if (!didInteractive.get()) {
264
286
  const progress = clampProgress(event.progress);
265
- const vKeyboardHeight = keyboardHeight.get();
266
- const vEffectiveKeyboardHeight = calculateEffectiveKeyboardHeight(
267
- vKeyboardHeight,
268
- contentLength.get(),
269
- scrollLength.get(),
270
- alignItemsAtEnd
271
- );
287
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromInset(keyboardHeight.get());
272
288
  const targetOffset = calculateKeyboardTargetOffset(
273
289
  scrollOffsetAtKeyboardStart.get(),
274
290
  vEffectiveKeyboardHeight,
@@ -284,30 +300,18 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
284
300
  }
285
301
  }
286
302
  if (!horizontal && alignItemsAtEnd && !vIsOpening && shouldUpdateAlignItemsAtEndMinSize.get()) {
287
- const vKeyboardHeight = calculateKeyboardInset(event.height, safeAreaInsetBottom);
288
- const vEffectiveKeyboardHeight = calculateEffectiveKeyboardHeight(
289
- vKeyboardHeight,
290
- contentLength.get(),
291
- scrollLength.get(),
292
- alignItemsAtEnd
293
- );
303
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromEvent(event.height);
294
304
  reactNativeReanimated.runOnJS(updateAlignItemsAtEndMinSize)(vEffectiveKeyboardHeight);
295
305
  }
296
306
  },
297
307
  onEnd: (event) => {
298
308
  "worklet";
299
309
  const wasInteractive = didInteractive.get();
300
- const vMode = mode.get();
301
- mode.set("idle");
310
+ const vMode = animationMode.get();
311
+ animationMode.set("idle");
302
312
  if (vMode === "running") {
303
313
  const progress = clampProgress(event.progress);
304
- const vKeyboardHeight = keyboardHeight.get();
305
- const vEffectiveKeyboardHeight = calculateEffectiveKeyboardHeight(
306
- vKeyboardHeight,
307
- contentLength.get(),
308
- scrollLength.get(),
309
- alignItemsAtEnd
310
- );
314
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromInset(keyboardHeight.get());
311
315
  const vIsOpening = isOpening.get();
312
316
  if (!wasInteractive) {
313
317
  const targetOffset = calculateKeyboardTargetOffset(
@@ -336,7 +340,18 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
336
340
  }
337
341
  }
338
342
  },
339
- [alignItemsAtEnd, horizontal, safeAreaInsetBottom, scrollViewRef]
343
+ [
344
+ alignItemsAtEnd,
345
+ clearAlignItemsAtEndMinSize,
346
+ getEffectiveKeyboardHeightFromEvent,
347
+ getEffectiveKeyboardHeightFromInset,
348
+ horizontal,
349
+ reportContentInset,
350
+ safeAreaInsetBottom,
351
+ scrollViewRef,
352
+ setScrollProcessingEnabled,
353
+ updateAlignItemsAtEndMinSize
354
+ ]
340
355
  );
341
356
  const animatedProps = reactNativeReanimated.useAnimatedProps(() => {
342
357
  "worklet";
@@ -369,7 +384,7 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
369
384
  marginBottom: keyboardInset.get()
370
385
  }),
371
386
  [styleProp, keyboardInset]
372
- ) : void 0;
387
+ ) : styleProp;
373
388
  const contentContainerStyle = React.useMemo(() => {
374
389
  if (alignItemsAtEndMinSize === void 0) {
375
390
  return contentContainerStyleProp;
@@ -386,7 +401,7 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
386
401
  contentContainerStyle,
387
402
  keyboardDismissMode: "interactive",
388
403
  onMetricsChange: handleMetricsChange,
389
- onScroll: scrollHandler,
404
+ onScroll: finalScrollHandler,
390
405
  ref: combinedRef,
391
406
  refScrollView: scrollViewRef,
392
407
  scrollIndicatorInsets: { bottom: 0, top: 0 },
@@ -396,4 +411,3 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
396
411
  });
397
412
 
398
413
  exports.KeyboardAvoidingLegendList = KeyboardAvoidingLegendList;
399
- exports.LegendList = KeyboardAvoidingLegendList;
package/keyboard.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
- import { forwardRef, useRef, useState, useCallback, useEffect, useMemo } from 'react';
2
+ import { forwardRef, useRef, useState, useMemo, useCallback, useEffect } from 'react';
3
3
  import { StyleSheet, Platform } from 'react-native';
4
4
  import { useKeyboardHandler } from 'react-native-keyboard-controller';
5
- import { useAnimatedRef, useSharedValue, useAnimatedScrollHandler, runOnJS, useAnimatedProps, useAnimatedStyle } from 'react-native-reanimated';
5
+ import { useAnimatedRef, useSharedValue, isWorkletFunction, useAnimatedScrollHandler, runOnJS, useComposedEventHandler, useAnimatedProps, useAnimatedStyle } from 'react-native-reanimated';
6
6
  import { AnimatedLegendList } from '@legendapp/list/reanimated';
7
7
 
8
8
  // src/integrations/keyboard.tsx
@@ -74,7 +74,7 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
74
74
  const scrollOffsetY = useSharedValue(0);
75
75
  const animatedOffsetY = useSharedValue(null);
76
76
  const scrollOffsetAtKeyboardStart = useSharedValue(0);
77
- const mode = useSharedValue("idle");
77
+ const animationMode = useSharedValue("idle");
78
78
  const keyboardInset = useSharedValue(0);
79
79
  const keyboardHeight = useSharedValue(0);
80
80
  const contentLength = useSharedValue(0);
@@ -85,17 +85,33 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
85
85
  const isKeyboardOpen = useSharedValue(false);
86
86
  const keyboardInsetRef = useRef(0);
87
87
  const [alignItemsAtEndMinSize, setAlignItemsAtEndMinSize] = useState(void 0);
88
+ const onScrollValue = onScrollProp;
89
+ const onScrollCallback = typeof onScrollValue === "function" ? onScrollValue : void 0;
90
+ const onScrollProcessed = onScrollValue && typeof onScrollValue === "object" && "workletEventHandler" in onScrollValue ? onScrollValue : null;
91
+ const onScrollCallbackIsWorklet = useMemo(
92
+ () => onScrollCallback ? isWorkletFunction(onScrollCallback) : false,
93
+ [onScrollCallback]
94
+ );
88
95
  const scrollHandler = useAnimatedScrollHandler(
89
96
  (event) => {
90
- if (mode.get() !== "running" || didInteractive.get()) {
97
+ if (animationMode.get() !== "running" || didInteractive.get()) {
91
98
  scrollOffsetY.set(event.contentOffset[horizontal ? "x" : "y"]);
92
99
  }
93
- if (onScrollProp) {
94
- runOnJS(onScrollProp)(event);
100
+ if (onScrollCallback) {
101
+ if (onScrollCallbackIsWorklet) {
102
+ onScrollCallback(event);
103
+ } else {
104
+ runOnJS(onScrollCallback)(event);
105
+ }
95
106
  }
96
107
  },
97
- [onScrollProp, horizontal]
108
+ [horizontal, onScrollCallback, onScrollCallbackIsWorklet]
98
109
  );
110
+ const composedScrollHandler = useComposedEventHandler([
111
+ scrollHandler,
112
+ onScrollProcessed
113
+ ]);
114
+ const finalScrollHandler = onScrollProcessed ? composedScrollHandler : scrollHandler;
99
115
  const setScrollProcessingEnabled = useCallback(
100
116
  (enabled) => {
101
117
  var _a;
@@ -163,19 +179,39 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
163
179
  useEffect(() => {
164
180
  updateAlignItemsAtEndMinSize();
165
181
  }, [updateAlignItemsAtEndMinSize]);
182
+ const getEffectiveKeyboardHeightFromInset = useCallback(
183
+ (nextKeyboardInset) => {
184
+ "worklet";
185
+ return calculateEffectiveKeyboardHeight(
186
+ nextKeyboardInset,
187
+ contentLength.get(),
188
+ scrollLength.get(),
189
+ alignItemsAtEnd
190
+ );
191
+ },
192
+ [alignItemsAtEnd, contentLength, scrollLength]
193
+ );
194
+ const getEffectiveKeyboardHeightFromEvent = useCallback(
195
+ (eventHeight) => {
196
+ "worklet";
197
+ const nextKeyboardInset = calculateKeyboardInset(eventHeight, safeAreaInsetBottom);
198
+ return getEffectiveKeyboardHeightFromInset(nextKeyboardInset);
199
+ },
200
+ [getEffectiveKeyboardHeightFromInset, safeAreaInsetBottom]
201
+ );
166
202
  useKeyboardHandler(
167
203
  // biome-ignore assist/source/useSortedKeys: prefer start/move/end
168
204
  {
169
205
  onStart: (event) => {
170
206
  "worklet";
171
- mode.set("running");
207
+ animationMode.set("running");
172
208
  const progress = clampProgress(event.progress);
173
209
  if (isKeyboardOpen.get() && progress >= 1 && event.height > 0) {
174
210
  return;
175
211
  }
176
212
  if (!didInteractive.get()) {
177
213
  if (event.height > 0) {
178
- keyboardHeight.set(event.height - safeAreaInsetBottom);
214
+ keyboardHeight.set(calculateKeyboardInset(event.height, safeAreaInsetBottom));
179
215
  }
180
216
  const vIsOpening = progress > 0;
181
217
  isOpening.set(vIsOpening);
@@ -188,15 +224,7 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
188
224
  const vScrollOffset = scrollOffsetY.get();
189
225
  scrollOffsetAtKeyboardStart.set(vScrollOffset);
190
226
  if (isIos) {
191
- const vContentLength = contentLength.get();
192
- const vScrollLength = scrollLength.get();
193
- const vKeyboardHeight = keyboardHeight.get();
194
- const vEffectiveKeyboardHeight = calculateEffectiveKeyboardHeight(
195
- vKeyboardHeight,
196
- vContentLength,
197
- vScrollLength,
198
- alignItemsAtEnd
199
- );
227
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromInset(keyboardHeight.get());
200
228
  const targetOffset = Math.max(
201
229
  0,
202
230
  vIsOpening ? vScrollOffset + vEffectiveKeyboardHeight : vScrollOffset - vEffectiveKeyboardHeight
@@ -213,10 +241,10 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
213
241
  },
214
242
  onInteractive: (event) => {
215
243
  "worklet";
216
- if (mode.get() !== "running") {
244
+ if (animationMode.get() !== "running") {
217
245
  runOnJS(setScrollProcessingEnabled)(false);
218
246
  }
219
- mode.set("running");
247
+ animationMode.set("running");
220
248
  if (!didInteractive.get()) {
221
249
  didInteractive.set(true);
222
250
  }
@@ -225,13 +253,7 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
225
253
  keyboardInset.set(newInset);
226
254
  }
227
255
  if (shouldUpdateAlignItemsAtEndMinSize.get() && !horizontal && alignItemsAtEnd) {
228
- const vKeyboardHeight = calculateKeyboardInset(event.height, safeAreaInsetBottom);
229
- const vEffectiveKeyboardHeight = calculateEffectiveKeyboardHeight(
230
- vKeyboardHeight,
231
- contentLength.get(),
232
- scrollLength.get(),
233
- alignItemsAtEnd
234
- );
256
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromEvent(event.height);
235
257
  runOnJS(updateAlignItemsAtEndMinSize)(vEffectiveKeyboardHeight);
236
258
  }
237
259
  },
@@ -241,13 +263,7 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
241
263
  if (isAndroid) {
242
264
  if (!didInteractive.get()) {
243
265
  const progress = clampProgress(event.progress);
244
- const vKeyboardHeight = keyboardHeight.get();
245
- const vEffectiveKeyboardHeight = calculateEffectiveKeyboardHeight(
246
- vKeyboardHeight,
247
- contentLength.get(),
248
- scrollLength.get(),
249
- alignItemsAtEnd
250
- );
266
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromInset(keyboardHeight.get());
251
267
  const targetOffset = calculateKeyboardTargetOffset(
252
268
  scrollOffsetAtKeyboardStart.get(),
253
269
  vEffectiveKeyboardHeight,
@@ -263,30 +279,18 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
263
279
  }
264
280
  }
265
281
  if (!horizontal && alignItemsAtEnd && !vIsOpening && shouldUpdateAlignItemsAtEndMinSize.get()) {
266
- const vKeyboardHeight = calculateKeyboardInset(event.height, safeAreaInsetBottom);
267
- const vEffectiveKeyboardHeight = calculateEffectiveKeyboardHeight(
268
- vKeyboardHeight,
269
- contentLength.get(),
270
- scrollLength.get(),
271
- alignItemsAtEnd
272
- );
282
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromEvent(event.height);
273
283
  runOnJS(updateAlignItemsAtEndMinSize)(vEffectiveKeyboardHeight);
274
284
  }
275
285
  },
276
286
  onEnd: (event) => {
277
287
  "worklet";
278
288
  const wasInteractive = didInteractive.get();
279
- const vMode = mode.get();
280
- mode.set("idle");
289
+ const vMode = animationMode.get();
290
+ animationMode.set("idle");
281
291
  if (vMode === "running") {
282
292
  const progress = clampProgress(event.progress);
283
- const vKeyboardHeight = keyboardHeight.get();
284
- const vEffectiveKeyboardHeight = calculateEffectiveKeyboardHeight(
285
- vKeyboardHeight,
286
- contentLength.get(),
287
- scrollLength.get(),
288
- alignItemsAtEnd
289
- );
293
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromInset(keyboardHeight.get());
290
294
  const vIsOpening = isOpening.get();
291
295
  if (!wasInteractive) {
292
296
  const targetOffset = calculateKeyboardTargetOffset(
@@ -315,7 +319,18 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
315
319
  }
316
320
  }
317
321
  },
318
- [alignItemsAtEnd, horizontal, safeAreaInsetBottom, scrollViewRef]
322
+ [
323
+ alignItemsAtEnd,
324
+ clearAlignItemsAtEndMinSize,
325
+ getEffectiveKeyboardHeightFromEvent,
326
+ getEffectiveKeyboardHeightFromInset,
327
+ horizontal,
328
+ reportContentInset,
329
+ safeAreaInsetBottom,
330
+ scrollViewRef,
331
+ setScrollProcessingEnabled,
332
+ updateAlignItemsAtEndMinSize
333
+ ]
319
334
  );
320
335
  const animatedProps = useAnimatedProps(() => {
321
336
  "worklet";
@@ -348,7 +363,7 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
348
363
  marginBottom: keyboardInset.get()
349
364
  }),
350
365
  [styleProp, keyboardInset]
351
- ) : void 0;
366
+ ) : styleProp;
352
367
  const contentContainerStyle = useMemo(() => {
353
368
  if (alignItemsAtEndMinSize === void 0) {
354
369
  return contentContainerStyleProp;
@@ -365,7 +380,7 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
365
380
  contentContainerStyle,
366
381
  keyboardDismissMode: "interactive",
367
382
  onMetricsChange: handleMetricsChange,
368
- onScroll: scrollHandler,
383
+ onScroll: finalScrollHandler,
369
384
  ref: combinedRef,
370
385
  refScrollView: scrollViewRef,
371
386
  scrollIndicatorInsets: { bottom: 0, top: 0 },
@@ -374,4 +389,4 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
374
389
  );
375
390
  });
376
391
 
377
- export { KeyboardAvoidingLegendList, KeyboardAvoidingLegendList as LegendList };
392
+ export { KeyboardAvoidingLegendList };