feat(editor): ✨ Add unlock/lock sidebar
This commit is contained in:
@ -297,3 +297,17 @@ export const GripIcon = (props: IconProps) => (
|
|||||||
<circle cx="5" cy="15" r="1"></circle>
|
<circle cx="5" cy="15" r="1"></circle>
|
||||||
</Icon>
|
</Icon>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const LockedIcon = (props: IconProps) => (
|
||||||
|
<Icon viewBox="0 0 24 24" {...featherIconsBaseProps} {...props}>
|
||||||
|
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
|
||||||
|
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
|
||||||
|
</Icon>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const UnlockedIcon = (props: IconProps) => (
|
||||||
|
<Icon viewBox="0 0 24 24" {...featherIconsBaseProps} {...props}>
|
||||||
|
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
|
||||||
|
<path d="M7 11V7a5 5 0 0 1 9.9-1"></path>
|
||||||
|
</Icon>
|
||||||
|
)
|
||||||
|
@ -2,7 +2,7 @@ import { Flex } from '@chakra-ui/react'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Graph from './graph/Graph'
|
import Graph from './graph/Graph'
|
||||||
import { StepDndContext } from 'contexts/StepDndContext'
|
import { StepDndContext } from 'contexts/StepDndContext'
|
||||||
import { StepTypesList } from './StepTypesList'
|
import { StepsSideBar } from './StepsSideBar'
|
||||||
import { PreviewDrawer } from './preview/PreviewDrawer'
|
import { PreviewDrawer } from './preview/PreviewDrawer'
|
||||||
import { RightPanel, useEditor } from 'contexts/EditorContext'
|
import { RightPanel, useEditor } from 'contexts/EditorContext'
|
||||||
import { GraphProvider } from 'contexts/GraphContext'
|
import { GraphProvider } from 'contexts/GraphContext'
|
||||||
@ -13,7 +13,7 @@ export const Board = () => {
|
|||||||
return (
|
return (
|
||||||
<Flex flex="1" pos="relative" bgColor="gray.50" h="full">
|
<Flex flex="1" pos="relative" bgColor="gray.50" h="full">
|
||||||
<StepDndContext>
|
<StepDndContext>
|
||||||
<StepTypesList />
|
<StepsSideBar />
|
||||||
<GraphProvider>
|
<GraphProvider>
|
||||||
<Graph flex="1" />
|
<Graph flex="1" />
|
||||||
<BoardMenuButton pos="absolute" right="40px" top="20px" />
|
<BoardMenuButton pos="absolute" right="40px" top="20px" />
|
||||||
|
@ -1,137 +0,0 @@
|
|||||||
import {
|
|
||||||
Stack,
|
|
||||||
Input,
|
|
||||||
Text,
|
|
||||||
SimpleGrid,
|
|
||||||
useEventListener,
|
|
||||||
Portal,
|
|
||||||
} from '@chakra-ui/react'
|
|
||||||
import {
|
|
||||||
BubbleStepType,
|
|
||||||
DraggableStepType,
|
|
||||||
InputStepType,
|
|
||||||
IntegrationStepType,
|
|
||||||
LogicStepType,
|
|
||||||
} from 'models'
|
|
||||||
import { useStepDnd } from 'contexts/StepDndContext'
|
|
||||||
import React, { useState } from 'react'
|
|
||||||
import { StepCard, StepCardOverlay } from './StepCard'
|
|
||||||
|
|
||||||
export const StepTypesList = () => {
|
|
||||||
const { setDraggedStepType, draggedStepType } = useStepDnd()
|
|
||||||
const [position, setPosition] = useState({
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
})
|
|
||||||
const [relativeCoordinates, setRelativeCoordinates] = useState({ x: 0, y: 0 })
|
|
||||||
|
|
||||||
const handleMouseMove = (event: MouseEvent) => {
|
|
||||||
if (!draggedStepType) return
|
|
||||||
const { clientX, clientY } = event
|
|
||||||
setPosition({
|
|
||||||
...position,
|
|
||||||
x: clientX - relativeCoordinates.x,
|
|
||||||
y: clientY - relativeCoordinates.y,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
useEventListener('mousemove', handleMouseMove)
|
|
||||||
|
|
||||||
const handleMouseDown = (e: React.MouseEvent, type: DraggableStepType) => {
|
|
||||||
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 })
|
|
||||||
setDraggedStepType(type)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleMouseUp = () => {
|
|
||||||
if (!draggedStepType) return
|
|
||||||
setDraggedStepType(undefined)
|
|
||||||
setPosition({
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
useEventListener('mouseup', handleMouseUp)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Stack
|
|
||||||
w="320px"
|
|
||||||
pos="absolute"
|
|
||||||
left="10px"
|
|
||||||
top="10px"
|
|
||||||
h="calc(100vh - 80px)"
|
|
||||||
rounded="lg"
|
|
||||||
shadow="xl"
|
|
||||||
borderWidth="1px"
|
|
||||||
zIndex="2"
|
|
||||||
py="4"
|
|
||||||
px="2"
|
|
||||||
bgColor="gray.50"
|
|
||||||
spacing={6}
|
|
||||||
userSelect="none"
|
|
||||||
>
|
|
||||||
<Input placeholder="Search..." bgColor="white" />
|
|
||||||
<Stack>
|
|
||||||
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
|
||||||
Bubbles
|
|
||||||
</Text>
|
|
||||||
<SimpleGrid columns={2} spacing="2">
|
|
||||||
{Object.values(BubbleStepType).map((type) => (
|
|
||||||
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
|
||||||
))}
|
|
||||||
</SimpleGrid>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Stack>
|
|
||||||
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
|
||||||
Inputs
|
|
||||||
</Text>
|
|
||||||
<SimpleGrid columns={2} spacing="2">
|
|
||||||
{Object.values(InputStepType).map((type) => (
|
|
||||||
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
|
||||||
))}
|
|
||||||
</SimpleGrid>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Stack>
|
|
||||||
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
|
||||||
Logic
|
|
||||||
</Text>
|
|
||||||
<SimpleGrid columns={2} spacing="2">
|
|
||||||
{Object.values(LogicStepType).map((type) => (
|
|
||||||
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
|
||||||
))}
|
|
||||||
</SimpleGrid>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Stack>
|
|
||||||
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
|
||||||
Integrations
|
|
||||||
</Text>
|
|
||||||
<SimpleGrid columns={2} spacing="2">
|
|
||||||
{Object.values(IntegrationStepType).map((type) => (
|
|
||||||
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
|
||||||
))}
|
|
||||||
</SimpleGrid>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
{draggedStepType && (
|
|
||||||
<Portal>
|
|
||||||
<StepCardOverlay
|
|
||||||
type={draggedStepType}
|
|
||||||
onMouseUp={handleMouseUp}
|
|
||||||
pos="fixed"
|
|
||||||
top="0"
|
|
||||||
left="0"
|
|
||||||
style={{
|
|
||||||
transform: `translate(${position.x}px, ${position.y}px) rotate(-2deg)`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Portal>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export { StepTypesList } from './StepTypesList'
|
|
@ -31,31 +31,31 @@ type StepIconProps = { type: StepType } & IconProps
|
|||||||
export const StepIcon = ({ type, ...props }: StepIconProps) => {
|
export const StepIcon = ({ type, ...props }: StepIconProps) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BubbleStepType.TEXT:
|
case BubbleStepType.TEXT:
|
||||||
return <ChatIcon {...props} />
|
return <ChatIcon color="blue.500" {...props} />
|
||||||
case BubbleStepType.IMAGE:
|
case BubbleStepType.IMAGE:
|
||||||
return <ImageIcon {...props} />
|
return <ImageIcon color="blue.500" {...props} />
|
||||||
case BubbleStepType.VIDEO:
|
case BubbleStepType.VIDEO:
|
||||||
return <FilmIcon {...props} />
|
return <FilmIcon color="blue.500" {...props} />
|
||||||
case InputStepType.TEXT:
|
case InputStepType.TEXT:
|
||||||
return <TextIcon {...props} />
|
return <TextIcon color="orange.500" {...props} />
|
||||||
case InputStepType.NUMBER:
|
case InputStepType.NUMBER:
|
||||||
return <NumberIcon {...props} />
|
return <NumberIcon color="orange.500" {...props} />
|
||||||
case InputStepType.EMAIL:
|
case InputStepType.EMAIL:
|
||||||
return <EmailIcon {...props} />
|
return <EmailIcon color="orange.500" {...props} />
|
||||||
case InputStepType.URL:
|
case InputStepType.URL:
|
||||||
return <GlobeIcon {...props} />
|
return <GlobeIcon color="orange.500" {...props} />
|
||||||
case InputStepType.DATE:
|
case InputStepType.DATE:
|
||||||
return <CalendarIcon {...props} />
|
return <CalendarIcon color="orange.500" {...props} />
|
||||||
case InputStepType.PHONE:
|
case InputStepType.PHONE:
|
||||||
return <PhoneIcon {...props} />
|
return <PhoneIcon color="orange.500" {...props} />
|
||||||
case InputStepType.CHOICE:
|
case InputStepType.CHOICE:
|
||||||
return <CheckSquareIcon {...props} />
|
return <CheckSquareIcon color="orange.500" {...props} />
|
||||||
case LogicStepType.SET_VARIABLE:
|
case LogicStepType.SET_VARIABLE:
|
||||||
return <EditIcon {...props} />
|
return <EditIcon color="purple.500" {...props} />
|
||||||
case LogicStepType.CONDITION:
|
case LogicStepType.CONDITION:
|
||||||
return <FilterIcon {...props} />
|
return <FilterIcon color="purple.500" {...props} />
|
||||||
case LogicStepType.REDIRECT:
|
case LogicStepType.REDIRECT:
|
||||||
return <ExternalLinkIcon {...props} />
|
return <ExternalLinkIcon color="purple.500" {...props} />
|
||||||
case IntegrationStepType.GOOGLE_SHEETS:
|
case IntegrationStepType.GOOGLE_SHEETS:
|
||||||
return <GoogleSheetsLogo {...props} />
|
return <GoogleSheetsLogo {...props} />
|
||||||
case IntegrationStepType.GOOGLE_ANALYTICS:
|
case IntegrationStepType.GOOGLE_ANALYTICS:
|
191
apps/builder/components/board/StepsSideBar/StepSideBar.tsx
Normal file
191
apps/builder/components/board/StepsSideBar/StepSideBar.tsx
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
import {
|
||||||
|
Stack,
|
||||||
|
Input,
|
||||||
|
Text,
|
||||||
|
SimpleGrid,
|
||||||
|
useEventListener,
|
||||||
|
Portal,
|
||||||
|
Flex,
|
||||||
|
IconButton,
|
||||||
|
Tooltip,
|
||||||
|
Fade,
|
||||||
|
} from '@chakra-ui/react'
|
||||||
|
import {
|
||||||
|
BubbleStepType,
|
||||||
|
DraggableStepType,
|
||||||
|
InputStepType,
|
||||||
|
IntegrationStepType,
|
||||||
|
LogicStepType,
|
||||||
|
} from 'models'
|
||||||
|
import { useStepDnd } from 'contexts/StepDndContext'
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import { StepCard, StepCardOverlay } from './StepCard'
|
||||||
|
import { LockedIcon, UnlockedIcon } from 'assets/icons'
|
||||||
|
import { headerHeight } from 'components/shared/TypebotHeader'
|
||||||
|
|
||||||
|
export const StepsSideBar = () => {
|
||||||
|
const { setDraggedStepType, draggedStepType } = useStepDnd()
|
||||||
|
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 handleMouseMove = (event: MouseEvent) => {
|
||||||
|
if (!draggedStepType) return
|
||||||
|
const { clientX, clientY } = event
|
||||||
|
setPosition({
|
||||||
|
...position,
|
||||||
|
x: clientX - relativeCoordinates.x,
|
||||||
|
y: clientY - relativeCoordinates.y,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
useEventListener('mousemove', handleMouseMove)
|
||||||
|
|
||||||
|
const handleMouseDown = (e: React.MouseEvent, type: DraggableStepType) => {
|
||||||
|
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 })
|
||||||
|
setDraggedStepType(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleMouseUp = () => {
|
||||||
|
if (!draggedStepType) return
|
||||||
|
setDraggedStepType(undefined)
|
||||||
|
setPosition({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
useEventListener('mouseup', handleMouseUp)
|
||||||
|
|
||||||
|
const handleLockClick = () => setIsLocked(!isLocked)
|
||||||
|
|
||||||
|
const handleDockBarEnter = () => setIsExtended(true)
|
||||||
|
|
||||||
|
const handleMouseLeave = () => {
|
||||||
|
if (isLocked) return
|
||||||
|
setIsExtended(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex
|
||||||
|
w="340px"
|
||||||
|
pos="absolute"
|
||||||
|
left="0"
|
||||||
|
h={`calc(100vh - ${headerHeight}px)`}
|
||||||
|
zIndex="2"
|
||||||
|
pl="4"
|
||||||
|
py="4"
|
||||||
|
onMouseLeave={handleMouseLeave}
|
||||||
|
transform={isExtended ? 'translateX(0)' : 'translateX(-340px)'}
|
||||||
|
transition="transform 350ms cubic-bezier(0.075, 0.82, 0.165, 1) 0s"
|
||||||
|
>
|
||||||
|
<Stack
|
||||||
|
w="full"
|
||||||
|
rounded="lg"
|
||||||
|
shadow="xl"
|
||||||
|
borderWidth="1px"
|
||||||
|
pt="2"
|
||||||
|
pb="4"
|
||||||
|
px="2"
|
||||||
|
bgColor="gray.50"
|
||||||
|
spacing={6}
|
||||||
|
userSelect="none"
|
||||||
|
>
|
||||||
|
<Stack>
|
||||||
|
<Flex justifyContent="flex-end">
|
||||||
|
<Tooltip label={isLocked ? 'Unlock sidebar' : 'Lock sidebar'}>
|
||||||
|
<IconButton
|
||||||
|
icon={isLocked ? <LockedIcon /> : <UnlockedIcon />}
|
||||||
|
aria-label={isLocked ? 'Unlock' : 'Lock'}
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
onClick={handleLockClick}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
<Input placeholder="Search..." bgColor="white" />
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack>
|
||||||
|
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
||||||
|
Bubbles
|
||||||
|
</Text>
|
||||||
|
<SimpleGrid columns={2} spacing="2">
|
||||||
|
{Object.values(BubbleStepType).map((type) => (
|
||||||
|
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
||||||
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack>
|
||||||
|
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
||||||
|
Inputs
|
||||||
|
</Text>
|
||||||
|
<SimpleGrid columns={2} spacing="2">
|
||||||
|
{Object.values(InputStepType).map((type) => (
|
||||||
|
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
||||||
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack>
|
||||||
|
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
||||||
|
Logic
|
||||||
|
</Text>
|
||||||
|
<SimpleGrid columns={2} spacing="2">
|
||||||
|
{Object.values(LogicStepType).map((type) => (
|
||||||
|
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
||||||
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack>
|
||||||
|
<Text fontSize="sm" fontWeight="semibold" color="gray.600">
|
||||||
|
Integrations
|
||||||
|
</Text>
|
||||||
|
<SimpleGrid columns={2} spacing="2">
|
||||||
|
{Object.values(IntegrationStepType).map((type) => (
|
||||||
|
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
|
||||||
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
{draggedStepType && (
|
||||||
|
<Portal>
|
||||||
|
<StepCardOverlay
|
||||||
|
type={draggedStepType}
|
||||||
|
onMouseUp={handleMouseUp}
|
||||||
|
pos="fixed"
|
||||||
|
top="0"
|
||||||
|
left="0"
|
||||||
|
style={{
|
||||||
|
transform: `translate(${position.x}px, ${position.y}px) rotate(-2deg)`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Portal>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
<Fade in={!isLocked} unmountOnExit>
|
||||||
|
<Flex
|
||||||
|
pos="absolute"
|
||||||
|
h="100%"
|
||||||
|
right="-50px"
|
||||||
|
w="50px"
|
||||||
|
top="0"
|
||||||
|
justify="center"
|
||||||
|
align="center"
|
||||||
|
onMouseEnter={handleDockBarEnter}
|
||||||
|
>
|
||||||
|
<Flex w="5px" h="20px" bgColor="gray.400" rounded="md" />
|
||||||
|
</Flex>
|
||||||
|
</Fade>
|
||||||
|
</Flex>
|
||||||
|
)
|
||||||
|
}
|
1
apps/builder/components/board/StepsSideBar/index.tsx
Normal file
1
apps/builder/components/board/StepsSideBar/index.tsx
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { StepsSideBar } from './StepSideBar'
|
@ -94,6 +94,7 @@ export const ChoiceItemNode = ({
|
|||||||
>
|
>
|
||||||
{(ref, isOpened) => (
|
{(ref, isOpened) => (
|
||||||
<Flex
|
<Flex
|
||||||
|
ref={ref}
|
||||||
align="center"
|
align="center"
|
||||||
pos="relative"
|
pos="relative"
|
||||||
onMouseEnter={handleMouseEnter}
|
onMouseEnter={handleMouseEnter}
|
||||||
@ -109,7 +110,6 @@ export const ChoiceItemNode = ({
|
|||||||
borderColor={isOpened ? 'blue.400' : 'gray.300'}
|
borderColor={isOpened ? 'blue.400' : 'gray.300'}
|
||||||
>
|
>
|
||||||
<Editable
|
<Editable
|
||||||
ref={ref}
|
|
||||||
defaultValue={item.content ?? 'Click to edit'}
|
defaultValue={item.content ?? 'Click to edit'}
|
||||||
flex="1"
|
flex="1"
|
||||||
startWithEditView={!isDefined(item.content)}
|
startWithEditView={!isDefined(item.content)}
|
||||||
|
@ -27,7 +27,7 @@ export const ContentPopover = ({ step }: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Portal>
|
<Portal>
|
||||||
<PopoverContent onMouseDown={handleMouseDown}>
|
<PopoverContent onMouseDown={handleMouseDown} w="500px">
|
||||||
<PopoverArrow />
|
<PopoverArrow />
|
||||||
<PopoverBody ref={ref} shadow="lg">
|
<PopoverBody ref={ref} shadow="lg">
|
||||||
<StepContent step={step} />
|
<StepContent step={step} />
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { BubbleStep, DraggableStep, Step, TextBubbleStep } from 'models'
|
import { BubbleStep, DraggableStep, Step, TextBubbleStep } from 'models'
|
||||||
import { Coordinates, useGraph } from 'contexts/GraphContext'
|
import { Coordinates, useGraph } from 'contexts/GraphContext'
|
||||||
import { StepIcon } from 'components/board/StepTypesList/StepIcon'
|
import { StepIcon } from 'components/board/StepsSideBar/StepIcon'
|
||||||
import { isBubbleStep, isTextBubbleStep } from 'utils'
|
import { isBubbleStep, isTextBubbleStep } from 'utils'
|
||||||
import { TextEditor } from './TextEditor/TextEditor'
|
import { TextEditor } from './TextEditor/TextEditor'
|
||||||
import { StepNodeContent } from './StepNodeContent/StepNodeContent'
|
import { StepNodeContent } from './StepNodeContent/StepNodeContent'
|
||||||
@ -152,7 +152,7 @@ export const StepNode = ({
|
|||||||
renderMenu={() => <StepNodeContextMenu stepId={step.id} />}
|
renderMenu={() => <StepNodeContextMenu stepId={step.id} />}
|
||||||
>
|
>
|
||||||
{(ref, isOpened) => (
|
{(ref, isOpened) => (
|
||||||
<Popover placement="left" isLazy isOpen={openedStepId === step.id}>
|
<Popover placement="bottom" isLazy isOpen={openedStepId === step.id}>
|
||||||
<PopoverTrigger>
|
<PopoverTrigger>
|
||||||
<Flex
|
<Flex
|
||||||
pos="relative"
|
pos="relative"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { StackProps, HStack } from '@chakra-ui/react'
|
import { StackProps, HStack } from '@chakra-ui/react'
|
||||||
import { StartStep, Step } from 'models'
|
import { StartStep, Step } from 'models'
|
||||||
import { StepIcon } from 'components/board/StepTypesList/StepIcon'
|
import { StepIcon } from 'components/board/StepsSideBar/StepIcon'
|
||||||
import { StepNodeContent } from './StepNodeContent/StepNodeContent'
|
import { StepNodeContent } from './StepNodeContent/StepNodeContent'
|
||||||
|
|
||||||
export const StepNodeOverlay = ({
|
export const StepNodeOverlay = ({
|
||||||
|
@ -43,7 +43,7 @@ export const DropdownList = <T,>({
|
|||||||
{currentItem ?? placeholder}
|
{currentItem ?? placeholder}
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
<Portal>
|
<Portal>
|
||||||
<MenuList maxW="500px" shadow="lg" zIndex={1500}>
|
<MenuList maxW="500px" zIndex={1500}>
|
||||||
<Stack maxH={'35vh'} overflowY="scroll" spacing="0">
|
<Stack maxH={'35vh'} overflowY="scroll" spacing="0">
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ChangeEvent, FormEvent, useEffect, useState } from 'react'
|
import { ChangeEvent, useEffect, useState } from 'react'
|
||||||
import { Button, HStack, Input, Stack } from '@chakra-ui/react'
|
import { Button, Flex, HStack, Input, Stack } from '@chakra-ui/react'
|
||||||
import { SearchContextManager } from '@giphy/react-components'
|
import { SearchContextManager } from '@giphy/react-components'
|
||||||
import { UploadButton } from '../buttons/UploadButton'
|
import { UploadButton } from '../buttons/UploadButton'
|
||||||
import { GiphySearch } from './GiphySearch'
|
import { GiphySearch } from './GiphySearch'
|
||||||
@ -79,7 +79,7 @@ type ContentProps = { initialUrl?: string; onNewUrl: (url: string) => void }
|
|||||||
const UploadFileContent = ({ onNewUrl }: ContentProps) => {
|
const UploadFileContent = ({ onNewUrl }: ContentProps) => {
|
||||||
const { typebot } = useTypebot()
|
const { typebot } = useTypebot()
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Flex justify="center" py="2">
|
||||||
<UploadButton
|
<UploadButton
|
||||||
filePath={`typebots/${typebot?.id}`}
|
filePath={`typebots/${typebot?.id}`}
|
||||||
onFileUploaded={onNewUrl}
|
onFileUploaded={onNewUrl}
|
||||||
@ -88,7 +88,7 @@ const UploadFileContent = ({ onNewUrl }: ContentProps) => {
|
|||||||
>
|
>
|
||||||
Choose an image
|
Choose an image
|
||||||
</UploadButton>
|
</UploadButton>
|
||||||
</Stack>
|
</Flex>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,11 +106,14 @@ const EmbedLinkContent = ({ initialUrl, onNewUrl }: ContentProps) => {
|
|||||||
setImageUrl(e.target.value)
|
setImageUrl(e.target.value)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Input
|
<Stack py="2">
|
||||||
placeholder={'Paste the image link...'}
|
<Input
|
||||||
onChange={handleImageUrlChange}
|
my="2"
|
||||||
value={imageUrl}
|
placeholder={'Paste the image link...'}
|
||||||
/>
|
onChange={handleImageUrlChange}
|
||||||
|
value={imageUrl}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +90,14 @@ const components = {
|
|||||||
_hover: { textDecoration: 'none' },
|
_hover: { textDecoration: 'none' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Menu: {
|
||||||
|
parts: ['list'],
|
||||||
|
defaultProps: {
|
||||||
|
list: {
|
||||||
|
shadow: 'lg',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const customTheme = extendTheme({ colors, fonts, components })
|
export const customTheme = extendTheme({ colors, fonts, components })
|
||||||
|
@ -12,7 +12,7 @@ const providers: Provider[] = [
|
|||||||
EmailProvider({
|
EmailProvider({
|
||||||
server: {
|
server: {
|
||||||
host: process.env.EMAIL_SERVER_HOST,
|
host: process.env.EMAIL_SERVER_HOST,
|
||||||
port: process.env.EMAIL_SERVER_PORT,
|
port: Number(process.env.EMAIL_SERVER_PORT),
|
||||||
auth: {
|
auth: {
|
||||||
user: process.env.EMAIL_SERVER_USER,
|
user: process.env.EMAIL_SERVER_USER,
|
||||||
pass: process.env.EMAIL_SERVER_PASSWORD,
|
pass: process.env.EMAIL_SERVER_PASSWORD,
|
||||||
|
@ -2,7 +2,7 @@ import { PublicTypebot, Typebot } from 'models'
|
|||||||
import shortId from 'short-uuid'
|
import shortId from 'short-uuid'
|
||||||
import { HStack, Text } from '@chakra-ui/react'
|
import { HStack, Text } from '@chakra-ui/react'
|
||||||
import { CalendarIcon } from 'assets/icons'
|
import { CalendarIcon } from 'assets/icons'
|
||||||
import { StepIcon } from 'components/board/StepTypesList/StepIcon'
|
import { StepIcon } from 'components/board/StepsSideBar/StepIcon'
|
||||||
import { isInputStep, sendRequest } from 'utils'
|
import { isInputStep, sendRequest } from 'utils'
|
||||||
|
|
||||||
export const parseTypebotToPublicTypebot = (
|
export const parseTypebotToPublicTypebot = (
|
||||||
|
Reference in New Issue
Block a user