Files
CodeNomad/packages/ui/src/components/instance/shell/useDrawerResize.ts
Shantur Rathore 8ce7a9b4ee refactor(ui): modularize instance shell
Split InstanceShell2 into focused shell modules (drawer chrome/resize, session context/cache, sidebar, right panel tabs/components) to improve maintainability while preserving behavior.
2026-02-11 08:16:44 +00:00

114 lines
3.3 KiB
TypeScript

import { createSignal, onCleanup, type Accessor, type Setter } from "solid-js"
import { useGlobalPointerDrag } from "./useGlobalPointerDrag"
type DrawerResizeSide = "left" | "right"
type DrawerResizeOptions = {
sessionSidebarWidth: Accessor<number>
rightDrawerWidth: Accessor<number>
setSessionSidebarWidth: Setter<number>
setRightDrawerWidth: Setter<number>
clampLeft: (width: number) => number
clampRight: (width: number) => number
measureDrawerHost: () => void
}
type DrawerResizeApi = {
handleDrawerResizeMouseDown: (side: DrawerResizeSide) => (event: MouseEvent) => void
handleDrawerResizeTouchStart: (side: DrawerResizeSide) => (event: TouchEvent) => void
}
export function useDrawerResize(options: DrawerResizeOptions): DrawerResizeApi {
const [activeResizeSide, setActiveResizeSide] = createSignal<DrawerResizeSide | null>(null)
const [resizeStartX, setResizeStartX] = createSignal(0)
const [resizeStartWidth, setResizeStartWidth] = createSignal(0)
const scheduleDrawerMeasure = () => {
if (typeof window === "undefined") {
options.measureDrawerHost()
return
}
requestAnimationFrame(() => options.measureDrawerHost())
}
const applyDrawerWidth = (side: DrawerResizeSide, width: number) => {
if (side === "left") {
options.setSessionSidebarWidth(width)
} else {
options.setRightDrawerWidth(width)
}
scheduleDrawerMeasure()
}
const handleDrawerPointerMove = (clientX: number) => {
const side = activeResizeSide()
if (!side) return
const startWidth = resizeStartWidth()
const clamp = side === "left" ? options.clampLeft : options.clampRight
const delta = side === "left" ? clientX - resizeStartX() : resizeStartX() - clientX
const nextWidth = clamp(startWidth + delta)
applyDrawerWidth(side, nextWidth)
}
function drawerMouseMove(event: MouseEvent) {
event.preventDefault()
handleDrawerPointerMove(event.clientX)
}
function drawerMouseUp() {
stopDrawerResize()
}
function drawerTouchMove(event: TouchEvent) {
const touch = event.touches[0]
if (!touch) return
event.preventDefault()
handleDrawerPointerMove(touch.clientX)
}
function drawerTouchEnd() {
stopDrawerResize()
}
const drawerPointerDrag = useGlobalPointerDrag({
onMouseMove: drawerMouseMove,
onMouseUp: drawerMouseUp,
onTouchMove: drawerTouchMove,
onTouchEnd: drawerTouchEnd,
})
function stopDrawerResize() {
setActiveResizeSide(null)
drawerPointerDrag.stop()
}
const startDrawerResize = (side: DrawerResizeSide, clientX: number) => {
setActiveResizeSide(side)
setResizeStartX(clientX)
setResizeStartWidth(side === "left" ? options.sessionSidebarWidth() : options.rightDrawerWidth())
drawerPointerDrag.start()
}
const handleDrawerResizeMouseDown = (side: DrawerResizeSide) => (event: MouseEvent) => {
event.preventDefault()
startDrawerResize(side, event.clientX)
}
const handleDrawerResizeTouchStart = (side: DrawerResizeSide) => (event: TouchEvent) => {
const touch = event.touches[0]
if (!touch) return
event.preventDefault()
startDrawerResize(side, touch.clientX)
}
onCleanup(() => {
stopDrawerResize()
})
return {
handleDrawerResizeMouseDown,
handleDrawerResizeTouchStart,
}
}