auto-save 2026-05-14 00:14 (+10, ~3)

This commit is contained in:
2026-05-14 00:14:48 +08:00
parent a1f635564c
commit 6cd0713230
13 changed files with 1948 additions and 25 deletions

View File

@@ -1,32 +1,55 @@
"use client"
import { NodeResizeControl } from "@xyflow/react"
import { type PointerEvent } from "react"
import { useReactFlow } from "@xyflow/react"
/** 节点右边缘 resize 把手:高度跟随节点宽度可拖2401200px。平时透明hover 显紫色细条。 */
/** 节点右边缘 resize 把手:手写 pointer 事件改 node.width自适应 viewport zoom不走 xyflow NodeResizeControl在 glass-node overflow:hidden 下不工作)。 */
export function ResizeRight({ minWidth = 240, maxWidth = 1200 }: { minWidth?: number; maxWidth?: number }) {
const { setNodes, getZoom } = useReactFlow()
const onPointerDown = (e: PointerEvent<HTMLDivElement>) => {
console.log("[ResizeRight] pointerDown", e.clientX, e.clientY)
e.preventDefault()
e.stopPropagation()
const target = e.currentTarget
const nodeEl = target.closest(".react-flow__node") as HTMLElement | null
const nodeId = nodeEl?.getAttribute("data-id")
console.log("[ResizeRight] nodeId", nodeId)
if (!nodeId || !nodeEl) return
target.setPointerCapture(e.pointerId)
const startX = e.clientX
const zoom = getZoom() || 1
const startWidth = parseFloat(getComputedStyle(nodeEl).width) / zoom
const onMove = (ev: globalThis.PointerEvent) => {
const dx = (ev.clientX - startX) / zoom
const next = Math.max(minWidth, Math.min(maxWidth, startWidth + dx))
console.log("[ResizeRight] move", dx, next)
setNodes((nodes) => nodes.map((n) => (n.id === nodeId ? { ...n, width: next, style: { ...n.style, width: next } } : n)))
}
const onUp = () => {
console.log("[ResizeRight] up")
window.removeEventListener("pointermove", onMove)
window.removeEventListener("pointerup", onUp)
try { target.releasePointerCapture(e.pointerId) } catch {}
}
window.addEventListener("pointermove", onMove)
window.addEventListener("pointerup", onUp)
}
return (
<NodeResizeControl
position="right"
minWidth={minWidth}
maxWidth={maxWidth}
<div
onPointerDown={onPointerDown}
title="拖动调整宽度"
className="nodrag absolute z-20 hover:bg-violet-400/60 active:bg-violet-400/80 transition rounded-r"
style={{
background: "transparent",
border: "none",
width: 10,
height: "calc(100% - 24px)", // 留出顶部 source Handle 圆点的 hover 空间
right: 0, // hit area 完全在节点内侧右边 10pxReactFlow wrapper 不允许外溢)
right: 0,
top: 12,
transform: "none",
zIndex: 20, // 高于 ReactFlow handle 默认 z-index
bottom: 12,
width: 6,
cursor: "ew-resize",
touchAction: "none",
}}
>
<div
className="absolute right-0 top-0 h-full w-1 hover:w-1.5 bg-transparent hover:bg-violet-400/70 active:bg-violet-400 transition-all rounded-r"
style={{ cursor: "ew-resize" }}
/>
<div
className="w-full h-full"
style={{ cursor: "ew-resize" }}
/>
</NodeResizeControl>
/>
)
}