1 | import isString from 'lodash/isString';
|
2 | import omit from 'lodash/omit';
|
3 | import pick from 'lodash/pick';
|
4 | import React, { PureComponent } from 'react';
|
5 | import PropTypes from 'prop-types';
|
6 | import { StyleSheet, Text, TouchableHighlight, View } from './react-native';
|
7 |
|
8 | const styles = StyleSheet.create({
|
9 | container: {
|
10 | flexDirection: 'row',
|
11 | justifyContent: 'flex-start',
|
12 | alignItems: 'center',
|
13 | padding: 8,
|
14 | },
|
15 | touchable: {
|
16 | overflow: 'hidden',
|
17 | },
|
18 | icon: {
|
19 | marginRight: 10,
|
20 | },
|
21 | text: {
|
22 | fontWeight: '600',
|
23 | backgroundColor: 'transparent',
|
24 | },
|
25 | });
|
26 |
|
27 | const IOS7_BLUE = '#007AFF';
|
28 |
|
29 | const TEXT_PROP_NAMES = [
|
30 | 'ellipsizeMode',
|
31 | 'numberOfLines',
|
32 | 'textBreakStrategy',
|
33 | 'selectable',
|
34 | 'suppressHighlighting',
|
35 | 'allowFontScaling',
|
36 | 'adjustsFontSizeToFit',
|
37 | 'minimumFontScale',
|
38 | ];
|
39 |
|
40 | const TOUCHABLE_PROP_NAMES = [
|
41 | 'accessible',
|
42 | 'accessibilityLabel',
|
43 | 'accessibilityHint',
|
44 | 'accessibilityComponentType',
|
45 | 'accessibilityRole',
|
46 | 'accessibilityStates',
|
47 | 'accessibilityTraits',
|
48 | 'onFocus',
|
49 | 'onBlur',
|
50 | 'disabled',
|
51 | 'onPress',
|
52 | 'onPressIn',
|
53 | 'onPressOut',
|
54 | 'onLayout',
|
55 | 'onLongPress',
|
56 | 'nativeID',
|
57 | 'testID',
|
58 | 'delayPressIn',
|
59 | 'delayPressOut',
|
60 | 'delayLongPress',
|
61 | 'activeOpacity',
|
62 | 'underlayColor',
|
63 | 'selectionColor',
|
64 | 'onShowUnderlay',
|
65 | 'onHideUnderlay',
|
66 | 'hasTVPreferredFocus',
|
67 | 'tvParallaxProperties',
|
68 | ];
|
69 |
|
70 | export default function createIconButtonComponent(Icon) {
|
71 | return class IconButton extends PureComponent {
|
72 | static propTypes = {
|
73 | backgroundColor: PropTypes.oneOfType([
|
74 | PropTypes.string,
|
75 | PropTypes.number,
|
76 | ]),
|
77 | borderRadius: PropTypes.number,
|
78 | color: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
79 | size: PropTypes.number,
|
80 | iconStyle: PropTypes.any,
|
81 | style: PropTypes.any,
|
82 | children: PropTypes.node,
|
83 | };
|
84 |
|
85 | static defaultProps = {
|
86 | backgroundColor: IOS7_BLUE,
|
87 | borderRadius: 5,
|
88 | color: 'white',
|
89 | size: 20,
|
90 | };
|
91 |
|
92 | render() {
|
93 | const { style, iconStyle, children, ...restProps } = this.props;
|
94 |
|
95 | const iconProps = pick(
|
96 | restProps,
|
97 | TEXT_PROP_NAMES,
|
98 | 'style',
|
99 | 'name',
|
100 | 'size',
|
101 | 'color'
|
102 | );
|
103 | const touchableProps = pick(restProps, TOUCHABLE_PROP_NAMES);
|
104 | const props = omit(
|
105 | restProps,
|
106 | Object.keys(iconProps),
|
107 | Object.keys(touchableProps),
|
108 | 'iconStyle',
|
109 | 'borderRadius',
|
110 | 'backgroundColor'
|
111 | );
|
112 | iconProps.style = iconStyle ? [styles.icon, iconStyle] : styles.icon;
|
113 |
|
114 | const colorStyle = pick(this.props, 'color');
|
115 | const blockStyle = pick(this.props, 'backgroundColor', 'borderRadius');
|
116 |
|
117 | return (
|
118 | <TouchableHighlight
|
119 | style={[styles.touchable, blockStyle]}
|
120 | {...touchableProps}
|
121 | >
|
122 | <View style={[styles.container, blockStyle, style]} {...props}>
|
123 | <Icon {...iconProps} />
|
124 | {isString(children) ? (
|
125 | <Text style={[styles.text, colorStyle]}>{children}</Text>
|
126 | ) : (
|
127 | children
|
128 | )}
|
129 | </View>
|
130 | </TouchableHighlight>
|
131 | );
|
132 | }
|
133 | };
|
134 | }
|