{"version":3,"file":"use-slider-button.mjs","names":["clamp"],"sources":["../../../../../../../packages/components/slider/src/composables/use-slider-button.ts"],"sourcesContent":["import { computed, inject, nextTick, ref, watch } from 'vue'\nimport { clamp, debounce } from 'lodash-unified'\nimport { useEventListener } from '@vueuse/core'\nimport { EVENT_CODE, UPDATE_MODEL_EVENT } from '@element-plus/constants'\nimport { getEventCode, isNumber } from '@element-plus/utils'\nimport { sliderContextKey } from '../constants'\n\nimport type { CSSProperties, ComputedRef, Ref, SetupContext } from 'vue'\nimport type { SliderProps } from '../slider'\nimport type {\n  SliderButtonEmits,\n  SliderButtonInitData,\n  SliderButtonProps,\n} from '../button'\nimport type { TooltipInstance } from '@element-plus/components/tooltip'\n\nconst useTooltip = (\n  props: SliderButtonProps,\n  formatTooltip: Ref<SliderProps['formatTooltip']>,\n  showTooltip: Ref<SliderProps['showTooltip']>\n) => {\n  const tooltip = ref<TooltipInstance>()\n\n  const tooltipVisible = ref(false)\n\n  const enableFormat = computed(() => {\n    return formatTooltip.value instanceof Function\n  })\n\n  const formatValue = computed(() => {\n    return (\n      (enableFormat.value && formatTooltip.value!(props.modelValue)) ||\n      props.modelValue\n    )\n  })\n\n  const displayTooltip = debounce(() => {\n    showTooltip.value && (tooltipVisible.value = true)\n  }, 50)\n\n  const hideTooltip = debounce(() => {\n    showTooltip.value && (tooltipVisible.value = false)\n  }, 50)\n\n  return {\n    tooltip,\n    tooltipVisible,\n    formatValue,\n    displayTooltip,\n    hideTooltip,\n  }\n}\n\nexport const useSliderButton = (\n  props: SliderButtonProps,\n  initData: SliderButtonInitData,\n  emit: SetupContext<SliderButtonEmits>['emit']\n) => {\n  const {\n    disabled,\n    min,\n    max,\n    step,\n    showTooltip,\n    persistent,\n    precision,\n    sliderSize,\n    formatTooltip,\n    emitChange,\n    resetSize,\n    updateDragging,\n    markList,\n  } = inject(sliderContextKey)!\n\n  const { tooltip, tooltipVisible, formatValue, displayTooltip, hideTooltip } =\n    useTooltip(props, formatTooltip!, showTooltip)\n\n  const button = ref<HTMLDivElement>()\n\n  const currentPosition = computed(() => {\n    return `${\n      ((props.modelValue - min.value) / (max.value - min.value)) * 100\n    }%`\n  })\n\n  const wrapperStyle: ComputedRef<CSSProperties> = computed(() => {\n    return props.vertical\n      ? { bottom: currentPosition.value }\n      : { left: currentPosition.value }\n  })\n\n  const shouldMoveToMark = computed(() => {\n    return step.value === 'mark' && markList.value.length > 0\n  })\n\n  const handleMouseEnter = () => {\n    initData.hovering = true\n    displayTooltip()\n  }\n\n  const handleMouseLeave = () => {\n    initData.hovering = false\n    if (!initData.dragging) {\n      hideTooltip()\n    }\n  }\n\n  const onButtonDown = (event: MouseEvent | TouchEvent) => {\n    if (disabled.value) return\n    event.preventDefault()\n    onDragStart(event)\n    window.addEventListener('mousemove', onDragging)\n    window.addEventListener('touchmove', onDragging)\n    window.addEventListener('mouseup', onDragEnd)\n    window.addEventListener('touchend', onDragEnd)\n    window.addEventListener('contextmenu', onDragEnd)\n    button.value!.focus()\n  }\n\n  const incrementPosition = (amount: number) => {\n    if (disabled.value) return\n    initData.newPosition =\n      Number.parseFloat(currentPosition.value) +\n      (amount / (max.value - min.value)) * 100\n    setPosition(initData.newPosition)\n    emitChange()\n  }\n\n  const moveToMark = (amount: number) => {\n    if (disabled.value || !markList.value.length) return\n\n    const current = props.modelValue\n    const epsilon = Number.EPSILON\n    const stride = Math.abs(amount)\n    let target: number | undefined\n\n    if (amount > 0) {\n      const startIndex = markList.value.findIndex(\n        (m) => m.point > current + epsilon\n      )\n      if (startIndex !== -1) {\n        const targetIndex = Math.min(\n          startIndex + stride - 1,\n          markList.value.length - 1\n        )\n        target = markList.value[targetIndex].point\n      }\n    } else {\n      let startIndex = -1\n      for (let i = markList.value.length - 1; i >= 0; i--) {\n        if (markList.value[i].point < current - epsilon) {\n          startIndex = i\n          break\n        }\n      }\n\n      if (startIndex !== -1) {\n        const targetIndex = Math.max(startIndex - (stride - 1), 0)\n        target = markList.value[targetIndex].point\n      }\n    }\n\n    if (target !== undefined && target !== current) {\n      const newPos = ((target - min.value) / (max.value - min.value)) * 100\n      setPosition(newPos)\n      emitChange()\n    }\n  }\n\n  const onLeftKeyDown = () => {\n    if (shouldMoveToMark.value) {\n      moveToMark(-1)\n    } else if (isNumber(step.value)) {\n      incrementPosition(-step.value)\n    }\n  }\n\n  const onRightKeyDown = () => {\n    if (shouldMoveToMark.value) {\n      moveToMark(1)\n    } else if (isNumber(step.value)) {\n      incrementPosition(step.value)\n    }\n  }\n\n  const onPageDownKeyDown = () => {\n    if (shouldMoveToMark.value) {\n      moveToMark(-4)\n    } else if (isNumber(step.value)) {\n      incrementPosition(-step.value * 4)\n    }\n  }\n\n  const onPageUpKeyDown = () => {\n    if (shouldMoveToMark.value) {\n      moveToMark(4)\n    } else if (isNumber(step.value)) {\n      incrementPosition(step.value * 4)\n    }\n  }\n\n  const onHomeKeyDown = () => {\n    if (disabled.value) return\n    setPosition(0)\n    emitChange()\n  }\n\n  const onEndKeyDown = () => {\n    if (disabled.value) return\n    setPosition(100)\n    emitChange()\n  }\n\n  const onKeyDown = (event: KeyboardEvent) => {\n    const code = getEventCode(event)\n    let isPreventDefault = true\n\n    switch (code) {\n      case EVENT_CODE.left:\n      case EVENT_CODE.down:\n        onLeftKeyDown()\n        break\n      case EVENT_CODE.right:\n      case EVENT_CODE.up:\n        onRightKeyDown()\n        break\n      case EVENT_CODE.home:\n        onHomeKeyDown()\n        break\n      case EVENT_CODE.end:\n        onEndKeyDown()\n        break\n      case EVENT_CODE.pageDown:\n        onPageDownKeyDown()\n        break\n      case EVENT_CODE.pageUp:\n        onPageUpKeyDown()\n        break\n      default:\n        isPreventDefault = false\n        break\n    }\n\n    isPreventDefault && event.preventDefault()\n  }\n\n  const getClientXY = (event: MouseEvent | TouchEvent) => {\n    let clientX: number\n    let clientY: number\n    if (event.type.startsWith('touch')) {\n      clientY = (event as TouchEvent).touches[0].clientY\n      clientX = (event as TouchEvent).touches[0].clientX\n    } else {\n      clientY = (event as MouseEvent).clientY\n      clientX = (event as MouseEvent).clientX\n    }\n    return {\n      clientX,\n      clientY,\n    }\n  }\n\n  const onDragStart = (event: MouseEvent | TouchEvent) => {\n    initData.dragging = true\n    initData.isClick = true\n    const { clientX, clientY } = getClientXY(event)\n    if (props.vertical) {\n      initData.startY = clientY\n    } else {\n      initData.startX = clientX\n    }\n    initData.startPosition = Number.parseFloat(currentPosition.value)\n    initData.newPosition = initData.startPosition\n  }\n\n  const onDragging = (event: MouseEvent | TouchEvent) => {\n    if (initData.dragging) {\n      initData.isClick = false\n      displayTooltip()\n      resetSize()\n      let diff: number\n      const { clientX, clientY } = getClientXY(event)\n      if (props.vertical) {\n        initData.currentY = clientY\n        diff = ((initData.startY - initData.currentY) / sliderSize.value) * 100\n      } else {\n        initData.currentX = clientX\n        diff = ((initData.currentX - initData.startX) / sliderSize.value) * 100\n      }\n      initData.newPosition = initData.startPosition + diff\n      setPosition(initData.newPosition)\n    }\n  }\n\n  const onDragEnd = () => {\n    if (initData.dragging) {\n      /*\n       * 防止在 mouseup 后立即触发 click，导致滑块有几率产生一小段位移\n       * 不使用 preventDefault 是因为 mouseup 和 click 没有注册在同一个 DOM 上\n       */\n      setTimeout(() => {\n        initData.dragging = false\n        if (!initData.hovering) {\n          hideTooltip()\n        }\n        if (!initData.isClick) {\n          setPosition(initData.newPosition)\n        }\n        emitChange()\n      }, 0)\n      window.removeEventListener('mousemove', onDragging)\n      window.removeEventListener('touchmove', onDragging)\n      window.removeEventListener('mouseup', onDragEnd)\n      window.removeEventListener('touchend', onDragEnd)\n      window.removeEventListener('contextmenu', onDragEnd)\n    }\n  }\n\n  const setPosition = async (newPosition: number) => {\n    if (newPosition === null || Number.isNaN(+newPosition)) return\n\n    newPosition = clamp(newPosition, 0, 100)\n    let value: number\n\n    if (step.value === 'mark') {\n      if (markList.value.length === 0) {\n        value = newPosition <= 50 ? min.value : max.value\n      } else {\n        const closestMark = markList.value.reduce((prev, curr) => {\n          return Math.abs(curr.position - newPosition) <\n            Math.abs(prev.position - newPosition)\n            ? curr\n            : prev\n        })\n        value = closestMark.point\n      }\n    } else {\n      const fullSteps = Math.floor((max.value - min.value) / step.value)\n      const fullRangePercentage =\n        ((fullSteps * step.value) / (max.value - min.value)) * 100\n      const threshold = fullRangePercentage + (100 - fullRangePercentage) / 2\n      if (newPosition < fullRangePercentage) {\n        const valueBetween = fullRangePercentage / fullSteps\n        const steps = Math.round(newPosition / valueBetween)\n        value = min.value + steps * step.value\n      } else if (newPosition < threshold) {\n        value = min.value + fullSteps * step.value\n      } else {\n        value = max.value\n      }\n      value = Number.parseFloat(value.toFixed(precision.value))\n    }\n\n    if (value !== props.modelValue) {\n      emit(UPDATE_MODEL_EVENT, value)\n    }\n\n    if (!initData.dragging && props.modelValue !== initData.oldValue) {\n      initData.oldValue = props.modelValue\n    }\n\n    await nextTick()\n    initData.dragging && displayTooltip()\n    tooltip.value!.updatePopper()\n  }\n\n  watch(\n    () => initData.dragging,\n    (val) => {\n      updateDragging(val)\n    }\n  )\n\n  useEventListener(button, 'touchstart', onButtonDown, { passive: false })\n\n  return {\n    disabled,\n    button,\n    tooltip,\n    tooltipVisible,\n    showTooltip,\n    persistent,\n    wrapperStyle,\n    formatValue,\n    handleMouseEnter,\n    handleMouseLeave,\n    onButtonDown,\n    onKeyDown,\n    setPosition,\n  }\n}\n"],"mappings":";;;;;;;;;AAgBA,MAAM,cACJ,OACA,eACA,gBACG;CACH,MAAM,UAAU,IAAqB;CAErC,MAAM,iBAAiB,IAAI,KAAK;CAEhC,MAAM,eAAe,eAAe;EAClC,OAAO,cAAc,iBAAiB;CACxC,CAAC;CAiBD,OAAO;EACL;EACA;EACA,aAlBkB,eAAe;GACjC,OACG,aAAa,SAAS,cAAc,MAAO,MAAM,UAAU,KAC5D,MAAM;EAEV,CAaY;EACV,gBAZqB,eAAe;GACpC,YAAY,UAAU,eAAe,QAAQ;EAC/C,GAAG,EAUY;EACb,aATkB,eAAe;GACjC,YAAY,UAAU,eAAe,QAAQ;EAC/C,GAAG,EAOS;CACZ;AACF;AAEA,MAAa,mBACX,OACA,UACA,SACG;CACH,MAAM,EACJ,UACA,KACA,KACA,MACA,aACA,YACA,WACA,YACA,eACA,YACA,WACA,gBACA,aACE,OAAO,gBAAgB;CAE3B,MAAM,EAAE,SAAS,gBAAgB,aAAa,gBAAgB,gBAC5D,WAAW,OAAO,eAAgB,WAAW;CAE/C,MAAM,SAAS,IAAoB;CAEnC,MAAM,kBAAkB,eAAe;EACrC,OAAO,IACH,MAAM,aAAa,IAAI,UAAU,IAAI,QAAQ,IAAI,SAAU,IAC9D;CACH,CAAC;CAED,MAAM,eAA2C,eAAe;EAC9D,OAAO,MAAM,WACT,EAAE,QAAQ,gBAAgB,MAAM,IAChC,EAAE,MAAM,gBAAgB,MAAM;CACpC,CAAC;CAED,MAAM,mBAAmB,eAAe;EACtC,OAAO,KAAK,UAAU,UAAU,SAAS,MAAM,SAAS;CAC1D,CAAC;CAED,MAAM,yBAAyB;EAC7B,SAAS,WAAW;EACpB,eAAe;CACjB;CAEA,MAAM,yBAAyB;EAC7B,SAAS,WAAW;EACpB,IAAI,CAAC,SAAS,UACZ,YAAY;CAEhB;CAEA,MAAM,gBAAgB,UAAmC;EACvD,IAAI,SAAS,OAAO;EACpB,MAAM,eAAe;EACrB,YAAY,KAAK;EACjB,OAAO,iBAAiB,aAAa,UAAU;EAC/C,OAAO,iBAAiB,aAAa,UAAU;EAC/C,OAAO,iBAAiB,WAAW,SAAS;EAC5C,OAAO,iBAAiB,YAAY,SAAS;EAC7C,OAAO,iBAAiB,eAAe,SAAS;EAChD,OAAO,MAAO,MAAM;CACtB;CAEA,MAAM,qBAAqB,WAAmB;EAC5C,IAAI,SAAS,OAAO;EACpB,SAAS,cACP,OAAO,WAAW,gBAAgB,KAAK,IACtC,UAAU,IAAI,QAAQ,IAAI,SAAU;EACvC,YAAY,SAAS,WAAW;EAChC,WAAW;CACb;CAEA,MAAM,cAAc,WAAmB;EACrC,IAAI,SAAS,SAAS,CAAC,SAAS,MAAM,QAAQ;EAE9C,MAAM,UAAU,MAAM;EACtB,MAAM,UAAU,OAAO;EACvB,MAAM,SAAS,KAAK,IAAI,MAAM;EAC9B,IAAI;EAEJ,IAAI,SAAS,GAAG;GACd,MAAM,aAAa,SAAS,MAAM,WAC/B,MAAM,EAAE,QAAQ,UAAU,OAC7B;GACA,IAAI,eAAe,IAAI;IACrB,MAAM,cAAc,KAAK,IACvB,aAAa,SAAS,GACtB,SAAS,MAAM,SAAS,CAC1B;IACA,SAAS,SAAS,MAAM,YAAY,CAAC;GACvC;EACF,OAAO;GACL,IAAI,aAAa;GACjB,KAAK,IAAI,IAAI,SAAS,MAAM,SAAS,GAAG,KAAK,GAAG,KAC9C,IAAI,SAAS,MAAM,EAAE,CAAC,QAAQ,UAAU,SAAS;IAC/C,aAAa;IACb;GACF;GAGF,IAAI,eAAe,IAAI;IACrB,MAAM,cAAc,KAAK,IAAI,cAAc,SAAS,IAAI,CAAC;IACzD,SAAS,SAAS,MAAM,YAAY,CAAC;GACvC;EACF;EAEA,IAAI,WAAW,KAAA,KAAa,WAAW,SAAS;GAC9C,MAAM,UAAW,SAAS,IAAI,UAAU,IAAI,QAAQ,IAAI,SAAU;GAClE,YAAY,MAAM;GAClB,WAAW;EACb;CACF;CAEA,MAAM,sBAAsB;EAC1B,IAAI,iBAAiB,OACnB,WAAW,EAAE;OACR,IAAI,SAAS,KAAK,KAAK,GAC5B,kBAAkB,CAAC,KAAK,KAAK;CAEjC;CAEA,MAAM,uBAAuB;EAC3B,IAAI,iBAAiB,OACnB,WAAW,CAAC;OACP,IAAI,SAAS,KAAK,KAAK,GAC5B,kBAAkB,KAAK,KAAK;CAEhC;CAEA,MAAM,0BAA0B;EAC9B,IAAI,iBAAiB,OACnB,WAAW,EAAE;OACR,IAAI,SAAS,KAAK,KAAK,GAC5B,kBAAkB,CAAC,KAAK,QAAQ,CAAC;CAErC;CAEA,MAAM,wBAAwB;EAC5B,IAAI,iBAAiB,OACnB,WAAW,CAAC;OACP,IAAI,SAAS,KAAK,KAAK,GAC5B,kBAAkB,KAAK,QAAQ,CAAC;CAEpC;CAEA,MAAM,sBAAsB;EAC1B,IAAI,SAAS,OAAO;EACpB,YAAY,CAAC;EACb,WAAW;CACb;CAEA,MAAM,qBAAqB;EACzB,IAAI,SAAS,OAAO;EACpB,YAAY,GAAG;EACf,WAAW;CACb;CAEA,MAAM,aAAa,UAAyB;EAC1C,MAAM,OAAO,aAAa,KAAK;EAC/B,IAAI,mBAAmB;EAEvB,QAAQ,MAAR;GACE,KAAK,WAAW;GAChB,KAAK,WAAW;IACd,cAAc;IACd;GACF,KAAK,WAAW;GAChB,KAAK,WAAW;IACd,eAAe;IACf;GACF,KAAK,WAAW;IACd,cAAc;IACd;GACF,KAAK,WAAW;IACd,aAAa;IACb;GACF,KAAK,WAAW;IACd,kBAAkB;IAClB;GACF,KAAK,WAAW;IACd,gBAAgB;IAChB;GACF,SACE,mBAAmB;EAEvB;EAEA,oBAAoB,MAAM,eAAe;CAC3C;CAEA,MAAM,eAAe,UAAmC;EACtD,IAAI;EACJ,IAAI;EACJ,IAAI,MAAM,KAAK,WAAW,OAAO,GAAG;GAClC,UAAW,MAAqB,QAAQ,EAAE,CAAC;GAC3C,UAAW,MAAqB,QAAQ,EAAE,CAAC;EAC7C,OAAO;GACL,UAAW,MAAqB;GAChC,UAAW,MAAqB;EAClC;EACA,OAAO;GACL;GACA;EACF;CACF;CAEA,MAAM,eAAe,UAAmC;EACtD,SAAS,WAAW;EACpB,SAAS,UAAU;EACnB,MAAM,EAAE,SAAS,YAAY,YAAY,KAAK;EAC9C,IAAI,MAAM,UACR,SAAS,SAAS;OAElB,SAAS,SAAS;EAEpB,SAAS,gBAAgB,OAAO,WAAW,gBAAgB,KAAK;EAChE,SAAS,cAAc,SAAS;CAClC;CAEA,MAAM,cAAc,UAAmC;EACrD,IAAI,SAAS,UAAU;GACrB,SAAS,UAAU;GACnB,eAAe;GACf,UAAU;GACV,IAAI;GACJ,MAAM,EAAE,SAAS,YAAY,YAAY,KAAK;GAC9C,IAAI,MAAM,UAAU;IAClB,SAAS,WAAW;IACpB,QAAS,SAAS,SAAS,SAAS,YAAY,WAAW,QAAS;GACtE,OAAO;IACL,SAAS,WAAW;IACpB,QAAS,SAAS,WAAW,SAAS,UAAU,WAAW,QAAS;GACtE;GACA,SAAS,cAAc,SAAS,gBAAgB;GAChD,YAAY,SAAS,WAAW;EAClC;CACF;CAEA,MAAM,kBAAkB;EACtB,IAAI,SAAS,UAAU;GAKrB,iBAAiB;IACf,SAAS,WAAW;IACpB,IAAI,CAAC,SAAS,UACZ,YAAY;IAEd,IAAI,CAAC,SAAS,SACZ,YAAY,SAAS,WAAW;IAElC,WAAW;GACb,GAAG,CAAC;GACJ,OAAO,oBAAoB,aAAa,UAAU;GAClD,OAAO,oBAAoB,aAAa,UAAU;GAClD,OAAO,oBAAoB,WAAW,SAAS;GAC/C,OAAO,oBAAoB,YAAY,SAAS;GAChD,OAAO,oBAAoB,eAAe,SAAS;EACrD;CACF;CAEA,MAAM,cAAc,OAAO,gBAAwB;EACjD,IAAI,gBAAgB,QAAQ,OAAO,MAAM,CAAC,WAAW,GAAG;EAExD,cAAcA,QAAM,aAAa,GAAG,GAAG;EACvC,IAAI;EAEJ,IAAI,KAAK,UAAU,QAAQ;GACzB,IAAI,SAAS,MAAM,WAAW,GAC5B,QAAQ,eAAe,KAAK,IAAI,QAAQ,IAAI;QAQ5C,QANoB,SAAS,MAAM,QAAQ,MAAM,SAAS;IACxD,OAAO,KAAK,IAAI,KAAK,WAAW,WAAW,IACzC,KAAK,IAAI,KAAK,WAAW,WAAW,IAClC,OACA;GACN,CACkB,CAAC,CAAC;EAExB,OAAO;GACL,MAAM,YAAY,KAAK,OAAO,IAAI,QAAQ,IAAI,SAAS,KAAK,KAAK;GACjE,MAAM,sBACF,YAAY,KAAK,SAAU,IAAI,QAAQ,IAAI,SAAU;GACzD,MAAM,YAAY,uBAAuB,MAAM,uBAAuB;GACtE,IAAI,cAAc,qBAAqB;IACrC,MAAM,eAAe,sBAAsB;IAC3C,MAAM,QAAQ,KAAK,MAAM,cAAc,YAAY;IACnD,QAAQ,IAAI,QAAQ,QAAQ,KAAK;GACnC,OAAO,IAAI,cAAc,WACvB,QAAQ,IAAI,QAAQ,YAAY,KAAK;QAErC,QAAQ,IAAI;GAEd,QAAQ,OAAO,WAAW,MAAM,QAAQ,UAAU,KAAK,CAAC;EAC1D;EAEA,IAAI,UAAU,MAAM,YAClB,KAAK,oBAAoB,KAAK;EAGhC,IAAI,CAAC,SAAS,YAAY,MAAM,eAAe,SAAS,UACtD,SAAS,WAAW,MAAM;EAG5B,MAAM,SAAS;EACf,SAAS,YAAY,eAAe;EACpC,QAAQ,MAAO,aAAa;CAC9B;CAEA,YACQ,SAAS,WACd,QAAQ;EACP,eAAe,GAAG;CACpB,CACF;CAEA,iBAAiB,QAAQ,cAAc,cAAc,EAAE,SAAS,MAAM,CAAC;CAEvE,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF"}