@legendapp/list 3.0.0-beta.9 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.DS_Store +0 -0
  2. package/CHANGELOG.md +21 -1
  3. package/README.md +8 -2
  4. package/animated.d.ts +659 -5
  5. package/animated.js +2 -2
  6. package/animated.mjs +1 -1
  7. package/keyboard-legacy.d.ts +226 -0
  8. package/keyboard-legacy.js +456 -0
  9. package/keyboard-legacy.mjs +435 -0
  10. package/keyboard.d.ts +261 -9
  11. package/keyboard.js +114 -135
  12. package/keyboard.mjs +115 -137
  13. package/package.json +55 -5
  14. package/{types-1Hgg1rTO.d.mts → react-native.d.ts} +269 -284
  15. package/react-native.js +6453 -0
  16. package/react-native.mjs +6424 -0
  17. package/{types-1Hgg1rTO.d.ts → react-native.web.d.ts} +330 -283
  18. package/react-native.web.js +7111 -0
  19. package/react-native.web.mjs +7082 -0
  20. package/react.d.ts +771 -0
  21. package/react.js +7111 -0
  22. package/react.mjs +7082 -0
  23. package/reanimated.d.ts +681 -8
  24. package/reanimated.js +225 -38
  25. package/reanimated.mjs +227 -40
  26. package/section-list.d.ts +663 -5
  27. package/section-list.js +39 -3829
  28. package/section-list.mjs +37 -3828
  29. package/animated.d.mts +0 -9
  30. package/index.d.mts +0 -23
  31. package/index.d.ts +0 -23
  32. package/index.js +0 -3935
  33. package/index.mjs +0 -3907
  34. package/index.native.d.mts +0 -23
  35. package/index.native.d.ts +0 -23
  36. package/index.native.js +0 -3739
  37. package/index.native.mjs +0 -3711
  38. package/keyboard-controller.d.mts +0 -12
  39. package/keyboard-controller.d.ts +0 -12
  40. package/keyboard-controller.js +0 -69
  41. package/keyboard-controller.mjs +0 -48
  42. package/keyboard.d.mts +0 -13
  43. package/reanimated.d.mts +0 -18
  44. package/section-list.d.mts +0 -113
  45. package/section-list.native.d.mts +0 -113
  46. package/section-list.native.d.ts +0 -113
  47. package/section-list.native.js +0 -3897
  48. package/section-list.native.mjs +0 -3876
