@uiw/react-native
Version:
UIW for React Native
105 lines (104 loc) • 3.3 kB
JavaScript
import React from 'react';
import { Pressable, View, StyleSheet } from 'react-native';
import Picker from '../../Picker';
import Ellipsis from '../../Ellipsis';
import Icon from '../../Icon';
import { useTheme } from '@shopify/restyle';
import { getTreeDeep } from '../../utils/tree-select';
export default function (props) {
const {
disabled,
placeholder,
contentStyle,
extra,
showClear,
options = [],
value = [],
onChange,
...others
} = props;
const theme = useTheme();
const [visible, setVisible] = React.useState(false);
// 递归树数据
const [deep, optionsMap, optionsParentMap] = React.useMemo(() => {
const deep = getTreeDeep(options, 'children');
const optionsMap = new Map();
const optionsParentMap = new Map();
function traverse(current, children) {
children.forEach(item => {
optionsParentMap.set(item['value'] + '', current);
optionsMap.set(item['value'] + '', item);
if (item['children']) {
traverse(item, item['children']);
}
});
}
traverse(undefined, options);
return [deep, optionsMap, optionsParentMap];
}, [props.options]);
const initialLabelValues = React.useMemo(() => {
const labels = [];
value?.forEach(defaultValue => {
const defaultOption = optionsMap.get(defaultValue);
if (defaultOption) {
labels.push(defaultOption['label']);
}
});
return labels;
}, [value, options]);
const style = createStyles({
disabled: theme.colors.disabled,
backgroundColor: theme.colors.mask,
title: theme.colors.primary_text
});
return <React.Fragment>
<Pressable onPress={() => {
if (disabled) return;
setVisible(true);
}}>
<View style={[disabled ? style.disabled : style.content, contentStyle]}>
<Ellipsis style={[style.contentTitle]} maxLen={30}>
{initialLabelValues.length > 0 && initialLabelValues.join() || placeholder}
</Ellipsis>
{React.isValidElement(extra) ? extra : value && value.length > 0 && showClear ? <Pressable onPress={() => props.onChange?.([])} style={{
paddingRight: 3
}} disabled={disabled}>
<Icon name="circle-close-o" size={18} color={theme.colors.primary_text || '#ccc'} />
</Pressable> : <Icon name="right" size={18} color={theme.colors.text || '#ccc'} />}
</View>
</Pressable>
<Picker displayType="modal" visible={visible} cols={1} value={value} onChange={value => {
onChange?.(value);
}} onClosed={() => setVisible(false)} {...others} data={options} />
</React.Fragment>;
}
function createStyles({
backgroundColor = '#fff',
disabled = '#f5f5f5',
title = '#000'
}) {
return StyleSheet.create({
content: {
flexDirection: 'row',
height: 35,
alignItems: 'center',
justifyContent: 'space-between',
paddingRight: 5,
backgroundColor: backgroundColor,
paddingHorizontal: 16
},
disabled: {
flexDirection: 'row',
height: 35,
alignItems: 'center',
justifyContent: 'space-between',
paddingRight: 5,
backgroundColor: disabled,
paddingHorizontal: 16
},
contentTitle: {
fontSize: 16,
color: title
}
});
}