Skip to content

Commit

Permalink
feat(inputs): ✨ Add number input
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Jan 8, 2022
1 parent 2a04030 commit d54ebc0
Show file tree
Hide file tree
Showing 33 changed files with 465 additions and 205 deletions.
9 changes: 9 additions & 0 deletions apps/builder/assets/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,12 @@ export const DownloadIcon = (props: IconProps) => (
<line x1="12" y1="15" x2="12" y2="3"></line>
</Icon>
)

export const NumberIcon = (props: IconProps) => (
<Icon viewBox="0 0 24 24" {...featherIconsBaseProps} {...props}>
<line x1="4" y1="9" x2="20" y2="9"></line>
<line x1="4" y1="15" x2="20" y2="15"></line>
<line x1="10" y1="3" x2="8" y2="21"></line>
<line x1="16" y1="3" x2="14" y2="21"></line>
</Icon>
)
15 changes: 9 additions & 6 deletions apps/builder/components/board/StepTypesList/StepCard.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { Button, ButtonProps, Flex, HStack } from '@chakra-ui/react'
import { StepType } from 'models'
import { BubbleStepType, InputStepType, StepType } from 'models'
import { useDnd } from 'contexts/DndContext'
import React, { useEffect, useState } from 'react'
import { StepIcon } from './StepIcon'
import { StepLabel } from './StepLabel'
import { StepTypeLabel } from './StepTypeLabel'

