mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
Added block height to state and made loop relative to block height and position
This commit is contained in:
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user