@cainiaofe/cn-ui-m
Version:
73 lines (72 loc) • 2.88 kB
JavaScript
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,
};