@@ -0,0 +1,435 @@
1
+ import * as React from 'react';
2
+ import { useRef, useState, useMemo, useCallback, useEffect } from 'react';
3
+ import { StyleSheet, Platform } from 'react-native';
4
+ import { useKeyboardHandler } from 'react-native-keyboard-controller';
5
+ import { useAnimatedRef, useSharedValue, isWorkletFunction, useAnimatedScrollHandler, runOnJS, useComposedEventHandler, useAnimatedProps, useAnimatedStyle } from 'react-native-reanimated';
6
+ import { internal } from '@legendapp/list/react-native';
7
+ import { AnimatedLegendList } from '@legendapp/list/reanimated';
8
+
9
+ // src/integrations/keyboard-legacy.tsx
10
+ var { typedForwardRef, useCombinedRef } = internal;
11
+ var clampProgress = (progress) => {
12
+ "worklet";
13
+ return Math.min(1, Math.max(0, progress));
14
+ };
15
+ var calculateKeyboardInset = (height, safeAreaInsetBottom) => {
16
+ "worklet";
17
+ return Math.max(0, height - safeAreaInsetBottom);
18
+ };
19
+ var calculateEffectiveKeyboardHeight = (keyboardHeight, contentLength, scrollLength, alignItemsAtEnd) => {
20
+ "worklet";
21
+ if (alignItemsAtEnd) {
22
+ return keyboardHeight;
23
+ } else {
24
+ const availableSpace = Math.max(0, scrollLength - contentLength);
25
+ return Math.max(0, keyboardHeight - availableSpace);
26
+ }
27
+ };
28
+ var calculateKeyboardTargetOffset = (startOffset, keyboardHeight, isOpening, progress) => {
29
+ "worklet";
30
+ const normalizedProgress = isOpening ? progress : 1 - progress;
31
+ const delta = (isOpening ? keyboardHeight : -keyboardHeight) * normalizedProgress;
32
+ return Math.max(0, startOffset + delta);
33
+ };
34
+ var KeyboardAvoidingLegendList = typedForwardRef(function KeyboardAvoidingLegendList2(props, forwardedRef) {
35
+ const {
36
+ contentContainerStyle: contentContainerStyleProp,
37
+ contentInset: contentInsetProp,
38
+ horizontal,
39
+ onMetricsChange: onMetricsChangeProp,
40
+ onContentSizeChange: onContentSizeChangeProp,
41
+ onLayout: onLayoutProp,
42
+ onScroll: onScrollProp,
43
+ safeAreaInsetBottom = 0,
44
+ style: styleProp,
45
+ ...rest
46
+ } = props;
47
+ const { alignItemsAtEnd } = props;
48
+ const styleFlattened = StyleSheet.flatten(styleProp);
49
+ const refLegendList = useRef(null);
50
+ const combinedRef = useCombinedRef(forwardedRef, refLegendList);
51
+ const isIos = Platform.OS === "ios";
52
+ const isAndroid = Platform.OS === "android";
53
+ const scrollViewRef = useAnimatedRef();
54
+ const scrollOffsetY = useSharedValue(0);
55
+ const animatedOffsetY = useSharedValue(null);
56
+ const scrollOffsetAtKeyboardStart = useSharedValue(0);
57
+ const animationMode = useSharedValue("idle");
58
+ const keyboardInset = useSharedValue(0);
59
+ const keyboardHeight = useSharedValue(0);
60
+ const contentLength = useSharedValue(0);
61
+ const scrollLength = useSharedValue(0);
62
+ const isOpening = useSharedValue(false);
63
+ const didInteractive = useSharedValue(false);
64
+ const shouldUpdateAlignItemsAtEndMinSize = useSharedValue(false);
65
+ const isKeyboardOpen = useSharedValue(false);
66
+ const hasSeenKeyboardTransition = useSharedValue(false);
67
+ const skipKeyboardAnimationForCurrentTransition = useSharedValue(false);
68
+ const keyboardInsetRef = useRef(0);
69
+ const [alignItemsAtEndMinSize, setAlignItemsAtEndMinSize] = useState(void 0);
70
+ const onScrollValue = onScrollProp;
71
+ const onScrollCallback = typeof onScrollValue === "function" ? onScrollValue : void 0;
72
+ const onScrollProcessed = onScrollValue && typeof onScrollValue === "object" && "workletEventHandler" in onScrollValue ? onScrollValue : null;
73
+ const onScrollCallbackIsWorklet = useMemo(
74
+ () => onScrollCallback ? isWorkletFunction(onScrollCallback) : false,
75
+ [onScrollCallback]
76
+ );
77
+ const handleContentSizeChange = useCallback(
78
+ (width, height) => {
79
+ const nextContentLength = horizontal ? width : height;
80
+ if (Number.isFinite(nextContentLength) && nextContentLength > 0) {
81
+ contentLength.set(nextContentLength);
82
+ }
83
+ onContentSizeChangeProp == null ? void 0 : onContentSizeChangeProp(width, height);
84
+ },
85
+ [contentLength, horizontal, onContentSizeChangeProp]
86
+ );
87
+ const handleLayout = useCallback(
88
+ (event) => {
89
+ const nextScrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
90
+ if (Number.isFinite(nextScrollLength) && nextScrollLength > 0) {
91
+ scrollLength.set(nextScrollLength);
92
+ }
93
+ onLayoutProp == null ? void 0 : onLayoutProp(event);
94
+ },
95
+ [horizontal, onLayoutProp, scrollLength]
96
+ );
97
+ const scrollHandler = useAnimatedScrollHandler(
98
+ (event) => {
99
+ if (animationMode.get() !== "running" || didInteractive.get()) {
100
+ scrollOffsetY.set(event.contentOffset[horizontal ? "x" : "y"]);
101
+ }
102
+ if (onScrollCallback) {
103
+ if (onScrollCallbackIsWorklet) {
104
+ onScrollCallback(event);
105
+ } else {
106
+ runOnJS(onScrollCallback)(event);
107
+ }
108
+ }
109
+ },
110
+ [horizontal, onScrollCallback, onScrollCallbackIsWorklet]
111
+ );
112
+ const composedScrollHandler = useComposedEventHandler([
113
+ scrollHandler,
114
+ onScrollProcessed
115
+ ]);
116
+ const finalScrollHandler = onScrollProcessed ? composedScrollHandler : scrollHandler;
117
+ const setScrollProcessingEnabled = useCallback(
118
+ (enabled) => {
119
+ var _a;
120
+ return (_a = refLegendList.current) == null ? void 0 : _a.setScrollProcessingEnabled(enabled);
121
+ },
122
+ [refLegendList]
123
+ );
124
+ const reportContentInset = useCallback(
125
+ (bottom) => {
126
+ var _a;
127
+ return (_a = refLegendList.current) == null ? void 0 : _a.reportContentInset({ bottom });
128
+ },
129
+ [refLegendList]
130
+ );
131
+ const clearAlignItemsAtEndMinSize = useCallback(() => {
132
+ setAlignItemsAtEndMinSize((prev) => prev === void 0 ? prev : void 0);
133
+ }, []);
134
+ const updateAlignItemsAtEndMinSize = useCallback(
135
+ (nextKeyboardInset) => {
136
+ var _a;
137
+ if (isAndroid) {
138
+ return;
139
+ }
140
+ if (nextKeyboardInset !== void 0) {
141
+ keyboardInsetRef.current = nextKeyboardInset;
142
+ }
143
+ if (!alignItemsAtEnd || horizontal) {
144
+ clearAlignItemsAtEndMinSize();
145
+ return;
146
+ }
147
+ const state = (_a = refLegendList.current) == null ? void 0 : _a.getState();
148
+ if (!state) {
149
+ return;
150
+ }
151
+ const currentInset = keyboardInsetRef.current;
152
+ if (currentInset <= 0) {
153
+ clearAlignItemsAtEndMinSize();
154
+ return;
155
+ }
156
+ if (state.scrollLength <= 0) {
157
+ return;
158
+ }
159
+ const nextMinSize = Math.max(0, state.scrollLength - currentInset);
160
+ setAlignItemsAtEndMinSize((prev) => prev === nextMinSize ? prev : nextMinSize);
161
+ },
162
+ [alignItemsAtEnd, clearAlignItemsAtEndMinSize, horizontal, isAndroid]
163
+ );
164
+ const updateScrollMetrics = useCallback(() => {
165
+ var _a;
166
+ const state = (_a = refLegendList.current) == null ? void 0 : _a.getState();
167
+ if (!state) {
168
+ return;
169
+ }
170
+ contentLength.set(state.contentLength);
171
+ if (animationMode.get() !== "running") {
172
+ scrollOffsetY.set(state.scroll);
173
+ }
174
+ scrollLength.set(state.scrollLength);
175
+ updateAlignItemsAtEndMinSize();
176
+ }, [animationMode, contentLength, scrollLength, scrollOffsetY, updateAlignItemsAtEndMinSize]);
177
+ const handleMetricsChange = useCallback(
178
+ (metrics) => {
179
+ updateScrollMetrics();
180
+ onMetricsChangeProp == null ? void 0 : onMetricsChangeProp(metrics);
181
+ },
182
+ [onMetricsChangeProp, updateScrollMetrics]
183
+ );
184
+ useEffect(() => {
185
+ updateScrollMetrics();
186
+ }, [updateScrollMetrics]);
187
+ useEffect(() => {
188
+ updateAlignItemsAtEndMinSize();
189
+ }, [updateAlignItemsAtEndMinSize]);
190
+ const getEffectiveKeyboardHeightFromInset = useCallback(
191
+ (nextKeyboardInset) => {
192
+ "worklet";
193
+ return calculateEffectiveKeyboardHeight(
194
+ nextKeyboardInset,
195
+ contentLength.get(),
196
+ scrollLength.get(),
197
+ alignItemsAtEnd
198
+ );
199
+ },
200
+ [alignItemsAtEnd, contentLength, scrollLength]
201
+ );
202
+ const getEffectiveKeyboardHeightFromEvent = useCallback(
203
+ (eventHeight) => {
204
+ "worklet";
205
+ const nextKeyboardInset = calculateKeyboardInset(eventHeight, safeAreaInsetBottom);
206
+ return getEffectiveKeyboardHeightFromInset(nextKeyboardInset);
207
+ },
208
+ [getEffectiveKeyboardHeightFromInset, safeAreaInsetBottom]
209
+ );
210
+ useKeyboardHandler(
211
+ // biome-ignore assist/source/useSortedKeys: prefer start/move/end
212
+ {
213
+ onStart: (event) => {
214
+ "worklet";
215
+ const progress = clampProgress(event.progress);
216
+ const shouldSkipInitialCloseAnimation = !hasSeenKeyboardTransition.get() && !isKeyboardOpen.get() && keyboardHeight.get() <= 0 && progress <= 0 && event.height <= 0;
217
+ skipKeyboardAnimationForCurrentTransition.set(shouldSkipInitialCloseAnimation);
218
+ hasSeenKeyboardTransition.set(true);
219
+ if (isKeyboardOpen.get() && progress >= 1 && event.height > 0) {
220
+ didInteractive.set(false);
221
+ animationMode.set("idle");
222
+ runOnJS(setScrollProcessingEnabled)(true);
223
+ return;
224
+ }
225
+ if (shouldSkipInitialCloseAnimation) {
226
+ isOpening.set(false);
227
+ return;
228
+ }
229
+ animationMode.set("running");
230
+ if (!didInteractive.get()) {
231
+ if (event.height > 0) {
232
+ keyboardHeight.set(calculateKeyboardInset(event.height, safeAreaInsetBottom));
233
+ }
234
+ const vIsOpening = progress > 0;
235
+ isOpening.set(vIsOpening);
236
+ shouldUpdateAlignItemsAtEndMinSize.set(
237
+ !!alignItemsAtEnd && !horizontal && contentLength.get() < scrollLength.get()
238
+ );
239
+ if (!shouldUpdateAlignItemsAtEndMinSize.get()) {
240
+ runOnJS(clearAlignItemsAtEndMinSize)();
241
+ }
242
+ const vScrollOffset = scrollOffsetY.get();
243
+ scrollOffsetAtKeyboardStart.set(vScrollOffset);
244
+ if (isIos) {
245
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromInset(keyboardHeight.get());
246
+ const targetOffset = Math.max(
247
+ 0,
248
+ vIsOpening ? vScrollOffset + vEffectiveKeyboardHeight : vScrollOffset - vEffectiveKeyboardHeight
249
+ );
250
+ scrollOffsetY.set(targetOffset);
251
+ animatedOffsetY.set(targetOffset);
252
+ keyboardInset.set(vEffectiveKeyboardHeight);
253
+ runOnJS(updateAlignItemsAtEndMinSize)(vEffectiveKeyboardHeight);
254
+ } else if (isAndroid) {
255
+ animatedOffsetY.set(vScrollOffset);
256
+ }
257
+ runOnJS(setScrollProcessingEnabled)(false);
258
+ }
259
+ },
260
+ onInteractive: (event) => {
261
+ "worklet";
262
+ if (animationMode.get() !== "running") {
263
+ runOnJS(setScrollProcessingEnabled)(false);
264
+ }
265
+ animationMode.set("running");
266
+ if (!didInteractive.get()) {
267
+ didInteractive.set(true);
268
+ }
269
+ if (isAndroid && !horizontal) {
270
+ const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom);
271
+ keyboardInset.set(newInset);
272
+ }
273
+ if (shouldUpdateAlignItemsAtEndMinSize.get() && !horizontal && alignItemsAtEnd) {
274
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromEvent(event.height);
275
+ runOnJS(updateAlignItemsAtEndMinSize)(vEffectiveKeyboardHeight);
276
+ }
277
+ },
278
+ onMove: (event) => {
279
+ "worklet";
280
+ const vIsOpening = isOpening.get();
281
+ const progress = clampProgress(event.progress);
282
+ const skipKeyboardAnimation = skipKeyboardAnimationForCurrentTransition.get();
283
+ if (skipKeyboardAnimation) {
284
+ return;
285
+ }
286
+ if (isAndroid) {
287
+ if (!didInteractive.get()) {
288
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromInset(keyboardHeight.get());
289
+ const targetOffset = calculateKeyboardTargetOffset(
290
+ scrollOffsetAtKeyboardStart.get(),
291
+ vEffectiveKeyboardHeight,
292
+ vIsOpening,
293
+ progress
294
+ );
295
+ scrollOffsetY.set(targetOffset);
296
+ animatedOffsetY.set(targetOffset);
297
+ }
298
+ if (!horizontal) {
299
+ const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom);
300
+ keyboardInset.set(newInset);
301
+ }
302
+ }
303
+ if (!horizontal && alignItemsAtEnd && !vIsOpening && shouldUpdateAlignItemsAtEndMinSize.get()) {
304
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromEvent(event.height);
305
+ runOnJS(updateAlignItemsAtEndMinSize)(vEffectiveKeyboardHeight);
306
+ }
307
+ },
308
+ onEnd: (event) => {
309
+ "worklet";
310
+ const wasInteractive = didInteractive.get();
311
+ const skipKeyboardAnimation = skipKeyboardAnimationForCurrentTransition.get();
312
+ const vMode = animationMode.get();
313
+ animationMode.set("idle");
314
+ if (skipKeyboardAnimation) {
315
+ skipKeyboardAnimationForCurrentTransition.set(false);
316
+ didInteractive.set(false);
317
+ isOpening.set(false);
318
+ isKeyboardOpen.set(false);
319
+ keyboardHeight.set(0);
320
+ if (!horizontal) {
321
+ keyboardInset.set(0);
322
+ runOnJS(reportContentInset)(0);
323
+ runOnJS(updateAlignItemsAtEndMinSize)(0);
324
+ }
325
+ return;
326
+ }
327
+ if (vMode === "running") {
328
+ const progress = clampProgress(event.progress);
329
+ const vEffectiveKeyboardHeight = getEffectiveKeyboardHeightFromInset(keyboardHeight.get());
330
+ const vIsOpening = isOpening.get();
331
+ if (!wasInteractive) {
332
+ const targetOffset = calculateKeyboardTargetOffset(
333
+ scrollOffsetAtKeyboardStart.get(),
334
+ vEffectiveKeyboardHeight,
335
+ vIsOpening,
336
+ progress
337
+ );
338
+ scrollOffsetY.set(targetOffset);
339
+ animatedOffsetY.set(targetOffset);
340
+ }
341
+ runOnJS(setScrollProcessingEnabled)(true);
342
+ didInteractive.set(false);
343
+ isKeyboardOpen.set(event.height > 0);
344
+ if (event.height > 0) {
345
+ keyboardHeight.set(calculateKeyboardInset(event.height, safeAreaInsetBottom));
346
+ }
347
+ if (!horizontal) {
348
+ const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom);
349
+ keyboardInset.set(newInset);
350
+ runOnJS(reportContentInset)(newInset);
351
+ if (!vIsOpening) {
352
+ runOnJS(updateAlignItemsAtEndMinSize)(newInset);
353
+ }
354
+ if (newInset <= 0) {
355
+ animatedOffsetY.set(scrollOffsetY.get());
356
+ }
357
+ }
358
+ }
359
+ }
360
+ },
361
+ [
362
+ alignItemsAtEnd,
363
+ clearAlignItemsAtEndMinSize,
364
+ getEffectiveKeyboardHeightFromEvent,
365
+ getEffectiveKeyboardHeightFromInset,
366
+ horizontal,
367
+ isAndroid,
368
+ isIos,
369
+ reportContentInset,
370
+ safeAreaInsetBottom,
371
+ setScrollProcessingEnabled,
372
+ updateAlignItemsAtEndMinSize
373
+ ]
374
+ );
375
+ const animatedProps = useAnimatedProps(() => {
376
+ "worklet";
377
+ var _a, _b, _c, _d;
378
+ const vAnimatedOffsetY = animatedOffsetY.get();
379
+ const baseProps = {
380
+ contentOffset: vAnimatedOffsetY === null ? void 0 : {
381
+ x: 0,
382
+ y: vAnimatedOffsetY
383
+ }
384
+ };
385
+ if (isIos) {
386
+ const keyboardInsetBottom = keyboardInset.get();
387
+ const contentInset = {
388
+ bottom: ((_a = contentInsetProp == null ? void 0 : contentInsetProp.bottom) != null ? _a : 0) + (horizontal ? 0 : keyboardInsetBottom),
389
+ left: (_b = contentInsetProp == null ? void 0 : contentInsetProp.left) != null ? _b : 0,
390
+ right: (_c = contentInsetProp == null ? void 0 : contentInsetProp.right) != null ? _c : 0,
391
+ top: (_d = contentInsetProp == null ? void 0 : contentInsetProp.top) != null ? _d : 0
392
+ };
393
+ return Object.assign(baseProps, {
394
+ contentInset
395
+ });
396
+ } else {
397
+ return baseProps;
398
+ }
399
+ });
400
+ const androidAnimatedStyle = useAnimatedStyle(
401
+ () => ({
402
+ ...styleFlattened || {},
403
+ marginBottom: keyboardInset.get()
404
+ }),
405
+ [styleProp, keyboardInset]
406
+ );
407
+ const style = isAndroid ? androidAnimatedStyle : styleProp;
408
+ const contentContainerStyle = useMemo(() => {
409
+ if (alignItemsAtEndMinSize === void 0) {
410
+ return contentContainerStyleProp;
411
+ }
412
+ const minSizeStyle = horizontal ? { minWidth: alignItemsAtEndMinSize } : { minHeight: alignItemsAtEndMinSize };
413
+ return contentContainerStyleProp ? [contentContainerStyleProp, minSizeStyle] : minSizeStyle;
414
+ }, [alignItemsAtEndMinSize, contentContainerStyleProp, horizontal]);
415
+ return /* @__PURE__ */ React.createElement(
416
+ AnimatedLegendList,
417
+ {
418
+ ...rest,
419
+ animatedProps,
420
+ automaticallyAdjustContentInsets: false,
421
+ contentContainerStyle,
422
+ keyboardDismissMode: "interactive",
423
+ onContentSizeChange: handleContentSizeChange,
424
+ onLayout: handleLayout,
425
+ onMetricsChange: handleMetricsChange,
426
+ onScroll: finalScrollHandler,
427
+ ref: combinedRef,
428
+ refScrollView: scrollViewRef,
429
+ scrollIndicatorInsets: { bottom: 0, top: 0 },
430
+ style
431
+ }
432
+ );
433
+ });
434
+
435
+ export { KeyboardAvoidingLegendList };