UNPKG

@uiw/react-native

Version:
203 lines (184 loc) 5.65 kB
import { View, Text, StyleSheet, TouchableHighlight } from 'react-native'; import React, { Component } from 'react'; import { Picker } from '@react-native-picker/picker'; import arrayTreeFilter from '../utils/arrayTreeFilter'; import Modal from '../Modal'; import { colors } from '../utils'; export default class SelectCascader extends Component { static defaultProps = { dismissText: '取消', okText: '确定', title: '请选择', cols: 3, maskClosable: true }; state = { value: new Array(), modalVisible: this.props.visible, controlVisible: 'props' }; static getDerivedStateFromProps(props, state) { if (JSON.stringify(props.value) === JSON.stringify(state.value) && state.controlVisible === 'props' && state.modalVisible === props.visible) { return null; } if (JSON.stringify(props.value) === JSON.stringify(state.value)) { return { modalVisible: state.controlVisible === 'props' ? props.visible : state.modalVisible, controlVisible: 'props' }; } const getValue = (d, val) => { let data = d || props.data; let value = val || props.value || props.defaultValue; if (!value || !value.length || value.indexOf(undefined) > -1) { value = []; for (let i = 0; i < props.cols; i++) { if (data && data.length) { value[i] = data[0].value; if (data[0].children) { data = data[0].children; } } } } return value; }; if (JSON.stringify(props.value) !== JSON.stringify(state.value) && state.controlVisible === 'props' && state.modalVisible === props.visible) { return { value: getValue(props.data, props.value) }; } return { value: getValue(props.data, props.value), modalVisible: state.controlVisible === 'props' ? props.visible : state.modalVisible, controlVisible: 'props' }; } getSel(value) { if (!value) { return ''; } const treeChildren = arrayTreeFilter(this.props.data, (c, level) => { return c.value === value[level]; }); return treeChildren.map(v => { return v.label; }).join(','); } onValueChange = (itemValue, index) => { const value = this.state.value.concat(); value[index] = itemValue; const children = arrayTreeFilter(this.props.data, (c, level) => { return level <= index && c.value === value[level]; }); let data = children[index]; let i; for (i = index + 1; data && data.children && data.children.length && i < this.props.cols; i++) { data = data.children[0]; value[i] = data.value; } value.length = i; value[index] = itemValue; this.setState({ value }); if (this.props.onChange) { this.props.onChange(value, this.getSel(value)); } }; getCols = () => { const { data, cols, pickerItemStyle } = this.props; const { value } = this.state; const childrenTree = arrayTreeFilter(data, (c, level) => { return c.value === value[level]; }).map(c => c.children); 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((children = [], level) => <Picker key={level} // eslint-disable-next-line react-native/no-inline-styles style={{ flex: 1 }} selectedValue={value[level]} onValueChange={itemValue => this.onValueChange(itemValue, level)} itemStyle={pickerItemStyle}> {children.map(item => <Picker.Item value={item.value} label={item.label} key={item.value} />)} </Picker>); }; onDismiss = () => { if (this.props.onDismiss) { this.props.onDismiss(); } }; onOk = () => { if (this.props.onOk) { const { value } = this.state; this.props.onOk(value, this.getSel(value)); } }; render() { const { title, dismissText, okText, activeOpacity = 1, underlayColor = '#f1f1f1', onDismiss, headerStyle, maskClosable, renderDismissNode, renderTitleNode, renderOkNode } = this.props; const cols = this.getCols(); return <Modal visible={this.state.modalVisible} onClosed={() => { maskClosable && this.setState({ modalVisible: false, controlVisible: 'state' }); }}> <> <View style={[styles.header, headerStyle]}> <TouchableHighlight activeOpacity={activeOpacity} underlayColor={underlayColor} onPress={onDismiss} style={[styles.headerItem]}> {renderDismissNode ?? <Text>{dismissText}</Text>} </TouchableHighlight> <View style={[styles.headerItem]}>{renderTitleNode ?? <Text>{title}</Text>}</View> <TouchableHighlight activeOpacity={activeOpacity} underlayColor={underlayColor} onPress={this.onOk} style={[styles.headerItem]}> {renderOkNode ?? <Text>{okText}</Text>} </TouchableHighlight> </View> <View style={styles.list}>{cols}</View> </> </Modal>; } } const styles = StyleSheet.create({ header: { height: 44, alignItems: 'center', flexDirection: 'row', justifyContent: 'center', borderBottomWidth: 1, borderBottomColor: colors.blue }, headerItem: { height: 44, alignItems: 'center', justifyContent: 'center', flex: 1 }, list: { flexDirection: 'row', alignItems: 'center' } });