weex-nuke
Version:
基于 Rax 、Weex 的高性能组件体系 ~~
224 lines (199 loc) • 5.76 kB
JSX
'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;