Added ability for horizontal ports

This commit is contained in:
Emir Karabeg
2025-01-30 12:56:59 -08:00
parent dc7b00e08b
commit 2dc677b4ff
7 changed files with 70 additions and 7 deletions

View File

@@ -2,11 +2,20 @@ import { EdgeProps, getSmoothStepPath } from 'reactflow'
import { X } from 'lucide-react'
export const CustomEdge = (props: EdgeProps) => {
const isHorizontal =
props.sourcePosition === 'right' || props.sourcePosition === 'left'
// For horizontal handles, we'll add a minimum extension to ensure the path
// always goes outward before going up/down
const [edgePath] = getSmoothStepPath({
sourceX: props.sourceX,
sourceY: props.sourceY,
sourcePosition: props.sourcePosition,
targetX: props.targetX,
targetY: props.targetY,
targetPosition: props.targetPosition,
borderRadius: 8,
offset: isHorizontal ? 30 : 20, // Increased offset for horizontal handles to ensure outward extension
})
const midPoint = {

View File

@@ -1,5 +1,13 @@
import { Button } from '@/components/ui/button'
import { Trash2, Play, Circle, CircleOff, Copy } from 'lucide-react'
import {
Trash2,
Play,
Circle,
CircleOff,
Copy,
ArrowLeftRight,
ArrowUpDown,
} from 'lucide-react'
import { useWorkflowStore } from '@/stores/workflow/workflow-store'
import {
Tooltip,
@@ -17,10 +25,16 @@ export function ActionBar({ blockId }: ActionBarProps) {
const toggleBlockEnabled = useWorkflowStore(
(state) => state.toggleBlockEnabled
)
const toggleBlockHandles = useWorkflowStore(
(state) => state.toggleBlockHandles
)
const duplicateBlock = useWorkflowStore((state) => state.duplicateBlock)
const isEnabled = useWorkflowStore(
(state) => state.blocks[blockId]?.enabled ?? true
)
const horizontalHandles = useWorkflowStore(
(state) => state.blocks[blockId]?.horizontalHandles ?? false
)
return (
<div className="absolute top-0 -right-20 flex flex-col items-center gap-2 p-2 bg-white rounded-md shadow-sm border border-gray-200 animate-in fade-in slide-in-from-left-2">
@@ -75,6 +89,26 @@ export function ActionBar({ blockId }: ActionBarProps) {
<TooltipContent side="right">Duplicate Block</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="sm"
onClick={() => toggleBlockHandles(blockId)}
className="text-gray-500"
>
{horizontalHandles ? (
<ArrowLeftRight className="h-4 w-4" />
) : (
<ArrowUpDown className="h-4 w-4" />
)}
</Button>
</TooltipTrigger>
<TooltipContent side="right">
{horizontalHandles ? 'Vertical Ports' : 'Horizontal Ports'}
</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button

View File

@@ -17,7 +17,7 @@ export function LongInput({
return (
<Textarea
className="w-full resize-none placeholder:text-muted-foreground/50 allow-scroll"
rows={3}
rows={4}
placeholder={placeholder ?? ''}
value={value?.toString() ?? ''}
onChange={(e) => setValue(e.target.value)}

View File

@@ -31,6 +31,9 @@ export function WorkflowBlock({
const isEnabled = useWorkflowStore(
(state) => state.blocks[id]?.enabled ?? true
)
const horizontalHandles = useWorkflowStore(
(state) => state.blocks[id]?.horizontalHandles ?? false
)
function groupSubBlocks(subBlocks: SubBlockConfig[]) {
const rows: SubBlockConfig[][] = []
@@ -70,14 +73,14 @@ export function WorkflowBlock({
<Handle
type="target"
position={Position.Top}
position={horizontalHandles ? Position.Left : Position.Top}
className={cn(
'!w-3.5 !h-3.5',
'!bg-white !rounded-full !border !border-gray-200',
'!opacity-0 group-hover:!opacity-100',
'!transition-opacity !duration-200 !cursor-crosshair',
'hover:!border-blue-500',
'!top-[-7px]'
horizontalHandles ? '!left-[-7px]' : '!top-[-7px]'
)}
/>
@@ -124,14 +127,14 @@ export function WorkflowBlock({
<Handle
type="source"
position={Position.Bottom}
position={horizontalHandles ? Position.Right : Position.Bottom}
className={cn(
'!w-3.5 !h-3.5',
'!bg-white !rounded-full !border !border-gray-200',
'!opacity-0 group-hover:!opacity-100',
'!transition-opacity !duration-200 !cursor-crosshair',
'hover:!border-blue-500',
'!bottom-[-7px]'
horizontalHandles ? '!right-[-7px]' : '!bottom-[-7px]'
)}
/>
</Card>

View File

@@ -15,6 +15,7 @@ export interface BlockState {
subBlocks: Record<string, SubBlockState>
outputs: Record<string, OutputType>
enabled: boolean
horizontalHandles?: boolean
}
export interface SubBlockState {
@@ -45,6 +46,7 @@ export interface WorkflowActions {
updateLastSaved: () => void
toggleBlockEnabled: (id: string) => void
duplicateBlock: (id: string) => void
toggleBlockHandles: (id: string) => void
}
export type WorkflowStore = WorkflowState & WorkflowActions

View File

@@ -211,7 +211,6 @@ const initializeRegistry = () => {
})
}
// Call this in your app's entry point
if (typeof window !== 'undefined') {
initializeRegistry()
}

View File

@@ -242,6 +242,22 @@ export const useWorkflowStore = create<WorkflowStoreWithHistory>()(
pushHistory(set, get, newState, `Duplicate ${block.type} block`)
get().updateLastSaved()
},
toggleBlockHandles: (id: string) => {
const newState = {
blocks: {
...get().blocks,
[id]: {
...get().blocks[id],
horizontalHandles: !get().blocks[id].horizontalHandles,
},
},
edges: [...get().edges],
}
set(newState)
get().updateLastSaved()
},
})),
{ name: 'workflow-store' }
)