diff options
| author | rxliuli <rxliuli@gmail.com> | 2025-11-04 05:03:50 +0800 |
|---|---|---|
| committer | rxliuli <rxliuli@gmail.com> | 2025-11-04 05:03:50 +0800 |
| commit | bce557cc2dc767628bed6aac87301a1be7c5431b (patch) | |
| tree | b51a051228d01fe3306cd7626d4a96768aadb944 /node_modules/svelte/src/runtime/internal/style_manager.js | |
init commit
Diffstat (limited to 'node_modules/svelte/src/runtime/internal/style_manager.js')
| -rw-r--r-- | node_modules/svelte/src/runtime/internal/style_manager.js | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/node_modules/svelte/src/runtime/internal/style_manager.js b/node_modules/svelte/src/runtime/internal/style_manager.js new file mode 100644 index 0000000..a989847 --- /dev/null +++ b/node_modules/svelte/src/runtime/internal/style_manager.js @@ -0,0 +1,99 @@ +import { append_empty_stylesheet, detach, get_root_for_style } from './dom.js'; +import { raf } from './environment.js'; + +// we need to store the information for multiple documents because a Svelte application could also contain iframes +// https://github.com/sveltejs/svelte/issues/3624 +/** @type {Map<Document | ShadowRoot, import('./private.d.ts').StyleInformation>} */ +const managed_styles = new Map(); + +let active = 0; + +// https://github.com/darkskyapp/string-hash/blob/master/index.js +/** + * @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; +} + +/** + * @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; +} + +/** + * @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; +} + +/** + * @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(); + }); +} |
