{"version":3,"file":"thumb.mjs","sources":["../../../../../../packages/components/scrollbar/src/thumb.vue"],"sourcesContent":["<template>\r\n  <transition :name=\"ns.b('fade')\">\r\n    <div\r\n      v-show=\"always || visible\"\r\n      ref=\"instance\"\r\n      :class=\"[ns.e('bar'), ns.is(bar.key)]\"\r\n      @mousedown=\"clickTrackHandler\"\r\n    >\r\n      <div\r\n        ref=\"thumb\"\r\n        :class=\"ns.e('thumb')\"\r\n        :style=\"thumbStyle\"\r\n        @mousedown=\"clickThumbHandler\"\r\n      ></div>\r\n    </div>\r\n  </transition>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport {\r\n  computed,\r\n  defineComponent,\r\n  inject,\r\n  onBeforeUnmount,\r\n  ref,\r\n  toRef,\r\n} from 'vue'\r\nimport { useEventListener, isClient } from '@vueuse/core'\r\nimport { throwError } from '@sgui-plus/utils/error'\r\nimport { useNamespace } from '@sgui-plus/hooks'\r\nimport { ScrollbarContextKey } from './constants'\r\nimport { BAR_MAP, renderThumbStyle } from './util'\r\n\r\nimport { thumbProps } from './thumb'\r\n\r\nconst COMPONENT_NAME = 'Thumb'\r\nexport default defineComponent({\r\n  name: COMPONENT_NAME,\r\n  props: thumbProps,\r\n\r\n  setup(props) {\r\n    const scrollbar = inject(ScrollbarContextKey)\r\n    const ns = useNamespace('scrollbar')\r\n\r\n    if (!scrollbar)\r\n      throwError(COMPONENT_NAME, 'can not inject scrollbar context')\r\n\r\n    const instance = ref<HTMLDivElement>()\r\n    const thumb = ref<HTMLDivElement>()\r\n\r\n    const thumbState = ref({})\r\n    const visible = ref(false)\r\n\r\n    let cursorDown = false\r\n    let cursorLeave = false\r\n    let originalOnSelectStart:\r\n      | ((this: GlobalEventHandlers, ev: Event) => any)\r\n      | null = isClient ? document.onselectstart : null\r\n\r\n    const bar = computed(\r\n      () => BAR_MAP[props.vertical ? 'vertical' : 'horizontal']\r\n    )\r\n\r\n    const thumbStyle = computed(() =>\r\n      renderThumbStyle({\r\n        size: props.size,\r\n        move: props.move,\r\n        bar: bar.value,\r\n      })\r\n    )\r\n\r\n    const offsetRatio = computed(\r\n      () =>\r\n        // offsetRatioX = original width of thumb / current width of thumb / ratioX\r\n        // offsetRatioY = original height of thumb / current height of thumb / ratioY\r\n        // instance height = wrap height - GAP\r\n        instance.value![bar.value.offset] ** 2 /\r\n        scrollbar.wrapElement![bar.value.scrollSize] /\r\n        props.ratio /\r\n        thumb.value![bar.value.offset]\r\n    )\r\n\r\n    const clickThumbHandler = (e: MouseEvent) => {\r\n      // prevent click event of middle and right button\r\n      e.stopPropagation()\r\n      if (e.ctrlKey || [1, 2].includes(e.button)) return\r\n\r\n      window.getSelection()?.removeAllRanges()\r\n      startDrag(e)\r\n\r\n      const el = e.currentTarget as HTMLDivElement\r\n      if (!el) return\r\n      thumbState.value[bar.value.axis] =\r\n        el[bar.value.offset] -\r\n        (e[bar.value.client] - el.getBoundingClientRect()[bar.value.direction])\r\n    }\r\n\r\n    const clickTrackHandler = (e: MouseEvent) => {\r\n      if (!thumb.value || !instance.value || !scrollbar.wrapElement) return\r\n\r\n      const offset = Math.abs(\r\n        (e.target as HTMLElement).getBoundingClientRect()[bar.value.direction] -\r\n          e[bar.value.client]\r\n      )\r\n      const thumbHalf = thumb.value[bar.value.offset] / 2\r\n      const thumbPositionPercentage =\r\n        ((offset - thumbHalf) * 100 * offsetRatio.value) /\r\n        instance.value[bar.value.offset]\r\n\r\n      scrollbar.wrapElement[bar.value.scroll] =\r\n        (thumbPositionPercentage *\r\n          scrollbar.wrapElement[bar.value.scrollSize]) /\r\n        100\r\n    }\r\n\r\n    const startDrag = (e: MouseEvent) => {\r\n      e.stopImmediatePropagation()\r\n      cursorDown = true\r\n      document.addEventListener('mousemove', mouseMoveDocumentHandler)\r\n      document.addEventListener('mouseup', mouseUpDocumentHandler)\r\n      originalOnSelectStart = document.onselectstart\r\n      document.onselectstart = () => false\r\n    }\r\n\r\n    const mouseMoveDocumentHandler = (e: MouseEvent) => {\r\n      if (!instance.value || !thumb.value) return\r\n      if (cursorDown === false) return\r\n\r\n      const prevPage = thumbState.value[bar.value.axis]\r\n      if (!prevPage) return\r\n\r\n      const offset =\r\n        (instance.value.getBoundingClientRect()[bar.value.direction] -\r\n          e[bar.value.client]) *\r\n        -1\r\n      const thumbClickPosition = thumb.value[bar.value.offset] - prevPage\r\n      const thumbPositionPercentage =\r\n        ((offset - thumbClickPosition) * 100 * offsetRatio.value) /\r\n        instance.value[bar.value.offset]\r\n      scrollbar.wrapElement[bar.value.scroll] =\r\n        (thumbPositionPercentage *\r\n          scrollbar.wrapElement[bar.value.scrollSize]) /\r\n        100\r\n    }\r\n\r\n    const mouseUpDocumentHandler = () => {\r\n      cursorDown = false\r\n      thumbState.value[bar.value.axis] = 0\r\n      document.removeEventListener('mousemove', mouseMoveDocumentHandler)\r\n      document.removeEventListener('mouseup', mouseUpDocumentHandler)\r\n      restoreOnselectstart()\r\n      if (cursorLeave) visible.value = false\r\n    }\r\n\r\n    const mouseMoveScrollbarHandler = () => {\r\n      cursorLeave = false\r\n      visible.value = !!props.size\r\n    }\r\n\r\n    const mouseLeaveScrollbarHandler = () => {\r\n      cursorLeave = true\r\n      visible.value = cursorDown\r\n    }\r\n\r\n    onBeforeUnmount(() => {\r\n      restoreOnselectstart()\r\n      document.removeEventListener('mouseup', mouseUpDocumentHandler)\r\n    })\r\n\r\n    const restoreOnselectstart = () => {\r\n      if (document.onselectstart !== originalOnSelectStart)\r\n        document.onselectstart = originalOnSelectStart\r\n    }\r\n\r\n    useEventListener(\r\n      toRef(scrollbar, 'scrollbarElement'),\r\n      'mousemove',\r\n      mouseMoveScrollbarHandler\r\n    )\r\n    useEventListener(\r\n      toRef(scrollbar, 'scrollbarElement'),\r\n      'mouseleave',\r\n      mouseLeaveScrollbarHandler\r\n    )\r\n\r\n    return {\r\n      ns,\r\n      instance,\r\n      thumb,\r\n      bar,\r\n      thumbStyle,\r\n      visible,\r\n      clickTrackHandler,\r\n      clickThumbHandler,\r\n    }\r\n  },\r\n})\r\n</script>\r\n"],"names":["_openBlock","_createBlock","_Transition","_withCtx","_withDirectives","_createElementVNode","_normalizeClass","_normalizeStyle"],"mappings":";;;;SACmB,WAAM,CAAA,IAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,KAAA,EAAA,QAAA,EAAA;SAAvBA,SAca,EAAA,EAAAC,WAAA,CAAAC,UAAA,EAAA;AAAA,IAAA,IAAA,EAAA,IAAA,CAAA,EAAA,CAAA,CAAA,CAAA,MAAA,CAAA;;;aAXLC,OAAU,CAAA,MAAA;AAAA,MAAAC,cAAA,CACRC,kBAAO,CAAA,KAAA,EAAA;AAAA,QACZ,GAAA,EAAA,UAAA;AAAA,QAAA,KAAA,EAAAC,cAAA,CAAA,CAAA,IAAA,CAAA,EAAA,CAAA,CAAA,CAAA,KAAA,CAAA,EAAA,IAAA,CAAA,EAAA,CAAA,EAAA,CAAA,IAAA,CAAA,GAAA,CAAA,GAAA,CAAA,CAAA,CAAA;QAED,WAKO,EAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,iBAAA,IAAA,IAAA,CAAA,iBAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,OAAA,EAAA;2BAHC,KAAE,EAAA;AAAA,UACP,GAAK,EAAA,OAAA;AAAA,UACL,KAAS,EAAAA,cAAA,CAAA,IAAA,CAAA,EAAA,CAAA,CAAA,CAAA,OAAA,CAAA,CAAA;AAAA,UAAA,KAAA,EAAAC,cAAA,CAAA,IAAA,CAAA,UAAA,CAAA;;iBATJ,EAAiB,CAAA;AAAA,OAAA,EAAA,EAAA,CAAA,EAAA;;;;;;;;;;;"}