53 lines
2.5 KiB
Vue
53 lines
2.5 KiB
Vue
<script setup lang="ts">
|
|||
|
|
const props = defineProps<{ modelValue: number }>()
|
||
|
|
const emit = defineEmits<{ 'update:modelValue': [value: number] }>()
|
||
|
|
let drag: { pointerId: number; startX: number; startValue: number; width: number } | null = null
|
||
|
|
|
||
|
|
function resize(value: number) {
|
||
|
|
emit('update:modelValue', Math.min(65, Math.max(35, value)))
|
||
|
|
}
|
||
|
|
function startDrag(event: PointerEvent) {
|
||
|
|
if (event.button !== 0 || !event.isPrimary) return
|
||
|
|
const handle = event.currentTarget as HTMLElement
|
||
|
|
const width = (handle.parentElement?.getBoundingClientRect().width ?? 0) - 16
|
||
|
|
if (width <= 0) return
|
||
|
|
event.preventDefault()
|
||
|
|
handle.focus()
|
||
|
|
drag = { pointerId: event.pointerId, startX: event.clientX, startValue: props.modelValue, width }
|
||
|
|
handle.setPointerCapture(event.pointerId)
|
||
|
|
}
|
||
|
|
function moveDrag(event: PointerEvent) {
|
||
|
|
if (!drag || drag.pointerId !== event.pointerId) return
|
||
|
|
resize(drag.startValue + (event.clientX - drag.startX) / drag.width * 100)
|
||
|
|
}
|
||
|
|
function endDrag(event: PointerEvent) {
|
||
|
|
if (drag?.pointerId !== event.pointerId) return
|
||
|
|
drag = null
|
||
|
|
const handle = event.currentTarget as HTMLElement
|
||
|
|
if (handle.hasPointerCapture(event.pointerId)) handle.releasePointerCapture(event.pointerId)
|
||
|
|
}
|
||
|
|
function keyResize(event: KeyboardEvent) {
|
||
|
|
const value = { ArrowLeft: props.modelValue - 2, ArrowRight: props.modelValue + 2, Home: 35, End: 65, Enter: 43 }[event.key]
|
||
|
|
if (value === undefined) return
|
||
|
|
event.preventDefault()
|
||
|
|
resize(value)
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<template>
|
||
|
|
<div class="transfer-pane-divider" role="separator" tabindex="0" aria-label="调整转运信息和换标申请宽度"
|
||
|
|
aria-orientation="vertical" :aria-valuenow="Math.round(modelValue)" :aria-valuemin="35" :aria-valuemax="65"
|
||
|
|
aria-controls="transfer-main-pane transfer-relabel-pane" title="左右拖动调整宽度,双击恢复"
|
||
|
|
@pointerdown="startDrag" @pointermove="moveDrag" @pointerup="endDrag" @pointercancel="endDrag"
|
||
|
|
@lostpointercapture="drag = null" @keydown="keyResize" @dblclick="resize(43)">
|
||
|
|
<span aria-hidden="true" />
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.transfer-pane-divider { display:flex; width:16px; align-items:center; justify-content:center; align-self:stretch; cursor:col-resize; touch-action:none; user-select:none; outline:none; }
|
||
|
|
.transfer-pane-divider span { width:4px; height:64px; border-radius:4px; background:#c5d1e1; transition:background .15s; }
|
||
|
|
.transfer-pane-divider:hover, .transfer-pane-divider:focus-visible { background:#e9f1ff; border-radius:6px; }
|
||
|
|
.transfer-pane-divider:hover span, .transfer-pane-divider:focus-visible span { background:#3478c8; }
|
||
|
|
</style>
|