Implemented ability to drag blocks

This commit is contained in:
Emir Karabeg
2025-01-11 13:10:00 -08:00
parent 5d23cf8139
commit a59b5bcf3f
2 changed files with 78 additions and 1 deletions

View File

@@ -23,6 +23,7 @@ export default function Workflow() {
const [pan, setPan] = useState({ x: 0, y: 0 })
const [isPanning, setIsPanning] = useState(false)
const [startPanPos, setStartPanPos] = useState({ x: 0, y: 0 })
const [draggedBlock, setDraggedBlock] = useState<string | null>(null)
// Initialize pan position after mount
useEffect(() => {
@@ -178,6 +179,18 @@ export default function Workflow() {
return () => document.removeEventListener('wheel', preventDefaultZoom)
}, [])
// Add this new function to handle block position updates
const updateBlockPosition = useCallback(
(id: string, newPosition: { x: number; y: number }) => {
setBlocks((prevBlocks) =>
prevBlocks.map((block) =>
block.id === id ? { ...block, position: newPosition } : block
)
)
},
[]
)
return (
<div
className="w-full h-[calc(100vh-56px)] overflow-hidden"
@@ -208,6 +221,8 @@ export default function Workflow() {
position={block.position}
config={block.config}
name={`${block.config.toolbar.title} ${index + 1}`}
onPositionUpdate={updateBlockPosition}
zoom={zoom}
/>
))}
</div>

View File

@@ -2,6 +2,7 @@ import { Card } from '@/components/ui/card'
import { BlockConfig, SubBlockConfig } from '../../types/block'
import { cn } from '@/lib/utils'
import { SubBlock } from './sub-block/sub-block'
import { useCallback, useState, MouseEvent, useEffect } from 'react'
export interface WorkflowBlockProps {
id: string
@@ -9,6 +10,8 @@ export interface WorkflowBlockProps {
position: { x: number; y: number }
config: BlockConfig
name: string
onPositionUpdate: (id: string, position: { x: number; y: number }) => void
zoom: number
}
function groupSubBlocks(subBlocks: SubBlockConfig[]) {
@@ -42,7 +45,64 @@ export function WorkflowBlock({
position,
config,
name,
onPositionUpdate,
zoom,
}: WorkflowBlockProps) {
const [isDragging, setIsDragging] = useState(false)
const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 })
const handleMouseDown = useCallback(
(e: MouseEvent) => {
e.stopPropagation()
setIsDragging(true)
// Account for the sidebar width (344px) and control bar height (56px)
const sidebarWidth = 344 // 72px (sidebar) + 272px (toolbar)
const controlBarHeight = 56
const rect = e.currentTarget.getBoundingClientRect()
setDragOffset({
x: (e.clientX - sidebarWidth) / zoom - position.x,
y: (e.clientY - controlBarHeight) / zoom - position.y,
})
},
[zoom, position]
)
const handleMouseMove = useCallback(
(e: MouseEvent) => {
if (isDragging) {
e.stopPropagation()
// Account for the sidebar width and control bar height
const sidebarWidth = 344
const controlBarHeight = 56
const newX = (e.clientX - sidebarWidth) / zoom - dragOffset.x
const newY = (e.clientY - controlBarHeight) / zoom - dragOffset.y
onPositionUpdate(id, { x: newX, y: newY })
}
},
[id, isDragging, dragOffset, onPositionUpdate, zoom]
)
const handleMouseUp = useCallback(() => {
setIsDragging(false)
}, [])
// Add event listeners to handle dragging outside the block
useEffect(() => {
if (isDragging) {
document.addEventListener('mousemove', handleMouseMove as any)
document.addEventListener('mouseup', handleMouseUp)
return () => {
document.removeEventListener('mousemove', handleMouseMove as any)
document.removeEventListener('mouseup', handleMouseUp)
}
}
}, [isDragging, handleMouseMove, handleMouseUp])
const { toolbar, workflow } = config
const subBlockRows = groupSubBlocks(workflow.subBlocks)
@@ -50,12 +110,14 @@ export function WorkflowBlock({
<Card
className={cn(
'absolute w-[320px] shadow-md cursor-move',
'transform -translate-x-1/2 -translate-y-1/2'
'transform -translate-x-1/2 -translate-y-1/2',
isDragging && 'pointer-events-none'
)}
style={{
left: `${position.x}px`,
top: `${position.y}px`,
}}
onMouseDown={handleMouseDown}
>
<div className="flex items-center gap-3 p-3 border-b">
<div