|
|
@ -1,4 +1,4 @@ |
|
|
import { onUnmounted, ref } from 'vue'; |
|
|
import { onUnmounted } from 'vue'; |
|
|
|
|
|
|
|
|
interface ResizableOptions { |
|
|
interface ResizableOptions { |
|
|
max?: number; |
|
|
max?: number; |
|
|
@ -9,40 +9,70 @@ interface ResizableOptions { |
|
|
export function useResizable(options: ResizableOptions = {}) { |
|
|
export function useResizable(options: ResizableOptions = {}) { |
|
|
const { min = 0, max = 999, onChange } = options; |
|
|
const { min = 0, max = 999, onChange } = options; |
|
|
|
|
|
|
|
|
const isDragging = ref(false); |
|
|
let startX = 0; |
|
|
|
|
|
let startWidth = 0; |
|
|
let cleanup: (() => void) | null = null; |
|
|
let targetTransition = ''; |
|
|
|
|
|
let dragBarTransition = ''; |
|
|
|
|
|
let dragBarOffsetLeft = 0; |
|
|
|
|
|
let dragBarLeft = ''; |
|
|
|
|
|
let dragBarRight = ''; |
|
|
let userSelect = ''; |
|
|
let userSelect = ''; |
|
|
let cursor = ''; |
|
|
let cursor = ''; |
|
|
|
|
|
let cleanup: (() => void) | null = null; |
|
|
|
|
|
|
|
|
|
|
|
const startDrag = ( |
|
|
|
|
|
e: MouseEvent, |
|
|
|
|
|
currentWidth: number, |
|
|
|
|
|
targetElement: HTMLElement | null, |
|
|
|
|
|
dragBarElement: HTMLElement | null, |
|
|
|
|
|
) => { |
|
|
|
|
|
cleanup?.(); |
|
|
|
|
|
|
|
|
const startDrag = (e: MouseEvent, width: number) => { |
|
|
|
|
|
e.preventDefault(); |
|
|
e.preventDefault(); |
|
|
e.stopPropagation(); |
|
|
e.stopPropagation(); |
|
|
|
|
|
|
|
|
isDragging.value = true; |
|
|
if (!dragBarElement || !targetElement) return; |
|
|
const startX = e.clientX; |
|
|
|
|
|
const startWidth = width; |
|
|
startX = e.clientX; |
|
|
|
|
|
startWidth = currentWidth; |
|
|
|
|
|
|
|
|
|
|
|
targetTransition = targetElement.style.transition; |
|
|
|
|
|
dragBarTransition = dragBarElement.style.transition; |
|
|
|
|
|
|
|
|
|
|
|
dragBarOffsetLeft = dragBarElement.offsetLeft; |
|
|
|
|
|
dragBarLeft = dragBarElement.style.left; |
|
|
|
|
|
dragBarRight = dragBarElement.style.right; |
|
|
|
|
|
|
|
|
userSelect = document.body.style.userSelect; |
|
|
userSelect = document.body.style.userSelect; |
|
|
cursor = document.body.style.cursor; |
|
|
cursor = document.body.style.cursor; |
|
|
|
|
|
|
|
|
|
|
|
targetElement.style.transition = 'none'; |
|
|
|
|
|
dragBarElement.style.transition = 'none'; |
|
|
|
|
|
|
|
|
|
|
|
dragBarElement.style.left = `${dragBarOffsetLeft}px`; |
|
|
|
|
|
dragBarElement.style.right = 'auto'; |
|
|
|
|
|
|
|
|
document.body.style.userSelect = 'none'; |
|
|
document.body.style.userSelect = 'none'; |
|
|
document.body.style.cursor = 'col-resize'; |
|
|
document.body.style.cursor = 'col-resize'; |
|
|
|
|
|
|
|
|
const onMouseMove = (moveEvent: MouseEvent) => { |
|
|
const onMouseMove = (moveEvent: MouseEvent) => { |
|
|
if (!isDragging.value) return; |
|
|
|
|
|
|
|
|
|
|
|
const deltaX = moveEvent.clientX - startX; |
|
|
const deltaX = moveEvent.clientX - startX; |
|
|
let newWidth = startWidth + deltaX; |
|
|
const newLeft = dragBarOffsetLeft + deltaX; |
|
|
|
|
|
dragBarElement.style.left = `${newLeft}px`; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const onMouseUp = (upEvent: MouseEvent) => { |
|
|
|
|
|
const deltaX = upEvent.clientX - startX; |
|
|
|
|
|
let newWidth = startWidth + deltaX; |
|
|
newWidth = Math.min(max, Math.max(min, newWidth)); |
|
|
newWidth = Math.min(max, Math.max(min, newWidth)); |
|
|
|
|
|
|
|
|
|
|
|
if (dragBarElement) { |
|
|
|
|
|
dragBarElement.style.left = dragBarLeft; |
|
|
|
|
|
dragBarElement.style.right = dragBarRight; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
onChange?.(newWidth); |
|
|
onChange?.(newWidth); |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const onMouseUp = () => { |
|
|
|
|
|
if (!isDragging.value) return; |
|
|
|
|
|
cleanup?.(); |
|
|
cleanup?.(); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
@ -53,10 +83,18 @@ export function useResizable(options: ResizableOptions = {}) { |
|
|
document.removeEventListener('mousemove', onMouseMove); |
|
|
document.removeEventListener('mousemove', onMouseMove); |
|
|
document.removeEventListener('mouseup', onMouseUp); |
|
|
document.removeEventListener('mouseup', onMouseUp); |
|
|
|
|
|
|
|
|
|
|
|
if (targetElement) { |
|
|
|
|
|
targetElement.style.transition = targetTransition; |
|
|
|
|
|
} |
|
|
|
|
|
if (dragBarElement) { |
|
|
|
|
|
dragBarElement.style.transition = dragBarTransition; |
|
|
|
|
|
dragBarElement.style.left = dragBarLeft; |
|
|
|
|
|
dragBarElement.style.right = dragBarRight; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
document.body.style.userSelect = userSelect; |
|
|
document.body.style.userSelect = userSelect; |
|
|
document.body.style.cursor = cursor; |
|
|
document.body.style.cursor = cursor; |
|
|
|
|
|
|
|
|
isDragging.value = false; |
|
|
|
|
|
cleanup = null; |
|
|
cleanup = null; |
|
|
}; |
|
|
}; |
|
|
}; |
|
|
}; |
|
|
@ -66,7 +104,6 @@ export function useResizable(options: ResizableOptions = {}) { |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
return { |
|
|
return { |
|
|
isDragging, |
|
|
|
|
|
startDrag, |
|
|
startDrag, |
|
|
}; |
|
|
}; |
|
|
} |
|
|
} |
|
|
|