feat(ui): 💄 Face lift
This commit is contained in:
@ -250,3 +250,12 @@ export const UserIcon = (props: IconProps) => (
|
|||||||
<circle cx="12" cy="7" r="4"></circle>
|
<circle cx="12" cy="7" r="4"></circle>
|
||||||
</Icon>
|
</Icon>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const ExpandIcon = (props: IconProps) => (
|
||||||
|
<Icon viewBox="0 0 24 24" {...featherIconsBaseProps} {...props}>
|
||||||
|
<polyline points="15 3 21 3 21 9"></polyline>
|
||||||
|
<polyline points="9 21 3 21 3 15"></polyline>
|
||||||
|
<line x1="21" y1="3" x2="14" y2="10"></line>
|
||||||
|
<line x1="3" y1="21" x2="10" y2="14"></line>
|
||||||
|
</Icon>
|
||||||
|
)
|
||||||
|
@ -16,7 +16,7 @@ export const Board = () => {
|
|||||||
<StepTypesList />
|
<StepTypesList />
|
||||||
<GraphProvider>
|
<GraphProvider>
|
||||||
<Graph flex="1" />
|
<Graph flex="1" />
|
||||||
<BoardMenuButton pos="absolute" right="20px" top="20px" />
|
<BoardMenuButton pos="absolute" right="40px" top="20px" />
|
||||||
{rightPanel === RightPanel.PREVIEW && <PreviewDrawer />}
|
{rightPanel === RightPanel.PREVIEW && <PreviewDrawer />}
|
||||||
</GraphProvider>
|
</GraphProvider>
|
||||||
</DndContext>
|
</DndContext>
|
||||||
|
@ -35,6 +35,8 @@ export const BoardMenuButton = (props: MenuButtonProps) => {
|
|||||||
<Menu>
|
<Menu>
|
||||||
<MenuButton
|
<MenuButton
|
||||||
as={IconButton}
|
as={IconButton}
|
||||||
|
variant="outline"
|
||||||
|
colorScheme="blue"
|
||||||
icon={<MoreVerticalIcon transform={'rotate(90deg)'} />}
|
icon={<MoreVerticalIcon transform={'rotate(90deg)'} />}
|
||||||
isLoading={isDownloading}
|
isLoading={isDownloading}
|
||||||
{...props}
|
{...props}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Button, ButtonProps, Flex, HStack } from '@chakra-ui/react'
|
import { Flex, HStack, StackProps, Text } from '@chakra-ui/react'
|
||||||
import { StepType, DraggableStepType } from 'models'
|
import { StepType, DraggableStepType } from 'models'
|
||||||
import { useDnd } from 'contexts/DndContext'
|
import { useDnd } from 'contexts/DndContext'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
@ -23,22 +23,31 @@ export const StepCard = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex pos="relative">
|
<Flex pos="relative">
|
||||||
<Button
|
<HStack
|
||||||
as={HStack}
|
|
||||||
borderWidth="1px"
|
borderWidth="1px"
|
||||||
rounded="lg"
|
rounded="lg"
|
||||||
flex="1"
|
flex="1"
|
||||||
cursor={'grab'}
|
cursor={'grab'}
|
||||||
opacity={isMouseDown ? '0.4' : '1'}
|
opacity={isMouseDown ? '0.4' : '1'}
|
||||||
onMouseDown={handleMouseDown}
|
onMouseDown={handleMouseDown}
|
||||||
|
bgColor="white"
|
||||||
|
shadow="sm"
|
||||||
|
px="4"
|
||||||
|
py="2"
|
||||||
|
_hover={{ shadow: 'md' }}
|
||||||
|
transition="box-shadow 200ms"
|
||||||
>
|
>
|
||||||
{!isMouseDown && (
|
{!isMouseDown ? (
|
||||||
<>
|
<>
|
||||||
<StepIcon type={type} />
|
<StepIcon type={type} />
|
||||||
<StepTypeLabel type={type} />
|
<StepTypeLabel type={type} />
|
||||||
</>
|
</>
|
||||||
|
) : (
|
||||||
|
<Text color="white" userSelect="none">
|
||||||
|
Placeholder
|
||||||
|
</Text>
|
||||||
)}
|
)}
|
||||||
</Button>
|
</HStack>
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -46,23 +55,24 @@ export const StepCard = ({
|
|||||||
export const StepCardOverlay = ({
|
export const StepCardOverlay = ({
|
||||||
type,
|
type,
|
||||||
...props
|
...props
|
||||||
}: Omit<ButtonProps, 'type'> & { type: StepType }) => {
|
}: StackProps & { type: StepType }) => {
|
||||||
return (
|
return (
|
||||||
<Button
|
<HStack
|
||||||
as={HStack}
|
|
||||||
borderWidth="1px"
|
borderWidth="1px"
|
||||||
rounded="lg"
|
rounded="lg"
|
||||||
cursor={'grab'}
|
cursor={'grabbing'}
|
||||||
w="147px"
|
w="147px"
|
||||||
pos="fixed"
|
|
||||||
top="0"
|
|
||||||
left="0"
|
|
||||||
transition="none"
|
transition="none"
|
||||||
pointerEvents="none"
|
pointerEvents="none"
|
||||||
|
px="4"
|
||||||
|
py="2"
|
||||||
|
bgColor="white"
|
||||||
|
shadow="xl"
|
||||||
|
zIndex={2}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<StepIcon type={type} />
|
<StepIcon type={type} />
|
||||||
<StepTypeLabel type={type} />
|
<StepTypeLabel type={type} />
|
||||||
</Button>
|
</HStack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
SimpleGrid,
|
SimpleGrid,
|
||||||
useEventListener,
|
useEventListener,
|
||||||
|
Portal,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import {
|
import {
|
||||||
BubbleStepType,
|
BubbleStepType,
|
||||||
@ -38,10 +39,11 @@ export const StepTypesList = () => {
|
|||||||
const handleMouseDown = (e: React.MouseEvent, type: DraggableStepType) => {
|
const handleMouseDown = (e: React.MouseEvent, type: DraggableStepType) => {
|
||||||
const element = e.currentTarget as HTMLDivElement
|
const element = e.currentTarget as HTMLDivElement
|
||||||
const rect = element.getBoundingClientRect()
|
const rect = element.getBoundingClientRect()
|
||||||
const relativeX = e.clientX - rect.left
|
setPosition({ x: rect.left, y: rect.top })
|
||||||
const relativeY = e.clientY - rect.top
|
const x = e.clientX - rect.left
|
||||||
setPosition({ x: e.clientX - relativeX, y: e.clientY - relativeY })
|
const y = e.clientY - rect.top
|
||||||
setRelativeCoordinates({ x: relativeX, y: relativeY })
|
setRelativeCoordinates({ x, y })
|
||||||
|
console.log({ x: rect.left, y: rect.top })
|
||||||
setDraggedStepType(type)
|
setDraggedStepType(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,60 +62,76 @@ export const StepTypesList = () => {
|
|||||||
w="320px"
|
w="320px"
|
||||||
pos="absolute"
|
pos="absolute"
|
||||||
left="10px"
|
left="10px"
|
||||||
top="20px"
|
top="10px"
|
||||||
h="calc(100vh - 100px)"
|
h="calc(100vh - 80px)"
|
||||||
rounded="lg"
|
rounded="lg"
|
||||||
shadow="lg"
|
shadow="xl"
|
||||||
borderWidth="1px"
|
borderWidth="1px"
|
||||||
zIndex="10"
|
zIndex="2"
|
||||||
py="4"
|
py="4"
|
||||||
px="2"
|
px="2"
|
||||||
bgColor="white"
|
bgColor="gray.50"
|
||||||
|
spacing={6}
|
||||||
|
userSelect="none"
|
||||||
>
|
>
|
||||||
<Input placeholder="Search..." />
|
<Input placeholder="Search..." bgColor="white" />
|
||||||
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
<Stack>
|
||||||
Bubbles
|
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
||||||
</Text>
|
Bubbles
|
||||||
<SimpleGrid columns={2} spacing="2">
|
</Text>
|
||||||
{Object.values(BubbleStepType).map((type) => (
|
<SimpleGrid columns={2} spacing="2">
|
||||||
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
{Object.values(BubbleStepType).map((type) => (
|
||||||
))}
|
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
||||||
</SimpleGrid>
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
<Stack>
|
||||||
Inputs
|
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
||||||
</Text>
|
Inputs
|
||||||
<SimpleGrid columns={2} spacing="2">
|
</Text>
|
||||||
{Object.values(InputStepType).map((type) => (
|
<SimpleGrid columns={2} spacing="2">
|
||||||
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
{Object.values(InputStepType).map((type) => (
|
||||||
))}
|
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
||||||
</SimpleGrid>
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
<Stack>
|
||||||
Logic
|
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
||||||
</Text>
|
Logic
|
||||||
<SimpleGrid columns={2} spacing="2">
|
</Text>
|
||||||
{Object.values(LogicStepType).map((type) => (
|
<SimpleGrid columns={2} spacing="2">
|
||||||
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
{Object.values(LogicStepType).map((type) => (
|
||||||
))}
|
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
||||||
</SimpleGrid>
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack>
|
||||||
|
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
||||||
|
Integrations
|
||||||
|
</Text>
|
||||||
|
<SimpleGrid columns={2} spacing="2">
|
||||||
|
{Object.values(IntegrationStepType).map((type) => (
|
||||||
|
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
||||||
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
|
||||||
Integrations
|
|
||||||
</Text>
|
|
||||||
<SimpleGrid columns={2} spacing="2">
|
|
||||||
{Object.values(IntegrationStepType).map((type) => (
|
|
||||||
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
|
||||||
))}
|
|
||||||
</SimpleGrid>
|
|
||||||
{draggedStepType && (
|
{draggedStepType && (
|
||||||
<StepCardOverlay
|
<Portal>
|
||||||
type={draggedStepType}
|
<StepCardOverlay
|
||||||
onMouseUp={handleMouseUp}
|
type={draggedStepType}
|
||||||
style={{
|
onMouseUp={handleMouseUp}
|
||||||
transform: `translate(${position.x}px, ${position.y}px) rotate(-2deg)`,
|
pos="fixed"
|
||||||
}}
|
top="0"
|
||||||
/>
|
left="0"
|
||||||
|
style={{
|
||||||
|
transform: `translate(${position.x}px, ${position.y}px) rotate(-2deg)`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Portal>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
|
@ -25,7 +25,6 @@ export const BlockNode = ({ block }: Props) => {
|
|||||||
const { setMouseOverBlockId } = useDnd()
|
const { setMouseOverBlockId } = useDnd()
|
||||||
const { draggedStep, draggedStepType } = useDnd()
|
const { draggedStep, draggedStepType } = useDnd()
|
||||||
const [isMouseDown, setIsMouseDown] = useState(false)
|
const [isMouseDown, setIsMouseDown] = useState(false)
|
||||||
const [titleValue, setTitleValue] = useState(block.title)
|
|
||||||
const [isConnecting, setIsConnecting] = useState(false)
|
const [isConnecting, setIsConnecting] = useState(false)
|
||||||
const isPreviewing = useMemo(
|
const isPreviewing = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@ -41,7 +40,7 @@ export const BlockNode = ({ block }: Props) => {
|
|||||||
)
|
)
|
||||||
}, [block.id, connectingIds])
|
}, [block.id, connectingIds])
|
||||||
|
|
||||||
const handleTitleChange = (title: string) => setTitleValue(title)
|
const handleTitleSubmit = (title: string) => updateBlock(block.id, { title })
|
||||||
|
|
||||||
const handleMouseDown = () => {
|
const handleMouseDown = () => {
|
||||||
setIsMouseDown(true)
|
setIsMouseDown(true)
|
||||||
@ -49,6 +48,7 @@ export const BlockNode = ({ block }: Props) => {
|
|||||||
const handleMouseUp = () => {
|
const handleMouseUp = () => {
|
||||||
setIsMouseDown(false)
|
setIsMouseDown(false)
|
||||||
}
|
}
|
||||||
|
useEventListener('mouseup', handleMouseUp)
|
||||||
|
|
||||||
const handleMouseMove = (event: MouseEvent) => {
|
const handleMouseMove = (event: MouseEvent) => {
|
||||||
if (!isMouseDown) return
|
if (!isMouseDown) return
|
||||||
@ -85,24 +85,31 @@ export const BlockNode = ({ block }: Props) => {
|
|||||||
p="4"
|
p="4"
|
||||||
rounded="lg"
|
rounded="lg"
|
||||||
bgColor="blue.50"
|
bgColor="blue.50"
|
||||||
|
backgroundImage="linear-gradient(rgb(235, 239, 244), rgb(231, 234, 241))"
|
||||||
borderWidth="2px"
|
borderWidth="2px"
|
||||||
borderColor={
|
borderColor={
|
||||||
isConnecting || isOpened || isPreviewing ? 'blue.400' : 'gray.400'
|
isConnecting || isOpened || isPreviewing ? 'blue.400' : 'white'
|
||||||
}
|
}
|
||||||
minW="300px"
|
minW="300px"
|
||||||
transition="border 300ms"
|
transition="border 300ms, box-shadow 200ms"
|
||||||
pos="absolute"
|
pos="absolute"
|
||||||
style={{
|
style={{
|
||||||
transform: `translate(${block.graphCoordinates.x}px, ${block.graphCoordinates.y}px)`,
|
transform: `translate(${block.graphCoordinates.x}px, ${block.graphCoordinates.y}px)`,
|
||||||
}}
|
}}
|
||||||
onMouseDown={handleMouseDown}
|
onMouseDown={handleMouseDown}
|
||||||
onMouseUp={handleMouseUp}
|
|
||||||
onMouseEnter={handleMouseEnter}
|
onMouseEnter={handleMouseEnter}
|
||||||
onMouseLeave={handleMouseLeave}
|
onMouseLeave={handleMouseLeave}
|
||||||
|
cursor={isMouseDown ? 'grabbing' : 'pointer'}
|
||||||
|
boxShadow="0px 0px 0px 1px #e9edf3;"
|
||||||
|
_hover={{ shadow: 'lg' }}
|
||||||
>
|
>
|
||||||
<Editable value={titleValue} onChange={handleTitleChange}>
|
<Editable
|
||||||
|
defaultValue={block.title}
|
||||||
|
onSubmit={handleTitleSubmit}
|
||||||
|
fontWeight="semibold"
|
||||||
|
>
|
||||||
<EditablePreview
|
<EditablePreview
|
||||||
_hover={{ bgColor: 'blue.100' }}
|
_hover={{ bgColor: 'gray.300' }}
|
||||||
px="1"
|
px="1"
|
||||||
userSelect={'none'}
|
userSelect={'none'}
|
||||||
/>
|
/>
|
||||||
|
@ -99,15 +99,17 @@ export const ChoiceItemNode = ({
|
|||||||
onMouseEnter={handleMouseEnter}
|
onMouseEnter={handleMouseEnter}
|
||||||
onMouseLeave={handleMouseLeave}
|
onMouseLeave={handleMouseLeave}
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
|
shadow="sm"
|
||||||
|
_hover={{ shadow: 'md' }}
|
||||||
|
transition="box-shadow 200ms"
|
||||||
|
borderWidth="1px"
|
||||||
|
rounded="md"
|
||||||
|
px="4"
|
||||||
|
py="2"
|
||||||
|
borderColor={isOpened ? 'blue.400' : 'gray.300'}
|
||||||
>
|
>
|
||||||
<Editable
|
<Editable
|
||||||
ref={ref}
|
ref={ref}
|
||||||
px="4"
|
|
||||||
py="2"
|
|
||||||
rounded="md"
|
|
||||||
bgColor="green.200"
|
|
||||||
borderWidth="2px"
|
|
||||||
borderColor={isOpened ? 'blue.400' : 'gray.400'}
|
|
||||||
defaultValue={item.content ?? 'Click to edit'}
|
defaultValue={item.content ?? 'Click to edit'}
|
||||||
flex="1"
|
flex="1"
|
||||||
startWithEditView={!isDefined(item.content)}
|
startWithEditView={!isDefined(item.content)}
|
||||||
@ -115,7 +117,10 @@ export const ChoiceItemNode = ({
|
|||||||
onMouseDown={handleMouseDown}
|
onMouseDown={handleMouseDown}
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
>
|
>
|
||||||
<EditablePreview />
|
<EditablePreview
|
||||||
|
w="full"
|
||||||
|
color={item.content !== 'Click to edit' ? 'inherit' : 'gray.500'}
|
||||||
|
/>
|
||||||
<EditableInput />
|
<EditableInput />
|
||||||
</Editable>
|
</Editable>
|
||||||
{typebot && isSingleChoiceInput(typebot.steps.byId[item.stepId]) && (
|
{typebot && isSingleChoiceInput(typebot.steps.byId[item.stepId]) && (
|
||||||
@ -138,6 +143,8 @@ export const ChoiceItemNode = ({
|
|||||||
aria-label="Add item"
|
aria-label="Add item"
|
||||||
icon={<PlusIcon />}
|
icon={<PlusIcon />}
|
||||||
size="xs"
|
size="xs"
|
||||||
|
shadow="md"
|
||||||
|
colorScheme="blue"
|
||||||
onClick={handlePlusClick}
|
onClick={handlePlusClick}
|
||||||
/>
|
/>
|
||||||
</Fade>
|
</Fade>
|
||||||
|
@ -15,11 +15,12 @@ export const ChoiceItemNodeOverlay = ({
|
|||||||
px="4"
|
px="4"
|
||||||
py="2"
|
py="2"
|
||||||
rounded="md"
|
rounded="md"
|
||||||
bgColor="green.200"
|
bgColor="white"
|
||||||
borderWidth="2px"
|
borderWidth="1px"
|
||||||
borderColor={'gray.400'}
|
borderColor={'gray.300'}
|
||||||
w="212px"
|
w="212px"
|
||||||
pointerEvents="none"
|
pointerEvents="none"
|
||||||
|
shadow="lg"
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{item.content ?? 'Click to edit'}
|
{item.content ?? 'Click to edit'}
|
||||||
|
@ -44,14 +44,17 @@ export const ChoiceItemsList = ({ step }: ChoiceItemsListProps) => {
|
|||||||
}
|
}
|
||||||
useEventListener('mousemove', handleStepMove)
|
useEventListener('mousemove', handleStepMove)
|
||||||
|
|
||||||
const handleMouseUp = (e: React.MouseEvent<HTMLDivElement>) => {
|
const handleMouseUp = (e: MouseEvent) => {
|
||||||
if (expandedPlaceholderIndex === undefined || !draggedChoiceItem) return
|
if (!draggedChoiceItem) return
|
||||||
e.stopPropagation()
|
if (expandedPlaceholderIndex !== -1) {
|
||||||
|
e.stopPropagation()
|
||||||
|
createChoiceItem(draggedChoiceItem, expandedPlaceholderIndex)
|
||||||
|
}
|
||||||
setMouseOverBlockId(undefined)
|
setMouseOverBlockId(undefined)
|
||||||
setExpandedPlaceholderIndex(undefined)
|
setExpandedPlaceholderIndex(undefined)
|
||||||
setDraggedChoiceItem(undefined)
|
setDraggedChoiceItem(undefined)
|
||||||
createChoiceItem(draggedChoiceItem, expandedPlaceholderIndex)
|
|
||||||
}
|
}
|
||||||
|
useEventListener('mouseup', handleMouseUp, undefined, { capture: true })
|
||||||
|
|
||||||
const handleStepMouseDown = (
|
const handleStepMouseDown = (
|
||||||
{ absolute, relative }: { absolute: Coordinates; relative: Coordinates },
|
{ absolute, relative }: { absolute: Coordinates; relative: Coordinates },
|
||||||
@ -76,15 +79,10 @@ export const ChoiceItemsList = ({ step }: ChoiceItemsListProps) => {
|
|||||||
const stopPropagating = (e: React.MouseEvent) => e.stopPropagation()
|
const stopPropagating = (e: React.MouseEvent) => e.stopPropagation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack flex={1} spacing={1} onClick={stopPropagating}>
|
||||||
flex={1}
|
|
||||||
spacing={1}
|
|
||||||
onMouseUpCapture={handleMouseUp}
|
|
||||||
onClick={stopPropagating}
|
|
||||||
>
|
|
||||||
<Flex
|
<Flex
|
||||||
h={expandedPlaceholderIndex === 0 ? '50px' : '2px'}
|
h={expandedPlaceholderIndex === 0 ? '50px' : '2px'}
|
||||||
bgColor={'gray.400'}
|
bgColor={'gray.300'}
|
||||||
visibility={showSortPlaceholders ? 'visible' : 'hidden'}
|
visibility={showSortPlaceholders ? 'visible' : 'hidden'}
|
||||||
rounded="lg"
|
rounded="lg"
|
||||||
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
||||||
@ -107,7 +105,7 @@ export const ChoiceItemsList = ({ step }: ChoiceItemsListProps) => {
|
|||||||
? '50px'
|
? '50px'
|
||||||
: '2px'
|
: '2px'
|
||||||
}
|
}
|
||||||
bgColor={'gray.400'}
|
bgColor={'gray.300'}
|
||||||
visibility={showSortPlaceholders ? 'visible' : 'hidden'}
|
visibility={showSortPlaceholders ? 'visible' : 'hidden'}
|
||||||
rounded="lg"
|
rounded="lg"
|
||||||
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
||||||
@ -118,13 +116,15 @@ export const ChoiceItemsList = ({ step }: ChoiceItemsListProps) => {
|
|||||||
<Flex
|
<Flex
|
||||||
px="4"
|
px="4"
|
||||||
py="2"
|
py="2"
|
||||||
bgColor="gray.200"
|
borderWidth="1px"
|
||||||
borderWidth="2px"
|
borderColor="gray.300"
|
||||||
|
bgColor="gray.50"
|
||||||
rounded="md"
|
rounded="md"
|
||||||
pos="relative"
|
pos="relative"
|
||||||
align="center"
|
align="center"
|
||||||
|
cursor="not-allowed"
|
||||||
>
|
>
|
||||||
<Text>Default</Text>
|
<Text color="gray.500">Default</Text>
|
||||||
<SourceEndpoint
|
<SourceEndpoint
|
||||||
source={{
|
source={{
|
||||||
blockId: step.blockId,
|
blockId: step.blockId,
|
||||||
@ -140,7 +140,6 @@ export const ChoiceItemsList = ({ step }: ChoiceItemsListProps) => {
|
|||||||
<Portal>
|
<Portal>
|
||||||
<ChoiceItemNodeOverlay
|
<ChoiceItemNodeOverlay
|
||||||
item={draggedChoiceItem}
|
item={draggedChoiceItem}
|
||||||
onMouseUp={handleMouseUp}
|
|
||||||
pos="fixed"
|
pos="fixed"
|
||||||
top="0"
|
top="0"
|
||||||
left="0"
|
left="0"
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
import {
|
||||||
|
Modal,
|
||||||
|
ModalOverlay,
|
||||||
|
ModalContent,
|
||||||
|
ModalHeader,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalBody,
|
||||||
|
ModalFooter,
|
||||||
|
ModalBodyProps,
|
||||||
|
} from '@chakra-ui/react'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isOpen: boolean
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SettingsModal = ({
|
||||||
|
isOpen,
|
||||||
|
onClose,
|
||||||
|
...props
|
||||||
|
}: Props & ModalBodyProps) => {
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onClose={onClose}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader />
|
||||||
|
<ModalCloseButton />
|
||||||
|
<ModalBody {...props}>{props.children}</ModalBody>
|
||||||
|
<ModalFooter />
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
@ -4,7 +4,11 @@ import {
|
|||||||
PopoverBody,
|
PopoverBody,
|
||||||
useEventListener,
|
useEventListener,
|
||||||
Portal,
|
Portal,
|
||||||
|
Stack,
|
||||||
|
IconButton,
|
||||||
|
Flex,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
|
import { ExpandIcon } from 'assets/icons'
|
||||||
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
||||||
import {
|
import {
|
||||||
InputStep,
|
InputStep,
|
||||||
@ -30,9 +34,10 @@ import { SetVariableSettingsBody } from './bodies/SetVariableSettingsBody'
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
step: Step
|
step: Step
|
||||||
|
onExpandClick: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SettingsPopoverContent = ({ step }: Props) => {
|
export const SettingsPopoverContent = ({ step, onExpandClick }: Props) => {
|
||||||
const ref = useRef<HTMLDivElement | null>(null)
|
const ref = useRef<HTMLDivElement | null>(null)
|
||||||
const handleMouseDown = (e: React.MouseEvent) => e.stopPropagation()
|
const handleMouseDown = (e: React.MouseEvent) => e.stopPropagation()
|
||||||
|
|
||||||
@ -44,15 +49,33 @@ export const SettingsPopoverContent = ({ step }: Props) => {
|
|||||||
<Portal>
|
<Portal>
|
||||||
<PopoverContent onMouseDown={handleMouseDown}>
|
<PopoverContent onMouseDown={handleMouseDown}>
|
||||||
<PopoverArrow />
|
<PopoverArrow />
|
||||||
<PopoverBody p="6" overflowY="scroll" maxH="400px" ref={ref}>
|
<PopoverBody
|
||||||
<SettingsPopoverBodyContent step={step} />
|
px="6"
|
||||||
|
pb="6"
|
||||||
|
pt="4"
|
||||||
|
overflowY="scroll"
|
||||||
|
maxH="400px"
|
||||||
|
ref={ref}
|
||||||
|
shadow="lg"
|
||||||
|
>
|
||||||
|
<Stack>
|
||||||
|
<Flex justifyContent="flex-end">
|
||||||
|
<IconButton
|
||||||
|
aria-label="expand"
|
||||||
|
icon={<ExpandIcon />}
|
||||||
|
size="xs"
|
||||||
|
onClick={onExpandClick}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
<StepSettings step={step} />
|
||||||
|
</Stack>
|
||||||
</PopoverBody>
|
</PopoverBody>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Portal>
|
</Portal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const SettingsPopoverBodyContent = ({ step }: Props) => {
|
export const StepSettings = ({ step }: { step: Step }) => {
|
||||||
const { updateStep } = useTypebot()
|
const { updateStep } = useTypebot()
|
||||||
const handleOptionsChange = (options: StepOptions) =>
|
const handleOptionsChange = (options: StepOptions) =>
|
||||||
updateStep(step.id, { options } as Partial<InputStep>)
|
updateStep(step.id, { options } as Partial<InputStep>)
|
||||||
|
@ -107,22 +107,20 @@ export const ComparisonsList = ({
|
|||||||
>
|
>
|
||||||
<Stack
|
<Stack
|
||||||
key={comparisonId}
|
key={comparisonId}
|
||||||
bgColor="blue.50"
|
|
||||||
p="4"
|
p="4"
|
||||||
rounded="md"
|
rounded="md"
|
||||||
flex="1"
|
flex="1"
|
||||||
|
borderWidth="1px"
|
||||||
>
|
>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={comparisons.byId[comparisonId].variableId}
|
initialVariableId={comparisons.byId[comparisonId].variableId}
|
||||||
onSelectVariable={handleVariableSelected(comparisonId)}
|
onSelectVariable={handleVariableSelected(comparisonId)}
|
||||||
bgColor="white"
|
|
||||||
placeholder="Search for a variable"
|
placeholder="Search for a variable"
|
||||||
/>
|
/>
|
||||||
<DropdownList<ComparisonOperators>
|
<DropdownList<ComparisonOperators>
|
||||||
currentItem={comparisons.byId[comparisonId].comparisonOperator}
|
currentItem={comparisons.byId[comparisonId].comparisonOperator}
|
||||||
onItemSelect={handleComparisonOperatorSelected(comparisonId)}
|
onItemSelect={handleComparisonOperatorSelected(comparisonId)}
|
||||||
items={Object.values(ComparisonOperators)}
|
items={Object.values(ComparisonOperators)}
|
||||||
bgColor="white"
|
|
||||||
/>
|
/>
|
||||||
{comparisons.byId[comparisonId].comparisonOperator !==
|
{comparisons.byId[comparisonId].comparisonOperator !==
|
||||||
ComparisonOperators.IS_SET && (
|
ComparisonOperators.IS_SET && (
|
||||||
@ -130,7 +128,6 @@ export const ComparisonsList = ({
|
|||||||
delay={100}
|
delay={100}
|
||||||
initialValue={comparisons.byId[comparisonId].value ?? ''}
|
initialValue={comparisons.byId[comparisonId].value ?? ''}
|
||||||
onChange={handleValueChange(comparisonId)}
|
onChange={handleValueChange(comparisonId)}
|
||||||
bgColor="white"
|
|
||||||
placeholder="Type a value..."
|
placeholder="Type a value..."
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -141,16 +138,22 @@ export const ComparisonsList = ({
|
|||||||
aria-label="Remove comparison"
|
aria-label="Remove comparison"
|
||||||
onClick={deleteComparison(comparisonId)}
|
onClick={deleteComparison(comparisonId)}
|
||||||
pos="absolute"
|
pos="absolute"
|
||||||
left="-10px"
|
left="-15px"
|
||||||
top="-10px"
|
top="-15px"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
shadow="md"
|
||||||
/>
|
/>
|
||||||
</Fade>
|
</Fade>
|
||||||
</Flex>
|
</Flex>
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
<Button leftIcon={<PlusIcon />} onClick={createComparison} flexShrink={0}>
|
<Button
|
||||||
Add
|
leftIcon={<PlusIcon />}
|
||||||
|
onClick={createComparison}
|
||||||
|
flexShrink={0}
|
||||||
|
colorScheme="blue"
|
||||||
|
>
|
||||||
|
Add a comparison
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
|
@ -87,16 +87,22 @@ export const ExtractCellList = ({
|
|||||||
aria-label="Remove cell"
|
aria-label="Remove cell"
|
||||||
onClick={deleteCell(cellId)}
|
onClick={deleteCell(cellId)}
|
||||||
pos="absolute"
|
pos="absolute"
|
||||||
left="-10px"
|
left="-15px"
|
||||||
top="-10px"
|
top="-15px"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
shadow="md"
|
||||||
/>
|
/>
|
||||||
</Fade>
|
</Fade>
|
||||||
</Flex>
|
</Flex>
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
<Button leftIcon={<PlusIcon />} onClick={createCell} flexShrink={0}>
|
<Button
|
||||||
Add
|
leftIcon={<PlusIcon />}
|
||||||
|
onClick={createCell}
|
||||||
|
flexShrink={0}
|
||||||
|
colorScheme="blue"
|
||||||
|
>
|
||||||
|
Add a value
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
@ -118,12 +124,11 @@ export const CellWithVariableIdStack = ({
|
|||||||
onCellChange({ ...cell, variableId: variable.id })
|
onCellChange({ ...cell, variableId: variable.id })
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Stack bgColor="blue.50" p="4" rounded="md" flex="1">
|
<Stack p="4" rounded="md" flex="1" borderWidth="1px">
|
||||||
<DropdownList<string>
|
<DropdownList<string>
|
||||||
currentItem={cell.column}
|
currentItem={cell.column}
|
||||||
onItemSelect={handleColumnSelect}
|
onItemSelect={handleColumnSelect}
|
||||||
items={columns}
|
items={columns}
|
||||||
bgColor="white"
|
|
||||||
placeholder="Select a column"
|
placeholder="Select a column"
|
||||||
/>
|
/>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
|
@ -87,16 +87,22 @@ export const UpdateCellList = ({
|
|||||||
aria-label="Remove cell"
|
aria-label="Remove cell"
|
||||||
onClick={deleteCell(cellId)}
|
onClick={deleteCell(cellId)}
|
||||||
pos="absolute"
|
pos="absolute"
|
||||||
left="-10px"
|
left="-15px"
|
||||||
top="-10px"
|
top="-15px"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
shadow="md"
|
||||||
/>
|
/>
|
||||||
</Fade>
|
</Fade>
|
||||||
</Flex>
|
</Flex>
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
<Button leftIcon={<PlusIcon />} onClick={createCell} flexShrink={0}>
|
<Button
|
||||||
Add
|
leftIcon={<PlusIcon />}
|
||||||
|
onClick={createCell}
|
||||||
|
flexShrink={0}
|
||||||
|
colorScheme="blue"
|
||||||
|
>
|
||||||
|
Add a value
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
@ -118,12 +124,11 @@ export const CellWithValueStack = ({
|
|||||||
onCellChange({ ...cell, value })
|
onCellChange({ ...cell, value })
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Stack bgColor="blue.50" p="4" rounded="md" flex="1">
|
<Stack p="4" rounded="md" flex="1" borderWidth="1px">
|
||||||
<DropdownList<string>
|
<DropdownList<string>
|
||||||
currentItem={cell.column}
|
currentItem={cell.column}
|
||||||
onItemSelect={handleColumnSelect}
|
onItemSelect={handleColumnSelect}
|
||||||
items={columns}
|
items={columns}
|
||||||
bgColor="white"
|
|
||||||
placeholder="Select a column"
|
placeholder="Select a column"
|
||||||
/>
|
/>
|
||||||
<InputWithVariable
|
<InputWithVariable
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Box, BoxProps } from '@chakra-ui/react'
|
import { Box, BoxProps, Flex } from '@chakra-ui/react'
|
||||||
import { ConnectingSourceIds, useGraph } from 'contexts/GraphContext'
|
import { ConnectingSourceIds, useGraph } from 'contexts/GraphContext'
|
||||||
import React, { MouseEvent, useEffect, useRef } from 'react'
|
import React, { MouseEvent, useEffect, useRef } from 'react'
|
||||||
|
|
||||||
@ -28,14 +28,20 @@ export const SourceEndpoint = ({
|
|||||||
}, [ref])
|
}, [ref])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Flex
|
||||||
ref={ref}
|
ref={ref}
|
||||||
boxSize="15px"
|
boxSize="18px"
|
||||||
rounded="full"
|
rounded="full"
|
||||||
bgColor="gray.500"
|
|
||||||
onMouseDown={handleMouseDown}
|
onMouseDown={handleMouseDown}
|
||||||
cursor="pointer"
|
cursor="copy"
|
||||||
|
borderWidth="1px"
|
||||||
|
borderColor="gray.400"
|
||||||
|
bgColor="white"
|
||||||
|
justify="center"
|
||||||
|
align="center"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
>
|
||||||
|
<Box bgColor="gray.400" rounded="full" boxSize="7px" />
|
||||||
|
</Flex>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
HStack,
|
HStack,
|
||||||
Popover,
|
Popover,
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
|
useDisclosure,
|
||||||
useEventListener,
|
useEventListener,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import React, { useEffect, useMemo, useState } from 'react'
|
import React, { useEffect, useMemo, useState } from 'react'
|
||||||
@ -28,6 +29,8 @@ import { SourceEndpoint } from './SourceEndpoint'
|
|||||||
import { hasDefaultConnector } from 'services/typebots'
|
import { hasDefaultConnector } from 'services/typebots'
|
||||||
import { TargetEndpoint } from './TargetEndpoint'
|
import { TargetEndpoint } from './TargetEndpoint'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import { SettingsModal } from './SettingsPopoverContent/SettingsModal'
|
||||||
|
import { StepSettings } from './SettingsPopoverContent/SettingsPopoverContent'
|
||||||
|
|
||||||
export const StepNode = ({
|
export const StepNode = ({
|
||||||
step,
|
step,
|
||||||
@ -54,6 +57,11 @@ export const StepNode = ({
|
|||||||
const [isEditing, setIsEditing] = useState<boolean>(
|
const [isEditing, setIsEditing] = useState<boolean>(
|
||||||
isTextBubbleStep(step) && step.content.plainText === ''
|
isTextBubbleStep(step) && step.content.plainText === ''
|
||||||
)
|
)
|
||||||
|
const {
|
||||||
|
isOpen: isModalOpen,
|
||||||
|
onOpen: onModalOpen,
|
||||||
|
onClose: onModalClose,
|
||||||
|
} = useDisclosure()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsConnecting(
|
setIsConnecting(
|
||||||
@ -190,8 +198,8 @@ export const StepNode = ({
|
|||||||
flex="1"
|
flex="1"
|
||||||
userSelect="none"
|
userSelect="none"
|
||||||
p="3"
|
p="3"
|
||||||
borderWidth="2px"
|
borderWidth="1px"
|
||||||
borderColor={isConnecting || isOpened ? 'blue.400' : 'gray.400'}
|
borderColor={isConnecting || isOpened ? 'blue.400' : 'gray.300'}
|
||||||
rounded="lg"
|
rounded="lg"
|
||||||
cursor={'pointer'}
|
cursor={'pointer'}
|
||||||
bgColor="white"
|
bgColor="white"
|
||||||
@ -213,7 +221,7 @@ export const StepNode = ({
|
|||||||
}}
|
}}
|
||||||
pos="absolute"
|
pos="absolute"
|
||||||
right="15px"
|
right="15px"
|
||||||
top="19px"
|
top="18px"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</HStack>
|
</HStack>
|
||||||
@ -237,7 +245,12 @@ export const StepNode = ({
|
|||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
{hasPopover(step) && <SettingsPopoverContent step={step} />}
|
{hasPopover(step) && (
|
||||||
|
<SettingsPopoverContent step={step} onExpandClick={onModalOpen} />
|
||||||
|
)}
|
||||||
|
<SettingsModal isOpen={isModalOpen} onClose={onModalClose}>
|
||||||
|
<StepSettings step={step} />
|
||||||
|
</SettingsModal>
|
||||||
</Popover>
|
</Popover>
|
||||||
)}
|
)}
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
|
@ -16,6 +16,7 @@ export const StepNodeOverlay = ({
|
|||||||
cursor={'grab'}
|
cursor={'grab'}
|
||||||
w="264px"
|
w="264px"
|
||||||
pointerEvents="none"
|
pointerEvents="none"
|
||||||
|
shadow="lg"
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<StepIcon type={step.type} />
|
<StepIcon type={step.type} />
|
||||||
|
@ -102,7 +102,7 @@ export const StepsList = ({
|
|||||||
? '50px'
|
? '50px'
|
||||||
: '2px'
|
: '2px'
|
||||||
}
|
}
|
||||||
bgColor={'gray.400'}
|
bgColor={'gray.300'}
|
||||||
visibility={showSortPlaceholders ? 'visible' : 'hidden'}
|
visibility={showSortPlaceholders ? 'visible' : 'hidden'}
|
||||||
rounded="lg"
|
rounded="lg"
|
||||||
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
||||||
@ -125,7 +125,7 @@ export const StepsList = ({
|
|||||||
? '50px'
|
? '50px'
|
||||||
: '2px'
|
: '2px'
|
||||||
}
|
}
|
||||||
bgColor={'gray.400'}
|
bgColor={'gray.300'}
|
||||||
visibility={showSortPlaceholders ? 'visible' : 'hidden'}
|
visibility={showSortPlaceholders ? 'visible' : 'hidden'}
|
||||||
rounded="lg"
|
rounded="lg"
|
||||||
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
||||||
|
@ -103,9 +103,9 @@ export const DrawingEdge = () => {
|
|||||||
return (
|
return (
|
||||||
<path
|
<path
|
||||||
d={path}
|
d={path}
|
||||||
stroke="#718096"
|
stroke="#1a5fff"
|
||||||
strokeWidth="2px"
|
strokeWidth="2px"
|
||||||
markerEnd="url(#arrow)"
|
markerEnd="url(#blue-arrow)"
|
||||||
fill="none"
|
fill="none"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -126,7 +126,7 @@ export const Edge = ({
|
|||||||
d={path}
|
d={path}
|
||||||
stroke={isPreviewing ? '#1a5fff' : '#718096'}
|
stroke={isPreviewing ? '#1a5fff' : '#718096'}
|
||||||
strokeWidth="2px"
|
strokeWidth="2px"
|
||||||
markerEnd="url(#arrow)"
|
markerEnd={isPreviewing ? 'url(#blue-arrow)' : 'url(#arrow)'}
|
||||||
fill="none"
|
fill="none"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -74,6 +74,21 @@ export const Edges = () => {
|
|||||||
fill="#718096"
|
fill="#718096"
|
||||||
/>
|
/>
|
||||||
</marker>
|
</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="#1a5fff"
|
||||||
|
/>
|
||||||
|
</marker>
|
||||||
</chakra.svg>
|
</chakra.svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,18 @@ const fonts = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const colors = {
|
const colors = {
|
||||||
|
gray: {
|
||||||
|
50: '#F9FAFB',
|
||||||
|
100: '#F3F4F6',
|
||||||
|
200: '#E5E7EB',
|
||||||
|
300: '#D1D5DB',
|
||||||
|
400: '#9CA3AF',
|
||||||
|
500: '#6B7280',
|
||||||
|
600: '#4B5563',
|
||||||
|
700: '#374151',
|
||||||
|
800: '#1F2937',
|
||||||
|
900: '#111827',
|
||||||
|
},
|
||||||
blue: {
|
blue: {
|
||||||
50: '#e0edff',
|
50: '#e0edff',
|
||||||
100: '#b0caff',
|
100: '#b0caff',
|
||||||
|
@ -291,7 +291,7 @@ export const getEndpointTopOffset = (
|
|||||||
const endpointRef = endpoints.byId[id]?.ref
|
const endpointRef = endpoints.byId[id]?.ref
|
||||||
if (!endpointRef) return 0
|
if (!endpointRef) return 0
|
||||||
return (
|
return (
|
||||||
7 +
|
8 +
|
||||||
(endpointRef.current?.getBoundingClientRect().top ?? 0) -
|
(endpointRef.current?.getBoundingClientRect().top ?? 0) -
|
||||||
graphPosition.y -
|
graphPosition.y -
|
||||||
headerHeight
|
headerHeight
|
||||||
|
Reference in New Issue
Block a user