From 47dcb1b41fb2fdf991026f2718c6e237685994dd Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Thu, 30 Jun 2022 12:48:42 +0900 Subject: [PATCH] refactor(client): use setup syntax --- packages/client/src/components/form/range.vue | 270 ++++++++---------- 1 file changed, 117 insertions(+), 153 deletions(-) diff --git a/packages/client/src/components/form/range.vue b/packages/client/src/components/form/range.vue index 7ef727d571..d46174acc1 100644 --- a/packages/client/src/components/form/range.vue +++ b/packages/client/src/components/form/range.vue @@ -16,162 +16,126 @@ </div> </template> -<script lang="ts"> -import { computed, defineAsyncComponent, defineComponent, onMounted, onUnmounted, ref, watch } from 'vue'; +<script lang="ts" setup> +import { computed, defineAsyncComponent, onMounted, onUnmounted, ref, watch } from 'vue'; import * as os from '@/os'; -export default defineComponent({ - props: { - modelValue: { - type: Number, - required: false, - default: 0, - }, - disabled: { - type: Boolean, - required: false, - default: false, - }, - min: { - type: Number, - required: false, - default: 0, - }, - max: { - type: Number, - required: false, - default: 100, - }, - step: { - type: Number, - required: false, - default: 1, - }, - autofocus: { - type: Boolean, - required: false, - }, - textConverter: { - type: Function, - required: false, - default: (v) => v.toString(), - }, - }, - - setup(props, context) { - const containerEl = ref<HTMLElement>(); - const thumbEl = ref<HTMLElement>(); - - const rawValue = ref((props.modelValue - props.min) / (props.max - props.min)); - const steppedRawValue = computed(() => { - if (props.step) { - const step = props.step / (props.max - props.min); - return (step * Math.round(rawValue.value / step)); - } else { - return rawValue.value; - } - }); - const finalValue = computed(() => { - if (Number.isInteger(props.step)) { - return Math.round((steppedRawValue.value * (props.max - props.min)) + props.min); - } else { - return (steppedRawValue.value * (props.max - props.min)) + props.min; - } - }); - - const thumbWidth = computed(() => { - if (thumbEl.value == null) return 0; - return thumbEl.value!.offsetWidth; - }); - const thumbPosition = ref(0); - const calcThumbPosition = () => { - if (containerEl.value == null) { - thumbPosition.value = 0; - } else { - thumbPosition.value = (containerEl.value.offsetWidth - thumbWidth.value) * steppedRawValue.value; - } - }; - watch([steppedRawValue, containerEl], calcThumbPosition); - - let ro: ResizeObserver | undefined; - - onMounted(() => { - ro = new ResizeObserver((entries, observer) => { - calcThumbPosition(); - }); - ro.observe(containerEl.value); - }); - - onUnmounted(() => { - if (ro) ro.disconnect(); - }); - - const steps = computed(() => { - if (props.step) { - return (props.max - props.min) / props.step; - } else { - return 0; - } - }); - - const onMousedown = (ev: MouseEvent | TouchEvent) => { - ev.preventDefault(); - - const tooltipShowing = ref(true); - os.popup(defineAsyncComponent(() => import('@/components/ui/tooltip.vue')), { - showing: tooltipShowing, - text: computed(() => { - return props.textConverter(finalValue.value); - }), - targetElement: thumbEl, - }, {}, 'closed'); - - const style = document.createElement('style'); - style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }')); - document.head.appendChild(style); - - const onDrag = (ev: MouseEvent | TouchEvent) => { - ev.preventDefault(); - const containerRect = containerEl.value!.getBoundingClientRect(); - const pointerX = ev.touches && ev.touches.length > 0 ? ev.touches[0].clientX : ev.clientX; - const pointerPositionOnContainer = pointerX - (containerRect.left + (thumbWidth.value / 2)); - rawValue.value = Math.min(1, Math.max(0, pointerPositionOnContainer / (containerEl.value!.offsetWidth - thumbWidth.value))); - }; - - let beforeValue = finalValue.value; - - const onMouseup = () => { - document.head.removeChild(style); - tooltipShowing.value = false; - window.removeEventListener('mousemove', onDrag); - window.removeEventListener('touchmove', onDrag); - window.removeEventListener('mouseup', onMouseup); - window.removeEventListener('touchend', onMouseup); - - // 値が変わってたら通知 - if (beforeValue !== finalValue.value) { - context.emit('update:modelValue', finalValue.value); - } - }; - - window.addEventListener('mousemove', onDrag); - window.addEventListener('touchmove', onDrag); - window.addEventListener('mouseup', onMouseup, { once: true }); - window.addEventListener('touchend', onMouseup, { once: true }); - }; - - return { - rawValue, - finalValue, - steppedRawValue, - onMousedown, - containerEl, - thumbEl, - thumbPosition, - steps, - }; - }, +const props = withDefaults(defineProps<{ + modelValue: number; + disabled?: boolean; + min: number; + max: number; + step?: number; + textConverter?: (value: number) => string, +}>(), { + step: 1, + textConverter: (v) => v.toString(), }); + +const emit = defineEmits<{ + (ev: 'update:modelValue', value: number): void; +}>(); + +const containerEl = ref<HTMLElement>(); +const thumbEl = ref<HTMLElement>(); + +const rawValue = ref((props.modelValue - props.min) / (props.max - props.min)); +const steppedRawValue = computed(() => { + if (props.step) { + const step = props.step / (props.max - props.min); + return (step * Math.round(rawValue.value / step)); + } else { + return rawValue.value; + } +}); +const finalValue = computed(() => { + if (Number.isInteger(props.step)) { + return Math.round((steppedRawValue.value * (props.max - props.min)) + props.min); + } else { + return (steppedRawValue.value * (props.max - props.min)) + props.min; + } +}); + +const thumbWidth = computed(() => { + if (thumbEl.value == null) return 0; + return thumbEl.value!.offsetWidth; +}); +const thumbPosition = ref(0); +const calcThumbPosition = () => { + if (containerEl.value == null) { + thumbPosition.value = 0; + } else { + thumbPosition.value = (containerEl.value.offsetWidth - thumbWidth.value) * steppedRawValue.value; + } +}; +watch([steppedRawValue, containerEl], calcThumbPosition); + +let ro: ResizeObserver | undefined; + +onMounted(() => { + ro = new ResizeObserver((entries, observer) => { + calcThumbPosition(); + }); + ro.observe(containerEl.value); +}); + +onUnmounted(() => { + if (ro) ro.disconnect(); +}); + +const steps = computed(() => { + if (props.step) { + return (props.max - props.min) / props.step; + } else { + return 0; + } +}); + +const onMousedown = (ev: MouseEvent | TouchEvent) => { + ev.preventDefault(); + + const tooltipShowing = ref(true); + os.popup(defineAsyncComponent(() => import('@/components/ui/tooltip.vue')), { + showing: tooltipShowing, + text: computed(() => { + return props.textConverter(finalValue.value); + }), + targetElement: thumbEl, + }, {}, 'closed'); + + const style = document.createElement('style'); + style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }')); + document.head.appendChild(style); + + const onDrag = (ev: MouseEvent | TouchEvent) => { + ev.preventDefault(); + const containerRect = containerEl.value!.getBoundingClientRect(); + const pointerX = ev.touches && ev.touches.length > 0 ? ev.touches[0].clientX : ev.clientX; + const pointerPositionOnContainer = pointerX - (containerRect.left + (thumbWidth.value / 2)); + rawValue.value = Math.min(1, Math.max(0, pointerPositionOnContainer / (containerEl.value!.offsetWidth - thumbWidth.value))); + }; + + let beforeValue = finalValue.value; + + const onMouseup = () => { + document.head.removeChild(style); + tooltipShowing.value = false; + window.removeEventListener('mousemove', onDrag); + window.removeEventListener('touchmove', onDrag); + window.removeEventListener('mouseup', onMouseup); + window.removeEventListener('touchend', onMouseup); + + // 値が変わってたら通知 + if (beforeValue !== finalValue.value) { + emit('update:modelValue', finalValue.value); + } + }; + + window.addEventListener('mousemove', onDrag); + window.addEventListener('touchmove', onDrag); + window.addEventListener('mouseup', onMouseup, { once: true }); + window.addEventListener('touchend', onMouseup, { once: true }); +}; </script> <style lang="scss" scoped>