feat(bubbles): ✨ Add image bubble
This commit is contained in:
@ -0,0 +1,54 @@
|
||||
import {
|
||||
Portal,
|
||||
PopoverContent,
|
||||
PopoverArrow,
|
||||
PopoverBody,
|
||||
} from '@chakra-ui/react'
|
||||
import { ImagePopoverContent } from 'components/shared/ImageUploadContent'
|
||||
import { useTypebot } from 'contexts/TypebotContext'
|
||||
import {
|
||||
BubbleStep,
|
||||
BubbleStepType,
|
||||
ImageBubbleContent,
|
||||
ImageBubbleStep,
|
||||
TextBubbleStep,
|
||||
} from 'models'
|
||||
import { useRef } from 'react'
|
||||
|
||||
type Props = {
|
||||
step: Exclude<BubbleStep, TextBubbleStep>
|
||||
}
|
||||
|
||||
export const ContentPopover = ({ step }: Props) => {
|
||||
const ref = useRef<HTMLDivElement | null>(null)
|
||||
const handleMouseDown = (e: React.MouseEvent) => e.stopPropagation()
|
||||
|
||||
return (
|
||||
<Portal>
|
||||
<PopoverContent onMouseDown={handleMouseDown} w="500px">
|
||||
<PopoverArrow />
|
||||
<PopoverBody ref={ref} shadow="lg">
|
||||
<StepContent step={step} />
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
</Portal>
|
||||
)
|
||||
}
|
||||
|
||||
export const StepContent = ({ step }: Props) => {
|
||||
const { updateStep } = useTypebot()
|
||||
const handleContentChange = (content: ImageBubbleContent) =>
|
||||
updateStep(step.id, { content } as Partial<ImageBubbleStep>)
|
||||
|
||||
const handleNewImageSubmit = (url: string) => handleContentChange({ url })
|
||||
switch (step.type) {
|
||||
case BubbleStepType.IMAGE: {
|
||||
return (
|
||||
<ImagePopoverContent
|
||||
url={step.content?.url}
|
||||
onSubmit={handleNewImageSubmit}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
export { ContentPopover } from './ContentPopover'
|
@ -15,6 +15,7 @@ import {
|
||||
LogicStepType,
|
||||
Step,
|
||||
StepOptions,
|
||||
TextBubbleStep,
|
||||
} from 'models'
|
||||
import { useRef } from 'react'
|
||||
import {
|
||||
@ -33,7 +34,7 @@ import { RedirectSettings } from './bodies/RedirectSettings'
|
||||
import { SetVariableSettingsBody } from './bodies/SetVariableSettingsBody'
|
||||
|
||||
type Props = {
|
||||
step: Step
|
||||
step: Exclude<Step, TextBubbleStep>
|
||||
onExpandClick: () => void
|
||||
}
|
||||
|
||||
|
@ -7,15 +7,10 @@ import {
|
||||
useEventListener,
|
||||
} from '@chakra-ui/react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { DraggableStep, Step } from 'models'
|
||||
import { BubbleStep, DraggableStep, Step, TextBubbleStep } from 'models'
|
||||
import { useGraph } from 'contexts/GraphContext'
|
||||
import { StepIcon } from 'components/board/StepTypesList/StepIcon'
|
||||
import {
|
||||
isInputStep,
|
||||
isLogicStep,
|
||||
isTextBubbleStep,
|
||||
isIntegrationStep,
|
||||
} from 'utils'
|
||||
import { isBubbleStep, isTextBubbleStep } from 'utils'
|
||||
import { Coordinates } from '@dnd-kit/core/dist/types'
|
||||
import { TextEditor } from './TextEditor/TextEditor'
|
||||
import { StepNodeContent } from './StepNodeContent'
|
||||
@ -29,6 +24,7 @@ import { TargetEndpoint } from './TargetEndpoint'
|
||||
import { useRouter } from 'next/router'
|
||||
import { SettingsModal } from './SettingsPopoverContent/SettingsModal'
|
||||
import { StepSettings } from './SettingsPopoverContent/SettingsPopoverContent'
|
||||
import { ContentPopover } from './ContentPopover'
|
||||
|
||||
export const StepNode = ({
|
||||
step,
|
||||
@ -185,15 +181,16 @@ export const StepNode = ({
|
||||
}}
|
||||
pos="absolute"
|
||||
right="15px"
|
||||
top="18px"
|
||||
bottom="18px"
|
||||
/>
|
||||
)}
|
||||
</HStack>
|
||||
</Flex>
|
||||
</PopoverTrigger>
|
||||
{hasPopover(step) && (
|
||||
{hasSettingsPopover(step) && (
|
||||
<SettingsPopoverContent step={step} onExpandClick={onModalOpen} />
|
||||
)}
|
||||
{hasContentPopover(step) && <ContentPopover step={step} />}
|
||||
<SettingsModal isOpen={isModalOpen} onClose={onModalClose}>
|
||||
<StepSettings step={step} />
|
||||
</SettingsModal>
|
||||
@ -203,5 +200,10 @@ export const StepNode = ({
|
||||
)
|
||||
}
|
||||
|
||||
const hasPopover = (step: Step) =>
|
||||
isInputStep(step) || isLogicStep(step) || isIntegrationStep(step)
|
||||
const hasSettingsPopover = (step: Step): step is Exclude<Step, BubbleStep> =>
|
||||
!isBubbleStep(step)
|
||||
|
||||
const hasContentPopover = (
|
||||
step: Step
|
||||
): step is Exclude<BubbleStep, TextBubbleStep> =>
|
||||
isBubbleStep(step) && !isTextBubbleStep(step)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Flex, HStack, Stack, Tag, Text } from '@chakra-ui/react'
|
||||
import { Box, Flex, HStack, Image, Stack, Tag, Text } from '@chakra-ui/react'
|
||||
import { useTypebot } from 'contexts/TypebotContext'
|
||||
import {
|
||||
Step,
|
||||
@ -34,6 +34,20 @@ export const StepNodeContent = ({ step }: Props) => {
|
||||
/>
|
||||
)
|
||||
}
|
||||
case BubbleStepType.IMAGE: {
|
||||
return !step.content?.url ? (
|
||||
<Text color={'gray.500'}>Click to edit...</Text>
|
||||
) : (
|
||||
<Box w="full">
|
||||
<Image
|
||||
src={step.content?.url}
|
||||
alt="Step image"
|
||||
rounded="md"
|
||||
objectFit="cover"
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
case InputStepType.TEXT: {
|
||||
return (
|
||||
<Text color={'gray.500'}>
|
||||
|
@ -12,7 +12,7 @@ import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
||||
import { BaseSelection, createEditor, Transforms } from 'slate'
|
||||
import { ToolBar } from './ToolBar'
|
||||
import { parseHtmlStringToPlainText } from 'services/utils'
|
||||
import { TextStep, Variable } from 'models'
|
||||
import { TextBubbleStep, Variable } from 'models'
|
||||
import { VariableSearchInput } from 'components/shared/VariableSearchInput'
|
||||
import { ReactEditor } from 'slate-react'
|
||||
|
||||
@ -87,7 +87,7 @@ export const TextEditor = ({
|
||||
richText: value,
|
||||
plainText: parseHtmlStringToPlainText(html),
|
||||
},
|
||||
} as TextStep)
|
||||
} as TextBubbleStep)
|
||||
}
|
||||
|
||||
const handleMouseDown = (e: React.MouseEvent) => {
|
||||
|
Reference in New Issue
Block a user