{"version":3,"file":"scrollbar2.mjs","names":[],"sources":["../../../../../../packages/components/scrollbar/src/scrollbar.vue"],"sourcesContent":["<template>\n  <div ref=\"scrollbarRef\" :class=\"ns.b()\">\n    <div\n      ref=\"wrapRef\"\n      :class=\"wrapKls\"\n      :style=\"wrapStyle\"\n      :tabindex=\"tabindex\"\n      @scroll=\"handleScroll\"\n    >\n      <component\n        :is=\"tag\"\n        :id=\"id\"\n        ref=\"resizeRef\"\n        :class=\"resizeKls\"\n        :style=\"viewStyle\"\n        :role=\"role\"\n        :aria-label=\"ariaLabel\"\n        :aria-orientation=\"ariaOrientation\"\n      >\n        <slot />\n      </component>\n    </div>\n    <template v-if=\"!native\">\n      <bar ref=\"barRef\" :always=\"always\" :min-size=\"minSize\" />\n    </template>\n  </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport {\n  computed,\n  nextTick,\n  onActivated,\n  onMounted,\n  onUpdated,\n  provide,\n  reactive,\n  ref,\n  watch,\n} from 'vue'\nimport { useEventListener, useResizeObserver } from '@vueuse/core'\nimport { addUnit, debugWarn, isNumber, isObject } from '@element-plus/utils'\nimport { useNamespace } from '@element-plus/hooks'\nimport Bar from './bar.vue'\nimport { scrollbarContextKey } from './constants'\nimport { scrollbarEmits } from './scrollbar'\n\nimport type { ScrollbarDirection, ScrollbarProps } from './scrollbar'\nimport type { BarInstance } from './bar'\nimport type { CSSProperties, StyleValue } from 'vue'\n\nconst COMPONENT_NAME = 'ElScrollbar'\n\ndefineOptions({\n  name: COMPONENT_NAME,\n})\n\nconst props = withDefaults(defineProps<ScrollbarProps>(), {\n  distance: 0,\n  height: '',\n  maxHeight: '',\n  wrapStyle: '',\n  wrapClass: '',\n  viewStyle: '',\n  viewClass: '',\n  tag: 'div',\n  minSize: 20,\n  tabindex: undefined,\n})\nconst emit = defineEmits(scrollbarEmits)\n\nconst ns = useNamespace('scrollbar')\n\nlet stopResizeObserver: (() => void) | undefined = undefined\nlet stopWrapResizeObserver: (() => void) | undefined = undefined\nlet stopResizeListener: (() => void) | undefined = undefined\nlet wrapScrollTop = 0\nlet wrapScrollLeft = 0\nlet direction = '' as ScrollbarDirection\nconst distanceScrollState = {\n  bottom: false,\n  top: false,\n  right: false,\n  left: false,\n}\n\nconst scrollbarRef = ref<HTMLDivElement>()\nconst wrapRef = ref<HTMLDivElement>()\nconst resizeRef = ref<HTMLElement>()\nconst barRef = ref<BarInstance>()\n\nconst wrapStyle = computed<StyleValue>(() => {\n  const style: CSSProperties = {}\n  const height = addUnit(props.height)\n  const maxHeight = addUnit(props.maxHeight)\n  if (height) style.height = height\n  if (maxHeight) style.maxHeight = maxHeight\n  return [props.wrapStyle, style]\n})\n\nconst wrapKls = computed(() => {\n  return [\n    props.wrapClass,\n    ns.e('wrap'),\n    { [ns.em('wrap', 'hidden-default')]: !props.native },\n  ]\n})\n\nconst resizeKls = computed(() => {\n  return [ns.e('view'), props.viewClass]\n})\n\nconst shouldSkipDirection = (direction: ScrollbarDirection) => {\n  return distanceScrollState[direction] ?? false\n}\n\nconst DIRECTION_PAIRS: Record<ScrollbarDirection, ScrollbarDirection> = {\n  top: 'bottom',\n  bottom: 'top',\n  left: 'right',\n  right: 'left',\n}\nconst updateTriggerStatus = (arrivedStates: Record<string, boolean>) => {\n  const oppositeDirection = DIRECTION_PAIRS[direction]\n  if (!oppositeDirection) return\n\n  const arrived = arrivedStates[direction]\n  const oppositeArrived = arrivedStates[oppositeDirection]\n\n  if (arrived && !distanceScrollState[direction]) {\n    distanceScrollState[direction] = true\n  }\n\n  if (!oppositeArrived && distanceScrollState[oppositeDirection]) {\n    distanceScrollState[oppositeDirection] = false\n  }\n}\n\nconst handleScroll = () => {\n  if (wrapRef.value) {\n    barRef.value?.handleScroll(wrapRef.value)\n    const prevTop = wrapScrollTop\n    const prevLeft = wrapScrollLeft\n    wrapScrollTop = wrapRef.value.scrollTop\n    wrapScrollLeft = wrapRef.value.scrollLeft\n\n    const arrivedStates = {\n      bottom:\n        wrapScrollTop + wrapRef.value.clientHeight >=\n        wrapRef.value.scrollHeight - props.distance,\n      top: wrapScrollTop <= props.distance && prevTop !== 0,\n      right:\n        wrapScrollLeft + wrapRef.value.clientWidth >=\n          wrapRef.value.scrollWidth - props.distance &&\n        prevLeft !== wrapScrollLeft,\n      left: wrapScrollLeft <= props.distance && prevLeft !== 0,\n    }\n\n    emit('scroll', {\n      scrollTop: wrapScrollTop,\n      scrollLeft: wrapScrollLeft,\n    })\n\n    if (prevTop !== wrapScrollTop) {\n      direction = wrapScrollTop > prevTop ? 'bottom' : 'top'\n    }\n    if (prevLeft !== wrapScrollLeft) {\n      direction = wrapScrollLeft > prevLeft ? 'right' : 'left'\n    }\n    if (props.distance > 0) {\n      if (shouldSkipDirection(direction)) {\n        return\n      }\n      updateTriggerStatus(arrivedStates)\n    }\n    if (arrivedStates[direction]) emit('end-reached', direction)\n  }\n}\n\nfunction scrollTo(xCord: number, yCord?: number): void\nfunction scrollTo(options: ScrollToOptions): void\nfunction scrollTo(arg1: unknown, arg2?: number) {\n  if (isObject(arg1)) {\n    wrapRef.value!.scrollTo(arg1)\n  } else if (isNumber(arg1) && isNumber(arg2)) {\n    wrapRef.value!.scrollTo(arg1, arg2)\n  }\n}\n\nconst setScrollTop = (value: number) => {\n  if (!isNumber(value)) {\n    debugWarn(COMPONENT_NAME, 'value must be a number')\n    return\n  }\n  wrapRef.value!.scrollTop = value\n}\n\nconst setScrollLeft = (value: number) => {\n  if (!isNumber(value)) {\n    debugWarn(COMPONENT_NAME, 'value must be a number')\n    return\n  }\n  wrapRef.value!.scrollLeft = value\n}\n\nconst update = () => {\n  barRef.value?.update()\n  distanceScrollState[direction] = false\n}\n\nwatch(\n  () => props.noresize,\n  (noresize) => {\n    if (noresize) {\n      stopResizeObserver?.()\n      stopWrapResizeObserver?.()\n      stopResizeListener?.()\n    } else {\n      ;({ stop: stopResizeObserver } = useResizeObserver(resizeRef, update))\n      ;({ stop: stopWrapResizeObserver } = useResizeObserver(wrapRef, update))\n      stopResizeListener = useEventListener('resize', update)\n    }\n  },\n  { immediate: true }\n)\n\nwatch(\n  () => [props.maxHeight, props.height],\n  () => {\n    if (!props.native)\n      nextTick(() => {\n        update()\n        if (wrapRef.value) {\n          barRef.value?.handleScroll(wrapRef.value)\n        }\n      })\n  }\n)\n\nprovide(\n  scrollbarContextKey,\n  reactive({\n    scrollbarElement: scrollbarRef,\n    wrapElement: wrapRef,\n  })\n)\n\nonActivated(() => {\n  if (wrapRef.value) {\n    wrapRef.value.scrollTop = wrapScrollTop\n    wrapRef.value.scrollLeft = wrapScrollLeft\n  }\n})\n\nonMounted(() => {\n  if (!props.native)\n    nextTick(() => {\n      update()\n    })\n})\nonUpdated(() => update())\n\ndefineExpose({\n  /** @description scrollbar wrap ref */\n  wrapRef,\n  /** @description update scrollbar state manually */\n  update,\n  /** @description scrolls to a particular set of coordinates */\n  scrollTo,\n  /** @description set distance to scroll top */\n  setScrollTop,\n  /** @description set distance to scroll left */\n  setScrollLeft,\n  /** @description handle scroll event */\n  handleScroll,\n})\n</script>\n"],"mappings":""}