11import { memo , useCallback , useEffect , useMemo , useRef , useState } from 'react'
22import { useParams } from 'next/navigation'
3- import { Handle , type NodeProps , Position , useUpdateNodeInternals } from 'reactflow'
3+ import { Handle , type NodeProps , Position } from 'reactflow'
44import { Badge } from '@/components/emcn/components/badge/badge'
55import { Tooltip } from '@/components/emcn/components/tooltip/tooltip'
66import { getEnv , isTruthy } from '@/lib/env'
@@ -14,8 +14,7 @@ import { useDisplayName } from '@/hooks/use-display-name'
1414import { usePanelEditorStore } from '@/stores/panel-new/editor/store'
1515import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
1616import { useSubBlockStore } from '@/stores/workflows/subblock/store'
17- import { useWorkflowStore } from '@/stores/workflows/workflow/store'
18- import { useCurrentWorkflow } from '../../hooks'
17+ import { useBlockDimensions , useCurrentWorkflow } from '../../hooks'
1918import { ActionBar , Connections } from './components'
2019import {
2120 useBlockProperties ,
@@ -267,7 +266,6 @@ export const WorkflowBlock = memo(function WorkflowBlock({
267266 const { type, config, name, isPending } = data
268267
269268 const contentRef = useRef < HTMLDivElement > ( null )
270- const updateNodeInternals = useUpdateNodeInternals ( )
271269
272270 const params = useParams ( )
273271 const currentWorkflowId = params . workflowId as string
@@ -368,7 +366,6 @@ export const WorkflowBlock = memo(function WorkflowBlock({
368366 }
369367 } , [ id , collaborativeSetSubblockValue ] )
370368
371- const updateBlockLayoutMetrics = useWorkflowStore ( ( state ) => state . updateBlockLayoutMetrics )
372369 const activeWorkflowId = useWorkflowRegistry ( ( state ) => state . activeWorkflowId )
373370 const setCurrentBlockId = usePanelEditorStore ( ( state ) => state . setCurrentBlockId )
374371 const currentBlockId = usePanelEditorStore ( ( state ) => state . currentBlockId )
@@ -378,14 +375,6 @@ export const WorkflowBlock = memo(function WorkflowBlock({
378375 const isStarterBlock = type === 'starter'
379376 const isWebhookTriggerBlock = type === 'webhook' || type === 'generic_webhook'
380377
381- /**
382- * Update node internals when handles change to ensure ReactFlow
383- * correctly calculates connection points.
384- */
385- useEffect ( ( ) => {
386- updateNodeInternals ( id )
387- } , [ id , horizontalHandles , updateNodeInternals ] )
388-
389378 /**
390379 * Subscribe to this block's subblock values to track changes for conditional rendering
391380 * of subblocks based on their conditions.
@@ -605,51 +594,43 @@ export const WorkflowBlock = memo(function WorkflowBlock({
605594 *
606595 * Width is a fixed 250px for workflow blocks.
607596 */
608- useEffect ( ( ) => {
609- // Only workflow blocks (non-subflow) render here, width is constant
610- const FIXED_WIDTH = 250
611- const HEADER_HEIGHT = 40
612- const CONTENT_PADDING = 16
613- const ROW_HEIGHT = 29
614-
615- const shouldShowDefaultHandles =
616- config . category !== 'triggers' && type !== 'starter' && ! displayTriggerMode
617- const hasContentBelowHeader = subBlockRows . length > 0 || shouldShowDefaultHandles
618-
619- // Count rows based on block type and whether default handles section is shown
620- const defaultHandlesRow = shouldShowDefaultHandles ? 1 : 0
621-
622- let rowsCount = 0
623- if ( type === 'condition' ) {
624- rowsCount = conditionRows . length + defaultHandlesRow
625- } else {
626- const subblockRowCount = subBlockRows . reduce ( ( acc , row ) => acc + row . length , 0 )
627- rowsCount = subblockRowCount + defaultHandlesRow
628- }
629-
630- const contentHeight = hasContentBelowHeader ? CONTENT_PADDING + rowsCount * ROW_HEIGHT : 0
631- const calculatedHeight = Math . max ( HEADER_HEIGHT + contentHeight , 100 )
597+ useBlockDimensions ( {
598+ blockId : id ,
599+ calculateDimensions : ( ) => {
600+ const FIXED_WIDTH = 250
601+ const HEADER_HEIGHT = 40
602+ const CONTENT_PADDING = 16
603+ const ROW_HEIGHT = 29
604+
605+ const shouldShowDefaultHandles =
606+ config . category !== 'triggers' && type !== 'starter' && ! displayTriggerMode
607+ const hasContentBelowHeader = subBlockRows . length > 0 || shouldShowDefaultHandles
608+
609+ // Count rows based on block type and whether default handles section is shown
610+ const defaultHandlesRow = shouldShowDefaultHandles ? 1 : 0
611+
612+ let rowsCount = 0
613+ if ( type === 'condition' ) {
614+ rowsCount = conditionRows . length + defaultHandlesRow
615+ } else {
616+ const subblockRowCount = subBlockRows . reduce ( ( acc , row ) => acc + row . length , 0 )
617+ rowsCount = subblockRowCount + defaultHandlesRow
618+ }
632619
633- const prevHeight =
634- typeof currentStoreBlock ?. height === 'number' ? currentStoreBlock . height : undefined
635- const prevWidth = 250 // fixed across the app for workflow blocks
620+ const contentHeight = hasContentBelowHeader ? CONTENT_PADDING + rowsCount * ROW_HEIGHT : 0
621+ const calculatedHeight = Math . max ( HEADER_HEIGHT + contentHeight , 100 )
636622
637- if ( prevHeight !== calculatedHeight || prevWidth !== FIXED_WIDTH ) {
638- updateBlockLayoutMetrics ( id , { width : FIXED_WIDTH , height : calculatedHeight } )
639- updateNodeInternals ( id )
640- }
641- // eslint-disable-next-line react-hooks/exhaustive-deps
642- } , [
643- id ,
644- type ,
645- config . category ,
646- displayTriggerMode ,
647- subBlockRows . length ,
648- conditionRows . length ,
649- currentStoreBlock ?. height ,
650- updateBlockLayoutMetrics ,
651- updateNodeInternals ,
652- ] )
623+ return { width : FIXED_WIDTH , height : calculatedHeight }
624+ } ,
625+ dependencies : [
626+ type ,
627+ config . category ,
628+ displayTriggerMode ,
629+ subBlockRows . length ,
630+ conditionRows . length ,
631+ horizontalHandles ,
632+ ] ,
633+ } )
653634
654635 const showWebhookIndicator = ( isStarterBlock || isWebhookTriggerBlock ) && isWebhookConfigured
655636 const shouldShowScheduleBadge =
0 commit comments