### 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)tags/v0.20.0
| @@ -11,16 +11,20 @@ import { | |||
| DropdownMenuLabel, | |||
| DropdownMenuTrigger, | |||
| } from '@/components/ui/dropdown-menu'; | |||
| import { IModalProps } from '@/interfaces/common'; | |||
| import { Operator } from '@/pages/agent/constant'; | |||
| import { AgentInstanceContext, HandleContext } from '@/pages/agent/context'; | |||
| import OperatorIcon from '@/pages/agent/operator-icon'; | |||
| import { PropsWithChildren, useContext } from 'react'; | |||
| import { PropsWithChildren, createContext, useContext } from 'react'; | |||
| type OperatorItemProps = { operators: Operator[] }; | |||
| const HideModalContext = createContext<IModalProps<any>['showModal']>(() => {}); | |||
| function OperatorItemList({ operators }: OperatorItemProps) { | |||
| const { addCanvasNode } = useContext(AgentInstanceContext); | |||
| const { nodeId, id, type, position } = useContext(HandleContext); | |||
| const hideModal = useContext(HideModalContext); | |||
| return ( | |||
| <ul className="space-y-2"> | |||
| @@ -34,6 +38,7 @@ function OperatorItemList({ operators }: OperatorItemProps) { | |||
| id, | |||
| position, | |||
| })} | |||
| onSelect={() => hideModal?.()} | |||
| > | |||
| <OperatorIcon name={x}></OperatorIcon> | |||
| {x} | |||
| @@ -95,16 +100,21 @@ function AccordionOperators() { | |||
| ); | |||
| } | |||
| export function NextStepDropdown({ children }: PropsWithChildren) { | |||
| export function NextStepDropdown({ | |||
| children, | |||
| hideModal, | |||
| }: PropsWithChildren & IModalProps<any>) { | |||
| return ( | |||
| <DropdownMenu> | |||
| <DropdownMenu open onOpenChange={hideModal}> | |||
| <DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger> | |||
| <DropdownMenuContent | |||
| onClick={(e) => e.stopPropagation()} | |||
| className="w-[300px] font-semibold" | |||
| > | |||
| <DropdownMenuLabel>Next Step</DropdownMenuLabel> | |||
| <AccordionOperators></AccordionOperators> | |||
| <HideModalContext.Provider value={hideModal}> | |||
| <AccordionOperators></AccordionOperators> | |||
| </HideModalContext.Provider> | |||
| </DropdownMenuContent> | |||
| </DropdownMenu> | |||
| ); | |||
| @@ -1,3 +1,4 @@ | |||
| import { useSetModalState } from '@/hooks/common-hooks'; | |||
| import { cn } from '@/lib/utils'; | |||
| import { Handle, HandleProps } from '@xyflow/react'; | |||
| import { Plus } from 'lucide-react'; | |||
| @@ -10,6 +11,8 @@ export function CommonHandle({ | |||
| nodeId, | |||
| ...props | |||
| }: HandleProps & { nodeId: string }) { | |||
| const { visible, hideModal, showModal } = useSetModalState(); | |||
| const value = useMemo( | |||
| () => ({ | |||
| nodeId, | |||
| @@ -22,20 +25,24 @@ export function CommonHandle({ | |||
| return ( | |||
| <HandleContext.Provider value={value}> | |||
| <NextStepDropdown> | |||
| <Handle | |||
| {...props} | |||
| className={cn( | |||
| 'inline-flex justify-center items-center !bg-background-checked !size-4 !rounded-sm !border-none ', | |||
| className, | |||
| )} | |||
| onClick={(e) => { | |||
| e.stopPropagation(); | |||
| }} | |||
| > | |||
| <Plus className="size-3 pointer-events-none" /> | |||
| </Handle> | |||
| </NextStepDropdown> | |||
| <Handle | |||
| {...props} | |||
| className={cn( | |||
| 'inline-flex justify-center items-center !bg-background-checked !size-4 !rounded-sm !border-none ', | |||
| className, | |||
| )} | |||
| onClick={(e) => { | |||
| e.stopPropagation(); | |||
| showModal(); | |||
| }} | |||
| > | |||
| <Plus className="size-3 pointer-events-none" /> | |||
| {visible && ( | |||
| <NextStepDropdown hideModal={hideModal}> | |||
| <span></span> | |||
| </NextStepDropdown> | |||
| )} | |||
| </Handle> | |||
| </HandleContext.Provider> | |||
| ); | |||
| } | |||
| @@ -6,7 +6,7 @@ import { get } from 'lodash'; | |||
| import { memo } from 'react'; | |||
| import { NodeHandleId } from '../../constant'; | |||
| import { CommonHandle } from './handle'; | |||
| import { LeftHandleStyle, RightHandleStyle } from './handle-icon'; | |||
| import { LeftHandleStyle } from './handle-icon'; | |||
| import styles from './index.less'; | |||
| import NodeHeader from './node-header'; | |||
| import { NodeWrapper } from './node-wrapper'; | |||
| @@ -30,7 +30,7 @@ function InnerMessageNode({ | |||
| nodeId={id} | |||
| id={NodeHandleId.End} | |||
| ></CommonHandle> | |||
| <CommonHandle | |||
| {/* <CommonHandle | |||
| type="source" | |||
| position={Position.Right} | |||
| isConnectable={isConnectable} | |||
| @@ -38,7 +38,7 @@ function InnerMessageNode({ | |||
| id={NodeHandleId.Start} | |||
| nodeId={id} | |||
| isConnectableEnd={false} | |||
| ></CommonHandle> | |||
| ></CommonHandle> */} | |||
| <NodeHeader | |||
| id={id} | |||
| name={data.name} | |||