/* eslint-disable @typescript-eslint/no-explicit-any */ import { Stack, Text, SimpleGrid, useEventListener, Portal, Flex, IconButton, Input, Tooltip, Fade, useColorModeValue, } from '@chakra-ui/react' import { useBlockDnd } from '@/features/graph/providers/GraphDndProvider' import React, { useState } from 'react' import { BlockCard } from './BlockCard' import { LockedIcon, UnlockedIcon } from '@/components/icons' import { BlockCardOverlay } from './BlockCardOverlay' import { headerHeight } from '../constants' import { useTranslate } from '@tolgee/react' import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants' import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants' import { IntegrationBlockType } from '@typebot.io/schemas/features/blocks/integrations/constants' import { LogicBlockType } from '@typebot.io/schemas/features/blocks/logic/constants' import { BlockV6 } from '@typebot.io/schemas' import { useDebouncedCallback } from 'use-debounce' import { forgedBlocks } from '@typebot.io/forge-repository/definitions' // Integration blocks migrated to forged blocks const legacyIntegrationBlocks = [IntegrationBlockType.OPEN_AI] export const BlocksSideBar = () => { const { t } = useTranslate() const { setDraggedBlockType, draggedBlockType } = useBlockDnd() const [position, setPosition] = useState({ x: 0, y: 0, }) const [relativeCoordinates, setRelativeCoordinates] = useState({ x: 0, y: 0 }) const [isLocked, setIsLocked] = useState(true) const [isExtended, setIsExtended] = useState(true) const [searchInput, setSearchInput] = useState('') const closeSideBar = useDebouncedCallback(() => setIsExtended(false), 200) const handleMouseMove = (event: MouseEvent) => { if (!draggedBlockType) return const { clientX, clientY } = event setPosition({ ...position, x: clientX - relativeCoordinates.x, y: clientY - relativeCoordinates.y, }) } useEventListener('mousemove', handleMouseMove) const handleMouseDown = (e: React.MouseEvent, type: BlockV6['type']) => { const element = e.currentTarget as HTMLDivElement const rect = element.getBoundingClientRect() setPosition({ x: rect.left, y: rect.top }) const x = e.clientX - rect.left const y = e.clientY - rect.top setRelativeCoordinates({ x, y }) setDraggedBlockType(type) } const handleMouseUp = () => { if (!draggedBlockType) return setDraggedBlockType(undefined) setPosition({ x: 0, y: 0, }) } useEventListener('mouseup', handleMouseUp) const handleLockClick = () => setIsLocked(!isLocked) const handleDockBarEnter = () => { closeSideBar.flush() setIsExtended(true) } const handleMouseLeave = () => { if (isLocked) return closeSideBar() } const handleSearchInputChange = (event: { target: { value: React.SetStateAction } }) => { setSearchInput(event.target.value) } const blocksArray = Object.values(forgedBlocks) const filteredForgedBlockIds = blocksArray .filter((block) => { return ( block.id.toLowerCase().includes(searchInput.toLowerCase()) || (block.tags && block.tags.some((tag: string) => tag.toLowerCase().includes(searchInput.toLowerCase()) )) || block.name.toLowerCase().includes(searchInput.toLowerCase()) ) }) .map((block) => block.id) return ( : } aria-label={ isLocked ? t('editor.sidebarBlocks.sidebar.icon.unlock.label') : t('editor.sidebarBlocks.sidebar.icon.lock.label') } size="sm" onClick={handleLockClick} /> {t('editor.sidebarBlocks.blockType.bubbles.heading')} {Object.values(BubbleBlockType) .filter((type) => type.toLowerCase().includes(searchInput.toLowerCase()) ) .map((type) => ( ))} {t('editor.sidebarBlocks.blockType.inputs.heading')} {Object.values(InputBlockType) .filter((type) => type.toLowerCase().includes(searchInput.toLowerCase()) ) .map((type) => ( ))} {t('editor.sidebarBlocks.blockType.logic.heading')} {Object.values(LogicBlockType) .filter((type) => type.toLowerCase().includes(searchInput.toLowerCase()) ) .map((type) => ( ))} {t('editor.sidebarBlocks.blockType.integrations.heading')} {Object.values(IntegrationBlockType) .filter((type) => type.toLowerCase().includes(searchInput.toLowerCase()) ) .concat(filteredForgedBlockIds as any) .filter((type) => !legacyIntegrationBlocks.includes(type)) .map((type) => ( ))} {draggedBlockType && ( )} ) }