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 {Insets} from '../../../types/public/Insets';
12import {ColorValue, StyleProp} from '../../StyleSheet/StyleSheet';
13import {ViewStyle} from '../../StyleSheet/StyleSheetTypes';
14import {
15  GestureResponderEvent,
16  MouseEvent,
17  NativeSyntheticEvent,
18  TargetedEvent,
19} from '../../Types/CoreEventTypes';
20import {View} from '../View/View';
21import {AccessibilityProps} from '../View/ViewAccessibility';
22import {ViewProps} from '../View/ViewPropTypes';
23
24export interface PressableStateCallbackType {
25  readonly pressed: boolean;
26}
27
28export interface PressableAndroidRippleConfig {
29  color?: null | ColorValue | undefined;
30  borderless?: null | boolean | undefined;
31  radius?: null | number | undefined;
32  foreground?: null | boolean | undefined;
33}
34
35export interface PressableProps
36  extends AccessibilityProps,
37    Omit<ViewProps, 'children' | 'style' | 'hitSlop'> {
38  /**
39   * Called when the hover is activated to provide visual feedback.
40   */
41  onHoverIn?: null | ((event: MouseEvent) => void) | undefined;
42
43  /**
44   * Called when the hover is deactivated to undo visual feedback.
45   */
46  onHoverOut?: null | ((event: MouseEvent) => void) | undefined;
47
48  /**
49   * Called when a single tap gesture is detected.
50   */
51  onPress?: null | ((event: GestureResponderEvent) => void) | undefined;
52
53  /**
54   * Called when a touch is engaged before `onPress`.
55   */
56  onPressIn?: null | ((event: GestureResponderEvent) => void) | undefined;
57
58  /**
59   * Called when a touch is released before `onPress`.
60   */
61  onPressOut?: null | ((event: GestureResponderEvent) => void) | undefined;
62
63  /**
64   * Called when a long-tap gesture is detected.
65   */
66  onLongPress?: null | ((event: GestureResponderEvent) => void) | undefined;
67
68  /**
69   * Called after the element loses focus.
70   * @platform macos windows
71   */
72  onBlur?:
73    | null
74    | ((event: NativeSyntheticEvent<TargetedEvent>) => void)
75    | undefined;
76
77  /**
78   * Called after the element is focused.
79   * @platform macos windows
80   */
81  onFocus?:
82    | null
83    | ((event: NativeSyntheticEvent<TargetedEvent>) => void)
84    | undefined;
85
86  /**
87   * Either children or a render prop that receives a boolean reflecting whether
88   * the component is currently pressed.
89   */
90  children?:
91    | React.ReactNode
92    | ((state: PressableStateCallbackType) => React.ReactNode)
93    | undefined;
94
95  /**
96   * Whether a press gesture can be interrupted by a parent gesture such as a
97   * scroll event. Defaults to true.
98   */
99  cancelable?: null | boolean | undefined;
100
101  /**
102   * Duration to wait after hover in before calling `onHoverIn`.
103   * @platform macos windows
104   */
105  delayHoverIn?: number | null | undefined;
106
107  /**
108   * Duration to wait after hover out before calling `onHoverOut`.
109   * @platform macos windows
110   */
111  delayHoverOut?: number | null | undefined;
112
113  /**
114   * Duration (in milliseconds) from `onPressIn` before `onLongPress` is called.
115   */
116  delayLongPress?: null | number | undefined;
117
118  /**
119   * Whether the press behavior is disabled.
120   */
121  disabled?: null | boolean | undefined;
122
123  /**
124   * Additional distance outside of this view in which a press is detected.
125   */
126  hitSlop?: null | Insets | number | undefined;
127
128  /**
129   * Additional distance outside of this view in which a touch is considered a
130   * press before `onPressOut` is triggered.
131   */
132  pressRetentionOffset?: null | Insets | number | undefined;
133
134  /**
135   * If true, doesn't play system sound on touch.
136   */
137  android_disableSound?: null | boolean | undefined;
138
139  /**
140   * Enables the Android ripple effect and configures its color.
141   */
142  android_ripple?: null | PressableAndroidRippleConfig | undefined;
143
144  /**
145   * Used only for documentation or testing (e.g. snapshot testing).
146   */
147  testOnly_pressed?: null | boolean | undefined;
148
149  /**
150   * Either view styles or a function that receives a boolean reflecting whether
151   * the component is currently pressed and returns view styles.
152   */
153  style?:
154    | StyleProp<ViewStyle>
155    | ((state: PressableStateCallbackType) => StyleProp<ViewStyle>)
156    | undefined;
157
158  /**
159   * Duration (in milliseconds) to wait after press down before calling onPressIn.
160   */
161  unstable_pressDelay?: number | undefined;
162}
163
164// TODO use React.AbstractComponent when available
165export const Pressable: React.ForwardRefExoticComponent<
166  PressableProps & React.RefAttributes<View>
167>;
168