element-plus
Version:
A Component Library for Vue 3
1 lines • 4.04 kB
Source Map (JSON)
{"version":3,"file":"use-tab-nav-touch.mjs","names":[],"sources":["../../../../../../../packages/components/tabs/src/composables/use-tab-nav-touch.ts"],"sourcesContent":["import { computed, ref } from 'vue'\nimport { clamp, isUndefined } from 'lodash-unified'\nimport { getClientXY } from '@element-plus/utils'\n\nimport type { ComputedRef, Ref } from 'vue'\n\nexport interface Scrollable {\n next?: boolean\n prev?: number\n}\n\ninterface TouchState {\n startX: number\n startY: number\n startOffset: number\n}\n\nconst TOUCH_SCROLL_THRESHOLD = 5\n\ninterface UseTabNavTouchParams {\n scrollable: Ref<false | Scrollable>\n navOffset: Ref<number>\n navSize: ComputedRef<number>\n navContainerSize: ComputedRef<number>\n isHorizontal: ComputedRef<boolean>\n}\n\nexport const useTabNavTouch = ({\n scrollable,\n navOffset,\n navSize,\n navContainerSize,\n isHorizontal,\n}: UseTabNavTouchParams) => {\n const isTouchScrolling = ref(false)\n const maxOffset = computed(() =>\n Math.max(navSize.value - navContainerSize.value, 0)\n )\n let touchState: TouchState | undefined\n let isMainAxisTouch: boolean | undefined\n\n const handleTouchStart = (event: TouchEvent) => {\n if (!scrollable.value || event.touches.length !== 1) return\n\n const { clientX, clientY } = getClientXY(event)\n touchState = {\n startX: clientX,\n startY: clientY,\n startOffset: navOffset.value,\n }\n isMainAxisTouch = undefined\n }\n\n const handleTouchMove = (event: TouchEvent) => {\n if (!touchState || !scrollable.value) return\n\n if (event.touches.length !== 1) {\n handleTouchEnd()\n return\n }\n\n const { clientX, clientY } = getClientXY(event)\n const deltaX = touchState.startX - clientX\n const deltaY = touchState.startY - clientY\n const mainAxisDelta = isHorizontal.value ? deltaX : deltaY\n const crossAxisDelta = isHorizontal.value ? deltaY : deltaX\n const mainAxisDistance = Math.abs(mainAxisDelta)\n const crossAxisDistance = Math.abs(crossAxisDelta)\n\n if (isUndefined(isMainAxisTouch)) {\n if (\n Math.max(mainAxisDistance, crossAxisDistance) <= TOUCH_SCROLL_THRESHOLD\n ) {\n return\n }\n isMainAxisTouch = mainAxisDistance > crossAxisDistance\n }\n\n if (!isMainAxisTouch) {\n return\n }\n\n const nextOffset = clamp(\n touchState.startOffset + mainAxisDelta,\n 0,\n maxOffset.value\n )\n\n if (\n maxOffset.value <= 0 ||\n nextOffset === navOffset.value ||\n !event.cancelable\n ) {\n return\n }\n\n event.preventDefault()\n isTouchScrolling.value = true\n navOffset.value = nextOffset\n }\n\n const handleTouchEnd = () => {\n touchState = undefined\n isMainAxisTouch = undefined\n isTouchScrolling.value = false\n }\n\n return {\n isTouchScrolling,\n handleTouchStart,\n handleTouchMove,\n handleTouchEnd,\n }\n}\n"],"mappings":";;;;AAiBA,MAAM,yBAAyB;AAU/B,MAAa,kBAAkB,EAC7B,YACA,WACA,SACA,kBACA,mBAC0B;CAC1B,MAAM,mBAAmB,IAAI,MAAM;CACnC,MAAM,YAAY,eAChB,KAAK,IAAI,QAAQ,QAAQ,iBAAiB,OAAO,EAAE,CACpD;CACD,IAAI;CACJ,IAAI;CAEJ,MAAM,oBAAoB,UAAsB;EAC9C,IAAI,CAAC,WAAW,SAAS,MAAM,QAAQ,WAAW,GAAG;EAErD,MAAM,EAAE,SAAS,YAAY,YAAY,MAAM;EAC/C,aAAa;GACX,QAAQ;GACR,QAAQ;GACR,aAAa,UAAU;GACxB;EACD,kBAAkB,KAAA;;CAGpB,MAAM,mBAAmB,UAAsB;EAC7C,IAAI,CAAC,cAAc,CAAC,WAAW,OAAO;EAEtC,IAAI,MAAM,QAAQ,WAAW,GAAG;GAC9B,gBAAgB;GAChB;;EAGF,MAAM,EAAE,SAAS,YAAY,YAAY,MAAM;EAC/C,MAAM,SAAS,WAAW,SAAS;EACnC,MAAM,SAAS,WAAW,SAAS;EACnC,MAAM,gBAAgB,aAAa,QAAQ,SAAS;EACpD,MAAM,iBAAiB,aAAa,QAAQ,SAAS;EACrD,MAAM,mBAAmB,KAAK,IAAI,cAAc;EAChD,MAAM,oBAAoB,KAAK,IAAI,eAAe;EAElD,IAAI,YAAY,gBAAgB,EAAE;GAChC,IACE,KAAK,IAAI,kBAAkB,kBAAkB,IAAI,wBAEjD;GAEF,kBAAkB,mBAAmB;;EAGvC,IAAI,CAAC,iBACH;EAGF,MAAM,aAAa,MACjB,WAAW,cAAc,eACzB,GACA,UAAU,MACX;EAED,IACE,UAAU,SAAS,KACnB,eAAe,UAAU,SACzB,CAAC,MAAM,YAEP;EAGF,MAAM,gBAAgB;EACtB,iBAAiB,QAAQ;EACzB,UAAU,QAAQ;;CAGpB,MAAM,uBAAuB;EAC3B,aAAa,KAAA;EACb,kBAAkB,KAAA;EAClB,iBAAiB,QAAQ;;CAG3B,OAAO;EACL;EACA;EACA;EACA;EACD"}