UNPKG

@cainiaofe/cn-ui-m

Version:
73 lines (72 loc) 2.88 kB
import { __assign } from "tslib"; import * as React from 'react'; import classNames from 'classnames'; import { withNativeProps } from "../../utils/with-native-props"; import { useControlled } from '@cainiaofe/cn-ui-common'; import { useDrag } from '@use-gesture/react'; import { bound } from "../../utils/bound"; import { Star } from './star'; import { isRTL } from '@cainiaofe/cn-i18n'; var rtl = isRTL(); var classPrefix = 'cn-ui-m-rating'; /** * @category 组件 * 评分 */ export var CnRating = function (props) { var _a; var _b = useControlled(props), value = _b[0], setValue = _b[1]; var containerRef = React.useRef(null); var starList = Array(props.count).fill(null); function renderStar(v, half) { var _a; return (React.createElement("div", { className: classNames("".concat(classPrefix, "-star"), (_a = {}, _a["".concat(classPrefix, "-star-active")] = value >= v, _a["".concat(classPrefix, "-star-half")] = half, _a["".concat(classPrefix, "-star-readonly")] = props.readOnly, _a)), role: "radio", "aria-checked": value >= v, "aria-label": "".concat(v) }, props.character)); } var bind = useDrag(function (state) { if (props.readOnly) return; var clientX = state.xy[0], tap = state.tap; var container = containerRef.current; if (!container) return; var rect = container.getBoundingClientRect(); var rawValue = rtl ? ((rect.right - clientX) / rect.width) * props.count : ((clientX - rect.left) / rect.width) * props.count; var ceiledValue = props.allowHalf ? Math.ceil(rawValue * 2) / 2 : Math.ceil(rawValue); var boundValue = bound(ceiledValue, 0, props.count); if (tap) { if (props.allowClear && boundValue === value) { setValue(0); return; } } setValue(boundValue); }, { axis: 'x', pointer: { touch: true, }, filterTaps: true, }); return withNativeProps(props, React.createElement("div", __assign({ className: classNames(CN_UI_HASH_CLASS_NAME, classPrefix, (_a = {}, _a["".concat(classPrefix, "-half")] = props.allowHalf, _a)), role: "radiogroup", "aria-readonly": props.readOnly, ref: containerRef }, bind()), starList.map(function (_, i) { return (React.createElement("div", { key: i, className: classNames("".concat(classPrefix, "-box")) }, props.allowHalf && renderStar(i + 0.5, true), renderStar(i + 1, false))); }))); }; CnRating.displayName = 'CnRating'; CnRating.defaultProps = { count: 5, allowHalf: false, character: React.createElement(Star, null), defaultValue: 0, readOnly: false, allowClear: true, };