@coreui/vue-pro
Version:
UI Components Library for Vue.js
241 lines (237 loc) • 9.14 kB
JavaScript
var vue = require('vue');
var vCTooltip = require('../../directives/v-c-tooltip.js');
const CRating = vue.defineComponent({
name: 'CRating',
props: {
/**
* Enables the clearing upon clicking the selected item again.
*/
allowClear: Boolean,
/**
* Toggle the disabled state for the component.
*/
disabled: Boolean,
/**
* If enabled, only the currently selected icon will be visibly highlighted.
*/
highlightOnlySelected: Boolean,
/**
* Specifies the total number of stars to be displayed in the star rating component. This property determines the scale of the rating, such as out of 5 stars, 10 stars, etc.
*/
itemCount: {
type: Number,
default: 5,
},
/**
* The default name for a value passed using v-model.
*/
modelValue: Number,
/**
* The name attribute of the radio input elements.
*/
name: String,
/**
* Minimum increment value change allowed.
*/
precision: {
type: Number,
default: 1,
},
/**
* Toggle the readonly state for the component.
*/
readOnly: Boolean,
/**
* Size the component small, large, or custom if you define custom icons with custom height.
*
* @values 'sm', 'lg', 'custom'
*/
size: {
type: String,
validator: (value) => {
return ['sm', 'lg', 'custom'].includes(value);
},
},
/**
* Enable tooltips with default values or set specific labels for each icon.
*/
tooltips: {
type: [Boolean, Array],
},
/**
* The `value` attribute of component.
* */
value: Number,
},
emits: [
/**
* Execute a function when a user changes the selected element.
*
* @property {number | null} value
*/
'change',
/**
* Execute a function when a user hover the element.
*
* @property {number | null} value
*/
'hover',
/**
* Emit the new value whenever there’s a change event.
*/
'update:modelValue',
],
setup(props, { slots, emit }) {
const cleared = vue.ref(false);
const currentValue = vue.ref((props.modelValue || props.value) ?? null);
const hoverValue = vue.ref(null);
const tooltipValue = vue.ref(null);
const name = props.name || `name${Math.floor(Math.random() * 1_000_000)}`;
const uid = `id${Math.floor(Math.random() * 1_000_000)}`;
vue.watch(() => props.value, () => {
if (props.value !== undefined) {
currentValue.value = props.value;
}
});
vue.watch(() => props.modelValue, () => {
if (props.modelValue !== undefined) {
currentValue.value = props.modelValue;
}
});
const handleMouseEnter = (value) => {
if (props.disabled || props.readOnly) {
return;
}
emit('hover', value);
hoverValue.value = value;
tooltipValue.value = value;
};
const handleMouseLeave = () => {
if (props.disabled || props.readOnly) {
return;
}
emit('hover', null);
hoverValue.value = null;
};
const handleOnChange = (value) => {
if (props.disabled || props.readOnly) {
return;
}
if (cleared.value) {
cleared.value = false;
return;
}
currentValue.value = value;
emit('change', value);
emit('update:modelValue', value);
};
const handleOnClick = (value) => {
if (props.disabled || props.readOnly) {
return;
}
if (props.allowClear && value === currentValue.value) {
emit('change', value);
cleared.value = true;
currentValue.value = null;
hoverValue.value = null;
}
};
return () => vue.h('div', {
class: [
'rating',
{
[`rating-${props.size}`]: props.size,
disabled: props.disabled,
readonly: props.readOnly,
},
],
role: 'radiogroup',
}, [
Array.from({ length: props.itemCount }, (_, index) => {
const numberOfRadios = 1 / props.precision;
return vue.withDirectives(vue.h('div', {
class: 'rating-item',
}, [
Array.from({ length: numberOfRadios }, (_, _index) => {
const isNotLastItem = _index + 1 < numberOfRadios;
const value = numberOfRadios === 1
? index + 1
: index + (_index + 1) * (1 * props.precision);
const id = `${uid}${value}`;
const isItemChecked = () => value === currentValue.value;
const isItemActive = () => {
if (props.highlightOnlySelected
? hoverValue.value === value
: hoverValue.value && hoverValue.value >= value) {
return true;
}
if (hoverValue.value === null &&
(props.highlightOnlySelected
? isItemChecked()
: currentValue.value && currentValue.value >= value)) {
return true;
}
return false;
};
return [
vue.h('label', {
class: [
'rating-item-label',
{
active: isItemActive(),
},
],
for: id,
onClick: () => handleOnClick(value),
onMouseenter: () => handleMouseEnter(value),
onMouseleave: () => handleMouseLeave(),
...(isNotLastItem && {
style: {
zIndex: 1 / props.precision - _index,
position: 'absolute',
width: `${props.precision * (_index + 1) * 100}%`,
overflow: 'hidden',
opacity: 0,
},
}),
}, {
default: () => [
slots.icon
? vue.h('div', { class: 'rating-item-custom-icon' }, slots.icon({ value: index + 1 }))
: vue.h('div', { class: 'rating-item-icon' }),
slots.activeIcon &&
vue.h('div', { class: 'rating-item-custom-icon-active' }, slots.activeIcon({ value: index + 1 })),
],
}),
vue.h('input', {
checked: isItemChecked(),
class: 'rating-item-input',
disabled: props.disabled || props.readOnly,
id: id,
name: name,
onBlur: () => handleMouseLeave(),
onChange: () => handleOnChange(value),
onFocus: () => handleMouseEnter(value),
type: 'radio',
value: value,
}),
];
}),
]), props.tooltips
? [
[
vCTooltip.default,
{
content: Array.isArray(props.tooltips) ? props.tooltips[index] : index + 1,
placement: 'top',
},
],
]
: []);
}),
]);
},
});
exports.CRating = CRating;
//# sourceMappingURL=CRating.js.map
;