mirror of https://github.com/sveltejs/svelte
allow transitions and animations to work within iframes (#3625)
parent
c46b3727f1
commit
966aae3420
@ -0,0 +1,16 @@
|
||||
<script>
|
||||
export let visible;
|
||||
|
||||
function foo() {
|
||||
return {
|
||||
duration: 100,
|
||||
css: t => {
|
||||
return `opacity: ${t}`;
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if visible}
|
||||
<div transition:foo></div>
|
||||
{/if}
|
@ -0,0 +1,58 @@
|
||||
<script>
|
||||
import { onMount, onDestroy, tick } from 'svelte';
|
||||
|
||||
export let component;
|
||||
|
||||
let frame;
|
||||
let doc;
|
||||
let content;
|
||||
|
||||
$: mountComponent(doc, component);
|
||||
$: updateProps($$props);
|
||||
|
||||
function mountComponent(doc) {
|
||||
if (content) content.$destroy();
|
||||
if (doc && component) {
|
||||
const { component, ...props } = $$props;
|
||||
content = new component({ target: doc.body, props });
|
||||
}
|
||||
}
|
||||
|
||||
function updateProps(props) {
|
||||
if (content) {
|
||||
const { component, ...rest } = props;
|
||||
content.$set(rest);
|
||||
}
|
||||
}
|
||||
|
||||
function loadHandler() {
|
||||
doc = frame.contentDocument;
|
||||
// import styles
|
||||
Array.from(document.querySelectorAll('style, link[rel="stylesheet"]'))
|
||||
.forEach(node => doc.head.appendChild(node.cloneNode(true)));
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
await tick();
|
||||
if (frame.contentDocument.readyState === 'complete' && frame.contentDocument.defaultView) {
|
||||
loadHandler();
|
||||
} else {
|
||||
frame.addEventListener('load', loadHandler);
|
||||
}
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if (frame) frame.removeEventListener('load', loadHandler);
|
||||
if (content) content.$destroy();
|
||||
});
|
||||
</script>
|
||||
|
||||
<iframe bind:this={frame} title="frame"></iframe>
|
||||
|
||||
<style>
|
||||
iframe {
|
||||
border: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,18 @@
|
||||
export default {
|
||||
skip_if_ssr: true,
|
||||
|
||||
async test({ assert, component, target, window, raf }) {
|
||||
const frame = target.querySelector('iframe');
|
||||
await Promise.resolve();
|
||||
|
||||
component.visible = true;
|
||||
const div = frame.contentDocument.querySelector('div');
|
||||
|
||||
raf.tick(25);
|
||||
|
||||
component.visible = false;
|
||||
|
||||
raf.tick(26);
|
||||
assert.ok(~div.style.animation.indexOf('25ms'));
|
||||
},
|
||||
};
|
@ -0,0 +1,8 @@
|
||||
<script>
|
||||
import Frame from './Frame.svelte';
|
||||
import Foo from './Foo.svelte';
|
||||
|
||||
export let visible;
|
||||
</script>
|
||||
|
||||
<Frame component={Foo} {visible}/>
|
Loading…
Reference in new issue