UNPKG

@nutui/nutui-react-taro

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

133 lines (132 loc) 4.74 kB
import React__default, { useState, useRef, useEffect } from "react"; import classNames from "classnames"; import { StarFill } from "@nutui/icons-react-taro"; import { useReady } from "@tarojs/taro"; import { View } from "@tarojs/components"; import { C as ComponentDefaults } from "./typings-DV9RBfhj.js"; import { u as usePropsValue } from "./use-props-value-SH9krhkx.js"; import { g as getRectByTaro } from "./get-rect-by-taro-D0h6aiDr.js"; import { u as useRefs } from "./use-refs-BeEmziIR.js"; const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { count: 5, min: 0, checkedIcon: null, uncheckedIcon: null, disabled: false, readOnly: false, allowHalf: false, touchable: false }); const Rate = (props) => { const { className, style, count, value, defaultValue, min, checkedIcon, uncheckedIcon, disabled, readOnly, allowHalf, touchable, onChange, onTouchEnd } = Object.assign(Object.assign({}, defaultProps), props); const classPrefix = "nut-rate"; const [countArray, setCountArray] = useState([1, 2, 3, 4, 5]); const [refs, setRefs] = useRefs(); const rateRects = useRef([]); const [score, setScore] = usePropsValue({ value, defaultValue: Math.max(defaultValue || 0, min), finalValue: 0, onChange }); useEffect(() => { const tmp = []; for (let i = 1; i <= Number(count); i++) { tmp.push(i); } setCountArray(tmp); }, [count]); const renderIcon = (n) => { return n <= score ? checkedIcon || React__default.createElement(StarFill, null) : uncheckedIcon || (checkedIcon ? React__default.cloneElement(checkedIcon, { color: void 0 }) : React__default.createElement(StarFill, null)); }; const onClick = (e, index) => { e.preventDefault(); e.stopPropagation(); if (disabled || readOnly) return; let value2 = 0; if (!(index === 1 && score === index)) { value2 = index; } value2 = Math.max(value2, min); setScore(value2); }; const onHalfClick = (event, n) => { event.preventDefault(); event.stopPropagation(); const value2 = Math.max(min, n - 0.5); setScore(value2); }; const getScoreByPosition = (x) => { var _a; if ((_a = rateRects.current) === null || _a === void 0 ? void 0 : _a.length) { for (let index = rateRects.current.length - 1; index >= 0; index--) { const item = rateRects.current[index]; if (item && x > item.left) { return allowHalf ? index + (x > item.left + item.width / 2 ? 1 : 0.5) : index + 1; } } return 0; } }; const updateRects = () => { for (let index = 0; index < refs.length; index++) { const item = refs[index]; if (item) { getRectByTaro(item).then((res) => { rateRects.current[index] = res; }); } } }; useReady(() => { updateRects(); }); const handleTouchStart = (e) => { if (!touchable || readOnly || disabled) { return; } if (e.cancelable) { e.preventDefault(); } e.stopPropagation(); updateRects(); }; const handleTouchMove = (e) => { if (!touchable || readOnly || disabled) { return; } if (e.cancelable) { e.preventDefault(); } e.stopPropagation(); const val = getScoreByPosition(e.touches[0].clientX); if (val !== void 0) { setScore(Math.max(min, val)); } }; const handleTouchEnd = (e) => { if (!touchable || readOnly || disabled) { return; } if (e.cancelable) { e.preventDefault(); } e.stopPropagation(); const val = getScoreByPosition(e.changedTouches[0].clientX); if (val !== void 0) { setScore(Math.max(min, val)); onTouchEnd && onTouchEnd(e, Math.max(min, val)); } }; return React__default.createElement(View, { className: classNames(classPrefix, { disabled, readonly: readOnly }, className), catchMove: true, style, onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd, onTouchCancel: handleTouchEnd }, countArray.map((n, index) => { return React__default.createElement( "div", { className: `${classPrefix}-item`, key: n, ref: setRefs(index), onClick: (event) => onClick(event, n) }, React__default.createElement("div", { className: classNames(`${classPrefix}-item-icon`, { [`${classPrefix}-item-icon-disabled`]: disabled || n > score }) }, renderIcon(n)), allowHalf && score > n - 1 && React__default.createElement("div", { className: classNames(`${classPrefix}-item-half`, `${classPrefix}-item-icon`, `${classPrefix}-item-icon-half`), onClick: (event) => onHalfClick(event, n) }, renderIcon(n)) ); })); }; Rate.displayName = "NutRate"; export { Rate as R };