Added block height to state and made loop relative to block height and position

This commit is contained in:
Emir Karabeg
2025-02-11 21:36:52 -08:00
parent 611ed7da15
commit ddfa86641b
4 changed files with 103 additions and 25 deletions
@@ -30,6 +30,7 @@ export function WorkflowBlock({ id, data, selected }: NodeProps<WorkflowBlockPro
// Refs
const blockRef = useRef<HTMLDivElement>(null)
const contentRef = useRef<HTMLDivElement>(null)
const updateNodeInternals = useUpdateNodeInternals()
// Store selectors
@@ -38,16 +39,65 @@ export function WorkflowBlock({ id, data, selected }: NodeProps<WorkflowBlockPro
(state) => state.blocks[id]?.horizontalHandles ?? false
)
const isWide = useWorkflowStore((state) => state.blocks[id]?.isWide ?? false)
const blockHeight = useWorkflowStore((state) => state.blocks[id]?.height ?? 0)
// Store actions
const updateBlockName = useWorkflowStore((state) => state.updateBlockName)
const toggleBlockWide = useWorkflowStore((state) => state.toggleBlockWide)
const updateBlockHeight = useWorkflowStore((state) => state.updateBlockHeight)
// Update node internals when handles change
useEffect(() => {
updateNodeInternals(id)
}, [id, horizontalHandles, updateNodeInternals])
// Add debounce helper
const debounce = (func: Function, wait: number) => {
let timeout: NodeJS.Timeout
return (...args: any[]) => {
clearTimeout(timeout)
timeout = setTimeout(() => func(...args), wait)
}
}
// Add effect to observe size changes with debounced updates
useEffect(() => {
if (!contentRef.current) return
let rafId: number
const debouncedUpdate = debounce((height: number) => {
if (height !== blockHeight) {
updateBlockHeight(id, height)
updateNodeInternals(id)
}
}, 100)
const resizeObserver = new ResizeObserver((entries) => {
// Cancel any pending animation frame
if (rafId) {
cancelAnimationFrame(rafId)
}
// Schedule the update on the next animation frame
rafId = requestAnimationFrame(() => {
for (const entry of entries) {
const height =
entry.borderBoxSize[0]?.blockSize ?? entry.target.getBoundingClientRect().height
debouncedUpdate(height)
}
})
})
resizeObserver.observe(contentRef.current)
return () => {
resizeObserver.disconnect()
if (rafId) {
cancelAnimationFrame(rafId)
}
}
}, [id, blockHeight, updateBlockHeight, updateNodeInternals])
// SubBlock layout management
function groupSubBlocks(subBlocks: SubBlockConfig[]) {
const visibleSubBlocks = subBlocks.filter((block) => !block.hidden)
@@ -185,7 +235,7 @@ export function WorkflowBlock({ id, data, selected }: NodeProps<WorkflowBlockPro
</div>
{/* Block Content */}
<div className="px-4 pt-3 pb-4 space-y-4 cursor-pointer">
<div ref={contentRef} className="px-4 pt-3 pb-4 space-y-4 cursor-pointer">
{subBlockRows.map((row, rowIndex) => (
<div key={`row-${rowIndex}`} className="flex gap-4">
{row.map((subBlock, blockIndex) => (
@@ -34,22 +34,33 @@ function calculateLoopBounds(loop: Loop, blocks: Record<string, any>) {
// Calculate bounds of all blocks in loop
const bound = loopBlocks.reduce(
(acc, block) => {
// Calculate block dimensions
const blockWidth = block.isWide ? 480 : 320
const blockHeight = block.height || 200 // Fallback height if not set
// Update bounds
acc.minX = Math.min(acc.minX, block.position.x)
acc.minY = Math.min(acc.minY, block.position.y)
acc.maxX = Math.max(acc.maxX, block.position.x + (block.isWide ? 480 : 320))
acc.maxY = Math.max(acc.maxY, block.position.y + 200)
acc.maxX = Math.max(acc.maxX, block.position.x + blockWidth)
acc.maxY = Math.max(acc.maxY, block.position.y + blockHeight)
return acc
},
{ minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity }
)
// Add padding around the group
const PADDING = 50
// Add padding around the group with extra bottom padding
const PADDING = {
TOP: 50,
RIGHT: 50,
BOTTOM: 110,
LEFT: 50,
}
return {
x: bound.minX - PADDING,
y: bound.minY - PADDING,
width: bound.maxX - bound.minX + PADDING * 2,
height: bound.maxY - bound.minY + PADDING * 2,
x: bound.minX - PADDING.LEFT,
y: bound.minY - PADDING.TOP,
width: bound.maxX - bound.minX + PADDING.LEFT + PADDING.RIGHT,
height: bound.maxY - bound.minY + PADDING.TOP + PADDING.BOTTOM,
}
}