mirror of
https://github.com/langgenius/dify.git
synced 2026-02-12 14:04:47 +08:00
- Enhanced `useNodesInteractions` to better manage group node handlers and connections, ensuring accurate identification of leaf nodes and their branches. - Updated logic to create handlers based on node connections, differentiating between internal and external connections. - Refined initial node setup to include target branches for group nodes, improving the overall interaction model for grouped elements.
95 lines
3.1 KiB
TypeScript
95 lines
3.1 KiB
TypeScript
import type { GroupHandler, GroupMember, GroupNodeData } from './types'
|
|
import type { BlockEnum, NodeProps } from '@/app/components/workflow/types'
|
|
import { RiArrowRightSLine } from '@remixicon/react'
|
|
import { memo, useMemo } from 'react'
|
|
import BlockIcon from '@/app/components/workflow/block-icon'
|
|
import { cn } from '@/utils/classnames'
|
|
import { NodeSourceHandle } from '../_base/components/node-handle'
|
|
|
|
const MAX_MEMBER_ICONS = 12
|
|
|
|
const GroupNode = (props: NodeProps<GroupNodeData>) => {
|
|
const { data } = props
|
|
|
|
// show the explicitly passed members first; otherwise use the _children information to fill the type
|
|
const members: GroupMember[] = useMemo(() => (
|
|
data.members?.length
|
|
? data.members
|
|
: data._children?.length
|
|
? data._children.map(child => ({
|
|
id: child.nodeId,
|
|
type: child.nodeType as BlockEnum,
|
|
label: child.nodeType,
|
|
}))
|
|
: []
|
|
), [data._children, data.members])
|
|
|
|
const handlers: GroupHandler[] = useMemo(() => (
|
|
data.handlers?.length
|
|
? data.handlers
|
|
: members.length
|
|
? members.map(member => ({
|
|
id: `${member.id}-source`,
|
|
label: member.label || member.id,
|
|
nodeId: member.id,
|
|
sourceHandle: 'source',
|
|
}))
|
|
: []
|
|
), [data.handlers, members])
|
|
|
|
return (
|
|
<div className="space-y-2 px-3 pb-3">
|
|
{members.length > 0 && (
|
|
<div className="flex items-center gap-1 overflow-hidden">
|
|
<div className="flex flex-wrap items-center gap-1 overflow-hidden">
|
|
{members.slice(0, MAX_MEMBER_ICONS).map(member => (
|
|
<div
|
|
key={member.id}
|
|
className="flex h-7 items-center rounded-full bg-components-input-bg-normal px-1.5 shadow-xs"
|
|
>
|
|
<BlockIcon
|
|
type={member.type}
|
|
size="xs"
|
|
className="!shadow-none"
|
|
/>
|
|
</div>
|
|
))}
|
|
{members.length > MAX_MEMBER_ICONS && (
|
|
<div className="system-xs-medium rounded-full bg-components-input-bg-normal px-2 py-1 text-text-tertiary">
|
|
+
|
|
{members.length - MAX_MEMBER_ICONS}
|
|
</div>
|
|
)}
|
|
</div>
|
|
<RiArrowRightSLine className="ml-auto h-4 w-4 shrink-0 text-text-tertiary" />
|
|
</div>
|
|
)}
|
|
{handlers.length > 0 && (
|
|
<div className="space-y-1">
|
|
{handlers.map(handler => (
|
|
<div
|
|
key={handler.id}
|
|
className={cn(
|
|
'relative',
|
|
'system-sm-semibold uppercase',
|
|
'flex h-9 items-center rounded-md bg-components-panel-on-panel-item-bg px-3 text-text-primary shadow-xs',
|
|
)}
|
|
>
|
|
{handler.label || handler.id}
|
|
<NodeSourceHandle
|
|
{...props}
|
|
handleId={handler.id}
|
|
handleClassName="!top-1/2 !-translate-y-1/2 !-right-[21px]"
|
|
/>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
GroupNode.displayName = 'GroupNode'
|
|
|
|
export default memo(GroupNode)
|