diff --git a/app/w/[id]/workflow.tsx b/app/w/[id]/workflow.tsx
index 121ba28520..114b0ceb23 100644
--- a/app/w/[id]/workflow.tsx
+++ b/app/w/[id]/workflow.tsx
@@ -178,28 +178,32 @@ function WorkflowCanvas() {
event.preventDefault()
try {
+ const data = JSON.parse(event.dataTransfer.getData('application/json'))
+
+ // Early return if this is a connection block drag
+ if (data.type === 'connectionBlock') {
+ return
+ }
+
const reactFlowBounds = event.currentTarget.getBoundingClientRect()
const position = project({
x: event.clientX - reactFlowBounds.left,
y: event.clientY - reactFlowBounds.top,
})
- const { type } = JSON.parse(
- event.dataTransfer.getData('application/json')
- )
- const blockConfig = getBlock(type)
+ const blockConfig = getBlock(data.type)
if (!blockConfig) {
- console.error('Invalid block type:', type)
+ console.error('Invalid block type:', data.type)
return
}
const id = crypto.randomUUID()
const name = `${blockConfig.toolbar.title} ${
- Object.values(blocks).filter((b) => b.type === type).length + 1
+ Object.values(blocks).filter((b) => b.type === data.type).length + 1
}`
- addBlock(id, type, name, position)
+ addBlock(id, data.type, name, position)
} catch (err) {
console.error('Error dropping block:', err)
}
diff --git a/app/w/components/workflow-block/components/connection-blocks/connection-blocks.tsx b/app/w/components/workflow-block/components/connection-blocks/connection-blocks.tsx
index b8e9243a13..73dd1589f1 100644
--- a/app/w/components/workflow-block/components/connection-blocks/connection-blocks.tsx
+++ b/app/w/components/workflow-block/components/connection-blocks/connection-blocks.tsx
@@ -3,9 +3,13 @@ import { Card } from '@/components/ui/card'
interface ConnectionBlocksProps {
blockId: string
+ setIsConnecting: (isConnecting: boolean) => void
}
-export function ConnectionBlocks({ blockId }: ConnectionBlocksProps) {
+export function ConnectionBlocks({
+ blockId,
+ setIsConnecting,
+}: ConnectionBlocksProps) {
const { incomingConnections, hasIncomingConnections } =
useBlockConnections(blockId)
@@ -13,10 +17,11 @@ export function ConnectionBlocks({ blockId }: ConnectionBlocksProps) {
const handleDragStart = (e: React.DragEvent, connection: any) => {
e.stopPropagation() // Prevent parent drag handlers from firing
+ setIsConnecting(true)
e.dataTransfer.setData(
'application/json',
JSON.stringify({
- type: 'connection',
+ type: 'connectionBlock',
connectionData: {
id: connection.id,
name: connection.name,
@@ -28,6 +33,10 @@ export function ConnectionBlocks({ blockId }: ConnectionBlocksProps) {
e.dataTransfer.effectAllowed = 'copy'
}
+ const handleDragEnd = (e: React.DragEvent) => {
+ setIsConnecting(false)
+ }
+
return (
{incomingConnections.map((connection) => (
@@ -35,6 +44,7 @@ export function ConnectionBlocks({ blockId }: ConnectionBlocksProps) {
key={connection.id}
draggable
onDragStart={(e) => handleDragStart(e, connection)}
+ onDragEnd={handleDragEnd}
className="group flex items-center rounded-lg border bg-card p-2 shadow-sm transition-colors hover:bg-accent/50 cursor-grab active:cursor-grabbing w-fit"
>
diff --git a/app/w/components/workflow-block/components/sub-block/components/short-input.tsx b/app/w/components/workflow-block/components/sub-block/components/short-input.tsx
index 2d3adeae87..d280511bf3 100644
--- a/app/w/components/workflow-block/components/sub-block/components/short-input.tsx
+++ b/app/w/components/workflow-block/components/sub-block/components/short-input.tsx
@@ -1,12 +1,14 @@
import { Input } from '@/components/ui/input'
import { useState, useRef, useEffect } from 'react'
import { useSubBlockValue } from '../hooks/use-sub-block-value'
+import { cn } from '@/lib/utils'
interface ShortInputProps {
placeholder?: string
password?: boolean
blockId: string
subBlockId: string
+ isConnecting: boolean
}
export function ShortInput({
@@ -14,16 +16,12 @@ export function ShortInput({
subBlockId,
placeholder,
password,
+ isConnecting,
}: ShortInputProps) {
const inputRef = useRef
(null)
const [isFocused, setIsFocused] = useState(false)
const [value, setValue] = useSubBlockValue(blockId, subBlockId)
- const displayValue =
- password && !isFocused
- ? '•'.repeat(value?.toString().length ?? 0)
- : value?.toString() ?? ''
-
useEffect(() => {
if (inputRef.current && isFocused) {
const input = inputRef.current
@@ -32,16 +30,49 @@ export function ShortInput({
}
}, [value, isFocused])
+ const handleDrop = (e: React.DragEvent) => {
+ e.preventDefault()
+ try {
+ const data = JSON.parse(e.dataTransfer.getData('application/json'))
+ if (data.type === 'connectionBlock') {
+ const currentValue = value?.toString() ?? ''
+ const newValue =
+ currentValue +
+ data.connectionData.name.replace(' ', '').toLowerCase() +
+ (data.connectionData.outputType === 'any'
+ ? '.res'
+ : `.${data.connectionData.outputType}`)
+ setValue(newValue)
+ }
+ } catch (error) {
+ console.error('Failed to parse drop data:', error)
+ }
+ }
+
+ const handleDragOver = (e: React.DragEvent) => {
+ e.preventDefault() // This is needed to allow drops
+ }
+
+ const displayValue =
+ password && !isFocused
+ ? '•'.repeat(value?.toString().length ?? 0)
+ : value?.toString() ?? ''
+
return (
setValue(e.target.value)}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
+ onDrop={handleDrop}
+ onDragOver={handleDragOver}
autoComplete="off"
/>
)
diff --git a/app/w/components/workflow-block/components/sub-block/sub-block.tsx b/app/w/components/workflow-block/components/sub-block/sub-block.tsx
index c4712031b7..0a2e290bfd 100644
--- a/app/w/components/workflow-block/components/sub-block/sub-block.tsx
+++ b/app/w/components/workflow-block/components/sub-block/sub-block.tsx
@@ -10,9 +10,10 @@ import { Code } from './components/code'
interface SubBlockProps {
blockId: string
config: SubBlockConfig
+ isConnecting: boolean
}
-export function SubBlock({ blockId, config }: SubBlockProps) {
+export function SubBlock({ blockId, config, isConnecting }: SubBlockProps) {
const handleMouseDown = (e: React.MouseEvent) => {
e.stopPropagation()
}
@@ -26,6 +27,7 @@ export function SubBlock({ blockId, config }: SubBlockProps) {
subBlockId={config.id}
placeholder={config.placeholder}
password={config.password}
+ isConnecting={isConnecting}
/>
)
case 'long-input':
diff --git a/app/w/components/workflow-block/workflow-block.tsx b/app/w/components/workflow-block/workflow-block.tsx
index 73e622e1e4..45e87215a9 100644
--- a/app/w/components/workflow-block/workflow-block.tsx
+++ b/app/w/components/workflow-block/workflow-block.tsx
@@ -5,6 +5,7 @@ import { Handle, Position } from 'reactflow'
import { cn } from '@/lib/utils'
import { ActionBar } from './components/action-bar/action-bar'
import { ConnectionBlocks } from './components/connection-blocks/connection-blocks'
+import { useState } from 'react'
interface WorkflowBlockProps {
id: string
@@ -23,6 +24,8 @@ export function WorkflowBlock({
selected,
}: WorkflowBlockProps) {
const { toolbar, workflow } = config
+ // Dragging connection state
+ const [isConnecting, setIsConnecting] = useState(false)
function groupSubBlocks(subBlocks: SubBlockConfig[]) {
const rows: SubBlockConfig[][] = []
@@ -53,7 +56,7 @@ export function WorkflowBlock({
return (
{selected && }
-
+
-
+
))}