123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- import { createTextVNode as _createTextVNode, mergeProps as _mergeProps, createVNode as _createVNode, Fragment as _Fragment } from "vue";
- // Styles
- import "./VRating.css";
- // Components
- import { VBtn } from "../VBtn/index.mjs"; // Composables
- import { makeComponentProps } from "../../composables/component.mjs";
- import { makeDensityProps } from "../../composables/density.mjs";
- import { IconValue } from "../../composables/icons.mjs";
- import { useLocale } from "../../composables/locale.mjs";
- import { useProxiedModel } from "../../composables/proxiedModel.mjs";
- import { makeSizeProps } from "../../composables/size.mjs";
- import { makeTagProps } from "../../composables/tag.mjs";
- import { makeThemeProps, provideTheme } from "../../composables/theme.mjs"; // Utilities
- import { computed, shallowRef } from 'vue';
- import { clamp, createRange, genericComponent, getUid, propsFactory, useRender } from "../../util/index.mjs"; // Types
- export const makeVRatingProps = propsFactory({
- name: String,
- itemAriaLabel: {
- type: String,
- default: '$vuetify.rating.ariaLabel.item'
- },
- activeColor: String,
- color: String,
- clearable: Boolean,
- disabled: Boolean,
- emptyIcon: {
- type: IconValue,
- default: '$ratingEmpty'
- },
- fullIcon: {
- type: IconValue,
- default: '$ratingFull'
- },
- halfIncrements: Boolean,
- hover: Boolean,
- length: {
- type: [Number, String],
- default: 5
- },
- readonly: Boolean,
- modelValue: {
- type: [Number, String],
- default: 0
- },
- itemLabels: Array,
- itemLabelPosition: {
- type: String,
- default: 'top',
- validator: v => ['top', 'bottom'].includes(v)
- },
- ripple: Boolean,
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeSizeProps(),
- ...makeTagProps(),
- ...makeThemeProps()
- }, 'VRating');
- export const VRating = genericComponent()({
- name: 'VRating',
- props: makeVRatingProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- t
- } = useLocale();
- const {
- themeClasses
- } = provideTheme(props);
- const rating = useProxiedModel(props, 'modelValue');
- const normalizedValue = computed(() => clamp(parseFloat(rating.value), 0, +props.length));
- const range = computed(() => createRange(Number(props.length), 1));
- const increments = computed(() => range.value.flatMap(v => props.halfIncrements ? [v - 0.5, v] : [v]));
- const hoverIndex = shallowRef(-1);
- const itemState = computed(() => increments.value.map(value => {
- const isHovering = props.hover && hoverIndex.value > -1;
- const isFilled = normalizedValue.value >= value;
- const isHovered = hoverIndex.value >= value;
- const isFullIcon = isHovering ? isHovered : isFilled;
- const icon = isFullIcon ? props.fullIcon : props.emptyIcon;
- const activeColor = props.activeColor ?? props.color;
- const color = isFilled || isHovered ? activeColor : props.color;
- return {
- isFilled,
- isHovered,
- icon,
- color
- };
- }));
- const eventState = computed(() => [0, ...increments.value].map(value => {
- function onMouseenter() {
- hoverIndex.value = value;
- }
- function onMouseleave() {
- hoverIndex.value = -1;
- }
- function onClick() {
- if (props.disabled || props.readonly) return;
- rating.value = normalizedValue.value === value && props.clearable ? 0 : value;
- }
- return {
- onMouseenter: props.hover ? onMouseenter : undefined,
- onMouseleave: props.hover ? onMouseleave : undefined,
- onClick
- };
- }));
- const name = computed(() => props.name ?? `v-rating-${getUid()}`);
- function VRatingItem(_ref2) {
- let {
- value,
- index,
- showStar = true
- } = _ref2;
- const {
- onMouseenter,
- onMouseleave,
- onClick
- } = eventState.value[index + 1];
- const id = `${name.value}-${String(value).replace('.', '-')}`;
- const btnProps = {
- color: itemState.value[index]?.color,
- density: props.density,
- disabled: props.disabled,
- icon: itemState.value[index]?.icon,
- ripple: props.ripple,
- size: props.size,
- variant: 'plain'
- };
- return _createVNode(_Fragment, null, [_createVNode("label", {
- "for": id,
- "class": {
- 'v-rating__item--half': props.halfIncrements && value % 1 > 0,
- 'v-rating__item--full': props.halfIncrements && value % 1 === 0
- },
- "onMouseenter": onMouseenter,
- "onMouseleave": onMouseleave,
- "onClick": onClick
- }, [_createVNode("span", {
- "class": "v-rating__hidden"
- }, [t(props.itemAriaLabel, value, props.length)]), !showStar ? undefined : slots.item ? slots.item({
- ...itemState.value[index],
- props: btnProps,
- value,
- index,
- rating: normalizedValue.value
- }) : _createVNode(VBtn, _mergeProps({
- "aria-label": t(props.itemAriaLabel, value, props.length)
- }, btnProps), null)]), _createVNode("input", {
- "class": "v-rating__hidden",
- "name": name.value,
- "id": id,
- "type": "radio",
- "value": value,
- "checked": normalizedValue.value === value,
- "tabindex": -1,
- "readonly": props.readonly,
- "disabled": props.disabled
- }, null)]);
- }
- function createLabel(labelProps) {
- if (slots['item-label']) return slots['item-label'](labelProps);
- if (labelProps.label) return _createVNode("span", null, [labelProps.label]);
- return _createVNode("span", null, [_createTextVNode("\xA0")]);
- }
- useRender(() => {
- const hasLabels = !!props.itemLabels?.length || slots['item-label'];
- return _createVNode(props.tag, {
- "class": ['v-rating', {
- 'v-rating--hover': props.hover,
- 'v-rating--readonly': props.readonly
- }, themeClasses.value, props.class],
- "style": props.style
- }, {
- default: () => [_createVNode(VRatingItem, {
- "value": 0,
- "index": -1,
- "showStar": false
- }, null), range.value.map((value, i) => _createVNode("div", {
- "class": "v-rating__wrapper"
- }, [hasLabels && props.itemLabelPosition === 'top' ? createLabel({
- value,
- index: i,
- label: props.itemLabels?.[i]
- }) : undefined, _createVNode("div", {
- "class": "v-rating__item"
- }, [props.halfIncrements ? _createVNode(_Fragment, null, [_createVNode(VRatingItem, {
- "value": value - 0.5,
- "index": i * 2
- }, null), _createVNode(VRatingItem, {
- "value": value,
- "index": i * 2 + 1
- }, null)]) : _createVNode(VRatingItem, {
- "value": value,
- "index": i
- }, null)]), hasLabels && props.itemLabelPosition === 'bottom' ? createLabel({
- value,
- index: i,
- label: props.itemLabels?.[i]
- }) : undefined]))]
- });
- });
- return {};
- }
- });
- //# sourceMappingURL=VRating.mjs.map
|