UNPKG

@uiw/react-native

Version:
105 lines (104 loc) 3.3 kB
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 } }); }