import { defineComponent, onMounted, ref, watch } from 'vue';
import { RateProps, rateProps } from './rate-types';
import { useNamespace } from '../../shared/hooks/use-namespace';
import './rate.scss';
export default defineComponent({
name: 'DRate',
props: rateProps,
emits: ['change', 'update:modelValue'],
setup(props: RateProps, ctx) {
const totalLevelArray = ref<{ width: string }[]>([]);
const chooseValue = ref(0);
const setChange = (start: number, end: number, width: string) => {
for (let i = start; i < end; i++) {
totalLevelArray.value[i]['width'] = width;
}
};
const initRating = () => {
chooseValue.value = props.modelValue;
const halfStar = chooseValue.value % 1;
const intCurrentLevel = Math.floor(chooseValue.value);
setChange(0, intCurrentLevel, '100%');
if (halfStar > 0) {
totalLevelArray.value[intCurrentLevel]['width'] = halfStar * 100 + '%';
setChange(intCurrentLevel + 1, props.count, '0');
} else {
setChange(intCurrentLevel, props.count, '0');
}
};
const initLevelArray = () => {
totalLevelArray.value = [];
for (let i = 0; i < props.count; i++) {
totalLevelArray.value.push({ width: '0' });
}
};
watch([() => props.modelValue, () => props.count], () => {
initLevelArray();
initRating();
});
onMounted(() => {
initLevelArray();
initRating();
});
const isSemiSelected = (e: MouseEvent) => {
const target = e.target as HTMLElement;
return props.allowHalf && e.offsetX * 2 <= target.clientWidth;
};
const hoverToggle = (e: MouseEvent, index: number) => {
if (props.read) {
return;
}
setChange(0, index + 1, '100%');
const width = isSemiSelected(e) ? '50%' : '100%';
setChange(index, index + 1, width);
setChange(index + 1, props.count, '0');
};
const onMouseleave = () => {
initRating();
};
const selectValue = (e: MouseEvent, index: number) => {
if (props.read) {
return;
}
setChange(0, index, '100%');
if (isSemiSelected(e)) {
setChange(index, index + 1, '50%');
chooseValue.value = index - 0.5;
} else {
setChange(index, index + 1, '100%');
chooseValue.value = index;
}
setChange(index + 1, props.count, '0');
props.onChange && props.onChange(chooseValue.value + 1);
props.onTouched && props.onTouched();
ctx.emit('update:modelValue', chooseValue.value + 1);
};
return {
totalLevelArray,
chooseValue,
hoverToggle,
selectValue,
onMouseleave,
};
},
render() {
const { totalLevelArray, icon, character, read, type, color, hoverToggle, selectValue, onMouseleave } = this;
const ns = useNamespace('rate');
return (
<div class={ns.b()} onMouseleave={onMouseleave} style={`--star-color: ${color}`}>
{totalLevelArray.map((item, index) => (
<div
class={[ns.m('align'), ns.m('pointer'), read ? ns.m('only-read') : '']}
key={index}
onMouseover={(e) => hoverToggle(e, index)}
onClick={(e) => selectValue(e, index)}>
{icon && !character && (
<span class={ns.e('color')}>
<d-icon name={icon} />
</span>
)}
{character && !icon && <span class={ns.e('color')}>{character}</span>}
{!icon && !character && (
<span class={ns.e('color')}>
<svg
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns-xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g fill="#E3E5E9" id="Mask">
<polygon points="8 12.7603585 3.67376208 14.3147912 3.81523437 9.71994835 1 6.0857977 5.41367261 4.80046131 8 1 10.5863274 4.80046131 15 6.0857977 12.1847656 9.71994835 12.3262379 14.3147912"></polygon>
</g>
</g>
</svg>
</span>
)}
{icon && !character && (
<span class={[ns.e('color-active'), ns.e('active-star'), ns.em('color', type)]} style={{ width: item.width }}>
<d-icon name={icon} color={color} />
</span>
)}
{character && !icon && (
<span class={[ns.e('color-active'), ns.e('active-star'), ns.em('color', type)]} style={{ color: color, width: item.width }}>
{character}
</span>
)}
{!character && !icon && (
<span
class={[ns.e('color-active'), ns.e('active-star'), !color ? ns.em('color', type) : ns.em('color', 'customize')]}
style={{ width: item.width }}>
<svg
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns-xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Mask">
<polygon points="8 12.7603585 3.67376208 14.3147912 3.81523437 9.71994835 1 6.0857977 5.41367261 4.80046131 8 1 10.5863274 4.80046131 15 6.0857977 12.1847656 9.71994835 12.3262379 14.3147912"></polygon>
</g>
</g>
</svg>
</span>
)}
</div>
))}
</div>
);
},
});