-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathPressableWithFeedback.tsx
96 lines (87 loc) · 3.39 KB
/
PressableWithFeedback.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import React, {forwardRef, useState} from 'react';
import type {StyleProp, ViewStyle} from 'react-native';
import type {AnimatedStyle} from 'react-native-reanimated';
import OpacityView from '@components/OpacityView';
import type {Color} from '@styles/theme/types';
import variables from '@styles/variables';
import GenericPressable from './GenericPressable';
import type {PressableRef} from './GenericPressable/types';
import type PressableProps from './GenericPressable/types';
type PressableWithFeedbackProps = PressableProps & {
/** Style for the wrapper view */
wrapperStyle?: StyleProp<AnimatedStyle<ViewStyle>>;
/**
* Determines what opacity value should be applied to the underlaying view when Pressable is pressed.
* To disable dimming, pass 1 as pressDimmingValue
* @default variables.pressDimValue
*/
pressDimmingValue?: number;
/**
* Determines what opacity value should be applied to the underlaying view when pressable is hovered.
* To disable dimming, pass 1 as hoverDimmingValue
* @default variables.hoverDimValue
*/
hoverDimmingValue?: number;
/** Whether the view needs to be rendered offscreen (for Android only) */
needsOffscreenAlphaCompositing?: boolean;
/** The color of the underlay that will show through when the Pressable is active. */
underlayColor?: Color;
};
function PressableWithFeedback(
{
children,
wrapperStyle = [],
needsOffscreenAlphaCompositing = false,
pressDimmingValue = variables.pressDimValue,
hoverDimmingValue = variables.hoverDimValue,
...rest
}: PressableWithFeedbackProps,
ref: PressableRef,
) {
const [isPressed, setIsPressed] = useState(false);
const [isHovered, setIsHovered] = useState(false);
return (
<OpacityView
shouldDim={!!(!rest.disabled && (isPressed || isHovered))}
dimmingValue={isPressed ? pressDimmingValue : hoverDimmingValue}
style={wrapperStyle}
needsOffscreenAlphaCompositing={needsOffscreenAlphaCompositing}
>
<GenericPressable
ref={ref}
// eslint-disable-next-line react/jsx-props-no-spreading
{...rest}
disabled={rest.disabled}
onHoverIn={(event) => {
setIsHovered(true);
if (rest.onHoverIn) {
rest.onHoverIn(event);
}
}}
onHoverOut={(event) => {
setIsHovered(false);
if (rest.onHoverOut) {
rest.onHoverOut(event);
}
}}
onPressIn={(event) => {
setIsPressed(true);
if (rest.onPressIn) {
rest.onPressIn(event);
}
}}
onPressOut={(event) => {
setIsPressed(false);
if (rest.onPressOut) {
rest.onPressOut(event);
}
}}
>
{(state) => (typeof children === 'function' ? children(state) : children)}
</GenericPressable>
</OpacityView>
);
}
PressableWithFeedback.displayName = 'PressableWithFeedback';
export default forwardRef(PressableWithFeedback);
export type {PressableWithFeedbackProps};