@extclp/vexip-ui
Version:
A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good
1 lines • 12.3 kB
Source Map (JSON)
{"version":3,"file":"captcha-slider.vue2.mjs","sources":["../../../components/captcha/captcha-slider.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { Icon } from '@/components/icon'\nimport { useFieldStore } from '@/components/form'\nimport { Renderer } from '@/components/renderer'\n\nimport { computed, nextTick, ref, watch } from 'vue'\n\nimport {\n createIconProp,\n createSizeProp,\n emitEvent,\n useIcons,\n useLocale,\n useNameHelper,\n useProps\n} from '@vexip-ui/config'\nimport { useMoving, useSetTimeout } from '@vexip-ui/hooks'\nimport { boundRange, toFixed } from '@vexip-ui/utils'\nimport { captchaSliderProps } from './props'\n\nimport type { CaptchaSliderSlots } from './symbol'\n\ndefineOptions({ name: 'CaptchaSlider' })\n\nconst { idFor, labelId, disabled, loading, size, validateField, getFieldValue, setFieldValue } =\n useFieldStore<boolean>(focus)\n\nconst _props = defineProps(captchaSliderProps)\nconst props = useProps('captcha', _props, {\n size: createSizeProp(size),\n target: {\n default: 100,\n validator: value => value >= 0 && value <= 100\n },\n tip: null,\n successTip: null,\n tolerance: {\n default: 1,\n validator: value => value >= 0\n },\n disabled: () => disabled.value,\n loading: () => loading.value,\n loadingIcon: createIconProp(),\n loadingLock: false,\n loadingEffect: null,\n onBeforeTest: {\n default: null,\n isFunc: true\n },\n slots: () => ({})\n})\n\ndefineSlots<CaptchaSliderSlots>()\n\nconst nh = useNameHelper('captcha')\nconst locale = useLocale('captcha')\nconst icons = useIcons()\n\nconst { timer } = useSetTimeout()\n\nconst currentLeft = ref(0)\nconst testing = ref(false)\nconst resetting = ref(false)\nconst isSuccess = ref(false)\nconst testLoading = ref(false)\n\nconst track = ref<HTMLElement>()\n\nconst readonly = computed(() => props.disabled || (props.loading && props.loadingLock))\n\nlet widthLimit: number\n\nconst { target: trigger, moving: dragging } = useMoving({\n onStart: (_, event) => {\n if (\n testing.value ||\n readonly.value ||\n !track.value ||\n !trigger.value ||\n isSuccess.value ||\n resetting.value ||\n event.button > 0\n ) {\n return false\n }\n\n widthLimit = track.value.getBoundingClientRect().width\n currentLeft.value = 0\n verifyPosition()\n trigger.value.focus()\n emitEvent(props.onDragStart, currentLeft.value)\n },\n onMove: state => {\n if (testing.value || readonly.value || isSuccess.value || resetting.value) {\n return false\n }\n\n currentLeft.value = (state.deltaX / widthLimit) * 100\n verifyPosition()\n emitEvent(props.onDrag, currentLeft.value)\n },\n onEnd: async () => {\n if (testing.value || readonly.value) return\n\n testing.value = true\n\n const matched = matchTarget(currentLeft.value)\n let customResult: unknown\n\n if (typeof props.onBeforeTest === 'function') {\n nextTick(() => {\n testLoading.value = true\n })\n customResult = await props.onBeforeTest(currentLeft.value, matched)\n nextTick(() => {\n testLoading.value = false\n })\n }\n\n if (currentLeft.value && (customResult === false || (!matched && customResult !== true))) {\n resetting.value = true\n currentLeft.value = 0\n isSuccess.value = false\n\n setFieldValue(false)\n emitEvent(props.onFail)\n } else if (matched || customResult === true) {\n isSuccess.value = true\n\n if (customResult && !matched) {\n resetting.value = true\n currentLeft.value = props.target\n }\n\n setFieldValue(true)\n emitEvent(props.onSuccess, currentLeft.value)\n }\n\n validateField()\n trigger.value?.blur()\n emitEvent(props.onDragEnd, currentLeft.value)\n\n clearTimeout(timer.testing)\n testing.value = false\n }\n})\n\nconst isLoading = computed(() => props.loading || testLoading.value)\nconst className = computed(() => {\n const baseCls = nh.be('slider')\n\n return {\n [baseCls]: true,\n [nh.bs('vars')]: true,\n [`${baseCls}--success`]: isSuccess.value,\n [`${baseCls}--disabled`]: props.disabled,\n [`${baseCls}--loading`]: isLoading.value,\n [`${baseCls}--${props.size}`]: props.size !== 'default'\n }\n})\nconst fillerStyle = computed(() => {\n return {\n [nh.cv('filler-transition')]: resetting.value ? 'transform 250ms ease' : undefined,\n transform: `scaleX(${currentLeft.value / 100})`\n }\n})\nconst tipStyle = computed(() => {\n return {\n [nh.cv('tip-transition')]: resetting.value ? 'background-position 250ms ease' : undefined,\n backgroundPosition: `-${currentLeft.value}%`\n }\n})\nconst triggerStyle = computed(() => {\n return {\n left: `${currentLeft.value}%`,\n [nh.cv('trigger-transition')]: resetting.value ? 'left 250ms ease' : undefined\n }\n})\n\nwatch(\n () => getFieldValue(),\n value => {\n if (!value) {\n reset()\n } else {\n if (!matchTarget(currentLeft.value)) {\n resetting.value = true\n currentLeft.value = props.target\n }\n\n isSuccess.value = true\n }\n }\n)\nwatch(readonly, value => value && reset())\n\ndefineExpose({\n idFor,\n currentLeft,\n resetting,\n isSuccess,\n dragging,\n isLoading,\n track,\n trigger,\n focus,\n reset\n})\n\nfunction verifyPosition() {\n currentLeft.value = toFixed(boundRange(currentLeft.value, 0, 100), 3)\n}\n\nfunction reset() {\n resetting.value = true\n currentLeft.value = 0\n isSuccess.value = false\n}\n\nfunction afterReset() {\n resetting.value = false\n}\n\nfunction matchTarget(value: number) {\n return Math.abs(props.target - value) <= props.tolerance\n}\n\nfunction focus(options?: FocusOptions) {\n trigger.value?.focus(options)\n}\n</script>\n\n<template>\n <div\n :id=\"idFor\"\n ref=\"wrapper\"\n :class=\"className\"\n tabindex=\"-1\"\n role=\"group\"\n :aria-labelledby=\"labelId\"\n >\n <div\n :class=\"{\n [nh.be('filler')]: true,\n [nh.bem('filler', 'loading')]: isLoading,\n [nh.bem('filler', 'success')]: isSuccess\n }\"\n :style=\"fillerStyle\"\n ></div>\n <div\n :class=\"{\n [nh.be('tip')]: true,\n [nh.bem('tip', 'focused')]: dragging,\n [nh.bem('tip', 'loading')]: isLoading,\n [nh.bem('tip', 'success')]: isSuccess\n }\"\n :style=\"tipStyle\"\n >\n <slot name=\"tip\" :success=\"isSuccess\">\n <Renderer :renderer=\"props.slots.tip\" :data=\"{ success: isSuccess }\">\n {{ isSuccess ? (props.successTip ?? locale.success) : (props.tip ?? locale.slideEnd) }}\n </Renderer>\n </slot>\n </div>\n <div ref=\"track\" :class=\"nh.be('track')\">\n <div\n ref=\"trigger\"\n :class=\"{\n [nh.be('trigger')]: true,\n [nh.bem('trigger', 'focused')]: dragging,\n [nh.bem('trigger', 'loading')]: isLoading,\n [nh.bem('trigger', 'success')]: isSuccess\n }\"\n tabindex=\"0\"\n :style=\"triggerStyle\"\n @transitionend=\"afterReset\"\n >\n <slot name=\"trigger\" :success=\"isSuccess\">\n <Renderer :renderer=\"props.slots.trigger\" :data=\"{ success: isSuccess }\">\n <Icon v-if=\"isSuccess\" v-bind=\"icons.check\"></Icon>\n <Icon\n v-else-if=\"isLoading\"\n v-bind=\"icons.loading\"\n :effect=\"props.loadingEffect || icons.loading.effect\"\n :icon=\"props.loadingIcon || icons.loading.icon\"\n ></Icon>\n <Icon v-else v-bind=\"icons.anglesRight\"></Icon>\n </Renderer>\n </slot>\n </div>\n </div>\n </div>\n</template>\n"],"names":["idFor","labelId","disabled","loading","size","validateField","getFieldValue","setFieldValue","useFieldStore","focus","props","useProps","__props","createSizeProp","value","createIconProp","nh","useNameHelper","locale","useLocale","icons","useIcons","timer","useSetTimeout","currentLeft","ref","testing","resetting","isSuccess","testLoading","track","readonly","computed","widthLimit","trigger","dragging","useMoving","_","event","verifyPosition","emitEvent","state","matched","matchTarget","customResult","nextTick","_a","isLoading","className","baseCls","fillerStyle","tipStyle","triggerStyle","watch","reset","__expose","toFixed","boundRange","afterReset","options"],"mappings":"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"}