Commit 1ee66e56 authored by XieZhiXiong's avatar XieZhiXiong

feat: 添加Checkbox组件

parent c9b470b7
/*
* @Author: XieZhiXiong
* @Date: 2021-03-11 20:05:02
* @LastEditors: XieZhiXiong
* @LastEditTime: 2021-03-12 10:17:38
* @Description: 多选组
*/
import React from 'react';
// import { View } from 'react-native';
interface CheckboxData {
/**
* 选中的值
*/
value: any[];
/**
* 选中改变触发事件
*/
toggleChange: ((value: any) => void) | undefined;
/**
* 是否禁用
*/
disabled: boolean;
/**
* checkbox 大小,默认 22
*/
size: number;
}
export const CheckboxContext = React.createContext<CheckboxData>({
value: [],
toggleChange: undefined,
disabled: false,
size: 22,
});
interface CheckboxGroupProps {
/**
* 当前选中值
*/
value?: React.Key[];
/**
* 默认选中值当前选中值
*/
defaultValue?: React.Key[];
/**
* 选项变化时的回调函数
*/
onChange?: (value: React.Key[]) => void;
/**
* 禁选所有子单选器
*/
disabled?: boolean;
/**
* 单选框大小,默认22,只对 单选样式生效
*/
size?: number;
children?: React.ReactNode;
}
interface CheckboxGroupState {
value: any;
toggleChange: (value: React.Key[]) => void | undefined;
}
class CheckboxGroup extends React.Component<
CheckboxGroupProps,
CheckboxGroupState
> {
static getDerivedStateFromProps(nextProps: CheckboxGroupProps) {
const { value } = nextProps;
if ('value' in nextProps) {
return {
value,
};
}
return null;
}
constructor(props: CheckboxGroupProps) {
super(props);
this.state = {
value: props.defaultValue || [],
toggleChange: this.toggleChange,
};
}
toggleChange = (next: any) => {
const { value } = this.state;
const { onChange } = this.props;
if (next === value) {
return;
}
if (!('value' in this.props)) {
this.setState({
value: next,
});
}
if (onChange) {
onChange(next);
}
};
render() {
const { disabled, size, children } = this.props;
return (
<CheckboxContext.Provider
value={{
...this.state,
disabled: !!disabled,
size: size as number,
}}
>
{children}
</CheckboxContext.Provider>
);
}
}
export default CheckboxGroup;
/* eslint-disable react-hooks/exhaustive-deps */
/*
* @Author: XieZhiXiong
* @Date: 2021-02-03 11:17:02
* @LastEditors: XieZhiXiong
* @LastEditTime: 2021-03-19 14:14:29
* @Description: 复选框
* @Todo: 目前只支持单独使用,不支持 group组 使用,有时间在加
*/
import React, { useState, useEffect, useContext } from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import Icons from 'react-native-vector-icons/AntDesign';
import { useTheme } from '@react-navigation/native';
import { ThemeStyle } from '../../constants/theme';
import useAppStyle from '../../hooks/useAppStyle';
import CheckboxGroup, { CheckboxContext } from './Group';
import styles from './styles';
interface CheckboxProps {
/**
* 是否选中
*/
checked?: boolean;
/**
* 是否选中
*/
value?: string | number;
/**
* 选择触发
*/
onChange?: (checked: boolean) => void;
/**
* 选中颜色,默认主题色
*/
color?: string;
/**
* 大小,默认18
*/
size?: number;
children?: React.ReactNode;
}
const Checkbox = (props: CheckboxProps) => {
const {
checked = false,
value,
onChange,
color,
size = 18,
children,
} = props;
const [check, setCheck] = useState(checked);
const checkboxContext = useContext(CheckboxContext);
const myStyle = useAppStyle(styles);
const appTheme = useTheme() as ThemeStyle;
const finalColor = color || appTheme.colors.primary;
useEffect(() => {
if ('checked' in props && !checkboxContext.toggleChange) {
setCheck(checked);
}
}, [checked]);
useEffect(() => {
if (checkboxContext.toggleChange) {
const isCheck =
checkboxContext.value.find(item => item === value) !== undefined;
setCheck(isCheck);
}
}, [checkboxContext.value]);
const triggerChange = (flag: boolean) => {
if (checkboxContext.toggleChange) {
const newData = [...checkboxContext.value];
if (flag) {
newData.push(value);
} else {
const index = newData.findIndex(item => item === value);
if (index !== -1) {
newData.splice(index, 1);
}
}
checkboxContext.toggleChange(newData);
return;
}
if (onChange) {
onChange(flag);
}
};
const handleClick = () => {
const flag = !check;
if (!('value' in props) && !checkboxContext.toggleChange) {
setCheck(flag);
}
triggerChange(flag);
};
const contentNode =
typeof children === 'string' ? (
<Text style={myStyle['checkbox-label']}>{children}</Text>
) : (
children
);
return (
<TouchableOpacity
style={myStyle.checkbox}
activeOpacity={0.8}
onPress={handleClick}
>
<View
style={StyleSheet.flatten([
myStyle['checkbox-icon'],
{
width: size,
height: size,
},
check
? {
...myStyle['checkbox-icon__check'],
backgroundColor: finalColor,
borderColor: finalColor,
}
: null,
])}
>
<Icons
name="check"
size={size - 4}
color="#FFFFFF"
style={{
opacity: check ? 1 : 0,
}}
/>
</View>
{!!children && contentNode}
</TouchableOpacity>
);
};
Checkbox.defaultProps = {
onChange: undefined,
size: 18,
children: null,
};
Checkbox.Group = CheckboxGroup;
export default Checkbox;
/*
* @Author: XieZhiXiong
* @Date: 2021-02-03 11:17:06
* @LastEditors: XieZhiXiong
* @LastEditTime: 2021-02-03 13:55:39
* @Description:
*/
import { StyleSheet } from 'react-native';
import { ThemeStyle } from '../../constants/theme';
import themeLayout from '../../constants/theme/layout';
export default (theme: ThemeStyle) =>
StyleSheet.create({
checkbox: {
flexDirection: 'row',
alignItems: 'center',
// backgroundColor: '#FFFFFF',
},
'checkbox-icon': {
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: '#EBECF0',
borderRadius: 9999,
},
'checkbox-icon__check': {
borderColor: theme.colors.primary,
backgroundColor: theme.colors.primary,
},
'checkbox-label': {
marginLeft: themeLayout['margin-xs'],
fontSize: 12,
color: theme.fonts.black1,
},
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment