Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { ReactElement } from 'react'
import { useEffect, useRef, useState } from 'react'
import { createLogger } from '@sim/logger'
import { ChevronDown, ChevronUp, Plus } from 'lucide-react'
import { ChevronDown, ChevronsUpDown, ChevronUp, Plus } from 'lucide-react'
import { useParams } from 'next/navigation'
import Editor from 'react-simple-code-editor'
import { useUpdateNodeInternals } from 'reactflow'
Expand Down Expand Up @@ -39,6 +39,16 @@ import { useWorkflowStore } from '@/stores/workflows/workflow/store'

const logger = createLogger('ConditionInput')

/**
* Default height for router textareas in pixels
*/
const ROUTER_DEFAULT_HEIGHT_PX = 100

/**
* Minimum height for router textareas in pixels
*/
const ROUTER_MIN_HEIGHT_PX = 80

/**
* Represents a single conditional block (if/else if/else).
*/
Expand Down Expand Up @@ -743,6 +753,61 @@ export function ConditionInput({
}
}, [conditionalBlocks, isRouterMode])

// State for tracking individual router textarea heights
const [routerHeights, setRouterHeights] = useState<{ [key: string]: number }>({})
const isResizing = useRef(false)

/**
* Gets the height for a specific router block, returning default if not set.
*
* @param blockId - ID of the router block
* @returns Height in pixels
*/
const getRouterHeight = (blockId: string): number => {
return routerHeights[blockId] ?? ROUTER_DEFAULT_HEIGHT_PX
}

/**
* Handles mouse-based resize for router textareas.
*
* @param e - Mouse event from the resize handle
* @param blockId - ID of the block being resized
*/
const startRouterResize = (e: React.MouseEvent, blockId: string) => {
if (isPreview || disabled) return
e.preventDefault()
e.stopPropagation()
isResizing.current = true

const startY = e.clientY
const startHeight = getRouterHeight(blockId)

const handleMouseMove = (moveEvent: MouseEvent) => {
if (!isResizing.current) return

const deltaY = moveEvent.clientY - startY
const newHeight = Math.max(ROUTER_MIN_HEIGHT_PX, startHeight + deltaY)

// Update the textarea height directly for smooth resizing
const textarea = inputRefs.current.get(blockId)
if (textarea) {
textarea.style.height = `${newHeight}px`
}

// Update state to keep track
setRouterHeights((prev) => ({ ...prev, [blockId]: newHeight }))
}

const handleMouseUp = () => {
isResizing.current = false
document.removeEventListener('mousemove', handleMouseMove)
document.removeEventListener('mouseup', handleMouseUp)
}

document.addEventListener('mousemove', handleMouseMove)
document.addEventListener('mouseup', handleMouseUp)
}

// Show loading or empty state if not ready or no blocks
if (!isReady || conditionalBlocks.length === 0) {
return (
Expand Down Expand Up @@ -907,10 +972,24 @@ export function ConditionInput({
}}
placeholder='Describe when this route should be taken...'
disabled={disabled || isPreview}
className='min-h-[60px] resize-none rounded-none border-0 px-3 py-2 text-sm placeholder:text-muted-foreground/50 focus-visible:ring-0 focus-visible:ring-offset-0'
rows={2}
className='min-h-[100px] resize-none rounded-none border-0 px-3 py-2 text-sm placeholder:text-muted-foreground/50 focus-visible:ring-0 focus-visible:ring-offset-0'
rows={4}
style={{ height: `${getRouterHeight(block.id)}px` }}
/>

{/* Custom resize handle */}
{!isPreview && !disabled && (
<div
className='absolute right-1 bottom-1 flex h-4 w-4 cursor-ns-resize items-center justify-center rounded-[4px] border border-[var(--border-1)] bg-[var(--surface-5)] dark:bg-[var(--surface-5)]'
onMouseDown={(e) => startRouterResize(e, block.id)}
onDragStart={(e) => {
e.preventDefault()
}}
>
<ChevronsUpDown className='h-3 w-3 text-[var(--text-muted)]' />
</div>
)}

{block.showEnvVars && (
<EnvVarDropdown
visible={block.showEnvVars}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,48 +234,45 @@ export function LongInput({
}, [value])

// Handle resize functionality
const startResize = useCallback(
(e: React.MouseEvent) => {
e.preventDefault()
e.stopPropagation()
isResizing.current = true

const startY = e.clientY
const startHeight = height

const handleMouseMove = (moveEvent: MouseEvent) => {
if (!isResizing.current) return

const deltaY = moveEvent.clientY - startY
const newHeight = Math.max(MIN_HEIGHT_PX, startHeight + deltaY)

if (textareaRef.current && overlayRef.current) {
textareaRef.current.style.height = `${newHeight}px`
overlayRef.current.style.height = `${newHeight}px`
}
if (containerRef.current) {
containerRef.current.style.height = `${newHeight}px`
}
// Keep React state in sync so parent layouts (e.g., Editor) update during drag
setHeight(newHeight)
}
const startResize = (e: React.MouseEvent) => {
e.preventDefault()
e.stopPropagation()
isResizing.current = true

const startY = e.clientY
const startHeight = height

const handleMouseMove = (moveEvent: MouseEvent) => {
if (!isResizing.current) return

const handleMouseUp = () => {
if (textareaRef.current) {
const finalHeight = Number.parseInt(textareaRef.current.style.height, 10) || height
setHeight(finalHeight)
}
const deltaY = moveEvent.clientY - startY
const newHeight = Math.max(MIN_HEIGHT_PX, startHeight + deltaY)

isResizing.current = false
document.removeEventListener('mousemove', handleMouseMove)
document.removeEventListener('mouseup', handleMouseUp)
if (textareaRef.current && overlayRef.current) {
textareaRef.current.style.height = `${newHeight}px`
overlayRef.current.style.height = `${newHeight}px`
}
if (containerRef.current) {
containerRef.current.style.height = `${newHeight}px`
}
// Keep React state in sync so parent layouts (e.g., Editor) update during drag
setHeight(newHeight)
}

document.addEventListener('mousemove', handleMouseMove)
document.addEventListener('mouseup', handleMouseUp)
},
[height]
)
const handleMouseUp = () => {
if (textareaRef.current) {
const finalHeight = Number.parseInt(textareaRef.current.style.height, 10) || height
setHeight(finalHeight)
}

isResizing.current = false
document.removeEventListener('mousemove', handleMouseMove)
document.removeEventListener('mouseup', handleMouseUp)
}

document.addEventListener('mousemove', handleMouseMove)
document.addEventListener('mouseup', handleMouseUp)
}

// Expose wand control handlers to parent via ref
useImperativeHandle(
Expand Down