UNPKG

@atlaskit/modal-dialog

Version:

A modal dialog displays content that requires user interaction, in a layer above the page.

116 lines (114 loc) 3.22 kB
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine'; /** * Set a `style` property on a `HTMLElement` * * @returns a `cleanup` function to restore the `style` property to it's original state */ function setStyle(el, { property, rule, priority = '' }) { const originalValue = el.style.getPropertyValue(property); const originalPriority = el.style.getPropertyPriority(property); el.style.setProperty(property, rule, priority); return function cleanup() { el.style.setProperty(property, originalValue, originalPriority); }; } function hasSameOrigin(href1, href2) { let url1; let url2; try { url1 = new URL(href1); url2 = new URL(href2); } catch { // failed to parse a href return false; } // https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy return url1.protocol === url2.protocol && url1.host === url2.host && url1.port === url2.port; } function isIframeOnAnotherDomain(iframe) { /** * iframe with contents defined inline. Runs on the current origin. * `<iframe srcdoc="<!doctype html><body>Hello</body>" />` */ if (iframe.srcdoc) { return false; } /** * iframe with contents defined inline. Runs on the current origin. * `<iframe src={`data:text/html;charset=utf-8,${encodeURI('<!doctype html><body>Hello</body>')}`} />` */ if (iframe.src.startsWith('data:')) { return false; } return !hasSameOrigin(window.location.href, iframe.src); } const registry = new Map(); function applyFix(watchForEndOfInteraction) { const iframes = Array.from(document.querySelectorAll('iframe')).filter(isIframeOnAnotherDomain); const cleanups = iframes.map(iframe => { let entry = registry.get(iframe); if (!entry) { entry = { reset: setStyle(iframe, { property: 'pointer-events', rule: 'none', priority: 'important' }), count: 1 }; registry.set(iframe, entry); } else { // pointer-events:none already applied to the iframe // increment how many things requested the fix entry.count++; } return function cleanup() { entry.count--; if (entry.count < 1) { entry.reset(); registry.delete(iframe); } }; }); function stop() { cleanupWatcher(); combine(...cleanups)(); } const cleanupWatcher = watchForEndOfInteraction({ stop }); } export function makeFixForAdapter({ watchForInteractionStart, watchForInteractionEnd }) { let registrationCount = 0; let stopWatchingInteractionStart = null; function start() { applyFix(watchForInteractionEnd); } function registerUsage() { if (registrationCount === 0) { stopWatchingInteractionStart = watchForInteractionStart({ start }); } registrationCount++; return function unregisterUsage() { var _stopWatchingInteract; registrationCount--; if (registrationCount !== 0) { return; } (_stopWatchingInteract = stopWatchingInteractionStart) === null || _stopWatchingInteract === void 0 ? void 0 : _stopWatchingInteract(); stopWatchingInteractionStart = null; }; } return { registerUsage }; }