import { Editable, EditableInput, EditablePreview, Stack, useEventListener, } from '@chakra-ui/react' import React, { useEffect, useMemo, useState } from 'react' import { Block } from 'models' import { useGraph } from 'contexts/GraphContext' import { useStepDnd } from 'contexts/StepDndContext' 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' type Props = { block: Block } export const BlockNode = ({ block }: Props) => { const { connectingIds, setConnectingIds, previewingEdgeId, blocksCoordinates, updateBlockCoordinates, isReadOnly, } = useGraph() const { typebot, updateBlock } = useTypebot() const { setMouseOverBlockId } = useStepDnd() const { draggedStep, draggedStepType } = useStepDnd() const [isMouseDown, setIsMouseDown] = useState(false) const [isConnecting, setIsConnecting] = useState(false) const isPreviewing = useMemo(() => { if (!previewingEdgeId) return const edge = typebot?.edges.byId[previewingEdgeId] return edge?.to.blockId === block.id || edge?.from.blockId === block.id }, [block.id, previewingEdgeId, typebot?.edges.byId]) const blockCoordinates = useMemo( () => blocksCoordinates?.byId[block.id], [block.id, blocksCoordinates?.byId] ) const [debouncedBlockPosition] = useDebounce(blockCoordinates, 100) useEffect(() => { if (!debouncedBlockPosition || isReadOnly) return if ( debouncedBlockPosition?.x === block.graphCoordinates.x && debouncedBlockPosition.y === block.graphCoordinates.y ) return updateBlock(block.id, { 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(block.id, { 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 (draggedStepType || draggedStep) setMouseOverBlockId(block.id) if (connectingIds) setConnectingIds({ ...connectingIds, target: { blockId: block.id } }) } const handleMouseLeave = () => { setMouseOverBlockId(undefined) if (connectingIds) setConnectingIds({ ...connectingIds, target: undefined }) } return ( renderMenu={() => } isDisabled={isReadOnly} > {(ref, isOpened) => ( {typebot && ( )} )} ) }