docs(share): 📝 Add code blocks in embed instructions
This commit is contained in:
@ -0,0 +1,38 @@
|
||||
import { FlexProps } from '@chakra-ui/layout'
|
||||
import prettier from 'prettier/standalone'
|
||||
import parserHtml from 'prettier/parser-html'
|
||||
import { BubbleParams } from 'typebot-js'
|
||||
import { parseInitBubbleCode, typebotJsHtml } from '../params'
|
||||
import { useTypebot } from 'contexts/TypebotContext'
|
||||
import { CodeEditor } from 'components/shared/CodeEditor'
|
||||
|
||||
type ChatEmbedCodeProps = {
|
||||
withStarterVariables?: boolean
|
||||
onCopied?: () => void
|
||||
} & Pick<BubbleParams, 'button' | 'proactiveMessage'>
|
||||
|
||||
export const ChatEmbedCode = ({
|
||||
proactiveMessage,
|
||||
button,
|
||||
}: ChatEmbedCodeProps & FlexProps) => {
|
||||
const { typebot } = useTypebot()
|
||||
|
||||
const snippet = prettier.format(
|
||||
createSnippet({
|
||||
publishId: typebot?.publicId ?? '',
|
||||
button,
|
||||
proactiveMessage,
|
||||
}),
|
||||
{
|
||||
parser: 'html',
|
||||
plugins: [parserHtml],
|
||||
}
|
||||
)
|
||||
return <CodeEditor value={snippet} lang="html" isReadOnly />
|
||||
}
|
||||
|
||||
const createSnippet = (params: BubbleParams): string => {
|
||||
const jsCode = parseInitBubbleCode(params)
|
||||
return `${typebotJsHtml}
|
||||
<script>${jsCode}</script>`
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
import {
|
||||
StackProps,
|
||||
Stack,
|
||||
Heading,
|
||||
HStack,
|
||||
Input,
|
||||
Flex,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
NumberInput,
|
||||
NumberInputField,
|
||||
NumberInputStepper,
|
||||
NumberIncrementStepper,
|
||||
NumberDecrementStepper,
|
||||
Switch,
|
||||
Text,
|
||||
Tag,
|
||||
} from '@chakra-ui/react'
|
||||
import { ColorPicker } from 'components/theme/GeneralSettings/ColorPicker'
|
||||
import { useTypebot } from 'contexts/TypebotContext'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { BubbleParams } from 'typebot-js'
|
||||
|
||||
type ChatEmbedSettingsProps = {
|
||||
onUpdateSettings: (
|
||||
windowSettings: Pick<BubbleParams, 'button' | 'proactiveMessage'>
|
||||
) => void
|
||||
}
|
||||
export const ChatEmbedSettings = ({
|
||||
onUpdateSettings,
|
||||
...props
|
||||
}: ChatEmbedSettingsProps & StackProps) => {
|
||||
const { typebot } = useTypebot()
|
||||
const [proactiveMessageChecked, setProactiveMessageChecked] = useState(false)
|
||||
const [rememberProMessageChecked] = useState(true)
|
||||
const [customIconInputValue, setCustomIconInputValue] = useState('')
|
||||
|
||||
const [inputValues, setInputValues] = useState({
|
||||
messageDelay: '0',
|
||||
messageContent: 'I have a question for you!',
|
||||
})
|
||||
|
||||
const [bubbleColor, setBubbleColor] = useState(
|
||||
typebot?.theme.chat.buttons.backgroundColor ?? '#0042DA'
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (proactiveMessageChecked) {
|
||||
onUpdateSettings({
|
||||
button: {
|
||||
color: bubbleColor,
|
||||
iconUrl: customIconInputValue,
|
||||
},
|
||||
proactiveMessage: {
|
||||
delay: parseInt(inputValues.messageDelay) * 1000,
|
||||
textContent: inputValues.messageContent,
|
||||
rememberClose: rememberProMessageChecked,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
onUpdateSettings({
|
||||
button: {
|
||||
color: bubbleColor,
|
||||
iconUrl: customIconInputValue,
|
||||
},
|
||||
proactiveMessage: undefined,
|
||||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
inputValues,
|
||||
bubbleColor,
|
||||
rememberProMessageChecked,
|
||||
customIconInputValue,
|
||||
proactiveMessageChecked,
|
||||
])
|
||||
|
||||
return (
|
||||
<Stack {...props}>
|
||||
<Heading fontSize="md" fontWeight="semibold">
|
||||
Chat bubble settings
|
||||
</Heading>
|
||||
<Flex justify="space-between" align="center" mb="4">
|
||||
<Text>Button color</Text>
|
||||
<ColorPicker
|
||||
initialColor={bubbleColor}
|
||||
onColorChange={setBubbleColor}
|
||||
/>
|
||||
</Flex>
|
||||
<HStack>
|
||||
<Text flexShrink={0}>
|
||||
Custom button icon <Tag>Optional</Tag>
|
||||
</Text>
|
||||
<Input
|
||||
placeholder={'Paste image link (.png, .svg)'}
|
||||
value={customIconInputValue}
|
||||
onChange={(e) => setCustomIconInputValue(e.target.value)}
|
||||
/>
|
||||
</HStack>
|
||||
<Flex alignItems="center">
|
||||
<FormControl
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
w="full"
|
||||
justifyContent="space-between"
|
||||
pr={1}
|
||||
>
|
||||
<FormLabel htmlFor="fullscreen-option" mb="1">
|
||||
Enable popup message?
|
||||
</FormLabel>
|
||||
<Switch
|
||||
id="fullscreen-option"
|
||||
onChange={() =>
|
||||
setProactiveMessageChecked(!proactiveMessageChecked)
|
||||
}
|
||||
isChecked={proactiveMessageChecked}
|
||||
/>
|
||||
</FormControl>
|
||||
</Flex>
|
||||
{proactiveMessageChecked && (
|
||||
<>
|
||||
<Flex justify="space-between" align="center" pl="4" mb="2">
|
||||
<Text>Appearance delay</Text>
|
||||
<NumberInput
|
||||
onChange={(messageDelay) =>
|
||||
setInputValues({
|
||||
...inputValues,
|
||||
messageDelay,
|
||||
})
|
||||
}
|
||||
value={inputValues.messageDelay}
|
||||
min={0}
|
||||
>
|
||||
<NumberInputField />
|
||||
<NumberInputStepper>
|
||||
<NumberIncrementStepper />
|
||||
<NumberDecrementStepper />
|
||||
</NumberInputStepper>
|
||||
</NumberInput>
|
||||
</Flex>
|
||||
<Flex justify="space-between" align="center" pl="4" mb="2">
|
||||
<Text>Message content</Text>
|
||||
<Input
|
||||
type="text"
|
||||
onChange={(e) =>
|
||||
setInputValues({
|
||||
...inputValues,
|
||||
messageContent: e.target.value,
|
||||
})
|
||||
}
|
||||
value={inputValues.messageContent}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
)
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
import { FlexProps } from '@chakra-ui/react'
|
||||
import parserHtml from 'prettier/parser-html'
|
||||
import prettier from 'prettier/standalone'
|
||||
import { parseInitContainerCode, typebotJsHtml } from '../params'
|
||||
import { IframeParams } from 'typebot-js'
|
||||
import { useTypebot } from 'contexts/TypebotContext'
|
||||
import { CodeEditor } from 'components/shared/CodeEditor'
|
||||
|
||||
type ContainerEmbedCodeProps = {
|
||||
widthLabel: string
|
||||
heightLabel: string
|
||||
withStarterVariables?: boolean
|
||||
onCopied?: () => void
|
||||
}
|
||||
|
||||
export const ContainerEmbedCode = ({
|
||||
widthLabel,
|
||||
heightLabel,
|
||||
}: ContainerEmbedCodeProps & FlexProps) => {
|
||||
const { typebot } = useTypebot()
|
||||
|
||||
const snippet = prettier.format(
|
||||
parseSnippet({
|
||||
publishId: typebot?.publicId ?? '',
|
||||
heightLabel,
|
||||
widthLabel,
|
||||
}),
|
||||
{
|
||||
parser: 'html',
|
||||
plugins: [parserHtml],
|
||||
}
|
||||
)
|
||||
|
||||
return <CodeEditor value={snippet} lang="html" isReadOnly />
|
||||
}
|
||||
|
||||
type SnippetProps = IframeParams &
|
||||
Pick<ContainerEmbedCodeProps, 'widthLabel' | 'heightLabel'>
|
||||
|
||||
const parseSnippet = ({
|
||||
publishId,
|
||||
customDomain,
|
||||
backgroundColor,
|
||||
hiddenVariables,
|
||||
...embedProps
|
||||
}: SnippetProps): string => {
|
||||
const jsCode = parseInitContainerCode({
|
||||
customDomain,
|
||||
hiddenVariables,
|
||||
backgroundColor,
|
||||
publishId,
|
||||
})
|
||||
return `${typebotJsHtml}
|
||||
<div id="typebot-container" style="width: ${embedProps.widthLabel}; height: ${embedProps.heightLabel};"></div>
|
||||
<script>${jsCode}</script>`
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
import {
|
||||
StackProps,
|
||||
Stack,
|
||||
Flex,
|
||||
Heading,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Switch,
|
||||
Input,
|
||||
HStack,
|
||||
Text,
|
||||
} from '@chakra-ui/react'
|
||||
import { DropdownList } from 'components/shared/DropdownList'
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
type StandardEmbedWindowSettingsProps = {
|
||||
onUpdateWindowSettings: (windowSettings: {
|
||||
heightLabel: string
|
||||
widthLabel: string
|
||||
}) => void
|
||||
}
|
||||
export const StandardEmbedWindowSettings = ({
|
||||
onUpdateWindowSettings,
|
||||
...props
|
||||
}: StandardEmbedWindowSettingsProps & StackProps) => {
|
||||
const [fullscreen, setFullscreen] = useState(false)
|
||||
const [inputValues, setInputValues] = useState({
|
||||
widthValue: '100',
|
||||
widthType: '%',
|
||||
heightValue: '600',
|
||||
heightType: 'px',
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
onUpdateWindowSettings({
|
||||
widthLabel: fullscreen
|
||||
? '100%'
|
||||
: inputValues.widthValue + inputValues.widthType,
|
||||
heightLabel: fullscreen
|
||||
? '100vh'
|
||||
: inputValues.heightValue + inputValues.heightType,
|
||||
})
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [inputValues, fullscreen])
|
||||
|
||||
const handleWidthTypeSelect = (widthType: string) =>
|
||||
setInputValues({ ...inputValues, widthType })
|
||||
const handleHeightTypeSelect = (heightType: string) =>
|
||||
setInputValues({ ...inputValues, heightType })
|
||||
|
||||
return (
|
||||
<Stack {...props}>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
<Heading fontSize="md" fontWeight="semibold" style={{ flexShrink: 0 }}>
|
||||
Window settings
|
||||
</Heading>
|
||||
<FormControl
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
w="full"
|
||||
justifyContent="flex-end"
|
||||
>
|
||||
<FormLabel htmlFor="fullscreen-option" mb="1">
|
||||
Set to fullscreen?
|
||||
</FormLabel>
|
||||
<Switch
|
||||
id="fullscreen-option"
|
||||
onChange={() => setFullscreen(!fullscreen)}
|
||||
isChecked={fullscreen}
|
||||
/>
|
||||
</FormControl>
|
||||
</Flex>
|
||||
|
||||
{!fullscreen && (
|
||||
<>
|
||||
<Flex justify="space-between" align="center" mb="2">
|
||||
<Text>Width</Text>
|
||||
<HStack>
|
||||
<Input
|
||||
onChange={(e) =>
|
||||
setInputValues({
|
||||
...inputValues,
|
||||
widthValue: e.target.value,
|
||||
})
|
||||
}
|
||||
w="70px"
|
||||
value={inputValues.widthValue}
|
||||
/>
|
||||
<DropdownList<string>
|
||||
items={['px', '%']}
|
||||
onItemSelect={handleWidthTypeSelect}
|
||||
currentItem={inputValues.widthType}
|
||||
/>
|
||||
</HStack>
|
||||
</Flex>
|
||||
<Flex justify="space-between" align="center" mb="2">
|
||||
<Text>Height</Text>
|
||||
<HStack>
|
||||
<Input
|
||||
onChange={(e) =>
|
||||
setInputValues({
|
||||
...inputValues,
|
||||
heightValue: e.target.value,
|
||||
})
|
||||
}
|
||||
w="70px"
|
||||
value={inputValues.heightValue}
|
||||
/>
|
||||
<DropdownList<string>
|
||||
items={['px', '%']}
|
||||
onItemSelect={handleHeightTypeSelect}
|
||||
currentItem={inputValues.heightType}
|
||||
/>
|
||||
</HStack>
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
)
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
import { FlexProps } from '@chakra-ui/react'
|
||||
import { CodeEditor } from 'components/shared/CodeEditor'
|
||||
import { useTypebot } from 'contexts/TypebotContext'
|
||||
|
||||
type Props = {
|
||||
widthLabel: string
|
||||
heightLabel: string
|
||||
onCopied?: () => void
|
||||
}
|
||||
export const IframeEmbedCode = ({
|
||||
widthLabel,
|
||||
heightLabel,
|
||||
}: Props & FlexProps) => {
|
||||
const { typebot } = useTypebot()
|
||||
const src = `https://${typebot?.publicId}.typebot.io`
|
||||
const code = `<iframe src="${src}" width="${widthLabel}" height="${heightLabel}" />`
|
||||
|
||||
return <CodeEditor value={code} lang="html" isReadOnly />
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
import { FlexProps } from '@chakra-ui/layout'
|
||||
import { CodeEditor } from 'components/shared/CodeEditor'
|
||||
import { useTypebot } from 'contexts/TypebotContext'
|
||||
import parserHtml from 'prettier/parser-html'
|
||||
import prettier from 'prettier/standalone'
|
||||
import { PopupParams } from 'typebot-js'
|
||||
import { parseInitPopupCode, typebotJsHtml } from '../params'
|
||||
|
||||
type PopupEmbedCodeProps = {
|
||||
delay: number
|
||||
withStarterVariables?: boolean
|
||||
onCopied?: () => void
|
||||
}
|
||||
|
||||
export const PopupEmbedCode = ({ delay }: PopupEmbedCodeProps & FlexProps) => {
|
||||
const { typebot } = useTypebot()
|
||||
const snippet = prettier.format(
|
||||
createSnippet({
|
||||
publishId: typebot?.publicId ?? '',
|
||||
delay,
|
||||
}),
|
||||
{
|
||||
parser: 'html',
|
||||
plugins: [parserHtml],
|
||||
}
|
||||
)
|
||||
return <CodeEditor value={snippet} lang="html" isReadOnly />
|
||||
}
|
||||
|
||||
const createSnippet = (params: PopupParams): string => {
|
||||
const jsCode = parseInitPopupCode(params)
|
||||
return `${typebotJsHtml}
|
||||
<script>${jsCode}</script>`
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
import {
|
||||
StackProps,
|
||||
Stack,
|
||||
Flex,
|
||||
Heading,
|
||||
NumberInput,
|
||||
NumberInputField,
|
||||
NumberInputStepper,
|
||||
NumberIncrementStepper,
|
||||
NumberDecrementStepper,
|
||||
} from '@chakra-ui/react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { PopupParams } from 'typebot-js'
|
||||
|
||||
type PopupEmbedSettingsProps = {
|
||||
onUpdateSettings: (windowSettings: Pick<PopupParams, 'delay'>) => void
|
||||
}
|
||||
export const PopupEmbedSettings = ({
|
||||
onUpdateSettings,
|
||||
...props
|
||||
}: PopupEmbedSettingsProps & StackProps) => {
|
||||
const [inputValue, setInputValue] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
onUpdateSettings({
|
||||
delay: inputValue * 1000,
|
||||
})
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [inputValue])
|
||||
|
||||
return (
|
||||
<Stack {...props}>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
<Heading fontSize="md" fontWeight="semibold">
|
||||
Popup settings
|
||||
</Heading>
|
||||
</Flex>
|
||||
|
||||
<Flex justify="space-between" align="center" mb="2">
|
||||
<p>Appearance delay</p>
|
||||
<NumberInput
|
||||
onChange={(_, val) => setInputValue(val)}
|
||||
value={inputValue}
|
||||
min={0}
|
||||
>
|
||||
<NumberInputField />
|
||||
<NumberInputStepper>
|
||||
<NumberIncrementStepper />
|
||||
<NumberDecrementStepper />
|
||||
</NumberInputStepper>
|
||||
</NumberInput>
|
||||
</Flex>
|
||||
</Stack>
|
||||
)
|
||||
}
|
154
apps/builder/components/share/codeSnippets/ReactCode.tsx
Normal file
154
apps/builder/components/share/codeSnippets/ReactCode.tsx
Normal file
@ -0,0 +1,154 @@
|
||||
import { FlexProps } from '@chakra-ui/react'
|
||||
import React from 'react'
|
||||
import { BubbleParams, IframeParams, PopupParams } from 'typebot-js'
|
||||
import {
|
||||
parseInitBubbleCode,
|
||||
parseInitContainerCode,
|
||||
parseInitPopupCode,
|
||||
} from './params'
|
||||
import parserBabel from 'prettier/parser-babel'
|
||||
import prettier from 'prettier/standalone'
|
||||
import { CodeEditor } from 'components/shared/CodeEditor'
|
||||
import { useTypebot } from 'contexts/TypebotContext'
|
||||
|
||||
type StandardReactDivProps = { widthLabel: string; heightLabel: string }
|
||||
export const StandardReactDiv = ({
|
||||
widthLabel,
|
||||
heightLabel,
|
||||
}: StandardReactDivProps) => {
|
||||
const { typebot } = useTypebot()
|
||||
const snippet = prettier.format(
|
||||
parseContainerSnippet({
|
||||
publishId: typebot?.publicId ?? '',
|
||||
heightLabel,
|
||||
widthLabel,
|
||||
}),
|
||||
{
|
||||
parser: 'babel',
|
||||
plugins: [parserBabel],
|
||||
}
|
||||
)
|
||||
return <CodeEditor value={snippet} lang="js" isReadOnly />
|
||||
}
|
||||
|
||||
type SnippetProps = IframeParams &
|
||||
Pick<StandardReactDivProps, 'widthLabel' | 'heightLabel'>
|
||||
|
||||
const parseContainerSnippet = ({
|
||||
publishId,
|
||||
customDomain,
|
||||
backgroundColor,
|
||||
hiddenVariables,
|
||||
...embedProps
|
||||
}: SnippetProps): string => {
|
||||
const jsCode = parseInitContainerCode({
|
||||
publishId,
|
||||
customDomain,
|
||||
backgroundColor,
|
||||
hiddenVariables,
|
||||
})
|
||||
return `import {initContainer} from "typebot-js";
|
||||
|
||||
const Component = () => {
|
||||
useEffect(()=> {
|
||||
${jsCode}
|
||||
}, [])
|
||||
|
||||
return <div id="typebot-container" style={{width: "${embedProps.widthLabel}", height: "${embedProps.heightLabel}"}} />
|
||||
}`
|
||||
}
|
||||
|
||||
type PopupEmbedCodeProps = {
|
||||
delay: number
|
||||
withStarterVariables?: boolean
|
||||
}
|
||||
|
||||
export const PopupReactCode = ({ delay }: PopupEmbedCodeProps & FlexProps) => {
|
||||
const { typebot } = useTypebot()
|
||||
const snippet = prettier.format(
|
||||
parsePopupSnippet({
|
||||
publishId: typebot?.publicId ?? '',
|
||||
delay,
|
||||
}),
|
||||
{
|
||||
parser: 'babel',
|
||||
plugins: [parserBabel],
|
||||
}
|
||||
)
|
||||
return <CodeEditor value={snippet} lang="js" isReadOnly />
|
||||
}
|
||||
|
||||
const parsePopupSnippet = ({
|
||||
publishId,
|
||||
customDomain,
|
||||
backgroundColor,
|
||||
hiddenVariables,
|
||||
delay,
|
||||
}: PopupParams): string => {
|
||||
const jsCode = parseInitPopupCode({
|
||||
publishId,
|
||||
customDomain,
|
||||
backgroundColor,
|
||||
hiddenVariables,
|
||||
delay,
|
||||
})
|
||||
return `import {initPopup} from "typebot-js";
|
||||
|
||||
const Component = () => {
|
||||
useEffect(()=> {
|
||||
${jsCode}
|
||||
}, [])
|
||||
|
||||
return <></>;
|
||||
}`
|
||||
}
|
||||
|
||||
type ChatEmbedCodeProps = {
|
||||
withStarterVariables?: boolean
|
||||
} & Pick<BubbleParams, 'button' | 'proactiveMessage'>
|
||||
|
||||
export const ChatReactCode = ({
|
||||
proactiveMessage,
|
||||
button,
|
||||
}: ChatEmbedCodeProps & FlexProps) => {
|
||||
const { typebot } = useTypebot()
|
||||
const snippet = prettier.format(
|
||||
parseBubbleSnippet({
|
||||
publishId: typebot?.publicId ?? '',
|
||||
button,
|
||||
proactiveMessage,
|
||||
}),
|
||||
{
|
||||
parser: 'babel',
|
||||
plugins: [parserBabel],
|
||||
}
|
||||
)
|
||||
return <CodeEditor value={snippet} lang="js" isReadOnly />
|
||||
}
|
||||
|
||||
const parseBubbleSnippet = ({
|
||||
publishId,
|
||||
customDomain,
|
||||
backgroundColor,
|
||||
hiddenVariables,
|
||||
proactiveMessage,
|
||||
button,
|
||||
}: BubbleParams): string => {
|
||||
const jsCode = parseInitBubbleCode({
|
||||
publishId,
|
||||
customDomain,
|
||||
backgroundColor,
|
||||
hiddenVariables,
|
||||
proactiveMessage,
|
||||
button,
|
||||
})
|
||||
return `import {initBubble} from "typebot-js";
|
||||
|
||||
const Component = () => {
|
||||
useEffect(()=> {
|
||||
${jsCode}
|
||||
}, [])
|
||||
|
||||
return <></>
|
||||
}`
|
||||
}
|
142
apps/builder/components/share/codeSnippets/params.ts
Normal file
142
apps/builder/components/share/codeSnippets/params.ts
Normal file
@ -0,0 +1,142 @@
|
||||
import {
|
||||
BubbleParams,
|
||||
ButtonParams,
|
||||
IframeParams,
|
||||
PopupParams,
|
||||
ProactiveMessageParams,
|
||||
} from 'typebot-js'
|
||||
import parserBabel from 'prettier/parser-babel'
|
||||
import prettier from 'prettier/standalone'
|
||||
|
||||
const parseStringParam = (fieldName: string, fieldValue?: string) =>
|
||||
fieldValue ? `${fieldName}: "${fieldValue}",` : ``
|
||||
|
||||
const parseNonStringParam = (
|
||||
fieldName: string,
|
||||
fieldValue?: number | boolean
|
||||
) => (fieldValue ? `${fieldName}: ${fieldValue},` : ``)
|
||||
|
||||
const parseCustomDomain = (domain?: string): string =>
|
||||
parseStringParam('customDomain', domain)
|
||||
|
||||
const parseHiddenVariables = (
|
||||
variables: { [key: string]: string | undefined } | undefined
|
||||
): string => (variables ? `hiddenVariables: ${JSON.stringify(variables)},` : ``)
|
||||
|
||||
const parseBackgroundColor = (bgColor?: string): string =>
|
||||
parseStringParam('backgroundColor', bgColor)
|
||||
|
||||
const parseDelay = (delay?: number) => parseNonStringParam('delay', delay)
|
||||
|
||||
const parseButton = (button?: ButtonParams): string => {
|
||||
if (!button) return ''
|
||||
const iconUrlString = parseStringParam('iconUrl', button.iconUrl)
|
||||
const buttonColorstring = parseStringParam('color', button.color)
|
||||
return `button: {${iconUrlString}${buttonColorstring}},`
|
||||
}
|
||||
|
||||
const parseProactiveMessage = (
|
||||
proactiveMessage?: ProactiveMessageParams
|
||||
): string => {
|
||||
if (!proactiveMessage) return ``
|
||||
const { avatarUrl, textContent, delay, rememberClose } = proactiveMessage
|
||||
const avatarUrlString = parseStringParam('avatarUrl', avatarUrl)
|
||||
const textContentString = parseStringParam('textContent', textContent)
|
||||
const rememberCloseString = parseNonStringParam(
|
||||
'rememberClose',
|
||||
rememberClose
|
||||
)
|
||||
const delayString = parseNonStringParam('delay', delay)
|
||||
return `proactiveMessage: {${avatarUrlString}${textContentString}${rememberCloseString}${delayString}},`
|
||||
}
|
||||
|
||||
const parseIframeParams = ({
|
||||
customDomain,
|
||||
hiddenVariables,
|
||||
backgroundColor,
|
||||
}: Pick<
|
||||
IframeParams,
|
||||
'customDomain' | 'hiddenVariables' | 'backgroundColor'
|
||||
>) => ({
|
||||
customDomainString: parseCustomDomain(customDomain),
|
||||
hiddenVariablesString: parseHiddenVariables(hiddenVariables),
|
||||
bgColorString: parseBackgroundColor(backgroundColor),
|
||||
})
|
||||
|
||||
const parsePopupParams = ({ delay }: Pick<PopupParams, 'delay'>) => ({
|
||||
delayString: parseDelay(delay),
|
||||
})
|
||||
|
||||
const parseBubbleParams = ({
|
||||
button,
|
||||
proactiveMessage,
|
||||
}: Pick<BubbleParams, 'button' | 'proactiveMessage'>) => ({
|
||||
proactiveMessageString: parseProactiveMessage(proactiveMessage),
|
||||
buttonString: parseButton(button),
|
||||
})
|
||||
|
||||
export const parseInitContainerCode = ({
|
||||
publishId,
|
||||
customDomain,
|
||||
backgroundColor,
|
||||
hiddenVariables,
|
||||
}: IframeParams) => {
|
||||
const { customDomainString, hiddenVariablesString, bgColorString } =
|
||||
parseIframeParams({
|
||||
customDomain,
|
||||
hiddenVariables,
|
||||
backgroundColor,
|
||||
})
|
||||
return prettier.format(
|
||||
`Typebot.initContainer("typebot-container", {
|
||||
publishId: "${publishId}",${bgColorString}${customDomainString}${hiddenVariablesString}
|
||||
});`,
|
||||
{ parser: 'babel', plugins: [parserBabel] }
|
||||
)
|
||||
}
|
||||
|
||||
export const parseInitPopupCode = ({
|
||||
publishId,
|
||||
customDomain,
|
||||
hiddenVariables,
|
||||
backgroundColor,
|
||||
delay,
|
||||
}: PopupParams) => {
|
||||
const { customDomainString, hiddenVariablesString, bgColorString } =
|
||||
parseIframeParams({
|
||||
customDomain,
|
||||
hiddenVariables,
|
||||
backgroundColor,
|
||||
})
|
||||
const { delayString } = parsePopupParams({ delay })
|
||||
return prettier.format(
|
||||
`var typebotCommands = Typebot.initPopup({publishId: "${publishId}",${delayString}${bgColorString}${customDomainString}${hiddenVariablesString}});`,
|
||||
{ parser: 'babel', plugins: [parserBabel] }
|
||||
)
|
||||
}
|
||||
|
||||
export const parseInitBubbleCode = ({
|
||||
publishId,
|
||||
customDomain,
|
||||
hiddenVariables,
|
||||
backgroundColor,
|
||||
button,
|
||||
proactiveMessage,
|
||||
}: BubbleParams) => {
|
||||
const { customDomainString, hiddenVariablesString, bgColorString } =
|
||||
parseIframeParams({
|
||||
customDomain,
|
||||
hiddenVariables,
|
||||
backgroundColor,
|
||||
})
|
||||
const { buttonString, proactiveMessageString } = parseBubbleParams({
|
||||
button,
|
||||
proactiveMessage,
|
||||
})
|
||||
return prettier.format(
|
||||
`var typebotCommands = Typebot.initBubble({publishId: "${publishId}",${bgColorString}${customDomainString}${hiddenVariablesString}${proactiveMessageString}${buttonString}});`,
|
||||
{ parser: 'babel', plugins: [parserBabel] }
|
||||
)
|
||||
}
|
||||
|
||||
export const typebotJsHtml = `<script src="https://unpkg.com/typebot-js@2.0.20"></script>`
|
@ -21,6 +21,7 @@ import {
|
||||
ReactModal,
|
||||
NotionModal,
|
||||
IframeModal,
|
||||
WixModal,
|
||||
} from './modals'
|
||||
|
||||
export type ModalProps = {
|
||||
@ -82,7 +83,7 @@ export const integrationsList = [
|
||||
<EmbedButton
|
||||
logo={<WixLogo height={100} width="90px" />}
|
||||
label="Wix"
|
||||
Modal={WebflowModal}
|
||||
Modal={WixModal}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
@ -128,7 +129,7 @@ export const integrationsList = [
|
||||
),
|
||||
(props: Pick<ModalProps, 'publicId' | 'isPublished'>) => (
|
||||
<EmbedButton
|
||||
logo={<IframeLogo height={100} width={80} />}
|
||||
logo={<IframeLogo height={100} width="70px" />}
|
||||
label="Iframe"
|
||||
Modal={IframeModal}
|
||||
{...props}
|
||||
@ -136,7 +137,7 @@ export const integrationsList = [
|
||||
),
|
||||
(props: Pick<ModalProps, 'publicId' | 'isPublished'>) => (
|
||||
<EmbedButton
|
||||
logo={<OtherLogo height={100} width={80} />}
|
||||
logo={<OtherLogo height={100} width="70px" />}
|
||||
label="Other"
|
||||
Modal={JavascriptModal}
|
||||
{...props}
|
||||
|
@ -1,14 +1,27 @@
|
||||
import { OrderedList, ListItem, Tag } from '@chakra-ui/react'
|
||||
import { ChatEmbedCode } from 'components/share/codeSnippets/Chat/EmbedCode'
|
||||
import { ChatEmbedSettings } from 'components/share/codeSnippets/Chat/EmbedSettings'
|
||||
import { StandardEmbedWindowSettings } from 'components/share/codeSnippets/Container/EmbedSettings'
|
||||
import {
|
||||
parseInitContainerCode,
|
||||
typebotJsHtml,
|
||||
} from 'components/share/codeSnippets/params'
|
||||
import { PopupEmbedCode } from 'components/share/codeSnippets/Popup/EmbedCode'
|
||||
import { PopupEmbedSettings } from 'components/share/codeSnippets/Popup/EmbedSettings'
|
||||
import { CodeEditor } from 'components/shared/CodeEditor'
|
||||
import { useState } from 'react'
|
||||
import { BubbleParams } from 'typebot-js'
|
||||
import { ModalProps } from '../../EmbedButton'
|
||||
|
||||
type GtmInstructionsProps = {
|
||||
type: 'standard' | 'popup' | 'bubble'
|
||||
publicId: string
|
||||
}
|
||||
|
||||
export const GtmInstructions = ({ type }: GtmInstructionsProps) => {
|
||||
export const GtmInstructions = ({ type, publicId }: GtmInstructionsProps) => {
|
||||
switch (type) {
|
||||
case 'standard': {
|
||||
return <StandardInstructions />
|
||||
return <StandardInstructions publicId={publicId} />
|
||||
}
|
||||
case 'popup': {
|
||||
return <PopupInstructions />
|
||||
@ -19,23 +32,21 @@ export const GtmInstructions = ({ type }: GtmInstructionsProps) => {
|
||||
}
|
||||
}
|
||||
|
||||
const StandardInstructions = () => {
|
||||
// const [windowSizes, setWindowSizes] = useState({
|
||||
// height: '100%',
|
||||
// width: '100%',
|
||||
// })
|
||||
const StandardInstructions = ({ publicId }: Pick<ModalProps, 'publicId'>) => {
|
||||
const [windowSizes, setWindowSizes] = useState({
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
})
|
||||
|
||||
// const jsCode = parseInitContainerCode({
|
||||
// publishId: chatbot?.publishId ?? '',
|
||||
// backgroundColor: chatbot?.themeColors.chatbotBackground.value,
|
||||
// customDomain: chatbot?.customDomains[0],
|
||||
// })
|
||||
// const headCode = `${typebotJsHtml}
|
||||
// <script>
|
||||
// ${jsCode}
|
||||
// </script>`
|
||||
const jsCode = parseInitContainerCode({
|
||||
publishId: publicId,
|
||||
})
|
||||
const headCode = `${typebotJsHtml}
|
||||
<script>
|
||||
${jsCode}
|
||||
</script>`
|
||||
|
||||
// const elementCode = `<div id="typebot-container" style="background-color: ${backgroundColor}; height: ${windowSizes.height}; width: ${windowSizes.width}"></div>`
|
||||
const elementCode = `<div id="typebot-container" style="height: ${windowSizes.height}; width: ${windowSizes.width}"></div>`
|
||||
return (
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
<ListItem>
|
||||
@ -46,16 +57,12 @@ const StandardInstructions = () => {
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Paste the code below:
|
||||
{/* <CodeEditor
|
||||
code={headCode}
|
||||
mt={2}
|
||||
onCopied={() => sendGtmCopyEvent('standard')}
|
||||
/> */}
|
||||
<CodeEditor value={headCode} mt={2} isReadOnly lang="html" />
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
On your webpage, you need to have an element on which the typebot will
|
||||
go. It needs to have the id <Tag>typebot-container</Tag>:
|
||||
{/* <StandardEmbedWindowSettings
|
||||
<StandardEmbedWindowSettings
|
||||
my={4}
|
||||
onUpdateWindowSettings={(sizes) =>
|
||||
setWindowSizes({
|
||||
@ -64,14 +71,14 @@ const StandardInstructions = () => {
|
||||
})
|
||||
}
|
||||
/>
|
||||
<CodeBlock code={elementCode} mt={2} /> */}
|
||||
<CodeEditor value={elementCode} mt={2} isReadOnly lang="html" />
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
)
|
||||
}
|
||||
|
||||
const PopupInstructions = () => {
|
||||
// const [inputValue, setInputValue] = useState(0)
|
||||
const [inputValue, setInputValue] = useState(0)
|
||||
|
||||
return (
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
@ -83,29 +90,26 @@ const PopupInstructions = () => {
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Paste the code below:
|
||||
{/* <PopupEmbedSettings
|
||||
mb={4}
|
||||
<PopupEmbedSettings
|
||||
my={4}
|
||||
onUpdateSettings={(settings) => setInputValue(settings.delay ?? 0)}
|
||||
/>
|
||||
<PopupEmbedCode
|
||||
delay={inputValue}
|
||||
onCopied={() => sendGtmCopyEvent('popup')}
|
||||
/> */}
|
||||
<PopupEmbedCode delay={inputValue} />
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
)
|
||||
}
|
||||
|
||||
const BubbleInstructions = () => {
|
||||
// const [inputValues, setInputValues] = useState<
|
||||
// Pick<BubbleParams, 'proactiveMessage' | 'button'>
|
||||
// >({
|
||||
// proactiveMessage: undefined,
|
||||
// button: {
|
||||
// color: '',
|
||||
// iconUrl: '',
|
||||
// },
|
||||
// })
|
||||
const [inputValues, setInputValues] = useState<
|
||||
Pick<BubbleParams, 'proactiveMessage' | 'button'>
|
||||
>({
|
||||
proactiveMessage: undefined,
|
||||
button: {
|
||||
color: '',
|
||||
iconUrl: '',
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
@ -117,14 +121,10 @@ const BubbleInstructions = () => {
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Paste the code below:
|
||||
{/* <ChatEmbedSettings
|
||||
<ChatEmbedSettings
|
||||
onUpdateSettings={(settings) => setInputValues({ ...settings })}
|
||||
/>
|
||||
<ChatEmbedCode
|
||||
mt={4}
|
||||
{...inputValues}
|
||||
onCopied={() => sendGtmCopyEvent('bubble')}
|
||||
/> */}
|
||||
<ChatEmbedCode my={4} {...inputValues} />
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
)
|
||||
|
@ -18,7 +18,12 @@ import { capitalize } from 'utils'
|
||||
import { PublishFirstInfo } from 'components/shared/Info'
|
||||
import { GtmInstructions } from './GtmInstructions'
|
||||
|
||||
export const GtmModal = ({ isOpen, onClose, isPublished }: ModalProps) => {
|
||||
export const GtmModal = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
isPublished,
|
||||
publicId,
|
||||
}: ModalProps) => {
|
||||
const [chosenEmbedType, setChosenEmbedType] = useState<
|
||||
'standard' | 'popup' | 'bubble' | undefined
|
||||
>()
|
||||
@ -53,7 +58,7 @@ export const GtmModal = ({ isOpen, onClose, isPublished }: ModalProps) => {
|
||||
{!chosenEmbedType ? (
|
||||
<ChooseEmbedTypeList onSelectEmbedType={setChosenEmbedType} />
|
||||
) : (
|
||||
<GtmInstructions type={chosenEmbedType} />
|
||||
<GtmInstructions type={chosenEmbedType} publicId={publicId} />
|
||||
)}
|
||||
</ModalBody>
|
||||
<ModalFooter />
|
||||
|
@ -9,16 +9,13 @@ import {
|
||||
ModalFooter,
|
||||
Text,
|
||||
} from '@chakra-ui/react'
|
||||
import { StandardEmbedWindowSettings } from 'components/share/codeSnippets/Container/EmbedSettings'
|
||||
import { IframeEmbedCode } from 'components/share/codeSnippets/Iframe/EmbedCode'
|
||||
import { PublishFirstInfo } from 'components/shared/Info'
|
||||
import { useState } from 'react'
|
||||
import { ModalProps } from '../EmbedButton'
|
||||
|
||||
export const IframeModal = ({
|
||||
isPublished,
|
||||
publicId,
|
||||
isOpen,
|
||||
onClose,
|
||||
}: ModalProps) => {
|
||||
export const IframeModal = ({ isPublished, isOpen, onClose }: ModalProps) => {
|
||||
const [inputValues, setInputValues] = useState({
|
||||
heightLabel: '100%',
|
||||
widthLabel: '100%',
|
||||
@ -33,6 +30,12 @@ export const IframeModal = ({
|
||||
<ModalBody as={Stack} spacing={4}>
|
||||
{!isPublished && <PublishFirstInfo />}
|
||||
<Text>Paste this anywhere in your HTML code:</Text>
|
||||
<StandardEmbedWindowSettings
|
||||
onUpdateWindowSettings={(settings) =>
|
||||
setInputValues({ ...settings })
|
||||
}
|
||||
/>
|
||||
<IframeEmbedCode {...inputValues} />
|
||||
</ModalBody>
|
||||
<ModalFooter />
|
||||
</ModalContent>
|
||||
|
@ -1,4 +1,12 @@
|
||||
import { Stack, Tag, Text } from '@chakra-ui/react'
|
||||
import { ChatEmbedCode } from 'components/share/codeSnippets/Chat/EmbedCode'
|
||||
import { ChatEmbedSettings } from 'components/share/codeSnippets/Chat/EmbedSettings'
|
||||
import { ContainerEmbedCode } from 'components/share/codeSnippets/Container/EmbedCode'
|
||||
import { StandardEmbedWindowSettings } from 'components/share/codeSnippets/Container/EmbedSettings'
|
||||
import { PopupEmbedCode } from 'components/share/codeSnippets/Popup/EmbedCode'
|
||||
import { PopupEmbedSettings } from 'components/share/codeSnippets/Popup/EmbedSettings'
|
||||
import { useState } from 'react'
|
||||
import { BubbleParams } from 'typebot-js'
|
||||
|
||||
type JavascriptInstructionsProps = {
|
||||
type: 'standard' | 'popup' | 'bubble'
|
||||
@ -21,75 +29,61 @@ export const JavascriptInstructions = ({
|
||||
}
|
||||
|
||||
const StandardInstructions = () => {
|
||||
// const [inputValues, setInputValues] = useState({
|
||||
// heightLabel: '100%',
|
||||
// widthLabel: '100%',
|
||||
// })
|
||||
const [inputValues, setInputValues] = useState({
|
||||
heightLabel: '100%',
|
||||
widthLabel: '100%',
|
||||
})
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Stack spacing={4}>
|
||||
<Text>
|
||||
Paste this anywhere in the <Tag>body</Tag>
|
||||
</Text>
|
||||
{/* <StandardEmbedWindowSettings
|
||||
<StandardEmbedWindowSettings
|
||||
onUpdateWindowSettings={(settings) => setInputValues({ ...settings })}
|
||||
/>
|
||||
<ContainerEmbedCode
|
||||
withStarterVariables={true}
|
||||
{...inputValues}
|
||||
mt={4}
|
||||
onCopied={() => sendJsCopyEvent('standard')}
|
||||
/> */}
|
||||
<ContainerEmbedCode withStarterVariables={true} {...inputValues} mt={4} />
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
const PopupInstructions = () => {
|
||||
// const [inputValue, setInputValue] = useState(0)
|
||||
const [inputValue, setInputValue] = useState(0)
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Stack spacing={4}>
|
||||
<Text>
|
||||
Paste this anywhere in the <Tag>body</Tag>
|
||||
</Text>
|
||||
{/* <StandardEmbedWindowSettings
|
||||
onUpdateWindowSettings={(settings) => setInputValues({ ...settings })}
|
||||
<PopupEmbedSettings
|
||||
mb={4}
|
||||
onUpdateSettings={(settings) => setInputValue(settings.delay ?? 0)}
|
||||
/>
|
||||
<ContainerEmbedCode
|
||||
withStarterVariables={true}
|
||||
{...inputValues}
|
||||
mt={4}
|
||||
onCopied={() => sendJsCopyEvent('standard')}
|
||||
/> */}
|
||||
<PopupEmbedCode delay={inputValue} />
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
const BubbleInstructions = () => {
|
||||
// const [inputValues, setInputValues] = useState<
|
||||
// Pick<BubbleParams, 'proactiveMessage' | 'button'>
|
||||
// >({
|
||||
// proactiveMessage: undefined,
|
||||
// button: {
|
||||
// color: '',
|
||||
// iconUrl: '',
|
||||
// },
|
||||
// })
|
||||
const [inputValues, setInputValues] = useState<
|
||||
Pick<BubbleParams, 'proactiveMessage' | 'button'>
|
||||
>({
|
||||
proactiveMessage: undefined,
|
||||
button: {
|
||||
color: '',
|
||||
iconUrl: '',
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Stack spacing={4}>
|
||||
<Text>
|
||||
Paste this anywhere in the <Tag>body</Tag>
|
||||
</Text>
|
||||
{/* <StandardEmbedWindowSettings
|
||||
onUpdateWindowSettings={(settings) => setInputValues({ ...settings })}
|
||||
<ChatEmbedSettings
|
||||
onUpdateSettings={(settings) => setInputValues({ ...settings })}
|
||||
/>
|
||||
<ContainerEmbedCode
|
||||
withStarterVariables={true}
|
||||
{...inputValues}
|
||||
mt={4}
|
||||
onCopied={() => sendJsCopyEvent('standard')}
|
||||
/> */}
|
||||
<ChatEmbedCode {...inputValues} />
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
@ -1,5 +1,15 @@
|
||||
import { Stack, Text } from '@chakra-ui/react'
|
||||
import { ChatEmbedSettings } from 'components/share/codeSnippets/Chat/EmbedSettings'
|
||||
import { StandardEmbedWindowSettings } from 'components/share/codeSnippets/Container/EmbedSettings'
|
||||
import { PopupEmbedSettings } from 'components/share/codeSnippets/Popup/EmbedSettings'
|
||||
import {
|
||||
ChatReactCode,
|
||||
PopupReactCode,
|
||||
StandardReactDiv,
|
||||
} from 'components/share/codeSnippets/ReactCode'
|
||||
import { CodeEditor } from 'components/shared/CodeEditor'
|
||||
import { useState } from 'react'
|
||||
import { BubbleParams } from 'typebot-js'
|
||||
|
||||
type Props = {
|
||||
type: 'standard' | 'popup' | 'bubble'
|
||||
@ -20,58 +30,57 @@ export const ReactInstructions = ({ type }: Props) => {
|
||||
}
|
||||
|
||||
const StandardInstructions = () => {
|
||||
// const [inputValues, setInputValues] = useState({
|
||||
// heightLabel: '100%',
|
||||
// widthLabel: '100%',
|
||||
// })
|
||||
const [inputValues, setInputValues] = useState({
|
||||
heightLabel: '100%',
|
||||
widthLabel: '100%',
|
||||
})
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
{/* <InstallPackageInstruction /> */}
|
||||
{/* <StandardEmbedWindowSettings
|
||||
<InstallPackageInstruction />
|
||||
<StandardEmbedWindowSettings
|
||||
onUpdateWindowSettings={(settings) => setInputValues({ ...settings })}
|
||||
/> */}
|
||||
{/* <Text>{t('insert-the-typebot-container')}</Text>
|
||||
<StandardReactDiv {...inputValues} /> */}
|
||||
/>
|
||||
<Text>Insert the typebot container</Text>
|
||||
<StandardReactDiv {...inputValues} />
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
const PopupInstructions = () => {
|
||||
// const [inputValue, setInputValue] = useState(0)
|
||||
const [inputValue, setInputValue] = useState(0)
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
{/* <InstallPackageInstruction />
|
||||
<InstallPackageInstruction />
|
||||
<PopupEmbedSettings
|
||||
onUpdateSettings={(settings) => setInputValue(settings.delay ?? 0)}
|
||||
/>
|
||||
<Text>{t('initialize-the-typebot')}</Text>
|
||||
<PopupReactCode withStarterVariables={true} delay={inputValue} /> */}
|
||||
<Text>Initialize the typebot</Text>
|
||||
<PopupReactCode withStarterVariables={true} delay={inputValue} />
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
const BubbleInstructions = () => {
|
||||
// const { t } = useTranslation()
|
||||
// const [inputValues, setInputValues] = useState<
|
||||
// Pick<BubbleParams, 'proactiveMessage' | 'button'>
|
||||
// >({
|
||||
// proactiveMessage: undefined,
|
||||
// button: {
|
||||
// color: '',
|
||||
// iconUrl: '',
|
||||
// },
|
||||
// })
|
||||
const [inputValues, setInputValues] = useState<
|
||||
Pick<BubbleParams, 'proactiveMessage' | 'button'>
|
||||
>({
|
||||
proactiveMessage: undefined,
|
||||
button: {
|
||||
color: '',
|
||||
iconUrl: '',
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
{/* <InstallPackageInstruction />
|
||||
<InstallPackageInstruction />
|
||||
<ChatEmbedSettings
|
||||
onUpdateSettings={(settings) => setInputValues({ ...settings })}
|
||||
/>
|
||||
<Text>{t('initialize-the-typebot')}</Text>
|
||||
<ChatReactCode withStarterVariables={true} {...inputValues} mt={4} /> */}
|
||||
<Text>Initialize the typebot</Text>
|
||||
<ChatReactCode withStarterVariables={true} {...inputValues} mt={4} />
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
@ -1,13 +1,32 @@
|
||||
import { OrderedList, ListItem, Tag } from '@chakra-ui/react'
|
||||
import { ChatEmbedCode } from 'components/share/codeSnippets/Chat/EmbedCode'
|
||||
import { ChatEmbedSettings } from 'components/share/codeSnippets/Chat/EmbedSettings'
|
||||
import { StandardEmbedWindowSettings } from 'components/share/codeSnippets/Container/EmbedSettings'
|
||||
import {
|
||||
parseInitContainerCode,
|
||||
typebotJsHtml,
|
||||
} from 'components/share/codeSnippets/params'
|
||||
import { PopupEmbedCode } from 'components/share/codeSnippets/Popup/EmbedCode'
|
||||
import { PopupEmbedSettings } from 'components/share/codeSnippets/Popup/EmbedSettings'
|
||||
import { CodeEditor } from 'components/shared/CodeEditor'
|
||||
import { useState } from 'react'
|
||||
import { BubbleParams } from 'typebot-js'
|
||||
import { ModalProps } from '../../EmbedButton'
|
||||
import parserHtml from 'prettier/parser-html'
|
||||
import prettier from 'prettier/standalone'
|
||||
|
||||
type ShopifyInstructionsProps = {
|
||||
type: 'standard' | 'popup' | 'bubble'
|
||||
publicId: string
|
||||
}
|
||||
|
||||
export const ShopifyInstructions = ({ type }: ShopifyInstructionsProps) => {
|
||||
export const ShopifyInstructions = ({
|
||||
type,
|
||||
publicId,
|
||||
}: ShopifyInstructionsProps) => {
|
||||
switch (type) {
|
||||
case 'standard': {
|
||||
return <StandardInstructions />
|
||||
return <StandardInstructions publicId={publicId} />
|
||||
}
|
||||
case 'popup': {
|
||||
return <PopupInstructions />
|
||||
@ -18,24 +37,30 @@ export const ShopifyInstructions = ({ type }: ShopifyInstructionsProps) => {
|
||||
}
|
||||
}
|
||||
|
||||
const StandardInstructions = () => {
|
||||
// const backgroundColor = chatbot?.themeColors.siteBackground.value
|
||||
// const [windowSizes, setWindowSizes] = useState({
|
||||
// height: '100%',
|
||||
// width: '100%',
|
||||
// })
|
||||
const StandardInstructions = ({ publicId }: Pick<ModalProps, 'publicId'>) => {
|
||||
const [windowSizes, setWindowSizes] = useState({
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
})
|
||||
|
||||
// const jsCode = parseInitContainerCode({
|
||||
// publishId: chatbot?.publishId ?? '',
|
||||
// customDomain: chatbot?.customDomains[0],
|
||||
// backgroundColor: chatbot?.themeColors.chatbotBackground.value,
|
||||
// })
|
||||
// const headCode = `${typebotJsHtml}
|
||||
// <script>
|
||||
// ${jsCode}
|
||||
// </script>`
|
||||
const jsCode = parseInitContainerCode({
|
||||
publishId: publicId,
|
||||
})
|
||||
const headCode = prettier.format(
|
||||
`${typebotJsHtml}<script>${jsCode}</script>`,
|
||||
{
|
||||
parser: 'html',
|
||||
plugins: [parserHtml],
|
||||
}
|
||||
)
|
||||
|
||||
// const elementCode = `<div id="typebot-container" style="background-color: ${backgroundColor}; height: ${windowSizes.height}; width: ${windowSizes.width}"></div>`
|
||||
const elementCode = prettier.format(
|
||||
`<div id="typebot-container" style="height: ${windowSizes.height}; width: ${windowSizes.width}"></div>`,
|
||||
{
|
||||
parser: 'html',
|
||||
plugins: [parserHtml],
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
@ -46,17 +71,13 @@ const StandardInstructions = () => {
|
||||
<ListItem>
|
||||
In <Tag>Layout {'>'} theme.liquid</Tag> file, paste this code just
|
||||
before the closing <Tag>head</Tag> tag:
|
||||
{/* <CodeBlock
|
||||
code={headCode}
|
||||
mt={2}
|
||||
onCopied={() => sendShopifyCopyEvent('standard')}
|
||||
/> */}
|
||||
<CodeEditor value={headCode} mt={2} lang="html" isReadOnly />
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Then, you can place an element on which the typebot will go in any file
|
||||
in the <Tag>body</Tag> tags. It needs to have the id{' '}
|
||||
<Tag>typebot-container</Tag>:
|
||||
{/* <StandardEmbedWindowSettings
|
||||
<StandardEmbedWindowSettings
|
||||
my={4}
|
||||
onUpdateWindowSettings={(sizes) =>
|
||||
setWindowSizes({
|
||||
@ -65,14 +86,14 @@ const StandardInstructions = () => {
|
||||
})
|
||||
}
|
||||
/>
|
||||
<CodeBlock code={elementCode} mt={2} /> */}
|
||||
<CodeEditor value={elementCode} mt={2} lang="html" isReadOnly />
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
)
|
||||
}
|
||||
|
||||
const PopupInstructions = () => {
|
||||
// const [inputValue, setInputValue] = useState(0)
|
||||
const [inputValue, setInputValue] = useState(0)
|
||||
|
||||
return (
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
@ -83,29 +104,26 @@ const PopupInstructions = () => {
|
||||
<ListItem>
|
||||
In <Tag>Layout {'>'} theme.liquid</Tag> file, paste this code just
|
||||
before the closing <Tag>head</Tag> tag:
|
||||
{/* <PopupEmbedSettings
|
||||
mb={4}
|
||||
onUpdateSettings={(settings) => setInputValue(settings.delay ?? 0)}
|
||||
/>
|
||||
<PopupEmbedCode
|
||||
delay={inputValue}
|
||||
onCopied={() => sendShopifyCopyEvent('popup')}
|
||||
/> */}
|
||||
<PopupEmbedSettings
|
||||
my="4"
|
||||
onUpdateSettings={(settings) => setInputValue(settings.delay ?? 0)}
|
||||
/>
|
||||
<PopupEmbedCode delay={inputValue} />
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
)
|
||||
}
|
||||
|
||||
const BubbleInstructions = () => {
|
||||
// const [inputValues, setInputValues] = useState<
|
||||
// Pick<BubbleParams, 'proactiveMessage' | 'button'>
|
||||
// >({
|
||||
// proactiveMessage: undefined,
|
||||
// button: {
|
||||
// color: '',
|
||||
// iconUrl: '',
|
||||
// },
|
||||
// })
|
||||
const [inputValues, setInputValues] = useState<
|
||||
Pick<BubbleParams, 'proactiveMessage' | 'button'>
|
||||
>({
|
||||
proactiveMessage: undefined,
|
||||
button: {
|
||||
color: '',
|
||||
iconUrl: '',
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
@ -116,14 +134,11 @@ const BubbleInstructions = () => {
|
||||
<ListItem>
|
||||
In <Tag>Layout {'>'} theme.liquid</Tag> file, paste this code just
|
||||
before the closing <Tag>head</Tag> tag:
|
||||
{/* <ChatEmbedSettings
|
||||
onUpdateSettings={(settings) => setInputValues({ ...settings })}
|
||||
/>
|
||||
<ChatEmbedCode
|
||||
mt={4}
|
||||
{...inputValues}
|
||||
onCopied={() => sendShopifyCopyEvent('bubble')}
|
||||
/> */}
|
||||
<ChatEmbedSettings
|
||||
my="4"
|
||||
onUpdateSettings={(settings) => setInputValues({ ...settings })}
|
||||
/>
|
||||
<ChatEmbedCode mt={4} {...inputValues} />
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
)
|
||||
|
@ -18,7 +18,12 @@ import { capitalize } from 'utils'
|
||||
import { PublishFirstInfo } from 'components/shared/Info'
|
||||
import { ShopifyInstructions } from './ShopifyInstructions'
|
||||
|
||||
export const ShopifyModal = ({ isOpen, onClose, isPublished }: ModalProps) => {
|
||||
export const ShopifyModal = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
isPublished,
|
||||
publicId,
|
||||
}: ModalProps) => {
|
||||
const [chosenEmbedType, setChosenEmbedType] = useState<
|
||||
'standard' | 'popup' | 'bubble' | undefined
|
||||
>()
|
||||
@ -53,7 +58,7 @@ export const ShopifyModal = ({ isOpen, onClose, isPublished }: ModalProps) => {
|
||||
{!chosenEmbedType ? (
|
||||
<ChooseEmbedTypeList onSelectEmbedType={setChosenEmbedType} />
|
||||
) : (
|
||||
<ShopifyInstructions type={chosenEmbedType} />
|
||||
<ShopifyInstructions type={chosenEmbedType} publicId={publicId} />
|
||||
)}
|
||||
</ModalBody>
|
||||
<ModalFooter />
|
||||
|
@ -1,4 +1,11 @@
|
||||
import { OrderedList, ListItem, Tag, Text, Stack } from '@chakra-ui/react'
|
||||
import { ChatEmbedCode } from 'components/share/codeSnippets/Chat/EmbedCode'
|
||||
import { ChatEmbedSettings } from 'components/share/codeSnippets/Chat/EmbedSettings'
|
||||
import { ContainerEmbedCode } from 'components/share/codeSnippets/Container/EmbedCode'
|
||||
import { PopupEmbedCode } from 'components/share/codeSnippets/Popup/EmbedCode'
|
||||
import { PopupEmbedSettings } from 'components/share/codeSnippets/Popup/EmbedSettings'
|
||||
import { useState } from 'react'
|
||||
import { BubbleParams } from 'typebot-js'
|
||||
|
||||
type WebflowInstructionsProps = {
|
||||
type: 'standard' | 'popup' | 'bubble'
|
||||
@ -21,8 +28,22 @@ export const WebflowInstructions = ({ type }: WebflowInstructionsProps) => {
|
||||
}
|
||||
|
||||
const StandardInstructions = () => (
|
||||
<Stack>
|
||||
<Text>In the Webflow editor:</Text>
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
<ListItem>
|
||||
Press <Tag>A</Tag> to open the <Tag>Add elements</Tag> panel
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Add an <Tag>embed</Tag> element from the <Tag>components</Tag>
|
||||
section and paste this code:
|
||||
<ContainerEmbedCode widthLabel="100%" heightLabel="100%" my={4} />
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
)
|
||||
|
||||
const PopupInstructions = () => {
|
||||
const [inputValue, setInputValue] = useState(0)
|
||||
|
||||
return (
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
<ListItem>
|
||||
Press <Tag>A</Tag> to open the <Tag>Add elements</Tag> panel
|
||||
@ -30,78 +51,41 @@ const StandardInstructions = () => (
|
||||
<ListItem>
|
||||
Add an <Tag>embed</Tag> element from the <Tag>components</Tag>
|
||||
section and paste this code:
|
||||
{/* <ContainerEmbedCode
|
||||
widthLabel="100%"
|
||||
heightLabel="100%"
|
||||
mt={4}
|
||||
onCopied={() => sendWebflowCopyEvent('standard')}
|
||||
/> */}
|
||||
<PopupEmbedSettings
|
||||
onUpdateSettings={(settings) => setInputValue(settings.delay ?? 0)}
|
||||
my={4}
|
||||
/>
|
||||
<PopupEmbedCode delay={inputValue} mt={4} />
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
</Stack>
|
||||
)
|
||||
|
||||
const PopupInstructions = () => {
|
||||
// const [inputValue, setInputValue] = useState(0)
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Text>In the Webflow editor</Text>
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
<ListItem>
|
||||
Press <Tag>A</Tag> to open the <Tag>Add elements</Tag> panel
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Add an <Tag>embed</Tag> element from the <Tag>components</Tag>
|
||||
section and paste this code:
|
||||
{/* <PopupEmbedSettings
|
||||
onUpdateSettings={(settings) => setInputValue(settings.delay ?? 0)}
|
||||
mt={4}
|
||||
/>
|
||||
<PopupEmbedCode
|
||||
delay={inputValue}
|
||||
mt={4}
|
||||
onCopied={() => sendWebflowCopyEvent('popup')}
|
||||
/> */}
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
const BubbleInstructions = () => {
|
||||
// const [inputValues, setInputValues] = useState<
|
||||
// Pick<BubbleParams, 'proactiveMessage' | 'button'>
|
||||
// >({
|
||||
// proactiveMessage: undefined,
|
||||
// button: {
|
||||
// color: '',
|
||||
// iconUrl: '',
|
||||
// },
|
||||
// })
|
||||
const [inputValues, setInputValues] = useState<
|
||||
Pick<BubbleParams, 'proactiveMessage' | 'button'>
|
||||
>({
|
||||
proactiveMessage: undefined,
|
||||
button: {
|
||||
color: '',
|
||||
iconUrl: '',
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Text>In the Webflow editor</Text>
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
<ListItem>
|
||||
Press <Tag>A</Tag> to open the <Tag>Add elements</Tag> panel
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Add an <Tag>embed</Tag> element from the <Tag>components</Tag>
|
||||
section and paste this code:
|
||||
{/* <ChatEmbedSettings
|
||||
onUpdateSettings={(settings) => setInputValues({ ...settings })}
|
||||
mt={4}
|
||||
/>
|
||||
<ChatEmbedCode
|
||||
withStarterVariables={true}
|
||||
{...inputValues}
|
||||
mt={4}
|
||||
onCopied={() => sendWebflowCopyEvent('bubble')}
|
||||
/> */}
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
</Stack>
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
<ListItem>
|
||||
Press <Tag>A</Tag> to open the <Tag>Add elements</Tag> panel
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Add an <Tag>embed</Tag> element from the <Tag>components</Tag>
|
||||
section and paste this code:
|
||||
<ChatEmbedSettings
|
||||
onUpdateSettings={(settings) => setInputValues({ ...settings })}
|
||||
my={4}
|
||||
/>
|
||||
<ChatEmbedCode withStarterVariables={true} {...inputValues} my={4} />
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
)
|
||||
}
|
||||
|
@ -1,5 +1,11 @@
|
||||
import { ListItem, OrderedList, Tag } from '@chakra-ui/react'
|
||||
import { ChatEmbedCode } from 'components/share/codeSnippets/Chat/EmbedCode'
|
||||
import { ChatEmbedSettings } from 'components/share/codeSnippets/Chat/EmbedSettings'
|
||||
import { ContainerEmbedCode } from 'components/share/codeSnippets/Container/EmbedCode'
|
||||
import { PopupEmbedCode } from 'components/share/codeSnippets/Popup/EmbedCode'
|
||||
import { PopupEmbedSettings } from 'components/share/codeSnippets/Popup/EmbedSettings'
|
||||
import { useState } from 'react'
|
||||
import { BubbleParams } from 'typebot-js'
|
||||
|
||||
type WixInstructionsProps = {
|
||||
type: 'standard' | 'popup' | 'bubble'
|
||||
@ -21,24 +27,23 @@ export const WixInstructions = ({ type }: WixInstructionsProps) => {
|
||||
|
||||
const StandardInstructions = () => {
|
||||
return (
|
||||
<>
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
<ListItem>
|
||||
In the Wix Website Editor:
|
||||
<Tag>
|
||||
Add {'>'} Embed {'>'} Embed a Widget
|
||||
</Tag>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Click on <Tag>Enter code</Tag> and paste this code:
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
</>
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
<ListItem>
|
||||
In the Wix Website Editor:
|
||||
<Tag>
|
||||
Add {'>'} Embed {'>'} Embed a Widget
|
||||
</Tag>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Click on <Tag>Enter code</Tag> and paste this code:
|
||||
</ListItem>
|
||||
<ContainerEmbedCode widthLabel="100%" heightLabel="100%" />
|
||||
</OrderedList>
|
||||
)
|
||||
}
|
||||
|
||||
const PopupInstructions = () => {
|
||||
// const [inputValue, setInputValue] = useState(0)
|
||||
const [inputValue, setInputValue] = useState(0)
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -52,45 +57,49 @@ const PopupInstructions = () => {
|
||||
<ListItem>
|
||||
Click <Tag>+ Add Custom Code</Tag> at the top right.
|
||||
</ListItem>
|
||||
<ListItem>Paste this snippet in the code box:</ListItem>
|
||||
<ListItem>
|
||||
Paste this snippet in the code box:
|
||||
<PopupEmbedSettings
|
||||
onUpdateSettings={(settings) => setInputValue(settings.delay ?? 0)}
|
||||
my={4}
|
||||
/>
|
||||
<PopupEmbedCode delay={inputValue} />
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const BubbleInstructions = () => {
|
||||
// const [inputValues, setInputValues] = useState<
|
||||
// Pick<BubbleParams, 'proactiveMessage' | 'button'>
|
||||
// >({
|
||||
// proactiveMessage: undefined,
|
||||
// button: {
|
||||
// color: '',
|
||||
// iconUrl: '',
|
||||
// },
|
||||
// })
|
||||
const [inputValues, setInputValues] = useState<
|
||||
Pick<BubbleParams, 'proactiveMessage' | 'button'>
|
||||
>({
|
||||
proactiveMessage: undefined,
|
||||
button: {
|
||||
color: '',
|
||||
iconUrl: '',
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
<ListItem>
|
||||
Go to <Tag>Settings</Tag> in your dashboard on Wix
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Click on <Tag>Custom Code</Tag> under <Tag>Advanced</Tag>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Click <Tag>+ Add Custom Code</Tag> at the top right.
|
||||
</ListItem>
|
||||
<ListItem>Paste this snippet in the code box:</ListItem>
|
||||
</OrderedList>
|
||||
{/* <ChatEmbedSettings
|
||||
onUpdateSettings={(settings) => setInputValues({ ...settings })}
|
||||
/>
|
||||
<ChatEmbedCode
|
||||
mt={4}
|
||||
{...inputValues}
|
||||
onCopied={() => sendWixCopyEvent('bubble')}
|
||||
/> */}
|
||||
</>
|
||||
<OrderedList spacing={2} mb={4}>
|
||||
<ListItem>
|
||||
Go to <Tag>Settings</Tag> in your dashboard on Wix
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Click on <Tag>Custom Code</Tag> under <Tag>Advanced</Tag>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Click <Tag>+ Add Custom Code</Tag> at the top right.
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
Paste this snippet in the code box:{' '}
|
||||
<ChatEmbedSettings
|
||||
my="4"
|
||||
onUpdateSettings={(settings) => setInputValues({ ...settings })}
|
||||
/>
|
||||
<ChatEmbedCode {...inputValues} />
|
||||
</ListItem>
|
||||
</OrderedList>
|
||||
)
|
||||
}
|
||||
|
@ -2,11 +2,13 @@ import { Box, BoxProps } from '@chakra-ui/react'
|
||||
import { EditorState, EditorView, basicSetup } from '@codemirror/basic-setup'
|
||||
import { json } from '@codemirror/lang-json'
|
||||
import { css } from '@codemirror/lang-css'
|
||||
import { javascript } from '@codemirror/lang-javascript'
|
||||
import { html } from '@codemirror/lang-html'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
type Props = {
|
||||
value: string
|
||||
lang?: 'css' | 'json'
|
||||
lang?: 'css' | 'json' | 'js' | 'html'
|
||||
onChange?: (value: string) => void
|
||||
isReadOnly?: boolean
|
||||
}
|
||||
@ -24,7 +26,11 @@ export const CodeEditor = ({
|
||||
useEffect(() => {
|
||||
if (!editorView.current || !isReadOnly) return
|
||||
editorView.current.dispatch({
|
||||
changes: { from: 0, insert: value },
|
||||
changes: {
|
||||
from: 0,
|
||||
to: editorView.current.state.doc.length,
|
||||
insert: value,
|
||||
},
|
||||
})
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [value])
|
||||
@ -36,6 +42,14 @@ export const CodeEditor = ({
|
||||
}, [plainTextValue])
|
||||
|
||||
useEffect(() => {
|
||||
const editor = initEditor(value)
|
||||
return () => {
|
||||
editor?.destroy()
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
|
||||
const initEditor = (value: string) => {
|
||||
if (!editorContainer.current) return
|
||||
const updateListenerExtension = EditorView.updateListener.of((update) => {
|
||||
if (update.docChanged && onChange)
|
||||
@ -48,6 +62,8 @@ export const CodeEditor = ({
|
||||
]
|
||||
if (lang === 'json') extensions.push(json())
|
||||
if (lang === 'css') extensions.push(css())
|
||||
if (lang === 'js') extensions.push(javascript())
|
||||
if (lang === 'html') extensions.push(html())
|
||||
const editor = new EditorView({
|
||||
state: EditorState.create({
|
||||
extensions,
|
||||
@ -58,13 +74,8 @@ export const CodeEditor = ({
|
||||
changes: { from: 0, insert: value },
|
||||
})
|
||||
editorView.current = editor
|
||||
return () => {
|
||||
editor.destroy()
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
return editor
|
||||
}
|
||||
|
||||
return (
|
||||
<Box ref={editorContainer} h="200px" data-testid="code-editor" {...props} />
|
||||
)
|
||||
return <Box ref={editorContainer} data-testid="code-editor" {...props} />
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
"@chakra-ui/react": "^1.8.1",
|
||||
"@codemirror/basic-setup": "^0.19.1",
|
||||
"@codemirror/lang-css": "^0.19.3",
|
||||
"@codemirror/lang-html": "^0.19.4",
|
||||
"@codemirror/lang-javascript": "^0.19.7",
|
||||
"@codemirror/lang-json": "^0.19.1",
|
||||
"@codemirror/text": "^0.19.6",
|
||||
"@emotion/react": "^11.7.1",
|
||||
@ -69,7 +71,8 @@
|
||||
"swr": "^1.2.0",
|
||||
"use-debounce": "^7.0.1",
|
||||
"use-immer": "^0.6.0",
|
||||
"utils": "*"
|
||||
"utils": "*",
|
||||
"typebot-js": "2.0.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.18.1",
|
||||
@ -79,6 +82,7 @@
|
||||
"@types/node": "^16.11.9",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/papaparse": "^5.3.1",
|
||||
"@types/prettier": "^2.4.4",
|
||||
"@types/qs": "^6.9.7",
|
||||
"@types/react": "^17.0.38",
|
||||
"@types/react-table": "^7.7.9",
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { ItemBase, ItemType } from '.'
|
||||
import { Item } from './item'
|
||||
import { StepBase } from './steps'
|
||||
|
||||
export type InputStep =
|
||||
|
52
yarn.lock
52
yarn.lock
@ -1110,7 +1110,7 @@
|
||||
"@codemirror/state" "^0.19.0"
|
||||
"@codemirror/view" "^0.19.23"
|
||||
|
||||
"@codemirror/highlight@^0.19.0", "@codemirror/highlight@^0.19.6":
|
||||
"@codemirror/highlight@^0.19.0", "@codemirror/highlight@^0.19.6", "@codemirror/highlight@^0.19.7":
|
||||
version "0.19.7"
|
||||
resolved "https://registry.yarnpkg.com/@codemirror/highlight/-/highlight-0.19.7.tgz#91a0c9994c759f5f153861e3aae74ff9e7c7c35b"
|
||||
integrity sha512-3W32hBCY0pbbv/xidismw+RDMKuIag+fo4kZIbD7WoRj+Ttcaxjf+vP6RttRHXLaaqbWh031lTeON8kMlDhMYw==
|
||||
@ -1130,7 +1130,7 @@
|
||||
"@codemirror/state" "^0.19.2"
|
||||
"@codemirror/view" "^0.19.0"
|
||||
|
||||
"@codemirror/lang-css@^0.19.3":
|
||||
"@codemirror/lang-css@^0.19.0", "@codemirror/lang-css@^0.19.3":
|
||||
version "0.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@codemirror/lang-css/-/lang-css-0.19.3.tgz#7a17adf78c6fcdab4ad5ee4e360631c41e949e4a"
|
||||
integrity sha512-tyCUJR42/UlfOPLb94/p7dN+IPsYSIzHbAHP2KQHANj0I+Orqp+IyIOS++M8TuCX4zkWh9dvi8s92yy/Tn8Ifg==
|
||||
@ -1141,6 +1141,33 @@
|
||||
"@codemirror/state" "^0.19.0"
|
||||
"@lezer/css" "^0.15.2"
|
||||
|
||||
"@codemirror/lang-html@^0.19.4":
|
||||
version "0.19.4"
|
||||
resolved "https://registry.yarnpkg.com/@codemirror/lang-html/-/lang-html-0.19.4.tgz#e6eec28462f18842a0e108732a214a7416b5e333"
|
||||
integrity sha512-GpiEikNuCBeFnS+/TJSeanwqaOfNm8Kkp9WpVNEPZCLyW1mAMCuFJu/3xlWYeWc778Hc3vJqGn3bn+cLNubgCA==
|
||||
dependencies:
|
||||
"@codemirror/autocomplete" "^0.19.0"
|
||||
"@codemirror/highlight" "^0.19.6"
|
||||
"@codemirror/lang-css" "^0.19.0"
|
||||
"@codemirror/lang-javascript" "^0.19.0"
|
||||
"@codemirror/language" "^0.19.0"
|
||||
"@codemirror/state" "^0.19.0"
|
||||
"@lezer/common" "^0.15.0"
|
||||
"@lezer/html" "^0.15.0"
|
||||
|
||||
"@codemirror/lang-javascript@^0.19.0", "@codemirror/lang-javascript@^0.19.7":
|
||||
version "0.19.7"
|
||||
resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-0.19.7.tgz#84581ef6abf2a16d78f017ffc96c2d6227de5eb5"
|
||||
integrity sha512-DL9f3JLqOEHH9cIwEqqjnP5bkjdVXeECksLtV+/MbPm+l4H+AG+PkwZaJQ2oR1GfPZKh8MVSIE94aGWNkJP8WQ==
|
||||
dependencies:
|
||||
"@codemirror/autocomplete" "^0.19.0"
|
||||
"@codemirror/highlight" "^0.19.7"
|
||||
"@codemirror/language" "^0.19.0"
|
||||
"@codemirror/lint" "^0.19.0"
|
||||
"@codemirror/state" "^0.19.0"
|
||||
"@codemirror/view" "^0.19.0"
|
||||
"@lezer/javascript" "^0.15.1"
|
||||
|
||||
"@codemirror/lang-json@^0.19.1":
|
||||
version "0.19.1"
|
||||
resolved "https://registry.yarnpkg.com/@codemirror/lang-json/-/lang-json-0.19.1.tgz#616588d1422529965243c10af6c44ad0b9134fb0"
|
||||
@ -1633,6 +1660,20 @@
|
||||
dependencies:
|
||||
"@lezer/lr" "^0.15.0"
|
||||
|
||||
"@lezer/html@^0.15.0":
|
||||
version "0.15.0"
|
||||
resolved "https://registry.yarnpkg.com/@lezer/html/-/html-0.15.0.tgz#572c9444bc39c1afc0529a70e089abf7254edf5d"
|
||||
integrity sha512-ErmgP/Vv0AhYJvs/Ekb9oue4IzBHemKLi7K8tJ0jgS+20Y8FGC9foK6knCXtEHqdPaxVGQH9PVp7gecLnzLd9Q==
|
||||
dependencies:
|
||||
"@lezer/lr" "^0.15.0"
|
||||
|
||||
"@lezer/javascript@^0.15.1":
|
||||
version "0.15.3"
|
||||
resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-0.15.3.tgz#833a4c5650bae07805b9af88de6706368844dc55"
|
||||
integrity sha512-8jA2NpOfpWwSPZxRhd9BxK2ZPvGd7nLE3LFTJ5AbMhXAzMHeMjneV6GEVd7dAIee85dtap0jdb6bgOSO0+lfwA==
|
||||
dependencies:
|
||||
"@lezer/lr" "^0.15.0"
|
||||
|
||||
"@lezer/json@^0.15.0":
|
||||
version "0.15.0"
|
||||
resolved "https://registry.yarnpkg.com/@lezer/json/-/json-0.15.0.tgz#b96c1161eb8514e05f4eaaec95c68376e76e539f"
|
||||
@ -2208,6 +2249,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
||||
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
|
||||
|
||||
"@types/prettier@^2.4.4":
|
||||
version "2.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.4.tgz#5d9b63132df54d8909fce1c3f8ca260fdd693e17"
|
||||
integrity sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==
|
||||
|
||||
"@types/prop-types@*":
|
||||
version "15.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
|
||||
@ -8061,7 +8107,7 @@ type-fest@^0.21.3:
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
|
||||
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
|
||||
|
||||
typebot-js@^2.0.21:
|
||||
typebot-js@2.0.21, typebot-js@^2.0.21:
|
||||
version "2.0.21"
|
||||
resolved "https://registry.yarnpkg.com/typebot-js/-/typebot-js-2.0.21.tgz#1211ef4ffbf8f69facf538721073ec17660283b9"
|
||||
integrity sha512-7a0vODc1MLYe2u9TtaO7u0Sz9V9+3Tk+YeY2cXjDgWEhFWNcUPyBZOJZMB5EDir5/togTMTIYr/TCm6fyGRi2Q==
|
||||
|
Reference in New Issue
Block a user