@extclp/vexip-ui
Version:
A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good
1 lines • 12.1 kB
Source Map (JSON)
{"version":3,"file":"hooks.mjs","sources":["../../../components/scroll/hooks.ts"],"sourcesContent":["import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'\r\n\r\nimport { useManualRef } from '@vexip-ui/hooks'\r\nimport { multipleFixed, toNumber } from '@vexip-ui/utils'\r\n\r\nimport type { Ref } from 'vue'\r\nimport type { ScrollMode } from './symbol'\r\n\r\nexport function useScrollWrapper({\r\n mode,\r\n disabled,\r\n width,\r\n height,\r\n scrollX,\r\n scrollY,\r\n onResize,\r\n onBeforeRefresh,\r\n onAfterRefresh,\r\n}: {\r\n mode: Ref<Exclude<ScrollMode, 'horizontal-exact'>>,\r\n disabled: Ref<boolean>,\r\n width: Ref<number | string>,\r\n height: Ref<number | string>,\r\n scrollX: Ref<number>,\r\n scrollY: Ref<number>,\r\n onResize?: (entry: ResizeObserverEntry) => void,\r\n onBeforeRefresh?: () => void,\r\n onAfterRefresh?: () => void,\r\n}) {\r\n const { manualRef, triggerUpdate } = useManualRef()\r\n\r\n const wrapperEl = ref<HTMLElement>()\r\n const contentEl = ref<HTMLElement>()\r\n\r\n // 容器长宽\r\n const wrapper = reactive({\r\n el: wrapperEl,\r\n width: toNumber(width.value),\r\n height: toNumber(height.value),\r\n })\r\n\r\n // 内容长宽\r\n const content = reactive({\r\n el: contentEl,\r\n width: 0,\r\n height: 0,\r\n })\r\n\r\n const x = manualRef(-scrollX.value)\r\n const y = manualRef(-scrollY.value)\r\n\r\n const isReady = ref(false)\r\n\r\n const percentX = manualRef(0)\r\n const percentY = manualRef(0)\r\n\r\n const xScrollLimit = computed(() => {\r\n return wrapper.width ? wrapper.width - content.width : 0\r\n })\r\n const yScrollLimit = computed(() => {\r\n return wrapper.height ? wrapper.height - content.height : 0\r\n })\r\n const enableXScroll = computed(() => {\r\n return (\r\n !disabled.value &&\r\n mode.value !== 'vertical' &&\r\n !!wrapper.width &&\r\n content.width - wrapper.width > 1\r\n )\r\n })\r\n const enableYScroll = computed(() => {\r\n return (\r\n !disabled.value &&\r\n mode.value !== 'horizontal' &&\r\n !!wrapper.height &&\r\n content.height - wrapper.height > 1\r\n )\r\n })\r\n const xBarLength = computed(() => {\r\n if (wrapper.width) {\r\n return Math.max(Math.min((wrapper.width / (content.width || 1)) * 100, 99), 5)\r\n }\r\n\r\n return 35\r\n })\r\n const yBarLength = computed(() => {\r\n if (wrapper.height) {\r\n return Math.max(Math.min((wrapper.height / (content.height || 1)) * 100, 99), 5)\r\n }\r\n\r\n return 35\r\n })\r\n\r\n watch(wrapperEl, () => {\r\n refreshWrapper()\r\n })\r\n watch(contentEl, () => {\r\n computeContentSize()\r\n })\r\n watch(scrollX, value => {\r\n x.value = -value\r\n verifyScroll()\r\n })\r\n watch(scrollY, value => {\r\n y.value = -value\r\n verifyScroll()\r\n })\r\n watch(width, () => {\r\n refreshWrapper().then(verifyScroll)\r\n })\r\n watch(height, () => {\r\n refreshWrapper().then(verifyScroll)\r\n })\r\n\r\n function computeWrapperSize(sizeType: 'width' | 'height') {\r\n return nextTick(() => {\r\n if (!wrapper.el) return\r\n\r\n const size = sizeType === 'width' ? width.value : height.value\r\n const titleCaseSizeType = sizeType.slice(0, 1).toUpperCase() + sizeType.slice(1)\r\n\r\n // 获取 wrapper 的 px 大小\r\n if (typeof size === 'string') {\r\n if (!size.endsWith('px') && (!size || Number.isNaN(Number(size)))) {\r\n wrapper[sizeType] =\r\n wrapper.el[`offset${titleCaseSizeType}` as 'offsetWidth' | 'offsetHeight']\r\n } else {\r\n wrapper[sizeType] = parseInt(size)\r\n }\r\n } else {\r\n wrapper[sizeType] = size\r\n }\r\n })\r\n }\r\n\r\n async function refreshWrapper() {\r\n const promises: Promise<void>[] = []\r\n\r\n if (mode.value !== 'vertical') {\r\n promises.push(computeWrapperSize('width'))\r\n }\r\n\r\n if (mode.value !== 'horizontal') {\r\n promises.push(computeWrapperSize('height'))\r\n }\r\n\r\n await Promise.all(promises)\r\n }\r\n\r\n let timer: ReturnType<typeof setTimeout>\r\n\r\n function computeContentSize() {\r\n clearTimeout(timer)\r\n\r\n return new Promise<void>(resolve => {\r\n isReady.value = false\r\n\r\n timer = setTimeout(() => {\r\n if (!content.el) {\r\n resolve()\r\n return\r\n }\r\n\r\n if (mode.value !== 'vertical') {\r\n content.width = content.el.offsetWidth\r\n\r\n if (wrapper.width >= content.width) {\r\n x.value = 0\r\n } else {\r\n if (x.value === 0) {\r\n x.value = -scrollX.value\r\n }\r\n }\r\n }\r\n\r\n if (mode.value !== 'horizontal') {\r\n content.height = content.el.offsetHeight\r\n\r\n if (wrapper.height >= content.height) {\r\n y.value = 0\r\n } else {\r\n if (y.value === 0) {\r\n y.value = -scrollY.value\r\n }\r\n }\r\n }\r\n\r\n setTimeout(() => {\r\n isReady.value = true\r\n verifyScroll()\r\n resolve()\r\n }, 1)\r\n }, 0)\r\n })\r\n }\r\n\r\n /**\r\n * Will post process the percent scroll values.\r\n */\r\n function verifyScroll() {\r\n if (!isReady.value) {\r\n return\r\n }\r\n\r\n if (mode.value !== 'vertical') {\r\n x.value = Math.min(0, Math.max(x.value, xScrollLimit.value))\r\n\r\n if (mode.value !== 'both') {\r\n y.value = 0\r\n }\r\n }\r\n\r\n if (mode.value !== 'horizontal') {\r\n y.value = Math.min(0, Math.max(y.value, yScrollLimit.value))\r\n\r\n if (mode.value !== 'both') {\r\n x.value = 0\r\n }\r\n }\r\n\r\n computePercent()\r\n triggerUpdate()\r\n }\r\n\r\n function computePercent() {\r\n percentX.value = multipleFixed(x.value / (xScrollLimit.value || -1), 100, 2)\r\n percentY.value = multipleFixed(y.value / (yScrollLimit.value || -1), 100, 2)\r\n\r\n percentX.value = Math.max(0, Math.min(percentX.value, 100))\r\n percentY.value = Math.max(0, Math.min(percentY.value, 100))\r\n }\r\n\r\n function handleResize(entity: ResizeObserverEntry) {\r\n refresh()\r\n onResize?.(entity)\r\n }\r\n\r\n let isMounted = false\r\n\r\n onMounted(() => {\r\n refresh()\r\n isMounted = true\r\n })\r\n\r\n async function refresh() {\r\n if (typeof onBeforeRefresh === 'function') {\r\n onBeforeRefresh()\r\n }\r\n\r\n refreshWrapper()\r\n await computeContentSize().then(() => {\r\n setTimeout(\r\n () => {\r\n verifyScroll()\r\n\r\n if (typeof onAfterRefresh === 'function') {\r\n onAfterRefresh()\r\n }\r\n },\r\n isMounted ? 20 : 100,\r\n )\r\n })\r\n }\r\n\r\n return {\r\n wrapperEl,\r\n contentEl,\r\n\r\n wrapper,\r\n content,\r\n isReady,\r\n x,\r\n y,\r\n percentX,\r\n percentY,\r\n xScrollLimit,\r\n yScrollLimit,\r\n enableXScroll,\r\n enableYScroll,\r\n xBarLength,\r\n yBarLength,\r\n\r\n handleResize,\r\n verifyScroll,\r\n computePercent,\r\n refresh,\r\n triggerUpdate,\r\n }\r\n}\r\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":";;;AAQO,SAASA,EAAiB;AAAA,EAC/B,MAAAC;AAAA,EACA,UAAAC;AAAA,EACA,OAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,gBAAAC;AACF,GAUG;AACD,QAAM,EAAE,WAAAC,GAAW,eAAAC,EAAc,IAAIC,EAAa,GAE5CC,IAAYC,EAAiB,GAC7BC,IAAYD,EAAiB,GAG7BE,IAAUC,EAAS;AAAA,IACvB,IAAIJ;AAAA,IACJ,OAAOK,EAASf,EAAM,KAAK;AAAA,IAC3B,QAAQe,EAASd,EAAO,KAAK;AAAA,EAAA,CAC9B,GAGKe,IAAUF,EAAS;AAAA,IACvB,IAAIF;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,EAAA,CACT,GAEKK,IAAIV,EAAU,CAACL,EAAQ,KAAK,GAC5BgB,IAAIX,EAAU,CAACJ,EAAQ,KAAK,GAE5BgB,IAAUR,EAAI,EAAK,GAEnBS,IAAWb,EAAU,CAAC,GACtBc,IAAWd,EAAU,CAAC,GAEtBe,IAAeC,EAAS,MACrBV,EAAQ,QAAQA,EAAQ,QAAQG,EAAQ,QAAQ,CACxD,GACKQ,IAAeD,EAAS,MACrBV,EAAQ,SAASA,EAAQ,SAASG,EAAQ,SAAS,CAC3D,GACKS,IAAgBF,EAAS,MAE3B,CAACxB,EAAS,SACVD,EAAK,UAAU,cACf,CAAC,CAACe,EAAQ,SACVG,EAAQ,QAAQH,EAAQ,QAAQ,CAEnC,GACKa,IAAgBH,EAAS,MAE3B,CAACxB,EAAS,SACVD,EAAK,UAAU,gBACf,CAAC,CAACe,EAAQ,UACVG,EAAQ,SAASH,EAAQ,SAAS,CAErC,GACKc,IAAaJ,EAAS,MACtBV,EAAQ,QACH,KAAK,IAAI,KAAK,IAAKA,EAAQ,SAASG,EAAQ,SAAS,KAAM,KAAK,EAAE,GAAG,CAAC,IAGxE,EACR,GACKY,IAAaL,EAAS,MACtBV,EAAQ,SACH,KAAK,IAAI,KAAK,IAAKA,EAAQ,UAAUG,EAAQ,UAAU,KAAM,KAAK,EAAE,GAAG,CAAC,IAG1E,EACR;AAED,EAAAa,EAAMnB,GAAW,MAAM;AACN,IAAAoB,EAAA;AAAA,EAAA,CAChB,GACDD,EAAMjB,GAAW,MAAM;AACF,IAAAmB,EAAA;AAAA,EAAA,CACpB,GACDF,EAAM3B,GAAS,CAAS8B,MAAA;AACtB,IAAAf,EAAE,QAAQ,CAACe,GACEC,EAAA;AAAA,EAAA,CACd,GACDJ,EAAM1B,GAAS,CAAS6B,MAAA;AACtB,IAAAd,EAAE,QAAQ,CAACc,GACEC,EAAA;AAAA,EAAA,CACd,GACDJ,EAAM7B,GAAO,MAAM;AACF,IAAA8B,EAAA,EAAE,KAAKG,CAAY;AAAA,EAAA,CACnC,GACDJ,EAAM5B,GAAQ,MAAM;AACH,IAAA6B,EAAA,EAAE,KAAKG,CAAY;AAAA,EAAA,CACnC;AAED,WAASC,EAAmBC,GAA8B;AACxD,WAAOC,EAAS,MAAM;AAChB,UAAA,CAACvB,EAAQ,GAAI;AAEjB,YAAMwB,IAAOF,MAAa,UAAUnC,EAAM,QAAQC,EAAO,OACnDqC,IAAoBH,EAAS,MAAM,GAAG,CAAC,EAAE,gBAAgBA,EAAS,MAAM,CAAC;AAG3E,MAAA,OAAOE,KAAS,WACd,CAACA,EAAK,SAAS,IAAI,MAAM,CAACA,KAAQ,OAAO,MAAM,OAAOA,CAAI,CAAC,KAC7DxB,EAAQsB,CAAQ,IACdtB,EAAQ,GAAG,SAASyB,CAAiB,EAAoC,IAEnEzB,EAAAsB,CAAQ,IAAI,SAASE,CAAI,IAGnCxB,EAAQsB,CAAQ,IAAIE;AAAA,IACtB,CACD;AAAA,EAAA;AAGH,iBAAeP,IAAiB;AAC9B,UAAMS,IAA4B,CAAC;AAE/B,IAAAzC,EAAK,UAAU,cACRyC,EAAA,KAAKL,EAAmB,OAAO,CAAC,GAGvCpC,EAAK,UAAU,gBACRyC,EAAA,KAAKL,EAAmB,QAAQ,CAAC,GAGtC,MAAA,QAAQ,IAAIK,CAAQ;AAAA,EAAA;AAGxB,MAAAC;AAEJ,WAAST,IAAqB;AAC5B,wBAAaS,CAAK,GAEX,IAAI,QAAc,CAAWC,MAAA;AAClC,MAAAtB,EAAQ,QAAQ,IAEhBqB,IAAQ,WAAW,MAAM;AACnB,YAAA,CAACxB,EAAQ,IAAI;AACP,UAAAyB,EAAA;AACR;AAAA,QAAA;AAGE,QAAA3C,EAAK,UAAU,eACTkB,EAAA,QAAQA,EAAQ,GAAG,aAEvBH,EAAQ,SAASG,EAAQ,QAC3BC,EAAE,QAAQ,IAENA,EAAE,UAAU,MACZA,EAAA,QAAQ,CAACf,EAAQ,SAKrBJ,EAAK,UAAU,iBACTkB,EAAA,SAASA,EAAQ,GAAG,cAExBH,EAAQ,UAAUG,EAAQ,SAC5BE,EAAE,QAAQ,IAENA,EAAE,UAAU,MACZA,EAAA,QAAQ,CAACf,EAAQ,SAKzB,WAAW,MAAM;AACf,UAAAgB,EAAQ,QAAQ,IACHc,EAAA,GACLQ,EAAA;AAAA,WACP,CAAC;AAAA,SACH,CAAC;AAAA,IAAA,CACL;AAAA,EAAA;AAMH,WAASR,IAAe;AAClB,IAACd,EAAQ,UAITrB,EAAK,UAAU,eACfmB,EAAA,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAIA,EAAE,OAAOK,EAAa,KAAK,CAAC,GAEvDxB,EAAK,UAAU,WACjBoB,EAAE,QAAQ,KAIVpB,EAAK,UAAU,iBACfoB,EAAA,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAIA,EAAE,OAAOM,EAAa,KAAK,CAAC,GAEvD1B,EAAK,UAAU,WACjBmB,EAAE,QAAQ,KAICyB,EAAA,GACDlC,EAAA;AAAA,EAAA;AAGhB,WAASkC,IAAiB;AACf,IAAAtB,EAAA,QAAQuB,EAAc1B,EAAE,SAASK,EAAa,SAAS,KAAK,KAAK,CAAC,GAClED,EAAA,QAAQsB,EAAczB,EAAE,SAASM,EAAa,SAAS,KAAK,KAAK,CAAC,GAElEJ,EAAA,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAIA,EAAS,OAAO,GAAG,CAAC,GACjDC,EAAA,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAIA,EAAS,OAAO,GAAG,CAAC;AAAA,EAAA;AAG5D,WAASuB,EAAaC,GAA6B;AACzC,IAAAC,EAAA,GACR1C,KAAA,QAAAA,EAAWyC;AAAA,EAAM;AAGnB,MAAIE,IAAY;AAEhB,EAAAC,EAAU,MAAM;AACN,IAAAF,EAAA,GACIC,IAAA;AAAA,EAAA,CACb;AAED,iBAAeD,IAAU;AACnB,IAAA,OAAOzC,KAAoB,cACbA,EAAA,GAGHyB,EAAA,GACT,MAAAC,EAAA,EAAqB,KAAK,MAAM;AACpC;AAAA,QACE,MAAM;AACS,UAAAE,EAAA,GAET,OAAO3B,KAAmB,cACbA,EAAA;AAAA,QAEnB;AAAA,QACAyC,IAAY,KAAK;AAAA,MACnB;AAAA,IAAA,CACD;AAAA,EAAA;AAGI,SAAA;AAAA,IACL,WAAArC;AAAA,IACA,WAAAE;AAAA,IAEA,SAAAC;AAAA,IACA,SAAAG;AAAA,IACA,SAAAG;AAAA,IACA,GAAAF;AAAA,IACA,GAAAC;AAAA,IACA,UAAAE;AAAA,IACA,UAAAC;AAAA,IACA,cAAAC;AAAA,IACA,cAAAE;AAAA,IACA,eAAAC;AAAA,IACA,eAAAC;AAAA,IACA,YAAAC;AAAA,IACA,YAAAC;AAAA,IAEA,cAAAgB;AAAA,IACA,cAAAX;AAAA,IACA,gBAAAS;AAAA,IACA,SAAAI;AAAA,IACA,eAAAtC;AAAA,EACF;AACF;"}