UNPKG

2.78 kBJavaScriptView Raw
1import React from 'react';
2
3import {
4 ScrollView, Text, TouchableWithoutFeedback, View,
5} from 'react-native';
6
7// import PropTypes from 'prop-types';
8
9import { isEqual } from './helper';
10
11function Select({
12 children, multiple, onChange, options, style, value,
13}) {
14
15 // 兼容自定义标签
16 if (options === undefined) {
17 options = children;
18 }
19
20 // 兼容单个选项
21 if (!Array.isArray(options)) {
22 options = options ? [options] : [];
23 }
24
25 const values = [], selected = [];
26 const onSelect = index => {
27 // 未定义回调
28 if (onChange === undefined) return;
29
30 // 单选
31 if (!multiple) {
32 return onChange(values[index], index);
33 }
34
35 // 切换状态
36 if (index in selected) {
37 delete selected[index];
38 } else {
39 selected[index] = values[index];
40 }
41
42 // 执行回调
43 onChange(selected.filter(option => option === undefined), Object.keys(selected));
44 };
45 const isSelected = ({ props }, index) => {
46 // 判断 selected
47 let isTrue = value === undefined && props.selected;
48
49 // 判断 value
50 if (multiple) {
51 isTrue = isTrue || value.findIndex(_value => isEqual(_value, props.value)) !== -1;
52 } else {
53 if (selected.length > 1) return false;
54 isTrue = isTrue || isEqual(value, props.value);
55 }
56
57 // 处理选中
58 if (isTrue) {
59 selected[index] = props.value;
60 return true;
61 }
62
63 return false;
64 };
65
66 // 界面渲染
67 return (
68 <ScrollView style={[{ flexGrow: 1, flexShrink: 0 }, style]}>
69 {options.map((item, index) => {
70 // number | string
71 if (typeof item in { number: null, string: null }) {
72 item = <Text value={item}>{item}</Text>;
73 }
74
75 // object<{ label, value }>
76 if (item.label !== undefined) {
77 item = <Text value={item.value || item.label}>{item.label}</Text>;
78 }
79
80 // 填充 values 相应键值
81 values[index] = item.props.value;
82
83 // 是否选中
84 const selected = isSelected(item, index);
85
86 // Text 兼容
87 if (item.type === Text) {
88 item = (
89 <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
90 <Text {...item.props} style={[{ backgroundColor: 'transparent' }, item.props.style]} />
91 {selected ? <Text>-</Text> : null}
92 </View>
93 );
94 }
95
96 // 渲染单条
97 return (
98 <TouchableWithoutFeedback key={index} onPress={() => onSelect(index)}>
99 <View>
100 <item.type {...item.props} selected={selected} />
101 </View>
102 </TouchableWithoutFeedback>
103 );
104 })}
105 </ScrollView>
106 );
107}
108Select.propTypes = {};
109Select.defaultProps = {};
110
111export default Select;