From 792a2215c3cba9f167f99e5e8396ebb659ae083c Mon Sep 17 00:00:00 2001 From: "S. Elliott Johnson" Date: Mon, 8 May 2023 22:06:35 -0600 Subject: [PATCH] Convert src/runtime/internal/style_manager.ts to JavaScript --- src/runtime/internal/style_manager.ts | 167 +++++++++++++------------- 1 file changed, 84 insertions(+), 83 deletions(-) diff --git a/src/runtime/internal/style_manager.ts b/src/runtime/internal/style_manager.ts index c43b5b955e..346895f423 100644 --- a/src/runtime/internal/style_manager.ts +++ b/src/runtime/internal/style_manager.ts @@ -1,95 +1,96 @@ import { append_empty_stylesheet, detach, get_root_for_style } from './dom'; import { raf } from './environment'; - -interface StyleInformation { - stylesheet: CSSStyleSheet; - rules: Record; -} - // we need to store the information for multiple documents because a Svelte application could also contain iframes // https://github.com/sveltejs/svelte/issues/3624 -const managed_styles = new Map(); +const managed_styles = new Map(); let active = 0; - // https://github.com/darkskyapp/string-hash/blob/master/index.js -function hash(str: string) { - let hash = 5381; - let i = str.length; - - while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i); - return hash >>> 0; +/** @param {string} str + * @returns {number} + */ +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: Document | ShadowRoot, - node: Element & ElementCSSInlineStyle -) { - const info = { stylesheet: append_empty_stylesheet(node), rules: {} }; - managed_styles.set(doc, info); - return info; +/** @param {Document | ShadowRoot} doc + * @param {Element & ElementCSSInlineStyle} node + * @returns {{ stylesheet: any; rules: {}; }} + */ +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: 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'; - - 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; +/** @param {Element & ElementCSSInlineStyle} node + * @param {number} a + * @param {number} b + * @param {number} duration + * @param {number} delay + * @param {(t: number) => number} ease + * @param {(t: number, u: number) => string} fn + * @param {number} uid + * @returns {string} + */ +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: Element & ElementCSSInlineStyle, name?: string) { - const previous = (node.style.animation || '').split(', '); - const next = previous.filter( - name - ? (anim) => anim.indexOf(name) < 0 // remove specific animation - : (anim) => anim.indexOf('__svelte') === -1 // remove all Svelte animations - ); - const deleted = previous.length - next.length; - if (deleted) { - node.style.animation = next.join(', '); - active -= deleted; - if (!active) clear_rules(); - } +/** @param {Element & ElementCSSInlineStyle} node + * @param {string} name + * @returns {void} + */ +export function delete_rule(node, name) { + const previous = (node.style.animation || '').split(', '); + const next = previous.filter(name + ? (anim) => anim.indexOf(name) < 0 // remove specific animation + : (anim) => anim.indexOf('__svelte') === -1 // remove all Svelte animations + ); + const deleted = previous.length - next.length; + if (deleted) { + node.style.animation = next.join(', '); + active -= deleted; + if (!active) + clear_rules(); + } } - +/** @returns {void} */ export function clear_rules() { - raf(() => { - if (active) return; - managed_styles.forEach((info) => { - const { ownerNode } = info.stylesheet; - // there is no ownerNode if it runs on jsdom. - if (ownerNode) detach(ownerNode); - }); - managed_styles.clear(); - }); + raf(() => { + if (active) + return; + managed_styles.forEach((info) => { + const { ownerNode } = info.stylesheet; + // there is no ownerNode if it runs on jsdom. + if (ownerNode) + detach(ownerNode); + }); + managed_styles.clear(); + }); } + + + + +/** @typedef {Object} StyleInformation + * @property {CSSStyleSheet} stylesheet + * @property {Record} rules + */ \ No newline at end of file