📝 (embed) Add new script embed instructions
This commit is contained in:
@ -24,6 +24,8 @@ import {
|
||||
WixModal,
|
||||
} from './modals'
|
||||
import { OtherModal } from './modals/OtherModal'
|
||||
import { ScriptIcon } from '@/features/blocks/logic/script'
|
||||
import { ScriptModal } from './modals/Script/ScriptModal'
|
||||
|
||||
export type ModalProps = {
|
||||
publicId: string
|
||||
@ -112,6 +114,14 @@ export const integrationsList = [
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
(props: Pick<ModalProps, 'publicId' | 'isPublished'>) => (
|
||||
<EmbedButton
|
||||
logo={<ScriptIcon height={100} width="70px" color="gray.300" />}
|
||||
label="Script"
|
||||
Modal={ScriptModal}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
(props: Pick<ModalProps, 'publicId' | 'isPublished'>) => (
|
||||
<EmbedButton
|
||||
logo={<NotionLogo height={100} width="60px" />}
|
||||
|
@ -0,0 +1,25 @@
|
||||
import React, { useState } from 'react'
|
||||
import { ModalProps } from '../../EmbedButton'
|
||||
import { EmbedModal } from '../../EmbedModal'
|
||||
import { isDefined } from '@udecode/plate-common'
|
||||
import { ScriptInstructions } from './instructions/ScriptInstructions'
|
||||
|
||||
export const ScriptModal = ({ isOpen, onClose, isPublished }: ModalProps) => {
|
||||
const [selectedEmbedType, setSelectedEmbedType] = useState<
|
||||
'standard' | 'popup' | 'bubble' | undefined
|
||||
>()
|
||||
return (
|
||||
<EmbedModal
|
||||
titlePrefix="Script"
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
isPublished={isPublished}
|
||||
onSelectEmbedType={setSelectedEmbedType}
|
||||
selectedEmbedType={selectedEmbedType}
|
||||
>
|
||||
{isDefined(selectedEmbedType) && (
|
||||
<ScriptInstructions type={selectedEmbedType} />
|
||||
)}
|
||||
</EmbedModal>
|
||||
)
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
import { CodeEditor } from '@/components/CodeEditor'
|
||||
import { useTypebot } from '@/features/editor'
|
||||
import { isCloudProdInstance } from '@/utils/helpers'
|
||||
import { Stack, Text } from '@chakra-ui/react'
|
||||
import { BubbleProps } from '@typebot.io/js'
|
||||
import { Typebot } from 'models'
|
||||
import { useState } from 'react'
|
||||
import { env, getViewerUrl } from 'utils'
|
||||
import { BubbleSettings } from '../../../settings/BubbleSettings/BubbleSettings'
|
||||
import { parseInlineScript, parseInitBubbleCode } from '../../../snippetParsers'
|
||||
|
||||
export const parseDefaultBubbleTheme = (typebot?: Typebot) => ({
|
||||
button: {
|
||||
backgroundColor: typebot?.theme.chat.buttons.backgroundColor,
|
||||
iconColor: typebot?.theme.chat.buttons.color,
|
||||
},
|
||||
previewMessage: {
|
||||
backgroundColor: typebot?.theme.general.background.content ?? 'white',
|
||||
textColor: 'black',
|
||||
},
|
||||
})
|
||||
|
||||
export const ScriptBubbleInstructions = () => {
|
||||
const { typebot } = useTypebot()
|
||||
const [theme, setTheme] = useState<BubbleProps['theme']>(
|
||||
parseDefaultBubbleTheme(typebot)
|
||||
)
|
||||
const [previewMessage, setPreviewMessage] =
|
||||
useState<BubbleProps['previewMessage']>()
|
||||
|
||||
const scriptSnippet = parseInlineScript(
|
||||
parseInitBubbleCode({
|
||||
typebot: typebot?.publicId ?? '',
|
||||
apiHost: isCloudProdInstance
|
||||
? undefined
|
||||
: env('VIEWER_INTERNAL_URL') ?? getViewerUrl(),
|
||||
theme,
|
||||
previewMessage,
|
||||
})
|
||||
)
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<BubbleSettings
|
||||
theme={theme}
|
||||
previewMessage={previewMessage}
|
||||
defaultPreviewMessageAvatar={typebot?.theme.chat.hostAvatar?.url ?? ''}
|
||||
onThemeChange={setTheme}
|
||||
onPreviewMessageChange={setPreviewMessage}
|
||||
/>
|
||||
<Text>Run this script to initialize the typebot:</Text>
|
||||
<CodeEditor isReadOnly value={scriptSnippet} lang="javascript" />
|
||||
</Stack>
|
||||
)
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import { ScriptBubbleInstructions } from './ScriptBubbleInstructions'
|
||||
import { ScriptPopupInstructions } from './ScriptPopupInstructions'
|
||||
import { ScriptStandardInstructions } from './ScriptStandardInstructions'
|
||||
|
||||
type Props = {
|
||||
type: 'standard' | 'popup' | 'bubble'
|
||||
}
|
||||
|
||||
export const ScriptInstructions = ({ type }: Props) => {
|
||||
switch (type) {
|
||||
case 'standard': {
|
||||
return <ScriptStandardInstructions />
|
||||
}
|
||||
case 'popup': {
|
||||
return <ScriptPopupInstructions />
|
||||
}
|
||||
case 'bubble': {
|
||||
return <ScriptBubbleInstructions />
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
import { CodeEditor } from '@/components/CodeEditor'
|
||||
import { useTypebot } from '@/features/editor'
|
||||
import { isCloudProdInstance } from '@/utils/helpers'
|
||||
import { Stack, Text } from '@chakra-ui/react'
|
||||
import { useState } from 'react'
|
||||
import { env, getViewerUrl } from 'utils'
|
||||
import { PopupSettings } from '../../../settings/PopupSettings'
|
||||
import { parseInitPopupCode } from '../../../snippetParsers'
|
||||
import { parseInlineScript } from '../../../snippetParsers/shared'
|
||||
|
||||
export const ScriptPopupInstructions = () => {
|
||||
const { typebot } = useTypebot()
|
||||
const [inputValue, setInputValue] = useState<number>()
|
||||
|
||||
const scriptSnippet = parseInlineScript(
|
||||
parseInitPopupCode({
|
||||
typebot: typebot?.publicId ?? '',
|
||||
apiHost: isCloudProdInstance
|
||||
? undefined
|
||||
: env('VIEWER_INTERNAL_URL') ?? getViewerUrl(),
|
||||
autoShowDelay: inputValue,
|
||||
})
|
||||
)
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<PopupSettings
|
||||
onUpdateSettings={(settings) => setInputValue(settings.autoShowDelay)}
|
||||
/>
|
||||
<Text>Run this script to initialize the typebot:</Text>
|
||||
<CodeEditor isReadOnly value={scriptSnippet} lang="javascript" />
|
||||
</Stack>
|
||||
)
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
import { CodeEditor } from '@/components/CodeEditor'
|
||||
import { useTypebot } from '@/features/editor'
|
||||
import { isCloudProdInstance } from '@/utils/helpers'
|
||||
import { Stack, Code, Text } from '@chakra-ui/react'
|
||||
import { useState } from 'react'
|
||||
import { env, getViewerUrl } from 'utils'
|
||||
import { StandardSettings } from '../../../settings/StandardSettings'
|
||||
import { parseInitStandardCode } from '../../../snippetParsers/standard'
|
||||
import { parseStandardElementCode } from '../../Javascript/JavascriptStandardSnippet'
|
||||
import { parseInlineScript } from '../../../snippetParsers/shared'
|
||||
|
||||
export const ScriptStandardInstructions = () => {
|
||||
const { typebot } = useTypebot()
|
||||
const [inputValues, setInputValues] = useState<{
|
||||
heightLabel: string
|
||||
widthLabel?: string
|
||||
}>({
|
||||
heightLabel: '100%',
|
||||
widthLabel: '100%',
|
||||
})
|
||||
|
||||
const standardElementSnippet = parseStandardElementCode(
|
||||
inputValues.widthLabel,
|
||||
inputValues.heightLabel
|
||||
)
|
||||
|
||||
const scriptSnippet = parseInlineScript(
|
||||
parseInitStandardCode({
|
||||
typebot: typebot?.publicId ?? '',
|
||||
apiHost: isCloudProdInstance
|
||||
? undefined
|
||||
: env('VIEWER_INTERNAL_URL') ?? getViewerUrl(),
|
||||
})
|
||||
)
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<StandardSettings
|
||||
onUpdateWindowSettings={(settings) => setInputValues({ ...settings })}
|
||||
/>
|
||||
<Text>
|
||||
Make sure you have this <Code>typebot-standard</Code> element in your{' '}
|
||||
<Code>{'<body>'}</Code>:
|
||||
</Text>
|
||||
<CodeEditor isReadOnly value={standardElementSnippet} lang="html" />
|
||||
<Text>Then, run this script to initialize the typebot:</Text>
|
||||
<CodeEditor isReadOnly value={scriptSnippet} lang="javascript" />
|
||||
</Stack>
|
||||
)
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
import { BotProps } from '@typebot.io/js'
|
||||
import parserBabel from 'prettier/parser-babel'
|
||||
import prettier from 'prettier/standalone'
|
||||
import { isDefined } from 'utils'
|
||||
|
||||
export const parseStringParam = (fieldName: string, fieldValue?: string) =>
|
||||
@ -30,3 +32,12 @@ export const parseReactBotProps = ({ typebot, apiHost }: BotProps) => {
|
||||
}
|
||||
|
||||
export const typebotImportUrl = `https://cdn.jsdelivr.net/npm/@typebot.io/js@0.0.14/dist/web.js`
|
||||
|
||||
export const parseInlineScript = (script: string) =>
|
||||
prettier.format(
|
||||
`const typebotInitScript = document.createElement("script");
|
||||
typebotInitScript.type = "module";
|
||||
typebotInitScript.innerHTML = \`${script}\`;
|
||||
document.body.append(typebotInitScript);`,
|
||||
{ parser: 'babel', plugins: [parserBabel] }
|
||||
)
|
||||
|
5
apps/docs/docs/embed/script.md
Normal file
5
apps/docs/docs/embed/script.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Script
|
||||
|
||||
The script embed option is useful only if you don't have access to the HTML tree of your application or if your website builder only allows you to inline script snippets.
|
||||
|
||||
Otherwise, it's preferable to follow [HTML & Javascript](./html-javascript) embed instructions because the script snippets are just scripts that will inject the code from the HTML & Javascript embed method.
|
Reference in New Issue
Block a user