Skip to content

Infra/TS - Checkbox #789

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class CheckboxScreen extends Component {
value4: true,
value5: false
};

render() {
return (
<View useSafeArea flex>
Expand Down
43 changes: 43 additions & 0 deletions generatedTypes/components/checkbox/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import { StyleProp, TouchableOpacityProps, ViewStyle } from 'react-native';
interface CheckboxProps {
/**
* The value of the Checkbox. If true the switch will be turned on. Default value is false.
*/
value?: boolean;
/**
* Invoked with the new value when the value changes.
*/
onValueChange?: Function;
/**
* Whether the checkbox should be disabled
*/
disabled?: boolean;
/**
* The Checkbox color
*/
color?: string;
/**
* The size of the checkbox. affect both width and height
*/
size?: number;
/**
* The Checkbox border radius
*/
borderRadius?: number;
/**
* The icon asset to use for the selected indication (accept only local assets)
*/
selectedIcon?: number;
/**
* The selected icon color
*/
iconColor?: string;
/**
* Additional styling
*/
style?: StyleProp<ViewStyle>;
}
declare type Props = CheckboxProps & TouchableOpacityProps;
declare const _default: React.ComponentType<Props>;
export default _default;
2 changes: 1 addition & 1 deletion generatedTypes/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export {default as View} from './components/view';
export {default as Text} from './components/text';
export {default as TouchableOpacity} from './components/touchableOpacity';
export {default as Button} from './components/button';
export {default as Checkbox} from './components/checkbox';
export {default as Image} from './components/image';
export {default as Overlay} from './components/overlay';
export {default as RadioButton} from './components/radioButton/RadioButton';
Expand Down Expand Up @@ -67,7 +68,6 @@ export {
/* All components that are missing either manual or auto generated typings */
export const AnimatedImage;
export const AnimatedScanner;
export const Checkbox;
export const ColorPalette;
export const ColorSwatch;
export const DateTimePicker;
Expand Down
146 changes: 89 additions & 57 deletions src/components/checkbox/index.js → src/components/checkbox/index.tsx
Original file line number Diff line number Diff line change
@@ -1,64 +1,98 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React from 'react';
import {Animated, Easing, StyleSheet} from 'react-native';
import React, {Component} from 'react';
import {Animated, Easing, StyleSheet, StyleProp, TouchableOpacityProps, ViewStyle} from 'react-native';
import {Colors} from '../../style';
//@ts-ignore
import Assets from '../../assets';
import {BaseComponent} from '../../commons';
import {asBaseComponent} from '../../commons/new';
import TouchableOpacity from '../touchableOpacity';

const DEFAULT_SIZE = 24;
const DEFAULT_COLOR = Colors.blue30;
const DEFAULT_ICON_COLOR = Colors.white;
const DEFAULT_DISABLED_COLOR = Colors.dark70;

interface CheckboxProps {
/**
* The value of the Checkbox. If true the switch will be turned on. Default value is false.
*/
value?: boolean;
/**
* Invoked with the new value when the value changes.
*/
onValueChange?: Function;
/**
* Whether the checkbox should be disabled
*/
disabled?: boolean;
/**
* The Checkbox color
*/
color?: string;
/**
* The size of the checkbox. affect both width and height
*/
size?: number;
/**
* The Checkbox border radius
*/
borderRadius?: number;
/**
* The icon asset to use for the selected indication (accept only local assets)
*/
selectedIcon?: number;
/**
* The selected icon color
*/
iconColor?: string;
/**
* Additional styling
*/
style?: StyleProp<ViewStyle>
}

type CheckboxState = {
isChecked: Animated.Value;
};

type Props = CheckboxProps & TouchableOpacityProps;

/**
* Checkbox component for toggling boolean value related to some context
* @description: Checkbox component for toggling boolean value related to some context
* @extends: TouchableOpacity
* @extendslink: docs/TouchableOpacity
* @gif: https://media.giphy.com/media/xULW8j5WzsuPytqklq/giphy.gif
* @example: https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/CheckboxScreen.tsx
*/
class Checkbox extends BaseComponent {
class Checkbox extends Component<Props, CheckboxState> {
static displayName = 'Checkbox';
static propTypes = {
/**
* The value of the Checkbox. If true the switch will be turned on. Default value is false.
*/
value: PropTypes.bool,
/**
* Invoked with the new value when the value changes.
*/
onValueChange: PropTypes.func,
/**
* Whether the checkbox should be disabled
*/
disabled: PropTypes.bool,
/**
* The Checkbox color
*/
color: PropTypes.string,
/**
* The size of the checkbox. affect both width and height
*/
size: PropTypes.number,
/**
* The Checkbox border radius
*/
borderRadius: PropTypes.number,
/**
* The icon asset to use for the selected indication (accept only local assets)
*/
selectedIcon: PropTypes.number,
/**
* The selected icon color
*/
iconColor: PropTypes.string

styles: {
container: StyleProp<ViewStyle>;
selectedIcon: StyleProp<ViewStyle>;
};

constructor(props) {
animationStyle: {
opacity: CheckboxState['isChecked'];
transform: [
{
scaleX: CheckboxState['isChecked'];
},
{
scaleY: CheckboxState['isChecked'];
}
];
};

constructor(props: Props) {
super(props);

this.state = {
isChecked: new Animated.Value(this.props.value ? 1 : 0)
};

this.styles = createStyles(props);

this.animationStyle = {
opacity: this.state.isChecked,
transform: [
Expand All @@ -72,15 +106,15 @@ class Checkbox extends BaseComponent {
};
}

componentDidUpdate(prevProps) {
const {value} = this.getThemeProps();
componentDidUpdate(prevProps: Props) {
const {value} = this.props;
if (prevProps.value !== value) {
this.animateCheckbox(value);
}
}

getAccessibilityProps() {
const {accessibilityLabel, disabled, value} = this.getThemeProps();
const {accessibilityLabel, disabled, value} = this.props;
const checkedState = value ? 'checked' : 'unchecked';

return {
Expand All @@ -91,11 +125,7 @@ class Checkbox extends BaseComponent {
};
}

generateStyles() {
this.styles = createStyles(this.getThemeProps());
}

animateCheckbox(value) {
animateCheckbox(value: CheckboxProps['value']) {
const {isChecked} = this.state;

Animated.timing(isChecked, {
Expand All @@ -107,35 +137,35 @@ class Checkbox extends BaseComponent {
}

onPress = () => {
const {disabled} = this.getThemeProps();
const {disabled} = this.props;

if (!disabled) {
_.invoke(this.props, 'onValueChange', !this.props.value);
}
};

getColor() {
const {color, disabled} = this.getThemeProps();
const {color, disabled} = this.props;
return disabled ? DEFAULT_DISABLED_COLOR : color || DEFAULT_COLOR;
}

getBorderStyle() {
const {style: propsStyle} = this.getThemeProps();
const borderColor = {borderColor: this.getColor()};
const style = [this.styles.container, {borderWidth: 2}, borderColor, propsStyle];
const borderStyle = [this.styles.container, {borderWidth: 2}, borderColor];

return style;
return borderStyle;
}

render() {
const {selectedIcon, color, iconColor, disabled, testID, ...others} = this.getThemeProps();
const {selectedIcon, color, iconColor, disabled, testID, style, ...others} = this.props;
return (
// @ts-ignore
<TouchableOpacity
{...this.getAccessibilityProps()}
activeOpacity={1}
testID={testID}
{...others}
style={this.getBorderStyle()}
style={[this.getBorderStyle(), style]}
onPress={this.onPress}
>
{
Expand All @@ -159,7 +189,9 @@ class Checkbox extends BaseComponent {
}
}

function createStyles({color = DEFAULT_COLOR, iconColor = DEFAULT_ICON_COLOR, size = DEFAULT_SIZE, borderRadius}) {
function createStyles(props: Props) {
const {color = DEFAULT_COLOR, iconColor = DEFAULT_ICON_COLOR, size = DEFAULT_SIZE, borderRadius} = props;

return StyleSheet.create({
container: {
width: size,
Expand All @@ -177,4 +209,4 @@ function createStyles({color = DEFAULT_COLOR, iconColor = DEFAULT_ICON_COLOR, si
});
}

export default Checkbox;
export default asBaseComponent<Props>(Checkbox);
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* This is a fake index.ts file, for auto-generating the types of all the inline required components.
* The real index file that will be bundled is "src/index.js".
* The real index file that will be bundled is "src/index.js".
* Please use this file for declaring all the exports, so they could be picked up by typescript's complier
*/

Expand All @@ -9,6 +9,7 @@ export {default as View} from './components/view';
export {default as Text} from './components/text';
export {default as TouchableOpacity} from './components/touchableOpacity';
export {default as Button} from './components/button';
export {default as Checkbox} from './components/checkbox';
export {default as Image} from './components/image';
export {default as Overlay} from './components/overlay';
export {default as RadioButton} from './components/radioButton/RadioButton';
Expand Down