75 lines
2.2 KiB
Vue
75 lines
2.2 KiB
Vue
<script setup lang="ts">
|
|
import { ref } from 'vue'
|
|
|
|
const direction = ref<'horizontal' | 'vertical'>('horizontal')
|
|
const splitRatio = ref(50) // percentage for first pane
|
|
const isDragging = ref(false)
|
|
|
|
function toggleDirection() {
|
|
direction.value = direction.value === 'horizontal' ? 'vertical' : 'horizontal'
|
|
}
|
|
|
|
function startDrag(event: MouseEvent) {
|
|
isDragging.value = true
|
|
const container = (event.target as HTMLElement).closest('.split-pane-container') as HTMLElement
|
|
if (!container) return
|
|
|
|
const onMove = (e: MouseEvent) => {
|
|
if (!isDragging.value) return
|
|
const rect = container.getBoundingClientRect()
|
|
if (direction.value === 'horizontal') {
|
|
splitRatio.value = Math.min(80, Math.max(20, ((e.clientX - rect.left) / rect.width) * 100))
|
|
} else {
|
|
splitRatio.value = Math.min(80, Math.max(20, ((e.clientY - rect.top) / rect.height) * 100))
|
|
}
|
|
}
|
|
|
|
const onUp = () => {
|
|
isDragging.value = false
|
|
window.removeEventListener('mousemove', onMove)
|
|
window.removeEventListener('mouseup', onUp)
|
|
}
|
|
|
|
window.addEventListener('mousemove', onMove)
|
|
window.addEventListener('mouseup', onUp)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
class="split-pane-container w-full h-full flex"
|
|
:class="direction === 'horizontal' ? 'flex-row' : 'flex-col'"
|
|
>
|
|
<!-- First pane -->
|
|
<div
|
|
class="overflow-hidden"
|
|
:style="direction === 'horizontal'
|
|
? `width: ${splitRatio}%; flex-shrink: 0`
|
|
: `height: ${splitRatio}%; flex-shrink: 0`"
|
|
>
|
|
<slot name="first" />
|
|
</div>
|
|
|
|
<!-- Divider -->
|
|
<div
|
|
class="bg-gray-700 hover:bg-wraith-500 transition-colors cursor-col-resize shrink-0"
|
|
:class="direction === 'horizontal' ? 'w-1 cursor-col-resize' : 'h-1 cursor-row-resize'"
|
|
@mousedown="startDrag"
|
|
/>
|
|
|
|
<!-- Second pane -->
|
|
<div class="flex-1 overflow-hidden">
|
|
<slot name="second" />
|
|
</div>
|
|
|
|
<!-- Direction toggle button (slot for external control) -->
|
|
<slot name="controls">
|
|
<button
|
|
@click="toggleDirection"
|
|
class="absolute top-2 right-2 text-xs text-gray-600 hover:text-gray-400 z-10"
|
|
title="Toggle split direction"
|
|
>{{ direction === 'horizontal' ? '⇅' : '⇄' }}</button>
|
|
</slot>
|
|
</div>
|
|
</template>
|