UNPKG

weex-nuke

Version:

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

222 lines (204 loc) 5.49 kB
/** @jsx createElement */ 'use strict'; 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);