vexip-ui
Version:
A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good
1 lines • 14.3 kB
Source Map (JSON)
{"version":3,"file":"video-progress.vue2.cjs","sources":["../../../components/video/video-progress.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ResizeObserver } from '@/components/resize-observer'\nimport { Slider } from '@/components/slider'\n\nimport { computed, ref } from 'vue'\n\nimport { getStepByWord, useLocale, useNameHelper } from '@vexip-ui/config'\nimport { useListener, useSetTimeout } from '@vexip-ui/hooks'\nimport { boundRange, throttle } from '@vexip-ui/utils'\nimport { formatSeconds } from './helper'\n\nimport type { PropType } from 'vue'\nimport type { SliderExposed } from '@/components/slider'\nimport type { VideoSegment } from './symbol'\n\ninterface PointState {\n start: number,\n startPercent: number,\n end: number,\n endPercent: number,\n duration: number,\n durationPercent: number,\n width: number\n}\n\ndefineOptions({ name: 'VideoProgress' })\n\nconst props = defineProps({\n time: {\n type: Number,\n default: 0,\n },\n duration: {\n type: Number,\n default: 0,\n },\n segments: {\n type: Array as PropType<VideoSegment[]>,\n default: () => [],\n },\n noPreview: {\n type: Boolean,\n default: false,\n },\n previewSrc: {\n type: String,\n default: '',\n },\n})\n\nconst emit = defineEmits(['change'])\n\nconst nh = useNameHelper('video')\nconst locale = useLocale('video')\n\nconst { timer } = useSetTimeout()\n\nconst slidTime = ref(0)\nconst hovered = ref(false)\nconst hoveredTime = ref(0)\nconst indicatorLeft = ref(0)\nconst previewLeft = ref(0)\n\nlet paddingX = [0, 0]\nlet sliderWidth = 100\nlet previewWidth = 60\n\nconst wrapper = ref<HTMLElement>()\nconst slider = ref<SliderExposed>()\nconst sliderEl = computed(() => slider.value?.$el as HTMLElement | undefined)\nconst preview = ref<HTMLElement>()\n\nconst sliding = computed(() => !!slider.value?.sliding[1])\nconst percent = computed(() => {\n return props.duration ? ((sliding.value ? slidTime.value : props.time) / props.duration) * 100 : 0\n})\nconst className = computed(() => {\n return {\n [nh.be('progress')]: true,\n [nh.bem('progress', 'sliding')]: sliding.value,\n [nh.bem('progress', 'disabled')]: props.duration <= 0,\n }\n})\nconst points = computed<PointState[]>(() => {\n const duration = Math.max(1, props.duration)\n\n let times = props.segments.map(segment => segment.time)\n\n if (!times.length) times = [0, duration]\n\n times = times.at(-1) === duration ? times : [...times, duration]\n times = times[0] === 0 ? times : [0, ...times]\n\n const points: PointState[] = []\n\n for (let i = 0, len = times.length - 1; i < len; ++i) {\n const start = times[i]\n const end = times[i + 1]\n const pointDuration = end - start\n\n points.push({\n start,\n startPercent: (start / duration) * 100,\n end,\n endPercent: (end / duration) * 100,\n duration: pointDuration,\n durationPercent: (pointDuration / duration) * 100,\n width: ((end - start) / duration) * 100,\n })\n }\n\n return points\n})\nconst segmentLabel = computed(() => {\n const time = hoveredTime.value\n const segments = props.segments\n\n if (!segments.length) return ''\n\n let index = -1\n\n if (time <= 0) {\n index = 0\n } else {\n for (let i = 1, len = segments.length; i < len; ++i) {\n if (segments[i].time > time) {\n index = i - 1\n break\n }\n }\n }\n\n if (index < 0) {\n index = segments.length - 1\n }\n\n const title = segments[index]?.title || getStepByWord(locale.value.chapterCount, index + 1)\n\n return title && ` (${title})`\n})\n\nuseListener(sliderEl, 'pointerenter', () => {\n clearTimeout(timer.hover)\n\n timer.hover = setTimeout(() => {\n hovered.value = true\n }, 100)\n})\nuseListener(sliderEl, 'pointerleave', () => {\n clearTimeout(timer.hover)\n\n timer.hover = setTimeout(() => {\n hovered.value = false\n }, 100)\n})\nuseListener(\n sliderEl,\n 'pointermove',\n throttle((event: PointerEvent) => {\n if (!sliding.value) {\n processMoveOnTrack(event)\n }\n }),\n)\n\nfunction processMoveOnTrack(event: PointerEvent) {\n if (!sliderEl.value) return\n\n const offsetX = boundRange(\n event.clientX - sliderEl.value.getBoundingClientRect().left,\n 0,\n sliderWidth,\n )\n\n hoveredTime.value = (offsetX / sliderWidth) * props.duration\n indicatorLeft.value = offsetX + paddingX[0]\n previewLeft.value = boundRange(\n offsetX - previewWidth * 0.5 + paddingX[0],\n 0,\n sliderWidth - previewWidth + paddingX[0] + paddingX[1],\n )\n}\n\nfunction onSliderResize(entry: ResizeObserverEntry) {\n if (!wrapper.value) return\n\n const style = getComputedStyle(wrapper.value)\n\n paddingX = [parseFloat(style.paddingLeft), parseFloat(style.paddingRight)]\n sliderWidth = entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width\n}\n\nfunction onPreviewResize(entry: ResizeObserverEntry) {\n previewWidth = entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width\n}\n\nfunction handleChange(permillage: number) {\n emit('change', (permillage / 1000) * props.duration)\n}\n\nconst onSlideMove = throttle(processMoveOnTrack)\n\nfunction onSlideStart() {\n slidTime.value = props.time\n\n document.addEventListener('pointermove', onSlideMove)\n document.addEventListener('pointerup', onSlideEnd)\n}\n\nfunction onSlideEnd() {\n document.removeEventListener('pointermove', onSlideMove)\n document.removeEventListener('pointerup', onSlideEnd)\n}\n</script>\n\n<template>\n <div ref=\"wrapper\" :class=\"className\">\n <ResizeObserver :on-resize=\"onSliderResize\">\n <Slider\n ref=\"slider\"\n :class=\"nh.be('progress-slider')\"\n :value=\"percent * 10\"\n :max=\"1000\"\n :vertical=\"false\"\n :range=\"false\"\n hide-tip\n trigger-fade\n flip-marker\n :disabled=\"duration <= 0\"\n @change=\"handleChange\"\n @pointerdown=\"onSlideStart\"\n >\n <template #filler=\"state\">\n <div\n v-for=\"(point, index) in points\"\n :key=\"index\"\n :class=\"nh.be('progress-segment')\"\n :style=\"{ width: `${point.width}%` }\"\n >\n <div :class=\"nh.be('progress-track')\">\n <div\n :class=\"nh.be('progress-filler')\"\n :style=\"{\n visibility: state.percent[1] < point.startPercent ? 'hidden' : undefined,\n transform: `translateX(${Math.min(\n (Math.max(state.percent[1] - point.startPercent, 0) / point.durationPercent) *\n 100 -\n 100,\n 0\n )}%) translateZ(0)`\n }\"\n ></div>\n </div>\n </div>\n </template>\n <template #trigger>\n <slot name=\"trigger\">\n <div :class=\"nh.be('progress-trigger')\"></div>\n </slot>\n </template>\n </Slider>\n </ResizeObserver>\n <div\n :class=\"{\n [nh.be('progress-indicator')]: true,\n [nh.bem('progress-indicator', 'active')]: hovered && !sliding\n }\"\n :style=\"{ transform: `translateX(${indicatorLeft}px) translateZ(0)` }\"\n ></div>\n <ResizeObserver v-if=\"!noPreview\" :on-resize=\"onPreviewResize\">\n <div\n ref=\"preview\"\n :class=\"{\n [nh.be('preview')]: true,\n [nh.bem('preview', 'has-image')]: previewSrc,\n [nh.bem('preview', 'active')]: hovered || sliding\n }\"\n :style=\"{ transform: `translateX(${previewLeft}px) translateZ(0)` }\"\n >\n <slot name=\"preview\">\n <div v-if=\"previewSrc\" :class=\"nh.be('preview-image')\">\n <img :src=\"previewSrc\" />\n </div>\n <div :class=\"nh.be('preview-time')\">\n {{ formatSeconds(hoveredTime) + segmentLabel }}\n </div>\n </slot>\n </div>\n </ResizeObserver>\n </div>\n</template>\n"],"names":["props","__props","emit","__emit","nh","useNameHelper","locale","useLocale","timer","useSetTimeout","slidTime","ref","hovered","hoveredTime","indicatorLeft","previewLeft","paddingX","sliderWidth","previewWidth","wrapper","slider","sliderEl","computed","_a","preview","sliding","percent","className","points","duration","times","segment","len","start","end","pointDuration","segmentLabel","time","segments","index","i","title","getStepByWord","useListener","throttle","event","processMoveOnTrack","offsetX","boundRange","onSliderResize","entry","style","_b","onPreviewResize","handleChange","permillage","onSlideMove","onSlideStart","onSlideEnd","_createElementBlock","_createVNode","_unref","ResizeObserver","Slider","_normalizeClass","_withCtx","state","_openBlock","_Fragment","_renderList","point","_normalizeStyle","_createElementVNode","_renderSlot","_ctx","_createBlock","_hoisted_1","formatSeconds"],"mappings":"gmBA2BA,MAAMA,EAAQC,EAuBRC,EAAOC,EAEPC,EAAKC,gBAAc,OAAO,EAC1BC,EAASC,YAAU,OAAO,EAE1B,CAAE,MAAAC,CAAM,EAAIC,gBAAc,EAE1BC,EAAWC,MAAI,CAAC,EAChBC,EAAUD,MAAI,EAAK,EACnBE,EAAcF,MAAI,CAAC,EACnBG,EAAgBH,MAAI,CAAC,EACrBI,EAAcJ,MAAI,CAAC,EAErB,IAAAK,EAAW,CAAC,EAAG,CAAC,EAChBC,EAAc,IACdC,EAAe,GAEnB,MAAMC,EAAUR,EAAAA,IAAiB,EAC3BS,EAAST,EAAAA,IAAmB,EAC5BU,EAAWC,EAAA,SAAS,IAAM,OAAA,OAAAC,EAAAH,EAAO,QAAP,YAAAG,EAAc,IAA8B,EACtEC,EAAUb,EAAAA,IAAiB,EAE3Bc,EAAUH,WAAS,WAAM,OAAC,GAACC,EAAAH,EAAO,QAAP,MAAAG,EAAc,QAAQ,IAAE,EACnDG,EAAUJ,EAAAA,SAAS,IAChBtB,EAAM,UAAayB,EAAQ,MAAQf,EAAS,MAAQV,EAAM,MAAQA,EAAM,SAAY,IAAM,CAClG,EACK2B,EAAYL,EAAAA,SAAS,KAClB,CACL,CAAClB,EAAG,GAAG,UAAU,CAAC,EAAG,GACrB,CAACA,EAAG,IAAI,WAAY,SAAS,CAAC,EAAGqB,EAAQ,MACzC,CAACrB,EAAG,IAAI,WAAY,UAAU,CAAC,EAAGJ,EAAM,UAAY,CACtD,EACD,EACK4B,EAASN,EAAAA,SAAuB,IAAM,CAC1C,MAAMO,EAAW,KAAK,IAAI,EAAG7B,EAAM,QAAQ,EAE3C,IAAI8B,EAAQ9B,EAAM,SAAS,IAAI+B,GAAWA,EAAQ,IAAI,EAEjDD,EAAM,SAAgBA,EAAA,CAAC,EAAGD,CAAQ,GAE/BC,EAAAA,EAAM,GAAG,EAAE,IAAMD,EAAWC,EAAQ,CAAC,GAAGA,EAAOD,CAAQ,EACvDC,EAAAA,EAAM,CAAC,IAAM,EAAIA,EAAQ,CAAC,EAAG,GAAGA,CAAK,EAE7C,MAAMF,EAAuB,CAAC,EAErB,QAAA,EAAI,EAAGI,EAAMF,EAAM,OAAS,EAAG,EAAIE,EAAK,EAAE,EAAG,CAC9C,MAAAC,EAAQH,EAAM,CAAC,EACfI,EAAMJ,EAAM,EAAI,CAAC,EACjBK,EAAgBD,EAAMD,EAE5BL,EAAO,KAAK,CACV,MAAAK,EACA,aAAeA,EAAQJ,EAAY,IACnC,IAAAK,EACA,WAAaA,EAAML,EAAY,IAC/B,SAAUM,EACV,gBAAkBA,EAAgBN,EAAY,IAC9C,OAASK,EAAMD,GAASJ,EAAY,GAAA,CACrC,CAAA,CAGID,OAAAA,CAAA,CACR,EACKQ,EAAed,EAAAA,SAAS,IAAM,OAClC,MAAMe,EAAOxB,EAAY,MACnByB,EAAWtC,EAAM,SAEnB,GAAA,CAACsC,EAAS,OAAe,MAAA,GAE7B,IAAIC,EAAQ,GAEZ,GAAIF,GAAQ,EACFE,EAAA,MAEC,SAAAC,EAAI,EAAGR,EAAMM,EAAS,OAAQE,EAAIR,EAAK,EAAEQ,EAChD,GAAIF,EAASE,CAAC,EAAE,KAAOH,EAAM,CAC3BE,EAAQC,EAAI,EACZ,KAAA,CAKFD,EAAQ,IACVA,EAAQD,EAAS,OAAS,GAGtB,MAAAG,IAAQlB,EAAAe,EAASC,CAAK,IAAd,YAAAhB,EAAiB,QAASmB,gBAAcpC,EAAO,MAAM,aAAciC,EAAQ,CAAC,EAEnF,OAAAE,GAAS,KAAKA,CAAK,GAAA,CAC3B,EAEWE,cAAAtB,EAAU,eAAgB,IAAM,CAC1C,aAAab,EAAM,KAAK,EAElBA,EAAA,MAAQ,WAAW,IAAM,CAC7BI,EAAQ,MAAQ,IACf,GAAG,CAAA,CACP,EACW+B,cAAAtB,EAAU,eAAgB,IAAM,CAC1C,aAAab,EAAM,KAAK,EAElBA,EAAA,MAAQ,WAAW,IAAM,CAC7BI,EAAQ,MAAQ,IACf,GAAG,CAAA,CACP,EACD+B,EAAA,YACEtB,EACA,cACAuB,EAAA,SAAUC,GAAwB,CAC3BpB,EAAQ,OACXqB,EAAmBD,CAAK,CAE3B,CAAA,CACH,EAEA,SAASC,EAAmBD,EAAqB,CAC3C,GAAA,CAACxB,EAAS,MAAO,OAErB,MAAM0B,EAAUC,EAAA,WACdH,EAAM,QAAUxB,EAAS,MAAM,sBAAwB,EAAA,KACvD,EACAJ,CACF,EAEYJ,EAAA,MAASkC,EAAU9B,EAAejB,EAAM,SACtCc,EAAA,MAAQiC,EAAU/B,EAAS,CAAC,EAC1CD,EAAY,MAAQiC,EAAA,WAClBD,EAAU7B,EAAe,GAAMF,EAAS,CAAC,EACzC,EACAC,EAAcC,EAAeF,EAAS,CAAC,EAAIA,EAAS,CAAC,CACvD,CAAA,CAGF,SAASiC,EAAeC,EAA4B,SAC9C,GAAA,CAAC/B,EAAQ,MAAO,OAEd,MAAAgC,EAAQ,iBAAiBhC,EAAQ,KAAK,EAEjCH,EAAA,CAAC,WAAWmC,EAAM,WAAW,EAAG,WAAWA,EAAM,YAAY,CAAC,EACzElC,IAAcmC,GAAA7B,EAAA2B,EAAM,gBAAN,YAAA3B,EAAsB,KAAtB,YAAA6B,EAA0B,aAAcF,EAAM,YAAY,KAAA,CAG1E,SAASG,EAAgBH,EAA4B,SACnDhC,IAAekC,GAAA7B,EAAA2B,EAAM,gBAAN,YAAA3B,EAAsB,KAAtB,YAAA6B,EAA0B,aAAcF,EAAM,YAAY,KAAA,CAG3E,SAASI,EAAaC,EAAoB,CACxCrD,EAAK,SAAWqD,EAAa,IAAQvD,EAAM,QAAQ,CAAA,CAG/C,MAAAwD,EAAcZ,WAASE,CAAkB,EAE/C,SAASW,GAAe,CACtB/C,EAAS,MAAQV,EAAM,KAEd,SAAA,iBAAiB,cAAewD,CAAW,EAC3C,SAAA,iBAAiB,YAAaE,CAAU,CAAA,CAGnD,SAASA,GAAa,CACX,SAAA,oBAAoB,cAAeF,CAAW,EAC9C,SAAA,oBAAoB,YAAaE,CAAU,CAAA,6BAKpDC,EAAA,mBAyEM,MAAA,SAzEG,UAAJ,IAAIxC,EAAW,uBAAOQ,EAAS,KAAA,CAAA,GAClCiC,cA4CiBC,EAAA,MAAAC,CAAA,EAAA,CA5CA,YAAWb,GAAc,mBACxC,IA0CS,CA1CTW,cA0CSC,EAAAA,MAAAE,CAAA,EAAA,SAzCH,SAAJ,IAAI3C,EACH,MAAK4C,EAAE,eAAAH,EAAA,MAAEzD,CAAA,EAAC,GAAE,iBAAA,CAAA,EACZ,MAAOsB,EAAO,MAAA,GACd,IAAK,IACL,SAAU,GACV,MAAO,GACR,WAAA,GACA,eAAA,GACA,cAAA,GACC,SAAUzB,EAAQ,UAAA,EAClB,SAAQqD,EACR,cAAaG,CAAA,GAEH,OAAMQ,EAAAA,QAEmBC,GAFZ,EACtBC,EAAAA,UAAA,EAAA,EAAAR,EAoBM,mBAAAS,WAnBqB,KAAAC,EAAA,WAAAzC,EAAA,MAAjB,CAAA0C,EAAO/B,mBADjBoB,EAAA,mBAoBM,MAAA,CAlBH,IAAKpB,EACL,MAAKyB,EAAE,eAAAH,EAAA,MAAEzD,CAAA,EAAC,GAAE,kBAAA,CAAA,EACZ,MAAKmE,iBAAA,CAAA,MAAA,GAAcD,EAAM,KAAK,GAAA,CAAA,CAAA,GAE/BE,EAAAA,mBAaM,MAAA,CAbA,MAAKR,EAAE,eAAAH,EAAA,MAAEzD,CAAA,EAAC,GAAE,gBAAA,CAAA,CAAA,GAChBoE,EAAAA,mBAWO,MAAA,CAVJ,MAAKR,EAAE,eAAAH,EAAA,MAAEzD,CAAA,EAAC,GAAE,iBAAA,CAAA,EACZ,MAAKmE,EAAAA,eAAA,CAAkC,WAAAL,EAAM,QAAO,CAAA,EAAMI,EAAM,sBAA0B,OAAsD,UAAA,cAAA,KAAK,IAA0B,KAAK,IAAIJ,EAAM,QAAa,CAAA,EAAAI,EAAM,aAAmB,CAAA,EAAAA,EAAM,0EAaxO,kBACT,IAEO,CAFPG,EAAAA,WAEOC,sBAFP,IAEO,CADLF,EAAAA,mBAA8C,MAAA,CAAxC,MAAKR,EAAE,eAAAH,EAAA,MAAEzD,CAAA,EAAC,GAAE,kBAAA,CAAA,4DAK1BoE,EAAAA,mBAMO,MAAA,CALJ,MAAKR,EAAAA,eAAA,CAAa,CAAAH,EAAA,MAAAzD,CAAA,EAAG,GAAE,oBAAA,CAAA,EAAA,GAAwC,CAAAyD,EAAA,MAAAzD,CAAA,EAAG,IAAsC,qBAAA,QAAA,CAAA,EAAAQ,EAAA,QAAYa,EAAO,KAAA,GAI3H,gDAAkCX,EAAa,KAAA,mBAAA,CAAA,CAAA,UAE3Bb,EAAS,qDAAhC0E,EAAAA,YAmBiBd,EAAAA,MAAAC,CAAA,EAAA,OAnBkB,YAAWT,CAAA,qBAC5C,IAiBM,CAjBNmB,EAAAA,mBAiBM,MAAA,SAhBA,UAAJ,IAAIhD,EACH,MAAKwC,EAAAA,eAAA,CAAe,CAAAH,EAAA,MAAAzD,CAAA,EAAG,GAAE,SAAA,CAAA,EAAA,IAA+ByD,EAAAA,MAAEzD,CAAA,EAAC,IAAG,UAAA,WAAA,CAAA,EAA2BH,EAAU,WAAa,CAAA4D,EAAA,MAAAzD,CAAA,EAAG,IAA2B,UAAA,QAAA,CAAA,EAAAQ,EAAA,OAAWa,EAAO,KAAA,GAKhK,gDAAkCV,EAAW,KAAA,mBAAA,CAAA,CAAA,GAE9C0D,EAAAA,WAOOC,sBAPP,IAOO,CANMzE,EAAU,0BAArB0D,EAAAA,mBAEM,MAAA,OAFkB,MAAKK,EAAE,eAAAH,EAAA,MAAEzD,CAAA,EAAC,GAAE,eAAA,CAAA,CAAA,GAClCoE,qBAAyB,MAAA,CAAnB,IAAKvE,EAAU,YAAA,KAAA,EAAA2E,CAAA,mCAEvBJ,EAAAA,mBAEM,MAAA,CAFA,MAAKR,EAAE,eAAAH,EAAA,MAAEzD,CAAA,EAAC,GAAE,cAAA,CAAA,CAAA,IACb,gBAAAyD,QAAagB,EAAAA,aAAA,EAAChE,EAAW,KAAA,EAAIuB,EAAY,KAAA,EAAA,CAAA"}