UNPKG

@arudovwen/react-form-builder

Version:
282 lines (274 loc) 8.68 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _reactDom = _interopRequireDefault(require("react-dom")); var _classnames = _interopRequireDefault(require("classnames")); /** * @fileoverview react-star-rating * @author @cameronjroe * <StarRating * name={string} - name for form input (required) * caption={string} - caption for rating (optional) * ratingAmount={number} - the rating amount (required, default: 5) * rating={number} - a set rating between the rating amount (optional) * disabled={boolean} - whether to disable the rating from being selected (optional) * editing={boolean} - whether the rating is explicitly in editing mode (optional) * size={string} - size of stars (optional) * onRatingClick={function} - a handler function that gets called onClick of the rating (optional) * /> */ class StarRating extends _react.default.Component { constructor(props) { super(props); this.min = 0; this.max = props.ratingAmount || 5; const ratingVal = props.rating; const ratingCache = { pos: ratingVal ? this.getStarRatingPosition(ratingVal) : 0, rating: props.rating }; this.state = { ratingCache, editing: props.editing || !props.rating, stars: 5, rating: ratingCache.rating, pos: ratingCache.pos, glyph: this.getStars() }; } /** * Gets the stars based on ratingAmount * @return {string} stars */ getStars() { let stars = ''; const numRating = this.props.ratingAmount; for (let i = 0; i < numRating; i++) { stars += '\u2605'; } return stars; } // componentWillMount() { // this.min = 0; // this.max = this.props.ratingAmount || 5; // if (this.props.rating) { // this.state.editing = this.props.editing || false; // const ratingVal = this.props.rating; // this.state.ratingCache.pos = this.getStarRatingPosition(ratingVal); // this.state.ratingCache.rating = ratingVal; // this.setState({ // ratingCache: this.state.ratingCache, // rating: ratingVal, // pos: this.getStarRatingPosition(ratingVal), // }); // } // } componentDidMount() { this.root = _reactDom.default.findDOMNode(this.rootNode); this.ratingContainer = _reactDom.default.findDOMNode(this.node); } componentWillUnmount() { delete this.root; delete this.ratingContainer; } getPosition(e) { return e.pageX - this.root.getBoundingClientRect().left; } applyPrecision(val, precision) { return parseFloat(val.toFixed(precision)); } getDecimalPlaces(num) { const match = `${num}`.match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/); return !match ? 0 : Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0)); } getWidthFromValue(val) { const min = this.min; const max = this.max; if (val <= min || min === max) { return 0; } if (val >= max) { return 100; } return val / (max - min) * 100; } getValueFromPosition(pos) { const precision = this.getDecimalPlaces(this.props.step); const maxWidth = this.ratingContainer.offsetWidth; const diff = this.max - this.min; let factor = diff * pos / (maxWidth * this.props.step); factor = Math.ceil(factor); let val = this.applyPrecision(parseFloat(this.min + factor * this.props.step), precision); val = Math.max(Math.min(val, this.max), this.min); return val; } calculate(pos) { const val = this.getValueFromPosition(pos); let width = this.getWidthFromValue(val); width += '%'; return { width, val }; } getStarRatingPosition(val) { const width = `${this.getWidthFromValue(val)}%`; return width; } getRatingEvent(e) { const pos = this.getPosition(e); return this.calculate(pos); } getSvg() { return /*#__PURE__*/_react.default.createElement("svg", { className: "react-star-rating__star", viewBox: "0 0 286 272", version: "1.1", xmlns: "http://www.w3.org/2000/svg" }, /*#__PURE__*/_react.default.createElement("g", { stroke: "none", "stroke-width": "1", fill: "none", "fill-rule": "evenodd" }, /*#__PURE__*/_react.default.createElement("polygon", { id: "star-flat", points: "143 225 54.8322122 271.352549 71.6707613 173.176275 0.341522556 103.647451 98.9161061 89.3237254 143 0 187.083894 89.3237254 285.658477 103.647451 214.329239 173.176275 231.167788 271.352549 " }))); } handleMouseLeave() { this.setState({ pos: this.state.ratingCache.pos, rating: this.state.ratingCache.rating }); } handleMouseMove(e) { // get hover position const ratingEvent = this.getRatingEvent(e); this.updateRating(ratingEvent.width, ratingEvent.val); } updateRating(width, val) { this.setState({ pos: width, rating: val }); } shouldComponentUpdate(nextProps, nextState) { if (nextProps !== this.props) { this.updateRating(this.getStarRatingPosition(nextProps.rating), nextProps.rating); return true; } return nextState.ratingCache.rating !== this.state.ratingCache.rating || nextState.rating !== this.state.rating; } handleClick(e) { // is it disabled? if (this.props.disabled) { e.stopPropagation(); e.preventDefault(); return false; } const ratingCache = { pos: this.state.pos, rating: this.state.rating, caption: this.props.caption, name: this.props.name }; this.setState({ ratingCache }); this.props.onRatingClick(e, ratingCache); return true; } treatName(title) { if (typeof title === 'string') { return title.toLowerCase().split(' ').join('_'); } return null; } render() { // let caption = null; const classes = (0, _classnames.default)({ 'react-star-rating__root': true, 'rating-disabled': this.props.disabled, [`react-star-rating__size--${this.props.size}`]: this.props.size, 'rating-editing': this.state.editing }); // is there a caption? // if (this.props.caption) { // caption = (<span className="react-rating-caption">{this.props.caption}</span>); // } // are we editing this rating? let starRating; if (this.state.editing) { starRating = /*#__PURE__*/_react.default.createElement("div", { ref: c => this.node = c, className: "rating-container rating-gly-star", "data-content": this.state.glyph, onMouseMove: this.handleMouseMove.bind(this), onMouseLeave: this.handleMouseLeave.bind(this), onClick: this.handleClick.bind(this) }, /*#__PURE__*/_react.default.createElement("div", { className: "rating-stars", "data-content": this.state.glyph, style: { width: this.state.pos } })); } else { starRating = /*#__PURE__*/_react.default.createElement("div", { ref: c => this.node = c, className: "rating-container rating-gly-star", "data-content": this.state.glyph }, /*#__PURE__*/_react.default.createElement("div", { className: "rating-stars", "data-content": this.state.glyph, style: { width: this.state.pos } })); } return /*#__PURE__*/_react.default.createElement("span", { className: "react-star-rating" }, /*#__PURE__*/_react.default.createElement("span", { ref: c => this.rootNode = c, style: { cursor: 'pointer' }, className: classes }, starRating, /*#__PURE__*/_react.default.createElement("input", { type: "hidden", name: this.props.name, value: this.state.ratingCache.rating, style: { display: 'none !important' }, min: this.min, max: this.max, readOnly: true, style: { width: 65 } }))); } } exports.default = StarRating; StarRating.propTypes = { name: _propTypes.default.string.isRequired, caption: _propTypes.default.string, ratingAmount: _propTypes.default.number.isRequired, rating: _propTypes.default.number, onRatingClick: _propTypes.default.func, disabled: _propTypes.default.bool, editing: _propTypes.default.bool, size: _propTypes.default.string }; StarRating.defaultProps = { step: 0.5, ratingAmount: 5, onRatingClick() {}, disabled: false };