Commit b6c683a1 authored by StyleZhang's avatar StyleZhang

next step

parent 5200ec0b
...@@ -15,7 +15,7 @@ const initialNodes = [ ...@@ -15,7 +15,7 @@ const initialNodes = [
id: '2', id: '2',
type: 'custom', type: 'custom',
position: { x: 434, y: 130 }, position: { x: 434, y: 130 },
data: { type: 'code' }, data: { type: 'if-else' },
}, },
{ {
id: '3', id: '3',
......
...@@ -17,7 +17,6 @@ const CustomEdge = ({ ...@@ -17,7 +17,6 @@ const CustomEdge = ({
targetY, targetY,
selected, selected,
}: EdgeProps) => { }: EdgeProps) => {
console.log()
const [ const [
edgePath, edgePath,
labelX, labelX,
...@@ -37,7 +36,7 @@ const CustomEdge = ({ ...@@ -37,7 +36,7 @@ const CustomEdge = ({
id={id} id={id}
path={edgePath} path={edgePath}
style={{ style={{
stroke: selected ? '#2970FF' : '#D0D5DD', stroke: (selected || data?.connectedNodeIsHovering) ? '#2970FF' : '#D0D5DD',
strokeWidth: 2, strokeWidth: 2,
}} }}
/> />
......
import { useCallback } from 'react' import { useCallback } from 'react'
import produce from 'immer' import produce from 'immer'
import type { EdgeMouseHandler } from 'reactflow' import type {
import { useStoreApi } from 'reactflow' EdgeMouseHandler,
NodeMouseHandler,
} from 'reactflow'
import {
getConnectedEdges,
useStoreApi,
} from 'reactflow'
import type { SelectedNode } from './types' import type { SelectedNode } from './types'
import { useStore } from './store' import { useStore } from './store'
...@@ -9,6 +15,38 @@ export const useWorkflow = () => { ...@@ -9,6 +15,38 @@ export const useWorkflow = () => {
const store = useStoreApi() const store = useStoreApi()
const setSelectedNode = useStore(state => state.setSelectedNode) const setSelectedNode = useStore(state => state.setSelectedNode)
const handleEnterNode = useCallback<NodeMouseHandler>((_, node) => {
const {
edges,
setEdges,
} = store.getState()
const newEdges = produce(edges, (draft) => {
const connectedEdges = getConnectedEdges([node], edges)
connectedEdges.forEach((edge) => {
const currentEdge = draft.find(e => e.id === edge.id)
if (currentEdge)
currentEdge.data = { ...currentEdge.data, connectedNodeIsHovering: true }
})
})
setEdges(newEdges)
}, [store])
const handleLeaveNode = useCallback<NodeMouseHandler>((_, node) => {
const {
edges,
setEdges,
} = store.getState()
const newEdges = produce(edges, (draft) => {
const connectedEdges = getConnectedEdges([node], edges)
connectedEdges.forEach((edge) => {
const currentEdge = draft.find(e => e.id === edge.id)
if (currentEdge)
currentEdge.data = { ...currentEdge.data, connectedNodeIsHovering: false }
})
})
setEdges(newEdges)
}, [store])
const handleEnterEdge = useCallback<EdgeMouseHandler>((_, edge) => { const handleEnterEdge = useCallback<EdgeMouseHandler>((_, edge) => {
const { const {
edges, edges,
...@@ -61,6 +99,8 @@ export const useWorkflow = () => { ...@@ -61,6 +99,8 @@ export const useWorkflow = () => {
}, [setSelectedNode, store]) }, [setSelectedNode, store])
return { return {
handleEnterNode,
handleLeaveNode,
handleEnterEdge, handleEnterEdge,
handleLeaveEdge, handleLeaveEdge,
handleSelectNode, handleSelectNode,
......
...@@ -37,6 +37,8 @@ const Workflow: FC<WorkflowProps> = memo(({ ...@@ -37,6 +37,8 @@ const Workflow: FC<WorkflowProps> = memo(({
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges) const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges)
const { const {
handleEnterNode,
handleLeaveNode,
handleEnterEdge, handleEnterEdge,
handleLeaveEdge, handleLeaveEdge,
handleSelectNode, handleSelectNode,
...@@ -61,6 +63,8 @@ const Workflow: FC<WorkflowProps> = memo(({ ...@@ -61,6 +63,8 @@ const Workflow: FC<WorkflowProps> = memo(({
edgeTypes={edgeTypes} edgeTypes={edgeTypes}
nodes={nodes} nodes={nodes}
edges={edges} edges={edges}
onNodeMouseEnter={handleEnterNode}
onNodeMouseLeave={handleLeaveNode}
onEdgesChange={onEdgesChange} onEdgesChange={onEdgesChange}
onEdgeMouseEnter={handleEnterEdge} onEdgeMouseEnter={handleEnterEdge}
onEdgeMouseLeave={handleLeaveEdge} onEdgeMouseLeave={handleLeaveEdge}
......
...@@ -2,23 +2,27 @@ import { ...@@ -2,23 +2,27 @@ import {
memo, memo,
useCallback, useCallback,
} from 'react' } from 'react'
import {
getOutgoers,
useStoreApi,
} from 'reactflow'
import BlockIcon from '../../../block-icon' import BlockIcon from '../../../block-icon'
import type { Node } from '../../../types' import type { Node } from '../../../types'
import { BlockEnum } from '../../../types'
import { useStore } from '../../../store' import { useStore } from '../../../store'
import BlockSelector from '../../../block-selector' import BlockSelector from '../../../block-selector'
import { Plus } from '@/app/components/base/icons/src/vender/line/general' import { Plus } from '@/app/components/base/icons/src/vender/line/general'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
const NextStep = () => { const NextStep = () => {
const store = useStoreApi()
const selectedNode = useStore(state => state.selectedNode) const selectedNode = useStore(state => state.selectedNode)
const outgoers: Node[] = [] const outgoers: Node[] = getOutgoers(selectedNode as Node, store.getState().getNodes(), store.getState().edges)
const renderAddNextNodeTrigger = useCallback((open: boolean) => { const renderAddNextNodeTrigger = useCallback((open: boolean) => {
return ( return (
<div <div
className={` className={`
flex items-center px-2 w-[328px] h-9 rounded-lg border border-dashed border-gray-200 bg-gray-50 relative flex items-center px-2 w-[328px] h-9 rounded-lg border border-dashed border-gray-200 bg-gray-50
hover:bg-gray-100 text-xs text-gray-500 cursor-pointer hover:bg-gray-100 text-xs text-gray-500 cursor-pointer
${open && '!bg-gray-100'} ${open && '!bg-gray-100'}
`} `}
...@@ -49,7 +53,80 @@ const NextStep = () => { ...@@ -49,7 +53,80 @@ const NextStep = () => {
<div className='shrink-0 relative flex items-center justify-center w-9 h-9 bg-white rounded-lg border-[0.5px] border-gray-200 shadow-xs'> <div className='shrink-0 relative flex items-center justify-center w-9 h-9 bg-white rounded-lg border-[0.5px] border-gray-200 shadow-xs'>
<BlockIcon type={selectedNode!.data.type} /> <BlockIcon type={selectedNode!.data.type} />
</div> </div>
<div className='shrink-0 w-6'></div> <svg className='shrink-0 w-6'>
{
(!outgoers.length || outgoers.length === 1) && (
<g>
<path
d='M0,18 L24,18'
strokeWidth={1}
stroke='#D0D5DD'
fill='none'
/>
<rect
x={0}
y={16}
width={1}
height={4}
fill='#98A2B3'
/>
<rect
x={23}
y={16}
width={1}
height={4}
fill='#98A2B3'
/>
</g>
)
}
{
outgoers.length > 1 && (
<g>
{
Array(outgoers.length + 1).fill(0).map((_, index) => (
<g key={index}>
{
index === 0 && (
<path
d='M0,18 L24,18'
strokeWidth={1}
stroke='#D0D5DD'
fill='none'
/>
)
}
{
index > 0 && (
<path
d={`M0,18 Q12,18 12,28 L12,${index * 48 + 18 - 10} Q12,${index * 48 + 18} 24,${index * 48 + 18}`}
strokeWidth={1}
stroke='#D0D5DD'
fill='none'
/>
)
}
<rect
x={23}
y={index * 48 + 18 - 2}
width={1}
height={4}
fill='#98A2B3'
/>
</g>
))
}
<rect
x={0}
y={16}
width={1}
height={4}
fill='#98A2B3'
/>
</g>
)
}
</svg>
<div className='grow'> <div className='grow'>
{ {
!!outgoers.length && outgoers.map(outgoer => ( !!outgoers.length && outgoers.map(outgoer => (
...@@ -76,7 +153,7 @@ const NextStep = () => { ...@@ -76,7 +153,7 @@ const NextStep = () => {
)) ))
} }
{ {
(!outgoers.length || selectedNode!.data.type === BlockEnum.IfElse) && ( (!outgoers.length || outgoers.length > 1) && (
<BlockSelector <BlockSelector
onSelect={() => {}} onSelect={() => {}}
placement='top' placement='top'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment