@ -1,7 +1,7 @@
|
||||
import { Coordinates, useGraph, useGroupsCoordinates } from '../../providers'
|
||||
import React, { useEffect, useLayoutEffect, useMemo, useState } from 'react'
|
||||
import { Edge as EdgeProps } from 'models'
|
||||
import { Portal, useDisclosure } from '@chakra-ui/react'
|
||||
import { color, Portal, useColorMode, useDisclosure } from '@chakra-ui/react'
|
||||
import { useTypebot } from '@/features/editor'
|
||||
import { EdgeMenu } from './EdgeMenu'
|
||||
import { colors } from '@/lib/theme'
|
||||
@ -23,6 +23,7 @@ type Props = {
|
||||
edge: EdgeProps
|
||||
}
|
||||
export const Edge = ({ edge }: Props) => {
|
||||
const isDark = useColorMode().colorMode === 'dark'
|
||||
const { deleteEdge } = useTypebot()
|
||||
const {
|
||||
previewingEdge,
|
||||
@ -141,7 +142,13 @@ export const Edge = ({ edge }: Props) => {
|
||||
<path
|
||||
data-testid="edge"
|
||||
d={path}
|
||||
stroke={isPreviewing ? colors.blue[400] : colors.gray[400]}
|
||||
stroke={
|
||||
isPreviewing
|
||||
? colors.blue[400]
|
||||
: isDark
|
||||
? colors.gray[700]
|
||||
: colors.gray[400]
|
||||
}
|
||||
strokeWidth="2px"
|
||||
markerEnd={isPreviewing ? 'url(#blue-arrow)' : 'url(#arrow)'}
|
||||
fill="none"
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { chakra } from '@chakra-ui/react'
|
||||
import { chakra, useColorMode } from '@chakra-ui/react'
|
||||
import { colors } from '@/lib/theme'
|
||||
import { Edge as EdgeProps } from 'models'
|
||||
import React from 'react'
|
||||
@ -17,72 +17,75 @@ export const Edges = ({
|
||||
edges,
|
||||
answersCounts,
|
||||
onUnlockProPlanClick,
|
||||
}: Props) => (
|
||||
<chakra.svg
|
||||
width="full"
|
||||
height="full"
|
||||
overflow="visible"
|
||||
pos="absolute"
|
||||
left="0"
|
||||
top="0"
|
||||
shapeRendering="geometricPrecision"
|
||||
>
|
||||
<DrawingEdge />
|
||||
{edges.map((edge) => (
|
||||
<Edge key={edge.id} edge={edge} />
|
||||
))}
|
||||
{answersCounts?.map((answerCount) => (
|
||||
<DropOffEdge
|
||||
key={answerCount.groupId}
|
||||
answersCounts={answersCounts}
|
||||
groupId={answerCount.groupId}
|
||||
onUnlockProPlanClick={onUnlockProPlanClick}
|
||||
/>
|
||||
))}
|
||||
<marker
|
||||
id={'arrow'}
|
||||
refX="8"
|
||||
refY="4"
|
||||
orient="auto"
|
||||
viewBox="0 0 20 20"
|
||||
markerUnits="userSpaceOnUse"
|
||||
markerWidth="20"
|
||||
markerHeight="20"
|
||||
}: Props) => {
|
||||
const isDark = useColorMode().colorMode === 'dark'
|
||||
return (
|
||||
<chakra.svg
|
||||
width="full"
|
||||
height="full"
|
||||
overflow="visible"
|
||||
pos="absolute"
|
||||
left="0"
|
||||
top="0"
|
||||
shapeRendering="geometricPrecision"
|
||||
>
|
||||
<path
|
||||
d="M7.07138888,5.50174526 L2.43017246,7.82235347 C1.60067988,8.23709976 0.592024983,7.90088146 0.177278692,7.07138888 C0.0606951226,6.83822174 0,6.58111307 0,6.32042429 L0,1.67920787 C0,0.751806973 0.751806973,0 1.67920787,0 C1.93989666,0 2.19700532,0.0606951226 2.43017246,0.177278692 L7,3 C7.82949258,3.41474629 8.23709976,3.92128809 7.82235347,4.75078067 C7.6598671,5.07575341 7.39636161,5.33925889 7.07138888,5.50174526 Z"
|
||||
fill={colors.gray[400]}
|
||||
/>
|
||||
</marker>
|
||||
<marker
|
||||
id={'blue-arrow'}
|
||||
refX="8"
|
||||
refY="4"
|
||||
orient="auto"
|
||||
viewBox="0 0 20 20"
|
||||
markerUnits="userSpaceOnUse"
|
||||
markerWidth="20"
|
||||
markerHeight="20"
|
||||
>
|
||||
<path
|
||||
d="M7.07138888,5.50174526 L2.43017246,7.82235347 C1.60067988,8.23709976 0.592024983,7.90088146 0.177278692,7.07138888 C0.0606951226,6.83822174 0,6.58111307 0,6.32042429 L0,1.67920787 C0,0.751806973 0.751806973,0 1.67920787,0 C1.93989666,0 2.19700532,0.0606951226 2.43017246,0.177278692 L7,3 C7.82949258,3.41474629 8.23709976,3.92128809 7.82235347,4.75078067 C7.6598671,5.07575341 7.39636161,5.33925889 7.07138888,5.50174526 Z"
|
||||
fill={colors.blue[400]}
|
||||
/>
|
||||
</marker>
|
||||
<marker
|
||||
id={'red-arrow'}
|
||||
refX="8"
|
||||
refY="4"
|
||||
orient="auto"
|
||||
viewBox="0 0 20 20"
|
||||
markerUnits="userSpaceOnUse"
|
||||
markerWidth="20"
|
||||
markerHeight="20"
|
||||
>
|
||||
<path
|
||||
d="M7.07138888,5.50174526 L2.43017246,7.82235347 C1.60067988,8.23709976 0.592024983,7.90088146 0.177278692,7.07138888 C0.0606951226,6.83822174 0,6.58111307 0,6.32042429 L0,1.67920787 C0,0.751806973 0.751806973,0 1.67920787,0 C1.93989666,0 2.19700532,0.0606951226 2.43017246,0.177278692 L7,3 C7.82949258,3.41474629 8.23709976,3.92128809 7.82235347,4.75078067 C7.6598671,5.07575341 7.39636161,5.33925889 7.07138888,5.50174526 Z"
|
||||
fill="#e53e3e"
|
||||
/>
|
||||
</marker>
|
||||
</chakra.svg>
|
||||
)
|
||||
<DrawingEdge />
|
||||
{edges.map((edge) => (
|
||||
<Edge key={edge.id} edge={edge} />
|
||||
))}
|
||||
{answersCounts?.map((answerCount) => (
|
||||
<DropOffEdge
|
||||
key={answerCount.groupId}
|
||||
answersCounts={answersCounts}
|
||||
groupId={answerCount.groupId}
|
||||
onUnlockProPlanClick={onUnlockProPlanClick}
|
||||
/>
|
||||
))}
|
||||
<marker
|
||||
id={'arrow'}
|
||||
refX="8"
|
||||
refY="4"
|
||||
orient="auto"
|
||||
viewBox="0 0 20 20"
|
||||
markerUnits="userSpaceOnUse"
|
||||
markerWidth="20"
|
||||
markerHeight="20"
|
||||
>
|
||||
<path
|
||||
d="M7.07138888,5.50174526 L2.43017246,7.82235347 C1.60067988,8.23709976 0.592024983,7.90088146 0.177278692,7.07138888 C0.0606951226,6.83822174 0,6.58111307 0,6.32042429 L0,1.67920787 C0,0.751806973 0.751806973,0 1.67920787,0 C1.93989666,0 2.19700532,0.0606951226 2.43017246,0.177278692 L7,3 C7.82949258,3.41474629 8.23709976,3.92128809 7.82235347,4.75078067 C7.6598671,5.07575341 7.39636161,5.33925889 7.07138888,5.50174526 Z"
|
||||
fill={isDark ? colors.gray[600] : colors.gray[400]}
|
||||
/>
|
||||
</marker>
|
||||
<marker
|
||||
id={'blue-arrow'}
|
||||
refX="8"
|
||||
refY="4"
|
||||
orient="auto"
|
||||
viewBox="0 0 20 20"
|
||||
markerUnits="userSpaceOnUse"
|
||||
markerWidth="20"
|
||||
markerHeight="20"
|
||||
>
|
||||
<path
|
||||
d="M7.07138888,5.50174526 L2.43017246,7.82235347 C1.60067988,8.23709976 0.592024983,7.90088146 0.177278692,7.07138888 C0.0606951226,6.83822174 0,6.58111307 0,6.32042429 L0,1.67920787 C0,0.751806973 0.751806973,0 1.67920787,0 C1.93989666,0 2.19700532,0.0606951226 2.43017246,0.177278692 L7,3 C7.82949258,3.41474629 8.23709976,3.92128809 7.82235347,4.75078067 C7.6598671,5.07575341 7.39636161,5.33925889 7.07138888,5.50174526 Z"
|
||||
fill={colors.blue[400]}
|
||||
/>
|
||||
</marker>
|
||||
<marker
|
||||
id={'red-arrow'}
|
||||
refX="8"
|
||||
refY="4"
|
||||
orient="auto"
|
||||
viewBox="0 0 20 20"
|
||||
markerUnits="userSpaceOnUse"
|
||||
markerWidth="20"
|
||||
markerHeight="20"
|
||||
>
|
||||
<path
|
||||
d="M7.07138888,5.50174526 L2.43017246,7.82235347 C1.60067988,8.23709976 0.592024983,7.90088146 0.177278692,7.07138888 C0.0606951226,6.83822174 0,6.58111307 0,6.32042429 L0,1.67920787 C0,0.751806973 0.751806973,0 1.67920787,0 C1.93989666,0 2.19700532,0.0606951226 2.43017246,0.177278692 L7,3 C7.82949258,3.41474629 8.23709976,3.92128809 7.82235347,4.75078067 C7.6598671,5.07575341 7.39636161,5.33925889 7.07138888,5.50174526 Z"
|
||||
fill="#e53e3e"
|
||||
/>
|
||||
</marker>
|
||||
</chakra.svg>
|
||||
)
|
||||
}
|
||||
|
@ -1,4 +1,9 @@
|
||||
import { BoxProps, Flex, useEventListener } from '@chakra-ui/react'
|
||||
import {
|
||||
BoxProps,
|
||||
Flex,
|
||||
useColorModeValue,
|
||||
useEventListener,
|
||||
} from '@chakra-ui/react'
|
||||
import { useGraph, useGroupsCoordinates } from '../../providers'
|
||||
import { Source } from 'models'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
@ -9,6 +14,9 @@ export const SourceEndpoint = ({
|
||||
}: BoxProps & {
|
||||
source: Source
|
||||
}) => {
|
||||
const color = useColorModeValue('blue.200', 'blue.100')
|
||||
const connectedColor = useColorModeValue('blue.300', 'blue.200')
|
||||
const bg = useColorModeValue('gray.100', 'gray.700')
|
||||
const [ranOnce, setRanOnce] = useState(false)
|
||||
const { setConnectingIds, addSourceEndpoint, previewingEdge } = useGraph()
|
||||
|
||||
@ -61,7 +69,7 @@ export const SourceEndpoint = ({
|
||||
boxSize="20px"
|
||||
justify="center"
|
||||
align="center"
|
||||
bgColor="gray.100"
|
||||
bg={bg}
|
||||
rounded="full"
|
||||
>
|
||||
<Flex
|
||||
@ -72,8 +80,8 @@ export const SourceEndpoint = ({
|
||||
borderColor={
|
||||
previewingEdge?.from.blockId === source.blockId &&
|
||||
previewingEdge.from.itemId === source.itemId
|
||||
? 'blue.300'
|
||||
: 'blue.200'
|
||||
? connectedColor
|
||||
: color
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
|
@ -3,6 +3,7 @@ import {
|
||||
HStack,
|
||||
Popover,
|
||||
PopoverTrigger,
|
||||
useColorModeValue,
|
||||
useDisclosure,
|
||||
useEventListener,
|
||||
} from '@chakra-ui/react'
|
||||
@ -26,17 +27,17 @@ import { SourceEndpoint } from '../../Endpoints/SourceEndpoint'
|
||||
import { useRouter } from 'next/router'
|
||||
import { SettingsModal } from './SettingsPopoverContent/SettingsModal'
|
||||
import { BlockSettings } from './SettingsPopoverContent/SettingsPopoverContent'
|
||||
import { TextBubbleEditor } from '../../../../blocks/bubbles/textBubble/components/TextBubbleEditor'
|
||||
import { TargetEndpoint } from '../../Endpoints'
|
||||
import { MediaBubblePopoverContent } from './MediaBubblePopoverContent'
|
||||
import {
|
||||
NodePosition,
|
||||
useBlockDnd,
|
||||
useDragDistance,
|
||||
useGraph,
|
||||
} from '../../../providers'
|
||||
import { ContextMenu } from '@/components/ContextMenu'
|
||||
import { setMultipleRefs } from '@/utils/helpers'
|
||||
import { TextBubbleEditor } from '@/features/blocks/bubbles/textBubble'
|
||||
import {
|
||||
NodePosition,
|
||||
useGraph,
|
||||
useBlockDnd,
|
||||
useDragDistance,
|
||||
} from '../../../providers'
|
||||
import { hasDefaultConnector } from '../../../utils'
|
||||
|
||||
export const BlockNode = ({
|
||||
@ -50,6 +51,9 @@ export const BlockNode = ({
|
||||
indices: { blockIndex: number; groupIndex: number }
|
||||
onMouseDown?: (blockNodePosition: NodePosition, block: DraggableBlock) => void
|
||||
}) => {
|
||||
const bg = useColorModeValue('gray.50', 'gray.850')
|
||||
const previewingBorderColor = useColorModeValue('blue.400', 'blue.300')
|
||||
const borderColor = useColorModeValue('gray.200', 'gray.800')
|
||||
const { query } = useRouter()
|
||||
const {
|
||||
setConnectingIds,
|
||||
@ -165,7 +169,7 @@ export const BlockNode = ({
|
||||
<ContextMenu<HTMLDivElement>
|
||||
renderMenu={() => <BlockNodeContextMenu indices={indices} />}
|
||||
>
|
||||
{(ref, isOpened) => (
|
||||
{(ref, isContextMenuOpened) => (
|
||||
<Popover
|
||||
placement="left"
|
||||
isLazy
|
||||
@ -186,12 +190,18 @@ export const BlockNode = ({
|
||||
flex="1"
|
||||
userSelect="none"
|
||||
p="3"
|
||||
borderWidth={isOpened || isPreviewing ? '2px' : '1px'}
|
||||
borderColor={isOpened || isPreviewing ? 'blue.400' : 'gray.200'}
|
||||
margin={isOpened || isPreviewing ? '-1px' : 0}
|
||||
borderWidth={
|
||||
isContextMenuOpened || isPreviewing ? '2px' : '1px'
|
||||
}
|
||||
borderColor={
|
||||
isContextMenuOpened || isPreviewing
|
||||
? previewingBorderColor
|
||||
: borderColor
|
||||
}
|
||||
margin={isContextMenuOpened || isPreviewing ? '-1px' : 0}
|
||||
rounded="lg"
|
||||
cursor={'pointer'}
|
||||
bgColor="gray.50"
|
||||
bg={bg}
|
||||
align="flex-start"
|
||||
w="full"
|
||||
transition="border-color 0.2s"
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { BlockIcon } from '@/features/editor'
|
||||
import { StackProps, HStack } from '@chakra-ui/react'
|
||||
import { StackProps, HStack, useColorModeValue } from '@chakra-ui/react'
|
||||
import { StartBlock, Block, BlockIndices } from 'models'
|
||||
import { BlockNodeContent } from './BlockNodeContent/BlockNodeContent'
|
||||
|
||||
@ -13,7 +13,8 @@ export const BlockNodeOverlay = ({
|
||||
p="3"
|
||||
borderWidth="1px"
|
||||
rounded="lg"
|
||||
bgColor="white"
|
||||
borderColor={useColorModeValue('gray.200', 'gray.800')}
|
||||
bgColor={useColorModeValue('gray.50', 'gray.850')}
|
||||
cursor={'grab'}
|
||||
w="264px"
|
||||
pointerEvents="none"
|
||||
|
@ -10,6 +10,8 @@ import { useEffect, useRef, useState } from 'react'
|
||||
import { useTypebot } from '@/features/editor'
|
||||
import { BlockNode } from './BlockNode'
|
||||
import { BlockNodeOverlay } from './BlockNodeOverlay'
|
||||
import { PlaceholderNode } from '../PlaceholderNode'
|
||||
import { isDefined } from 'utils'
|
||||
|
||||
type Props = {
|
||||
groupId: string
|
||||
@ -49,7 +51,7 @@ export const BlockNodesList = ({
|
||||
const isDraggingOnCurrentGroup =
|
||||
(draggedBlock || draggedBlockType) && mouseOverGroup?.id === groupId
|
||||
const showSortPlaceholders =
|
||||
!isStartGroup && (draggedBlock || draggedBlockType)
|
||||
!isStartGroup && isDefined(draggedBlock || draggedBlockType)
|
||||
|
||||
useEffect(() => {
|
||||
if (mouseOverGroup?.id !== groupId) setExpandedPlaceholderIndex(undefined)
|
||||
@ -126,17 +128,10 @@ export const BlockNodesList = ({
|
||||
transition="none"
|
||||
pointerEvents={isReadOnly || isStartGroup ? 'none' : 'auto'}
|
||||
>
|
||||
<Flex
|
||||
ref={handlePushElementRef(0)}
|
||||
h={
|
||||
showSortPlaceholders && expandedPlaceholderIndex === 0
|
||||
? '50px'
|
||||
: '2px'
|
||||
}
|
||||
bgColor={'gray.300'}
|
||||
visibility={showSortPlaceholders ? 'visible' : 'hidden'}
|
||||
rounded="lg"
|
||||
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
||||
<PlaceholderNode
|
||||
isVisible={showSortPlaceholders}
|
||||
isExpanded={expandedPlaceholderIndex === 0}
|
||||
onRef={handlePushElementRef(0)}
|
||||
/>
|
||||
{typebot &&
|
||||
blocks.map((block, idx) => (
|
||||
@ -148,17 +143,10 @@ export const BlockNodesList = ({
|
||||
isConnectable={blocks.length - 1 === idx}
|
||||
onMouseDown={handleBlockMouseDown(idx)}
|
||||
/>
|
||||
<Flex
|
||||
ref={handlePushElementRef(idx + 1)}
|
||||
h={
|
||||
showSortPlaceholders && expandedPlaceholderIndex === idx + 1
|
||||
? '50px'
|
||||
: '2px'
|
||||
}
|
||||
bgColor={'gray.300'}
|
||||
visibility={showSortPlaceholders ? 'visible' : 'hidden'}
|
||||
rounded="lg"
|
||||
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
||||
<PlaceholderNode
|
||||
isVisible={showSortPlaceholders}
|
||||
isExpanded={expandedPlaceholderIndex === idx + 1}
|
||||
onRef={handlePushElementRef(idx + 1)}
|
||||
/>
|
||||
</Stack>
|
||||
))}
|
||||
|
@ -4,6 +4,7 @@ import {
|
||||
EditablePreview,
|
||||
IconButton,
|
||||
Stack,
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react'
|
||||
import React, { memo, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { Group } from 'models'
|
||||
@ -52,6 +53,10 @@ const NonMemoizedDraggableGroupNode = ({
|
||||
groupIndex,
|
||||
onGroupDrag,
|
||||
}: Props & { onGroupDrag: (newCoord: Coordinates) => void }) => {
|
||||
const bg = useColorModeValue('white', 'gray.900')
|
||||
const previewingBorderColor = useColorModeValue('blue.400', 'blue.300')
|
||||
const borderColor = useColorModeValue('white', 'gray.800')
|
||||
const editableHoverBg = useColorModeValue('gray.100', 'gray.700')
|
||||
const {
|
||||
connectingIds,
|
||||
setConnectingIds,
|
||||
@ -172,16 +177,20 @@ const NonMemoizedDraggableGroupNode = ({
|
||||
renderMenu={() => <GroupNodeContextMenu groupIndex={groupIndex} />}
|
||||
isDisabled={isReadOnly || isStartGroup}
|
||||
>
|
||||
{(ref, isOpened) => (
|
||||
{(ref, isContextMenuOpened) => (
|
||||
<Stack
|
||||
ref={setMultipleRefs([ref, groupRef])}
|
||||
data-testid="group"
|
||||
p="4"
|
||||
rounded="xl"
|
||||
bgColor="#ffffff"
|
||||
borderWidth="2px"
|
||||
bg={bg}
|
||||
borderWidth={
|
||||
isConnecting || isContextMenuOpened || isPreviewing ? '2px' : '1px'
|
||||
}
|
||||
borderColor={
|
||||
isConnecting || isOpened || isPreviewing ? 'blue.400' : '#ffffff'
|
||||
isConnecting || isContextMenuOpened || isPreviewing
|
||||
? previewingBorderColor
|
||||
: borderColor
|
||||
}
|
||||
w="300px"
|
||||
transition="border 300ms, box-shadow 200ms"
|
||||
@ -208,7 +217,9 @@ const NonMemoizedDraggableGroupNode = ({
|
||||
pr="8"
|
||||
>
|
||||
<EditablePreview
|
||||
_hover={{ bgColor: 'gray.200' }}
|
||||
_hover={{
|
||||
bg: editableHoverBg,
|
||||
}}
|
||||
px="1"
|
||||
userSelect={'none'}
|
||||
/>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Flex } from '@chakra-ui/react'
|
||||
import { Flex, useColorModeValue } from '@chakra-ui/react'
|
||||
import {
|
||||
Coordinates,
|
||||
useGraph,
|
||||
@ -30,6 +30,9 @@ export const ItemNode = ({
|
||||
onMouseDown,
|
||||
connectionDisabled,
|
||||
}: Props) => {
|
||||
const previewingBorderColor = useColorModeValue('blue.400', 'blue.300')
|
||||
const borderColor = useColorModeValue('gray.200', 'gray.700')
|
||||
const bg = useColorModeValue('white', undefined)
|
||||
const { typebot } = useTypebot()
|
||||
const { previewingEdge } = useGraph()
|
||||
const [isMouseOver, setIsMouseOver] = useState(false)
|
||||
@ -59,7 +62,7 @@ export const ItemNode = ({
|
||||
<ContextMenu<HTMLDivElement>
|
||||
renderMenu={() => <ItemNodeContextMenu indices={indices} />}
|
||||
>
|
||||
{(ref, isOpened) => (
|
||||
{(ref, isContextMenuOpened) => (
|
||||
<Flex
|
||||
data-testid="item"
|
||||
pos="relative"
|
||||
@ -74,10 +77,14 @@ export const ItemNode = ({
|
||||
_hover={{ shadow: 'md' }}
|
||||
transition="box-shadow 200ms, border-color 200ms"
|
||||
rounded="md"
|
||||
borderWidth={isOpened || isPreviewing ? '2px' : '1px'}
|
||||
borderColor={isOpened || isPreviewing ? 'blue.400' : 'gray.100'}
|
||||
margin={isOpened || isPreviewing ? '-1px' : 0}
|
||||
bgColor="white"
|
||||
bg={bg}
|
||||
borderWidth={isContextMenuOpened || isPreviewing ? '2px' : '1px'}
|
||||
borderColor={
|
||||
isContextMenuOpened || isPreviewing
|
||||
? previewingBorderColor
|
||||
: borderColor
|
||||
}
|
||||
margin={isContextMenuOpened || isPreviewing ? '-1px' : 0}
|
||||
w="full"
|
||||
>
|
||||
<ItemNodeContent
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Flex, FlexProps } from '@chakra-ui/react'
|
||||
import { Flex, FlexProps, useColorModeValue } from '@chakra-ui/react'
|
||||
import { Item } from 'models'
|
||||
import React, { ReactNode } from 'react'
|
||||
|
||||
@ -12,9 +12,9 @@ export const ItemNodeOverlay = ({ item, ...props }: Props) => {
|
||||
px="4"
|
||||
py="2"
|
||||
rounded="md"
|
||||
bgColor="white"
|
||||
bgColor={useColorModeValue('white', 'gray.850')}
|
||||
borderWidth="1px"
|
||||
borderColor={'gray.300'}
|
||||
borderColor={useColorModeValue('gray.200', 'gray.700')}
|
||||
w="212px"
|
||||
pointerEvents="none"
|
||||
shadow="lg"
|
||||
|
@ -1,4 +1,11 @@
|
||||
import { Flex, Portal, Stack, Text, useEventListener } from '@chakra-ui/react'
|
||||
import {
|
||||
Flex,
|
||||
Portal,
|
||||
Stack,
|
||||
Text,
|
||||
useColorModeValue,
|
||||
useEventListener,
|
||||
} from '@chakra-ui/react'
|
||||
import {
|
||||
computeNearestPlaceholderIndex,
|
||||
useBlockDnd,
|
||||
@ -10,6 +17,8 @@ import { BlockIndices, BlockWithItems, LogicBlockType, Item } from 'models'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { ItemNode } from './ItemNode'
|
||||
import { SourceEndpoint } from '../../Endpoints'
|
||||
import { ItemNodeOverlay } from './ItemNodeOverlay'
|
||||
import { PlaceholderNode } from '../PlaceholderNode'
|
||||
|
||||
type Props = {
|
||||
block: BlockWithItems
|
||||
@ -121,13 +130,10 @@ export const ItemNodesList = ({
|
||||
|
||||
return (
|
||||
<Stack flex={1} spacing={1} maxW="full" onClick={stopPropagating}>
|
||||
<Flex
|
||||
ref={handlePushElementRef(0)}
|
||||
h={showPlaceholders && expandedPlaceholderIndex === 0 ? '50px' : '2px'}
|
||||
bgColor={'gray.300'}
|
||||
visibility={showPlaceholders ? 'visible' : 'hidden'}
|
||||
rounded="lg"
|
||||
transition={showPlaceholders ? 'height 200ms' : 'none'}
|
||||
<PlaceholderNode
|
||||
isVisible={showPlaceholders}
|
||||
isExpanded={expandedPlaceholderIndex === 0}
|
||||
onRef={handlePushElementRef(0)}
|
||||
/>
|
||||
{block.items.map((item, idx) => (
|
||||
<Stack key={item.id} spacing={1}>
|
||||
@ -136,45 +142,14 @@ export const ItemNodesList = ({
|
||||
indices={{ groupIndex, blockIndex, itemIndex: idx }}
|
||||
onMouseDown={handleBlockMouseDown(idx)}
|
||||
/>
|
||||
<Flex
|
||||
ref={handlePushElementRef(idx + 1)}
|
||||
h={
|
||||
showPlaceholders && expandedPlaceholderIndex === idx + 1
|
||||
? '50px'
|
||||
: '2px'
|
||||
}
|
||||
bgColor={'gray.300'}
|
||||
visibility={showPlaceholders ? 'visible' : 'hidden'}
|
||||
rounded="lg"
|
||||
transition={showPlaceholders ? 'height 200ms' : 'none'}
|
||||
<PlaceholderNode
|
||||
isVisible={showPlaceholders}
|
||||
isExpanded={expandedPlaceholderIndex === idx + 1}
|
||||
onRef={handlePushElementRef(idx + 1)}
|
||||
/>
|
||||
</Stack>
|
||||
))}
|
||||
{isLastBlock && (
|
||||
<Flex
|
||||
px="4"
|
||||
py="2"
|
||||
borderWidth="1px"
|
||||
borderColor="gray.300"
|
||||
bgColor={'gray.50'}
|
||||
rounded="md"
|
||||
pos="relative"
|
||||
align="center"
|
||||
cursor="not-allowed"
|
||||
>
|
||||
<Text color="gray.500">
|
||||
{block.type === LogicBlockType.CONDITION ? 'Else' : 'Default'}
|
||||
</Text>
|
||||
<SourceEndpoint
|
||||
source={{
|
||||
groupId: block.groupId,
|
||||
blockId: block.id,
|
||||
}}
|
||||
pos="absolute"
|
||||
right="-49px"
|
||||
/>
|
||||
</Flex>
|
||||
)}
|
||||
{isLastBlock && <DefaultItemNode block={block} />}
|
||||
|
||||
{draggedItem && draggedItem.blockId === block.id && (
|
||||
<Portal>
|
||||
@ -189,14 +164,38 @@ export const ItemNodesList = ({
|
||||
w="220px"
|
||||
transformOrigin="0 0 0"
|
||||
>
|
||||
<ItemNode
|
||||
item={draggedItem}
|
||||
indices={{ groupIndex, blockIndex, itemIndex: 0 }}
|
||||
connectionDisabled
|
||||
/>
|
||||
<ItemNodeOverlay item={draggedItem} />
|
||||
</Flex>
|
||||
</Portal>
|
||||
)}
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
const DefaultItemNode = ({ block }: { block: BlockWithItems }) => {
|
||||
return (
|
||||
<Flex
|
||||
px="4"
|
||||
py="2"
|
||||
borderWidth="1px"
|
||||
borderColor={useColorModeValue('gray.300', undefined)}
|
||||
bgColor={useColorModeValue('gray.50', 'gray.850')}
|
||||
rounded="md"
|
||||
pos="relative"
|
||||
align="center"
|
||||
cursor="not-allowed"
|
||||
>
|
||||
<Text color="gray.500">
|
||||
{block.type === LogicBlockType.CONDITION ? 'Else' : 'Default'}
|
||||
</Text>
|
||||
<SourceEndpoint
|
||||
source={{
|
||||
groupId: block.groupId,
|
||||
blockId: block.id,
|
||||
}}
|
||||
pos="absolute"
|
||||
right="-49px"
|
||||
/>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
import { Flex, useColorModeValue } from '@chakra-ui/react'
|
||||
import React from 'react'
|
||||
|
||||
type Props = {
|
||||
isVisible: boolean
|
||||
isExpanded: boolean
|
||||
onRef: (ref: HTMLDivElement) => void
|
||||
}
|
||||
|
||||
export const PlaceholderNode = ({ isVisible, isExpanded, onRef }: Props) => {
|
||||
return (
|
||||
<Flex
|
||||
ref={onRef}
|
||||
h={isExpanded ? '50px' : '2px'}
|
||||
bgColor={useColorModeValue('gray.300', 'gray.700')}
|
||||
visibility={isVisible ? 'visible' : 'hidden'}
|
||||
rounded="lg"
|
||||
transition={isVisible ? 'height 200ms' : 'none'}
|
||||
/>
|
||||
)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { Stack, IconButton } from '@chakra-ui/react'
|
||||
import { Stack, IconButton, useColorModeValue } from '@chakra-ui/react'
|
||||
import { PlusIcon, MinusIcon } from '@/components/icons'
|
||||
import { headerHeight } from '@/features/editor'
|
||||
|
||||
@ -14,7 +14,7 @@ export const ZoomButtons = ({
|
||||
pos="fixed"
|
||||
top={`calc(${headerHeight}px + 70px)`}
|
||||
right="40px"
|
||||
bgColor="white"
|
||||
bgColor={useColorModeValue('white', 'gray.900')}
|
||||
rounded="md"
|
||||
zIndex={1}
|
||||
spacing="0"
|
||||
@ -25,7 +25,7 @@ export const ZoomButtons = ({
|
||||
aria-label={'Zoom in'}
|
||||
size="sm"
|
||||
onClick={onZoomIn}
|
||||
bgColor="white"
|
||||
bgColor={useColorModeValue('white', undefined)}
|
||||
borderBottomRadius={0}
|
||||
/>
|
||||
<IconButton
|
||||
@ -33,7 +33,7 @@ export const ZoomButtons = ({
|
||||
aria-label={'Zoom out'}
|
||||
size="sm"
|
||||
onClick={onZoomOut}
|
||||
bgColor="white"
|
||||
bgColor={useColorModeValue('white', undefined)}
|
||||
borderTopRadius={0}
|
||||
/>
|
||||
</Stack>
|
||||
|
Reference in New Issue
Block a user