UNPKG

react-custom-rating-component

Version:
123 lines (122 loc) 7.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var react_1 = tslib_1.__importStar(require("react")); var svgIconPath = 'm25,1 6,17h18l-14,11 5,17-15-10-15,10 5-17-14-11h18z'; var svgIconViewBox = '0 0 51 48'; var FullStar = function (_a) { var iconStyles = _a.iconStyles; return (react_1.default.createElement("svg", { viewBox: svgIconViewBox, style: iconStyles }, react_1.default.createElement("path", { d: svgIconPath, fill: 'currentColor' }))); }; var EmptyStar = function (_a) { var iconStyles = _a.iconStyles, _b = _a.defaultColor, defaultColor = _b === void 0 ? 'rgb(203, 211, 227)' : _b; var pathStyle = { fill: defaultColor, transition: 'fill .2s ease-in-out', }; return (react_1.default.createElement("svg", { viewBox: svgIconViewBox, style: iconStyles }, react_1.default.createElement("path", { style: pathStyle, d: svgIconPath }))); }; var HeartEmptyIcon = function (_a) { var iconStyles = _a.iconStyles, defaultColor = _a.defaultColor; return (react_1.default.createElement("svg", { viewBox: '0 0 24 24', style: iconStyles, fill: defaultColor }, react_1.default.createElement("path", { d: 'M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z' }))); }; var HeartFullIcon = function (_a) { var iconStyles = _a.iconStyles; return (react_1.default.createElement("svg", { viewBox: '0 0 24 24', style: iconStyles, fill: 'currentColor' }, react_1.default.createElement("path", { d: 'm12 21.35-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z' }))); }; var Rating = function (_a) { var _b = _a.precision, precision = _b === void 0 ? 1 : _b, _c = _a.count, count = _c === void 0 ? 5 : _c, _d = _a.shape, shape = _d === void 0 ? 'star' : _d, _e = _a.defaultValue, defaultValue = _e === void 0 ? 0 : _e, onChange = _a.onChange, onHover = _a.onHover, _f = _a.readOnly, readOnly = _f === void 0 ? false : _f, _g = _a.size, size = _g === void 0 ? '24px' : _g, _h = _a.spacing, spacing = _h === void 0 ? '5px' : _h, _j = _a.activeColor, activeColor = _j === void 0 ? 'orange' : _j, _k = _a.defaultColor, defaultColor = _k === void 0 ? 'gray' : _k, _l = _a.titleArray, titleArray = _l === void 0 ? ['Poor', 'Good', 'Very Good', 'Best', 'Excellent'] : _l, _m = _a.showTitle, showTitle = _m === void 0 ? false : _m, emptyIcon = _a.emptyIcon, fillIcon = _a.fillIcon; if (showTitle && titleArray.length < count) { throw new Error('titleArray length must be greater than or equal to count.'); } var _o = (0, react_1.useState)(defaultValue), activeIcon = _o[0], setActiveIcon = _o[1]; var _p = (0, react_1.useState)(-1), hoverActiveIcon = _p[0], setHoverActiveIcon = _p[1]; var _q = (0, react_1.useState)(false), isHovered = _q[0], setIsHovered = _q[1]; var ratingContainerRef = (0, react_1.useRef)(null); var calculateRating = function (e) { var _a; var _b = ratingContainerRef.current.getBoundingClientRect(), width = _b.width, left = _b.left; var percent = (e.clientX - left) / width; var numberInStars = percent * count; var nearestNumber = Math.round((numberInStars + precision / 2) / precision) * precision; return Number(nearestNumber.toFixed(((_a = precision.toString().split('.')[1]) === null || _a === void 0 ? void 0 : _a.length) || 0)); }; var handleClick = function (e) { if (readOnly) return; setIsHovered(false); setActiveIcon(calculateRating(e)); onChange && onChange(calculateRating(e)); }; var handleMouseMove = function (e) { if (readOnly) return; setIsHovered(true); setHoverActiveIcon(calculateRating(e)); onHover && onHover(calculateRating(e)); }; var handleMouseLeave = function () { if (readOnly) return; setHoverActiveIcon(-1); // Reset to default state setIsHovered(false); }; var iconStyles = { width: size, height: size, }; var IconProps = { iconStyles: iconStyles, activeColor: activeColor, defaultColor: defaultColor, }; var getShape = function (style) { if (shape === 'custom' && fillIcon && emptyIcon) { return style === 'full' ? fillIcon(IconProps) : emptyIcon(IconProps); } switch (shape) { case 'heart': if (style === 'full') return react_1.default.createElement(HeartFullIcon, tslib_1.__assign({}, IconProps)); return react_1.default.createElement(HeartEmptyIcon, tslib_1.__assign({}, IconProps)); default: if (style === 'full') return react_1.default.createElement(FullStar, tslib_1.__assign({}, IconProps)); return react_1.default.createElement(EmptyStar, tslib_1.__assign({}, IconProps)); } }; return (react_1.default.createElement("div", { style: { display: 'flex' }, className: 'rcr-component-wrapper' }, react_1.default.createElement("div", { onClick: handleClick, onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave, ref: ratingContainerRef, style: { display: 'flex', gap: spacing, position: 'relative', cursor: readOnly ? 'default' : 'pointer', lineHeight: 0, boxSizing: 'border-box', padding: 0, margin: 0, } }, new Array(count).fill('').map(function (_, index) { var activeState = isHovered ? hoverActiveIcon : activeIcon; var showEmptyIcon = activeState === -1 || activeState < index + 1; var isActiveRating = activeState !== 1; var isRatingWithPrecision = activeState % 1 !== 0; var isRatingEqualToIndex = Math.ceil(activeState) === index + 1; var showRatingWithPrecision = isActiveRating && isRatingWithPrecision && isRatingEqualToIndex; return (react_1.default.createElement("div", { style: { position: 'relative', cursor: readOnly ? 'default' : 'pointer', }, key: index, title: showTitle ? titleArray[index] : '' }, react_1.default.createElement("div", { style: { color: activeColor, width: showRatingWithPrecision ? "".concat((activeState % 1) * 100, "%") : '0%', overflow: 'hidden', position: 'absolute', } }, getShape('full')), react_1.default.createElement("div", { style: { color: activeColor } }, showEmptyIcon ? getShape('empty') : getShape('full')))); })))); }; exports.default = Rating;