{"version":3,"file":"rate2.mjs","names":[],"sources":["../../../../../../packages/components/rate/src/rate.vue"],"sourcesContent":["<template>\n  <div\n    :id=\"inputId\"\n    :class=\"[rateClasses, ns.is('disabled', rateDisabled)]\"\n    role=\"slider\"\n    :aria-label=\"!isLabeledByFormItem ? ariaLabel || 'rating' : undefined\"\n    :aria-labelledby=\"\n      isLabeledByFormItem ? formItemContext?.labelId : undefined\n    \"\n    :aria-valuenow=\"currentValue\"\n    :aria-valuetext=\"text || undefined\"\n    aria-valuemin=\"0\"\n    :aria-valuemax=\"max\"\n    :style=\"rateStyles\"\n    :tabindex=\"rateDisabled ? undefined : 0\"\n    :aria-disabled=\"rateDisabled\"\n    @keydown=\"handleKey\"\n  >\n    <span\n      v-for=\"(item, key) in max\"\n      :key=\"key\"\n      :class=\"ns.e('item')\"\n      @mousemove=\"setCurrentValue(item, $event)\"\n      @mouseleave=\"resetCurrentValue\"\n      @click=\"selectValue(item)\"\n    >\n      <el-icon\n        ref=\"iconRefs\"\n        :class=\"[\n          ns.e('icon'),\n          { hover: hoverIndex === item },\n          ns.is('active', item <= currentValue),\n          ns.is('focus-visible', item === Math.ceil(currentValue || 1)),\n        ]\"\n      >\n        <component\n          :is=\"activeComponent\"\n          v-show=\"!showDecimalIcon(item) && item <= currentValue\"\n        />\n        <component\n          :is=\"voidComponent\"\n          v-show=\"!showDecimalIcon(item) && item > currentValue\"\n        />\n        <component\n          :is=\"voidComponent\"\n          v-show=\"showDecimalIcon(item)\"\n          :class=\"[ns.em('decimal', 'box')]\"\n        />\n        <el-icon\n          v-show=\"showDecimalIcon(item)\"\n          :style=\"decimalStyle\"\n          :class=\"[ns.e('icon'), ns.e('decimal')]\"\n        >\n          <component :is=\"decimalIconComponent\" />\n        </el-icon>\n      </el-icon>\n    </span>\n    <span\n      v-if=\"showText || showScore\"\n      :class=\"ns.e('text')\"\n      :style=\"{ color: textColor }\"\n    >\n      {{ text }}\n    </span>\n  </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed, inject, markRaw, ref, watch } from 'vue'\nimport { clamp } from 'lodash-unified'\nimport {\n  CHANGE_EVENT,\n  EVENT_CODE,\n  UPDATE_MODEL_EVENT,\n} from '@element-plus/constants'\nimport { getEventCode, isArray, isObject, isString } from '@element-plus/utils'\nimport {\n  formItemContextKey,\n  useFormDisabled,\n  useFormItemInputId,\n  useFormSize,\n} from '@element-plus/components/form'\nimport { ElIcon } from '@element-plus/components/icon'\nimport { Star, StarFilled } from '@element-plus/icons-vue'\nimport { useNamespace } from '@element-plus/hooks'\nimport { rateEmits } from './rate'\n\nimport type { CSSProperties, Component } from 'vue'\nimport type { IconInstance } from '@element-plus/components/icon'\nimport type { RateProps } from './rate'\n\nfunction getValueFromMap<T>(\n  value: number,\n  map: Record<string, T | { excluded?: boolean; value: T }>\n) {\n  const isExcludedObject = (\n    val: unknown\n  ): val is { excluded?: boolean } & Record<any, unknown> => isObject(val)\n\n  const matchedKeys = Object.keys(map)\n    .map((key) => +key)\n    .filter((key) => {\n      const val = map[key]\n      const excluded = isExcludedObject(val) ? val.excluded : false\n      return excluded ? value < key : value <= key\n    })\n    .sort((a, b) => a - b)\n  const matchedValue = map[matchedKeys[0]]\n  return (isExcludedObject(matchedValue) && matchedValue.value) || matchedValue\n}\n\ndefineOptions({\n  name: 'ElRate',\n})\n\nconst props = withDefaults(defineProps<RateProps>(), {\n  modelValue: 0,\n  id: undefined,\n  lowThreshold: 2,\n  highThreshold: 4,\n  max: 5,\n  colors: () => ['', '', ''],\n  voidColor: '',\n  disabledVoidColor: '',\n  icons: () => [StarFilled, StarFilled, StarFilled],\n  voidIcon: () => Star,\n  disabledVoidIcon: () => StarFilled,\n  disabled: undefined,\n  textColor: '',\n  texts: () => [\n    'Extremely bad',\n    'Disappointed',\n    'Fair',\n    'Satisfied',\n    'Surprise',\n  ],\n  scoreTemplate: '{value}',\n})\nconst emit = defineEmits(rateEmits)\n\nconst formItemContext = inject(formItemContextKey, undefined)\nconst rateSize = useFormSize()\nconst ns = useNamespace('rate')\nconst { inputId, isLabeledByFormItem } = useFormItemInputId(props, {\n  formItemContext,\n})\n\nconst currentValue = ref(clamp(props.modelValue, 0, props.max))\nconst hoverIndex = ref(-1)\nconst pointerAtLeftHalf = ref(true)\n\nconst iconRefs = ref<IconInstance[]>([])\nconst iconClientWidths = computed<number[]>(() =>\n  iconRefs.value.map((icon) => icon.$el.clientWidth)\n)\nconst rateClasses = computed(() => [ns.b(), ns.m(rateSize.value)])\nconst rateDisabled = useFormDisabled()\nconst rateStyles = computed(() => {\n  return ns.cssVarBlock({\n    'void-color': props.voidColor,\n    'disabled-void-color': props.disabledVoidColor,\n    'fill-color': activeColor.value,\n  }) as CSSProperties\n})\n\nconst text = computed(() => {\n  let result = ''\n  if (props.showScore) {\n    result = props.scoreTemplate.replace(\n      /\\{\\s*value\\s*\\}/,\n      rateDisabled.value ? `${props.modelValue}` : `${currentValue.value}`\n    )\n  } else if (props.showText) {\n    result = props.texts[Math.ceil(currentValue.value) - 1]\n  }\n  return result\n})\nconst valueDecimal = computed(\n  () => props.modelValue * 100 - Math.floor(props.modelValue) * 100\n)\nconst colorMap = computed(() =>\n  isArray(props.colors)\n    ? {\n        [props.lowThreshold]: props.colors[0],\n        [props.highThreshold]: { value: props.colors[1], excluded: true },\n        [props.max]: props.colors[2],\n      }\n    : props.colors\n)\nconst activeColor = computed(() => {\n  const color = getValueFromMap(currentValue.value, colorMap.value)\n  // {value: '', excluded: true} returned\n  return isObject(color) ? '' : color\n})\nconst decimalStyle = computed(() => {\n  let width = ''\n  if (rateDisabled.value) {\n    width = `${valueDecimal.value}%`\n  } else if (props.allowHalf) {\n    width = '50%'\n  }\n  return {\n    color: activeColor.value,\n    width,\n  }\n})\nconst componentMap = computed(() => {\n  let icons = isArray(props.icons) ? [...props.icons] : { ...props.icons }\n  icons = markRaw(icons) as\n    | Array<string | Component>\n    | Record<number, string | Component>\n  return isArray(icons)\n    ? {\n        [props.lowThreshold]: icons[0],\n        [props.highThreshold]: {\n          value: icons[1],\n          excluded: true,\n        },\n        [props.max]: icons[2],\n      }\n    : icons\n})\nconst decimalIconComponent = computed(() =>\n  getValueFromMap(props.modelValue, componentMap.value)\n)\nconst voidComponent = computed(() =>\n  rateDisabled.value\n    ? isString(props.disabledVoidIcon)\n      ? props.disabledVoidIcon\n      : (markRaw(props.disabledVoidIcon) as Component)\n    : isString(props.voidIcon)\n      ? props.voidIcon\n      : (markRaw(props.voidIcon) as Component)\n)\nconst activeComponent = computed(() =>\n  getValueFromMap(currentValue.value, componentMap.value)\n)\n\nfunction showDecimalIcon(item: number) {\n  const showWhenDisabled =\n    rateDisabled.value &&\n    valueDecimal.value > 0 &&\n    item - 1 < props.modelValue &&\n    item > props.modelValue\n  const showWhenAllowHalf =\n    props.allowHalf &&\n    pointerAtLeftHalf.value &&\n    item - 0.5 <= currentValue.value &&\n    item > currentValue.value\n  return showWhenDisabled || showWhenAllowHalf\n}\n\nfunction emitValue(value: number) {\n  // if allow clear, and selected value is same as modelValue, reset value to 0\n  if (props.clearable && value === props.modelValue) {\n    value = 0\n  }\n\n  emit(UPDATE_MODEL_EVENT, value)\n  if (props.modelValue !== value) {\n    emit(CHANGE_EVENT, value)\n  }\n}\n\nfunction selectValue(value: number) {\n  if (rateDisabled.value) {\n    return\n  }\n  if (props.allowHalf && pointerAtLeftHalf.value) {\n    emitValue(currentValue.value)\n  } else {\n    emitValue(value)\n  }\n}\n\nfunction handleKey(e: KeyboardEvent) {\n  if (rateDisabled.value) {\n    return\n  }\n  const code = getEventCode(e)\n  const step = props.allowHalf ? 0.5 : 1\n  let _currentValue = currentValue.value\n\n  switch (code) {\n    case EVENT_CODE.up:\n    case EVENT_CODE.right:\n      _currentValue += step\n      break\n    case EVENT_CODE.left:\n    case EVENT_CODE.down:\n      _currentValue -= step\n      break\n  }\n\n  _currentValue = clamp(_currentValue, 0, props.max)\n\n  if (_currentValue === currentValue.value) {\n    return\n  }\n\n  e.stopPropagation()\n  e.preventDefault()\n  emit(UPDATE_MODEL_EVENT, _currentValue)\n  emit(CHANGE_EVENT, _currentValue)\n  return _currentValue\n}\n\nfunction setCurrentValue(value: number, event?: MouseEvent) {\n  if (rateDisabled.value) {\n    return\n  }\n  if (props.allowHalf && event) {\n    pointerAtLeftHalf.value =\n      event.offsetX * 2 <= iconClientWidths.value[value - 1]\n    currentValue.value = pointerAtLeftHalf.value ? value - 0.5 : value\n  } else {\n    currentValue.value = value\n  }\n  hoverIndex.value = value\n}\n\nfunction resetCurrentValue() {\n  if (rateDisabled.value) {\n    return\n  }\n  if (props.allowHalf) {\n    pointerAtLeftHalf.value = props.modelValue !== Math.floor(props.modelValue)\n  }\n  currentValue.value = clamp(props.modelValue, 0, props.max)\n  hoverIndex.value = -1\n}\n\nwatch(\n  () => props.modelValue,\n  (val) => {\n    currentValue.value = clamp(val, 0, props.max)\n    pointerAtLeftHalf.value = props.modelValue !== Math.floor(props.modelValue)\n  }\n)\n\nif (!props.modelValue) {\n  emit(UPDATE_MODEL_EVENT, 0)\n}\n\ndefineExpose({\n  /** @description set current value */\n  setCurrentValue,\n  /** @description reset current value */\n  resetCurrentValue,\n})\n</script>\n"],"mappings":""}