Feat: Solved the conflict between the Handle click and drag events of the canvas node #3221 (#8413)

### What problem does this PR solve?

Feat: Solved the conflict between the Handle click and drag events of
the canvas node #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-06-23 14:36:01 +08:00
committed by GitHub
parent 83e23f1e8a
commit 81a4c0698c
3 changed files with 38 additions and 21 deletions

View File

@ -11,16 +11,20 @@ import {
DropdownMenuLabel, DropdownMenuLabel,
DropdownMenuTrigger, DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'; } from '@/components/ui/dropdown-menu';
import { IModalProps } from '@/interfaces/common';
import { Operator } from '@/pages/agent/constant'; import { Operator } from '@/pages/agent/constant';
import { AgentInstanceContext, HandleContext } from '@/pages/agent/context'; import { AgentInstanceContext, HandleContext } from '@/pages/agent/context';
import OperatorIcon from '@/pages/agent/operator-icon'; import OperatorIcon from '@/pages/agent/operator-icon';
import { PropsWithChildren, useContext } from 'react'; import { PropsWithChildren, createContext, useContext } from 'react';
type OperatorItemProps = { operators: Operator[] }; type OperatorItemProps = { operators: Operator[] };
const HideModalContext = createContext<IModalProps<any>['showModal']>(() => {});
function OperatorItemList({ operators }: OperatorItemProps) { function OperatorItemList({ operators }: OperatorItemProps) {
const { addCanvasNode } = useContext(AgentInstanceContext); const { addCanvasNode } = useContext(AgentInstanceContext);
const { nodeId, id, type, position } = useContext(HandleContext); const { nodeId, id, type, position } = useContext(HandleContext);
const hideModal = useContext(HideModalContext);
return ( return (
<ul className="space-y-2"> <ul className="space-y-2">
@ -34,6 +38,7 @@ function OperatorItemList({ operators }: OperatorItemProps) {
id, id,
position, position,
})} })}
onSelect={() => hideModal?.()}
> >
<OperatorIcon name={x}></OperatorIcon> <OperatorIcon name={x}></OperatorIcon>
{x} {x}
@ -95,16 +100,21 @@ function AccordionOperators() {
); );
} }
export function NextStepDropdown({ children }: PropsWithChildren) { export function NextStepDropdown({
children,
hideModal,
}: PropsWithChildren & IModalProps<any>) {
return ( return (
<DropdownMenu> <DropdownMenu open onOpenChange={hideModal}>
<DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger> <DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger>
<DropdownMenuContent <DropdownMenuContent
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
className="w-[300px] font-semibold" className="w-[300px] font-semibold"
> >
<DropdownMenuLabel>Next Step</DropdownMenuLabel> <DropdownMenuLabel>Next Step</DropdownMenuLabel>
<HideModalContext.Provider value={hideModal}>
<AccordionOperators></AccordionOperators> <AccordionOperators></AccordionOperators>
</HideModalContext.Provider>
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
); );

View File

@ -1,3 +1,4 @@
import { useSetModalState } from '@/hooks/common-hooks';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { Handle, HandleProps } from '@xyflow/react'; import { Handle, HandleProps } from '@xyflow/react';
import { Plus } from 'lucide-react'; import { Plus } from 'lucide-react';
@ -10,6 +11,8 @@ export function CommonHandle({
nodeId, nodeId,
...props ...props
}: HandleProps & { nodeId: string }) { }: HandleProps & { nodeId: string }) {
const { visible, hideModal, showModal } = useSetModalState();
const value = useMemo( const value = useMemo(
() => ({ () => ({
nodeId, nodeId,
@ -22,7 +25,6 @@ export function CommonHandle({
return ( return (
<HandleContext.Provider value={value}> <HandleContext.Provider value={value}>
<NextStepDropdown>
<Handle <Handle
{...props} {...props}
className={cn( className={cn(
@ -31,11 +33,16 @@ export function CommonHandle({
)} )}
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
showModal();
}} }}
> >
<Plus className="size-3 pointer-events-none" /> <Plus className="size-3 pointer-events-none" />
</Handle> {visible && (
<NextStepDropdown hideModal={hideModal}>
<span></span>
</NextStepDropdown> </NextStepDropdown>
)}
</Handle>
</HandleContext.Provider> </HandleContext.Provider>
); );
} }

View File

@ -6,7 +6,7 @@ import { get } from 'lodash';
import { memo } from 'react'; import { memo } from 'react';
import { NodeHandleId } from '../../constant'; import { NodeHandleId } from '../../constant';
import { CommonHandle } from './handle'; import { CommonHandle } from './handle';
import { LeftHandleStyle, RightHandleStyle } from './handle-icon'; import { LeftHandleStyle } from './handle-icon';
import styles from './index.less'; import styles from './index.less';
import NodeHeader from './node-header'; import NodeHeader from './node-header';
import { NodeWrapper } from './node-wrapper'; import { NodeWrapper } from './node-wrapper';
@ -30,7 +30,7 @@ function InnerMessageNode({
nodeId={id} nodeId={id}
id={NodeHandleId.End} id={NodeHandleId.End}
></CommonHandle> ></CommonHandle>
<CommonHandle {/* <CommonHandle
type="source" type="source"
position={Position.Right} position={Position.Right}
isConnectable={isConnectable} isConnectable={isConnectable}
@ -38,7 +38,7 @@ function InnerMessageNode({
id={NodeHandleId.Start} id={NodeHandleId.Start}
nodeId={id} nodeId={id}
isConnectableEnd={false} isConnectableEnd={false}
></CommonHandle> ></CommonHandle> */}
<NodeHeader <NodeHeader
id={id} id={id}
name={data.name} name={data.name}