summaryrefslogtreecommitdiff
path: root/node_modules/svelte/src/runtime/internal/style_manager.js
diff options
context:
space:
mode:
authorrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
committerrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
commitbce557cc2dc767628bed6aac87301a1be7c5431b (patch)
treeb51a051228d01fe3306cd7626d4a96768aadb944 /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.js99
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();
+ });
+}