1 | import * as React from 'react';
|
2 | import {
|
3 | View,
|
4 | ViewStyle,
|
5 | StyleSheet,
|
6 | StyleProp,
|
7 | GestureResponderEvent,
|
8 | TouchableWithoutFeedback,
|
9 | } from 'react-native';
|
10 | import color from 'color';
|
11 |
|
12 | import TouchableRipple from './TouchableRipple/TouchableRipple';
|
13 | import Icon, { IconSource } from './Icon';
|
14 | import CrossFadeIcon from './CrossFadeIcon';
|
15 | import { withTheme } from '../core/theming';
|
16 |
|
17 | import type { $RemoveChildren } from '../types';
|
18 |
|
19 | type Props = $RemoveChildren<typeof TouchableRipple> & {
|
20 | |
21 |
|
22 |
|
23 | icon: IconSource;
|
24 | |
25 |
|
26 |
|
27 | color?: string;
|
28 | |
29 |
|
30 |
|
31 | size?: number;
|
32 | |
33 |
|
34 |
|
35 | disabled?: boolean;
|
36 | |
37 |
|
38 |
|
39 | animated?: boolean;
|
40 | |
41 |
|
42 |
|
43 | accessibilityLabel?: string;
|
44 | |
45 |
|
46 |
|
47 | onPress?: (e: GestureResponderEvent) => void;
|
48 | style?: StyleProp<ViewStyle>;
|
49 | ref?: React.RefObject<TouchableWithoutFeedback>;
|
50 | |
51 |
|
52 |
|
53 | theme: ReactNativePaper.Theme;
|
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 | const IconButton = ({
|
91 | icon,
|
92 | color: customColor,
|
93 | size = 24,
|
94 | accessibilityLabel,
|
95 | disabled,
|
96 | onPress,
|
97 | animated = false,
|
98 | theme,
|
99 | style,
|
100 | ...rest
|
101 | }: Props) => {
|
102 | const iconColor =
|
103 | typeof customColor !== 'undefined' ? customColor : theme.colors.text;
|
104 | const rippleColor = color(iconColor).alpha(0.32).rgb().string();
|
105 | const IconComponent = animated ? CrossFadeIcon : Icon;
|
106 | const buttonSize = size * 1.5;
|
107 | return (
|
108 | <TouchableRipple
|
109 | borderless
|
110 | centered
|
111 | onPress={onPress}
|
112 | rippleColor={rippleColor}
|
113 | style={[
|
114 | styles.container,
|
115 | { width: buttonSize, height: buttonSize, borderRadius: buttonSize / 2 },
|
116 | disabled && styles.disabled,
|
117 | style,
|
118 | ]}
|
119 | accessibilityLabel={accessibilityLabel}
|
120 |
|
121 | accessibilityTraits={disabled ? ['button', 'disabled'] : 'button'}
|
122 | accessibilityComponentType="button"
|
123 | accessibilityRole="button"
|
124 | accessibilityState={{ disabled }}
|
125 | disabled={disabled}
|
126 | hitSlop={
|
127 | TouchableRipple.supported
|
128 | ? { top: 10, left: 10, bottom: 10, right: 10 }
|
129 | : { top: 6, left: 6, bottom: 6, right: 6 }
|
130 | }
|
131 | {...rest}
|
132 | >
|
133 | <View>
|
134 | <IconComponent color={iconColor} source={icon} size={size} />
|
135 | </View>
|
136 | </TouchableRipple>
|
137 | );
|
138 | };
|
139 |
|
140 | const styles = StyleSheet.create({
|
141 | container: {
|
142 | alignItems: 'center',
|
143 | justifyContent: 'center',
|
144 | overflow: 'hidden',
|
145 | margin: 6,
|
146 | },
|
147 | disabled: {
|
148 | opacity: 0.32,
|
149 | },
|
150 | });
|
151 |
|
152 | export default withTheme(IconButton);
|