{"version":3,"file":"hooks.cjs","sources":["../../../components/scroll/hooks.ts"],"sourcesContent":["import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'\n\nimport { useManualRef } from '@vexip-ui/hooks'\nimport { multipleFixed, toNumber } from '@vexip-ui/utils'\n\nimport type { Ref } from 'vue'\nimport type { ScrollMode } from './symbol'\n\nexport function useScrollWrapper({\n  mode,\n  disabled,\n  width,\n  height,\n  scrollX,\n  scrollY,\n  onResize,\n  onBeforeRefresh,\n  onAfterRefresh,\n}: {\n  mode: Ref<Exclude<ScrollMode, 'horizontal-exact'>>,\n  disabled: Ref<boolean>,\n  width: Ref<number | string>,\n  height: Ref<number | string>,\n  scrollX: Ref<number>,\n  scrollY: Ref<number>,\n  onResize?: (entry: ResizeObserverEntry) => void,\n  onBeforeRefresh?: () => void,\n  onAfterRefresh?: () => void\n}) {\n  const { manualRef, triggerUpdate } = useManualRef()\n\n  const wrapperEl = ref<HTMLElement>()\n  const contentEl = ref<HTMLElement>()\n\n  // 容器长宽\n  const wrapper = reactive({\n    el: wrapperEl,\n    width: toNumber(width.value),\n    height: toNumber(height.value),\n  })\n\n  // 内容长宽\n  const content = reactive({\n    el: contentEl,\n    width: 0,\n    height: 0,\n  })\n\n  const x = manualRef(-scrollX.value)\n  const y = manualRef(-scrollY.value)\n\n  const isReady = ref(false)\n\n  const percentX = manualRef(0)\n  const percentY = manualRef(0)\n\n  const xScrollLimit = computed(() => {\n    return wrapper.width ? wrapper.width - content.width : 0\n  })\n  const yScrollLimit = computed(() => {\n    return wrapper.height ? wrapper.height - content.height : 0\n  })\n  const enableXScroll = computed(() => {\n    return (\n      !disabled.value &&\n      mode.value !== 'vertical' &&\n      !!wrapper.width &&\n      content.width - wrapper.width > 1\n    )\n  })\n  const enableYScroll = computed(() => {\n    return (\n      !disabled.value &&\n      mode.value !== 'horizontal' &&\n      !!wrapper.height &&\n      content.height - wrapper.height > 1\n    )\n  })\n  const xBarLength = computed(() => {\n    if (wrapper.width) {\n      return Math.max(Math.min((wrapper.width / (content.width || 1)) * 100, 99), 5)\n    }\n\n    return 35\n  })\n  const yBarLength = computed(() => {\n    if (wrapper.height) {\n      return Math.max(Math.min((wrapper.height / (content.height || 1)) * 100, 99), 5)\n    }\n\n    return 35\n  })\n\n  watch(wrapperEl, () => {\n    refreshWrapper()\n  })\n  watch(contentEl, () => {\n    computeContentSize()\n  })\n  watch(scrollX, value => {\n    x.value = -value\n    verifyScroll()\n  })\n  watch(scrollY, value => {\n    y.value = -value\n    verifyScroll()\n  })\n  watch(width, () => {\n    refreshWrapper().then(verifyScroll)\n  })\n  watch(height, () => {\n    refreshWrapper().then(verifyScroll)\n  })\n\n  function computeWrapperSize(sizeType: 'width' | 'height') {\n    return nextTick(() => {\n      if (!wrapper.el) return\n\n      const size = sizeType === 'width' ? width.value : height.value\n      const titleCaseSizeType = sizeType.slice(0, 1).toUpperCase() + sizeType.slice(1)\n\n      // 获取 wrapper 的 px 大小\n      if (typeof size === 'string') {\n        if (!size.endsWith('px') && (!size || Number.isNaN(Number(size)))) {\n          wrapper[sizeType] =\n            wrapper.el[`offset${titleCaseSizeType}` as 'offsetWidth' | 'offsetHeight']\n        } else {\n          wrapper[sizeType] = parseInt(size)\n        }\n      } else {\n        wrapper[sizeType] = size\n      }\n    })\n  }\n\n  async function refreshWrapper() {\n    const promises: Promise<void>[] = []\n\n    if (mode.value !== 'vertical') {\n      promises.push(computeWrapperSize('width'))\n    }\n\n    if (mode.value !== 'horizontal') {\n      promises.push(computeWrapperSize('height'))\n    }\n\n    await Promise.all(promises)\n  }\n\n  let timer: ReturnType<typeof setTimeout>\n\n  function computeContentSize() {\n    clearTimeout(timer)\n\n    return new Promise<void>(resolve => {\n      isReady.value = false\n\n      timer = setTimeout(() => {\n        if (!content.el) {\n          resolve()\n          return\n        }\n\n        if (mode.value !== 'vertical') {\n          content.width = content.el.offsetWidth\n\n          if (wrapper.width >= content.width) {\n            x.value = 0\n          } else {\n            if (x.value === 0) {\n              x.value = -scrollX.value\n            }\n          }\n        }\n\n        if (mode.value !== 'horizontal') {\n          content.height = content.el.offsetHeight\n\n          if (wrapper.height >= content.height) {\n            y.value = 0\n          } else {\n            if (y.value === 0) {\n              y.value = -scrollY.value\n            }\n          }\n        }\n\n        setTimeout(() => {\n          isReady.value = true\n          verifyScroll()\n          resolve()\n        }, 1)\n      }, 0)\n    })\n  }\n\n  /**\n   * Will post process the percent scroll values.\n   */\n  function verifyScroll() {\n    if (!isReady.value) {\n      return\n    }\n\n    if (mode.value !== 'vertical') {\n      x.value = Math.min(0, Math.max(x.value, xScrollLimit.value))\n\n      if (mode.value !== 'both') {\n        y.value = 0\n      }\n    }\n\n    if (mode.value !== 'horizontal') {\n      y.value = Math.min(0, Math.max(y.value, yScrollLimit.value))\n\n      if (mode.value !== 'both') {\n        x.value = 0\n      }\n    }\n\n    computePercent()\n    triggerUpdate()\n  }\n\n  function computePercent() {\n    percentX.value = multipleFixed(x.value / (xScrollLimit.value || -1), 100, 2)\n    percentY.value = multipleFixed(y.value / (yScrollLimit.value || -1), 100, 2)\n\n    percentX.value = Math.max(0, Math.min(percentX.value, 100))\n    percentY.value = Math.max(0, Math.min(percentY.value, 100))\n  }\n\n  function handleResize(entity: ResizeObserverEntry) {\n    refresh()\n    onResize?.(entity)\n  }\n\n  let isMounted = false\n\n  onMounted(() => {\n    refresh()\n    isMounted = true\n  })\n\n  async function refresh() {\n    if (typeof onBeforeRefresh === 'function') {\n      onBeforeRefresh()\n    }\n\n    refreshWrapper()\n    await computeContentSize().then(() => {\n      setTimeout(\n        () => {\n          verifyScroll()\n\n          if (typeof onAfterRefresh === 'function') {\n            onAfterRefresh()\n          }\n        },\n        isMounted ? 20 : 100,\n      )\n    })\n  }\n\n  return {\n    wrapperEl,\n    contentEl,\n\n    wrapper,\n    content,\n    isReady,\n    x,\n    y,\n    percentX,\n    percentY,\n    xScrollLimit,\n    yScrollLimit,\n    enableXScroll,\n    enableYScroll,\n    xBarLength,\n    yBarLength,\n\n    handleResize,\n    verifyScroll,\n    computePercent,\n    refresh,\n    triggerUpdate,\n  }\n}\n"],"names":["useScrollWrapper","mode","disabled","width","height","scrollX","scrollY","onResize","onBeforeRefresh","onAfterRefresh","manualRef","triggerUpdate","useManualRef","wrapperEl","ref","contentEl","wrapper","reactive","toNumber","content","x","y","isReady","percentX","percentY","xScrollLimit","computed","yScrollLimit","enableXScroll","enableYScroll","xBarLength","yBarLength","watch","refreshWrapper","computeContentSize","value","verifyScroll","computeWrapperSize","sizeType","nextTick","size","titleCaseSizeType","promises","timer","resolve","computePercent","multipleFixed","handleResize","entity","refresh","isMounted","onMounted"],"mappings":"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"}