@uiw/react-native
Version:
UIW for React Native
139 lines (137 loc) • 4.07 kB
JavaScript
import React from 'react';
import { SafeAreaView, TouchableOpacity, View } from 'react-native';
import { arrayTreeFilter } from '../utils/utils';
import Flex from '../Flex';
import Text from '../Typography/Text';
import Modal from '../Modal';
import WheelPicker from './components/WheelPicker';
import { useTheme } from '@shopify/restyle';
/** 弹窗Picker的属性 */
const generateNextValue = (data, value, cols) => {
let d = data;
let level = 0;
const nextValue = [];
if (value && value.length) {
do {
const index = d.findIndex(item => item.value + '' === value[level] + '');
if (index < 0) {
break;
}
nextValue[level] = value[level] + '';
level += 1;
d = d[index].children || [];
} while (d.length > 0);
}
for (let i = level; i < cols; i++) {
if (d && d.length) {
nextValue[i] = d[0].value + '';
d = d[0].children || [];
} else {
break;
}
}
return nextValue;
};
function Picker(props) {
const {
cols = 1,
data = [],
visible = false,
displayType = 'view',
cancelText = '取消',
okText = '确定',
title,
onClosed,
onChange,
...restProps
} = props;
const theme = useTheme();
const [value, setValue] = React.useState(generateNextValue(data, props.value, cols));
React.useEffect(() => {
setValue(generateNextValue(data, props.value, cols));
}, [data, props.value]);
const onValueChange = (value, index) => {
// 修改当前的值,然后把后面的值都清掉
const newValue = [...value];
newValue[index] = value + '';
newValue.length = index + 1;
const nextValue = generateNextValue(data, newValue, cols);
setValue(nextValue);
if (displayType === 'view') {
onChange?.(value);
}
};
const getCols = () => {
const childrenTree = arrayTreeFilter(data, (c, level) => {
return c.value + '' === value[level] + '';
}).map(c => c.children);
// in case the users data is async get when select change
const needPad = cols - childrenTree.length;
if (needPad > 0) {
for (let i = 0; i < needPad; i++) {
childrenTree.push([]);
}
}
childrenTree.length = cols - 1;
childrenTree.unshift(data);
return childrenTree.map((item = [], level) => <WheelPicker containerStyle={{
marginRight: level !== childrenTree.length - 1 ? 5 : 0
}} key={level} {...restProps} {...{
data: item.map(el => ({
...el,
value: `${el.value}`
})),
value: `${value[level]}`
}} onChange={val => onValueChange(val, level)} />);
};
const handleOk = () => {
onChange?.(value);
onClosed?.();
};
const handleClose = () => {
onClosed?.();
};
const PickerComp = <Flex>{getCols()}</Flex>;
if (displayType === 'modal') {
return <Modal visible={visible} onClosed={handleClose}>
<SafeAreaView>
<View style={{
padding: 8
}}>
<Flex justify="between">
<Flex.Item>
<TouchableOpacity activeOpacity={0.5} onPress={handleClose}>
<Text color="primary_background" style={{
fontSize: 16
}}>
{cancelText}
</Text>
</TouchableOpacity>
</Flex.Item>
<Flex.Item>
<Text color="primary_background" style={{
fontSize: 16
}}>
{title}
</Text>
</Flex.Item>
<Flex.Item>
<TouchableOpacity activeOpacity={0.5} onPress={handleOk}>
<Text color="primary_background" style={{
fontSize: 16
}}>
{okText}
</Text>
</TouchableOpacity>
</Flex.Item>
</Flex>
<View style={{
height: '100%'
}}>{PickerComp}</View>
</View>
</SafeAreaView>
</Modal>;
}
return PickerComp;
}
export default Picker;