UNPKG

@6thquake/react-material

Version:

React components that implement Google's Material Design.

606 lines (555 loc) 17 kB
import _extends from "@babel/runtime/helpers/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose"; import React, { Component } from 'react'; import withStyles from '../styles/withStyles'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import { StarBorder } from '@material-ui/icons'; import { StarHalf } from '@material-ui/icons'; import { Star } from '@material-ui/icons'; const styles = { rmVote: { margin: '0', padding: '0', listStyle: 'none', fontSize: '24px', display: 'inline-block', verticalAlign: 'middle', fontWeight: '400', fontStyle: 'normal' }, rmVoteStar: { color: '#f5a623', margin: '0', padding: '0', cursor: 'pointer', display: 'inline-block', position: 'relative', transition: 'all .3s ease', '&:hover': { transform: 'scale(1.1)' } }, rmVoteDisabled: { '@global li': { '&:hover': { cursor: 'default', transform: 'scale(1)' } } }, rmVoteStarFull: {}, rmVoteStarZero: {}, rmVoteStarHalf: {}, rmVoteStarContent: { position: 'absolute', left: '0', top: '0', width: '50%', height: '100%', overflow: 'hidden' }, xs: { fontSize: 12 }, sm: { fontSize: 16 }, md: { fontSize: 24 }, lg: { fontSize: 32 } }; class StarVote extends React.Component { constructor(props) { super(props); this.onMouseOver = (key, e) => { // li onMouseOver event e.nativeEvent.stopImmediatePropagation(); e.stopPropagation(); e.preventDefault(); let tagArray = []; if (!this.state.disabled) { for (var i = 0; i < this.state.count; i++) { if (i <= key) { tagArray.push(1); } else { tagArray.push(0); } } } this.setState({ tagArrTemp: [...tagArray] }); }; this.onMouseOverContent = (key, e) => { //onMouseOver选一半 e.preventDefault(); e.nativeEvent.stopImmediatePropagation(); e.stopPropagation(); if (!this.state.disabled) { let tagArray = []; if (!this.state.disabled) { for (var i = 0; i < this.state.count; i++) { if (i < key) { tagArray.push(1); } else if (i === key) { tagArray.push(0.5); } else { tagArray.push(0); } } } this.setState({ tagArrTemp: [...tagArray] }); } }; this.onClick = (key, e) => { e.preventDefault(); e.nativeEvent.stopImmediatePropagation(); e.stopPropagation(); let tagArray = []; let tagArrayCopy = [...this.state.tagArr]; if (!this.state.disabled) { for (var i = 0; i < this.state.count; i++) { if (i < key) { tagArray.push(1); } else if (i === key) { if (this.state.tagArr[key] === 1) { tagArray.push(0); } else { tagArray.push(1); } } else { tagArray.push(0); } } this.setState({ tagArr: [...tagArray] }); this.props.onChange(key); } }; this.onMouseOut = (key, e) => { //onMouseOut 清除 e.nativeEvent.stopImmediatePropagation(); e.stopPropagation(); if (!this.state.disabled) { this.setState({ tagArrTemp: [] }); } }; this.onMouseOutContent = (key, e) => { e.nativeEvent.stopImmediatePropagation(); e.stopPropagation(); this.setState({ tagArrTemp: [] }); }; this.onClickContent = (key, e) => { // e.preventDefault(); e.nativeEvent.stopImmediatePropagation(); e.stopPropagation(); let tagArray = []; if (!this.state.disabled) { for (var i = 0; i < this.state.count; i++) { if (i < key) { tagArray.push(1); } else if (i === key) { if (this.state.tagArr[key] === 0.5) { tagArray.push(0); } else { tagArray.push(0.5); } } else { tagArray.push(0); } } this.setState({ tagArr: [...tagArray] }); this.state.onChange(key); } }; this.state = { count: props.count, value: props.value, defaultValue: props.defaultValue, onChange: props.onChange, allowHalf: props.allowHalf, disabled: props.disabled, tagArr: [], tagArrTemp: [] }; try { if (Boolean(this.state.allowHalf)) { //允许半选 this.state.allowHalf = true; } else { this.state.allowHalf = false; //默认不允许半选 } if (Boolean(this.state.disabled)) { this.state.disabled = true; // 只读,无法进行交互 } else { this.state.disabled = false; // 默认为false 可以进行点击、取消等交互事件 } if (!this.state.count) { this.state.count = 5; // 未提供总数 默认 为 5 } else if (!parseInt(this.state.count)) { throw new Error('the attribute count must be integer type!'); } else { this.state.count = this.state.count > 10 ? 10 : Math.abs(this.state.count); } if (this.state.value) { //存在当前数 if (!this.state.allowHalf) { // 不允许半选,count 、 value等验证必须为整数 且受控值 value 必须小于 cout if (!parseInt(this.state.value)) { throw new Error('not integer type of the attribute value!'); } else if (this.state.value > this.state.count) { throw new Error('attribute value must less than the attribute count'); } else { this.state.value = Math.abs(this.props.value); } } else { // 如果允许半选,存在当前数的情况 需要验证当前数是否是数值 必须是 0.5的倍数 且小于 count if (Math.sign(this.state.value) != 'NaN') { if (!parseInt(Math.abs(this.state.value) / 0.5)) { throw new Error('attribute value must be an integer or multiple of 0.5!'); } else { this.state.value = Math.abs(this.state.value); } } } } if (this.state.defaultValue) { //存在defaultValue if (!this.state.allowHalf) { // 不允许半选,defaultValue等验证必须为整数 且受控值 value 必须小于 cout if (!parseInt(this.state.defaultValue)) { throw new Error('not integer type of the attribute value!'); } else if (this.state.defaultValue > this.state.count) { throw new Error('attribute value must less than the attribute count'); } else { this.state.defaultValue = Math.abs(this.props.defaultValue); } } else { // 如果允许半选,存在defaultValue的情况 需要验证 defaultValue 是否是数值 必须是 0.5的倍数 且小于 count if (Math.sign(this.state.defaultValue) != 'NaN') { if (!parseInt(Math.abs(this.state.defaultValue) / 0.5)) { throw new Error('attribute value must be an integer or multiple of 0.5!'); } else { this.state.defaultValue = Math.abs(this.state.defaultValue); } } } } else { this.state.defaultValue = 0; } } catch (err) { console.log(err); } } componentDidMount() { let tagArray = []; if (this.state.value) { // 如果存在当前数 按照当前数去渲染 for (var i = 0; i < this.state.count; i++) { if (this.state.value.toString().includes('.5')) { //当前数为半数 if (Math.floor(this.state.value) === i) { tagArray.push(0.5); } else if (Math.floor(this.state.value) > i) { tagArray.push(1); } else { tagArray.push(0); } } else { //当前数为整数 if (i < this.state.value) { tagArray.push(1); } else { //包括大于等于 tagArray.push(0); } } } } else if (this.state.defaultValue) { // 不存在当前数 按照defaultValue 处理 for (var i = 0; i < this.state.count; i++) { if (this.state.value.toString().includes('.5')) { //当前数为半数 if (Math.floor(this.state.defaultValue) === i) { tagArray.push(0.5); } else if (Math.floor(this.state.defaultValue) > i) { tagArray.push(1); } else { tagArray.push(0); } } else { //当前数为整数 if (i < this.state.defaultValue) { tagArray.push(1); } else { //包括大于等于 tagArray.push(0); } } } } this.setState({ tagArr: [...tagArray] }); } render() { const _this$props = this.props, { classes, size, spacing } = _this$props, other = _objectWithoutPropertiesLoose(_this$props, ["classes", "size", "spacing"]); let tagArray = []; if (this.state.tagArrTemp.length != 0) { tagArray = [...this.state.tagArrTemp]; } else { tagArray = [...this.state.tagArr]; } let fontSize = ''; switch (size) { case 'xs': case 'sm': case 'md': case 'lg': fontSize = 'inherit'; break; case 'small': fontSize = 'small'; break; case 'large': fontSize = 'large'; break; case 'medium': default: fontSize = 'default'; break; } var _ref = React.createElement(Star, { fontSize: fontSize }); var _ref2 = React.createElement(StarHalf, { fontSize: fontSize }); var _ref3 = React.createElement(StarBorder, { fontSize: fontSize }); var _ref4 = React.createElement(Star, { fontSize: fontSize }); var _ref5 = React.createElement(StarHalf, { fontSize: fontSize }); var _ref6 = React.createElement(StarBorder, { fontSize: fontSize }); let listItems = tagArray.map((tag, index) => { if (this.state.allowHalf) { // 允许半选 if (tag === 1) { return React.createElement("li", { key: index, onMouseOver: e => this.onMouseOver(index, e), onMouseOut: e => this.onMouseOut(index, e), onClick: e => this.onClick(index, e), className: classNames({ [classes.rmVoteStar]: true, [classes.rmVoteStarFull]: true, [classes.xs]: size === 'xs', [classes.sm]: size === 'sm', [classes.md]: size === 'md', [classes.lg]: size === 'lg' }), style: { margin: `0px ${spacing}px` } }, _ref, React.createElement("div", { onMouseOver: e => this.onMouseOverContent(index, e), onMouseOut: e => this.onMouseOutContent(index, e), onClick: e => this.onClickContent(index, e), className: classes.rmVoteStarContent })); } else if (tag === 0.5) { return React.createElement("li", { key: index, onMouseOver: e => this.onMouseOver(index, e), onMouseOut: e => this.onMouseOut(index, e), onClick: e => this.onClick(index, e), className: classNames({ [classes.rmVoteStar]: true, [classes.rmVoteStarHalf]: true, [classes.xs]: size === 'xs', [classes.sm]: size === 'sm', [classes.md]: size === 'md', [classes.lg]: size === 'lg' }), style: { margin: `0px ${spacing}px` } }, _ref2, React.createElement("div", { onMouseOver: e => this.onMouseOverContent(index, e), onMouseOut: e => this.onMouseOutContent(index, e), onClick: e => this.onClickContent(index, e), className: classes.rmVoteStarContent })); } else { return React.createElement("li", { key: index, onMouseOver: e => this.onMouseOver(index, e), onMouseOut: e => this.onMouseOut(index, e), onClick: e => this.onClick(index, e), className: classNames({ [classes.rmVoteStar]: true, [classes.rmVoteStarZero]: true, [classes.xs]: size === 'xs', [classes.sm]: size === 'sm', [classes.md]: size === 'md', [classes.lg]: size === 'lg' }), style: { margin: `0px ${spacing}px` } }, _ref3, React.createElement("div", { onMouseOver: e => this.onMouseOverContent(index, e), onMouseOut: e => this.onMouseOutContent(index, e), onClick: e => this.onClickContent(index, e), className: classes.rmVoteStarContent })); } } else { if (tag === 1) { return React.createElement("li", { key: index, onMouseOver: e => this.onMouseOver(index, e), onMouseOut: e => this.onMouseOut(index, e), onClick: e => this.onClick(index, e), className: classNames({ [classes.rmVoteStar]: true, [classes.rmVoteStarFull]: true, [classes.xs]: size === 'xs', [classes.sm]: size === 'sm', [classes.md]: size === 'md', [classes.lg]: size === 'lg' }), style: { margin: `0px ${spacing}px` } }, _ref4, React.createElement("div", { className: classes.rmVoteStarContent })); } else if (tag === 0.5) { return React.createElement("li", { key: index, onMouseOver: e => this.onMouseOver(index, e), onMouseOut: e => this.onMouseOut(index, e), onClick: e => this.onClick(index, e), className: classNames({ [classes.rmVoteStar]: true, [classes.rmVoteStarHalf]: true, [classes.xs]: size === 'xs', [classes.sm]: size === 'sm', [classes.md]: size === 'md', [classes.lg]: size === 'lg' }), style: { margin: `0px ${spacing}px` } }, _ref5, React.createElement("div", { className: classes.rmVoteStarContent })); } else { return React.createElement("li", { key: index, onMouseOver: e => this.onMouseOver(index, e), onMouseOut: e => this.onMouseOut(index, e), onClick: e => this.onClick(index, e), className: classNames({ [classes.rmVoteStar]: true, [classes.rmVoteStarZero]: true, [classes.xs]: size === 'xs', [classes.sm]: size === 'sm', [classes.md]: size === 'md', [classes.lg]: size === 'lg' }), style: { margin: `0px ${spacing}px` } }, _ref6, React.createElement("div", { className: classes.rmVoteStarContent })); } } }); if (this.state.disabled) { return React.createElement("ul", _extends({ className: classNames({ [classes.rmVoteDisabled]: true, [classes.rmVote]: true }) }, other), listItems); } else { return React.createElement("ul", _extends({ className: classes.rmVote }, other), listItems); } } } process.env.NODE_ENV !== "production" ? StarVote.propTypes = { /** * Whether the value is allowed to be a decimal */ allowHalf: PropTypes.bool, /** * Total count of star */ count: PropTypes.number, /** * The default value */ defaultValue: PropTypes.number, /** * Read only, can not interact */ disabled: PropTypes.bool, /** * Callback fired after value changed */ onChange: PropTypes.func, /** * Size of each item. */ size: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'small', 'medium', 'large']), /** * Spacing between items. */ spacing: PropTypes.number, /** * Current value,controlled value */ value: PropTypes.number } : void 0; StarVote.defaultProps = { count: 5, defaultValue: 0, allowHalf: false, disabled: false, size: 'medium', spacing: 4 }; export default withStyles(styles, { name: 'RMStarVote' })(StarVote);