) =>
toast(log as UseToastOptions)
- console.log(log.details)
- }
return (
`
+export const typebotJsHtml = ``
diff --git a/apps/builder/components/shared/Graph/Nodes/StepNode/SettingsPopoverContent/bodies/WebhookSettings/WebhookSettings.tsx b/apps/builder/components/shared/Graph/Nodes/StepNode/SettingsPopoverContent/bodies/WebhookSettings/WebhookSettings.tsx
index ca2bf4496..4ab7f5173 100644
--- a/apps/builder/components/shared/Graph/Nodes/StepNode/SettingsPopoverContent/bodies/WebhookSettings/WebhookSettings.tsx
+++ b/apps/builder/components/shared/Graph/Nodes/StepNode/SettingsPopoverContent/bodies/WebhookSettings/WebhookSettings.tsx
@@ -80,7 +80,6 @@ export const WebhookSettings = ({
return () => {
setLocalWebhook((localWebhook) => {
- console.log(localWebhook)
if (!localWebhook) return
updateWebhook(webhookId, localWebhook).then()
return localWebhook
diff --git a/apps/builder/components/shared/SupportBubble.tsx b/apps/builder/components/shared/SupportBubble.tsx
index 9f1949913..77fa6076a 100644
--- a/apps/builder/components/shared/SupportBubble.tsx
+++ b/apps/builder/components/shared/SupportBubble.tsx
@@ -17,7 +17,12 @@ export const SupportBubble = () => {
process.env.NEXT_PUBLIC_VIEWER_URL
}/typebot-support`,
backgroundColor: '#ffffff',
- button: { color: '#0042DA' },
+ button: {
+ color: '#0042DA',
+ iconUrl:
+ 'https://user-images.githubusercontent.com/16015833/159536717-35bb78f8-f659-49f2-ad7f-00172be69cfb.svg',
+ iconStyle: 'border-radius: 0; width: 50%',
+ },
hiddenVariables: {
'User ID': user?.id,
Name: user?.name ?? undefined,
diff --git a/apps/builder/components/shared/TypebotHeader/TypebotHeader.tsx b/apps/builder/components/shared/TypebotHeader/TypebotHeader.tsx
index f5d7cffac..f64a2b88a 100644
--- a/apps/builder/components/shared/TypebotHeader/TypebotHeader.tsx
+++ b/apps/builder/components/shared/TypebotHeader/TypebotHeader.tsx
@@ -13,6 +13,7 @@ import { RightPanel, useEditor } from 'contexts/EditorContext'
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
import { useRouter } from 'next/router'
import React from 'react'
+import { isNotDefined } from 'utils'
import { PublishButton } from '../buttons/PublishButton'
import { CollaborationMenuButton } from './CollaborationMenuButton'
import { EditableTypebotName } from './EditableTypebotName'
@@ -21,6 +22,7 @@ export const headerHeight = 56
export const TypebotHeader = () => {
const router = useRouter()
+ const { rightPanel } = useEditor()
const {
typebot,
updateOnBothTypebots,
@@ -154,7 +156,7 @@ export const TypebotHeader = () => {
- {router.pathname.includes('/edit') && (
+ {router.pathname.includes('/edit') && isNotDefined(rightPanel) && (
Preview
)}
diff --git a/apps/builder/components/shared/buttons/PublishButton.tsx b/apps/builder/components/shared/buttons/PublishButton.tsx
index d0a776a1b..5b06c96b7 100644
--- a/apps/builder/components/shared/buttons/PublishButton.tsx
+++ b/apps/builder/components/shared/buttons/PublishButton.tsx
@@ -12,10 +12,12 @@ import {
} from '@chakra-ui/react'
import { ChevronLeftIcon } from 'assets/icons'
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
+import { useRouter } from 'next/router'
import { timeSince } from 'services/utils'
import { isNotDefined } from 'utils'
export const PublishButton = () => {
+ const { push, query } = useRouter()
const {
isPublishing,
isPublished,
@@ -24,6 +26,11 @@ export const PublishButton = () => {
restorePublishedTypebot,
} = useTypebot()
+ const handlePublishClick = () => {
+ publishTypebot()
+ if (!publishedTypebot) push(`/typebots/${query.typebotId}/share`)
+ }
+
return (
{
colorScheme="blue"
isLoading={isPublishing}
isDisabled={isPublished}
- onClick={publishTypebot}
+ onClick={handlePublishClick}
borderRightRadius={publishedTypebot && !isPublished ? 0 : undefined}
>
{isPublished ? 'Published' : 'Publish'}
diff --git a/apps/builder/contexts/UserContext.tsx b/apps/builder/contexts/UserContext.tsx
index 50c5ffb96..56147b5b5 100644
--- a/apps/builder/contexts/UserContext.tsx
+++ b/apps/builder/contexts/UserContext.tsx
@@ -21,7 +21,7 @@ const userContext = createContext<{
hasUnsavedChanges: boolean
isOAuthProvider: boolean
updateUser: (newUser: Partial) => void
- saveUser: () => void
+ saveUser: (newUser?: Partial) => void
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
}>({})
@@ -75,10 +75,11 @@ export const UserContext = ({ children }: { children: ReactNode }) => {
setUser({ ...user, ...newUser })
}
- const saveUser = async () => {
+ const saveUser = async (newUser?: Partial) => {
if (isNotDefined(user)) return
setIsSaving(true)
- const { error } = await updateUserInDb(user.id, user)
+ if (newUser) updateUser(newUser)
+ const { error } = await updateUserInDb(user.id, { ...user, ...newUser })
if (error) toast({ title: error.name, description: error.message })
await refreshUser()
setIsSaving(false)
diff --git a/apps/builder/layouts/dashboard/TemplatesContent.tsx b/apps/builder/layouts/dashboard/TemplatesContent.tsx
index 720baeec2..7f105cf63 100644
--- a/apps/builder/layouts/dashboard/TemplatesContent.tsx
+++ b/apps/builder/layouts/dashboard/TemplatesContent.tsx
@@ -6,13 +6,14 @@ import {
Text,
Stack,
useToast,
+ Tooltip,
} from '@chakra-ui/react'
import { CreateTypebotMoreButton } from 'components/templates/ImportFileMenuItem'
import { TemplateButton } from 'components/templates/TemplateButton'
import { useUser } from 'contexts/UserContext'
import { defaultTheme, Typebot } from 'models'
import { useRouter } from 'next/router'
-import React, { useState } from 'react'
+import React, { useEffect, useState } from 'react'
import { createTypebot, importTypebot } from 'services/typebots/typebots'
export type TemplateProps = { name: string; emoji: string; fileName: string }
@@ -22,6 +23,8 @@ const templates: TemplateProps[] = [
export const TemplatesContent = () => {
const { user } = useUser()
const router = useRouter()
+ const [isFromScratchTooltipOpened, setIsFromScratchTooltipOpened] =
+ useState(false)
const [isLoading, setIsLoading] = useState(false)
@@ -31,6 +34,13 @@ export const TemplatesContent = () => {
title: 'An error occured',
})
+ useEffect(() => {
+ if (!router.isReady) return
+ const isFirstBot = router.query.isFirstBot as string | undefined
+ if (isFirstBot) setIsFromScratchTooltipOpened(true)
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [router.isReady])
+
const handleCreateSubmit = async (typebot?: Typebot) => {
if (!user) return
setIsLoading(true)
@@ -60,13 +70,23 @@ export const TemplatesContent = () => {
- handleCreateSubmit()}
- isLoading={isLoading}
- colorScheme="blue"
+
- Start from scratch
-
+ handleCreateSubmit()}
+ isLoading={isLoading}
+ colorScheme="blue"
+ >
+ Start from scratch
+
+
+
diff --git a/apps/builder/package.json b/apps/builder/package.json
index 9808864e9..ec28309f1 100644
--- a/apps/builder/package.json
+++ b/apps/builder/package.json
@@ -40,6 +40,7 @@
"@udecode/plate-ui-toolbar": "^10.2.2",
"bot-engine": "*",
"browser-image-compression": "^1.0.17",
+ "canvas-confetti": "^1.5.1",
"cuid": "^2.1.8",
"db": "*",
"deep-object-diff": "^1.1.7",
@@ -85,6 +86,7 @@
},
"devDependencies": {
"@playwright/test": "^1.19.2",
+ "@types/canvas-confetti": "^1.4.2",
"@types/google-spreadsheet": "^3.1.5",
"@types/jsonwebtoken": "8.5.8",
"@types/micro-cors": "^0.1.2",
diff --git a/apps/builder/playwright/tests/bubbles/image.spec.ts b/apps/builder/playwright/tests/bubbles/image.spec.ts
index 342a31982..f90b164e7 100644
--- a/apps/builder/playwright/tests/bubbles/image.spec.ts
+++ b/apps/builder/playwright/tests/bubbles/image.spec.ts
@@ -80,7 +80,10 @@ test.describe.parallel('Image bubble step', () => {
await page.click('text=Click to edit...')
await page.click('text=Giphy')
- await page.click('img >> nth=3', { force: true })
+ await page.click('img >> nth=3', {
+ force: true,
+ position: { x: 0, y: 0 },
+ })
await expect(page.locator('img[alt="Step image"]')).toHaveAttribute(
'src',
new RegExp('giphy.com/media', 'gm')
diff --git a/apps/builder/playwright/tests/customDomains.spec.ts b/apps/builder/playwright/tests/customDomains.spec.ts
index 28e529e55..2e8cf25c3 100644
--- a/apps/builder/playwright/tests/customDomains.spec.ts
+++ b/apps/builder/playwright/tests/customDomains.spec.ts
@@ -54,7 +54,7 @@ test.describe('Dashboard page', () => {
test.use({
storageState: path.join(__dirname, '../freeUser.json'),
})
- test("create folder shouldn't be available", async ({ page }) => {
+ test("Add my domain shouldn't be available", async ({ page }) => {
await page.goto(`/typebots/${typebotId}/share`)
await page.click('text=Add my domain')
await expect(page.locator('text=Upgrade now')).toBeVisible()
diff --git a/apps/builder/playwright/tests/inputs/text.spec.ts b/apps/builder/playwright/tests/inputs/text.spec.ts
index a85b630f0..8b929e0dd 100644
--- a/apps/builder/playwright/tests/inputs/text.spec.ts
+++ b/apps/builder/playwright/tests/inputs/text.spec.ts
@@ -41,26 +41,4 @@ test.describe.parallel('Text input step', () => {
).toBeVisible()
await expect(typebotViewer(page).locator(`text=Go`)).toBeVisible()
})
-
- test('variable in URL should prefill the input', async ({ page }) => {
- const typebotId = cuid()
- await createTypebots([
- {
- id: typebotId,
- ...parseDefaultBlockWithStep({
- type: InputStepType.TEXT,
- options: { ...defaultTextInputOptions, variableId: 'var1' },
- }),
- },
- ])
-
- await page.goto(`/typebots/${typebotId}/edit?var1=My prefilled answer`)
- await page.click('text=Preview')
- await expect(
- typebotViewer(page).locator(
- `input[placeholder="${defaultTextInputOptions.labels.placeholder}"]`
- )
- ).toHaveAttribute('value', 'My prefilled answer')
- await expect(typebotViewer(page).locator(`button`)).toBeEnabled()
- })
})
diff --git a/apps/builder/public/bots/onboarding.json b/apps/builder/public/bots/onboarding.json
new file mode 100644
index 000000000..482d0a56a
--- /dev/null
+++ b/apps/builder/public/bots/onboarding.json
@@ -0,0 +1,635 @@
+{
+ "id": "cl128l5vx007509il86n74oer",
+ "createdAt": "2022-03-22T14:33:05.037Z",
+ "updatedAt": "2022-03-22T16:33:37.928Z",
+ "name": "Onboarding",
+ "ownerId": "ckzmhmiey001009mnzt5nkxu8",
+ "publishedTypebotId": "cl128n64i00092e69wenv1dlx",
+ "folderId": null,
+ "blocks": [
+ {
+ "id": "cl1265zct0000mb1a6bir36w7",
+ "steps": [
+ {
+ "id": "cl1265zct0001mb1afel460do",
+ "type": "start",
+ "label": "Start",
+ "blockId": "cl1265zct0000mb1a6bir36w7",
+ "outgoingEdgeId": "cl1266kt100082e6d1wks5dtp"
+ }
+ ],
+ "title": "Start",
+ "graphCoordinates": { "x": 0, "y": 0 }
+ },
+ {
+ "id": "cl1266bah00032e6dgdnj4vgz",
+ "steps": [
+ {
+ "id": "cl1266bam00042e6dm0gn22vy",
+ "type": "Condition",
+ "items": [
+ {
+ "id": "cl1266bam00052e6dn1sdjnax",
+ "type": 1,
+ "stepId": "cl1266bam00042e6dm0gn22vy",
+ "content": {
+ "comparisons": [
+ {
+ "id": "cl1266cg600062e6d76qwk74v",
+ "variableId": "cl126f4hf000i2e6d8zvzc3t1",
+ "comparisonOperator": "Is set"
+ }
+ ],
+ "logicalOperator": "AND"
+ },
+ "outgoingEdgeId": "cl12bk3j6000c2e69bak89ja9"
+ }
+ ],
+ "blockId": "cl1266bah00032e6dgdnj4vgz",
+ "outgoingEdgeId": "cl12bnfyd000g2e69g7lr3czq"
+ }
+ ],
+ "title": "Block #1",
+ "graphCoordinates": { "x": 266, "y": 162 }
+ },
+ {
+ "id": "cl1267q1z000d2e6d949f2ge4",
+ "steps": [
+ {
+ "id": "cl1267q2c000e2e6dynjeg83n",
+ "type": "text",
+ "blockId": "cl1267q1z000d2e6d949f2ge4",
+ "content": {
+ "html": "Welcome 👋
",
+ "richText": [
+ { "type": "p", "children": [{ "text": "Welcome 👋" }] }
+ ],
+ "plainText": "Welcome 👋"
+ }
+ },
+ {
+ "id": "cl1267y1u000f2e6d4rlglv6g",
+ "type": "text",
+ "blockId": "cl1267q1z000d2e6d949f2ge4",
+ "content": {
+ "html": "What's your name?
",
+ "richText": [
+ { "type": "p", "children": [{ "text": "What's your name?" }] }
+ ],
+ "plainText": "What's your name?"
+ }
+ },
+ {
+ "id": "cl126820m000g2e6dfleq78bt",
+ "type": "text input",
+ "blockId": "cl1267q1z000d2e6d949f2ge4",
+ "options": {
+ "isLong": false,
+ "labels": {
+ "button": "Send",
+ "placeholder": "Type your answer..."
+ },
+ "variableId": "cl126f4hf000i2e6d8zvzc3t1"
+ }
+ },
+ {
+ "id": "cl1289y1s00142e6dvbkpvbje",
+ "type": "Code",
+ "blockId": "cl1267q1z000d2e6d949f2ge4",
+ "options": {
+ "name": "Store Name in DB",
+ "content": "postMessage({from: \"typebot\", action: \"storeName\", content: \"{{Name}}\"}, \"*\")"
+ },
+ "outgoingEdgeId": "cl12bk56s000d2e69oll3nqxm"
+ }
+ ],
+ "title": "Block #3",
+ "graphCoordinates": { "x": 269, "y": 381 }
+ },
+ {
+ "id": "cl126ixoq000p2e6dfbz9sype",
+ "steps": [
+ {
+ "id": "cl1266v6f000a2e6db7wj3ux7",
+ "type": "text",
+ "blockId": "cl126ixoq000p2e6dfbz9sype",
+ "content": {
+ "html": "Welcome {{Name}} 👋
",
+ "richText": [
+ { "type": "p", "children": [{ "text": "Welcome {{Name}} 👋" }] }
+ ],
+ "plainText": "Welcome {{Name}} 👋"
+ }
+ },
+ {
+ "id": "cl126hb9m000l2e6d5qk3mohn",
+ "type": "text",
+ "blockId": "cl126ixoq000p2e6dfbz9sype",
+ "content": {
+ "html": "I'm super pumped that you've decided to try out Typebot 😍
",
+ "richText": [
+ {
+ "type": "p",
+ "children": [
+ {
+ "text": "I'm super pumped that you've decided to try out Typebot 😍"
+ }
+ ]
+ }
+ ],
+ "plainText": "I'm super pumped that you've decided to try out Typebot 😍"
+ }
+ },
+ {
+ "id": "cl126hpw1000m2e6dneousygl",
+ "type": "text",
+ "blockId": "cl126ixoq000p2e6dfbz9sype",
+ "content": {
+ "html": "You are small steps away from meaningful, hyper-personalized experience for your users
",
+ "richText": [
+ {
+ "type": "p",
+ "children": [
+ {
+ "text": "You are small steps away from meaningful, hyper-personalized experience for your users"
+ }
+ ]
+ }
+ ],
+ "plainText": "You are small steps away from meaningful, hyper-personalized experience for your users"
+ }
+ },
+ {
+ "id": "cl126guhd000k2e6d6ypkex9z",
+ "type": "text",
+ "blockId": "cl126ixoq000p2e6dfbz9sype",
+ "content": {
+ "html": "Let's get you set up for your Typebot journey.
",
+ "richText": [
+ {
+ "type": "p",
+ "children": [
+ { "text": "Let's get you set up for your Typebot journey." }
+ ]
+ }
+ ],
+ "plainText": "Let's get you set up for your Typebot journey."
+ }
+ },
+ {
+ "id": "cl126ixp9000q2e6dslh0zypi",
+ "type": "text",
+ "blockId": "cl126ixoq000p2e6dfbz9sype",
+ "content": {
+ "html": "Do you work for a specific company?
",
+ "richText": [
+ {
+ "type": "p",
+ "children": [{ "text": "Do you work for a specific company?" }]
+ }
+ ],
+ "plainText": "Do you work for a specific company?"
+ }
+ },
+ {
+ "id": "cl126jb2q000r2e6dgqlnxnt8",
+ "type": "choice input",
+ "items": [
+ {
+ "id": "cl126jb2q000s2e6dm60yq5p2",
+ "type": 0,
+ "stepId": "cl126jb2q000r2e6dgqlnxnt8",
+ "content": "Yes",
+ "outgoingEdgeId": "cl126jsoo000x2e6ditu7dgf8"
+ },
+ {
+ "id": "cl126jc5a000t2e6dqv91w7j6",
+ "type": 0,
+ "stepId": "cl126jb2q000r2e6dgqlnxnt8",
+ "content": "No",
+ "outgoingEdgeId": "cl126l5tx00122e6dmisci6h5"
+ }
+ ],
+ "blockId": "cl126ixoq000p2e6dfbz9sype",
+ "options": { "buttonLabel": "Send", "isMultipleChoice": false }
+ }
+ ],
+ "title": "Block #5",
+ "graphCoordinates": { "x": 614, "y": 244 }
+ },
+ {
+ "id": "cl126jioj000u2e6dqssno3hv",
+ "steps": [
+ {
+ "id": "cl126jioz000v2e6dwrk1f2cb",
+ "type": "text input",
+ "blockId": "cl126jioj000u2e6dqssno3hv",
+ "options": {
+ "isLong": false,
+ "labels": {
+ "button": "Send",
+ "placeholder": "Type the company name..."
+ },
+ "variableId": "cl126jqww000w2e6dq9yv4ifq"
+ }
+ },
+ {
+ "id": "cl12890kw00132e6dp9v5dexm",
+ "type": "Code",
+ "blockId": "cl126jioj000u2e6dqssno3hv",
+ "options": {
+ "name": "Store company in DB",
+ "content": "postMessage({from: \"typebot\", action: \"storeCompany\", content: \"{{Company}}\"}, \"*\")"
+ },
+ "outgoingEdgeId": "cl128ag8i00162e6dufv3tgo0"
+ }
+ ],
+ "title": "Block #6",
+ "graphCoordinates": { "x": 969, "y": 308 }
+ },
+ {
+ "id": "cl126krbp00102e6dnjelmfa1",
+ "steps": [
+ {
+ "id": "cl126krck00112e6d1m6ctxpn",
+ "type": "text",
+ "blockId": "cl126krbp00102e6dnjelmfa1",
+ "content": {
+ "html": "What type of forms are you planning to build with Typebot?
",
+ "richText": [
+ {
+ "type": "p",
+ "children": [
+ {
+ "text": "What type of forms are you planning to build with Typebot?"
+ }
+ ]
+ }
+ ],
+ "plainText": "What type of forms are you planning to build with Typebot?"
+ }
+ },
+ {
+ "id": "cl126lb8v00142e6duv5qe08l",
+ "type": "choice input",
+ "items": [
+ {
+ "id": "cl126onz9001g2e6dk0nbjeu6",
+ "type": 0,
+ "stepId": "cl126lb8v00142e6duv5qe08l",
+ "content": "Lead qualification"
+ },
+ {
+ "id": "cl126lm6c00172e6d1pfvdiju",
+ "type": 0,
+ "stepId": "cl126lb8v00142e6duv5qe08l",
+ "content": "Customer support"
+ },
+ {
+ "id": "cl126orr2001h2e6d0fqs7737",
+ "type": 0,
+ "stepId": "cl126lb8v00142e6duv5qe08l",
+ "content": "Customer research"
+ },
+ {
+ "id": "cl126oudu001i2e6dktwi7qwv",
+ "type": 0,
+ "stepId": "cl126lb8v00142e6duv5qe08l",
+ "content": "User onboarding"
+ },
+ {
+ "id": "cl126luv500192e6dl317ssyr",
+ "type": 0,
+ "stepId": "cl126lb8v00142e6duv5qe08l",
+ "content": "Quizzes"
+ },
+ {
+ "id": "cl126lz8q001a2e6d8b9lb3b5",
+ "type": 0,
+ "stepId": "cl126lb8v00142e6duv5qe08l",
+ "content": "Content distribution"
+ },
+ {
+ "id": "cl126nf7k001d2e6dg2zczjgz",
+ "type": 0,
+ "stepId": "cl126lb8v00142e6duv5qe08l",
+ "content": "FAQ"
+ },
+ {
+ "id": "cl126ngy8001e2e6ddfo5s9fm",
+ "type": 0,
+ "stepId": "cl126lb8v00142e6duv5qe08l",
+ "content": "Other"
+ }
+ ],
+ "blockId": "cl126krbp00102e6dnjelmfa1",
+ "options": {
+ "variableId": "cl126mo3t001b2e6dvyi16bkd",
+ "buttonLabel": "Send",
+ "isMultipleChoice": true
+ }
+ },
+ {
+ "id": "cl128ain900172e6d1osj4u90",
+ "type": "Code",
+ "blockId": "cl126krbp00102e6dnjelmfa1",
+ "options": {
+ "name": "Store categories in DB",
+ "content": "postMessage({from: \"typebot\", action: \"storeCategories\", content: \"{{Categories}}\"}, \"*\")"
+ },
+ "outgoingEdgeId": "cl128azam00182e6dct61k7v5"
+ }
+ ],
+ "title": "Block #6",
+ "graphCoordinates": { "x": 1218, "y": 510 }
+ },
+ {
+ "id": "cl126p75m001j2e6d73qmes0m",
+ "steps": [
+ {
+ "id": "cl126p76d001k2e6dbhnf2ysq",
+ "type": "text",
+ "blockId": "cl126p75m001j2e6d73qmes0m",
+ "content": {
+ "html": "Thank you for answering those questions!
",
+ "richText": [
+ {
+ "type": "p",
+ "children": [
+ { "text": "Thank you for answering those questions!" }
+ ]
+ }
+ ],
+ "plainText": "Thank you for answering those questions!"
+ }
+ },
+ {
+ "id": "cl128375600112e6d4l0jtuyf",
+ "type": "Code",
+ "blockId": "cl126p75m001j2e6d73qmes0m",
+ "options": {
+ "name": "Shoot confettis",
+ "content": "postMessage({from: \"typebot\", action: \"shootConfettis\"}, \"*\")"
+ }
+ },
+ {
+ "id": "cl126rfy6001t2e6d21gcb6b0",
+ "type": "image",
+ "blockId": "cl126p75m001j2e6d73qmes0m",
+ "content": {
+ "url": "https://media4.giphy.com/media/l0amJzVHIAfl7jMDos/giphy.gif?cid=fe3852a3i4c33635xdtj3nesr9uq4zteujaab6b0jr42gpxx&rid=giphy.gif&ct=g"
+ }
+ },
+ {
+ "id": "cl126txta001y2e6dtxrbsnek",
+ "type": "text",
+ "blockId": "cl126p75m001j2e6d73qmes0m",
+ "content": {
+ "html": "You can reach out to me using the contact bubble on the bottom right corner 🤓
",
+ "richText": [
+ {
+ "type": "p",
+ "children": [
+ {
+ "text": "You can reach out to me using the contact bubble on the bottom right corner 🤓"
+ }
+ ]
+ }
+ ],
+ "plainText": "You can reach out to me using the contact bubble on the bottom right corner 🤓"
+ }
+ },
+ {
+ "id": "cl12buyly00172e6991bz38ch",
+ "blockId": "cl126p75m001j2e6d73qmes0m",
+ "type": "text",
+ "content": {
+ "html": "Let's create your first typebot...
",
+ "richText": [
+ {
+ "type": "p",
+ "children": [{ "text": "Let's create your first typebot..." }]
+ }
+ ],
+ "plainText": "Let's create your first typebot..."
+ }
+ },
+ {
+ "id": "cl12bwpi800182e69kcivnp1s",
+ "blockId": "cl126p75m001j2e6d73qmes0m",
+ "type": "Code",
+ "options": {
+ "name": "Go to typebot creation",
+ "content": "setTimeout(() => {window.location.href = \"https://app.typebot.io/typebots/create?isFirstBot=true\"}, 4000)"
+ }
+ }
+ ],
+ "title": "Block #7",
+ "graphCoordinates": { "x": 1612, "y": 1103 }
+ },
+ {
+ "id": "cl126pv6w001n2e6dp0qkvthu",
+ "steps": [
+ {
+ "id": "cl127yxym000b2e6d9hksxo6h",
+ "type": "text",
+ "blockId": "cl126pv6w001n2e6dp0qkvthu",
+ "content": {
+ "html": "What else?
",
+ "richText": [
+ { "type": "p", "children": [{ "text": "What else?" }] }
+ ],
+ "plainText": "What else?"
+ }
+ },
+ {
+ "id": "cl126pv7n001o2e6dajltc4qz",
+ "type": "text input",
+ "blockId": "cl126pv6w001n2e6dp0qkvthu",
+ "options": {
+ "isLong": false,
+ "labels": { "button": "Send", "placeholder": "Type your answer" },
+ "variableId": "cl126q38p001q2e6d0hj23f6b"
+ }
+ },
+ {
+ "id": "cl128b34o00192e6dqjxs3cxf",
+ "type": "Code",
+ "blockId": "cl126pv6w001n2e6dp0qkvthu",
+ "options": {
+ "name": "Store Other categories in DB",
+ "content": "postMessage({from: \"typebot\", action: \"storeOtherCategories\", content: \"{{Other categories}}\"}, \"*\")"
+ },
+ "outgoingEdgeId": "cl128c0fu001a2e6droq69g6z"
+ }
+ ],
+ "title": "Block #8",
+ "graphCoordinates": { "x": 1943, "y": 895 }
+ },
+ {
+ "id": "cl1278gx9002v2e6d4kf3v89s",
+ "steps": [
+ {
+ "id": "cl1278gyk002w2e6d744eb87n",
+ "type": "Condition",
+ "items": [
+ {
+ "id": "cl1278gyk002x2e6dwmpzs3nf",
+ "type": 1,
+ "stepId": "cl1278gyk002w2e6d744eb87n",
+ "content": {
+ "comparisons": [
+ {
+ "id": "cl1278irq002y2e6dv4965diw",
+ "value": "Other",
+ "variableId": "cl126mo3t001b2e6dvyi16bkd",
+ "comparisonOperator": "Contains"
+ }
+ ],
+ "logicalOperator": "AND"
+ },
+ "outgoingEdgeId": "cl1278r3b002z2e6d6d6rk9dh"
+ }
+ ],
+ "blockId": "cl1278gx9002v2e6d4kf3v89s",
+ "outgoingEdgeId": "cl1278trd00312e6dxmzhcmmn"
+ }
+ ],
+ "title": "Block #13",
+ "graphCoordinates": { "x": 1585, "y": 792 }
+ }
+ ],
+ "variables": [
+ { "id": "cl126f4hf000i2e6d8zvzc3t1", "name": "Name" },
+ { "id": "cl126jqww000w2e6dq9yv4ifq", "name": "Company" },
+ { "id": "cl126mo3t001b2e6dvyi16bkd", "name": "Categories" },
+ { "id": "cl126q38p001q2e6d0hj23f6b", "name": "Other categories" }
+ ],
+ "edges": [
+ {
+ "id": "cl1266kt100082e6d1wks5dtp",
+ "to": { "blockId": "cl1266bah00032e6dgdnj4vgz" },
+ "from": {
+ "stepId": "cl1265zct0001mb1afel460do",
+ "blockId": "cl1265zct0000mb1a6bir36w7"
+ }
+ },
+ {
+ "id": "cl126jsoo000x2e6ditu7dgf8",
+ "to": { "blockId": "cl126jioj000u2e6dqssno3hv" },
+ "from": {
+ "itemId": "cl126jb2q000s2e6dm60yq5p2",
+ "stepId": "cl126jb2q000r2e6dgqlnxnt8",
+ "blockId": "cl126ixoq000p2e6dfbz9sype"
+ }
+ },
+ {
+ "id": "cl126l5tx00122e6dmisci6h5",
+ "to": { "blockId": "cl126krbp00102e6dnjelmfa1" },
+ "from": {
+ "itemId": "cl126jc5a000t2e6dqv91w7j6",
+ "stepId": "cl126jb2q000r2e6dgqlnxnt8",
+ "blockId": "cl126ixoq000p2e6dfbz9sype"
+ }
+ },
+ {
+ "id": "cl1278r3b002z2e6d6d6rk9dh",
+ "to": { "blockId": "cl126pv6w001n2e6dp0qkvthu" },
+ "from": {
+ "itemId": "cl1278gyk002x2e6dwmpzs3nf",
+ "stepId": "cl1278gyk002w2e6d744eb87n",
+ "blockId": "cl1278gx9002v2e6d4kf3v89s"
+ }
+ },
+ {
+ "id": "cl1278trd00312e6dxmzhcmmn",
+ "to": { "blockId": "cl126p75m001j2e6d73qmes0m" },
+ "from": {
+ "stepId": "cl1278gyk002w2e6d744eb87n",
+ "blockId": "cl1278gx9002v2e6d4kf3v89s"
+ }
+ },
+ {
+ "id": "cl128ag8i00162e6dufv3tgo0",
+ "to": { "blockId": "cl126krbp00102e6dnjelmfa1" },
+ "from": {
+ "stepId": "cl12890kw00132e6dp9v5dexm",
+ "blockId": "cl126jioj000u2e6dqssno3hv"
+ }
+ },
+ {
+ "id": "cl128azam00182e6dct61k7v5",
+ "to": { "blockId": "cl1278gx9002v2e6d4kf3v89s" },
+ "from": {
+ "stepId": "cl128ain900172e6d1osj4u90",
+ "blockId": "cl126krbp00102e6dnjelmfa1"
+ }
+ },
+ {
+ "id": "cl128c0fu001a2e6droq69g6z",
+ "to": { "blockId": "cl126p75m001j2e6d73qmes0m" },
+ "from": {
+ "stepId": "cl128b34o00192e6dqjxs3cxf",
+ "blockId": "cl126pv6w001n2e6dp0qkvthu"
+ }
+ },
+ {
+ "from": {
+ "blockId": "cl1266bah00032e6dgdnj4vgz",
+ "stepId": "cl1266bam00042e6dm0gn22vy",
+ "itemId": "cl1266bam00052e6dn1sdjnax"
+ },
+ "to": { "blockId": "cl126ixoq000p2e6dfbz9sype" },
+ "id": "cl12bk3j6000c2e69bak89ja9"
+ },
+ {
+ "from": {
+ "blockId": "cl1267q1z000d2e6d949f2ge4",
+ "stepId": "cl1289y1s00142e6dvbkpvbje"
+ },
+ "to": {
+ "blockId": "cl126ixoq000p2e6dfbz9sype",
+ "stepId": "cl126hb9m000l2e6d5qk3mohn"
+ },
+ "id": "cl12bk56s000d2e69oll3nqxm"
+ },
+ {
+ "from": {
+ "blockId": "cl1266bah00032e6dgdnj4vgz",
+ "stepId": "cl1266bam00042e6dm0gn22vy"
+ },
+ "to": { "blockId": "cl1267q1z000d2e6d949f2ge4" },
+ "id": "cl12bnfyd000g2e69g7lr3czq"
+ }
+ ],
+ "theme": {
+ "chat": {
+ "inputs": {
+ "color": "#303235",
+ "backgroundColor": "#FFFFFF",
+ "placeholderColor": "#9095A0"
+ },
+ "buttons": { "color": "#FFFFFF", "backgroundColor": "#0042DA" },
+ "hostBubbles": { "color": "#303235", "backgroundColor": "#F7F8FF" },
+ "guestBubbles": { "color": "#FFFFFF", "backgroundColor": "#FF8E21" },
+ "hostAvatar": {
+ "isEnabled": true,
+ "url": "https://s3.eu-west-3.amazonaws.com/typebot/typebots/ckzp7a2za005809lczf2knzix/273013187_1315820332248257_6244778509534754615_n.jpg"
+ }
+ },
+ "general": { "font": "Open Sans", "background": { "type": "None" } }
+ },
+ "settings": {
+ "general": {
+ "isBrandingEnabled": true,
+ "isInputPrefillEnabled": true,
+ "isNewResultOnRefreshEnabled": false
+ },
+ "metadata": {
+ "description": "Build beautiful conversational forms and embed them directly in your applications without a line of code. Triple your response rate and collect answers that has more value compared to a traditional form."
+ },
+ "typingEmulation": { "speed": 300, "enabled": true, "maxDelay": 1.5 }
+ },
+ "publicId": "typebot-onboarding",
+ "customDomain": null
+}
diff --git a/apps/landing-page/components/Homepage/RealTimeResults.tsx b/apps/landing-page/components/Homepage/RealTimeResults.tsx
index 6642b2613..4ff87952a 100644
--- a/apps/landing-page/components/Homepage/RealTimeResults.tsx
+++ b/apps/landing-page/components/Homepage/RealTimeResults.tsx
@@ -32,7 +32,6 @@ export const RealTimeResults = () => {
}, [])
const processMessage = (event: MessageEvent) => {
- console.log(event.data)
if (event.data.from === 'typebot') refreshIframeContent()
}
diff --git a/apps/viewer/layouts/TypebotPage.tsx b/apps/viewer/layouts/TypebotPage.tsx
index 06afde504..ebbbe35f9 100644
--- a/apps/viewer/layouts/TypebotPage.tsx
+++ b/apps/viewer/layouts/TypebotPage.tsx
@@ -21,11 +21,22 @@ export const TypebotPage = ({
url,
}: TypebotPageProps & { typebot: PublicTypebot }) => {
const [showTypebot, setShowTypebot] = useState(false)
+ const [predefinedVariables, setPredefinedVariables] =
+ useState<{ [key: string]: string }>()
const [error, setError] = useState(
isIE ? new Error('Internet explorer is not supported') : undefined
)
const [resultId, setResultId] = useState()
+ useEffect(() => {
+ const urlParams = new URLSearchParams(location.search)
+ const predefinedVariables: { [key: string]: string } = {}
+ urlParams.forEach((value, key) => {
+ predefinedVariables[key] = value
+ })
+ setPredefinedVariables(predefinedVariables)
+ }, [])
+
// Workaround for react-frame-component bug (https://github.com/ryanseddon/react-frame-component/pull/207)
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => {
@@ -83,6 +94,7 @@ export const TypebotPage = ({
{showTypebot && (
{
.status(404)
.send({ statusCode: 404, data: { message: `Couldn't find webhook` } })
const preparedWebhook = prepareWebhookAttributes(webhook, step.options)
- console.log(preparedWebhook)
const result = await executeWebhook(typebot)(
preparedWebhook,
variables,
diff --git a/apps/viewer/playwright/fixtures/typebots/predefinedVariables.json b/apps/viewer/playwright/fixtures/typebots/predefinedVariables.json
new file mode 100644
index 000000000..d792a7100
--- /dev/null
+++ b/apps/viewer/playwright/fixtures/typebots/predefinedVariables.json
@@ -0,0 +1,122 @@
+{
+ "id": "cl13bgvlm0050t71aq6a3w777",
+ "createdAt": "2022-03-23T08:41:30.106Z",
+ "updatedAt": "2022-03-23T08:41:30.106Z",
+ "name": "My typebot",
+ "ownerId": "cl139ni700000481a01gxhw4z",
+ "publishedTypebotId": null,
+ "folderId": null,
+ "blocks": [
+ {
+ "id": "cl13bgvlk0000t71a4wabccvw",
+ "steps": [
+ {
+ "id": "cl13bgvlk0001t71a3pilbj53",
+ "type": "start",
+ "label": "Start",
+ "blockId": "cl13bgvlk0000t71a4wabccvw",
+ "outgoingEdgeId": "cl13bgz4800062e6dv7ejcchb"
+ }
+ ],
+ "title": "Start",
+ "graphCoordinates": { "x": 0, "y": 0 }
+ },
+ {
+ "id": "cl13bgy1s00042e6dao1wyobm",
+ "graphCoordinates": { "x": 329, "y": 65 },
+ "title": "Block #1",
+ "steps": [
+ {
+ "id": "cl13bgy1w00052e6d5x57wt7o",
+ "blockId": "cl13bgy1s00042e6dao1wyobm",
+ "type": "text",
+ "content": {
+ "html": "Hey I know you!
",
+ "richText": [
+ { "type": "p", "children": [{ "text": "Hey I know you!" }] }
+ ],
+ "plainText": "Hey I know you!"
+ }
+ },
+ {
+ "id": "cl13bh6jd00072e6dftdirwy4",
+ "blockId": "cl13bgy1s00042e6dao1wyobm",
+ "type": "text",
+ "content": {
+ "html": "Your name is {{Name}}
",
+ "richText": [
+ { "type": "p", "children": [{ "text": "Your name is {{Name}}" }] }
+ ],
+ "plainText": "Your name is {{Name}}"
+ }
+ },
+ {
+ "id": "cl13bhfxd00092e6dydvcqlhm",
+ "blockId": "cl13bgy1s00042e6dao1wyobm",
+ "type": "text",
+ "content": {
+ "html": "What's your email?
",
+ "richText": [
+ { "type": "p", "children": [{ "text": "What's your email?" }] }
+ ],
+ "plainText": "What's your email?"
+ }
+ },
+ {
+ "id": "cl13bhnay000a2e6dxa630dh3",
+ "blockId": "cl13bgy1s00042e6dao1wyobm",
+ "type": "email input",
+ "options": {
+ "labels": { "button": "Send", "placeholder": "Type your email..." },
+ "retryMessageContent": "This email doesn't seem to be valid. Can you type it again?",
+ "variableId": "cl13bhr3w000b2e6d3c9kid0p"
+ }
+ }
+ ]
+ }
+ ],
+ "variables": [
+ { "id": "cl13bha3l00082e6duaz0xm6f", "name": "Name" },
+ { "id": "cl13bhr3w000b2e6d3c9kid0p", "name": "Email" }
+ ],
+ "edges": [
+ {
+ "from": {
+ "blockId": "cl13bgvlk0000t71a4wabccvw",
+ "stepId": "cl13bgvlk0001t71a3pilbj53"
+ },
+ "to": { "blockId": "cl13bgy1s00042e6dao1wyobm" },
+ "id": "cl13bgz4800062e6dv7ejcchb"
+ }
+ ],
+ "theme": {
+ "chat": {
+ "inputs": {
+ "color": "#303235",
+ "backgroundColor": "#FFFFFF",
+ "placeholderColor": "#9095A0"
+ },
+ "buttons": { "color": "#FFFFFF", "backgroundColor": "#0042DA" },
+ "hostAvatar": {
+ "url": "https://avatars.githubusercontent.com/u/16015833?v=4",
+ "isEnabled": true
+ },
+ "hostBubbles": { "color": "#303235", "backgroundColor": "#F7F8FF" },
+ "guestBubbles": { "color": "#FFFFFF", "backgroundColor": "#FF8E21" }
+ },
+ "general": { "font": "Open Sans", "background": { "type": "None" } }
+ },
+ "settings": {
+ "general": {
+ "isBrandingEnabled": true,
+ "isInputPrefillEnabled": true,
+ "isNewResultOnRefreshEnabled": false
+ },
+ "metadata": {
+ "description": "Build beautiful conversational forms and embed them directly in your applications without a line of code. Triple your response rate and collect answers that has more value compared to a traditional form."
+ },
+ "typingEmulation": { "speed": 300, "enabled": true, "maxDelay": 1.5 }
+ },
+ "publicId": null,
+ "customDomain": null
+}
diff --git a/apps/viewer/playwright/tests/predefinedVariables.spec.ts b/apps/viewer/playwright/tests/predefinedVariables.spec.ts
new file mode 100644
index 000000000..7c70c3fa8
--- /dev/null
+++ b/apps/viewer/playwright/tests/predefinedVariables.spec.ts
@@ -0,0 +1,22 @@
+import test, { expect } from '@playwright/test'
+import { importTypebotInDatabase } from '../services/database'
+import cuid from 'cuid'
+import path from 'path'
+import { typebotViewer } from '../services/selectorUtils'
+
+test('should correctly be injected', async ({ page }) => {
+ const typebotId = cuid()
+ await importTypebotInDatabase(
+ path.join(__dirname, '../fixtures/typebots/predefinedVariables.json'),
+ { id: typebotId, publicId: `${typebotId}-public` }
+ )
+ await page.goto(`/${typebotId}-public`)
+ await expect(typebotViewer(page).locator('text="Your name is"')).toBeVisible()
+ await page.goto(`/${typebotId}-public?Name=Baptiste&Email=email@test.com`)
+ await expect(
+ typebotViewer(page).locator('text="Your name is Baptiste"')
+ ).toBeVisible()
+ await expect(
+ typebotViewer(page).locator('input[value="email@test.com"]')
+ ).toBeVisible()
+})
diff --git a/packages/bot-engine/src/components/ChatBlock/ChatBlock.tsx b/packages/bot-engine/src/components/ChatBlock/ChatBlock.tsx
index 08a47af25..56ce3f8db 100644
--- a/packages/bot-engine/src/components/ChatBlock/ChatBlock.tsx
+++ b/packages/bot-engine/src/components/ChatBlock/ChatBlock.tsx
@@ -158,7 +158,7 @@ export const ChatBlock = ({
if (currentStep?.outgoingEdgeId || processedSteps.length === steps.length)
return onBlockEnd(currentStep.outgoingEdgeId)
}
- const nextStep = steps[processedSteps.length]
+ const nextStep = steps[processedSteps.length + startStepIndex]
if (nextStep) insertStepInStack(nextStep)
}
diff --git a/packages/bot-engine/src/components/ConversationContainer.tsx b/packages/bot-engine/src/components/ConversationContainer.tsx
index 8b6c82bb4..d683d1126 100644
--- a/packages/bot-engine/src/components/ConversationContainer.tsx
+++ b/packages/bot-engine/src/components/ConversationContainer.tsx
@@ -11,12 +11,14 @@ import { LinkedTypebot, useTypebot } from 'contexts/TypebotContext'
type Props = {
theme: Theme
+ predefinedVariables?: { [key: string]: string | undefined }
onNewBlockVisible: (edge: Edge) => void
onCompleted: () => void
onVariablesPrefilled?: (prefilledVariables: VariableWithValue[]) => void
}
export const ConversationContainer = ({
theme,
+ predefinedVariables,
onNewBlockVisible,
onCompleted,
onVariablesPrefilled,
@@ -50,23 +52,28 @@ export const ConversationContainer = ({
}
useEffect(() => {
- const prefilledVariables = injectUrlParamsIntoVariables()
- if (onVariablesPrefilled) {
- onVariablesPrefilled(prefilledVariables)
- setPrefilledVariables(prefilledVariables)
+ if (predefinedVariables) {
+ const prefilledVariables = injectPredefinedVariables(predefinedVariables)
+ if (onVariablesPrefilled) {
+ onVariablesPrefilled(prefilledVariables)
+ setPrefilledVariables(prefilledVariables)
+ }
}
displayNextBlock(typebot.blocks[0].steps[0].outgoingEdgeId)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
- const injectUrlParamsIntoVariables = () => {
- const urlParams = new URLSearchParams(location.search)
+ const injectPredefinedVariables = (predefinedVariables: {
+ [key: string]: string | undefined
+ }) => {
const prefilledVariables: VariableWithValue[] = []
- urlParams.forEach((value, key) => {
+ Object.keys(predefinedVariables).forEach((key) => {
const matchingVariable = typebot.variables.find(
(v) => v.name.toLowerCase() === key.toLowerCase()
)
if (isNotDefined(matchingVariable)) return
+ const value = predefinedVariables[key]
+ if (!value) return
updateVariableValue(matchingVariable?.id, value)
prefilledVariables.push({ ...matchingVariable, value })
})
diff --git a/packages/bot-engine/src/components/TypebotViewer.tsx b/packages/bot-engine/src/components/TypebotViewer.tsx
index 6b7757863..94ab3cc6d 100644
--- a/packages/bot-engine/src/components/TypebotViewer.tsx
+++ b/packages/bot-engine/src/components/TypebotViewer.tsx
@@ -26,17 +26,20 @@ export type TypebotViewerProps = {
isPreview?: boolean
apiHost?: string
style?: CSSProperties
+ predefinedVariables?: { [key: string]: string | undefined }
onNewBlockVisible?: (edge: Edge) => void
onNewAnswer?: (answer: Answer) => void
onNewLog?: (log: Omit) => void
onCompleted?: () => void
onVariablesPrefilled?: (prefilledVariables: VariableWithValue[]) => void
}
+
export const TypebotViewer = ({
typebot,
apiHost = process.env.NEXT_PUBLIC_VIEWER_URL,
isPreview = false,
style,
+ predefinedVariables,
onNewLog,
onNewBlockVisible,
onNewAnswer,
@@ -104,6 +107,7 @@ export const TypebotViewer = ({
theme={typebot.theme}
onNewBlockVisible={handleNewBlockVisible}
onCompleted={handleCompleted}
+ predefinedVariables={predefinedVariables}
onVariablesPrefilled={onVariablesPrefilled}
/>
diff --git a/packages/db/prisma/migrations/20220322143206_add_company_and_categories/migration.sql b/packages/db/prisma/migrations/20220322143206_add_company_and_categories/migration.sql
new file mode 100644
index 000000000..6c3952dcb
--- /dev/null
+++ b/packages/db/prisma/migrations/20220322143206_add_company_and_categories/migration.sql
@@ -0,0 +1,3 @@
+-- AlterTable
+ALTER TABLE "User" ADD COLUMN "company" TEXT,
+ADD COLUMN "onboardingCategories" TEXT[];
diff --git a/packages/db/prisma/schema.prisma b/packages/db/prisma/schema.prisma
index 98fe7fd51..1d2f9e8ee 100644
--- a/packages/db/prisma/schema.prisma
+++ b/packages/db/prisma/schema.prisma
@@ -56,6 +56,8 @@ model User {
customDomains CustomDomain[]
apiToken String?
CollaboratorsOnTypebots CollaboratorsOnTypebots[]
+ company String?
+ onboardingCategories String[]
}
model CustomDomain {
diff --git a/packages/typebot-js/package.json b/packages/typebot-js/package.json
index 94b794dd8..18ef93a2c 100644
--- a/packages/typebot-js/package.json
+++ b/packages/typebot-js/package.json
@@ -1,6 +1,6 @@
{
"name": "typebot-js",
- "version": "2.2.0",
+ "version": "2.2.1",
"main": "dist/index.js",
"unpkg": "dist/index.umd.min.js",
"license": "AGPL-3.0-or-later",
diff --git a/packages/typebot-js/src/embedTypes/chat/button.ts b/packages/typebot-js/src/embedTypes/chat/button.ts
index 1195f32e8..f4adf1c3f 100644
--- a/packages/typebot-js/src/embedTypes/chat/button.ts
+++ b/packages/typebot-js/src/embedTypes/chat/button.ts
@@ -1,40 +1,44 @@
-import { ButtonParams } from "../../types";
+import { ButtonParams } from '../../types'
export const createButton = (params?: ButtonParams): HTMLButtonElement => {
- const button = document.createElement("button");
- button.id = "typebot-bubble-button";
- button.style.backgroundColor = params?.color ?? "#0042DA";
- button.appendChild(createButtonIcon(params?.iconUrl));
- button.appendChild(createCloseIcon());
- return button;
-};
+ const button = document.createElement('button')
+ button.id = 'typebot-bubble-button'
+ button.style.backgroundColor = params?.color ?? '#0042DA'
+ button.appendChild(createButtonIcon(params?.iconUrl, params?.iconStyle))
+ button.appendChild(createCloseIcon())
+ return button
+}
-const createButtonIcon = (src?: string): SVGElement | HTMLImageElement => {
- if (!src) return createDefaultIcon();
- const icon = document.createElement("img");
- icon.classList.add("icon");
- icon.src = src;
- return icon;
-};
+const createButtonIcon = (
+ src?: string,
+ style?: string
+): SVGElement | HTMLImageElement => {
+ if (!src) return createDefaultIcon()
+ const icon = document.createElement('img')
+ icon.classList.add('icon')
+ icon.src = src
+ if (style) icon.setAttribute('style', style)
+ return icon
+}
const createDefaultIcon = (): SVGElement => {
- const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
- icon.setAttribute("viewBox", "0 0 41 19");
- icon.style.width = "63%";
- icon.innerHTML = typebotLogoSvgTextContent();
- icon.classList.add("icon");
- return icon;
-};
+ const icon = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+ icon.setAttribute('viewBox', '0 0 41 19')
+ icon.style.width = '63%'
+ icon.innerHTML = typebotLogoSvgTextContent()
+ icon.classList.add('icon')
+ return icon
+}
const createCloseIcon = (): SVGElement => {
- const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
- icon.setAttribute("viewBox", "0 0 512 512");
- icon.innerHTML = closeSvgPath;
- icon.classList.add("close-icon");
- return icon;
-};
+ const icon = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+ icon.setAttribute('viewBox', '0 0 512 512')
+ icon.innerHTML = closeSvgPath
+ icon.classList.add('close-icon')
+ return icon
+}
const typebotLogoSvgTextContent = () =>
- ` `;
+ ` `
-export const closeSvgPath = ` `;
+export const closeSvgPath = ` `
diff --git a/packages/typebot-js/src/types.ts b/packages/typebot-js/src/types.ts
index 1f3b1864d..8394b3335 100644
--- a/packages/typebot-js/src/types.ts
+++ b/packages/typebot-js/src/types.ts
@@ -29,6 +29,7 @@ export type BubbleParams = {
export type ButtonParams = {
color?: string
iconUrl?: string
+ iconStyle?: string
}
export type ProactiveMessageParams = {
diff --git a/turbo.json b/turbo.json
index 2ae30bb6c..77bfd8c23 100644
--- a/turbo.json
+++ b/turbo.json
@@ -18,5 +18,6 @@
"dx": {
"cache": false
}
- }
+ },
+ "globalDependencies": ["$NEXT_PUBLIC_E2E_TEST"]
}
diff --git a/yarn.lock b/yarn.lock
index d028e6d2d..80e51e465 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4067,6 +4067,11 @@
"@types/node" "*"
"@types/responselike" "*"
+"@types/canvas-confetti@^1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@types/canvas-confetti/-/canvas-confetti-1.4.2.tgz#35c99fc904492fdcc6515c742509e04f3527211c"
+ integrity sha512-t45KUDHlwrD9PJVRHc5z1SlXhO82BQEgMKUXGEV1KnWLFMPA6Y5LfUsLTHHzH9KcKDHZLEiYYH5nIDcjRKWNTg==
+
"@types/connect-history-api-fallback@^1.3.5":
version "1.3.5"
resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae"
@@ -5896,6 +5901,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001283, caniuse-lite@^1.0.30001297, can
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001314.tgz#65c7f9fb7e4594fca0a333bec1d8939662377596"
integrity sha512-0zaSO+TnCHtHJIbpLroX7nsD+vYuOVjl3uzFbJO1wMVbuveJA0RK2WcQA9ZUIOiO0/ArMiMgHJLxfEZhQiC0kw==
+canvas-confetti@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/canvas-confetti/-/canvas-confetti-1.5.1.tgz#bf5b8622ef3bcd347378a972fc4194a89cfe0c9b"
+ integrity sha512-Ncz+oZJP6OvY7ti4E1slxVlyAV/3g7H7oQtcCDXgwGgARxPnwYY9PW5Oe+I8uvspYNtuHviAdgA0LfcKFWJfpg==
+
ccount@^1.0.0, ccount@^1.0.3:
version "1.1.0"
resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043"