Skip to content

Commit

Permalink
feat: 增加节点类型,优化节点拖拽、连线交互
Browse files Browse the repository at this point in the history
  • Loading branch information
kampiu authored and kampiu committed Jan 16, 2024
1 parent f735ad9 commit 8bd2d8b
Show file tree
Hide file tree
Showing 39 changed files with 937 additions and 360 deletions.
File renamed without changes.
19 changes: 10 additions & 9 deletions src/Nodes/NodeA/NodeA.module.less
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
.node {
width: 40px;
height: 40px;
width: 52px;
height: 52px;
background-color: #FFFFFF;
border: 1px solid #DDDDDD;
border-radius: 4px;
user-select: none;
position: relative;

&:hover {
.node {
&-text {
opacity: 1;
}
&-connect {

.node {
&-handle {
width: 100%;
height: 100%;
Expand All @@ -26,6 +23,7 @@

&-text {
position: absolute;
display: inline-block;
width: 100%;
height: 20px;
text-align: center;
Expand All @@ -34,7 +32,6 @@
font-size: 12px;
line-height: 20px;
color: #333333;
opacity: 0;
}

&-handle {
Expand All @@ -54,6 +51,10 @@
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
font-size: 24px;
position: absolute;
left:0;
top: 0;
z-index: 10;
}
}
41 changes: 27 additions & 14 deletions src/Nodes/NodeA/NodeA.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { forwardRef, useEffect, useImperativeHandle } from "react"
import React, { forwardRef, useCallback, useImperativeHandle } from "react"
import styles from "./NodeA.module.less"
import { Handle, Position } from "reactflow"
import { Handle, Position, useStore } from "reactflow"
import type { NodeProps } from "@reactflow/core/dist/esm/types/nodes"
import { useFlowDataSelector } from "@/context/FlowData"
import hotkeys from "hotkeys-js"
import withMenu from "../withMenu"
import clsx from "clsx"
import Icons from "../../components/Icons"
import { useImmer } from "use-immer"

interface NodeAProps extends NodeProps {
isMenu?: boolean
Expand All @@ -19,33 +20,42 @@ const NodeA = forwardRef<NodeAInstance, NodeAProps>((props, ref) => {

const {isMenu, isConnectable} = props

const activeNode = useFlowDataSelector((store) => store.activeNode)
const connectionNodeId = useStore((store) => store.connectionNodeId)

const [nodeStatus, setNodeStatus] = useImmer({
canConnect: false,
})

useImperativeHandle(ref, (): NodeAInstance => {
return {}
})

useEffect(() => {
const onMouseEnter = useCallback(() => {
if (!isMenu) {
hotkeys("a", (event) => {
console.log("--a--", event)
hotkeys("l", {keyup: true}, (event) => {
event.preventDefault()
setNodeStatus((preNodeStatus) => {
preNodeStatus.canConnect = event.type === "keydown"
})
})
}
}, [])
}, [isMenu])

return (
<div className={ styles.node }>
<div className={ styles.nodeWrapper }>
<Icons.DataDisplay />
</div>
<div
onMouseEnter={ onMouseEnter }
className={ clsx(styles.node, {
[styles.nodeConnect]: nodeStatus.canConnect,
}) }
>
{
!isMenu && (
<>
<Handle
type="source"
className={ styles.nodeHandle }
style={ {
zIndex: activeNode === null ? 100 : -1,
zIndex: connectionNodeId === null && nodeStatus.canConnect ? 100 : -1,
} }
position={ Position.Top }
isConnectable={ isConnectable }
Expand All @@ -54,7 +64,7 @@ const NodeA = forwardRef<NodeAInstance, NodeAProps>((props, ref) => {
type="target"
className={ styles.nodeHandle }
style={ {
zIndex: (!props.id && activeNode !== props.id) ? 100 : -1
zIndex: (!props.id && connectionNodeId !== props.id) ? 100 : -1
} }
position={ Position.Top }
isConnectable={ isConnectable }
Expand All @@ -65,6 +75,9 @@ const NodeA = forwardRef<NodeAInstance, NodeAProps>((props, ref) => {
</>
)
}
<div className={ styles.nodeWrapper }>
<Icons.DataDisplay/>
</div>
</div>
)
})
Expand Down
59 changes: 0 additions & 59 deletions src/Nodes/NodeB/NodeB.module.less

This file was deleted.

44 changes: 33 additions & 11 deletions src/Nodes/NodeB/NodeB.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { forwardRef, useImperativeHandle } from "react"
import styles from "./NodeB.module.less"
import { Handle, Position } from "reactflow"
import React, { forwardRef, useCallback, useImperativeHandle } from "react"
import styles from "../NodeA/NodeA.module.less"
import { Handle, Position, useStore } from "reactflow"
import type { NodeProps } from "@reactflow/core/dist/esm/types/nodes"
import { useFlowDataSelector } from "@/context/FlowData"
import Icons from "../../components/Icons"
import { useImmer } from "use-immer"
import hotkeys from "hotkeys-js"
import clsx from "clsx"

interface NodeBProps extends NodeProps {
isMenu?: boolean
Expand All @@ -17,25 +19,42 @@ const NodeB = forwardRef<NodeBInstance, NodeBProps>((props, ref) => {

const {isMenu, isConnectable} = props

const activeNode = useFlowDataSelector((store) => store.activeNode)
const connectionNodeId = useStore((store) => store.connectionNodeId)

const [nodeStatus, setNodeStatus] = useImmer({
canConnect: false,
})

useImperativeHandle(ref, (): NodeBInstance => {
return {}
})

const onMouseEnter = useCallback(() => {
if (!isMenu) {
hotkeys("l", {keyup: true}, (event) => {
event.preventDefault()
setNodeStatus((preNodeStatus) => {
preNodeStatus.canConnect = event.type === "keydown"
})
})
}
}, [isMenu])

return (
<div className={ styles.node }>
<div className={styles.nodeWrapper}>
<Icons.ReverseOperationOut />
</div>
<div
onMouseEnter={ onMouseEnter }
className={ clsx(styles.node, {
[styles.nodeConnect]: nodeStatus.canConnect,
}) }
>
{
!isMenu && (
<>
<Handle
type="source"
className={ styles.nodeHandle }
style={ {
zIndex: activeNode === null ? 100 : -1,
zIndex: connectionNodeId === null && nodeStatus.canConnect ? 100 : -1,
} }
position={ Position.Top }
isConnectable={ isConnectable }
Expand All @@ -44,7 +63,7 @@ const NodeB = forwardRef<NodeBInstance, NodeBProps>((props, ref) => {
type="target"
className={ styles.nodeHandle }
style={ {
zIndex: (!props.id && activeNode !== props.id) ? 100 : -1
zIndex: (!props.id && connectionNodeId !== props.id) ? 100 : -1
} }
position={ Position.Top }
isConnectable={ isConnectable }
Expand All @@ -53,6 +72,9 @@ const NodeB = forwardRef<NodeBInstance, NodeBProps>((props, ref) => {
</>
)
}
<div className={ styles.nodeWrapper }>
<Icons.ReverseOperationOut/>
</div>
</div>
)
})
Expand Down
3 changes: 2 additions & 1 deletion src/Nodes/NodeB/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import NodeB from "./NodeB"
import FlowManager from "../../FlowManager"
import { Flow } from "../../types"
import { ComponentType } from "react"

/** 节点注册方法 */
export const install = () => {
FlowManager.registerNode({
type: Flow.NodeType.NodeB,
title: "NodeB",
component: NodeB
component: NodeB as ComponentType<any>
})
}

Expand Down
59 changes: 0 additions & 59 deletions src/Nodes/NodeC/NodeC.module.less

This file was deleted.

Loading

0 comments on commit 8bd2d8b

Please sign in to comment.