diff --git a/src/runtime/internal/style_manager.ts b/src/runtime/internal/style_manager.ts index 8060e65a5d3f..7fe7bcf3d59d 100644 --- a/src/runtime/internal/style_manager.ts +++ b/src/runtime/internal/style_manager.ts @@ -1,5 +1,6 @@ import { element } from './dom'; import { raf } from './environment'; +import { is_function } from './utils'; interface ExtendedDoc extends Document { __svelte_stylesheet: CSSStyleSheet; @@ -18,6 +19,21 @@ function hash(str: string) { return hash >>> 0; } +function append_style(doc) { + return doc.host ? + doc.insertBefore(element('style') as HTMLStyleElement, doc.firstElementChild) : + doc.head.appendChild(element('style') as HTMLStyleElement); +} + +function get_root_node(node) { + if (is_function(node.getRootNode)) return node.getRootNode(); + let rootNode = node.parentNode; + while (rootNode.parentNode != null) { + rootNode = rootNode.parentNode; + } + return rootNode; +} + export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b: number, duration: number, delay: number, ease: (t: number) => number, fn: (t: number, u: number) => string, uid: number = 0) { const step = 16.666 / duration; let keyframes = '{\n'; @@ -29,9 +45,9 @@ export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b: const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`; const name = `__svelte_${hash(rule)}_${uid}`; - const doc = node.ownerDocument as ExtendedDoc; + const doc = get_root_node(node) as ExtendedDoc; active_docs.add(doc); - const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = doc.head.appendChild(element('style') as HTMLStyleElement).sheet as CSSStyleSheet); + const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = append_style(doc).sheet as CSSStyleSheet); const current_rules = doc.__svelte_rules || (doc.__svelte_rules = {}); if (!current_rules[name]) { diff --git a/test/custom-elements/index.ts b/test/custom-elements/index.ts index 35df15687959..d200eff0e5e1 100644 --- a/test/custom-elements/index.ts +++ b/test/custom-elements/index.ts @@ -63,7 +63,9 @@ describe('custom-elements', function() { const solo = /\.solo$/.test(dir); const skip = /\.skip$/.test(dir); + const easing = path.resolve('easing/index.mjs'); const internal = path.resolve('internal/index.mjs'); + const transition = path.resolve('transition/index.mjs'); const index = path.resolve('index.mjs'); const warnings = []; @@ -76,10 +78,18 @@ describe('custom-elements', function() { plugins: [ { resolveId(importee) { - if (importee === 'svelte/internal' || importee === './internal') { + if (importee === '../easing') { + return easing; + } + + if (importee === 'svelte/internal' || importee === './internal' || importee === '../internal') { return internal; } + if (importee === 'svelte/transition' || importee === './transition') { + return transition; + } + if (importee === 'svelte') { return index; } diff --git a/test/custom-elements/samples/transition/main.svelte b/test/custom-elements/samples/transition/main.svelte new file mode 100644 index 000000000000..f2a235d60db2 --- /dev/null +++ b/test/custom-elements/samples/transition/main.svelte @@ -0,0 +1,18 @@ + + + + +{#if show} +

+ Fades in and out +

+{/if} diff --git a/test/custom-elements/samples/transition/test.js b/test/custom-elements/samples/transition/test.js new file mode 100644 index 000000000000..71e69ac90f7f --- /dev/null +++ b/test/custom-elements/samples/transition/test.js @@ -0,0 +1,18 @@ +import * as assert from 'assert'; +import './main.svelte'; + +export default async function (target) { + target.innerHTML = ''; + + // wait one tick in order for styles to be applied + await Promise.resolve(); + + const el = target.querySelector('custom-element'); + const style = el.shadowRoot.querySelector('style'); + + assert.ok(style); + assert.ok(style.sheet); + assert.equal(style, el.shadowRoot.firstElementChild); + assert.equal(style.sheet.cssRules.length, 1); + assert.equal(el.shadowRoot.__svelte_stylesheet, style.sheet); +}