diff --git a/apps/docs/deploy/web/html-javascript.mdx b/apps/docs/deploy/web/html-javascript.mdx index 448030baa..027ad3a6c 100644 --- a/apps/docs/deploy/web/html-javascript.mdx +++ b/apps/docs/deploy/web/html-javascript.mdx @@ -401,6 +401,7 @@ Here are the commands you can use to trigger your embedded typebot: - `Typebot.setInputValue(...)`: Set the value in the currently displayed input. - `Typebot.sendCommand(...)`: Send a [command](/editor/events/command) to the bot. +- `Typebot.reload()`: Reload the bot. You can bind these commands on a button element, for example: diff --git a/packages/embeds/js/package.json b/packages/embeds/js/package.json index 9fe52bcf4..6697bf3ea 100644 --- a/packages/embeds/js/package.json +++ b/packages/embeds/js/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/js", - "version": "0.5.0", + "version": "0.6.0", "description": "Javascript library to display typebots on your website", "license": "FSL-1.1-ALv2", "type": "module", diff --git a/packages/embeds/js/src/features/bubble/components/Bubble.tsx b/packages/embeds/js/src/features/bubble/components/Bubble.tsx index 4fd8226ec..fd28066de 100644 --- a/packages/embeds/js/src/features/bubble/components/Bubble.tsx +++ b/packages/embeds/js/src/features/bubble/components/Bubble.tsx @@ -129,6 +129,9 @@ export const Bubble = (props: BubbleProps) => { case "unmount": unmountBubble(); break; + case "reload": + reloadBot(); + break; } }; @@ -151,6 +154,11 @@ export const Bubble = (props: BubbleProps) => { isOpen() ? closeBot() : openBot(); }; + const reloadBot = () => { + setHasOpenedOnce(false); + setHasOpenedOnce(true); + }; + const handlePreviewMessageClick = () => { bubbleProps.onPreviewMessageClick?.(); openBot(); diff --git a/packages/embeds/js/src/features/commands/index.ts b/packages/embeds/js/src/features/commands/index.ts index d07f82414..1dd64c9cc 100644 --- a/packages/embeds/js/src/features/commands/index.ts +++ b/packages/embeds/js/src/features/commands/index.ts @@ -8,3 +8,4 @@ export * from "./utils/setPrefilledVariables"; export * from "./utils/hidePreviewMessage"; export * from "./utils/sendCommand"; export * from "./types"; +export * from "./utils/reload"; diff --git a/packages/embeds/js/src/features/commands/types.ts b/packages/embeds/js/src/features/commands/types.ts index 86568c2e2..f1dba8f66 100644 --- a/packages/embeds/js/src/features/commands/types.ts +++ b/packages/embeds/js/src/features/commands/types.ts @@ -8,7 +8,13 @@ export type CommandData = CommandArgs & { isFromTypebot: boolean; } & ( | { - command: "open" | "toggle" | "close" | "hidePreviewMessage" | "unmount"; + command: + | "open" + | "toggle" + | "close" + | "hidePreviewMessage" + | "unmount" + | "reload"; } | ShowMessageCommandData | SetPrefilledVariablesCommandData diff --git a/packages/embeds/js/src/features/commands/utils/reload.ts b/packages/embeds/js/src/features/commands/utils/reload.ts new file mode 100644 index 000000000..889dbfe5e --- /dev/null +++ b/packages/embeds/js/src/features/commands/utils/reload.ts @@ -0,0 +1,10 @@ +import type { CommandArgs, CommandData } from "../types"; + +export const reload = ({ id }: CommandArgs = {}) => { + const message: CommandData = { + isFromTypebot: true, + command: "reload", + id, + }; + window.postMessage(message); +}; diff --git a/packages/embeds/js/src/features/popup/components/Popup.tsx b/packages/embeds/js/src/features/popup/components/Popup.tsx index 1e9844f3e..77b8e3a4b 100644 --- a/packages/embeds/js/src/features/popup/components/Popup.tsx +++ b/packages/embeds/js/src/features/popup/components/Popup.tsx @@ -88,14 +88,26 @@ export const Popup = (props: PopupProps) => { const processIncomingEvent = (event: MessageEvent) => { const { data } = event; if (!data.isFromTypebot || (data.id && botProps.id !== data.id)) return; - if (data.command === "open") openBot(); - if (data.command === "close") closeBot(); - if (data.command === "toggle") toggleBot(); - if (data.command === "setPrefilledVariables") - setPrefilledVariables((existingPrefilledVariables) => ({ - ...existingPrefilledVariables, - ...data.variables, - })); + switch (data.command) { + case "open": + openBot(); + break; + case "close": + closeBot(); + break; + case "toggle": + toggleBot(); + break; + case "setPrefilledVariables": + setPrefilledVariables((existingPrefilledVariables) => ({ + ...existingPrefilledVariables, + ...data.variables, + })); + break; + case "reload": + reloadBot(); + break; + } }; const openBot = () => { @@ -117,6 +129,11 @@ export const Popup = (props: PopupProps) => { isBotOpened() ? closeBot() : openBot(); }; + const reloadBot = () => { + setIsBotOpened(false); + setIsBotOpened(true); + }; + const handleOnChatStatePersisted = (isPersisted: boolean) => { botProps.onChatStatePersisted?.(isPersisted); if (isPersisted) setBotOpenedStateInStorage(); diff --git a/packages/embeds/js/src/features/standard/components/Standard.tsx b/packages/embeds/js/src/features/standard/components/Standard.tsx index 4974adb20..7ef7db560 100644 --- a/packages/embeds/js/src/features/standard/components/Standard.tsx +++ b/packages/embeds/js/src/features/standard/components/Standard.tsx @@ -27,6 +27,13 @@ export const Standard = ( setIsBotDisplayed(true); }; + const reloadBot = () => { + setIsBotDisplayed(false); + setTimeout(() => { + setIsBotDisplayed(true); + }, 1); + }; + const botLauncherObserver = new IntersectionObserver((intersections) => { if (intersections.some((intersection) => intersection.isIntersecting)) launchBot(); @@ -48,11 +55,17 @@ export const Standard = ( const processIncomingEvent = (event: MessageEvent) => { const { data } = event; if (!data.isFromTypebot || (data.id && props.id !== data.id)) return; - if (data.command === "setPrefilledVariables") - setPrefilledVariables((existingPrefilledVariables) => ({ - ...existingPrefilledVariables, - ...data.variables, - })); + switch (data.command) { + case "setPrefilledVariables": + setPrefilledVariables((existingPrefilledVariables) => ({ + ...existingPrefilledVariables, + ...data.variables, + })); + break; + case "reload": + reloadBot(); + break; + } }; onCleanup(() => { diff --git a/packages/embeds/js/src/index.ts b/packages/embeds/js/src/index.ts index 6e394dfe5..4c429a04e 100644 --- a/packages/embeds/js/src/index.ts +++ b/packages/embeds/js/src/index.ts @@ -7,6 +7,7 @@ export * from "./features/commands/utils/unmount"; export * from "./features/commands/utils/setPrefilledVariables"; export * from "./features/commands/utils/hidePreviewMessage"; export * from "./features/commands/utils/sendCommand"; +export * from "./features/commands/utils/reload"; export * from "./features/commands/types"; export type { BotProps } from "./components/Bot"; diff --git a/packages/embeds/js/src/window.ts b/packages/embeds/js/src/window.ts index 2e1a299c3..b3886bfde 100644 --- a/packages/embeds/js/src/window.ts +++ b/packages/embeds/js/src/window.ts @@ -9,7 +9,7 @@ import { showPreviewMessage } from "./features/commands/utils/showPreviewMessage import { toggle } from "./features/commands/utils/toggle"; import { unmount } from "./features/commands/utils/unmount"; import type { PopupProps } from "./features/popup/components/Popup"; -import type { BotProps } from "./index"; +import { type BotProps, reload } from "./index"; export const initStandard = (props: BotProps & { id?: string }) => { const standardElement = props.id @@ -32,27 +32,6 @@ export const initBubble = (props: BubbleProps) => { document.body.prepend(bubbleElement); }; -type Typebot = { - initStandard: typeof initStandard; - initPopup: typeof initPopup; - initBubble: typeof initBubble; - close: typeof close; - hidePreviewMessage: typeof hidePreviewMessage; - open: typeof open; - setPrefilledVariables: typeof setPrefilledVariables; - showPreviewMessage: typeof showPreviewMessage; - toggle: typeof toggle; - setInputValue: typeof setInputValue; - unmount: typeof unmount; - sendCommand: typeof sendCommand; -}; - -declare const window: - | { - Typebot: Typebot | undefined; - } - | undefined; - export const parseTypebot = () => ({ initStandard, initPopup, @@ -66,8 +45,17 @@ export const parseTypebot = () => ({ setInputValue, unmount, sendCommand, + reload, }); +type Typebot = ReturnType; + +declare const window: + | { + Typebot: Typebot; + } + | undefined; + export const injectTypebotInWindow = (typebot: Typebot) => { if (typeof window === "undefined") return; window.Typebot = { ...typebot }; diff --git a/packages/embeds/nextjs/package.json b/packages/embeds/nextjs/package.json index e943c0668..5129488be 100644 --- a/packages/embeds/nextjs/package.json +++ b/packages/embeds/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/nextjs", - "version": "0.5.0", + "version": "0.6.0", "license": "FSL-1.1-ALv2", "description": "Convenient library to display typebots on your Next.js website", "type": "module", diff --git a/packages/embeds/react/package.json b/packages/embeds/react/package.json index 5f3bbbaae..c9affae27 100644 --- a/packages/embeds/react/package.json +++ b/packages/embeds/react/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/react", - "version": "0.5.0", + "version": "0.6.0", "description": "Convenient library to display typebots on your React app", "license": "FSL-1.1-ALv2", "type": "module", diff --git a/packages/embeds/stories/src/bubble.stories.tsx b/packages/embeds/stories/src/bubble.stories.tsx index cb03c19b7..5cb859085 100644 --- a/packages/embeds/stories/src/bubble.stories.tsx +++ b/packages/embeds/stories/src/bubble.stories.tsx @@ -3,6 +3,7 @@ import { close, hidePreviewMessage, open, + reload, sendCommand, setInputValue, setPrefilledVariables, @@ -20,6 +21,7 @@ export const Default = () => { + @@ -34,7 +36,7 @@ export const Default = () => {