this repo has no description
at main 99 lines 2.9 kB view raw
1import { append_empty_stylesheet, detach, get_root_for_style } from './dom.js'; 2import { raf } from './environment.js'; 3 4// we need to store the information for multiple documents because a Svelte application could also contain iframes 5// https://github.com/sveltejs/svelte/issues/3624 6/** @type {Map<Document | ShadowRoot, import('./private.d.ts').StyleInformation>} */ 7const managed_styles = new Map(); 8 9let active = 0; 10 11// https://github.com/darkskyapp/string-hash/blob/master/index.js 12/** 13 * @param {string} str 14 * @returns {number} 15 */ 16function hash(str) { 17 let hash = 5381; 18 let i = str.length; 19 while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i); 20 return hash >>> 0; 21} 22 23/** 24 * @param {Document | ShadowRoot} doc 25 * @param {Element & ElementCSSInlineStyle} node 26 * @returns {{ stylesheet: any; rules: {}; }} 27 */ 28function create_style_information(doc, node) { 29 const info = { stylesheet: append_empty_stylesheet(node), rules: {} }; 30 managed_styles.set(doc, info); 31 return info; 32} 33 34/** 35 * @param {Element & ElementCSSInlineStyle} node 36 * @param {number} a 37 * @param {number} b 38 * @param {number} duration 39 * @param {number} delay 40 * @param {(t: number) => number} ease 41 * @param {(t: number, u: number) => string} fn 42 * @param {number} uid 43 * @returns {string} 44 */ 45export function create_rule(node, a, b, duration, delay, ease, fn, uid = 0) { 46 const step = 16.666 / duration; 47 let keyframes = '{\n'; 48 for (let p = 0; p <= 1; p += step) { 49 const t = a + (b - a) * ease(p); 50 keyframes += p * 100 + `%{${fn(t, 1 - t)}}\n`; 51 } 52 const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`; 53 const name = `__svelte_${hash(rule)}_${uid}`; 54 const doc = get_root_for_style(node); 55 const { stylesheet, rules } = managed_styles.get(doc) || create_style_information(doc, node); 56 if (!rules[name]) { 57 rules[name] = true; 58 stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length); 59 } 60 const animation = node.style.animation || ''; 61 node.style.animation = `${ 62 animation ? `${animation}, ` : '' 63 }${name} ${duration}ms linear ${delay}ms 1 both`; 64 active += 1; 65 return name; 66} 67 68/** 69 * @param {Element & ElementCSSInlineStyle} node 70 * @param {string} [name] 71 * @returns {void} 72 */ 73export function delete_rule(node, name) { 74 const previous = (node.style.animation || '').split(', '); 75 const next = previous.filter( 76 name 77 ? (anim) => anim.indexOf(name) < 0 // remove specific animation 78 : (anim) => anim.indexOf('__svelte') === -1 // remove all Svelte animations 79 ); 80 const deleted = previous.length - next.length; 81 if (deleted) { 82 node.style.animation = next.join(', '); 83 active -= deleted; 84 if (!active) clear_rules(); 85 } 86} 87 88/** @returns {void} */ 89export function clear_rules() { 90 raf(() => { 91 if (active) return; 92 managed_styles.forEach((info) => { 93 const { ownerNode } = info.stylesheet; 94 // there is no ownerNode if it runs on jsdom. 95 if (ownerNode) detach(ownerNode); 96 }); 97 managed_styles.clear(); 98 }); 99}