|
import { append_empty_stylesheet, detach, get_root_for_style } from './dom.js'; |
|
import { raf } from './environment.js'; |
|
|
|
|
|
|
|
|
|
const managed_styles = new Map(); |
|
|
|
let active = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
function hash(str) { |
|
let hash = 5381; |
|
let i = str.length; |
|
while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i); |
|
return hash >>> 0; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
function create_style_information(doc, node) { |
|
const info = { stylesheet: append_empty_stylesheet(node), rules: {} }; |
|
managed_styles.set(doc, info); |
|
return info; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function create_rule(node, a, b, duration, delay, ease, fn, uid = 0) { |
|
const step = 16.666 / duration; |
|
let keyframes = '{\n'; |
|
for (let p = 0; p <= 1; p += step) { |
|
const t = a + (b - a) * ease(p); |
|
keyframes += p * 100 + `%{${fn(t, 1 - t)}}\n`; |
|
} |
|
const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`; |
|
const name = `__svelte_${hash(rule)}_${uid}`; |
|
const doc = get_root_for_style(node); |
|
const { stylesheet, rules } = managed_styles.get(doc) || create_style_information(doc, node); |
|
if (!rules[name]) { |
|
rules[name] = true; |
|
stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length); |
|
} |
|
const animation = node.style.animation || ''; |
|
node.style.animation = `${ |
|
animation ? `${animation}, ` : '' |
|
}${name} ${duration}ms linear ${delay}ms 1 both`; |
|
active += 1; |
|
return name; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
export function delete_rule(node, name) { |
|
const previous = (node.style.animation || '').split(', '); |
|
const next = previous.filter( |
|
name |
|
? (anim) => anim.indexOf(name) < 0 |
|
: (anim) => anim.indexOf('__svelte') === -1 |
|
); |
|
const deleted = previous.length - next.length; |
|
if (deleted) { |
|
node.style.animation = next.join(', '); |
|
active -= deleted; |
|
if (!active) clear_rules(); |
|
} |
|
} |
|
|
|
|
|
export function clear_rules() { |
|
raf(() => { |
|
if (active) return; |
|
managed_styles.forEach((info) => { |
|
const { ownerNode } = info.stylesheet; |
|
|
|
if (ownerNode) detach(ownerNode); |
|
}); |
|
managed_styles.clear(); |
|
}); |
|
} |
|
|