export const StepCard = ({
type,
onMouseDown,
}: {
type: StepType
onMouseDown: (e: React.MouseEvent, type: StepType) => void
type: BubbleStepType | InputStepType
onMouseDown: (
e: React.MouseEvent,
type: BubbleStepType | InputStepType
) => void
}) => {
const { draggedStepType } = useDnd()
const [isMouseDown, setIsMouseDown] = useState(false)
Expand All @@ -35,7 +38,7 @@ export const StepCard = ({
{!isMouseDown && (
<>
<StepIcon type={type} />
<StepLabel type={type} />
<StepTypeLabel type={type} />
</>
)}
</Button>
Expand All @@ -62,7 +65,7 @@ export const StepCardOverlay = ({
{...props}
>
<StepIcon type={type} />
<StepLabel type={type} />
<StepTypeLabel type={type} />
</Button>
)
}
15 changes: 9 additions & 6 deletions apps/builder/components/board/StepTypesList/StepIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import { ChatIcon, FlagIcon, TextIcon } from 'assets/icons'
import { StepType } from 'models'
import { ChatIcon, FlagIcon, NumberIcon, TextIcon } from 'assets/icons'
import { BubbleStepType, InputStepType, StepType } from 'models'
import React from 'react'

type StepIconProps = { type: StepType }

export const StepIcon = ({ type }: StepIconProps) => {
switch (type) {
case StepType.TEXT: {
case BubbleStepType.TEXT: {
return <ChatIcon />
}
case StepType.TEXT: {
case InputStepType.TEXT: {
return <TextIcon />
}
case StepType.START: {
case InputStepType.NUMBER: {
return <NumberIcon />
}
case 'start': {
return <FlagIcon />
}
default: {
return <TextIcon />
return <></>
}
}
}
19 changes: 0 additions & 19 deletions apps/builder/components/board/StepTypesList/StepLabel.tsx

This file was deleted.

20 changes: 20 additions & 0 deletions apps/builder/components/board/StepTypesList/StepTypeLabel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Text } from '@chakra-ui/react'
import { BubbleStepType, InputStepType, StepType } from 'models'
import React from 'react'

type Props = { type: StepType }

export const StepTypeLabel = ({ type }: Props) => {
switch (type) {
case BubbleStepType.TEXT:
case InputStepType.TEXT: {
return <Text>Text</Text>
}
case InputStepType.NUMBER: {
return <Text>Number</Text>
}
default: {
return <></>
}
}
}
23 changes: 9 additions & 14 deletions apps/builder/components/board/StepTypesList/StepTypesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,11 @@ import {
SimpleGrid,
useEventListener,
} from '@chakra-ui/react'
import { StepType } from 'models'
import { BubbleStepType, InputStepType } from 'models'
import { useDnd } from 'contexts/DndContext'
import React, { useState } from 'react'
import { StepCard, StepCardOverlay } from './StepCard'

export const stepListItems: {
bubbles: { type: StepType }[]
inputs: { type: StepType }[]
} = {
bubbles: [{ type: StepType.TEXT }],
inputs: [{ type: StepType.TEXT_INPUT }],
}

export const StepTypesList = () => {
const { setDraggedStepType, draggedStepType } = useDnd()
const [position, setPosition] = useState({
Expand All @@ -37,7 +29,10 @@ export const StepTypesList = () => {
}
useEventListener('mousemove', handleMouseMove)

const handleMouseDown = (e: React.MouseEvent, type: StepType) => {
const handleMouseDown = (
e: React.MouseEvent,
type: BubbleStepType | InputStepType
) => {
const element = e.currentTarget as HTMLDivElement
const rect = element.getBoundingClientRect()
const relativeX = e.clientX - rect.left
Expand Down Expand Up @@ -77,17 +72,17 @@ export const StepTypesList = () => {
Bubbles
</Text>
<SimpleGrid columns={2} spacing="2">
{stepListItems.bubbles.map((props) => (
<StepCard key={props.type} onMouseDown={handleMouseDown} {...props} />
{Object.values(BubbleStepType).map((type) => (
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
))}
</SimpleGrid>

<Text fontSize="sm" fontWeight="semibold" color="gray.600">
Inputs
</Text>
<SimpleGrid columns={2} spacing="2">
{stepListItems.inputs.map((props) => (
<StepCard key={props.type} onMouseDown={handleMouseDown} {...props} />
{Object.values(InputStepType).map((type) => (
<StepCard key={type} type={type} onMouseDown={handleMouseDown} />
))}
</SimpleGrid>
{draggedStepType && (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { FormLabel, HStack, Stack } from '@chakra-ui/react'
import { SmartNumberInput } from 'components/settings/SmartNumberInput'
import { DebouncedInput } from 'components/shared/DebouncedInput'
import { NumberInputOptions } from 'models'
import React from 'react'
import { removeUndefinedFields } from 'services/utils'

type NumberInputSettingsBodyProps = {
options?: NumberInputOptions
onOptionsChange: (options: NumberInputOptions) => void
}

export const NumberInputSettingsBody = ({
options,
onOptionsChange,
}: NumberInputSettingsBodyProps) => {
const handlePlaceholderChange = (placeholder: string) =>
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
const handleButtonLabelChange = (button: string) =>
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
const handleMinChange = (min?: number) =>
onOptionsChange(removeUndefinedFields({ ...options, min }))
const handleMaxChange = (max?: number) =>
onOptionsChange(removeUndefinedFields({ ...options, max }))
const handleStepChange = (step?: number) =>
onOptionsChange(removeUndefinedFields({ ...options, step }))

return (
<Stack spacing={4}>
<Stack>
<FormLabel mb="0" htmlFor="placeholder">
Placeholder:
</FormLabel>
<DebouncedInput
id="placeholder"
initialValue={options?.labels?.placeholder ?? 'Type your answer...'}
delay={100}
onChange={handlePlaceholderChange}
/>
</Stack>
<Stack>
<FormLabel mb="0" htmlFor="button">
Button label:
</FormLabel>
<DebouncedInput
id="button"
initialValue={options?.labels?.button ?? 'Send'}
delay={100}
onChange={handleButtonLabelChange}
/>
</Stack>
<HStack justifyContent="space-between">
<FormLabel mb="0" htmlFor="min">
Min:
</FormLabel>
<SmartNumberInput
id="min"
initialValue={options?.min}
onValueChange={handleMinChange}
/>
</HStack>
<HStack justifyContent="space-between">
<FormLabel mb="0" htmlFor="max">
Max:
</FormLabel>
<SmartNumberInput
id="max"
initialValue={options?.max}
onValueChange={handleMaxChange}
/>
</HStack>
<HStack justifyContent="space-between">
<FormLabel mb="0" htmlFor="step">
Step:
</FormLabel>
<SmartNumberInput
id="step"
initialValue={options?.step}
onValueChange={handleStepChange}
/>
</HStack>
</Stack>
)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { PopoverContent, PopoverArrow, PopoverBody } from '@chakra-ui/react'
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
import { Step, StepType, TextInputOptions } from 'models'
import { InputStepType, Step, TextInputOptions } from 'models'
import { NumberInputSettingsBody } from './NumberInputSettingsBody'
import { TextInputSettingsBody } from './TextInputSettingsBody'

type Props = {
Expand All @@ -25,14 +26,22 @@ const SettingsPopoverBodyContent = ({ step }: Props) => {
updateStep(step.id, { options } as Partial<Step>)

switch (step.type) {
case StepType.TEXT_INPUT: {
case InputStepType.TEXT: {
return (
<TextInputSettingsBody
options={step.options}
onOptionsChange={handleOptionsChange}
/>
)
}
case InputStepType.NUMBER: {
return (
<NumberInputSettingsBody
options={step.options}
onOptionsChange={handleOptionsChange}
/>
)
}
default: {
return <></>
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import { Block, Step } from 'models'
import { SourceEndpoint } from './SourceEndpoint'
import { useGraph } from 'contexts/GraphContext'
import { StepIcon } from 'components/board/StepTypesList/StepIcon'
import { isDefined } from 'utils'
import { isDefined, isTextBubbleStep } from 'utils'
import { Coordinates } from '@dnd-kit/core/dist/types'
import { TextEditor } from './TextEditor/TextEditor'
import { StepContent } from './StepContent'
import { StepNodeLabel } from './StepNodeLabel'
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
import { ContextMenu } from 'components/shared/ContextMenu'
import { StepNodeContextMenu } from './RightClickMenu'
import { SettingsPopoverContent } from './SettingsPopoverContent'
import { isStepText } from 'services/typebots'
import { DraggableStep } from 'contexts/DndContext'

export const StepNode = ({
step,
Expand All @@ -34,7 +34,7 @@ export const StepNode = ({
onMouseMoveTopOfElement?: () => void
onMouseDown?: (
stepNodePosition: { absolute: Coordinates; relative: Coordinates },
step: Step
step: DraggableStep
) => void
}) => {
const { setConnectingIds, connectingIds } = useGraph()
Expand All @@ -43,7 +43,7 @@ export const StepNode = ({
const [mouseDownEvent, setMouseDownEvent] =
useState<{ absolute: Coordinates; relative: Coordinates }>()
const [isEditing, setIsEditing] = useState<boolean>(
isStepText(step) && step.content.plainText === ''
isTextBubbleStep(step) && step.content.plainText === ''
)

useEffect(() => {
Expand Down Expand Up @@ -102,8 +102,8 @@ export const StepNode = ({
mouseDownEvent &&
onMouseDown &&
(event.movementX > 0 || event.movementY > 0)
if (isMovingAndIsMouseDown) {
onMouseDown(mouseDownEvent, step as Step)
if (isMovingAndIsMouseDown && step.type !== 'start') {
onMouseDown(mouseDownEvent, step)
deleteStep(step.id)
setMouseDownEvent(undefined)
}
Expand Down Expand Up @@ -142,7 +142,7 @@ export const StepNode = ({
connectingIds?.target?.blockId,
])

return isEditing && isStepText(step) ? (
return isEditing && isTextBubbleStep(step) ? (
<TextEditor
stepId={step.id}
initialValue={step.content.richText}
Expand Down Expand Up @@ -186,7 +186,7 @@ export const StepNode = ({
bgColor="white"
>
<StepIcon type={step.type} />
<StepContent {...step} />
<StepNodeLabel {...step} />
{isConnectable && (
<SourceEndpoint
onConnectionDragStart={handleConnectionDragStart}
Expand Down
Loading

2 comments on commit d54ebc0

@vercel
Copy link

@vercel vercel bot commented on d54ebc0 Jan 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

builder-v2-typebot-io.vercel.app
next.typebot.io
builder-v2-git-main-typebot-io.vercel.app

@vercel
Copy link

@vercel vercel bot commented on d54ebc0 Jan 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

viewer-v2 – ./apps/viewer

viewer-v2-git-main-typebot-io.vercel.app
viewer-v2-typebot-io.vercel.app
typebot-io.vercel.app

Please sign in to comment.