UNPKG

winbox-ui-next

Version:

We Design Vue 2.0: A Vue.js 3 UI Library

154 lines (153 loc) 5.11 kB
import { defineComponent, ref, computed, createVNode, mergeProps } from "vue"; import NP from "number-precision"; import IconStarFill from "../icon/icon-star-fill/index.js"; import IconFaceMehFill from "../icon/icon-face-meh-fill/index.js"; import IconFaceSmileFill from "../icon/icon-face-smile-fill/index.js"; import IconFaceFrownFill from "../icon/icon-face-frown-fill/index.js"; import { getPrefixCls } from "../_utils/global-config.js"; var _Rate = defineComponent({ name: "Rate", props: { count: { type: Number, default: 5 }, modelValue: { type: Number, default: void 0 }, defaultValue: { type: Number, default: 0 }, allowHalf: { type: Boolean, default: false }, clearable: { type: Boolean, default: false }, grading: { type: Boolean, default: false }, readonly: { type: Boolean, default: false }, disabled: { type: Boolean, default: false }, onChange: { type: [Function, Array] }, onHoverChange: { type: [Function, Array] } }, emits: [ "update:modelValue", "change", "hoverChange" ], setup(props, { emit, slots }) { const prefixCls = getPrefixCls("rate"); const _value = ref(props.defaultValue); const animation = ref(false); const hoverIndex = ref(0); const computedValue = computed(() => { var _a; return (_a = props.modelValue) != null ? _a : _value.value; }); const disabled = computed(() => props.disabled || props.readonly); const resetHoverIndex = () => { if (hoverIndex.value) { hoverIndex.value = 0; emit("hoverChange", 0); } }; const handleMouseEnter = (index, isHalf) => { const newHoverIndex = isHalf && props.allowHalf ? index + 0.5 : index + 1; if (newHoverIndex !== hoverIndex.value) { hoverIndex.value = newHoverIndex; emit("hoverChange", newHoverIndex); } }; const handleClick = (index, isHalf) => { const newValue = isHalf && props.allowHalf ? index + 0.5 : index + 1; animation.value = true; if (newValue !== computedValue.value) { _value.value = newValue; emit("update:modelValue", newValue); emit("change", newValue); } else if (props.clearable) { _value.value = 0; emit("update:modelValue", 0); emit("change", 0); } }; const handleAnimationEnd = (index) => { if (animation.value && index + 1 >= computedValue.value - 1) { animation.value = false; } }; const renderGradingCharacter = (index, displayIndex) => { if (index > displayIndex) { return createVNode(IconFaceMehFill, null, null); } if (displayIndex <= 2) { return createVNode(IconFaceFrownFill, null, null); } if (displayIndex <= 3) { return createVNode(IconFaceMehFill, null, null); } return createVNode(IconFaceSmileFill, null, null); }; const renderCharacter = (index) => { var _a, _b; const fixedValue = props.allowHalf ? NP.times(NP.round(NP.divide(computedValue.value, 0.5), 0), 0.5) : Math.round(computedValue.value); const displayIndex = hoverIndex.value || fixedValue; const displayCharacter = props.grading ? renderGradingCharacter(index, displayIndex) : (_b = (_a = slots.character) == null ? void 0 : _a.call(slots, index)) != null ? _b : createVNode(IconStarFill, null, null); const leftProps = disabled.value ? {} : { onMouseenter: () => handleMouseEnter(index, true), onClick: () => handleClick(index, true) }; const rightProps = disabled.value ? {} : { onMouseenter: () => handleMouseEnter(index, false), onClick: () => handleClick(index, false) }; const style = animation.value ? { animationDelay: `${50 * index}ms` } : {}; const cls2 = [`${prefixCls}-character`, { [`${prefixCls}-character-half`]: props.allowHalf && index + 0.5 === displayIndex, [`${prefixCls}-character-full`]: index + 1 <= displayIndex, [`${prefixCls}-character-scale`]: animation.value && index + 1 < computedValue.value }]; return createVNode("div", { "class": cls2, "style": style, "onAnimationend": () => handleAnimationEnd(index) }, [createVNode("div", mergeProps({ "class": `${prefixCls}-character-left` }, leftProps), [displayCharacter]), createVNode("div", mergeProps({ "class": `${prefixCls}-character-right` }, rightProps), [displayCharacter])]); }; const indexArray = computed(() => [...Array(props.grading ? 5 : props.count)]); const cls = computed(() => [prefixCls, { [`${prefixCls}-readonly`]: props.readonly, [`${prefixCls}-disabled`]: props.disabled }]); return () => createVNode("div", { "class": cls.value, "onMouseleave": resetHoverIndex }, [indexArray.value.map((_, index) => renderCharacter(index))]); } }); export { _Rate as default };