@@ -72,6 +72,7 @@ export function ConditionInput({
7272 const hasInitializedRef = useRef ( false )
7373 // Track previous blockId to detect workflow changes
7474 const previousBlockIdRef = useRef < string > ( blockId )
75+ const shouldPersistRef = useRef < boolean > ( false )
7576
7677 // Create default blocks with stable IDs
7778 const createDefaultBlocks = ( ) : ConditionalBlock [ ] => [
@@ -150,35 +151,30 @@ export function ConditionInput({
150151 // If effective value is null, and we've already initialized, keep current state
151152 if ( effectiveValueStr === null ) {
152153 if ( hasInitializedRef . current ) {
153- // We already have blocks, just mark as ready if not already
154154 if ( ! isReady ) setIsReady ( true )
155155 isSyncingFromStoreRef . current = false
156156 return
157157 }
158158
159- // If we haven't initialized yet, set default blocks
160159 setConditionalBlocks ( createDefaultBlocks ( ) )
161160 hasInitializedRef . current = true
162161 setIsReady ( true )
162+ shouldPersistRef . current = false
163163 isSyncingFromStoreRef . current = false
164164 return
165165 }
166166
167- // Skip if the effective value hasn't changed and we're already initialized
168167 if ( effectiveValueStr === prevStoreValueRef . current && hasInitializedRef . current ) {
169168 if ( ! isReady ) setIsReady ( true )
170169 isSyncingFromStoreRef . current = false
171170 return
172171 }
173172
174- // Update the previous store value ref
175173 prevStoreValueRef . current = effectiveValueStr
176174
177- // Parse the effective value
178175 const parsedBlocks = safeParseJSON ( effectiveValueStr )
179176
180177 if ( parsedBlocks ) {
181- // Use the parsed blocks, but ensure titles are correct based on position
182178 const blocksWithCorrectTitles = parsedBlocks . map ( ( block , index ) => ( {
183179 ...block ,
184180 title : index === 0 ? 'if' : index === parsedBlocks . length - 1 ? 'else' : 'else if' ,
@@ -187,14 +183,14 @@ export function ConditionInput({
187183 setConditionalBlocks ( blocksWithCorrectTitles )
188184 hasInitializedRef . current = true
189185 if ( ! isReady ) setIsReady ( true )
186+ shouldPersistRef . current = false
190187 } else if ( ! hasInitializedRef . current ) {
191- // Only set default blocks if we haven't initialized yet
192188 setConditionalBlocks ( createDefaultBlocks ( ) )
193189 hasInitializedRef . current = true
194190 setIsReady ( true )
191+ shouldPersistRef . current = false
195192 }
196193 } finally {
197- // Reset the syncing flag after a short delay
198194 setTimeout ( ( ) => {
199195 isSyncingFromStoreRef . current = false
200196 } , 0 )
@@ -203,18 +199,21 @@ export function ConditionInput({
203199
204200 // Update store whenever conditional blocks change
205201 useEffect ( ( ) => {
206- // Skip if we're currently syncing from store to prevent loops
207- // or if we're not ready yet (still initializing) or in preview mode
208- if ( isSyncingFromStoreRef . current || ! isReady || conditionalBlocks . length === 0 || isPreview )
202+ if (
203+ isSyncingFromStoreRef . current ||
204+ ! isReady ||
205+ conditionalBlocks . length === 0 ||
206+ isPreview ||
207+ ! shouldPersistRef . current
208+ )
209209 return
210210
211211 const newValue = JSON . stringify ( conditionalBlocks )
212212
213- // Only update if the value has actually changed
214213 if ( newValue !== prevStoreValueRef . current ) {
215214 prevStoreValueRef . current = newValue
216215 setStoreValue ( newValue )
217- updateNodeInternals ( ` ${ blockId } - ${ subBlockId } ` )
216+ updateNodeInternals ( blockId )
218217 }
219218 } , [
220219 conditionalBlocks ,
@@ -224,6 +223,15 @@ export function ConditionInput({
224223 updateNodeInternals ,
225224 isReady ,
226225 isPreview ,
226+ } , [
227+ conditionalBlocks ,
228+ blockId ,
229+ subBlockId ,
230+ setStoreValue ,
231+ updateNodeInternals ,
232+ isReady ,
233+ isPreview ,
234+ ] )
227235 ] )
228236
229237 // Cleanup when component unmounts
@@ -341,6 +349,7 @@ export function ConditionInput({
341349 )
342350 const dropPosition = textarea ?. selectionStart ?? 0
343351
352+ shouldPersistRef . current = true
344353 setConditionalBlocks ( ( blocks ) =>
345354 blocks . map ( ( block ) => {
346355 if ( block . id === blockId ) {
@@ -373,6 +382,7 @@ export function ConditionInput({
373382 // Handle tag selection - updated for individual blocks
374383 const handleTagSelect = ( blockId : string , newValue : string ) => {
375384 if ( isPreview || disabled ) return
385+ shouldPersistRef . current = true
376386 setConditionalBlocks ( ( blocks ) =>
377387 blocks . map ( ( block ) =>
378388 block . id === blockId
@@ -390,6 +400,7 @@ export function ConditionInput({
390400 // Handle environment variable selection - updated for individual blocks
391401 const handleEnvVarSelect = ( blockId : string , newValue : string ) => {
392402 if ( isPreview || disabled ) return
403+ shouldPersistRef . current = true
393404 setConditionalBlocks ( ( blocks ) =>
394405 blocks . map ( ( block ) =>
395406 block . id === blockId
@@ -407,6 +418,7 @@ export function ConditionInput({
407418 const handleTagSelectImmediate = ( blockId : string , newValue : string ) => {
408419 if ( isPreview || disabled ) return
409420
421+ shouldPersistRef . current = true
410422 setConditionalBlocks ( ( blocks ) =>
411423 blocks . map ( ( block ) =>
412424 block . id === blockId
@@ -436,6 +448,7 @@ export function ConditionInput({
436448 const handleEnvVarSelectImmediate = ( blockId : string , newValue : string ) => {
437449 if ( isPreview || disabled ) return
438450
451+ shouldPersistRef . current = true
439452 setConditionalBlocks ( ( blocks ) =>
440453 blocks . map ( ( block ) =>
441454 block . id === blockId
@@ -475,13 +488,13 @@ export function ConditionInput({
475488 if ( isPreview || disabled ) return
476489
477490 const blockIndex = conditionalBlocks . findIndex ( ( block ) => block . id === afterId )
491+ if ( conditionalBlocks [ blockIndex ] ?. title === 'else' ) return
478492
479- // Generate a stable ID using the blockId and a timestamp
480493 const newBlockId = generateStableId ( blockId , `else-if-${ Date . now ( ) } ` )
481494
482495 const newBlock : ConditionalBlock = {
483496 id : newBlockId ,
484- title : '' , // Will be set by updateBlockTitles
497+ title : '' ,
485498 value : '' ,
486499 showTags : false ,
487500 showEnvVars : false ,
@@ -492,9 +505,9 @@ export function ConditionInput({
492505
493506 const newBlocks = [ ...conditionalBlocks ]
494507 newBlocks . splice ( blockIndex + 1 , 0 , newBlock )
508+ shouldPersistRef . current = true
495509 setConditionalBlocks ( updateBlockTitles ( newBlocks ) )
496510
497- // Focus the new block's editor after a short delay
498511 setTimeout ( ( ) => {
499512 const textarea : any = containerRef . current ?. querySelector (
500513 `[data-block-id="${ newBlock . id } "] textarea`
@@ -516,13 +529,20 @@ export function ConditionInput({
516529 } )
517530
518531 if ( conditionalBlocks . length === 1 ) return
532+ shouldPersistRef . current = true
519533 setConditionalBlocks ( ( blocks ) => updateBlockTitles ( blocks . filter ( ( block ) => block . id !== id ) ) )
534+
535+ setTimeout ( ( ) => updateNodeInternals ( blockId ) , 0 )
520536 }
521537
522538 const moveBlock = ( id : string , direction : 'up' | 'down' ) => {
523539 if ( isPreview || disabled ) return
524540
525541 const blockIndex = conditionalBlocks . findIndex ( ( block ) => block . id === id )
542+ if ( blockIndex === - 1 ) return
543+
544+ if ( conditionalBlocks [ blockIndex ] ?. title === 'else' ) return
545+
526546 if (
527547 ( direction === 'up' && blockIndex === 0 ) ||
528548 ( direction === 'down' && blockIndex === conditionalBlocks . length - 1 )
@@ -531,11 +551,17 @@ export function ConditionInput({
531551
532552 const newBlocks = [ ...conditionalBlocks ]
533553 const targetIndex = direction === 'up' ? blockIndex - 1 : blockIndex + 1
554+
555+ if ( direction === 'down' && newBlocks [ targetIndex ] ?. title === 'else' ) return
556+
534557 ; [ newBlocks [ blockIndex ] , newBlocks [ targetIndex ] ] = [
535558 newBlocks [ targetIndex ] ,
536559 newBlocks [ blockIndex ] ,
537560 ]
561+ shouldPersistRef . current = true
538562 setConditionalBlocks ( updateBlockTitles ( newBlocks ) )
563+
564+ setTimeout ( ( ) => updateNodeInternals ( blockId ) , 0 )
539565 }
540566
541567 // Add useEffect to handle keyboard events for both dropdowns
@@ -626,7 +652,7 @@ export function ConditionInput({
626652 variant = 'ghost'
627653 size = 'sm'
628654 onClick = { ( ) => addBlock ( block . id ) }
629- disabled = { isPreview || disabled }
655+ disabled = { isPreview || disabled || block . title === 'else' }
630656 className = 'h-8 w-8'
631657 >
632658 < Plus className = 'h-4 w-4' />
@@ -643,7 +669,7 @@ export function ConditionInput({
643669 variant = 'ghost'
644670 size = 'sm'
645671 onClick = { ( ) => moveBlock ( block . id , 'up' ) }
646- disabled = { isPreview || index === 0 || disabled }
672+ disabled = { isPreview || index === 0 || disabled || block . title === 'else' }
647673 className = 'h-8 w-8'
648674 >
649675 < ChevronUp className = 'h-4 w-4' />
@@ -659,7 +685,13 @@ export function ConditionInput({
659685 variant = 'ghost'
660686 size = 'sm'
661687 onClick = { ( ) => moveBlock ( block . id , 'down' ) }
662- disabled = { isPreview || index === conditionalBlocks . length - 1 || disabled }
688+ disabled = {
689+ isPreview ||
690+ disabled ||
691+ index === conditionalBlocks . length - 1 ||
692+ conditionalBlocks [ index + 1 ] ?. title === 'else' ||
693+ block . title === 'else'
694+ }
663695 className = 'h-8 w-8'
664696 >
665697 < ChevronDown className = 'h-4 w-4' />
@@ -723,6 +755,7 @@ export function ConditionInput({
723755 const tagTrigger = checkTagTrigger ( newCode , pos )
724756 const envVarTrigger = checkEnvVarTrigger ( newCode , pos )
725757
758+ shouldPersistRef . current = true
726759 setConditionalBlocks ( ( blocks ) =>
727760 blocks . map ( ( b ) => {
728761 if ( b . id === block . id ) {
0 commit comments