Add "turn into" option in block context menu

Closes #1302
This commit is contained in:
Baptiste Arnaud
2024-03-05 15:46:28 +01:00
parent 84d6c594af
commit 2fb379b102
16 changed files with 244 additions and 13 deletions

View File

@@ -0,0 +1,95 @@
import {
MenuList,
MenuItem,
useDisclosure,
Menu,
MenuButton,
HStack,
Text,
} from '@chakra-ui/react'
import { RepeatIcon, ChevronRightIcon } from '@/components/icons'
import { useDebouncedCallback } from 'use-debounce'
import { useForgedBlock } from '@/features/forge/hooks/useForgedBlock'
import { ForgedBlockIcon } from '@/features/forge/ForgedBlockIcon'
import { ForgedBlock } from '@typebot.io/forge-schemas'
import { TurnableIntoParam } from '@typebot.io/forge'
import { ZodObject } from 'zod'
import { BlockV6 } from '@typebot.io/schemas'
type Props = {
block: BlockV6
onTurnIntoClick: (
params: TurnableIntoParam,
/* eslint-disable @typescript-eslint/no-explicit-any */
blockSchema: ZodObject<any>
) => void
}
export const ForgedBlockTurnIntoMenu = ({ block, onTurnIntoClick }: Props) => {
const { actionDef } = useForgedBlock(
block.type,
'options' in block ? block.options?.action : undefined
)
const { onClose, onOpen, isOpen } = useDisclosure()
const debounceSubMenuClose = useDebouncedCallback(onClose, 200)
const handleMouseEnter = () => {
debounceSubMenuClose.cancel()
onOpen()
}
if (
!actionDef ||
!actionDef?.turnableInto ||
actionDef?.turnableInto.length === 0
)
return null
return (
<Menu isOpen={isOpen} placement="right" offset={[0, 0]} onClose={onClose}>
<MenuButton
as={MenuItem}
onClick={onOpen}
onMouseEnter={handleMouseEnter}
onMouseLeave={debounceSubMenuClose}
icon={<RepeatIcon />}
>
<HStack justifyContent="space-between">
<Text>Turn into</Text>
<ChevronRightIcon />
</HStack>
</MenuButton>
<MenuList
onMouseEnter={handleMouseEnter}
onMouseLeave={debounceSubMenuClose}
>
{actionDef.turnableInto.map((params) => (
<TurnIntoMenuItem
key={params.blockType}
blockType={params.blockType}
onClick={(blockSchema) => onTurnIntoClick(params, blockSchema)}
/>
))}
</MenuList>
</Menu>
)
}
const TurnIntoMenuItem = ({
blockType,
onClick,
}: {
blockType: ForgedBlock['type']
onClick: (blockSchema: ZodObject<any>) => void
}) => {
const { blockDef, blockSchema } = useForgedBlock(blockType)
if (!blockDef || !blockSchema) return null
return (
<MenuItem
icon={<ForgedBlockIcon type={blockType} />}
onClick={() => onClick(blockSchema)}
>
{blockDef.name}
</MenuItem>
)
}

View File

@@ -1,12 +1,9 @@
import { useMemo } from 'react'
import { forgedBlockSchemas, forgedBlocks } from '@typebot.io/forge-schemas'
import { enabledBlocks } from '@typebot.io/forge-repository'
import { BlockWithOptions } from '@typebot.io/schemas'
import { BlockV6 } from '@typebot.io/schemas'
export const useForgedBlock = (
blockType: BlockWithOptions['type'],
action?: string
) =>
export const useForgedBlock = (blockType: BlockV6['type'], action?: string) =>
useMemo(() => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((enabledBlocks as any).includes(blockType) === false) return {}