weex-nuke
Version:
基于 Rax 、Weex 的高性能组件体系 ~~
222 lines (204 loc) • 5.49 kB
JSX
/** @jsx createElement */
;
import { createElement, Component, PropTypes } from 'rax';
import View from 'nuke-view';
import Touchable from 'nuke-touchable';
import { connectStyle } from 'nuke-theme-provider';
import Icon from 'nuke-icon';
import stylesProvider from '../styles';
/**
* Radio
* @description 单选框
*/
class Radio extends Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
const checked = props.checked || false;
this.state = {
checked,
value: props.value || '',
};
}
componentWillMount() {
if (
this.context.__group__ &&
!this.props.ignoreContext &&
this.context.selectedValue === this.props.value
) {
this.state = {
checked: true,
};
}
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextContext.__group__ && !this.props.ignoreContext) {
if (
typeof nextContext === 'object' &&
nextContext.selectedValue === nextProps.value
) {
this.setState({ checked: true });
} else {
this.setState({ checked: false });
}
} else if ('checked' in nextProps) {
if (nextProps.checked !== this.props.checked) {
this.setState({
checked: nextProps.checked,
});
}
}
}
onChange(e) {
const { onChange, value, disabled } = this.props;
if (disabled) return;
const tmp = this.state.checked;
if (this.context.__group__ && !this.props.ignoreContext) {
this.context.onChange(value, e);
} else if (!('checked' in this.props)) {
this.setState({
checked: !tmp,
});
}
onChange(!tmp);
e.stopPropagation && e.stopPropagation();
}
renderInner(props) {
const {
style,
disabled,
themeStyle,
checkedStyle,
type,
disabledStyle,
size,
} = props;
if (!this.state.checked) return null;
if (type === 'dot') {
let dotStyle = Object.assign({}, themeStyle['dot-inner'], themeStyle[`dot-inner-${size}`],
checkedStyle && checkedStyle.color ? { backgroundColor: checkedStyle.color } : {},
);
if (disabled) {
dotStyle = Object.assign({}, dotStyle, themeStyle['dot-inner-disabled'], {
backgroundColor:
(disabledStyle && disabledStyle.color) ||
themeStyle['dot-inner-disabled'].backgroundColor,
});
}
return <View style={dotStyle} />;
}
const innerStyle = Object.assign({},
themeStyle[`icon-${size}`],
themeStyle[`${type}-inner`],
{ color: (style && style.color) || themeStyle[`${type}-inner-checked`].color },
disabled ? {
color:
(disabledStyle && disabledStyle.color) ||
themeStyle[`${type}-inner-disabled`].color,
} : {}
);
return <Icon style={innerStyle} name="right" onClick={this.onChange} />;
}
render() {
const {
size,
style,
disabled,
type,
themeStyle,
checkedStyle,
disabledStyle,
touchStyle,
} = this.props;
const { checked } = this.state;
const elementTouchStyle = Object.assign(
{},
themeStyle[`touch-${size}`],
touchStyle
);
const wrapStyle = Object.assign(
{},
themeStyle[`wrap-${size}`],
themeStyle[`wrap-${type}`],
checked
? Object.assign({}, themeStyle[`wrap-${type}-checked`], checkedStyle)
: {},
disabled
? Object.assign({}, themeStyle[`wrap-${type}-disabled`], disabledStyle)
: {},
checked && disabled
? Object.assign({}, themeStyle[`wrap-${type}-checked-disabled`])
: {},
style,
);
return (
<Touchable style={elementTouchStyle} onPress={this.onChange}>
<View style={wrapStyle}>{this.renderInner(this.props)}</View>
</Touchable>
);
}
}
Radio.displayName = 'Radio';
Radio.propTypes = {
/**
* 受控选择 controlled select
*/
checked: PropTypes.boolean,
/**
* 单选尺寸 size of radio
* @enumdesc small,medium
*/
size: PropTypes.oneOf(['small', 'medium']),
/**
* 受控禁用 controlled disabled
*/
disabled: PropTypes.boolean,
/**
* 状态变更回调 status change callback
*/
onChange: PropTypes.func,
/**
* 外观类型 appearance type
* @enumdesc normal,list,empty,dot
*/
type: PropTypes.oneOf(['normal', 'list', 'empty', 'dot']),
/**
* 单选group的选中值,配合DataSource使用
* value of radio group.
*/
value: PropTypes.string,
/**
* 选中样式,选中状态下会覆盖style
*/
checkedStyle: PropTypes.object,
/**
* 禁用样式,禁用状态下会覆盖style
*/
disabledStyle: PropTypes.object,
/**
* 点击区域样式,通常点击区域要大于外观区域
*/
touchStyle: PropTypes.object,
/**
* 忽略上层父级 context,当 radio.group 的子级存在非 group 模式的 radio 时需设置为 false
* ignore context passing. usually use the nested with radio group
*/
ignoreContext: PropTypes.boolean,
};
Radio.defaultProps = {
size: 'medium',
disabled: false,
onChange: () => { },
type: 'normal',
value: '',
checkedStyle: {},
disabledStyle: {},
touchStyle: {},
ignoreContext: false,
};
Radio.contextTypes = {
onChange: PropTypes.func,
__group__: PropTypes.bool,
selectedValue: PropTypes.any,
};
export default connectStyle(stylesProvider)(Radio);