diff --git a/README.md b/README.md
index 50371f4..391ff23 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,16 @@
-# [ KeyframeKit][KeyframeKit]
-
-Unlock full playback control over your CSS animations with JavaScript.
+# KeyframeKit
[![NPM version][npm-version-src]][npm-version-href]
[![NPM downloads][npm-downloads-src]][npm-downloads-href]
[![Minified size][minified-size-src]][minified-size-href]
-[![CI][ci-src]][ci-href]
+[![Site][site-src]][site-href]
+
+Unlock full playback control over your CSS animations with JavaScript.
## What is this?
A lightweight TypeScript library that converts CSS `@keyframes` animations into [Web Animations API]-compatible animations, letting you play CSS-defined animations from JavaScript with full playback control and hardware-accelerated performance.
-[Read more][KeyframeKit article] | [Live Demo]
+[Documentation][KeyframeKit Site] | [Live Demo]
## Installation
@@ -77,7 +77,7 @@ Instead of getting an animation from the document's stylesheets, you can also im
import { importStyleSheet, convertStyleSheetKeyframes } from 'keyframekit';
const styles = await importStyleSheet('./styles.css');
-// note: on Chrome, Edge or Firefox (not Safari), you can just write:
+// note: on Chrome, Edge or Firefox (soon Safari), you can just write:
// import styles from './styles.css' with { type: 'css' };
// get animation keyframes from stylesheet
@@ -135,7 +135,7 @@ attachedAnim.play();
-[KeyframeKit]: https://keyframekit.berryscript.com
+[KeyframeKit Site]: https://keyframekit.berryscript.com
[Web Animations API]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API
[KeyframeKit article]: https://barhatsor.medium.com/99573ef4738b
[Live Demo]: https://codepen.io/barhatsor/pen/JoRPNmz
@@ -146,11 +146,11 @@ attachedAnim.play();
[KeyframeKit License]: ./LICENSE
-[npm-version-src]: https://img.shields.io/npm/v/keyframekit.svg
+[npm-version-src]: https://img.shields.io/npm/v/keyframekit.svg?color=6367FF
[npm-version-href]: https://www.npmjs.com/package/keyframekit
-[npm-downloads-src]: https://img.shields.io/npm/d18m/keyframekit
+[npm-downloads-src]: https://img.shields.io/npm/d18m/keyframekit?color=8494FF
[npm-downloads-href]: https://www.npmjs.com/package/keyframekit
-[minified-size-src]: https://img.shields.io/github/size/barhatsor/KeyframeKit/dist/index.min.js
+[minified-size-src]: https://img.shields.io/github/size/barhatsor/KeyframeKit/dist/index.min.js?color=C9BEFF
[minified-size-href]: /dist/index.min.js
-[ci-src]: https://github.com/barhatsor/KeyframeKit/actions/workflows/ci.yml/badge.svg
-[ci-href]: https://github.com/barhatsor/KeyframeKit/actions/workflows/ci.yml
+[site-src]: https://img.shields.io/badge/see_it-live-FFDBFD
+[site-href]: https://keyframekit.berryscript.com
diff --git a/dist/index.d.ts b/dist/index.d.ts
index eec6c16..24af57e 100644
--- a/dist/index.d.ts
+++ b/dist/index.d.ts
@@ -39,7 +39,7 @@ export declare class ConvertedKeyframes {
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)
*
* Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole
- * animation at once, on top of each keyframe's easing.
+ * animation at once, on top of each keyframe's easing. Instead, set per-keyframe easing.
*/
toKeyframeEffect(options: number | KeyframeEffectOptions | null): KeyframeEffectParameters;
}
diff --git a/dist/index.js b/dist/index.js
index 19672c7..829ceea 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -124,7 +124,7 @@ class ConvertedKeyframes {
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)
*
* Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole
- * animation at once, on top of each keyframe's easing.
+ * animation at once, on top of each keyframe's easing. Instead, set per-keyframe easing.
*/
toKeyframeEffect(options) {
const keyframeEffect = new KeyframeEffectParameters({
diff --git a/dist/index.js.map b/dist/index.js.map
index a0a07f1..4a5fb0c 100644
--- a/dist/index.js.map
+++ b/dist/index.js.map
@@ -1 +1 @@
-{"version":3,"file":"index.js","sources":["../src/KeyframesFactory/sourcing-stylesheets/getDocumentStyleSheetsOnLoad.ts","../src/KeyframesFactory/sourcing-stylesheets/importStyleSheet.ts","../src/KeyframeEffectParameters.ts","../src/KeyframesFactory/data-types/ConvertedKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertKeyframesRule.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/isStyleSheetAccessible.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertStyleSheetKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertAllStyleSheetKeyframesRules.ts"],"sourcesContent":["\n/**\n * Gets a document's stylesheets when it loads,\n * or immediately returns them if it's already loaded.\n * @param document The document to get stylesheets from.\n * @group Sourcing Stylesheets\n */\nexport async function getDocumentStyleSheetsOnLoad(\n document = window.document\n) {\n\n await waitForDocumentLoad(document);\n\n return document.styleSheets;\n\n}\n\nasync function waitForDocumentLoad(document: Document) {\n\n const isLoaded = () => document.readyState === 'complete';\n\n if (isLoaded())\n return;\n\n const { promise, resolve } = Promise.withResolvers();\n const cleanup = new AbortController();\n\n const onReadyStateChange = () => {\n if (isLoaded())\n resolve();\n };\n\n document.addEventListener(\n 'readystatechange',\n onReadyStateChange,\n { signal: cleanup.signal }\n );\n\n await promise;\n\n // remove the listener\n cleanup.abort();\n\n}\n","\n/**\n * Imports a stylesheet from a URL.\n * @param url The URL of the stylesheet to import.\n * @throws\n * - `TypeError`\n * - Thrown if the stylesheet could not be imported.\n * @remarks\n * - `@import` rules won't be resolved in imported stylesheets.\n * [See more.](https://github.com/WICG/construct-stylesheets/issues/119#issuecomment-588352418)\n * - This polyfill exists because [Safari dosen't support](https://caniuse.com/mdn-javascript_statements_import_import_attributes_type_css)\n * CSS Modules (see [this bug](https://bugs.webkit.org/show_bug.cgi?id=227967)).\n * @see\n * - [Creating a CSS module script - HTML Spec](https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-css-module-script)\n * - [import() return value - MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#return_value)\n * @group Sourcing Stylesheets\n */\nexport async function importStyleSheet(url: string) {\n\n const resp = await fetch(url);\n\n if (!resp.ok)\n throw new TypeError(`Failed to fetch dynamically imported module: ${url}`);\n\n const respText = await resp.text();\n\n const styleSheet = new CSSStyleSheet();\n styleSheet.replaceSync(respText);\n\n return styleSheet;\n\n}\n","\n/**\n * A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @see\n * [Processing a keyframes argument - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument)\n * @group Defining Animations\n */\nexport type KeyframeArgument = Keyframe[] | PropertyIndexedKeyframes;\n\n/**\n * Provides a more convenient way to define animations than is offered natively.\n * @see\n * [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * @group Defining Animations\n */\nexport class KeyframeEffectParameters {\n\n keyframes: KeyframeArgument;\n options: KeyframeEffectOptions;\n\n /**\n * @param obj\n * @param obj.keyframes A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @param obj.options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n */\n constructor({ keyframes, options = {} }: {\n keyframes: KeyframeArgument,\n options?: number | KeyframeEffectOptions\n }) {\n\n this.keyframes = keyframes;\n this.options = parseOptionsArg(options);\n\n }\n\n /**\n * @param obj\n * @param obj.target An element to attach the animation to.\n * @param obj.options Additional keyframe effect options. Can override existing keys.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n * @param obj.timeline The timeline with which to associate the animation.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Animation/Animation#timeline)\n * @see\n * - [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * - [The Animation interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-animation-interface)\n */\n toAnimation({ target, options: additionalOptions = {}, timeline = document.timeline }: {\n target: Element | null,\n options?: number | KeyframeEffectOptions,\n timeline?: AnimationTimeline | null\n }): Animation {\n\n const parsedAdditionalOptions = parseOptionsArg(additionalOptions);\n\n // override existing option keys with additional options\n const options: KeyframeEffectOptions = {\n ...this.options,\n ...parsedAdditionalOptions\n };\n\n\n const keyframeEffect = new KeyframeEffect(\n target,\n this.keyframes,\n options\n );\n\n const animation = new Animation(\n keyframeEffect,\n timeline\n );\n\n return animation;\n\n }\n\n}\n\n/**\n * @see\n * - https://drafts.csswg.org/web-animations-1/#dom-keyframeeffect-keyframeeffect-target-keyframes-options-options\n * - https://drafts.csswg.org/web-animations-1/#dom-effecttiming-duration\n */\nfunction parseOptionsArg(optionsArg: number | KeyframeEffectOptions) {\n if (typeof optionsArg === 'number')\n return { duration: optionsArg };\n return optionsArg;\n}\n","\nimport { KeyframeEffectParameters } from '../../KeyframeEffectParameters';\n\n\n/**\n * Web Animations API keyframes converted with the factory functions.\n * \n * Call {@linkcode toKeyframeEffect} to create an animation from them.\n * @group Data Types\n */\nexport class ConvertedKeyframes {\n\n keyframes: Keyframe[];\n\n constructor(keyframes: Keyframe[]) {\n this.keyframes = keyframes;\n }\n\n /**\n * @param options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n *\n * Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole\n * animation at once, on top of each keyframe's easing.\n */\n toKeyframeEffect(\n options: number | KeyframeEffectOptions | null\n ) {\n\n const keyframeEffect = new KeyframeEffectParameters({\n keyframes: this.keyframes,\n // convert (required) nullable to optional\n options: options ?? undefined\n });\n\n return keyframeEffect;\n\n }\n\n}\n\n\n/**\n * Maps CSS keyframes rule names to their converted Web Animations API keyframes.\n * @group Data Types\n */\nexport type ConvertedKeyframesRules = Map;\n","\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\n\n\nconst CHARS = {\n PERCENT_SIGN: '%',\n COMMA: ',',\n HYPHEN_MINUS: '-',\n DOUBLE_HYPHEN_MINUS: '--',\n WEBKIT_PREFIX: '-webkit-'\n} as const;\n\n/** https://drafts.csswg.org/css-animations/#animation-timing-function */\nconst TIMING_FUNCTION_PROPERTY = 'animation-timing-function';\nconst DEFAULT_TIMING_FUNCTION = 'ease';\n\n\n/**\n * Converts a CSS keyframes rule to Web Animations API keyframes.\n * @param keyframesRule The rule to convert.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertKeyframesRule(\n keyframesRule: CSSKeyframesRule\n): ConvertedKeyframes {\n\n const keyframes = Array.from(keyframesRule);\n\n // we `flatMap` as keyframes can be conjoined, eg. `0%, 100%`\n // and we have to split them for the Web Animations API's format\n // see: https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext\n const parsedKeyframes = keyframes.flatMap(keyframe =>\n parseKeyText(keyframe.keyText).map(percent =>\n parseKeyframe({ keyframe, percent })\n )\n );\n\n // sort the keyframes in place by escalating offset\n // (this is required to avoid a TypeError,\n // see: https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument).\n // note: the `!` are safe: these are keyframes created by\n // us, which always have an offset.\n parsedKeyframes.sort((a, b) => a.offset! - b.offset!);\n\n return new ConvertedKeyframes(parsedKeyframes);\n\n}\n\nfunction parseKeyframe({ keyframe, percent }: {\n keyframe: CSSKeyframeRule,\n percent: number\n}) {\n\n const offset = percent / 100;\n\n const parsedProperties = parseKeyframeProperties(keyframe.style);\n \n // a CSS keyframe's timing function eases the segment up to the next keyframe,\n // like a Web Animations API keyframe's `easing`.\n // keyframes without one use the animation's timing function, which is set on\n // the animated element, not in the rule, so we use its initial value, `ease`\n // (a Web Animations API keyframe's `easing` defaults to `linear`).\n // see: https://drafts.csswg.org/css-animations/#timing-functions\n let easing = keyframe.style.getPropertyValue(TIMING_FUNCTION_PROPERTY);\n if (easing === '')\n easing = DEFAULT_TIMING_FUNCTION;\n\n const parsedKeyframe: Keyframe = {\n ...parsedProperties,\n offset,\n easing\n };\n\n return parsedKeyframe;\n\n}\n\n/** https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument */\ntype KeyframeProperties = { [propertyName: string]: string };\n\nfunction parseKeyframeProperties(style: CSSStyleDeclaration) {\n\n const parsedProperties: KeyframeProperties = {};\n\n for (const propertyName of style) {\n\n // converted to the keyframe's `easing`, in `parseKeyframe`\n if (propertyName === TIMING_FUNCTION_PROPERTY)\n continue;\n\n /// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/getPropertyValue\n const propertyValue = style.getPropertyValue(propertyName);\n\n /// https://drafts.csswg.org/web-animations-1/#ref-for-animation-property-name-to-idl-attribute-name%E2%91%A0\n const attributeName = animationPropertyNameToIDLAttributeName(\n propertyName\n );\n\n parsedProperties[attributeName] = propertyValue;\n\n }\n\n return parsedProperties;\n\n}\n\n/** https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext */\nfunction parseKeyText(keyText: string) {\n\n const percentages = keyText.split(CHARS.COMMA);\n\n // we need to trim `percent`, as Blink\n // returns spaced keyText percentages (e.g. `1%, 2%`)\n const parsePercent = (percent: string) => Number(\n removeSuffix(percent.trim(), CHARS.PERCENT_SIGN)\n );\n\n return percentages.map(\n percent => parsePercent(percent)\n );\n\n}\n\n\n/** https://drafts.csswg.org/web-animations-1/#animation-property-name-to-idl-attribute-name */\nfunction animationPropertyNameToIDLAttributeName(property: string) {\n\n if (isCustomPropertyName(property)) return property;\n\n if (property === 'float') return 'cssFloat';\n\n if (property === 'offset') return 'cssOffset';\n\n // https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2\n const lowercaseFirst = isWebkitCasedAttribute(property);\n\n return cssPropertyToIDLAttribute(property, lowercaseFirst);\n\n}\n\n/** https://drafts.csswg.org/cssom/#css-property-to-idl-attribute */\nfunction cssPropertyToIDLAttribute(property: string, lowercaseFirst: boolean = false) {\n\n let output = '';\n let uppercaseNext = false;\n\n if (lowercaseFirst)\n property = property.slice(1);\n\n for (const c of property) {\n\n if (c === CHARS.HYPHEN_MINUS) {\n\n uppercaseNext = true;\n\n } else if (uppercaseNext) {\n\n uppercaseNext = false;\n\n output += c.toUpperCase();\n\n } else {\n\n output += c;\n\n }\n\n }\n\n return output;\n\n}\n\n/** https://drafts.csswg.org/css-variables-2/#typedef-custom-property-name */\nfunction isCustomPropertyName(property: string) {\n return property.startsWith(CHARS.DOUBLE_HYPHEN_MINUS) &&\n property !== CHARS.DOUBLE_HYPHEN_MINUS;\n}\n\n/** https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2 */\nfunction isWebkitCasedAttribute(property: string) {\n return property.startsWith(CHARS.WEBKIT_PREFIX);\n}\n\n\nfunction removeSuffix(value: string, suffix: string) {\n return value.slice(0, -suffix.length);\n}\n","\n/**\n * Checks whether a stylesheet's rules can be read.\n *\n * Reading `cssRules` throws a `SecurityError` when the stylesheet\n * isn't origin-clean, e.g. a cross-origin `` loaded without CORS.\n * Browsers differ on which stylesheets qualify (Safari 17 also treats\n * `data:` URL stylesheets in sandboxed iframes as cross-origin),\n * so we test for access instead of comparing origins.\n * @see https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssrules\n */\nexport function isStyleSheetAccessible(styleSheet: CSSStyleSheet) {\n\n try {\n styleSheet.cssRules;\n return true;\n } catch (error) {\n if (error instanceof DOMException && error.name === 'SecurityError')\n return false;\n throw error;\n }\n\n}\n","\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Converts a CSS keyframes rule from a stylesheet (or stylesheet list)\n * into Web Animations API keyframes.\n * @param obj\n * @param obj.of The name of the `@keyframes` rule to get keyframes from.\n * @param obj.in The stylesheet or stylesheet list where the rule resides.\n * @throws\n * - `TypeError`\n * - Thrown if keyframes rule name is not a string.\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the name, the last one is used, like in CSS.\n * - When searching a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertStyleSheetKeyframes({ of: ruleName, in: source }: {\n of: string,\n in: CSSStyleSheetSource\n}): ConvertedKeyframes | undefined {\n\n if (typeof ruleName !== 'string')\n throw new TypeError(`Keyframes rule name must be a string.`);\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertStyleSheetKeyframesInStyleSheetList({\n of: ruleName,\n styleSheetList: source\n });\n case source instanceof CSSStyleSheet:\n return convertStyleSheetKeyframesInStyleSheet({\n of: ruleName,\n styleSheet: source\n });\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheetList({ of: ruleName, styleSheetList }: {\n of: string,\n styleSheetList: StyleSheetList\n}) {\n\n const foundRules = Array.from(styleSheetList)\n .filter(isStyleSheetAccessible)\n .map(styleSheet => findKeyframesRuleInStyleSheet({ ruleName, styleSheet }))\n .filter(rule => rule !== undefined);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const foundRule = foundRules.at(-1);\n if (foundRule === undefined)\n return\n\n return convertKeyframesRule(foundRule);\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheet({ of: ruleName, styleSheet }: {\n of: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const rule = findKeyframesRuleInStyleSheet({ ruleName, styleSheet });\n\n if (rule === undefined)\n return;\n\n return convertKeyframesRule(rule);\n\n}\n\nfunction findKeyframesRuleInStyleSheet({ ruleName, styleSheet }: {\n ruleName: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const cssRules = Array.from(styleSheet.cssRules);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const rule = cssRules.findLast((rule): rule is CSSKeyframesRule =>\n rule instanceof CSSKeyframesRule &&\n rule.name === ruleName\n );\n\n return rule;\n\n}\n","\nimport type { ConvertedKeyframesRules } from '../data-types/ConvertedKeyframes';\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Gets all the CSS keyframes rules in a stylesheet or stylesheet list,\n * then converts them to Web Animations API keyframes.\n * @param obj\n * @param obj.in The style sheet or style sheet list to get keyframes from.\n * @throws\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the same name, the last one is used, like in CSS.\n * - When reading a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertAllStyleSheetKeyframesRules({ in: source }: {\n in: CSSStyleSheetSource\n}): ConvertedKeyframesRules {\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertAllStyleSheetKeyframesRulesInStyleSheetList(source);\n case source instanceof CSSStyleSheet:\n return convertAllStyleSheetKeyframesRulesInStyleSheet(source);\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheetList(\n styleSheetList: StyleSheetList\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const styleSheet of styleSheetList) {\n\n if (!isStyleSheetAccessible(styleSheet))\n continue;\n\n const rules = convertAllStyleSheetKeyframesRulesInStyleSheet(styleSheet);\n\n for (const [ruleName, keyframesRule] of rules) {\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n keyframesRules.set(ruleName, keyframesRule);\n }\n\n }\n\n return keyframesRules;\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheet(\n styleSheet: CSSStyleSheet\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const rule of styleSheet.cssRules) {\n\n if (!(rule instanceof CSSKeyframesRule))\n continue;\n\n const keyframes = convertKeyframesRule(rule);\n\n keyframesRules.set(rule.name, keyframes);\n\n }\n\n return keyframesRules;\n\n}\n"],"names":[],"mappings":";;;;AACA;;;;;AAKG;AACI,eAAe,4BAA4B,CAChD,QAAQ,GAAG,MAAM,CAAC,QAAQ,EAAA;AAG1B,IAAA,MAAM,mBAAmB,CAAC,QAAQ,CAAC;IAEnC,OAAO,QAAQ,CAAC,WAAW;AAE7B;AAEA,eAAe,mBAAmB,CAAC,QAAkB,EAAA;IAEnD,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,UAAU,KAAK,UAAU;AAEzD,IAAA,IAAI,QAAQ,EAAE;QACZ;IAEF,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,EAAQ;AAC1D,IAAA,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE;IAErC,MAAM,kBAAkB,GAAG,MAAK;AAC9B,QAAA,IAAI,QAAQ,EAAE;AACZ,YAAA,OAAO,EAAE;AACb,IAAA,CAAC;AAED,IAAA,QAAQ,CAAC,gBAAgB,CACvB,kBAAkB,EAClB,kBAAkB,EAClB,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAC3B;AAED,IAAA,MAAM,OAAO;;IAGb,OAAO,CAAC,KAAK,EAAE;AAEjB;;AC1CA;;;;;;;;;;;;;;;AAeG;AACI,eAAe,gBAAgB,CAAC,GAAW,EAAA;AAEhD,IAAA,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC;IAE7B,IAAI,CAAC,IAAI,CAAC,EAAE;AACV,QAAA,MAAM,IAAI,SAAS,CAAC,gDAAgD,GAAG,CAAA,CAAE,CAAC;AAE5E,IAAA,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE;AAElC,IAAA,MAAM,UAAU,GAAG,IAAI,aAAa,EAAE;AACtC,IAAA,UAAU,CAAC,WAAW,CAAC,QAAQ,CAAC;AAEhC,IAAA,OAAO,UAAU;AAEnB;;ACrBA;;;;;AAKG;MACU,wBAAwB,CAAA;AAEnC,IAAA,SAAS;AACT,IAAA,OAAO;AAEP;;;;;;AAMG;AACH,IAAA,WAAA,CAAY,EAAE,SAAS,EAAE,OAAO,GAAG,EAAE,EAGpC,EAAA;AAEC,QAAA,IAAI,CAAC,SAAS,GAAG,SAAS;AAC1B,QAAA,IAAI,CAAC,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC;IAEzC;AAEA;;;;;;;;;;AAUG;AACH,IAAA,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,EAAE,EAAE,QAAQ,GAAG,QAAQ,CAAC,QAAQ,EAIlF,EAAA;AAEC,QAAA,MAAM,uBAAuB,GAAG,eAAe,CAAC,iBAAiB,CAAC;;AAGlE,QAAA,MAAM,OAAO,GAA0B;YACrC,GAAG,IAAI,CAAC,OAAO;AACf,YAAA,GAAG;SACJ;AAGD,QAAA,MAAM,cAAc,GAAG,IAAI,cAAc,CACvC,MAAM,EACN,IAAI,CAAC,SAAS,EACd,OAAO,CACR;QAED,MAAM,SAAS,GAAG,IAAI,SAAS,CAC7B,cAAc,EACd,QAAQ,CACT;AAED,QAAA,OAAO,SAAS;IAElB;AAED;AAED;;;;AAIG;AACH,SAAS,eAAe,CAAC,UAA0C,EAAA;IACjE,IAAI,OAAO,UAAU,KAAK,QAAQ;AAChC,QAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE;AACjC,IAAA,OAAO,UAAU;AACnB;;ACtFA;;;;;AAKG;MACU,kBAAkB,CAAA;AAE7B,IAAA,SAAS;AAET,IAAA,WAAA,CAAY,SAAqB,EAAA;AAC/B,QAAA,IAAI,CAAC,SAAS,GAAG,SAAS;IAC5B;AAEA;;;;;;AAMG;AACH,IAAA,gBAAgB,CACd,OAA8C,EAAA;AAG9C,QAAA,MAAM,cAAc,GAAG,IAAI,wBAAwB,CAAC;YAClD,SAAS,EAAE,IAAI,CAAC,SAAS;;YAEzB,OAAO,EAAE,OAAO,IAAI;AACrB,SAAA,CAAC;AAEF,QAAA,OAAO,cAAc;IAEvB;AAED;;ACnCD,MAAM,KAAK,GAAG;AACZ,IAAA,YAAY,EAAE,GAAG;AACjB,IAAA,KAAK,EAAE,GAAG;AACV,IAAA,YAAY,EAAE,GAAG;AACjB,IAAA,mBAAmB,EAAE,IAAI;AACzB,IAAA,aAAa,EAAE;CACP;AAEV;AACA,MAAM,wBAAwB,GAAG,2BAA2B;AAC5D,MAAM,uBAAuB,GAAG,MAAM;AAGtC;;;;AAIG;AACG,SAAU,oBAAoB,CAClC,aAA+B,EAAA;IAG/B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC;;;;AAK3C,IAAA,MAAM,eAAe,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,IAChD,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,IACxC,aAAa,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CACrC,CACF;;;;;;AAOD,IAAA,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,MAAO,GAAG,CAAC,CAAC,MAAO,CAAC;AAErD,IAAA,OAAO,IAAI,kBAAkB,CAAC,eAAe,CAAC;AAEhD;AAEA,SAAS,aAAa,CAAC,EAAE,QAAQ,EAAE,OAAO,EAGzC,EAAA;AAEC,IAAA,MAAM,MAAM,GAAG,OAAO,GAAG,GAAG;IAE5B,MAAM,gBAAgB,GAAG,uBAAuB,CAAC,QAAQ,CAAC,KAAK,CAAC;;;;;;;IAQhE,IAAI,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,wBAAwB,CAAC;IACtE,IAAI,MAAM,KAAK,EAAE;QACf,MAAM,GAAG,uBAAuB;AAElC,IAAA,MAAM,cAAc,GAAa;AAC/B,QAAA,GAAG,gBAAgB;QACnB,MAAM;QACN;KACD;AAED,IAAA,OAAO,cAAc;AAEvB;AAKA,SAAS,uBAAuB,CAAC,KAA0B,EAAA;IAEzD,MAAM,gBAAgB,GAAuB,EAAE;AAE/C,IAAA,KAAK,MAAM,YAAY,IAAI,KAAK,EAAE;;QAGhC,IAAI,YAAY,KAAK,wBAAwB;YAC3C;;QAGF,MAAM,aAAa,GAAG,KAAK,CAAC,gBAAgB,CAAC,YAAY,CAAC;;AAG1D,QAAA,MAAM,aAAa,GAAG,uCAAuC,CAC3D,YAAY,CACb;AAED,QAAA,gBAAgB,CAAC,aAAa,CAAC,GAAG,aAAa;IAEjD;AAEA,IAAA,OAAO,gBAAgB;AAEzB;AAEA;AACA,SAAS,YAAY,CAAC,OAAe,EAAA;IAEnC,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;;;IAI9C,MAAM,YAAY,GAAG,CAAC,OAAe,KAAK,MAAM,CAC9C,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,YAAY,CAAC,CACjD;AAED,IAAA,OAAO,WAAW,CAAC,GAAG,CACpB,OAAO,IAAI,YAAY,CAAC,OAAO,CAAC,CACjC;AAEH;AAGA;AACA,SAAS,uCAAuC,CAAC,QAAgB,EAAA;IAE/D,IAAI,oBAAoB,CAAC,QAAQ,CAAC;AAAE,QAAA,OAAO,QAAQ;IAEnD,IAAI,QAAQ,KAAK,OAAO;AAAE,QAAA,OAAO,UAAU;IAE3C,IAAI,QAAQ,KAAK,QAAQ;AAAE,QAAA,OAAO,WAAW;;AAG7C,IAAA,MAAM,cAAc,GAAG,sBAAsB,CAAC,QAAQ,CAAC;AAEvD,IAAA,OAAO,yBAAyB,CAAC,QAAQ,EAAE,cAAc,CAAC;AAE5D;AAEA;AACA,SAAS,yBAAyB,CAAC,QAAgB,EAAE,iBAA0B,KAAK,EAAA;IAElF,IAAI,MAAM,GAAG,EAAE;IACf,IAAI,aAAa,GAAG,KAAK;AAEzB,IAAA,IAAI,cAAc;AAChB,QAAA,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AAE9B,IAAA,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE;AAExB,QAAA,IAAI,CAAC,KAAK,KAAK,CAAC,YAAY,EAAE;YAE5B,aAAa,GAAG,IAAI;QAEtB;aAAO,IAAI,aAAa,EAAE;YAExB,aAAa,GAAG,KAAK;AAErB,YAAA,MAAM,IAAI,CAAC,CAAC,WAAW,EAAE;QAE3B;aAAO;YAEL,MAAM,IAAI,CAAC;QAEb;IAEF;AAEA,IAAA,OAAO,MAAM;AAEf;AAEA;AACA,SAAS,oBAAoB,CAAC,QAAgB,EAAA;AAC5C,IAAA,OAAO,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,mBAAmB,CAAC;AAC9C,QAAA,QAAQ,KAAK,KAAK,CAAC,mBAAmB;AAC/C;AAEA;AACA,SAAS,sBAAsB,CAAC,QAAgB,EAAA;IAC9C,OAAO,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,aAAa,CAAC;AACjD;AAGA,SAAS,YAAY,CAAC,KAAa,EAAE,MAAc,EAAA;IACjD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;AACvC;;AC1LA;;;;;;;;;AASG;AACG,SAAU,sBAAsB,CAAC,UAAyB,EAAA;AAE9D,IAAA,IAAI;QACF,UAAU,CAAC,QAAQ;AACnB,QAAA,OAAO,IAAI;IACb;IAAE,OAAO,KAAK,EAAE;QACd,IAAI,KAAK,YAAY,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe;AACjE,YAAA,OAAO,KAAK;AACd,QAAA,MAAM,KAAK;IACb;AAEF;;ACfA;;;;;;;;;;;;;;;;;;;;;AAqBG;AACG,SAAU,0BAA0B,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAGpE,EAAA;IAEC,IAAI,OAAO,QAAQ,KAAK,QAAQ;AAC9B,QAAA,MAAM,IAAI,SAAS,CAAC,CAAA,qCAAA,CAAuC,CAAC;IAE9D,QAAQ,IAAI;QACV,KAAK,MAAM,YAAY,cAAc;AACnC,YAAA,OAAO,0CAA0C,CAAC;AAChD,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,cAAc,EAAE;AACjB,aAAA,CAAC;QACJ,KAAK,MAAM,YAAY,aAAa;AAClC,YAAA,OAAO,sCAAsC,CAAC;AAC5C,gBAAA,EAAE,EAAE,QAAQ;AACZ,gBAAA,UAAU,EAAE;AACb,aAAA,CAAC;AACJ,QAAA;AACE,YAAA,MAAM,IAAI,SAAS,CAAC,CAAA,0DAAA,CAA4D,CAAC;;AAGvF;AAEA,SAAS,0CAA0C,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,cAAc,EAGjF,EAAA;AAEC,IAAA,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,cAAc;SACzC,MAAM,CAAC,sBAAsB;AAC7B,SAAA,GAAG,CAAC,UAAU,IAAI,6BAA6B,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;SACzE,MAAM,CAAC,IAAI,IAAI,IAAI,KAAK,SAAS,CAAC;;;IAIrC,MAAM,SAAS,GAAG,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;IACnC,IAAI,SAAS,KAAK,SAAS;QACzB;AAEF,IAAA,OAAO,oBAAoB,CAAC,SAAS,CAAC;AAExC;AAEA,SAAS,sCAAsC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,UAAU,EAGzE,EAAA;IAEC,MAAM,IAAI,GAAG,6BAA6B,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IAEpE,IAAI,IAAI,KAAK,SAAS;QACpB;AAEF,IAAA,OAAO,oBAAoB,CAAC,IAAI,CAAC;AAEnC;AAEA,SAAS,6BAA6B,CAAC,EAAE,QAAQ,EAAE,UAAU,EAG5D,EAAA;IAEC,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;;;AAIhD,IAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,KAClC,IAAI,YAAY,gBAAgB;AAChC,QAAA,IAAI,CAAC,IAAI,KAAK,QAAQ,CACvB;AAED,IAAA,OAAO,IAAI;AAEb;;ACjGA;;;;;;;;;;;;;;;;;;AAkBG;SACa,kCAAkC,CAAC,EAAE,EAAE,EAAE,MAAM,EAE9D,EAAA;IAEC,QAAQ,IAAI;QACV,KAAK,MAAM,YAAY,cAAc;AACnC,YAAA,OAAO,kDAAkD,CAAC,MAAM,CAAC;QACnE,KAAK,MAAM,YAAY,aAAa;AAClC,YAAA,OAAO,8CAA8C,CAAC,MAAM,CAAC;AAC/D,QAAA;AACE,YAAA,MAAM,IAAI,SAAS,CAAC,CAAA,0DAAA,CAA4D,CAAC;;AAGvF;AAEA,SAAS,kDAAkD,CACzD,cAA8B,EAAA;AAG9B,IAAA,MAAM,cAAc,GAA4B,IAAI,GAAG,EAAE;AAEzD,IAAA,KAAK,MAAM,UAAU,IAAI,cAAc,EAAE;AAEvC,QAAA,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC;YACrC;AAEF,QAAA,MAAM,KAAK,GAAG,8CAA8C,CAAC,UAAU,CAAC;QAExE,KAAK,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,KAAK,EAAE;;;AAG7C,YAAA,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC;QAC7C;IAEF;AAEA,IAAA,OAAO,cAAc;AAEvB;AAEA,SAAS,8CAA8C,CACrD,UAAyB,EAAA;AAGzB,IAAA,MAAM,cAAc,GAA4B,IAAI,GAAG,EAAE;AAEzD,IAAA,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,QAAQ,EAAE;AAEtC,QAAA,IAAI,EAAE,IAAI,YAAY,gBAAgB,CAAC;YACrC;AAEF,QAAA,MAAM,SAAS,GAAG,oBAAoB,CAAC,IAAI,CAAC;QAE5C,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;IAE1C;AAEA,IAAA,OAAO,cAAc;AAEvB;;;;;;;;;;;;"}
\ No newline at end of file
+{"version":3,"file":"index.js","sources":["../src/KeyframesFactory/sourcing-stylesheets/getDocumentStyleSheetsOnLoad.ts","../src/KeyframesFactory/sourcing-stylesheets/importStyleSheet.ts","../src/KeyframeEffectParameters.ts","../src/KeyframesFactory/data-types/ConvertedKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertKeyframesRule.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/isStyleSheetAccessible.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertStyleSheetKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertAllStyleSheetKeyframesRules.ts"],"sourcesContent":["\n/**\n * Gets a document's stylesheets when it loads,\n * or immediately returns them if it's already loaded.\n * @param document The document to get stylesheets from.\n * @group Sourcing Stylesheets\n */\nexport async function getDocumentStyleSheetsOnLoad(\n document = window.document\n) {\n\n await waitForDocumentLoad(document);\n\n return document.styleSheets;\n\n}\n\nasync function waitForDocumentLoad(document: Document) {\n\n const isLoaded = () => document.readyState === 'complete';\n\n if (isLoaded())\n return;\n\n const { promise, resolve } = Promise.withResolvers();\n const cleanup = new AbortController();\n\n const onReadyStateChange = () => {\n if (isLoaded())\n resolve();\n };\n\n document.addEventListener(\n 'readystatechange',\n onReadyStateChange,\n { signal: cleanup.signal }\n );\n\n await promise;\n\n // remove the listener\n cleanup.abort();\n\n}\n","\n/**\n * Imports a stylesheet from a URL.\n * @param url The URL of the stylesheet to import.\n * @throws\n * - `TypeError`\n * - Thrown if the stylesheet could not be imported.\n * @remarks\n * - `@import` rules won't be resolved in imported stylesheets.\n * [See more.](https://github.com/WICG/construct-stylesheets/issues/119#issuecomment-588352418)\n * - This polyfill exists because [Safari dosen't support](https://caniuse.com/mdn-javascript_statements_import_import_attributes_type_css)\n * CSS Modules (see [this bug](https://bugs.webkit.org/show_bug.cgi?id=227967)).\n * @see\n * - [Creating a CSS module script - HTML Spec](https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-css-module-script)\n * - [import() return value - MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#return_value)\n * @group Sourcing Stylesheets\n */\nexport async function importStyleSheet(url: string) {\n\n const resp = await fetch(url);\n\n if (!resp.ok)\n throw new TypeError(`Failed to fetch dynamically imported module: ${url}`);\n\n const respText = await resp.text();\n\n const styleSheet = new CSSStyleSheet();\n styleSheet.replaceSync(respText);\n\n return styleSheet;\n\n}\n","\n/**\n * A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @see\n * [Processing a keyframes argument - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument)\n * @group Defining Animations\n */\nexport type KeyframeArgument = Keyframe[] | PropertyIndexedKeyframes;\n\n/**\n * Provides a more convenient way to define animations than is offered natively.\n * @see\n * [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * @group Defining Animations\n */\nexport class KeyframeEffectParameters {\n\n keyframes: KeyframeArgument;\n options: KeyframeEffectOptions;\n\n /**\n * @param obj\n * @param obj.keyframes A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @param obj.options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n */\n constructor({ keyframes, options = {} }: {\n keyframes: KeyframeArgument,\n options?: number | KeyframeEffectOptions\n }) {\n\n this.keyframes = keyframes;\n this.options = parseOptionsArg(options);\n\n }\n\n /**\n * @param obj\n * @param obj.target An element to attach the animation to.\n * @param obj.options Additional keyframe effect options. Can override existing keys.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n * @param obj.timeline The timeline with which to associate the animation.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Animation/Animation#timeline)\n * @see\n * - [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * - [The Animation interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-animation-interface)\n */\n toAnimation({ target, options: additionalOptions = {}, timeline = document.timeline }: {\n target: Element | null,\n options?: number | KeyframeEffectOptions,\n timeline?: AnimationTimeline | null\n }): Animation {\n\n const parsedAdditionalOptions = parseOptionsArg(additionalOptions);\n\n // override existing option keys with additional options\n const options: KeyframeEffectOptions = {\n ...this.options,\n ...parsedAdditionalOptions\n };\n\n\n const keyframeEffect = new KeyframeEffect(\n target,\n this.keyframes,\n options\n );\n\n const animation = new Animation(\n keyframeEffect,\n timeline\n );\n\n return animation;\n\n }\n\n}\n\n/**\n * @see\n * - https://drafts.csswg.org/web-animations-1/#dom-keyframeeffect-keyframeeffect-target-keyframes-options-options\n * - https://drafts.csswg.org/web-animations-1/#dom-effecttiming-duration\n */\nfunction parseOptionsArg(optionsArg: number | KeyframeEffectOptions) {\n if (typeof optionsArg === 'number')\n return { duration: optionsArg };\n return optionsArg;\n}\n","\nimport { KeyframeEffectParameters } from '../../KeyframeEffectParameters';\n\n\n/**\n * Web Animations API keyframes converted with the factory functions.\n * \n * Call {@linkcode toKeyframeEffect} to create an animation from them.\n * @group Data Types\n */\nexport class ConvertedKeyframes {\n\n keyframes: Keyframe[];\n\n constructor(keyframes: Keyframe[]) {\n this.keyframes = keyframes;\n }\n\n /**\n * @param options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n *\n * Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole\n * animation at once, on top of each keyframe's easing. Instead, set per-keyframe easing.\n */\n toKeyframeEffect(\n options: number | KeyframeEffectOptions | null\n ) {\n\n const keyframeEffect = new KeyframeEffectParameters({\n keyframes: this.keyframes,\n // convert (required) nullable to optional\n options: options ?? undefined\n });\n\n return keyframeEffect;\n\n }\n\n}\n\n\n/**\n * Maps CSS keyframes rule names to their converted Web Animations API keyframes.\n * @group Data Types\n */\nexport type ConvertedKeyframesRules = Map;\n","\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\n\n\nconst CHARS = {\n PERCENT_SIGN: '%',\n COMMA: ',',\n HYPHEN_MINUS: '-',\n DOUBLE_HYPHEN_MINUS: '--',\n WEBKIT_PREFIX: '-webkit-'\n} as const;\n\n/** https://drafts.csswg.org/css-animations/#animation-timing-function */\nconst TIMING_FUNCTION_PROPERTY = 'animation-timing-function';\nconst DEFAULT_TIMING_FUNCTION = 'ease';\n\n\n/**\n * Converts a CSS keyframes rule to Web Animations API keyframes.\n * @param keyframesRule The rule to convert.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertKeyframesRule(\n keyframesRule: CSSKeyframesRule\n): ConvertedKeyframes {\n\n const keyframes = Array.from(keyframesRule);\n\n // we `flatMap` as keyframes can be conjoined, eg. `0%, 100%`\n // and we have to split them for the Web Animations API's format\n // see: https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext\n const parsedKeyframes = keyframes.flatMap(keyframe =>\n parseKeyText(keyframe.keyText).map(percent =>\n parseKeyframe({ keyframe, percent })\n )\n );\n\n // sort the keyframes in place by escalating offset\n // (this is required to avoid a TypeError,\n // see: https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument).\n // note: the `!` are safe: these are keyframes created by\n // us, which always have an offset.\n parsedKeyframes.sort((a, b) => a.offset! - b.offset!);\n\n return new ConvertedKeyframes(parsedKeyframes);\n\n}\n\nfunction parseKeyframe({ keyframe, percent }: {\n keyframe: CSSKeyframeRule,\n percent: number\n}) {\n\n const offset = percent / 100;\n\n const parsedProperties = parseKeyframeProperties(keyframe.style);\n \n // a CSS keyframe's timing function eases the segment up to the next keyframe,\n // like a Web Animations API keyframe's `easing`.\n // keyframes without one use the animation's timing function, which is set on\n // the animated element, not in the rule, so we use its initial value, `ease`\n // (a Web Animations API keyframe's `easing` defaults to `linear`).\n // see: https://drafts.csswg.org/css-animations/#timing-functions\n let easing = keyframe.style.getPropertyValue(TIMING_FUNCTION_PROPERTY);\n if (easing === '')\n easing = DEFAULT_TIMING_FUNCTION;\n\n const parsedKeyframe: Keyframe = {\n ...parsedProperties,\n offset,\n easing\n };\n\n return parsedKeyframe;\n\n}\n\n/** https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument */\ntype KeyframeProperties = { [propertyName: string]: string };\n\nfunction parseKeyframeProperties(style: CSSStyleDeclaration) {\n\n const parsedProperties: KeyframeProperties = {};\n\n for (const propertyName of style) {\n\n // converted to the keyframe's `easing`, in `parseKeyframe`\n if (propertyName === TIMING_FUNCTION_PROPERTY)\n continue;\n\n /// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/getPropertyValue\n const propertyValue = style.getPropertyValue(propertyName);\n\n /// https://drafts.csswg.org/web-animations-1/#ref-for-animation-property-name-to-idl-attribute-name%E2%91%A0\n const attributeName = animationPropertyNameToIDLAttributeName(\n propertyName\n );\n\n parsedProperties[attributeName] = propertyValue;\n\n }\n\n return parsedProperties;\n\n}\n\n/** https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext */\nfunction parseKeyText(keyText: string) {\n\n const percentages = keyText.split(CHARS.COMMA);\n\n // we need to trim `percent`, as Blink\n // returns spaced keyText percentages (e.g. `1%, 2%`)\n const parsePercent = (percent: string) => Number(\n removeSuffix(percent.trim(), CHARS.PERCENT_SIGN)\n );\n\n return percentages.map(\n percent => parsePercent(percent)\n );\n\n}\n\n\n/** https://drafts.csswg.org/web-animations-1/#animation-property-name-to-idl-attribute-name */\nfunction animationPropertyNameToIDLAttributeName(property: string) {\n\n if (isCustomPropertyName(property)) return property;\n\n if (property === 'float') return 'cssFloat';\n\n if (property === 'offset') return 'cssOffset';\n\n // https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2\n const lowercaseFirst = isWebkitCasedAttribute(property);\n\n return cssPropertyToIDLAttribute(property, lowercaseFirst);\n\n}\n\n/** https://drafts.csswg.org/cssom/#css-property-to-idl-attribute */\nfunction cssPropertyToIDLAttribute(property: string, lowercaseFirst: boolean = false) {\n\n let output = '';\n let uppercaseNext = false;\n\n if (lowercaseFirst)\n property = property.slice(1);\n\n for (const c of property) {\n\n if (c === CHARS.HYPHEN_MINUS) {\n\n uppercaseNext = true;\n\n } else if (uppercaseNext) {\n\n uppercaseNext = false;\n\n output += c.toUpperCase();\n\n } else {\n\n output += c;\n\n }\n\n }\n\n return output;\n\n}\n\n/** https://drafts.csswg.org/css-variables-2/#typedef-custom-property-name */\nfunction isCustomPropertyName(property: string) {\n return property.startsWith(CHARS.DOUBLE_HYPHEN_MINUS) &&\n property !== CHARS.DOUBLE_HYPHEN_MINUS;\n}\n\n/** https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2 */\nfunction isWebkitCasedAttribute(property: string) {\n return property.startsWith(CHARS.WEBKIT_PREFIX);\n}\n\n\nfunction removeSuffix(value: string, suffix: string) {\n return value.slice(0, -suffix.length);\n}\n","\n/**\n * Checks whether a stylesheet's rules can be read.\n *\n * Reading `cssRules` throws a `SecurityError` when the stylesheet\n * isn't origin-clean, e.g. a cross-origin `` loaded without CORS.\n * Browsers differ on which stylesheets qualify (Safari 17 also treats\n * `data:` URL stylesheets in sandboxed iframes as cross-origin),\n * so we test for access instead of comparing origins.\n * @see https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssrules\n */\nexport function isStyleSheetAccessible(styleSheet: CSSStyleSheet) {\n\n try {\n styleSheet.cssRules;\n return true;\n } catch (error) {\n if (error instanceof DOMException && error.name === 'SecurityError')\n return false;\n throw error;\n }\n\n}\n","\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Converts a CSS keyframes rule from a stylesheet (or stylesheet list)\n * into Web Animations API keyframes.\n * @param obj\n * @param obj.of The name of the `@keyframes` rule to get keyframes from.\n * @param obj.in The stylesheet or stylesheet list where the rule resides.\n * @throws\n * - `TypeError`\n * - Thrown if keyframes rule name is not a string.\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the name, the last one is used, like in CSS.\n * - When searching a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertStyleSheetKeyframes({ of: ruleName, in: source }: {\n of: string,\n in: CSSStyleSheetSource\n}): ConvertedKeyframes | undefined {\n\n if (typeof ruleName !== 'string')\n throw new TypeError(`Keyframes rule name must be a string.`);\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertStyleSheetKeyframesInStyleSheetList({\n of: ruleName,\n styleSheetList: source\n });\n case source instanceof CSSStyleSheet:\n return convertStyleSheetKeyframesInStyleSheet({\n of: ruleName,\n styleSheet: source\n });\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheetList({ of: ruleName, styleSheetList }: {\n of: string,\n styleSheetList: StyleSheetList\n}) {\n\n const foundRules = Array.from(styleSheetList)\n .filter(isStyleSheetAccessible)\n .map(styleSheet => findKeyframesRuleInStyleSheet({ ruleName, styleSheet }))\n .filter(rule => rule !== undefined);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const foundRule = foundRules.at(-1);\n if (foundRule === undefined)\n return\n\n return convertKeyframesRule(foundRule);\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheet({ of: ruleName, styleSheet }: {\n of: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const rule = findKeyframesRuleInStyleSheet({ ruleName, styleSheet });\n\n if (rule === undefined)\n return;\n\n return convertKeyframesRule(rule);\n\n}\n\nfunction findKeyframesRuleInStyleSheet({ ruleName, styleSheet }: {\n ruleName: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const cssRules = Array.from(styleSheet.cssRules);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const rule = cssRules.findLast((rule): rule is CSSKeyframesRule =>\n rule instanceof CSSKeyframesRule &&\n rule.name === ruleName\n );\n\n return rule;\n\n}\n","\nimport type { ConvertedKeyframesRules } from '../data-types/ConvertedKeyframes';\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Gets all the CSS keyframes rules in a stylesheet or stylesheet list,\n * then converts them to Web Animations API keyframes.\n * @param obj\n * @param obj.in The style sheet or style sheet list to get keyframes from.\n * @throws\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the same name, the last one is used, like in CSS.\n * - When reading a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertAllStyleSheetKeyframesRules({ in: source }: {\n in: CSSStyleSheetSource\n}): ConvertedKeyframesRules {\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertAllStyleSheetKeyframesRulesInStyleSheetList(source);\n case source instanceof CSSStyleSheet:\n return convertAllStyleSheetKeyframesRulesInStyleSheet(source);\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheetList(\n styleSheetList: StyleSheetList\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const styleSheet of styleSheetList) {\n\n if (!isStyleSheetAccessible(styleSheet))\n continue;\n\n const rules = convertAllStyleSheetKeyframesRulesInStyleSheet(styleSheet);\n\n for (const [ruleName, keyframesRule] of rules) {\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n keyframesRules.set(ruleName, keyframesRule);\n }\n\n }\n\n return keyframesRules;\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheet(\n styleSheet: CSSStyleSheet\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const rule of styleSheet.cssRules) {\n\n if (!(rule instanceof CSSKeyframesRule))\n continue;\n\n const keyframes = convertKeyframesRule(rule);\n\n keyframesRules.set(rule.name, keyframes);\n\n }\n\n return keyframesRules;\n\n}\n"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/index.min.js.map b/dist/index.min.js.map
index 21bc8e1..95cc5a0 100644
--- a/dist/index.min.js.map
+++ b/dist/index.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"index.min.js","sources":["../src/KeyframesFactory/sourcing-stylesheets/getDocumentStyleSheetsOnLoad.ts","../src/KeyframesFactory/sourcing-stylesheets/importStyleSheet.ts","../src/KeyframeEffectParameters.ts","../src/KeyframesFactory/data-types/ConvertedKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertKeyframesRule.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/isStyleSheetAccessible.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertStyleSheetKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertAllStyleSheetKeyframesRules.ts"],"sourcesContent":["\n/**\n * Gets a document's stylesheets when it loads,\n * or immediately returns them if it's already loaded.\n * @param document The document to get stylesheets from.\n * @group Sourcing Stylesheets\n */\nexport async function getDocumentStyleSheetsOnLoad(\n document = window.document\n) {\n\n await waitForDocumentLoad(document);\n\n return document.styleSheets;\n\n}\n\nasync function waitForDocumentLoad(document: Document) {\n\n const isLoaded = () => document.readyState === 'complete';\n\n if (isLoaded())\n return;\n\n const { promise, resolve } = Promise.withResolvers();\n const cleanup = new AbortController();\n\n const onReadyStateChange = () => {\n if (isLoaded())\n resolve();\n };\n\n document.addEventListener(\n 'readystatechange',\n onReadyStateChange,\n { signal: cleanup.signal }\n );\n\n await promise;\n\n // remove the listener\n cleanup.abort();\n\n}\n","\n/**\n * Imports a stylesheet from a URL.\n * @param url The URL of the stylesheet to import.\n * @throws\n * - `TypeError`\n * - Thrown if the stylesheet could not be imported.\n * @remarks\n * - `@import` rules won't be resolved in imported stylesheets.\n * [See more.](https://github.com/WICG/construct-stylesheets/issues/119#issuecomment-588352418)\n * - This polyfill exists because [Safari dosen't support](https://caniuse.com/mdn-javascript_statements_import_import_attributes_type_css)\n * CSS Modules (see [this bug](https://bugs.webkit.org/show_bug.cgi?id=227967)).\n * @see\n * - [Creating a CSS module script - HTML Spec](https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-css-module-script)\n * - [import() return value - MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#return_value)\n * @group Sourcing Stylesheets\n */\nexport async function importStyleSheet(url: string) {\n\n const resp = await fetch(url);\n\n if (!resp.ok)\n throw new TypeError(`Failed to fetch dynamically imported module: ${url}`);\n\n const respText = await resp.text();\n\n const styleSheet = new CSSStyleSheet();\n styleSheet.replaceSync(respText);\n\n return styleSheet;\n\n}\n","\n/**\n * A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @see\n * [Processing a keyframes argument - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument)\n * @group Defining Animations\n */\nexport type KeyframeArgument = Keyframe[] | PropertyIndexedKeyframes;\n\n/**\n * Provides a more convenient way to define animations than is offered natively.\n * @see\n * [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * @group Defining Animations\n */\nexport class KeyframeEffectParameters {\n\n keyframes: KeyframeArgument;\n options: KeyframeEffectOptions;\n\n /**\n * @param obj\n * @param obj.keyframes A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @param obj.options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n */\n constructor({ keyframes, options = {} }: {\n keyframes: KeyframeArgument,\n options?: number | KeyframeEffectOptions\n }) {\n\n this.keyframes = keyframes;\n this.options = parseOptionsArg(options);\n\n }\n\n /**\n * @param obj\n * @param obj.target An element to attach the animation to.\n * @param obj.options Additional keyframe effect options. Can override existing keys.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n * @param obj.timeline The timeline with which to associate the animation.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Animation/Animation#timeline)\n * @see\n * - [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * - [The Animation interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-animation-interface)\n */\n toAnimation({ target, options: additionalOptions = {}, timeline = document.timeline }: {\n target: Element | null,\n options?: number | KeyframeEffectOptions,\n timeline?: AnimationTimeline | null\n }): Animation {\n\n const parsedAdditionalOptions = parseOptionsArg(additionalOptions);\n\n // override existing option keys with additional options\n const options: KeyframeEffectOptions = {\n ...this.options,\n ...parsedAdditionalOptions\n };\n\n\n const keyframeEffect = new KeyframeEffect(\n target,\n this.keyframes,\n options\n );\n\n const animation = new Animation(\n keyframeEffect,\n timeline\n );\n\n return animation;\n\n }\n\n}\n\n/**\n * @see\n * - https://drafts.csswg.org/web-animations-1/#dom-keyframeeffect-keyframeeffect-target-keyframes-options-options\n * - https://drafts.csswg.org/web-animations-1/#dom-effecttiming-duration\n */\nfunction parseOptionsArg(optionsArg: number | KeyframeEffectOptions) {\n if (typeof optionsArg === 'number')\n return { duration: optionsArg };\n return optionsArg;\n}\n","\nimport { KeyframeEffectParameters } from '../../KeyframeEffectParameters';\n\n\n/**\n * Web Animations API keyframes converted with the factory functions.\n * \n * Call {@linkcode toKeyframeEffect} to create an animation from them.\n * @group Data Types\n */\nexport class ConvertedKeyframes {\n\n keyframes: Keyframe[];\n\n constructor(keyframes: Keyframe[]) {\n this.keyframes = keyframes;\n }\n\n /**\n * @param options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n *\n * Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole\n * animation at once, on top of each keyframe's easing.\n */\n toKeyframeEffect(\n options: number | KeyframeEffectOptions | null\n ) {\n\n const keyframeEffect = new KeyframeEffectParameters({\n keyframes: this.keyframes,\n // convert (required) nullable to optional\n options: options ?? undefined\n });\n\n return keyframeEffect;\n\n }\n\n}\n\n\n/**\n * Maps CSS keyframes rule names to their converted Web Animations API keyframes.\n * @group Data Types\n */\nexport type ConvertedKeyframesRules = Map;\n","\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\n\n\nconst CHARS = {\n PERCENT_SIGN: '%',\n COMMA: ',',\n HYPHEN_MINUS: '-',\n DOUBLE_HYPHEN_MINUS: '--',\n WEBKIT_PREFIX: '-webkit-'\n} as const;\n\n/** https://drafts.csswg.org/css-animations/#animation-timing-function */\nconst TIMING_FUNCTION_PROPERTY = 'animation-timing-function';\nconst DEFAULT_TIMING_FUNCTION = 'ease';\n\n\n/**\n * Converts a CSS keyframes rule to Web Animations API keyframes.\n * @param keyframesRule The rule to convert.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertKeyframesRule(\n keyframesRule: CSSKeyframesRule\n): ConvertedKeyframes {\n\n const keyframes = Array.from(keyframesRule);\n\n // we `flatMap` as keyframes can be conjoined, eg. `0%, 100%`\n // and we have to split them for the Web Animations API's format\n // see: https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext\n const parsedKeyframes = keyframes.flatMap(keyframe =>\n parseKeyText(keyframe.keyText).map(percent =>\n parseKeyframe({ keyframe, percent })\n )\n );\n\n // sort the keyframes in place by escalating offset\n // (this is required to avoid a TypeError,\n // see: https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument).\n // note: the `!` are safe: these are keyframes created by\n // us, which always have an offset.\n parsedKeyframes.sort((a, b) => a.offset! - b.offset!);\n\n return new ConvertedKeyframes(parsedKeyframes);\n\n}\n\nfunction parseKeyframe({ keyframe, percent }: {\n keyframe: CSSKeyframeRule,\n percent: number\n}) {\n\n const offset = percent / 100;\n\n const parsedProperties = parseKeyframeProperties(keyframe.style);\n \n // a CSS keyframe's timing function eases the segment up to the next keyframe,\n // like a Web Animations API keyframe's `easing`.\n // keyframes without one use the animation's timing function, which is set on\n // the animated element, not in the rule, so we use its initial value, `ease`\n // (a Web Animations API keyframe's `easing` defaults to `linear`).\n // see: https://drafts.csswg.org/css-animations/#timing-functions\n let easing = keyframe.style.getPropertyValue(TIMING_FUNCTION_PROPERTY);\n if (easing === '')\n easing = DEFAULT_TIMING_FUNCTION;\n\n const parsedKeyframe: Keyframe = {\n ...parsedProperties,\n offset,\n easing\n };\n\n return parsedKeyframe;\n\n}\n\n/** https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument */\ntype KeyframeProperties = { [propertyName: string]: string };\n\nfunction parseKeyframeProperties(style: CSSStyleDeclaration) {\n\n const parsedProperties: KeyframeProperties = {};\n\n for (const propertyName of style) {\n\n // converted to the keyframe's `easing`, in `parseKeyframe`\n if (propertyName === TIMING_FUNCTION_PROPERTY)\n continue;\n\n /// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/getPropertyValue\n const propertyValue = style.getPropertyValue(propertyName);\n\n /// https://drafts.csswg.org/web-animations-1/#ref-for-animation-property-name-to-idl-attribute-name%E2%91%A0\n const attributeName = animationPropertyNameToIDLAttributeName(\n propertyName\n );\n\n parsedProperties[attributeName] = propertyValue;\n\n }\n\n return parsedProperties;\n\n}\n\n/** https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext */\nfunction parseKeyText(keyText: string) {\n\n const percentages = keyText.split(CHARS.COMMA);\n\n // we need to trim `percent`, as Blink\n // returns spaced keyText percentages (e.g. `1%, 2%`)\n const parsePercent = (percent: string) => Number(\n removeSuffix(percent.trim(), CHARS.PERCENT_SIGN)\n );\n\n return percentages.map(\n percent => parsePercent(percent)\n );\n\n}\n\n\n/** https://drafts.csswg.org/web-animations-1/#animation-property-name-to-idl-attribute-name */\nfunction animationPropertyNameToIDLAttributeName(property: string) {\n\n if (isCustomPropertyName(property)) return property;\n\n if (property === 'float') return 'cssFloat';\n\n if (property === 'offset') return 'cssOffset';\n\n // https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2\n const lowercaseFirst = isWebkitCasedAttribute(property);\n\n return cssPropertyToIDLAttribute(property, lowercaseFirst);\n\n}\n\n/** https://drafts.csswg.org/cssom/#css-property-to-idl-attribute */\nfunction cssPropertyToIDLAttribute(property: string, lowercaseFirst: boolean = false) {\n\n let output = '';\n let uppercaseNext = false;\n\n if (lowercaseFirst)\n property = property.slice(1);\n\n for (const c of property) {\n\n if (c === CHARS.HYPHEN_MINUS) {\n\n uppercaseNext = true;\n\n } else if (uppercaseNext) {\n\n uppercaseNext = false;\n\n output += c.toUpperCase();\n\n } else {\n\n output += c;\n\n }\n\n }\n\n return output;\n\n}\n\n/** https://drafts.csswg.org/css-variables-2/#typedef-custom-property-name */\nfunction isCustomPropertyName(property: string) {\n return property.startsWith(CHARS.DOUBLE_HYPHEN_MINUS) &&\n property !== CHARS.DOUBLE_HYPHEN_MINUS;\n}\n\n/** https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2 */\nfunction isWebkitCasedAttribute(property: string) {\n return property.startsWith(CHARS.WEBKIT_PREFIX);\n}\n\n\nfunction removeSuffix(value: string, suffix: string) {\n return value.slice(0, -suffix.length);\n}\n","\n/**\n * Checks whether a stylesheet's rules can be read.\n *\n * Reading `cssRules` throws a `SecurityError` when the stylesheet\n * isn't origin-clean, e.g. a cross-origin `` loaded without CORS.\n * Browsers differ on which stylesheets qualify (Safari 17 also treats\n * `data:` URL stylesheets in sandboxed iframes as cross-origin),\n * so we test for access instead of comparing origins.\n * @see https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssrules\n */\nexport function isStyleSheetAccessible(styleSheet: CSSStyleSheet) {\n\n try {\n styleSheet.cssRules;\n return true;\n } catch (error) {\n if (error instanceof DOMException && error.name === 'SecurityError')\n return false;\n throw error;\n }\n\n}\n","\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Converts a CSS keyframes rule from a stylesheet (or stylesheet list)\n * into Web Animations API keyframes.\n * @param obj\n * @param obj.of The name of the `@keyframes` rule to get keyframes from.\n * @param obj.in The stylesheet or stylesheet list where the rule resides.\n * @throws\n * - `TypeError`\n * - Thrown if keyframes rule name is not a string.\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the name, the last one is used, like in CSS.\n * - When searching a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertStyleSheetKeyframes({ of: ruleName, in: source }: {\n of: string,\n in: CSSStyleSheetSource\n}): ConvertedKeyframes | undefined {\n\n if (typeof ruleName !== 'string')\n throw new TypeError(`Keyframes rule name must be a string.`);\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertStyleSheetKeyframesInStyleSheetList({\n of: ruleName,\n styleSheetList: source\n });\n case source instanceof CSSStyleSheet:\n return convertStyleSheetKeyframesInStyleSheet({\n of: ruleName,\n styleSheet: source\n });\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheetList({ of: ruleName, styleSheetList }: {\n of: string,\n styleSheetList: StyleSheetList\n}) {\n\n const foundRules = Array.from(styleSheetList)\n .filter(isStyleSheetAccessible)\n .map(styleSheet => findKeyframesRuleInStyleSheet({ ruleName, styleSheet }))\n .filter(rule => rule !== undefined);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const foundRule = foundRules.at(-1);\n if (foundRule === undefined)\n return\n\n return convertKeyframesRule(foundRule);\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheet({ of: ruleName, styleSheet }: {\n of: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const rule = findKeyframesRuleInStyleSheet({ ruleName, styleSheet });\n\n if (rule === undefined)\n return;\n\n return convertKeyframesRule(rule);\n\n}\n\nfunction findKeyframesRuleInStyleSheet({ ruleName, styleSheet }: {\n ruleName: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const cssRules = Array.from(styleSheet.cssRules);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const rule = cssRules.findLast((rule): rule is CSSKeyframesRule =>\n rule instanceof CSSKeyframesRule &&\n rule.name === ruleName\n );\n\n return rule;\n\n}\n","\nimport type { ConvertedKeyframesRules } from '../data-types/ConvertedKeyframes';\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Gets all the CSS keyframes rules in a stylesheet or stylesheet list,\n * then converts them to Web Animations API keyframes.\n * @param obj\n * @param obj.in The style sheet or style sheet list to get keyframes from.\n * @throws\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the same name, the last one is used, like in CSS.\n * - When reading a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertAllStyleSheetKeyframesRules({ in: source }: {\n in: CSSStyleSheetSource\n}): ConvertedKeyframesRules {\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertAllStyleSheetKeyframesRulesInStyleSheetList(source);\n case source instanceof CSSStyleSheet:\n return convertAllStyleSheetKeyframesRulesInStyleSheet(source);\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheetList(\n styleSheetList: StyleSheetList\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const styleSheet of styleSheetList) {\n\n if (!isStyleSheetAccessible(styleSheet))\n continue;\n\n const rules = convertAllStyleSheetKeyframesRulesInStyleSheet(styleSheet);\n\n for (const [ruleName, keyframesRule] of rules) {\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n keyframesRules.set(ruleName, keyframesRule);\n }\n\n }\n\n return keyframesRules;\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheet(\n styleSheet: CSSStyleSheet\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const rule of styleSheet.cssRules) {\n\n if (!(rule instanceof CSSKeyframesRule))\n continue;\n\n const keyframes = convertKeyframesRule(rule);\n\n keyframesRules.set(rule.name, keyframes);\n\n }\n\n return keyframesRules;\n\n}\n"],"names":["async","getDocumentStyleSheetsOnLoad","document","window","isLoaded","readyState","promise","resolve","Promise","withResolvers","cleanup","AbortController","addEventListener","signal","abort","waitForDocumentLoad","styleSheets","importStyleSheet","url","resp","fetch","ok","TypeError","respText","text","styleSheet","CSSStyleSheet","replaceSync","KeyframeEffectParameters","keyframes","options","constructor","this","parseOptionsArg","toAnimation","target","additionalOptions","timeline","parsedAdditionalOptions","keyframeEffect","KeyframeEffect","Animation","optionsArg","duration","ConvertedKeyframes","toKeyframeEffect","undefined","TIMING_FUNCTION_PROPERTY","convertKeyframesRule","keyframesRule","parsedKeyframes","Array","from","flatMap","keyframe","keyText","percentages","split","map","percent","Number","trim","slice","suffix","parsePercent","parseKeyText","offset","parsedProperties","style","propertyName","propertyValue","getPropertyValue","animationPropertyNameToIDLAttributeName","parseKeyframeProperties","easing","parseKeyframe","sort","a","b","property","startsWith","isCustomPropertyName","lowercaseFirst","isWebkitCasedAttribute","output","uppercaseNext","c","toUpperCase","cssPropertyToIDLAttribute","isStyleSheetAccessible","cssRules","error","DOMException","name","convertStyleSheetKeyframes","of","ruleName","in","source","StyleSheetList","styleSheetList","foundRule","filter","findKeyframesRuleInStyleSheet","rule","at","convertStyleSheetKeyframesInStyleSheetList","convertStyleSheetKeyframesInStyleSheet","findLast","CSSKeyframesRule","convertAllStyleSheetKeyframesRules","keyframesRules","Map","rules","convertAllStyleSheetKeyframesRulesInStyleSheet","set","convertAllStyleSheetKeyframesRulesInStyleSheetList"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"index.min.js","sources":["../src/KeyframesFactory/sourcing-stylesheets/getDocumentStyleSheetsOnLoad.ts","../src/KeyframesFactory/sourcing-stylesheets/importStyleSheet.ts","../src/KeyframeEffectParameters.ts","../src/KeyframesFactory/data-types/ConvertedKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertKeyframesRule.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/isStyleSheetAccessible.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertStyleSheetKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertAllStyleSheetKeyframesRules.ts"],"sourcesContent":["\n/**\n * Gets a document's stylesheets when it loads,\n * or immediately returns them if it's already loaded.\n * @param document The document to get stylesheets from.\n * @group Sourcing Stylesheets\n */\nexport async function getDocumentStyleSheetsOnLoad(\n document = window.document\n) {\n\n await waitForDocumentLoad(document);\n\n return document.styleSheets;\n\n}\n\nasync function waitForDocumentLoad(document: Document) {\n\n const isLoaded = () => document.readyState === 'complete';\n\n if (isLoaded())\n return;\n\n const { promise, resolve } = Promise.withResolvers();\n const cleanup = new AbortController();\n\n const onReadyStateChange = () => {\n if (isLoaded())\n resolve();\n };\n\n document.addEventListener(\n 'readystatechange',\n onReadyStateChange,\n { signal: cleanup.signal }\n );\n\n await promise;\n\n // remove the listener\n cleanup.abort();\n\n}\n","\n/**\n * Imports a stylesheet from a URL.\n * @param url The URL of the stylesheet to import.\n * @throws\n * - `TypeError`\n * - Thrown if the stylesheet could not be imported.\n * @remarks\n * - `@import` rules won't be resolved in imported stylesheets.\n * [See more.](https://github.com/WICG/construct-stylesheets/issues/119#issuecomment-588352418)\n * - This polyfill exists because [Safari dosen't support](https://caniuse.com/mdn-javascript_statements_import_import_attributes_type_css)\n * CSS Modules (see [this bug](https://bugs.webkit.org/show_bug.cgi?id=227967)).\n * @see\n * - [Creating a CSS module script - HTML Spec](https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-css-module-script)\n * - [import() return value - MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#return_value)\n * @group Sourcing Stylesheets\n */\nexport async function importStyleSheet(url: string) {\n\n const resp = await fetch(url);\n\n if (!resp.ok)\n throw new TypeError(`Failed to fetch dynamically imported module: ${url}`);\n\n const respText = await resp.text();\n\n const styleSheet = new CSSStyleSheet();\n styleSheet.replaceSync(respText);\n\n return styleSheet;\n\n}\n","\n/**\n * A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @see\n * [Processing a keyframes argument - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument)\n * @group Defining Animations\n */\nexport type KeyframeArgument = Keyframe[] | PropertyIndexedKeyframes;\n\n/**\n * Provides a more convenient way to define animations than is offered natively.\n * @see\n * [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * @group Defining Animations\n */\nexport class KeyframeEffectParameters {\n\n keyframes: KeyframeArgument;\n options: KeyframeEffectOptions;\n\n /**\n * @param obj\n * @param obj.keyframes A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @param obj.options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n */\n constructor({ keyframes, options = {} }: {\n keyframes: KeyframeArgument,\n options?: number | KeyframeEffectOptions\n }) {\n\n this.keyframes = keyframes;\n this.options = parseOptionsArg(options);\n\n }\n\n /**\n * @param obj\n * @param obj.target An element to attach the animation to.\n * @param obj.options Additional keyframe effect options. Can override existing keys.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n * @param obj.timeline The timeline with which to associate the animation.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Animation/Animation#timeline)\n * @see\n * - [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * - [The Animation interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-animation-interface)\n */\n toAnimation({ target, options: additionalOptions = {}, timeline = document.timeline }: {\n target: Element | null,\n options?: number | KeyframeEffectOptions,\n timeline?: AnimationTimeline | null\n }): Animation {\n\n const parsedAdditionalOptions = parseOptionsArg(additionalOptions);\n\n // override existing option keys with additional options\n const options: KeyframeEffectOptions = {\n ...this.options,\n ...parsedAdditionalOptions\n };\n\n\n const keyframeEffect = new KeyframeEffect(\n target,\n this.keyframes,\n options\n );\n\n const animation = new Animation(\n keyframeEffect,\n timeline\n );\n\n return animation;\n\n }\n\n}\n\n/**\n * @see\n * - https://drafts.csswg.org/web-animations-1/#dom-keyframeeffect-keyframeeffect-target-keyframes-options-options\n * - https://drafts.csswg.org/web-animations-1/#dom-effecttiming-duration\n */\nfunction parseOptionsArg(optionsArg: number | KeyframeEffectOptions) {\n if (typeof optionsArg === 'number')\n return { duration: optionsArg };\n return optionsArg;\n}\n","\nimport { KeyframeEffectParameters } from '../../KeyframeEffectParameters';\n\n\n/**\n * Web Animations API keyframes converted with the factory functions.\n * \n * Call {@linkcode toKeyframeEffect} to create an animation from them.\n * @group Data Types\n */\nexport class ConvertedKeyframes {\n\n keyframes: Keyframe[];\n\n constructor(keyframes: Keyframe[]) {\n this.keyframes = keyframes;\n }\n\n /**\n * @param options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n *\n * Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole\n * animation at once, on top of each keyframe's easing. Instead, set per-keyframe easing.\n */\n toKeyframeEffect(\n options: number | KeyframeEffectOptions | null\n ) {\n\n const keyframeEffect = new KeyframeEffectParameters({\n keyframes: this.keyframes,\n // convert (required) nullable to optional\n options: options ?? undefined\n });\n\n return keyframeEffect;\n\n }\n\n}\n\n\n/**\n * Maps CSS keyframes rule names to their converted Web Animations API keyframes.\n * @group Data Types\n */\nexport type ConvertedKeyframesRules = Map;\n","\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\n\n\nconst CHARS = {\n PERCENT_SIGN: '%',\n COMMA: ',',\n HYPHEN_MINUS: '-',\n DOUBLE_HYPHEN_MINUS: '--',\n WEBKIT_PREFIX: '-webkit-'\n} as const;\n\n/** https://drafts.csswg.org/css-animations/#animation-timing-function */\nconst TIMING_FUNCTION_PROPERTY = 'animation-timing-function';\nconst DEFAULT_TIMING_FUNCTION = 'ease';\n\n\n/**\n * Converts a CSS keyframes rule to Web Animations API keyframes.\n * @param keyframesRule The rule to convert.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertKeyframesRule(\n keyframesRule: CSSKeyframesRule\n): ConvertedKeyframes {\n\n const keyframes = Array.from(keyframesRule);\n\n // we `flatMap` as keyframes can be conjoined, eg. `0%, 100%`\n // and we have to split them for the Web Animations API's format\n // see: https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext\n const parsedKeyframes = keyframes.flatMap(keyframe =>\n parseKeyText(keyframe.keyText).map(percent =>\n parseKeyframe({ keyframe, percent })\n )\n );\n\n // sort the keyframes in place by escalating offset\n // (this is required to avoid a TypeError,\n // see: https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument).\n // note: the `!` are safe: these are keyframes created by\n // us, which always have an offset.\n parsedKeyframes.sort((a, b) => a.offset! - b.offset!);\n\n return new ConvertedKeyframes(parsedKeyframes);\n\n}\n\nfunction parseKeyframe({ keyframe, percent }: {\n keyframe: CSSKeyframeRule,\n percent: number\n}) {\n\n const offset = percent / 100;\n\n const parsedProperties = parseKeyframeProperties(keyframe.style);\n \n // a CSS keyframe's timing function eases the segment up to the next keyframe,\n // like a Web Animations API keyframe's `easing`.\n // keyframes without one use the animation's timing function, which is set on\n // the animated element, not in the rule, so we use its initial value, `ease`\n // (a Web Animations API keyframe's `easing` defaults to `linear`).\n // see: https://drafts.csswg.org/css-animations/#timing-functions\n let easing = keyframe.style.getPropertyValue(TIMING_FUNCTION_PROPERTY);\n if (easing === '')\n easing = DEFAULT_TIMING_FUNCTION;\n\n const parsedKeyframe: Keyframe = {\n ...parsedProperties,\n offset,\n easing\n };\n\n return parsedKeyframe;\n\n}\n\n/** https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument */\ntype KeyframeProperties = { [propertyName: string]: string };\n\nfunction parseKeyframeProperties(style: CSSStyleDeclaration) {\n\n const parsedProperties: KeyframeProperties = {};\n\n for (const propertyName of style) {\n\n // converted to the keyframe's `easing`, in `parseKeyframe`\n if (propertyName === TIMING_FUNCTION_PROPERTY)\n continue;\n\n /// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/getPropertyValue\n const propertyValue = style.getPropertyValue(propertyName);\n\n /// https://drafts.csswg.org/web-animations-1/#ref-for-animation-property-name-to-idl-attribute-name%E2%91%A0\n const attributeName = animationPropertyNameToIDLAttributeName(\n propertyName\n );\n\n parsedProperties[attributeName] = propertyValue;\n\n }\n\n return parsedProperties;\n\n}\n\n/** https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext */\nfunction parseKeyText(keyText: string) {\n\n const percentages = keyText.split(CHARS.COMMA);\n\n // we need to trim `percent`, as Blink\n // returns spaced keyText percentages (e.g. `1%, 2%`)\n const parsePercent = (percent: string) => Number(\n removeSuffix(percent.trim(), CHARS.PERCENT_SIGN)\n );\n\n return percentages.map(\n percent => parsePercent(percent)\n );\n\n}\n\n\n/** https://drafts.csswg.org/web-animations-1/#animation-property-name-to-idl-attribute-name */\nfunction animationPropertyNameToIDLAttributeName(property: string) {\n\n if (isCustomPropertyName(property)) return property;\n\n if (property === 'float') return 'cssFloat';\n\n if (property === 'offset') return 'cssOffset';\n\n // https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2\n const lowercaseFirst = isWebkitCasedAttribute(property);\n\n return cssPropertyToIDLAttribute(property, lowercaseFirst);\n\n}\n\n/** https://drafts.csswg.org/cssom/#css-property-to-idl-attribute */\nfunction cssPropertyToIDLAttribute(property: string, lowercaseFirst: boolean = false) {\n\n let output = '';\n let uppercaseNext = false;\n\n if (lowercaseFirst)\n property = property.slice(1);\n\n for (const c of property) {\n\n if (c === CHARS.HYPHEN_MINUS) {\n\n uppercaseNext = true;\n\n } else if (uppercaseNext) {\n\n uppercaseNext = false;\n\n output += c.toUpperCase();\n\n } else {\n\n output += c;\n\n }\n\n }\n\n return output;\n\n}\n\n/** https://drafts.csswg.org/css-variables-2/#typedef-custom-property-name */\nfunction isCustomPropertyName(property: string) {\n return property.startsWith(CHARS.DOUBLE_HYPHEN_MINUS) &&\n property !== CHARS.DOUBLE_HYPHEN_MINUS;\n}\n\n/** https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2 */\nfunction isWebkitCasedAttribute(property: string) {\n return property.startsWith(CHARS.WEBKIT_PREFIX);\n}\n\n\nfunction removeSuffix(value: string, suffix: string) {\n return value.slice(0, -suffix.length);\n}\n","\n/**\n * Checks whether a stylesheet's rules can be read.\n *\n * Reading `cssRules` throws a `SecurityError` when the stylesheet\n * isn't origin-clean, e.g. a cross-origin `` loaded without CORS.\n * Browsers differ on which stylesheets qualify (Safari 17 also treats\n * `data:` URL stylesheets in sandboxed iframes as cross-origin),\n * so we test for access instead of comparing origins.\n * @see https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssrules\n */\nexport function isStyleSheetAccessible(styleSheet: CSSStyleSheet) {\n\n try {\n styleSheet.cssRules;\n return true;\n } catch (error) {\n if (error instanceof DOMException && error.name === 'SecurityError')\n return false;\n throw error;\n }\n\n}\n","\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Converts a CSS keyframes rule from a stylesheet (or stylesheet list)\n * into Web Animations API keyframes.\n * @param obj\n * @param obj.of The name of the `@keyframes` rule to get keyframes from.\n * @param obj.in The stylesheet or stylesheet list where the rule resides.\n * @throws\n * - `TypeError`\n * - Thrown if keyframes rule name is not a string.\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the name, the last one is used, like in CSS.\n * - When searching a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertStyleSheetKeyframes({ of: ruleName, in: source }: {\n of: string,\n in: CSSStyleSheetSource\n}): ConvertedKeyframes | undefined {\n\n if (typeof ruleName !== 'string')\n throw new TypeError(`Keyframes rule name must be a string.`);\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertStyleSheetKeyframesInStyleSheetList({\n of: ruleName,\n styleSheetList: source\n });\n case source instanceof CSSStyleSheet:\n return convertStyleSheetKeyframesInStyleSheet({\n of: ruleName,\n styleSheet: source\n });\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheetList({ of: ruleName, styleSheetList }: {\n of: string,\n styleSheetList: StyleSheetList\n}) {\n\n const foundRules = Array.from(styleSheetList)\n .filter(isStyleSheetAccessible)\n .map(styleSheet => findKeyframesRuleInStyleSheet({ ruleName, styleSheet }))\n .filter(rule => rule !== undefined);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const foundRule = foundRules.at(-1);\n if (foundRule === undefined)\n return\n\n return convertKeyframesRule(foundRule);\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheet({ of: ruleName, styleSheet }: {\n of: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const rule = findKeyframesRuleInStyleSheet({ ruleName, styleSheet });\n\n if (rule === undefined)\n return;\n\n return convertKeyframesRule(rule);\n\n}\n\nfunction findKeyframesRuleInStyleSheet({ ruleName, styleSheet }: {\n ruleName: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const cssRules = Array.from(styleSheet.cssRules);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const rule = cssRules.findLast((rule): rule is CSSKeyframesRule =>\n rule instanceof CSSKeyframesRule &&\n rule.name === ruleName\n );\n\n return rule;\n\n}\n","\nimport type { ConvertedKeyframesRules } from '../data-types/ConvertedKeyframes';\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Gets all the CSS keyframes rules in a stylesheet or stylesheet list,\n * then converts them to Web Animations API keyframes.\n * @param obj\n * @param obj.in The style sheet or style sheet list to get keyframes from.\n * @throws\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the same name, the last one is used, like in CSS.\n * - When reading a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertAllStyleSheetKeyframesRules({ in: source }: {\n in: CSSStyleSheetSource\n}): ConvertedKeyframesRules {\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertAllStyleSheetKeyframesRulesInStyleSheetList(source);\n case source instanceof CSSStyleSheet:\n return convertAllStyleSheetKeyframesRulesInStyleSheet(source);\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheetList(\n styleSheetList: StyleSheetList\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const styleSheet of styleSheetList) {\n\n if (!isStyleSheetAccessible(styleSheet))\n continue;\n\n const rules = convertAllStyleSheetKeyframesRulesInStyleSheet(styleSheet);\n\n for (const [ruleName, keyframesRule] of rules) {\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n keyframesRules.set(ruleName, keyframesRule);\n }\n\n }\n\n return keyframesRules;\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheet(\n styleSheet: CSSStyleSheet\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const rule of styleSheet.cssRules) {\n\n if (!(rule instanceof CSSKeyframesRule))\n continue;\n\n const keyframes = convertKeyframesRule(rule);\n\n keyframesRules.set(rule.name, keyframes);\n\n }\n\n return keyframesRules;\n\n}\n"],"names":["async","getDocumentStyleSheetsOnLoad","document","window","isLoaded","readyState","promise","resolve","Promise","withResolvers","cleanup","AbortController","addEventListener","signal","abort","waitForDocumentLoad","styleSheets","importStyleSheet","url","resp","fetch","ok","TypeError","respText","text","styleSheet","CSSStyleSheet","replaceSync","KeyframeEffectParameters","keyframes","options","constructor","this","parseOptionsArg","toAnimation","target","additionalOptions","timeline","parsedAdditionalOptions","keyframeEffect","KeyframeEffect","Animation","optionsArg","duration","ConvertedKeyframes","toKeyframeEffect","undefined","TIMING_FUNCTION_PROPERTY","convertKeyframesRule","keyframesRule","parsedKeyframes","Array","from","flatMap","keyframe","keyText","percentages","split","map","percent","Number","trim","slice","suffix","parsePercent","parseKeyText","offset","parsedProperties","style","propertyName","propertyValue","getPropertyValue","animationPropertyNameToIDLAttributeName","parseKeyframeProperties","easing","parseKeyframe","sort","a","b","property","startsWith","isCustomPropertyName","lowercaseFirst","isWebkitCasedAttribute","output","uppercaseNext","c","toUpperCase","cssPropertyToIDLAttribute","isStyleSheetAccessible","cssRules","error","DOMException","name","convertStyleSheetKeyframes","of","ruleName","in","source","StyleSheetList","styleSheetList","foundRule","filter","findKeyframesRuleInStyleSheet","rule","at","convertStyleSheetKeyframesInStyleSheetList","convertStyleSheetKeyframesInStyleSheet","findLast","CSSKeyframesRule","convertAllStyleSheetKeyframesRules","keyframesRules","Map","rules","convertAllStyleSheetKeyframesRulesInStyleSheet","set","convertAllStyleSheetKeyframesRulesInStyleSheetList"],"mappings":"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"}
\ No newline at end of file
diff --git a/docs/docs/get-started.md b/docs/docs/get-started.md
index 24a66f3..eed453c 100644
--- a/docs/docs/get-started.md
+++ b/docs/docs/get-started.md
@@ -5,18 +5,18 @@ title: Get Started
# KeyframeKit
-Unlock full playback control over your CSS animations with JavaScript.
-
[![NPM version][npm-version-src]][npm-version-href]
[![NPM downloads][npm-downloads-src]][npm-downloads-href]
[![Minified size][minified-size-src]][minified-size-href]
-[![CI][ci-src]][ci-href]
+[![Site][site-src]][site-href]
{class=badges}
+Unlock full playback control over your CSS animations with JavaScript.
+
## What is this?
A lightweight TypeScript library that converts CSS `@keyframes` animations into [Web Animations API]-compatible animations, letting you play CSS-defined animations from JavaScript with full playback control and hardware-accelerated performance.\
-[Read more][KeyframeKit article] | [Live Demo]
+[Documentation][KeyframeKit Site] | [Live Demo]
## Installation
@@ -89,7 +89,7 @@ Instead of getting an animation from the document's stylesheets, you can also im
import { importStyleSheet, convertStyleSheetKeyframes } from 'keyframekit';
const styles = await importStyleSheet('./styles.css');
-// note: on Chrome, Edge or Firefox (not Safari), you can just write:
+// note: on Chrome, Edge or Firefox (soon Safari), you can just write:
// import styles from './styles.css' with { type: 'css' };
// get animation keyframes from stylesheet
@@ -147,8 +147,8 @@ attachedAnim.play();
+[KeyframeKit Site]: /
[Web Animations API]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API
-[KeyframeKit article]: https://barhatsor.medium.com/99573ef4738b
[Live Demo]: https://codepen.io/barhatsor/pen/JoRPNmz
[Using the Web Animations API (MDN)]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API
[Imported stylesheet @import issue]: https://github.com/WICG/construct-stylesheets/issues/119#issuecomment-588352418
@@ -158,11 +158,11 @@ attachedAnim.play();
-[npm-version-src]: https://img.shields.io/npm/v/keyframekit.svg
+[npm-version-src]: https://img.shields.io/npm/v/keyframekit.svg?color=6367FF
[npm-version-href]: https://www.npmjs.com/package/keyframekit
-[npm-downloads-src]: https://img.shields.io/npm/d18m/keyframekit
+[npm-downloads-src]: https://img.shields.io/npm/d18m/keyframekit?color=8494FF
[npm-downloads-href]: https://www.npmjs.com/package/keyframekit
-[minified-size-src]: https://img.shields.io/github/size/barhatsor/KeyframeKit/dist/index.min.js
+[minified-size-src]: https://img.shields.io/github/size/barhatsor/KeyframeKit/dist/index.min.js?color=C9BEFF
[minified-size-href]: https://github.com/barhatsor/KeyframeKit/blob/main/dist/index.min.js
-[ci-src]: https://github.com/barhatsor/KeyframeKit/actions/workflows/ci.yml/badge.svg
-[ci-href]: https://github.com/barhatsor/KeyframeKit/actions/workflows/ci.yml
+[site-src]: https://img.shields.io/badge/see_it-live-FFDBFD
+[site-href]: /
diff --git a/docs/docs/public/playground/KeyframeKit/dist/index.d.ts b/docs/docs/public/playground/KeyframeKit/dist/index.d.ts
index eec6c16..24af57e 100644
--- a/docs/docs/public/playground/KeyframeKit/dist/index.d.ts
+++ b/docs/docs/public/playground/KeyframeKit/dist/index.d.ts
@@ -39,7 +39,7 @@ export declare class ConvertedKeyframes {
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)
*
* Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole
- * animation at once, on top of each keyframe's easing.
+ * animation at once, on top of each keyframe's easing. Instead, set per-keyframe easing.
*/
toKeyframeEffect(options: number | KeyframeEffectOptions | null): KeyframeEffectParameters;
}
diff --git a/docs/docs/public/playground/KeyframeKit/dist/index.js b/docs/docs/public/playground/KeyframeKit/dist/index.js
index 19672c7..829ceea 100644
--- a/docs/docs/public/playground/KeyframeKit/dist/index.js
+++ b/docs/docs/public/playground/KeyframeKit/dist/index.js
@@ -124,7 +124,7 @@ class ConvertedKeyframes {
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)
*
* Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole
- * animation at once, on top of each keyframe's easing.
+ * animation at once, on top of each keyframe's easing. Instead, set per-keyframe easing.
*/
toKeyframeEffect(options) {
const keyframeEffect = new KeyframeEffectParameters({
diff --git a/docs/docs/public/playground/KeyframeKit/dist/index.js.map b/docs/docs/public/playground/KeyframeKit/dist/index.js.map
index a0a07f1..4a5fb0c 100644
--- a/docs/docs/public/playground/KeyframeKit/dist/index.js.map
+++ b/docs/docs/public/playground/KeyframeKit/dist/index.js.map
@@ -1 +1 @@
-{"version":3,"file":"index.js","sources":["../src/KeyframesFactory/sourcing-stylesheets/getDocumentStyleSheetsOnLoad.ts","../src/KeyframesFactory/sourcing-stylesheets/importStyleSheet.ts","../src/KeyframeEffectParameters.ts","../src/KeyframesFactory/data-types/ConvertedKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertKeyframesRule.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/isStyleSheetAccessible.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertStyleSheetKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertAllStyleSheetKeyframesRules.ts"],"sourcesContent":["\n/**\n * Gets a document's stylesheets when it loads,\n * or immediately returns them if it's already loaded.\n * @param document The document to get stylesheets from.\n * @group Sourcing Stylesheets\n */\nexport async function getDocumentStyleSheetsOnLoad(\n document = window.document\n) {\n\n await waitForDocumentLoad(document);\n\n return document.styleSheets;\n\n}\n\nasync function waitForDocumentLoad(document: Document) {\n\n const isLoaded = () => document.readyState === 'complete';\n\n if (isLoaded())\n return;\n\n const { promise, resolve } = Promise.withResolvers();\n const cleanup = new AbortController();\n\n const onReadyStateChange = () => {\n if (isLoaded())\n resolve();\n };\n\n document.addEventListener(\n 'readystatechange',\n onReadyStateChange,\n { signal: cleanup.signal }\n );\n\n await promise;\n\n // remove the listener\n cleanup.abort();\n\n}\n","\n/**\n * Imports a stylesheet from a URL.\n * @param url The URL of the stylesheet to import.\n * @throws\n * - `TypeError`\n * - Thrown if the stylesheet could not be imported.\n * @remarks\n * - `@import` rules won't be resolved in imported stylesheets.\n * [See more.](https://github.com/WICG/construct-stylesheets/issues/119#issuecomment-588352418)\n * - This polyfill exists because [Safari dosen't support](https://caniuse.com/mdn-javascript_statements_import_import_attributes_type_css)\n * CSS Modules (see [this bug](https://bugs.webkit.org/show_bug.cgi?id=227967)).\n * @see\n * - [Creating a CSS module script - HTML Spec](https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-css-module-script)\n * - [import() return value - MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#return_value)\n * @group Sourcing Stylesheets\n */\nexport async function importStyleSheet(url: string) {\n\n const resp = await fetch(url);\n\n if (!resp.ok)\n throw new TypeError(`Failed to fetch dynamically imported module: ${url}`);\n\n const respText = await resp.text();\n\n const styleSheet = new CSSStyleSheet();\n styleSheet.replaceSync(respText);\n\n return styleSheet;\n\n}\n","\n/**\n * A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @see\n * [Processing a keyframes argument - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument)\n * @group Defining Animations\n */\nexport type KeyframeArgument = Keyframe[] | PropertyIndexedKeyframes;\n\n/**\n * Provides a more convenient way to define animations than is offered natively.\n * @see\n * [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * @group Defining Animations\n */\nexport class KeyframeEffectParameters {\n\n keyframes: KeyframeArgument;\n options: KeyframeEffectOptions;\n\n /**\n * @param obj\n * @param obj.keyframes A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @param obj.options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n */\n constructor({ keyframes, options = {} }: {\n keyframes: KeyframeArgument,\n options?: number | KeyframeEffectOptions\n }) {\n\n this.keyframes = keyframes;\n this.options = parseOptionsArg(options);\n\n }\n\n /**\n * @param obj\n * @param obj.target An element to attach the animation to.\n * @param obj.options Additional keyframe effect options. Can override existing keys.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n * @param obj.timeline The timeline with which to associate the animation.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Animation/Animation#timeline)\n * @see\n * - [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * - [The Animation interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-animation-interface)\n */\n toAnimation({ target, options: additionalOptions = {}, timeline = document.timeline }: {\n target: Element | null,\n options?: number | KeyframeEffectOptions,\n timeline?: AnimationTimeline | null\n }): Animation {\n\n const parsedAdditionalOptions = parseOptionsArg(additionalOptions);\n\n // override existing option keys with additional options\n const options: KeyframeEffectOptions = {\n ...this.options,\n ...parsedAdditionalOptions\n };\n\n\n const keyframeEffect = new KeyframeEffect(\n target,\n this.keyframes,\n options\n );\n\n const animation = new Animation(\n keyframeEffect,\n timeline\n );\n\n return animation;\n\n }\n\n}\n\n/**\n * @see\n * - https://drafts.csswg.org/web-animations-1/#dom-keyframeeffect-keyframeeffect-target-keyframes-options-options\n * - https://drafts.csswg.org/web-animations-1/#dom-effecttiming-duration\n */\nfunction parseOptionsArg(optionsArg: number | KeyframeEffectOptions) {\n if (typeof optionsArg === 'number')\n return { duration: optionsArg };\n return optionsArg;\n}\n","\nimport { KeyframeEffectParameters } from '../../KeyframeEffectParameters';\n\n\n/**\n * Web Animations API keyframes converted with the factory functions.\n * \n * Call {@linkcode toKeyframeEffect} to create an animation from them.\n * @group Data Types\n */\nexport class ConvertedKeyframes {\n\n keyframes: Keyframe[];\n\n constructor(keyframes: Keyframe[]) {\n this.keyframes = keyframes;\n }\n\n /**\n * @param options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n *\n * Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole\n * animation at once, on top of each keyframe's easing.\n */\n toKeyframeEffect(\n options: number | KeyframeEffectOptions | null\n ) {\n\n const keyframeEffect = new KeyframeEffectParameters({\n keyframes: this.keyframes,\n // convert (required) nullable to optional\n options: options ?? undefined\n });\n\n return keyframeEffect;\n\n }\n\n}\n\n\n/**\n * Maps CSS keyframes rule names to their converted Web Animations API keyframes.\n * @group Data Types\n */\nexport type ConvertedKeyframesRules = Map;\n","\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\n\n\nconst CHARS = {\n PERCENT_SIGN: '%',\n COMMA: ',',\n HYPHEN_MINUS: '-',\n DOUBLE_HYPHEN_MINUS: '--',\n WEBKIT_PREFIX: '-webkit-'\n} as const;\n\n/** https://drafts.csswg.org/css-animations/#animation-timing-function */\nconst TIMING_FUNCTION_PROPERTY = 'animation-timing-function';\nconst DEFAULT_TIMING_FUNCTION = 'ease';\n\n\n/**\n * Converts a CSS keyframes rule to Web Animations API keyframes.\n * @param keyframesRule The rule to convert.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertKeyframesRule(\n keyframesRule: CSSKeyframesRule\n): ConvertedKeyframes {\n\n const keyframes = Array.from(keyframesRule);\n\n // we `flatMap` as keyframes can be conjoined, eg. `0%, 100%`\n // and we have to split them for the Web Animations API's format\n // see: https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext\n const parsedKeyframes = keyframes.flatMap(keyframe =>\n parseKeyText(keyframe.keyText).map(percent =>\n parseKeyframe({ keyframe, percent })\n )\n );\n\n // sort the keyframes in place by escalating offset\n // (this is required to avoid a TypeError,\n // see: https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument).\n // note: the `!` are safe: these are keyframes created by\n // us, which always have an offset.\n parsedKeyframes.sort((a, b) => a.offset! - b.offset!);\n\n return new ConvertedKeyframes(parsedKeyframes);\n\n}\n\nfunction parseKeyframe({ keyframe, percent }: {\n keyframe: CSSKeyframeRule,\n percent: number\n}) {\n\n const offset = percent / 100;\n\n const parsedProperties = parseKeyframeProperties(keyframe.style);\n \n // a CSS keyframe's timing function eases the segment up to the next keyframe,\n // like a Web Animations API keyframe's `easing`.\n // keyframes without one use the animation's timing function, which is set on\n // the animated element, not in the rule, so we use its initial value, `ease`\n // (a Web Animations API keyframe's `easing` defaults to `linear`).\n // see: https://drafts.csswg.org/css-animations/#timing-functions\n let easing = keyframe.style.getPropertyValue(TIMING_FUNCTION_PROPERTY);\n if (easing === '')\n easing = DEFAULT_TIMING_FUNCTION;\n\n const parsedKeyframe: Keyframe = {\n ...parsedProperties,\n offset,\n easing\n };\n\n return parsedKeyframe;\n\n}\n\n/** https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument */\ntype KeyframeProperties = { [propertyName: string]: string };\n\nfunction parseKeyframeProperties(style: CSSStyleDeclaration) {\n\n const parsedProperties: KeyframeProperties = {};\n\n for (const propertyName of style) {\n\n // converted to the keyframe's `easing`, in `parseKeyframe`\n if (propertyName === TIMING_FUNCTION_PROPERTY)\n continue;\n\n /// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/getPropertyValue\n const propertyValue = style.getPropertyValue(propertyName);\n\n /// https://drafts.csswg.org/web-animations-1/#ref-for-animation-property-name-to-idl-attribute-name%E2%91%A0\n const attributeName = animationPropertyNameToIDLAttributeName(\n propertyName\n );\n\n parsedProperties[attributeName] = propertyValue;\n\n }\n\n return parsedProperties;\n\n}\n\n/** https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext */\nfunction parseKeyText(keyText: string) {\n\n const percentages = keyText.split(CHARS.COMMA);\n\n // we need to trim `percent`, as Blink\n // returns spaced keyText percentages (e.g. `1%, 2%`)\n const parsePercent = (percent: string) => Number(\n removeSuffix(percent.trim(), CHARS.PERCENT_SIGN)\n );\n\n return percentages.map(\n percent => parsePercent(percent)\n );\n\n}\n\n\n/** https://drafts.csswg.org/web-animations-1/#animation-property-name-to-idl-attribute-name */\nfunction animationPropertyNameToIDLAttributeName(property: string) {\n\n if (isCustomPropertyName(property)) return property;\n\n if (property === 'float') return 'cssFloat';\n\n if (property === 'offset') return 'cssOffset';\n\n // https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2\n const lowercaseFirst = isWebkitCasedAttribute(property);\n\n return cssPropertyToIDLAttribute(property, lowercaseFirst);\n\n}\n\n/** https://drafts.csswg.org/cssom/#css-property-to-idl-attribute */\nfunction cssPropertyToIDLAttribute(property: string, lowercaseFirst: boolean = false) {\n\n let output = '';\n let uppercaseNext = false;\n\n if (lowercaseFirst)\n property = property.slice(1);\n\n for (const c of property) {\n\n if (c === CHARS.HYPHEN_MINUS) {\n\n uppercaseNext = true;\n\n } else if (uppercaseNext) {\n\n uppercaseNext = false;\n\n output += c.toUpperCase();\n\n } else {\n\n output += c;\n\n }\n\n }\n\n return output;\n\n}\n\n/** https://drafts.csswg.org/css-variables-2/#typedef-custom-property-name */\nfunction isCustomPropertyName(property: string) {\n return property.startsWith(CHARS.DOUBLE_HYPHEN_MINUS) &&\n property !== CHARS.DOUBLE_HYPHEN_MINUS;\n}\n\n/** https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2 */\nfunction isWebkitCasedAttribute(property: string) {\n return property.startsWith(CHARS.WEBKIT_PREFIX);\n}\n\n\nfunction removeSuffix(value: string, suffix: string) {\n return value.slice(0, -suffix.length);\n}\n","\n/**\n * Checks whether a stylesheet's rules can be read.\n *\n * Reading `cssRules` throws a `SecurityError` when the stylesheet\n * isn't origin-clean, e.g. a cross-origin `` loaded without CORS.\n * Browsers differ on which stylesheets qualify (Safari 17 also treats\n * `data:` URL stylesheets in sandboxed iframes as cross-origin),\n * so we test for access instead of comparing origins.\n * @see https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssrules\n */\nexport function isStyleSheetAccessible(styleSheet: CSSStyleSheet) {\n\n try {\n styleSheet.cssRules;\n return true;\n } catch (error) {\n if (error instanceof DOMException && error.name === 'SecurityError')\n return false;\n throw error;\n }\n\n}\n","\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Converts a CSS keyframes rule from a stylesheet (or stylesheet list)\n * into Web Animations API keyframes.\n * @param obj\n * @param obj.of The name of the `@keyframes` rule to get keyframes from.\n * @param obj.in The stylesheet or stylesheet list where the rule resides.\n * @throws\n * - `TypeError`\n * - Thrown if keyframes rule name is not a string.\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the name, the last one is used, like in CSS.\n * - When searching a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertStyleSheetKeyframes({ of: ruleName, in: source }: {\n of: string,\n in: CSSStyleSheetSource\n}): ConvertedKeyframes | undefined {\n\n if (typeof ruleName !== 'string')\n throw new TypeError(`Keyframes rule name must be a string.`);\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertStyleSheetKeyframesInStyleSheetList({\n of: ruleName,\n styleSheetList: source\n });\n case source instanceof CSSStyleSheet:\n return convertStyleSheetKeyframesInStyleSheet({\n of: ruleName,\n styleSheet: source\n });\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheetList({ of: ruleName, styleSheetList }: {\n of: string,\n styleSheetList: StyleSheetList\n}) {\n\n const foundRules = Array.from(styleSheetList)\n .filter(isStyleSheetAccessible)\n .map(styleSheet => findKeyframesRuleInStyleSheet({ ruleName, styleSheet }))\n .filter(rule => rule !== undefined);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const foundRule = foundRules.at(-1);\n if (foundRule === undefined)\n return\n\n return convertKeyframesRule(foundRule);\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheet({ of: ruleName, styleSheet }: {\n of: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const rule = findKeyframesRuleInStyleSheet({ ruleName, styleSheet });\n\n if (rule === undefined)\n return;\n\n return convertKeyframesRule(rule);\n\n}\n\nfunction findKeyframesRuleInStyleSheet({ ruleName, styleSheet }: {\n ruleName: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const cssRules = Array.from(styleSheet.cssRules);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const rule = cssRules.findLast((rule): rule is CSSKeyframesRule =>\n rule instanceof CSSKeyframesRule &&\n rule.name === ruleName\n );\n\n return rule;\n\n}\n","\nimport type { ConvertedKeyframesRules } from '../data-types/ConvertedKeyframes';\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Gets all the CSS keyframes rules in a stylesheet or stylesheet list,\n * then converts them to Web Animations API keyframes.\n * @param obj\n * @param obj.in The style sheet or style sheet list to get keyframes from.\n * @throws\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the same name, the last one is used, like in CSS.\n * - When reading a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertAllStyleSheetKeyframesRules({ in: source }: {\n in: CSSStyleSheetSource\n}): ConvertedKeyframesRules {\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertAllStyleSheetKeyframesRulesInStyleSheetList(source);\n case source instanceof CSSStyleSheet:\n return convertAllStyleSheetKeyframesRulesInStyleSheet(source);\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheetList(\n styleSheetList: StyleSheetList\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const styleSheet of styleSheetList) {\n\n if (!isStyleSheetAccessible(styleSheet))\n continue;\n\n const rules = convertAllStyleSheetKeyframesRulesInStyleSheet(styleSheet);\n\n for (const [ruleName, keyframesRule] of rules) {\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n keyframesRules.set(ruleName, keyframesRule);\n }\n\n }\n\n return keyframesRules;\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheet(\n styleSheet: CSSStyleSheet\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const rule of styleSheet.cssRules) {\n\n if (!(rule instanceof CSSKeyframesRule))\n continue;\n\n const keyframes = convertKeyframesRule(rule);\n\n keyframesRules.set(rule.name, keyframes);\n\n }\n\n return keyframesRules;\n\n}\n"],"names":[],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"index.js","sources":["../src/KeyframesFactory/sourcing-stylesheets/getDocumentStyleSheetsOnLoad.ts","../src/KeyframesFactory/sourcing-stylesheets/importStyleSheet.ts","../src/KeyframeEffectParameters.ts","../src/KeyframesFactory/data-types/ConvertedKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertKeyframesRule.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/isStyleSheetAccessible.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertStyleSheetKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertAllStyleSheetKeyframesRules.ts"],"sourcesContent":["\n/**\n * Gets a document's stylesheets when it loads,\n * or immediately returns them if it's already loaded.\n * @param document The document to get stylesheets from.\n * @group Sourcing Stylesheets\n */\nexport async function getDocumentStyleSheetsOnLoad(\n document = window.document\n) {\n\n await waitForDocumentLoad(document);\n\n return document.styleSheets;\n\n}\n\nasync function waitForDocumentLoad(document: Document) {\n\n const isLoaded = () => document.readyState === 'complete';\n\n if (isLoaded())\n return;\n\n const { promise, resolve } = Promise.withResolvers();\n const cleanup = new AbortController();\n\n const onReadyStateChange = () => {\n if (isLoaded())\n resolve();\n };\n\n document.addEventListener(\n 'readystatechange',\n onReadyStateChange,\n { signal: cleanup.signal }\n );\n\n await promise;\n\n // remove the listener\n cleanup.abort();\n\n}\n","\n/**\n * Imports a stylesheet from a URL.\n * @param url The URL of the stylesheet to import.\n * @throws\n * - `TypeError`\n * - Thrown if the stylesheet could not be imported.\n * @remarks\n * - `@import` rules won't be resolved in imported stylesheets.\n * [See more.](https://github.com/WICG/construct-stylesheets/issues/119#issuecomment-588352418)\n * - This polyfill exists because [Safari dosen't support](https://caniuse.com/mdn-javascript_statements_import_import_attributes_type_css)\n * CSS Modules (see [this bug](https://bugs.webkit.org/show_bug.cgi?id=227967)).\n * @see\n * - [Creating a CSS module script - HTML Spec](https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-css-module-script)\n * - [import() return value - MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#return_value)\n * @group Sourcing Stylesheets\n */\nexport async function importStyleSheet(url: string) {\n\n const resp = await fetch(url);\n\n if (!resp.ok)\n throw new TypeError(`Failed to fetch dynamically imported module: ${url}`);\n\n const respText = await resp.text();\n\n const styleSheet = new CSSStyleSheet();\n styleSheet.replaceSync(respText);\n\n return styleSheet;\n\n}\n","\n/**\n * A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @see\n * [Processing a keyframes argument - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument)\n * @group Defining Animations\n */\nexport type KeyframeArgument = Keyframe[] | PropertyIndexedKeyframes;\n\n/**\n * Provides a more convenient way to define animations than is offered natively.\n * @see\n * [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * @group Defining Animations\n */\nexport class KeyframeEffectParameters {\n\n keyframes: KeyframeArgument;\n options: KeyframeEffectOptions;\n\n /**\n * @param obj\n * @param obj.keyframes A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @param obj.options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n */\n constructor({ keyframes, options = {} }: {\n keyframes: KeyframeArgument,\n options?: number | KeyframeEffectOptions\n }) {\n\n this.keyframes = keyframes;\n this.options = parseOptionsArg(options);\n\n }\n\n /**\n * @param obj\n * @param obj.target An element to attach the animation to.\n * @param obj.options Additional keyframe effect options. Can override existing keys.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n * @param obj.timeline The timeline with which to associate the animation.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Animation/Animation#timeline)\n * @see\n * - [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * - [The Animation interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-animation-interface)\n */\n toAnimation({ target, options: additionalOptions = {}, timeline = document.timeline }: {\n target: Element | null,\n options?: number | KeyframeEffectOptions,\n timeline?: AnimationTimeline | null\n }): Animation {\n\n const parsedAdditionalOptions = parseOptionsArg(additionalOptions);\n\n // override existing option keys with additional options\n const options: KeyframeEffectOptions = {\n ...this.options,\n ...parsedAdditionalOptions\n };\n\n\n const keyframeEffect = new KeyframeEffect(\n target,\n this.keyframes,\n options\n );\n\n const animation = new Animation(\n keyframeEffect,\n timeline\n );\n\n return animation;\n\n }\n\n}\n\n/**\n * @see\n * - https://drafts.csswg.org/web-animations-1/#dom-keyframeeffect-keyframeeffect-target-keyframes-options-options\n * - https://drafts.csswg.org/web-animations-1/#dom-effecttiming-duration\n */\nfunction parseOptionsArg(optionsArg: number | KeyframeEffectOptions) {\n if (typeof optionsArg === 'number')\n return { duration: optionsArg };\n return optionsArg;\n}\n","\nimport { KeyframeEffectParameters } from '../../KeyframeEffectParameters';\n\n\n/**\n * Web Animations API keyframes converted with the factory functions.\n * \n * Call {@linkcode toKeyframeEffect} to create an animation from them.\n * @group Data Types\n */\nexport class ConvertedKeyframes {\n\n keyframes: Keyframe[];\n\n constructor(keyframes: Keyframe[]) {\n this.keyframes = keyframes;\n }\n\n /**\n * @param options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n *\n * Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole\n * animation at once, on top of each keyframe's easing. Instead, set per-keyframe easing.\n */\n toKeyframeEffect(\n options: number | KeyframeEffectOptions | null\n ) {\n\n const keyframeEffect = new KeyframeEffectParameters({\n keyframes: this.keyframes,\n // convert (required) nullable to optional\n options: options ?? undefined\n });\n\n return keyframeEffect;\n\n }\n\n}\n\n\n/**\n * Maps CSS keyframes rule names to their converted Web Animations API keyframes.\n * @group Data Types\n */\nexport type ConvertedKeyframesRules = Map;\n","\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\n\n\nconst CHARS = {\n PERCENT_SIGN: '%',\n COMMA: ',',\n HYPHEN_MINUS: '-',\n DOUBLE_HYPHEN_MINUS: '--',\n WEBKIT_PREFIX: '-webkit-'\n} as const;\n\n/** https://drafts.csswg.org/css-animations/#animation-timing-function */\nconst TIMING_FUNCTION_PROPERTY = 'animation-timing-function';\nconst DEFAULT_TIMING_FUNCTION = 'ease';\n\n\n/**\n * Converts a CSS keyframes rule to Web Animations API keyframes.\n * @param keyframesRule The rule to convert.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertKeyframesRule(\n keyframesRule: CSSKeyframesRule\n): ConvertedKeyframes {\n\n const keyframes = Array.from(keyframesRule);\n\n // we `flatMap` as keyframes can be conjoined, eg. `0%, 100%`\n // and we have to split them for the Web Animations API's format\n // see: https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext\n const parsedKeyframes = keyframes.flatMap(keyframe =>\n parseKeyText(keyframe.keyText).map(percent =>\n parseKeyframe({ keyframe, percent })\n )\n );\n\n // sort the keyframes in place by escalating offset\n // (this is required to avoid a TypeError,\n // see: https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument).\n // note: the `!` are safe: these are keyframes created by\n // us, which always have an offset.\n parsedKeyframes.sort((a, b) => a.offset! - b.offset!);\n\n return new ConvertedKeyframes(parsedKeyframes);\n\n}\n\nfunction parseKeyframe({ keyframe, percent }: {\n keyframe: CSSKeyframeRule,\n percent: number\n}) {\n\n const offset = percent / 100;\n\n const parsedProperties = parseKeyframeProperties(keyframe.style);\n \n // a CSS keyframe's timing function eases the segment up to the next keyframe,\n // like a Web Animations API keyframe's `easing`.\n // keyframes without one use the animation's timing function, which is set on\n // the animated element, not in the rule, so we use its initial value, `ease`\n // (a Web Animations API keyframe's `easing` defaults to `linear`).\n // see: https://drafts.csswg.org/css-animations/#timing-functions\n let easing = keyframe.style.getPropertyValue(TIMING_FUNCTION_PROPERTY);\n if (easing === '')\n easing = DEFAULT_TIMING_FUNCTION;\n\n const parsedKeyframe: Keyframe = {\n ...parsedProperties,\n offset,\n easing\n };\n\n return parsedKeyframe;\n\n}\n\n/** https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument */\ntype KeyframeProperties = { [propertyName: string]: string };\n\nfunction parseKeyframeProperties(style: CSSStyleDeclaration) {\n\n const parsedProperties: KeyframeProperties = {};\n\n for (const propertyName of style) {\n\n // converted to the keyframe's `easing`, in `parseKeyframe`\n if (propertyName === TIMING_FUNCTION_PROPERTY)\n continue;\n\n /// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/getPropertyValue\n const propertyValue = style.getPropertyValue(propertyName);\n\n /// https://drafts.csswg.org/web-animations-1/#ref-for-animation-property-name-to-idl-attribute-name%E2%91%A0\n const attributeName = animationPropertyNameToIDLAttributeName(\n propertyName\n );\n\n parsedProperties[attributeName] = propertyValue;\n\n }\n\n return parsedProperties;\n\n}\n\n/** https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext */\nfunction parseKeyText(keyText: string) {\n\n const percentages = keyText.split(CHARS.COMMA);\n\n // we need to trim `percent`, as Blink\n // returns spaced keyText percentages (e.g. `1%, 2%`)\n const parsePercent = (percent: string) => Number(\n removeSuffix(percent.trim(), CHARS.PERCENT_SIGN)\n );\n\n return percentages.map(\n percent => parsePercent(percent)\n );\n\n}\n\n\n/** https://drafts.csswg.org/web-animations-1/#animation-property-name-to-idl-attribute-name */\nfunction animationPropertyNameToIDLAttributeName(property: string) {\n\n if (isCustomPropertyName(property)) return property;\n\n if (property === 'float') return 'cssFloat';\n\n if (property === 'offset') return 'cssOffset';\n\n // https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2\n const lowercaseFirst = isWebkitCasedAttribute(property);\n\n return cssPropertyToIDLAttribute(property, lowercaseFirst);\n\n}\n\n/** https://drafts.csswg.org/cssom/#css-property-to-idl-attribute */\nfunction cssPropertyToIDLAttribute(property: string, lowercaseFirst: boolean = false) {\n\n let output = '';\n let uppercaseNext = false;\n\n if (lowercaseFirst)\n property = property.slice(1);\n\n for (const c of property) {\n\n if (c === CHARS.HYPHEN_MINUS) {\n\n uppercaseNext = true;\n\n } else if (uppercaseNext) {\n\n uppercaseNext = false;\n\n output += c.toUpperCase();\n\n } else {\n\n output += c;\n\n }\n\n }\n\n return output;\n\n}\n\n/** https://drafts.csswg.org/css-variables-2/#typedef-custom-property-name */\nfunction isCustomPropertyName(property: string) {\n return property.startsWith(CHARS.DOUBLE_HYPHEN_MINUS) &&\n property !== CHARS.DOUBLE_HYPHEN_MINUS;\n}\n\n/** https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2 */\nfunction isWebkitCasedAttribute(property: string) {\n return property.startsWith(CHARS.WEBKIT_PREFIX);\n}\n\n\nfunction removeSuffix(value: string, suffix: string) {\n return value.slice(0, -suffix.length);\n}\n","\n/**\n * Checks whether a stylesheet's rules can be read.\n *\n * Reading `cssRules` throws a `SecurityError` when the stylesheet\n * isn't origin-clean, e.g. a cross-origin `` loaded without CORS.\n * Browsers differ on which stylesheets qualify (Safari 17 also treats\n * `data:` URL stylesheets in sandboxed iframes as cross-origin),\n * so we test for access instead of comparing origins.\n * @see https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssrules\n */\nexport function isStyleSheetAccessible(styleSheet: CSSStyleSheet) {\n\n try {\n styleSheet.cssRules;\n return true;\n } catch (error) {\n if (error instanceof DOMException && error.name === 'SecurityError')\n return false;\n throw error;\n }\n\n}\n","\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Converts a CSS keyframes rule from a stylesheet (or stylesheet list)\n * into Web Animations API keyframes.\n * @param obj\n * @param obj.of The name of the `@keyframes` rule to get keyframes from.\n * @param obj.in The stylesheet or stylesheet list where the rule resides.\n * @throws\n * - `TypeError`\n * - Thrown if keyframes rule name is not a string.\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the name, the last one is used, like in CSS.\n * - When searching a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertStyleSheetKeyframes({ of: ruleName, in: source }: {\n of: string,\n in: CSSStyleSheetSource\n}): ConvertedKeyframes | undefined {\n\n if (typeof ruleName !== 'string')\n throw new TypeError(`Keyframes rule name must be a string.`);\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertStyleSheetKeyframesInStyleSheetList({\n of: ruleName,\n styleSheetList: source\n });\n case source instanceof CSSStyleSheet:\n return convertStyleSheetKeyframesInStyleSheet({\n of: ruleName,\n styleSheet: source\n });\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheetList({ of: ruleName, styleSheetList }: {\n of: string,\n styleSheetList: StyleSheetList\n}) {\n\n const foundRules = Array.from(styleSheetList)\n .filter(isStyleSheetAccessible)\n .map(styleSheet => findKeyframesRuleInStyleSheet({ ruleName, styleSheet }))\n .filter(rule => rule !== undefined);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const foundRule = foundRules.at(-1);\n if (foundRule === undefined)\n return\n\n return convertKeyframesRule(foundRule);\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheet({ of: ruleName, styleSheet }: {\n of: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const rule = findKeyframesRuleInStyleSheet({ ruleName, styleSheet });\n\n if (rule === undefined)\n return;\n\n return convertKeyframesRule(rule);\n\n}\n\nfunction findKeyframesRuleInStyleSheet({ ruleName, styleSheet }: {\n ruleName: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const cssRules = Array.from(styleSheet.cssRules);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const rule = cssRules.findLast((rule): rule is CSSKeyframesRule =>\n rule instanceof CSSKeyframesRule &&\n rule.name === ruleName\n );\n\n return rule;\n\n}\n","\nimport type { ConvertedKeyframesRules } from '../data-types/ConvertedKeyframes';\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Gets all the CSS keyframes rules in a stylesheet or stylesheet list,\n * then converts them to Web Animations API keyframes.\n * @param obj\n * @param obj.in The style sheet or style sheet list to get keyframes from.\n * @throws\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the same name, the last one is used, like in CSS.\n * - When reading a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertAllStyleSheetKeyframesRules({ in: source }: {\n in: CSSStyleSheetSource\n}): ConvertedKeyframesRules {\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertAllStyleSheetKeyframesRulesInStyleSheetList(source);\n case source instanceof CSSStyleSheet:\n return convertAllStyleSheetKeyframesRulesInStyleSheet(source);\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheetList(\n styleSheetList: StyleSheetList\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const styleSheet of styleSheetList) {\n\n if (!isStyleSheetAccessible(styleSheet))\n continue;\n\n const rules = convertAllStyleSheetKeyframesRulesInStyleSheet(styleSheet);\n\n for (const [ruleName, keyframesRule] of rules) {\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n keyframesRules.set(ruleName, keyframesRule);\n }\n\n }\n\n return keyframesRules;\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheet(\n styleSheet: CSSStyleSheet\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const rule of styleSheet.cssRules) {\n\n if (!(rule instanceof CSSKeyframesRule))\n continue;\n\n const keyframes = convertKeyframesRule(rule);\n\n keyframesRules.set(rule.name, keyframes);\n\n }\n\n return keyframesRules;\n\n}\n"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/docs/docs/public/playground/KeyframeKit/dist/index.min.js.map b/docs/docs/public/playground/KeyframeKit/dist/index.min.js.map
index 21bc8e1..95cc5a0 100644
--- a/docs/docs/public/playground/KeyframeKit/dist/index.min.js.map
+++ b/docs/docs/public/playground/KeyframeKit/dist/index.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"index.min.js","sources":["../src/KeyframesFactory/sourcing-stylesheets/getDocumentStyleSheetsOnLoad.ts","../src/KeyframesFactory/sourcing-stylesheets/importStyleSheet.ts","../src/KeyframeEffectParameters.ts","../src/KeyframesFactory/data-types/ConvertedKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertKeyframesRule.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/isStyleSheetAccessible.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertStyleSheetKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertAllStyleSheetKeyframesRules.ts"],"sourcesContent":["\n/**\n * Gets a document's stylesheets when it loads,\n * or immediately returns them if it's already loaded.\n * @param document The document to get stylesheets from.\n * @group Sourcing Stylesheets\n */\nexport async function getDocumentStyleSheetsOnLoad(\n document = window.document\n) {\n\n await waitForDocumentLoad(document);\n\n return document.styleSheets;\n\n}\n\nasync function waitForDocumentLoad(document: Document) {\n\n const isLoaded = () => document.readyState === 'complete';\n\n if (isLoaded())\n return;\n\n const { promise, resolve } = Promise.withResolvers();\n const cleanup = new AbortController();\n\n const onReadyStateChange = () => {\n if (isLoaded())\n resolve();\n };\n\n document.addEventListener(\n 'readystatechange',\n onReadyStateChange,\n { signal: cleanup.signal }\n );\n\n await promise;\n\n // remove the listener\n cleanup.abort();\n\n}\n","\n/**\n * Imports a stylesheet from a URL.\n * @param url The URL of the stylesheet to import.\n * @throws\n * - `TypeError`\n * - Thrown if the stylesheet could not be imported.\n * @remarks\n * - `@import` rules won't be resolved in imported stylesheets.\n * [See more.](https://github.com/WICG/construct-stylesheets/issues/119#issuecomment-588352418)\n * - This polyfill exists because [Safari dosen't support](https://caniuse.com/mdn-javascript_statements_import_import_attributes_type_css)\n * CSS Modules (see [this bug](https://bugs.webkit.org/show_bug.cgi?id=227967)).\n * @see\n * - [Creating a CSS module script - HTML Spec](https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-css-module-script)\n * - [import() return value - MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#return_value)\n * @group Sourcing Stylesheets\n */\nexport async function importStyleSheet(url: string) {\n\n const resp = await fetch(url);\n\n if (!resp.ok)\n throw new TypeError(`Failed to fetch dynamically imported module: ${url}`);\n\n const respText = await resp.text();\n\n const styleSheet = new CSSStyleSheet();\n styleSheet.replaceSync(respText);\n\n return styleSheet;\n\n}\n","\n/**\n * A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @see\n * [Processing a keyframes argument - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument)\n * @group Defining Animations\n */\nexport type KeyframeArgument = Keyframe[] | PropertyIndexedKeyframes;\n\n/**\n * Provides a more convenient way to define animations than is offered natively.\n * @see\n * [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * @group Defining Animations\n */\nexport class KeyframeEffectParameters {\n\n keyframes: KeyframeArgument;\n options: KeyframeEffectOptions;\n\n /**\n * @param obj\n * @param obj.keyframes A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @param obj.options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n */\n constructor({ keyframes, options = {} }: {\n keyframes: KeyframeArgument,\n options?: number | KeyframeEffectOptions\n }) {\n\n this.keyframes = keyframes;\n this.options = parseOptionsArg(options);\n\n }\n\n /**\n * @param obj\n * @param obj.target An element to attach the animation to.\n * @param obj.options Additional keyframe effect options. Can override existing keys.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n * @param obj.timeline The timeline with which to associate the animation.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Animation/Animation#timeline)\n * @see\n * - [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * - [The Animation interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-animation-interface)\n */\n toAnimation({ target, options: additionalOptions = {}, timeline = document.timeline }: {\n target: Element | null,\n options?: number | KeyframeEffectOptions,\n timeline?: AnimationTimeline | null\n }): Animation {\n\n const parsedAdditionalOptions = parseOptionsArg(additionalOptions);\n\n // override existing option keys with additional options\n const options: KeyframeEffectOptions = {\n ...this.options,\n ...parsedAdditionalOptions\n };\n\n\n const keyframeEffect = new KeyframeEffect(\n target,\n this.keyframes,\n options\n );\n\n const animation = new Animation(\n keyframeEffect,\n timeline\n );\n\n return animation;\n\n }\n\n}\n\n/**\n * @see\n * - https://drafts.csswg.org/web-animations-1/#dom-keyframeeffect-keyframeeffect-target-keyframes-options-options\n * - https://drafts.csswg.org/web-animations-1/#dom-effecttiming-duration\n */\nfunction parseOptionsArg(optionsArg: number | KeyframeEffectOptions) {\n if (typeof optionsArg === 'number')\n return { duration: optionsArg };\n return optionsArg;\n}\n","\nimport { KeyframeEffectParameters } from '../../KeyframeEffectParameters';\n\n\n/**\n * Web Animations API keyframes converted with the factory functions.\n * \n * Call {@linkcode toKeyframeEffect} to create an animation from them.\n * @group Data Types\n */\nexport class ConvertedKeyframes {\n\n keyframes: Keyframe[];\n\n constructor(keyframes: Keyframe[]) {\n this.keyframes = keyframes;\n }\n\n /**\n * @param options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n *\n * Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole\n * animation at once, on top of each keyframe's easing.\n */\n toKeyframeEffect(\n options: number | KeyframeEffectOptions | null\n ) {\n\n const keyframeEffect = new KeyframeEffectParameters({\n keyframes: this.keyframes,\n // convert (required) nullable to optional\n options: options ?? undefined\n });\n\n return keyframeEffect;\n\n }\n\n}\n\n\n/**\n * Maps CSS keyframes rule names to their converted Web Animations API keyframes.\n * @group Data Types\n */\nexport type ConvertedKeyframesRules = Map;\n","\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\n\n\nconst CHARS = {\n PERCENT_SIGN: '%',\n COMMA: ',',\n HYPHEN_MINUS: '-',\n DOUBLE_HYPHEN_MINUS: '--',\n WEBKIT_PREFIX: '-webkit-'\n} as const;\n\n/** https://drafts.csswg.org/css-animations/#animation-timing-function */\nconst TIMING_FUNCTION_PROPERTY = 'animation-timing-function';\nconst DEFAULT_TIMING_FUNCTION = 'ease';\n\n\n/**\n * Converts a CSS keyframes rule to Web Animations API keyframes.\n * @param keyframesRule The rule to convert.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertKeyframesRule(\n keyframesRule: CSSKeyframesRule\n): ConvertedKeyframes {\n\n const keyframes = Array.from(keyframesRule);\n\n // we `flatMap` as keyframes can be conjoined, eg. `0%, 100%`\n // and we have to split them for the Web Animations API's format\n // see: https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext\n const parsedKeyframes = keyframes.flatMap(keyframe =>\n parseKeyText(keyframe.keyText).map(percent =>\n parseKeyframe({ keyframe, percent })\n )\n );\n\n // sort the keyframes in place by escalating offset\n // (this is required to avoid a TypeError,\n // see: https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument).\n // note: the `!` are safe: these are keyframes created by\n // us, which always have an offset.\n parsedKeyframes.sort((a, b) => a.offset! - b.offset!);\n\n return new ConvertedKeyframes(parsedKeyframes);\n\n}\n\nfunction parseKeyframe({ keyframe, percent }: {\n keyframe: CSSKeyframeRule,\n percent: number\n}) {\n\n const offset = percent / 100;\n\n const parsedProperties = parseKeyframeProperties(keyframe.style);\n \n // a CSS keyframe's timing function eases the segment up to the next keyframe,\n // like a Web Animations API keyframe's `easing`.\n // keyframes without one use the animation's timing function, which is set on\n // the animated element, not in the rule, so we use its initial value, `ease`\n // (a Web Animations API keyframe's `easing` defaults to `linear`).\n // see: https://drafts.csswg.org/css-animations/#timing-functions\n let easing = keyframe.style.getPropertyValue(TIMING_FUNCTION_PROPERTY);\n if (easing === '')\n easing = DEFAULT_TIMING_FUNCTION;\n\n const parsedKeyframe: Keyframe = {\n ...parsedProperties,\n offset,\n easing\n };\n\n return parsedKeyframe;\n\n}\n\n/** https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument */\ntype KeyframeProperties = { [propertyName: string]: string };\n\nfunction parseKeyframeProperties(style: CSSStyleDeclaration) {\n\n const parsedProperties: KeyframeProperties = {};\n\n for (const propertyName of style) {\n\n // converted to the keyframe's `easing`, in `parseKeyframe`\n if (propertyName === TIMING_FUNCTION_PROPERTY)\n continue;\n\n /// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/getPropertyValue\n const propertyValue = style.getPropertyValue(propertyName);\n\n /// https://drafts.csswg.org/web-animations-1/#ref-for-animation-property-name-to-idl-attribute-name%E2%91%A0\n const attributeName = animationPropertyNameToIDLAttributeName(\n propertyName\n );\n\n parsedProperties[attributeName] = propertyValue;\n\n }\n\n return parsedProperties;\n\n}\n\n/** https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext */\nfunction parseKeyText(keyText: string) {\n\n const percentages = keyText.split(CHARS.COMMA);\n\n // we need to trim `percent`, as Blink\n // returns spaced keyText percentages (e.g. `1%, 2%`)\n const parsePercent = (percent: string) => Number(\n removeSuffix(percent.trim(), CHARS.PERCENT_SIGN)\n );\n\n return percentages.map(\n percent => parsePercent(percent)\n );\n\n}\n\n\n/** https://drafts.csswg.org/web-animations-1/#animation-property-name-to-idl-attribute-name */\nfunction animationPropertyNameToIDLAttributeName(property: string) {\n\n if (isCustomPropertyName(property)) return property;\n\n if (property === 'float') return 'cssFloat';\n\n if (property === 'offset') return 'cssOffset';\n\n // https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2\n const lowercaseFirst = isWebkitCasedAttribute(property);\n\n return cssPropertyToIDLAttribute(property, lowercaseFirst);\n\n}\n\n/** https://drafts.csswg.org/cssom/#css-property-to-idl-attribute */\nfunction cssPropertyToIDLAttribute(property: string, lowercaseFirst: boolean = false) {\n\n let output = '';\n let uppercaseNext = false;\n\n if (lowercaseFirst)\n property = property.slice(1);\n\n for (const c of property) {\n\n if (c === CHARS.HYPHEN_MINUS) {\n\n uppercaseNext = true;\n\n } else if (uppercaseNext) {\n\n uppercaseNext = false;\n\n output += c.toUpperCase();\n\n } else {\n\n output += c;\n\n }\n\n }\n\n return output;\n\n}\n\n/** https://drafts.csswg.org/css-variables-2/#typedef-custom-property-name */\nfunction isCustomPropertyName(property: string) {\n return property.startsWith(CHARS.DOUBLE_HYPHEN_MINUS) &&\n property !== CHARS.DOUBLE_HYPHEN_MINUS;\n}\n\n/** https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2 */\nfunction isWebkitCasedAttribute(property: string) {\n return property.startsWith(CHARS.WEBKIT_PREFIX);\n}\n\n\nfunction removeSuffix(value: string, suffix: string) {\n return value.slice(0, -suffix.length);\n}\n","\n/**\n * Checks whether a stylesheet's rules can be read.\n *\n * Reading `cssRules` throws a `SecurityError` when the stylesheet\n * isn't origin-clean, e.g. a cross-origin `` loaded without CORS.\n * Browsers differ on which stylesheets qualify (Safari 17 also treats\n * `data:` URL stylesheets in sandboxed iframes as cross-origin),\n * so we test for access instead of comparing origins.\n * @see https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssrules\n */\nexport function isStyleSheetAccessible(styleSheet: CSSStyleSheet) {\n\n try {\n styleSheet.cssRules;\n return true;\n } catch (error) {\n if (error instanceof DOMException && error.name === 'SecurityError')\n return false;\n throw error;\n }\n\n}\n","\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Converts a CSS keyframes rule from a stylesheet (or stylesheet list)\n * into Web Animations API keyframes.\n * @param obj\n * @param obj.of The name of the `@keyframes` rule to get keyframes from.\n * @param obj.in The stylesheet or stylesheet list where the rule resides.\n * @throws\n * - `TypeError`\n * - Thrown if keyframes rule name is not a string.\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the name, the last one is used, like in CSS.\n * - When searching a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertStyleSheetKeyframes({ of: ruleName, in: source }: {\n of: string,\n in: CSSStyleSheetSource\n}): ConvertedKeyframes | undefined {\n\n if (typeof ruleName !== 'string')\n throw new TypeError(`Keyframes rule name must be a string.`);\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertStyleSheetKeyframesInStyleSheetList({\n of: ruleName,\n styleSheetList: source\n });\n case source instanceof CSSStyleSheet:\n return convertStyleSheetKeyframesInStyleSheet({\n of: ruleName,\n styleSheet: source\n });\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheetList({ of: ruleName, styleSheetList }: {\n of: string,\n styleSheetList: StyleSheetList\n}) {\n\n const foundRules = Array.from(styleSheetList)\n .filter(isStyleSheetAccessible)\n .map(styleSheet => findKeyframesRuleInStyleSheet({ ruleName, styleSheet }))\n .filter(rule => rule !== undefined);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const foundRule = foundRules.at(-1);\n if (foundRule === undefined)\n return\n\n return convertKeyframesRule(foundRule);\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheet({ of: ruleName, styleSheet }: {\n of: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const rule = findKeyframesRuleInStyleSheet({ ruleName, styleSheet });\n\n if (rule === undefined)\n return;\n\n return convertKeyframesRule(rule);\n\n}\n\nfunction findKeyframesRuleInStyleSheet({ ruleName, styleSheet }: {\n ruleName: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const cssRules = Array.from(styleSheet.cssRules);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const rule = cssRules.findLast((rule): rule is CSSKeyframesRule =>\n rule instanceof CSSKeyframesRule &&\n rule.name === ruleName\n );\n\n return rule;\n\n}\n","\nimport type { ConvertedKeyframesRules } from '../data-types/ConvertedKeyframes';\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Gets all the CSS keyframes rules in a stylesheet or stylesheet list,\n * then converts them to Web Animations API keyframes.\n * @param obj\n * @param obj.in The style sheet or style sheet list to get keyframes from.\n * @throws\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the same name, the last one is used, like in CSS.\n * - When reading a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertAllStyleSheetKeyframesRules({ in: source }: {\n in: CSSStyleSheetSource\n}): ConvertedKeyframesRules {\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertAllStyleSheetKeyframesRulesInStyleSheetList(source);\n case source instanceof CSSStyleSheet:\n return convertAllStyleSheetKeyframesRulesInStyleSheet(source);\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheetList(\n styleSheetList: StyleSheetList\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const styleSheet of styleSheetList) {\n\n if (!isStyleSheetAccessible(styleSheet))\n continue;\n\n const rules = convertAllStyleSheetKeyframesRulesInStyleSheet(styleSheet);\n\n for (const [ruleName, keyframesRule] of rules) {\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n keyframesRules.set(ruleName, keyframesRule);\n }\n\n }\n\n return keyframesRules;\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheet(\n styleSheet: CSSStyleSheet\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const rule of styleSheet.cssRules) {\n\n if (!(rule instanceof CSSKeyframesRule))\n continue;\n\n const keyframes = convertKeyframesRule(rule);\n\n keyframesRules.set(rule.name, keyframes);\n\n }\n\n return keyframesRules;\n\n}\n"],"names":["async","getDocumentStyleSheetsOnLoad","document","window","isLoaded","readyState","promise","resolve","Promise","withResolvers","cleanup","AbortController","addEventListener","signal","abort","waitForDocumentLoad","styleSheets","importStyleSheet","url","resp","fetch","ok","TypeError","respText","text","styleSheet","CSSStyleSheet","replaceSync","KeyframeEffectParameters","keyframes","options","constructor","this","parseOptionsArg","toAnimation","target","additionalOptions","timeline","parsedAdditionalOptions","keyframeEffect","KeyframeEffect","Animation","optionsArg","duration","ConvertedKeyframes","toKeyframeEffect","undefined","TIMING_FUNCTION_PROPERTY","convertKeyframesRule","keyframesRule","parsedKeyframes","Array","from","flatMap","keyframe","keyText","percentages","split","map","percent","Number","trim","slice","suffix","parsePercent","parseKeyText","offset","parsedProperties","style","propertyName","propertyValue","getPropertyValue","animationPropertyNameToIDLAttributeName","parseKeyframeProperties","easing","parseKeyframe","sort","a","b","property","startsWith","isCustomPropertyName","lowercaseFirst","isWebkitCasedAttribute","output","uppercaseNext","c","toUpperCase","cssPropertyToIDLAttribute","isStyleSheetAccessible","cssRules","error","DOMException","name","convertStyleSheetKeyframes","of","ruleName","in","source","StyleSheetList","styleSheetList","foundRule","filter","findKeyframesRuleInStyleSheet","rule","at","convertStyleSheetKeyframesInStyleSheetList","convertStyleSheetKeyframesInStyleSheet","findLast","CSSKeyframesRule","convertAllStyleSheetKeyframesRules","keyframesRules","Map","rules","convertAllStyleSheetKeyframesRulesInStyleSheet","set","convertAllStyleSheetKeyframesRulesInStyleSheetList"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"index.min.js","sources":["../src/KeyframesFactory/sourcing-stylesheets/getDocumentStyleSheetsOnLoad.ts","../src/KeyframesFactory/sourcing-stylesheets/importStyleSheet.ts","../src/KeyframeEffectParameters.ts","../src/KeyframesFactory/data-types/ConvertedKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertKeyframesRule.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/isStyleSheetAccessible.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertStyleSheetKeyframes.ts","../src/KeyframesFactory/converting-stylesheet-keyframes/convertAllStyleSheetKeyframesRules.ts"],"sourcesContent":["\n/**\n * Gets a document's stylesheets when it loads,\n * or immediately returns them if it's already loaded.\n * @param document The document to get stylesheets from.\n * @group Sourcing Stylesheets\n */\nexport async function getDocumentStyleSheetsOnLoad(\n document = window.document\n) {\n\n await waitForDocumentLoad(document);\n\n return document.styleSheets;\n\n}\n\nasync function waitForDocumentLoad(document: Document) {\n\n const isLoaded = () => document.readyState === 'complete';\n\n if (isLoaded())\n return;\n\n const { promise, resolve } = Promise.withResolvers();\n const cleanup = new AbortController();\n\n const onReadyStateChange = () => {\n if (isLoaded())\n resolve();\n };\n\n document.addEventListener(\n 'readystatechange',\n onReadyStateChange,\n { signal: cleanup.signal }\n );\n\n await promise;\n\n // remove the listener\n cleanup.abort();\n\n}\n","\n/**\n * Imports a stylesheet from a URL.\n * @param url The URL of the stylesheet to import.\n * @throws\n * - `TypeError`\n * - Thrown if the stylesheet could not be imported.\n * @remarks\n * - `@import` rules won't be resolved in imported stylesheets.\n * [See more.](https://github.com/WICG/construct-stylesheets/issues/119#issuecomment-588352418)\n * - This polyfill exists because [Safari dosen't support](https://caniuse.com/mdn-javascript_statements_import_import_attributes_type_css)\n * CSS Modules (see [this bug](https://bugs.webkit.org/show_bug.cgi?id=227967)).\n * @see\n * - [Creating a CSS module script - HTML Spec](https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-css-module-script)\n * - [import() return value - MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#return_value)\n * @group Sourcing Stylesheets\n */\nexport async function importStyleSheet(url: string) {\n\n const resp = await fetch(url);\n\n if (!resp.ok)\n throw new TypeError(`Failed to fetch dynamically imported module: ${url}`);\n\n const respText = await resp.text();\n\n const styleSheet = new CSSStyleSheet();\n styleSheet.replaceSync(respText);\n\n return styleSheet;\n\n}\n","\n/**\n * A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @see\n * [Processing a keyframes argument - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument)\n * @group Defining Animations\n */\nexport type KeyframeArgument = Keyframe[] | PropertyIndexedKeyframes;\n\n/**\n * Provides a more convenient way to define animations than is offered natively.\n * @see\n * [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * @group Defining Animations\n */\nexport class KeyframeEffectParameters {\n\n keyframes: KeyframeArgument;\n options: KeyframeEffectOptions;\n\n /**\n * @param obj\n * @param obj.keyframes A keyframes object.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats)\n * @param obj.options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n */\n constructor({ keyframes, options = {} }: {\n keyframes: KeyframeArgument,\n options?: number | KeyframeEffectOptions\n }) {\n\n this.keyframes = keyframes;\n this.options = parseOptionsArg(options);\n\n }\n\n /**\n * @param obj\n * @param obj.target An element to attach the animation to.\n * @param obj.options Additional keyframe effect options. Can override existing keys.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n * @param obj.timeline The timeline with which to associate the animation.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Animation/Animation#timeline)\n * @see\n * - [The KeyframeEffect interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-keyframeeffect-interface)\n * - [The Animation interface - Web Animations Spec](https://drafts.csswg.org/web-animations-1/#the-animation-interface)\n */\n toAnimation({ target, options: additionalOptions = {}, timeline = document.timeline }: {\n target: Element | null,\n options?: number | KeyframeEffectOptions,\n timeline?: AnimationTimeline | null\n }): Animation {\n\n const parsedAdditionalOptions = parseOptionsArg(additionalOptions);\n\n // override existing option keys with additional options\n const options: KeyframeEffectOptions = {\n ...this.options,\n ...parsedAdditionalOptions\n };\n\n\n const keyframeEffect = new KeyframeEffect(\n target,\n this.keyframes,\n options\n );\n\n const animation = new Animation(\n keyframeEffect,\n timeline\n );\n\n return animation;\n\n }\n\n}\n\n/**\n * @see\n * - https://drafts.csswg.org/web-animations-1/#dom-keyframeeffect-keyframeeffect-target-keyframes-options-options\n * - https://drafts.csswg.org/web-animations-1/#dom-effecttiming-duration\n */\nfunction parseOptionsArg(optionsArg: number | KeyframeEffectOptions) {\n if (typeof optionsArg === 'number')\n return { duration: optionsArg };\n return optionsArg;\n}\n","\nimport { KeyframeEffectParameters } from '../../KeyframeEffectParameters';\n\n\n/**\n * Web Animations API keyframes converted with the factory functions.\n * \n * Call {@linkcode toKeyframeEffect} to create an animation from them.\n * @group Data Types\n */\nexport class ConvertedKeyframes {\n\n keyframes: Keyframe[];\n\n constructor(keyframes: Keyframe[]) {\n this.keyframes = keyframes;\n }\n\n /**\n * @param options Keyframe effect options.\n * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)\n *\n * Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole\n * animation at once, on top of each keyframe's easing. Instead, set per-keyframe easing.\n */\n toKeyframeEffect(\n options: number | KeyframeEffectOptions | null\n ) {\n\n const keyframeEffect = new KeyframeEffectParameters({\n keyframes: this.keyframes,\n // convert (required) nullable to optional\n options: options ?? undefined\n });\n\n return keyframeEffect;\n\n }\n\n}\n\n\n/**\n * Maps CSS keyframes rule names to their converted Web Animations API keyframes.\n * @group Data Types\n */\nexport type ConvertedKeyframesRules = Map;\n","\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\n\n\nconst CHARS = {\n PERCENT_SIGN: '%',\n COMMA: ',',\n HYPHEN_MINUS: '-',\n DOUBLE_HYPHEN_MINUS: '--',\n WEBKIT_PREFIX: '-webkit-'\n} as const;\n\n/** https://drafts.csswg.org/css-animations/#animation-timing-function */\nconst TIMING_FUNCTION_PROPERTY = 'animation-timing-function';\nconst DEFAULT_TIMING_FUNCTION = 'ease';\n\n\n/**\n * Converts a CSS keyframes rule to Web Animations API keyframes.\n * @param keyframesRule The rule to convert.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertKeyframesRule(\n keyframesRule: CSSKeyframesRule\n): ConvertedKeyframes {\n\n const keyframes = Array.from(keyframesRule);\n\n // we `flatMap` as keyframes can be conjoined, eg. `0%, 100%`\n // and we have to split them for the Web Animations API's format\n // see: https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext\n const parsedKeyframes = keyframes.flatMap(keyframe =>\n parseKeyText(keyframe.keyText).map(percent =>\n parseKeyframe({ keyframe, percent })\n )\n );\n\n // sort the keyframes in place by escalating offset\n // (this is required to avoid a TypeError,\n // see: https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument).\n // note: the `!` are safe: these are keyframes created by\n // us, which always have an offset.\n parsedKeyframes.sort((a, b) => a.offset! - b.offset!);\n\n return new ConvertedKeyframes(parsedKeyframes);\n\n}\n\nfunction parseKeyframe({ keyframe, percent }: {\n keyframe: CSSKeyframeRule,\n percent: number\n}) {\n\n const offset = percent / 100;\n\n const parsedProperties = parseKeyframeProperties(keyframe.style);\n \n // a CSS keyframe's timing function eases the segment up to the next keyframe,\n // like a Web Animations API keyframe's `easing`.\n // keyframes without one use the animation's timing function, which is set on\n // the animated element, not in the rule, so we use its initial value, `ease`\n // (a Web Animations API keyframe's `easing` defaults to `linear`).\n // see: https://drafts.csswg.org/css-animations/#timing-functions\n let easing = keyframe.style.getPropertyValue(TIMING_FUNCTION_PROPERTY);\n if (easing === '')\n easing = DEFAULT_TIMING_FUNCTION;\n\n const parsedKeyframe: Keyframe = {\n ...parsedProperties,\n offset,\n easing\n };\n\n return parsedKeyframe;\n\n}\n\n/** https://drafts.csswg.org/web-animations-1/#processing-a-keyframes-argument */\ntype KeyframeProperties = { [propertyName: string]: string };\n\nfunction parseKeyframeProperties(style: CSSStyleDeclaration) {\n\n const parsedProperties: KeyframeProperties = {};\n\n for (const propertyName of style) {\n\n // converted to the keyframe's `easing`, in `parseKeyframe`\n if (propertyName === TIMING_FUNCTION_PROPERTY)\n continue;\n\n /// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/getPropertyValue\n const propertyValue = style.getPropertyValue(propertyName);\n\n /// https://drafts.csswg.org/web-animations-1/#ref-for-animation-property-name-to-idl-attribute-name%E2%91%A0\n const attributeName = animationPropertyNameToIDLAttributeName(\n propertyName\n );\n\n parsedProperties[attributeName] = propertyValue;\n\n }\n\n return parsedProperties;\n\n}\n\n/** https://drafts.csswg.org/css-animations/#dom-csskeyframerule-keytext */\nfunction parseKeyText(keyText: string) {\n\n const percentages = keyText.split(CHARS.COMMA);\n\n // we need to trim `percent`, as Blink\n // returns spaced keyText percentages (e.g. `1%, 2%`)\n const parsePercent = (percent: string) => Number(\n removeSuffix(percent.trim(), CHARS.PERCENT_SIGN)\n );\n\n return percentages.map(\n percent => parsePercent(percent)\n );\n\n}\n\n\n/** https://drafts.csswg.org/web-animations-1/#animation-property-name-to-idl-attribute-name */\nfunction animationPropertyNameToIDLAttributeName(property: string) {\n\n if (isCustomPropertyName(property)) return property;\n\n if (property === 'float') return 'cssFloat';\n\n if (property === 'offset') return 'cssOffset';\n\n // https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2\n const lowercaseFirst = isWebkitCasedAttribute(property);\n\n return cssPropertyToIDLAttribute(property, lowercaseFirst);\n\n}\n\n/** https://drafts.csswg.org/cssom/#css-property-to-idl-attribute */\nfunction cssPropertyToIDLAttribute(property: string, lowercaseFirst: boolean = false) {\n\n let output = '';\n let uppercaseNext = false;\n\n if (lowercaseFirst)\n property = property.slice(1);\n\n for (const c of property) {\n\n if (c === CHARS.HYPHEN_MINUS) {\n\n uppercaseNext = true;\n\n } else if (uppercaseNext) {\n\n uppercaseNext = false;\n\n output += c.toUpperCase();\n\n } else {\n\n output += c;\n\n }\n\n }\n\n return output;\n\n}\n\n/** https://drafts.csswg.org/css-variables-2/#typedef-custom-property-name */\nfunction isCustomPropertyName(property: string) {\n return property.startsWith(CHARS.DOUBLE_HYPHEN_MINUS) &&\n property !== CHARS.DOUBLE_HYPHEN_MINUS;\n}\n\n/** https://drafts.csswg.org/cssom/#ref-for-supported-css-property%E2%91%A2 */\nfunction isWebkitCasedAttribute(property: string) {\n return property.startsWith(CHARS.WEBKIT_PREFIX);\n}\n\n\nfunction removeSuffix(value: string, suffix: string) {\n return value.slice(0, -suffix.length);\n}\n","\n/**\n * Checks whether a stylesheet's rules can be read.\n *\n * Reading `cssRules` throws a `SecurityError` when the stylesheet\n * isn't origin-clean, e.g. a cross-origin `` loaded without CORS.\n * Browsers differ on which stylesheets qualify (Safari 17 also treats\n * `data:` URL stylesheets in sandboxed iframes as cross-origin),\n * so we test for access instead of comparing origins.\n * @see https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssrules\n */\nexport function isStyleSheetAccessible(styleSheet: CSSStyleSheet) {\n\n try {\n styleSheet.cssRules;\n return true;\n } catch (error) {\n if (error instanceof DOMException && error.name === 'SecurityError')\n return false;\n throw error;\n }\n\n}\n","\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { ConvertedKeyframes } from '../data-types/ConvertedKeyframes';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Converts a CSS keyframes rule from a stylesheet (or stylesheet list)\n * into Web Animations API keyframes.\n * @param obj\n * @param obj.of The name of the `@keyframes` rule to get keyframes from.\n * @param obj.in The stylesheet or stylesheet list where the rule resides.\n * @throws\n * - `TypeError`\n * - Thrown if keyframes rule name is not a string.\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the name, the last one is used, like in CSS.\n * - When searching a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertStyleSheetKeyframes({ of: ruleName, in: source }: {\n of: string,\n in: CSSStyleSheetSource\n}): ConvertedKeyframes | undefined {\n\n if (typeof ruleName !== 'string')\n throw new TypeError(`Keyframes rule name must be a string.`);\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertStyleSheetKeyframesInStyleSheetList({\n of: ruleName,\n styleSheetList: source\n });\n case source instanceof CSSStyleSheet:\n return convertStyleSheetKeyframesInStyleSheet({\n of: ruleName,\n styleSheet: source\n });\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheetList({ of: ruleName, styleSheetList }: {\n of: string,\n styleSheetList: StyleSheetList\n}) {\n\n const foundRules = Array.from(styleSheetList)\n .filter(isStyleSheetAccessible)\n .map(styleSheet => findKeyframesRuleInStyleSheet({ ruleName, styleSheet }))\n .filter(rule => rule !== undefined);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const foundRule = foundRules.at(-1);\n if (foundRule === undefined)\n return\n\n return convertKeyframesRule(foundRule);\n\n}\n\nfunction convertStyleSheetKeyframesInStyleSheet({ of: ruleName, styleSheet }: {\n of: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const rule = findKeyframesRuleInStyleSheet({ ruleName, styleSheet });\n\n if (rule === undefined)\n return;\n\n return convertKeyframesRule(rule);\n\n}\n\nfunction findKeyframesRuleInStyleSheet({ ruleName, styleSheet }: {\n ruleName: string,\n styleSheet: CSSStyleSheet\n}) {\n\n const cssRules = Array.from(styleSheet.cssRules);\n\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n const rule = cssRules.findLast((rule): rule is CSSKeyframesRule =>\n rule instanceof CSSKeyframesRule &&\n rule.name === ruleName\n );\n\n return rule;\n\n}\n","\nimport type { ConvertedKeyframesRules } from '../data-types/ConvertedKeyframes';\nimport type { CSSStyleSheetSource } from '../data-types/CSSStyleSheetSource';\nimport { convertKeyframesRule } from './convertKeyframesRule';\nimport { isStyleSheetAccessible } from './isStyleSheetAccessible';\n\n\n/**\n * Gets all the CSS keyframes rules in a stylesheet or stylesheet list,\n * then converts them to Web Animations API keyframes.\n * @param obj\n * @param obj.in The style sheet or style sheet list to get keyframes from.\n * @throws\n * - `TypeError`\n * - Thrown if source is not a `CSSStyleSheet` or a `StyleSheetList`.\n * - `SecurityError`\n * - Thrown if source is a `CSSStyleSheet` whose rules can't be read\n * (e.g. a cross-origin stylesheet loaded without CORS).\n * @remarks\n * - If multiple rules have the same name, the last one is used, like in CSS.\n * - When reading a `StyleSheetList`, stylesheets whose rules can't be read\n * are skipped.\n * - Only top-level rules are read: `@keyframes` rules nested in other rules\n * (e.g. `@media`, `@supports` or `@layer`) aren't found.\n * @group Converting Stylesheet Keyframes\n */\nexport function convertAllStyleSheetKeyframesRules({ in: source }: {\n in: CSSStyleSheetSource\n}): ConvertedKeyframesRules {\n\n switch (true) {\n case source instanceof StyleSheetList:\n return convertAllStyleSheetKeyframesRulesInStyleSheetList(source);\n case source instanceof CSSStyleSheet:\n return convertAllStyleSheetKeyframesRulesInStyleSheet(source);\n default:\n throw new TypeError(`Source must be either a CSSStyleSheet or a StyleSheetList.`);\n }\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheetList(\n styleSheetList: StyleSheetList\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const styleSheet of styleSheetList) {\n\n if (!isStyleSheetAccessible(styleSheet))\n continue;\n\n const rules = convertAllStyleSheetKeyframesRulesInStyleSheet(styleSheet);\n\n for (const [ruleName, keyframesRule] of rules) {\n // the last rule with the name is the one CSS uses\n // see: https://drafts.csswg.org/css-animations/#keyframes\n keyframesRules.set(ruleName, keyframesRule);\n }\n\n }\n\n return keyframesRules;\n\n}\n\nfunction convertAllStyleSheetKeyframesRulesInStyleSheet(\n styleSheet: CSSStyleSheet\n): ConvertedKeyframesRules {\n\n const keyframesRules: ConvertedKeyframesRules = new Map();\n\n for (const rule of styleSheet.cssRules) {\n\n if (!(rule instanceof CSSKeyframesRule))\n continue;\n\n const keyframes = convertKeyframesRule(rule);\n\n keyframesRules.set(rule.name, keyframes);\n\n }\n\n return keyframesRules;\n\n}\n"],"names":["async","getDocumentStyleSheetsOnLoad","document","window","isLoaded","readyState","promise","resolve","Promise","withResolvers","cleanup","AbortController","addEventListener","signal","abort","waitForDocumentLoad","styleSheets","importStyleSheet","url","resp","fetch","ok","TypeError","respText","text","styleSheet","CSSStyleSheet","replaceSync","KeyframeEffectParameters","keyframes","options","constructor","this","parseOptionsArg","toAnimation","target","additionalOptions","timeline","parsedAdditionalOptions","keyframeEffect","KeyframeEffect","Animation","optionsArg","duration","ConvertedKeyframes","toKeyframeEffect","undefined","TIMING_FUNCTION_PROPERTY","convertKeyframesRule","keyframesRule","parsedKeyframes","Array","from","flatMap","keyframe","keyText","percentages","split","map","percent","Number","trim","slice","suffix","parsePercent","parseKeyText","offset","parsedProperties","style","propertyName","propertyValue","getPropertyValue","animationPropertyNameToIDLAttributeName","parseKeyframeProperties","easing","parseKeyframe","sort","a","b","property","startsWith","isCustomPropertyName","lowercaseFirst","isWebkitCasedAttribute","output","uppercaseNext","c","toUpperCase","cssPropertyToIDLAttribute","isStyleSheetAccessible","cssRules","error","DOMException","name","convertStyleSheetKeyframes","of","ruleName","in","source","StyleSheetList","styleSheetList","foundRule","filter","findKeyframesRuleInStyleSheet","rule","at","convertStyleSheetKeyframesInStyleSheetList","convertStyleSheetKeyframesInStyleSheet","findLast","CSSKeyframesRule","convertAllStyleSheetKeyframesRules","keyframesRules","Map","rules","convertAllStyleSheetKeyframesRulesInStyleSheet","set","convertAllStyleSheetKeyframesRulesInStyleSheetList"],"mappings":"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"}
\ No newline at end of file
diff --git a/docs/docs/reference/ConvertedKeyframes.md b/docs/docs/reference/ConvertedKeyframes.md
index 4d1f8b7..ce37e01 100644
--- a/docs/docs/reference/ConvertedKeyframes.md
+++ b/docs/docs/reference/ConvertedKeyframes.md
@@ -42,7 +42,7 @@ Keyframe effect options.
[MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)
Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole
- animation at once, on top of each keyframe's easing.
+ animation at once, on top of each keyframe's easing. Instead, set per-keyframe easing.
#### Returns
diff --git a/src/KeyframesFactory/data-types/ConvertedKeyframes.ts b/src/KeyframesFactory/data-types/ConvertedKeyframes.ts
index 651ba74..7465400 100644
--- a/src/KeyframesFactory/data-types/ConvertedKeyframes.ts
+++ b/src/KeyframesFactory/data-types/ConvertedKeyframes.ts
@@ -21,7 +21,7 @@ export class ConvertedKeyframes {
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)
*
* Note: to ease like CSS, leave out `easing`. If you set it, it eases the whole
- * animation at once, on top of each keyframe's easing.
+ * animation at once, on top of each keyframe's easing. Instead, set per-keyframe easing.
*/
toKeyframeEffect(
options: number | KeyframeEffectOptions | null