import * as React from 'react' ; import AntPicker from '@ant-design/react-native/lib/picker' ; import { noop } from '../../utils' ; import { MultiSelectorProps , MultiSelectorState } from './PropsType' ; import { TouchableWithoutFeedback } from 'react-native' ; returns function shallowDiffValue ( value = [ ] , lastValue = [ ] ) { if ( value . length !== lastValue . length ) return false ; for ( let i = 0 ; i < value . length ; i ++ ) { if ( value [ i ] !== lastValue [ i ] ) { return false ; } } return true ; } function convertToObj ( item ? , rangeKey = '' ) { if ( typeof item === 'object' ) { return { value : item [ rangeKey ] , label : item [ rangeKey ] } ; } else { return { value : item , label : item } ; } } function formatRange ( range = [ ] , rangeKey ? ) { const result = ( range [ 0 ] || [ ] ) . map ( item => { return convertToObj ( item , rangeKey ) ; } ) ; let tmp = result ; for ( let i = 1 ; i < range . length ; i ++ ) { const nextColData = ( range [ i ] || [ ] ) . map ( item => { return convertToObj ( item , rangeKey ) ; } ) ; tmp . forEach ( item => { item . children = nextColData ; } ) ; tmp = nextColData ; } return result ; } function getIndexByValues ( range = [ ] , value = [ ] ) { let tmp = range ; return value . map ( v => { for ( let i = 0 ; i < tmp . length ; i ++ ) { if ( tmp [ i ] . value === v ) { tmp = tmp [ i ] . children || [ ] ; return i ; } } return 0 ; } ) ; } export default class MultiSelector extends React . Component < MultiSelectorProps , MultiSelectorState > { static defaultProps = { range : [ ] , value : [ ] } ; state : MultiSelectorState = { cols : 3 , pRange : [ ] , pValue : [ ] , range : [ ] , value : [ ] } ; dismissByOk = false ; static getDerivedStateFromProps ( nextProps , lastState ) { let ret = null ; if ( nextProps . range !== lastState . pRange ) { ret = ret || { } ; nextProps . range && ( ret . cols = nextProps . range . length ) ; ret . pRange = nextProps . range ; ret . range = formatRange ( nextProps . range , nextProps . rangeKey ) ; } if ( ! shallowDiffValue ( nextProps . value , lastState . pValue ) ) { ret = ret || { } ; ret . pValue = nextProps . value ; let tmp = ( ret && ret . range ) || lastState . range ; ret . value = ( nextProps . value || [ ] ) . map ( ( valIndex = 0 ) => { const v = tmp [ valIndex ] && tmp [ valIndex ] . value ; tmp = ( tmp [ valIndex ] && tmp [ valIndex ] . children ) || [ ] ; return v ; } ) ; } return ret ; } onChange = ( value ) : void => { const { onChange = noop } = this . props ; const { range } = this . state ; onChange ( { detail : { value : getIndexByValues ( range , value ) } } ) ; } ; onPickerChange = ( value ) : void => { const { onColumnChange = noop } = this . props ; const { range , value : stateValue } = this . state ; const indexes = getIndexByValues ( range , value ) ; let changingColIndex = 0 ; for ( let i = 0 ; i < stateValue . length ; i ++ ) { if ( stateValue [ i ] !== value [ i ] ) { changingColIndex = i ; break ; } } onColumnChange ( { detail : { column : changingColIndex , value : indexes [ changingColIndex ] } } ) ; this . setState ( { value } ) ; } ; onOk = ( ) : void => { this . dismissByOk = true ; } ; onVisibleChange = ( visible ) : void => { if ( ! visible && ! this . dismissByOk ) { const { onCancel = noop } = this . props ; onCancel ( ) ; } this . dismissByOk = false ; } ; render ( ) { const { children , disabled } = this . props ; const { cols , range , value } = this . state ; return ( < AntPicker data = { range } value = { value } cols = { cols } onChange = { this . onChange } onPickerChange = { this . onPickerChange } onOk = { this . onOk } onVisibleChange = { this . onVisibleChange } disabled = { disabled } > < TouchableWithoutFeedback > { children } < /TouchableWithoutFeedback> < /AntPicker>); } }