UNPKG

@coreui/vue-pro

Version:

UI Components Library for Vue.js

241 lines (237 loc) 9.14 kB
'use strict'; 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