2
0
Files
bot/apps/builder/src/features/graph/components/endpoints/EventSourceEndpoint.tsx
2024-03-26 19:27:58 +01:00

131 lines
3.1 KiB
TypeScript

import {
BoxProps,
Flex,
useColorModeValue,
useEventListener,
} from '@chakra-ui/react'
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'
import { useEndpoints } from '../../providers/EndpointsProvider'
import { useGraph } from '../../providers/GraphProvider'
import { TEventSource } from '@typebot.io/schemas'
const endpointHeight = 32
export const EventSourceEndpoint = ({
source,
isHidden,
...props
}: BoxProps & {
source: TEventSource
isHidden?: boolean
}) => {
const color = useColorModeValue('blue.200', 'blue.100')
const connectedColor = useColorModeValue('blue.300', 'blue.200')
const bg = useColorModeValue('gray.100', 'gray.700')
const { setConnectingIds, previewingEdge, graphPosition } = useGraph()
const { setSourceEndpointYOffset, deleteSourceEndpointYOffset } =
useEndpoints()
const [eventTransformProp, setEventTransformProp] = useState<string>()
const ref = useRef<HTMLDivElement | null>(null)
useLayoutEffect(() => {
const mutationObserver = new MutationObserver((entries) => {
setEventTransformProp((entries[0].target as HTMLElement).style.transform)
})
const groupElement = document.getElementById(`event-${source.eventId}`)
if (!groupElement) return
mutationObserver.observe(groupElement, {
attributes: true,
attributeFilter: ['style'],
})
return () => {
mutationObserver.disconnect()
}
}, [source.eventId])
useEffect(() => {
const y = ref.current
? Number(
(
(ref.current?.getBoundingClientRect().y +
(endpointHeight * graphPosition.scale) / 2 -
graphPosition.y) /
graphPosition.scale
).toFixed(2)
)
: undefined
if (y === undefined) return
setSourceEndpointYOffset?.({
id: source.eventId,
y,
})
}, [
graphPosition.scale,
graphPosition.y,
setSourceEndpointYOffset,
source.eventId,
eventTransformProp,
])
useEffect(
() => () => {
deleteSourceEndpointYOffset?.(source.eventId)
},
[deleteSourceEndpointYOffset, source.eventId]
)
useEventListener(
'pointerdown',
(e) => {
e.stopPropagation()
setConnectingIds({ source })
},
ref.current
)
useEventListener(
'mousedown',
(e) => {
e.stopPropagation()
},
ref.current
)
return (
<Flex
ref={ref}
data-testid="endpoint"
boxSize="32px"
rounded="full"
cursor="copy"
justify="center"
align="center"
pointerEvents="all"
visibility={isHidden ? 'hidden' : 'visible'}
{...props}
>
<Flex
boxSize="20px"
justify="center"
align="center"
bg={bg}
rounded="full"
>
<Flex
boxSize="13px"
rounded="full"
borderWidth="3.5px"
shadow={`sm`}
borderColor={
previewingEdge &&
'eventId' in previewingEdge.from &&
previewingEdge.from.eventId === source.eventId
? connectedColor
: color
}
/>
</Flex>
</Flex>
)
}