weex-nuke
Version:
基于 Rax 、Weex 的高性能组件体系 ~~
190 lines (177 loc) • 4.54 kB
JSX
/** @jsx createElement */
;
import { createElement, Component, cloneElement, PropTypes } from 'rax';
import View from 'nuke-view';
import Touchable from 'nuke-touchable';
import Text from 'nuke-text';
import { connectStyle } from 'nuke-theme-provider';
import Radio from './radio';
import stylesProvider from '../styles';
/**
* Radio.group
* @description 单选框group模式
*/
class RadioGroup extends Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
let value;
if ('value' in props) {
value = props.value;
}
this.state = {
selectedValue: value,
};
}
getChildContext() {
return {
__group__: true,
onChange: this.onChange,
selectedValue: this.state.selectedValue,
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.value !== this.state.selectedValue) {
this.setState({
selectedValue: nextProps.value,
});
}
}
onChange(value) {
// 同一个group下只能有一个被选中
this.setState({
selectedValue: value,
});
this.props.onChange && this.props.onChange(value);
}
wrapPress(value) {
this.onChange(value);
}
render() {
const {
dataSource = [],
style = {},
size,
type,
groupItemStyle,
themeStyle,
touchStyle,
labelStyle,
reverse,
renderItem,
} = this.props;
let { children } = this.props;
const elementGroupStyle = Object.assign({}, themeStyle.group, groupItemStyle);
const finalTextStyle = Object.assign(
size === 'small' ? themeStyle['group-small-text'] : themeStyle['group-medium-text'],
labelStyle
);
const current = this.state.selectedValue;
if (!children) {
children = dataSource.map((item, index) => {
if (typeof item !== 'object') {
item = { label: item, value: item, index };
}
const { label, value, ...others } = item;
let checked = false;
current === value ? (checked = true) : (checked = false);
let labelGroup = [
<Radio
t="radioitem"
{...others}
size={size}
value={value}
checked={checked}
touchStyle={touchStyle}
type={type}
{...others}
/>,
<Text t="radiotext" style={finalTextStyle}>
{label}
</Text>,
];
if (reverse) {
labelGroup = labelGroup.reverse();
}
if (label && !renderItem) {
return (
<Touchable t="radio-item-wrap" key={index} style={elementGroupStyle} onPress={() => this.wrapPress(value)}>
{labelGroup}
</Touchable>
);
} else if (label && renderItem) {
return typeof renderItem === 'function'
? cloneElement(renderItem(item), {
onPress: this.onChange.bind(this, item.value),
})
: null;
}
return (
<View t="radio-item-wrap" style={elementGroupStyle}>
<Radio {...others} checked={checked} touchStyle={touchStyle} />
</View>
);
});
}
return (
<View t="radio-group-wrap" style={style}>
{children}
</View>
);
}
}
RadioGroup.displayName = 'RadioGroup';
RadioGroup.propTypes = {
/**
* 单选类型的数据源
*/
dataSource: PropTypes.array,
/**
* 选中回调 callback when select done
*/
onChange: PropTypes.func,
/**
* 选中的值,配合dataSource使用
*/
value: PropTypes.any,
/**
* 单选框的尺寸
*/
size: PropTypes.oneOf(['small', 'medium']),
/**
* 单选框的类型
*/
type: PropTypes.oneOf(['normal', 'list', 'dark', 'dot']),
/**
* group 模式下每个item的最外层样式
*/
groupItemStyle: PropTypes.object,
/**
* group 模式下label文案的样式
*/
labelStyle: PropTypes.object,
/**
* 是否翻转文字与radio reverse the label and radio
*/
reverse: PropTypes.bool,
/**
* 自定义渲染group item的方法
*/
renderItem: PropTypes.func,
};
RadioGroup.defaultProps = {
dataSource: [],
onChange: () => {},
value: '',
size: 'small',
type: 'normal',
groupItemStyle: {},
labelStyle: {},
reverse: false,
};
RadioGroup.childContextTypes = {
onChange: PropTypes.func,
__group__: PropTypes.bool,
selectedValue: PropTypes.any,
};
export default connectStyle(stylesProvider)(RadioGroup);