Skip to content

Commit b25761a

Browse files
authored
Typescript - RadioButton and RadioGroup (#766)
* Typescript - RadioButton and RadioGroup * Move propTypes in to the files * Revert RadioGroup deletion * Rename RadioGroup * Use ImageSourcePropType * Revert splitting getAccessibilityProps (add ts-ignore)
1 parent 423fc33 commit b25761a

File tree

14 files changed

+304
-224
lines changed

14 files changed

+304
-224
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React from 'react';
2+
import { TextStyle, ImageStyle } from 'react-native';
3+
interface RadioButtonPropTypes {
4+
/**
5+
* The identifier value of the radio button. must be different than other RadioButtons in the same group
6+
*/
7+
value?: string | boolean;
8+
/**
9+
* When using RadioButton without a RadioGroup, use this prop to toggle selection
10+
*/
11+
selected?: boolean;
12+
/**
13+
* Invoked when pressing the button
14+
*/
15+
onPress?: Function;
16+
/**
17+
* Whether the radio button should be disabled
18+
*/
19+
disabled?: boolean;
20+
/**
21+
* The color of the radio button
22+
*/
23+
color?: string;
24+
/**
25+
* The size of the radio button, affect both width & height
26+
*/
27+
size?: number;
28+
/**
29+
* The radio button border radius
30+
*/
31+
borderRadius?: number;
32+
/**
33+
* A label for the radio button description
34+
*/
35+
label?: string;
36+
/**
37+
* Label style
38+
*/
39+
labelStyle?: TextStyle;
40+
/**
41+
* Icon image source
42+
*/
43+
iconSource?: object | number;
44+
/**
45+
* Icon image style
46+
*/
47+
iconStyle?: ImageStyle;
48+
/**
49+
* Should the icon be on the right side of the label
50+
*/
51+
iconOnRight?: boolean;
52+
}
53+
declare const _default: React.ComponentType<RadioButtonPropTypes>;
54+
export default _default;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from 'react';
2+
interface RadioGroupPropTypes {
3+
/**
4+
* The initial value of the selected radio button
5+
*/
6+
initialValue?: string | boolean;
7+
/**
8+
* Invoked once when value changes, by selecting one of the radio buttons in the group
9+
*/
10+
onValueChange?: Function;
11+
}
12+
declare const _default: React.ComponentType<RadioGroupPropTypes>;
13+
export default _default;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from 'react';
2+
export interface RadioGroupContextPropTypes {
3+
/**
4+
* The identifier value of the radio button. must be different than other RadioButtons in the same group
5+
*/
6+
value?: string | boolean;
7+
/**
8+
* Invoked once when value changes, by selecting one of the radio buttons in the group
9+
*/
10+
onValueChange?: Function;
11+
}
12+
declare const _default: React.Context<RadioGroupContextPropTypes>;
13+
export default _default;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import React from 'react';
2+
export default function asRadioGroupChild(WrappedComponent: React.ComponentType<any>): any;

generatedTypes/index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ export {default as View} from './components/view';
88
export {default as Text} from './components/text';
99
export {default as TouchableOpacity} from './components/touchableOpacity';
1010
export {default as Button} from './components/button';
11+
export {default as RadioButton} from './components/radioButton/RadioButton';
12+
export {default as RadioGroup} from './components/radioButton/RadioGroup';
1113

1214
/* All components with manual typings */
1315
export {
@@ -41,8 +43,6 @@ export {
4143
Stepper,
4244
TabBar,
4345
TagsInput,
44-
RadioButton,
45-
RadioGroup,
4646
SharedTransition,
4747
StackAggregator,
4848
Toast,

src/components/radioButton/RadioButton.js renamed to src/components/radioButton/RadioButton.tsx

Lines changed: 96 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,109 @@
11
import _ from 'lodash';
2-
import PropTypes from 'prop-types';
3-
import React from 'react';
4-
import {StyleSheet, Animated, Easing} from 'react-native';
2+
import React, {PureComponent} from 'react';
3+
import {
4+
StyleSheet,
5+
Animated,
6+
Easing,
7+
TextStyle,
8+
StyleProp,
9+
ImageSourcePropType,
10+
ImageStyle,
11+
ViewStyle,
12+
ViewProps
13+
} from 'react-native';
514
import {Colors} from '../../style';
6-
import {BaseComponent} from '../../commons';
15+
import {asBaseComponent, forwardRef, BaseComponentInjectedProps, ForwardRefInjectedProps} from '../../commons/new';
716
import TouchableOpacity from '../touchableOpacity';
817
import View from '../view';
918
import Text from '../text';
10-
import Image from '../image';
19+
const Image = require('../image').default; // TODO: change this once Image is written in typescript
1120
import asRadioGroupChild from './asRadioGroupChild';
21+
import {RadioGroupContextPropTypes} from './RadioGroupContext';
1222

1323
const DEFAULT_SIZE = 24;
1424
const DEFAULT_COLOR = Colors.blue30;
1525

26+
interface RadioButtonPropTypes {
27+
/**
28+
* The identifier value of the radio button. must be different than other RadioButtons in the same group
29+
*/
30+
value?: string | boolean;
31+
/**
32+
* When using RadioButton without a RadioGroup, use this prop to toggle selection
33+
*/
34+
selected?: boolean;
35+
/**
36+
* Invoked when pressing the button
37+
*/
38+
onPress?: Function;
39+
/**
40+
* Whether the radio button should be disabled
41+
*/
42+
disabled?: boolean;
43+
/**
44+
* The color of the radio button
45+
*/
46+
color?: string;
47+
/**
48+
* The size of the radio button, affect both width & height
49+
*/
50+
size?: number;
51+
/**
52+
* The radio button border radius
53+
*/
54+
borderRadius?: number;
55+
/**
56+
* A label for the radio button description
57+
*/
58+
label?: string;
59+
/**
60+
* Label style
61+
*/
62+
labelStyle?: TextStyle;
63+
/**
64+
* Icon image source
65+
*/
66+
iconSource?: ImageSourcePropType;
67+
/**
68+
* Icon image style
69+
*/
70+
iconStyle?: ImageStyle;
71+
/**
72+
* Should the icon be on the right side of the label
73+
*/
74+
iconOnRight?: boolean;
75+
}
76+
77+
interface RadioButtonState {
78+
opacityAnimationValue: Animated.Value;
79+
scaleAnimationValue: Animated.Value;
80+
}
81+
82+
type Props = RadioButtonPropTypes &
83+
RadioGroupContextPropTypes &
84+
BaseComponentInjectedProps &
85+
ForwardRefInjectedProps &
86+
ViewProps;
87+
1688
/**
1789
* A Radio Button component, should be wrapped inside a RadioGroup
1890
*/
19-
class RadioButton extends BaseComponent {
91+
class RadioButton extends PureComponent<Props, RadioButtonState> {
2092
static displayName = 'RadioButton';
2193

22-
static propTypes = {
23-
/**
24-
* The identifier value of the radio button. must be different than other RadioButtons in the same group
25-
*/
26-
value: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
27-
/**
28-
* When using RadioButton without a RadioGroup, use this prop to toggle selection
29-
*/
30-
selected: PropTypes.bool,
31-
/**
32-
* Invoked when pressing the button
33-
*/
34-
onPress: PropTypes.func,
35-
/**
36-
* Whether the radio button should be disabled
37-
*/
38-
disabled: PropTypes.bool,
39-
/**
40-
* The color of the radio button
41-
*/
42-
color: PropTypes.string,
43-
/**
44-
* The size of the radio button, affect both width & height
45-
*/
46-
size: PropTypes.number,
47-
/**
48-
* The radio button border radius
49-
*/
50-
borderRadius: PropTypes.number,
51-
/**
52-
* A label for the radio button description
53-
*/
54-
label: PropTypes.string,
55-
/**
56-
* Label style
57-
*/
58-
labelStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number, PropTypes.array]),
59-
/**
60-
* Icon image source
61-
*/
62-
iconSource: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
63-
/**
64-
* Icon image style
65-
*/
66-
iconStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number, PropTypes.array]),
67-
/**
68-
* Should the icon be on the right side of the label
69-
*/
70-
iconOnRight: PropTypes.bool
71-
};
72-
7394
static defaultProps = {
7495
iconOnRight: false
7596
};
7697

77-
constructor(props) {
98+
styles: {
99+
radioButtonOutline: StyleProp<ViewStyle>;
100+
radioButtonInner: StyleProp<ViewStyle>;
101+
image: StyleProp<ImageStyle>;
102+
};
103+
104+
constructor(props: Props) {
78105
super(props);
106+
this.styles = createStyles(props);
79107
this.state = {
80108
opacityAnimationValue: new Animated.Value(0),
81109
scaleAnimationValue: new Animated.Value(0.8)
@@ -86,7 +114,7 @@ class RadioButton extends BaseComponent {
86114
this.animate();
87115
}
88116

89-
componentDidUpdate(prevProps) {
117+
componentDidUpdate(prevProps: Props) {
90118
if (prevProps.selected !== this.props.selected) {
91119
this.animate();
92120
}
@@ -128,10 +156,6 @@ class RadioButton extends BaseComponent {
128156
}
129157
}
130158

131-
generateStyles() {
132-
this.styles = createStyles(this.getThemeProps());
133-
}
134-
135159
onPress = () => {
136160
const {disabled, value, selected} = this.props;
137161
if (!disabled) {
@@ -141,7 +165,7 @@ class RadioButton extends BaseComponent {
141165
};
142166

143167
getAccessibilityProps = () => {
144-
const {label = '', selected, disabled} = this.getThemeProps();
168+
const {label = '', selected, disabled} = this.props;
145169
const selectedAccessibilityText = selected ? 'selected' : 'unselected';
146170
const accessibilityLabel = `${selectedAccessibilityText}. ${label}`;
147171

@@ -154,7 +178,7 @@ class RadioButton extends BaseComponent {
154178
};
155179

156180
getRadioButtonOutlineStyle() {
157-
const {color, size, borderRadius, style: propsStyle, disabled} = this.getThemeProps();
181+
const {color, size, borderRadius, style: propsStyle, disabled} = this.props;
158182
const style = [this.styles.radioButtonOutline];
159183

160184
if (size) {
@@ -172,7 +196,7 @@ class RadioButton extends BaseComponent {
172196
}
173197

174198
getRadioButtonInnerStyle() {
175-
const {color, borderRadius, disabled} = this.getThemeProps();
199+
const {color, borderRadius, disabled} = this.props;
176200
const style = [this.styles.radioButtonInner];
177201

178202
if (borderRadius) {
@@ -197,18 +221,18 @@ class RadioButton extends BaseComponent {
197221
}
198222

199223
renderIcon() {
200-
const {iconSource} = this.props;
201-
const {iconStyle} = this.getThemeProps();
224+
const {iconSource, iconStyle} = this.props;
202225
const style = [this.styles.image, iconStyle];
203226
return iconSource && <Image style={style} source={iconSource}/>;
204227
}
205228

206229
render() {
207-
const {onPress, onValueChange, ...others} = this.getThemeProps();
230+
const {onPress, onValueChange, ...others} = this.props;
208231
const {opacityAnimationValue, scaleAnimationValue} = this.state;
209232
const Container = onPress || onValueChange ? TouchableOpacity : View;
210233

211234
return (
235+
// @ts-ignore
212236
<Container
213237
row
214238
centerV
@@ -234,7 +258,8 @@ class RadioButton extends BaseComponent {
234258
}
235259
}
236260

237-
function createStyles({size = DEFAULT_SIZE, borderRadius = DEFAULT_SIZE / 2, color = DEFAULT_COLOR, disabled}) {
261+
function createStyles(props: Props) {
262+
const {size = DEFAULT_SIZE, borderRadius = DEFAULT_SIZE / 2, color = DEFAULT_COLOR, disabled} = props;
238263
return StyleSheet.create({
239264
radioButtonOutline: {
240265
borderWidth: 2,
@@ -255,4 +280,4 @@ function createStyles({size = DEFAULT_SIZE, borderRadius = DEFAULT_SIZE / 2, col
255280
});
256281
}
257282

258-
export default asRadioGroupChild(RadioButton);
283+
export default asBaseComponent<RadioButtonPropTypes>(forwardRef(asRadioGroupChild(RadioButton)));

0 commit comments

Comments
 (0)