import { Editable, EditableInput, EditablePreview, Stack, useEventListener, } from '@chakra-ui/react' import React, { useEffect, useRef, useState } from 'react' import { Block } from 'models' import { useGraph } from 'contexts/GraphContext' import { useStepDnd } from 'contexts/GraphDndContext' import { StepNodesList } from '../StepNode/StepNodesList' import { isNotDefined } from 'utils' import { useTypebot } from 'contexts/TypebotContext/TypebotContext' import { ContextMenu } from 'components/shared/ContextMenu' import { BlockNodeContextMenu } from './BlockNodeContextMenu' import { useDebounce } from 'use-debounce' import { setMultipleRefs } from 'services/utils' type Props = { block: Block blockIndex: number } export const BlockNode = ({ block, blockIndex }: Props) => { const { connectingIds, setConnectingIds, previewingEdge, blocksCoordinates, updateBlockCoordinates, isReadOnly, } = useGraph() const { typebot, updateBlock } = useTypebot() const { setMouseOverBlock, mouseOverBlock } = useStepDnd() const [isMouseDown, setIsMouseDown] = useState(false) const [isConnecting, setIsConnecting] = useState(false) const isPreviewing = previewingEdge?.to.blockId === block.id || previewingEdge?.from.blockId === block.id const isStartBlock = block.steps.length === 1 && block.steps[0].type === 'start' const blockCoordinates = blocksCoordinates[block.id] const blockRef = useRef(null) const [debouncedBlockPosition] = useDebounce(blockCoordinates, 100) useEffect(() => { if (!debouncedBlockPosition || isReadOnly) return if ( debouncedBlockPosition?.x === block.graphCoordinates.x && debouncedBlockPosition.y === block.graphCoordinates.y ) return updateBlock(blockIndex, { graphCoordinates: debouncedBlockPosition }) // eslint-disable-next-line react-hooks/exhaustive-deps }, [debouncedBlockPosition]) useEffect(() => { setIsConnecting( connectingIds?.target?.blockId === block.id && isNotDefined(connectingIds.target?.stepId) ) }, [block.id, connectingIds]) const handleTitleSubmit = (title: string) => updateBlock(blockIndex, { title }) const handleMouseDown = () => { setIsMouseDown(true) } const handleMouseUp = () => { setIsMouseDown(false) } useEventListener('mouseup', handleMouseUp) const handleMouseMove = (event: MouseEvent) => { if (!isMouseDown) return const { movementX, movementY } = event if (!blockCoordinates) return updateBlockCoordinates(block.id, { x: blockCoordinates.x + movementX, y: blockCoordinates.y + movementY, }) } useEventListener('mousemove', handleMouseMove) const handleMouseEnter = () => { if (isReadOnly) return if (mouseOverBlock?.id !== block.id && !isStartBlock) setMouseOverBlock({ id: block.id, ref: blockRef }) if (connectingIds) setConnectingIds({ ...connectingIds, target: { blockId: block.id } }) } const handleMouseLeave = () => { if (isReadOnly) return setMouseOverBlock(undefined) if (connectingIds) setConnectingIds({ ...connectingIds, target: undefined }) } return ( renderMenu={() => } isDisabled={isReadOnly} > {(ref, isOpened) => ( {typebot && ( )} )} ) }