1/**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @format
8 */
9
10import type * as React from 'react';
11import {Constructor} from '../../../types/private/Utilities';
12import {Insets} from '../../../types/public/Insets';
13import {ColorValue, StyleProp} from '../../StyleSheet/StyleSheet';
14import {ViewStyle} from '../../StyleSheet/StyleSheetTypes';
15import {
16  NativeSyntheticEvent,
17  NativeTouchEvent,
18} from '../../Types/CoreEventTypes';
19import {RefreshControlProps} from '../RefreshControl/RefreshControl';
20import {Touchable} from '../Touchable/Touchable';
21import {ViewProps} from '../View/ViewPropTypes';
22
23// See https://reactnative.dev/docs/scrollview#contentoffset
24export interface PointProp {
25  x: number;
26  y: number;
27}
28
29export interface ScrollResponderEvent
30  extends NativeSyntheticEvent<NativeTouchEvent> {}
31
32interface SubscribableMixin {
33  /**
34   * Special form of calling `addListener` that *guarantees* that a
35   * subscription *must* be tied to a component instance, and therefore will
36   * be cleaned up when the component is unmounted. It is impossible to create
37   * the subscription and pass it in - this method must be the one to create
38   * the subscription and therefore can guarantee it is retained in a way that
39   * will be cleaned up.
40   *
41   * @param eventEmitter emitter to subscribe to.
42   * @param eventType Type of event to listen to.
43   * @param listener Function to invoke when event occurs.
44   * @param context Object to use as listener context.
45   */
46  addListenerOn(
47    eventEmitter: any,
48    eventType: string,
49    listener: () => any,
50    context: any,
51  ): void;
52}
53
54interface ScrollResponderMixin extends SubscribableMixin {
55  /**
56   * Invoke this from an `onScroll` event.
57   */
58  scrollResponderHandleScrollShouldSetResponder(): boolean;
59
60  /**
61   * Merely touch starting is not sufficient for a scroll view to become the
62   * responder. Being the "responder" means that the very next touch move/end
63   * event will result in an action/movement.
64   *
65   * Invoke this from an `onStartShouldSetResponder` event.
66   *
67   * `onStartShouldSetResponder` is used when the next move/end will trigger
68   * some UI movement/action, but when you want to yield priority to views
69   * nested inside of the view.
70   *
71   * There may be some cases where scroll views actually should return `true`
72   * from `onStartShouldSetResponder`: Any time we are detecting a standard tap
73   * that gives priority to nested views.
74   *
75   * - If a single tap on the scroll view triggers an action such as
76   *   recentering a map style view yet wants to give priority to interaction
77   *   views inside (such as dropped pins or labels), then we would return true
78   *   from this method when there is a single touch.
79   *
80   * - Similar to the previous case, if a two finger "tap" should trigger a
81   *   zoom, we would check the `touches` count, and if `>= 2`, we would return
82   *   true.
83   *
84   */
85  scrollResponderHandleStartShouldSetResponder(): boolean;
86
87  /**
88   * There are times when the scroll view wants to become the responder
89   * (meaning respond to the next immediate `touchStart/touchEnd`), in a way
90   * that *doesn't* give priority to nested views (hence the capture phase):
91   *
92   * - Currently animating.
93   * - Tapping anywhere that is not the focused input, while the keyboard is
94   *   up (which should dismiss the keyboard).
95   *
96   * Invoke this from an `onStartShouldSetResponderCapture` event.
97   */
98  scrollResponderHandleStartShouldSetResponderCapture(
99    e: ScrollResponderEvent,
100  ): boolean;
101
102  /**
103   * Invoke this from an `onResponderReject` event.
104   *
105   * Some other element is not yielding its role as responder. Normally, we'd
106   * just disable the `UIScrollView`, but a touch has already began on it, the
107   * `UIScrollView` will not accept being disabled after that. The easiest
108   * solution for now is to accept the limitation of disallowing this
109   * altogether. To improve this, find a way to disable the `UIScrollView` after
110   * a touch has already started.
111   */
112  scrollResponderHandleResponderReject(): any;
113
114  /**
115   * We will allow the scroll view to give up its lock iff it acquired the lock
116   * during an animation. This is a very useful default that happens to satisfy
117   * many common user experiences.
118   *
119   * - Stop a scroll on the left edge, then turn that into an outer view's
120   *   backswipe.
121   * - Stop a scroll mid-bounce at the top, continue pulling to have the outer
122   *   view dismiss.
123   * - However, without catching the scroll view mid-bounce (while it is
124   *   motionless), if you drag far enough for the scroll view to become
125   *   responder (and therefore drag the scroll view a bit), any backswipe
126   *   navigation of a swipe gesture higher in the view hierarchy, should be
127   *   rejected.
128   */
129  scrollResponderHandleTerminationRequest(): boolean;
130
131  /**
132   * Invoke this from an `onTouchEnd` event.
133   *
134   * @param e Event.
135   */
136  scrollResponderHandleTouchEnd(e: ScrollResponderEvent): void;
137
138  /**
139   * Invoke this from an `onResponderRelease` event.
140   */
141  scrollResponderHandleResponderRelease(e: ScrollResponderEvent): void;
142
143  scrollResponderHandleScroll(e: ScrollResponderEvent): void;
144
145  /**
146   * Invoke this from an `onResponderGrant` event.
147   */
148  scrollResponderHandleResponderGrant(e: ScrollResponderEvent): void;
149
150  /**
151   * Unfortunately, `onScrollBeginDrag` also fires when *stopping* the scroll
152   * animation, and there's not an easy way to distinguish a drag vs. stopping
153   * momentum.
154   *
155   * Invoke this from an `onScrollBeginDrag` event.
156   */
157  scrollResponderHandleScrollBeginDrag(e: ScrollResponderEvent): void;
158
159  /**
160   * Invoke this from an `onScrollEndDrag` event.
161   */
162  scrollResponderHandleScrollEndDrag(e: ScrollResponderEvent): void;
163
164  /**
165   * Invoke this from an `onMomentumScrollBegin` event.
166   */
167  scrollResponderHandleMomentumScrollBegin(e: ScrollResponderEvent): void;
168
169  /**
170   * Invoke this from an `onMomentumScrollEnd` event.
171   */
172  scrollResponderHandleMomentumScrollEnd(e: ScrollResponderEvent): void;
173
174  /**
175   * Invoke this from an `onTouchStart` event.
176   *
177   * Since we know that the `SimpleEventPlugin` occurs later in the plugin
178   * order, after `ResponderEventPlugin`, we can detect that we were *not*
179   * permitted to be the responder (presumably because a contained view became
180   * responder). The `onResponderReject` won't fire in that case - it only
181   * fires when a *current* responder rejects our request.
182   *
183   * @param e Touch Start event.
184   */
185  scrollResponderHandleTouchStart(e: ScrollResponderEvent): void;
186
187  /**
188   * Invoke this from an `onTouchMove` event.
189   *
190   * Since we know that the `SimpleEventPlugin` occurs later in the plugin
191   * order, after `ResponderEventPlugin`, we can detect that we were *not*
192   * permitted to be the responder (presumably because a contained view became
193   * responder). The `onResponderReject` won't fire in that case - it only
194   * fires when a *current* responder rejects our request.
195   *
196   * @param e Touch Start event.
197   */
198  scrollResponderHandleTouchMove(e: ScrollResponderEvent): void;
199
200  /**
201   * A helper function for this class that lets us quickly determine if the
202   * view is currently animating. This is particularly useful to know when
203   * a touch has just started or ended.
204   */
205  scrollResponderIsAnimating(): boolean;
206
207  /**
208   * Returns the node that represents native view that can be scrolled.
209   * Components can pass what node to use by defining a `getScrollableNode`
210   * function otherwise `this` is used.
211   */
212  scrollResponderGetScrollableNode(): any;
213
214  /**
215   * A helper function to scroll to a specific point  in the scrollview.
216   * This is currently used to help focus on child textviews, but can also
217   * be used to quickly scroll to any element we want to focus. Syntax:
218   *
219   * scrollResponderScrollTo(options: {x: number = 0; y: number = 0; animated: boolean = true})
220   *
221   * Note: The weird argument signature is due to the fact that, for historical reasons,
222   * the function also accepts separate arguments as an alternative to the options object.
223   * This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
224   */
225  scrollResponderScrollTo(
226    x?:
227      | number
228      | {
229          x?: number | undefined;
230          y?: number | undefined;
231          animated?: boolean | undefined;
232        },
233    y?: number,
234    animated?: boolean,
235  ): void;
236
237  /**
238   * A helper function to zoom to a specific rect in the scrollview. The argument has the shape
239   * {x: number; y: number; width: number; height: number; animated: boolean = true}
240   *
241   * @platform ios
242   */
243  scrollResponderZoomTo(
244    rect: {
245      x: number;
246      y: number;
247      width: number;
248      height: number;
249      animated?: boolean | undefined;
250    },
251    animated?: boolean, // deprecated, put this inside the rect argument instead
252  ): void;
253
254  /**
255   * This method should be used as the callback to onFocus in a TextInputs'
256   * parent view. Note that any module using this mixin needs to return
257   * the parent view's ref in getScrollViewRef() in order to use this method.
258   * @param nodeHandle The TextInput node handle
259   * @param additionalOffset The scroll view's top "contentInset".
260   *        Default is 0.
261   * @param preventNegativeScrolling Whether to allow pulling the content
262   *        down to make it meet the keyboard's top. Default is false.
263   */
264  scrollResponderScrollNativeHandleToKeyboard(
265    nodeHandle: any,
266    additionalOffset?: number,
267    preventNegativeScrollOffset?: boolean,
268  ): void;
269
270  /**
271   * The calculations performed here assume the scroll view takes up the entire
272   * screen - even if has some content inset. We then measure the offsets of the
273   * keyboard, and compensate both for the scroll view's "contentInset".
274   *
275   * @param left Position of input w.r.t. table view.
276   * @param top Position of input w.r.t. table view.
277   * @param width Width of the text input.
278   * @param height Height of the text input.
279   */
280  scrollResponderInputMeasureAndScrollToKeyboard(
281    left: number,
282    top: number,
283    width: number,
284    height: number,
285  ): void;
286
287  scrollResponderTextInputFocusError(e: ScrollResponderEvent): void;
288
289  /**
290   * `componentWillMount` is the closest thing to a  standard "constructor" for
291   * React components.
292   *
293   * The `keyboardWillShow` is called before input focus.
294   */
295  componentWillMount(): void;
296
297  /**
298   * Warning, this may be called several times for a single keyboard opening.
299   * It's best to store the information in this method and then take any action
300   * at a later point (either in `keyboardDidShow` or other).
301   *
302   * Here's the order that events occur in:
303   * - focus
304   * - willShow {startCoordinates, endCoordinates} several times
305   * - didShow several times
306   * - blur
307   * - willHide {startCoordinates, endCoordinates} several times
308   * - didHide several times
309   *
310   * The `ScrollResponder` providesModule callbacks for each of these events.
311   * Even though any user could have easily listened to keyboard events
312   * themselves, using these `props` callbacks ensures that ordering of events
313   * is consistent - and not dependent on the order that the keyboard events are
314   * subscribed to. This matters when telling the scroll view to scroll to where
315   * the keyboard is headed - the scroll responder better have been notified of
316   * the keyboard destination before being instructed to scroll to where the
317   * keyboard will be. Stick to the `ScrollResponder` callbacks, and everything
318   * will work.
319   *
320   * WARNING: These callbacks will fire even if a keyboard is displayed in a
321   * different navigation pane. Filter out the events to determine if they are
322   * relevant to you. (For example, only if you receive these callbacks after
323   * you had explicitly focused a node etc).
324   */
325  scrollResponderKeyboardWillShow(e: ScrollResponderEvent): void;
326
327  scrollResponderKeyboardWillHide(e: ScrollResponderEvent): void;
328
329  scrollResponderKeyboardDidShow(e: ScrollResponderEvent): void;
330
331  scrollResponderKeyboardDidHide(e: ScrollResponderEvent): void;
332}
333
334export interface ScrollViewPropsIOS {
335  /**
336   * When true the scroll view bounces horizontally when it reaches the end
337   * even if the content is smaller than the scroll view itself. The default
338   * value is true when `horizontal={true}` and false otherwise.
339   */
340  alwaysBounceHorizontal?: boolean | undefined;
341  /**
342   * When true the scroll view bounces vertically when it reaches the end
343   * even if the content is smaller than the scroll view itself. The default
344   * value is false when `horizontal={true}` and true otherwise.
345   */
346  alwaysBounceVertical?: boolean | undefined;
347
348  /**
349   * Controls whether iOS should automatically adjust the content inset for scroll views that are placed behind a navigation bar or tab bar/ toolbar.
350   * The default value is true.
351   */
352  automaticallyAdjustContentInsets?: boolean | undefined; // true
353
354  /**
355   * Controls whether the ScrollView should automatically adjust its contentInset and
356   * scrollViewInsets when the Keyboard changes its size. The default value is false.
357   */
358  automaticallyAdjustKeyboardInsets?: boolean | undefined;
359
360  /**
361   * Controls whether iOS should automatically adjust the scroll indicator
362   * insets. The default value is true. Available on iOS 13 and later.
363   */
364  automaticallyAdjustsScrollIndicatorInsets?: boolean | undefined;
365
366  /**
367   * When true the scroll view bounces when it reaches the end of the
368   * content if the content is larger then the scroll view along the axis of
369   * the scroll direction. When false it disables all bouncing even if
370   * the `alwaysBounce*` props are true. The default value is true.
371   */
372  bounces?: boolean | undefined;
373  /**
374   * When true gestures can drive zoom past min/max and the zoom will animate
375   * to the min/max value at gesture end otherwise the zoom will not exceed
376   * the limits.
377   */
378  bouncesZoom?: boolean | undefined;
379
380  /**
381   * When false once tracking starts won't try to drag if the touch moves.
382   * The default value is true.
383   */
384  canCancelContentTouches?: boolean | undefined;
385
386  /**
387   * When true the scroll view automatically centers the content when the
388   * content is smaller than the scroll view bounds; when the content is
389   * larger than the scroll view this property has no effect. The default
390   * value is false.
391   */
392  centerContent?: boolean | undefined;
393
394  /**
395   * The amount by which the scroll view content is inset from the edges of the scroll view.
396   * Defaults to {0, 0, 0, 0}.
397   */
398  contentInset?: Insets | undefined; // zeros
399
400  /**
401   * Used to manually set the starting scroll offset.
402   * The default value is {x: 0, y: 0}
403   */
404  contentOffset?: PointProp | undefined; // zeros
405
406  /**
407   * This property specifies how the safe area insets are used to modify the content area of the scroll view.
408   * The default value of this property must be 'automatic'. But the default value is 'never' until [email protected].
409   */
410  contentInsetAdjustmentBehavior?:
411    | 'automatic'
412    | 'scrollableAxes'
413    | 'never'
414    | 'always'
415    | undefined;
416
417  /**
418   * When true the ScrollView will try to lock to only vertical or horizontal
419   * scrolling while dragging.  The default value is false.
420   */
421  directionalLockEnabled?: boolean | undefined;
422
423  /**
424   * The style of the scroll indicators.
425   * - default (the default), same as black.
426   * - black, scroll indicator is black. This style is good against
427   *   a white content background.
428   * - white, scroll indicator is white. This style is good against
429   *   a black content background.
430   */
431  indicatorStyle?: 'default' | 'black' | 'white' | undefined;
432
433  /**
434   * When set, the scroll view will adjust the scroll position so that the first child
435   * that is currently visible and at or beyond minIndexForVisible will not change position.
436   * This is useful for lists that are loading content in both directions, e.g. a chat thread,
437   * where new messages coming in might otherwise cause the scroll position to jump. A value
438   * of 0 is common, but other values such as 1 can be used to skip loading spinners or other
439   * content that should not maintain position.
440   *
441   * The optional autoscrollToTopThreshold can be used to make the content automatically scroll
442   * to the top after making the adjustment if the user was within the threshold of the top
443   * before the adjustment was made. This is also useful for chat-like applications where you
444   * want to see new messages scroll into place, but not if the user has scrolled up a ways and
445   * it would be disruptive to scroll a bunch.
446   *
447   * Caveat 1: Reordering elements in the scrollview with this enabled will probably cause
448   * jumpiness and jank. It can be fixed, but there are currently no plans to do so. For now,
449   * don't re-order the content of any ScrollViews or Lists that use this feature.
450   *
451   * Caveat 2: This uses contentOffset and frame.origin in native code to compute visibility.
452   * Occlusion, transforms, and other complexity won't be taken into account as to whether
453   * content is "visible" or not.
454   */
455  maintainVisibleContentPosition?:
456    | null
457    | {
458        autoscrollToTopThreshold?: number | null | undefined;
459        minIndexForVisible: number;
460      }
461    | undefined;
462  /**
463   * The maximum allowed zoom scale. The default value is 1.0.
464   */
465  maximumZoomScale?: number | undefined;
466
467  /**
468   * The minimum allowed zoom scale. The default value is 1.0.
469   */
470  minimumZoomScale?: number | undefined;
471
472  /**
473   * Called when a scrolling animation ends.
474   */
475  onScrollAnimationEnd?: (() => void) | undefined;
476
477  /**
478   * When true, ScrollView allows use of pinch gestures to zoom in and out.
479   * The default value is true.
480   */
481  pinchGestureEnabled?: boolean | undefined;
482
483  /**
484   * This controls how often the scroll event will be fired while scrolling (as a time interval in ms).
485   * A lower number yields better accuracy for code that is tracking the scroll position,
486   * but can lead to scroll performance problems due to the volume of information being sent over the bridge.
487   * The default value is zero, which means the scroll event will be sent only once each time the view is scrolled.
488   */
489  scrollEventThrottle?: number | undefined; // null
490
491  /**
492   * The amount by which the scroll view indicators are inset from the edges of the scroll view.
493   * This should normally be set to the same value as the contentInset.
494   * Defaults to {0, 0, 0, 0}.
495   */
496  scrollIndicatorInsets?: Insets | undefined; //zeroes
497
498  /**
499   * When true, the scroll view can be programmatically scrolled beyond its
500   * content size. The default value is false.
501   * @platform ios
502   */
503  scrollToOverflowEnabled?: boolean | undefined;
504
505  /**
506   * When true the scroll view scrolls to top when the status bar is tapped.
507   * The default value is true.
508   */
509  scrollsToTop?: boolean | undefined;
510
511  /**
512   * When `snapToInterval` is set, `snapToAlignment` will define the relationship of the snapping to the scroll view.
513   *      - `start` (the default) will align the snap at the left (horizontal) or top (vertical)
514   *      - `center` will align the snap in the center
515   *      - `end` will align the snap at the right (horizontal) or bottom (vertical)
516   */
517  snapToAlignment?: 'start' | 'center' | 'end' | undefined;
518
519  /**
520   * Fires when the scroll view scrolls to top after the status bar has been tapped
521   * @platform ios
522   */
523  onScrollToTop?:
524    | ((event: NativeSyntheticEvent<NativeScrollEvent>) => void)
525    | undefined;
526
527  /**
528   * The current scale of the scroll view content. The default value is 1.0.
529   */
530  zoomScale?: number | undefined;
531}
532
533export interface ScrollViewPropsAndroid {
534  /**
535   * Sometimes a scrollview takes up more space than its content fills.
536   * When this is the case, this prop will fill the rest of the
537   * scrollview with a color to avoid setting a background and creating
538   * unnecessary overdraw. This is an advanced optimization that is not
539   * needed in the general case.
540   */
541  endFillColor?: ColorValue | undefined;
542
543  /**
544   * Tag used to log scroll performance on this scroll view. Will force
545   * momentum events to be turned on (see sendMomentumEvents). This doesn't do
546   * anything out of the box and you need to implement a custom native
547   * FpsListener for it to be useful.
548   * @platform android
549   */
550  scrollPerfTag?: string | undefined;
551
552  /**
553     * Used to override default value of overScroll mode.
554
555        * Possible values:
556        *   - 'auto' - Default value, allow a user to over-scroll this view only if the content is large enough to meaningfully scroll.
557        *   - 'always' - Always allow a user to over-scroll this view.
558        *   - 'never' - Never allow a user to over-scroll this view.
559        */
560  overScrollMode?: 'auto' | 'always' | 'never' | undefined;
561
562  /**
563   * Enables nested scrolling for Android API level 21+. Nested scrolling is supported by default on iOS.
564   */
565  nestedScrollEnabled?: boolean | undefined;
566
567  /**
568   * Fades out the edges of the scroll content.
569   *
570   * If the value is greater than 0, the fading edges will be set accordingly
571   * to the current scroll direction and position,
572   * indicating if there is more content to show.
573   *
574   * The default value is 0.
575   * @platform android
576   */
577  fadingEdgeLength?: number | undefined;
578
579  /**
580   * Causes the scrollbars not to turn transparent when they are not in use. The default value is false.
581   */
582  persistentScrollbar?: boolean | undefined;
583}
584
585export interface ScrollViewProps
586  extends ViewProps,
587    ScrollViewPropsIOS,
588    ScrollViewPropsAndroid,
589    Touchable {
590  /**
591   * These styles will be applied to the scroll view content container which
592   * wraps all of the child views. Example:
593   *
594   *   return (
595   *     <ScrollView contentContainerStyle={styles.contentContainer}>
596   *     </ScrollView>
597   *   );
598   *   ...
599   *   const styles = StyleSheet.create({
600   *     contentContainer: {
601   *       paddingVertical: 20
602   *     }
603   *   });
604   */
605  contentContainerStyle?: StyleProp<ViewStyle> | undefined;
606
607  /**
608   * A floating-point number that determines how quickly the scroll view
609   * decelerates after the user lifts their finger. You may also use string
610   * shortcuts `"normal"` and `"fast"` which match the underlying iOS settings
611   * for `UIScrollViewDecelerationRateNormal` and
612   * `UIScrollViewDecelerationRateFast` respectively.
613   *
614   *  - `'normal'`: 0.998 on iOS, 0.985 on Android (the default)
615   *  - `'fast'`: 0.99 on iOS, 0.9 on Android
616   */
617  decelerationRate?: 'fast' | 'normal' | number | undefined;
618
619  /**
620   * When true the scroll view's children are arranged horizontally in a row
621   * instead of vertically in a column. The default value is false.
622   */
623  horizontal?: boolean | null | undefined;
624
625  /**
626   * If sticky headers should stick at the bottom instead of the top of the
627   * ScrollView. This is usually used with inverted ScrollViews.
628   */
629  invertStickyHeaders?: boolean | undefined;
630
631  /**
632   * Determines whether the keyboard gets dismissed in response to a drag.
633   *   - 'none' (the default) drags do not dismiss the keyboard.
634   *   - 'onDrag' the keyboard is dismissed when a drag begins.
635   *   - 'interactive' the keyboard is dismissed interactively with the drag
636   *     and moves in synchrony with the touch; dragging upwards cancels the
637   *     dismissal.
638   */
639  keyboardDismissMode?: 'none' | 'interactive' | 'on-drag' | undefined;
640
641  /**
642   * Determines when the keyboard should stay visible after a tap.
643   * - 'never' (the default), tapping outside of the focused text input when the keyboard is up dismisses the keyboard. When this happens, children won't receive the tap.
644   * - 'always', the keyboard will not dismiss automatically, and the scroll view will not catch taps, but children of the scroll view can catch taps.
645   * - 'handled', the keyboard will not dismiss automatically when the tap was handled by a children, (or captured by an ancestor).
646   * - false, deprecated, use 'never' instead
647   * - true, deprecated, use 'always' instead
648   */
649  keyboardShouldPersistTaps?:
650    | boolean
651    | 'always'
652    | 'never'
653    | 'handled'
654    | undefined;
655
656  /**
657   * Called when scrollable content view of the ScrollView changes.
658   * Handler function is passed the content width and content height as parameters: (contentWidth, contentHeight)
659   * It's implemented using onLayout handler attached to the content container which this ScrollView renders.
660   *
661   */
662  onContentSizeChange?: ((w: number, h: number) => void) | undefined;
663
664  /**
665   * Fires at most once per frame during scrolling.
666   * The frequency of the events can be contolled using the scrollEventThrottle prop.
667   */
668  onScroll?:
669    | ((event: NativeSyntheticEvent<NativeScrollEvent>) => void)
670    | undefined;
671
672  /**
673   * Fires if a user initiates a scroll gesture.
674   */
675  onScrollBeginDrag?:
676    | ((event: NativeSyntheticEvent<NativeScrollEvent>) => void)
677    | undefined;
678
679  /**
680   * Fires when a user has finished scrolling.
681   */
682  onScrollEndDrag?:
683    | ((event: NativeSyntheticEvent<NativeScrollEvent>) => void)
684    | undefined;
685
686  /**
687   * Fires when scroll view has finished moving
688   */
689  onMomentumScrollEnd?:
690    | ((event: NativeSyntheticEvent<NativeScrollEvent>) => void)
691    | undefined;
692
693  /**
694   * Fires when scroll view has begun moving
695   */
696  onMomentumScrollBegin?:
697    | ((event: NativeSyntheticEvent<NativeScrollEvent>) => void)
698    | undefined;
699
700  /**
701   * When true the scroll view stops on multiples of the scroll view's size
702   * when scrolling. This can be used for horizontal pagination. The default
703   * value is false.
704   */
705  pagingEnabled?: boolean | undefined;
706
707  /**
708   * When false, the content does not scroll. The default value is true
709   */
710  scrollEnabled?: boolean | undefined; // true
711
712  /**
713   * Experimental: When true offscreen child views (whose `overflow` value is
714   * `hidden`) are removed from their native backing superview when offscreen.
715   * This can improve scrolling performance on long lists. The default value is
716   * false.
717   */
718  removeClippedSubviews?: boolean | undefined;
719
720  /**
721   * When true, shows a horizontal scroll indicator.
722   */
723  showsHorizontalScrollIndicator?: boolean | undefined;
724
725  /**
726   * When true, shows a vertical scroll indicator.
727   */
728  showsVerticalScrollIndicator?: boolean | undefined;
729
730  /**
731   * When true, Sticky header is hidden when scrolling down, and dock at the top when scrolling up.
732   */
733  stickyHeaderHiddenOnScroll?: boolean;
734
735  /**
736   * Style
737   */
738  style?: StyleProp<ViewStyle> | undefined;
739
740  /**
741   * A RefreshControl component, used to provide pull-to-refresh
742   * functionality for the ScrollView.
743   */
744  refreshControl?: React.ReactElement<RefreshControlProps> | undefined;
745
746  /**
747   * When set, causes the scroll view to stop at multiples of the value of `snapToInterval`.
748   * This can be used for paginating through children that have lengths smaller than the scroll view.
749   * Used in combination with `snapToAlignment` and `decelerationRate="fast"`. Overrides less
750   * configurable `pagingEnabled` prop.
751   */
752  snapToInterval?: number | undefined;
753
754  /**
755   * When set, causes the scroll view to stop at the defined offsets. This can be used for
756   * paginating through variously sized children that have lengths smaller than the scroll view.
757   * Typically used in combination with `decelerationRate="fast"`. Overrides less configurable
758   * `pagingEnabled` and `snapToInterval` props.
759   */
760  snapToOffsets?: number[] | undefined;
761
762  /**
763   * Use in conjunction with `snapToOffsets`. By default, the beginning of the list counts as a
764   * snap offset. Set `snapToStart` to false to disable this behavior and allow the list to scroll
765   * freely between its start and the first `snapToOffsets` offset. The default value is true.
766   */
767  snapToStart?: boolean | undefined;
768
769  /**
770   * Use in conjunction with `snapToOffsets`. By default, the end of the list counts as a snap
771   * offset. Set `snapToEnd` to false to disable this behavior and allow the list to scroll freely
772   * between its end and the last `snapToOffsets` offset. The default value is true.
773   */
774  snapToEnd?: boolean | undefined;
775
776  /**
777   * An array of child indices determining which children get docked to the
778   * top of the screen when scrolling. For example passing
779   * `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the
780   * top of the scroll view. This property is not supported in conjunction
781   * with `horizontal={true}`.
782   */
783  stickyHeaderIndices?: number[] | undefined;
784
785  /**
786   * When true, the scroll view stops on the next index (in relation to scroll position at release)
787   * regardless of how fast the gesture is. This can be used for horizontal pagination when the page
788   * is less than the width of the ScrollView. The default value is false.
789   */
790  disableIntervalMomentum?: boolean | undefined;
791
792  /**
793   * When true, the default JS pan responder on the ScrollView is disabled, and full control over
794   * touches inside the ScrollView is left to its child components. This is particularly useful
795   * if `snapToInterval` is enabled, since it does not follow typical touch patterns. Do not use
796   * this on regular ScrollView use cases without `snapToInterval` as it may cause unexpected
797   * touches to occur while scrolling. The default value is false.
798   */
799  disableScrollViewPanResponder?: boolean | undefined;
800
801  /**
802   * A React Component that will be used to render sticky headers, should be used together with
803   * stickyHeaderIndices. You may need to set this component if your sticky header uses custom
804   * transforms, for example, when you want your list to have an animated and hidable header.
805   * If component have not been provided, the default ScrollViewStickyHeader component will be used.
806   */
807  StickyHeaderComponent?: React.ComponentType<any> | undefined;
808}
809
810declare class ScrollViewComponent extends React.Component<ScrollViewProps> {}
811export declare const ScrollViewBase: Constructor<ScrollResponderMixin> &
812  typeof ScrollViewComponent;
813export class ScrollView extends ScrollViewBase {
814  /**
815   * Scrolls to a given x, y offset, either immediately or with a smooth animation.
816   * Syntax:
817   *
818   * scrollTo(options: {x: number = 0; y: number = 0; animated: boolean = true})
819   *
820   * Note: The weird argument signature is due to the fact that, for historical reasons,
821   * the function also accepts separate arguments as an alternative to the options object.
822   * This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
823   */
824  scrollTo(
825    y?:
826      | number
827      | {
828          x?: number | undefined;
829          y?: number | undefined;
830          animated?: boolean | undefined;
831        },
832    deprecatedX?: number,
833    deprecatedAnimated?: boolean,
834  ): void;
835
836  /**
837   * A helper function that scrolls to the end of the scrollview;
838   * If this is a vertical ScrollView, it scrolls to the bottom.
839   * If this is a horizontal ScrollView scrolls to the right.
840   *
841   * The options object has an animated prop, that enables the scrolling animation or not.
842   * The animated prop defaults to true
843   */
844  scrollToEnd(options?: {animated?: boolean}): void;
845
846  /**
847   * Displays the scroll indicators momentarily.
848   */
849  flashScrollIndicators(): void;
850
851  /**
852   * Returns a reference to the underlying scroll responder, which supports
853   * operations like `scrollTo`. All ScrollView-like components should
854   * implement this method so that they can be composed while providing access
855   * to the underlying scroll responder's methods.
856   */
857  getScrollResponder(): ScrollResponderMixin;
858
859  getScrollableNode(): any;
860
861  // Undocumented
862  getInnerViewNode(): any;
863
864  /**
865   * @deprecated Use scrollTo instead
866   */
867  scrollWithoutAnimationTo?: ((y: number, x: number) => void) | undefined;
868
869  /**
870   * This function sends props straight to native. They will not participate in
871   * future diff process - this means that if you do not include them in the
872   * next render, they will remain active (see [Direct
873   * Manipulation](https://reactnative.dev/docs/direct-manipulation)).
874   */
875  setNativeProps(nativeProps: object): void;
876}
877
878export interface NativeScrollRectangle {
879  left: number;
880  top: number;
881  bottom: number;
882  right: number;
883}
884
885export interface NativeScrollPoint {
886  x: number;
887  y: number;
888}
889
890export interface NativeScrollVelocity {
891  x: number;
892  y: number;
893}
894
895export interface NativeScrollSize {
896  height: number;
897  width: number;
898}
899
900export interface NativeScrollEvent {
901  contentInset: NativeScrollRectangle;
902  contentOffset: NativeScrollPoint;
903  contentSize: NativeScrollSize;
904  layoutMeasurement: NativeScrollSize;
905  velocity?: NativeScrollVelocity | undefined;
906  zoomScale: number;
907  /**
908   * @platform ios
909   */
910  targetContentOffset?: NativeScrollPoint | undefined;
911}
912