2
0

fix(lib): 🐛 Safari context menu trap

This commit is contained in:
Baptiste Arnaud
2022-04-08 18:38:36 -05:00
parent fb3bba897f
commit 144ffaeb03
8 changed files with 41 additions and 41 deletions

View File

@ -16,19 +16,19 @@
<body>
<script>
const { open } = Typebot.initBubble({
publishId: "feedback-form",
url: 'https://typebot.io/typebot-support',
button: {
color: "green",
iconUrl: "https://image.flaticon.com/icons/png/512/5138/5138352.png",
color: 'green',
iconUrl: 'https://image.flaticon.com/icons/png/512/5138/5138352.png',
},
proactiveMessage: {
avatarUrl:
"https://images.unsplash.com/photo-1534528741775-53994a69daeb?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80",
'https://images.unsplash.com/photo-1534528741775-53994a69daeb?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
textContent: "Hey what's up?",
delay: 1000,
rememberClose: true,
},
});
})
</script>
<div style="width: 100%; height: 300vh; background-color: aquamarine">
<button onclick="(()=>{open()})()" style="width: 200px; height: 60px">

View File

@ -1,6 +1,6 @@
{
"name": "typebot-js",
"version": "2.2.2",
"version": "2.2.3",
"main": "dist/index.js",
"unpkg": "dist/index.umd.min.js",
"license": "AGPL-3.0-or-later",

View File

@ -1,28 +1,33 @@
import { createIframe } from "../../iframe";
import { IframeParams } from "../../types";
import { createIframe } from '../../iframe'
import { IframeParams } from '../../types'
export const createIframeContainer = (
params: IframeParams
): HTMLIFrameElement => {
const iframe = createIframe({ ...params, loadWhenVisible: true });
return iframe;
};
const iframe = createIframe({ ...params, loadWhenVisible: true })
return iframe
}
export const openIframe = (
bubble: HTMLDivElement,
iframe: HTMLIFrameElement
): void => {
loadTypebotIfFirstOpen(iframe);
bubble.classList.add("iframe-opened");
bubble.classList.remove("message-opened");
};
loadTypebotIfFirstOpen(iframe)
iframe.style.display = 'flex'
setTimeout(() => bubble.classList.add('iframe-opened'), 50)
bubble.classList.remove('message-opened')
}
export const closeIframe = (bubble: HTMLDivElement): void => {
bubble.classList.remove("iframe-opened");
};
export const closeIframe = (
bubble: HTMLDivElement,
iframe: HTMLIFrameElement
): void => {
bubble.classList.remove('iframe-opened')
setTimeout(() => (iframe.style.display = 'none'), 550)
}
export const loadTypebotIfFirstOpen = (iframe: HTMLIFrameElement): void => {
if (!iframe.dataset.src) return;
iframe.src = iframe.dataset.src;
iframe.removeAttribute("data-src");
};
if (!iframe.dataset.src) return
iframe.src = iframe.dataset.src
iframe.removeAttribute('data-src')
}

View File

@ -60,9 +60,11 @@ const createBubble = (
? addProactiveMessage(params.proactiveMessage, bubbleElement)
: undefined
const iframeElement = createIframeContainer(params)
buttonElement.addEventListener('click', () =>
onBubbleButtonClick(bubbleElement, iframeElement)
)
buttonElement.addEventListener('click', () => {
iframeElement.style.display === 'none'
? openIframe(bubbleElement, iframeElement)
: closeIframe(bubbleElement, iframeElement)
})
if (proactiveMessageElement)
proactiveMessageElement.addEventListener('click', () =>
onProactiveMessageClick(bubbleElement, iframeElement)
@ -71,15 +73,6 @@ const createBubble = (
return { bubbleElement, proactiveMessageElement, iframeElement }
}
const onBubbleButtonClick = (
bubble: HTMLDivElement,
iframe: HTMLIFrameElement
): void => {
loadTypebotIfFirstOpen(iframe)
bubble.classList.toggle('iframe-opened')
bubble.classList.remove('message-opened')
}
const onProactiveMessageClick = (
bubble: HTMLDivElement,
iframe: HTMLIFrameElement
@ -115,7 +108,7 @@ export const getBubbleActions = (
openIframe(existingBubbleElement, existingIframeElement)
},
close: () => {
closeIframe(existingBubbleElement)
closeIframe(existingBubbleElement, existingIframeElement)
},
}
}

View File

@ -61,7 +61,6 @@
}
#typebot-bubble > iframe {
visibility: hidden;
opacity: 0;
display: flex;
border-radius: 10px;
@ -83,7 +82,6 @@
#typebot-bubble.iframe-opened > iframe {
transform: translate(0, 0);
visibility: visible;
opacity: 1;
}

View File

@ -18,6 +18,7 @@ export const createIframe = ({
iframe.classList.add('typebot-iframe')
const { onNewVariableValue, onVideoPlayed } = iframeParams
listenForTypebotMessages({ onNewVariableValue, onVideoPlayed })
iframe.style.display = 'none'
return iframe
}

View File

@ -5,7 +5,7 @@ beforeEach(() => {
})
describe('openBubble', () => {
it('should add the opened bubble', () => {
it('should add the opened bubble', async () => {
expect.assertions(3)
const { open } = Typebot.initBubble({
url: 'https://typebot.io/typebot-id',
@ -13,6 +13,7 @@ describe('openBubble', () => {
const bubble = document.getElementById('typebot-bubble') as HTMLDivElement
expect(bubble.classList.contains('iframe-opened')).toBe(false)
open()
await new Promise((resolve) => setTimeout(resolve, 50))
expect(bubble.classList.contains('iframe-opened')).toBe(true)
expect(open).not.toThrow()
})
@ -35,13 +36,14 @@ describe('openBubble', () => {
})
describe('closeBubble', () => {
it('should remove the corresponding class', () => {
it('should remove the corresponding class', async () => {
expect.assertions(2)
const { close, open } = Typebot.initBubble({
url: 'https://typebot.io/typebot-id',
})
open()
const bubble = document.getElementById('typebot-bubble') as HTMLDivElement
await new Promise((resolve) => setTimeout(resolve, 50))
expect(bubble.classList.contains('iframe-opened')).toBe(true)
close()
expect(bubble.classList.contains('iframe-opened')).toBe(false)
@ -72,7 +74,7 @@ describe('openProactiveMessage', () => {
})
describe('Request commands afterwards', () => {
it('should return defined commands', () => {
it('should return defined commands', async () => {
Typebot.initBubble({
proactiveMessage: {
textContent: 'Hi click here!',
@ -85,6 +87,7 @@ describe('Request commands afterwards', () => {
expect(open).toBeDefined()
expect(openProactiveMessage).toBeDefined()
open()
await new Promise((resolve) => setTimeout(resolve, 50))
const bubble = document.getElementById('typebot-bubble') as HTMLDivElement
expect(bubble.classList.contains('iframe-opened')).toBe(true)
})

View File

@ -36,7 +36,7 @@ describe('initBubble', () => {
})
const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement
expect(bubble.classList.contains('iframe-opened')).toBe(false)
await new Promise((r) => setTimeout(r, 1000))
await new Promise((r) => setTimeout(r, 1050))
expect(bubble.classList.contains('iframe-opened')).toBe(true)
const rememberCloseDecisionFromStorage = localStorage.getItem(
Typebot.localStorageKeys.rememberClose