Commit 59d8f926 authored by StyleZhang's avatar StyleZhang

block-selector

parent c6f1900a
......@@ -11,45 +11,10 @@ const initialNodes = [
position: { x: 330, y: 30 },
data: { type: 'start' },
},
{
id: '2',
type: 'custom',
position: { x: 330, y: 212 },
data: { type: 'start' },
},
{
id: '3',
type: 'custom',
position: { x: 150, y: 394 },
data: { type: 'start' },
},
{
id: '4',
type: 'custom',
position: { x: 510, y: 394 },
data: { type: 'start' },
},
]
const initialEdges = [
{
id: '1',
source: '1',
target: '2',
type: 'custom',
},
{
id: '2',
source: '2',
target: '3',
type: 'custom',
},
{
id: '3',
source: '2',
target: '4',
type: 'custom',
},
]
const Page: FC = () => {
......
import type { FC, ReactElement } from 'react'
import {
memo,
useCallback,
useState,
} from 'react'
import Tabs from './tabs'
import type {
OffsetOptions,
Placement,
} from '@floating-ui/react'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
FloatingPortal,
flip,
offset,
shift,
useClick,
useDismiss,
useFloating,
useInteractions,
} from '@floating-ui/react'
import Tabs from './tabs'
import { SearchLg } from '@/app/components/base/icons/src/vender/line/general'
type NodeSelectorProps = {
children: ReactElement
placement?: Placement
offset?: OffsetOptions
className?: string
children: (props: any) => ReactElement
}
const NodeSelector: FC<NodeSelectorProps> = ({
placement = 'top',
offset: offsetValue = 0,
className,
children,
}) => {
const [open, setOpen] = useState(false)
const handleTrigger: any = useCallback((e: MouseEvent) => {
e.stopPropagation()
setOpen(v => !v)
}, [])
const { refs, floatingStyles, context } = useFloating({
placement,
strategy: 'fixed',
open,
onOpenChange: setOpen,
middleware: [
flip(),
shift(),
offset(offsetValue),
],
})
const click = useClick(context)
const dismiss = useDismiss(context, {
bubbles: false,
})
const { getReferenceProps, getFloatingProps } = useInteractions([
click,
dismiss,
])
return (
<PortalToFollowElem
open={open}
onOpenChange={setOpen}
placement='right-start'
<>
{children({ ...getReferenceProps(), ref: refs.setReference, open })}
{
open && (
<FloatingPortal>
<div
ref={refs.setFloating}
style={floatingStyles}
{...getFloatingProps()}
className='z-[1000]'
>
<PortalToFollowElemTrigger onClick={handleTrigger}>
{children}
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-50'>
<div className='w-[256px] rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg'>
<div className={`w-[256px] rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg ${className}`}>
<div className='px-2 pt-2'>
<div className='flex items-center px-2 rounded-lg bg-gray-100'>
<SearchLg className='shrink-0 ml-[1px] mr-[5px] w-3.5 h-3.5 text-gray-400' />
......@@ -46,8 +77,11 @@ const NodeSelector: FC<NodeSelectorProps> = ({
</div>
<Tabs />
</div>
</PortalToFollowElemContent>
</PortalToFollowElem>
</div>
</FloatingPortal>
)
}
</>
)
}
......
import type { FC } from 'react'
import {
memo,
useCallback,
useMemo,
} from 'react'
import { getOutgoers } from 'reactflow'
......@@ -25,6 +26,42 @@ const NextStep: FC<NextStepProps> = ({
return getOutgoers(selectedNode, nodes, edges)
}, [selectedNode, nodes, edges])
const renderBlockSelectorChildren = useCallback(({ open, ref, ...restProps }: any) => {
return (
<div
{...restProps}
ref={ref}
className={`
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
${open && '!bg-gray-100'}
`}
>
<div className='flex items-center justify-center mr-1.5 w-5 h-5 rounded-[5px] bg-gray-200'>
<Plus className='w-3 h-3' />
</div>
SELECT NEXT BLOCK
</div>
)
}, [])
const renderBlockSelectorButtonChildren = useCallback(({ open, ref, ...restProps }: any) => {
return (
<div
{...restProps}
ref={ref}
>
<Button
className={`
hidden group-hover:flex px-2 py-0 h-6 bg-white text-xs text-gray-700 font-medium rounded-md
${open && '!bg-gray-100 !flex'}
`}
>
Change
</Button>
</div>
)
}, [])
return (
<div className='flex py-1'>
<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'>
......@@ -34,13 +71,8 @@ const NextStep: FC<NextStepProps> = ({
<div className='grow'>
{
!outgoers.length && (
<BlockSelector>
<div className='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'>
<div className='flex items-center justify-center mr-1.5 w-5 h-5 rounded-[5px] bg-gray-200'>
<Plus className='w-3 h-3' />
</div>
SELECT NEXT BLOCK
</div>
<BlockSelector className='!w-[328px]'>
{renderBlockSelectorChildren}
</BlockSelector>
)
}
......@@ -55,10 +87,11 @@ const NextStep: FC<NextStepProps> = ({
className='shrink-0 mr-1.5'
/>
<div className='grow'>{outgoer.data.name}</div>
<BlockSelector>
<Button className='hidden group-hover:flex px-2 py-0 h-6 bg-white text-xs text-gray-700 font-medium rounded-md'>
Change
</Button>
<BlockSelector
placement='top-end'
offset={6}
>
{renderBlockSelectorButtonChildren}
</BlockSelector>
</div>
))
......
......@@ -2,7 +2,11 @@ import type {
FC,
ReactNode,
} from 'react'
import { memo, useMemo } from 'react'
import {
memo,
useCallback,
useMemo,
} from 'react'
import {
getOutgoers,
useNodeId,
......@@ -33,6 +37,23 @@ const BaseNode: FC<BaseNodeProps> = ({
const outgoers = useMemo(() => {
return getOutgoers(currentNode!, nodes, edges)
}, [currentNode, nodes, edges])
const renderBlockSelectorChildren = useCallback(({ open, ref, ...restProps }: any) => {
return (
<div onClick={e => e.stopPropagation()}>
<div
{...restProps}
ref={ref}
className={`
hidden absolute -bottom-2 left-1/2 -translate-x-1/2 items-center justify-center
w-4 h-4 rounded-full bg-primary-600 cursor-pointer z-10 group-hover:flex
${open && '!flex'}
`}
>
<Plus className='w-2.5 h-2.5 text-white' />
</div>
</div>
)
}, [])
return (
<div
......@@ -57,17 +78,16 @@ const BaseNode: FC<BaseNodeProps> = ({
<div className='px-3 pt-1 pb-1 text-xs text-gray-500'>
Define the initial parameters for launching a workflow
</div>
<BlockSelector>
<div
className={`
hidden absolute -bottom-2 left-1/2 -translate-x-1/2 items-center justify-center
w-4 h-4 rounded-full bg-primary-600 cursor-pointer z-10
${!outgoers.length && 'group-hover:flex'}
`}
{
!outgoers.length && (
<BlockSelector
placement='right'
offset={6}
>
<Plus className='w-2.5 h-2.5 text-white' />
</div>
{renderBlockSelectorChildren}
</BlockSelector>
)
}
</div>
)
}
......
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