@@ -14,6 +14,7 @@ interface OutputSelectProps {
1414 onOutputSelect : ( outputIds : string [ ] ) => void
1515 disabled ?: boolean
1616 placeholder ?: string
17+ valueMode ?: 'id' | 'label'
1718}
1819
1920export function OutputSelect ( {
@@ -22,6 +23,7 @@ export function OutputSelect({
2223 onOutputSelect,
2324 disabled = false ,
2425 placeholder = 'Select output sources' ,
26+ valueMode = 'id' ,
2527} : OutputSelectProps ) {
2628 const [ isOutputDropdownOpen , setIsOutputDropdownOpen ] = useState ( false )
2729 const dropdownRef = useRef < HTMLDivElement > ( null )
@@ -201,28 +203,31 @@ export function OutputSelect({
201203 return outputs
202204 } , [ workflowBlocks , workflowId , isShowingDiff , isDiffReady , diffWorkflow , blocks , subBlockValues ] )
203205
206+ // Utility to check selected by id or label
207+ const isSelectedValue = ( o : { id : string ; label : string } ) =>
208+ selectedOutputs . includes ( o . id ) || selectedOutputs . includes ( o . label )
209+
204210 // Get selected outputs display text
205211 const selectedOutputsDisplayText = useMemo ( ( ) => {
206212 if ( ! selectedOutputs || selectedOutputs . length === 0 ) {
207213 return placeholder
208214 }
209215
210- // Ensure all selected outputs exist in the workflowOutputs array
211- const validOutputs = selectedOutputs . filter ( ( id ) => workflowOutputs . some ( ( o ) => o . id === id ) )
216+ // Ensure all selected outputs exist in the workflowOutputs array by id or label
217+ const validOutputs = selectedOutputs . filter ( ( val ) =>
218+ workflowOutputs . some ( ( o ) => o . id === val || o . label === val )
219+ )
212220
213221 if ( validOutputs . length === 0 ) {
214222 return placeholder
215223 }
216224
217225 if ( validOutputs . length === 1 ) {
218- const output = workflowOutputs . find ( ( o ) => o . id === validOutputs [ 0 ] )
226+ const output = workflowOutputs . find (
227+ ( o ) => o . id === validOutputs [ 0 ] || o . label === validOutputs [ 0 ]
228+ )
219229 if ( output ) {
220- // Add defensive check for output.blockName
221- const blockNameText =
222- output . blockName && typeof output . blockName === 'string'
223- ? output . blockName . replace ( / \s + / g, '' ) . toLowerCase ( )
224- : `block-${ output . blockId } `
225- return `${ blockNameText } .${ output . path } `
230+ return output . label
226231 }
227232 return placeholder
228233 }
@@ -234,10 +239,14 @@ export function OutputSelect({
234239 const selectedOutputInfo = useMemo ( ( ) => {
235240 if ( ! selectedOutputs || selectedOutputs . length === 0 ) return null
236241
237- const validOutputs = selectedOutputs . filter ( ( id ) => workflowOutputs . some ( ( o ) => o . id === id ) )
242+ const validOutputs = selectedOutputs . filter ( ( val ) =>
243+ workflowOutputs . some ( ( o ) => o . id === val || o . label === val )
244+ )
238245 if ( validOutputs . length === 0 ) return null
239246
240- const output = workflowOutputs . find ( ( o ) => o . id === validOutputs [ 0 ] )
247+ const output = workflowOutputs . find (
248+ ( o ) => o . id === validOutputs [ 0 ] || o . label === validOutputs [ 0 ]
249+ )
241250 if ( ! output ) return null
242251
243252 return {
@@ -355,33 +364,41 @@ export function OutputSelect({
355364 }
356365
357366 let attachedScrollTargets : ( HTMLElement | Window ) [ ] = [ ]
367+ let rafId : number | null = null
358368 if ( isOutputDropdownOpen ) {
359369 updatePosition ( )
360370 window . addEventListener ( 'resize' , updatePosition )
361- // Attach to all scrollable ancestors (including the modal's scroll container)
362371 attachedScrollTargets = getScrollableAncestors ( dropdownRef . current )
363372 attachedScrollTargets . forEach ( ( target ) =>
364373 target . addEventListener ( 'scroll' , updatePosition , { passive : true } )
365374 )
375+ const loop = ( ) => {
376+ updatePosition ( )
377+ rafId = requestAnimationFrame ( loop )
378+ }
379+ rafId = requestAnimationFrame ( loop )
366380 }
367381
368382 return ( ) => {
369383 window . removeEventListener ( 'resize' , updatePosition )
370384 attachedScrollTargets . forEach ( ( target ) =>
371385 target . removeEventListener ( 'scroll' , updatePosition )
372386 )
387+ if ( rafId ) cancelAnimationFrame ( rafId )
373388 }
374389 } , [ isOutputDropdownOpen ] )
375390
376391 // Handle output selection - toggle selection
377392 const handleOutputSelection = ( value : string ) => {
393+ const emittedValue =
394+ valueMode === 'label' ? value : workflowOutputs . find ( ( o ) => o . label === value ) ?. id || value
378395 let newSelectedOutputs : string [ ]
379- const index = selectedOutputs . indexOf ( value )
396+ const index = selectedOutputs . indexOf ( emittedValue )
380397
381398 if ( index === - 1 ) {
382- newSelectedOutputs = [ ...new Set ( [ ...selectedOutputs , value ] ) ]
399+ newSelectedOutputs = [ ...new Set ( [ ...selectedOutputs , emittedValue ] ) ]
383400 } else {
384- newSelectedOutputs = selectedOutputs . filter ( ( id ) => id !== value )
401+ newSelectedOutputs = selectedOutputs . filter ( ( id ) => id !== emittedValue )
385402 }
386403
387404 onOutputSelect ( newSelectedOutputs )
@@ -434,7 +451,7 @@ export function OutputSelect({
434451 ref = { portalRef }
435452 style = { {
436453 position : 'fixed' ,
437- top : portalStyle . top ,
454+ top : portalStyle . top - 1 , // overlap border by 1px to avoid visible gap
438455 left : portalStyle . left ,
439456 width : portalStyle . width ,
440457 zIndex : 2147483647 ,
@@ -462,7 +479,7 @@ export function OutputSelect({
462479 < button
463480 type = 'button'
464481 key = { output . id }
465- onClick = { ( ) => handleOutputSelection ( output . id ) }
482+ onClick = { ( ) => handleOutputSelection ( output . label ) }
466483 className = { cn (
467484 'flex w-full items-center gap-2 px-3 py-1.5 text-left font-normal text-sm' ,
468485 'hover:bg-accent hover:text-accent-foreground' ,
@@ -480,7 +497,7 @@ export function OutputSelect({
480497 </ span >
481498 </ div >
482499 < span className = 'flex-1 truncate' > { output . path } </ span >
483- { selectedOutputs . includes ( output . id ) && (
500+ { isSelectedValue ( output ) && (
484501 < Check className = 'h-4 w-4 flex-shrink-0 text-muted-foreground' />
485502 ) }
486503 </ button >
0 commit comments