UNPKG

weex-nuke

Version:

基于 Rax 、Weex 的高性能组件体系 ~~

224 lines (199 loc) 5.76 kB
'use strict'; /** @jsx createElement */ import { Component, createElement, PropTypes } from 'rax'; import View from 'nuke-view'; import { isWeb } from 'nuke-env'; import Touchable from 'nuke-touchable'; import { connectStyle } from 'nuke-theme-provider'; import Icon from 'nuke-icon'; import Input from 'nuke-normal-input'; import stylesProvider from './styles'; const noop = () => {}; class NumberPicker extends Component { constructor(props) { super(props); let value; if ('value' in props) { value = props.value; } else { value = props.defaultValue; } value = this.getValidValue(value); this.state = { value, error: false, focused: false, displayValue: value, }; ['onAdd', 'onReduce', 'onChange', 'onFocus', 'onBlur'].forEach((m) => { this[m] = this[m].bind(this); }); } componentWillReceiveProps(nextProps) { // todo: dynamic min & max if ('value' in nextProps) { const value = this.getValidValue(nextProps.value); this.setState({ value, displayValue: value, }); } } onAdd() { const { max, step } = this.props; const nextValue = parseInt(this.state.value, 10) + parseInt(step, 10); if (!max || nextValue <= max) { this.setValue(nextValue); } } onReduce() { const { min, step } = this.props; const nextValue = parseInt(this.state.value, 10) - parseInt(step, 10); if (!min || nextValue >= min) { this.setValue(nextValue); } } onChange(val, e) { if (this.props.editable) { this.setState({ displayValue: val, }); } // alert(val); this.setValue(val); } onFocus() { this.setState({ focused: true }); } onBlur(e) { // debugger; const val = this.refs.numberpicker.wrappedInstance.getValue(); // alert(val); this.setValue(val); this.setState({ focused: false }); } setValue(displayValue) { let flag; let value; let error = false; const { disabled, autoCorrect, onChange } = this.props; if (disabled) { return; } value = this.state.value; const validValue = this.getValidValue(displayValue); if (autoCorrect) { value = displayValue = validValue; } else { error = validValue.toString() !== displayValue.toString(); if (!error) { value = validValue; } } if (value !== this.state.value || ((flag = true) && value.toString() !== this.state.displayValue.toString())) { if (!('value' in this.props)) { this.setState({ value, displayValue, }); } else if (!error) { this.setState({ displayValue: this.state.value, }); } this.setState({ error, }); if (!flag) { onChange(value); } } else { this.setState({ error, }); } } getValue() { return this.state.value; } getValidValue(value) { const { min, max } = this.props; value = value === '' ? this.state.value : parseInt(value, 10); value = isNaN(value) ? this.state.value : value < min ? min : value > max ? max : value; return value; } render() { const { value, displayValue, focused, error } = this.state; const styles = this.props.themeStyle; const inputWrapStyle = Object.assign({}, styles['input-wrap'], error ? styles['error-input-wrap'] : {}); const { min, max, step, disabled, editable, autoFocus, style = {} } = this.props; const inputAttrs = {}; if (disabled || !editable) { inputAttrs.disabled = true; } const inputStyle = Object.assign( {}, styles.input, isWeb ? styles['input-ff'] : {}, disabled || inputAttrs.disabled ? styles['input-disabled'] : null, error ? styles['error-input'] : {} ); const reduceDisabled = disabled || value <= min || value - step < min; const addDisabled = disabled || value >= max || value + step > max; return ( <View style={[styles['number-picker'], style]}> <Touchable style={[styles.reduce, reduceDisabled ? styles['disabled-button'] : {}]} onPress={this.onReduce}> <Icon style={[styles.icon, reduceDisabled ? styles['icon-disabled'] : {}]} name="minus" /> </Touchable> <Input inputStyle={inputStyle} type="number" fixedFont ref="numberpicker" style={inputWrapStyle} materialDesign={false} min={min} max={max} step={step} autoFocus={autoFocus} {...inputAttrs} value={focused || error ? displayValue : value} onFocus={this.onFocus} onBlur={this.onBlur} onChange={this.onChange} /> <Touchable style={[styles.add, addDisabled ? styles['disabled-button'] : {}]} onPress={this.onAdd}> <Icon style={[styles.icon, addDisabled ? styles['icon-disabled'] : {}]} name="add" /> </Touchable> </View> ); } } NumberPicker.defaultProps = { step: 1, defaultValue: 0, editable: true, disabled: false, autoFocus: false, autoCorrect: false, onChange: noop, style: {}, themeStyle: {}, }; NumberPicker.propTypes = { min: PropTypes.number, max: PropTypes.number, step: PropTypes.number, value: PropTypes.number, editable: PropTypes.bool, disabled: PropTypes.bool, autoFocus: PropTypes.bool, autoCorrect: PropTypes.bool, defaultValue: PropTypes.number, onChange: PropTypes.func, style: PropTypes.any, themeStyle: PropTypes.any, }; NumberPicker.displayName = 'NumberPicker'; const StyledNumberPicker = connectStyle(stylesProvider, { withRef: true })(NumberPicker); export default StyledNumberPicker;